From ae5942733ebf1d83d920e1f11e615c18159953b8 Mon Sep 17 00:00:00 2001 From: drbob Date: Mon, 20 Jan 2014 11:42:27 +0000 Subject: [PATCH] - Split majority of p3posted into p3postbase.cc - so that it can be reused by other services. - Fixed iterator overflow into rsgxsupdateitems.cc - Fixed Mutex deadlock in pqiperson.cc - Removed old code. - Fixed lots of compile warnings - mainly wrong variable ordering in constructors. git-svn-id: http://svn.code.sf.net/p/retroshare/code/branches/v0.6-initdev@7044 b45a01b8-16f6-495d-af2f-9b41ad6348cc --- libretroshare/src/gxs/rsgxsdataaccess.h | 4 +- libretroshare/src/gxs/rsgxsnetservice.cc | 9 +- libretroshare/src/gxs/rsgxsutil.h | 2 +- libretroshare/src/libretroshare.pro | 6 +- libretroshare/src/pqi/pqiperson.cc | 7 +- libretroshare/src/pqi/pqiperson.h | 2 + libretroshare/src/pqi/pqissl.cc | 9 +- libretroshare/src/pqi/pqithreadstreamer.cc | 2 +- libretroshare/src/retroshare/rsposted.h | 1 - .../src/serialiser/rsgxsupdateitems.cc | 6 +- libretroshare/src/services/p3gxschannels.cc | 2 +- libretroshare/src/services/p3gxscircles.cc | 4 +- libretroshare/src/services/p3gxsforums.cc | 2 +- libretroshare/src/services/p3gxsserviceVEG.cc | 1467 ----------- libretroshare/src/services/p3gxsserviceVEG.h | 191 -- libretroshare/src/services/p3idservice.cc | 7 +- libretroshare/src/services/p3idservice.h | 2 +- libretroshare/src/services/p3postbase.cc | 723 ++++++ libretroshare/src/services/p3postbase.h | 135 ++ libretroshare/src/services/p3posted.cc | 974 +------- libretroshare/src/services/p3posted.h | 148 +- libretroshare/src/services/p3postedVEG.cc | 2148 ----------------- libretroshare/src/services/p3postedVEG.h | 190 -- libretroshare/src/services/p3wiki.cc | 2 +- 24 files changed, 921 insertions(+), 5122 deletions(-) delete mode 100644 libretroshare/src/services/p3gxsserviceVEG.cc delete mode 100644 libretroshare/src/services/p3gxsserviceVEG.h create mode 100644 libretroshare/src/services/p3postbase.cc create mode 100644 libretroshare/src/services/p3postbase.h delete mode 100644 libretroshare/src/services/p3postedVEG.cc delete mode 100644 libretroshare/src/services/p3postedVEG.h diff --git a/libretroshare/src/gxs/rsgxsdataaccess.h b/libretroshare/src/gxs/rsgxsdataaccess.h index 3b0aa8113..1cf439209 100644 --- a/libretroshare/src/gxs/rsgxsdataaccess.h +++ b/libretroshare/src/gxs/rsgxsdataaccess.h @@ -436,11 +436,13 @@ private: private: RsGeneralDataService* mDataStore; + + RsMutex mDataMutex; /* protecting below */ + uint32_t mNextToken; std::map mPublicToken; std::map mRequests; - RsMutex mDataMutex; }; diff --git a/libretroshare/src/gxs/rsgxsnetservice.cc b/libretroshare/src/gxs/rsgxsnetservice.cc index 9f2ffbf3c..6a31a0c27 100644 --- a/libretroshare/src/gxs/rsgxsnetservice.cc +++ b/libretroshare/src/gxs/rsgxsnetservice.cc @@ -1646,10 +1646,13 @@ void RsGxsNetService::locked_genReqGrpTransaction(NxsTransaction* tr) RsNxsSyncGrpItem*& grpSyncItem = *llit; const std::string& grpId = grpSyncItem->grpId; metaIter = grpMetaMap.find(grpId); - bool haveItem = metaIter != grpMetaMap.end(); + bool haveItem = false; bool latestVersion = false; - - latestVersion = grpSyncItem->publishTs > metaIter->second->mPublishTs; + if (metaIter != grpMetaMap.end()) + { + haveItem = true; + latestVersion = grpSyncItem->publishTs > metaIter->second->mPublishTs; + } if(!haveItem || (haveItem && latestVersion) ){ diff --git a/libretroshare/src/gxs/rsgxsutil.h b/libretroshare/src/gxs/rsgxsutil.h index 9e11b5e41..2828ea637 100644 --- a/libretroshare/src/gxs/rsgxsutil.h +++ b/libretroshare/src/gxs/rsgxsutil.h @@ -143,7 +143,7 @@ class GroupUpdatePublish { public: GroupUpdatePublish(RsGxsGrpItem* item, RsGxsGroupUpdateMeta updateMeta, uint32_t token) - : grpItem(item), mToken(token), mUpdateMeta(updateMeta) {} + : grpItem(item), mUpdateMeta(updateMeta), mToken(token) {} RsGxsGrpItem* grpItem; RsGxsGroupUpdateMeta mUpdateMeta; uint32_t mToken; diff --git a/libretroshare/src/libretroshare.pro b/libretroshare/src/libretroshare.pro index e4ccd7596..51cf17d3f 100644 --- a/libretroshare/src/libretroshare.pro +++ b/libretroshare/src/libretroshare.pro @@ -711,11 +711,13 @@ gxs { serialiser/rswireitems.cc \ # Posted Service - HEADERS += services/p3posted.h \ + HEADERS += services/p3postbase.h \ + services/p3posted.h \ retroshare/rsposted.h \ serialiser/rsposteditems.h - SOURCES += services/p3posted.cc \ + SOURCES += services/p3postbase.cc \ + services/p3posted.cc \ serialiser/rsposteditems.cc #Photo Service diff --git a/libretroshare/src/pqi/pqiperson.cc b/libretroshare/src/pqi/pqiperson.cc index 8c45fff1e..45fab8acb 100644 --- a/libretroshare/src/pqi/pqiperson.cc +++ b/libretroshare/src/pqi/pqiperson.cc @@ -151,7 +151,7 @@ int pqiperson::tick() out += " No Heartbeat & No Packets -> assume dead. calling pqissl::reset()"; pqioutput(PQL_WARNING, pqipersonzone, out); - this->reset(); + this->reset_locked(); } } @@ -384,6 +384,11 @@ int pqiperson::reset() { RsStackMutex stack(mPersonMtx); /**** LOCK MUTEX ****/ + return reset_locked(); +} + +int pqiperson::reset_locked() +{ pqioutput(PQL_WARNING, pqipersonzone, "pqiperson::reset() resetting all pqiconnect for Id: " + PeerId()); std::map::iterator it; diff --git a/libretroshare/src/pqi/pqiperson.h b/libretroshare/src/pqi/pqiperson.h index bcb2de6a8..0afe260e3 100644 --- a/libretroshare/src/pqi/pqiperson.h +++ b/libretroshare/src/pqi/pqiperson.h @@ -179,6 +179,8 @@ int handleNotifyEvent_locked(NetInterface *ni, int event, const struct socka RsMutex mPersonMtx; /**** LOCKS below ****/ +int reset_locked(); + void setRateCap_locked(float val_in, float val_out); std::map kids; diff --git a/libretroshare/src/pqi/pqissl.cc b/libretroshare/src/pqi/pqissl.cc index aebe05550..49c8821fe 100644 --- a/libretroshare/src/pqi/pqissl.cc +++ b/libretroshare/src/pqi/pqissl.cc @@ -93,16 +93,15 @@ static const int PQISSL_SSL_CONNECT_TIMEOUT = 30; pqissl::pqissl(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm) :NetBinInterface(parent, parent->PeerId()), + mLinkMgr(lm), pqil(l), mSslMtx("pqissl"), - waiting(WAITING_NOT), active(false), certvalid(false), + active(false), certvalid(false), waiting(WAITING_NOT), sslmode(PQISSL_ACTIVE), ssl_connection(NULL), sockfd(-1), - pqil(l), // no init for remote_addr. - readpkt(NULL), pktlen(0), + readpkt(NULL), pktlen(0), total_len(0), attempt_ts(0), sameLAN(false), n_read_zero(0), mReadZeroTS(0), mConnectDelay(0), mConnectTS(0), - mConnectTimeout(0), mTimeoutTS(0), mLinkMgr(lm) - + mConnectTimeout(0), mTimeoutTS(0) { RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ diff --git a/libretroshare/src/pqi/pqithreadstreamer.cc b/libretroshare/src/pqi/pqithreadstreamer.cc index b9507b135..43aae789c 100644 --- a/libretroshare/src/pqi/pqithreadstreamer.cc +++ b/libretroshare/src/pqi/pqithreadstreamer.cc @@ -32,7 +32,7 @@ #define DEFAULT_STREAMER_IDLE_SLEEP 1000000 // 1 sec pqithreadstreamer::pqithreadstreamer(PQInterface *parent, RsSerialiser *rss, std::string id, BinInterface *bio_in, int bio_flags_in) -:pqistreamer(rss, id, bio_in, bio_flags_in), mThreadMutex("pqithreadstreamer"), mParent(parent), mTimeout(0) +:pqistreamer(rss, id, bio_in, bio_flags_in), mParent(parent), mThreadMutex("pqithreadstreamer"), mTimeout(0) { mTimeout = DEFAULT_STREAMER_TIMEOUT; mSleepPeriod = DEFAULT_STREAMER_SLEEP; diff --git a/libretroshare/src/retroshare/rsposted.h b/libretroshare/src/retroshare/rsposted.h index 9eb30d248..eeb60c001 100644 --- a/libretroshare/src/retroshare/rsposted.h +++ b/libretroshare/src/retroshare/rsposted.h @@ -82,7 +82,6 @@ class RsPosted : public RsGxsIfaceHelper, public RsGxsCommentService virtual ~RsPosted() { return; } /* Specific Service Data */ - virtual bool getGroupData(const uint32_t &token, std::vector &groups) = 0; virtual bool getPostData(const uint32_t &token, std::vector &posts) = 0; virtual bool getRelatedPosts(const uint32_t &token, std::vector &posts) = 0; diff --git a/libretroshare/src/serialiser/rsgxsupdateitems.cc b/libretroshare/src/serialiser/rsgxsupdateitems.cc index 26bcff9c3..52618720f 100644 --- a/libretroshare/src/serialiser/rsgxsupdateitems.cc +++ b/libretroshare/src/serialiser/rsgxsupdateitems.cc @@ -51,7 +51,7 @@ void RsGxsMsgUpdateItem::clear() std::ostream& RsGxsMsgUpdateItem::print(std::ostream& out, uint16_t indent) { - + return out; } @@ -64,7 +64,7 @@ void RsGxsServerMsgUpdateItem::clear() std::ostream& RsGxsServerMsgUpdateItem::print(std::ostream& out, uint16_t indent) { - + return out; } @@ -75,7 +75,7 @@ void RsGxsServerGrpUpdateItem::clear() std::ostream& RsGxsServerGrpUpdateItem::print(std::ostream& out, uint16_t indent) { - + return out; } diff --git a/libretroshare/src/services/p3gxschannels.cc b/libretroshare/src/services/p3gxschannels.cc index 96fee6a69..e570cbf66 100644 --- a/libretroshare/src/services/p3gxschannels.cc +++ b/libretroshare/src/services/p3gxschannels.cc @@ -1165,7 +1165,7 @@ bool p3GxsChannels::generateVote(uint32_t &token, const RsGxsGroupId &grpId, con uint32_t idx = (uint32_t) (ownIds.size() * RSRandom::random_f32()); uint32_t i = 0; - for(it = ownIds.begin(); (it != ownIds.end()) && (i < idx); it++, i++); + for(it = ownIds.begin(); (it != ownIds.end()) && (i < idx); it++, i++) ; if (it != ownIds.end()) { diff --git a/libretroshare/src/services/p3gxscircles.cc b/libretroshare/src/services/p3gxscircles.cc index 8d9e98f30..f82193a4f 100644 --- a/libretroshare/src/services/p3gxscircles.cc +++ b/libretroshare/src/services/p3gxscircles.cc @@ -1511,7 +1511,7 @@ void p3GxsCircles::generateDummyCircle() int selection = (RSRandom::random_u32() % npgps); std::list::iterator it = mDummyPgpLinkedIds.begin(); - for(int j = 0; (it != mDummyPgpLinkedIds.end()) && (j < selection); j++, it++); + for(int j = 0; (it != mDummyPgpLinkedIds.end()) && (j < selection); j++, it++) ; if (it != mDummyPgpLinkedIds.end()) { idset.insert(*it); @@ -1525,7 +1525,7 @@ void p3GxsCircles::generateDummyCircle() int selection = (RSRandom::random_u32() % mDummyOwnIds.size()); std::list::iterator it = mDummyOwnIds.begin(); mDummyOwnIds.push_back(*it); - for(int j = 0; (it != mDummyOwnIds.end()) && (j < selection); j++, it++); + for(int j = 0; (it != mDummyOwnIds.end()) && (j < selection); j++, it++) ; if (it != mDummyOwnIds.end()) { idset.insert(*it); diff --git a/libretroshare/src/services/p3gxsforums.cc b/libretroshare/src/services/p3gxsforums.cc index bdc8472e0..83493e32e 100644 --- a/libretroshare/src/services/p3gxsforums.cc +++ b/libretroshare/src/services/p3gxsforums.cc @@ -438,7 +438,7 @@ bool p3GxsForums::generateMessage(uint32_t &token, const RsGxsGroupId &grpId, co uint32_t idx = (uint32_t) (ownIds.size() * RSRandom::random_f32()); int i = 0; - for(it = ownIds.begin(); (it != ownIds.end()) && (i < idx); it++, i++); + for(it = ownIds.begin(); (it != ownIds.end()) && (i < idx); it++, i++) ; if (it != ownIds.end()) { diff --git a/libretroshare/src/services/p3gxsserviceVEG.cc b/libretroshare/src/services/p3gxsserviceVEG.cc deleted file mode 100644 index 11ab6e013..000000000 --- a/libretroshare/src/services/p3gxsserviceVEG.cc +++ /dev/null @@ -1,1467 +0,0 @@ -/* - * libretroshare/src/services p3gxsservice.cc - * - * Generic Service Support Class for RetroShare. - * - * Copyright 2012 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "services/p3gxsserviceVEG.h" - -p3GxsServiceVEG::p3GxsServiceVEG(uint16_t type) - :p3Service(type), mReqMtx("p3GxsService") -{ - mNextToken = 0; - return; -} - -bool p3GxsServiceVEG::generateToken(uint32_t &token) -{ - RsStackMutex stack(mReqMtx); /****** LOCKED *****/ - - token = mNextToken++; - - return true; -} - -bool p3GxsServiceVEG::storeRequest(const uint32_t &token, const uint32_t &ansType, const RsTokReqOptionsVEG &opts, const uint32_t &type, const std::list &ids) -{ - RsStackMutex stack(mReqMtx); /****** LOCKED *****/ - - gxsRequest req; - req.token = token; - req.reqTime = time(NULL); - req.reqType = type; - req.ansType = ansType; - req.Options = opts; - req.status = GXS_REQUEST_STATUS_PENDING; - req.inList = ids; - - mRequests[token] = req; - - return true; -} - - -bool p3GxsServiceVEG::clearRequest(const uint32_t &token) -{ - RsStackMutex stack(mReqMtx); /****** LOCKED *****/ - - std::map::iterator it; - - it = mRequests.find(token); - if (it == mRequests.end()) - { - return false; - } - - mRequests.erase(it); - - return true; -} - -bool p3GxsServiceVEG::updateRequestStatus(const uint32_t &token, const uint32_t &status) -{ - RsStackMutex stack(mReqMtx); /****** LOCKED *****/ - - std::map::iterator it; - - it = mRequests.find(token); - if (it == mRequests.end()) - { - return false; - } - - it->second.status = status; - - return true; -} - -bool p3GxsServiceVEG::updateRequestInList(const uint32_t &token, std::list ids) -{ - RsStackMutex stack(mReqMtx); /****** LOCKED *****/ - - std::map::iterator it; - - it = mRequests.find(token); - if (it == mRequests.end()) - { - return false; - } - - std::list::iterator iit; - for(iit = ids.begin(); iit != ids.end(); iit++) - { - it->second.inList.push_back(*iit); - } - - return true; -} - - -bool p3GxsServiceVEG::updateRequestOutList(const uint32_t &token, std::list ids) -{ - RsStackMutex stack(mReqMtx); /****** LOCKED *****/ - - std::map::iterator it; - - it = mRequests.find(token); - if (it == mRequests.end()) - { - return false; - } - - std::list::iterator iit; - for(iit = ids.begin(); iit != ids.end(); iit++) - { - it->second.outList.push_back(*iit); - } - - return true; -} - -#if 0 -bool p3GxsServiceVEG::updateRequestData(const uint32_t &token, std::map data) -{ - RsStackMutex stack(mReqMtx); /****** LOCKED *****/ - - std::map::iterator it; - - it = mRequests.find(token); - if (it == mRequests.end()) - { - return false; - } - - std::map::iterator dit; - for(dit = data.begin(); dit != data.end(); dit++) - { - it->second.readyData[dit->first] = dit->second; - } - - return true; -} -#endif - -bool p3GxsServiceVEG::checkRequestStatus(const uint32_t &token, uint32_t &status, uint32_t &reqtype, uint32_t &anstype, time_t &ts) -{ - RsStackMutex stack(mReqMtx); /****** LOCKED *****/ - - std::map::iterator it; - - it = mRequests.find(token); - if (it == mRequests.end()) - { - return false; - } - - status = it->second.status; - reqtype = it->second.reqType; - anstype = it->second.ansType; - ts = it->second.reqTime; - - return true; -} - - - // special ones for testing (not in final design) -bool p3GxsServiceVEG::tokenList(std::list &tokens) -{ - RsStackMutex stack(mReqMtx); /****** LOCKED *****/ - - std::map::iterator it; - - for(it = mRequests.begin(); it != mRequests.end(); it++) - { - tokens.push_back(it->first); - } - - return true; -} - -bool p3GxsServiceVEG::popRequestInList(const uint32_t &token, std::string &id) -{ - RsStackMutex stack(mReqMtx); /****** LOCKED *****/ - - std::map::iterator it; - - it = mRequests.find(token); - if (it == mRequests.end()) - { - return false; - } - - if (it->second.inList.size() == 0) - { - return false; - } - - id = it->second.inList.front(); - it->second.inList.pop_front(); - - return true; -} - - -bool p3GxsServiceVEG::popRequestOutList(const uint32_t &token, std::string &id) -{ - RsStackMutex stack(mReqMtx); /****** LOCKED *****/ - - std::map::iterator it; - - it = mRequests.find(token); - if (it == mRequests.end()) - { - return false; - } - - if (it->second.outList.size() == 0) - { - return false; - } - - id = it->second.outList.front(); - it->second.outList.pop_front(); - - return true; -} - - -bool p3GxsServiceVEG::loadRequestOutList(const uint32_t &token, std::list &ids) -{ - RsStackMutex stack(mReqMtx); /****** LOCKED *****/ - - std::map::iterator it; - - it = mRequests.find(token); - if (it == mRequests.end()) - { - return false; - } - - if (it->second.outList.size() == 0) - { - return false; - } - - ids = it->second.outList; - it->second.outList.clear(); - - return true; -} - - -#define MAX_REQUEST_AGE 10 - -bool p3GxsServiceVEG::fakeprocessrequests() - { - std::list::iterator it; - std::list tokens; - - tokenList(tokens); - - time_t now = time(NULL); - for(it = tokens.begin(); it != tokens.end(); it++) - { - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - uint32_t token = *it; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - std::cerr << "p3GxsServiceVEG::fakeprocessrequests() Token: " << token << " Status: " << status << " ReqType: " << reqtype << "Age: " << now - ts << std::endl; - - if (status == GXS_REQUEST_STATUS_PENDING) - { - updateRequestStatus(token, GXS_REQUEST_STATUS_PARTIAL); - } - else if (status == GXS_REQUEST_STATUS_PARTIAL) - { - updateRequestStatus(token, GXS_REQUEST_STATUS_COMPLETE); - } - else if (status == GXS_REQUEST_STATUS_DONE) - { - std::cerr << "p3GxsServiceVEG::fakeprocessrequests() Clearing Done Request Token: " << token; - std::cerr << std::endl; - clearRequest(token); - } - else if (now - ts > MAX_REQUEST_AGE) - { - std::cerr << "p3GxsServiceVEG::fakeprocessrequests() Clearing Old Request Token: " << token; - std::cerr << std::endl; - clearRequest(token); - } - } - - return true; -} - - - -/*********************************************************************************************************/ -/*********************************************************************************************************/ -/*********************************************************************************************************/ -/*********************************************************************************************************/ -/*********************************************************************************************************/ - - -/****** GXS Data Dummy .... Handles generic data storage and access. designed for testing GUIs - * without being dependent on the backend. - * - * - * - * Important to specify the exact behaviour with flags! - * - * - * - ****/ - -GxsDataProxyVEG::GxsDataProxyVEG() - :mDataMtx("GxsDataProxyMtx") -{ - return; -} - - -static bool checkGroupFilter(const RsTokReqOptionsVEG &opts, const RsGroupMetaData &group) -{ - bool statusMatch = false; - if (opts.mStatusMask) - { - // Exact Flags match required. - if ((opts.mStatusMask & opts.mStatusFilter) == (opts.mStatusMask & group.mGroupStatus)) - { - std::cerr << "checkGroupFilter() Accepting Group as StatusMatches: "; - std::cerr << " Mask: " << opts.mStatusMask << " StatusFilter: " << opts.mStatusFilter; - std::cerr << " GroupStatus: " << group.mGroupStatus << " GroupId: " << group.mGroupId; - std::cerr << std::endl; - - statusMatch = true; - } - else - { - std::cerr << "checkGroupFilter() Dropping Group due to !StatusMatch "; - std::cerr << " Mask: " << opts.mStatusMask << " StatusFilter: " << opts.mStatusFilter; - std::cerr << " GroupStatus: " << group.mGroupStatus << " GroupId: " << group.mGroupId; - std::cerr << std::endl; - } - } - else - { - // no status comparision, - statusMatch = true; - } - - bool flagsMatch = false; - if (opts.mFlagsMask) - { - // Exact Flags match required. - if ((opts.mFlagsMask & opts.mFlagsFilter) == (opts.mFlagsMask & group.mGroupFlags)) - { - std::cerr << "checkGroupFilter() Accepting Group as Flags Match: "; - std::cerr << " Mask: " << opts.mFlagsMask << " FlagsFilter: " << opts.mFlagsFilter; - std::cerr << " GroupFlags: " << group.mGroupFlags << " GroupId: " << group.mGroupId; - std::cerr << std::endl; - - flagsMatch = true; - } - else - { - std::cerr << "checkGroupFilter() Dropping Group due to !Flags Match "; - std::cerr << " Mask: " << opts.mFlagsMask << " FlagsFilter: " << opts.mFlagsFilter; - std::cerr << " GroupFlags: " << group.mGroupFlags << " GroupId: " << group.mGroupId; - std::cerr << std::endl; - } - } - else - { - // no status comparision, - flagsMatch = true; - } - - bool subMatch = false; - if (opts.mSubscribeFilter) - { - // Exact Flags match required. - if (opts.mSubscribeFilter & group.mSubscribeFlags) - { - std::cerr << "checkGroupFilter() Accepting Group as SubscribeMatches: "; - std::cerr << " SubscribeFilter: " << opts.mSubscribeFilter; - std::cerr << " GroupSubscribeFlags: " << group.mSubscribeFlags << " GroupId: " << group.mGroupId; - std::cerr << std::endl; - - subMatch = true; - } - else - { - std::cerr << "checkGroupFilter() Dropping Group due to !SubscribeMatch "; - std::cerr << " SubscribeFilter: " << opts.mSubscribeFilter; - std::cerr << " GroupSubscribeFlags: " << group.mSubscribeFlags << " GroupId: " << group.mGroupId; - std::cerr << std::endl; - } - } - else - { - // no subscribe comparision, - subMatch = true; - } - - return (statusMatch && flagsMatch && subMatch); -} - - -static bool checkMsgFilter(const RsTokReqOptionsVEG &opts, const RsMsgMetaData &msg) -{ - bool statusMatch = false; - if (opts.mStatusMask) - { - // Exact Flags match required. - if ((opts.mStatusMask & opts.mStatusFilter) == (opts.mStatusMask & msg.mMsgStatus)) - { - std::cerr << "checkMsgFilter() Accepting Msg as StatusMatches: "; - std::cerr << " Mask: " << opts.mStatusMask << " StatusFilter: " << opts.mStatusFilter; - std::cerr << " MsgStatus: " << msg.mMsgStatus << " MsgId: " << msg.mMsgId; - std::cerr << std::endl; - - statusMatch = true; - } - else - { - std::cerr << "checkMsgFilter() Dropping Msg due to !StatusMatch "; - std::cerr << " Mask: " << opts.mStatusMask << " StatusFilter: " << opts.mStatusFilter; - std::cerr << " MsgStatus: " << msg.mMsgStatus << " MsgId: " << msg.mMsgId; - std::cerr << std::endl; - } - } - else - { - // no status comparision, - statusMatch = true; - } - - bool flagsMatch = false; - if (opts.mFlagsMask) - { - // Exact Flags match required. - if ((opts.mFlagsMask & opts.mFlagsFilter) == (opts.mFlagsMask & msg.mMsgFlags)) - { - std::cerr << "checkMsgFilter() Accepting Msg as Flags Match: "; - std::cerr << " Mask: " << opts.mFlagsMask << " FlagsFilter: " << opts.mFlagsFilter; - std::cerr << " MsgFlags: " << msg.mMsgFlags << " MsgId: " << msg.mMsgId; - std::cerr << std::endl; - - flagsMatch = true; - } - else - { - std::cerr << "checkMsgFilter() Dropping Msg due to !Flags Match "; - std::cerr << " Mask: " << opts.mFlagsMask << " FlagsFilter: " << opts.mFlagsFilter; - std::cerr << " MsgFlags: " << msg.mMsgFlags << " MsgId: " << msg.mMsgId; - std::cerr << std::endl; - } - } - else - { - // no status comparision, - flagsMatch = true; - } - - return (statusMatch && flagsMatch); -} - - -bool GxsDataProxyVEG::filterGroupList(const RsTokReqOptionsVEG &opts, std::list &groupIds) -{ - std::list::iterator it; - for(it = groupIds.begin(); it != groupIds.end(); ) - { - RsStackMutex stack(mDataMtx); /***** LOCKED *****/ - - bool keep = false; - /* find group */ - std::map::iterator mit; - mit = mGroupMetaData.find(*it); - if (mit != mGroupMetaData.end()) - { - keep = checkGroupFilter(opts, mit->second); - } - - if (keep) - { - it++; - } - else - { - it = groupIds.erase(it); - } - } - return true; -} - - -bool GxsDataProxyVEG::filterMsgList(const RsTokReqOptionsVEG &opts, std::list &msgIds) -{ - std::list::iterator it; - for(it = msgIds.begin(); it != msgIds.end(); ) - { - RsStackMutex stack(mDataMtx); /***** LOCKED *****/ - - bool keep = false; - /* find msg */ - std::map::iterator mit; - mit = mMsgMetaData.find(*it); - if (mit != mMsgMetaData.end()) - { - keep = checkMsgFilter(opts, mit->second); - } - - if (keep) - { - it++; - } - else - { - it = msgIds.erase(it); - } - } - return true; -} - - - -bool GxsDataProxyVEG::getGroupList( uint32_t &token, const RsTokReqOptionsVEG &opts, const std::list &groupIds, std::list &outGroupIds) -{ - /* CASEs that this handles ... - * 1) if groupIds is Empty... return all groupIds. - * 2) else copy list. - * - */ - std::cerr << "GxsDataProxyVEG::getGroupList()"; - std::cerr << std::endl; - - if (groupIds.size() == 0) - { - /* grab all the ids */ - RsStackMutex stack(mDataMtx); /***** LOCKED *****/ - - std::map::iterator mit; - for(mit = mGroupMetaData.begin(); mit != mGroupMetaData.end(); mit++) - { - outGroupIds.push_back(mit->first); - } - } - else - { - outGroupIds = groupIds; - } - - filterGroupList(opts, outGroupIds); - - return true; -} - - -bool GxsDataProxyVEG::getMsgList( uint32_t &token, const RsTokReqOptionsVEG &opts, const std::list &groupIds, std::list &outMsgIds) -{ - /* CASEs this handles. - * Input is groupList + Flags. - * 1) No Flags => All Messages in those Groups. - * - */ - std::cerr << "GxsDataProxyVEG::getMsgList()"; - std::cerr << std::endl; - - - bool onlyOrigMsgs = false; - bool onlyLatestMsgs = false; - bool onlyThreadHeadMsgs = false; - - // Can only choose one of these two. - if (opts.mOptions & RS_TOKREQOPT_MSG_ORIGMSG) - { - std::cerr << "GxsDataProxyVEG::getMsgList() MSG_ORIGMSG"; - std::cerr << std::endl; - onlyOrigMsgs = true; - } - else if (opts.mOptions & RS_TOKREQOPT_MSG_LATEST) - { - std::cerr << "GxsDataProxyVEG::getMsgList() MSG_LATEST"; - std::cerr << std::endl; - onlyLatestMsgs = true; - } - - if (opts.mOptions & RS_TOKREQOPT_MSG_THREAD) - { - std::cerr << "GxsDataProxyVEG::getMsgList() MSG_THREAD"; - std::cerr << std::endl; - onlyThreadHeadMsgs = true; - } - - std::list::const_iterator it; - std::map::iterator mit; - - for(it = groupIds.begin(); it != groupIds.end(); it++) - { - if (onlyLatestMsgs) // THIS ONE IS HARD -> LOTS OF COMP. - { - RsStackMutex stack(mDataMtx); /***** LOCKED *****/ - - // RUN THROUGH ALL MSGS... in map origId -> TS. - std::map > origMsgTs; - std::map >::iterator oit; - for(mit = mMsgMetaData.begin(); mit != mMsgMetaData.end(); mit++) - { - if (mit->second.mGroupId != *it) - { - continue; - } - - /* if we are grabbing thread Head... then parentId == empty. */ - if (onlyThreadHeadMsgs) - { - if (!(mit->second.mParentId.empty())) - { - continue; - } - } - - - oit = origMsgTs.find(mit->second.mOrigMsgId); - bool addMsg = false; - if (oit == origMsgTs.end()) - { - std::cerr << "GxsDataProxyVEG::getMsgList() Found New OrigMsgId: "; - std::cerr << mit->second.mOrigMsgId; - std::cerr << " MsgId: " << mit->second.mMsgId; - std::cerr << " TS: " << mit->second.mPublishTs; - std::cerr << std::endl; - - addMsg = true; - } - // check timestamps. - else if (oit->second.second < mit->second.mPublishTs) - { - std::cerr << "GxsDataProxyVEG::getMsgList() Found Later Msg. OrigMsgId: "; - std::cerr << mit->second.mOrigMsgId; - std::cerr << " MsgId: " << mit->second.mMsgId; - std::cerr << " TS: " << mit->second.mPublishTs; - - addMsg = true; - } - - if (addMsg) - { - // add as latest. (overwriting if necessary) - origMsgTs[mit->second.mOrigMsgId] = std::make_pair(mit->second.mMsgId, mit->second.mPublishTs); - } - } - - // Add the discovered Latest Msgs. - for(oit = origMsgTs.begin(); oit != origMsgTs.end(); oit++) - { - outMsgIds.push_back(oit->second.first); - } - - } - else // ALL OTHER CASES. - { - RsStackMutex stack(mDataMtx); /***** LOCKED *****/ - - for(mit = mMsgMetaData.begin(); mit != mMsgMetaData.end(); mit++) - { - if (mit->second.mGroupId == *it) - { - bool add = false; - - /* if we are grabbing thread Head... then parentId == empty. */ - if (onlyThreadHeadMsgs) - { - if (!(mit->second.mParentId.empty())) - { - continue; - } - } - - - if (onlyOrigMsgs) - { - if (mit->second.mMsgId == mit->second.mOrigMsgId) - { - add = true; - } - } - else - { - add = true; - } - - if (add) - { - outMsgIds.push_back(mit->first); - } - } - } - } - } - - filterMsgList(opts, outMsgIds); - - return true; -} - - -bool GxsDataProxyVEG::getMsgRelatedList(uint32_t &token, const RsTokReqOptionsVEG &opts, const std::list &msgIds, std::list &outMsgIds) -{ - /* CASEs this handles. - * Input is msgList + Flags. - * 1) No Flags => just copy msgIds (probably requesting data). - * - */ - - std::cerr << "GxsDataProxyVEG::getMsgRelatedList()"; - std::cerr << std::endl; - - bool onlyLatestMsgs = false; - bool onlyAllVersions = false; - bool onlyChildMsgs = false; - bool onlyThreadMsgs = false; - - if (opts.mOptions & RS_TOKREQOPT_MSG_LATEST) - { - std::cerr << "GxsDataProxyVEG::getMsgRelatedList() MSG_LATEST"; - std::cerr << std::endl; - onlyLatestMsgs = true; - } - else if (opts.mOptions & RS_TOKREQOPT_MSG_VERSIONS) - { - std::cerr << "GxsDataProxyVEG::getMsgRelatedList() MSG_VERSIONS"; - std::cerr << std::endl; - onlyAllVersions = true; - } - - if (opts.mOptions & RS_TOKREQOPT_MSG_PARENT) - { - std::cerr << "GxsDataProxyVEG::getMsgRelatedList() MSG_PARENTS"; - std::cerr << std::endl; - onlyChildMsgs = true; - } - - if (opts.mOptions & RS_TOKREQOPT_MSG_THREAD) - { - std::cerr << "GxsDataProxyVEG::getMsgRelatedList() MSG_THREAD"; - std::cerr << std::endl; - onlyThreadMsgs = true; - } - - if (onlyAllVersions && onlyChildMsgs) - { - std::cerr << "GxsDataProxyVEG::getMsgRelatedList() ERROR Incompatible FLAGS (VERSIONS & PARENT)"; - std::cerr << std::endl; - - return false; - } - - if (onlyAllVersions && onlyThreadMsgs) - { - std::cerr << "GxsDataProxyVEG::getMsgRelatedList() ERROR Incompatible FLAGS (VERSIONS & THREAD)"; - std::cerr << std::endl; - - return false; - } - - if ((!onlyLatestMsgs) && onlyChildMsgs) - { - std::cerr << "GxsDataProxyVEG::getMsgRelatedList() ERROR Incompatible FLAGS (!LATEST & PARENT)"; - std::cerr << std::endl; - - return false; - } - - if ((!onlyLatestMsgs) && onlyThreadMsgs) - { - std::cerr << "GxsDataProxyVEG::getMsgRelatedList() ERROR Incompatible FLAGS (!LATEST & THREAD)"; - std::cerr << std::endl; - - return false; - } - - if (onlyChildMsgs && onlyThreadMsgs) - { - std::cerr << "GxsDataProxyVEG::getMsgRelatedList() ERROR Incompatible FLAGS (PARENT & THREAD)"; - std::cerr << std::endl; - - return false; - } - - - /* FALL BACK OPTION */ - if ((!onlyLatestMsgs) && (!onlyAllVersions) && (!onlyChildMsgs) && (!onlyThreadMsgs)) - { - std::cerr << "GxsDataProxyVEG::getMsgRelatedList() FALLBACK -> NO FLAGS -> JUST COPY"; - std::cerr << std::endl; - /* just copy */ - outMsgIds = msgIds; - filterMsgList(opts, outMsgIds); - - return true; - } - - std::list::const_iterator it; - std::map::iterator mit; - - for(it = msgIds.begin(); it != msgIds.end(); it++) - { - RsStackMutex stack(mDataMtx); /***** LOCKED *****/ - - /* getOriginal Message */ - mit = mMsgMetaData.find(*it); - if (mit == mMsgMetaData.end()) - { - continue; - } - - std::string origMsgId = mit->second.mOrigMsgId; - - if (onlyLatestMsgs) - { - if (onlyChildMsgs || onlyThreadMsgs) - { - // RUN THROUGH ALL MSGS... in map origId -> TS. - std::map > origMsgTs; - std::map >::iterator oit; - for(mit = mMsgMetaData.begin(); mit != mMsgMetaData.end(); mit++) - { - // skip msgs that aren't children. - if (onlyChildMsgs) - { - if (mit->second.mParentId != origMsgId) - { - continue; - } - } - else /* onlyThreadMsgs */ - { - if (mit->second.mThreadId != (*it)) - { - continue; - } - } - - - oit = origMsgTs.find(mit->second.mOrigMsgId); - bool addMsg = false; - if (oit == origMsgTs.end()) - { - std::cerr << "GxsDataProxyVEG::getMsgRelatedList() Found New OrigMsgId: "; - std::cerr << mit->second.mOrigMsgId; - std::cerr << " MsgId: " << mit->second.mMsgId; - std::cerr << " TS: " << mit->second.mPublishTs; - std::cerr << std::endl; - - addMsg = true; - } - // check timestamps. - else if (oit->second.second < mit->second.mPublishTs) - { - std::cerr << "GxsDataProxyVEG::getMsgRelatedList() Found Later Msg. OrigMsgId: "; - std::cerr << mit->second.mOrigMsgId; - std::cerr << " MsgId: " << mit->second.mMsgId; - std::cerr << " TS: " << mit->second.mPublishTs; - - addMsg = true; - } - - if (addMsg) - { - // add as latest. (overwriting if necessary) - origMsgTs[mit->second.mOrigMsgId] = std::make_pair(mit->second.mMsgId, mit->second.mPublishTs); - } - } - - // Add the discovered Latest Msgs. - for(oit = origMsgTs.begin(); oit != origMsgTs.end(); oit++) - { - outMsgIds.push_back(oit->second.first); - } - } - else - { - - /* first guess is potentially better than Orig (can't be worse!) */ - time_t latestTs = mit->second.mPublishTs; - std::string latestMsgId = mit->second.mMsgId; - - for(mit = mMsgMetaData.begin(); mit != mMsgMetaData.end(); mit++) - { - if (mit->second.mOrigMsgId == origMsgId) - { - if (mit->second.mPublishTs > latestTs) - { - latestTs = mit->second.mPublishTs; - latestMsgId = mit->first; - } - } - } - outMsgIds.push_back(latestMsgId); - } - } - else if (onlyAllVersions) - { - for(mit = mMsgMetaData.begin(); mit != mMsgMetaData.end(); mit++) - { - if (mit->second.mOrigMsgId == origMsgId) - { - outMsgIds.push_back(mit->first); - } - } - } - } - - filterMsgList(opts, outMsgIds); - - return true; -} - - -bool GxsDataProxyVEG::createGroup(void *groupData) -{ - RsGroupMetaData meta; - if (convertGroupToMetaData(groupData, meta)) - { - if (!isUniqueGroup(meta.mGroupId)) - { - std::cerr << "GxsDataProxyVEG::createGroup() ERROR GroupId Clashes, discarding"; - std::cerr << std::endl; - return false; - } - - RsStackMutex stack(mDataMtx); /***** LOCKED *****/ - - - /* Set the Group Status Flags */ - meta.mGroupStatus |= (RSGXS_GROUP_STATUS_UPDATED | RSGXS_GROUP_STATUS_NEWGROUP); - - - /* push into maps */ - mGroupData[meta.mGroupId] = groupData; - mGroupMetaData[meta.mGroupId] = meta; - - return true; - } - - std::cerr << "GxsDataProxyVEG::createGroup() ERROR Failed to convert Data"; - std::cerr << std::endl; - return false; -} - - -bool GxsDataProxyVEG::createMsg(void *msgData) -{ - RsMsgMetaData meta; - if (convertMsgToMetaData(msgData, meta)) - { - if (!isUniqueMsg(meta.mMsgId)) - { - std::cerr << "GxsDataProxyVEG::createMsg() ERROR MsgId Clashes, discarding"; - std::cerr << std::endl; - return false; - } - - RsStackMutex stack(mDataMtx); /***** LOCKED *****/ - - - /* find the group */ - std::map::iterator git; - git = mGroupMetaData.find(meta.mGroupId); - if (git == mGroupMetaData.end()) - { - std::cerr << "GxsDataProxyVEG::createMsg() ERROR GroupId Doesn't exist, discarding"; - std::cerr << std::endl; - return false; - } - - /* flag the group as changed */ - git->second.mGroupStatus |= (RSGXS_GROUP_STATUS_UPDATED | RSGXS_GROUP_STATUS_NEWMSG); - - /* Set the Msg Status Flags */ - meta.mMsgStatus |= (RSGXS_MSG_STATUS_UNREAD_BY_USER | RSGXS_MSG_STATUS_UNPROCESSED); - - /* Set the Msg->GroupId Status Flags */ - - /* push into maps */ - mMsgData[meta.mMsgId] = msgData; - mMsgMetaData[meta.mMsgId] = meta; - - return true; - } - - std::cerr << "GxsDataProxyVEG::createMsg() ERROR Failed to convert Data"; - std::cerr << std::endl; - return false; -} - - - // Get Message Status - is retrived via MessageSummary. -bool GxsDataProxyVEG::setMessageStatus(const std::string &msgId,const uint32_t status, const uint32_t statusMask) -{ - RsStackMutex stack(mDataMtx); /***** LOCKED *****/ - - std::map::iterator mit; - mit = mMsgMetaData.find(msgId); - - if (mit == mMsgMetaData.end()) - { - // error. - std::cerr << "GxsDataProxyVEG::getMsgSummary() Error Finding MsgId: " << msgId; - std::cerr << std::endl; - } - else - { - /* tweak status */ - mit->second.mMsgStatus &= ~statusMask; - mit->second.mMsgStatus |= (status & statusMask); - } - - // always return true - as this is supposed to be async operation. - return true; -} - -bool GxsDataProxyVEG::setGroupStatus(const std::string &groupId, const uint32_t status, const uint32_t statusMask) -{ - RsStackMutex stack(mDataMtx); /***** LOCKED *****/ - - std::map::iterator git; - git = mGroupMetaData.find(groupId); - - if (git == mGroupMetaData.end()) - { - // error. - std::cerr << "GxsDataProxyVEG::setGroupStatus() Error Finding GroupId: " << groupId; - std::cerr << std::endl; - } - else - { - /* tweak status */ - git->second.mGroupStatus &= ~statusMask; - git->second.mGroupStatus |= (status & statusMask); - } - - // always return true - as this is supposed to be async operation. - return true; -} - - -bool GxsDataProxyVEG::setGroupSubscribeFlags(const std::string &groupId, uint32_t subscribeFlags, uint32_t subscribeMask) -{ - RsStackMutex stack(mDataMtx); /***** LOCKED *****/ - - std::map::iterator git; - git = mGroupMetaData.find(groupId); - - if (git == mGroupMetaData.end()) - { - // error. - std::cerr << "GxsDataProxyVEG::setGroupSubscribeFlags() Error Finding GroupId: " << groupId; - std::cerr << std::endl; - } - else - { - /* tweak subscribe Flags */ - git->second.mSubscribeFlags &= ~subscribeMask; - git->second.mSubscribeFlags |= (subscribeFlags & subscribeMask); - } - - // always return true - as this is supposed to be async operation. - return true; -} - -bool GxsDataProxyVEG::setMessageServiceString(const std::string &msgId, const std::string &str) -{ - RsStackMutex stack(mDataMtx); /***** LOCKED *****/ - - std::map::iterator mit; - mit = mMsgMetaData.find(msgId); - - if (mit == mMsgMetaData.end()) - { - // error. - std::cerr << "GxsDataProxyVEG::setMessageServiceString() Error Finding MsgId: " << msgId; - std::cerr << std::endl; - } - else - { - mit->second.mServiceString = str; - } - - // always return true - as this is supposed to be async operation. - return true; -} - -bool GxsDataProxyVEG::setGroupServiceString(const std::string &groupId, const std::string &str) -{ - RsStackMutex stack(mDataMtx); /***** LOCKED *****/ - - std::map::iterator git; - git = mGroupMetaData.find(groupId); - - if (git == mGroupMetaData.end()) - { - // error. - std::cerr << "GxsDataProxyVEG::setGroupServiceString() Error Finding GroupId: " << groupId; - std::cerr << std::endl; - } - else - { - git->second.mServiceString = str; - } - - // always return true - as this is supposed to be async operation. - return true; -} - - - /* These Functions must be overloaded to complete the service */ -bool GxsDataProxyVEG::convertGroupToMetaData(void *groupData, RsGroupMetaData &meta) -{ - std::cerr << "GxsDataProxyVEG::convert fn ... please implement!"; - std::cerr << std::endl; - return false; -} - -bool GxsDataProxyVEG::convertMsgToMetaData(void *groupData, RsMsgMetaData &meta) -{ - std::cerr << "GxsDataProxyVEG::convert fn ... please implement!"; - std::cerr << std::endl; - return false; -} - - /* extract Data */ -bool GxsDataProxyVEG::getGroupSummary(const std::string &groupId, RsGroupMetaData &groupSummary) -{ - RsStackMutex stack(mDataMtx); /***** LOCKED *****/ - - std::map::iterator mit; - mit = mGroupMetaData.find(groupId); - - if (mit == mGroupMetaData.end()) - { - // error. - std::cerr << "GxsDataProxyVEG::getGroupMetaData() Error Finding GroupId: " << groupId; - std::cerr << std::endl; - return false; - } - else - { - groupSummary = mit->second; - } - return true; -} - - -bool GxsDataProxyVEG::getMsgSummary(const std::string &msgId, RsMsgMetaData &msgSummary) -{ - RsStackMutex stack(mDataMtx); /***** LOCKED *****/ - - std::map::iterator mit; - mit = mMsgMetaData.find(msgId); - - if (mit == mMsgMetaData.end()) - { - // error. - std::cerr << "GxsDataProxyVEG::getMsgSummary() Error Finding MsgId: " << msgId; - std::cerr << std::endl; - } - else - { - msgSummary = (mit->second); - } - return true; -} - - - /* extract Data */ -bool GxsDataProxyVEG::getGroupSummary(const std::list &groupIds, std::list &groupSummary) -{ - std::list::const_iterator it; - for(it = groupIds.begin(); it != groupIds.end(); it++) - { - RsStackMutex stack(mDataMtx); /***** LOCKED *****/ - - std::map::iterator mit; - mit = mGroupMetaData.find(*it); - - if (mit == mGroupMetaData.end()) - { - // error. - std::cerr << "GxsDataProxyVEG::getGroupMetaData() Error Finding GroupId: " << *it; - std::cerr << std::endl; - } - else - { - groupSummary.push_back(mit->second); - } - } - return true; -} - - -bool GxsDataProxyVEG::getMsgSummary(const std::list &msgIds, std::list &msgSummary) -{ - std::list::const_iterator it; - for(it = msgIds.begin(); it != msgIds.end(); it++) - { - RsStackMutex stack(mDataMtx); /***** LOCKED *****/ - - std::map::iterator mit; - mit = mMsgMetaData.find(*it); - - if (mit == mMsgMetaData.end()) - { - // error. - std::cerr << "GxsDataProxyVEG::getMsgSummary() Error Finding MsgId: " << *it; - std::cerr << std::endl; - } - else - { - msgSummary.push_back(mit->second); - } - } - return true; -} - - -bool GxsDataProxyVEG::getGroupData(const std::string &groupId, void * &groupData) -{ - RsStackMutex stack(mDataMtx); /***** LOCKED *****/ - - std::map::iterator mit; - mit = mGroupData.find(groupId); - - if (mit == mGroupData.end()) - { - // error. - std::cerr << "GxsDataProxyVEG::getGroupData() Error Finding GroupId: " << groupId; - std::cerr << std::endl; - return false; - } - else - { - groupData = mit->second; - } - return true; -} - -bool GxsDataProxyVEG::getMsgData(const std::string &msgId, void * &msgData) -{ - RsStackMutex stack(mDataMtx); /***** LOCKED *****/ - - std::map::iterator mit; - mit = mMsgData.find(msgId); - - if (mit == mMsgData.end()) - { - // error. - std::cerr << "GxsDataProxyVEG::getMsgData() Error Finding MsgId: " << msgId; - std::cerr << std::endl; - return false; - } - else - { - msgData = mit->second; - } - return true; -} - -#if 0 -bool GxsDataProxyVEG::getGroupData(const std::list &groupIds, std::list &groupData) -{ - std::list::const_iterator it; - for(it = groupIds.begin(); it != groupIds.end(); it++) - { - RsStackMutex stack(mDataMtx); /***** LOCKED *****/ - - std::map::iterator mit; - mit = mGroupData.find(*it); - - if (mit == mGroupData.end()) - { - // error. - std::cerr << "GxsDataProxyVEG::getGroupData() Error Finding GroupId: " << *it; - std::cerr << std::endl; - } - else - { - groupData.push_back(mit->second); - } - } - return true; -} - -bool GxsDataProxyVEG::getMsgData(const std::list &msgIds, std::list &msgData) -{ - std::list::const_iterator it; - for(it = msgIds.begin(); it != msgIds.end(); it++) - { - RsStackMutex stack(mDataMtx); /***** LOCKED *****/ - - std::map::iterator mit; - mit = mMsgData.find(*it); - - if (mit == mMsgData.end()) - { - // error. - std::cerr << "GxsDataProxyVEG::getMsgData() Error Finding MsgId: " << *it; - std::cerr << std::endl; - } - else - { - msgData.push_back(mit->second); - } - } - return true; -} -#endif - -bool GxsDataProxyVEG::isUniqueMsg(const std::string &msgId) -{ - RsStackMutex stack(mDataMtx); /***** LOCKED *****/ - - std::map::iterator mit; - mit = mMsgData.find(msgId); - - return (mit == mMsgData.end()); -} - - -bool GxsDataProxyVEG::isUniqueGroup(const std::string &groupId) -{ - RsStackMutex stack(mDataMtx); /***** LOCKED *****/ - - std::map::iterator mit; - mit = mGroupData.find(groupId); - - return (mit == mGroupData.end()); -} - - - -/*********************************************************************************************************/ -/*********************************************************************************************************/ -/*********************************************************************************************************/ -/*********************************************************************************************************/ -/*********************************************************************************************************/ - - -p3GxsDataServiceVEG::p3GxsDataServiceVEG(uint16_t type, GxsDataProxyVEG *proxy) - :p3GxsServiceVEG(type), mProxy(proxy) -{ - return; -} - - - - - -bool p3GxsDataServiceVEG::fakeprocessrequests() -{ - std::list toClear; - std::list::iterator cit; - time_t now = time(NULL); - - { RsStackMutex stack(mReqMtx); /******* LOCKED *******/ - - std::map::iterator it; - - for(it = mRequests.begin(); it != mRequests.end(); it++) - { - //std::cerr << "p3GxsDataServiceVEG::fakeprocessrequests() Token: " << it->second.token << " Status: " << it->second.status << " ReqType: " << it->second.reqType << " Age: " << now - it->second.reqTime << std::endl; - - if (it->second.status == GXS_REQUEST_STATUS_PENDING) - { - std::cerr << "p3GxsDataServiceVEG::fakeprocessrequests() Processing Token: " << it->second.token << " Status: " << it->second.status << " ReqType: " << it->second.reqType << " Age: " << now - it->second.reqTime << std::endl; - it->second.status = GXS_REQUEST_STATUS_PARTIAL; - /* PROCESS REQUEST! */ - switch(it->second.reqType) - { - case GXS_REQUEST_TYPE_GROUPS: - mProxy->getGroupList(it->second.token, it->second.Options, it->second.inList, it->second.outList); - break; - case GXS_REQUEST_TYPE_MSGS: - mProxy->getMsgList(it->second.token, it->second.Options, it->second.inList, it->second.outList); - break; - case GXS_REQUEST_TYPE_MSGRELATED: - mProxy->getMsgRelatedList(it->second.token, it->second.Options, it->second.inList, it->second.outList); - break; - default: - it->second.status = GXS_REQUEST_STATUS_FAILED; - break; - } - } - else if (it->second.status == GXS_REQUEST_STATUS_PARTIAL) - { - it->second.status = GXS_REQUEST_STATUS_COMPLETE; - } - else if (it->second.status == GXS_REQUEST_STATUS_DONE) - { - std::cerr << "p3GxsDataServiceVEG::fakeprocessrequests() Clearing Done Request Token: " << it->second.token; - std::cerr << std::endl; - toClear.push_back(it->second.token); - } - else if (now - it->second.reqTime > MAX_REQUEST_AGE) - { - std::cerr << "p3GxsDataServiceVEG::fakeprocessrequests() Clearing Old Request Token: " << it->second.token; - std::cerr << std::endl; - toClear.push_back(it->second.token); - } - } - - } // END OF MUTEX. - - for(cit = toClear.begin(); cit != toClear.end(); cit++) - { - clearRequest(*cit); - } - - return true; -} - -#if 0 // DISABLED AND MOVED TO GXS CODE. - -//std::ostream &operator<<(std::ostream &out, const RsGroupMetaData &meta) -//{ -// out << "[ GroupId: " << meta.mGroupId << " Name: " << meta.mGroupName << " ]"; -// return out; -//} - -//std::ostream &operator<<(std::ostream &out, const RsMsgMetaData &meta) -//{ -// out << "[ GroupId: " << meta.mGroupId << " MsgId: " << meta.mMsgId; -// out << " Name: " << meta.mMsgName; -// out << " OrigMsgId: " << meta.mOrigMsgId; -// out << " ThreadId: " << meta.mThreadId; -// out << " ParentId: " << meta.mParentId; -// out << " AuthorId: " << meta.mAuthorId; -// out << " Name: " << meta.mMsgName << " ]"; -// return out; -//} - -#endif - diff --git a/libretroshare/src/services/p3gxsserviceVEG.h b/libretroshare/src/services/p3gxsserviceVEG.h deleted file mode 100644 index 096ebdfb0..000000000 --- a/libretroshare/src/services/p3gxsserviceVEG.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - * libretroshare/src/services p3gxsservice.h - * - * Generic Service Support Class for RetroShare. - * - * Copyright 2012 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#ifndef P3_GXS_SERVICE_HEADER -#define P3_GXS_SERVICE_HEADER - -#include "services/p3service.h" -#include "retroshare/rsidentityVEG.h" - -/* - * This class provides useful generic support for GXS style services. - * I expect much of this will be incorporated into the base GXS. - * - */ - -#define GXS_REQUEST_STATUS_FAILED 0 -#define GXS_REQUEST_STATUS_PENDING 1 -#define GXS_REQUEST_STATUS_PARTIAL 2 -#define GXS_REQUEST_STATUS_FINISHED_INCOMPLETE 3 -#define GXS_REQUEST_STATUS_COMPLETE 4 -#define GXS_REQUEST_STATUS_DONE 5 // ONCE ALL DATA RETRIEVED. - -#define GXS_REQUEST_TYPE_GROUPS 0x00010000 -#define GXS_REQUEST_TYPE_MSGS 0x00020000 -#define GXS_REQUEST_TYPE_MSGRELATED 0x00040000 - -class gxsRequest -{ - public: - uint32_t token; - uint32_t reqTime; - - uint32_t ansType; - uint32_t reqType; - RsTokReqOptionsVEG Options; - - uint32_t status; - - std::list inList; - std::list outList; - //std::map readyData; -}; - - -class p3GxsServiceVEG: public p3Service -{ - protected: - - p3GxsServiceVEG(uint16_t type); - - public: - -//virtual ~p3Service() { p3Service::~p3Service(); return; } - -bool generateToken(uint32_t &token); -bool storeRequest(const uint32_t &token, const uint32_t &ansType, const RsTokReqOptionsVEG &opts, const uint32_t &type, const std::list &ids); -bool clearRequest(const uint32_t &token); - -bool updateRequestStatus(const uint32_t &token, const uint32_t &status); -bool updateRequestInList(const uint32_t &token, std::list ids); -bool updateRequestOutList(const uint32_t &token, std::list ids); -//bool updateRequestData(const uint32_t &token, std::map data); -bool checkRequestStatus(const uint32_t &token, uint32_t &status, uint32_t &reqtype, uint32_t &anstype, time_t &ts); - - // special ones for testing (not in final design) -bool tokenList(std::list &tokens); -bool popRequestInList(const uint32_t &token, std::string &id); -bool popRequestOutList(const uint32_t &token, std::string &id); -bool loadRequestOutList(const uint32_t &token, std::list &ids); - -virtual bool fakeprocessrequests(); - - protected: - - RsMutex mReqMtx; - - uint32_t mNextToken; - - std::map mRequests; - -}; - - -class GxsDataProxyVEG -{ - public: - - GxsDataProxyVEG(); - -virtual bool getGroupList( uint32_t &token, const RsTokReqOptionsVEG &opts, const std::list &groupIds, std::list &outGroupIds); -virtual bool getMsgList( uint32_t &token, const RsTokReqOptionsVEG &opts, const std::list &groupIds, std::list &outMsgIds); -virtual bool getMsgRelatedList(uint32_t &token, const RsTokReqOptionsVEG &opts, const std::list &msgIds, std::list &outMsgIds); - - - /* This functions return a token - which can be used to retrieve the RsGroupMetaData, later - * This is required, as signatures and keys might have to be generated in the background - * Though at the moment: for this test system it won't change anything? FIXME. - */ -virtual bool createGroup(void *groupData); -virtual bool createMsg(void *msgData); - - /* These Functions must be overloaded to complete the service */ -virtual bool convertGroupToMetaData(void *groupData, RsGroupMetaData &meta); -virtual bool convertMsgToMetaData(void *groupData, RsMsgMetaData &meta); - - /* extract Data */ - bool getGroupSummary(const std::list &groupIds, std::list &groupSummary); - bool getMsgSummary(const std::list &msgIds, std::list &msgSummary); - - bool getGroupSummary(const std::string &groupId, RsGroupMetaData &groupSummary); - bool getMsgSummary(const std::string &msgId, RsMsgMetaData &msgSummary); - - //bool getGroupData(const std::list &groupIds, std::list &groupData); - //bool getMsgData(const std::list &msgIds, std::list &msgData); - bool getGroupData(const std::string &groupId, void * &groupData); - bool getMsgData(const std::string &msgId, void * &msgData); - - bool isUniqueGroup(const std::string &groupId); - bool isUniqueMsg(const std::string &msgId); - - - /* Handle Status & Subscribe Modes */ -// This is removed as redundant - use getGroupList - with OptFlags to find these. -//virtual bool requestGroupsChanged(uint32_t &token); //std::list &groupIds); - - // Get Message Status - is retrived via MessageSummary. - // These operations could have a token, but for the moment we are going to assume - // they are async and always succeed - (or fail silently). -virtual bool setMessageStatus(const std::string &msgId, const uint32_t status, const uint32_t statusMask); -virtual bool setGroupStatus(const std::string &groupId, const uint32_t status, const uint32_t statusMask); -virtual bool setGroupSubscribeFlags(const std::string &groupId, uint32_t subscribeFlags, uint32_t subscribeMask); - -virtual bool setMessageServiceString(const std::string &msgId, const std::string &str); -virtual bool setGroupServiceString(const std::string &grpId, const std::string &str); - - protected: - - bool filterGroupList(const RsTokReqOptionsVEG &opts, std::list &groupIds); - bool filterMsgList(const RsTokReqOptionsVEG &opts, std::list &msgIds); - - - RsMutex mDataMtx; - - std::map mGroupData; - std::map mMsgData; - - std::map mGroupMetaData; - std::map mMsgMetaData; - -}; - - -class p3GxsDataServiceVEG: public p3GxsServiceVEG -{ - public: - - p3GxsDataServiceVEG(uint16_t type, GxsDataProxyVEG *proxy); -virtual bool fakeprocessrequests(); - - - protected: - - GxsDataProxyVEG *mProxy; -}; - - - -#endif // P3_GXS_SERVICE_HEADER - diff --git a/libretroshare/src/services/p3idservice.cc b/libretroshare/src/services/p3idservice.cc index 9524cb48b..5bb445bfd 100644 --- a/libretroshare/src/services/p3idservice.cc +++ b/libretroshare/src/services/p3idservice.cc @@ -139,9 +139,10 @@ RsIdentity *rsIdentity = NULL; p3IdService::p3IdService(RsGeneralDataService *gds, RsNetworkExchangeService *nes) : RsGxsIdExchange(gds, nes, new RsGxsIdSerialiser(), RS_SERVICE_GXSV2_TYPE_GXSID, idAuthenPolicy()), - RsIdentity(this), GxsTokenQueue(this), RsTickEvent(), mIdMtx("p3IdService"), + RsIdentity(this), GxsTokenQueue(this), RsTickEvent(), mPublicKeyCache(DEFAULT_MEM_CACHE_SIZE, "GxsIdPublicKeyCache"), - mPrivateKeyCache(DEFAULT_MEM_CACHE_SIZE, "GxsIdPrivateKeyCache"), mNes(nes) + mPrivateKeyCache(DEFAULT_MEM_CACHE_SIZE, "GxsIdPrivateKeyCache"), + mIdMtx("p3IdService"), mNes(nes) { mBgSchedule_Mode = 0; mBgSchedule_Active = false; @@ -2884,7 +2885,7 @@ void p3IdService::generateDummy_FriendPGP() int idx = RSRandom::random_f32() * (gpgids.size() - 1); it = gpgids.begin(); - for(int j = 0; j < idx; j++, it++); + for(int j = 0; j < idx; j++, it++) ; // HACK FOR DUMMY GENERATION. id.mMeta.mAuthorId = *it; diff --git a/libretroshare/src/services/p3idservice.h b/libretroshare/src/services/p3idservice.h index 48f8ebf9b..ff5dae197 100644 --- a/libretroshare/src/services/p3idservice.h +++ b/libretroshare/src/services/p3idservice.h @@ -91,9 +91,9 @@ virtual std::string save() const; bool tagsPending() const; // should we reprocess? bool tagValid(int i) const; + uint32_t tagFlags; time_t publishTs; time_t lastCheckTs; - uint32_t tagFlags; }; diff --git a/libretroshare/src/services/p3postbase.cc b/libretroshare/src/services/p3postbase.cc new file mode 100644 index 000000000..f277f15da --- /dev/null +++ b/libretroshare/src/services/p3postbase.cc @@ -0,0 +1,723 @@ +/* + * libretroshare/src/services p3posted.cc + * + * Posted interface for RetroShare. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include + +#include "retroshare/rsgxsflags.h" +#include +#include + +#include "services/p3postbase.h" +#include "serialiser/rsgxscommentitems.h" + +// For Dummy Msgs. +#include "util/rsrandom.h" +#include "util/rsstring.h" + +/**** + * #define POSTBASE_DEBUG 1 + ****/ + +#define POSTBASE_BACKGROUND_PROCESSING 0x0002 +#define PROCESSING_START_PERIOD 30 +#define PROCESSING_INC_PERIOD 15 + +#define POSTBASE_ALL_GROUPS 0x0011 +#define POSTBASE_UNPROCESSED_MSGS 0x0012 +#define POSTBASE_ALL_MSGS 0x0013 +#define POSTBASE_BG_POST_META 0x0014 +/********************************************************************************/ +/******************* Startup / Tick ******************************************/ +/********************************************************************************/ + +p3PostBase::p3PostBase(RsGeneralDataService *gds, RsNetworkExchangeService *nes, RsGixs* gixs, + RsSerialType* serviceSerialiser, uint16_t serviceType) + : RsGenExchange(gds, nes, serviceSerialiser, serviceType, gixs, postBaseAuthenPolicy()), GxsTokenQueue(this), RsTickEvent(), mPostBaseMtx("PostBaseMtx") +{ + mBgProcessing = false; + + mCommentService = new p3GxsCommentService(this, serviceType); + RsTickEvent::schedule_in(POSTBASE_BACKGROUND_PROCESSING, PROCESSING_START_PERIOD); +} + + +uint32_t p3PostBase::postBaseAuthenPolicy() +{ + uint32_t policy = 0; + uint32_t flag = 0; + + flag = GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN | GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN; + RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PUBLIC_GRP_BITS); + + flag |= GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN | GXS_SERV::MSG_AUTHEN_CHILD_PUBLISH_SIGN; + RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS); + RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS); + + flag = 0; + RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::GRP_OPTION_BITS); + + return policy; +} + +void p3PostBase::notifyChanges(std::vector &changes) +{ + std::cerr << "p3PostBase::notifyChanges()"; + std::cerr << std::endl; + + std::vector changesForGUI; + std::vector::iterator it; + + for(it = changes.begin(); it != changes.end(); it++) + { + RsGxsGroupChange *groupChange = dynamic_cast(*it); + RsGxsMsgChange *msgChange = dynamic_cast(*it); + if (msgChange) + { + std::cerr << "p3PostBase::notifyChanges() Found Message Change Notification"; + std::cerr << std::endl; + + std::map > &msgChangeMap = msgChange->msgChangeMap; + std::map >::iterator mit; + for(mit = msgChangeMap.begin(); mit != msgChangeMap.end(); mit++) + { + std::cerr << "p3PostBase::notifyChanges() Msgs for Group: " << mit->first; + std::cerr << std::endl; + // To start with we are just going to trigger updates on these groups. + // FUTURE OPTIMISATION. + // It could be taken a step further and directly request these msgs for an update. + addGroupForProcessing(mit->first); + } + delete msgChange; + } + + /* pass on Group Changes to GUI */ + if (groupChange) + { + std::cerr << "p3PostBase::notifyChanges() Found Group Change Notification"; + std::cerr << std::endl; + + std::list &groupList = groupChange->mGrpIdList; + std::list::iterator git; + for(git = groupList.begin(); git != groupList.end(); git++) + { + std::cerr << "p3PostBase::notifyChanges() Incoming Group: " << *git; + std::cerr << std::endl; + } + changesForGUI.push_back(groupChange); + } + } + changes.clear(); + receiveHelperChanges(changesForGUI); + + std::cerr << "p3PostBase::notifyChanges() -> receiveChanges()"; + std::cerr << std::endl; +} + +void p3PostBase::service_tick() +{ + RsTickEvent::tick_events(); + GxsTokenQueue::checkRequests(); + + mCommentService->comment_tick(); + + return; +} + +/********************************************************************************************/ +/********************************************************************************************/ + +void p3PostBase::setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) +{ + uint32_t mask = GXS_SERV::GXS_MSG_STATUS_UNREAD | GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; + uint32_t status = GXS_SERV::GXS_MSG_STATUS_UNREAD; + if (read) + { + status = 0; + } + + setMsgStatusFlags(token, msgId, status, mask); + +} + + + // Overloaded from RsTickEvent for Event callbacks. +void p3PostBase::handle_event(uint32_t event_type, const std::string & /* elabel */) +{ + std::cerr << "p3PostBase::handle_event(" << event_type << ")"; + std::cerr << std::endl; + + // stuff. + switch(event_type) + { + case POSTBASE_BACKGROUND_PROCESSING: + background_tick(); + break; + + default: + /* error */ + std::cerr << "p3PostBase::handle_event() Unknown Event Type: " << event_type; + std::cerr << std::endl; + break; + } +} + + +/********************************************************************************* + * Background Calculations. + * + * Get list of change groups from Notify.... + * this doesn't imclude your own submissions (at this point). + * So they will not be processed until someone else changes something. + * TODO FIX: Must push for that change. + * + * Eventually, we should just be able to get the new messages from Notify, + * and only process them! + */ + +void p3PostBase::background_tick() +{ + +#if 0 + { + RsStackMutex stack(mPostBaseMtx); /********** STACK LOCKED MTX ******/ + if (mBgGroupList.empty()) + { + background_requestAllGroups(); + } + } +#endif + + background_requestUnprocessedGroup(); + + RsTickEvent::schedule_in(POSTBASE_BACKGROUND_PROCESSING, PROCESSING_INC_PERIOD); + +} + +bool p3PostBase::background_requestAllGroups() +{ + std::cerr << "p3PostBase::background_requestAllGroups()"; + std::cerr << std::endl; + + uint32_t ansType = RS_TOKREQ_ANSTYPE_LIST; + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_IDS; + + uint32_t token = 0; + RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts); + GxsTokenQueue::queueRequest(token, POSTBASE_ALL_GROUPS); + + return true; +} + + +void p3PostBase::background_loadGroups(const uint32_t &token) +{ + /* get messages */ + std::cerr << "p3PostBase::background_loadGroups()"; + std::cerr << std::endl; + + std::list groupList; + bool ok = RsGenExchange::getGroupList(token, groupList); + + if (!ok) + { + return; + } + + std::list::iterator it; + for(it = groupList.begin(); it != groupList.end(); it++) + { + addGroupForProcessing(*it); + } +} + + +void p3PostBase::addGroupForProcessing(RsGxsGroupId grpId) +{ +#ifdef POSTBASE_DEBUG + std::cerr << "p3PostBase::addGroupForProcessing(" << grpId << ")"; + std::cerr << std::endl; +#endif // POSTBASE_DEBUG + + { + RsStackMutex stack(mPostBaseMtx); /********** STACK LOCKED MTX ******/ + // no point having multiple lookups queued. + if (mBgGroupList.end() == std::find(mBgGroupList.begin(), + mBgGroupList.end(), grpId)) + { + mBgGroupList.push_back(grpId); + } + } +} + + +void p3PostBase::background_requestUnprocessedGroup() +{ +#ifdef POSTBASE_DEBUG + std::cerr << "p3PostBase::background_requestUnprocessedGroup()"; + std::cerr << std::endl; +#endif // POSTBASE_DEBUG + + + RsGxsGroupId grpId; + { + RsStackMutex stack(mPostBaseMtx); /********** STACK LOCKED MTX ******/ + if (mBgProcessing) + { + std::cerr << "p3PostBase::background_requestUnprocessedGroup() Already Active"; + std::cerr << std::endl; + return; + } + if (mBgGroupList.empty()) + { + std::cerr << "p3PostBase::background_requestUnprocessedGroup() No Groups to Process"; + std::cerr << std::endl; + return; + } + + grpId = mBgGroupList.front(); + mBgGroupList.pop_front(); + mBgProcessing = true; + } + + background_requestGroupMsgs(grpId, true); +} + + + + + +void p3PostBase::background_requestGroupMsgs(const RsGxsGroupId &grpId, bool unprocessedOnly) +{ + std::cerr << "p3PostBase::background_requestGroupMsgs() id: " << grpId; + std::cerr << std::endl; + + uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; + + if (unprocessedOnly) + { + opts.mStatusFilter = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; + opts.mStatusMask = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; + } + + std::list grouplist; + grouplist.push_back(grpId); + + uint32_t token = 0; + + RsGenExchange::getTokenService()->requestMsgInfo(token, ansType, opts, grouplist); + + if (unprocessedOnly) + { + GxsTokenQueue::queueRequest(token, POSTBASE_UNPROCESSED_MSGS); + } + else + { + GxsTokenQueue::queueRequest(token, POSTBASE_ALL_MSGS); + } +} + + + + +void p3PostBase::background_loadUnprocessedMsgs(const uint32_t &token) +{ + background_loadMsgs(token, true); +} + + +void p3PostBase::background_loadAllMsgs(const uint32_t &token) +{ + background_loadMsgs(token, false); +} + + +/* This function is generalised to support any collection of messages, across multiple groups */ + +void p3PostBase::background_loadMsgs(const uint32_t &token, bool unprocessed) +{ + /* get messages */ + std::cerr << "p3PostBase::background_loadMsgs()"; + std::cerr << std::endl; + + std::map > msgData; + bool ok = RsGenExchange::getMsgData(token, msgData); + + if (!ok) + { + std::cerr << "p3PostBase::background_loadMsgs() Failed to getMsgData()"; + std::cerr << std::endl; + + /* cleanup */ + background_cleanup(); + return; + + } + + { + RsStackMutex stack(mPostBaseMtx); /********** STACK LOCKED MTX ******/ + mBgStatsMap.clear(); + mBgIncremental = unprocessed; + } + + std::map > postMap; + + // generate vector of changes to push to the GUI. + std::vector changes; + RsGxsMsgChange *msgChanges = new RsGxsMsgChange(RsGxsNotify::TYPE_PROCESSED); + + + RsGxsGroupId groupId; + std::map >::iterator mit; + std::vector::iterator vit; + for (mit = msgData.begin(); mit != msgData.end(); mit++) + { + groupId = mit->first; + for (vit = mit->second.begin(); vit != mit->second.end(); vit++) + { + RsGxsMessageId parentId = (*vit)->meta.mParentId; + RsGxsMessageId threadId = (*vit)->meta.mThreadId; + + + bool inc_counters = false; + uint32_t vote_up_inc = 0; + uint32_t vote_down_inc = 0; + uint32_t comment_inc = 0; + + bool add_voter = false; + RsGxsId voterId; + RsGxsCommentItem *commentItem; + RsGxsVoteItem *voteItem; + + /* THIS Should be handled by UNPROCESSED Filter - but isn't */ + if (!IS_MSG_UNPROCESSED((*vit)->meta.mMsgStatus)) + { + RsStackMutex stack(mPostBaseMtx); /********** STACK LOCKED MTX ******/ + if (mBgIncremental) + { + std::cerr << "p3PostBase::background_loadMsgs() Msg already Processed - Skipping"; + std::cerr << std::endl; + std::cerr << "p3PostBase::background_loadMsgs() ERROR This should not happen"; + std::cerr << std::endl; + delete(*vit); + continue; + } + } + + /* 3 types expected: PostedPost, Comment and Vote */ + if (parentId.empty()) + { + /* we don't care about top-level (Posts) */ + std::cerr << "\tIgnoring TopLevel Item"; + std::cerr << std::endl; + + /* but we need to notify GUI about them */ + msgChanges->msgChangeMap[mit->first].push_back((*vit)->meta.mMsgId); + } + else if (NULL != (commentItem = dynamic_cast(*vit))) + { + /* comment - want all */ + /* Comments are counted by Thread Id */ + std::cerr << "\tProcessing Comment: " << commentItem; + std::cerr << std::endl; + + inc_counters = true; + comment_inc = 1; + } + else if (NULL != (voteItem = dynamic_cast(*vit))) + { + /* vote - only care about direct children */ + if (parentId == threadId) + { + /* Votes are organised by Parent Id, + * ie. you can vote for both Posts and Comments + */ + std::cerr << "\tProcessing Vote: " << voteItem; + std::cerr << std::endl; + + inc_counters = true; + add_voter = true; + voterId = voteItem->meta.mAuthorId; + + if (voteItem->mMsg.mVoteType == GXS_VOTE_UP) + { + vote_up_inc = 1; + } + else + { + vote_down_inc = 1; + } + } + } + else + { + /* unknown! */ + std::cerr << "p3PostBase::background_processNewMessages() ERROR Strange NEW Message:"; + std::cerr << std::endl; + std::cerr << "\t" << (*vit)->meta; + std::cerr << std::endl; + + } + + if (inc_counters) + { + RsStackMutex stack(mPostBaseMtx); /********** STACK LOCKED MTX ******/ + + std::map::iterator sit = mBgStatsMap.find(threadId); + if (sit == mBgStatsMap.end()) + { + // add to map of ones to update. + postMap[groupId].push_back(threadId); + + mBgStatsMap[threadId] = PostStats(0,0,0); + sit = mBgStatsMap.find(threadId); + } + + sit->second.comments += comment_inc; + sit->second.up_votes += vote_up_inc; + sit->second.down_votes += vote_down_inc; + + + if (add_voter) + { + sit->second.voters.push_back(voterId); + } + + std::cerr << "\tThreadId: " << threadId; + std::cerr << " Comment Total: " << sit->second.comments; + std::cerr << " UpVote Total: " << sit->second.up_votes; + std::cerr << " DownVote Total: " << sit->second.down_votes; + std::cerr << std::endl; + } + + /* flag all messages as processed */ + if ((*vit)->meta.mMsgStatus & GXS_SERV::GXS_MSG_STATUS_UNPROCESSED) + { + uint32_t token_a; + RsGxsGrpMsgIdPair msgId = std::make_pair(groupId, (*vit)->meta.mMsgId); + RsGenExchange::setMsgStatusFlags(token_a, msgId, 0, GXS_SERV::GXS_MSG_STATUS_UNPROCESSED); + } + delete(*vit); + } + } + + /* push updates of new Posts */ + if (msgChanges->msgChangeMap.size() > 0) + { + std::cerr << "p3PostBase::background_processNewMessages() -> receiveChanges()"; + std::cerr << std::endl; + + changes.push_back(msgChanges); + receiveHelperChanges(changes); + } + + /* request the summary info from the parents */ + uint32_t token_b; + uint32_t anstype = RS_TOKREQ_ANSTYPE_SUMMARY; + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_MSG_META; + RsGenExchange::getTokenService()->requestMsgInfo(token_b, anstype, opts, postMap); + + GxsTokenQueue::queueRequest(token_b, POSTBASE_BG_POST_META); + return; +} + + +#define RSGXS_MAX_SERVICE_STRING 1024 +bool encodePostCache(std::string &str, const PostStats &s) +{ + char line[RSGXS_MAX_SERVICE_STRING]; + + snprintf(line, RSGXS_MAX_SERVICE_STRING, "%d %d %d", s.comments, s.up_votes, s.down_votes); + + str = line; + return true; +} + +bool extractPostCache(const std::string &str, PostStats &s) +{ + + uint32_t iupvotes, idownvotes, icomments; + if (3 == sscanf(str.c_str(), "%d %d %d", &icomments, &iupvotes, &idownvotes)) + { + s.comments = icomments; + s.up_votes = iupvotes; + s.down_votes = idownvotes; + return true; + } + return false; +} + + +void p3PostBase::background_updateVoteCounts(const uint32_t &token) +{ + std::cerr << "p3PostBase::background_updateVoteCounts()"; + std::cerr << std::endl; + + GxsMsgMetaMap parentMsgList; + GxsMsgMetaMap::iterator mit; + std::vector::iterator vit; + + bool ok = RsGenExchange::getMsgMeta(token, parentMsgList); + + if (!ok) + { + std::cerr << "p3PostBase::background_updateVoteCounts() ERROR"; + std::cerr << std::endl; + background_cleanup(); + return; + } + + // generate vector of changes to push to the GUI. + std::vector changes; + RsGxsMsgChange *msgChanges = new RsGxsMsgChange(RsGxsNotify::TYPE_PROCESSED); + + for(mit = parentMsgList.begin(); mit != parentMsgList.end(); mit++) + { + for(vit = mit->second.begin(); vit != mit->second.end(); vit++) + { + std::cerr << "p3PostBase::background_updateVoteCounts() Processing Msg(" << mit->first; + std::cerr << ", " << vit->mMsgId << ")"; + std::cerr << std::endl; + + RsStackMutex stack(mPostBaseMtx); /********** STACK LOCKED MTX ******/ + + /* extract current vote count */ + PostStats stats; + if (mBgIncremental) + { + if (!extractPostCache(vit->mServiceString, stats)) + { + if (!(vit->mServiceString.empty())) + { + std::cerr << "p3PostBase::background_updateVoteCounts() Failed to extract Votes"; + std::cerr << std::endl; + std::cerr << "\tFrom String: " << vit->mServiceString; + std::cerr << std::endl; + } + } + } + + /* get increment */ + std::map::iterator it; + it = mBgStatsMap.find(vit->mMsgId); + + if (it != mBgStatsMap.end()) + { + std::cerr << "p3PostBase::background_updateVoteCounts() Adding to msgChangeMap: "; + std::cerr << mit->first << " MsgId: " << vit->mMsgId; + std::cerr << std::endl; + + stats.increment(it->second); + msgChanges->msgChangeMap[mit->first].push_back(vit->mMsgId); + } + else + { + // warning. + std::cerr << "p3PostBase::background_updateVoteCounts() Warning No New Votes found."; + std::cerr << " For MsgId: " << vit->mMsgId; + std::cerr << std::endl; + } + + std::string str; + if (!encodePostCache(str, stats)) + { + std::cerr << "p3PostBase::background_updateVoteCounts() Failed to encode Votes"; + std::cerr << std::endl; + } + else + { + std::cerr << "p3PostBase::background_updateVoteCounts() Encoded String: " << str; + std::cerr << std::endl; + /* store new result */ + uint32_t token_c; + RsGxsGrpMsgIdPair msgId = std::make_pair(vit->mGroupId, vit->mMsgId); + RsGenExchange::setMsgServiceString(token_c, msgId, str); + } + } + } + + if (msgChanges->msgChangeMap.size() > 0) + { + std::cerr << "p3PostBase::background_updateVoteCounts() -> receiveChanges()"; + std::cerr << std::endl; + + changes.push_back(msgChanges); + receiveHelperChanges(changes); + } + + // DONE!. + background_cleanup(); + return; + +} + + +bool p3PostBase::background_cleanup() +{ + std::cerr << "p3PostBase::background_cleanup()"; + std::cerr << std::endl; + + RsStackMutex stack(mPostBaseMtx); /********** STACK LOCKED MTX ******/ + + // Cleanup. + mBgStatsMap.clear(); + mBgProcessing = false; + + return true; +} + + + // Overloaded from GxsTokenQueue for Request callbacks. +void p3PostBase::handleResponse(uint32_t token, uint32_t req_type) +{ + std::cerr << "p3PostBase::handleResponse(" << token << "," << req_type << ")"; + std::cerr << std::endl; + + // stuff. + switch(req_type) + { + case POSTBASE_ALL_GROUPS: + background_loadGroups(token); + break; + case POSTBASE_UNPROCESSED_MSGS: + background_loadUnprocessedMsgs(token); + break; + case POSTBASE_ALL_MSGS: + background_loadAllMsgs(token); + break; + case POSTBASE_BG_POST_META: + background_updateVoteCounts(token); + break; + default: + /* error */ + std::cerr << "p3PostBase::handleResponse() Unknown Request Type: " << req_type; + std::cerr << std::endl; + break; + } +} + diff --git a/libretroshare/src/services/p3postbase.h b/libretroshare/src/services/p3postbase.h new file mode 100644 index 000000000..b5ce1d895 --- /dev/null +++ b/libretroshare/src/services/p3postbase.h @@ -0,0 +1,135 @@ +/* + * libretroshare/src/services: p3postbase.h + * + * GxsChannel interface for RetroShare. + * + * Copyright 2012-2013 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef P3_POSTBASE_SERVICE_HEADER +#define P3_POSTBASE_SERVICE_HEADER + + +#include "services/p3gxscommon.h" +#include "gxs/rsgenexchange.h" + +#include "util/rstickevent.h" + +#include + +#include +#include +#include + +/* + * + */ + + +class PostStats +{ + public: + PostStats() :up_votes(0), down_votes(0), comments(0) { return; } + PostStats(int up, int down, int c) :up_votes(up), down_votes(down), comments(c) { return; } + + void increment(const PostStats &s) + { + up_votes += s.up_votes; + down_votes += s.down_votes; + comments += s.comments; + return; + } + + int up_votes; + int down_votes; + int comments; + std::list voters; +}; + +bool encodePostCache(std::string &str, const PostStats &s); +bool extractPostCache(const std::string &str, PostStats &s); + + +class p3PostBase: public RsGenExchange, public GxsTokenQueue, public RsTickEvent +{ + public: + + p3PostBase(RsGeneralDataService *gds, RsNetworkExchangeService *nes, RsGixs* gixs, + RsSerialType* serviceSerialiser, uint16_t serviceType); + +virtual void service_tick(); + + // This should be overloaded to call RsGxsIfaceHelper::receiveChanges(). +virtual void receiveHelperChanges(std::vector& changes) = 0; + + protected: + +virtual void notifyChanges(std::vector& changes); + + // Overloaded from GxsTokenQueue for Request callbacks. +virtual void handleResponse(uint32_t token, uint32_t req_type); + + // Overloaded from RsTickEvent. +virtual void handle_event(uint32_t event_type, const std::string &elabel); + + public: + + ////////////////////////////////////////////////////////////////////////////// + +virtual void setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read); + + + protected: + + p3GxsCommentService *mCommentService; + + private: + +static uint32_t postBaseAuthenPolicy(); + + // Background processing. + void background_tick(); + + bool background_requestAllGroups(); + void background_loadGroups(const uint32_t &token); + + void addGroupForProcessing(RsGxsGroupId grpId); + void background_requestUnprocessedGroup(); + + void background_requestGroupMsgs(const RsGxsGroupId &grpId, bool unprocessedOnly); + void background_loadUnprocessedMsgs(const uint32_t &token); + void background_loadAllMsgs(const uint32_t &token); + void background_loadMsgs(const uint32_t &token, bool unprocessed); + + + void background_updateVoteCounts(const uint32_t &token); + bool background_cleanup(); + + + RsMutex mPostBaseMtx; + + bool mBgProcessing; + bool mBgIncremental; + std::list mBgGroupList; + std::map mBgStatsMap; + +}; + +#endif diff --git a/libretroshare/src/services/p3posted.cc b/libretroshare/src/services/p3posted.cc index 08cde19de..e03ba6a70 100644 --- a/libretroshare/src/services/p3posted.cc +++ b/libretroshare/src/services/p3posted.cc @@ -26,146 +26,26 @@ #include "services/p3posted.h" #include "serialiser/rsposteditems.h" -#include - - -#include "retroshare/rsgxsflags.h" -#include #include -// For Dummy Msgs. -#include "util/rsrandom.h" -#include "util/rsstring.h" - /**** * #define POSTED_DEBUG 1 ****/ RsPosted *rsPosted = NULL; -//const uint32_t RsPosted::FLAG_MSGTYPE_POST = 0x0001; -//const uint32_t RsPosted::FLAG_MSGTYPE_MASK = 0x000f; - - -#define POSTED_TESTEVENT_DUMMYDATA 0x0001 -#define DUMMYDATA_PERIOD 60 // long enough for some RsIdentities to be generated. - -#define POSTED_BACKGROUND_PROCESSING 0x0002 -#define PROCESSING_START_PERIOD 30 -#define PROCESSING_INC_PERIOD 15 - -#define POSTED_ALL_GROUPS 0x0011 -#define POSTED_UNPROCESSED_MSGS 0x0012 -#define POSTED_ALL_MSGS 0x0013 -#define POSTED_BG_POST_META 0x0014 /********************************************************************************/ /******************* Startup / Tick ******************************************/ /********************************************************************************/ p3Posted::p3Posted(RsGeneralDataService *gds, RsNetworkExchangeService *nes, RsGixs* gixs) - : RsGenExchange(gds, nes, new RsGxsPostedSerialiser(), RS_SERVICE_GXSV2_TYPE_POSTED, gixs, postedAuthenPolicy()), RsPosted(this), GxsTokenQueue(this), RsTickEvent(), mPostedMtx("PostedMtx") + :p3PostBase(gds, nes, gixs, new RsGxsPostedSerialiser(), RS_SERVICE_GXSV2_TYPE_POSTED), + RsPosted(this) { - mBgProcessing = false; - - // For Dummy Msgs. - mGenActive = false; - mCommentService = new p3GxsCommentService(this, RS_SERVICE_GXSV2_TYPE_POSTED); - - // Test Data disabled in repo. - //RsTickEvent::schedule_in(POSTED_TESTEVENT_DUMMYDATA, DUMMYDATA_PERIOD); - - RsTickEvent::schedule_in(POSTED_BACKGROUND_PROCESSING, PROCESSING_START_PERIOD); -} - - - -uint32_t p3Posted::postedAuthenPolicy() -{ - uint32_t policy = 0; - uint32_t flag = 0; - - flag = GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN | GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PUBLIC_GRP_BITS); - - flag |= GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN | GXS_SERV::MSG_AUTHEN_CHILD_PUBLISH_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS); - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS); - - flag = 0; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::GRP_OPTION_BITS); - - return policy; -} - - - - - -void p3Posted::notifyChanges(std::vector &changes) -{ - std::cerr << "p3Posted::notifyChanges()"; - std::cerr << std::endl; - - std::vector changesForGUI; - std::vector::iterator it; - - for(it = changes.begin(); it != changes.end(); it++) - { - RsGxsGroupChange *groupChange = dynamic_cast(*it); - RsGxsMsgChange *msgChange = dynamic_cast(*it); - if (msgChange) - { - std::cerr << "p3Posted::notifyChanges() Found Message Change Notification"; - std::cerr << std::endl; - - std::map > &msgChangeMap = msgChange->msgChangeMap; - std::map >::iterator mit; - for(mit = msgChangeMap.begin(); mit != msgChangeMap.end(); mit++) - { - std::cerr << "p3Posted::notifyChanges() Msgs for Group: " << mit->first; - std::cerr << std::endl; - // To start with we are just going to trigger updates on these groups. - // FUTURE OPTIMISATION. - // It could be taken a step further and directly request these msgs for an update. - addGroupForProcessing(mit->first); - } - delete msgChange; - } - - /* pass on Group Changes to GUI */ - if (groupChange) - { - std::cerr << "p3Posted::notifyChanges() Found Group Change Notification"; - std::cerr << std::endl; - - std::list &groupList = groupChange->mGrpIdList; - std::list::iterator git; - for(git = groupList.begin(); git != groupList.end(); git++) - { - std::cerr << "p3Posted::notifyChanges() Incoming Group: " << *git; - std::cerr << std::endl; - } - changesForGUI.push_back(groupChange); - } - } - changes.clear(); - RsGxsIfaceHelper::receiveChanges(changesForGUI); - - std::cerr << "p3Posted::notifyChanges() -> receiveChanges()"; - std::cerr << std::endl; -} - -void p3Posted::service_tick() -{ - dummy_tick(); - RsTickEvent::tick_events(); - GxsTokenQueue::checkRequests(); - - mCommentService->comment_tick(); - return; } + bool p3Posted::getGroupData(const uint32_t &token, std::vector &groups) { std::vector grpData; @@ -296,7 +176,7 @@ bool RsPostedPost::calculateScores(time_t ref_time) /* so we want to calculate all the scores for this Post. */ PostStats stats; - extractPostedCache(mMeta.mServiceString, stats); + extractPostCache(mMeta.mServiceString, stats); mUpVotes = stats.up_votes; mDownVotes = stats.down_votes; @@ -323,8 +203,6 @@ bool RsPostedPost::calculateScores(time_t ref_time) return true; } - -/********************************************************************************************/ /********************************************************************************************/ /********************************************************************************************/ @@ -354,848 +232,4 @@ bool p3Posted::createPost(uint32_t &token, RsPostedPost &msg) return true; } - /********************************************************************************************/ -/********************************************************************************************/ - -void p3Posted::setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) -{ - uint32_t mask = GXS_SERV::GXS_MSG_STATUS_UNREAD | GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - uint32_t status = GXS_SERV::GXS_MSG_STATUS_UNREAD; - if (read) - { - status = 0; - } - - setMsgStatusFlags(token, msgId, status, mask); - -} - - - - - -/********************************************************************************************/ -/********************************************************************************************/ - -/* so we need the same tick idea as wiki for generating dummy channels - */ - -#define MAX_GEN_GROUPS 5 -#define MAX_GEN_MESSAGES 100 - -std::string p3Posted::genRandomId() -{ - std::string randomId; - for(int i = 0; i < 20; i++) - { - randomId += (char) ('a' + (RSRandom::random_u32() % 26)); - } - - return randomId; -} - -bool p3Posted::generateDummyData() -{ - mGenCount = 0; - mGenRefs.resize(MAX_GEN_MESSAGES); - - std::string groupName; - rs_sprintf(groupName, "TestTopic_%d", mGenCount); - - std::cerr << "p3Posted::generateDummyData() Starting off with Group: " << groupName; - std::cerr << std::endl; - - /* create a new group */ - generateGroup(mGenToken, groupName); - - mGenActive = true; - - return true; -} - - -void p3Posted::dummy_tick() -{ - /* check for a new callback */ - - if (mGenActive) - { - std::cerr << "p3Posted::dummyTick() AboutActive"; - std::cerr << std::endl; - - uint32_t status = RsGenExchange::getTokenService()->requestStatus(mGenToken); - if (status != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) - { - std::cerr << "p3Posted::dummy_tick() Status: " << status; - std::cerr << std::endl; - - if (status == RsTokenService::GXS_REQUEST_V2_STATUS_FAILED) - { - std::cerr << "p3Posted::dummy_tick() generateDummyMsgs() FAILED"; - std::cerr << std::endl; - mGenActive = false; - } - return; - } - - if (mGenCount < MAX_GEN_GROUPS) - { - /* get the group Id */ - RsGxsGroupId groupId; - RsGxsMessageId emptyId; - if (!acknowledgeTokenGrp(mGenToken, groupId)) - { - std::cerr << " ERROR "; - std::cerr << std::endl; - mGenActive = false; - return; - } - - std::cerr << "p3Posted::dummy_tick() Acknowledged GroupId: " << groupId; - std::cerr << std::endl; - - PostedDummyRef ref(groupId, emptyId, emptyId); - mGenRefs[mGenCount] = ref; - } - else if (mGenCount < MAX_GEN_MESSAGES) - { - /* get the msg Id, and generate next snapshot */ - RsGxsGrpMsgIdPair msgId; - if (!acknowledgeTokenMsg(mGenToken, msgId)) - { - std::cerr << " ERROR "; - std::cerr << std::endl; - mGenActive = false; - return; - } - - std::cerr << "p3Posted::dummy_tick() Acknowledged "; - std::cerr << std::endl; - - /* store results for later selection */ - - PostedDummyRef ref(msgId.first, mGenThreadId, msgId.second); - mGenRefs[mGenCount] = ref; - } - else - { - std::cerr << "p3Posted::dummy_tick() Finished"; - std::cerr << std::endl; - - /* done */ - mGenActive = false; - return; - } - - mGenCount++; - - if (mGenCount < MAX_GEN_GROUPS) - { - std::string groupName; - rs_sprintf(groupName, "TestTopic_%d", mGenCount); - - std::cerr << "p3Posted::dummy_tick() Generating Group: " << groupName; - std::cerr << std::endl; - - /* create a new group */ - generateGroup(mGenToken, groupName); - } - else - { - /* create a new message */ - uint32_t idx = (uint32_t) (mGenCount * RSRandom::random_f32()); - PostedDummyRef &ref = mGenRefs[idx]; - - RsGxsGroupId grpId = ref.mGroupId; - RsGxsMessageId parentId = ref.mMsgId; - mGenThreadId = ref.mThreadId; - if (mGenThreadId.empty()) - { - mGenThreadId = parentId; - } - - std::cerr << "p3Posted::dummy_tick() Generating Msg ... "; - std::cerr << " GroupId: " << grpId; - std::cerr << " ThreadId: " << mGenThreadId; - std::cerr << " ParentId: " << parentId; - std::cerr << std::endl; - - if (parentId.empty()) - { - generatePost(mGenToken, grpId); - } - else - { - generateComment(mGenToken, grpId, parentId, mGenThreadId); - } - } - } -} - - -bool p3Posted::generatePost(uint32_t &token, const RsGxsGroupId &grpId) -{ - RsPostedPost msg; - - std::string rndId = genRandomId(); - - rs_sprintf(msg.mNotes, "Posted Msg: GroupId: %s, some randomness: %s", - grpId.c_str(), rndId.c_str()); - - msg.mMeta.mMsgName = msg.mNotes; - - msg.mMeta.mGroupId = grpId; - msg.mMeta.mThreadId = ""; - msg.mMeta.mParentId = ""; - - msg.mMeta.mMsgStatus = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED | GXS_SERV::GXS_MSG_STATUS_UNREAD; - - /* chose a random Id to sign with */ - std::list ownIds; - std::list::iterator it; - - rsIdentity->getOwnIds(ownIds); - - uint32_t idx = (uint32_t) (ownIds.size() * RSRandom::random_f32()); - uint32_t i = 0; - for(it = ownIds.begin(); (it != ownIds.end()) && (i < idx); it++, i++) ; - - if (it != ownIds.end()) - { - std::cerr << "p3Posted::generateMessage() Author: " << *it; - std::cerr << std::endl; - msg.mMeta.mAuthorId = *it; - } - else - { - std::cerr << "p3Posted::generateMessage() No Author!"; - std::cerr << std::endl; - } - - createPost(token, msg); - - return true; -} - - -bool p3Posted::generateComment(uint32_t &token, const RsGxsGroupId &grpId, const RsGxsMessageId &parentId, const RsGxsMessageId &threadId) -{ - RsGxsComment msg; - - std::string rndId = genRandomId(); - - rs_sprintf(msg.mComment, "Posted Comment: GroupId: %s, ThreadId: %s, ParentId: %s + some randomness: %s", - grpId.c_str(), threadId.c_str(), parentId.c_str(), rndId.c_str()); - - msg.mMeta.mMsgName = msg.mComment; - - msg.mMeta.mGroupId = grpId; - msg.mMeta.mThreadId = threadId; - msg.mMeta.mParentId = parentId; - - msg.mMeta.mMsgStatus = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED | GXS_SERV::GXS_MSG_STATUS_UNREAD; - - /* chose a random Id to sign with */ - std::list ownIds; - std::list::iterator it; - - rsIdentity->getOwnIds(ownIds); - - uint32_t idx = (uint32_t) (ownIds.size() * RSRandom::random_f32()); - uint32_t i = 0; - for(it = ownIds.begin(); (it != ownIds.end()) && (i < idx); it++, i++) ; - - if (it != ownIds.end()) - { - std::cerr << "p3Posted::generateMessage() Author: " << *it; - std::cerr << std::endl; - msg.mMeta.mAuthorId = *it; - } - else - { - std::cerr << "p3Posted::generateMessage() No Author!"; - std::cerr << std::endl; - } - - createComment(token, msg); - - return true; -} - - -bool p3Posted::generateGroup(uint32_t &token, std::string groupName) -{ - /* generate a new group */ - RsPostedGroup group; - group.mMeta.mGroupName = groupName; - - createGroup(token, group); - - return true; -} - - - // Overloaded from RsTickEvent for Event callbacks. -void p3Posted::handle_event(uint32_t event_type, const std::string & /* elabel */) -{ - std::cerr << "p3Posted::handle_event(" << event_type << ")"; - std::cerr << std::endl; - - // stuff. - switch(event_type) - { - case POSTED_TESTEVENT_DUMMYDATA: - generateDummyData(); - break; - - case POSTED_BACKGROUND_PROCESSING: - background_tick(); - break; - - default: - /* error */ - std::cerr << "p3Posted::handle_event() Unknown Event Type: " << event_type; - std::cerr << std::endl; - break; - } -} - - -/********************************************************************************* - * Background Calculations. - * - * Get list of change groups from Notify.... - * this doesn't imclude your own submissions (at this point). - * So they will not be processed until someone else changes something. - * TODO FIX: Must push for that change. - * - * Eventually, we should just be able to get the new messages from Notify, - * and only process them! - */ - -void p3Posted::background_tick() -{ - -#if 0 - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - if (mBgGroupList.empty()) - { - background_requestAllGroups(); - } - } -#endif - - background_requestUnprocessedGroup(); - - RsTickEvent::schedule_in(POSTED_BACKGROUND_PROCESSING, PROCESSING_INC_PERIOD); - -} - -bool p3Posted::background_requestAllGroups() -{ - std::cerr << "p3Posted::background_requestAllGroups()"; - std::cerr << std::endl; - - uint32_t ansType = RS_TOKREQ_ANSTYPE_LIST; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_IDS; - - uint32_t token = 0; - RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts); - GxsTokenQueue::queueRequest(token, POSTED_ALL_GROUPS); - - return true; -} - - -void p3Posted::background_loadGroups(const uint32_t &token) -{ - /* get messages */ - std::cerr << "p3Posted::background_loadGroups()"; - std::cerr << std::endl; - - std::list groupList; - bool ok = RsGenExchange::getGroupList(token, groupList); - - if (!ok) - { - return; - } - - std::list::iterator it; - for(it = groupList.begin(); it != groupList.end(); it++) - { - addGroupForProcessing(*it); - } -} - - -void p3Posted::addGroupForProcessing(RsGxsGroupId grpId) -{ -#ifdef POSTED_DEBUG - std::cerr << "p3Posted::addGroupForProcessing(" << grpId << ")"; - std::cerr << std::endl; -#endif // POSTED_DEBUG - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - // no point having multiple lookups queued. - if (mBgGroupList.end() == std::find(mBgGroupList.begin(), - mBgGroupList.end(), grpId)) - { - mBgGroupList.push_back(grpId); - } - } -} - - -void p3Posted::background_requestUnprocessedGroup() -{ -#ifdef POSTED_DEBUG - std::cerr << "p3Posted::background_requestUnprocessedGroup()"; - std::cerr << std::endl; -#endif // POSTED_DEBUG - - - RsGxsGroupId grpId; - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - if (mBgProcessing) - { - std::cerr << "p3Posted::background_requestUnprocessedGroup() Already Active"; - std::cerr << std::endl; - return; - } - if (mBgGroupList.empty()) - { - std::cerr << "p3Posted::background_requestUnprocessedGroup() No Groups to Process"; - std::cerr << std::endl; - return; - } - - grpId = mBgGroupList.front(); - mBgGroupList.pop_front(); - mBgProcessing = true; - } - - background_requestGroupMsgs(grpId, true); -} - - - - - -void p3Posted::background_requestGroupMsgs(const RsGxsGroupId &grpId, bool unprocessedOnly) -{ - std::cerr << "p3Posted::background_requestGroupMsgs() id: " << grpId; - std::cerr << std::endl; - - uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - - if (unprocessedOnly) - { - opts.mStatusFilter = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - opts.mStatusMask = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - } - - std::list grouplist; - grouplist.push_back(grpId); - - uint32_t token = 0; - - RsGenExchange::getTokenService()->requestMsgInfo(token, ansType, opts, grouplist); - - if (unprocessedOnly) - { - GxsTokenQueue::queueRequest(token, POSTED_UNPROCESSED_MSGS); - } - else - { - GxsTokenQueue::queueRequest(token, POSTED_ALL_MSGS); - } -} - - - - -void p3Posted::background_loadUnprocessedMsgs(const uint32_t &token) -{ - background_loadMsgs(token, true); -} - - -void p3Posted::background_loadAllMsgs(const uint32_t &token) -{ - background_loadMsgs(token, false); -} - - -/* This function is generalised to support any collection of messages, across multiple groups */ - -void p3Posted::background_loadMsgs(const uint32_t &token, bool unprocessed) -{ - /* get messages */ - std::cerr << "p3Posted::background_loadMsgs()"; - std::cerr << std::endl; - - std::map > msgData; - bool ok = RsGenExchange::getMsgData(token, msgData); - - if (!ok) - { - std::cerr << "p3Posted::background_loadMsgs() Failed to getMsgData()"; - std::cerr << std::endl; - - /* cleanup */ - background_cleanup(); - return; - - } - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - mBgStatsMap.clear(); - mBgIncremental = unprocessed; - } - - std::map > postMap; - - // generate vector of changes to push to the GUI. - std::vector changes; - RsGxsMsgChange *msgChanges = new RsGxsMsgChange(RsGxsNotify::TYPE_PROCESSED); - - - RsGxsGroupId groupId; - std::map >::iterator mit; - std::vector::iterator vit; - for (mit = msgData.begin(); mit != msgData.end(); mit++) - { - groupId = mit->first; - for (vit = mit->second.begin(); vit != mit->second.end(); vit++) - { - RsGxsMessageId parentId = (*vit)->meta.mParentId; - RsGxsMessageId threadId = (*vit)->meta.mThreadId; - - - bool inc_counters = false; - uint32_t vote_up_inc = 0; - uint32_t vote_down_inc = 0; - uint32_t comment_inc = 0; - - bool add_voter = false; - RsGxsId voterId; - RsGxsCommentItem *commentItem; - RsGxsVoteItem *voteItem; - - /* THIS Should be handled by UNPROCESSED Filter - but isn't */ - if (!IS_MSG_UNPROCESSED((*vit)->meta.mMsgStatus)) - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - if (mBgIncremental) - { - std::cerr << "p3Posted::background_loadMsgs() Msg already Processed - Skipping"; - std::cerr << std::endl; - std::cerr << "p3Posted::background_loadMsgs() ERROR This should not happen"; - std::cerr << std::endl; - delete(*vit); - continue; - } - } - - /* 3 types expected: PostedPost, Comment and Vote */ - if (parentId.empty()) - { - /* we don't care about top-level (Posts) */ - std::cerr << "\tIgnoring TopLevel Item"; - std::cerr << std::endl; - - /* but we need to notify GUI about them */ - msgChanges->msgChangeMap[mit->first].push_back((*vit)->meta.mMsgId); - } - else if (NULL != (commentItem = dynamic_cast(*vit))) - { - /* comment - want all */ - /* Comments are counted by Thread Id */ - std::cerr << "\tProcessing Comment: " << commentItem; - std::cerr << std::endl; - - inc_counters = true; - comment_inc = 1; - } - else if (NULL != (voteItem = dynamic_cast(*vit))) - { - /* vote - only care about direct children */ - if (parentId == threadId) - { - /* Votes are organised by Parent Id, - * ie. you can vote for both Posts and Comments - */ - std::cerr << "\tProcessing Vote: " << voteItem; - std::cerr << std::endl; - - inc_counters = true; - add_voter = true; - voterId = voteItem->meta.mAuthorId; - - if (voteItem->mMsg.mVoteType == GXS_VOTE_UP) - { - vote_up_inc = 1; - } - else - { - vote_down_inc = 1; - } - } - } - else - { - /* unknown! */ - std::cerr << "p3Posted::background_processNewMessages() ERROR Strange NEW Message:"; - std::cerr << std::endl; - std::cerr << "\t" << (*vit)->meta; - std::cerr << std::endl; - - } - - if (inc_counters) - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator sit = mBgStatsMap.find(threadId); - if (sit == mBgStatsMap.end()) - { - // add to map of ones to update. - postMap[groupId].push_back(threadId); - - mBgStatsMap[threadId] = PostStats(0,0,0); - sit = mBgStatsMap.find(threadId); - } - - sit->second.comments += comment_inc; - sit->second.up_votes += vote_up_inc; - sit->second.down_votes += vote_down_inc; - - - if (add_voter) - { - sit->second.voters.push_back(voterId); - } - - std::cerr << "\tThreadId: " << threadId; - std::cerr << " Comment Total: " << sit->second.comments; - std::cerr << " UpVote Total: " << sit->second.up_votes; - std::cerr << " DownVote Total: " << sit->second.down_votes; - std::cerr << std::endl; - } - - /* flag all messages as processed */ - if ((*vit)->meta.mMsgStatus & GXS_SERV::GXS_MSG_STATUS_UNPROCESSED) - { - uint32_t token_a; - RsGxsGrpMsgIdPair msgId = std::make_pair(groupId, (*vit)->meta.mMsgId); - RsGenExchange::setMsgStatusFlags(token_a, msgId, 0, GXS_SERV::GXS_MSG_STATUS_UNPROCESSED); - } - delete(*vit); - } - } - - /* push updates of new Posts */ - if (msgChanges->msgChangeMap.size() > 0) - { - std::cerr << "p3Posted::background_processNewMessages() -> receiveChanges()"; - std::cerr << std::endl; - - changes.push_back(msgChanges); - RsGxsIfaceHelper::receiveChanges(changes); - } - - /* request the summary info from the parents */ - uint32_t token_b; - uint32_t anstype = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_META; - RsGenExchange::getTokenService()->requestMsgInfo(token_b, anstype, opts, postMap); - - GxsTokenQueue::queueRequest(token_b, POSTED_BG_POST_META); - return; -} - - -#define RSGXS_MAX_SERVICE_STRING 1024 -bool encodePostedCache(std::string &str, const PostStats &s) -{ - char line[RSGXS_MAX_SERVICE_STRING]; - - snprintf(line, RSGXS_MAX_SERVICE_STRING, "%d %d %d", s.comments, s.up_votes, s.down_votes); - - str = line; - return true; -} - -bool extractPostedCache(const std::string &str, PostStats &s) -{ - - uint32_t iupvotes, idownvotes, icomments; - if (3 == sscanf(str.c_str(), "%d %d %d", &icomments, &iupvotes, &idownvotes)) - { - s.comments = icomments; - s.up_votes = iupvotes; - s.down_votes = idownvotes; - return true; - } - return false; -} - - -void p3Posted::background_updateVoteCounts(const uint32_t &token) -{ - std::cerr << "p3Posted::background_updateVoteCounts()"; - std::cerr << std::endl; - - GxsMsgMetaMap parentMsgList; - GxsMsgMetaMap::iterator mit; - std::vector::iterator vit; - - bool ok = RsGenExchange::getMsgMeta(token, parentMsgList); - - if (!ok) - { - std::cerr << "p3Posted::background_updateVoteCounts() ERROR"; - std::cerr << std::endl; - background_cleanup(); - return; - } - - // generate vector of changes to push to the GUI. - std::vector changes; - RsGxsMsgChange *msgChanges = new RsGxsMsgChange(RsGxsNotify::TYPE_PROCESSED); - - for(mit = parentMsgList.begin(); mit != parentMsgList.end(); mit++) - { - for(vit = mit->second.begin(); vit != mit->second.end(); vit++) - { - std::cerr << "p3Posted::background_updateVoteCounts() Processing Msg(" << mit->first; - std::cerr << ", " << vit->mMsgId << ")"; - std::cerr << std::endl; - - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - /* extract current vote count */ - PostStats stats; - if (mBgIncremental) - { - if (!extractPostedCache(vit->mServiceString, stats)) - { - if (!(vit->mServiceString.empty())) - { - std::cerr << "p3Posted::background_updateVoteCounts() Failed to extract Votes"; - std::cerr << std::endl; - std::cerr << "\tFrom String: " << vit->mServiceString; - std::cerr << std::endl; - } - } - } - - /* get increment */ - std::map::iterator it; - it = mBgStatsMap.find(vit->mMsgId); - - if (it != mBgStatsMap.end()) - { - std::cerr << "p3Posted::background_updateVoteCounts() Adding to msgChangeMap: "; - std::cerr << mit->first << " MsgId: " << vit->mMsgId; - std::cerr << std::endl; - - stats.increment(it->second); - msgChanges->msgChangeMap[mit->first].push_back(vit->mMsgId); - } - else - { - // warning. - std::cerr << "p3Posted::background_updateVoteCounts() Warning No New Votes found."; - std::cerr << " For MsgId: " << vit->mMsgId; - std::cerr << std::endl; - } - - std::string str; - if (!encodePostedCache(str, stats)) - { - std::cerr << "p3Posted::background_updateVoteCounts() Failed to encode Votes"; - std::cerr << std::endl; - } - else - { - std::cerr << "p3Posted::background_updateVoteCounts() Encoded String: " << str; - std::cerr << std::endl; - /* store new result */ - uint32_t token_c; - RsGxsGrpMsgIdPair msgId = std::make_pair(vit->mGroupId, vit->mMsgId); - RsGenExchange::setMsgServiceString(token_c, msgId, str); - } - } - } - - if (msgChanges->msgChangeMap.size() > 0) - { - std::cerr << "p3Posted::background_updateVoteCounts() -> receiveChanges()"; - std::cerr << std::endl; - - changes.push_back(msgChanges); - RsGxsIfaceHelper::receiveChanges(changes); - } - - // DONE!. - background_cleanup(); - return; - -} - - -bool p3Posted::background_cleanup() -{ - std::cerr << "p3Posted::background_cleanup()"; - std::cerr << std::endl; - - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - // Cleanup. - mBgStatsMap.clear(); - mBgProcessing = false; - - return true; -} - - - // Overloaded from GxsTokenQueue for Request callbacks. -void p3Posted::handleResponse(uint32_t token, uint32_t req_type) -{ - std::cerr << "p3Posted::handleResponse(" << token << "," << req_type << ")"; - std::cerr << std::endl; - - // stuff. - switch(req_type) - { - case POSTED_ALL_GROUPS: - background_loadGroups(token); - break; - case POSTED_UNPROCESSED_MSGS: - background_loadUnprocessedMsgs(token); - break; - case POSTED_ALL_MSGS: - background_loadAllMsgs(token); - break; - case POSTED_BG_POST_META: - background_updateVoteCounts(token); - break; - default: - /* error */ - std::cerr << "p3Posted::handleResponse() Unknown Request Type: " << req_type; - std::cerr << std::endl; - break; - } -} - diff --git a/libretroshare/src/services/p3posted.h b/libretroshare/src/services/p3posted.h index a3bcd4d53..0f82277ec 100644 --- a/libretroshare/src/services/p3posted.h +++ b/libretroshare/src/services/p3posted.h @@ -28,10 +28,7 @@ #include "retroshare/rsposted.h" -#include "services/p3gxscommon.h" -#include "gxs/rsgenexchange.h" - -#include "util/rstickevent.h" +#include "services/p3postbase.h" #include @@ -43,72 +40,41 @@ * */ - -class PostStats -{ - public: - PostStats() :up_votes(0), down_votes(0), comments(0) { return; } - PostStats(int up, int down, int c) :up_votes(up), down_votes(down), comments(c) { return; } - - void increment(const PostStats &s) - { - up_votes += s.up_votes; - down_votes += s.down_votes; - comments += s.comments; - return; - } - - int up_votes; - int down_votes; - int comments; - std::list voters; -}; - -bool encodePostedCache(std::string &str, const PostStats &s); -bool extractPostedCache(const std::string &str, PostStats &s); - - -class p3Posted: public RsGenExchange, public RsPosted, - public GxsTokenQueue, - public RsTickEvent /* only needed for testing - remove after */ +class p3Posted: public p3PostBase, public RsPosted { public: p3Posted(RsGeneralDataService* gds, RsNetworkExchangeService* nes, RsGixs* gixs); -virtual void service_tick(); - protected: - -virtual void notifyChanges(std::vector& changes); - - // Overloaded from GxsTokenQueue for Request callbacks. -virtual void handleResponse(uint32_t token, uint32_t req_type); - - // Overloaded from RsTickEvent. -virtual void handle_event(uint32_t event_type, const std::string &elabel); +virtual void notifyChanges(std::vector& changes) +{ + return p3PostBase::notifyChanges(changes); +} public: +virtual void receiveHelperChanges(std::vector& changes) +{ + return RsGxsIfaceHelper::receiveChanges(changes); +} + + // Posted Specific DataTypes. virtual bool getGroupData(const uint32_t &token, std::vector &groups); virtual bool getPostData(const uint32_t &token, std::vector &posts); - virtual bool getRelatedPosts(const uint32_t &token, std::vector &posts); - ////////////////////////////////////////////////////////////////////////////// - -virtual void setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read); - -//virtual bool setMessageStatus(const std::string &msgId, const uint32_t status, const uint32_t statusMask); -//virtual bool setGroupSubscribeFlags(const std::string &groupId, uint32_t subscribeFlags, uint32_t subscribeMask); - -//virtual bool groupRestoreKeys(const std::string &groupId); -//virtual bool groupShareKeys(const std::string &groupId, std::list& peers); - virtual bool createGroup(uint32_t &token, RsPostedGroup &group); virtual bool createPost(uint32_t &token, RsPostedPost &post); + ////////////////////////////////////////////////////////////////////////////// + // WRAPPERS due to the separate Interface. + +virtual void setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) + { + return p3PostBase::setMessageReadStatus(token, msgId, read); + } /* Comment service - Provide RsGxsCommentService - redirect to p3GxsCommentService */ @@ -145,82 +111,6 @@ virtual bool acknowledgeVote(const uint32_t& token, std::pair mBgGroupList; - std::map mBgStatsMap; - - - - -// DUMMY DATA, -virtual bool generateDummyData(); - -std::string genRandomId(); - -void dummy_tick(); - -bool generatePost(uint32_t &token, const RsGxsGroupId &grpId); -bool generateComment(uint32_t &token, const RsGxsGroupId &grpId, - const RsGxsMessageId &parentId, const RsGxsMessageId &threadId); -bool generateGroup(uint32_t &token, std::string groupName); - - class PostedDummyRef - { - public: - PostedDummyRef() { return; } - PostedDummyRef(const RsGxsGroupId &grpId, const RsGxsMessageId &threadId, const RsGxsMessageId &msgId) - :mGroupId(grpId), mThreadId(threadId), mMsgId(msgId) { return; } - - RsGxsGroupId mGroupId; - RsGxsMessageId mThreadId; - RsGxsMessageId mMsgId; - }; - - uint32_t mGenToken; - bool mGenActive; - int mGenCount; - std::vector mGenRefs; - RsGxsMessageId mGenThreadId; - - p3GxsCommentService *mCommentService; }; - - - - - - - - #endif diff --git a/libretroshare/src/services/p3postedVEG.cc b/libretroshare/src/services/p3postedVEG.cc deleted file mode 100644 index 63acd3cba..000000000 --- a/libretroshare/src/services/p3postedVEG.cc +++ /dev/null @@ -1,2148 +0,0 @@ -/* - * libretroshare/src/services p3photoservice.cc - * - * Photo Service for RetroShare. - * - * Copyright 2012-2012 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "services/p3postedVEG.h" -#include "util/rsrandom.h" -#include -#include -#include - -/**** - * #define POSTED_DEBUG 1 - ****/ - -RsPostedVEG *rsPostedVEG = NULL; - - -/********************************************************************************/ -/******************* Startup / Tick ******************************************/ -/********************************************************************************/ - -p3PostedServiceVEG::p3PostedServiceVEG(uint16_t type) - :p3GxsDataServiceVEG(type, new PostedDataProxy()), mPostedMtx("p3PostedService"), mUpdated(true) -{ - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - mPostedProxy = (PostedDataProxy *) mProxy; - - mViewMode = RSPOSTED_VIEWMODE_HOT; - mViewPeriod = RSPOSTED_PERIOD_WEEK; - mViewStart = 0; - mViewCount = 50; - - mProcessingRanking = false; - mRankingState = 0; - mRankingExternalToken = 0; - mRankingInternalToken = 0; - - mLastBgCheck = 0; - mBgProcessing = 0; - mBgPhase = 0; - mBgToken = 0; - - } - - generateDummyData(); - return; -} - -#define POSTED_BACKGROUND_PERIOD 60 - -int p3PostedServiceVEG::tick() -{ - //std::cerr << "p3PostedServiceVEG::tick()"; - //std::cerr << std::endl; - - fakeprocessrequests(); - - - // Contine Ranking Request. - checkRankingRequest(); - - // Run Background Stuff. - background_checkTokenRequest(); - - /* every minute - run a background check */ - time_t now = time(NULL); - bool doCheck = false; - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - if (now - mLastBgCheck > POSTED_BACKGROUND_PERIOD) - { - doCheck = true; - mLastBgCheck = now; - } - } - - if (doCheck) - { - addExtraDummyData(); - background_requestGroups(); - } - - - - // Add in new votes + comments. - return 0; -} - -bool p3PostedServiceVEG::updated() -{ - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - if (mUpdated) - { - mUpdated = false; - return true; - } - return false; -} - - - - /* Data Requests */ -bool p3PostedServiceVEG::requestGroupInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptionsVEG &opts, const std::list &groupIds) -{ - generateToken(token); - std::cerr << "p3PostedServiceVEG::requestGroupInfo() gets Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_GROUPS, groupIds); - - return true; -} - -bool p3PostedServiceVEG::requestMsgInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptionsVEG &opts, const std::list &groupIds) -{ - generateToken(token); - std::cerr << "p3PostedServiceVEG::requestMsgInfo() gets Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_MSGS, groupIds); - - return true; -} - -bool p3PostedServiceVEG::requestMsgRelatedInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptionsVEG &opts, const std::list &msgIds) -{ - generateToken(token); - std::cerr << "p3PostedServiceVEG::requestMsgRelatedInfo() gets Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_MSGRELATED, msgIds); - - return true; -} - - /* Generic Lists */ -bool p3PostedServiceVEG::getGroupList( const uint32_t &token, std::list &groupIds) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (anstype != RS_TOKREQ_ANSTYPE_LIST) - { - std::cerr << "p3PostedServiceVEG::getGroupList() ERROR AnsType Wrong" << std::endl; - return false; - } - - if (reqtype != GXS_REQUEST_TYPE_GROUPS) - { - std::cerr << "p3PostedServiceVEG::getGroupList() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3PostedServiceVEG::getGroupList() ERROR Status Incomplete" << std::endl; - return false; - } - - bool ans = loadRequestOutList(token, groupIds); - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - return ans; -} - - - - -bool p3PostedServiceVEG::getMsgList( const uint32_t &token, std::list &msgIds) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (anstype != RS_TOKREQ_ANSTYPE_LIST) - { - std::cerr << "p3PostedServiceVEG::getMsgList() ERROR AnsType Wrong" << std::endl; - return false; - } - - if ((reqtype != GXS_REQUEST_TYPE_MSGS) && (reqtype != GXS_REQUEST_TYPE_MSGRELATED)) - { - std::cerr << "p3PostedServiceVEG::getMsgList() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3PostedServiceVEG::getMsgList() ERROR Status Incomplete" << std::endl; - return false; - } - - bool ans = loadRequestOutList(token, msgIds); - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - return ans; -} - - - /* Generic Summary */ -bool p3PostedServiceVEG::getGroupSummary( const uint32_t &token, std::list &groupInfo) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (anstype != RS_TOKREQ_ANSTYPE_SUMMARY) - { - std::cerr << "p3PostedServiceVEG::getGroupSummary() ERROR AnsType Wrong" << std::endl; - return false; - } - - if (reqtype != GXS_REQUEST_TYPE_GROUPS) - { - std::cerr << "p3PostedServiceVEG::getGroupSummary() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3PostedServiceVEG::getGroupSummary() ERROR Status Incomplete" << std::endl; - return false; - } - - std::list groupIds; - bool ans = loadRequestOutList(token, groupIds); - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - /* convert to RsGroupMetaData */ - mProxy->getGroupSummary(groupIds, groupInfo); - - return ans; -} - -bool p3PostedServiceVEG::getMsgSummary( const uint32_t &token, std::list &msgInfo) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (anstype != RS_TOKREQ_ANSTYPE_SUMMARY) - { - std::cerr << "p3PostedServiceVEG::getMsgSummary() ERROR AnsType Wrong" << std::endl; - return false; - } - - if ((reqtype != GXS_REQUEST_TYPE_MSGS) && (reqtype != GXS_REQUEST_TYPE_MSGRELATED)) - { - std::cerr << "p3PostedServiceVEG::getMsgSummary() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3PostedServiceVEG::getMsgSummary() ERROR Status Incomplete" << std::endl; - return false; - } - - std::list msgIds; - bool ans = loadRequestOutList(token, msgIds); - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - /* convert to RsMsgMetaData */ - mProxy->getMsgSummary(msgIds, msgInfo); - - return ans; -} - - - /* Specific Service Data */ -bool p3PostedServiceVEG::getGroup(const uint32_t &token, RsPostedGroup &group) -{ - std::cerr << "p3PostedServiceVEG::getGroup() Token: " << token; - std::cerr << std::endl; - - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - - if (anstype != RS_TOKREQ_ANSTYPE_DATA) - { - std::cerr << "p3PostedServiceVEG::getGroup() ERROR AnsType Wrong" << std::endl; - return false; - } - - if (reqtype != GXS_REQUEST_TYPE_GROUPS) - { - std::cerr << "p3PostedServiceVEG::getGroup() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3PostedServiceVEG::getGroup() ERROR Status Incomplete" << std::endl; - return false; - } - - std::string id; - if (!popRequestOutList(token, id)) - { - /* finished */ - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - return false; - } - - /* convert to RsPostedGroup */ - bool ans = mPostedProxy->getGroup(id, group); - return ans; -} - - -bool p3PostedServiceVEG::getPost(const uint32_t &token, RsPostedPost &post) -{ - std::cerr << "p3PostedServiceVEG::getPost() Token: " << token; - std::cerr << std::endl; - - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - - if (anstype != RS_TOKREQ_ANSTYPE_DATA) - { - std::cerr << "p3PostedServiceVEG::getPost() ERROR AnsType Wrong" << std::endl; - return false; - } - - if ((reqtype != GXS_REQUEST_TYPE_MSGS) && (reqtype != GXS_REQUEST_TYPE_MSGRELATED)) - { - std::cerr << "p3PostedServiceVEG::getPost() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3PostedServiceVEG::getPost() ERROR Status Incomplete" << std::endl; - return false; - } - - std::string id; - if (!popRequestOutList(token, id)) - { - /* finished */ - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - return false; - } - - /* convert to RsPhotoAlbum */ - bool ans = mPostedProxy->getPost(id, post); - return ans; -} - - -bool p3PostedServiceVEG::getComment(const uint32_t &token, RsPostedComment &comment) -{ - std::cerr << "p3PostedServiceVEG::getComment() Token: " << token; - std::cerr << std::endl; - - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - - if (anstype != RS_TOKREQ_ANSTYPE_DATA) - { - std::cerr << "p3PostedServiceVEG::getComment() ERROR AnsType Wrong" << std::endl; - return false; - } - - if ((reqtype != GXS_REQUEST_TYPE_MSGS) && (reqtype != GXS_REQUEST_TYPE_MSGRELATED)) - { - std::cerr << "p3PostedServiceVEG::getComment() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3PostedServiceVEG::getComment() ERROR Status Incomplete" << std::endl; - return false; - } - - std::string id; - if (!popRequestOutList(token, id)) - { - /* finished */ - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - return false; - } - - /* convert to RsPhotoAlbum */ - bool ans = mPostedProxy->getComment(id, comment); - return ans; -} - - /* Cancel Request */ -bool p3PostedServiceVEG::cancelRequest(const uint32_t &token) -{ - return clearRequest(token); -} - - ////////////////////////////////////////////////////////////////////////////// - - - -bool p3PostedServiceVEG::setMessageStatus(const std::string &msgId, const uint32_t status, const uint32_t statusMask) -{ - return mPostedProxy->setMessageStatus(msgId, status, statusMask); -} - -bool p3PostedServiceVEG::setGroupStatus(const std::string &groupId, const uint32_t status, const uint32_t statusMask) -{ - return mPostedProxy->setGroupStatus(groupId, status, statusMask); -} - -bool p3PostedServiceVEG::setGroupSubscribeFlags(const std::string &groupId, uint32_t subscribeFlags, uint32_t subscribeMask) -{ - return mPostedProxy->setGroupSubscribeFlags(groupId, subscribeFlags, subscribeMask); -} - -bool p3PostedServiceVEG::setMessageServiceString(const std::string &msgId, const std::string &str) -{ - return mPostedProxy->setMessageServiceString(msgId, str); -} - -bool p3PostedServiceVEG::setGroupServiceString(const std::string &grpId, const std::string &str) -{ - return mPostedProxy->setGroupServiceString(grpId, str); -} - - -bool p3PostedServiceVEG::groupRestoreKeys(const std::string &groupId) -{ - return false; -} - -bool p3PostedServiceVEG::groupShareKeys(const std::string &groupId, std::list& peers) -{ - return false; -} - - -bool p3PostedServiceVEG::submitGroup(uint32_t &token, RsPostedGroup &group, bool isNew) -{ - /* check if its a modification or a new album */ - - /* add to database */ - - /* check if its a mod or new photo */ - if (group.mMeta.mGroupId.empty()) - { - /* new photo */ - - /* generate a temp id */ - group.mMeta.mGroupId = genRandomId(); - group.mMeta.mPublishTs = time(NULL); - - std::cerr << "p3PostedServiceVEG::submitGroup() Generated New GroupID: " << group.mMeta.mGroupId; - std::cerr << std::endl; - } - - //group.mModFlags = 0; // These are always cleared. - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - mUpdated = true; - mPostedProxy->addGroup(group); - } - - // Fake a request to return the GroupMetaData. - generateToken(token); - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptionsVEG opts; // NULL is good. - std::list groupIds; - groupIds.push_back(group.mMeta.mGroupId); // It will just return this one. - - std::cerr << "p3PostedServiceVEG::submitGroup() Generating Request Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_GROUPS, groupIds); - - return true; -} - - -bool p3PostedServiceVEG::submitPost(uint32_t &token, RsPostedPost &post, bool isNew) -{ - if (post.mMeta.mGroupId.empty()) - { - /* new photo */ - std::cerr << "p3PostedServiceVEG::submitPost() Missing GroupID: ERROR"; - std::cerr << std::endl; - return false; - } - - /* generate a new id */ - post.mMeta.mMsgId = genRandomId(); - post.mMeta.mPublishTs = time(NULL); - - if (isNew) - { - /* new (Original Msg) photo */ - post.mMeta.mOrigMsgId = post.mMeta.mMsgId; - std::cerr << "p3PostedServiceVEG::submitPost() New Msg"; - std::cerr << std::endl; - } - else - { - std::cerr << "p3PostedServiceVEG::submitPost() Updated Msg"; - std::cerr << std::endl; - } - - //post.mModFlags = 0; // These are always cleared. - - std::cerr << "p3PostedServiceVEG::submitPost() OrigMsgId: " << post.mMeta.mOrigMsgId; - std::cerr << " MsgId: " << post.mMeta.mMsgId; - std::cerr << std::endl; - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - mUpdated = true; - mPostedProxy->addPost(post); - } - - // Fake a request to return the MsgMetaData. - generateToken(token); - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptionsVEG opts; // NULL is good. - std::list msgIds; - msgIds.push_back(post.mMeta.mMsgId); // It will just return this one. - - std::cerr << "p3PostedServiceVEG::submitPost() Generating Request Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_MSGRELATED, msgIds); - - return true; -} - - - -bool p3PostedServiceVEG::submitVote(uint32_t &token, RsPostedVote &vote, bool isNew) -{ - if (vote.mMeta.mGroupId.empty()) - { - /* new photo */ - std::cerr << "p3PostedServiceVEG::submitVote() Missing GroupID: ERROR"; - std::cerr << std::endl; - return false; - } - - /* generate a new id */ - vote.mMeta.mMsgId = genRandomId(); - vote.mMeta.mPublishTs = time(NULL); - - if (isNew) - { - /* new (Original Msg) photo */ - vote.mMeta.mOrigMsgId = vote.mMeta.mMsgId; - std::cerr << "p3PostedServiceVEG::submitVote() New Msg"; - std::cerr << std::endl; - } - else - { - std::cerr << "p3PostedServiceVEG::submitVote() Updated Msg"; - std::cerr << std::endl; - } - - //vote.mModFlags = 0; // These are always cleared. - - std::cerr << "p3PostedServiceVEG::submitVote() OrigMsgId: " << vote.mMeta.mOrigMsgId; - std::cerr << " MsgId: " << vote.mMeta.mMsgId; - std::cerr << std::endl; - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - mUpdated = true; - mPostedProxy->addVote(vote); - } - - // Fake a request to return the MsgMetaData. - generateToken(token); - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptionsVEG opts; // NULL is good. - std::list msgIds; - msgIds.push_back(vote.mMeta.mMsgId); // It will just return this one. - - std::cerr << "p3PostedServiceVEG::submitVote() Generating Request Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_MSGRELATED, msgIds); - - - return true; -} - - -bool p3PostedServiceVEG::submitComment(uint32_t &token, RsPostedComment &comment, bool isNew) -{ - if (comment.mMeta.mGroupId.empty()) - { - /* new photo */ - std::cerr << "p3PostedServiceVEG::submitPost() Missing GroupID: ERROR"; - std::cerr << std::endl; - return false; - } - - /* generate a new id */ - comment.mMeta.mMsgId = genRandomId(); - comment.mMeta.mPublishTs = time(NULL); - - if (isNew) - { - /* new (Original Msg) photo */ - comment.mMeta.mOrigMsgId = comment.mMeta.mMsgId; - std::cerr << "p3PostedServiceVEG::submitComment() New Msg"; - std::cerr << std::endl; - } - else - { - std::cerr << "p3PostedServiceVEG::submitComment() Updated Msg"; - std::cerr << std::endl; - } - - //comment.mModFlags = 0; // These are always cleared. - - std::cerr << "p3PostedServiceVEG::submitComment() OrigMsgId: " << comment.mMeta.mOrigMsgId; - std::cerr << " MsgId: " << comment.mMeta.mMsgId; - std::cerr << std::endl; - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - mUpdated = true; - mPostedProxy->addComment(comment); - } - - // Fake a request to return the MsgMetaData. - generateToken(token); - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptionsVEG opts; // NULL is good. - std::list msgIds; - msgIds.push_back(comment.mMeta.mMsgId); // It will just return this one. - - std::cerr << "p3PostedServiceVEG::submitComment() Generating Request Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_MSGRELATED, msgIds); - - return true; -} - - - -/********************************************************************************************/ - -bool PostedDataProxy::getGroup(const std::string &id, RsPostedGroup &group) -{ - void *groupData = NULL; - RsGroupMetaData meta; - if (getGroupData(id, groupData) && getGroupSummary(id, meta)) - { - RsPostedGroup *pG = (RsPostedGroup *) groupData; - group = *pG; - - group.mMeta = meta; - - std::cerr << "PostedDataProxy::getGroup() Id: " << id; - std::cerr << " MetaData: " << meta << " DataPointer: " << groupData; - std::cerr << std::endl; - return true; - } - - std::cerr << "PostedDataProxy::getGroup() FAILED Id: " << id; - std::cerr << std::endl; - - return false; -} - - - -bool PostedDataProxy::getPost(const std::string &id, RsPostedPost &post) -{ - void *msgData = NULL; - RsMsgMetaData meta; - if (getMsgData(id, msgData) && getMsgSummary(id, meta)) - { - RsPostedMsg *pM = (RsPostedMsg *) msgData; - - if (pM->postedType == RSPOSTED_MSGTYPE_POST) - { - RsPostedPost *pP = (RsPostedPost *) pM; - post = *pP; - - // update definitive version of the metadata. - post.mMeta = meta; - - std::cerr << "PostedDataProxy::getPost() Id: " << id; - std::cerr << " MetaData: " << meta << " DataPointer: " << msgData; - std::cerr << std::endl; - return true; - } - else - { - std::cerr << "PostedDataProxy::getPost() ERROR NOT POST Id: " << id; - std::cerr << " MetaData: " << meta << " DataPointer: " << msgData; - std::cerr << std::endl; - return false; - } - } - - std::cerr << "PostedDataProxy::getPost() FAILED Id: " << id; - std::cerr << std::endl; - - return false; -} - - - - -bool PostedDataProxy::getVote(const std::string &id, RsPostedVote &vote) -{ - void *msgData = NULL; - RsMsgMetaData meta; - if (getMsgData(id, msgData) && getMsgSummary(id, meta)) - { - RsPostedMsg *pM = (RsPostedMsg *) msgData; - - if (pM->postedType == RSPOSTED_MSGTYPE_VOTE) - { - RsPostedVote *pP = (RsPostedVote *) pM; - vote = *pP; - - // update definitive version of the metadata. - vote.mMeta = meta; - - std::cerr << "PostedDataProxy::getVote() Id: " << id; - std::cerr << " MetaData: " << meta << " DataPointer: " << msgData; - std::cerr << std::endl; - return true; - } - else - { - std::cerr << "PostedDataProxy::getVote() ERROR NOT VOTE Id: " << id; - std::cerr << " MetaData: " << meta << " DataPointer: " << msgData; - std::cerr << std::endl; - return false; - } - } - - std::cerr << "PostedDataProxy::getVote() FAILED Id: " << id; - std::cerr << std::endl; - - return false; -} - - - - -bool PostedDataProxy::getComment(const std::string &id, RsPostedComment &comment) -{ - void *msgData = NULL; - RsMsgMetaData meta; - if (getMsgData(id, msgData) && getMsgSummary(id, meta)) - { - RsPostedMsg *pM = (RsPostedMsg *) msgData; - - if (pM->postedType == RSPOSTED_MSGTYPE_COMMENT) - { - RsPostedComment *pP = (RsPostedComment *) pM; - comment = *pP; - - // update definitive version of the metadata. - comment.mMeta = meta; - - std::cerr << "PostedDataProxy::getComment() Id: " << id; - std::cerr << " MetaData: " << meta << " DataPointer: " << msgData; - std::cerr << std::endl; - return true; - } - else - { - std::cerr << "PostedDataProxy::getComment() ERROR NOT POST Id: " << id; - std::cerr << " MetaData: " << meta << " DataPointer: " << msgData; - std::cerr << std::endl; - return false; - } - } - - std::cerr << "PostedDataProxy::getComment() FAILED Id: " << id; - std::cerr << std::endl; - - return false; -} - - - - -bool PostedDataProxy::addGroup(const RsPostedGroup &group) -{ - // Make duplicate. - RsPostedGroup *pG = new RsPostedGroup(); - *pG = group; - - std::cerr << "PostedDataProxy::addGroup()"; - std::cerr << " MetaData: " << pG->mMeta << " DataPointer: " << pG; - std::cerr << std::endl; - - return createGroup(pG); -} - - -bool PostedDataProxy::addPost(const RsPostedPost &post) -{ - // Make duplicate. - RsPostedPost *pP = new RsPostedPost(); - *pP = post; - - std::cerr << "PostedDataProxy::addPost()"; - std::cerr << " MetaData: " << pP->mMeta << " DataPointer: " << pP; - std::cerr << std::endl; - - return createMsg(pP); -} - - -bool PostedDataProxy::addVote(const RsPostedVote &vote) -{ - // Make duplicate. - RsPostedVote *pP = new RsPostedVote(); - *pP = vote; - - std::cerr << "PostedDataProxy::addVote()"; - std::cerr << " MetaData: " << pP->mMeta << " DataPointer: " << pP; - std::cerr << std::endl; - - return createMsg(pP); -} - - -bool PostedDataProxy::addComment(const RsPostedComment &comment) -{ - // Make duplicate. - RsPostedComment *pP = new RsPostedComment(); - *pP = comment; - - std::cerr << "PostedDataProxy::addComment()"; - std::cerr << " MetaData: " << pP->mMeta << " DataPointer: " << pP; - std::cerr << std::endl; - - return createMsg(pP); -} - - - /* These Functions must be overloaded to complete the service */ -bool PostedDataProxy::convertGroupToMetaData(void *groupData, RsGroupMetaData &meta) -{ - RsPostedGroup *group = (RsPostedGroup *) groupData; - meta = group->mMeta; - - return true; -} - -bool PostedDataProxy::convertMsgToMetaData(void *msgData, RsMsgMetaData &meta) -{ - RsPostedMsg *msg = (RsPostedMsg *) msgData; - meta = msg->mMeta; - - return true; -} - - -/********************************************************************************************/ - -std::string p3PostedServiceVEG::genRandomId() -{ - std::string randomId; - for(int i = 0; i < 20; i++) - { - randomId += (char) ('a' + (RSRandom::random_u32() % 26)); - } - - return randomId; -} - - -/********************************************************************************************/ - -std::ostream &operator<<(std::ostream &out, const RsPostedPost &post) -{ - out << "RsPostedPost [ "; - out << "Title: " << post.mMeta.mMsgName; - out << "]"; - return out; -} - -std::ostream &operator<<(std::ostream &out, const RsPostedVote &vote) -{ - out << "RsPostedVote [ "; - out << "Title: " << vote.mMeta.mMsgName; - out << "]"; - return out; -} - -std::ostream &operator<<(std::ostream &out, const RsPostedComment &comment) -{ - out << "RsPostedComment [ "; - out << "Title: " << comment.mMeta.mMsgName; - out << "]"; - return out; -} - -std::ostream &operator<<(std::ostream &out, const RsPostedGroup &group) -{ - out << "RsPostedGroup [ "; - out << "Title: " << group.mMeta.mGroupName; - out << "]"; - return out; -} - - -/********************************************************************************************/ -/********************************************************************************************/ - -bool p3PostedServiceVEG::generateDummyData() -{ -#define MAX_GROUPS 10 //100 -#define MAX_POSTS 50 //1000 - -#define MAX_BASE_COMMENTS 1000 //10000 -#define MAX_COMMENTS 4000 //10000 - -#define MAX_VOTES 10000 //10000 - - std::list mGroups; - std::list::iterator git; - - std::list mPosts; - std::list::iterator pit; - - std::list mVotes; - std::list::iterator vit; - - std::list mComments; - std::list::iterator cit; - -#define DUMMY_NAME_MAX_LEN 10000 - char name[DUMMY_NAME_MAX_LEN]; - int i, j; - time_t now = time(NULL); - - for(i = 0; i < MAX_GROUPS; i++) - { - /* generate a new forum */ - RsPostedGroup group; - - snprintf(name, DUMMY_NAME_MAX_LEN, "TestTopic_%d", i+1); - - group.mMeta.mGroupId = genRandomId(); - group.mMeta.mGroupName = name; - - group.mMeta.mPublishTs = now - (RSRandom::random_f32() * 100000); - /* key fields to fill in: - * GroupId. - * Name. - * Flags. - * Pop. - */ - - - - /* use probability to decide which are subscribed / own / popularity. - */ - - float rnd = RSRandom::random_f32(); - if (rnd < 0.1) - { - group.mMeta.mSubscribeFlags = RSGXS_GROUP_SUBSCRIBE_ADMIN | RSGXS_GROUP_SUBSCRIBE_SUBSCRIBED; - - } - else if (rnd < 0.3) - { - group.mMeta.mSubscribeFlags = RSGXS_GROUP_SUBSCRIBE_SUBSCRIBED; - } - else - { - group.mMeta.mSubscribeFlags = 0; - } - - group.mMeta.mPop = (int) (RSRandom::random_f32() * 10.0); - mGroups.push_back(group); - - } - - for(i = 0; i < MAX_POSTS; i++) - { - /* generate a base thread */ - - /* rotate the Forum Groups Around, then pick one. - */ - - int rnd = (int) (RSRandom::random_f32() * 10.0); - - for(j = 0; j < rnd; j++) - { - RsPostedGroup head = mGroups.front(); - mGroups.pop_front(); - mGroups.push_back(head); - } - - RsPostedGroup group = mGroups.front(); - - /* now create a new thread */ - - RsPostedPost post; - - snprintf(name, DUMMY_NAME_MAX_LEN, "%s => Post_%d", group.mMeta.mGroupName.c_str(), i+1); - post.mMeta.mMsgName = name; - - post.mMeta.mGroupId = group.mMeta.mGroupId; - post.mMeta.mMsgId = genRandomId(); - post.mMeta.mOrigMsgId = post.mMeta.mMsgId; - post.mMeta.mThreadId = post.mMeta.mMsgId; - post.mMeta.mParentId = ""; - - post.mMeta.mPublishTs = group.mMeta.mPublishTs + (RSRandom::random_f32() * 10000); - if (post.mMeta.mPublishTs > now) - post.mMeta.mPublishTs = now - 1; - - mPosts.push_back(post); - - } - - for(i = 0; i < MAX_BASE_COMMENTS; i++) - { - /* generate a base thread */ - - /* rotate the Forum Groups Around, then pick one. - */ - - int rnd = (int) (RSRandom::random_f32() * 10.0); - - for(j = 0; j < rnd; j++) - { - RsPostedPost head = mPosts.front(); - mPosts.pop_front(); - mPosts.push_back(head); - } - - RsPostedPost parent = mPosts.front(); - - /* now create a new child msg */ - - RsPostedComment comment; - - /* fill in key data - * GroupId - * MsgId - * OrigMsgId - * ThreadId - * ParentId - * PublishTS (take Forum TS + a bit ). - * - * ChildTS ???? - */ - snprintf(name, DUMMY_NAME_MAX_LEN, "%s => Comment_%d", parent.mMeta.mMsgName.c_str(), i+1); - comment.mMeta.mMsgName = name; - //comment.mMsg = name; - - comment.mMeta.mGroupId = parent.mMeta.mGroupId; - comment.mMeta.mMsgId = genRandomId(); - comment.mMeta.mOrigMsgId = comment.mMeta.mMsgId; - comment.mMeta.mThreadId = parent.mMeta.mThreadId; - comment.mMeta.mParentId = parent.mMeta.mOrigMsgId; - - comment.mMeta.mPublishTs = parent.mMeta.mPublishTs + (RSRandom::random_f32() * 10000); - if (comment.mMeta.mPublishTs > now) - comment.mMeta.mPublishTs = now - 1; - - mComments.push_back(comment); - } - - - for(i = 0; i < MAX_COMMENTS; i++) - { - /* generate a base thread */ - - /* rotate the Forum Groups Around, then pick one. - */ - - int rnd = (int) (RSRandom::random_f32() * 10.0); - - for(j = 0; j < rnd; j++) - { - RsPostedComment head = mComments.front(); - mComments.pop_front(); - mComments.push_back(head); - } - - RsPostedComment parent = mComments.front(); - - /* now create a new child msg */ - - RsPostedComment comment; - - /* fill in key data - * GroupId - * MsgId - * OrigMsgId - * ThreadId - * ParentId - * PublishTS (take Forum TS + a bit ). - * - * ChildTS ???? - */ - snprintf(name, DUMMY_NAME_MAX_LEN, "%s => Comment_%d", parent.mMeta.mMsgName.c_str(), i+1); - comment.mMeta.mMsgName = name; - //comment.mMsg = name; - - comment.mMeta.mGroupId = parent.mMeta.mGroupId; - comment.mMeta.mMsgId = genRandomId(); - comment.mMeta.mOrigMsgId = comment.mMeta.mMsgId; - comment.mMeta.mThreadId = parent.mMeta.mThreadId; - comment.mMeta.mParentId = parent.mMeta.mOrigMsgId; - - comment.mMeta.mPublishTs = parent.mMeta.mPublishTs + (RSRandom::random_f32() * 10000); - if (comment.mMeta.mPublishTs > now) - comment.mMeta.mPublishTs = now - 1; - - mComments.push_back(comment); - } - - - for(i = 0; i < MAX_VOTES; i++) - { - /* generate a base thread */ - - /* rotate the Forum Groups Around, then pick one. - */ - - int rnd = (int) (RSRandom::random_f32() * 10.0); - - for(j = 0; j < rnd; j++) - { - RsPostedPost head = mPosts.front(); - mPosts.pop_front(); - mPosts.push_back(head); - } - - RsPostedPost parent = mPosts.front(); - - /* now create a new child msg */ - - RsPostedVote vote; - - snprintf(name, DUMMY_NAME_MAX_LEN, "%s => Vote_%d", parent.mMeta.mMsgName.c_str(), i+1); - vote.mMeta.mMsgName = name; - //vote.mMsg = name; - - vote.mMeta.mGroupId = parent.mMeta.mGroupId; - vote.mMeta.mMsgId = genRandomId(); - vote.mMeta.mOrigMsgId = vote.mMeta.mMsgId; - vote.mMeta.mThreadId = parent.mMeta.mThreadId; - vote.mMeta.mParentId = parent.mMeta.mOrigMsgId; - - vote.mMeta.mPublishTs = parent.mMeta.mPublishTs + (RSRandom::random_f32() * 10000); - if (vote.mMeta.mPublishTs > now) - vote.mMeta.mPublishTs = now - 1; - - mVotes.push_back(vote); - } - - - mUpdated = true; - - /* Then - at the end, we push them all into the Proxy */ - for(git = mGroups.begin(); git != mGroups.end(); git++) - { - /* pushback */ - mPostedProxy->addGroup(*git); - - } - - for(pit = mPosts.begin(); pit != mPosts.end(); pit++) - { - /* pushback */ - mPostedProxy->addPost(*pit); - } - - for(cit = mComments.begin(); cit != mComments.end(); cit++) - { - /* pushback */ -#define COMMENT_FRAC_FOR_LATER (0.70) - if (RSRandom::random_f32() > COMMENT_FRAC_FOR_LATER) - { - mPostedProxy->addComment(*cit); - } - else - { - mDummyLaterComments.push_back(*cit); - } - } - - - for(vit = mVotes.begin(); vit != mVotes.end(); vit++) - { - /* pushback */ - -#define VOTE_FRAC_FOR_LATER (0.70) - if (RSRandom::random_f32() > VOTE_FRAC_FOR_LATER) - { - mPostedProxy->addVote(*vit); - } - else - { - mDummyLaterVotes.push_back(*vit); - } - } - - return true; -} - -#define EXTRA_COMMENT_ADD (20) -#define EXTRA_VOTE_ADD (50) - -bool p3PostedServiceVEG::addExtraDummyData() -{ - std::cerr << "p3PostedServiceVEG::addExtraDummyData()"; - std::cerr << std::endl; - - int i = 0; - - std::list::iterator vit; - std::list::iterator cit; - - for(cit = mDummyLaterComments.begin(); (cit != mDummyLaterComments.end()) && (i < EXTRA_COMMENT_ADD); i++) - { - mPostedProxy->addComment(*cit); - cit = mDummyLaterComments.erase(cit); - } - - i = 0; - for(vit = mDummyLaterVotes.begin(); (vit != mDummyLaterVotes.end()) && (i < EXTRA_VOTE_ADD); i++) - { - mPostedProxy->addVote(*vit); - vit = mDummyLaterVotes.erase(vit); - } - - return true; -} - - - - -/********************************************************************************************/ -/********************************************************************************************/ -/********************************************************************************************/ -/********************************************************************************************/ -/********************************************************************************************/ - - -/* This is the part that will be kept for the final Version. - * we provide a processed view of the data... - * - * start off crude -> then make it efficient. - */ - - - -bool p3PostedServiceVEG::setViewMode(uint32_t mode) -{ - std::cerr << "p3PostedServiceVEG::setViewMode() : " << mode; - std::cerr << std::endl; - - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - mViewMode = mode; - - return true; -} - -bool p3PostedServiceVEG::setViewPeriod(uint32_t period) -{ - std::cerr << "p3PostedServiceVEG::setViewPeriod() : " << period; - std::cerr << std::endl; - - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - mViewPeriod = period; - - return true; -} - -bool p3PostedServiceVEG::setViewRange(uint32_t first, uint32_t count) -{ - std::cerr << "p3PostedServiceVEG::setViewRange() : " << first << " +" << count; - std::cerr << std::endl; - - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - mViewStart = first; - mViewCount = count; - - return true; -} - -float p3PostedServiceVEG::calcPostScore(const RsMsgMetaData &meta) -{ - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - float score = 0; - uint32_t votes = 0; - uint32_t comments = 0; - time_t now = time(NULL); - time_t age_secs = now - meta.mPublishTs; - // This is a potential problem for gaming the system... post into the future. - // Should fix this by discarding/hiding until ts valid XXX. - if (age_secs < 0) - { - age_secs = 0; - } - - if (!extractPostedCache(meta.mServiceString, votes, comments)) - { - /* no votes/comments yet */ - } - - /* this is dependent on View Mode */ - switch(mViewMode) - { - default: - case RSPOSTED_VIEWMODE_LATEST: - { - score = -age_secs; // - - break; - } - case RSPOSTED_VIEWMODE_TOP: - { - score = votes; - break; - } -// Potentially only -// This is effectively HackerNews Algorithm: which is (p-1)/(t+2)^1.5, where p is votes and t is age in hours. - case RSPOSTED_VIEWMODE_HOT: - { -#define POSTED_AGESHIFT (2.0) -#define POSTED_AGEFACTOR (3600.0) - score = votes / pow(POSTED_AGESHIFT + age_secs / POSTED_AGEFACTOR, 1.5); - break; - } -// Like HOT, but using number of Comments. - case RSPOSTED_VIEWMODE_COMMENTS: - { - score = comments / pow(POSTED_AGESHIFT + age_secs / POSTED_AGEFACTOR, 1.5); - break; - } - } - - return score; -} - -static uint32_t convertPeriodFlagToSeconds(uint32_t periodMode) -{ - float secs = 1; - switch(periodMode) - { - // Fallthrough all of them. - case RSPOSTED_PERIOD_YEAR: - secs *= 12; - case RSPOSTED_PERIOD_MONTH: - secs *= 4.3; // average ~30.4 days = 4.3 weeks. - case RSPOSTED_PERIOD_WEEK: - secs *= 7; - case RSPOSTED_PERIOD_DAY: - secs *= 24; - case RSPOSTED_PERIOD_HOUR: - secs *= 3600; - } - - return (uint32_t) secs; -} - -#define POSTED_RANKINGS_INITIAL_CHECK 1 -#define POSTED_RANKINGS_DATA_REQUEST 2 -#define POSTED_RANKINGS_NODATA 3 -#define POSTED_RANKINGS_DATA_DONE 4 - - /* Poll */ -uint32_t p3PostedServiceVEG::requestStatus(const uint32_t token) -{ - std::cerr << "p3PostedServiceVEG::requestStatus() Token: " << token; - std::cerr << std::endl; - - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - - uint32_t int_token = token; - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - if ((mProcessingRanking) && (token == mRankingExternalToken)) - { - std::cerr << "p3PostedServiceVEG::requestStatus() is RankingToken"; - std::cerr << std::endl; - - { - switch(mRankingState) - { - case POSTED_RANKINGS_INITIAL_CHECK: - status = GXS_REQUEST_STATUS_PENDING; - std::cerr << "p3PostedServiceVEG::requestStatus() RANKING PENDING"; - std::cerr << std::endl; - return status; - break; - case POSTED_RANKINGS_NODATA: - status = GXS_REQUEST_STATUS_COMPLETE; - std::cerr << "p3PostedServiceVEG::requestStatus() RANKING RETURNED NO DATA"; - std::cerr << std::endl; - return status; - break; - case POSTED_RANKINGS_DATA_REQUEST: - // Switch to real token. - int_token = mRankingInternalToken; - std::cerr << "p3PostedServiceVEG::requestStatus() Flipping to Int Token: " << int_token; - std::cerr << std::endl; - break; - - } - } - } - } - - checkRequestStatus(int_token, status, reqtype, anstype, ts); - - return status; -} - -bool p3PostedServiceVEG::getRankedPost(const uint32_t &token, RsPostedPost &post) -{ - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - if (!mProcessingRanking) - { - - std::cerr << "p3PostedServiceVEG::getRankedPost() ERROR not processing"; - std::cerr << std::endl; - return false; - } - - if (token != mRankingExternalToken) - { - std::cerr << "p3PostedServiceVEG::getRankedPost() ERROR wrong token"; - std::cerr << std::endl; - - return false; - } - - if (mRankingState == POSTED_RANKINGS_NODATA) - { - std::cerr << "p3PostedServiceVEG::getRankedPost() No Data for this request - sorry"; - std::cerr << std::endl; - - /* clean up */ - mProcessingRanking = false; - mRankingExternalToken = 0; - mRankingInternalToken = 0; - mRankingState = POSTED_RANKINGS_DATA_DONE; - - return false; - } - - if (mRankingState != POSTED_RANKINGS_DATA_REQUEST) - { - - std::cerr << "p3PostedServiceVEG::getRankedPost() ERROR wrong state"; - std::cerr << std::endl; - - return false; - - } - - - if (!getPost(mRankingInternalToken, post)) - { - std::cerr << "p3PostedServiceVEG::getRankedPost() End of Posts for this token"; - std::cerr << std::endl; - - /* clean up */ - mProcessingRanking = false; - mRankingExternalToken = 0; - mRankingInternalToken = 0; - mRankingState = POSTED_RANKINGS_DATA_DONE; - - return false; - } - - std::cerr << "p3PostedServiceVEG::getRankedPost() Got Post"; - std::cerr << std::endl; - - return true; -} - - -bool p3PostedServiceVEG::requestRanking(uint32_t &token, std::string groupId) -{ - std::cerr << "p3PostedServiceVEG::requestRanking()"; - std::cerr << std::endl; - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - if (mProcessingRanking) - { - std::cerr << "p3PostedServiceVEG::requestRanking() ERROR Request already running - ignoring"; - std::cerr << std::endl; - - return false; - } - } - - generateToken(token); - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - mProcessingRanking = true; - mRankingState = POSTED_RANKINGS_INITIAL_CHECK; - mRankingExternalToken = token; - } - - /* now we request all the posts within the timeframe */ - - uint32_t posttoken; - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptionsVEG opts; - - opts.mOptions = RS_TOKREQOPT_MSG_THREAD | RS_TOKREQOPT_MSG_LATEST; - //uint32_t age = convertPeriodFlagToSeconds(mViewPeriod); - - std::list groupIds; - groupIds.push_back(groupId); - - requestMsgInfo(posttoken, ansType, opts, groupIds); - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - std::cerr << "p3PostedServiceVEG::requestRanking() Saved Internal Token: " << posttoken; - std::cerr << std::endl; - mRankingInternalToken = posttoken; - } - return true; -} - -bool p3PostedServiceVEG::checkRankingRequest() -{ - uint32_t token = 0; - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - if (!mProcessingRanking) - { - //std::cerr << "p3PostedServiceVEG::checkRankingRequest() Not Processing"; - //std::cerr << std::endl; - return false; - } - - if (mRankingState != POSTED_RANKINGS_INITIAL_CHECK) - { - std::cerr << "p3PostedServiceVEG::checkRankingRequest() Not in Initial Check"; - std::cerr << std::endl; - return false; - } - - /* here it actually running! */ - token = mRankingInternalToken; - - std::cerr << "p3PostedServiceVEG::checkRankingRequest() Running with token: " << token; - std::cerr << std::endl; - } - - - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - if (checkRequestStatus(token, status, reqtype, anstype, ts)) - { - std::cerr << "p3PostedServiceVEG::checkRankingRequest() checkRequestStatus => OK"; - std::cerr << std::endl; - } - else - { - std::cerr << "p3PostedServiceVEG::checkRankingRequest() checkRequestStatus => ERROR"; - std::cerr << std::endl; - return false; - } - - if (status == GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3PostedServiceVEG::checkRankingRequest() Init Complete => processPosts"; - std::cerr << std::endl; - - processPosts(); - } - return true; -} - - -bool p3PostedServiceVEG::processPosts() -{ - std::cerr << "p3PostedServiceVEG::processPosts()"; - std::cerr << std::endl; - - uint32_t token = 0; - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - if (!mProcessingRanking) - { - std::cerr << "p3PostedServiceVEG::processPosts() ERROR Ranking Request not running"; - std::cerr << std::endl; - - return false; - } - - if (mRankingState != POSTED_RANKINGS_INITIAL_CHECK) - { - std::cerr << "p3PostedServiceVEG::processPosts() ERROR Ranking Request not running"; - std::cerr << std::endl; - - return false; - } - token = mRankingInternalToken; - } - - /* extract the info -> and sort */ - std::list postList; - std::list::const_iterator it; - - if (!getMsgSummary(token, postList)) - { - std::cerr << "p3PostedServiceVEG::processPosts() No Data for Request"; - std::cerr << std::endl; - - /* put it into a state, where the GUI will get to read an empty Queue */ - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - mRankingState = POSTED_RANKINGS_NODATA; - - return false; - } - - std::multimap postMap; - std::multimap::reverse_iterator mit; - - for(it = postList.begin(); it != postList.end(); it++) - { - float score = calcPostScore(*it); - postMap.insert(std::make_pair(score, it->mMsgId)); - } - - /* now grab the N required, and request the data again... - * -> this is what will be passed back to GUI - */ - - std::list msgList; - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - unsigned int i = 0; - for(mit = postMap.rbegin(); (mit != postMap.rend()) && (i < mViewStart); mit++, i++) - { - std::cerr << "p3PostedServiceVEG::processPosts() Skipping PostId: " << mit->second; - std::cerr << " with score: " << mit->first; - std::cerr << std::endl; - } - - - for(i = 0; (mit != postMap.rend()) && (i < mViewCount); mit++, i++) - { - std::cerr << "p3PostedServiceVEG::processPosts() Adding PostId: " << mit->second; - std::cerr << " with score: " << mit->first; - std::cerr << std::endl; - msgList.push_back(mit->second); - } - } - - token = 0; - uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; - RsTokReqOptionsVEG opts; - - requestMsgRelatedInfo(token, ansType, opts, msgList); - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - mRankingState = POSTED_RANKINGS_DATA_REQUEST; - mRankingInternalToken = token; - - std::cerr << "p3PostedServiceVEG::processPosts() Second Stage: token: " << token; - std::cerr << std::endl; - } - return true; -} - - - - - - - - -/***** Background Processing **** - * - * Process Each Message - as it arrives. - * - * Update - * - */ - -#define POSTED_BG_REQUEST_GROUPS 1 -#define POSTED_BG_REQUEST_UNPROCESSED 2 -#define POSTED_BG_REQUEST_PARENTS 3 -#define POSTED_BG_PROCESS_VOTES 4 - -bool p3PostedServiceVEG::background_checkTokenRequest() -{ - uint32_t token = 0; - uint32_t phase = 0; - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - if (!mBgProcessing) - { - return false; - } - - token = mBgToken; - phase = mBgPhase; - } - - - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (status == GXS_REQUEST_STATUS_COMPLETE) - { - switch(phase) - { - case POSTED_BG_REQUEST_GROUPS: - background_requestNewMessages(); - break; - case POSTED_BG_REQUEST_UNPROCESSED: - background_processNewMessages(); - break; - case POSTED_BG_REQUEST_PARENTS: - background_updateVoteCounts(); - break; - default: - break; - } - } - return true; -} - - -bool p3PostedServiceVEG::background_requestGroups() -{ - std::cerr << "p3PostedServiceVEG::background_requestGroups()"; - std::cerr << std::endl; - - // grab all the subscribed groups. - uint32_t token = 0; - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - mBgProcessing = true; - mBgPhase = POSTED_BG_REQUEST_GROUPS; - mBgToken = 0; - } - - uint32_t ansType = RS_TOKREQ_ANSTYPE_LIST; - RsTokReqOptionsVEG opts; - std::list groupIds; - - opts.mSubscribeFilter = RSGXS_GROUP_SUBSCRIBE_SUBSCRIBED; - - requestGroupInfo(token, ansType, opts, groupIds); - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - mBgToken = token; - } - - return true; -} - - -bool p3PostedServiceVEG::background_requestNewMessages() -{ - std::cerr << "p3PostedServiceVEG::background_requestNewMessages()"; - std::cerr << std::endl; - - std::list groupIds; - uint32_t token = 0; - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - token = mBgToken; - } - - if (!getGroupList(token, groupIds)) - { - std::cerr << "p3PostedServiceVEG::background_requestNewMessages() ERROR No Group List"; - std::cerr << std::endl; - background_cleanup(); - return false; - } - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - mBgPhase = POSTED_BG_REQUEST_UNPROCESSED; - mBgToken = 0; - } - - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptionsVEG opts; - token = 0; - - opts.mStatusFilter = RSGXS_MSG_STATUS_UNPROCESSED; - opts.mStatusMask = RSGXS_MSG_STATUS_UNPROCESSED; - - requestMsgInfo(token, ansType, opts, groupIds); - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - mBgToken = token; - } - return true; -} - - -bool p3PostedServiceVEG::background_processNewMessages() -{ - std::cerr << "p3PostedServiceVEG::background_processNewMessages()"; - std::cerr << std::endl; - - std::list newMsgList; - std::list::iterator it; - uint32_t token = 0; - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - token = mBgToken; - } - - if (!getMsgSummary(token, newMsgList)) - { - std::cerr << "p3PostedServiceVEG::background_processNewMessages() ERROR No New Msgs"; - std::cerr << std::endl; - background_cleanup(); - return false; - } - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - mBgPhase = POSTED_BG_REQUEST_PARENTS; - mBgToken = 0; - mBgVoteMap.clear(); - mBgCommentMap.clear(); - } - - /* loop through and sort by parents. - * - grab - */ - - std::list parentList; - - std::map::iterator vit; - - for(it = newMsgList.begin(); it != newMsgList.end(); it++) - { - std::cerr << "Found New MsgId: " << it->mMsgId; - std::cerr << std::endl; - - /* discard threadheads */ - if (it->mParentId.empty()) - { - std::cerr << "\tIgnoring ThreadHead: " << *it; - std::cerr << std::endl; - } - else if (it->mMsgFlags & RSPOSTED_MSGTYPE_COMMENT) - { - /* Comments are counted by Thread Id */ - std::cerr << "\tProcessing Comment: " << *it; - std::cerr << std::endl; - - vit = mBgCommentMap.find(it->mThreadId); - if (vit == mBgCommentMap.end()) - { - mBgCommentMap[it->mThreadId] = 1; - - /* check VoteMap too before adding to parentList */ - if (mBgVoteMap.end() == mBgVoteMap.find(it->mThreadId)) - { - parentList.push_back(it->mThreadId); - } - - std::cerr << "\tThreadId: " << it->mThreadId; - std::cerr << " Comment Total: " << mBgCommentMap[it->mThreadId]; - std::cerr << std::endl; - } - else - { - mBgVoteMap[it->mThreadId]++; - std::cerr << "\tThreadId: " << it->mThreadId; - std::cerr << " Comment Total: " << mBgCommentMap[it->mThreadId]; - std::cerr << std::endl; - } - } - else if (it->mMsgFlags & RSPOSTED_MSGTYPE_VOTE) - { - /* Votes are organised by Parent Id, - * ie. you can vote for both Posts and Comments - */ - std::cerr << "\tProcessing Vote: " << *it; - std::cerr << std::endl; - - vit = mBgVoteMap.find(it->mParentId); - if (vit == mBgVoteMap.end()) - { - mBgVoteMap[it->mParentId] = 1; - - /* check CommentMap too before adding to parentList */ - if (mBgCommentMap.end() == mBgCommentMap.find(it->mParentId)) - { - parentList.push_back(it->mParentId); - } - - std::cerr << "\tParentId: " << it->mParentId; - std::cerr << " Vote Total: " << mBgVoteMap[it->mParentId]; - std::cerr << std::endl; - } - else - { - mBgVoteMap[it->mParentId]++; - std::cerr << "\tParentId: " << it->mParentId; - std::cerr << " Vote Total: " << mBgVoteMap[it->mParentId]; - std::cerr << std::endl; - } - } - else - { - /* unknown! */ - std::cerr << "p3PostedServiceVEG::background_processNewMessages() ERROR Strange NEW Message:"; - std::cerr << std::endl; - std::cerr << "\t" << *it; - std::cerr << std::endl; - - } - - /* flag each new vote as processed */ - setMessageStatus(it->mMsgId, 0, RSGXS_MSG_STATUS_UNPROCESSED); - } - - - /* request the summary info from the parents */ - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - token = 0; - RsTokReqOptionsVEG opts; - requestMsgRelatedInfo(token, ansType, opts, parentList); - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - mBgToken = token; - } - return true; -} - - -bool p3PostedServiceVEG::encodePostedCache(std::string &str, uint32_t votes, uint32_t comments) -{ - char line[RSGXS_MAX_SERVICE_STRING]; - - snprintf(line, RSGXS_MAX_SERVICE_STRING, "%d %d", votes, comments); - - str = line; - return true; -} - -bool p3PostedServiceVEG::extractPostedCache(const std::string &str, uint32_t &votes, uint32_t &comments) -{ - - uint32_t ivotes, icomments; - if (2 == sscanf(str.c_str(), "%d %d", &ivotes, &icomments)) - { - votes = ivotes; - comments = icomments; - return true; - } - - return false; -} - - -bool p3PostedServiceVEG::background_updateVoteCounts() -{ - std::cerr << "p3PostedServiceVEG::background_updateVoteCounts()"; - std::cerr << std::endl; - - std::list parentMsgList; - std::list::iterator it; - - if (!getMsgSummary(mBgToken, parentMsgList)) - { - std::cerr << "p3PostedServiceVEG::background_updateVoteCounts() ERROR"; - std::cerr << std::endl; - background_cleanup(); - return false; - } - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - mBgPhase = POSTED_BG_PROCESS_VOTES; - mBgToken = 0; - } - - for(it = parentMsgList.begin(); it != parentMsgList.end(); it++) - { - /* extract current vote count */ - uint32_t votes = 0; - uint32_t comments = 0; - - if (!extractPostedCache(it->mServiceString, votes, comments)) - { - if (!(it->mServiceString.empty())) - { - std::cerr << "p3PostedServiceVEG::background_updateVoteCounts() Failed to extract Votes"; - std::cerr << std::endl; - std::cerr << "\tFrom String: " << it->mServiceString; - std::cerr << std::endl; - } - } - - /* find increment in votemap */ - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator vit; - vit = mBgVoteMap.find(it->mMsgId); - if (vit != mBgVoteMap.end()) - { - votes += vit->second; - } - else - { - // warning. - std::cerr << "p3PostedServiceVEG::background_updateVoteCounts() Warning No New Votes found."; - std::cerr << " For MsgId: " << it->mMsgId; - std::cerr << std::endl; - } - - } - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator cit; - cit = mBgCommentMap.find(it->mMsgId); - if (cit != mBgCommentMap.end()) - { - comments += cit->second; - } - else - { - // warning. - std::cerr << "p3PostedServiceVEG::background_updateVoteCounts() Warning No New Comments found."; - std::cerr << " For MsgId: " << it->mMsgId; - std::cerr << std::endl; - } - - } - - std::string str; - if (!encodePostedCache(str, votes, comments)) - { - std::cerr << "p3PostedServiceVEG::background_updateVoteCounts() Failed to encode Votes"; - std::cerr << std::endl; - } - else - { - std::cerr << "p3PostedServiceVEG::background_updateVoteCounts() Encoded String: " << str; - std::cerr << std::endl; - /* store new result */ - setMessageServiceString(it->mMsgId, str); - } - } - - // DONE!. - background_cleanup(); - return true; - -} - - -bool p3PostedServiceVEG::background_cleanup() -{ - std::cerr << "p3PostedServiceVEG::background_cleanup()"; - std::cerr << std::endl; - - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - // Cleanup. - mBgVoteMap.clear(); - mBgCommentMap.clear(); - mBgProcessing = false; - mBgToken = 0; - - return true; -} - - diff --git a/libretroshare/src/services/p3postedVEG.h b/libretroshare/src/services/p3postedVEG.h deleted file mode 100644 index f48bee9d0..000000000 --- a/libretroshare/src/services/p3postedVEG.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * libretroshare/src/services: p3posted.h - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2012-2012 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#ifndef P3_POSTED_SERVICE_VEG_HEADER -#define P3_POSTED_SERVICE_VEG_HEADER - -#include "services/p3gxsserviceVEG.h" -#include "retroshare/rspostedVEG.h" - -#include -#include - -/* - * Posted Service - * - */ - - -class PostedDataProxy: public GxsDataProxyVEG -{ - public: - - bool addGroup(const RsPostedGroup &group); - bool addPost(const RsPostedPost &post); - bool addVote(const RsPostedVote &vote); - bool addComment(const RsPostedComment &comment); - - bool getGroup(const std::string &id, RsPostedGroup &group); - bool getPost(const std::string &id, RsPostedPost &post); - bool getVote(const std::string &id, RsPostedVote &vote); - bool getComment(const std::string &id, RsPostedComment &comment); - - /* These Functions must be overloaded to complete the service */ -virtual bool convertGroupToMetaData(void *groupData, RsGroupMetaData &meta); -virtual bool convertMsgToMetaData(void *groupData, RsMsgMetaData &meta); - -}; - - - -class p3PostedServiceVEG: public p3GxsDataServiceVEG, public RsPostedVEG -{ - public: - - p3PostedServiceVEG(uint16_t type); - -virtual int tick(); - - public: - -// NEW INTERFACE. -/************* Extern Interface *******/ - -virtual bool updated(); - - /* Data Requests */ -virtual bool requestGroupInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptionsVEG &opts, const std::list &groupIds); -virtual bool requestMsgInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptionsVEG &opts, const std::list &groupIds); -virtual bool requestMsgRelatedInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptionsVEG &opts, const std::list &msgIds); - - /* Generic Lists */ -virtual bool getGroupList( const uint32_t &token, std::list &groupIds); -virtual bool getMsgList( const uint32_t &token, std::list &msgIds); - - /* Generic Summary */ -virtual bool getGroupSummary( const uint32_t &token, std::list &groupInfo); -virtual bool getMsgSummary( const uint32_t &token, std::list &msgInfo); - - /* Actual Data -> specific to Interface */ - /* Specific Service Data */ -virtual bool getGroup(const uint32_t &token, RsPostedGroup &group); -virtual bool getPost(const uint32_t &token, RsPostedPost &post); -virtual bool getComment(const uint32_t &token, RsPostedComment &comment); - - - /* Poll */ -virtual uint32_t requestStatus(const uint32_t token); - - /* Cancel Request */ -virtual bool cancelRequest(const uint32_t &token); - - ////////////////////////////////////////////////////////////////////////////// -virtual bool setMessageStatus(const std::string &msgId, const uint32_t status, const uint32_t statusMask); -virtual bool setGroupStatus(const std::string &groupId, const uint32_t status, const uint32_t statusMask); -virtual bool setGroupSubscribeFlags(const std::string &groupId, uint32_t subscribeFlags, uint32_t subscribeMask); -virtual bool setMessageServiceString(const std::string &msgId, const std::string &str); -virtual bool setGroupServiceString(const std::string &grpId, const std::string &str); - -virtual bool groupRestoreKeys(const std::string &groupId); -virtual bool groupShareKeys(const std::string &groupId, std::list& peers); - -virtual bool submitGroup(uint32_t &token, RsPostedGroup &group, bool isNew); -virtual bool submitPost(uint32_t &token, RsPostedPost &post, bool isNew); -virtual bool submitVote(uint32_t &token, RsPostedVote &vote, bool isNew); -virtual bool submitComment(uint32_t &token, RsPostedComment &comment, bool isNew); - - // Extended Interface for Collated Data View. -virtual bool setViewMode(uint32_t mode); -virtual bool setViewPeriod(uint32_t period); -virtual bool setViewRange(uint32_t first, uint32_t count); - -virtual bool requestRanking(uint32_t &token, std::string groupId); -virtual bool getRankedPost(const uint32_t &token, RsPostedPost &post); - - - // These are exposed for GUI usage. -virtual bool encodePostedCache(std::string &str, uint32_t votes, uint32_t comments); -virtual bool extractPostedCache(const std::string &str, uint32_t &votes, uint32_t &comments); -virtual float calcPostScore(const RsMsgMetaData &meta); - - private: - - // -bool checkRankingRequest(); -bool processPosts(); - - // background processing of Votes. - // NB: These should probably be handled by a background thread. - // At the moment they are run from the tick() thread. - -bool background_checkTokenRequest(); -bool background_requestGroups(); -bool background_requestNewMessages(); -bool background_processNewMessages(); - -bool background_updateVoteCounts(); -bool background_cleanup(); - - - -std::string genRandomId(); -bool generateDummyData(); -bool addExtraDummyData(); - - PostedDataProxy *mPostedProxy; - - RsMutex mPostedMtx; - bool mUpdated; - - // Ranking view mode, stored here. - uint32_t mViewMode; - uint32_t mViewPeriod; - uint32_t mViewStart; - uint32_t mViewCount; - - // Processing Ranking stuff. - bool mProcessingRanking; - uint32_t mRankingState; - uint32_t mRankingExternalToken; - uint32_t mRankingInternalToken; - - // background processing - Mutex protected. - time_t mLastBgCheck; - bool mBgProcessing; - uint32_t mBgPhase; - uint32_t mBgToken; - - std::map mBgVoteMap; // ParentId -> Vote Count. - std::map mBgCommentMap; // ThreadId -> Comment Count. - - // extra dummy data. - std::list mDummyLaterVotes; - std::list mDummyLaterComments; - - -}; - -#endif diff --git a/libretroshare/src/services/p3wiki.cc b/libretroshare/src/services/p3wiki.cc index 2390a4254..e20dc4f17 100644 --- a/libretroshare/src/services/p3wiki.cc +++ b/libretroshare/src/services/p3wiki.cc @@ -504,7 +504,7 @@ std::string chooseRandomAuthorId() uint32_t idx = (uint32_t) (ownIds.size() * RSRandom::random_f32()); int i = 0; - for(it = ownIds.begin(); (it != ownIds.end()) && (i < idx); it++, i++); + for(it = ownIds.begin(); (it != ownIds.end()) && (i < idx); it++, i++) ; std::string answer; if (it != ownIds.end())