//------------------------------------------------------------------------------
/*
    Copyright (c) 2011-2013, OpenCoin, Inc.
*/
//==============================================================================

#ifndef CACHED_TRANSACTION_NUM
#define CACHED_TRANSACTION_NUM 65536
#endif

#ifndef CACHED_TRANSACTION_AGE
#define CACHED_TRANSACTION_AGE 1800
#endif

TransactionMaster::TransactionMaster () : mCache ("TransactionCache", CACHED_TRANSACTION_NUM, CACHED_TRANSACTION_AGE)
{
    ;
}

bool TransactionMaster::inLedger (uint256 const& hash, uint32 ledger)
{
    Transaction::pointer txn = mCache.fetch (hash);

    if (!txn)
        return false;

    txn->setStatus (COMMITTED, ledger);
    return true;
}

Transaction::pointer TransactionMaster::fetch (uint256 const& txnID, bool checkDisk)
{
    Transaction::pointer txn = mCache.fetch (txnID);

    if (!checkDisk || txn)
        return txn;

    txn = Transaction::load (txnID);

    if (!txn)
        return txn;

    mCache.canonicalize (txnID, txn);

    return txn;
}

SerializedTransaction::pointer TransactionMaster::fetch (SHAMapItem::ref item, SHAMapTreeNode::TNType type,
        bool checkDisk, uint32 uCommitLedger)
{
    SerializedTransaction::pointer  txn;
    Transaction::pointer            iTx = getApp().getMasterTransaction ().fetch (item->getTag (), false);

    if (!iTx)
    {

        if (type == SHAMapTreeNode::tnTRANSACTION_NM)
        {
            SerializerIterator sit (item->peekSerializer ());
            txn = boost::make_shared<SerializedTransaction> (boost::ref (sit));
        }
        else if (type == SHAMapTreeNode::tnTRANSACTION_MD)
        {
            Serializer s;
            int length;
            item->peekSerializer ().getVL (s.modData (), 0, length);
            SerializerIterator sit (s);

            txn = boost::make_shared<SerializedTransaction> (boost::ref (sit));
        }
    }
    else
    {
        if (uCommitLedger)
            iTx->setStatus (COMMITTED, uCommitLedger);

        txn = iTx->getSTransaction ();
    }

    return txn;
}

bool TransactionMaster::canonicalize (Transaction::pointer& txn)
{
    uint256 tid = txn->getID ();

    if (!tid)
        return false;

    if (mCache.canonicalize (tid, txn))
        return true;

    return false;
}
// vim:ts=4
