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
This commit is contained in:
chrisparker126 2012-08-21 21:32:07 +00:00
parent 8a7c011c5d
commit 6dd18eea46
13 changed files with 983 additions and 746 deletions

View File

@ -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<std::string> &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;
}

View File

@ -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<RsGxsGroupId, std::vector<RsNxsMsg*> > GxsMsgResult; // <grpId,
class RsGeneralDataService
{
public:
static const std::string MSG_META_SERV_STRING;
static const std::string MSG_META_STATUS;
static const std::string GRP_META_SUBSCRIBE_FLAG;
static const std::string GRP_META_STATUS;
static const std::string GRP_META_SERV_STRING;
public:
RsGeneralDataService(){}

View File

@ -31,6 +31,7 @@
#include "rsgenexchange.h"
#include "gxssecurity.h"
#include "util/contentvalue.h"
RsGenExchange::RsGenExchange(RsGeneralDataService *gds,
RsNetworkExchangeService *ns, RsSerialType *serviceSerialiser, uint16_t servType)
@ -63,26 +64,33 @@ void RsGenExchange::tick()
publishMsgs();
processGrpMetaChanges();
processMsgMetaChanges();
notifyChanges(mNotifications);
mNotifications.clear();
}
bool RsGenExchange::acknowledgeTokenMsg(const uint32_t& token,
std::pair<RsGxsGroupId, RsGxsMessageId>& msgId)
RsGxsGrpMsgIdPair& msgId)
{
RsStackMutex stack(mGenMtx);
std::map<uint32_t, std::pair<RsGxsGroupId, RsGxsMessageId> >::iterator mit =
mMsgPublished.find(token);
std::map<uint32_t, RsGxsGrpMsgIdPair >::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<uint32_t, RsGxsGroupId >::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<RsNxsMsg *>& 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<uint32_t, MsgLocMetaData>::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<uint32_t, GrpLocMetaData>::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;
}

View File

@ -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<RsGxsGroupId, RsGxsMessageId>& 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<uint32_t, RsGxsGrpItem*> mGrpsToPublish;
std::map<uint32_t, RsGxsMsgItem*> mMsgsToPublish;
std::map<uint32_t, std::pair<RsGxsGroupId, RsGxsMessageId> > mMsgPublished;
std::map<uint32_t, RsGxsGroupId> mGrpPublished;
std::map<uint32_t, RsGxsGrpMsgIdPair > mMsgNotify;
std::map<uint32_t, RsGxsGroupId> mGrpNotify;
// for loc meta changes
std::map<uint32_t, GrpLocMetaData > mGrpLocMetaMap;
std::map<uint32_t, MsgLocMetaData> mMsgLocMetaMap;
std::vector<RsGxsNotify*> mNotifications;

View File

