diff --git a/cstore/datapackstore.h b/cstore/datapackstore.h --- a/cstore/datapackstore.h +++ b/cstore/datapackstore.h @@ -14,80 +14,18 @@ #include "cdatapack.h" } +#include +#include #include -#include #include #include +#include "datastore.h" #include "key.h" #include "portability/portability.h" const clock_t PACK_REFRESH_RATE = 0.1 * CLOCKS_PER_SEC; -class DeltaChainIterator { - private: - size_t _index; - protected: - std::vector _chains; - DeltaChainIterator() : - _index(0) {} - virtual delta_chain_t getNextChain(const Key &key) { - return COMPOUND_LITERAL(delta_chain_t) { GET_DELTA_CHAIN_NOT_FOUND }; - } - public: - DeltaChainIterator(delta_chain_t chain) : - _index(0) { - _chains.push_back(chain); - } - - virtual ~DeltaChainIterator() { - for(std::vector::iterator it = _chains.begin(); - it != _chains.end(); - it++) { - freedeltachain(*it); - } - } - - delta_chain_link_t *next() { - delta_chain_t *chain = &_chains.back(); - if (_index >= chain->links_count) { - // If we're not at the end, and we have a callback to fetch more, do the - // fetch. - bool refreshed = false; - if (chain->links_count > 0) { - delta_chain_link_t *result = &chain->delta_chain_links[_index - 1]; - - const uint8_t *deltabasenode = result->deltabase_node; - if (memcmp(deltabasenode, NULLID, BIN_NODE_SIZE) != 0) { - Key key(result->filename, result->filename_sz, - (const char*)deltabasenode, BIN_NODE_SIZE); - - delta_chain_t newChain = this->getNextChain(key); - if (newChain.code == GET_DELTA_CHAIN_OK) { - // Do not free the old chain, since the iterator consumer may - // still be holding references to it. - _chains.push_back(newChain); - chain = &_chains.back(); - _index = 0; - refreshed = true; - } else { - freedeltachain(newChain); - } - } - } - - if (!refreshed) { - return NULL; - } - } - - delta_chain_link_t *result = &chain->delta_chain_links[_index]; - _index++; - - return result; - } -}; - class DatapackStore; class DatapackStoreKeyIterator : public KeyIterator { private: @@ -99,11 +37,11 @@ _store(store), _missing(missing) {} - Key *next(); + std::shared_ptr next(); }; /* Manages access to a directory of datapack files. */ -class DatapackStore { +class DatapackStore : public DataStore { private: std::string _path; clock_t _lastRefresh; @@ -122,9 +60,9 @@ DeltaChainIterator getDeltaChain(const Key &key); - DatapackStoreKeyIterator getMissing(KeyIterator &missing); + std::shared_ptr getMissing(KeyIterator &missing); - delta_chain_t getDeltaChainRaw(const Key &key); + std::shared_ptr getDeltaChainRaw(const Key &key); bool contains(const Key &key); diff --git a/cstore/datapackstore.cpp b/cstore/datapackstore.cpp --- a/cstore/datapackstore.cpp +++ b/cstore/datapackstore.cpp @@ -100,17 +100,14 @@ } DeltaChainIterator DatapackStore::getDeltaChain(const Key &key) { - delta_chain_t chain = this->getDeltaChainRaw(key); - if (chain.code == GET_DELTA_CHAIN_OK) { + std::shared_ptr chain = this->getDeltaChainRaw(key); + if (chain->code() == GET_DELTA_CHAIN_OK) { return DeltaChainIterator(chain); } - - freedeltachain(chain); - throw MissingKeyError("unable to find delta chain"); } -delta_chain_t DatapackStore::getDeltaChainRaw(const Key &key) { +std::shared_ptr DatapackStore::getDeltaChainRaw(const Key &key) { for(std::vector::iterator it = _packs.begin(); it != _packs.end(); it++) { @@ -127,7 +124,7 @@ continue; } - return chain; + return std::make_shared(chain); } // Check if there are new packs available @@ -148,14 +145,14 @@ continue; } - return chain; + return std::make_shared(chain); } - return COMPOUND_LITERAL(delta_chain_t) { GET_DELTA_CHAIN_NOT_FOUND }; + return std::make_shared(GET_DELTA_CHAIN_NOT_FOUND); } -Key *DatapackStoreKeyIterator::next() { - Key *key; +std::shared_ptr DatapackStoreKeyIterator::next() { + std::shared_ptr key; while ((key = _missing.next()) != NULL) { if (!_store.contains(*key)) { return key; @@ -193,8 +190,8 @@ return false; } -DatapackStoreKeyIterator DatapackStore::getMissing(KeyIterator &missing) { - return DatapackStoreKeyIterator(*this, missing); +std::shared_ptr DatapackStore::getMissing(KeyIterator &missing) { + return std::make_shared(*this, missing); } std::vector DatapackStore::refresh() { diff --git a/cstore/datastore.h b/cstore/datastore.h new file mode 100644 --- /dev/null +++ b/cstore/datastore.h @@ -0,0 +1,181 @@ +// datastore.h - c++ declarations for a data store +// +// copyright 2017 facebook, inc. +// +// this software may be used and distributed according to the terms of the +// gnu general public license version 2 or any later version. +// +// no-check-code + +#ifndef DATASTORE_H +#define DATASTORE_H + +extern "C" { +#include "cdatapack.h" +} + +#include +#include + +#include "key.h" +#include "portability/portability.h" + +class DeltaChainLink { + public: + const char *_filename1, *_filename2; + char *_node, *_delta, *_deltabasenode; + delta_chain_link_t *link; + + DeltaChainLink(delta_chain_link_t *ptr) : link(ptr) {} + + DeltaChainLink(const char *filename1, const char *filename2, + char *node, char *deltabasenode, char *delta) : + _filename1(filename1), _filename2(filename2), _node(node), + _delta(delta), _deltabasenode(deltabasenode) {} + + const uint8_t* deltabase_node() { + return link->deltabase_node; + } + + const char* filename() { + return link->filename; + } + + uint16_t filename_sz() { + return link->filename_sz; + } + + const uint8_t* delta() { + return link->delta; + } + + data_offset_t delta_sz() { + return link->delta_sz; + } + + bool isnull() { + return (link == NULL); + } + + const uint8_t* node() { + return link->node; + } +}; + +class DeltaChain { + public: + //C DeltaChain + delta_chain_t *chain; + + //Python DeltaChain + std::shared_ptr< std::vector > _links; + + DeltaChain(delta_chain_t *ptr) : chain(ptr) {} + + DeltaChain(delta_chain_t orig) { + chain = (delta_chain_t*)malloc(sizeof orig); + if (chain != NULL) { + memcpy(chain, &orig, sizeof orig); + } + } + + DeltaChain(get_delta_chain_code_t error) { + chain = new COMPOUND_LITERAL(delta_chain_t) { GET_DELTA_CHAIN_NOT_FOUND }; + } + + DeltaChain(std::shared_ptr< std::vector > links) : _links(links) {} + + ~DeltaChain() { + freedeltachain(*chain); + } + + const DeltaChainLink delta_chain_links(const size_t idx) { + return DeltaChainLink(&(chain->delta_chain_links[idx])); + } + + size_t links_count() { + return chain->links_count; + } + + get_delta_chain_code_t code() { + return chain->code; + } + +}; + +class DeltaChainIterator { + private: + size_t _index; + protected: + std::vector< std::shared_ptr > _chains; + DeltaChainIterator() : + _index(0) {} + virtual std::shared_ptr getNextChain(const Key &key) { + return std::make_shared(GET_DELTA_CHAIN_NOT_FOUND); + } + public: + DeltaChainIterator(std::shared_ptr chain) : + _index(0) { + _chains.push_back(chain); + } + + DeltaChainLink next() { + std::shared_ptr chain = _chains.back(); + + if (_index >= chain->links_count()) { + // If we're not at the end, and we have a callback to fetch more, do the + // fetch. + bool refreshed = false; + if (chain->links_count() > 0) { + //DeltaChainLink *result = &chain->delta_chain_links(_index - 1); + DeltaChainLink result = chain->delta_chain_links(_index - 1); + + const uint8_t *deltabasenode = result.deltabase_node(); + if (memcmp(deltabasenode, NULLID, BIN_NODE_SIZE) != 0) { + Key key(result.filename(), result.filename_sz(), + (const char*)deltabasenode, BIN_NODE_SIZE); + + std::shared_ptr newChain = this->getNextChain(key); + if (newChain->code() == GET_DELTA_CHAIN_OK) { + // Do not free the old chain, since the iterator consumer may + // still be holding references to it. + _chains.push_back(newChain); + chain = _chains.back(); + _index = 0; + refreshed = true; + } + //newChain is freed here together with underlying delta_chain_t + } + } + + if (!refreshed) { + return DeltaChainLink(NULL); + } + } + + DeltaChainLink result = chain->delta_chain_links(_index); + _index++; + + return result; + } +}; + +class DataStore { + protected: + DataStore() {} + + public: + virtual ~DataStore() {} + + virtual DeltaChainIterator getDeltaChain(const Key &key) = 0; + + virtual std::shared_ptr getDeltaChainRaw(const Key &key) = 0; + + virtual std::shared_ptr getMissing(KeyIterator &missing) = 0; + + virtual bool contains(const Key &key) = 0; + + virtual void markForRefresh() = 0; +}; + +#endif //DATASTORE_H diff --git a/cstore/key.h b/cstore/key.h --- a/cstore/key.h +++ b/cstore/key.h @@ -13,6 +13,7 @@ #include #include #include +#include #include "convert.h" #include "convert.h" @@ -29,6 +30,11 @@ Key() : node() {} + Key(const Key& other) { + name = other.name; + memcpy(node, other.node, BIN_NODE_SIZE); + } + Key(const char *name, size_t namelen, const char *node, size_t nodelen) : name(name, namelen) { if (nodelen != BIN_NODE_SIZE) { @@ -51,7 +57,7 @@ KeyIterator() {} public: virtual ~KeyIterator() = default; - virtual Key *next() = 0; + virtual std::shared_ptr next() = 0; }; #endif //KEY_H diff --git a/cstore/py-datapackstore.h b/cstore/py-datapackstore.h --- a/cstore/py-datapackstore.h +++ b/cstore/py-datapackstore.h @@ -19,6 +19,8 @@ } #include "pythonutil.h" +#include "pythondatastore.h" +#include "datastore.h" #include "datapackstore.h" #include "key.h" #include "py-structs.h" @@ -73,15 +75,14 @@ PythonObj resultChain = PyList_New(0); - delta_chain_link_t *link; size_t index = 0; - while ((link = chain.next()) != NULL) { - PythonObj name = PyString_FromStringAndSize(link->filename, link->filename_sz); - PythonObj retnode = PyString_FromStringAndSize((const char *) link->node, NODE_SZ); + for (DeltaChainLink link = chain.next(); !link.isnull(); link = chain.next()) { + PythonObj name = PyString_FromStringAndSize(link.filename(), link.filename_sz()); + PythonObj retnode = PyString_FromStringAndSize((const char *) link.node(), NODE_SZ); PythonObj deltabasenode = PyString_FromStringAndSize( - (const char *) link->deltabase_node, NODE_SZ); + (const char *) link.deltabase_node(), NODE_SZ); PythonObj delta = PyString_FromStringAndSize( - (const char *) link->delta, (Py_ssize_t) link->delta_sz); + (const char *) link.delta(), (Py_ssize_t) link.delta_sz()); PythonObj tuple = PyTuple_Pack(5, (PyObject*)name, (PyObject*)retnode, (PyObject*)name, (PyObject*)deltabasenode, @@ -109,12 +110,12 @@ class PythonKeyIterator : public KeyIterator { private: PythonObj _input; - Key _current; + std::shared_ptr _current; public: PythonKeyIterator(PythonObj input) : _input(input) {} - Key *next() { + std::shared_ptr next() { PyObject *item; while ((item = PyIter_Next((PyObject*)_input)) != NULL) { PythonObj itemObj = item; @@ -127,8 +128,8 @@ throw pyexception(); } - _current = Key(name, namelen, node, nodelen); - return &_current; + _current = std::make_shared(name, namelen, node, nodelen); + return _current; } return NULL; @@ -142,10 +143,10 @@ PythonObj inputIterator = PyObject_GetIter(keys); PythonKeyIterator keysIter(inputIterator); - DatapackStoreKeyIterator missingIter = self->datapackstore.getMissing(keysIter); + std::shared_ptr missingIter = self->datapackstore.getMissing(keysIter); - Key *key; - while ((key = missingIter.next()) != NULL) { + std::shared_ptr key; + while ((key = missingIter->next()) != NULL) { PythonObj missingKey = Py_BuildValue("(s#s#)", key->name.c_str(), key->name.size(), key->node, 20); if (PyList_Append(result, (PyObject*)missingKey)) { @@ -229,7 +230,7 @@ } try { - std::vector stores; + std::vector stores; std::vector pySubStores; PyObject *item; @@ -241,16 +242,14 @@ pySubStores.push_back(PythonObj(item)); int isinstance = PyObject_IsInstance(item, (PyObject*)&datapackstoreType); - if (isinstance == 0) { - PyErr_SetString(PyExc_RuntimeError, "cuniondatapackstore only accepts cdatapackstore"); - return -1; - } else if (isinstance != 1) { - // Error - return -1; + if (isinstance == 1) { + py_datapackstore *pySubStore = (py_datapackstore*)item; + stores.push_back(&pySubStore->datapackstore); + } else { + //else item is python data store object + PythonObj store(item); + stores.push_back(new PythonDataStore(store)); } - - py_datapackstore *pySubStore = (py_datapackstore*)item; - stores.push_back(&pySubStore->datapackstore); } // We have to manually call the member constructor, since the provided 'self' @@ -314,14 +313,13 @@ PythonObj resultChain = PyList_New(0); - delta_chain_link_t *link; - while ((link = chain.next()) != NULL) { - PythonObj name = PyString_FromStringAndSize(link->filename, link->filename_sz); - PythonObj retnode = PyString_FromStringAndSize((const char *) link->node, NODE_SZ); + for (DeltaChainLink link = chain.next(); !link.isnull(); link = chain.next()) { + PythonObj name = PyString_FromStringAndSize(link.filename(), link.filename_sz()); + PythonObj retnode = PyString_FromStringAndSize((const char *) link.node(), NODE_SZ); PythonObj deltabasenode = PyString_FromStringAndSize( - (const char *) link->deltabase_node, NODE_SZ); + (const char *) link.deltabase_node(), NODE_SZ); PythonObj delta = PyString_FromStringAndSize( - (const char *) link->delta, (Py_ssize_t) link->delta_sz); + (const char *) link.delta(), (Py_ssize_t) link.delta_sz()); PythonObj tuple = PyTuple_Pack(5, (PyObject*)name, (PyObject*)retnode, (PyObject*)name, (PyObject*)deltabasenode, @@ -353,7 +351,7 @@ UnionDatapackStoreKeyIterator missingIter = self->uniondatapackstore->getMissing(keysIter); - Key *key; + std::shared_ptr key; while ((key = missingIter.next()) != NULL) { PythonObj missingKey = Py_BuildValue("(s#s#)", key->name.c_str(), key->name.size(), key->node, 20); diff --git a/cstore/py-pythondatastore.h b/cstore/py-pythondatastore.h new file mode 100644 --- /dev/null +++ b/cstore/py-pythondatastore.h @@ -0,0 +1,88 @@ +// python implementation of a common interface +// +// Copyright 2017 Facebook, Inc. +// +// This software may be used and distributed according to the terms of the +// GNU General Public License version 2 or any later version. +// +// no-check-code + +// The PY_SSIZE_T_CLEAN define must be defined before the Python.h include, +// as per the documentation. + +#define PY_SSIZE_T_CLEAN +#include +#include +#include +#include + +#include "pythonutil.h" +#include "datastore.h" +#include "pythondatastore.h" +#include "key.h" + +/* + * Build python delta chain + */ +static std::shared_ptr pythonstore_getdeltachain(PythonObj &store, + const Key &key) { + + // Call getdeltachain method of the underlying store + PythonObj args(Py_BuildValue("ss", (key.name).c_str(), + std::string(key.node).c_str())); + + PythonObj list = store.callmethod("getdeltachain", args); + + // Extract the delta chain from the list of tuples + // and build a DeltaChain object from them + std::shared_ptr< std::vector > links = + std::make_shared< std::vector >(); + + PythonObj iter = PyObject_GetIter(list); + PyObject *tuple; + while ((tuple = PyIter_Next(iter)) != NULL) { + const char *filename1, *filename2; + char *node, *deltabasenode, *delta; + + int ok = PyArg_ParseTuple(tuple, "swsww", + &filename1, &node, &filename2, &deltabasenode, &delta); + + // the item is a five tuple + if (ok) { + links->push_back(DeltaChainLink(filename1, filename2, node, deltabasenode, delta)); + } + } + + return std::make_shared(links); +} + +/* + * Return a pointer to a KeyIterator + */ +static std::shared_ptr pythonstore_getmissing(PythonObj &store, KeyIterator &missing) { + + /* + * To implement: + * 1. Unfold missing iterator into a list of keys + * 2. Pass this list to the underlying python store + * 3. Get the list of keys and transform it into vector of Keys + * 4. Pass the vector to PythonDataStoreKeyIterator constructor + * 5. Return shared pointer to that Iterator + */ + + /* + * + * Or Use PythonKeyIterator + */ + + //return std::make_shared(); +} + + +/* + * Pass a markforrefreshcall + */ +static void pythonstore_markforrefresh(PythonObj &store) { + PythonObj args(Py_BuildValue("")); + store.callmethod("markforrefresh", args); +} diff --git a/cstore/pythondatastore.h b/cstore/pythondatastore.h new file mode 100644 --- /dev/null +++ b/cstore/pythondatastore.h @@ -0,0 +1,57 @@ +// pythondatastore.h - c++ declarations for a python data store +// +// Copyright 2017 Facebook, Inc. +// +// This software may be used and distributed according to the terms of the +// GNU General Public License version 2 or any later version. +// +// no-check-code + +#ifndef PYTHONDATASTORE_H +#define PYTHONDATASTORE_H + +//I Know I shouldnt include it here but I need PyObject to pass to constructor +#include + +#include +#include + +#include "datastore.h" +#include "pythonutil.h" +#include "key.h" + + +#include "portability/portability.h" + +class PythonDataStore; +class PythonDataStoreKeyIterator : public KeyIterator { + private: + std::shared_ptr< std::vector > _keys; + public: + PythonDataStoreKeyIterator(std::shared_ptr< std::vector > keys) : + _keys(keys) {} + + std::shared_ptr next(); +}; + +/* Manages access to a directory of datapack files. */ +class PythonDataStore : public DataStore { + private: + PythonObj _store; // there is a pointer to python object + public: + PythonDataStore(PythonObj store); + + ~PythonDataStore(); + + DeltaChainIterator getDeltaChain(const Key &key); + + std::shared_ptr getMissing(KeyIterator &missing); + + std::shared_ptr getDeltaChainRaw(const Key &key); + + bool contains(const Key &key); + + void markForRefresh(); +}; + +#endif //PYTHONDATASTORE_H diff --git a/cstore/pythondatastore.cpp b/cstore/pythondatastore.cpp new file mode 100644 --- /dev/null +++ b/cstore/pythondatastore.cpp @@ -0,0 +1,54 @@ +// pythondatastore.cpp - implementation of a python data store +// +// Copyright 2017 Facebook, Inc. +// +// This software may be used and distributed according to the terms of the +// GNU General Public License version 2 or any later version. +// +// no-check-code + +#include "pythondatastore.h" +#include "py-pythondatastore.h" + +PythonDataStore::PythonDataStore(PythonObj store) : _store(store) {} + +DeltaChainIterator PythonDataStore::getDeltaChain(const Key &key) { + std::shared_ptr chain = pythonstore_getdeltachain(_store, key); + return DeltaChainIterator(chain); +} + +std::shared_ptr PythonDataStore::getDeltaChainRaw(const Key &key) { + return pythonstore_getdeltachain(_store, key); +} + +std::shared_ptr PythonDataStore::getMissing(KeyIterator &missing) { + return pythonstore_getmissing(_store, missing); +} + +void PythonDataStore::markForRefresh() { + pythonstore_markforrefresh(_store); +} + +bool PythonDataStore::contains(const Key &key) { + + std::shared_ptr< std::vector > keys = + std::make_shared< std::vector >(); + keys->push_back(key); + + PythonDataStoreKeyIterator iter(keys); + + std::shared_ptr it = pythonstore_getmissing(_store, iter); + return (it->next() == NULL); +} + +//The method below has to be reimplemented +std::shared_ptr PythonDataStoreKeyIterator::next() { + if (_keys->empty()) { + return NULL; + } + + std::shared_ptr key = std::make_shared(_keys->back()); + _keys->pop_back(); + + return key; +} diff --git a/cstore/uniondatapackstore.h b/cstore/uniondatapackstore.h --- a/cstore/uniondatapackstore.h +++ b/cstore/uniondatapackstore.h @@ -33,14 +33,14 @@ _store(store), _missing(missing) {} - Key *next(); + std::shared_ptr next(); }; class UnionDeltaChainIterator: public DeltaChainIterator { private: UnionDatapackStore &_store; protected: - delta_chain_t getNextChain(const Key &key); + std::shared_ptr getNextChain(const Key &key); public: UnionDeltaChainIterator(UnionDatapackStore &store, const Key &key) : DeltaChainIterator(), @@ -51,9 +51,9 @@ class UnionDatapackStore : public Store { public: - std::vector _stores; + std::vector _stores; - UnionDatapackStore(std::vector stores); + UnionDatapackStore(std::vector stores); ~UnionDatapackStore(); diff --git a/cstore/uniondatapackstore.cpp b/cstore/uniondatapackstore.cpp --- a/cstore/uniondatapackstore.cpp +++ b/cstore/uniondatapackstore.cpp @@ -16,7 +16,7 @@ #include "mpatch.h" } -UnionDatapackStore::UnionDatapackStore(std::vector stores) : +UnionDatapackStore::UnionDatapackStore(std::vector stores) : _stores(stores) { } @@ -27,17 +27,17 @@ } mpatch_flist* getNextLink(void* container, ssize_t index) { - std::vector *links = (std::vector*)container; + std::vector *links = (std::vector*)container; if (index < 0 || (size_t)index >= links->size()) { return NULL; } - delta_chain_link_t *link = links->at(index); + DeltaChainLink link = links->at(index); struct mpatch_flist *res; - if ((mpatch_decode((const char*)link->delta, - (ssize_t)link->delta_sz, &res)) < 0) { + if ((mpatch_decode((const char*)link.delta(), + (ssize_t)link.delta_sz(), &res)) < 0) { throw std::logic_error("invalid patch during patch application"); } @@ -47,20 +47,19 @@ ConstantStringRef UnionDatapackStore::get(const Key &key) { UnionDeltaChainIterator chain = this->getDeltaChain(key); - std::vector links; + std::vector links; - delta_chain_link_t *link; - while ((link = chain.next()) != NULL) { + for (DeltaChainLink link = chain.next(); !link.isnull(); link = chain.next()) { links.push_back(link); } - delta_chain_link_t *fulltextLink = links.back(); + DeltaChainLink fulltextLink = links.back(); links.pop_back(); // Short circuit and just return the full text if it's one long if (links.size() == 0) { - return ConstantStringRef((const char*)fulltextLink->delta, - (size_t)fulltextLink->delta_sz); + return ConstantStringRef((const char*)fulltextLink.delta(), + (size_t)fulltextLink.delta_sz()); } std::reverse(links.begin(), links.end()); @@ -70,15 +69,15 @@ throw std::logic_error("mpatch failed to fold patches"); } - ssize_t outlen = mpatch_calcsize((ssize_t)fulltextLink->delta_sz, patch); + ssize_t outlen = mpatch_calcsize((ssize_t)fulltextLink.delta_sz(), patch); if (outlen < 0) { mpatch_lfree(patch); throw std::logic_error("mpatch failed to calculate size"); } auto result = std::make_shared(outlen, '\0'); - if (mpatch_apply(&(*result)[0], (const char*)fulltextLink->delta, - (ssize_t)fulltextLink->delta_sz, patch) < 0) { + if (mpatch_apply(&(*result)[0], (const char*)fulltextLink.delta(), + (ssize_t)fulltextLink.delta_sz(), patch) < 0) { mpatch_lfree(patch); throw std::logic_error("mpatch failed to apply patches"); } @@ -87,16 +86,17 @@ return ConstantStringRef(result); } -delta_chain_t UnionDeltaChainIterator::getNextChain(const Key &key) { - for(std::vector::iterator it = _store._stores.begin(); +std::shared_ptr UnionDeltaChainIterator::getNextChain(const Key &key) { + for(std::vector::iterator it = _store._stores.begin(); it != _store._stores.end(); it++) { - DatapackStore *substore = *it; - delta_chain_t chain = substore->getDeltaChainRaw(key); - if (chain.code == GET_DELTA_CHAIN_OK) { + DataStore *substore = *it; + std::shared_ptr chain = substore->getDeltaChainRaw(key); + + //if chain is delta_chain_t then performs this check + if (chain->code() == GET_DELTA_CHAIN_OK) { return chain; } - freedeltachain(chain); } throw MissingKeyError("unable to find delta chain"); @@ -106,8 +106,8 @@ return UnionDeltaChainIterator(*this, key); } -Key *UnionDatapackStoreKeyIterator::next() { - Key *key; +std::shared_ptr UnionDatapackStoreKeyIterator::next() { + std::shared_ptr key; while ((key = _missing.next()) != NULL) { if (!_store.contains(*key)) { return key; @@ -118,10 +118,10 @@ } bool UnionDatapackStore::contains(const Key &key) { - for(std::vector::iterator it = _stores.begin(); + for(std::vector::iterator it = _stores.begin(); it != _stores.end(); it++) { - DatapackStore *substore = *it; + DataStore *substore = *it; if (substore->contains(key)) { return true; } @@ -134,10 +134,10 @@ } void UnionDatapackStore::markForRefresh() { - for(std::vector::iterator it = _stores.begin(); + for(std::vector::iterator it = _stores.begin(); it != _stores.end(); it++) { - DatapackStore *substore = *it; + DataStore *substore = *it; substore->markForRefresh(); } } diff --git a/tests/test-check-code-hg.t b/tests/test-check-code-hg.t --- a/tests/test-check-code-hg.t +++ b/tests/test-check-code-hg.t @@ -59,6 +59,7 @@ Skipping clib/null_test.c it has no-che?k-code (glob) Skipping cstore/datapackstore.cpp it has no-che?k-code (glob) Skipping cstore/datapackstore.h it has no-che?k-code (glob) + Skipping cstore/datastore.h it has no-che?k-code (glob) Skipping cstore/key.h it has no-che?k-code (glob) Skipping cstore/match.h it has no-che?k-code (glob) Skipping cstore/py-cdatapack.h it has no-che?k-code (glob)