fixed pinned post immediate update by adding the proper rsEvent notification when updating own group data. Should also help in circles

This commit is contained in:
csoler 2020-11-04 22:30:30 +01:00
parent 07775e5262
commit 1dd54317c7
5 changed files with 155 additions and 43 deletions

View File

@ -63,6 +63,72 @@ static const uint32_t INDEX_AUTHEN_ADMIN = 0x00000040; // admin key
#define GEN_EXCH_DEBUG 1 #define GEN_EXCH_DEBUG 1
// Data flow in RsGenExchange
//
// publishGroup()
// |
// +--- stores in mGrpsToPublish
//
// updateGroup()
// |
// +--- stores in mGroupUpdatePublish
//
// tick()
// |
// +--- processRecvdData();
// | |
// | +-- processRecvdGroups();
// | | |
// | | +---- mGroupPendingValidate
// | | |
// | | +---- acceptance => validateGrp() => check existance => store in mGroupUpdates
// | | |
// | | +--- validateNxsGrp()
// | |
// | +-- processRecvdMessages();
// | |
// | +-- performUpdateValidation(); // validates group updates in mGroupUpdates received from friends
// | |
// | +---- mGroupUpdates => updateValid() => store new groups
// | | |
// | | +--- stamp keys, check admin keys are the same, validateNxsGrp()
// | | |
// | +---- stores RsGxsGroupChange in mNotifications +--- data signature check
// |
// +--- publishGrps(); // creates signatures and data for locally created groups
// | |
// | +-- reads mGrpsToPublish, creates the group, clears mGrpsToPublish
// | |
// | +--- generateGroupKeys()
// | |
// | +--- serviceCreateGroup()
// | |
// | +--- createGroup()
// | |
// | +--- createGroupSignatures()
// |
// +--- processGroupUpdatePublish(); // goes through list of group updates to perform locally
// | |
// | +-- reads/deletes mGroupUpdatePublish, stores in mGrpsToPublish
// |
// +--- processGrpMetaChanges();
// | |
// | +-- updates mNotifications, calls mDataAccess
// |
// +--- processGroupDelete();
// |
// +--- publishMsgs();
// |
// +--- processMsgMetaChanges();
// | |
// | +-- updates mNotifications, calls mDataAccess
// |
// +--- processMessageDelete();
// |
// +--- mDataAccess->processRequests();
// |
// +--- processRoutingClues() ;
//
static const uint32_t MSG_CLEANUP_PERIOD = 60*59; // 59 minutes static const uint32_t MSG_CLEANUP_PERIOD = 60*59; // 59 minutes
static const uint32_t INTEGRITY_CHECK_PERIOD = 60*31; // 31 minutes static const uint32_t INTEGRITY_CHECK_PERIOD = 60*31; // 31 minutes
@ -2596,8 +2662,17 @@ void RsGenExchange::publishGrps()
RS_STACK_MUTEX(mGenMtx) ; RS_STACK_MUTEX(mGenMtx) ;
NxsGrpSignPendVect::iterator vit = mGrpsToPublish.begin(); NxsGrpSignPendVect::iterator vit = mGrpsToPublish.begin();
typedef std::pair<bool, RsGxsGroupId> GrpNote; typedef struct _GrpNote {
std::map<uint32_t, GrpNote> toNotify;
_GrpNote(bool success,bool is_update,const RsGxsGroupId& gid) : mSuccess(success),mIsUpdate(is_update),mGroupId(gid){}
bool mSuccess;
bool mIsUpdate;
RsGxsGroupId mGroupId;
} GrpNote;
std::map<uint32_t, GrpNote> toNotify; // used to notify about token processing if success or fails because of timeout
while( vit != mGrpsToPublish.end() ) while( vit != mGrpsToPublish.end() )
{ {
@ -2611,8 +2686,7 @@ void RsGenExchange::publishGrps()
if(now > (ggps.mStartTS + PENDING_SIGN_TIMEOUT) ) if(now > (ggps.mStartTS + PENDING_SIGN_TIMEOUT) )
{ {
// timed out // timed out
toNotify.insert(std::make_pair( toNotify.insert(std::make_pair( token, GrpNote(false,ggps.mIsUpdate, RsGxsGroupId())));
token, GrpNote(false, RsGxsGroupId())));
delete ggps.mItem; delete ggps.mItem;
vit = mGrpsToPublish.erase(vit); vit = mGrpsToPublish.erase(vit);
@ -2723,6 +2797,30 @@ void RsGenExchange::publishGrps()
computeHash(grp->grp, grp->metaData->mHash); computeHash(grp->grp, grp->metaData->mHash);
grp->metaData->mRecvTS = time(NULL); grp->metaData->mRecvTS = time(NULL);
// Also push in notifications. We do it here when we still have pointers on the old and new groups
RsGxsGroupChange *c = new RsGxsGroupChange(ggps.mIsUpdate?RsGxsNotify::TYPE_UPDATED:RsGxsNotify::TYPE_PUBLISHED, grpId,false);
c->mNewGroupItem = dynamic_cast<RsGxsGrpItem*>(mSerialiser->deserialise(grp->grp.bin_data,&grp->grp.bin_len));
c->mNewGroupItem->meta = *grp->metaData; // grp will be deleted because mDataStore will destroy it on update
if(ggps.mIsUpdate)
{
RsNxsGrpDataTemporaryMap oldGrpDatas;
oldGrpDatas.insert(std::make_pair(grpId, (RsNxsGrp*)NULL));
if(mDataStore->retrieveNxsGrps(oldGrpDatas,true,false) && oldGrpDatas.size() == 1)
{
auto oldGrp = oldGrpDatas[grpId];
c->mOldGroupItem = dynamic_cast<RsGxsGrpItem*>(mSerialiser->deserialise(oldGrp->grp.bin_data,&oldGrp->grp.bin_len));
c->mOldGroupItem->meta = *oldGrp->metaData;
}
}
mNotifications.push_back(c);
// now store (and incidently delete grp)
if(ggps.mIsUpdate) if(ggps.mIsUpdate)
mDataAccess->updateGroupData(grp); mDataAccess->updateGroupData(grp);
else else
@ -2766,8 +2864,7 @@ void RsGenExchange::publishGrps()
delete grp; delete grp;
delete grpItem; delete grpItem;
vit = mGrpsToPublish.erase(vit); vit = mGrpsToPublish.erase(vit);
toNotify.insert(std::make_pair( toNotify.insert(std::make_pair(token, GrpNote(false, ggps.mIsUpdate,grpId)));
token, GrpNote(false, grpId)));
} }
else if(create == CREATE_FAIL_TRY_LATER) else if(create == CREATE_FAIL_TRY_LATER)
@ -2790,30 +2887,21 @@ void RsGenExchange::publishGrps()
#endif #endif
// add to published to allow acknowledgement // add to published to allow acknowledgement
toNotify.insert(std::make_pair(token, toNotify.insert(std::make_pair(token, GrpNote(true,ggps.mIsUpdate,grpId)));
GrpNote(true,grpId)));
} }
} }
std::map<uint32_t, GrpNote>::iterator mit = toNotify.begin(); // toNotify contains the token and the group update/creation info. We parse it to
// - notify that group creation/update for a specific token was
std::list<RsGxsGroupId> grpChanged; for(auto mit=toNotify.begin(); mit != toNotify.end(); ++mit)
for(; mit != toNotify.end(); ++mit)
{ {
GrpNote& note = mit->second; GrpNote& note = mit->second;
RsTokenService::GxsRequestStatus status = RsTokenService::GxsRequestStatus status = note.mSuccess ? RsTokenService::COMPLETE : RsTokenService::FAILED;
note.first ? RsTokenService::COMPLETE
: RsTokenService::FAILED;
mGrpNotify.insert(std::make_pair(mit->first, note.second)); mGrpNotify.insert(std::make_pair(mit->first, note.mGroupId)); // always notify
mDataAccess->updatePublicRequestStatus(mit->first, status); mDataAccess->updatePublicRequestStatus(mit->first, status); // update the token request with the given status
if(note.first)
grpChanged.push_back(note.second);
} }
for(auto& groupId:grpChanged)
mNotifications.push_back(new RsGxsGroupChange(RsGxsNotify::TYPE_RECEIVED_NEW,groupId, true));
} }
// This is done off-mutex to avoid possible cross deadlocks with the net service. // This is done off-mutex to avoid possible cross deadlocks with the net service.
@ -2823,8 +2911,6 @@ void RsGenExchange::publishGrps()
mNetService->subscribeStatusChanged((*it),true) ; mNetService->subscribeStatusChanged((*it),true) ;
} }
uint32_t RsGenExchange::generatePublicToken() uint32_t RsGenExchange::generatePublicToken()
{ {
return mDataAccess->generatePublicToken(); return mDataAccess->generatePublicToken();
@ -3082,7 +3168,7 @@ void RsGenExchange::processRecvdMessages()
mNotifications.push_back(c); mNotifications.push_back(c);
} }
mDataStore->storeMessage(msgs_to_store); // we do that late because it destroys the items in msgs_to_store mDataStore->storeMessage(msgs_to_store); // All items will be destroyed later on, since msgs_to_store is a temporary map
} }
} }
@ -3317,7 +3403,6 @@ void RsGenExchange::performUpdateValidation()
} }
} }
// Warning: updateGroup will destroy the objects in grps. Dont use it afterwards!
mDataStore->updateGroup(grps); mDataStore->updateGroup(grps);
#ifdef GEN_EXCH_DEBUG #ifdef GEN_EXCH_DEBUG

