duckdb 0.6.2-dev1770.0 → 0.6.2-dev1772.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/package.json +1 -1
- package/src/duckdb/src/common/file_buffer.cpp +9 -34
- package/src/duckdb/src/execution/index/art/swizzleable_pointer.cpp +2 -2
- package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
- package/src/duckdb/src/include/duckdb/common/file_buffer.hpp +3 -16
- package/src/duckdb/src/include/duckdb/storage/buffer_manager.hpp +2 -4
- package/src/duckdb/src/include/duckdb/storage/index.hpp +1 -0
- package/src/duckdb/src/include/duckdb/storage/single_file_block_manager.hpp +3 -0
- package/src/duckdb/src/include/duckdb/storage/write_ahead_log.hpp +5 -5
- package/src/duckdb/src/storage/block.cpp +2 -2
- package/src/duckdb/src/storage/single_file_block_manager.cpp +31 -10
package/package.json
CHANGED
|
@@ -23,8 +23,6 @@ void FileBuffer::Init() {
|
|
|
23
23
|
size = 0;
|
|
24
24
|
internal_buffer = nullptr;
|
|
25
25
|
internal_size = 0;
|
|
26
|
-
malloced_buffer = nullptr;
|
|
27
|
-
malloced_size = 0;
|
|
28
26
|
}
|
|
29
27
|
|
|
30
28
|
FileBuffer::FileBuffer(FileBuffer &source, FileBufferType type_p) : allocator(source.allocator), type(type_p) {
|
|
@@ -33,31 +31,29 @@ FileBuffer::FileBuffer(FileBuffer &source, FileBufferType type_p) : allocator(so
|
|
|
33
31
|
size = source.size;
|
|
34
32
|
internal_buffer = source.internal_buffer;
|
|
35
33
|
internal_size = source.internal_size;
|
|
36
|
-
malloced_buffer = source.malloced_buffer;
|
|
37
|
-
malloced_size = source.malloced_size;
|
|
38
34
|
|
|
39
35
|
source.Init();
|
|
40
36
|
}
|
|
41
37
|
|
|
42
38
|
FileBuffer::~FileBuffer() {
|
|
43
|
-
if (!
|
|
39
|
+
if (!internal_buffer) {
|
|
44
40
|
return;
|
|
45
41
|
}
|
|
46
|
-
allocator.FreeData(
|
|
42
|
+
allocator.FreeData(internal_buffer, internal_size);
|
|
47
43
|
}
|
|
48
44
|
|
|
49
45
|
void FileBuffer::ReallocBuffer(size_t new_size) {
|
|
50
|
-
|
|
51
|
-
|
|
46
|
+
data_ptr_t new_buffer;
|
|
47
|
+
if (internal_buffer) {
|
|
48
|
+
new_buffer = allocator.ReallocateData(internal_buffer, internal_size, new_size);
|
|
52
49
|
} else {
|
|
53
|
-
|
|
50
|
+
new_buffer = allocator.AllocateData(new_size);
|
|
54
51
|
}
|
|
55
|
-
if (!
|
|
52
|
+
if (!new_buffer) {
|
|
56
53
|
throw std::bad_alloc();
|
|
57
54
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
internal_size = malloced_size;
|
|
55
|
+
internal_buffer = new_buffer;
|
|
56
|
+
internal_size = new_size;
|
|
61
57
|
// Caller must update these.
|
|
62
58
|
buffer = nullptr;
|
|
63
59
|
size = 0;
|
|
@@ -92,32 +88,11 @@ void FileBuffer::Read(FileHandle &handle, uint64_t location) {
|
|
|
92
88
|
handle.Read(internal_buffer, internal_size, location);
|
|
93
89
|
}
|
|
94
90
|
|
|
95
|
-
void FileBuffer::ReadAndChecksum(FileHandle &handle, uint64_t location) {
|
|
96
|
-
// read the buffer from disk
|
|
97
|
-
Read(handle, location);
|
|
98
|
-
// compute the checksum
|
|
99
|
-
auto stored_checksum = Load<uint64_t>(internal_buffer);
|
|
100
|
-
uint64_t computed_checksum = Checksum(buffer, size);
|
|
101
|
-
// verify the checksum
|
|
102
|
-
if (stored_checksum != computed_checksum) {
|
|
103
|
-
throw IOException("Corrupt database file: computed checksum %llu does not match stored checksum %llu in block",
|
|
104
|
-
computed_checksum, stored_checksum);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
91
|
void FileBuffer::Write(FileHandle &handle, uint64_t location) {
|
|
109
92
|
D_ASSERT(type != FileBufferType::TINY_BUFFER);
|
|
110
93
|
handle.Write(internal_buffer, internal_size, location);
|
|
111
94
|
}
|
|
112
95
|
|
|
113
|
-
void FileBuffer::ChecksumAndWrite(FileHandle &handle, uint64_t location) {
|
|
114
|
-
// compute the checksum and write it to the start of the buffer (if not temp buffer)
|
|
115
|
-
uint64_t checksum = Checksum(buffer, size);
|
|
116
|
-
Store<uint64_t>(checksum, internal_buffer);
|
|
117
|
-
// now write the buffer
|
|
118
|
-
Write(handle, location);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
96
|
void FileBuffer::Clear() {
|
|
122
97
|
memset(internal_buffer, 0, internal_size);
|
|
123
98
|
}
|
|
@@ -11,8 +11,8 @@ SwizzleablePointer::~SwizzleablePointer() {
|
|
|
11
11
|
|
|
12
12
|
SwizzleablePointer::SwizzleablePointer(duckdb::MetaBlockReader &reader) {
|
|
13
13
|
idx_t block_id = reader.Read<block_id_t>();
|
|
14
|
-
|
|
15
|
-
if (block_id == DConstants::INVALID_INDEX || offset == DConstants::INVALID_INDEX) {
|
|
14
|
+
uint32_t offset = reader.Read<uint32_t>();
|
|
15
|
+
if (block_id == DConstants::INVALID_INDEX || offset == (uint32_t)DConstants::INVALID_INDEX) {
|
|
16
16
|
pointer = 0;
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#ifndef DUCKDB_VERSION
|
|
2
|
-
#define DUCKDB_VERSION "0.6.2-
|
|
2
|
+
#define DUCKDB_VERSION "0.6.2-dev1772"
|
|
3
3
|
#endif
|
|
4
4
|
#ifndef DUCKDB_SOURCE_ID
|
|
5
|
-
#define DUCKDB_SOURCE_ID "
|
|
5
|
+
#define DUCKDB_SOURCE_ID "d25a77fff4"
|
|
6
6
|
#endif
|
|
7
7
|
#include "duckdb/function/table/system_functions.hpp"
|
|
8
8
|
#include "duckdb/main/database.hpp"
|
|
@@ -39,14 +39,8 @@ public:
|
|
|
39
39
|
public:
|
|
40
40
|
//! Read into the FileBuffer from the specified location.
|
|
41
41
|
void Read(FileHandle &handle, uint64_t location);
|
|
42
|
-
//! Read into the FileBuffer from the specified location. Automatically verifies the checksum, and throws an
|
|
43
|
-
//! exception if the checksum does not match correctly.
|
|
44
|
-
virtual void ReadAndChecksum(FileHandle &handle, uint64_t location);
|
|
45
42
|
//! Write the contents of the FileBuffer to the specified location.
|
|
46
43
|
void Write(FileHandle &handle, uint64_t location);
|
|
47
|
-
//! Write the contents of the FileBuffer to the specified location. Automatically adds a checksum of the contents of
|
|
48
|
-
//! the filebuffer in front of the written data.
|
|
49
|
-
virtual void ChecksumAndWrite(FileHandle &handle, uint64_t location);
|
|
50
44
|
|
|
51
45
|
void Clear();
|
|
52
46
|
|
|
@@ -57,6 +51,9 @@ public:
|
|
|
57
51
|
uint64_t AllocSize() const {
|
|
58
52
|
return internal_size;
|
|
59
53
|
}
|
|
54
|
+
data_ptr_t InternalBuffer() {
|
|
55
|
+
return internal_buffer;
|
|
56
|
+
}
|
|
60
57
|
|
|
61
58
|
struct MemoryRequirement {
|
|
62
59
|
idx_t alloc_size;
|
|
@@ -72,16 +69,6 @@ protected:
|
|
|
72
69
|
uint64_t internal_size;
|
|
73
70
|
|
|
74
71
|
void ReallocBuffer(size_t malloc_size);
|
|
75
|
-
|
|
76
|
-
private:
|
|
77
|
-
//! The buffer that was actually malloc'd, i.e. the pointer that must be freed when the FileBuffer is destroyed
|
|
78
|
-
data_ptr_t malloced_buffer;
|
|
79
|
-
uint64_t malloced_size;
|
|
80
|
-
|
|
81
|
-
protected:
|
|
82
|
-
uint64_t GetMallocedSize() {
|
|
83
|
-
return malloced_size;
|
|
84
|
-
}
|
|
85
72
|
void Init();
|
|
86
73
|
};
|
|
87
74
|
|
|
@@ -85,10 +85,8 @@ public:
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
//! Construct a managed buffer.
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
virtual unique_ptr<FileBuffer> ConstructManagedBuffer(idx_t size, unique_ptr<FileBuffer> &&source,
|
|
91
|
-
FileBufferType type = FileBufferType::MANAGED_BUFFER);
|
|
88
|
+
unique_ptr<FileBuffer> ConstructManagedBuffer(idx_t size, unique_ptr<FileBuffer> &&source,
|
|
89
|
+
FileBufferType type = FileBufferType::MANAGED_BUFFER);
|
|
92
90
|
|
|
93
91
|
DUCKDB_API void ReserveMemory(idx_t size);
|
|
94
92
|
DUCKDB_API void FreeReservedMemory(idx_t size);
|
|
@@ -118,6 +118,7 @@ public:
|
|
|
118
118
|
}
|
|
119
119
|
//! Serializes the index and returns the pair of block_id offset positions
|
|
120
120
|
virtual BlockPointer Serialize(duckdb::MetaBlockWriter &writer);
|
|
121
|
+
BlockPointer GetBlockPointer();
|
|
121
122
|
|
|
122
123
|
//! Returns block/offset of where index was most recently serialized.
|
|
123
124
|
BlockPointer GetSerializedDataPointer() const {
|
|
@@ -59,6 +59,9 @@ private:
|
|
|
59
59
|
|
|
60
60
|
void Initialize(DatabaseHeader &header);
|
|
61
61
|
|
|
62
|
+
void ReadAndChecksum(FileBuffer &handle, uint64_t location) const;
|
|
63
|
+
void ChecksumAndWrite(FileBuffer &handle, uint64_t location) const;
|
|
64
|
+
|
|
62
65
|
//! Return the blocks to which we will write the free list and modified blocks
|
|
63
66
|
vector<block_id_t> GetFreeListBlocks();
|
|
64
67
|
|
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
#include "duckdb/common/types/data_chunk.hpp"
|
|
13
13
|
#include "duckdb/common/enums/wal_type.hpp"
|
|
14
14
|
#include "duckdb/common/serializer/buffered_file_writer.hpp"
|
|
15
|
-
#include "duckdb/catalog/catalog_entry/sequence_catalog_entry.hpp"
|
|
16
|
-
#include "duckdb/storage/storage_info.hpp"
|
|
17
|
-
|
|
18
15
|
#include "duckdb/catalog/catalog_entry/scalar_macro_catalog_entry.hpp"
|
|
16
|
+
#include "duckdb/catalog/catalog_entry/sequence_catalog_entry.hpp"
|
|
19
17
|
#include "duckdb/catalog/catalog_entry/table_macro_catalog_entry.hpp"
|
|
18
|
+
#include "duckdb/main/attached_database.hpp"
|
|
19
|
+
#include "duckdb/storage/storage_info.hpp"
|
|
20
20
|
|
|
21
21
|
namespace duckdb {
|
|
22
22
|
|
|
@@ -38,8 +38,8 @@ class TransactionManager;
|
|
|
38
38
|
class ReplayState {
|
|
39
39
|
public:
|
|
40
40
|
ReplayState(AttachedDatabase &db, ClientContext &context, Deserializer &source)
|
|
41
|
-
: db(db), context(context), catalog(
|
|
42
|
-
|
|
41
|
+
: db(db), context(context), catalog(db.GetCatalog()), source(source), current_table(nullptr),
|
|
42
|
+
deserialize_only(false), checkpoint_id(INVALID_BLOCK) {
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
AttachedDatabase &db;
|
|
@@ -9,11 +9,11 @@ Block::Block(Allocator &allocator, block_id_t id)
|
|
|
9
9
|
|
|
10
10
|
Block::Block(Allocator &allocator, block_id_t id, uint32_t internal_size)
|
|
11
11
|
: FileBuffer(allocator, FileBufferType::BLOCK, internal_size), id(id) {
|
|
12
|
-
D_ASSERT((
|
|
12
|
+
D_ASSERT((AllocSize() & (Storage::SECTOR_SIZE - 1)) == 0);
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
Block::Block(FileBuffer &source, block_id_t id) : FileBuffer(source, FileBufferType::BLOCK), id(id) {
|
|
16
|
-
D_ASSERT((
|
|
16
|
+
D_ASSERT((AllocSize() & (Storage::SECTOR_SIZE - 1)) == 0);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
} // namespace duckdb
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#include "duckdb/storage/single_file_block_manager.hpp"
|
|
2
2
|
|
|
3
3
|
#include "duckdb/common/allocator.hpp"
|
|
4
|
+
#include "duckdb/common/checksum.hpp"
|
|
4
5
|
#include "duckdb/common/exception.hpp"
|
|
5
6
|
#include "duckdb/common/serializer/buffered_deserializer.hpp"
|
|
6
7
|
#include "duckdb/common/serializer/buffered_serializer.hpp"
|
|
@@ -142,7 +143,7 @@ SingleFileBlockManager::SingleFileBlockManager(AttachedDatabase &db, string path
|
|
|
142
143
|
|
|
143
144
|
SerializeHeaderStructure<MainHeader>(main_header, header_buffer.buffer);
|
|
144
145
|
// now write the header to the file
|
|
145
|
-
|
|
146
|
+
ChecksumAndWrite(header_buffer, 0);
|
|
146
147
|
header_buffer.Clear();
|
|
147
148
|
|
|
148
149
|
// write the database headers
|
|
@@ -155,14 +156,14 @@ SingleFileBlockManager::SingleFileBlockManager(AttachedDatabase &db, string path
|
|
|
155
156
|
h1.free_list = INVALID_BLOCK;
|
|
156
157
|
h1.block_count = 0;
|
|
157
158
|
SerializeHeaderStructure<DatabaseHeader>(h1, header_buffer.buffer);
|
|
158
|
-
|
|
159
|
+
ChecksumAndWrite(header_buffer, Storage::FILE_HEADER_SIZE);
|
|
159
160
|
// header 2
|
|
160
161
|
h2.iteration = 0;
|
|
161
162
|
h2.meta_block = INVALID_BLOCK;
|
|
162
163
|
h2.free_list = INVALID_BLOCK;
|
|
163
164
|
h2.block_count = 0;
|
|
164
165
|
SerializeHeaderStructure<DatabaseHeader>(h2, header_buffer.buffer);
|
|
165
|
-
|
|
166
|
+
ChecksumAndWrite(header_buffer, Storage::FILE_HEADER_SIZE * 2);
|
|
166
167
|
// ensure that writing to disk is completed before returning
|
|
167
168
|
handle->Sync();
|
|
168
169
|
// we start with h2 as active_header, this way our initial write will be in h1
|
|
@@ -172,14 +173,14 @@ SingleFileBlockManager::SingleFileBlockManager(AttachedDatabase &db, string path
|
|
|
172
173
|
} else {
|
|
173
174
|
MainHeader::CheckMagicBytes(*handle);
|
|
174
175
|
// otherwise, we check the metadata of the file
|
|
175
|
-
|
|
176
|
+
ReadAndChecksum(header_buffer, 0);
|
|
176
177
|
DeserializeHeaderStructure<MainHeader>(header_buffer.buffer);
|
|
177
178
|
|
|
178
179
|
// read the database headers from disk
|
|
179
180
|
DatabaseHeader h1, h2;
|
|
180
|
-
|
|
181
|
+
ReadAndChecksum(header_buffer, Storage::FILE_HEADER_SIZE);
|
|
181
182
|
h1 = DeserializeHeaderStructure<DatabaseHeader>(header_buffer.buffer);
|
|
182
|
-
|
|
183
|
+
ReadAndChecksum(header_buffer, Storage::FILE_HEADER_SIZE * 2);
|
|
183
184
|
h2 = DeserializeHeaderStructure<DatabaseHeader>(header_buffer.buffer);
|
|
184
185
|
// check the header with the highest iteration count
|
|
185
186
|
if (h1.iteration > h2.iteration) {
|
|
@@ -195,6 +196,27 @@ SingleFileBlockManager::SingleFileBlockManager(AttachedDatabase &db, string path
|
|
|
195
196
|
}
|
|
196
197
|
}
|
|
197
198
|
|
|
199
|
+
void SingleFileBlockManager::ReadAndChecksum(FileBuffer &block, uint64_t location) const {
|
|
200
|
+
// read the buffer from disk
|
|
201
|
+
block.Read(*handle, location);
|
|
202
|
+
// compute the checksum
|
|
203
|
+
auto stored_checksum = Load<uint64_t>(block.InternalBuffer());
|
|
204
|
+
uint64_t computed_checksum = Checksum(block.buffer, block.size);
|
|
205
|
+
// verify the checksum
|
|
206
|
+
if (stored_checksum != computed_checksum) {
|
|
207
|
+
throw IOException("Corrupt database file: computed checksum %llu does not match stored checksum %llu in block",
|
|
208
|
+
computed_checksum, stored_checksum);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
void SingleFileBlockManager::ChecksumAndWrite(FileBuffer &block, uint64_t location) const {
|
|
213
|
+
// compute the checksum and write it to the start of the buffer (if not temp buffer)
|
|
214
|
+
uint64_t checksum = Checksum(block.buffer, block.size);
|
|
215
|
+
Store<uint64_t>(checksum, block.InternalBuffer());
|
|
216
|
+
// now write the buffer
|
|
217
|
+
block.Write(*handle, location);
|
|
218
|
+
}
|
|
219
|
+
|
|
198
220
|
void SingleFileBlockManager::Initialize(DatabaseHeader &header) {
|
|
199
221
|
free_list_id = header.free_list;
|
|
200
222
|
meta_block = header.meta_block;
|
|
@@ -317,12 +339,12 @@ unique_ptr<Block> SingleFileBlockManager::CreateBlock(block_id_t block_id, FileB
|
|
|
317
339
|
void SingleFileBlockManager::Read(Block &block) {
|
|
318
340
|
D_ASSERT(block.id >= 0);
|
|
319
341
|
D_ASSERT(std::find(free_list.begin(), free_list.end(), block.id) == free_list.end());
|
|
320
|
-
|
|
342
|
+
ReadAndChecksum(block, BLOCK_START + block.id * Storage::BLOCK_ALLOC_SIZE);
|
|
321
343
|
}
|
|
322
344
|
|
|
323
345
|
void SingleFileBlockManager::Write(FileBuffer &buffer, block_id_t block_id) {
|
|
324
346
|
D_ASSERT(block_id >= 0);
|
|
325
|
-
|
|
347
|
+
ChecksumAndWrite(buffer, BLOCK_START + block_id * Storage::BLOCK_ALLOC_SIZE);
|
|
326
348
|
}
|
|
327
349
|
|
|
328
350
|
vector<block_id_t> SingleFileBlockManager::GetFreeListBlocks() {
|
|
@@ -431,8 +453,7 @@ void SingleFileBlockManager::WriteHeader(DatabaseHeader header) {
|
|
|
431
453
|
Store<DatabaseHeader>(header, header_buffer.buffer);
|
|
432
454
|
// now write the header to the file, active_header determines whether we write to h1 or h2
|
|
433
455
|
// note that if active_header is h1 we write to h2, and vice versa
|
|
434
|
-
|
|
435
|
-
active_header == 1 ? Storage::FILE_HEADER_SIZE : Storage::FILE_HEADER_SIZE * 2);
|
|
456
|
+
ChecksumAndWrite(header_buffer, active_header == 1 ? Storage::FILE_HEADER_SIZE : Storage::FILE_HEADER_SIZE * 2);
|
|
436
457
|
// switch active header to the other header
|
|
437
458
|
active_header = 1 - active_header;
|
|
438
459
|
//! Ensure the header write ends up on disk
|