* 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
This commit is contained in:
drbob 2011-02-08 18:18:16 +00:00
parent ce298e62cf
commit bad3e81077
3 changed files with 209 additions and 17 deletions

View File

@ -48,10 +48,12 @@
/***** /*****
* #define DISTRIB_DEBUG 1 * #define DISTRIB_DEBUG 1
* #define DISTRIB_THREAD_DEBUG 1 * #define DISTRIB_THREAD_DEBUG 1
* #define DISTRIB_DUMMYMSG_DEBUG 1
****/ ****/
//#define DISTRIB_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 *extractPublicKey(RsTlvSecurityKey &key);
RSA *extractPrivateKey(RsTlvSecurityKey &key); RSA *extractPrivateKey(RsTlvSecurityKey &key);
@ -289,6 +291,7 @@ void p3GroupDistrib::run() /* called once the thread is started */
Sleep(1000); Sleep(1000);
#endif #endif
#ifdef DISTRIB_DUMMYMSG_DEBUG
/* HACK for debugging */ /* HACK for debugging */
if (printed < 10) if (printed < 10)
{ {
@ -297,6 +300,8 @@ void p3GroupDistrib::run() /* called once the thread is started */
printed++; printed++;
} }
#endif
} }
} }
} }
@ -812,6 +817,9 @@ void p3GroupDistrib::loadMsg(RsDistribSignedMsg *newMsg, const std::string &src,
if((git->second.lastPost < (time_t)msg->timestamp)) if((git->second.lastPost < (time_t)msg->timestamp))
git->second.lastPost = msg->timestamp; git->second.lastPost = msg->timestamp;
// Interface to handle Dummy Msgs.
locked_CheckNewMsgDummies(git->second, msg, src, historical);
/* now update parents TS */ /* now update parents TS */
locked_updateChildTS(git->second, msg); locked_updateChildTS(git->second, msg);
@ -820,8 +828,6 @@ void p3GroupDistrib::loadMsg(RsDistribSignedMsg *newMsg, const std::string &src,
std::cerr << std::endl; std::cerr << std::endl;
#endif #endif
// Interface to handle Dummy Msgs.
locked_CheckNewMsgDummies(git->second, msg, src, historical);
/* Callback for any derived classes to play with */ /* Callback for any derived classes to play with */
locked_eventNewMsg(&(git->second), msg, src, historical); locked_eventNewMsg(&(git->second), msg, src, historical);
@ -3415,8 +3421,9 @@ bool p3GroupDistrib::locked_updateChildTS(GroupInfo &gi, RsDistribMsg *msg)
std::map<std::string, RsDistribMsg *>::iterator mit; std::map<std::string, RsDistribMsg *>::iterator mit;
if (gi.msgs.end() == (mit = gi.msgs.find(parentId))) if (gi.msgs.end() == (mit = gi.msgs.find(parentId)))
{ {
/* not found - abandon */ /* not found - abandon (check for dummyMsgs first) */
return true; return locked_updateDummyChildTS(gi, parentId, updateTS);
} }
RsDistribMsg *parent = mit->second; RsDistribMsg *parent = mit->second;
if ((!parent) || (parent->childTS > updateTS)) if ((!parent) || (parent->childTS > updateTS))
@ -3757,13 +3764,11 @@ bool p3GroupDistrib::groupsChanged(std::list<std::string> &groupIds)
* *
* - check for matching dummy msgId. * - check for matching dummy msgId.
* - if yes, delete. * - 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) RsDistribDummyMsg::RsDistribDummyMsg( std::string tId, std::string pId, std::string mId, uint32_t ts)
:threadId(tId), parentId(pId), msgId(mId) :threadId(tId), parentId(pId), msgId(mId), timestamp(ts), childTS(ts)
{ {
return; return;
} }
@ -3774,6 +3779,8 @@ std::ostream &operator<<(std::ostream &out, const RsDistribDummyMsg &msg)
return out; return out;
} }
bool p3GroupDistrib::locked_CheckNewMsgDummies(GroupInfo &grp, RsDistribMsg *msg, std::string id, bool historical) bool p3GroupDistrib::locked_CheckNewMsgDummies(GroupInfo &grp, RsDistribMsg *msg, std::string id, bool historical)
{ {
std::string threadId = msg->threadId; 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 << "p3GroupDistrib::locked_CheckNewMsgDummies() No ThreadId Msg, Adding DummyMsg";
std::cerr << std::endl; std::cerr << std::endl;
#endif #endif
locked_addDummyMsg(grp, threadId, "", threadId); locked_addDummyMsg(grp, threadId, "", threadId, msg->timestamp);
} }
else 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 << "p3GroupDistrib::locked_CheckNewMsgDummies() No ParentId Msg, Adding DummyMsg";
std::cerr << std::endl; std::cerr << std::endl;
#endif #endif
locked_addDummyMsg(grp, threadId, threadId, parentId); locked_addDummyMsg(grp, threadId, threadId, parentId, msg->timestamp);
} }
else else
{ {
@ -3855,7 +3862,7 @@ bool p3GroupDistrib::locked_CheckNewMsgDummies(GroupInfo &grp, RsDistribMsg *msg
return true; 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 #ifdef DISTRIB_DUMMYMSG_DEBUG
std::cerr << "p3GroupDistrib::locked_addDummyMsg(grpId:" << grp.grpId << ", threadId: " << threadId; 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! 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 #ifdef DISTRIB_DUMMYMSG_DEBUG
std::cerr << "p3GroupDistrib::locked_addDummyMsg() Adding Dummy Msg"; 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; std::cerr << std::endl;
#endif #endif
} }
locked_updateDummyChildTS(grp, parentId, ts); // NOTE both ChildTS functions should be merged.
return true; 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<std::string, RsDistribDummyMsg>::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() bool p3GroupDistrib::locked_printAllDummyMsgs()
{ {
#ifdef DISTRIB_DUMMYMSG_DEBUG #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<std::string> &msgIds)
{
#ifdef DISTRIB_DUMMYMSG_DEBUG
std::cerr << "p3GroupDistrib::getDummyParentMsgList(grpId:" << grpId << "," << pId << ")";
std::cerr << std::endl;
#endif
RsStackMutex stack(distribMtx); /************* STACK MUTEX ************/
std::map<std::string, GroupInfo>::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<std::string, RsDistribDummyMsg>::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<std::string, GroupInfo>::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<std::string, RsDistribDummyMsg>::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);
}

View File

@ -102,11 +102,14 @@ const uint32_t GROUP_KEY_DISTRIB_ADMIN = 0x0040;
class RsDistribDummyMsg class RsDistribDummyMsg
{ {
public: 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; } RsDistribDummyMsg() { return; }
std::string threadId; std::string threadId;
std::string parentId; std::string parentId;
std::string msgId; 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: public:
bool locked_CheckNewMsgDummies(GroupInfo &info, RsDistribMsg *msg, std::string id, bool historical); 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_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_printAllDummyMsgs();
bool locked_printDummyMsgs(GroupInfo &info); bool locked_printDummyMsgs(GroupInfo &info);
/* access the dummy msgs */
bool getDummyParentMsgList(std::string grpId, std::string pId, std::list<std::string> &msgIds);
RsDistribDummyMsg *locked_getGroupDummyMsg(std::string grpId, std::string msgId);
/* key cache functions - we use .... (not overloaded) /* key cache functions - we use .... (not overloaded)
*/ */

View File

@ -170,6 +170,9 @@ bool p3Forums::getForumThreadList(const std::string &fId, std::list<ThreadInfoSu
getParentMsgList(fId, "", msgIds); getParentMsgList(fId, "", msgIds);
std::list<std::string> msgDummyIds;
getDummyParentMsgList(fId, "", msgDummyIds);
RsStackMutex stack(distribMtx); /***** STACK LOCKED MUTEX *****/ RsStackMutex stack(distribMtx); /***** STACK LOCKED MUTEX *****/
for(it = msgIds.begin(); it != msgIds.end(); it++) for(it = msgIds.begin(); it != msgIds.end(); it++)
{ {
@ -196,6 +199,29 @@ bool p3Forums::getForumThreadList(const std::string &fId, std::list<ThreadInfoSu
msgs.push_back(tis); 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 = ""; // 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; return true;
} }
@ -206,6 +232,9 @@ bool p3Forums::getForumThreadMsgList(const std::string &fId, const std::string &
getParentMsgList(fId, pId, msgIds); getParentMsgList(fId, pId, msgIds);
std::list<std::string> msgDummyIds;
getDummyParentMsgList(fId, pId, msgDummyIds);
RsStackMutex stack(distribMtx); /***** STACK LOCKED MUTEX *****/ RsStackMutex stack(distribMtx); /***** STACK LOCKED MUTEX *****/
for(it = msgIds.begin(); it != msgIds.end(); it++) 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); 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; return true;
} }
@ -246,8 +298,28 @@ bool p3Forums::getForumMessage(const std::string &fId, const std::string &mId, F
RsDistribMsg *msg = locked_getGroupMsg(fId, mId); RsDistribMsg *msg = locked_getGroupMsg(fId, mId);
RsForumMsg *fmsg = dynamic_cast<RsForumMsg *>(msg); RsForumMsg *fmsg = dynamic_cast<RsForumMsg *>(msg);
if (!fmsg) 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.forumId = msg->grpId;
info.msgId = msg->msgId; info.msgId = msg->msgId;