Open-Transactions  0.93.0-ge03d287
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
opentxs::OTMessageOutbuffer Class Reference

#include <OTMessageOutbuffer.hpp>

Public Member Functions

EXPORT OTMessageOutbuffer ()
 
EXPORT ~OTMessageOutbuffer ()
 
EXPORT void Clear (const OTString *serverId=nullptr, const OTString *nymId=nullptr, OTPseudonym *nym=nullptr, const bool *harvestingForRetry=nullptr)
 
EXPORT void AddSentMessage (OTMessage &message)
 
EXPORT OTMessageGetSentMessage (const int64_t &requestNum, const OTString &serverId, const OTString &nymId)
 
EXPORT bool RemoveSentMessage (const int64_t &requestNum, const OTString &serverId, const OTString &nymId)
 
EXPORT OTMessageGetSentMessage (const OTTransaction &transaction)
 
EXPORT bool RemoveSentMessage (const OTTransaction &transaction)
 

Detailed Description

Definition at line 167 of file OTMessageOutbuffer.hpp.

Constructor & Destructor Documentation

opentxs::OTMessageOutbuffer::OTMessageOutbuffer ( )

Definition at line 163 of file OTMessageOutbuffer.cpp.

164  : dataFolder_(OTDataFolder::Get())
165 {
166  OT_ASSERT(dataFolder_.Exists());
167 }
EXPORT bool Exists() const
Definition: OTString.cpp:1035
#define OT_ASSERT(x)
Definition: Assert.hpp:150
static EXPORT OTString Get()
opentxs::OTMessageOutbuffer::~OTMessageOutbuffer ( )

Definition at line 842 of file OTMessageOutbuffer.cpp.

843 {
844  Clear();
845 }
EXPORT void Clear(const OTString *serverId=nullptr, const OTString *nymId=nullptr, OTPseudonym *nym=nullptr, const bool *harvestingForRetry=nullptr)

Member Function Documentation

void opentxs::OTMessageOutbuffer::AddSentMessage ( OTMessage message)

Definition at line 169 of file OTMessageOutbuffer.cpp.

