Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-77062

Perform copy-on-write of index catalog entries when cloning a collection

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • 7.1.0-rc0, 7.0.0-rc3
    • Affects Version/s: None
    • Component/s: None
    • None
    • Fully Compatible
    • ALL
    • v7.0
    • Execution Team 2023-05-29
    • 144

      The consequence is that other collection instances that have this IndexCatalogEntry can observe changes from other operations that make changes to the IndexCatalogEntry.

      TEST_F(CollectionCatalogTimestampTest, IndexCatalogEntryCopying) {
          const NamespaceString nss("test.abc");
          createCollection(opCtx.get(), nss, Timestamp::min());
          IndexCatalogEntry* entry;
          {
              // Start but do not finish an index build.
              IndexSpec spec;
              spec.version(1).name("x_1").addKeys(BSON("x" << 1));
              auto desc = std::make_unique<IndexDescriptor>(IndexNames::BTREE, spec.toBSON());
              AutoGetCollection autoColl(opCtx.get(), nss, MODE_X);
              WriteUnitOfWork wuow(opCtx.get());
              auto collWriter = autoColl.getWritableCollection(opCtx.get());
              ASSERT_OK(collWriter->prepareForIndexBuild(opCtx.get(), desc.get(), boost::none, false));
              entry = collWriter->getIndexCatalog()->createIndexEntry(
                  opCtx.get(), collWriter, std::move(desc), CreateIndexEntryFlags::kNone);
              wuow.commit();
          }
          // In a different client, open the latest collection instance of 'nss'
          auto newClient = opCtx->getServiceContext()->makeClient("alternativeClient");
          auto newOpCtx = newClient->makeOperationContext();
          auto latestCatalog = CollectionCatalog::latest(newOpCtx.get());
          auto latestColl =
              latestCatalog->establishConsistentCollection(newOpCtx.get(), nss, boost::none);
          ASSERT_EQ(1, latestColl->getIndexCatalog()->numIndexesTotal());
          ASSERT_EQ(0, latestColl->getIndexCatalog()->numIndexesReady());
          ASSERT_EQ(1, latestColl->getIndexCatalog()->numIndexesInProgress());
          // The index is NOT ready.
          auto descLatestBefore = latestColl->getIndexCatalog()->findIndexByName(
              newOpCtx.get(),
              "x_1",
              IndexCatalog::InclusionPolicy::kReady | IndexCatalog::InclusionPolicy::kFrozen |
                  IndexCatalog::InclusionPolicy::kUnfinished);
          auto entryLatestBefore = latestColl->getIndexCatalog()->getEntry(descLatestBefore);
          ASSERT(!entryLatestBefore->isReady());
          {
              // Now finish the index build on the original OperationContext.
              AutoGetCollection autoColl(opCtx.get(), nss, MODE_X);
              WriteUnitOfWork wuow(opCtx.get());
              auto collWriter = autoColl.getWritableCollection(opCtx.get());
              collWriter->getIndexCatalog()->indexBuildSuccess(opCtx.get(), collWriter, entry);
              wuow.commit();
          }
          // Container counts are still correct.
          ASSERT_EQ(1, latestColl->getIndexCatalog()->numIndexesTotal());
          ASSERT_EQ(0, latestColl->getIndexCatalog()->numIndexesReady());
          ASSERT_EQ(1, latestColl->getIndexCatalog()->numIndexesInProgress());
          // But the index is marked as ready now. When the collection clone happened above, it made a
          // copy of the containers, which is std::vector<std::shared_ptr<IndexCatalogEntry>> so we only
          // upped the ref count.
          auto descLatestAfter = latestColl->getIndexCatalog()->findIndexByName(
              newOpCtx.get(),
              "x_1",
              IndexCatalog::InclusionPolicy::kReady | IndexCatalog::InclusionPolicy::kFrozen |
                  IndexCatalog::InclusionPolicy::kUnfinished);
          auto entryLatestAfter = latestColl->getIndexCatalog()->getEntry(descLatestAfter);
          ASSERT(!entryLatestAfter->isReady());
      }
      

            Assignee:
            gregory.wlodarek@mongodb.com Gregory Wlodarek
            Reporter:
            gregory.wlodarek@mongodb.com Gregory Wlodarek
            Votes:
            0 Vote for this issue
            Watchers:
            7 Start watching this issue

              Created:
              Updated:
              Resolved: