| 125 | } |
| 126 | |
| 127 | PageRange Checkpointer::serializeMetadata(const catalog::Catalog& catalog, |
| 128 | StorageManager& storageManager) { |
| 129 | auto metadataWriter = |
| 130 | std::make_shared<common::InMemFileWriter>(*MemoryManager::Get(clientContext)); |
| 131 | common::Serializer metadataSerializer(metadataWriter); |
| 132 | storageManager.serialize(catalog, metadataSerializer); |
| 133 | |
| 134 | // We need to preallocate the pages for the page manager before we actually serialize it, |
| 135 | // this is because the page manager needs to track the pages used for itself. |
| 136 | // The number of pages needed for the page manager should only decrease after making an |
| 137 | // additional allocation, so we just calculate the number of pages needed to serialize the |
| 138 | // current state of the page manager. |
| 139 | // Thus, it is possible that we allocate an extra page that we won't end up writing to when we |
| 140 | // flush the metadata writer. This may cause a discrepancy between the number of tracked pages |
| 141 | // and the number of physical pages in the file but shouldn't cause any actual incorrect |
| 142 | // behavior in the database. |
| 143 | auto& pageManager = *storageManager.getDataFH()->getPageManager(); |
| 144 | const auto pagesForPageManager = pageManager.estimatePagesNeededForSerialize(); |
| 145 | auto pageAllocator = storageManager.getDataFH()->getPageManager(); |
| 146 | const auto allocatedPages = pageAllocator->allocatePageRange( |
| 147 | metadataWriter->getNumPagesToFlush() + pagesForPageManager); |
| 148 | pageManager.serialize(metadataSerializer); |
| 149 | |
| 150 | metadataWriter->flush(allocatedPages, pageAllocator->getDataFH(), |
| 151 | storageManager.getShadowFile()); |
| 152 | return allocatedPages; |
| 153 | } |
| 154 | |
| 155 | void Checkpointer::writeCheckpoint() { |
| 156 | if (isInMemory) { |
nothing calls this directly
no test coverage detected