View File

@ -116,6 +116,7 @@ enum class RsForumEventCode: uint8_t
STATISTICS_CHANGED = 0x07, /// suppliers and how many messages they have changed STATISTICS_CHANGED = 0x07, /// suppliers and how many messages they have changed
MODERATOR_LIST_CHANGED = 0x08, /// forum moderation list has changed. MODERATOR_LIST_CHANGED = 0x08, /// forum moderation list has changed.
SYNC_PARAMETERS_UPDATED = 0x0a, /// sync and storage times have changed SYNC_PARAMETERS_UPDATED = 0x0a, /// sync and storage times have changed
PINNED_POSTS_CHANGED = 0x0b, /// some posts where pinned or un-pinned
}; };
struct RsGxsForumEvent: RsEvent struct RsGxsForumEvent: RsEvent

View File

@ -683,8 +683,6 @@ void p3GxsCircles::notifyChanges(std::vector<RsGxsNotify *> &changes)
RsGxsCircleGroupItem *old_circle_grp_item = dynamic_cast<RsGxsCircleGroupItem*>(groupChange->mOldGroupItem); RsGxsCircleGroupItem *old_circle_grp_item = dynamic_cast<RsGxsCircleGroupItem*>(groupChange->mOldGroupItem);
RsGxsCircleGroupItem *new_circle_grp_item = dynamic_cast<RsGxsCircleGroupItem*>(groupChange->mNewGroupItem); RsGxsCircleGroupItem *new_circle_grp_item = dynamic_cast<RsGxsCircleGroupItem*>(groupChange->mNewGroupItem);
const RsGxsCircleId circle_id ( old_circle_grp_item->meta.mGroupId );
if(old_circle_grp_item == nullptr || new_circle_grp_item == nullptr) if(old_circle_grp_item == nullptr || new_circle_grp_item == nullptr)
{ {
RsErr() << __PRETTY_FUNCTION__ << " received GxsGroupUpdate item with mOldGroup and mNewGroup not of type RsGxsCircleGroupItem. This is inconsistent!" << std::endl; RsErr() << __PRETTY_FUNCTION__ << " received GxsGroupUpdate item with mOldGroup and mNewGroup not of type RsGxsCircleGroupItem. This is inconsistent!" << std::endl;
@ -692,6 +690,8 @@ void p3GxsCircles::notifyChanges(std::vector<RsGxsNotify *> &changes)
continue; continue;
} }
const RsGxsCircleId circle_id ( old_circle_grp_item->meta.mGroupId );
// First of all, we check if there is a difference between the old and new list of invited members // First of all, we check if there is a difference between the old and new list of invited members
for(auto& gxs_id: new_circle_grp_item->gxsIdSet.ids) for(auto& gxs_id: new_circle_grp_item->gxsIdSet.ids)

