From 5408427ea88376b24e0dd356ca3be41ccc6f9785 Mon Sep 17 00:00:00 2001 From: csoler Date: Tue, 17 Mar 2020 00:13:29 +0100 Subject: [PATCH] added auto delete active token feature to RsGxsIfaceHelper --- .../src/retroshare/rsgxsifacehelper.h | 139 ++++++++++++++++-- libretroshare/src/retroshare/rsidentity.h | 3 +- .../gui/gxsforums/GxsForumThreadWidget.cpp | 14 +- 3 files changed, 133 insertions(+), 23 deletions(-) diff --git a/libretroshare/src/retroshare/rsgxsifacehelper.h b/libretroshare/src/retroshare/rsgxsifacehelper.h index 99d029361..c04f13306 100644 --- a/libretroshare/src/retroshare/rsgxsifacehelper.h +++ b/libretroshare/src/retroshare/rsgxsifacehelper.h @@ -38,14 +38,25 @@ * To properly fix the API design many changes with the implied chain reactions * are necessary, so at this point this workaround seems acceptable. */ -struct RsGxsIfaceHelper + +enum class TokenRequestType: uint8_t { + GROUP_INFO = 0x01, + MSG_INFO = 0x02, + MSG_RELATED_INFO = 0x03, + GROUP_STATISTICS = 0x04, + SERVICE_STATISTICS = 0x05, +}; + +class RsGxsIfaceHelper +{ +public: /*! * @param gxs handle to RsGenExchange instance of service (Usually the * service class itself) */ RsGxsIfaceHelper(RsGxsIface& gxs) : - mGxs(gxs), mTokenService(*gxs.getTokenService()) {} + mGxs(gxs), mTokenService(*gxs.getTokenService()),mMtx("GxsIfaceHelper") {} ~RsGxsIfaceHelper(){} @@ -235,28 +246,80 @@ struct RsGxsIfaceHelper /// @see RsTokenService::requestGroupInfo bool requestGroupInfo( uint32_t& token, const RsTokReqOptions& opts, const std::list &groupIds ) - { return mTokenService.requestGroupInfo(token, 0, opts, groupIds); } + { + cancelActiveRequestTokens(TokenRequestType::GROUP_INFO); + + if( mTokenService.requestGroupInfo(token, 0, opts, groupIds)) + { + RS_STACK_MUTEX(mMtx); + mActiveTokens[token]=TokenRequestType::GROUP_INFO; + locked_dumpTokens(); + return true; + } + else + return false; + } /// @see RsTokenService::requestGroupInfo bool requestGroupInfo(uint32_t& token, const RsTokReqOptions& opts) - { return mTokenService.requestGroupInfo(token, 0, opts); } + { + cancelActiveRequestTokens(TokenRequestType::GROUP_INFO); + + if( mTokenService.requestGroupInfo(token, 0, opts)) + { + RS_STACK_MUTEX(mMtx); + mActiveTokens[token]=TokenRequestType::GROUP_INFO; + locked_dumpTokens(); + return true; + } + else + return false; + } /// @see RsTokenService::requestMsgInfo bool requestMsgInfo( uint32_t& token, const RsTokReqOptions& opts, const GxsMsgReq& msgIds ) - { return mTokenService.requestMsgInfo(token, 0, opts, msgIds); } + { + if(mTokenService.requestMsgInfo(token, 0, opts, msgIds)) + { + RS_STACK_MUTEX(mMtx); + mActiveTokens[token]=TokenRequestType::MSG_INFO; + locked_dumpTokens(); + return true; + } + else + return false; + } /// @see RsTokenService::requestMsgInfo - bool requestMsgInfo( - uint32_t& token, const RsTokReqOptions& opts, - const std::list& grpIds ) - { return mTokenService.requestMsgInfo(token, 0, opts, grpIds); } + bool requestMsgInfo( uint32_t& token, const RsTokReqOptions& opts, const std::list& grpIds ) + { + if(mTokenService.requestMsgInfo(token, 0, opts, grpIds)) + { + RS_STACK_MUTEX(mMtx); + mActiveTokens[token]=TokenRequestType::MSG_INFO; + locked_dumpTokens(); + return true; + } + else + return false; + } /// @see RsTokenService::requestMsgRelatedInfo bool requestMsgRelatedInfo( uint32_t& token, const RsTokReqOptions& opts, const std::vector& msgIds ) - { return mTokenService.requestMsgRelatedInfo(token, 0, opts, msgIds); } + { + if( mTokenService.requestMsgRelatedInfo(token, 0, opts, msgIds)) + { + RS_STACK_MUTEX(mMtx); + mActiveTokens[token]=TokenRequestType::MSG_RELATED_INFO; + locked_dumpTokens(); + return true; + } + else + return false; + } /** * @jsonapi{development} @@ -267,14 +330,46 @@ struct RsGxsIfaceHelper /// @see RsTokenService::requestServiceStatistic void requestServiceStatistic(uint32_t& token) - { mTokenService.requestServiceStatistic(token); } + { + mTokenService.requestServiceStatistic(token); + + RS_STACK_MUTEX(mMtx); + mActiveTokens[token]=TokenRequestType::SERVICE_STATISTICS; + + locked_dumpTokens(); + } /// @see RsTokenService::requestGroupStatistic void requestGroupStatistic(uint32_t& token, const RsGxsGroupId& grpId) - { mTokenService.requestGroupStatistic(token, grpId); } + { + mTokenService.requestGroupStatistic(token, grpId); + + RS_STACK_MUTEX(mMtx); + mActiveTokens[token]=TokenRequestType::GROUP_STATISTICS; + locked_dumpTokens(); + } + + bool cancelActiveRequestTokens(TokenRequestType type) + { + RS_STACK_MUTEX(mMtx); + for(auto it = mActiveTokens.begin();it!=mActiveTokens.end();) + if(it->second == type) + { + mTokenService.cancelRequest(it->first); + it = mActiveTokens.erase(it); + } + return true; + } /// @see RsTokenService::cancelRequest - bool cancelRequest(uint32_t token) { return mTokenService.cancelRequest(token); } + bool cancelRequest(uint32_t token) + { + { + RS_STACK_MUTEX(mMtx); + mActiveTokens.erase(token); + } + return mTokenService.cancelRequest(token); + } /** * @deprecated @@ -294,7 +389,7 @@ protected: */ RsTokenService::GxsRequestStatus waitToken( uint32_t token, - std::chrono::milliseconds maxWait = std::chrono::milliseconds(2000), + std::chrono::milliseconds maxWait = std::chrono::milliseconds(10000), std::chrono::milliseconds checkEvery = std::chrono::milliseconds(20), bool auto_delete_if_unsuccessful=true) { @@ -302,6 +397,11 @@ protected: if(res != RsTokenService::COMPLETE && auto_delete_if_unsuccessful) cancelRequest(token); + else + { + RS_STACK_MUTEX(mMtx); + mActiveTokens.erase(token); + } return res; } @@ -309,4 +409,15 @@ protected: private: RsGxsIface& mGxs; RsTokenService& mTokenService; + RsMutex mMtx; + + std::map mActiveTokens; + + void locked_dumpTokens() + { + std::cerr << "Active tokens (this=" << (void*)this << "): " ; + for(auto it: mActiveTokens) + std::cerr << std::dec << it.first << " (" << static_cast(it.second) << ") " ; + std::cerr << std::endl; + } }; diff --git a/libretroshare/src/retroshare/rsidentity.h b/libretroshare/src/retroshare/rsidentity.h index d30e55978..afd8f5544 100644 --- a/libretroshare/src/retroshare/rsidentity.h +++ b/libretroshare/src/retroshare/rsidentity.h @@ -383,8 +383,9 @@ struct RsIdentityDetails : RsSerializable /** The Main Interface Class for GXS people identities */ -struct RsIdentity : RsGxsIfaceHelper +class RsIdentity: public RsGxsIfaceHelper { +public: explicit RsIdentity(RsGxsIface& gxs) : RsGxsIfaceHelper(gxs) {} /** diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp index b071673b3..e57dbe040 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp +++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp @@ -1444,7 +1444,7 @@ void GxsForumThreadWidget::async_msg_action(const MsgMethod &action) if(!rsGxsForums->getForumContent(groupId(),msgs_to_request,msgs)) { - std::cerr << __PRETTY_FUNCTION__ << " failed to retrieve forum group info for forum " << groupId() << std::endl; + std::cerr << __PRETTY_FUNCTION__ << " failed to retrieve forum message info for forum " << groupId() << " and thread " << mThreadId << std::endl; return; } @@ -1719,7 +1719,7 @@ void GxsForumThreadWidget::updateGroupData() // 2 - sort the messages into a proper hierarchy - RsGxsForumGroup *group = new RsGxsForumGroup(groups[0]); // we use a pointer in order to avoid group deletion while we're in the thread. + RsGxsForumGroup group(groups[0]); // we use a copy to share the object in order to avoid group deletion while we're in the thread. // 3 - update the model in the UI thread. @@ -1729,8 +1729,7 @@ void GxsForumThreadWidget::updateGroupData() * thread, for example to update the data model with new information * after a blocking call to RetroShare API complete */ - mForumGroup = *group; - delete group; + mForumGroup = group; ui->threadTreeWidget->setColumnHidden(RsGxsForumModel::COLUMN_THREAD_DISTRIBUTION, !IS_GROUP_PGP_KNOWN_AUTHED(mForumGroup.mMeta.mSignFlags) && !(IS_GROUP_PGP_AUTHED(mForumGroup.mMeta.mSignFlags))); ui->subscribeToolButton->setHidden(IS_GROUP_SUBSCRIBED(mForumGroup.mMeta.mSubscribeFlags)) ; @@ -1759,7 +1758,7 @@ void GxsForumThreadWidget::updateMessageData(const RsGxsMessageId& msgId) if(!rsGxsForums->getForumContent(groupId(),msgs_to_request,msgs)) { - std::cerr << __PRETTY_FUNCTION__ << " failed to retrieve forum group info for forum " << groupId() << std::endl; + std::cerr << __PRETTY_FUNCTION__ << " failed to retrieve message info for forum " << groupId() << " and MsgId " << msgId << std::endl; return; } @@ -1778,7 +1777,7 @@ void GxsForumThreadWidget::updateMessageData(const RsGxsMessageId& msgId) // 2 - sort the messages into a proper hierarchy - RsGxsForumMsg *msg = new RsGxsForumMsg(msgs[0]); + RsGxsForumMsg msg(msgs[0]); // 3 - update the model in the UI thread. @@ -1788,9 +1787,8 @@ void GxsForumThreadWidget::updateMessageData(const RsGxsMessageId& msgId) * thread, for example to update the data model with new information * after a blocking call to RetroShare API complete */ - insertMessageData(*msg); + insertMessageData(msg); - delete msg; ui->threadTreeWidget->setColumnHidden(RsGxsForumModel::COLUMN_THREAD_DISTRIBUTION, !IS_GROUP_PGP_KNOWN_AUTHED(mForumGroup.mMeta.mSignFlags) && !(IS_GROUP_PGP_AUTHED(mForumGroup.mMeta.mSignFlags))); ui->subscribeToolButton->setHidden(IS_GROUP_SUBSCRIBED(mForumGroup.mMeta.mSubscribeFlags)) ; }, this );