summaryrefslogtreecommitdiff
path: root/src/mongo/db/index
diff options
context:
space:
mode:
authorJustin Seyster <justin.seyster@mongodb.com>2022-08-11 20:37:34 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-08-11 21:18:11 +0000
commit850596a5f30f7c18ac5fde21270db302951adcfd (patch)
tree69353d9e8f94a1e4bf86e85de1f863b8c0e65f01 /src/mongo/db/index
parentb9b5671845d2d91a7713b7d630749621e221ec12 (diff)
downloadmongo-850596a5f30f7c18ac5fde21270db302951adcfd.tar.gz
SERVER-68658 Unit test fixture for IndexBuildInterceptor
Diffstat (limited to 'src/mongo/db/index')
-rw-r--r--src/mongo/db/index/SConscript4
-rw-r--r--src/mongo/db/index/index_build_interceptor.cpp5
-rw-r--r--src/mongo/db/index/index_build_interceptor.h6
-rw-r--r--src/mongo/db/index/index_build_interceptor_test.cpp122
-rw-r--r--src/mongo/db/index/skipped_record_tracker.cpp4
-rw-r--r--src/mongo/db/index/skipped_record_tracker.h6
6 files changed, 137 insertions, 10 deletions
diff --git a/src/mongo/db/index/SConscript b/src/mongo/db/index/SConscript
index 56ddcb682c1..484b9e4dec6 100644
--- a/src/mongo/db/index/SConscript
+++ b/src/mongo/db/index/SConscript
@@ -177,14 +177,18 @@ indexTestEnv.CppUnitTest(
'column_key_generator_test.cpp',
'column_store_sorter_test.cpp',
'hash_key_generator_test.cpp',
+ 'index_build_interceptor_test.cpp',
's2_key_generator_test.cpp',
's2_bucket_key_generator_test.cpp',
'sort_key_generator_test.cpp',
'wildcard_key_generator_test.cpp',
],
LIBDEPS=[
+ '$BUILD_DIR/mongo/db/catalog/catalog_test_fixture',
+ '$BUILD_DIR/mongo/db/catalog_raii',
'$BUILD_DIR/mongo/db/exec/document_value/document_value_test_util',
'$BUILD_DIR/mongo/db/exec/working_set',
+ '$BUILD_DIR/mongo/db/index/index_access_method',
'$BUILD_DIR/mongo/db/matcher/expressions',
'$BUILD_DIR/mongo/db/mongohasher',
'$BUILD_DIR/mongo/db/query/collation/collator_interface_mock',
diff --git a/src/mongo/db/index/index_build_interceptor.cpp b/src/mongo/db/index/index_build_interceptor.cpp
index 59f8c7d1d6f..36072c25bf5 100644
--- a/src/mongo/db/index/index_build_interceptor.cpp
+++ b/src/mongo/db/index/index_build_interceptor.cpp
@@ -59,7 +59,8 @@ MONGO_FAIL_POINT_DEFINE(hangDuringIndexBuildDrainYieldSecond);
MONGO_FAIL_POINT_DEFINE(hangIndexBuildDuringDrainWritesPhase);
MONGO_FAIL_POINT_DEFINE(hangIndexBuildDuringDrainWritesPhaseSecond);
-IndexBuildInterceptor::IndexBuildInterceptor(OperationContext* opCtx, IndexCatalogEntry* entry)
+IndexBuildInterceptor::IndexBuildInterceptor(OperationContext* opCtx,
+ const IndexCatalogEntry* entry)
: _indexCatalogEntry(entry),
_sideWritesTable(opCtx->getServiceContext()->getStorageEngine()->makeTemporaryRecordStore(
opCtx, KeyFormat::Long)),
@@ -71,7 +72,7 @@ IndexBuildInterceptor::IndexBuildInterceptor(OperationContext* opCtx, IndexCatal
}
IndexBuildInterceptor::IndexBuildInterceptor(OperationContext* opCtx,
- IndexCatalogEntry* entry,
+ const IndexCatalogEntry* entry,
StringData sideWritesIdent,
boost::optional<StringData> duplicateKeyTrackerIdent,
boost::optional<StringData> skippedRecordTrackerIdent)
diff --git a/src/mongo/db/index/index_build_interceptor.h b/src/mongo/db/index/index_build_interceptor.h
index 07eb25cdba3..46c4f5e6e8b 100644
--- a/src/mongo/db/index/index_build_interceptor.h
+++ b/src/mongo/db/index/index_build_interceptor.h
@@ -67,7 +67,7 @@ public:
* table to store any duplicate key constraint violations found during the build, if the index
* being built has uniqueness constraints.
*/
- IndexBuildInterceptor(OperationContext* opCtx, IndexCatalogEntry* entry);
+ IndexBuildInterceptor(OperationContext* opCtx, const IndexCatalogEntry* entry);
/**
* Finds the temporary table associated with storing writes during this index build. Only used
@@ -76,7 +76,7 @@ public:
* violations found during the build, if the index being built has uniqueness constraints.
*/
IndexBuildInterceptor(OperationContext* opCtx,
- IndexCatalogEntry* entry,
+ const IndexCatalogEntry* entry,
StringData sideWritesIdent,
boost::optional<StringData> duplicateKeyTrackerIdent,
boost::optional<StringData> skippedRecordTrackerIdent);
@@ -194,7 +194,7 @@ private:
long long iteration) const;
// The entry for the index that is being built.
- IndexCatalogEntry* _indexCatalogEntry;
+ const IndexCatalogEntry* _indexCatalogEntry;
// This temporary record store records intercepted keys that will be written into the index by
// calling drainWritesIntoIndex(). It is owned by the interceptor and dropped along with it.
diff --git a/src/mongo/db/index/index_build_interceptor_test.cpp b/src/mongo/db/index/index_build_interceptor_test.cpp
new file mode 100644
index 00000000000..30f996d69d2
--- /dev/null
+++ b/src/mongo/db/index/index_build_interceptor_test.cpp
@@ -0,0 +1,122 @@
+/**
+ * Copyright (C) 2022-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program 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
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#include "mongo/db/catalog/catalog_test_fixture.h"
+#include "mongo/db/catalog_raii.h"
+#include "mongo/db/index/index_build_interceptor.h"
+
+namespace mongo {
+namespace {
+class IndexBuilderInterceptorTest : public CatalogTestFixture {
+protected:
+ const IndexCatalogEntry* createIndex(BSONObj spec) {
+ WriteUnitOfWork wuow(operationContext());
+ auto* indexCatalog = _coll->getWritableCollection(operationContext())->getIndexCatalog();
+ uassertStatusOK(indexCatalog->createIndexOnEmptyCollection(
+ operationContext(), _coll->getWritableCollection(operationContext()), spec));
+ wuow.commit();
+
+ return indexCatalog->getEntry(indexCatalog->findIndexByName(
+ operationContext(), spec.getStringField(IndexDescriptor::kIndexNameFieldName)));
+ }
+
+ std::unique_ptr<IndexBuildInterceptor> createIndexBuildInterceptor(BSONObj spec) {
+ return std::make_unique<IndexBuildInterceptor>(operationContext(),
+ createIndex(std::move(spec)));
+ }
+
+ std::unique_ptr<TemporaryRecordStore> getSideWritesTable(
+ std::unique_ptr<IndexBuildInterceptor> interceptor) {
+ // In order to get access to the interceptor's side writes table, we have to mark the table
+ // as permanent and then destroy the interceptor.
+ interceptor->keepTemporaryTables();
+ auto sideWritesIdent = interceptor->getSideWritesTableIdent();
+ interceptor.reset();
+
+ return operationContext()
+ ->getServiceContext()
+ ->getStorageEngine()
+ ->makeTemporaryRecordStoreFromExistingIdent(operationContext(), sideWritesIdent);
+ }
+
+ std::vector<BSONObj> getSideWritesTableContents(
+ std::unique_ptr<IndexBuildInterceptor> interceptor) {
+ auto table = getSideWritesTable(std::move(interceptor));
+
+ std::vector<BSONObj> contents;
+ auto cursor = table->rs()->getCursor(operationContext());
+ while (auto record = cursor->next()) {
+ contents.push_back(record->data.toBson().getOwned());
+ }
+ return contents;
+ }
+
+ void setUp() override {
+ CatalogTestFixture::setUp();
+ ASSERT_OK(storageInterface()->createCollection(operationContext(), _nss, {}));
+ _coll.emplace(operationContext(), _nss, MODE_X);
+ }
+
+ void tearDown() override {
+ _coll.reset();
+ CatalogTestFixture::tearDown();
+ }
+
+private:
+ NamespaceString _nss{"testDB.interceptor"};
+ boost::optional<AutoGetCollection> _coll;
+};
+
+TEST_F(IndexBuilderInterceptorTest, SingleInsertIsSavedToSideWritesTable) {
+ auto interceptor = createIndexBuildInterceptor(fromjson("{v: 2, name: 'a_1', key: {a: 1}}"));
+
+ KeyString::HeapBuilder ksBuilder(KeyString::Version::kLatestVersion);
+ ksBuilder.appendNumberLong(10);
+ KeyString::Value keyString(ksBuilder.release());
+
+ WriteUnitOfWork wuow(operationContext());
+ int64_t numKeys = 0;
+ ASSERT_OK(interceptor->sideWrite(
+ operationContext(), {keyString}, {}, {}, IndexBuildInterceptor::Op::kInsert, &numKeys));
+ ASSERT_EQ(1, numKeys);
+ wuow.commit();
+
+ BufBuilder bufBuilder;
+ keyString.serialize(bufBuilder);
+ BSONBinData serializedKeyString(bufBuilder.buf(), bufBuilder.len(), BinDataGeneral);
+
+ auto sideWrites = getSideWritesTableContents(std::move(interceptor));
+ ASSERT_EQ(1, sideWrites.size());
+ ASSERT_BSONOBJ_EQ(BSON("op"
+ << "i"
+ << "key" << serializedKeyString),
+ sideWrites[0]);
+}
+} // namespace
+} // namespace mongo
diff --git a/src/mongo/db/index/skipped_record_tracker.cpp b/src/mongo/db/index/skipped_record_tracker.cpp
index f5cf3e44e79..7e21c6202cd 100644
--- a/src/mongo/db/index/skipped_record_tracker.cpp
+++ b/src/mongo/db/index/skipped_record_tracker.cpp
@@ -46,11 +46,11 @@ namespace {
static constexpr StringData kRecordIdField = "recordId"_sd;
}
-SkippedRecordTracker::SkippedRecordTracker(IndexCatalogEntry* indexCatalogEntry)
+SkippedRecordTracker::SkippedRecordTracker(const IndexCatalogEntry* indexCatalogEntry)
: SkippedRecordTracker(nullptr, indexCatalogEntry, boost::none) {}
SkippedRecordTracker::SkippedRecordTracker(OperationContext* opCtx,
- IndexCatalogEntry* indexCatalogEntry,
+ const IndexCatalogEntry* indexCatalogEntry,
boost::optional<StringData> ident)
: _indexCatalogEntry(indexCatalogEntry) {
if (!ident) {
diff --git a/src/mongo/db/index/skipped_record_tracker.h b/src/mongo/db/index/skipped_record_tracker.h
index fecdf868ded..61cda65a47f 100644
--- a/src/mongo/db/index/skipped_record_tracker.h
+++ b/src/mongo/db/index/skipped_record_tracker.h
@@ -46,9 +46,9 @@ class SkippedRecordTracker {
SkippedRecordTracker(const SkippedRecordTracker&) = delete;
public:
- explicit SkippedRecordTracker(IndexCatalogEntry* indexCatalogEntry);
+ explicit SkippedRecordTracker(const IndexCatalogEntry* indexCatalogEntry);
SkippedRecordTracker(OperationContext* opCtx,
- IndexCatalogEntry* indexCatalogEntry,
+ const IndexCatalogEntry* indexCatalogEntry,
boost::optional<StringData> ident);
/**
@@ -85,7 +85,7 @@ public:
}
private:
- IndexCatalogEntry* _indexCatalogEntry;
+ const IndexCatalogEntry* _indexCatalogEntry;
// This temporary record store is owned by the duplicate key tracker.
std::unique_ptr<TemporaryRecordStore> _skippedRecordsTable;