// Cron only removes an item when that item REQUESTS to be removed (by setting // the flag.) // Once this happens, Cron has full permission to remove it. Thus, this hook is // forceful. It // is cron saying, YOU ARE BEING REMOVED. Period. So cleanup whatever you have // to clean up. // // In this case, it removes the corresponding offer from the market. // void OTTrade::onRemovalFromCron() { OTCron* cron = GetCron(); OT_ASSERT(cron != nullptr); // If I don't already have an offer on the market, then I will have trouble // figuring out // my SCALE, which is stored on the Offer. Therefore I will instantiate an // offer (since I // store the original internally) and I will look up the scale. // int64_t scale = 1; // todo stop hardcoding. int64_t transactionNum = 0; if (offer_ != nullptr) { if (!marketOffer_.Exists()) { otErr << "OTTrade::onRemovalFromCron called with nullptr offer_ and " "empty marketOffer_.\n"; return; } std::unique_ptr<OTOffer> offer(new OTOffer()); // Trying to load the offer from the trader's original signed request // (So I can use it to lookup the Market ID, so I can see if the offer // is // already there on the market.) if (!offer->LoadContractFromString(marketOffer_)) { otErr << "Error loading offer from string in " "OTTrade::onRemovalFromCron\n"; return; } scale = offer->GetScale(); transactionNum = offer->GetTransactionNum(); } else { scale = offer_->GetScale(); transactionNum = offer_->GetTransactionNum(); } OTMarket* market = cron->GetOrCreateMarket(GetInstrumentDefinitionID(), GetCurrencyID(), scale); // Couldn't find (or create) the market. // if (market == nullptr) { otErr << "Unable to find market within requested parameters in " "OTTrade::onRemovalFromCron.\n"; return; } // // Let's see if the offer is ALREADY allocated and on this market! // OTOffer* marketOffer = market->GetOffer(transactionNum); // The Offer is already on the Market. // if (marketOffer != nullptr) { offer_ = marketOffer; offer_->SetTrade(*this); } market->RemoveOffer(transactionNum); }
// OTCron calls this regularly, which is my chance to expire, etc. // Return True if I should stay on the Cron list for more processing. // Return False if I should be removed and deleted. bool OTTrade::ProcessCron() { // ----------------------------------------------------------------- // Right now Cron is called 10 times per second. // I'm going to slow down all trades so they are once every GetProcessInterval() if (GetLastProcessDate() > 0) { // (Default ProcessInternal is 1 second, but Trades will use 10 seconds, // and Payment Plans will use an hour or day.) if ((GetCurrentTime() - GetLastProcessDate()) <= GetProcessInterval()) return true; } // Keep a record of the last time this was processed. // (NOT saved to storage, only used while the software is running.) // (Thus no need to release signatures, sign contract, save contract, etc.) SetLastProcessDate(GetCurrentTime()); // ----------------------------------------------------------------- // PAST END DATE? -------------------------------- // First call the parent's version (which this overrides) so it has // a chance to check its stuff. Currently it checks IsExpired(). if (!OTCronItem::ProcessCron()) return false; // It's expired--remove it from Cron. // REACHED START DATE? -------------------------------- // Okay, so it's not expired. But might not have reached START DATE yet... if (!VerifyCurrentDate()) return true; // The Trade is not yet valid, so we return. BUT, we return // true, so it will stay on Cron until it BECOMES valid. // TRADE-specific stuff below. -------------------------------- bool bStayOnMarket = true; // by default stay on the market (until some rule expires me.) OTIdentifier OFFER_MARKET_ID; OTMarket * pMarket = NULL; // If the Offer is already active on a market, then I already have a pointer to // it. This function returns that pointer. If NULL, it tries to find the offer on // the market and then sets the pointer and returns. If it can't find it, IT TRIES // TO ADD IT TO THE MARKET and sets the pointer and returns it. OTOffer * pOffer = GetOffer(&OFFER_MARKET_ID, &pMarket); // Both of these parameters are optional. // In this case, the offer is NOT on the market. // Perhaps it wasn't ready to activate yet. if (NULL == pOffer) { // The offer SHOULD HAVE been on the market, since we're within the valid range, // and GetOffer adds it when it's not already there. // OTLog::Error("OTTrade::ProcessCron: Offer SHOULD have been on Market. I might ASSERT this.\n"); // Actually! If it's a Stop Order, then it WOULD be within the valid range, yet would // not yet have activated. So I don't want to log some big error every time a stop order // checks its prices. } else if (NULL == pMarket) { //todo. (This will already leave a log above in GetOffer somewhere.) } else // If a valid pointer was returned, that means the offer is on the market. { // Make sure it hasn't already been flagged by someone else... if (this->IsFlaggedForRemoval()) bStayOnMarket = false; else { // Process it! <=================== bStayOnMarket = pMarket->ProcessTrade(*this, *pOffer); // No need to save the Trade or Offer, since they will // be saved inside this call if they are changed. } } // The offer needs to be removed from the market. // (Which means this trade also needs to be removed from Cron. // I assume calling function will do that.) if (!bStayOnMarket) { pMarket->RemoveOffer(GetTransactionNum()); } // Return True if I should stay on the Cron list for more processing. // Return False if I should be removed and deleted. return bStayOnMarket; // defaults true, so if false, that means someone is removing it for a reason. }