diff --git a/src/gxs/rsdataservice.cc b/src/gxs/rsdataservice.cc index 2f2940541..cc215dc14 100644 --- a/src/gxs/rsdataservice.cc +++ b/src/gxs/rsdataservice.cc @@ -26,6 +26,10 @@ * #define RS_DATA_SERVICE_DEBUG_CACHE 1 ****/ +#define RS_DATA_SERVICE_DEBUG 1 +#define RS_DATA_SERVICE_DEBUG_TIME 1 +#define RS_DATA_SERVICE_DEBUG_CACHE 1 + #include #include #include @@ -1312,7 +1316,7 @@ int RsDataService::retrieveGxsMsgMetaData(const GxsMsgReq& reqIds, GxsMsgMetaRes { locked_retrieveMsgMeta(c, metaSet); #ifdef RS_DATA_SERVICE_DEBUG_CACHE - std::cerr << "Retrieving (all) Msg metadata grpId=" << grpId << ", " << std::dec << metaSet.size() << " messages" << std::endl; + std::cerr << mDbName << ": Retrieving (all) Msg metadata grpId=" << grpId << ", " << std::dec << metaSet.size() << " messages" << std::endl; #endif } }else{ @@ -1329,7 +1333,7 @@ int RsDataService::retrieveGxsMsgMetaData(const GxsMsgReq& reqIds, GxsMsgMetaRes { locked_retrieveMsgMeta(c, metaSet); #ifdef RS_DATA_SERVICE_DEBUG_CACHE - std::cerr << "Retrieving Msg metadata grpId=" << grpId << ", " << std::dec << metaSet.size() << " messages" << std::endl; + std::cerr << mDbName << ": Retrieving Msg metadata grpId=" << grpId << ", " << std::dec << metaSet.size() << " messages" << std::endl; #endif } } @@ -1343,6 +1347,7 @@ int RsDataService::retrieveGxsMsgMetaData(const GxsMsgReq& reqIds, GxsMsgMetaRes } #ifdef RS_DATA_SERVICE_DEBUG_TIME + if(mDbName==std::string("gxsforums_db")) std::cerr << "RsDataService::retrieveGxsMsgMetaData() " << mDbName << ", Requests: " << reqIds.size() << ", Results: " << resultCount << ", Time: " << timer.duration() << std::endl; #endif @@ -1413,7 +1418,7 @@ int RsDataService::retrieveGxsGrpMetaData(RsGxsGrpMetaTemporaryMap& grp) { grp[g->mGroupId] = g; #ifdef RS_DATA_SERVICE_DEBUG_CACHE - std::cerr << (void *)this << ": Retrieving (all) Grp metadata grpId=" << g->mGroupId << std::endl; + std::cerr << (void *)this << " " << mDbName << ": Retrieving (all) Grp metadata grpId=" << g->mGroupId << std::endl; #endif } valid = c->moveToNext(); @@ -1440,14 +1445,14 @@ int RsDataService::retrieveGxsGrpMetaData(RsGxsGrpMetaTemporaryMap& grp) if(itt != mGrpMetaDataCache.end()) { #ifdef RS_DATA_SERVICE_DEBUG_CACHE - std::cerr << "Retrieving Grp metadata grpId=" << mit->first << " from cache!" << std::endl; + std::cerr << mDbName << ": Retrieving Grp metadata grpId=" << mit->first << " from cache!" << std::endl; #endif grp[mit->first] = itt->second ; } else { #ifdef RS_DATA_SERVICE_DEBUG_CACHE - std::cerr << "Retrieving Grp metadata grpId=" << mit->first ; + std::cerr << mDbName << ": Retrieving Grp metadata grpId=" << mit->first ; #endif const RsGxsGroupId& grpId = mit->first; diff --git a/src/gxs/rsgenexchange.cc b/src/gxs/rsgenexchange.cc index ff54d48a1..c7c274fa4 100644 --- a/src/gxs/rsgenexchange.cc +++ b/src/gxs/rsgenexchange.cc @@ -3461,20 +3461,32 @@ bool RsGenExchange::exportGroupBase64( if(groupId.isNull()) return failure("groupId cannot be null"); + // We have no blocking API here, so we need to make a blocking request manually. const std::list groupIds({groupId}); RsTokReqOptions opts; opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; uint32_t token; - mDataAccess->requestGroupInfo( - token, RS_TOKREQ_ANSTYPE_DATA, opts, groupIds); - RsTokenService::GxsRequestStatus wtStatus = mDataAccess->waitToken(token); - if(wtStatus != RsTokenService::COMPLETE) - return failure( "waitToken(...) failed with: " + - std::to_string(wtStatus) ); + mDataAccess->requestGroupInfo( token, RS_TOKREQ_ANSTYPE_DATA, opts, groupIds); + + // provide a sync response: actually wait for the token. + std::chrono::milliseconds maxWait = std::chrono::milliseconds(10000); + std::chrono::milliseconds checkEvery = std::chrono::milliseconds(100); + + auto timeout = std::chrono::steady_clock::now() + maxWait; // wait for 10 secs at most + auto st = mDataAccess->requestStatus(token); + + while( !(st == RsTokenService::FAILED || st >= RsTokenService::COMPLETE) && std::chrono::steady_clock::now() < timeout ) + { + std::this_thread::sleep_for(checkEvery); + st = mDataAccess->requestStatus(token); + } + if(st != RsTokenService::COMPLETE) + return failure( "waitToken(...) failed with: " + std::to_string(st) ); uint8_t* buf = nullptr; uint32_t size; RsGxsGroupId grpId; + if(!getSerializedGroupData(token, grpId, buf, size)) return failure("failed retrieving GXS data"); diff --git a/src/gxs/rsgenexchange.h b/src/gxs/rsgenexchange.h index 49fd8b2e2..840dc97b3 100644 --- a/src/gxs/rsgenexchange.h +++ b/src/gxs/rsgenexchange.h @@ -726,7 +726,7 @@ public: virtual void setSyncPeriod(const RsGxsGroupId& grpId,uint32_t age_in_secs) ; virtual bool getGroupNetworkStats(const RsGxsGroupId& grpId,RsGroupNetworkStats& stats); - uint16_t serviceType() const { return mServType ; } + uint16_t serviceType() const override { return mServType ; } uint32_t serviceFullType() const { return RsServiceInfo::RsServiceInfoUIn16ToFullServiceId(mServType); } virtual RsReputationLevel minReputationForForwardingMessages( diff --git a/src/gxs/rsgxsdataaccess.cc b/src/gxs/rsgxsdataaccess.cc index 59c828e60..373d9a872 100644 --- a/src/gxs/rsgxsdataaccess.cc +++ b/src/gxs/rsgxsdataaccess.cc @@ -30,6 +30,8 @@ * #define DATA_DEBUG 1 **********/ +#define DATA_DEBUG 1 + RsGxsDataAccess::RsGxsDataAccess(RsGeneralDataService* ds) : mDataStore(ds), mDataMutex("RsGxsDataAccess"), mNextToken(0) {} diff --git a/src/retroshare/rsgxschannels.h b/src/retroshare/rsgxschannels.h index 6f14552c2..0134ada9c 100644 --- a/src/retroshare/rsgxschannels.h +++ b/src/retroshare/rsgxschannels.h @@ -45,11 +45,10 @@ class RsGxsChannels; extern RsGxsChannels* rsGxsChannels; -struct RsGxsChannelGroup : RsSerializable +struct RsGxsChannelGroup : RsSerializable, RsGxsGenericGroupData { RsGxsChannelGroup() : mAutoDownload(false) {} - RsGroupMetaData mMeta; std::string mDescription; RsGxsImage mImage; @@ -399,6 +398,15 @@ public: virtual bool subscribeToChannel( const RsGxsGroupId& channelId, bool subscribe ) = 0; + /** + * \brief Retrieve statistics about the given channel + * @jsonapi{development} + * \param[in] channelId Id of the channel group + * \param[out] stat Statistics structure + * \return + */ + virtual bool getChannelStatistics(const RsGxsGroupId& channelId,GxsGroupStatistic& stat) =0; + /** * @brief Request remote channels search * @jsonapi{development} diff --git a/src/retroshare/rsgxsforums.h b/src/retroshare/rsgxsforums.h index f9a54ebc4..4e368792e 100644 --- a/src/retroshare/rsgxsforums.h +++ b/src/retroshare/rsgxsforums.h @@ -54,11 +54,8 @@ static const uint32_t RS_GXS_FORUM_MSG_FLAGS_MODERATED = 0x00000001; #define IS_FORUM_MSG_MODERATION(flags) (flags & RS_GXS_FORUM_MSG_FLAGS_MODERATED) -struct RsGxsForumGroup : RsSerializable +struct RsGxsForumGroup : RsSerializable, RsGxsGenericGroupData { - /** Forum GXS metadata */ - RsGroupMetaData mMeta; - /** @brief Forum desciption */ std::string mDescription; @@ -222,6 +219,15 @@ public: */ virtual bool getForumsSummaries(std::list& forums) = 0; + /** + * @brief returns statistics about a particular forum + * @jsonapi{development} + * @param[in] forumId Id of the forum + * @param[out] stat statistics struct + * @return false when the object doesn't exist or when the timeout is reached requesting the data + */ + virtual bool getForumStatistics(const RsGxsGroupId& forumId,GxsGroupStatistic& stat)=0; + /** * @brief Get forums information (description, thumbnail...). * Blocking API. @@ -364,5 +370,5 @@ public: RS_DEPRECATED_FOR(createMessage) virtual bool createMsg(uint32_t &token, RsGxsForumMsg &msg) = 0; RS_DEPRECATED_FOR(editForum) - virtual bool updateGroup(uint32_t &token, RsGxsForumGroup &group) = 0; + virtual bool updateGroup(uint32_t &token, const RsGxsForumGroup &group) = 0; }; diff --git a/src/retroshare/rsgxsiface.h b/src/retroshare/rsgxsiface.h index 54a27656d..7bb6bba28 100644 --- a/src/retroshare/rsgxsiface.h +++ b/src/retroshare/rsgxsiface.h @@ -110,6 +110,12 @@ struct RsGxsChanges : RsEvent */ struct RsGxsIface { + /*! + * \brief serviceType + * \return The 16-bits service type. See @serialiser/rsserviceids.h + */ + virtual uint16_t serviceType() const =0; + /*! * Gxs services should call this for automatic handling of * changes, send diff --git a/src/retroshare/rsgxsifacehelper.h b/src/retroshare/rsgxsifacehelper.h index 99d029361..2a9b5bba3 100644 --- a/src/retroshare/rsgxsifacehelper.h +++ b/src/retroshare/rsgxsifacehelper.h @@ -26,6 +26,7 @@ #include #include "retroshare/rsgxsiface.h" +#include "retroshare/rsservicecontrol.h" #include "retroshare/rsreputations.h" #include "rsgxsflags.h" #include "util/rsdeprecate.h" @@ -38,14 +39,26 @@ * 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, + NO_KILL_TYPE = 0x06, +}; + +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(){} @@ -233,30 +246,81 @@ struct RsGxsIfaceHelper } /// @see RsTokenService::requestGroupInfo - bool requestGroupInfo( uint32_t& token, const RsTokReqOptions& opts, - const std::list &groupIds ) - { return mTokenService.requestGroupInfo(token, 0, opts, groupIds); } + bool requestGroupInfo( uint32_t& token, const RsTokReqOptions& opts, const std::list &groupIds, bool high_priority_request = false ) + { + cancelActiveRequestTokens(TokenRequestType::GROUP_INFO); + + if( mTokenService.requestGroupInfo(token, 0, opts, groupIds)) + { + RS_STACK_MUTEX(mMtx); + mActiveTokens[token]=high_priority_request? (TokenRequestType::NO_KILL_TYPE) : (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); } + bool requestGroupInfo(uint32_t& token, const RsTokReqOptions& opts, bool high_priority_request = false) + { + cancelActiveRequestTokens(TokenRequestType::GROUP_INFO); + + if( mTokenService.requestGroupInfo(token, 0, opts)) + { + RS_STACK_MUTEX(mMtx); + mActiveTokens[token]=high_priority_request? (TokenRequestType::NO_KILL_TYPE) : (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 +331,50 @@ 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); } + bool requestGroupStatistic(uint32_t& token, const RsGxsGroupId& grpId) + { + mTokenService.requestGroupStatistic(token, grpId); + + RS_STACK_MUTEX(mMtx); + mActiveTokens[token]=TokenRequestType::GROUP_STATISTICS; + locked_dumpTokens(); + return true; + } + + 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); + } + else + ++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,19 +394,80 @@ protected: */ RsTokenService::GxsRequestStatus waitToken( uint32_t token, - std::chrono::milliseconds maxWait = std::chrono::milliseconds(2000), - std::chrono::milliseconds checkEvery = std::chrono::milliseconds(20), + std::chrono::milliseconds maxWait = std::chrono::milliseconds(20000), + std::chrono::milliseconds checkEvery = std::chrono::milliseconds(100), bool auto_delete_if_unsuccessful=true) { - RsTokenService::GxsRequestStatus res = mTokenService.waitToken(token, maxWait, checkEvery); + #if defined(__ANDROID__) && (__ANDROID_API__ < 24) + auto wkStartime = std::chrono::steady_clock::now(); + int maxWorkAroundCnt = 10; +LLwaitTokenBeginLabel: +#endif + auto timeout = std::chrono::steady_clock::now() + maxWait; + auto st = requestStatus(token); - if(res != RsTokenService::COMPLETE && auto_delete_if_unsuccessful) + while( !(st == RsTokenService::FAILED || st >= RsTokenService::COMPLETE) && std::chrono::steady_clock::now() < timeout ) + { + std::this_thread::sleep_for(checkEvery); + st = requestStatus(token); + } + if(st != RsTokenService::COMPLETE && auto_delete_if_unsuccessful) cancelRequest(token); - return res; +#if defined(__ANDROID__) && (__ANDROID_API__ < 24) + /* Work around for very slow/old android devices, we don't expect this + * to be necessary on newer devices. If it take unreasonably long + * something worser is already happening elsewere and we return anyway. + */ + if( st > RsTokenService::FAILED && st < RsTokenService::COMPLETE + && maxWorkAroundCnt-- > 0 ) + { + maxWait *= 10; + checkEvery *= 3; + Dbg3() << __PRETTY_FUNCTION__ << " Slow Android device " + << " workaround st: " << st + << " maxWorkAroundCnt: " << maxWorkAroundCnt + << " maxWait: " << maxWait.count() + << " checkEvery: " << checkEvery.count() << std::endl; + goto LLwaitTokenBeginLabel; + } + Dbg3() << __PRETTY_FUNCTION__ << " lasted: " + << std::chrono::duration_cast( + std::chrono::steady_clock::now() - wkStartime ).count() + << "ms" << std::endl; + +#endif + + { + RS_STACK_MUTEX(mMtx); + mActiveTokens.erase(token); + } + + return st; } private: RsGxsIface& mGxs; RsTokenService& mTokenService; + RsMutex mMtx; + + std::map mActiveTokens; + + void locked_dumpTokens() + { + uint16_t service_id = mGxs.serviceType(); + + uint32_t count[7] = {0}; + + std::cerr << "Service 0x0" << std::hex << service_id + << " (" << rsServiceControl->getServiceName(RsServiceInfo::RsServiceInfoUIn16ToFullServiceId(service_id)) + << ") this=0x" << (void*)this << ") Active tokens (per type): " ; + + for(auto& it: mActiveTokens) // let's count how many token of each type we've got. + ++count[static_cast(it.second)]; + + for(uint32_t i=0;i<7;++i) + std::cerr /* << i << ":" */ << count[i] << " "; + std::cerr << std::endl; + } }; diff --git a/src/retroshare/rsgxsifacetypes.h b/src/retroshare/rsgxsifacetypes.h index d0e6e0372..36b224c01 100644 --- a/src/retroshare/rsgxsifacetypes.h +++ b/src/retroshare/rsgxsifacetypes.h @@ -118,8 +118,15 @@ struct RsGroupMetaData : RsSerializable } }; +// This is the parent class of all interface-level GXS group data. Derived classes +// will include service-specific information, such as icon, description, etc +struct RsGxsGenericGroupData +{ + virtual ~RsGxsGenericGroupData() = default; // making the type polymorphic + RsGroupMetaData mMeta; +}; struct RsMsgMetaData : RsSerializable { diff --git a/src/retroshare/rsidentity.h b/src/retroshare/rsidentity.h index d30e55978..afd8f5544 100644 --- a/src/retroshare/rsidentity.h +++ b/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/src/retroshare/rsposted.h b/src/retroshare/rsposted.h index 474136466..11f7ac643 100644 --- a/src/retroshare/rsposted.h +++ b/src/retroshare/rsposted.h @@ -40,9 +40,8 @@ class RsPosted; */ extern RsPosted* rsPosted; -struct RsPostedGroup +struct RsPostedGroup: RsGxsGenericGroupData { - RsGroupMetaData mMeta; std::string mDescription; RsGxsImage mGroupImage; }; @@ -150,12 +149,20 @@ public: const std::list& boardsIds, std::vector& boardsInfo ) = 0; + virtual bool getBoardsSummaries(std::list& groupInfo) =0; + virtual bool getBoardContent( const RsGxsGroupId& boardId, const std::set& contentsIds, std::vector& posts, std::vector& comments ) = 0; + virtual bool editBoard(RsPostedGroup& board) =0; + + virtual bool createBoard(RsPostedGroup& board) =0; + + virtual bool getBoardStatistics(const RsGxsGroupId& boardId,GxsGroupStatistic& stat) =0; + enum RS_DEPRECATED RankType {TopRankType, HotRankType, NewRankType }; RS_DEPRECATED_FOR(getBoardsInfo) diff --git a/src/retroshare/rstokenservice.h b/src/retroshare/rstokenservice.h index e48df29ad..7f801927f 100644 --- a/src/retroshare/rstokenservice.h +++ b/src/retroshare/rstokenservice.h @@ -222,6 +222,7 @@ public: */ virtual bool cancelRequest(const uint32_t &token) = 0; +#ifdef TO_REMOVE /** * Block caller while request is being processed. * Useful for blocking API implementation. @@ -231,8 +232,8 @@ public: */ RsTokenService::GxsRequestStatus waitToken( uint32_t token, - std::chrono::milliseconds maxWait = std::chrono::milliseconds(500), - std::chrono::milliseconds checkEvery = std::chrono::milliseconds(2), + std::chrono::milliseconds maxWait = std::chrono::milliseconds(10000), + std::chrono::milliseconds checkEvery = std::chrono::milliseconds(20), bool auto_delete_if_unsuccessful=true) { #if defined(__ANDROID__) && (__ANDROID_API__ < 24) @@ -276,6 +277,7 @@ LLwaitTokenBeginLabel: return st; } +#endif RS_SET_CONTEXT_DEBUG_LEVEL(2) }; diff --git a/src/services/p3gxschannels.cc b/src/services/p3gxschannels.cc index 2d141f57e..93c85d8d0 100644 --- a/src/services/p3gxschannels.cc +++ b/src/services/p3gxschannels.cc @@ -1033,18 +1033,35 @@ bool p3GxsChannels::getChannelsSummaries( return getGroupSummary(token, channels); } -bool p3GxsChannels::getChannelsInfo( - const std::list& chanIds, - std::vector& channelsInfo ) +bool p3GxsChannels::getChannelsInfo( const std::list& chanIds, std::vector& channelsInfo ) { uint32_t token; RsTokReqOptions opts; opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - if( !requestGroupInfo(token, opts, chanIds) - || waitToken(token) != RsTokenService::COMPLETE ) return false; + + if(chanIds.empty()) + { + if( !requestGroupInfo(token, opts) || waitToken(token) != RsTokenService::COMPLETE ) + return false; + } + else + { + if( !requestGroupInfo(token, opts, chanIds) || waitToken(token) != RsTokenService::COMPLETE ) + return false; + } + return getGroupData(token, channelsInfo) && !channelsInfo.empty(); } +bool p3GxsChannels::getChannelStatistics(const RsGxsGroupId& channelId,GxsGroupStatistic& stat) +{ + uint32_t token; + if(!RsGxsIfaceHelper::requestGroupStatistic(token, channelId) || waitToken(token) != RsTokenService::COMPLETE) + return false; + + return RsGenExchange::getGroupStatistic(token,stat); +} + bool p3GxsChannels::getContentSummaries( const RsGxsGroupId& channelId, std::vector& summaries ) { diff --git a/src/services/p3gxschannels.h b/src/services/p3gxschannels.h index c83fbc4df..81eb75f5f 100644 --- a/src/services/p3gxschannels.h +++ b/src/services/p3gxschannels.h @@ -196,6 +196,9 @@ virtual bool ExtraFileRemove(const RsFileHash &hash); const RsGxsGroupId& channelId, std::vector& summaries ) override; + /// Implementation of @see RsGxsChannels::getChannelStatistics + bool getChannelStatistics(const RsGxsGroupId& channelId,GxsGroupStatistic& stat) override; + /// Implementation of @see RsGxsChannels::createChannelV2 bool createChannelV2( const std::string& name, const std::string& description, diff --git a/src/services/p3gxsforums.cc b/src/services/p3gxsforums.cc index 5a6b0e568..c7f3fddcf 100644 --- a/src/services/p3gxsforums.cc +++ b/src/services/p3gxsforums.cc @@ -666,15 +666,22 @@ bool p3GxsForums::getForumsSummaries( std::list& forums ) return getGroupSummary(token, forums); } -bool p3GxsForums::getForumsInfo( - const std::list& forumIds, - std::vector& forumsInfo ) +bool p3GxsForums::getForumsInfo( const std::list& forumIds, std::vector& forumsInfo ) { uint32_t token; RsTokReqOptions opts; opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - if( !requestGroupInfo(token, opts, forumIds) - || waitToken(token,std::chrono::milliseconds(5000)) != RsTokenService::COMPLETE ) return false; + + if(forumIds.empty()) + { + if( !requestGroupInfo(token, opts) || waitToken(token,std::chrono::milliseconds(5000)) != RsTokenService::COMPLETE ) + return false; + } + else + { + if( !requestGroupInfo(token, opts, forumIds, forumIds.size()==1) || waitToken(token,std::chrono::milliseconds(5000)) != RsTokenService::COMPLETE ) + return false; + } return getGroupData(token, forumsInfo); } @@ -812,7 +819,16 @@ bool p3GxsForums::createGroup(uint32_t &token, RsGxsForumGroup &group) return true; } -bool p3GxsForums::updateGroup(uint32_t &token, RsGxsForumGroup &group) +bool p3GxsForums::getForumStatistics(const RsGxsGroupId& ForumId,GxsGroupStatistic& stat) +{ + uint32_t token; + if(!RsGxsIfaceHelper::requestGroupStatistic(token, ForumId) || waitToken(token) != RsTokenService::COMPLETE) + return false; + + return RsGenExchange::getGroupStatistic(token,stat); +} + +bool p3GxsForums::updateGroup(uint32_t &token, const RsGxsForumGroup &group) { std::cerr << "p3GxsForums::updateGroup()" << std::endl; diff --git a/src/services/p3gxsforums.h b/src/services/p3gxsforums.h index ae2bf74bf..c95acf447 100644 --- a/src/services/p3gxsforums.h +++ b/src/services/p3gxsforums.h @@ -94,6 +94,9 @@ public: const std::list& forumIds, std::vector& forumsInfo ); + /// Implementation of @see RsGxsForums::getForumStatistics + bool getForumStatistics(const RsGxsGroupId& ForumId,GxsGroupStatistic& stat) override; + /// @see RsGxsForums::getForumMsgMetaData virtual bool getForumMsgMetaData(const RsGxsGroupId& forumId, std::vector& msg_metas) ; @@ -125,13 +128,16 @@ public: std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) ) override; - virtual bool getGroupData(const uint32_t &token, std::vector &groups); - virtual bool getMsgData(const uint32_t &token, std::vector &msgs); - virtual bool getMsgMetaData(const uint32_t &token, GxsMsgMetaMap& msg_metas); - virtual void setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read); - virtual bool createGroup(uint32_t &token, RsGxsForumGroup &group); - virtual bool createMsg(uint32_t &token, RsGxsForumMsg &msg); - virtual bool updateGroup(uint32_t &token, RsGxsForumGroup &group); + /// implementation of rsGxsGorums + /// + bool getGroupData(const uint32_t &token, std::vector &groups) override; + bool getMsgData(const uint32_t &token, std::vector &msgs) override; + void setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) override; + bool createGroup(uint32_t &token, RsGxsForumGroup &group) override; + bool createMsg(uint32_t &token, RsGxsForumMsg &msg) override; + bool updateGroup(uint32_t &token, const RsGxsForumGroup &group) override; + + bool getMsgMetaData(const uint32_t &token, GxsMsgMetaMap& msg_metas) ; private: diff --git a/src/services/p3idservice.cc b/src/services/p3idservice.cc index 4d4d5ac5e..fe0cba89f 100644 --- a/src/services/p3idservice.cc +++ b/src/services/p3idservice.cc @@ -639,25 +639,28 @@ void p3IdService::notifyChanges(std::vector &changes) std::cerr << "p3IdService::notifyChanges() Auto Subscribe to Incoming Groups: " << *git; std::cerr << std::endl; #endif + if(!rsReputations->isIdentityBanned(RsGxsId(*git))) { - uint32_t token; - RsGenExchange::subscribeToGroup(token, *git, true); - - // also time_stamp the key that this group represents - - timeStampKey(RsGxsId(*git),RsIdentityUsage(serviceType(),RsIdentityUsage::IDENTITY_DATA_UPDATE)) ; - // notify that a new identity is received, if needed + bool should_subscribe = false; + switch(groupChange->getType()) { + case RsGxsNotify::TYPE_PROCESSED: break ; // Happens when the group is subscribed. This is triggered by RsGenExchange::subscribeToGroup, so better not + // call it again from here!! + case RsGxsNotify::TYPE_PUBLISHED: { auto ev = std::make_shared(); ev->mIdentityId = *git; ev->mIdentityEventCode = RsGxsIdentityEventCode::UPDATED_IDENTITY; rsEvents->postEvent(ev); + + // also time_stamp the key that this group represents + timeStampKey(RsGxsId(*git),RsIdentityUsage(serviceType(),RsIdentityUsage::IDENTITY_DATA_UPDATE)) ; + should_subscribe = true; } break; @@ -667,12 +670,23 @@ void p3IdService::notifyChanges(std::vector &changes) ev->mIdentityId = *git; ev->mIdentityEventCode = RsGxsIdentityEventCode::NEW_IDENTITY; rsEvents->postEvent(ev); + + // also time_stamp the key that this group represents + timeStampKey(RsGxsId(*git),RsIdentityUsage(serviceType(),RsIdentityUsage::IDENTITY_DATA_UPDATE)) ; + should_subscribe = true; } break; default: break; } + + if(should_subscribe) + { + uint32_t token; + RsGenExchange::subscribeToGroup(token, *git, true); + } + } } } diff --git a/src/services/p3posted.cc b/src/services/p3posted.cc index 006127918..8ecad994f 100644 --- a/src/services/p3posted.cc +++ b/src/services/p3posted.cc @@ -307,8 +307,18 @@ bool p3Posted::getBoardsInfo( uint32_t token; RsTokReqOptions opts; opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - if( !requestGroupInfo(token, opts, boardsIds) - || waitToken(token) != RsTokenService::COMPLETE ) return false; + + if(boardsIds.empty()) + { + if( !requestGroupInfo(token, opts) || waitToken(token) != RsTokenService::COMPLETE ) + return false; + } + else + { + if( !requestGroupInfo(token, opts, boardsIds) || waitToken(token) != RsTokenService::COMPLETE ) + return false; + } + return getGroupData(token, groupsInfo) && !groupsInfo.empty(); } @@ -330,5 +340,72 @@ bool p3Posted::getBoardContent( const RsGxsGroupId& groupId, return getPostData(token, posts, comments); } +bool p3Posted::getBoardsSummaries(std::list& boards ) +{ + uint32_t token; + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; + if( !requestGroupInfo(token, opts) || waitToken(token) != RsTokenService::COMPLETE ) return false; + + return getGroupSummary(token, boards); +} + +bool p3Posted::getBoardStatistics(const RsGxsGroupId& boardId,GxsGroupStatistic& stat) +{ + uint32_t token; + if(!RsGxsIfaceHelper::requestGroupStatistic(token, boardId) || waitToken(token) != RsTokenService::COMPLETE) + return false; + + return RsGenExchange::getGroupStatistic(token,stat); +} + +bool p3Posted::createBoard(RsPostedGroup& board) +{ + uint32_t token; + if(!createGroup(token, board)) + { + std::cerr << __PRETTY_FUNCTION__ << "Error! Failed creating group." << std::endl; + return false; + } + + if(waitToken(token,std::chrono::milliseconds(5000)) != RsTokenService::COMPLETE) + { + std::cerr << __PRETTY_FUNCTION__ << "Error! GXS operation failed." << std::endl; + return false; + } + + if(!RsGenExchange::getPublishedGroupMeta(token, board.mMeta)) + { + std::cerr << __PRETTY_FUNCTION__ << "Error! Failure getting updated " << " group data." << std::endl; + return false; + } + + return true; +} + +bool p3Posted::editBoard(RsPostedGroup& board) +{ + uint32_t token; + if(!updateGroup(token, board)) + { + std::cerr << __PRETTY_FUNCTION__ << " Error! Failed updating group." << std::endl; + return false; + } + + if(waitToken(token) != RsTokenService::COMPLETE) + { + std::cerr << __PRETTY_FUNCTION__ << " Error! GXS operation failed." << std::endl; + return false; + } + + if(!RsGenExchange::getPublishedGroupMeta(token, board.mMeta)) + { + std::cerr << __PRETTY_FUNCTION__ << " Error! Failure getting updated " << " group data." << std::endl; + return false; + } + + return true; +} + RsPosted::~RsPosted() = default; RsGxsPostedEvent::~RsGxsPostedEvent() = default; diff --git a/src/services/p3posted.h b/src/services/p3posted.h index a0802722c..5fe5b0718 100644 --- a/src/services/p3posted.h +++ b/src/services/p3posted.h @@ -66,6 +66,14 @@ virtual void receiveHelperChanges(std::vector& changes) std::vector& posts, std::vector& comments ) override; + bool getBoardsSummaries(std::list& groupInfo) override; + + bool getBoardStatistics(const RsGxsGroupId& boardId,GxsGroupStatistic& stat) override; + + bool editBoard(RsPostedGroup& board) override; + + bool createBoard(RsPostedGroup& board) override; + virtual bool getGroupData(const uint32_t &token, std::vector &groups); virtual bool getPostData(const uint32_t &token, std::vector &posts, std::vector &cmts); virtual bool getPostData(const uint32_t &token, std::vector &posts) { std::vector cmts; return getPostData( token, posts, cmts);}