duckdb 0.8.2-dev2669.0 → 0.8.2-dev2700.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/binding.gyp +1 -0
  2. package/package.json +1 -1
  3. package/src/duckdb/src/catalog/catalog_entry/duck_table_entry.cpp +6 -6
  4. package/src/duckdb/src/common/field_writer.cpp +1 -0
  5. package/src/duckdb/src/common/local_file_system.cpp +5 -0
  6. package/src/duckdb/src/common/types/interval.cpp +3 -0
  7. package/src/duckdb/src/core_functions/aggregate/nested/list.cpp +6 -1
  8. package/src/duckdb/src/execution/index/art/art.cpp +6 -9
  9. package/src/duckdb/src/execution/index/art/leaf.cpp +4 -4
  10. package/src/duckdb/src/execution/index/art/node.cpp +9 -12
  11. package/src/duckdb/src/execution/index/art/node16.cpp +4 -4
  12. package/src/duckdb/src/execution/index/art/node256.cpp +4 -4
  13. package/src/duckdb/src/execution/index/art/node4.cpp +4 -5
  14. package/src/duckdb/src/execution/index/art/node48.cpp +4 -4
  15. package/src/duckdb/src/execution/index/art/prefix.cpp +4 -6
  16. package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
  17. package/src/duckdb/src/include/duckdb/catalog/catalog_entry/index_catalog_entry.hpp +1 -1
  18. package/src/duckdb/src/include/duckdb/execution/index/art/art.hpp +2 -2
  19. package/src/duckdb/src/include/duckdb/execution/index/art/leaf.hpp +4 -4
  20. package/src/duckdb/src/include/duckdb/execution/index/art/node.hpp +6 -4
  21. package/src/duckdb/src/include/duckdb/execution/index/art/node16.hpp +2 -2
  22. package/src/duckdb/src/include/duckdb/execution/index/art/node256.hpp +2 -2
  23. package/src/duckdb/src/include/duckdb/execution/index/art/node4.hpp +2 -2
  24. package/src/duckdb/src/include/duckdb/execution/index/art/node48.hpp +2 -2
  25. package/src/duckdb/src/include/duckdb/execution/index/art/prefix.hpp +2 -2
  26. package/src/duckdb/src/include/duckdb/storage/block.hpp +27 -4
  27. package/src/duckdb/src/include/duckdb/storage/block_manager.hpp +9 -9
  28. package/src/duckdb/src/include/duckdb/storage/checkpoint/row_group_writer.hpp +5 -5
  29. package/src/duckdb/src/include/duckdb/storage/checkpoint/table_data_reader.hpp +2 -2
  30. package/src/duckdb/src/include/duckdb/storage/checkpoint/table_data_writer.hpp +3 -3
  31. package/src/duckdb/src/include/duckdb/storage/checkpoint_manager.hpp +19 -16
  32. package/src/duckdb/src/include/duckdb/storage/data_pointer.hpp +1 -1
  33. package/src/duckdb/src/include/duckdb/storage/in_memory_block_manager.hpp +2 -2
  34. package/src/duckdb/src/include/duckdb/storage/index.hpp +2 -2
  35. package/src/duckdb/src/include/duckdb/storage/metadata/metadata_manager.hpp +88 -0
  36. package/src/duckdb/src/include/duckdb/storage/metadata/metadata_reader.hpp +54 -0
  37. package/src/duckdb/src/include/duckdb/storage/metadata/metadata_writer.hpp +45 -0
  38. package/src/duckdb/src/include/duckdb/storage/partial_block_manager.hpp +2 -2
  39. package/src/duckdb/src/include/duckdb/storage/single_file_block_manager.hpp +6 -5
  40. package/src/duckdb/src/include/duckdb/storage/storage_info.hpp +2 -2
  41. package/src/duckdb/src/include/duckdb/storage/storage_manager.hpp +2 -2
  42. package/src/duckdb/src/include/duckdb/storage/table/persistent_table_data.hpp +2 -2
  43. package/src/duckdb/src/include/duckdb/storage/table/row_group.hpp +1 -1
  44. package/src/duckdb/src/include/duckdb/storage/table/row_group_collection.hpp +2 -0
  45. package/src/duckdb/src/include/duckdb/storage/table/row_group_segment_tree.hpp +2 -2
  46. package/src/duckdb/src/include/duckdb/storage/table/table_index_list.hpp +1 -1
  47. package/src/duckdb/src/include/duckdb/storage/table_io_manager.hpp +3 -0
  48. package/src/duckdb/src/include/duckdb/storage/write_ahead_log.hpp +3 -4
  49. package/src/duckdb/src/parallel/executor.cpp +3 -0
  50. package/src/duckdb/src/storage/buffer/block_manager.cpp +10 -9
  51. package/src/duckdb/src/storage/checkpoint/row_group_writer.cpp +1 -1
  52. package/src/duckdb/src/storage/checkpoint/table_data_reader.cpp +3 -4
  53. package/src/duckdb/src/storage/checkpoint/table_data_writer.cpp +7 -7
  54. package/src/duckdb/src/storage/checkpoint_manager.cpp +49 -43
  55. package/src/duckdb/src/storage/index.cpp +1 -1
  56. package/src/duckdb/src/storage/metadata/metadata_manager.cpp +267 -0
  57. package/src/duckdb/src/storage/metadata/metadata_reader.cpp +80 -0
  58. package/src/duckdb/src/storage/metadata/metadata_writer.cpp +86 -0
  59. package/src/duckdb/src/storage/single_file_block_manager.cpp +47 -52
  60. package/src/duckdb/src/storage/storage_info.cpp +1 -1
  61. package/src/duckdb/src/storage/storage_manager.cpp +4 -3
  62. package/src/duckdb/src/storage/table/column_data_checkpointer.cpp +3 -3
  63. package/src/duckdb/src/storage/table/persistent_table_data.cpp +1 -2
  64. package/src/duckdb/src/storage/table/row_group.cpp +9 -10
  65. package/src/duckdb/src/storage/table/row_group_collection.cpp +6 -3
  66. package/src/duckdb/src/storage/table_index_list.cpp +1 -1
  67. package/src/duckdb/src/storage/wal_replay.cpp +3 -2
  68. package/src/duckdb/src/storage/write_ahead_log.cpp +3 -2
  69. package/src/duckdb/ub_src_storage.cpp +0 -4
  70. package/src/duckdb/ub_src_storage_metadata.cpp +6 -0
  71. package/src/duckdb/src/include/duckdb/storage/meta_block_reader.hpp +0 -46
  72. package/src/duckdb/src/include/duckdb/storage/meta_block_writer.hpp +0 -50
  73. package/src/duckdb/src/storage/meta_block_reader.cpp +0 -69
  74. package/src/duckdb/src/storage/meta_block_writer.cpp +0 -80
