From bad3e81077f824be2762b089f7b7dc846c4f7161 Mon Sep 17 00:00:00 2001 From: drbob Date: Tue, 8 Feb 2011 18:18:16 +0000 Subject: [PATCH] * Changes to fix the "Parent Bug" in Forums. - added Search Functions (for DummyMsgs) to p3distrib - added timestamps to RsDistribDummyMsg. - interfaced in p3forums Not sure about its interaction with "Read Msgs". git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@4020 b45a01b8-16f6-495d-af2f-9b41ad6348cc --- libretroshare/src/services/p3distrib.cc | 140 +++++++++++++++++++++--- libretroshare/src/services/p3distrib.h | 12 +- libretroshare/src/services/p3forums.cc | 74 ++++++++++++- 3 files changed, 209 insertions(+), 17 deletions(-) diff --git a/libretroshare/src/services/p3distrib.cc b/libretroshare/src/services/p3distrib.cc index 3f573c140..40095c57c 100644 --- a/libretroshare/src/services/p3distrib.cc +++ b/libretroshare/src/services/p3distrib.cc @@ -48,10 +48,12 @@ /***** * #define DISTRIB_DEBUG 1 * #define DISTRIB_THREAD_DEBUG 1 + * #define DISTRIB_DUMMYMSG_DEBUG 1 ****/ //#define DISTRIB_DEBUG 1 -#define DISTRIB_THREAD_DEBUG 1 +//#define DISTRIB_THREAD_DEBUG 1 +#define DISTRIB_DUMMYMSG_DEBUG 1 RSA *extractPublicKey(RsTlvSecurityKey &key); RSA *extractPrivateKey(RsTlvSecurityKey &key); @@ -289,6 +291,7 @@ void p3GroupDistrib::run() /* called once the thread is started */ Sleep(1000); #endif +#ifdef DISTRIB_DUMMYMSG_DEBUG /* HACK for debugging */ if (printed < 10) { @@ -297,6 +300,8 @@ void p3GroupDistrib::run() /* called once the thread is started */ printed++; } +#endif + } } } @@ -812,6 +817,9 @@ void p3GroupDistrib::loadMsg(RsDistribSignedMsg *newMsg, const std::string &src, if((git->second.lastPost < (time_t)msg->timestamp)) git->second.lastPost = msg->timestamp; + // Interface to handle Dummy Msgs. + locked_CheckNewMsgDummies(git->second, msg, src, historical); + /* now update parents TS */ locked_updateChildTS(git->second, msg); @@ -819,9 +827,7 @@ void p3GroupDistrib::loadMsg(RsDistribSignedMsg *newMsg, const std::string &src, std::cerr << "p3GroupDistrib::loadMsg() Msg Loaded Successfully" << std::endl; std::cerr << std::endl; #endif - - // Interface to handle Dummy Msgs. - locked_CheckNewMsgDummies(git->second, msg, src, historical); + /* Callback for any derived classes to play with */ locked_eventNewMsg(&(git->second), msg, src, historical); @@ -3415,8 +3421,9 @@ bool p3GroupDistrib::locked_updateChildTS(GroupInfo &gi, RsDistribMsg *msg) std::map::iterator mit; if (gi.msgs.end() == (mit = gi.msgs.find(parentId))) { - /* not found - abandon */ - return true; + /* not found - abandon (check for dummyMsgs first) */ + return locked_updateDummyChildTS(gi, parentId, updateTS); + } RsDistribMsg *parent = mit->second; if ((!parent) || (parent->childTS > updateTS)) @@ -3757,13 +3764,11 @@ bool p3GroupDistrib::groupsChanged(std::list &groupIds) * * - check for matching dummy msgId. * - if yes, delete. - * - if msg->parentId != dummy->parentId, then there is still a missing parent. * */ -#define DISTRIB_DUMMYMSG_DEBUG 1 -RsDistribDummyMsg::RsDistribDummyMsg( std::string tId, std::string pId, std::string mId) -:threadId(tId), parentId(pId), msgId(mId) +RsDistribDummyMsg::RsDistribDummyMsg( std::string tId, std::string pId, std::string mId, uint32_t ts) +:threadId(tId), parentId(pId), msgId(mId), timestamp(ts), childTS(ts) { return; } @@ -3774,6 +3779,8 @@ std::ostream &operator<<(std::ostream &out, const RsDistribDummyMsg &msg) return out; } + + bool p3GroupDistrib::locked_CheckNewMsgDummies(GroupInfo &grp, RsDistribMsg *msg, std::string id, bool historical) { std::string threadId = msg->threadId; @@ -3804,7 +3811,7 @@ bool p3GroupDistrib::locked_CheckNewMsgDummies(GroupInfo &grp, RsDistribMsg *msg std::cerr << "p3GroupDistrib::locked_CheckNewMsgDummies() No ThreadId Msg, Adding DummyMsg"; std::cerr << std::endl; #endif - locked_addDummyMsg(grp, threadId, "", threadId); + locked_addDummyMsg(grp, threadId, "", threadId, msg->timestamp); } else { @@ -3826,7 +3833,7 @@ bool p3GroupDistrib::locked_CheckNewMsgDummies(GroupInfo &grp, RsDistribMsg *msg std::cerr << "p3GroupDistrib::locked_CheckNewMsgDummies() No ParentId Msg, Adding DummyMsg"; std::cerr << std::endl; #endif - locked_addDummyMsg(grp, threadId, threadId, parentId); + locked_addDummyMsg(grp, threadId, threadId, parentId, msg->timestamp); } else { @@ -3855,7 +3862,7 @@ bool p3GroupDistrib::locked_CheckNewMsgDummies(GroupInfo &grp, RsDistribMsg *msg return true; } -bool p3GroupDistrib::locked_addDummyMsg(GroupInfo &grp, std::string threadId, std::string parentId, std::string msgId) +bool p3GroupDistrib::locked_addDummyMsg(GroupInfo &grp, std::string threadId, std::string parentId, std::string msgId, uint32_t ts) { #ifdef DISTRIB_DUMMYMSG_DEBUG std::cerr << "p3GroupDistrib::locked_addDummyMsg(grpId:" << grp.grpId << ", threadId: " << threadId; @@ -3877,7 +3884,8 @@ bool p3GroupDistrib::locked_addDummyMsg(GroupInfo &grp, std::string threadId, st if (dit == grp.dummyMsgs.end()) // not there! { - grp.dummyMsgs[msgId] = RsDistribDummyMsg(threadId, parentId, msgId); + grp.dummyMsgs[msgId] = RsDistribDummyMsg(threadId, parentId, msgId, ts); + #ifdef DISTRIB_DUMMYMSG_DEBUG std::cerr << "p3GroupDistrib::locked_addDummyMsg() Adding Dummy Msg"; @@ -3891,6 +3899,8 @@ bool p3GroupDistrib::locked_addDummyMsg(GroupInfo &grp, std::string threadId, st std::cerr << std::endl; #endif } + + locked_updateDummyChildTS(grp, parentId, ts); // NOTE both ChildTS functions should be merged. return true; } @@ -3925,6 +3935,36 @@ bool p3GroupDistrib::locked_clearDummyMsg(GroupInfo &grp, std::string msgId) + /* now update parents TS */ +/* NB: it is a hack to have seperate updateChildTS functions for msgs and dummyMsgs, + * this need to be combined (do when we add a parentId index.) + */ + +bool p3GroupDistrib::locked_updateDummyChildTS(GroupInfo &gi, std::string parentId, time_t updateTS) +{ + while("" != parentId) + { + std::map::iterator mit; + if (gi.dummyMsgs.end() == (mit = gi.dummyMsgs.find(parentId))) + { + /* not found - abandon */ + return true; + } + RsDistribDummyMsg *parent = &(mit->second); + if (parent->childTS > updateTS) + { + /* we're too old - give up! */ + return true; + } + + /* update timestamp */ + parent->childTS = updateTS; + parentId = parent->parentId; + } + return false ; +} + + bool p3GroupDistrib::locked_printAllDummyMsgs() { #ifdef DISTRIB_DUMMYMSG_DEBUG @@ -3958,3 +3998,75 @@ bool p3GroupDistrib::locked_printDummyMsgs(GroupInfo &grp) } +/***** These Functions are used by the children classes to access the dummyData + ****/ + +bool p3GroupDistrib::getDummyParentMsgList(std::string grpId, std::string pId, std::list &msgIds) +{ +#ifdef DISTRIB_DUMMYMSG_DEBUG + std::cerr << "p3GroupDistrib::getDummyParentMsgList(grpId:" << grpId << "," << pId << ")"; + std::cerr << std::endl; +#endif + RsStackMutex stack(distribMtx); /************* STACK MUTEX ************/ + std::map::iterator git; + if (mGroups.end() == (git = mGroups.find(grpId))) + { +#ifdef DISTRIB_DUMMYMSG_DEBUG + std::cerr << "p3GroupDistrib::getDummyParentMsgList() Group Not Found"; + std::cerr << std::endl; +#endif + return false; + } + + std::map::iterator mit; + + for(mit = git->second.dummyMsgs.begin(); mit != git->second.dummyMsgs.end(); mit++) + { + if (mit->second.parentId == pId) + { + msgIds.push_back(mit->first); + } + } + +#ifdef DISTRIB_DUMMYMSG_DEBUG + std::cerr << "p3GroupDistrib::getDummyParentMsgList() found " << msgIds.size() << " msgs"; + std::cerr << std::endl; +#endif + return true; +} + + +RsDistribDummyMsg *p3GroupDistrib::locked_getGroupDummyMsg(std::string grpId, std::string msgId) +{ +#ifdef DISTRIB_DUMMYMSG_DEBUG + std::cerr << "p3GroupDistrib::locked_getGroupDummyMsg(grpId:" << grpId << "," << msgId << ")"; + std::cerr << std::endl; +#endif + /************* ALREADY LOCKED ************/ + std::map::iterator git; + if (mGroups.end() == (git = mGroups.find(grpId))) + { +#ifdef DISTRIB_DUMMYMSG_DEBUG + std::cerr << "p3GroupDistrib::locked_getGroupDummyMsg() Group not found"; + std::cerr << std::endl; +#endif + return NULL; + } + + std::map::iterator dit; + if (git->second.dummyMsgs.end() == (dit = git->second.dummyMsgs.find(msgId))) + { +#ifdef DISTRIB_DUMMYMSG_DEBUG + std::cerr << "p3GroupDistrib::locked_getGroupDummyMsg() Msg not found"; + std::cerr << std::endl; +#endif + return NULL; + } + + return &(dit->second); +} + + + + + diff --git a/libretroshare/src/services/p3distrib.h b/libretroshare/src/services/p3distrib.h index 39420beba..a52d9fc68 100644 --- a/libretroshare/src/services/p3distrib.h +++ b/libretroshare/src/services/p3distrib.h @@ -102,11 +102,14 @@ const uint32_t GROUP_KEY_DISTRIB_ADMIN = 0x0040; class RsDistribDummyMsg { public: - RsDistribDummyMsg( std::string tId, std::string pId, std::string mId); + RsDistribDummyMsg( std::string tId, std::string pId, std::string mId, uint32_t ts); RsDistribDummyMsg() { return; } std::string threadId; std::string parentId; std::string msgId; + + uint32_t timestamp; + time_t childTS; /* timestamp of most recent child */ }; @@ -708,12 +711,17 @@ class p3GroupDistrib: public CacheSource, public CacheStore, public p3Config, pu public: bool locked_CheckNewMsgDummies(GroupInfo &info, RsDistribMsg *msg, std::string id, bool historical); -bool locked_addDummyMsg(GroupInfo &info, std::string threadId, std::string parentId, std::string msgId); +bool locked_addDummyMsg(GroupInfo &info, std::string threadId, std::string parentId, std::string msgId, uint32_t ts); bool locked_clearDummyMsg(GroupInfo &info, std::string msgId); +bool locked_updateDummyChildTS(GroupInfo &gi, std::string parentId, time_t updateTS); // NOTE MUST BE MERGED WITH nromal version. bool locked_printAllDummyMsgs(); bool locked_printDummyMsgs(GroupInfo &info); + /* access the dummy msgs */ +bool getDummyParentMsgList(std::string grpId, std::string pId, std::list &msgIds); +RsDistribDummyMsg *locked_getGroupDummyMsg(std::string grpId, std::string msgId); + /* key cache functions - we use .... (not overloaded) */ diff --git a/libretroshare/src/services/p3forums.cc b/libretroshare/src/services/p3forums.cc index 9d6ea11d6..fb0d3fd6e 100644 --- a/libretroshare/src/services/p3forums.cc +++ b/libretroshare/src/services/p3forums.cc @@ -170,6 +170,9 @@ bool p3Forums::getForumThreadList(const std::string &fId, std::list msgDummyIds; + getDummyParentMsgList(fId, "", msgDummyIds); + RsStackMutex stack(distribMtx); /***** STACK LOCKED MUTEX *****/ for(it = msgIds.begin(); it != msgIds.end(); it++) { @@ -196,6 +199,29 @@ bool p3Forums::getForumThreadList(const std::string &fId, std::listmsgId; + tis.parentId = ""; // always NULL (see request) + tis.threadId = msg->msgId; // these are the thread heads! + + tis.ts = msg->timestamp; + tis.childTS = msg->childTS; + + /* dummy msg */ + tis.title = L"Missing Message"; + tis.msg = L"Placeholder for missing Message"; + + msgs.push_back(tis); + } + return true; } @@ -206,6 +232,9 @@ bool p3Forums::getForumThreadMsgList(const std::string &fId, const std::string & getParentMsgList(fId, pId, msgIds); + std::list msgDummyIds; + getDummyParentMsgList(fId, pId, msgDummyIds); + RsStackMutex stack(distribMtx); /***** STACK LOCKED MUTEX *****/ for(it = msgIds.begin(); it != msgIds.end(); it++) { @@ -236,6 +265,29 @@ bool p3Forums::getForumThreadMsgList(const std::string &fId, const std::string & msgs.push_back(tis); } + + // now add dummy msgs. + for(it = msgDummyIds.begin(); it != msgDummyIds.end(); it++) + { + /* get details */ + RsDistribDummyMsg *msg = locked_getGroupDummyMsg(fId, *it); + ThreadInfoSummary tis; + + tis.forumId = fId; + tis.msgId = msg->msgId; + tis.parentId = msg->parentId; + tis.threadId = msg->threadId; + + tis.ts = msg->timestamp; + tis.childTS = msg->childTS; + + /* dummy msg */ + tis.title = L"Missing Message"; + tis.msg = L"Placeholder for missing Message"; + /* the rest must be gotten from the derived Msg */ + + msgs.push_back(tis); + } return true; } @@ -246,8 +298,28 @@ bool p3Forums::getForumMessage(const std::string &fId, const std::string &mId, F RsDistribMsg *msg = locked_getGroupMsg(fId, mId); RsForumMsg *fmsg = dynamic_cast(msg); if (!fmsg) - return false; + { + /* try for a dummy msg */ + RsDistribDummyMsg *dmsg = locked_getGroupDummyMsg(fId, mId); + if (!dmsg) + return false; + /* fill in the dummy msg */ + info.forumId = fId; + info.msgId = dmsg->msgId; + info.parentId = dmsg->parentId; + info.threadId = dmsg->threadId; + + info.ts = dmsg->timestamp; + info.childTS = dmsg->childTS; + + info.title = L"Missing Message"; + info.msg = L"Placeholder for missing Message"; + + info.srcId = ""; + + return true; + } info.forumId = msg->grpId; info.msgId = msg->msgId;