From 6dd18eea464477db1fb05f23de98c6618190b45e Mon Sep 17 00:00:00 2001 From: chrisparker126 Date: Tue, 21 Aug 2012 21:32:07 +0000 Subject: [PATCH] seperated content value from retrodb added local meta changing fucntionality to gxs also added msgrelated info id retrieval to tokeservice git-svn-id: http://svn.code.sf.net/p/retroshare/code/branches/v0.5-gxs-b1@5452 b45a01b8-16f6-495d-af2f-9b41ad6348cc --- libretroshare/src/gxs/rsdataservice.cc | 16 +- libretroshare/src/gxs/rsgds.h | 14 + libretroshare/src/gxs/rsgenexchange.cc | 155 ++++++- libretroshare/src/gxs/rsgenexchange.h | 40 +- libretroshare/src/gxs/rsgxsdataaccess.cc | 433 ++++++++++-------- libretroshare/src/gxs/rsgxsdataaccess.h | 55 +-- libretroshare/src/gxs/rsgxsrequesttypes.h | 8 + libretroshare/src/gxs/rstokenservice.h | 42 +- .../src/services/p3photoserviceV2.cc | 6 +- libretroshare/src/util/contentvalue.cc | 311 +++++++++++++ libretroshare/src/util/contentvalue.h | 183 ++++++++ libretroshare/src/util/retrodb.cc | 314 +------------ libretroshare/src/util/retrodb.h | 152 +----- 13 files changed, 983 insertions(+), 746 deletions(-) create mode 100644 libretroshare/src/util/contentvalue.cc create mode 100644 libretroshare/src/util/contentvalue.h diff --git a/libretroshare/src/gxs/rsdataservice.cc b/libretroshare/src/gxs/rsdataservice.cc index fd9180444..a362f3bda 100644 --- a/libretroshare/src/gxs/rsdataservice.cc +++ b/libretroshare/src/gxs/rsdataservice.cc @@ -120,6 +120,14 @@ #define RS_DATA_SERVICE_DEBUG +const std::string RsGeneralDataService::GRP_META_SERV_STRING = KEY_NXS_SERV_STRING; +const std::string RsGeneralDataService::GRP_META_STATUS = KEY_GRP_STATUS; +const std::string RsGeneralDataService::GRP_META_SUBSCRIBE_FLAG = KEY_GRP_SUBCR_FLAG; + +const std::string RsGeneralDataService::MSG_META_SERV_STRING = KEY_NXS_SERV_STRING; +const std::string RsGeneralDataService::MSG_META_STATUS = KEY_MSG_STATUS; + + RsDataService::RsDataService(const std::string &serviceDir, const std::string &dbName, uint16_t serviceType, RsGxsSearchModule *mod) : RsGeneralDataService(), mServiceDir(serviceDir), mDbName(mServiceDir + "/" + dbName), mServType(serviceType){ @@ -910,12 +918,16 @@ int RsDataService::removeGroups(const std::vector &grpIds) int RsDataService::updateGroupMetaData(GrpLocMetaData &meta) { - return 0; + RsGxsGroupId& grpId = meta.grpId; + return mDb->sqlUpdate(GRP_TABLE_NAME, KEY_GRP_ID+ "='" + grpId + "'", meta.val) ? 1 : 0; } int RsDataService::updateMessageMetaData(MsgLocMetaData &metaData) { - return 0; + RsGxsGroupId& grpId = metaData.msgId.first; + RsGxsMessageId& msgId = metaData.msgId.second; + return mDb->sqlUpdate(MSG_TABLE_NAME, KEY_GRP_ID+ "='" + grpId + + "' AND " + KEY_MSG_ID + "='" + msgId + "'", metaData.val) ? 1 : 0; } diff --git a/libretroshare/src/gxs/rsgds.h b/libretroshare/src/gxs/rsgds.h index 58212ee8d..428a0be69 100644 --- a/libretroshare/src/gxs/rsgds.h +++ b/libretroshare/src/gxs/rsgds.h @@ -55,6 +55,8 @@ public: class MsgLocMetaData { public: + MsgLocMetaData(const MsgLocMetaData& meta){ msgId = meta.msgId; val = meta.val;} + MsgLocMetaData() {} RsGxsGrpMsgIdPair msgId; ContentValue val; }; @@ -66,6 +68,8 @@ public: class GrpLocMetaData { public: + GrpLocMetaData(const GrpLocMetaData& meta){ grpId = meta.grpId; val = meta.val;} + GrpLocMetaData(){} RsGxsGroupId grpId; ContentValue val; @@ -98,6 +102,16 @@ typedef std::map > GxsMsgResult; // & msgId) + RsGxsGrpMsgIdPair& msgId) { RsStackMutex stack(mGenMtx); - std::map >::iterator mit = - mMsgPublished.find(token); + std::map::iterator mit = + mMsgNotify.find(token); - if(mit == mMsgPublished.end()) - return false; + if(mit == mMsgNotify.end()) + { + return false; + } - msgId = mit->second; - // no dump token as client has ackowledged its completion - mDataAccess->disposeOfPublicToken(token); + msgId = mit->second; + + // no dump token as client has ackowledged its completion + mDataAccess->disposeOfPublicToken(token); return true; } @@ -95,9 +103,9 @@ bool RsGenExchange::acknowledgeTokenGrp(const uint32_t& token, RsStackMutex stack(mGenMtx); std::map::iterator mit = - mGrpPublished.find(token); + mGrpNotify.find(token); - if(mit == mGrpPublished.end()) + if(mit == mGrpNotify.end()) return false; grpId = mit->second; @@ -395,28 +403,131 @@ void RsGenExchange::notifyNewMessages(std::vector& messages) } -bool RsGenExchange::publishGroup(uint32_t& token, RsGxsGrpItem *grpItem) +void RsGenExchange::publishGroup(uint32_t& token, RsGxsGrpItem *grpItem) { RsStackMutex stack(mGenMtx); token = mDataAccess->generatePublicToken(); mGrpsToPublish.insert(std::make_pair(token, grpItem)); - - return true; } -bool RsGenExchange::publishMsg(uint32_t& token, RsGxsMsgItem *msgItem) +void RsGenExchange::publishMsg(uint32_t& token, RsGxsMsgItem *msgItem) +{ + RsStackMutex stack(mGenMtx); + + token = mDataAccess->generatePublicToken(); + mMsgsToPublish.insert(std::make_pair(token, msgItem)); +} + +void RsGenExchange::setGroupSubscribeFlag(uint32_t& token, const RsGxsGroupId& grpId, const uint32_t& flag) +{ + RsStackMutex stack(mGenMtx); + token = mDataAccess->generatePublicToken(); + + GrpLocMetaData g; + g.grpId = grpId; + g.val.put(RsGeneralDataService::GRP_META_SUBSCRIBE_FLAG, (int32_t)flag); + mGrpLocMetaMap.insert(std::make_pair(token, g)); +} + +void RsGenExchange::setGroupStatusFlag(uint32_t& token, const RsGxsGroupId& grpId, const uint32_t& status) +{ + RsStackMutex stack(mGenMtx); + token = mDataAccess->generatePublicToken(); + + GrpLocMetaData g; + g.grpId = grpId; + g.val.put(RsGeneralDataService::GRP_META_STATUS, (int32_t)status); + mGrpLocMetaMap.insert(std::make_pair(token, g)); +} + + +void RsGenExchange::setGroupServiceString(uint32_t& token, const RsGxsGroupId& grpId, const std::string& servString) +{ + RsStackMutex stack(mGenMtx); + token = mDataAccess->generatePublicToken(); + + GrpLocMetaData g; + g.grpId = grpId; + g.val.put(RsGeneralDataService::GRP_META_SERV_STRING, servString); + mGrpLocMetaMap.insert(std::make_pair(token, g)); +} + +void RsGenExchange::setMsgStatusFlag(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, const uint32_t& status) +{ + RsStackMutex stack(mGenMtx); + token = mDataAccess->generatePublicToken(); + + MsgLocMetaData m; + m.val.put(RsGeneralDataService::MSG_META_STATUS, (int32_t)status); + m.msgId = msgId; + mMsgLocMetaMap.insert(std::make_pair(token, m)); +} + +void RsGenExchange::setMsgServiceString(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, const std::string& servString ) +{ + RsStackMutex stack(mGenMtx); + token = mDataAccess->generatePublicToken(); + + MsgLocMetaData m; + m.val.put(RsGeneralDataService::MSG_META_SERV_STRING, servString); + m.msgId = msgId; + mMsgLocMetaMap.insert(std::make_pair(token, m)); +} + +void RsGenExchange::processMsgMetaChanges() { - RsStackMutex stack(mGenMtx); + RsStackMutex stack(mGenMtx); - token = mDataAccess->generatePublicToken(); - mMsgsToPublish.insert(std::make_pair(token, msgItem)); + std::map::iterator mit = mMsgLocMetaMap.begin(), + mit_end = mMsgLocMetaMap.end(); - return true; + for(; mit != mit_end; mit++) + { + MsgLocMetaData& m = mit->second; + bool ok = mDataStore->updateMessageMetaData(m) == 1; + uint32_t token = mit->first; + + if(ok) + { + mDataAccess->updatePublicRequestStatus(token, RsTokenServiceV2::GXS_REQUEST_STATUS_COMPLETE); + }else + { + mDataAccess->updatePublicRequestStatus(token, RsTokenServiceV2::GXS_REQUEST_STATUS_FAILED); + } + mMsgNotify.insert(std::make_pair(token, m.msgId)); + } + + mMsgLocMetaMap.clear(); } +void RsGenExchange::processGrpMetaChanges() +{ + RsStackMutex stack(mGenMtx); + + std::map::iterator mit = mGrpLocMetaMap.begin(), + mit_end = mGrpLocMetaMap.end(); + + for(; mit != mit_end; mit++) + { + GrpLocMetaData& g = mit->second; + uint32_t token = mit->first; + bool ok = mDataStore->updateGroupMetaData(g) == 1; + + if(ok) + { + mDataAccess->updatePublicRequestStatus(token, RsTokenServiceV2::GXS_REQUEST_STATUS_COMPLETE); + }else + { + mDataAccess->updatePublicRequestStatus(token, RsTokenServiceV2::GXS_REQUEST_STATUS_FAILED); + } + mGrpNotify.insert(std::make_pair(token, g.grpId)); + } + + mGrpLocMetaMap.clear(); +} void RsGenExchange::publishMsgs() { @@ -453,7 +564,7 @@ void RsGenExchange::publishMsgs() ok = mDataAccess->addMsgData(msg); // add to published to allow acknowledgement - mMsgPublished.insert(std::make_pair(mit->first, std::make_pair(msg->grpId, msg->msgId))); + mMsgNotify.insert(std::make_pair(mit->first, std::make_pair(msg->grpId, msg->msgId))); mDataAccess->updatePublicRequestStatus(mit->first, RsTokenServiceV2::GXS_REQUEST_STATUS_COMPLETE); } @@ -463,7 +574,7 @@ void RsGenExchange::publishMsgs() #ifdef GEN_EXCH_DEBUG std::cerr << "RsGenExchange::publishMsgs() failed to publish msg " << std::endl; #endif - mMsgPublished.insert(std::make_pair(mit->first, std::make_pair(RsGxsGroupId(""), RsGxsMessageId("")))); + mMsgNotify.insert(std::make_pair(mit->first, std::make_pair(RsGxsGroupId(""), RsGxsMessageId("")))); delete msg; continue; @@ -509,7 +620,7 @@ void RsGenExchange::publishGrps() ok = mDataAccess->addGroupData(grp); // add to published to allow acknowledgement - mGrpPublished.insert(std::make_pair(mit->first, grp->grpId)); + mGrpNotify.insert(std::make_pair(mit->first, grp->grpId)); mDataAccess->updatePublicRequestStatus(mit->first, RsTokenServiceV2::GXS_REQUEST_STATUS_COMPLETE); } @@ -522,7 +633,7 @@ void RsGenExchange::publishGrps() delete grp; // add to published to allow acknowledgement, grpid is empty as grp creation failed - mGrpPublished.insert(std::make_pair(mit->first, RsGxsGroupId(""))); + mGrpNotify.insert(std::make_pair(mit->first, RsGxsGroupId(""))); mDataAccess->updatePublicRequestStatus(mit->first, RsTokenServiceV2::GXS_REQUEST_STATUS_FAILED); continue; } diff --git a/libretroshare/src/gxs/rsgenexchange.h b/libretroshare/src/gxs/rsgenexchange.h index 20a8407e5..cf433dbaa 100644 --- a/libretroshare/src/gxs/rsgenexchange.h +++ b/libretroshare/src/gxs/rsgenexchange.h @@ -161,7 +161,7 @@ public: * @param msgIds map of grpid->msgIds of message created/modified * @return true if token exists false otherwise */ - bool acknowledgeTokenMsg(const uint32_t& token, std::pair& msgId); + bool acknowledgeTokenMsg(const uint32_t& token, RsGxsGrpMsgIdPair& msgId); /*! * This allows the client service to acknowledge that their grps has @@ -184,7 +184,7 @@ protected: * @param token * @param grpItem */ - bool publishGroup(uint32_t& token, RsGxsGrpItem* grpItem); + void publishGroup(uint32_t& token, RsGxsGrpItem* grpItem); /*! * Enables publication of a message item @@ -194,7 +194,23 @@ protected: * @param token * @param msgItem */ - bool publishMsg(uint32_t& token, RsGxsMsgItem* msgItem); + void publishMsg(uint32_t& token, RsGxsMsgItem* msgItem); + + /*! + * sets the group subscribe flag + * @param token this is set to token value associated to this request + * @param + */ + void setGroupSubscribeFlag(uint32_t& token, const RsGxsGroupId& grpId, const uint32_t& status); + + void setGroupStatusFlag(uint32_t& token, const RsGxsGroupId& grpId, const uint32_t& status); + + void setGroupServiceString(uint32_t& token, const RsGxsGroupId& grpId, const std::string& servString); + + void setMsgStatusFlag(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, const uint32_t& status); + + void setMsgServiceString(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, const std::string& servString ); + protected: @@ -227,6 +243,16 @@ private: void publishMsgs(); + /*! + * processes msg local meta changes + */ + void processMsgMetaChanges(); + + /*! + * Processes group local meta changes + */ + void processGrpMetaChanges(); + void createGroup(RsNxsGrp* grp); bool createMessage(RsNxsMsg* msg); @@ -244,8 +270,12 @@ private: std::map mGrpsToPublish; std::map mMsgsToPublish; - std::map > mMsgPublished; - std::map mGrpPublished; + std::map mMsgNotify; + std::map mGrpNotify; + + // for loc meta changes + std::map mGrpLocMetaMap; + std::map mMsgLocMetaMap; std::vector mNotifications; diff --git a/libretroshare/src/gxs/rsgxsdataaccess.cc b/libretroshare/src/gxs/rsgxsdataaccess.cc index fd9b198c6..e72035217 100644 --- a/libretroshare/src/gxs/rsgxsdataaccess.cc +++ b/libretroshare/src/gxs/rsgxsdataaccess.cc @@ -153,58 +153,22 @@ bool RsGxsDataAccess::requestMsgInfo(uint32_t &token, uint32_t ansType, return true; } -bool RsGxsDataAccess::requestSetGroupSubscribeFlags(uint32_t& token, const RsGxsGroupId &grpId, uint32_t subscribeFlags, - uint32_t subscribeMask) + +bool RsGxsDataAccess::requestMsgRelatedInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptionsV2 &opts, const GxsMsgReq& msgIds) { - generateToken(token); + MsgRelatedInfoReq* req = new MsgRelatedInfoReq(); + req->mMsgIds = msgIds; - GroupSetFlagReq* req = new GroupSetFlagReq(); + generateToken(token); - req->flag = subscribeFlags; - req->flagMask = subscribeMask; - req->grpId = grpId; + setReq(req, token, ansType, opts); + storeRequest(req); - std::cerr << "RsGxsDataAccess::requestSetGroupSubscribeFlags() gets Token: " << token << std::endl; - storeRequest(req); - return false; + return true; } -bool RsGxsDataAccess::requestSetGroupStatus(uint32_t& token, const RsGxsGroupId& grpId, uint32_t status, uint32_t statusMask) -{ - - generateToken(token); - - GroupSetFlagReq* req = new GroupSetFlagReq(); - - req->flag = status; - req->flagMask = statusMask; - req->grpId = grpId; - - std::cerr << "RsGxsDataAccess::requestSetGroupStatus() gets Token: " << token << std::endl; - storeRequest(req); - - return true; -} - -bool RsGxsDataAccess::requestSetMessageStatus(uint32_t& token, const RsGxsGrpMsgIdPair &msgId, uint32_t status, - uint32_t statusMask) -{ - - generateToken(token); - - MessageSetFlagReq* req = new MessageSetFlagReq(); - - req->flag = status; - req->flagMask = statusMask; - req->msgId = msgId; - - std::cerr << "RsGxsDataAccess::requestSetGroupStatus() gets Token: " << token << std::endl; - storeRequest(req); - - return true; -} void RsGxsDataAccess::setReq(GxsRequest* req, const uint32_t& token, const uint32_t& ansType, const RsTokReqOptionsV2& opts) const { @@ -424,6 +388,37 @@ bool RsGxsDataAccess::getMsgList(const uint32_t& token, GxsMsgIdResult& msgIds) return true; } +bool RsGxsDataAccess::getMsgRelatedInfo(const uint32_t &token, GxsMsgIdResult &msgIds) +{ + RsStackMutex stack(mDataMutex); + + GxsRequest* req = locked_retrieveRequest(token); + + if(req == NULL){ + + std::cerr << "RsGxsDataAccess::getMsgRelatedInfo() Unable to retrieve group data" << std::endl; + return false; + }else if(req->status == GXS_REQUEST_STATUS_COMPLETE){ + + MsgRelatedInfoReq* mrireq = dynamic_cast(req); + + if(mrireq) + { + msgIds = mrireq->mMsgIdResult; + locked_updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); + + }else{ + std::cerr << "RsGxsDataAccess::::getMsgRelatedInfo() Req found, failed caste" << std::endl; + return false; + } + }else{ + std::cerr << "RsGxsDataAccess::::getMsgRelatedInfo() Req not ready" << std::endl; + return false; + } + + return true; +} + bool RsGxsDataAccess::getGroupList(const uint32_t& token, std::list& groupIds) { RsStackMutex stack(mDataMutex); @@ -488,6 +483,7 @@ void RsGxsDataAccess::processRequests() MsgMetaReq* mmr; MsgDataReq* mdr; MsgIdReq* mir; + MsgRelatedInfoReq* mri; for(it = mRequests.begin(); it != mRequests.end(); it++) { @@ -527,6 +523,10 @@ void RsGxsDataAccess::processRequests() { getMsgList(mir); } + else if((mri = dynamic_cast(req)) != NULL) + { + getMsgRelatedInfo(mri); + } else { #ifdef GXSDATA_SERVE_DEBUG @@ -569,7 +569,6 @@ void RsGxsDataAccess::processRequests() bool RsGxsDataAccess::getGroupData(GroupDataReq* req) { - std::map grpData; std::list::iterator lit = req->mGroupIds.begin(), @@ -650,170 +649,200 @@ bool RsGxsDataAccess::getMsgSummary(MsgMetaReq* req) return true; } + +bool RsGxsDataAccess::getMsgRelatedInfo(MsgRelatedInfoReq* req) +{ + GxsMsgMetaResult result; + + const RsTokReqOptionsV2& opts = req->Options; + + { + RsStackMutex stack(mDataMutex); + mDataStore->retrieveGxsMsgMetaData(req->mMsgIds, result); + } + + + /* CASEs this handles. + * Input is groupList + Flags. + * 1) No Flags => All Messages in those Groups. + * + */ + std::cerr << "RsGxsDataAccess::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 << "RsGxsDataAccess::getMsgList() MSG_ORIGMSG"; + std::cerr << std::endl; + onlyOrigMsgs = true; + } + else if (opts.mOptions & RS_TOKREQOPT_MSG_LATEST) + { + std::cerr << "RsGxsDataAccess::getMsgList() MSG_LATEST"; + std::cerr << std::endl; + onlyLatestMsgs = true; + } + + if (opts.mOptions & RS_TOKREQOPT_MSG_THREAD) + { + std::cerr << "RsGxsDataAccess::getMsgList() MSG_THREAD"; + std::cerr << std::endl; + onlyThreadHeadMsgs = true; + } + + GxsMsgMetaResult::iterator meta_it; + MsgMetaFilter metaFilter; + + for(meta_it = result.begin(); meta_it != result.end(); meta_it++) + { + const RsGxsGroupId& grpId = meta_it->first; + + metaFilter[grpId] = std::map(); + + const std::vector& metaV = meta_it->second; + if (onlyLatestMsgs) // THIS ONE IS HARD -> LOTS OF COMP. + { + std::vector::const_iterator vit = metaV.begin(); + + + // RUN THROUGH ALL MSGS... in map origId -> TS. + std::map > origMsgTs; + std::map >::iterator oit; + + for(; vit != metaV.end(); vit++) + { + RsGxsMsgMetaData* msgMeta = *vit; + + /* if we are grabbing thread Head... then parentId == empty. */ + if (onlyThreadHeadMsgs) + { + if (!(msgMeta->mParentId.empty())) + { + continue; + } + } + + + oit = origMsgTs.find(msgMeta->mOrigMsgId); + bool addMsg = false; + if (oit == origMsgTs.end()) + { + std::cerr << "RsGxsDataAccess::getMsgList() Found New OrigMsgId: "; + std::cerr << msgMeta->mOrigMsgId; + std::cerr << " MsgId: " << msgMeta->mMsgId; + std::cerr << " TS: " << msgMeta->mPublishTs; + std::cerr << std::endl; + + addMsg = true; + } + // check timestamps. + else if (oit->second.second < msgMeta->mPublishTs) + { + std::cerr << "RsGxsDataAccess::getMsgList() Found Later Msg. OrigMsgId: "; + std::cerr << msgMeta->mOrigMsgId; + std::cerr << " MsgId: " << msgMeta->mMsgId; + std::cerr << " TS: " << msgMeta->mPublishTs; + + addMsg = true; + } + + if (addMsg) + { + // add as latest. (overwriting if necessary) + origMsgTs[msgMeta->mOrigMsgId] = std::make_pair(msgMeta->mMsgId, msgMeta->mPublishTs); + metaFilter[grpId].insert(std::make_pair(msgMeta->mMsgId, msgMeta)); + } + } + + // Add the discovered Latest Msgs. + for(oit = origMsgTs.begin(); oit != origMsgTs.end(); oit++) + { + req->mMsgIdResult[grpId].push_back(oit->second.first); + + } + + } + else // ALL OTHER CASES. + { + std::vector::const_iterator vit = metaV.begin(); + + for(; vit != metaV.end(); vit++) + { + RsGxsMsgMetaData* msgMeta = *vit; + bool add = false; + + /* if we are grabbing thread Head... then parentId == empty. */ + if (onlyThreadHeadMsgs) + { + if (!(msgMeta->mParentId.empty())) + { + continue; + } + } + + + if (onlyOrigMsgs) + { + if (msgMeta->mMsgId == msgMeta->mOrigMsgId) + { + add = true; + } + } + else + { + add = true; + } + + if (add) + { + req->mMsgIdResult[grpId].push_back(msgMeta->mMsgId); + } + + } + } + } + + filterMsgList(req->mMsgIdResult, opts, metaFilter); + + // delete the data + cleanseMetaFilter(metaFilter); + + return true; +} + bool RsGxsDataAccess::getMsgList(MsgIdReq* req) { - GxsMsgMetaResult result; - const RsTokReqOptionsV2& opts = req->Options; + GxsMsgMetaResult result; - { - RsStackMutex stack(mDataMutex); - mDataStore->retrieveGxsMsgMetaData(req->mMsgIds, result); - } + { + RsStackMutex stack(mDataMutex); + mDataStore->retrieveGxsMsgMetaData(req->mMsgIds, result); + } + GxsMsgMetaResult::iterator mit = result.begin(), mit_end = result.end(); - /* CASEs this handles. - * Input is groupList + Flags. - * 1) No Flags => All Messages in those Groups. - * - */ - std::cerr << "RsGxsDataAccess::getMsgList()"; - std::cerr << std::endl; + for(; mit != mit_end; mit++) + { + const RsGxsGroupId grpId = mit->first; + std::vector& metaV = mit->second; + std::vector::iterator vit = metaV.begin(), + vit_end = metaV.end(); - - 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 << "RsGxsDataAccess::getMsgList() MSG_ORIGMSG"; - std::cerr << std::endl; - onlyOrigMsgs = true; - } - else if (opts.mOptions & RS_TOKREQOPT_MSG_LATEST) - { - std::cerr << "RsGxsDataAccess::getMsgList() MSG_LATEST"; - std::cerr << std::endl; - onlyLatestMsgs = true; - } - - if (opts.mOptions & RS_TOKREQOPT_MSG_THREAD) - { - std::cerr << "RsGxsDataAccess::getMsgList() MSG_THREAD"; - std::cerr << std::endl; - onlyThreadHeadMsgs = true; - } - - GxsMsgMetaResult::iterator meta_it; - MsgMetaFilter metaFilter; - - for(meta_it = result.begin(); meta_it != result.end(); meta_it++) - { - const RsGxsGroupId& grpId = meta_it->first; - - metaFilter[grpId] = std::map(); - - const std::vector& metaV = meta_it->second; - if (onlyLatestMsgs) // THIS ONE IS HARD -> LOTS OF COMP. - { - std::vector::const_iterator vit = metaV.begin(); - - - // RUN THROUGH ALL MSGS... in map origId -> TS. - std::map > origMsgTs; - std::map >::iterator oit; - - for(; vit != metaV.end(); vit++) - { - RsGxsMsgMetaData* msgMeta = *vit; - - /* if we are grabbing thread Head... then parentId == empty. */ - if (onlyThreadHeadMsgs) - { - if (!(msgMeta->mParentId.empty())) - { - continue; - } - } - - - oit = origMsgTs.find(msgMeta->mOrigMsgId); - bool addMsg = false; - if (oit == origMsgTs.end()) - { - std::cerr << "RsGxsDataAccess::getMsgList() Found New OrigMsgId: "; - std::cerr << msgMeta->mOrigMsgId; - std::cerr << " MsgId: " << msgMeta->mMsgId; - std::cerr << " TS: " << msgMeta->mPublishTs; - std::cerr << std::endl; - - addMsg = true; - } - // check timestamps. - else if (oit->second.second < msgMeta->mPublishTs) - { - std::cerr << "RsGxsDataAccess::getMsgList() Found Later Msg. OrigMsgId: "; - std::cerr << msgMeta->mOrigMsgId; - std::cerr << " MsgId: " << msgMeta->mMsgId; - std::cerr << " TS: " << msgMeta->mPublishTs; - - addMsg = true; - } - - if (addMsg) - { - // add as latest. (overwriting if necessary) - origMsgTs[msgMeta->mOrigMsgId] = std::make_pair(msgMeta->mMsgId, msgMeta->mPublishTs); - metaFilter[grpId].insert(std::make_pair(msgMeta->mMsgId, msgMeta)); - } - } - - // Add the discovered Latest Msgs. - for(oit = origMsgTs.begin(); oit != origMsgTs.end(); oit++) - { - req->mMsgIds[grpId].push_back(oit->second.first); - - } - - } - else // ALL OTHER CASES. - { - std::vector::const_iterator vit = metaV.begin(); - - for(; vit != metaV.end(); vit++) - { - RsGxsMsgMetaData* msgMeta = *vit; - bool add = false; - - /* if we are grabbing thread Head... then parentId == empty. */ - if (onlyThreadHeadMsgs) - { - if (!(msgMeta->mParentId.empty())) - { - continue; - } - } - - - if (onlyOrigMsgs) - { - if (msgMeta->mMsgId == msgMeta->mOrigMsgId) - { - add = true; - } - } - else - { - add = true; - } - - if (add) - { - req->mMsgIdResult[grpId].push_back(msgMeta->mMsgId); - } - - } - } - } - - filterMsgList(req->mMsgIdResult, opts, metaFilter); - - // delete the data - cleanseMetaFilter(metaFilter); - - return true; + for(; vit != vit_end; vit++) + { + RsGxsMsgMetaData* meta = *vit; + req->mMsgIdResult[grpId].push_back(meta->mMsgId); + delete meta; // discard meta data mem + } + } + return true; } void RsGxsDataAccess::cleanseMetaFilter(MsgMetaFilter& filter) diff --git a/libretroshare/src/gxs/rsgxsdataaccess.h b/libretroshare/src/gxs/rsgxsdataaccess.h index 24c928dd2..f67a25ec1 100644 --- a/libretroshare/src/gxs/rsgxsdataaccess.h +++ b/libretroshare/src/gxs/rsgxsdataaccess.h @@ -64,36 +64,14 @@ public: bool requestMsgInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptionsV2 &opts, const GxsMsgReq&); /*! - * This sets the status of the message - * @param msgId the message id to set status for - * @param status status - * @param statusMask the mask for the settings targetted - * @return true if request made successfully, false otherwise + * For requesting msgs related to a given msg id within a group + * @param token The token returned for the request + * @param ansType The type of result wanted + * @param opts Additional option that affect outcome of request. Please see specific services, for valid values + * @param groupIds The ids of the groups to get, second entry of map empty to query for all msgs + * @return true if request successful false otherwise */ - bool requestSetMessageStatus(uint32_t &token, const RsGxsGrpMsgIdPair &msgId, - const uint32_t status, const uint32_t statusMask); - - /*! - * - * @param token - * @param grpId - * @param status - * @param statusMask - * @return true if request made successfully, false otherwise - */ - bool requestSetGroupStatus(uint32_t &token, const RsGxsGroupId &grpId, const uint32_t status, - const uint32_t statusMask); - - /*! - * Use request status to find out if successfully set - * @param groupId - * @param subscribeFlags - * @param subscribeMask - * @return true if request made successfully, false otherwise - */ - bool requestSetGroupSubscribeFlags(uint32_t& token, const RsGxsGroupId &groupId, uint32_t subscribeFlags, - uint32_t subscribeMask); - + bool requestMsgRelatedInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptionsV2 &opts, const GxsMsgReq&); /* Poll */ uint32_t requestStatus(const uint32_t token); @@ -103,8 +81,6 @@ public: /** E: RsTokenService **/ - - public: /*! @@ -177,6 +153,14 @@ public: */ bool getMsgData(const uint32_t &token, NxsMsgDataResult& msgData); + /*! + * + * @param token request token to be redeemed + * @param msgIds + * @return false if data cannot be found for token + */ + bool getMsgRelatedInfo(const uint32_t &token, GxsMsgIdResult &msgIds); + private: /** helper functions to implement token service **/ @@ -321,6 +305,15 @@ private: */ bool getMsgData(MsgDataReq* req); + + /*! + * Attempts to retrieve messages related to msgIds of associated equest + * @param token request token to be redeemed + * @param msgIds + * @return false if data cannot be found for token + */ + bool getMsgRelatedInfo(MsgRelatedInfoReq* req); + /*! * This filter msgs based of options supplied (at the moment just status masks) * @param msgIds The msgsIds to filter diff --git a/libretroshare/src/gxs/rsgxsrequesttypes.h b/libretroshare/src/gxs/rsgxsrequesttypes.h index d5da446c5..5536a4d6d 100644 --- a/libretroshare/src/gxs/rsgxsrequesttypes.h +++ b/libretroshare/src/gxs/rsgxsrequesttypes.h @@ -95,6 +95,14 @@ public: NxsMsgDataResult mMsgData; }; +class MsgRelatedInfoReq : public GxsRequest +{ + +public: + GxsMsgReq mMsgIds; + GxsMsgIdResult mMsgIdResult; +}; + class GroupSetFlagReq : public GxsRequest { public: diff --git a/libretroshare/src/gxs/rstokenservice.h b/libretroshare/src/gxs/rstokenservice.h index 4d4dc1843..d0e562dc6 100644 --- a/libretroshare/src/gxs/rstokenservice.h +++ b/libretroshare/src/gxs/rstokenservice.h @@ -132,46 +132,20 @@ public: * @param ansType The type of result wanted * @param opts Additional option that affect outcome of request. Please see specific services, for valid values * @param groupIds The ids of the groups to get, second entry of map empty to query for all msgs - * @return + * @return true if request successful false otherwise */ virtual bool requestMsgInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptionsV2 &opts, const GxsMsgReq& msgIds) = 0; - - /*! - * This sets the status of the message - * @param msgId the message id to set status for - * @param status status - * @param statusMask the mask for the settings targetted - * @return true if request made successfully, false otherwise + * For requesting msgs related to a given msg id within a group + * @param token The token returned for the request + * @param ansType The type of result wanted + * @param opts Additional option that affect outcome of request. Please see specific services, for valid values + * @param groupIds The ids of the groups to get, second entry of map empty to query for all msgs + * @return true if request successful false otherwise */ - virtual bool requestSetMessageStatus(uint32_t &token, const RsGxsGrpMsgIdPair &msgId, - const uint32_t status, const uint32_t statusMask) = 0; + virtual bool requestMsgRelatedInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptionsV2 &opts, const GxsMsgReq& msgIds) = 0; - /*! - * Set the status of a group given by group Id - * @param token The token returned for this request - * @param grpId The Id of the group to apply status change to - * @param status The status to apply - * @param statusMask The status mask (target particular type of status) - * @return true if request made successfully, false otherwise - */ - virtual bool requestSetGroupStatus(uint32_t &token, const RsGxsGroupId &grpId, const uint32_t status, - const uint32_t statusMask) = 0; - - /*! - * Use request status to find out if successfully set - * @param groupId - * @param subscribeFlags - * @param subscribeMask - * @return true if request made successfully, false otherwise - */ - virtual bool requestSetGroupSubscribeFlags(uint32_t& token, const RsGxsGroupId &groupId, uint32_t subscribeFlags, uint32_t subscribeMask) = 0; - - - // (FUTURE WORK). - //virtual bool groupRestoreKeys(const std::string &groupId) = 0; - //virtual bool groupShareKeys(const std::string &groupId, std::list& peers) = 0; /* Poll */ diff --git a/libretroshare/src/services/p3photoserviceV2.cc b/libretroshare/src/services/p3photoserviceV2.cc index 4fa74163d..a460ff3b7 100644 --- a/libretroshare/src/services/p3photoserviceV2.cc +++ b/libretroshare/src/services/p3photoserviceV2.cc @@ -142,7 +142,8 @@ bool p3PhotoServiceV2::submitAlbumDetails(uint32_t& token, RsPhotoAlbum& album) RsGxsPhotoAlbumItem* albumItem = new RsGxsPhotoAlbumItem(); albumItem->album = album; albumItem->meta = album.mMeta; - return RsGenExchange::publishGroup(token, albumItem); + RsGenExchange::publishGroup(token, albumItem); + return true; } @@ -177,7 +178,8 @@ bool p3PhotoServiceV2::submitPhoto(uint32_t& token, RsPhotoPhoto& photo) photoItem->photo = photo; photoItem->meta = photo.mMeta; - return RsGenExchange::publishMsg(token, photoItem); + RsGenExchange::publishMsg(token, photoItem); + return true; } bool p3PhotoServiceV2::acknowledgeMsg(const uint32_t& token, diff --git a/libretroshare/src/util/contentvalue.cc b/libretroshare/src/util/contentvalue.cc new file mode 100644 index 000000000..58f237cf7 --- /dev/null +++ b/libretroshare/src/util/contentvalue.cc @@ -0,0 +1,311 @@ + +/* + * util/contentvalue.cc, key val container + * + * Copyright 2012 Christopher Evi-Parker + * + * 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 +#include + +#include "contentvalue.h" + + + + +const uint8_t ContentValue::BOOL_TYPE = 1; +const uint8_t ContentValue::DATA_TYPE = 2; +const uint8_t ContentValue::STRING_TYPE = 3; +const uint8_t ContentValue::DOUBLE_TYPE = 4; +const uint8_t ContentValue::INT32_TYPE = 5; +const uint8_t ContentValue::INT64_TYPE = 6; + + +/**************** content value implementation ******************/ + +typedef std::pair KeyTypePair; + +ContentValue::ContentValue(){ + +} + +ContentValue::~ContentValue(){ + // release resources held in data + clearData(); +} + +ContentValue::ContentValue(ContentValue &from){ + + std::map keyTypeMap; + from.getKeyTypeMap(keyTypeMap); + std::map::const_iterator cit = + keyTypeMap.begin(); + + uint8_t type = 0; + std::string currKey; + std::string val = ""; + char *src = NULL; + uint32_t data_len = 0; + + for(; cit != keyTypeMap.end(); cit++){ + + type = cit->second; + currKey = cit->first; + + switch(type){ + + case INT32_TYPE: + { + int32_t value; + from.getAsInt32(currKey, value); + put(currKey, value); + break; + } + case INT64_TYPE: + { + int64_t value; + from.getAsInt64(currKey, value); + put(currKey, value); + break; + } + case STRING_TYPE: + { + from.getAsString(currKey, val); + put(currKey, val); + break; + } + case BOOL_TYPE: + { + bool value; + from.getAsBool(currKey, value); + put(currKey, value); + break; + } + case DATA_TYPE: + { + from.getAsData(currKey, data_len, src); + put(currKey, data_len, src); + break; + } + case DOUBLE_TYPE: + double value; + from.getAsDouble(currKey, value); + put(currKey, value); + break; + default: + std::cerr << "ContentValue::ContentValue(ContentValue &from):" + << "Error! Unrecognised data type!" << std::endl; + } + } +} + +void ContentValue::put(const std::string &key, bool value){ + + if(mKvSet.find(key) != mKvSet.end()) + removeKeyValue(key); + + mKvSet.insert(KeyTypePair(key, BOOL_TYPE)); + mKvBool.insert(std::pair(key, value)); +} + +void ContentValue::put(const std::string &key, const std::string &value){ + + if(mKvSet.find(key) != mKvSet.end()) + removeKeyValue(key); + + mKvSet.insert(KeyTypePair(key, STRING_TYPE)); + mKvString.insert(std::pair(key, value)); +} + +void ContentValue::put(const std::string &key, double value){ + + if(mKvSet.find(key) != mKvSet.end()) + removeKeyValue(key); + + mKvSet.insert(KeyTypePair(key,DOUBLE_TYPE)); + mKvDouble.insert(std::pair(key, value)); +} + +void ContentValue::put(const std::string &key, int32_t value){ + + if(mKvSet.find(key) != mKvSet.end()) + removeKeyValue(key); + + mKvSet.insert(KeyTypePair(key, INT32_TYPE)); + mKvInt32.insert(std::pair(key, value)); +} + +void ContentValue::put(const std::string &key, int64_t value){ + + if(mKvSet.find(key) != mKvSet.end()) + removeKeyValue(key); + + mKvSet.insert(KeyTypePair(key, INT64_TYPE)); + mKvInt64.insert(std::pair(key, value)); +} + +void ContentValue::put(const std::string &key, uint32_t len, const char* value){ + + + // release memory from old key value if key + // exists + if(mKvSet.find(key) != mKvSet.end()) { + removeKeyValue(key); + } + + mKvSet.insert(KeyTypePair(key, DATA_TYPE)); + char* dest = NULL; + + // len is zero then just put a NULL entry + if(len != 0){ + dest = new char[len]; + memcpy(dest, value, len); + } + + mKvData.insert(std::pair > + (key, std::pair(len, dest))); +} + +bool ContentValue::getAsBool(const std::string &key, bool& value) const{ + + std::map::const_iterator it; + if((it = mKvBool.find(key)) == mKvBool.end()) + return false; + + value = it->second; + return true; +} + +bool ContentValue::getAsInt32(const std::string &key, int32_t& value) const{ + + std::map::const_iterator it; + if((it = mKvInt32.find(key)) == mKvInt32.end()) + return false; + + value = it->second; + return true; +} + +bool ContentValue::getAsInt64(const std::string &key, int64_t& value) const{ + + std::map::const_iterator it; + if((it = mKvInt64.find(key)) == mKvInt64.end()) + return false; + + value = it->second; + return true; +} + +bool ContentValue::getAsString(const std::string &key, std::string &value) const{ + + std::map::const_iterator it; + if((it = mKvString.find(key)) == mKvString.end()) + return false; + + value = it->second; + return true; +} + +bool ContentValue::getAsData(const std::string& key, uint32_t &len, char*& value) const{ + + std::map >::const_iterator it; + if((it = mKvData.find(key)) == mKvData.end()) + return false; + + const std::pair &kvRef = it->second; + + len = kvRef.first; + value = kvRef.second; + return true; +} + +bool ContentValue::getAsDouble(const std::string &key, double& value) const{ + + std::map::const_iterator it; + if((it = mKvDouble.find(key)) == mKvDouble.end()) + return false; + + value = it->second; + return true; +} + +bool ContentValue::removeKeyValue(const std::string &key){ + + std::map::iterator mit; + + if((mit = mKvSet.find(key)) == mKvSet.end()) + return false; + + if(mit->second == BOOL_TYPE) + mKvBool.erase(key); + + if(mit->second == INT64_TYPE) + mKvInt64.erase(key); + + if(mit->second == DATA_TYPE){ + delete[] (mKvData[key].second); + mKvData.erase(key); + } + + if(mit->second == DOUBLE_TYPE) + mKvDouble.erase(key); + + if(mit->second == STRING_TYPE) + mKvString.erase(key); + + if(mit->second == INT32_TYPE) + mKvInt32.erase(key); + + + mKvSet.erase(key); + return true; +} + + +void ContentValue::getKeyTypeMap(std::map &keySet) const { + keySet = mKvSet; +} + +void ContentValue::clear(){ + mKvSet.clear(); + mKvBool.clear(); + mKvDouble.clear(); + mKvString.clear(); + mKvInt32.clear(); + mKvInt64.clear(); + clearData(); +} + +void ContentValue::clearData(){ + + std::map >::iterator + mit = mKvData.begin(); + + for(; mit != mKvData.end(); mit++){ + + if(mit->second.first != 0) + delete[] (mit->second.second); + } + + mKvData.clear(); +} + + + diff --git a/libretroshare/src/util/contentvalue.h b/libretroshare/src/util/contentvalue.h new file mode 100644 index 000000000..50b12af48 --- /dev/null +++ b/libretroshare/src/util/contentvalue.h @@ -0,0 +1,183 @@ +#ifndef CONTENTVALUE_H +#define CONTENTVALUE_H + +/* + * util/contentvalue.h, key val container + * + * Copyright 2012 Christopher Evi-Parker + * + * 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 +#include +#include + +/*! + * @brief Convenience container for making additions to databases + * This class provides a means of holding column values to insert into a database + */ +class ContentValue { + +public: + + static const uint8_t INT32_TYPE; + static const uint8_t INT64_TYPE; + static const uint8_t DOUBLE_TYPE; + static const uint8_t STRING_TYPE; + static const uint8_t DATA_TYPE; + static const uint8_t BOOL_TYPE; + + ContentValue(); + + /*! + * copy constructor that copys the key value set from another \n + * ContentValue object to this one + * makes a deep copy of raw data + * @param from ContentValue instance to copy key value set from + */ + ContentValue(ContentValue& from); + + /*! + * + * + * + */ + ~ContentValue(); + + /*! + * Adds a value to the set + * @param key the name of the value to put + * @param value the data for the value to put + * @warning cast string literals explicitly as string, observed string literal \n + * being casted to bool instead e.g. string("hello") rather than "hello" + */ + void put(const std::string& key, const std::string& value); + + /*! + * Adds a value to the set + * @param key the name of the value to put + * @param value the data for the value to put + */ + void put(const std::string& key, bool value); + + /*! + * Adds a value to the set + * @param key the name of the value to put + * @param value the data for the value to put + */ + void put(const std::string& key, int64_t value); + + /*! + * Adds a value to the set + * @param key the name of the value to put + * @param value the data for the value to put + */ + void put(const std::string& key, int32_t value); + + /*! + * Adds a value to the set + * @param key the name of the value to put + * @param value the data for the value to put + */ + void put(const std::string& key, double value); + + /*! + * Adds a value to the set + * @param key the name of the value to put + * @param value the data for the value to put + */ + void put(const std::string& key, uint32_t len, const char* value); + + + /*! + * get value as 32 bit signed integer + * @param key the value to get + */ + bool getAsInt32(const std::string& key, int32_t& value) const; + + /*! + * get value as 64 bit signed integer + * @param key the value to get + */ + bool getAsInt64(const std::string& key, int64_t& value) const; + + /*! + * get value as bool + * @param key the value to get + */ + bool getAsBool(const std::string& key, bool& value) const; + + /*! + * get as value double + * @param key the value to get + */ + bool getAsDouble(const std::string& key, double& value) const; + + /*! + * get as value as string + * @param key the value to get + * @param value the data retrieved + */ + bool getAsString(const std::string& key, std::string& value) const; + + /*! + * get as value as raw data + * @warning Deep copy of data reference should be made, if this instance ContentValue \n + * is destroyed pointer returned (value) is pointing to invalid memory + * @param key the value to get + */ + bool getAsData(const std::string&, uint32_t& len, char*& value) const; + + /*! + * @param keySet the is set with key to type pairs contained in the ContentValue instance + */ + void getKeyTypeMap(std::map& keySet) const; + + /*! + * @param key the key of the key value pair to remove + * @return true if key was found and removed, false otherwise + */ + bool removeKeyValue(const std::string& key); + + /*! + * clears this data structure of all its key value pairs held + */ + void clear(); + +private: + + /*! + * release memory resource associated with mKvData + */ + void clearData(); + +private: + + std::map mKvInt32; + std::map mKvInt64; + std::map mKvDouble; + std::map mKvString; + std::map > mKvData; + std::map mKvBool; + + std::map mKvSet; + +}; + +#endif // CONTENTVALUE_H diff --git a/libretroshare/src/util/retrodb.cc b/libretroshare/src/util/retrodb.cc index 3af1e67aa..d5b2964ca 100644 --- a/libretroshare/src/util/retrodb.cc +++ b/libretroshare/src/util/retrodb.cc @@ -32,6 +32,8 @@ //#define RETRODB_DEBUG + + void free_blob(void* dat){ char* c = (char*) dat; @@ -40,13 +42,6 @@ void free_blob(void* dat){ } -const uint8_t ContentValue::BOOL_TYPE = 1; -const uint8_t ContentValue::DATA_TYPE = 2; -const uint8_t ContentValue::STRING_TYPE = 3; -const uint8_t ContentValue::DOUBLE_TYPE = 4; -const uint8_t ContentValue::INT32_TYPE = 5; -const uint8_t ContentValue::INT64_TYPE = 6; - const int RetroDb::OPEN_READONLY = SQLITE_OPEN_READONLY; const int RetroDb::OPEN_READWRITE = SQLITE_OPEN_READWRITE; const int RetroDb::OPEN_READWRITE_CREATE = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; @@ -234,9 +229,9 @@ bool RetroDb::sqlInsert(const std::string &table, const std::string& nullColumnH uint8_t type = mit->second; std::string key = mit->first; - switch(type){ - case ContentValue::BOOL_TYPE: + + if(ContentValue::BOOL_TYPE == type) { bool value; cv.getAsBool(key, value); @@ -244,7 +239,7 @@ bool RetroDb::sqlInsert(const std::string &table, const std::string& nullColumnH qValues += oStrStream.str(); break; } - case ContentValue::DOUBLE_TYPE: + else if( ContentValue::DOUBLE_TYPE == type) { double value; cv.getAsDouble(key, value); @@ -252,7 +247,7 @@ bool RetroDb::sqlInsert(const std::string &table, const std::string& nullColumnH qValues += oStrStream.str(); break; } - case ContentValue::DATA_TYPE: + else if( ContentValue::DATA_TYPE == type) { char* value; uint32_t len; @@ -265,14 +260,14 @@ bool RetroDb::sqlInsert(const std::string &table, const std::string& nullColumnH qValues += "?"; // parameter break; } - case ContentValue::STRING_TYPE: + else if ( ContentValue::STRING_TYPE == type) { std::string value; cv.getAsString(key, value); qValues += "'" + value +"'"; break; } - case ContentValue::INT32_TYPE: + else if ( ContentValue::INT32_TYPE == type) { int32_t value; cv.getAsInt32(key, value); @@ -280,7 +275,7 @@ bool RetroDb::sqlInsert(const std::string &table, const std::string& nullColumnH qValues += oStrStream.str(); break; } - case ContentValue::INT64_TYPE: + else if( ContentValue::INT64_TYPE == type) { int64_t value; cv.getAsInt64(key, value); @@ -288,7 +283,7 @@ bool RetroDb::sqlInsert(const std::string &table, const std::string& nullColumnH qValues += oStrStream.str(); break; } - } + mit++; if(mit != keyTypeMap.end()){ // add comma if more columns left @@ -419,9 +414,7 @@ bool RetroDb::sqlUpdate(const std::string &tableName, std::string whereClause, c uint8_t type = mit->second; std::string key = mit->first; - switch(type){ - - case ContentValue::BOOL_TYPE: + if( ContentValue::BOOL_TYPE == type) { bool value; cv.getAsBool(key, value); @@ -429,7 +422,7 @@ bool RetroDb::sqlUpdate(const std::string &tableName, std::string whereClause, c qValues += key + "='" + oStrStream.str(); break; } - case ContentValue::DOUBLE_TYPE: + else if( ContentValue::DOUBLE_TYPE == type) { double value; cv.getAsDouble(key, value); @@ -437,7 +430,7 @@ bool RetroDb::sqlUpdate(const std::string &tableName, std::string whereClause, c qValues += key + "='" + oStrStream.str(); break; } - case ContentValue::DATA_TYPE: + else if( ContentValue::DATA_TYPE == type) { char* value; uint32_t len; @@ -446,14 +439,14 @@ bool RetroDb::sqlUpdate(const std::string &tableName, std::string whereClause, c qValues += key + "='" + oStrStream.str() + "' "; break; } - case ContentValue::STRING_TYPE: + else if( ContentValue::STRING_TYPE == type) { std::string value; cv.getAsString(key, value); qValues += key + "='" + value + "' "; break; } - case ContentValue::INT32_TYPE: + else if( ContentValue::INT32_TYPE == type) { int32_t value; cv.getAsInt32(key, value); @@ -461,7 +454,7 @@ bool RetroDb::sqlUpdate(const std::string &tableName, std::string whereClause, c qValues += key + "='" + oStrStream.str() + "' "; break; } - case ContentValue::INT64_TYPE: + else if( ContentValue::INT64_TYPE == type) { int64_t value; cv.getAsInt64(key, value); @@ -469,7 +462,7 @@ bool RetroDb::sqlUpdate(const std::string &tableName, std::string whereClause, c qValues += key + "='" + oStrStream.str() + "' "; break; } - } + mit++; if(mit != keyTypeMap.end()){ // add comma if more columns left @@ -715,276 +708,3 @@ const void* RetroCursor::getData(int columnIndex, uint32_t &datSize){ } - - -/**************** content value implementation ******************/ - -typedef std::pair KeyTypePair; - -ContentValue::ContentValue(){ - -} - -ContentValue::~ContentValue(){ - // release resources held in data - clearData(); -} - -ContentValue::ContentValue(ContentValue &from){ - - std::map keyTypeMap; - from.getKeyTypeMap(keyTypeMap); - std::map::const_iterator cit = - keyTypeMap.begin(); - - uint8_t type = 0; - std::string currKey; - std::string val = ""; - char *src = NULL; - uint32_t data_len = 0; - - for(; cit != keyTypeMap.end(); cit++){ - - type = cit->second; - currKey = cit->first; - - switch(type){ - - case INT32_TYPE: - { - int32_t value; - from.getAsInt32(currKey, value); - put(currKey, value); - break; - } - case INT64_TYPE: - { - int64_t value; - from.getAsInt64(currKey, value); - put(currKey, value); - break; - } - case STRING_TYPE: - { - from.getAsString(currKey, val); - put(currKey, val); - break; - } - case BOOL_TYPE: - { - bool value; - from.getAsBool(currKey, value); - put(currKey, value); - break; - } - case DATA_TYPE: - { - from.getAsData(currKey, data_len, src); - put(currKey, data_len, src); - break; - } - case DOUBLE_TYPE: - double value; - from.getAsDouble(currKey, value); - put(currKey, value); - break; - default: - std::cerr << "ContentValue::ContentValue(ContentValue &from):" - << "Error! Unrecognised data type!" << std::endl; - } - } -} - -void ContentValue::put(const std::string &key, bool value){ - - if(mKvSet.find(key) != mKvSet.end()) - removeKeyValue(key); - - mKvSet.insert(KeyTypePair(key, BOOL_TYPE)); - mKvBool.insert(std::pair(key, value)); -} - -void ContentValue::put(const std::string &key, const std::string &value){ - - if(mKvSet.find(key) != mKvSet.end()) - removeKeyValue(key); - - mKvSet.insert(KeyTypePair(key, STRING_TYPE)); - mKvString.insert(std::pair(key, value)); -} - -void ContentValue::put(const std::string &key, double value){ - - if(mKvSet.find(key) != mKvSet.end()) - removeKeyValue(key); - - mKvSet.insert(KeyTypePair(key,DOUBLE_TYPE)); - mKvDouble.insert(std::pair(key, value)); -} - -void ContentValue::put(const std::string &key, int32_t value){ - - if(mKvSet.find(key) != mKvSet.end()) - removeKeyValue(key); - - mKvSet.insert(KeyTypePair(key, INT32_TYPE)); - mKvInt32.insert(std::pair(key, value)); -} - -void ContentValue::put(const std::string &key, int64_t value){ - - if(mKvSet.find(key) != mKvSet.end()) - removeKeyValue(key); - - mKvSet.insert(KeyTypePair(key, INT64_TYPE)); - mKvInt64.insert(std::pair(key, value)); -} - -void ContentValue::put(const std::string &key, uint32_t len, const char* value){ - - - // release memory from old key value if key - // exists - if(mKvSet.find(key) != mKvSet.end()) { - removeKeyValue(key); - } - - mKvSet.insert(KeyTypePair(key, DATA_TYPE)); - char* dest = NULL; - - // len is zero then just put a NULL entry - if(len != 0){ - dest = new char[len]; - memcpy(dest, value, len); - } - - mKvData.insert(std::pair > - (key, std::pair(len, dest))); -} - -bool ContentValue::getAsBool(const std::string &key, bool& value) const{ - - std::map::const_iterator it; - if((it = mKvBool.find(key)) == mKvBool.end()) - return false; - - value = it->second; - return true; -} - -bool ContentValue::getAsInt32(const std::string &key, int32_t& value) const{ - - std::map::const_iterator it; - if((it = mKvInt32.find(key)) == mKvInt32.end()) - return false; - - value = it->second; - return true; -} - -bool ContentValue::getAsInt64(const std::string &key, int64_t& value) const{ - - std::map::const_iterator it; - if((it = mKvInt64.find(key)) == mKvInt64.end()) - return false; - - value = it->second; - return true; -} - -bool ContentValue::getAsString(const std::string &key, std::string &value) const{ - - std::map::const_iterator it; - if((it = mKvString.find(key)) == mKvString.end()) - return false; - - value = it->second; - return true; -} - -bool ContentValue::getAsData(const std::string& key, uint32_t &len, char*& value) const{ - - std::map >::const_iterator it; - if((it = mKvData.find(key)) == mKvData.end()) - return false; - - const std::pair &kvRef = it->second; - - len = kvRef.first; - value = kvRef.second; - return true; -} - -bool ContentValue::getAsDouble(const std::string &key, double& value) const{ - - std::map::const_iterator it; - if((it = mKvDouble.find(key)) == mKvDouble.end()) - return false; - - value = it->second; - return true; -} - -bool ContentValue::removeKeyValue(const std::string &key){ - - std::map::iterator mit; - - if((mit = mKvSet.find(key)) == mKvSet.end()) - return false; - - if(mit->second == BOOL_TYPE) - mKvBool.erase(key); - - if(mit->second == INT64_TYPE) - mKvInt64.erase(key); - - if(mit->second == DATA_TYPE){ - delete[] (mKvData[key].second); - mKvData.erase(key); - } - - if(mit->second == DOUBLE_TYPE) - mKvDouble.erase(key); - - if(mit->second == STRING_TYPE) - mKvString.erase(key); - - if(mit->second == INT32_TYPE) - mKvInt32.erase(key); - - - mKvSet.erase(key); - return true; -} - - -void ContentValue::getKeyTypeMap(std::map &keySet) const { - keySet = mKvSet; -} - -void ContentValue::clear(){ - mKvSet.clear(); - mKvBool.clear(); - mKvDouble.clear(); - mKvString.clear(); - mKvInt32.clear(); - mKvInt64.clear(); - clearData(); -} - -void ContentValue::clearData(){ - - std::map >::iterator - mit = mKvData.begin(); - - for(; mit != mKvData.end(); mit++){ - - if(mit->second.first != 0) - delete[] (mit->second.second); - } - - mKvData.clear(); -} - - - diff --git a/libretroshare/src/util/retrodb.h b/libretroshare/src/util/retrodb.h index d1e773357..38706547f 100644 --- a/libretroshare/src/util/retrodb.h +++ b/libretroshare/src/util/retrodb.h @@ -31,8 +31,8 @@ #include #include +#include "contentvalue.h" -class ContentValue; class RetroCursor; /*! @@ -288,157 +288,7 @@ private: }; -/*! - * @brief Convenience container for making additions to databases - * This class provides a means of holding column values to insert into a database - */ -class ContentValue { -public: - - static const uint8_t INT32_TYPE; - static const uint8_t INT64_TYPE; - static const uint8_t DOUBLE_TYPE; - static const uint8_t STRING_TYPE; - static const uint8_t DATA_TYPE; - static const uint8_t BOOL_TYPE; - - ContentValue(); - - /*! - * copy constructor that copys the key value set from another \n - * ContentValue object to this one - * makes a deep copy of raw data - * @param from ContentValue instance to copy key value set from - */ - ContentValue(ContentValue& from); - - /*! - * - * - * - */ - ~ContentValue(); - - /*! - * Adds a value to the set - * @param key the name of the value to put - * @param value the data for the value to put - * @warning cast string literals explicitly as string, observed string literal \n - * being casted to bool instead e.g. string("hello") rather than "hello" - */ - void put(const std::string& key, const std::string& value); - - /*! - * Adds a value to the set - * @param key the name of the value to put - * @param value the data for the value to put - */ - void put(const std::string& key, bool value); - - /*! - * Adds a value to the set - * @param key the name of the value to put - * @param value the data for the value to put - */ - void put(const std::string& key, int64_t value); - - /*! - * Adds a value to the set - * @param key the name of the value to put - * @param value the data for the value to put - */ - void put(const std::string& key, int32_t value); - - /*! - * Adds a value to the set - * @param key the name of the value to put - * @param value the data for the value to put - */ - void put(const std::string& key, double value); - - /*! - * Adds a value to the set - * @param key the name of the value to put - * @param value the data for the value to put - */ - void put(const std::string& key, uint32_t len, const char* value); - - - /*! - * get value as 32 bit signed integer - * @param key the value to get - */ - bool getAsInt32(const std::string& key, int32_t& value) const; - - /*! - * get value as 64 bit signed integer - * @param key the value to get - */ - bool getAsInt64(const std::string& key, int64_t& value) const; - - /*! - * get value as bool - * @param key the value to get - */ - bool getAsBool(const std::string& key, bool& value) const; - - /*! - * get as value double - * @param key the value to get - */ - bool getAsDouble(const std::string& key, double& value) const; - - /*! - * get as value as string - * @param key the value to get - * @param value the data retrieved - */ - bool getAsString(const std::string& key, std::string& value) const; - - /*! - * get as value as raw data - * @warning Deep copy of data reference should be made, if this instance ContentValue \n - * is destroyed pointer returned (value) is pointing to invalid memory - * @param key the value to get - */ - bool getAsData(const std::string&, uint32_t& len, char*& value) const; - - /*! - * @param keySet the is set with key to type pairs contained in the ContentValue instance - */ - void getKeyTypeMap(std::map& keySet) const; - - /*! - * @param key the key of the key value pair to remove - * @return true if key was found and removed, false otherwise - */ - bool removeKeyValue(const std::string& key); - - /*! - * clears this data structure of all its key value pairs held - */ - void clear(); - -private: - - /*! - * release memory resource associated with mKvData - */ - void clearData(); - -private: - - std::map mKvInt32; - std::map mKvInt64; - std::map mKvDouble; - std::map mKvString; - std::map > mKvData; - std::map mKvBool; - - std::map mKvSet; - -}; #endif // RSSQLITE_H