@@ -589,6 +589,9 @@ bool Executor::GetPipelinesProgress(double &current_progress) { // LCOV_EXCL_STA
589
589
  total_cardinality += child_cardinality;
590
590
  }
591
591
  current_progress = 0;
592
+ if (total_cardinality == 0) {
593
+ return true;
594
+ }
592
595
  for (size_t i = 0; i < progress.size(); i++) {
593
596
  current_progress += progress[i] * double(cardinality[i]) / double(total_cardinality);
594
597
  }
@@ -2,10 +2,15 @@
2
2
  #include "duckdb/storage/buffer_manager.hpp"
3
3
  #include "duckdb/storage/buffer/block_handle.hpp"
4
4
  #include "duckdb/storage/buffer/buffer_pool.hpp"
5
+ #include "duckdb/storage/metadata/metadata_manager.hpp"
5
6
 
6
7
  namespace duckdb {
7
8
 
8
- shared_ptr<BlockHandle> BlockManager::RegisterBlock(block_id_t block_id, bool is_meta_block) {
9
+ BlockManager::BlockManager(BufferManager &buffer_manager)
10
+ : buffer_manager(buffer_manager), metadata_manager(make_uniq<MetadataManager>(*this, buffer_manager)) {
11
+ }
12
+
13
+ shared_ptr<BlockHandle> BlockManager::RegisterBlock(block_id_t block_id) {
9
14
  lock_guard<mutex> lock(blocks_lock);
10
15
  // check if the block already exists
11
16
  auto entry = blocks.find(block_id);
@@ -19,19 +24,11 @@ shared_ptr<BlockHandle> BlockManager::RegisterBlock(block_id_t block_id, bool is
19
24
  }
20
25
  // create a new block pointer for this block
21
26
  auto result = make_shared<BlockHandle>(*this, block_id);
22
- // for meta block, cache the handle in meta_blocks
23
- if (is_meta_block) {
24
- meta_blocks[block_id] = result;
25
- }
26
27
  // register the block pointer in the set of blocks as a weak pointer
27
28
  blocks[block_id] = weak_ptr<BlockHandle>(result);
28
29
  return result;
29
30
  }
30
31
 
31
- void BlockManager::ClearMetaBlockHandles() {
32
- meta_blocks.clear();
33
- }
34
-
35
32
  shared_ptr<BlockHandle> BlockManager::ConvertToPersistent(block_id_t block_id, shared_ptr<BlockHandle> old_block) {
36
33
  // pin the old block to ensure we have it loaded in memory
37
34
  auto old_handle = buffer_manager.Pin(old_block);
@@ -79,6 +76,10 @@ void BlockManager::UnregisterBlock(block_id_t block_id, bool can_destroy) {
79
76
  }
80
77
  }
81
78
 
79
+ MetadataManager &BlockManager::GetMetadataManager() {
80
+ return *metadata_manager;
81
+ }
82
+
82
83
  void BlockManager::Truncate() {
83
84
  }
84
85
 
@@ -36,7 +36,7 @@ void SingleFileRowGroupWriter::WriteColumnDataPointers(ColumnCheckpointState &co
36
36
  }
37
37
  }
38
38
 
39
- MetaBlockWriter &SingleFileRowGroupWriter::GetPayloadWriter() {
39
+ MetadataWriter &SingleFileRowGroupWriter::GetPayloadWriter() {
40
40
  return table_data_writer;
41
41
  }
42
42
 
@@ -1,5 +1,5 @@
1
1
  #include "duckdb/storage/checkpoint/table_data_reader.hpp"
2
- #include "duckdb/storage/meta_block_reader.hpp"
2
+ #include "duckdb/storage/metadata/metadata_reader.hpp"
3
3
  #include "duckdb/common/types/null_value.hpp"
4
4
 
5
5
  #include "duckdb/catalog/catalog_entry/table_catalog_entry.hpp"
@@ -10,7 +10,7 @@
10
10
 
11
11
  namespace duckdb {
12
12
 
13
- TableDataReader::TableDataReader(MetaBlockReader &reader, BoundCreateTableInfo &info) : reader(reader), info(info) {
13
+ TableDataReader::TableDataReader(MetadataReader &reader, BoundCreateTableInfo &info) : reader(reader), info(info) {
14
14
  info.data = make_uniq<PersistentTableData>(info.Base().columns.LogicalColumnCount());
15
15
  }
16
16
 
@@ -23,8 +23,7 @@ void TableDataReader::ReadTableData() {
23
23
 
24
24
  // deserialize each of the individual row groups
25
25
  info.data->row_group_count = reader.Read<uint64_t>();
26
- info.data->block_id = reader.block->BlockId();
27
- info.data->offset = reader.offset;
26
+ info.data->block_pointer = reader.GetMetaBlockPointer();
28
27
  }
29
28
 
30
29
  } // namespace duckdb
@@ -31,8 +31,8 @@ void TableDataWriter::AddRowGroup(RowGroupPointer &&row_group_pointer, unique_pt
31
31
  }
32
32
 
33
33
  SingleFileTableDataWriter::SingleFileTableDataWriter(SingleFileCheckpointWriter &checkpoint_manager,
34
- TableCatalogEntry &table, MetaBlockWriter &table_data_writer,
35
- MetaBlockWriter &meta_data_writer)
34
+ TableCatalogEntry &table, MetadataWriter &table_data_writer,
35
+ MetadataWriter &meta_data_writer)
36
36
  : TableDataWriter(table), checkpoint_manager(checkpoint_manager), table_data_writer(table_data_writer),
37
37
  meta_data_writer(meta_data_writer) {
38
38
  }
@@ -44,7 +44,7 @@ unique_ptr<RowGroupWriter> SingleFileTableDataWriter::GetRowGroupWriter(RowGroup
44
44
  void SingleFileTableDataWriter::FinalizeTable(TableStatistics &&global_stats, DataTableInfo *info) {
45
45
  // store the current position in the metadata writer
46
46
  // this is where the row groups for this table start
47
- auto pointer = table_data_writer.GetBlockPointer();
47
+ auto pointer = table_data_writer.GetMetaBlockPointer();
48
48
 
49
49
  global_stats.Serialize(table_data_writer);
50
50
 
@@ -60,18 +60,18 @@ void SingleFileTableDataWriter::FinalizeTable(TableStatistics &&global_stats, Da
60
60
  }
61
61
 
62
62
  // Pointer to the table itself goes to the metadata stream.
63
- meta_data_writer.Write<block_id_t>(pointer.block_id);
63
+ meta_data_writer.Write<idx_t>(pointer.block_pointer);
64
64
  meta_data_writer.Write<uint64_t>(pointer.offset);
65
65
  meta_data_writer.Write<idx_t>(total_rows);
66
66
 
67
67
  // Now we serialize indexes in the table_metadata_writer
68
- vector<BlockPointer> index_pointers = info->indexes.SerializeIndexes(table_data_writer);
68
+ auto index_pointers = info->indexes.SerializeIndexes(table_data_writer);
69
69
 
70
70
  // Write-off to metadata block ids and offsets of indexes
71
71
  meta_data_writer.Write<idx_t>(index_pointers.size());
72
72
  for (auto &block_info : index_pointers) {
73
- meta_data_writer.Write<idx_t>(block_info.block_id);
74
- meta_data_writer.Write<idx_t>(block_info.offset);
73
+ meta_data_writer.Write<block_id_t>(block_info.block_id);
74
+ meta_data_writer.Write<uint32_t>(block_info.offset);
75
75
  }
76
76
  }
77
77
 
@@ -27,7 +27,7 @@
27
27
  #include "duckdb/storage/block_manager.hpp"
28
28
  #include "duckdb/storage/checkpoint/table_data_reader.hpp"
29
29
  #include "duckdb/storage/checkpoint/table_data_writer.hpp"
30
- #include "duckdb/storage/meta_block_reader.hpp"
30
+ #include "duckdb/storage/metadata/metadata_reader.hpp"
31
31
  #include "duckdb/storage/table/column_checkpoint_state.hpp"
32
32
  #include "duckdb/transaction/transaction_manager.hpp"
33
33
  #include "duckdb/main/attached_database.hpp"
@@ -45,12 +45,16 @@ BlockManager &SingleFileCheckpointWriter::GetBlockManager() {
45
45
  return *storage_manager.block_manager;
46
46
  }
47
47
 
48
- MetaBlockWriter &SingleFileCheckpointWriter::GetMetaBlockWriter() {
48
+ MetadataWriter &SingleFileCheckpointWriter::GetMetadataWriter() {
49
49
  return *metadata_writer;
50
50
  }
51
51
 
52
+ MetadataManager &SingleFileCheckpointWriter::GetMetadataManager() {
53
+ return GetBlockManager().GetMetadataManager();
54
+ }
55
+
52
56
  unique_ptr<TableDataWriter> SingleFileCheckpointWriter::GetTableDataWriter(TableCatalogEntry &table) {
53
- return make_uniq<SingleFileTableDataWriter>(*this, table, *table_metadata_writer, GetMetaBlockWriter());
57
+ return make_uniq<SingleFileTableDataWriter>(*this, table, *table_metadata_writer, GetMetadataWriter());
54
58
  }
55
59
 
56
60
  void SingleFileCheckpointWriter::CreateCheckpoint() {
@@ -63,13 +67,14 @@ void SingleFileCheckpointWriter::CreateCheckpoint() {
63
67
  D_ASSERT(!metadata_writer);
64
68
 
65
69
  auto &block_manager = GetBlockManager();
70
+ auto &metadata_manager = GetMetadataManager();
66
71
 
67
72
  //! Set up the writers for the checkpoints
68
- metadata_writer = make_uniq<MetaBlockWriter>(block_manager);
69
- table_metadata_writer = make_uniq<MetaBlockWriter>(block_manager);
73
+ metadata_writer = make_uniq<MetadataWriter>(metadata_manager);
74
+ table_metadata_writer = make_uniq<MetadataWriter>(metadata_manager);
70
75
 
71
76
  // get the id of the first meta block
72
- block_id_t meta_block = metadata_writer->GetBlockPointer().block_id;
77
+ auto meta_block = metadata_writer->GetMetaBlockPointer();
73
78
 
74
79
  vector<reference<SchemaCatalogEntry>> schemas;
75
80
  // we scan the set of committed schemas
@@ -82,7 +87,6 @@ void SingleFileCheckpointWriter::CreateCheckpoint() {
82
87
  WriteSchema(schema.get());
83
88
  }
84
89
  partial_block_manager.FlushPartialBlocks();
85
- // flush the meta data to disk
86
90
  metadata_writer->Flush();
87
91
  table_metadata_writer->Flush();
88
92
 
@@ -101,7 +105,7 @@ void SingleFileCheckpointWriter::CreateCheckpoint() {
101
105
 
102
106
  // finally write the updated header
103
107
  DatabaseHeader header;
104
- header.meta_block = meta_block;
108
+ header.meta_block = meta_block.block_pointer;
105
109
  block_manager.WriteHeader(header);
106
110
 
107
111
  if (config.options.checkpoint_abort == CheckpointAbort::DEBUG_ABORT_BEFORE_TRUNCATE) {
@@ -114,29 +118,32 @@ void SingleFileCheckpointWriter::CreateCheckpoint() {
114
118
  // truncate the file
115
119
  block_manager.Truncate();
116
120
 
117
- // mark all blocks written as part of the metadata as modified
118
- metadata_writer->MarkWrittenBlocks();
119
- table_metadata_writer->MarkWrittenBlocks();
121
+ metadata_manager.MarkBlocksAsModified();
122
+ }
123
+
124
+ MetadataManager &SingleFileCheckpointReader::GetMetadataManager() {
125
+ return storage.block_manager->GetMetadataManager();
120
126
  }
121
127
 
122
128
  void SingleFileCheckpointReader::LoadFromStorage() {
123
129
  auto &block_manager = *storage.block_manager;
124
- block_id_t meta_block = block_manager.GetMetaBlock();
125
- if (meta_block < 0) {
130
+ auto &metadata_manager = GetMetadataManager();
131
+ MetaBlockPointer meta_block(block_manager.GetMetaBlock(), 0);
132
+ if (!meta_block.IsValid()) {
126
133
  // storage is empty
127
134
  return;
128
135
  }
129
136
 
130
137
  Connection con(storage.GetDatabase());
131
138
  con.BeginTransaction();
132
- // create the MetaBlockReader to read from the storage
133
- MetaBlockReader reader(block_manager, meta_block);
134
- reader.SetContext(*con.context);
139
+ // create the MetadataReader to read from the storage
140
+ MetadataReader reader(metadata_manager, meta_block);
141
+ // reader.SetContext(*con.context);
135
142
  LoadCheckpoint(*con.context, reader);
136
143
  con.Commit();
137
144
  }
138
145
 
139
- void CheckpointReader::LoadCheckpoint(ClientContext &context, MetaBlockReader &reader) {
146
+ void CheckpointReader::LoadCheckpoint(ClientContext &context, MetadataReader &reader) {
140
147
  uint32_t schema_count = reader.Read<uint32_t>();
141
148
  for (uint32_t i = 0; i < schema_count; i++) {
142
149
  ReadSchema(context, reader);
@@ -148,7 +155,7 @@ void CheckpointReader::LoadCheckpoint(ClientContext &context, MetaBlockReader &r
148
155
  //===--------------------------------------------------------------------===//
149
156
  void CheckpointWriter::WriteSchema(SchemaCatalogEntry &schema) {
150
157
  // write the schema data
151
- schema.Serialize(GetMetaBlockWriter());
158
+ schema.Serialize(GetMetadataWriter());
152
159
  // then, we fetch the tables/views/sequences information
153
160
  vector<reference<TableCatalogEntry>> tables;
154
161
  vector<reference<ViewCatalogEntry>> views;
@@ -206,7 +213,7 @@ void CheckpointWriter::WriteSchema(SchemaCatalogEntry &schema) {
206
213
  indexes.push_back(entry.Cast<IndexCatalogEntry>());
207
214
  });
208
215
 
209
- FieldWriter writer(GetMetaBlockWriter());
216
+ FieldWriter writer(GetMetadataWriter());
210
217
  writer.WriteField<uint32_t>(custom_types.size());
211
218
  writer.WriteField<uint32_t>(sequences.size());
212
219
  writer.WriteField<uint32_t>(tables.size());
@@ -251,7 +258,7 @@ void CheckpointWriter::WriteSchema(SchemaCatalogEntry &schema) {
251
258
  }
252
259
  }
253
260
 
254
- void CheckpointReader::ReadSchema(ClientContext &context, MetaBlockReader &reader) {
261
+ void CheckpointReader::ReadSchema(ClientContext &context, MetadataReader &reader) {
255
262
  // read the schema and create it in the catalog
256
263
  auto info = CatalogEntry::Deserialize(reader);
257
264
  // we set create conflict to ignore to ignore the failure of recreating the main schema
@@ -304,10 +311,10 @@ void CheckpointReader::ReadSchema(ClientContext &context, MetaBlockReader &reade
304
311
  // Views
305
312
  //===--------------------------------------------------------------------===//
306
313
  void CheckpointWriter::WriteView(ViewCatalogEntry &view) {
307
- view.Serialize(GetMetaBlockWriter());
314
+ view.Serialize(GetMetadataWriter());
308
315
  }
309
316
 
310
- void CheckpointReader::ReadView(ClientContext &context, MetaBlockReader &reader) {
317
+ void CheckpointReader::ReadView(ClientContext &context, MetadataReader &reader) {
311
318
  auto info = CatalogEntry::Deserialize(reader);
312
319
  catalog.CreateView(context, info->Cast<CreateViewInfo>());
313
320
  }
@@ -316,10 +323,10 @@ void CheckpointReader::ReadView(ClientContext &context, MetaBlockReader &reader)
316
323
  // Sequences
317
324
  //===--------------------------------------------------------------------===//
318
325
  void CheckpointWriter::WriteSequence(SequenceCatalogEntry &seq) {
319
- seq.Serialize(GetMetaBlockWriter());
326
+ seq.Serialize(GetMetadataWriter());
320
327
  }
321
328
 
322
- void CheckpointReader::ReadSequence(ClientContext &context, MetaBlockReader &reader) {
329
+ void CheckpointReader::ReadSequence(ClientContext &context, MetadataReader &reader) {
323
330
  auto info = SequenceCatalogEntry::Deserialize(reader);
324
331
  catalog.CreateSequence(context, info->Cast<CreateSequenceInfo>());
325
332
  }
@@ -331,14 +338,14 @@ void CheckpointWriter::WriteIndex(IndexCatalogEntry &index_catalog) {
331
338
  // The index data should already have been written as part of WriteTableData.
332
339
  // Here, we need only serialize the pointer to that data.
333
340
  auto root_offset = index_catalog.index->GetSerializedDataPointer();
334
- auto &metadata_writer = GetMetaBlockWriter();
341
+ auto &metadata_writer = GetMetadataWriter();
335
342
  index_catalog.Serialize(metadata_writer);
336
343
  // Serialize the Block id and offset of root node
337
344
  metadata_writer.Write(root_offset.block_id);
338
345
  metadata_writer.Write(root_offset.offset);
339
346
  }
340
347
 
341
- void CheckpointReader::ReadIndex(ClientContext &context, MetaBlockReader &reader) {
348
+ void CheckpointReader::ReadIndex(ClientContext &context, MetadataReader &reader) {
342
349
  // deserialize the index metadata
343
350
  auto info = IndexCatalogEntry::Deserialize(reader);
344
351
  auto &index_info = info->Cast<CreateIndexInfo>();
@@ -393,8 +400,9 @@ void CheckpointReader::ReadIndex(ClientContext &context, MetaBlockReader &reader
393
400
  switch (index_info.index_type) {
394
401
  case IndexType::ART: {
395
402
  auto &storage = table_catalog.GetStorage();
396
- auto art = make_uniq<ART>(index_info.column_ids, TableIOManager::Get(storage), std::move(unbound_expressions),
397
- index_info.constraint_type, storage.db, nullptr, root_block_id, root_offset);
403
+ auto art =
404
+ make_uniq<ART>(index_info.column_ids, TableIOManager::Get(storage), std::move(unbound_expressions),
405
+ index_info.constraint_type, storage.db, nullptr, BlockPointer(root_block_id, root_offset));
398
406
  index_catalog.index = art.get();
399
407
  storage.info->indexes.AddIndex(std::move(art));
400
408
  break;
@@ -408,10 +416,10 @@ void CheckpointReader::ReadIndex(ClientContext &context, MetaBlockReader &reader
408
416
  // Custom Types
409
417
  //===--------------------------------------------------------------------===//
410
418
  void CheckpointWriter::WriteType(TypeCatalogEntry &type) {
411
- type.Serialize(GetMetaBlockWriter());
419
+ type.Serialize(GetMetadataWriter());
412
420
  }
413
421
 
414
- void CheckpointReader::ReadType(ClientContext &context, MetaBlockReader &reader) {
422
+ void CheckpointReader::ReadType(ClientContext &context, MetadataReader &reader) {
415
423
  auto info = TypeCatalogEntry::Deserialize(reader);
416
424
  catalog.CreateType(context, info->Cast<CreateTypeInfo>());
417
425
  }
@@ -420,19 +428,19 @@ void CheckpointReader::ReadType(ClientContext &context, MetaBlockReader &reader)
420
428
  // Macro's
421
429
  //===--------------------------------------------------------------------===//
422
430
  void CheckpointWriter::WriteMacro(ScalarMacroCatalogEntry &macro) {
423
- macro.Serialize(GetMetaBlockWriter());
431
+ macro.Serialize(GetMetadataWriter());
424
432
  }
425
433
 
426
- void CheckpointReader::ReadMacro(ClientContext &context, MetaBlockReader &reader) {
434
+ void CheckpointReader::ReadMacro(ClientContext &context, MetadataReader &reader) {
427
435
  auto info = MacroCatalogEntry::Deserialize(reader);
428
436
  catalog.CreateFunction(context, info->Cast<CreateMacroInfo>());
429
437
  }
430
438
 
431
439
  void CheckpointWriter::WriteTableMacro(TableMacroCatalogEntry &macro) {
432
- macro.Serialize(GetMetaBlockWriter());
440
+ macro.Serialize(GetMetadataWriter());
433
441
  }
434
442
 
435
- void CheckpointReader::ReadTableMacro(ClientContext &context, MetaBlockReader &reader) {
443
+ void CheckpointReader::ReadTableMacro(ClientContext &context, MetadataReader &reader) {
436
444
  auto info = MacroCatalogEntry::Deserialize(reader);
437
445
  catalog.CreateFunction(context, info->Cast<CreateMacroInfo>());
438
446
  }
@@ -442,14 +450,14 @@ void CheckpointReader::ReadTableMacro(ClientContext &context, MetaBlockReader &r
442
450
  //===--------------------------------------------------------------------===//
443
451
  void CheckpointWriter::WriteTable(TableCatalogEntry &table) {
444
452
  // write the table meta data
445
- table.Serialize(GetMetaBlockWriter());
453
+ table.Serialize(GetMetadataWriter());
446
454
  // now we need to write the table data.
447
455
  if (auto writer = GetTableDataWriter(table)) {
448
456
  writer->WriteTableData();
449
457
  }
450
458
  }
451
459
 
452
- void CheckpointReader::ReadTable(ClientContext &context, MetaBlockReader &reader) {
460
+ void CheckpointReader::ReadTable(ClientContext &context, MetadataReader &reader) {
453
461
  // deserialize the table meta data
454
462
  auto info = TableCatalogEntry::Deserialize(reader);
455
463
  // bind the info
@@ -464,13 +472,11 @@ void CheckpointReader::ReadTable(ClientContext &context, MetaBlockReader &reader
464
472
  catalog.CreateTable(context, *bound_info);
465
473
  }
466
474
 
467
- void CheckpointReader::ReadTableData(ClientContext &context, MetaBlockReader &reader,
468
- BoundCreateTableInfo &bound_info) {
469
- auto block_id = reader.Read<block_id_t>();
475
+ void CheckpointReader::ReadTableData(ClientContext &context, MetadataReader &reader, BoundCreateTableInfo &bound_info) {
476
+ auto block_pointer = reader.Read<idx_t>();
470
477
  auto offset = reader.Read<uint64_t>();
471
478
 
472
- MetaBlockReader table_data_reader(reader.block_manager, block_id);
473
- table_data_reader.offset = offset;
479
+ MetadataReader table_data_reader(reader.GetMetadataManager(), MetaBlockPointer(block_pointer, offset));
474
480
  TableDataReader data_reader(table_data_reader, bound_info);
475
481
 
476
482
  data_reader.ReadTableData();
@@ -479,8 +485,8 @@ void CheckpointReader::ReadTableData(ClientContext &context, MetaBlockReader &re
479
485
  // Get any indexes block info
480
486
  idx_t num_indexes = reader.Read<idx_t>();
481
487
  for (idx_t i = 0; i < num_indexes; i++) {
482
- auto idx_block_id = reader.Read<idx_t>();
483
- auto idx_offset = reader.Read<idx_t>();
488
+ auto idx_block_id = reader.Read<block_id_t>();
489
+ auto idx_offset = reader.Read<uint32_t>();
484
490
  bound_info.indexes.emplace_back(idx_block_id, idx_offset);
485
491
  }
486
492
  }
@@ -108,7 +108,7 @@ bool Index::IndexIsUpdated(const vector<PhysicalIndex> &column_ids) const {
108
108
  return false;
109
109
  }
110
110
 
111
- BlockPointer Index::Serialize(MetaBlockWriter &writer) {
111
+ BlockPointer Index::Serialize(MetadataWriter &writer) {
112
112
  throw NotImplementedException("The implementation of this index serialization does not exist.");
113
113
  }
114
114
 
@@ -0,0 +1,267 @@
1
+ #include "duckdb/storage/metadata/metadata_manager.hpp"
2
+ #include "duckdb/storage/buffer_manager.hpp"
3
+ #include "duckdb/storage/buffer/block_handle.hpp"
4
+
5
+ namespace duckdb {
6
+
7
+ MetadataManager::MetadataManager(BlockManager &block_manager, BufferManager &buffer_manager)
8
+ : block_manager(block_manager), buffer_manager(buffer_manager) {
9
+ }
10
+
11
+ MetadataManager::~MetadataManager() {
12
+ }
13
+
14
+ MetadataHandle MetadataManager::AllocateHandle() {
15
+ // check if there is any free space left in an existing block
16
+ // if not allocate a new bloc
17
+ block_id_t free_block = INVALID_BLOCK;
18
+ for (auto &kv : blocks) {
19
+ auto &block = kv.second;
20
+ D_ASSERT(kv.first == block.block_id);
21
+ if (!block.free_blocks.empty()) {
22
+ free_block = kv.first;
23
+ break;
24
+ }
25
+ }
26
+ if (free_block == INVALID_BLOCK) {
27
+ free_block = AllocateNewBlock();
28
+ }
29
+ D_ASSERT(free_block != INVALID_BLOCK);
30
+
31
+ // select the first free metadata block we can find
32
+ MetadataPointer pointer;
33
+ pointer.block_index = free_block;
34
+ auto &block = blocks[free_block];
35
+ D_ASSERT(!block.free_blocks.empty());
36
+ pointer.index = block.free_blocks.back();
37
+ // mark the block as used
38
+ block.free_blocks.pop_back();
39
+ D_ASSERT(pointer.index < METADATA_BLOCK_COUNT);
40
+ // pin the block
41
+ return Pin(pointer);
42
+ }
43
+
44
+ MetadataHandle MetadataManager::Pin(MetadataPointer pointer) {
45
+ D_ASSERT(pointer.index < METADATA_BLOCK_COUNT);
46
+ auto &block = blocks[pointer.block_index];
47
+
48
+ MetadataHandle handle;
49
+ handle.pointer.block_index = pointer.block_index;
50
+ handle.pointer.index = pointer.index;
51
+ handle.handle = buffer_manager.Pin(block.block);
52
+ return handle;
53
+ }
54
+
55
+ block_id_t MetadataManager::AllocateNewBlock() {
56
+ auto new_block_id = GetNextBlockId();
57
+
58
+ MetadataBlock new_block;
59
+ buffer_manager.Allocate(Storage::BLOCK_SIZE, false, &new_block.block);
60
+ new_block.block_id = new_block_id;
61
+ for (idx_t i = 0; i < METADATA_BLOCK_COUNT; i++) {
62
+ new_block.free_blocks.push_back(METADATA_BLOCK_COUNT - i - 1);
63
+ }
64
+ AddBlock(std::move(new_block));
65
+ return new_block_id;
66
+ }
67
+
68
+ void MetadataManager::AddBlock(MetadataBlock new_block, bool if_exists) {
69
+ if (blocks.find(new_block.block_id) != blocks.end()) {
70
+ if (if_exists) {
71
+ return;
72
+ }
73
+ throw InternalException("Block id with id %llu already exists", new_block.block_id);
74
+ }
75
+ blocks[new_block.block_id] = std::move(new_block);
76
+ }
77
+
78
+ void MetadataManager::AddAndRegisterBlock(MetadataBlock block) {
79
+ if (block.block) {
80
+ throw InternalException("Calling AddAndRegisterBlock on block that already exists");
81
+ }
82
+ block.block = block_manager.RegisterBlock(block.block_id);
83
+ AddBlock(std::move(block), true);
84
+ }
85
+
86
+ MetaBlockPointer MetadataManager::GetDiskPointer(MetadataPointer pointer, uint32_t offset) {
87
+ idx_t block_pointer = idx_t(pointer.block_index);
88
+ block_pointer |= idx_t(pointer.index) << 56ULL;
89
+ return MetaBlockPointer(block_pointer, offset);
90
+ }
91
+
92
+ block_id_t MetaBlockPointer::GetBlockId() {
93
+ return block_id_t(block_pointer & ~(idx_t(0xFF) << 56ULL));
94
+ }
95
+
96
+ uint32_t MetaBlockPointer::GetBlockIndex() {
97
+ return block_pointer >> 56ULL;
98
+ }
99
+
100
+ MetadataPointer MetadataManager::FromDiskPointer(MetaBlockPointer pointer) {
101
+ auto block_id = pointer.GetBlockId();
102
+ auto index = pointer.GetBlockIndex();
103
+ auto entry = blocks.find(block_id);
104
+ if (entry == blocks.end()) { // LCOV_EXCL_START
105
+ throw InternalException("Failed to load metadata pointer (id %llu, idx %llu, ptr %llu)\n", block_id, index,
106
+ pointer.block_pointer);
107
+ } // LCOV_EXCL_STOP
108
+ MetadataPointer result;
109
+ result.block_index = block_id;
110
+ result.index = index;
111
+ return result;
112
+ }
113
+
114
+ MetadataPointer MetadataManager::RegisterDiskPointer(MetaBlockPointer pointer) {
115
+ auto block_id = pointer.GetBlockId();
116
+ MetadataBlock block;
117
+ block.block_id = block_id;
118
+ AddAndRegisterBlock(block);
119
+ return FromDiskPointer(pointer);
120
+ }
121
+
122
+ BlockPointer MetadataManager::ToBlockPointer(MetaBlockPointer meta_pointer) {
123
+ BlockPointer result;
124
+ result.block_id = meta_pointer.GetBlockId();
125
+ result.offset = meta_pointer.GetBlockIndex() * MetadataManager::METADATA_BLOCK_SIZE + meta_pointer.offset;
126
+ D_ASSERT(result.offset < MetadataManager::METADATA_BLOCK_SIZE * MetadataManager::METADATA_BLOCK_COUNT);
127
+ return result;
128
+ }
129
+
130
+ MetaBlockPointer MetadataManager::FromBlockPointer(BlockPointer block_pointer) {
131
+ if (!block_pointer.IsValid()) {
132
+ return MetaBlockPointer();
133
+ }
134
+ idx_t index = block_pointer.offset / MetadataManager::METADATA_BLOCK_SIZE;
135
+ auto offset = block_pointer.offset % MetadataManager::METADATA_BLOCK_SIZE;
136
+ D_ASSERT(index < MetadataManager::METADATA_BLOCK_COUNT);
137
+ D_ASSERT(offset < MetadataManager::METADATA_BLOCK_SIZE);
138
+ MetaBlockPointer result;
139
+ result.block_pointer = idx_t(block_pointer.block_id) | index << 56ULL;
140
+ result.offset = offset;
141
+ return result;
142
+ }
143
+
144
+ idx_t MetadataManager::BlockCount() {
145
+ return blocks.size();
146
+ }
147
+
148
+ void MetadataManager::Flush() {
149
+ const idx_t total_metadata_size = MetadataManager::METADATA_BLOCK_SIZE * MetadataManager::METADATA_BLOCK_COUNT;
150
+ // write the blocks of the metadata manager to disk
151
+ for (auto &kv : blocks) {
152
+ auto &block = kv.second;
153
+ auto handle = buffer_manager.Pin(block.block);
154
+ // zero-initialize any free blocks
155
+ for (auto free_block : block.free_blocks) {
156
+ memset(handle.Ptr() + free_block * MetadataManager::METADATA_BLOCK_SIZE, 0,
157
+ MetadataManager::METADATA_BLOCK_SIZE);
158
+ }
159
+ // there are a few bytes left-over at the end of the block, zero-initialize them
160
+ memset(handle.Ptr() + total_metadata_size, 0, Storage::BLOCK_SIZE - total_metadata_size);
161
+ D_ASSERT(kv.first == block.block_id);
162
+ if (block.block->BlockId() >= MAXIMUM_BLOCK) {
163
+ // temporary block - convert to persistent
164
+ block.block = block_manager.ConvertToPersistent(kv.first, std::move(block.block));
165
+ } else {
166
+ // already a persistent block - only need to write it
167
+ D_ASSERT(block.block->BlockId() == block.block_id);
168
+ block_manager.Write(handle.GetFileBuffer(), block.block_id);
169
+ }
170
+ }
171
+ }
172
+
173
+ void MetadataManager::Serialize(Serializer &serializer) {
174
+ serializer.Write<uint64_t>(blocks.size());
175
+ for (auto &kv : blocks) {
176
+ kv.second.Serialize(serializer);
177
+ }
178
+ }
179
+
180
+ void MetadataManager::Deserialize(Deserializer &source) {
181
+ auto block_count = source.Read<uint64_t>();
182
+ for (idx_t i = 0; i < block_count; i++) {
183
+ auto block = MetadataBlock::Deserialize(source);
184
+ auto entry = blocks.find(block.block_id);
185
+ if (entry == blocks.end()) {
186
+ // block does not exist yet
187
+ AddAndRegisterBlock(std::move(block));
188
+ } else {
189
+ // block was already created - only copy over the free list
190
+ entry->second.free_blocks = std::move(block.free_blocks);
191
+ }
192
+ }
193
+ }
194
+
195
+ void MetadataBlock::Serialize(Serializer &serializer) {
196
+ serializer.Write<block_id_t>(block_id);
197
+ serializer.Write<idx_t>(FreeBlocksToInteger());
198
+ }
199
+
200
+ MetadataBlock MetadataBlock::Deserialize(Deserializer &source) {
201
+ MetadataBlock result;
202
+ result.block_id = source.Read<block_id_t>();
203
+ auto free_list = source.Read<idx_t>();
204
+ result.FreeBlocksFromInteger(free_list);
205
+ return result;
206
+ }
207
+
208
+ idx_t MetadataBlock::FreeBlocksToInteger() {
209
+ idx_t result = 0;
210
+ for (idx_t i = 0; i < free_blocks.size(); i++) {
211
+ D_ASSERT(free_blocks[i] < idx_t(64));
212
+ idx_t mask = idx_t(1) << idx_t(free_blocks[i]);
213
+ result |= mask;
214
+ }
215
+ return result;
216
+ }
217
+
218
+ void MetadataBlock::FreeBlocksFromInteger(idx_t free_list) {
219
+ free_blocks.clear();
220
+ if (free_list == 0) {
221
+ return;
222
+ }
223
+ for (idx_t i = 64; i > 0; i--) {
224
+ auto index = i - 1;
225
+ idx_t mask = idx_t(1) << index;
226
+ if (free_list & mask) {
227
+ free_blocks.push_back(index);
228
+ }
229
+ }
230
+ }
231
+
232
+ void MetadataManager::MarkBlocksAsModified() {
233
+ if (!modified_blocks.empty()) {
234
+ // for any blocks that were modified in the last checkpoint - set them to free blocks currently
235
+ for (auto &kv : modified_blocks) {
236
+ auto block_id = kv.first;
237
+ idx_t modified_list = kv.second;
238
+ auto entry = blocks.find(block_id);
239
+ D_ASSERT(entry != blocks.end());
240
+ auto &block = entry->second;
241
+ idx_t current_free_blocks = block.FreeBlocksToInteger();
242
+ // merge the current set of free blocks with the modified blocks
243
+ idx_t new_free_blocks = current_free_blocks | modified_list;
244
+ // if (new_free_blocks == NumericLimits<idx_t>::Maximum()) {
245
+ // // if new free_blocks is all blocks - mark entire block as modified
246
+ // blocks.erase(entry);
247
+ // block_manager.MarkBlockAsModified(block_id);
248
+ // } else {
249
+ // set the new set of free blocks
250
+ block.FreeBlocksFromInteger(new_free_blocks);
251
+ // }
252
+ }
253
+ }
254
+ modified_blocks.clear();
255
+ for (auto &kv : blocks) {
256
+ auto &block = kv.second;
257
+ idx_t free_list = block.FreeBlocksToInteger();
258
+ idx_t occupied_list = ~free_list;
259
+ modified_blocks[block.block_id] = occupied_list;
260
+ }
261
+ }
262
+
263
+ block_id_t MetadataManager::GetNextBlockId() {
264
+ return block_manager.GetFreeBlockId();
265
+ }
266
+
267
+ } // namespace duckdb