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