MCPcopy Create free account
hub / github.com/LadybugDB/ladybug / checkpointInMemAndOnDisk

Method checkpointInMemAndOnDisk

src/storage/table/csr_node_group.cpp:516–579  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

514}
515
516void CSRNodeGroup::checkpointInMemAndOnDisk(const UniqLock& lock, NodeGroupCheckpointState& state) {
517 // TODO(Guodong): Should skip early here if no changes in the node group, so we avoid scanning
518 // the csr header. Case: No insertions/deletions in persistent chunk and no in-mem chunks.
519 auto& csrState = state.cast<CSRNodeGroupCheckpointState>();
520 // Scan old csr header from disk and construct new csr header.
521 persistentChunkGroup->cast<ChunkedCSRNodeGroup>().scanCSRHeader(*state.mm, csrState);
522 csrState.newHeader =
523 std::make_unique<InMemChunkedCSRHeader>(*state.mm, false, StorageConfig::NODE_GROUP_SIZE);
524 // TODO(Guodong): Find max node offset in the node group.
525 csrState.newHeader->setNumValues(StorageConfig::NODE_GROUP_SIZE);
526 csrState.newHeader->copyFrom(*csrState.oldHeader);
527 auto leafRegions = collectLeafRegionsAndCSRLength(lock, csrState);
528 DASSERT(std::is_sorted(leafRegions.begin(), leafRegions.end(),
529 [](const auto& a, const auto& b) { return a.regionIdx < b.regionIdx; }));
530 const auto regionsToCheckpoint = mergeRegionsToCheckpoint(csrState, leafRegions);
531 if (regionsToCheckpoint.empty()) {
532 // No csr regions need to be checkpointed, meaning nothing is updated or deleted.
533 // We should reset the version and update info of the persistent chunked group.
534 persistentChunkGroup->resetVersionAndUpdateInfo();
535 if (csrState.columnIDs.size() != persistentChunkGroup->getNumColumns()) {
536 // The column set of the node group has changed. We need to re-create the persistent
537 // chunked group.
538 persistentChunkGroup = createNewPersistentChunkGroup(
539 persistentChunkGroup->cast<ChunkedCSRNodeGroup>(), csrState);
540 }
541 return;
542 }
543 if (regionsToCheckpoint.size() == 1 &&
544 regionsToCheckpoint[0].level > DEFAULT_PACKED_CSR_INFO.calibratorTreeHeight) {
545 // Need to re-distribute all CSR regions in the node group.
546 redistributeCSRRegions(csrState, leafRegions);
547 } else {
548 for (auto& region : regionsToCheckpoint) {
549 csrState.newHeader->populateRegionCSROffsets(region, *csrState.oldHeader);
550 // The left node offset of a region should always maintain stable across length and
551 // offset changes.
552 DASSERT(csrState.oldHeader->getStartCSROffset(region.leftNodeOffset) ==
553 csrState.newHeader->getStartCSROffset(region.leftNodeOffset));
554 }
555 }
556
557 // Count tuples across ALL node offsets, not just the regions being checkpointed.
558 // A region may have no changes (so it is not in regionsToCheckpoint) yet still hold tuples.
559 // If we only count tuples in regionsToCheckpoint we may incorrectly conclude that the node
560 // group is empty and set persistentChunkGroup to nullptr, losing those untouched tuples.
561 uint64_t numTuplesAfterCheckpoint = 0;
562 const auto numNodeOffsets = csrState.newHeader->length->getNumValues();
563 for (auto i = 0u; i < numNodeOffsets; ++i) {
564 numTuplesAfterCheckpoint += csrState.newHeader->getCSRLength(i);
565 }
566 if (numTuplesAfterCheckpoint == 0) {
567 reclaimStorage(csrState.pageAllocator, lock);
568 persistentChunkGroup = nullptr;
569 } else {
570 DASSERT(csrState.newHeader->sanityCheck());
571 for (const auto columnID : csrState.columnIDs) {
572 checkpointColumn(lock, columnID, csrState, regionsToCheckpoint);
573 }

Callers

nothing calls this directly

Calls 15

reclaimStorageFunction · 0.85
scanCSRHeaderMethod · 0.80
getStartCSROffsetMethod · 0.80
getCSRLengthMethod · 0.80
setNumValuesMethod · 0.45
copyFromMethod · 0.45
beginMethod · 0.45
endMethod · 0.45
emptyMethod · 0.45

Tested by

no test coverage detected