diff --git a/libretroshare/src/libretroshare.pro b/libretroshare/src/libretroshare.pro index d41d7294a..86abb1c0d 100644 --- a/libretroshare/src/libretroshare.pro +++ b/libretroshare/src/libretroshare.pro @@ -646,8 +646,8 @@ HEADERS += retroshare/rsgame.h \ services/p3wiki.h \ serialiser/rswikiitems.h - SOURCES += services/p3wiki.cc - # serialiser/rswikiitems.cc \ + SOURCES += services/p3wiki.cc \ + serialiser/rswikiitems.cc \ } diff --git a/libretroshare/src/rsserver/rsinit.cc b/libretroshare/src/rsserver/rsinit.cc index 7099e2395..a8c437fbd 100644 --- a/libretroshare/src/rsserver/rsinit.cc +++ b/libretroshare/src/rsserver/rsinit.cc @@ -1823,12 +1823,15 @@ RsTurtle *rsTurtle = NULL ; #endif #ifdef ENABLE_GXS_SERVICES -#include "services/p3photoserviceV2.h" +#include "services/p3idservice.h" +#include "services/p3wiki.h" #include "services/p3posted.h" -#include "services/p3wikiserviceVEG.h" +#include "services/p3photoserviceV2.h" + +// Not too many to convert now! +//#include "services/p3wikiserviceVEG.h" #include "services/p3wireVEG.h" //#include "services/p3idserviceVEG.h" -#include "services/p3idservice.h" #include "services/p3forumsVEG.h" #endif @@ -2277,8 +2280,8 @@ int RsServer::StartupRetroShare() #ifdef ENABLE_GXS_SERVICES // Testing New Cache Services. - p3WikiServiceVEG *mWikis = new p3WikiServiceVEG(RS_SERVICE_GXSV1_TYPE_WIKI); - pqih -> addService(mWikis); + //p3WikiServiceVEG *mWikis = new p3WikiServiceVEG(RS_SERVICE_GXSV1_TYPE_WIKI); + //pqih -> addService(mWikis); // Testing New Cache Services. p3WireVEG *mWire = new p3WireVEG(RS_SERVICE_GXSV1_TYPE_WIRE); @@ -2345,6 +2348,22 @@ int RsServer::StartupRetroShare() RS_SERVICE_GXSV1_TYPE_POSTED, posted_ds, nxsMgr, mPosted); + /**** Wiki GXS service ****/ + + p3Wiki *mWiki = NULL; + + RsGeneralDataService* wiki_ds = new RsDataService("./" + mLinkMgr->getOwnId()+ "/", "wiki_db", + RS_SERVICE_GXSV1_TYPE_WIKI); + + wiki_ds->resetDataStore(); //TODO: remove, new service data per RS session, for testing + + mWiki = new p3Wiki(posted_ds, NULL); + + // create GXS photo service + RsGxsNetService* wiki_ns = new RsGxsNetService( + RS_SERVICE_GXSV1_TYPE_WIKI, wiki_ds, nxsMgr, mWiki); + + #endif // ENABLE_GXS_SERVICES #ifdef ENABLE_GXS_CORE @@ -2355,16 +2374,19 @@ int RsServer::StartupRetroShare() mGxsCore->addService(mGxsIdService); mGxsCore->addService(mPhotoV2); mGxsCore->addService(mPosted); + mGxsCore->addService(mWiki); // cores ready start up GXS net servers + createThread(*gxsid_ns); createThread(*photo_ns); createThread(*posted_ns); - createThread(*gxsid_ns); + createThread(*wiki_ns); // now add to p3service - pqih->addService(photo_ns); pqih->addService(gxsid_ns); + pqih->addService(photo_ns); pqih->addService(posted_ns); + pqih->addService(wiki_ns); // start up gxs core server createThread(*mGxsCore); @@ -2630,12 +2652,14 @@ int RsServer::StartupRetroShare() #ifdef ENABLE_GXS_SERVICES // Testing of new cache system interfaces. - rsWikiVEG = mWikis; - rsWireVEG = mWire; - rsForumsVEG = mForumsV2; + rsIdentity = mGxsIdService; + rsWiki = mWiki; rsPosted = mPosted; rsPhotoV2 = mPhotoV2; + rsWireVEG = mWire; + rsForumsVEG = mForumsV2; + #endif // ENABLE_GXS_SERVICES diff --git a/libretroshare/src/serialiser/rsgxsiditems.cc b/libretroshare/src/serialiser/rsgxsiditems.cc index 350d616d5..ebacdc7a1 100644 --- a/libretroshare/src/serialiser/rsgxsiditems.cc +++ b/libretroshare/src/serialiser/rsgxsiditems.cc @@ -65,8 +65,7 @@ bool RsGxsIdSerialiser::serialise(RsItem *item, void *data, uint32_t *size) } else if((op_item = dynamic_cast(item)) != NULL) { - return serialiseGxsIdGroupItem(grp_item, data, size); - return sizeGxsIdOpinionItem(op_item); + return serialiseGxsIdOpinionItem(op_item, data, size); } else if((com_item = dynamic_cast(item)) != NULL) { @@ -453,7 +452,6 @@ uint32_t RsGxsIdSerialiser::sizeGxsIdCommentItem(RsGxsIdCommentItem *item) const RsGxsIdComment& comment = item->comment; uint32_t s = 8; // header - s += 4; // mIdType. s += GetTlvStringSize(comment.mComment); return s; diff --git a/libretroshare/src/serialiser/rswikiitems.cc b/libretroshare/src/serialiser/rswikiitems.cc new file mode 100644 index 000000000..2d1bcb272 --- /dev/null +++ b/libretroshare/src/serialiser/rswikiitems.cc @@ -0,0 +1,580 @@ +/* + * libretroshare/src/serialiser: rswikiitems.cc + * + * RetroShare C++ Interface. + * + * Copyright 2012-2012 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 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 "rswikiitems.h" +#include "serialiser/rstlvbase.h" +#include "serialiser/rsbaseserial.h" + +#define GXSID_DEBUG 1 + + +uint32_t RsGxsWikiSerialiser::size(RsItem *item) +{ + RsGxsWikiCollectionItem* grp_item = NULL; + RsGxsWikiSnapshotItem* snap_item = NULL; + RsGxsWikiCommentItem* com_item = NULL; + + if((grp_item = dynamic_cast(item)) != NULL) + { + return sizeGxsWikiCollectionItem(grp_item); + } + else if((snap_item = dynamic_cast(item)) != NULL) + { + return sizeGxsWikiSnapshotItem(snap_item); + } + else if((com_item = dynamic_cast(item)) != NULL) + { + return sizeGxsWikiCommentItem(com_item); + } + return NULL; +} + +bool RsGxsWikiSerialiser::serialise(RsItem *item, void *data, uint32_t *size) +{ + RsGxsWikiCollectionItem* grp_item = NULL; + RsGxsWikiSnapshotItem* snap_item = NULL; + RsGxsWikiCommentItem* com_item = NULL; + + if((grp_item = dynamic_cast(item)) != NULL) + { + return serialiseGxsWikiCollectionItem(grp_item, data, size); + } + else if((snap_item = dynamic_cast(item)) != NULL) + { + return serialiseGxsWikiSnapshotItem(snap_item, data, size); + } + else if((com_item = dynamic_cast(item)) != NULL) + { + return serialiseGxsWikiCommentItem(com_item, data, size); + } + return false; +} + +RsItem* RsGxsWikiSerialiser::deserialise(void* data, uint32_t* size) +{ + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialise()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_WIKI != getRsItemService(rstype))) + { + return NULL; /* wrong type */ + } + + switch(getRsItemSubType(rstype)) + { + + case RS_PKT_SUBTYPE_WIKI_COLLECTION_ITEM: + return deserialiseGxsWikiCollectionItem(data, size); + break; + case RS_PKT_SUBTYPE_WIKI_SNAPSHOT_ITEM: + return deserialiseGxsWikiSnapshotItem(data, size); + break; + case RS_PKT_SUBTYPE_WIKI_COMMENT_ITEM: + return deserialiseGxsWikiCommentItem(data, size); + break; + default: +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialise(): unknown subtype"; + std::cerr << std::endl; +#endif + break; + } + return NULL; +} + + + +/*****************************************************************************************/ +/*****************************************************************************************/ +/*****************************************************************************************/ + + +void RsGxsWikiCollectionItem::clear() +{ + collection.mDescription.clear(); + collection.mCategory.clear(); + collection.mHashTags.clear(); +} + +std::ostream& RsGxsWikiCollectionItem::print(std::ostream& out, uint16_t indent) +{ + printRsItemBase(out, "RsGxsWikiCollectionItem", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "Description: " << collection.mDescription << std::endl; + printIndent(out, int_Indent); + out << "Category: " << collection.mCategory << std::endl; + printIndent(out, int_Indent); + out << "HashTags: " << collection.mHashTags << std::endl; + + printRsItemEnd(out ,"RsGxsWikiCollectionItem", indent); + return out; +} + + +uint32_t RsGxsWikiSerialiser::sizeGxsWikiCollectionItem(RsGxsWikiCollectionItem *item) +{ + + const RsWikiCollection& collection = item->collection; + uint32_t s = 8; // header + + s += GetTlvStringSize(collection.mDescription); + s += GetTlvStringSize(collection.mCategory); + s += GetTlvStringSize(collection.mHashTags); + + return s; +} + +bool RsGxsWikiSerialiser::serialiseGxsWikiCollectionItem(RsGxsWikiCollectionItem *item, void *data, uint32_t *size) +{ + +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::serialiseGxsWikiCollectionItem()" << std::endl; +#endif + + uint32_t tlvsize = sizeGxsWikiCollectionItem(item); + uint32_t offset = 0; + + if(*size < tlvsize) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::serialiseGxsWikiCollectionItem()" << std::endl; +#endif + return false; + } + + *size = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* GxsWikiCollectionItem */ + ok &= SetTlvString(data, tlvsize, &offset, 1, item->collection.mDescription); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->collection.mCategory); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->collection.mHashTags); + + if(offset != tlvsize) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::serialiseGxsWikiCollectionItem() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef GXSID_DEBUG + if (!ok) + { + std::cerr << "RsGxsWikiSerialiser::serialiseGxsIdcollectionItem() NOK" << std::endl; + } +#endif + + return ok; + } + +RsGxsWikiCollectionItem* RsGxsWikiSerialiser::deserialiseGxsWikiCollectionItem(void *data, uint32_t *size) +{ + +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialiseGxsWikiCollectionItem()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_WIKI != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_WIKI_COLLECTION_ITEM != getRsItemSubType(rstype))) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialiseGxsWikiCollectionItem() FAIL wrong type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialiseGxsWikiCollectionItem() FAIL wrong size" << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + RsGxsWikiCollectionItem* item = new RsGxsWikiCollectionItem(); + /* skip the header */ + offset += 8; + + ok &= GetTlvString(data, rssize, &offset, 1, item->collection.mDescription); + ok &= GetTlvString(data, rssize, &offset, 1, item->collection.mCategory); + ok &= GetTlvString(data, rssize, &offset, 1, item->collection.mHashTags); + + if (offset != rssize) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialiseGxsWikiCollectionItem() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialiseGxsWikiCollectionItem() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + + + +/*****************************************************************************************/ +/*****************************************************************************************/ +/*****************************************************************************************/ + + +void RsGxsWikiSnapshotItem::clear() +{ + snapshot.mPage.clear(); + snapshot.mHashTags.clear(); +} + +std::ostream& RsGxsWikiSnapshotItem::print(std::ostream& out, uint16_t indent) +{ + printRsItemBase(out, "RsGxsWikiSnapshotItem", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "Page: " << snapshot.mPage << std::endl; + + printIndent(out, int_Indent); + out << "HashTags: " << snapshot.mHashTags << std::endl; + + printRsItemEnd(out ,"RsGxsWikiSnapshotItem", indent); + return out; +} + + +uint32_t RsGxsWikiSerialiser::sizeGxsWikiSnapshotItem(RsGxsWikiSnapshotItem *item) +{ + + const RsWikiSnapshot& snapshot = item->snapshot; + uint32_t s = 8; // header + + s += GetTlvStringSize(snapshot.mPage); + s += GetTlvStringSize(snapshot.mHashTags); + + return s; +} + +bool RsGxsWikiSerialiser::serialiseGxsWikiSnapshotItem(RsGxsWikiSnapshotItem *item, void *data, uint32_t *size) +{ + +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::serialiseGxsWikiSnapshotItem()" << std::endl; +#endif + + uint32_t tlvsize = sizeGxsWikiSnapshotItem(item); + uint32_t offset = 0; + + if(*size < tlvsize) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::serialiseGxsWikiSnapshotItem()" << std::endl; +#endif + return false; + } + + *size = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* GxsWikiSnapshotItem */ + ok &= SetTlvString(data, tlvsize, &offset, 1, item->snapshot.mPage); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->snapshot.mHashTags); + + if(offset != tlvsize) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::serialiseGxsWikiSnapshotItem() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef GXSID_DEBUG + if (!ok) + { + std::cerr << "RsGxsWikiSerialiser::serialiseGxsIdgroupItem() NOK" << std::endl; + } +#endif + + return ok; + } + +RsGxsWikiSnapshotItem* RsGxsWikiSerialiser::deserialiseGxsWikiSnapshotItem(void *data, uint32_t *size) +{ + +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialiseGxsWikiSnapshotItem()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_WIKI != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_WIKI_SNAPSHOT_ITEM != getRsItemSubType(rstype))) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialiseGxsWikiSnapshotItem() FAIL wrong type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialiseGxsWikiSnapshotItem() FAIL wrong size" << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + RsGxsWikiSnapshotItem* item = new RsGxsWikiSnapshotItem(); + /* skip the header */ + offset += 8; + + ok &= GetTlvString(data, rssize, &offset, 1, item->snapshot.mPage); + ok &= GetTlvString(data, rssize, &offset, 1, item->snapshot.mHashTags); + + if (offset != rssize) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialiseGxsWikiSnapshotItem() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialiseGxsWikiSnapshotItem() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + + +/*****************************************************************************************/ +/*****************************************************************************************/ +/*****************************************************************************************/ + + +void RsGxsWikiCommentItem::clear() +{ + comment.mComment.clear(); +} + +std::ostream& RsGxsWikiCommentItem::print(std::ostream& out, uint16_t indent) +{ + printRsItemBase(out, "RsGxsWikiCommentItem", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "Comment: " << comment.mComment << std::endl; + + printRsItemEnd(out ,"RsGxsWikiCommentItem", indent); + return out; +} + + +uint32_t RsGxsWikiSerialiser::sizeGxsWikiCommentItem(RsGxsWikiCommentItem *item) +{ + + const RsWikiComment& comment = item->comment; + uint32_t s = 8; // header + + s += GetTlvStringSize(comment.mComment); + + return s; +} + +bool RsGxsWikiSerialiser::serialiseGxsWikiCommentItem(RsGxsWikiCommentItem *item, void *data, uint32_t *size) +{ + +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::serialiseGxsWikiCommentItem()" << std::endl; +#endif + + uint32_t tlvsize = sizeGxsWikiCommentItem(item); + uint32_t offset = 0; + + if(*size < tlvsize) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::serialiseGxsWikiCommentItem()" << std::endl; +#endif + return false; + } + + *size = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* GxsWikiCommentItem */ + ok &= SetTlvString(data, tlvsize, &offset, 1, item->comment.mComment); + + if(offset != tlvsize) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::serialiseGxsWikiCommentItem() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef GXSID_DEBUG + if (!ok) + { + std::cerr << "RsGxsWikiSerialiser::serialiseGxsIdgroupItem() NOK" << std::endl; + } +#endif + + return ok; + } + +RsGxsWikiCommentItem* RsGxsWikiSerialiser::deserialiseGxsWikiCommentItem(void *data, uint32_t *size) +{ + +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialiseGxsWikiCommentItem()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_WIKI != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_WIKI_COMMENT_ITEM != getRsItemSubType(rstype))) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialiseGxsWikiCommentItem() FAIL wrong type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialiseGxsWikiCommentItem() FAIL wrong size" << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + RsGxsWikiCommentItem* item = new RsGxsWikiCommentItem(); + /* skip the header */ + offset += 8; + + ok &= GetTlvString(data, rssize, &offset, 1, item->comment.mComment); + + if (offset != rssize) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialiseGxsWikiCommentItem() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialiseGxsWikiCommentItem() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + + +/*****************************************************************************************/ +/*****************************************************************************************/ +/*****************************************************************************************/ + diff --git a/libretroshare/src/services/p3idservice.cc b/libretroshare/src/services/p3idservice.cc index 066d6ce0d..c016aa263 100644 --- a/libretroshare/src/services/p3idservice.cc +++ b/libretroshare/src/services/p3idservice.cc @@ -678,6 +678,9 @@ void p3IdService::generateDummyData() { RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + // Temporarily disable - until system is properly tested. + return; + /* grab all the gpg ids... and make some ids */ std::list gpgids; diff --git a/libretroshare/src/services/p3wiki.cc b/libretroshare/src/services/p3wiki.cc index 563b5b04f..ab1195aa2 100644 --- a/libretroshare/src/services/p3wiki.cc +++ b/libretroshare/src/services/p3wiki.cc @@ -40,6 +40,12 @@ p3Wiki::p3Wiki(RsGeneralDataService* gds, RsNetworkExchangeService* nes) } +void p3Wiki::service_tick() +{ + return; +} + + void p3Wiki::notifyChanges(std::vector& changes) { receiveChanges(changes); diff --git a/libretroshare/src/services/p3wiki.h b/libretroshare/src/services/p3wiki.h index 10bd1edd3..7a8f74b2a 100644 --- a/libretroshare/src/services/p3wiki.h +++ b/libretroshare/src/services/p3wiki.h @@ -49,6 +49,8 @@ virtual void notifyChanges(std::vector& changes) ; public: +virtual void service_tick(); + /* Specific Service Data */ virtual bool getCollections(const uint32_t &token, std::vector &collections); virtual bool getSnapshots(const uint32_t &token, std::vector &snapshots);