aboutsummaryrefslogtreecommitdiffstats
path: root/storage/src/tests/persistence/common
diff options
context:
space:
mode:
authorArnstein Ressem <aressem@yahoo-inc.com>2016-10-12 17:49:54 +0200
committerArnstein Ressem <aressem@yahoo-inc.com>2016-10-12 17:49:54 +0200
commitc008b2dfcd0e231491a2093ab2b00b539efc79be (patch)
treec0b454f8e34993c7b838e34aa2688e2f6065b210 /storage/src/tests/persistence/common
parent56f449121b5b24353b36399842aa88f8a3deb055 (diff)
Finished with the storage dependency mess cleanup.
Diffstat (limited to 'storage/src/tests/persistence/common')
-rw-r--r--storage/src/tests/persistence/common/CMakeLists.txt9
-rw-r--r--storage/src/tests/persistence/common/filestortestfixture.cpp143
-rw-r--r--storage/src/tests/persistence/common/filestortestfixture.h112
-rw-r--r--storage/src/tests/persistence/common/persistenceproviderwrapper.cpp222
-rw-r--r--storage/src/tests/persistence/common/persistenceproviderwrapper.h153
5 files changed, 639 insertions, 0 deletions
diff --git a/storage/src/tests/persistence/common/CMakeLists.txt b/storage/src/tests/persistence/common/CMakeLists.txt
new file mode 100644
index 00000000000..561f516b8d1
--- /dev/null
+++ b/storage/src/tests/persistence/common/CMakeLists.txt
@@ -0,0 +1,9 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_library(storage_testpersistence_common TEST
+ SOURCES
+ persistenceproviderwrapper.cpp
+ filestortestfixture.cpp
+ DEPENDS
+ persistence
+ storage_testcommon
+)
diff --git a/storage/src/tests/persistence/common/filestortestfixture.cpp b/storage/src/tests/persistence/common/filestortestfixture.cpp
new file mode 100644
index 00000000000..8f7a95f53c8
--- /dev/null
+++ b/storage/src/tests/persistence/common/filestortestfixture.cpp
@@ -0,0 +1,143 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include <vespa/fastos/fastos.h>
+#include <sstream>
+#include <vespa/storage/persistence/messages.h>
+#include <vespa/storage/persistence/filestorage/filestormanager.h>
+#include <vespa/persistence/dummyimpl/dummypersistence.h>
+#include <tests/persistence/common/filestortestfixture.h>
+
+namespace storage {
+
+spi::LoadType FileStorTestFixture::defaultLoadType = spi::LoadType(0, "default");
+const uint32_t FileStorTestFixture::MSG_WAIT_TIME;
+
+void
+FileStorTestFixture::setupDisks(uint32_t diskCount)
+{
+ _config.reset(new vdstestlib::DirConfig(getStandardConfig(true)));
+
+ _config2.reset(new vdstestlib::DirConfig(*_config));
+ _config2->getConfig("stor-server").set("root_folder", "vdsroot.2");
+ _config2->getConfig("stor-devices").set("root_folder", "vdsroot.2");
+ _config2->getConfig("stor-server").set("node_index", "1");
+
+ _smallConfig.reset(new vdstestlib::DirConfig(*_config));
+ _node.reset(new TestServiceLayerApp(DiskCount(diskCount), NodeIndex(1),
+ _config->getConfigId()));
+ _testdoctype1 = _node->getTypeRepo()->getDocumentType("testdoctype1");
+}
+
+// Default provider setup which should work out of the box for most tests.
+void
+FileStorTestFixture::setUp()
+{
+ setupDisks(1);
+ _node->setPersistenceProvider(
+ spi::PersistenceProvider::UP(
+ new spi::dummy::DummyPersistence(_node->getTypeRepo(), 1)));
+}
+
+void
+FileStorTestFixture::tearDown()
+{
+ _node.reset(0);
+}
+
+void
+FileStorTestFixture::createBucket(const document::BucketId& bid)
+{
+ spi::Context context(defaultLoadType, spi::Priority(0),
+ spi::Trace::TraceLevel(0));
+ _node->getPersistenceProvider().createBucket(
+ spi::Bucket(bid, spi::PartitionId(0)), context);
+
+ StorBucketDatabase::WrappedEntry entry(
+ _node->getStorageBucketDatabase().get(bid, "foo",
+ StorBucketDatabase::CREATE_IF_NONEXISTING));
+ entry->disk = 0;
+ entry->info = api::BucketInfo(0, 0, 0, 0, 0, true, false);
+ entry.write();
+}
+
+bool
+FileStorTestFixture::bucketExistsInDb(const document::BucketId& bucket) const
+{
+ StorBucketDatabase::WrappedEntry entry(
+ _node->getStorageBucketDatabase().get(bucket, "bucketExistsInDb"));
+ return entry.exist();
+}
+
+FileStorTestFixture::TestFileStorComponents::TestFileStorComponents(
+ FileStorTestFixture& fixture,
+ const char* testName,
+ const StorageLinkInjector& injector)
+ : _testName(testName),
+ _fixture(fixture),
+ manager(new FileStorManager(fixture._config->getConfigId(),
+ fixture._node->getPartitions(),
+ fixture._node->getPersistenceProvider(),
+ fixture._node->getComponentRegister()))
+{
+ injector.inject(top);
+ top.push_back(StorageLink::UP(manager));
+ top.open();
+}
+
+api::StorageMessageAddress
+FileStorTestFixture::TestFileStorComponents::makeSelfAddress() const {
+ return api::StorageMessageAddress("storage", lib::NodeType::STORAGE, 0);
+}
+
+void
+FileStorTestFixture::TestFileStorComponents::sendDummyGet(
+ const document::BucketId& bid)
+{
+ std::ostringstream id;
+ id << "id:foo:testdoctype1:n=" << bid.getId() << ":0";
+ std::shared_ptr<api::GetCommand> cmd(
+ new api::GetCommand(bid, document::DocumentId(id.str()), "[all]"));
+ cmd->setAddress(makeSelfAddress());
+ cmd->setPriority(255);
+ top.sendDown(cmd);
+}
+
+void
+FileStorTestFixture::TestFileStorComponents::sendDummyGetDiff(
+ const document::BucketId& bid)
+{
+ std::vector<api::GetBucketDiffCommand::Node> nodes;
+ nodes.push_back(0);
+ nodes.push_back(1);
+ std::shared_ptr<api::GetBucketDiffCommand> cmd(
+ new api::GetBucketDiffCommand(bid, nodes, 12345));
+ cmd->setAddress(makeSelfAddress());
+ cmd->setPriority(255);
+ top.sendDown(cmd);
+}
+
+void
+FileStorTestFixture::TestFileStorComponents::sendPut(
+ const document::BucketId& bid,
+ uint32_t docIdx,
+ uint64_t timestamp)
+{
+ std::ostringstream id;
+ id << "id:foo:testdoctype1:n=" << bid.getId() << ":" << docIdx;
+ document::Document::SP doc(
+ _fixture._node->getTestDocMan().createDocument("foobar", id.str()));
+ std::shared_ptr<api::PutCommand> cmd(
+ new api::PutCommand(bid, doc, timestamp));
+ cmd->setAddress(makeSelfAddress());
+ top.sendDown(cmd);
+}
+
+void
+FileStorTestFixture::setClusterState(const std::string& state)
+{
+ _node->getStateUpdater().setClusterState(
+ lib::ClusterState::CSP(new lib::ClusterState(state)));
+}
+
+
+} // ns storage
diff --git a/storage/src/tests/persistence/common/filestortestfixture.h b/storage/src/tests/persistence/common/filestortestfixture.h
new file mode 100644
index 00000000000..4f1de549f47
--- /dev/null
+++ b/storage/src/tests/persistence/common/filestortestfixture.h
@@ -0,0 +1,112 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#pragma once
+
+#include <vespa/vdstestlib/cppunit/macros.h>
+#include <tests/common/testhelper.h>
+#include <vespa/persistence/spi/persistenceprovider.h>
+#include <vespa/storage/persistence/filestorage/filestormanager.h>
+#include <vespa/storageapi/message/persistence.h>
+#include <tests/common/dummystoragelink.h>
+#include <tests/common/teststorageapp.h>
+#include <tests/common/testhelper.h>
+
+namespace storage {
+
+class FileStorTestFixture : public CppUnit::TestFixture
+{
+public:
+ static spi::LoadType defaultLoadType;
+
+ std::unique_ptr<TestServiceLayerApp> _node;
+ std::unique_ptr<vdstestlib::DirConfig> _config;
+ std::unique_ptr<vdstestlib::DirConfig> _config2;
+ std::unique_ptr<vdstestlib::DirConfig> _smallConfig;
+ const document::DocumentType* _testdoctype1;
+
+ static const uint32_t MSG_WAIT_TIME = 60 * 1000;
+
+ typedef uint32_t DocumentIndex;
+ typedef uint64_t PutTimestamp;
+
+ void setUp() override;
+ void tearDown() override;
+ void setupDisks(uint32_t diskCount);
+ void createBucket(const document::BucketId& bid);
+ bool bucketExistsInDb(const document::BucketId& bucket) const;
+
+ api::ReturnCode::Result resultOf(const api::StorageReply& reply) const {
+ return reply.getResult().getResult();
+ }
+ void setClusterState(const std::string&);
+
+ struct StorageLinkInjector
+ {
+ virtual ~StorageLinkInjector() {}
+
+ virtual void inject(DummyStorageLink&) const = 0;
+ };
+
+ struct NoOpStorageLinkInjector : StorageLinkInjector
+ {
+ void inject(DummyStorageLink&) const {}
+ };
+
+ void
+ expectNoReplies(DummyStorageLink& link) {
+ CPPUNIT_ASSERT_EQUAL(size_t(0), link.getNumReplies());
+ }
+
+ template <typename ReplyType>
+ void
+ expectReply(DummyStorageLink& link,
+ api::ReturnCode::Result result)
+ {
+ link.waitForMessages(1, 60*1000);
+ api::StorageReply* reply(
+ dynamic_cast<ReplyType*>(link.getReply(0).get()));
+ if (reply == 0) {
+ std::ostringstream ss;
+ ss << "got unexpected reply "
+ << link.getReply(0)->toString(true);
+ CPPUNIT_FAIL(ss.str());
+ }
+ CPPUNIT_ASSERT_EQUAL(result, reply->getResult().getResult());
+ }
+
+ template <typename ReplyType>
+ void
+ expectAbortedReply(DummyStorageLink& link) {
+ expectReply<ReplyType>(link, api::ReturnCode::ABORTED);
+ }
+
+ template <typename ReplyType>
+ void
+ expectOkReply(DummyStorageLink& link) {
+ expectReply<ReplyType>(link, api::ReturnCode::OK);
+ }
+
+
+ struct TestFileStorComponents
+ {
+ private:
+ TestName _testName;
+ FileStorTestFixture& _fixture;
+ public:
+ DummyStorageLink top;
+ FileStorManager* manager;
+
+ TestFileStorComponents(FileStorTestFixture& fixture,
+ const char* testName,
+ const StorageLinkInjector& i = NoOpStorageLinkInjector());
+
+ api::StorageMessageAddress makeSelfAddress() const;
+
+ void sendDummyGet(const document::BucketId& bid);
+ void sendPut(const document::BucketId& bid,
+ uint32_t docIdx,
+ uint64_t timestamp);
+ void sendDummyGetDiff(const document::BucketId& bid);
+ };
+};
+
+} // ns storage
diff --git a/storage/src/tests/persistence/common/persistenceproviderwrapper.cpp b/storage/src/tests/persistence/common/persistenceproviderwrapper.cpp
new file mode 100644
index 00000000000..9ec66590b24
--- /dev/null
+++ b/storage/src/tests/persistence/common/persistenceproviderwrapper.cpp
@@ -0,0 +1,222 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <iostream>
+#include <sstream>
+#include <tests/persistence/common/persistenceproviderwrapper.h>
+
+#define LOG_SPI(ops) \
+ { \
+ std::ostringstream logStream; \
+ logStream << ops; \
+ _log.push_back(logStream.str()); \
+ }
+
+#define CHECK_ERROR(className, failType) \
+ { \
+ if (_result.getErrorCode() != spi::Result::NONE && (_failureMask & (failType))) { \
+ return className(_result.getErrorCode(), _result.getErrorMessage()); \
+ } \
+ }
+
+namespace storage {
+
+namespace {
+
+const char*
+includedVersionsToString(spi::IncludedVersions versions)
+{
+ switch (versions) {
+ case spi::NEWEST_DOCUMENT_ONLY:
+ return "NEWEST_DOCUMENT_ONLY";
+ case spi::NEWEST_DOCUMENT_OR_REMOVE:
+ return "NEWEST_DOCUMENT_OR_REMOVE";
+ case spi::ALL_VERSIONS:
+ return "ALL_VERSIONS";
+ }
+ return "!!UNKNOWN!!";
+}
+
+} // anon namespace
+
+std::string
+PersistenceProviderWrapper::toString() const
+{
+ std::ostringstream ss;
+ for (size_t i = 0; i < _log.size(); ++i) {
+ ss << _log[i] << "\n";
+ }
+ return ss.str();
+}
+
+spi::PartitionStateListResult
+PersistenceProviderWrapper::getPartitionStates() const
+{
+ LOG_SPI("getPartitionStates()");
+ return _spi.getPartitionStates();
+}
+
+spi::BucketIdListResult
+PersistenceProviderWrapper::listBuckets(spi::PartitionId partitionId) const
+{
+ LOG_SPI("listBuckets(" << uint16_t(partitionId) << ")");
+ CHECK_ERROR(spi::BucketIdListResult, FAIL_LIST_BUCKETS);
+ return _spi.listBuckets(partitionId);
+}
+
+spi::Result
+PersistenceProviderWrapper::createBucket(const spi::Bucket& bucket,
+ spi::Context& context)
+{
+ LOG_SPI("createBucket(" << bucket << ")");
+ CHECK_ERROR(spi::Result, FAIL_CREATE_BUCKET);
+ return _spi.createBucket(bucket, context);
+}
+
+spi::BucketInfoResult
+PersistenceProviderWrapper::getBucketInfo(const spi::Bucket& bucket) const
+{
+ LOG_SPI("getBucketInfo(" << bucket << ")");
+ CHECK_ERROR(spi::BucketInfoResult, FAIL_BUCKET_INFO);
+ return _spi.getBucketInfo(bucket);
+}
+
+spi::Result
+PersistenceProviderWrapper::put(const spi::Bucket& bucket,
+ spi::Timestamp timestamp,
+ const document::Document::SP& doc,
+ spi::Context& context)
+{
+ LOG_SPI("put(" << bucket << ", " << timestamp << ", " << doc->getId() << ")");
+ CHECK_ERROR(spi::Result, FAIL_PUT);
+ return _spi.put(bucket, timestamp, doc, context);
+}
+
+spi::RemoveResult
+PersistenceProviderWrapper::remove(const spi::Bucket& bucket,
+ spi::Timestamp timestamp,
+ const spi::DocumentId& id,
+ spi::Context& context)
+{
+ LOG_SPI("remove(" << bucket << ", " << timestamp << ", " << id << ")");
+ CHECK_ERROR(spi::RemoveResult, FAIL_REMOVE);
+ return _spi.remove(bucket, timestamp, id, context);
+}
+
+spi::RemoveResult
+PersistenceProviderWrapper::removeIfFound(const spi::Bucket& bucket,
+ spi::Timestamp timestamp,
+ const spi::DocumentId& id,
+ spi::Context& context)
+{
+ LOG_SPI("removeIfFound(" << bucket << ", " << timestamp << ", " << id << ")");
+ CHECK_ERROR(spi::RemoveResult, FAIL_REMOVE_IF_FOUND);
+ return _spi.removeIfFound(bucket, timestamp, id, context);
+}
+
+spi::UpdateResult
+PersistenceProviderWrapper::update(const spi::Bucket& bucket,
+ spi::Timestamp timestamp,
+ const document::DocumentUpdate::SP& upd,
+ spi::Context& context)
+{
+ LOG_SPI("update(" << bucket << ", " << timestamp << ", " << upd->getId() << ")");
+ CHECK_ERROR(spi::UpdateResult, FAIL_UPDATE);
+ return _spi.update(bucket, timestamp, upd, context);
+}
+
+spi::GetResult
+PersistenceProviderWrapper::get(const spi::Bucket& bucket,
+ const document::FieldSet& fieldSet,
+ const spi::DocumentId& id,
+ spi::Context& context) const
+{
+ LOG_SPI("get(" << bucket << ", " << id << ")");
+ CHECK_ERROR(spi::GetResult, FAIL_GET);
+ return _spi.get(bucket, fieldSet, id, context);
+}
+
+spi::Result
+PersistenceProviderWrapper::flush(const spi::Bucket& bucket,
+ spi::Context& context)
+{
+ LOG_SPI("flush(" << bucket << ")");
+ CHECK_ERROR(spi::Result, FAIL_FLUSH);
+ return _spi.flush(bucket, context);
+}
+
+spi::CreateIteratorResult
+PersistenceProviderWrapper::createIterator(const spi::Bucket& bucket,
+ const document::FieldSet& fields,
+ const spi::Selection& sel,
+ spi::IncludedVersions versions,
+ spi::Context& context)
+{
+ // TODO: proper printing of FieldSet and Selection
+
+ LOG_SPI("createIterator(" << bucket << ", "
+ << includedVersionsToString(versions) << ")");
+ CHECK_ERROR(spi::CreateIteratorResult, FAIL_CREATE_ITERATOR);
+ return _spi.createIterator(bucket, fields, sel, versions, context);
+}
+
+spi::IterateResult
+PersistenceProviderWrapper::iterate(spi::IteratorId iterId,
+ uint64_t maxByteSize,
+ spi::Context& context) const
+{
+ LOG_SPI("iterate(" << uint64_t(iterId) << ", " << maxByteSize << ")");
+ CHECK_ERROR(spi::IterateResult, FAIL_ITERATE);
+ return _spi.iterate(iterId, maxByteSize, context);
+}
+
+spi::Result
+PersistenceProviderWrapper::destroyIterator(spi::IteratorId iterId,
+ spi::Context& context)
+{
+ LOG_SPI("destroyIterator(" << uint64_t(iterId) << ")");
+ CHECK_ERROR(spi::Result, FAIL_DESTROY_ITERATOR);
+ return _spi.destroyIterator(iterId, context);
+}
+
+spi::Result
+PersistenceProviderWrapper::deleteBucket(const spi::Bucket& bucket,
+ spi::Context& context)
+{
+ LOG_SPI("deleteBucket(" << bucket << ")");
+ CHECK_ERROR(spi::Result, FAIL_DELETE_BUCKET);
+ return _spi.deleteBucket(bucket, context);
+}
+
+spi::Result
+PersistenceProviderWrapper::split(const spi::Bucket& source,
+ const spi::Bucket& target1,
+ const spi::Bucket& target2,
+ spi::Context& context)
+{
+ LOG_SPI("split(" << source << ", " << target1 << ", " << target2 << ")");
+ CHECK_ERROR(spi::Result, FAIL_SPLIT);
+ return _spi.split(source, target1, target2, context);
+}
+
+spi::Result
+PersistenceProviderWrapper::join(const spi::Bucket& source1,
+ const spi::Bucket& source2,
+ const spi::Bucket& target,
+ spi::Context& context)
+{
+ LOG_SPI("join(" << source1 << ", " << source2 << ", " << target << ")");
+ CHECK_ERROR(spi::Result, FAIL_JOIN);
+ return _spi.join(source1, source2, target, context);
+}
+
+spi::Result
+PersistenceProviderWrapper::removeEntry(const spi::Bucket& bucket,
+ spi::Timestamp timestamp,
+ spi::Context& context)
+{
+ LOG_SPI("revert(" << bucket << ", " << timestamp << ")");
+ CHECK_ERROR(spi::Result, FAIL_REVERT);
+ return _spi.removeEntry(bucket, timestamp, context);
+}
+
+}
diff --git a/storage/src/tests/persistence/common/persistenceproviderwrapper.h b/storage/src/tests/persistence/common/persistenceproviderwrapper.h
new file mode 100644
index 00000000000..b115eb7ef3d
--- /dev/null
+++ b/storage/src/tests/persistence/common/persistenceproviderwrapper.h
@@ -0,0 +1,153 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+/**
+ * \class storage::PersistenceProviderWrapper
+ *
+ * \brief Test utility class for intercepting all operations upon a
+ * persistence layer, injecting errors and performing logging.
+ *
+ * The PersistenceProviderWrapper class implements the basic SPI by
+ * logging all operations and then delegating handling the operation
+ * to the SPI instance given during construction. If an error result
+ * is specified and the operation invoked is tagged that it should be
+ * failed via setFailureMask(), the operation on the wrapped SPI will
+ * not be executed, but the given error result will be immediately
+ * returned instead (wrapped in the proper return type).
+ */
+#pragma once
+
+#include <vector>
+#include <string>
+#include <vespa/persistence/spi/abstractpersistenceprovider.h>
+
+namespace storage {
+
+class PersistenceProviderWrapper : public spi::AbstractPersistenceProvider
+{
+public:
+ enum OPERATION_FAILURE_FLAGS
+ {
+ FAIL_LIST_BUCKETS = 1 << 0,
+ FAIL_BUCKET_INFO = 1 << 1,
+ FAIL_GET = 1 << 2,
+ FAIL_PUT = 1 << 3,
+ FAIL_REMOVE = 1 << 4,
+ FAIL_REMOVE_IF_FOUND = 1 << 5,
+ FAIL_REPLACE_WITH_REMOVE = 1 << 6,
+ FAIL_UPDATE = 1 << 7,
+ FAIL_REVERT = 1 << 8,
+ FAIL_FLUSH = 1 << 9,
+ FAIL_CREATE_ITERATOR = 1 << 10,
+ FAIL_ITERATE = 1 << 11,
+ FAIL_DESTROY_ITERATOR = 1 << 12,
+ FAIL_DELETE_BUCKET = 1 << 13,
+ FAIL_SPLIT = 1 << 14,
+ FAIL_JOIN = 1 << 15,
+ FAIL_CREATE_BUCKET = 1 << 16,
+ FAIL_BUCKET_PERSISTENCE = FAIL_PUT|FAIL_REMOVE|FAIL_UPDATE|FAIL_REVERT|FAIL_FLUSH,
+ FAIL_ALL_OPERATIONS = 0xffff,
+ // TODO: add more as needed
+ };
+private:
+ spi::PersistenceProvider& _spi;
+ spi::Result _result;
+ mutable std::vector<std::string> _log;
+ uint32_t _failureMask;
+public:
+ PersistenceProviderWrapper(spi::PersistenceProvider& spi)
+ : _spi(spi),
+ _result(spi::Result(spi::Result::NONE, "")),
+ _log(),
+ _failureMask(0)
+ {
+ }
+
+ /**
+ * Explicitly set result to anything != NONE to have all operations
+ * return the given error without the wrapped SPI ever being invoked.
+ */
+ void setResult(const spi::Result& result) {
+ _result = result;
+ }
+ void clearResult() {
+ _result = spi::Result(spi::Result::NONE, "");
+ }
+ const spi::Result& getResult() const { return _result; }
+ /**
+ * Set a mask for operations to fail with _result
+ */
+ void setFailureMask(uint32_t mask) { _failureMask = mask; }
+ uint32_t getFailureMask() const { return _failureMask; }
+
+ /**
+ * Get a string representation of all the operations performed on the
+ * SPI with a newline separating each operation.
+ */
+ std::string toString() const;
+ /**
+ * Clear log of all operations performed.
+ */
+ void clearOperationLog() { _log.clear(); }
+ const std::vector<std::string>& getOperationLog() const { return _log; }
+
+ spi::Result createBucket(const spi::Bucket&, spi::Context&);
+
+ spi::PartitionStateListResult getPartitionStates() const;
+
+ spi::BucketIdListResult listBuckets(spi::PartitionId) const;
+
+ spi::BucketInfoResult getBucketInfo(const spi::Bucket&) const;
+
+ spi::Result put(const spi::Bucket&, spi::Timestamp, const document::Document::SP&, spi::Context&);
+
+ spi::RemoveResult remove(const spi::Bucket&,
+ spi::Timestamp,
+ const spi::DocumentId&,
+ spi::Context&);
+
+ spi::RemoveResult removeIfFound(const spi::Bucket&,
+ spi::Timestamp,
+ const spi::DocumentId&,
+ spi::Context&);
+
+ spi::UpdateResult update(const spi::Bucket&,
+ spi::Timestamp,
+ const document::DocumentUpdate::SP&,
+ spi::Context&);
+
+ spi::GetResult get(const spi::Bucket&,
+ const document::FieldSet&,
+ const spi::DocumentId&,
+ spi::Context&) const;
+
+ spi::Result flush(const spi::Bucket&, spi::Context&);
+
+ spi::CreateIteratorResult createIterator(const spi::Bucket&,
+ const document::FieldSet&,
+ const spi::Selection&,
+ spi::IncludedVersions versions,
+ spi::Context&);
+
+ spi::IterateResult iterate(spi::IteratorId,
+ uint64_t maxByteSize, spi::Context&) const;
+
+ spi::Result destroyIterator(spi::IteratorId, spi::Context&);
+
+ spi::Result deleteBucket(const spi::Bucket&, spi::Context&);
+
+ spi::Result split(const spi::Bucket& source,
+ const spi::Bucket& target1,
+ const spi::Bucket& target2,
+ spi::Context&);
+
+ spi::Result join(const spi::Bucket& source1,
+ const spi::Bucket& source2,
+ const spi::Bucket& target,
+ spi::Context&);
+
+ spi::Result removeEntry(const spi::Bucket&,
+ spi::Timestamp,
+ spi::Context&);
+};
+
+} // storage
+