int main(int argc, char *argv[]) { if (argc != 4) { printf("Error message - Agruments invalid\n"); return -1; } clock=0; dispatch_list_counter=0; execute_list_counter=0; issue_list_counter=0; queue_size=atoi(argv[1]); fetch_size=atoi(argv[2]); file=argv[3]; fp = fopen (file,"r"); for(i=0;i<128;i++) Register[i].tag=-1; do { FakeRetire(); Execute(); Issue(); Dispatch(); fetch(); clock++; } while(Advance_cycle()); for(i=0;i<counter;i++) { printf(" %d fu{%d} src{%d,%d} dst{%d} IF{%d,1} ID{%d,%d} IS{%d,%d} EX{%d,%d} WB{%d,1} current_state = %d and arrival time is %d type %d\n",i,ROB[i].type,ROB[i].source_1,ROB[i].source_2,ROB[i].destination,ROB[i].IF_time,ROB[i].ID_time,ROB[i].IS_time-ROB[i].ID_time,ROB[i].IS_time,ROB[i].EX_time-ROB[i].IS_time,ROB[i].EX_time,ROB[i].timer,ROB[i].WB_time,ROB[i].current_state,ROB[i].arrival_clock,ROB[i].type); } return 0; }
void testIssueSet () { Currency const c1 (1); Account const i1 (1); Currency const c2 (2); Account const i2 (2); IssueRef const a1 (c1, i1); IssueRef const a2 (c2, i2); { Set c; c.insert (a1); if (! expect (c.size () == 1)) return; c.insert (a2); if (! expect (c.size () == 2)) return; if (! expect (c.erase (Issue (c1, i2)) == 0)) return; if (! expect (c.erase (Issue (c1, i1)) == 1)) return; if (! expect (c.erase (Issue (c2, i2)) == 1)) return; if (! expect (c.empty ())) return; } { Set c; c.insert (a1); if (! expect (c.size () == 1)) return; c.insert (a2); if (! expect (c.size () == 2)) return; if (! expect (c.erase (IssueRef (c1, i2)) == 0)) return; if (! expect (c.erase (IssueRef (c1, i1)) == 1)) return; if (! expect (c.erase (IssueRef (c2, i2)) == 1)) return; if (! expect (c.empty ())) return; #if STL_SET_HAS_EMPLACE c.emplace (c1, i1); if (! expect (c.size() == 1)) return; c.emplace (c2, i2); if (! expect (c.size() == 2)) return; #endif } }
void testIssueMap () { Currency const c1 (1); Account const i1 (1); Currency const c2 (2); Account const i2 (2); IssueRef const a1 (c1, i1); IssueRef const a2 (c2, i2); { Map c; c.insert (std::make_pair (a1, 1)); if (! expect (c.size () == 1)) return; c.insert (std::make_pair (a2, 2)); if (! expect (c.size () == 2)) return; if (! expect (c.erase (Issue (c1, i2)) == 0)) return; if (! expect (c.erase (Issue (c1, i1)) == 1)) return; if (! expect (c.erase (Issue (c2, i2)) == 1)) return; if (! expect (c.empty ())) return; } { Map c; c.insert (std::make_pair (a1, 1)); if (! expect (c.size () == 1)) return; c.insert (std::make_pair (a2, 2)); if (! expect (c.size () == 2)) return; if (! expect (c.erase (IssueRef (c1, i2)) == 0)) return; if (! expect (c.erase (IssueRef (c1, i1)) == 1)) return; if (! expect (c.erase (IssueRef (c2, i2)) == 1)) return; if (! expect (c.empty ())) return; } }
TER CreateOffer::doApply () { if (m_journal.debug) m_journal.debug << "OfferCreate> " << mTxn.getJson (0); std::uint32_t const uTxFlags = mTxn.getFlags (); bool const bPassive (uTxFlags & tfPassive); bool const bImmediateOrCancel (uTxFlags & tfImmediateOrCancel); bool const bFillOrKill (uTxFlags & tfFillOrKill); bool const bSell (uTxFlags & tfSell); STAmount saTakerPays = mTxn.getFieldAmount (sfTakerPays); STAmount saTakerGets = mTxn.getFieldAmount (sfTakerGets); if (!saTakerPays.isLegalNet () || !saTakerGets.isLegalNet ()) return temBAD_AMOUNT; auto const& uPaysIssuerID = saTakerPays.getIssuer (); auto const& uPaysCurrency = saTakerPays.getCurrency (); auto const& uGetsIssuerID = saTakerGets.getIssuer (); auto const& uGetsCurrency = saTakerGets.getCurrency (); bool const bHaveExpiration (mTxn.isFieldPresent (sfExpiration)); bool const bHaveCancel (mTxn.isFieldPresent (sfOfferSequence)); std::uint32_t const uExpiration = mTxn.getFieldU32 (sfExpiration); std::uint32_t const uCancelSequence = mTxn.getFieldU32 (sfOfferSequence); // FIXME understand why we use SequenceNext instead of current transaction // sequence to determine the transaction. Why is the offer seuqnce // number insufficient? std::uint32_t const uAccountSequenceNext = mTxnAccount->getFieldU32 (sfSequence); std::uint32_t const uSequence = mTxn.getSequence (); const uint256 uLedgerIndex = Ledger::getOfferIndex (mTxnAccountID, uSequence); if (m_journal.debug) { m_journal.debug << "Creating offer node: " << to_string (uLedgerIndex) << " uSequence=" << uSequence; if (bImmediateOrCancel) m_journal.debug << "Transaction: IoC set."; if (bFillOrKill) m_journal.debug << "Transaction: FoK set."; } // This is the original rate of this offer, and is the rate at which it will // be placed, even if crossing offers change the amounts. std::uint64_t const uRate = STAmount::getRate (saTakerGets, saTakerPays); TER terResult (tesSUCCESS); // This is the ledger view that we work against. Transactions are applied // as we go on processing transactions. core::LedgerView& view (mEngine->view ()); // This is a checkpoint with just the fees paid. If something goes wrong // with this transaction, we roll back to this ledger. core::LedgerView view_checkpoint (view); view.bumpSeq (); // Begin ledger variance. SLE::pointer sleCreator = mEngine->entryCache ( ltACCOUNT_ROOT, Ledger::getAccountRootIndex (mTxnAccountID)); if (uTxFlags & tfOfferCreateMask) { if (m_journal.debug) m_journal.debug << "Malformed transaction: Invalid flags set."; terResult = temINVALID_FLAG; } else if (bImmediateOrCancel && bFillOrKill) { if (m_journal.debug) m_journal.debug << "Malformed transaction: both IoC and FoK set."; terResult = temINVALID_FLAG; } else if (bHaveExpiration && !uExpiration) { m_journal.warning << "Malformed offer: bad expiration"; terResult = temBAD_EXPIRATION; } else if (saTakerPays.isNative () && saTakerGets.isNative ()) { m_journal.warning << "Malformed offer: XRP for XRP"; terResult = temBAD_OFFER; } else if (saTakerPays <= zero || saTakerGets <= zero) { m_journal.warning << "Malformed offer: bad amount"; terResult = temBAD_OFFER; } else if (uPaysCurrency == uGetsCurrency && uPaysIssuerID == uGetsIssuerID) { m_journal.warning << "Malformed offer: redundant offer"; terResult = temREDUNDANT; } // We don't allow a non-native currency to use the currency code XRP. else if (badCurrency() == uPaysCurrency || badCurrency() == uGetsCurrency) { m_journal.warning << "Malformed offer: Bad currency."; terResult = temBAD_CURRENCY; } else if (saTakerPays.isNative () != !uPaysIssuerID || saTakerGets.isNative () != !uGetsIssuerID) { m_journal.warning << "Malformed offer: bad issuer"; terResult = temBAD_ISSUER; } else if (view.isGlobalFrozen (uPaysIssuerID) || view.isGlobalFrozen (uGetsIssuerID)) { m_journal.warning << "Offer involves frozen asset"; terResult = tecFROZEN; } else if (view.accountFunds ( mTxnAccountID, saTakerGets, fhZERO_IF_FROZEN) <= zero) { m_journal.warning << "delay: Offers must be at least partially funded."; terResult = tecUNFUNDED_OFFER; } // This can probably be simplified to make sure that you cancel sequences // before the transaction sequence number. else if (bHaveCancel && (!uCancelSequence || uAccountSequenceNext - 1 <= uCancelSequence)) { if (m_journal.debug) m_journal.debug << "uAccountSequenceNext=" << uAccountSequenceNext << " uOfferSequence=" << uCancelSequence; terResult = temBAD_SEQUENCE; } if (terResult != tesSUCCESS) { if (m_journal.debug) m_journal.debug << "final terResult=" << transToken (terResult); return terResult; } // Process a cancellation request that's passed along with an offer. if ((terResult == tesSUCCESS) && bHaveCancel) { uint256 const uCancelIndex ( Ledger::getOfferIndex (mTxnAccountID, uCancelSequence)); SLE::pointer sleCancel = mEngine->entryCache (ltOFFER, uCancelIndex); // It's not an error to not find the offer to cancel: it might have // been consumed or removed as we are processing. if (sleCancel) { m_journal.warning << "Cancelling order with sequence " << uCancelSequence; terResult = view.offerDelete (sleCancel); } } // Expiration is defined in terms of the close time of the parent ledger, // because we definitively know the time that it closed but we do not // know the closing time of the ledger that is under construction. if (bHaveExpiration && (mEngine->getLedger ()->getParentCloseTimeNC () >= uExpiration)) { return tesSUCCESS; } // Make sure that we are authorized to hold what the taker will pay us. if (terResult == tesSUCCESS && !saTakerPays.isNative ()) terResult = checkAcceptAsset (Issue (uPaysCurrency, uPaysIssuerID)); bool crossed = false; bool const bOpenLedger (mParams & tapOPEN_LEDGER); if (terResult == tesSUCCESS) { // We reverse gets and pays because during offer crossing we are taking. core::Amounts const taker_amount (saTakerGets, saTakerPays); // The amount of the offer that we will need to place, after we finish // offer crossing processing. It may be equal to the original amount, // empty (fully crossed), or something in-between. core::Amounts place_offer; std::tie(terResult, place_offer) = crossOffers (view, taker_amount); if (terResult == tecFAILED_PROCESSING && bOpenLedger) terResult = telFAILED_PROCESSING; if (terResult == tesSUCCESS) { // We now need to reduce the offer by the cross flow. We reverse // in and out here, since during crossing we were takers. assert (saTakerPays.getCurrency () == place_offer.out.getCurrency ()); assert (saTakerPays.getIssuer () == place_offer.out.getIssuer ()); assert (saTakerGets.getCurrency () == place_offer.in.getCurrency ()); assert (saTakerGets.getIssuer () == place_offer.in.getIssuer ()); if (taker_amount != place_offer) crossed = true; if (m_journal.debug) { m_journal.debug << "Offer Crossing: " << transToken (terResult); if (terResult == tesSUCCESS) { m_journal.debug << " takerPays: " << saTakerPays.getFullText () << " -> " << place_offer.out.getFullText (); m_journal.debug << " takerGets: " << saTakerGets.getFullText () << " -> " << place_offer.in.getFullText (); } } saTakerPays = place_offer.out; saTakerGets = place_offer.in; } } if (terResult != tesSUCCESS) { m_journal.debug << "final terResult=" << transToken (terResult); return terResult; } if (m_journal.debug) { m_journal.debug << "takeOffers: saTakerPays=" <<saTakerPays.getFullText (); m_journal.debug << "takeOffers: saTakerGets=" << saTakerGets.getFullText (); m_journal.debug << "takeOffers: mTxnAccountID=" << to_string (mTxnAccountID); m_journal.debug << "takeOffers: FUNDS=" << view.accountFunds ( mTxnAccountID, saTakerGets, fhZERO_IF_FROZEN).getFullText (); } if (saTakerPays < zero || saTakerGets < zero) { // Earlier, we verified that the amounts, as specified in the offer, // were not negative. That they are now suggests that something went // very wrong with offer crossing. m_journal.fatal << (crossed ? "Partially consumed" : "Full") << " offer has negative component:" << " pays=" << saTakerPays.getFullText () << " gets=" << saTakerGets.getFullText (); assert (saTakerPays >= zero); assert (saTakerGets >= zero); return tefINTERNAL; } if (bFillOrKill && (saTakerPays != zero || saTakerGets != zero)) { // Fill or kill and have leftovers. view.swapWith (view_checkpoint); // Restore with just fees paid. return tesSUCCESS; } // What the reserve would be if this offer was placed. auto const accountReserve (mEngine->getLedger ()->getReserve ( sleCreator->getFieldU32 (sfOwnerCount) + 1)); if (saTakerPays == zero || // Wants nothing more. saTakerGets == zero || // Offering nothing more. bImmediateOrCancel) // Do not persist. { // Complete as is. } else if (mPriorBalance.getNValue () < accountReserve) { // If we are here, the signing account had an insufficient reserve // *prior* to our processing. We use the prior balance to simplify // client writing and make the user experience better. if (bOpenLedger) // Ledger is not final, can vote no. { // Hope for more reserve to come in or more offers to consume. If we // specified a local error this transaction will not be retried, so // specify a tec to distribute the transaction and allow it to be // retried. In particular, it may have been successful to a // degree (partially filled) and if it hasn't, it might succeed. terResult = tecINSUF_RESERVE_OFFER; } else if (!crossed) { // Ledger is final, insufficent reserve to create offer, processed // nothing. terResult = tecINSUF_RESERVE_OFFER; } else { // Ledger is final, insufficent reserve to create offer, processed // something. // Consider the offer unfunded. Treat as tesSUCCESS. } } else { assert (saTakerPays > zero); assert (saTakerGets > zero); // We need to place the remainder of the offer into its order book. if (m_journal.debug) m_journal.debug << "offer not fully consumed:" << " saTakerPays=" << saTakerPays.getFullText () << " saTakerGets=" << saTakerGets.getFullText (); std::uint64_t uOwnerNode; std::uint64_t uBookNode; uint256 uDirectory; // Add offer to owner's directory. terResult = view.dirAdd (uOwnerNode, Ledger::getOwnerDirIndex (mTxnAccountID), uLedgerIndex, std::bind ( &Ledger::ownerDirDescriber, std::placeholders::_1, std::placeholders::_2, mTxnAccountID)); if (tesSUCCESS == terResult) { // Update owner count. view.ownerCountAdjust (mTxnAccountID, 1, sleCreator); uint256 const uBookBase (Ledger::getBookBase ( {{uPaysCurrency, uPaysIssuerID}, {uGetsCurrency, uGetsIssuerID}})); if (m_journal.debug) m_journal.debug << "adding to book: " << to_string (uBookBase) << " : " << saTakerPays.getHumanCurrency () << "/" << to_string (saTakerPays.getIssuer ()) << " -> " << saTakerGets.getHumanCurrency () << "/" << to_string (saTakerGets.getIssuer ()); // We use the original rate to place the offer. uDirectory = Ledger::getQualityIndex (uBookBase, uRate); // Add offer to order book. terResult = view.dirAdd (uBookNode, uDirectory, uLedgerIndex, std::bind ( &Ledger::qualityDirDescriber, std::placeholders::_1, std::placeholders::_2, saTakerPays.getCurrency (), uPaysIssuerID, saTakerGets.getCurrency (), uGetsIssuerID, uRate)); } if (tesSUCCESS == terResult) { if (m_journal.debug) { m_journal.debug << "sfAccount=" << to_string (mTxnAccountID); m_journal.debug << "uPaysIssuerID=" << to_string (uPaysIssuerID); m_journal.debug << "uGetsIssuerID=" << to_string (uGetsIssuerID); m_journal.debug << "saTakerPays.isNative()=" << saTakerPays.isNative (); m_journal.debug << "saTakerGets.isNative()=" << saTakerGets.isNative (); m_journal.debug << "uPaysCurrency=" << saTakerPays.getHumanCurrency (); m_journal.debug << "uGetsCurrency=" << saTakerGets.getHumanCurrency (); } SLE::pointer sleOffer (mEngine->entryCreate (ltOFFER, uLedgerIndex)); sleOffer->setFieldAccount (sfAccount, mTxnAccountID); sleOffer->setFieldU32 (sfSequence, uSequence); sleOffer->setFieldH256 (sfBookDirectory, uDirectory); sleOffer->setFieldAmount (sfTakerPays, saTakerPays); sleOffer->setFieldAmount (sfTakerGets, saTakerGets); sleOffer->setFieldU64 (sfOwnerNode, uOwnerNode); sleOffer->setFieldU64 (sfBookNode, uBookNode); if (uExpiration) sleOffer->setFieldU32 (sfExpiration, uExpiration); if (bPassive) sleOffer->setFlag (lsfPassive); if (bSell) sleOffer->setFlag (lsfSell); if (m_journal.debug) m_journal.debug << "final terResult=" << transToken (terResult) << " sleOffer=" << sleOffer->getJson (0); } } if (terResult != tesSUCCESS) { m_journal.debug << "final terResult=" << transToken (terResult); } return terResult; }
// This function gets executed in each thread void *startFunction(void *socketnumber) { int s = *(int *)socketnumber; char message[1000]; //Send ACCEPTED to client acknowledge the client about the connection. strcpy(message, "ACCEPTED"); send(s , message , strlen(message),0); int r; char query[1000]; //Wait for client query..... while( (r = recv(s , query , 1000 , 0)) > 0 ) { //SEARCH for search, INSERT for insert, ISSUE for issue, RENEW for renew, RESERVE for reserve, EXIT for exit. if (query[0] == '1') { //If writer is greater than 0 then donot allow any readers to enter. while(writers>0); readers++; send(s, "1", strlen("1"),0); //Receive Book Name in r = recv(s,query,1000,0); query[r] = '\0'; if (r==0 || r==-1) { break; } Search(query, message, myLibrary,nbooks); send(s,message,strlen(message),0); readers--; } else if (query[0] == '2') { writers++; int thisWriter = turns++; //Wait for all the earliar readers to finish while(readers>0 || turn != thisWriter);//Do Nothing send(s, "1", strlen("1"),0); r = recv(s,query,1000,0); query[r] = '\0'; if (r==0 || r==-1) { break; } myLibrary = Insert(query,myLibrary,nbooks); send(s,"1",strlen("1"),0); writers--; turn++; } else if (query[0] == '3') { send(s, "1", strlen("1"),0); r = recv(s,query,1000,0); if (r==0 || r==-1) { break; } int result = Issue(atoi(query),message,myLibrary,nbooks); send(s,message,strlen(message),0); } else if (query[0] == '4') { send(s, "1", strlen("1"),0); r = recv(s,query,1000,0); if (r==0 || r==-1) { break; } int result = Renew(atoi(query),message,myLibrary,nbooks); send(s,message,strlen(message),0); } else if (query[0] == '5') { send(s, "1", strlen("1"),0); r = recv(s,query,1000,0); if (r==0 || r==-1) { break; } int result = Reserve(atoi(query),message,myLibrary,nbooks); send(s,message,strlen(message),0); } else if (query[0] == '6') { writers++; int thisWriter = turns++; send(s, "1", strlen("1"),0); int result = Exit(myLibrary,nbooks); } else if (query[0] == '7') { break; } } if(r == 0) { printf("Client %d disconnected\n",s ); } else if(r == -1) { printf("Receive Failed from clien %d",s); } printf("Client %d disconnected\n",s ); return(0); }
void testIssueType () { Currency const c1 (1); Account const i1 (1); Currency const c2 (2); Account const i2 (2); Currency const c3 (3); Account const i3 (3); expect (Issue (c1, i1) != Issue (c2, i1)); expect (Issue (c1, i1) < Issue (c2, i1)); expect (Issue (c1, i1) <= Issue (c2, i1)); expect (Issue (c2, i1) <= Issue (c2, i1)); expect (Issue (c2, i1) == Issue (c2, i1)); expect (Issue (c2, i1) >= Issue (c2, i1)); expect (Issue (c3, i1) >= Issue (c2, i1)); expect (Issue (c3, i1) > Issue (c2, i1)); expect (Issue (c1, i1) != Issue (c1, i2)); expect (Issue (c1, i1) < Issue (c1, i2)); expect (Issue (c1, i1) <= Issue (c1, i2)); expect (Issue (c1, i2) <= Issue (c1, i2)); expect (Issue (c1, i2) == Issue (c1, i2)); expect (Issue (c1, i2) >= Issue (c1, i2)); expect (Issue (c1, i3) >= Issue (c1, i2)); expect (Issue (c1, i3) > Issue (c1, i2)); std::hash <Issue> hash; expect (hash (Issue (c1, i1)) == hash (Issue (c1, i1))); expect (hash (Issue (c1, i2)) == hash (Issue (c1, i2))); expect (hash (Issue (c1, i3)) == hash (Issue (c1, i3))); expect (hash (Issue (c2, i1)) == hash (Issue (c2, i1))); expect (hash (Issue (c2, i2)) == hash (Issue (c2, i2))); expect (hash (Issue (c2, i3)) == hash (Issue (c2, i3))); expect (hash (Issue (c3, i1)) == hash (Issue (c3, i1))); expect (hash (Issue (c3, i2)) == hash (Issue (c3, i2))); expect (hash (Issue (c3, i3)) == hash (Issue (c3, i3))); expect (hash (Issue (c1, i1)) != hash (Issue (c1, i2))); expect (hash (Issue (c1, i1)) != hash (Issue (c1, i3))); expect (hash (Issue (c1, i1)) != hash (Issue (c2, i1))); expect (hash (Issue (c1, i1)) != hash (Issue (c2, i2))); expect (hash (Issue (c1, i1)) != hash (Issue (c2, i3))); expect (hash (Issue (c1, i1)) != hash (Issue (c3, i1))); expect (hash (Issue (c1, i1)) != hash (Issue (c3, i2))); expect (hash (Issue (c1, i1)) != hash (Issue (c3, i3))); }
path::RippleCalc::Output flow ( PaymentSandbox& sb, STAmount const& deliver, AccountID const& src, AccountID const& dst, STPathSet const& paths, bool defaultPaths, bool partialPayment, bool ownerPaysTransferFee, boost::optional<Quality> const& limitQuality, boost::optional<STAmount> const& sendMax, beast::Journal j, path::detail::FlowDebugInfo* flowDebugInfo) { Issue const srcIssue = [&] { if (sendMax) return sendMax->issue (); if (!isXRP (deliver.issue ().currency)) return Issue (deliver.issue ().currency, src); return xrpIssue (); }(); Issue const dstIssue = deliver.issue (); boost::optional<Issue> sendMaxIssue; if (sendMax) sendMaxIssue = sendMax->issue (); // convert the paths to a collection of strands. Each strand is the collection // of account->account steps and book steps that may be used in this payment. auto sr = toStrands (sb, src, dst, dstIssue, sendMaxIssue, paths, defaultPaths, ownerPaysTransferFee, j); if (sr.first != tesSUCCESS) { path::RippleCalc::Output result; result.setResult (sr.first); return result; } auto& strands = sr.second; if (j.trace()) { j.trace() << "\nsrc: " << src << "\ndst: " << dst << "\nsrcIssue: " << srcIssue << "\ndstIssue: " << dstIssue; j.trace() << "\nNumStrands: " << strands.size (); for (auto const& curStrand : strands) { j.trace() << "NumSteps: " << curStrand.size (); for (auto const& step : curStrand) { j.trace() << '\n' << *step << '\n'; } } } const bool srcIsXRP = isXRP (srcIssue.currency); const bool dstIsXRP = isXRP (dstIssue.currency); auto const asDeliver = toAmountSpec (deliver); // The src account may send either xrp or iou. The dst account may receive // either xrp or iou. Since XRP and IOU amounts are represented by different // types, use templates to tell `flow` about the amount types. if (srcIsXRP && dstIsXRP) { return finishFlow (sb, srcIssue, dstIssue, flow<XRPAmount, XRPAmount> ( sb, strands, asDeliver.xrp, defaultPaths, partialPayment, limitQuality, sendMax, j, flowDebugInfo)); } if (srcIsXRP && !dstIsXRP) { return finishFlow (sb, srcIssue, dstIssue, flow<XRPAmount, IOUAmount> ( sb, strands, asDeliver.iou, defaultPaths, partialPayment, limitQuality, sendMax, j, flowDebugInfo)); } if (!srcIsXRP && dstIsXRP) { return finishFlow (sb, srcIssue, dstIssue, flow<IOUAmount, XRPAmount> ( sb, strands, asDeliver.xrp, defaultPaths, partialPayment, limitQuality, sendMax, j, flowDebugInfo)); } assert (!srcIsXRP && !dstIsXRP); return finishFlow (sb, srcIssue, dstIssue, flow<IOUAmount, IOUAmount> ( sb, strands, asDeliver.iou, defaultPaths, partialPayment, limitQuality, sendMax, j, flowDebugInfo)); }