@ -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<MsgRelatedInfoReq*>(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<RsGxsGroupId>& 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<MsgRelatedInfoReq*>(req)) != NULL)
{
getMsgRelatedInfo(mri);
}
else
{
#ifdef GXSDATA_SERVE_DEBUG
@ -569,7 +569,6 @@ void RsGxsDataAccess::processRequests()
bool RsGxsDataAccess::getGroupData(GroupDataReq* req)
{
std::map<RsGxsGroupId, RsNxsGrp*> grpData;
std::list<RsGxsGroupId>::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<RsGxsMessageId, RsGxsMsgMetaData*>();
const std::vector<RsGxsMsgMetaData*>& metaV = meta_it->second;
if (onlyLatestMsgs) // THIS ONE IS HARD -> LOTS OF COMP.
{
std::vector<RsGxsMsgMetaData*>::const_iterator vit = metaV.begin();
// RUN THROUGH ALL MSGS... in map origId -> TS.
std::map<RsGxsGroupId, std::pair<RsGxsMessageId, time_t> > origMsgTs;
std::map<RsGxsGroupId, std::pair<RsGxsMessageId, time_t> >::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<RsGxsMsgMetaData*>::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<RsGxsMsgMetaData*>& metaV = mit->second;
std::vector<RsGxsMsgMetaData*>::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<RsGxsMessageId, RsGxsMsgMetaData*>();
const std::vector<RsGxsMsgMetaData*>& metaV = meta_it->second;
if (onlyLatestMsgs) // THIS ONE IS HARD -> LOTS OF COMP.
{
std::vector<RsGxsMsgMetaData*>::const_iterator vit = metaV.begin();
// RUN THROUGH ALL MSGS... in map origId -> TS.
std::map<RsGxsGroupId, std::pair<RsGxsMessageId, time_t> > origMsgTs;
std::map<RsGxsGroupId, std::pair<RsGxsMessageId, time_t> >::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<RsGxsMsgMetaData*>::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)

View File

@ -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

View File

@ -95,6 +95,14 @@ public:
NxsMsgDataResult mMsgData;
};
class MsgRelatedInfoReq : public GxsRequest
{
public:
GxsMsgReq mMsgIds;
GxsMsgIdResult mMsgIdResult;
};
class GroupSetFlagReq : public GxsRequest
{
public:

View File

@ -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<std::string>& peers) = 0;
/* Poll */

View File

@ -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,

View File

@ -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 <iostream>
#include <memory.h>
#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<std::string, uint8_t> KeyTypePair;
ContentValue::ContentValue(){
}
ContentValue::~ContentValue(){
// release resources held in data
clearData();
}
ContentValue::ContentValue(ContentValue &from){
std::map<std::string, uint8_t> keyTypeMap;
from.getKeyTypeMap(keyTypeMap);
std::map<std::string, uint8_t>::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<std::string, bool>(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<std::string, std::string>(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<std::string, double>(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<std::string, int32_t>(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<std::string, int64_t>(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<std::string, std::pair<uint32_t, char*> >
(key, std::pair<uint32_t, char*>(len, dest)));
}
bool ContentValue::getAsBool(const std::string &key, bool& value) const{
std::map<std::string, bool>::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<std::string, int32_t>::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<std::string, int64_t>::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<std::string, std::string>::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<std::string, std::pair<uint32_t, char*> >::const_iterator it;
if((it = mKvData.find(key)) == mKvData.end())
return false;
const std::pair<uint32_t, char*> &kvRef = it->second;
len = kvRef.first;
value = kvRef.second;
return true;
}
bool ContentValue::getAsDouble(const std::string &key, double& value) const{
std::map<std::string, double>::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<std::string, uint8_t>::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<std::string, uint8_t> &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<std::string, std::pair<uint32_t, char*> >::iterator
mit = mKvData.begin();
for(; mit != mKvData.end(); mit++){
if(mit->second.first != 0)
delete[] (mit->second.second);
}
mKvData.clear();
}

View File

@ -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 <inttypes.h>
#include <string>
#include <map>
/*!
* @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<std::string, uint8_t>& 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<std::string, int32_t> mKvInt32;
std::map<std::string, int64_t> mKvInt64;
std::map<std::string, double> mKvDouble;
std::map<std::string, std::string> mKvString;
std::map<std::string, std::pair<uint32_t, char*> > mKvData;
std::map<std::string, bool> mKvBool;
std::map<std::string, uint8_t> mKvSet;
};
#endif // CONTENTVALUE_H

View File

@ -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<std::string, uint8_t> KeyTypePair;
ContentValue::ContentValue(){
}
ContentValue::~ContentValue(){
// release resources held in data
clearData();
}
ContentValue::ContentValue(ContentValue &from){
std::map<std::string, uint8_t> keyTypeMap;
from.getKeyTypeMap(keyTypeMap);
std::map<std::string, uint8_t>::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<std::string, bool>(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<std::string, std::string>(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<std::string, double>(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<std::string, int32_t>(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<std::string, int64_t>(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<std::string, std::pair<uint32_t, char*> >
(key, std::pair<uint32_t, char*>(len, dest)));
}
bool ContentValue::getAsBool(const std::string &key, bool& value) const{
std::map<std::string, bool>::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<std::string, int32_t>::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<std::string, int64_t>::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<std::string, std::string>::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<std::string, std::pair<uint32_t, char*> >::const_iterator it;
if((it = mKvData.find(key)) == mKvData.end())
return false;
const std::pair<uint32_t, char*> &kvRef = it->second;
len = kvRef.first;
value = kvRef.second;
return true;
}
bool ContentValue::getAsDouble(const std::string &key, double& value) const{
std::map<std::string, double>::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<std::string, uint8_t>::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<std::string, uint8_t> &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<std::string, std::pair<uint32_t, char*> >::iterator
mit = mKvData.begin();
for(; mit != mKvData.end(); mit++){
if(mit->second.first != 0)
delete[] (mit->second.second);
}
mKvData.clear();
}

View File

@ -31,8 +31,8 @@
#include <list>
#include <map>
#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<std::string, uint8_t>& 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<std::string, int32_t> mKvInt32;
std::map<std::string, int64_t> mKvInt64;
std::map<std::string, double> mKvDouble;
std::map<std::string, std::string> mKvString;
std::map<std::string, std::pair<uint32_t, char*> > mKvData;
std::map<std::string, bool> mKvBool;
std::map<std::string, uint8_t> mKvSet;
};
#endif // RSSQLITE_H