View File

@ -307,7 +307,7 @@ void p3GxsForums::notifyChanges(std::vector<RsGxsNotify *> &changes)
if(old_forum_grp_item == nullptr || new_forum_grp_item == nullptr) if(old_forum_grp_item == nullptr || new_forum_grp_item == nullptr)
{ {
RsErr() << __PRETTY_FUNCTION__ << " received GxsGroupUpdate item with mOldGroup and mNewGroup not of type RsGxsForumGroupItem. This is inconsistent!" << std::endl; RsErr() << __PRETTY_FUNCTION__ << " received GxsGroupUpdate item with mOldGroup and mNewGroup not of type RsGxsForumGroupItem or NULL. This is inconsistent!" << std::endl;
delete grpChange; delete grpChange;
continue; continue;
} }
@ -335,6 +335,29 @@ void p3GxsForums::notifyChanges(std::vector<RsGxsNotify *> &changes)
rsEvents->postEvent(ev); rsEvents->postEvent(ev);
} }
// check the list of pinned posts
std::list<RsGxsMessageId> added_pins, removed_pins;
for(auto& msg_id: new_forum_grp_item->mGroup.mPinnedPosts.ids)
if(old_forum_grp_item->mGroup.mPinnedPosts.ids.find(msg_id) == old_forum_grp_item->mGroup.mPinnedPosts.ids.end())
added_pins.push_back(msg_id);
for(auto& msg_id: old_forum_grp_item->mGroup.mPinnedPosts.ids)
if(new_forum_grp_item->mGroup.mPinnedPosts.ids.find(msg_id) == new_forum_grp_item->mGroup.mPinnedPosts.ids.end())
removed_pins.push_back(msg_id);
if(!added_pins.empty() || !removed_pins.empty())
{
auto ev = std::make_shared<RsGxsForumEvent>();
ev->mForumGroupId = new_forum_grp_item->meta.mGroupId;
ev->mForumEventCode = RsForumEventCode::PINNED_POSTS_CHANGED;
rsEvents->postEvent(ev);
}
} }
break; break;

