diff options
author | Jon Bratseth <bratseth@yahoo-inc.com> | 2016-06-15 23:09:44 +0200 |
---|---|---|
committer | Jon Bratseth <bratseth@yahoo-inc.com> | 2016-06-15 23:09:44 +0200 |
commit | 72231250ed81e10d66bfe70701e64fa5fe50f712 (patch) | |
tree | 2728bba1131a6f6e5bdf95afec7d7ff9358dac50 /searchcore/src/tests/proton/documentdb/buckethandler/buckethandler_test.cpp |
Publish
Diffstat (limited to 'searchcore/src/tests/proton/documentdb/buckethandler/buckethandler_test.cpp')
-rw-r--r-- | searchcore/src/tests/proton/documentdb/buckethandler/buckethandler_test.cpp | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/searchcore/src/tests/proton/documentdb/buckethandler/buckethandler_test.cpp b/searchcore/src/tests/proton/documentdb/buckethandler/buckethandler_test.cpp new file mode 100644 index 00000000000..f139bf92e44 --- /dev/null +++ b/searchcore/src/tests/proton/documentdb/buckethandler/buckethandler_test.cpp @@ -0,0 +1,265 @@ +// 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 <vespa/log/log.h> +LOG_SETUP("buckethandler_test"); +#include <vespa/searchcore/proton/server/buckethandler.h> +#include <vespa/searchcore/proton/server/ibucketstatechangedhandler.h> +#include <vespa/searchcore/proton/server/ibucketmodifiedhandler.h> +#include <vespa/searchcore/proton/test/test.h> +#include <vespa/vespalib/testkit/testapp.h> + +using namespace proton; +using document::BucketId; +using document::GlobalId; +using storage::spi::Bucket; +using storage::spi::BucketInfo; +using storage::spi::PartitionId; +using storage::spi::Timestamp; +using vespalib::ThreadStackExecutor; +using proton::test::BucketStateCalculator; + +const PartitionId PART_ID(0); +const GlobalId GID_1("111111111111"); +const BucketId BUCKET_1(8, GID_1.convertToBucketId().getRawId()); +const Timestamp TIME_1(1u); + +struct MySubDb +{ + DocumentMetaStore _metaStore; + test::UserDocuments _docs; + MySubDb(std::shared_ptr<BucketDBOwner> bucketDB, SubDbType subDbType) + : _metaStore(bucketDB, + DocumentMetaStore::getFixedName(), + search::GrowStrategy(), + documentmetastore::IGidCompare::SP( + new documentmetastore::DefaultGidCompare), + subDbType), + _docs() + { + } + void insertDocs(const test::UserDocuments &docs_) { + _docs = docs_; + for (test::UserDocuments::Iterator itr = _docs.begin(); itr != _docs.end(); ++itr) { + const test::BucketDocuments &bucketDocs = itr->second; + for (size_t i = 0; i < bucketDocs.getDocs().size(); ++i) { + const test::Document &testDoc = bucketDocs.getDocs()[i]; + _metaStore.put(testDoc.getGid(), testDoc.getBucket(), + testDoc.getTimestamp(), testDoc.getLid()); + } + } + } + BucketId bucket(uint32_t userId) { + return _docs.getBucket(userId); + } + test::DocumentVector docs(uint32_t userId) { + return _docs.getGidOrderDocs(userId); + } +}; + + +struct MyChangedHandler : public IBucketStateChangedHandler +{ + BucketId _bucket; + BucketInfo::ActiveState _state; + MyChangedHandler() : _bucket(), _state(BucketInfo::NOT_ACTIVE) {} + + virtual void notifyBucketStateChanged(const document::BucketId &bucketId, + storage::spi::BucketInfo::ActiveState newState) { + _bucket = bucketId; + _state = newState; + } +}; + + +struct MyModifiedHandler : public IBucketModifiedHandler +{ + virtual void + notifyBucketModified(const BucketId &bucket) + { + (void) bucket; + } +}; + + +bool +expectEqual(uint32_t docCount, uint32_t metaCount, const BucketInfo &info) +{ + if (!EXPECT_EQUAL(docCount, info.getDocumentCount())) return false; + if (!EXPECT_EQUAL(metaCount, info.getEntryCount())) return false; + if (!EXPECT_EQUAL(docCount, info.getDocumentSize())) return false; + if (!EXPECT_EQUAL(metaCount, info.getUsedSize())) return false; + return true; +} + + +struct Fixture +{ + test::UserDocumentsBuilder _builder; + std::shared_ptr<BucketDBOwner> _bucketDB; + MySubDb _ready; + MySubDb _removed; + MySubDb _notReady; + ThreadStackExecutor _exec; + BucketHandler _handler; + MyChangedHandler _changedHandler; + MyModifiedHandler _modifiedHandler; + BucketStateCalculator::SP _calc; + test::BucketIdListResultHandler _bucketList; + test::BucketInfoResultHandler _bucketInfo; + test::GenericResultHandler _genResult; + Fixture() + : _builder(), + _bucketDB(std::make_shared<BucketDBOwner>()), + _ready(_bucketDB, SubDbType::READY), + _removed(_bucketDB, SubDbType::REMOVED), + _notReady(_bucketDB, SubDbType::NOTREADY), + _exec(1, 64000), + _handler(_exec), + _changedHandler(), + _modifiedHandler(), + _calc(new BucketStateCalculator()), + _bucketList(), _bucketInfo(), _genResult() + { + // bucket 2 & 3 & 4 & 7 in ready + _ready.insertDocs(_builder.createDocs(2, 1, 3). // 2 docs + createDocs(3, 3, 6). // 3 docs + createDocs(4, 6, 10). // 4 docs + createDocs(7, 10, 11). // 1 doc + getDocs()); + // bucket 2 in removed + _removed.insertDocs(_builder.clearDocs(). + createDocs(2, 16, 20). // 4 docs + getDocs()); + // bucket 4 in not ready + _notReady.insertDocs(_builder.clearDocs(). + createDocs(4, 22, 24). // 2 docs + getDocs()); + _handler.setReadyBucketHandler(_ready._metaStore); + _handler.addBucketStateChangedHandler(&_changedHandler); + _handler.notifyClusterStateChanged(_calc); + } + ~Fixture() + { + _handler.removeBucketStateChangedHandler(&_changedHandler); + } + void sync() { _exec.sync(); } + void handleGetBucketInfo(const BucketId &bucket) { + _handler.handleGetBucketInfo(Bucket(bucket, PART_ID), _bucketInfo); + } + void + setNodeUp(bool value) + { + _calc->setNodeUp(value); + _handler.notifyClusterStateChanged(_calc); + } +}; + + +TEST_F("require that handleListBuckets() returns buckets from all sub dbs", Fixture) +{ + f._handler.handleListBuckets(f._bucketList); + EXPECT_EQUAL(4u, f._bucketList.getList().size()); + EXPECT_EQUAL(f._ready.bucket(2), f._bucketList.getList()[0]); + EXPECT_EQUAL(f._ready.bucket(3), f._bucketList.getList()[1]); + EXPECT_EQUAL(f._ready.bucket(4), f._bucketList.getList()[2]); + EXPECT_EQUAL(f._ready.bucket(7), f._bucketList.getList()[3]); + EXPECT_EQUAL(f._removed.bucket(2), f._bucketList.getList()[0]); + EXPECT_EQUAL(f._notReady.bucket(4), f._bucketList.getList()[2]); +} + + +TEST_F("require that bucket is reported in handleGetBucketInfo() and size faked", Fixture) +{ + f.handleGetBucketInfo(f._ready.bucket(3)); + EXPECT_TRUE(expectEqual(3, 3, f._bucketInfo.getInfo())); + + f.handleGetBucketInfo(f._ready.bucket(2)); // bucket 2 also in removed sub db + EXPECT_TRUE(expectEqual(2, 6, f._bucketInfo.getInfo())); +} + + +TEST_F("require that handleGetBucketInfo() can get cached bucket", Fixture) +{ + { + BucketDBOwner::Guard db = f._bucketDB->takeGuard(); + db->add(GID_1, BUCKET_1, TIME_1, SubDbType::READY); + db->cacheBucket(BUCKET_1); + db->add(GID_1, BUCKET_1, TIME_1, SubDbType::NOTREADY); + } + f.handleGetBucketInfo(BUCKET_1); + EXPECT_TRUE(expectEqual(1, 1, f._bucketInfo.getInfo())); + + f._bucketDB->takeGuard()->uncacheBucket(); + + f.handleGetBucketInfo(BUCKET_1); + EXPECT_TRUE(expectEqual(2, 2, f._bucketInfo.getInfo())); + { + // Must ensure empty bucket db before destruction. + BucketDBOwner::Guard db = f._bucketDB->takeGuard(); + db->remove(GID_1, BUCKET_1, TIME_1, SubDbType::READY); + db->remove(GID_1, BUCKET_1, TIME_1, SubDbType::NOTREADY); + } +} + + +TEST_F("require that changed handlers are notified when bucket state changes", Fixture) +{ + f._handler.handleSetCurrentState(f._ready.bucket(2), BucketInfo::ACTIVE, f._genResult); + f.sync(); + EXPECT_EQUAL(f._ready.bucket(2), f._changedHandler._bucket); + EXPECT_EQUAL(BucketInfo::ACTIVE, f._changedHandler._state); + f._handler.handleSetCurrentState(f._ready.bucket(3), BucketInfo::NOT_ACTIVE, f._genResult); + f.sync(); + EXPECT_EQUAL(f._ready.bucket(3), f._changedHandler._bucket); + EXPECT_EQUAL(BucketInfo::NOT_ACTIVE, f._changedHandler._state); +} + + +TEST_F("require that unready bucket can be reported as active", Fixture) +{ + f._handler.handleSetCurrentState(f._ready.bucket(4), + BucketInfo::ACTIVE, f._genResult); + f.sync(); + EXPECT_EQUAL(f._ready.bucket(4), f._changedHandler._bucket); + EXPECT_EQUAL(BucketInfo::ACTIVE, f._changedHandler._state); + f.handleGetBucketInfo(f._ready.bucket(4)); + EXPECT_EQUAL(true, f._bucketInfo.getInfo().isActive()); + EXPECT_EQUAL(false, f._bucketInfo.getInfo().isReady()); +} + + +TEST_F("require that node being down deactivates buckets", Fixture) +{ + f._handler.handleSetCurrentState(f._ready.bucket(2), + BucketInfo::ACTIVE, f._genResult); + f.sync(); + EXPECT_EQUAL(f._ready.bucket(2), f._changedHandler._bucket); + EXPECT_EQUAL(BucketInfo::ACTIVE, f._changedHandler._state); + f.handleGetBucketInfo(f._ready.bucket(2)); + EXPECT_EQUAL(true, f._bucketInfo.getInfo().isActive()); + f.setNodeUp(false); + f.sync(); + f.handleGetBucketInfo(f._ready.bucket(2)); + EXPECT_EQUAL(false, f._bucketInfo.getInfo().isActive()); + f._handler.handleSetCurrentState(f._ready.bucket(2), + BucketInfo::ACTIVE, f._genResult); + f.sync(); + f.handleGetBucketInfo(f._ready.bucket(2)); + EXPECT_EQUAL(false, f._bucketInfo.getInfo().isActive()); + f.setNodeUp(true); + f.sync(); + f.handleGetBucketInfo(f._ready.bucket(2)); + EXPECT_EQUAL(false, f._bucketInfo.getInfo().isActive()); + f._handler.handleSetCurrentState(f._ready.bucket(2), + BucketInfo::ACTIVE, f._genResult); + f.sync(); + f.handleGetBucketInfo(f._ready.bucket(2)); + EXPECT_EQUAL(true, f._bucketInfo.getInfo().isActive()); +} + + +TEST_MAIN() +{ + TEST_RUN_ALL(); +} + |