/* * 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