171 {
172  int64_t lRequestNum = 0;
173 
174  if (theMessage.m_strRequestNum.Exists())
175  lRequestNum = atol(theMessage.m_strRequestNum.Get()); // The map index
176  // is the request
177  // number on the
178  // message itself.
179 
180  // It's technically possible to have TWO messages (from two different
181  // servers) that happen to have the same request number. So we verify
182  // that here, before removing any old ones with the same number and IDs.
183  //
184  auto it = messagesMap_.begin();
185 
186  for (; it != messagesMap_.end(); ++it) {
187 
188  const int64_t& lTempReqNum = it->first;
189 
190  if (lTempReqNum != lRequestNum) {
191  continue;
192  }
193 
194  OTMessage* pMsg = it->second;
195  OT_ASSERT(nullptr != pMsg);
196 
197  //
198  // If a server ID was passed in, but doesn't match the server ID on this
199  // message,
200  // Then skip this one. (Same with the NymID.)
201  //
202  if (!theMessage.m_strServerID.Compare(pMsg->m_strServerID) ||
203  !theMessage.m_strNymID.Compare(pMsg->m_strNymID)) {
204  continue;
205  }
206  else {
207  delete pMsg;
208  pMsg = nullptr;
209  messagesMap_.erase(it);
210  break;
211  }
212  }
213  // Whatever it was, it's gone now!
214 
215  // Now that we KNOW there's nothing already there with that request number
216  // (for that
217  // server ID and Nym ID), we go ahead and add the new message to the map.
218  // (And take ownership.)
219  //
220  messagesMap_.insert(
221  std::pair<int64_t, OTMessage*>(lRequestNum, &theMessage));
222 
223  //
224  // Save it to local storage, in case we don't see the reply until the next
225  // run.
226  //
227  bool bAlreadyExists = false, bIsNewFolder = false;
228  OTString strFolder, strFolder1, strFolder2;
229  strFolder1.Format("%s%s%s", OTFolders::Nym().Get(), OTLog::PathSeparator(),
230  theMessage.m_strServerID.Get());
231  strFolder2.Format("%s%s%s", strFolder1.Get(), OTLog::PathSeparator(),
232  "sent" /*todo hardcoding*/);
233 
234  strFolder.Format("%s%s%s", strFolder2.Get(), OTLog::PathSeparator(),
235  theMessage.m_strNymID.Get());
236 
237  OTString strFolderPath = "", strFolder1Path = "", strFolder2Path = "";
238 
239  OTPaths::AppendFolder(strFolderPath, dataFolder_, strFolder);
240  OTPaths::AppendFolder(strFolder1Path, dataFolder_, strFolder1);
241  OTPaths::AppendFolder(strFolder2Path, dataFolder_, strFolder2);
242 
243  OTPaths::ConfirmCreateFolder(strFolderPath, bAlreadyExists, bIsNewFolder);
244  OTPaths::ConfirmCreateFolder(strFolder1Path, bAlreadyExists, bIsNewFolder);
245  OTPaths::ConfirmCreateFolder(strFolder2Path, bAlreadyExists, bIsNewFolder);
246 
247  OTString strFile;
248  strFile.Format("%s.msg", theMessage.m_strRequestNum.Get());
249 
250  theMessage.SaveContract(strFolder.Get(), strFile.Get());
251 
252  // We also keep a list of the request numbers, so let's load it up, add the
253  // number
254  // to that list, and then save it again.
255  //
256  OTNumList theNumList;
257  std::string str_data_filename("sent.dat"); // todo hardcoding.
258  if (OTDB::Exists(strFolder.Get(), str_data_filename)) {
259  OTString strNumList(
260  OTDB::QueryPlainString(strFolder.Get(), str_data_filename));
261  if (strNumList.Exists()) theNumList.Add(strNumList);
262  theNumList.Add(lRequestNum); // Add the new request number to it.
263  }
264  else // it doesn't exist on disk, so let's just create it from the list we
265  // have in RAM so we can store it to disk.
266  {
267  it = messagesMap_.begin();
268  while (it != messagesMap_.end()) {
269 
270  const int64_t& lTempReqNum = it->first;
271 
272  OTMessage* pMsg = it->second;
273  OT_ASSERT(nullptr != pMsg);
274 
275  //
276  // If a server ID was passed in, but doesn't match the server ID on
277  // this message,
278  // Then skip this one. (Same with the NymID.)
279  //
280  if (!theMessage.m_strServerID.Compare(pMsg->m_strServerID) ||
281  !theMessage.m_strNymID.Compare(pMsg->m_strNymID)) {
282  ++it;
283  continue;
284  }
285  else {
286  theNumList.Add(lTempReqNum);
287  }
288  ++it;
289  }
290  } // else
291 
292  // By this point, theNumList has either been loaded from local storage and
293  // had the new number added,
294  // or it wasn't in local storage and thus we created it and added all the
295  // numnbers to it (including new one.)
296  // Therefore nothing left to do here, but save it back again!
297  //
298  OTString strOutput;
299  theNumList.Output(strOutput);
300 
301  if (!OTDB::StorePlainString(strOutput.Get(), strFolder.Get(),
302  str_data_filename)) // todo hardcoding.
303  {
304  otErr << "OTMessageOutbuffer::AddSentMessage: Error: failed writing "
305  "list of request numbers to storage.\n";
306  }
307 }
EXPORT bool StorePlainString(std::string strContents, std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:698
static EXPORT const char * PathSeparator()
Definition: OTLog.cpp:408
static EXPORT const OTString & Nym()
Definition: OTFolders.cpp:327
static EXPORT bool AppendFolder(OTString &out_strPath, const OTString &strBasePath, const OTString &strFolderName)
Definition: OTPaths.cpp:1212
EXPORT std::string QueryPlainString(std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:728
#define OT_ASSERT(x)
Definition: Assert.hpp:150
static EXPORT bool ConfirmCreateFolder(const OTString &strExactPath, bool &out_Exists, bool &out_IsNew)
Definition: OTPaths.cpp:921
OTLOG_IMPORT OTLogStream otErr
EXPORT bool Exists(std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:584
void opentxs::OTMessageOutbuffer::Clear ( const OTString serverId = nullptr,
const OTString nymId = nullptr,
OTPseudonym nym = nullptr,
const bool *  harvestingForRetry = nullptr 
)

Definition at line 395 of file OTMessageOutbuffer.cpp.

398 {
399  // const char * szFuncName = "OTMessageOutbuffer::Clear";
400 
401  auto it = messagesMap_.begin();
402 
403  while (it != messagesMap_.end()) {
404 
405  const int64_t& lRequestNum = it->first;
406  OTMessage* pThisMsg = it->second;
407  OT_ASSERT(nullptr != pThisMsg);
408 
409  //
410  // If a server ID was passed in, but doesn't match the server ID on this
411  // message,
412  // Then skip this one. (Same with the NymID.)
413  if (((nullptr != pstrServerID) &&
414  !pstrServerID->Compare(pThisMsg->m_strServerID)) ||
415  ((nullptr != pstrNymID) &&
416  !pstrNymID->Compare(pThisMsg->m_strNymID))) {
417  ++it;
418  continue;
419  }
420  else {
421  /*
422  Sent messages are cached because some of them are so important,
423  that
424  the server drops a reply notice into the Nymbox to make sure they
425  were
426  received. This way, when we download the Nymbox we can SEE which
427  messages
428  were ACTUALLY replied to, and at that time, we removed those
429  messages
430  already from *this "sent buffer." After that loop was done, we
431  called
432  CLEAR (this function) and cleared ALL the sent messages from the
433  buffer
434  (for the appropriate server and nym IDs...clear without those IDs
435  is
436  only for the destructor.)
437 
438  This Clear, where we are now, HARVESTS the transaction numbers back
439  from any messages left in the sent buffer. We are able to do this
440  with
441  confidence because we know that this function is only called in
442  @getNymbox
443  on client side, and only after the ones with actual replies (as
444  evidenced
445  by the Nymbox) have already been removed from *this "sent buffer."
446 
447  Why were they removed in advance? Because clearly: if the server
448  HAS replied
449  to them already, then there's no need to harvest anything: just let
450  it
451  process as normal, whether the transaction inside is a success or
452  fail.
453  (We KNOW the message didn't fail because otherwise there wouldn't
454  even be
455  a notice in the Nymbox. So this is about the transaction inside.)
456 
457  So we remove the ones that we DEFINITELY know the server HAS
458  replied to.
459 
460  And the ones remaining? We know for those, the server definitely
461  has NOT
462  replied to them (the message must have been dropped by the network
463  or
464  something.) How do we know this? Because there would be a notice in
465  the
466  Nymbox! So at the moment of successful @getNymbox, we are able to
467  loop through
468  those receipts and know FOR SURE, WHICH ones definitely have a
469  reply, and
470  which ones definitely DO NOT.
471 
472  The ones where we definitely do NOT have a reply--that is, the ones
473  that are in
474  the "sent messages" buffer, but are not in the Nymbox with the same
475  request
476  number--we harvest those numbers, since the server clearly never
477  saw them, or
478  rejected the message before the transaction itself even had a
479  chance to run.
480 
481  */
482  if (nullptr != pNym) {
483  OT_ASSERT(nullptr != pstrNymID && pstrNymID->Exists());
484  const OTIdentifier MSG_NYM_ID(*pstrNymID);
485  OT_ASSERT(pNym->CompareID(MSG_NYM_ID));
486 
487  OT_ASSERT(nullptr != pstrServerID && pstrServerID->Exists());
488 
489  OT_ASSERT(nullptr != pbHarvestingForRetry);
490 
491  /*
492  getNymbox -- client is NOT sending hash, server is
493  NOT rejecting bad hashes, server IS SENDING HASH in the
494  @getNymbox reply
495  getRequest -- client is NOT sending hash, server is
496  NOT rejecting bad hashes, server IS SENDING HASH in the
497  @getRequest reply
498 
499  processNymbox -- client is SENDING HASH, server is
500  REJECTING BAD HASHES, server is SENDING HASH in the
501  @processNymbox reply
502  notarizeTransactions -- client is SENDING HASH, server is
503  REJECTING BAD HASHES, server is SENDING HASH in the
504  @notarizeTransactions reply
505  processInbox -- client is SENDING HASH, server is
506  REJECTING BAD HASHES, server is SENDING HASH in the
507  @processInbox reply
508  triggerClause -- client is SENDING HASH, server is
509  REJECTING BAD HASHES, server is SENDING HASH in the
510  @triggerClause reply
511 
512  getTransactionNum -- client is SENDING HASH, server is
513  REJECTING BAD HASHES, server is SENDING HASH in the
514  @getTransactionNum reply
515 
516  Already covered in NotarizeTransaction:
517  transfer, withdrawal, deposit, marketOffer, paymentPlan,
518  smartContract, cancelCronItem, exchangeBasket
519  */
520 
521  if (pThisMsg->m_ascPayload.Exists() &&
522  (pThisMsg->m_strCommand.Compare("processNymbox") ||
523  pThisMsg->m_strCommand.Compare("processInbox") ||
524  pThisMsg->m_strCommand.Compare("notarizeTransactions") ||
525  pThisMsg->m_strCommand.Compare("triggerClause"))) {
526  //
527  // If we are here in the first place (i.e. after @getNymbox
528  // just removed
529  // all the messages in this sent buffer that already had a
530  // reply sitting
531  // in the nymbox) therefore we KNOW any messages in here
532  // never got a reply
533  // from the server
534 
535  const bool bReplyWasSuccess =
536  false; // If the msg had been a success, the reply
537  // (whether transaction within succeeded or
538  // failed) would have been dropped into my
539  // Nymbox, and thus removed from this "sent
540  // buffer" in @getNymbox.
541  const bool bReplyWasFailure =
542  true; // If the msg had been an explicit failure, the
543  // reply (without the transaction inside of it
544  // even having a chance to succeed or fail) would
545  // definitely NOT have been dropped into my
546  // Nymbox, and thus removed from this "sent
547  // buffer" in @getNymbox. However, IN THIS ONE
548  // CASE, since we DID just download the Nymbox and
549  // verify there ARE NO REPLIES for this request
550  // number (before calling this function), and
551  // since a dropped message is basically identical
552  // to a rejected message, since in either case,
553  // the transaction itself never even had a chance
554  // to run, we are able to now harvest the message
555  // AS IF the server HAD explicitly rejected the
556  // message. This is why I pass true here, where
557  // anywhere else in the code I would always pass
558  // false unless I had explicitly received a
559  // failure from the server. This place in the
560  // code, where we are now, is the failsafe
561  // endpoint for missed/dropped messages! IF they
562  // STILL haven't been found by this point, they
563  // are cleaned up as if the message was explicitly
564  // rejected by the server before the transaction
565  // even had a chance to run.
566 
567  const bool bTransactionWasSuccess =
568  false; // Per above, since "the transaction never had a
569  // chance to run" then it could NOT have been an
570  // explicit success.
571  const bool bTransactionWasFailure =
572  false; // Per above, since "the transaction never had a
573  // chance to run" then it could NOT have been an
574  // explicit failure.
575 
576  pThisMsg->HarvestTransactionNumbers(
577  *pNym, // Actually it's pNym who is "harvesting" the
578  // numbers in this call. <========= HARVEST
579  *pbHarvestingForRetry, bReplyWasSuccess,
580  bReplyWasFailure, bTransactionWasSuccess,
581  bTransactionWasFailure);
582  } // if there's a transaction to be harvested inside this
583  // message.
584  } // if pNym !nullptr
585 
586  auto temp_it = it;
587  ++temp_it;
588  messagesMap_.erase(it);
589  it = temp_it; // here's where the iterator gets incremented (during
590  // the erase, basically.)
591 
592  delete pThisMsg; // <============ DELETE
593  pThisMsg = nullptr;
594 
595  if (nullptr != pstrNymID && nullptr != pstrServerID) {
596  OTString strFolder, strFile;
597  strFolder.Format("%s%s%s%s%s%s%s", OTFolders::Nym().Get(),
598  OTLog::PathSeparator(), pstrServerID->Get(),
599  OTLog::PathSeparator(), "sent",
600  /*todo hardcoding*/ OTLog::PathSeparator(),
601  pstrNymID->Get());
602  strFile.Format("%lld.msg", lRequestNum);
603 
604  OTNumList theNumList;
605  std::string str_data_filename("sent.dat"); // todo hardcoding.
606  if (OTDB::Exists(strFolder.Get(), str_data_filename)) {
607  OTString strNumList(OTDB::QueryPlainString(
608  strFolder.Get(), str_data_filename));
609  if (strNumList.Exists()) theNumList.Add(strNumList);
610  theNumList.Remove(lRequestNum); // Clear (this function)
611  // loops and removes them.
612  // (Here's the one being
613  // removed this iteration.)
614  }
615  else // it doesn't exist on disk, so let's just create it from
616  // the list we have in RAM so we can store it to disk.
617  { // NOTE: this may be unnecessary since we are "clear"ing them
618  // all anyway. But that just means we can remove this
619  // block during optimization. Todo optimize.
620  // Since we create the NumList based on messagesMap_, and
621  // since the message for this iteration was already removed
622  // above, we don't need to remove anything at this point, we
623  // just create the NumList to contain the same numbers as
624  // are
625  // in messagesMap_.
626  //
627  it = messagesMap_.begin();
628  while (it != messagesMap_.end()) {
629 
630  const int64_t& lTempReqNum = it->first;
631 
632  OTMessage* pMsg = it->second;
633  OT_ASSERT(nullptr != pMsg);
634 
635  //
636  // If a server ID was passed in, but doesn't match the
637  // server ID on this message,
638  // Then skip this one. (Same with the NymID.)
639  //
640  if (!pstrServerID->Compare(pMsg->m_strServerID) ||
641  !pstrNymID->Compare(pMsg->m_strNymID)) {
642  ++it;
643  continue;
644  }
645  else {
646  theNumList.Add(lTempReqNum);
647  }
648  ++it;
649  }
650  } // else
651 
652  // By this point, theNumList has either been loaded from local
653  // storage and had the number removed,
654  // or it wasn't in local storage and thus we created it and
655  // added all the numbers to it from RAM (not
656  // including the one being erased, since it was already removed
657  // from the RAM list, above.) So either
658  // way, the number being removed is now ABSENT from theNumList.
659  //
660  // Therefore nothing left to do here, but save it back again!
661  //
662  OTString strOutput;
663  theNumList.Output(strOutput);
664  if (!OTDB::StorePlainString(strOutput.Get(), strFolder.Get(),
665  str_data_filename)) // todo
666  // hardcoding.
667  {
668  otErr << "OTMessageOutbuffer::Clear: Error: failed writing "
669  "list of request numbers to storage.\n";
670  }
671 
672  // Make sure any messages being erased here, are also erased
673  // from local storage.
674  // Now that we've updated the numlist in local storage, let's
675  // erase the sent message itself...
676  //
677  OTMessage* pMsg = new OTMessage;
678  OT_ASSERT(nullptr != pMsg);
679  std::unique_ptr<OTMessage> theMsgAngel(pMsg);
680 
681  if (OTDB::Exists(strFolder.Get(), strFile.Get()) &&
682  pMsg->LoadContract(strFolder.Get(), strFile.Get())) {
683  OTDB::EraseValueByKey(strFolder.Get(), strFile.Get());
684  }
685  }
686  }
687  }
688 }
EXPORT bool StorePlainString(std::string strContents, std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:698
static EXPORT const char * PathSeparator()
Definition: OTLog.cpp:408
static EXPORT const OTString & Nym()
Definition: OTFolders.cpp:327
EXPORT std::string QueryPlainString(std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:728
#define OT_ASSERT(x)
Definition: Assert.hpp:150
EXPORT bool EraseValueByKey(std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:843
OTLOG_IMPORT OTLogStream otErr
EXPORT bool Exists(std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:584
OTMessage * opentxs::OTMessageOutbuffer::GetSentMessage ( const int64_t &  requestNum,
const OTString serverId,
const OTString nymId 
)

Definition at line 313 of file OTMessageOutbuffer.cpp.

316 {
317  auto it = messagesMap_.begin();
318 
319  for (; it != messagesMap_.end(); ++it) {
320 
321  const int64_t& lTempReqNum = it->first;
322 
323  if (lTempReqNum != lRequestNum) {
324  continue;
325  }
326 
327  OTMessage* pMsg = it->second;
328  OT_ASSERT(nullptr != pMsg);
329 
330  //
331  // If a server ID was passed in, but doesn't match the server ID on this
332  // message,
333  // Then skip this one. (Same with the NymID.)
334  if (!strServerID.Compare(pMsg->m_strServerID) ||
335  !strNymID.Compare(pMsg->m_strNymID)) {
336  continue;
337  }
338  else {
339  return pMsg;
340  }
341  }
342 
343  // Didn't find it? Okay let's load it from local storage, if it's there...
344  //
345  OTString strFolder, strFile;
346  strFolder.Format(
347  "%s%s%s%s%s%s%s", OTFolders::Nym().Get(), OTLog::PathSeparator(),
348  strServerID.Get(), OTLog::PathSeparator(), "sent",
349  /*todo hardcoding*/ OTLog::PathSeparator(), strNymID.Get());
350  strFile.Format("%lld.msg", lRequestNum);
351 
352  // Check the existing list, if it exists.
353  //
354  OTNumList theNumList;
355  std::string str_data_filename("sent.dat");
356  if (OTDB::Exists(strFolder.Get(), str_data_filename)) // todo hardcoding.
357  {
358  OTString strNumList(
359  OTDB::QueryPlainString(strFolder.Get(), str_data_filename));
360 
361  if (strNumList.Exists()) theNumList.Add(strNumList);
362 
363  if (theNumList.Verify(lRequestNum)) {
364  // Even if the outgoing message was stored, we still act like it
365  // "doesn't exist" if it doesn't appear on the official list.
366  // The list is what matters -- the message is just the contents
367  // referenced
368  // by that list.
369 
370  OTMessage* pMsg = new OTMessage;
371  OT_ASSERT(nullptr != pMsg);
372  std::unique_ptr<OTMessage> theMsgAngel(pMsg);
373 
374  if (OTDB::Exists(strFolder.Get(), strFile.Get()) &&
375  pMsg->LoadContract(strFolder.Get(), strFile.Get())) {
376  // Since we had to load it from local storage, let's add it to
377  // the list in RAM.
378  //
379  messagesMap_.insert(std::pair<int64_t, OTMessage*>(
380  lRequestNum, theMsgAngel.release()));
381  return pMsg;
382  }
383  }
384  }
385 
386  // STILL didn't find it? (Failure.)
387  //
388  return nullptr;
389 }
static EXPORT const char * PathSeparator()
Definition: OTLog.cpp:408
static EXPORT const OTString & Nym()
Definition: OTFolders.cpp:327
EXPORT std::string QueryPlainString(std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:728
#define OT_ASSERT(x)
Definition: Assert.hpp:150
EXPORT bool Exists(std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:584
OTMessage * opentxs::OTMessageOutbuffer::GetSentMessage ( const OTTransaction transaction)

Definition at line 821 of file OTMessageOutbuffer.cpp.

823 {
824  const int64_t& lRequestNum = theTransaction.GetRequestNum();
825  const OTString strServerID(theTransaction.GetPurportedServerID());
826  const OTString strNymID(theTransaction.GetUserID());
827 
828  return GetSentMessage(lRequestNum, strServerID, strNymID);
829 }
EXPORT OTMessage * GetSentMessage(const int64_t &requestNum, const OTString &serverId, const OTString &nymId)
bool opentxs::OTMessageOutbuffer::RemoveSentMessage ( const int64_t &  requestNum,
const OTString serverId,
const OTString nymId 
)

Definition at line 692 of file OTMessageOutbuffer.cpp.

695 {
696  OTString strFolder, strFile;
697  strFolder.Format(
698  "%s%s%s%s%s%s%s", OTFolders::Nym().Get(), OTLog::PathSeparator(),
699  strServerID.Get(), OTLog::PathSeparator(), "sent",
700  /*todo hardcoding*/ OTLog::PathSeparator(), strNymID.Get());
701  strFile.Format("%lld.msg", lRequestNum);
702 
703  auto it = messagesMap_.begin();
704 
705  bool bReturnValue = false;
706 
707  while (it != messagesMap_.end()) {
708 
709  const int64_t& lTempReqNum = it->first;
710 
711  if (lTempReqNum != lRequestNum) {
712  ++it;
713  continue;
714  }
715 
716  OTMessage* pMsg = it->second;
717  OT_ASSERT(nullptr != pMsg);
718 
719  //
720  // If a server ID was passed in, but doesn't match the server ID on this
721  // message,
722  // Then skip this one. (Same with the NymID.)
723  if (!strServerID.Compare(pMsg->m_strServerID) ||
724  !strNymID.Compare(pMsg->m_strNymID)) {
725  ++it;
726  continue;
727  }
728  else {
729  delete pMsg;
730  pMsg = nullptr;
731 
732  auto temp_it = it;
733  ++temp_it;
734  messagesMap_.erase(it);
735  it = temp_it; // here's where it gets incremented. (During the
736  // erase, basically.)
737 
738  bReturnValue = true;
739  break;
740  }
741  }
742 
743  // Whether we found it in RAM or not, let's make sure to delete it from
744  // local storage, if it's there... (Since there's a list there we have to
745  // update,
746  // anyway.)
747  // We keep a list of the request numbers, so let's load it up, remove the
748  // number
749  // from that list, and then save it again.
750 
751  OTNumList theNumList;
752  std::string str_data_filename("sent.dat"); // todo hardcoding.
753  if (OTDB::Exists(strFolder.Get(), str_data_filename)) {
754  OTString strNumList(
755  OTDB::QueryPlainString(strFolder.Get(), str_data_filename));
756  if (strNumList.Exists()) theNumList.Add(strNumList);
757  theNumList.Remove(lRequestNum);
758  }
759  else // it doesn't exist on disk, so let's just create it from the list we
760  // have in RAM so we can store it to disk.
761  {
762  it = messagesMap_.begin();
763  while (it != messagesMap_.end()) {
764 
765  const int64_t& lTempReqNum = it->first;
766 
767  OTMessage* pMsg = it->second;
768  OT_ASSERT(nullptr != pMsg);
769 
770  //
771  // If a server ID was passed in, but doesn't match the server ID on
772  // this message,
773  // Then skip this one. (Same with the NymID.)
774  //
775  if (!strServerID.Compare(pMsg->m_strServerID) ||
776  !strNymID.Compare(pMsg->m_strNymID)) {
777  ++it;
778  continue;
779  }
780  else {
781  theNumList.Add(lTempReqNum);
782  }
783  ++it;
784  }
785  } // else
786 
787  // By this point, theNumList has either been loaded from local storage and
788  // had the number removed,
789  // or it wasn't in local storage and thus we created it and added all the
790  // numbers to it from RAM (not
791  // including the one being erased, since it was already removed from the RAM
792  // list, above.) So either
793  // way, the number being removed is now ABSENT from theNumList.
794  //
795  // Therefore nothing left to do here, but save it back again!
796  //
797  OTString strOutput;
798  theNumList.Output(strOutput);
799  if (!OTDB::StorePlainString(strOutput.Get(), strFolder.Get(),
800  str_data_filename)) {
801  otErr << "OTMessageOutbuffer::RemoveSentMessage: Error: failed writing "
802  "list of request numbers to storage.\n";
803  }
804 
805  // Now that we've updated the numlist in local storage, let's
806  // erase the sent message itself...
807  //
808  OTMessage* pMsg = new OTMessage;
809  OT_ASSERT(nullptr != pMsg);
810  std::unique_ptr<OTMessage> theMsgAngel(pMsg);
811 
812  if (OTDB::Exists(strFolder.Get(), strFile.Get()) &&
813  pMsg->LoadContract(strFolder.Get(), strFile.Get())) {
814  OTDB::EraseValueByKey(strFolder.Get(), strFile.Get());
815  return true;
816  }
817 
818  return bReturnValue;
819 }
EXPORT bool StorePlainString(std::string strContents, std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:698
static EXPORT const char * PathSeparator()
Definition: OTLog.cpp:408
static EXPORT const OTString & Nym()
Definition: OTFolders.cpp:327
EXPORT std::string QueryPlainString(std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:728
#define OT_ASSERT(x)
Definition: Assert.hpp:150
EXPORT bool EraseValueByKey(std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:843
OTLOG_IMPORT OTLogStream otErr
EXPORT bool Exists(std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:584
bool opentxs::OTMessageOutbuffer::RemoveSentMessage ( const OTTransaction transaction)

Definition at line 833 of file OTMessageOutbuffer.cpp.

834 {
835  const int64_t& lRequestNum = theTransaction.GetRequestNum();
836  const OTString strServerID(theTransaction.GetPurportedServerID());
837  const OTString strNymID(theTransaction.GetUserID());
838 
839  return RemoveSentMessage(lRequestNum, strServerID, strNymID);
840 }
EXPORT bool RemoveSentMessage(const int64_t &requestNum, const OTString &serverId, const OTString &nymId)

The documentation for this class was generated from the following files: