diff --git a/libretroshare/src/gxs/rsgenexchange.cc b/libretroshare/src/gxs/rsgenexchange.cc index 735a09b99..f7609a8f9 100644 --- a/libretroshare/src/gxs/rsgenexchange.cc +++ b/libretroshare/src/gxs/rsgenexchange.cc @@ -1571,7 +1571,7 @@ bool RsGenExchange::setAuthenPolicyFlag(const uint8_t &msgFlag, uint32_t& authen return true; } -void RsGenExchange::notifyNewGroups(std::vector &groups) +void RsGenExchange::receiveNewGroups(std::vector &groups) { RS_STACK_MUTEX(mGenMtx) ; @@ -1603,7 +1603,7 @@ void RsGenExchange::notifyNewGroups(std::vector &groups) } -void RsGenExchange::notifyNewMessages(std::vector& messages) +void RsGenExchange::receiveNewMessages(std::vector& messages) { RS_STACK_MUTEX(mGenMtx) ; @@ -1639,6 +1639,13 @@ void RsGenExchange::notifyNewMessages(std::vector& messages) } } +void RsGenExchange::receiveDistantSearchResults(TurtleRequestId id,const RsGxsGroupId &grpId) +{ + RS_STACK_MUTEX(mGenMtx); + + RsGxsDistantSearchResultChange* gc = new RsGxsDistantSearchResultChange(id,grpId); + mNotifications.push_back(gc); +} void RsGenExchange::notifyReceivePublishKey(const RsGxsGroupId &grpId) { RS_STACK_MUTEX(mGenMtx); @@ -1833,6 +1840,15 @@ uint32_t RsGenExchange::getSyncPeriod(const RsGxsGroupId& grpId) return RS_GXS_DEFAULT_MSG_REQ_PERIOD; } +bool RsGenExchange::getDistantSearchResults(const TurtleRequestId& id,std::list& group_infos) +{ + return (mNetService!=NULL) && mNetService->getDistantSearchResults(id,group_infos) ; +} +bool RsGenExchange::clearDistantSearchResults(const TurtleRequestId& id) +{ + return (mNetService!=NULL) && mNetService->clearDistantSearchResults(id) ; +} + bool RsGenExchange::getGroupNetworkStats(const RsGxsGroupId& grpId,RsGroupNetworkStats& stats) { return (!mNetService) || mNetService->getGroupNetworkStats(grpId,stats) ; diff --git a/libretroshare/src/gxs/rsgenexchange.h b/libretroshare/src/gxs/rsgenexchange.h index 1e51d8b04..e08ba80bd 100644 --- a/libretroshare/src/gxs/rsgenexchange.h +++ b/libretroshare/src/gxs/rsgenexchange.h @@ -132,18 +132,24 @@ public: /*! * @param messages messages are deleted after function returns */ - virtual void notifyNewMessages(std::vector& messages); + virtual void receiveNewMessages(std::vector& messages); /*! * @param groups groups are deleted after function returns */ - virtual void notifyNewGroups(std::vector& groups); + virtual void receiveNewGroups(std::vector& groups); /*! * @param grpId group id */ virtual void notifyReceivePublishKey(const RsGxsGroupId &grpId); + /*! + * \brief notifyReceiveDistantSearchResults + * Should be called when new search results arrive. + * \param grpId + */ + virtual void receiveDistantSearchResults(TurtleRequestId id,const RsGxsGroupId &grpId); /*! * @param grpId group id */ @@ -682,6 +688,9 @@ public: virtual void setSyncPeriod(const RsGxsGroupId& grpId,uint32_t age_in_secs) ; virtual bool getGroupNetworkStats(const RsGxsGroupId& grpId,RsGroupNetworkStats& stats); + virtual bool getDistantSearchResults(const TurtleRequestId& id,std::list& group_infos) ; + virtual bool clearDistantSearchResults(const TurtleRequestId& id); + uint16_t serviceType() const { return mServType ; } uint32_t serviceFullType() const { return ((uint32_t)mServType << 8) + (((uint32_t) RS_PKT_VERSION_SERVICE) << 24); } diff --git a/libretroshare/src/gxs/rsgxsnetservice.cc b/libretroshare/src/gxs/rsgxsnetservice.cc index 3a5c9ecb2..e5dfbd05a 100644 --- a/libretroshare/src/gxs/rsgxsnetservice.cc +++ b/libretroshare/src/gxs/rsgxsnetservice.cc @@ -498,8 +498,8 @@ void RsGxsNetService::processObserverNotifications() mNewPublishKeysToNotify.clear() ; } - if(!grps_copy.empty()) mObserver->notifyNewGroups (grps_copy); - if(!msgs_copy.empty()) mObserver->notifyNewMessages(msgs_copy); + if(!grps_copy.empty()) mObserver->receiveNewGroups (grps_copy); + if(!msgs_copy.empty()) mObserver->receiveNewMessages(msgs_copy); for(std::set::const_iterator it(keys_copy.begin());it!=keys_copy.end();++it) mObserver->notifyReceivePublishKey(*it); @@ -5117,9 +5117,36 @@ static bool termSearch(const std::string& src, const std::string& substring) /* always ignore case */ return src.end() != std::search( src.begin(), src.end(), substring.begin(), substring.end(), RsRegularExpression::CompareCharIC() ); } +void RsGxsNetService::receiveTurtleSearchResults(TurtleRequestId req, const std::list& group_infos) +{ + RS_STACK_MUTEX(mNxsMutex) ; +#warning We should use some central way to do that. This might be very costly if done often. + + RsGxsGrpMetaTemporaryMap grpMeta; + std::map& search_results_map(mDistantSearchResults[req]) ; + + for(auto it(group_infos.begin());it!=group_infos.end();++it) + if(search_results_map.find((*it).group_id) == search_results_map.end()) + grpMeta[(*it).group_id] = NULL; + + mDataStore->retrieveGxsGrpMetaData(grpMeta); + + std::list filtered_results ; + + // only keep groups that are not locally known, and groups that are not already in the mDistantSearchResults structure + + for(auto it(group_infos.begin());it!=group_infos.end();++it) + if(grpMeta[(*it).group_id] == NULL) + { + filtered_results.push_back(*it) ; + search_results_map[(*it).group_id] = *it; + mObserver->receiveDistantSearchResults(req,(*it).group_id) ; + } +} bool RsGxsNetService::search(const std::string& substring,std::list& group_infos) { + RS_STACK_MUTEX(mNxsMutex) ; RsGxsGrpMetaTemporaryMap grpMetaMap; mDataStore->retrieveGxsGrpMetaData(grpMetaMap); @@ -5148,3 +5175,22 @@ bool RsGxsNetService::search(const std::string& substring,std::list& group_infos) +{ + RS_STACK_MUTEX(mNxsMutex) ; + auto it = mDistantSearchResults.find(id) ; + + if(it == mDistantSearchResults.end()) + return false ; + + for(auto it2(it->second.begin());it2!=it->second.end();++it2) + group_infos.push_back(it2->second); + return true; +} +bool RsGxsNetService::clearDistantSearchResults(const TurtleRequestId& id) +{ + RS_STACK_MUTEX(mNxsMutex) ; + mDistantSearchResults.erase(id); + return true ; +} diff --git a/libretroshare/src/gxs/rsgxsnetservice.h b/libretroshare/src/gxs/rsgxsnetservice.h index db2de16b8..799a2b503 100644 --- a/libretroshare/src/gxs/rsgxsnetservice.h +++ b/libretroshare/src/gxs/rsgxsnetservice.h @@ -131,6 +131,7 @@ public: virtual TurtleRequestId turtleSearchRequest(const std::string& match_string); virtual bool search(const std::string& substring,std::list& group_infos) ; + virtual void receiveTurtleSearchResults(TurtleRequestId req,const std::list& group_infos); /*! * pauses synchronisation of subscribed groups and request for group id @@ -169,6 +170,16 @@ public: */ virtual bool getGroupNetworkStats(const RsGxsGroupId& id,RsGroupNetworkStats& stats) ; + /*! + * \brief getDistantSearchResults + * \param id Id of the search request previously issued + * \param group_infos Groups currently known for this search request. + * \return + * false if the id does not correspond to an ongoing distant search request. + */ + virtual bool getDistantSearchResults(const TurtleRequestId& id,std::list& group_infos) ; + virtual bool clearDistantSearchResults(const TurtleRequestId& id); + /*! * Used to inform the net service that we changed subscription status. That helps * optimising data transfer when e.g. unsubsribed groups are updated less often, etc @@ -598,6 +609,9 @@ private: std::set mNewStatsToNotify ; std::set mNewPublishKeysToNotify ; + // Distant search result map + std::map > mDistantSearchResults ; + void debugDump(); uint32_t mDefaultMsgStorePeriod ; diff --git a/libretroshare/src/gxs/rsgxsnettunnel.cc b/libretroshare/src/gxs/rsgxsnettunnel.cc index a52b2f020..eabc32e3a 100644 --- a/libretroshare/src/gxs/rsgxsnettunnel.cc +++ b/libretroshare/src/gxs/rsgxsnettunnel.cc @@ -1066,15 +1066,26 @@ void RsGxsNetTunnelService::receiveSearchResult(TurtleSearchRequestId request_id RsGxsNetTunnelTurtleSearchGroupSummaryItem *result_gs = dynamic_cast(item) ; - if(result_gs != NULL) + if(result_gs == NULL) { - GXS_NET_TUNNEL_DEBUG() << " : result is of type group summary result for service " << result_gs->service << std::dec << ": " << std::endl; - - for(auto it(result_gs->group_infos.begin());it!=result_gs->group_infos.end();++it) - std::cerr << " group " << (*it).group_id << ": " << (*it).group_name << ", " << (*it).number_of_messages << " messages, last is " << time(NULL)-(*it).last_message_ts << " secs ago." << std::endl; - -#warning MISSING CODE HERE - data should be passed up to UI in some way + GXS_NET_TUNNEL_ERROR() << ": deserialized item is not a GroupSummary Item. Smething's wrong here." << std::endl; + return ; } + + GXS_NET_TUNNEL_DEBUG() << " : result is of type group summary result for service " << result_gs->service << std::dec << ": " << std::endl; + + for(auto it(result_gs->group_infos.begin());it!=result_gs->group_infos.end();++it) + std::cerr << " group " << (*it).group_id << ": " << (*it).group_name << ", " << (*it).number_of_messages << " messages, last is " << time(NULL)-(*it).last_message_ts << " secs ago." << std::endl; + + auto it = mSearchableServices.find(result_gs->service) ; + + if(it == mSearchableServices.end()) + { + GXS_NET_TUNNEL_ERROR() << ": deserialized item is for service " << std::hex << result_gs->service << std::dec << " that is in the searchable services list." << std::endl; + return ; + } + + it->second->receiveTurtleSearchResults(request_id,result_gs->group_infos) ; } diff --git a/libretroshare/src/gxs/rsnxs.h b/libretroshare/src/gxs/rsnxs.h index 9d3673f1c..3f1cc9e25 100644 --- a/libretroshare/src/gxs/rsnxs.h +++ b/libretroshare/src/gxs/rsnxs.h @@ -103,9 +103,44 @@ public: virtual uint32_t getDefaultSyncAge() =0; virtual uint32_t getDefaultKeepAge() =0; + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// DISTANT SEARCH FUNCTIONS /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + /*! + * \brief turtleGroupRequest + * Requests a particular group meta data. The request protects the group ID. + * \param group_id + * \return + * returns the turtle request ID that might be associated to some results. + */ virtual TurtleRequestId turtleGroupRequest(const RsGxsGroupId& group_id)=0; + + /*! + * \brief turtleSearchRequest + * Uses distant search to match the substring to the group meta data. + * \param match_string + * \return + * returns the turtle request ID that might be associated to some results. + */ virtual TurtleRequestId turtleSearchRequest(const std::string& match_string)=0; + /*! + * \brief receiveTurtleSearchResults + * Called by turtle (through RsGxsNetTunnel) when new results are received + * \param req Turtle search request ID associated with this result + * \param group_infos Group summary information for the groups returned by the search + */ + virtual void receiveTurtleSearchResults(TurtleRequestId req,const std::list& group_infos)=0; + /*! + * \brief getDistantSearchResults + * \param id + * \param group_infos + * \return + */ + virtual bool getDistantSearchResults(const TurtleRequestId& id,std::list& group_infos)=0 ; + virtual bool clearDistantSearchResults(const TurtleRequestId& id)=0; + virtual bool search(const std::string& substring,std::list& group_infos) =0; /*! diff --git a/libretroshare/src/gxs/rsnxsobserver.h b/libretroshare/src/gxs/rsnxsobserver.h index 087842ef0..a16bc66af 100644 --- a/libretroshare/src/gxs/rsnxsobserver.h +++ b/libretroshare/src/gxs/rsnxsobserver.h @@ -29,6 +29,7 @@ #include #include "rsitems/rsnxsitems.h" +typedef uint32_t TurtleRequestId ; class RsNxsObserver { @@ -42,12 +43,22 @@ public: /*! * @param messages messages are deleted after function returns */ - virtual void notifyNewMessages(std::vector& messages) = 0; + virtual void receiveNewMessages(std::vector& messages) = 0; /*! * @param groups groups are deleted after function returns */ - virtual void notifyNewGroups(std::vector& groups) = 0; + virtual void receiveNewGroups(std::vector& groups) = 0; + + /*! + * \brief receiveDistantSearchResults + * Called when new distant search result arrive. + * \param grpId + */ + virtual void receiveDistantSearchResults(TurtleRequestId& /*id*/,const RsGxsGroupId& /*grpId*/) + { + std::cerr << __PRETTY_FUNCTION__ << ": not overloaded but still called. Nothing will happen." << std::endl; + } /*! * @param grpId group id diff --git a/libretroshare/src/gxstrans/p3gxstrans.cc b/libretroshare/src/gxstrans/p3gxstrans.cc index d0dbb61b0..05c37cdb5 100644 --- a/libretroshare/src/gxstrans/p3gxstrans.cc +++ b/libretroshare/src/gxstrans/p3gxstrans.cc @@ -839,7 +839,7 @@ bool p3GxsTrans::dispatchDecryptedMail( const RsGxsId& authorId, #endif std::vector rcct; rcct.push_back(receipt); - RsGenExchange::notifyNewMessages(rcct); + RsGenExchange::receiveNewMessages(rcct); GxsTransClient* recipientService = NULL; { diff --git a/libretroshare/src/retroshare/rsgxsservice.h b/libretroshare/src/retroshare/rsgxsservice.h index 14f02ed64..83f73887b 100644 --- a/libretroshare/src/retroshare/rsgxsservice.h +++ b/libretroshare/src/retroshare/rsgxsservice.h @@ -6,6 +6,7 @@ #include "retroshare/rstokenservice.h" struct RsMsgMetaData ; +typedef uint32_t TurtleRequestId; typedef std::map > GxsMsgMetaMap; typedef std::map > GxsMsgRelatedMetaMap; @@ -18,7 +19,7 @@ typedef std::map > GxsMsgRelatedMe struct RsGxsNotify { enum NotifyType - { TYPE_PUBLISHED, TYPE_RECEIVED_NEW, TYPE_PROCESSED, TYPE_RECEIVED_PUBLISHKEY }; + { TYPE_PUBLISHED, TYPE_RECEIVED_NEW, TYPE_PROCESSED, TYPE_RECEIVED_PUBLISHKEY, TYPE_RECEIVED_DISTANT_SEARCH_RESULTS }; virtual ~RsGxsNotify() {} virtual NotifyType getType() = 0; @@ -39,6 +40,17 @@ private: bool mMetaChange; }; +class RsGxsDistantSearchResultChange: public RsGxsNotify +{ +public: + RsGxsDistantSearchResultChange(TurtleRequestId id,const RsGxsGroupId& group_id) : mRequestId(id),mGroupId(group_id){} + + NotifyType getType() { return TYPE_RECEIVED_DISTANT_SEARCH_RESULTS ; } +private: + TurtleRequestId mRequestId ; + RsGxsGroupId mGroupId; +}; + /*! * Relevant to message changes */ diff --git a/libretroshare/src/services/p3gxschannels.cc b/libretroshare/src/services/p3gxschannels.cc index a9c54b789..221825e9b 100644 --- a/libretroshare/src/services/p3gxschannels.cc +++ b/libretroshare/src/services/p3gxschannels.cc @@ -295,6 +295,7 @@ void p3GxsChannels::notifyChanges(std::vector &changes) { switch (grpChange->getType()) { + default: case RsGxsNotify::TYPE_PROCESSED: case RsGxsNotify::TYPE_PUBLISHED: break; diff --git a/libretroshare/src/services/p3gxsforums.cc b/libretroshare/src/services/p3gxsforums.cc index 69d33441e..2fa829c1c 100644 --- a/libretroshare/src/services/p3gxsforums.cc +++ b/libretroshare/src/services/p3gxsforums.cc @@ -196,6 +196,7 @@ void p3GxsForums::notifyChanges(std::vector &changes) switch (c->getType()) { + default: case RsGxsNotify::TYPE_PROCESSED: case RsGxsNotify::TYPE_PUBLISHED: break; diff --git a/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.cpp b/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.cpp index e143278d1..04e64258b 100644 --- a/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.cpp +++ b/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.cpp @@ -1122,7 +1122,7 @@ void GxsGroupFrameDialog::loadRequest(const TokenQueue *queue, const TokenReques TurtleRequestId GxsGroupFrameDialog::distantSearch(const QString& search_string) // this should be overloaded in the child class { - std::cerr << "Searching for \"" << search_string.toStdString() << "\". Function is not implemented yet." << std::endl; + std::cerr << "Searching for \"" << search_string.toStdString() << "\". Function is not overloaded, so nothing will happen." << std::endl; return 0; }