/*******************************************************************************
* libretroshare/src/gxs: gxsdataservice.h *
* *
* libretroshare: retroshare core library *
* *
* Copyright 2011-2012 by Evi-Parker Christopher *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* This program 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 Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see . *
* *
*******************************************************************************/
#ifndef RSDATASERVICE_H
#define RSDATASERVICE_H
#include "gxs/rsgds.h"
#include "util/retrodb.h"
class MsgUpdate
{
public:
//MsgUpdate(){}
//MsgUpdate(const MsgUpdate& ){}//hier müsste ein echter constructor sein
RsGxsMessageId msgId;
ContentValue cv;
};
template class t_MetaDataCache
{
public:
t_MetaDataCache()
: mCache_ContainsAllMetas(false)
{}
virtual ~t_MetaDataCache() = default;
bool isCacheUpToDate() const { return mCache_ContainsAllMetas ; }
void setCacheUpToDate(bool b) { mCache_ContainsAllMetas = b; }
void getFullMetaList(std::map >& mp) const { mp = mMetas ; }
void getFullMetaList(std::vector >& mp) const { for(auto& m:mMetas) mp.push_back(m.second) ; }
std::shared_ptr getMeta(const ID& id)
{
auto itt = mMetas.find(id);
if(itt != mMetas.end())
return itt->second ;
else
return nullptr;
}
std::shared_ptr getOrCreateMeta(const ID& id)
{
auto it = mMetas.find(id) ;
if(it != mMetas.end())
{
#ifdef RS_DATA_SERVICE_DEBUG
RsDbg() << __PRETTY_FUNCTION__ << ": getting group meta " << grpId << " from cache." << std::endl;
#endif
return it->second ;
}
else
{
#ifdef RS_DATA_SERVICE_DEBUG
RsDbg() << __PRETTY_FUNCTION__ << ": group meta " << grpId << " not in cache. Loading it from DB..." << std::endl;
#endif
return (mMetas[id] = std::make_shared());
}
}
void updateMeta(const ID& id,const MetaDataClass& meta)
{
mMetas[id] = std::make_shared(meta); // create a new shared_ptr to possibly replace the previous one
}
void updateMeta(const ID& id,const std::shared_ptr& meta)
{
mMetas[id] = meta; // create a new shared_ptr to possibly replace the previous one
}
void clear(const ID& id)
{
auto it = mMetas.find(id) ;
// We dont actually delete the item, because it might be used by a calling client.
// In this case, the memory will not be used for long, so we keep it into a list for a safe amount
// of time and delete it later. Using smart pointers here would be more elegant, but that would need
// to be implemented thread safe, which is difficult in this case.
if(it != mMetas.end())
{
#ifdef RS_DATA_SERVICE_DEBUG
std::cerr << "(II) moving database cache entry " << (void*)(*it).second << " to dead list." << std::endl;
#endif
mMetas.erase(it) ;
// No need to modify mCache_ContainsAllMetas since, assuming that the cache always contains
// all possible elements from the DB, clearing one from the cache means that it is also deleted from the db, so
// the property is preserved.
}
}
void debug_computeSize(uint32_t& nb_items, uint64_t& total_size) const
{
nb_items = mMetas.size();
total_size = 0;
for(auto it:mMetas) total_size += it.second->serial_size();
}
private:
std::map > mMetas;
static const uint32_t CACHE_ENTRY_GRACE_PERIOD = 600 ; // Unused items are deleted 10 minutes after last usage.
bool mCache_ContainsAllMetas ;
};
class RsDataService : public RsGeneralDataService
{
public:
RsDataService(const std::string& serviceDir, const std::string& dbName, uint16_t serviceType,
RsGxsSearchModule* mod = NULL, const std::string& key = "");
virtual ~RsDataService();
/*!
* Retrieves all msgs
* @param reqIds requested msg ids (grpId,msgId), leave msg list empty to get all msgs for the grp
* @param msg result of msg retrieval
* @param withMeta true will also retrieve metadata
* @return error code
*/
int retrieveNxsMsgs(const GxsMsgReq& reqIds, GxsMsgResult& msg, bool withMeta = false) override;
/*!
* Retrieves groups, if empty, retrieves all grps, if map is not empty
* only retrieve entries, if entry cannot be found, it is removed from map
* @param grp retrieved groups
* @param withMeta this initialise the metaData member of the nxsgroups retrieved
* @return error code
*/
int retrieveNxsGrps(std::map& grp, bool withMeta) override;
/*!
* Retrieves meta data of all groups stored (most current versions only)
* @param grp output group meta data
* @return error code
*/
int retrieveGxsGrpMetaData(std::map > &grp) override;
/*!
* Retrieves meta data of all groups stored (most current versions only)
* @param grpIds grpIds for which to retrieve meta data
* @param msgMeta meta data result as map of grpIds to array of metadata for that grpId
* @return error code
*/
int retrieveGxsMsgMetaData(const GxsMsgReq& reqIds, GxsMsgMetaResult& msgMeta) override;
/*!
* remove msgs in data store
* @param grpId group Id of message to be removed
* @param msgIds ids of messages to be removed
* @return error code
*/
int removeMsgs(const GxsMsgReq& msgIds) override;
/*!
* remove groups in data store listed in grpIds param
* @param grpIds ids of groups to be removed
* @return error code
*/
int removeGroups(const std::vector& grpIds) override;
/*!
* Retrieves all group ids in store
* @param grpIds all grpids in store is inserted into this vector
* @return error code
*/
int retrieveGroupIds(std::vector &grpIds) override;
/*!
* Retrives all msg ids in store
* @param grpId groupId of message ids to retrieve
* @param msgId msgsids retrieved
* @return error code
*/
int retrieveMsgIds(const RsGxsGroupId& grpId, RsGxsMessageId::std_set& msgId) override;
/*!
* @return the cache size set for this RsGeneralDataService in bytes
*/
uint32_t cacheSize() const override;
/*!
* \brief serviceType
* \return
* The service type for the current data service.
*/
virtual uint16_t serviceType() const override { return mServType; }
/*!
* @param size size of cache to set in bytes
*/
int setCacheSize(uint32_t size) override;
/*!
* Stores a list of signed messages into data store
* @param msg map of message and decoded meta data information
* @return error code
*/
int storeMessage(const std::list& msg) override;
/*!
* Stores a list of groups in data store
* @param grp map of group and decoded meta data
* @return error code
*/
int storeGroup(const std::list& grp) override;
/*!
* Updates group entries in Db
* @param grp map of group and decoded meta data
* @return error code
*/
int updateGroup(const std::list& grsp) override;
/*!
* @param metaData The meta data item to update
* @return error code
*/
int updateMessageMetaData(const MsgLocMetaData& metaData) override;
/*!
* @param metaData The meta data item to update
* @return error code
*/
int updateGroupMetaData(const GrpLocMetaData &meta) override;
/*!
* Completely clear out data stored in
* and returns this to a state
* as it was when first constructed
* @return error code
*/
int resetDataStore() override;
bool validSize(RsNxsMsg* msg) const override;
bool validSize(RsNxsGrp* grp) const override;
/*!
* Convenience function used to only update group keys. This is used when sending
* publish keys between peers.
* @return SQL error code
*/
int updateGroupKeys(const RsGxsGroupId& grpId,const RsTlvSecurityKeySet& keys, uint32_t subscribe_flags) override;
void debug_printCacheSize() ;
private:
/*!
* Retrieves all the msg results from a cursor
* @param c cursor to result set
* @param msgs messages retrieved from cursor are stored here
*/
void locked_retrieveMessages(RetroCursor* c, std::vector& msgs, int metaOffset);
/*!
* Retrieves all the grp results from a cursor
* @param c cursor to result set
* @param grps groups retrieved from cursor are stored here
* @param withMeta this initialise the metaData member of the nxsgroups retrieved
*/
void locked_retrieveGroups(RetroCursor* c, std::vector& grps, int metaOffset);
/*!
* Retrieves all the msg meta results from a cursor
* @param c cursor to result set
* @param msgMeta message metadata retrieved from cursor are stored here
*/
void locked_retrieveMsgMetaList(RetroCursor* c, std::vector > &msgMeta);
/*!
* Retrieves all the grp meta results from a cursor
* @param c cursor to result set
* @param grpMeta group metadata retrieved from cursor are stored here
*/
void locked_retrieveGrpMetaList(RetroCursor *c, std::map > &grpMeta);
/*!
* extracts a msg meta item from a cursor at its
* current position
*/
std::shared_ptr locked_getMsgMeta(RetroCursor& c, int colOffset);
/*!
* extracts a grp meta item from a cursor at its
* current position
*/
std::shared_ptr locked_getGrpMeta(RetroCursor& c, int colOffset);
/*!
* extracts a msg item from a cursor at its
* current position
*/
RsNxsMsg* locked_getMessage(RetroCursor& c);
/*!
* extracts a grp item from a cursor at its
* current position
*/
RsNxsGrp* locked_getGroup(RetroCursor& c);
/*!
* Creates an sql database and its associated file
* also creates the message and groups table
* @param isNewDatabase is new database
*/
void initialise(bool isNewDatabase);
/*!
* Remove entries for data base
* @param msgIds
*/
bool locked_removeMessageEntries(const GxsMsgReq& msgIds);
bool locked_removeGroupEntries(const std::vector& grpIds);
private:
/*!
* Start release update
* @param release
* @return true/false
*/
bool startReleaseUpdate(int release);
/*!
* Finish release update
* @param release
* @param result
* @return true/false
*/
bool finishReleaseUpdate(int release, bool result);
private:
RsMutex mDbMutex;
std::list mMsgColumns;
std::list mMsgMetaColumns;
std::list mMsgColumnsWithMeta;
std::list mMsgIdColumn;
std::list mGrpColumns;
std::list mGrpMetaColumns;
std::list mGrpColumnsWithMeta;
std::list mGrpIdColumn;
// Message meta column
int mColMsgMeta_GrpId;
int mColMsgMeta_TimeStamp;
int mColMsgMeta_NxsFlags;
int mColMsgMeta_SignSet;
int mColMsgMeta_NxsIdentity;
int mColMsgMeta_NxsHash;
int mColMsgMeta_MsgId;
int mColMsgMeta_OrigMsgId;
int mColMsgMeta_MsgStatus;
int mColMsgMeta_ChildTs;
int mColMsgMeta_MsgParentId;
int mColMsgMeta_MsgThreadId;
int mColMsgMeta_Name;
int mColMsgMeta_NxsServString;
int mColMsgMeta_RecvTs;
int mColMsgMeta_NxsDataLen;
// Message columns
int mColMsg_GrpId;
int mColMsg_NxsData;
int mColMsg_MetaData;
int mColMsg_MsgId;
// Message columns with meta
int mColMsg_WithMetaOffset;
// Group meta columns
int mColGrpMeta_GrpId;
int mColGrpMeta_TimeStamp;
int mColGrpMeta_NxsFlags;
// int mColGrpMeta_SignSet;
int mColGrpMeta_NxsIdentity;
int mColGrpMeta_NxsHash;
int mColGrpMeta_KeySet;
int mColGrpMeta_SubscrFlag;
int mColGrpMeta_Pop;
int mColGrpMeta_MsgCount;
int mColGrpMeta_Status;
int mColGrpMeta_Name;
int mColGrpMeta_LastPost;
int mColGrpMeta_OrigGrpId;
int mColGrpMeta_ServString;
int mColGrpMeta_SignFlags;
int mColGrpMeta_CircleId;
int mColGrpMeta_CircleType;
int mColGrpMeta_InternCircle;
int mColGrpMeta_Originator;
int mColGrpMeta_AuthenFlags;
int mColGrpMeta_ParentGrpId;
int mColGrpMeta_RecvTs;
int mColGrpMeta_RepCutoff;
int mColGrpMeta_NxsDataLen;
// Group columns
int mColGrp_GrpId;
int mColGrp_NxsData;
int mColGrp_MetaData;
// Group columns with meta
int mColGrp_WithMetaOffset;
// Group id columns
int mColGrpId_GrpId;
// Msg id columns
int mColMsgId_MsgId;
std::string mServiceDir;
std::string mDbName;
std::string mDbPath;
uint16_t mServType;
RetroDb* mDb;
// used to store metadata instead of reading it from the database.
// The boolean variable below is also used to force re-reading when
// the entre list of grp metadata is requested (which happens quite often)
void locked_clearGrpMetaCache(const RsGxsGroupId& gid);
void locked_updateGrpMetaCache(const RsGxsGrpMetaData& meta);
t_MetaDataCache mGrpMetaDataCache;
std::map > mMsgMetaDataCache;
bool mUseCache;
};
#endif // RSDATASERVICE_H