aboutsummaryrefslogtreecommitdiffstats
path: root/storage/src/tests/bucketdb/lockablemaptest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'storage/src/tests/bucketdb/lockablemaptest.cpp')
-rw-r--r--storage/src/tests/bucketdb/lockablemaptest.cpp82
1 files changed, 68 insertions, 14 deletions
diff --git a/storage/src/tests/bucketdb/lockablemaptest.cpp b/storage/src/tests/bucketdb/lockablemaptest.cpp
index c5d22b6e6b5..709e158e531 100644
--- a/storage/src/tests/bucketdb/lockablemaptest.cpp
+++ b/storage/src/tests/bucketdb/lockablemaptest.cpp
@@ -6,6 +6,7 @@
#include <vespa/storage/bucketdb/lockablemap.hpp>
#include <vespa/storage/bucketdb/btree_lockable_map.hpp>
#include <vespa/vespalib/gtest/gtest.h>
+#include <gmock/gmock.h>
#include <vespa/log/log.h>
LOG_SETUP(".lockable_map_test");
@@ -200,13 +201,23 @@ EntryProcessor<Map>::~EntryProcessor() = default;
template <typename Map>
struct ConstProcessor {
+ mutable uint32_t count;
mutable std::vector<std::string> log;
+ mutable std::vector<typename Map::Decision> behaviour;
+
+ ConstProcessor();
+ explicit ConstProcessor(std::vector<typename Map::Decision> decisions);
+ ~ConstProcessor();
typename Map::Decision operator()(uint64_t key, const A& a) const {
std::ostringstream ost;
ost << key << " - " << a;
log.push_back(ost.str());
- return Map::CONTINUE;
+ auto d = Map::Decision::CONTINUE;
+ if (behaviour.size() > count) {
+ d = behaviour[count++];
+ }
+ return d;
}
std::string toString() {
@@ -218,6 +229,17 @@ struct ConstProcessor {
}
};
+template <typename Map>
+ConstProcessor<Map>::ConstProcessor()
+ : count(0), log(), behaviour() {}
+
+template <typename Map>
+ConstProcessor<Map>::ConstProcessor(std::vector<typename Map::Decision> decisions)
+ : count(0), log(), behaviour(std::move(decisions)) {}
+
+template <typename Map>
+ConstProcessor<Map>::~ConstProcessor() = default;
+
}
TYPED_TEST(LockableMapTest, iterating) {
@@ -300,17 +322,21 @@ TYPED_TEST(LockableMapTest, chunked_iteration_is_transparent_across_chunk_sizes)
map.insert(16, A(1, 2, 3), "foo", preExisted);
map.insert(11, A(4, 6, 0), "foo", preExisted);
map.insert(14, A(42, 0, 0), "foo", preExisted);
- NonConstProcessor<TypeParam> ncproc; // Increments 2nd value in all entries.
- // for_each_chunked with chunk size of 1
- map.for_each_chunked(std::ref(ncproc), "foo", 1us, 1);
- EXPECT_EQ(A(4, 7, 0), *map.get(11, "foo"));
- EXPECT_EQ(A(42, 1, 0), *map.get(14, "foo"));
- EXPECT_EQ(A(1, 3, 3), *map.get(16, "foo"));
- // for_each_chunked with chunk size larger than db size
- map.for_each_chunked(std::ref(ncproc), "foo", 1us, 100);
- EXPECT_EQ(A(4, 8, 0), *map.get(11, "foo"));
- EXPECT_EQ(A(42, 2, 0), *map.get(14, "foo"));
- EXPECT_EQ(A(1, 4, 3), *map.get(16, "foo"));
+ std::string expected("11 - A(4, 6, 0)\n"
+ "14 - A(42, 0, 0)\n"
+ "16 - A(1, 2, 3)\n");
+ {
+ ConstProcessor<TypeParam> cproc;
+ // for_each_chunked with chunk size of 1
+ map.for_each_chunked(std::ref(cproc), "foo", 1us, 1);
+ EXPECT_EQ(expected, cproc.toString());
+ }
+ {
+ ConstProcessor<TypeParam> cproc;
+ // for_each_chunked with chunk size larger than db size
+ map.for_each_chunked(std::ref(cproc), "foo", 1us, 100);
+ EXPECT_EQ(expected, cproc.toString());
+ }
}
TYPED_TEST(LockableMapTest, can_abort_during_chunked_iteration) {
@@ -323,13 +349,29 @@ TYPED_TEST(LockableMapTest, can_abort_during_chunked_iteration) {
std::vector<typename TypeParam::Decision> decisions;
decisions.push_back(TypeParam::CONTINUE);
decisions.push_back(TypeParam::ABORT);
- EntryProcessor<TypeParam> proc(decisions);
+ ConstProcessor<TypeParam> proc(std::move(decisions));
map.for_each_chunked(std::ref(proc), "foo", 1us, 100);
std::string expected("11 - A(4, 6, 0)\n"
- "14 - A(42, 0, 0)\n");
+ "14 - A(42, 0, 0)\n");
EXPECT_EQ(expected, proc.toString());
}
+TYPED_TEST(LockableMapTest, can_iterate_via_read_guard) {
+ TypeParam map;
+ bool pre_existed;
+ map.insert(16, A(1, 2, 3), "foo", pre_existed);
+ map.insert(11, A(4, 6, 0), "foo", pre_existed);
+ map.insert(14, A(42, 0, 0), "foo", pre_existed);
+ std::string expected("11 - A(4, 6, 0)\n"
+ "14 - A(42, 0, 0)\n"
+ "16 - A(1, 2, 3)\n");
+
+ ConstProcessor<TypeParam> cproc;
+ auto guard = map.acquire_read_guard();
+ guard->for_each(std::ref(cproc));
+ EXPECT_EQ(expected, cproc.toString());
+}
+
TYPED_TEST(LockableMapTest, find_buckets_simple) {
TypeParam map;
@@ -509,6 +551,18 @@ TYPED_TEST(LockableMapTest, find_all) {
EXPECT_EQ(1, results.size());
EXPECT_EQ(A(9,10,11), *results[id9.stripUnused()]); // sub bucket
+
+ // Make sure we clear any existing bucket locks before we continue, or test will deadlock
+ // if running with legacy (non-snapshot capable) DB implementation.
+ results.clear();
+ // Results should be equal when using read guard
+ auto guard = map.acquire_read_guard();
+
+ auto guard_results = guard->find_parents_self_and_children(BucketId(17, 0x1aaaa));
+ EXPECT_THAT(guard_results, ElementsAre(A(1,2,3), A(5,6,7), A(6,7,8), A(7,8,9)));
+
+ guard_results = guard->find_parents_self_and_children(BucketId(16, 0xffff));
+ EXPECT_THAT(guard_results, ElementsAre(A(9,10,11)));
}
TYPED_TEST(LockableMapTest, find_all_2) { // Ticket 3121525