View File

@ -386,6 +386,7 @@ void GxsForumThreadWidget::handleEvent_main_thread(std::shared_ptr<const RsEvent
case RsForumEventCode::NEW_FORUM: // [[fallthrough]]; case RsForumEventCode::NEW_FORUM: // [[fallthrough]];
case RsForumEventCode::UPDATED_MESSAGE: // [[fallthrough]]; case RsForumEventCode::UPDATED_MESSAGE: // [[fallthrough]];
case RsForumEventCode::NEW_MESSAGE: case RsForumEventCode::NEW_MESSAGE:
case RsForumEventCode::PINNED_POSTS_CHANGED:
case RsForumEventCode::SYNC_PARAMETERS_UPDATED: case RsForumEventCode::SYNC_PARAMETERS_UPDATED:
if(e->mForumGroupId == mForumGroup.mMeta.mGroupId) if(e->mForumGroupId == mForumGroup.mMeta.mGroupId)
updateDisplay(true); updateDisplay(true);
@ -1571,8 +1572,10 @@ void GxsForumThreadWidget::togglePinUpPost()
uint32_t token; uint32_t token;
rsGxsForums->updateGroup(token,mForumGroup); rsGxsForums->updateGroup(token,mForumGroup);
groupIdChanged(); // reloads all posts. We could also update the model directly, but the cost is so small now ;-) // We dont call this from here anymore. The update will be called by libretroshare using the rsEvent system when
updateDisplay(true) ; // the data is actually updated.
// groupIdChanged(); // reloads all posts. We could also update the model directly, but the cost is so small now ;-)
// updateDisplay(true) ;
} }
void GxsForumThreadWidget::createthread() void GxsForumThreadWidget::createthread()