duckdb 0.8.2-dev2673.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.
- package/binding.gyp +1 -0
- package/package.json +1 -1
- package/src/duckdb/src/catalog/catalog_entry/duck_table_entry.cpp +6 -6
- package/src/duckdb/src/common/field_writer.cpp +1 -0
- package/src/duckdb/src/common/local_file_system.cpp +5 -0
- package/src/duckdb/src/common/types/interval.cpp +3 -0
- package/src/duckdb/src/execution/index/art/art.cpp +6 -9
- package/src/duckdb/src/execution/index/art/leaf.cpp +4 -4
- package/src/duckdb/src/execution/index/art/node.cpp +9 -12
- package/src/duckdb/src/execution/index/art/node16.cpp +4 -4
- package/src/duckdb/src/execution/index/art/node256.cpp +4 -4
- package/src/duckdb/src/execution/index/art/node4.cpp +4 -5
- package/src/duckdb/src/execution/index/art/node48.cpp +4 -4
- package/src/duckdb/src/execution/index/art/prefix.cpp +4 -6
- package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
- package/src/duckdb/src/include/duckdb/catalog/catalog_entry/index_catalog_entry.hpp +1 -1
- package/src/duckdb/src/include/duckdb/execution/index/art/art.hpp +2 -2
- package/src/duckdb/src/include/duckdb/execution/index/art/leaf.hpp +4 -4
- package/src/duckdb/src/include/duckdb/execution/index/art/node.hpp +6 -4
- package/src/duckdb/src/include/duckdb/execution/index/art/node16.hpp +2 -2
- package/src/duckdb/src/include/duckdb/execution/index/art/node256.hpp +2 -2
- package/src/duckdb/src/include/duckdb/execution/index/art/node4.hpp +2 -2
- package/src/duckdb/src/include/duckdb/execution/index/art/node48.hpp +2 -2
- package/src/duckdb/src/include/duckdb/execution/index/art/prefix.hpp +2 -2
- package/src/duckdb/src/include/duckdb/storage/block.hpp +27 -4
- package/src/duckdb/src/include/duckdb/storage/block_manager.hpp +9 -9
- package/src/duckdb/src/include/duckdb/storage/checkpoint/row_group_writer.hpp +5 -5
- package/src/duckdb/src/include/duckdb/storage/checkpoint/table_data_reader.hpp +2 -2
- package/src/duckdb/src/include/duckdb/storage/checkpoint/table_data_writer.hpp +3 -3
- package/src/duckdb/src/include/duckdb/storage/checkpoint_manager.hpp +19 -16
- package/src/duckdb/src/include/duckdb/storage/data_pointer.hpp +1 -1
- package/src/duckdb/src/include/duckdb/storage/in_memory_block_manager.hpp +2 -2
- package/src/duckdb/src/include/duckdb/storage/index.hpp +2 -2
- package/src/duckdb/src/include/duckdb/storage/metadata/metadata_manager.hpp +88 -0
- package/src/duckdb/src/include/duckdb/storage/metadata/metadata_reader.hpp +54 -0
- package/src/duckdb/src/include/duckdb/storage/metadata/metadata_writer.hpp +45 -0
- package/src/duckdb/src/include/duckdb/storage/partial_block_manager.hpp +2 -2
- package/src/duckdb/src/include/duckdb/storage/single_file_block_manager.hpp +6 -5
- package/src/duckdb/src/include/duckdb/storage/storage_info.hpp +2 -2
- package/src/duckdb/src/include/duckdb/storage/storage_manager.hpp +2 -2
- package/src/duckdb/src/include/duckdb/storage/table/persistent_table_data.hpp +2 -2
- package/src/duckdb/src/include/duckdb/storage/table/row_group.hpp +1 -1
- package/src/duckdb/src/include/duckdb/storage/table/row_group_collection.hpp +2 -0
- package/src/duckdb/src/include/duckdb/storage/table/row_group_segment_tree.hpp +2 -2
- package/src/duckdb/src/include/duckdb/storage/table/table_index_list.hpp +1 -1
- package/src/duckdb/src/include/duckdb/storage/table_io_manager.hpp +3 -0
- package/src/duckdb/src/include/duckdb/storage/write_ahead_log.hpp +3 -4
- package/src/duckdb/src/storage/buffer/block_manager.cpp +10 -9
- package/src/duckdb/src/storage/checkpoint/row_group_writer.cpp +1 -1
- package/src/duckdb/src/storage/checkpoint/table_data_reader.cpp +3 -4
- package/src/duckdb/src/storage/checkpoint/table_data_writer.cpp +7 -7
- package/src/duckdb/src/storage/checkpoint_manager.cpp +49 -43
- package/src/duckdb/src/storage/index.cpp +1 -1
- package/src/duckdb/src/storage/metadata/metadata_manager.cpp +267 -0
- package/src/duckdb/src/storage/metadata/metadata_reader.cpp +80 -0
- package/src/duckdb/src/storage/metadata/metadata_writer.cpp +86 -0
- package/src/duckdb/src/storage/single_file_block_manager.cpp +47 -52
- package/src/duckdb/src/storage/storage_info.cpp +1 -1
- package/src/duckdb/src/storage/storage_manager.cpp +4 -3
- package/src/duckdb/src/storage/table/column_data_checkpointer.cpp +3 -3
- package/src/duckdb/src/storage/table/persistent_table_data.cpp +1 -2
- package/src/duckdb/src/storage/table/row_group.cpp +9 -10
- package/src/duckdb/src/storage/table/row_group_collection.cpp +6 -3
- package/src/duckdb/src/storage/table_index_list.cpp +1 -1
- package/src/duckdb/src/storage/wal_replay.cpp +3 -2
- package/src/duckdb/src/storage/write_ahead_log.cpp +3 -2
- package/src/duckdb/ub_src_storage.cpp +0 -4
- package/src/duckdb/ub_src_storage_metadata.cpp +6 -0
- package/src/duckdb/src/include/duckdb/storage/meta_block_reader.hpp +0 -46
- package/src/duckdb/src/include/duckdb/storage/meta_block_writer.hpp +0 -50
- package/src/duckdb/src/storage/meta_block_reader.cpp +0 -69
- package/src/duckdb/src/storage/meta_block_writer.cpp +0 -80
@@ -1,5 +1,5 @@
|
|
1
1
|
#include "duckdb/storage/checkpoint/table_data_reader.hpp"
|
2
|
-
#include "duckdb/storage/
|
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(
|
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->
|
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,
|
35
|
-
|
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.
|
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<
|
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
|
-
|
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<
|
74
|
-
meta_data_writer.Write<
|
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/
|
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
|
-
|
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,
|
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<
|
69
|
-
table_metadata_writer = make_uniq<
|
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
|
-
|
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
|
-
|
118
|
-
|
119
|
-
|
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
|
-
|
125
|
-
|
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
|
133
|
-
|
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,
|
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(
|
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(
|
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,
|
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(
|
314
|
+
view.Serialize(GetMetadataWriter());
|
308
315
|
}
|
309
316
|
|
310
|
-
void CheckpointReader::ReadView(ClientContext &context,
|
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(
|
326
|
+
seq.Serialize(GetMetadataWriter());
|
320
327
|
}
|
321
328
|
|
322
|
-
void CheckpointReader::ReadSequence(ClientContext &context,
|
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 =
|
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,
|
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 =
|
397
|
-
|
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(
|
419
|
+
type.Serialize(GetMetadataWriter());
|
412
420
|
}
|
413
421
|
|
414
|
-
void CheckpointReader::ReadType(ClientContext &context,
|
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 ¯o) {
|
423
|
-
macro.Serialize(
|
431
|
+
macro.Serialize(GetMetadataWriter());
|
424
432
|
}
|
425
433
|
|
426
|
-
void CheckpointReader::ReadMacro(ClientContext &context,
|
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 ¯o) {
|
432
|
-
macro.Serialize(
|
440
|
+
macro.Serialize(GetMetadataWriter());
|
433
441
|
}
|
434
442
|
|
435
|
-
void CheckpointReader::ReadTableMacro(ClientContext &context,
|
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(
|
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,
|
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,
|
468
|
-
|
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
|
-
|
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<
|
483
|
-
auto idx_offset = reader.Read<
|
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(
|
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
|