duckdb 0.5.2-dev275.0 → 0.5.2-dev289.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.cpp +127 -162
- package/src/duckdb.hpp +47 -57
- package/src/parquet-amalgamation.cpp +34991 -34991
package/package.json
CHANGED
package/src/duckdb.cpp
CHANGED
|
@@ -28634,7 +28634,7 @@ struct PartitionFunctor {
|
|
|
28634
28634
|
RowDataCollection &string_heap, RowDataBlock &data_block,
|
|
28635
28635
|
const data_ptr_t data_ptr, RowDataBlock &heap_block, BufferHandle &heap_handle) {
|
|
28636
28636
|
D_ASSERT(!layout.AllConstant());
|
|
28637
|
-
D_ASSERT(heap_block.block
|
|
28637
|
+
D_ASSERT(heap_block.block == heap_handle.GetBlockHandle());
|
|
28638
28638
|
D_ASSERT(data_block.count >= heap_block.count);
|
|
28639
28639
|
const auto count = data_block.count - heap_block.count;
|
|
28640
28640
|
if (count == 0) {
|
|
@@ -37411,7 +37411,7 @@ void SBScanState::PinRadix(idx_t block_idx_to) {
|
|
|
37411
37411
|
auto &radix_sorting_data = sb->radix_sorting_data;
|
|
37412
37412
|
D_ASSERT(block_idx_to < radix_sorting_data.size());
|
|
37413
37413
|
auto &block = radix_sorting_data[block_idx_to];
|
|
37414
|
-
if (!radix_handle.IsValid() || radix_handle.
|
|
37414
|
+
if (!radix_handle.IsValid() || radix_handle.GetBlockHandle() != block->block) {
|
|
37415
37415
|
radix_handle = buffer_manager.Pin(block->block);
|
|
37416
37416
|
}
|
|
37417
37417
|
}
|
|
@@ -37422,14 +37422,14 @@ void SBScanState::PinData(SortedData &sd) {
|
|
|
37422
37422
|
auto &heap_handle = sd.type == SortedDataType::BLOB ? blob_sorting_heap_handle : payload_heap_handle;
|
|
37423
37423
|
|
|
37424
37424
|
auto &data_block = sd.data_blocks[block_idx];
|
|
37425
|
-
if (!data_handle.IsValid() || data_handle.
|
|
37425
|
+
if (!data_handle.IsValid() || data_handle.GetBlockHandle() != data_block->block) {
|
|
37426
37426
|
data_handle = buffer_manager.Pin(data_block->block);
|
|
37427
37427
|
}
|
|
37428
37428
|
if (sd.layout.AllConstant() || !state.external) {
|
|
37429
37429
|
return;
|
|
37430
37430
|
}
|
|
37431
37431
|
auto &heap_block = sd.heap_blocks[block_idx];
|
|
37432
|
-
if (!heap_handle.IsValid() || heap_handle.
|
|
37432
|
+
if (!heap_handle.IsValid() || heap_handle.GetBlockHandle() != heap_block->block) {
|
|
37433
37433
|
heap_handle = buffer_manager.Pin(heap_block->block);
|
|
37434
37434
|
}
|
|
37435
37435
|
}
|
|
@@ -37441,7 +37441,7 @@ data_ptr_t SBScanState::RadixPtr() const {
|
|
|
37441
37441
|
data_ptr_t SBScanState::DataPtr(SortedData &sd) const {
|
|
37442
37442
|
auto &data_handle = sd.type == SortedDataType::BLOB ? blob_sorting_data_handle : payload_data_handle;
|
|
37443
37443
|
D_ASSERT(sd.data_blocks[block_idx]->block->Readers() != 0 &&
|
|
37444
|
-
data_handle.
|
|
37444
|
+
data_handle.GetBlockHandle() == sd.data_blocks[block_idx]->block);
|
|
37445
37445
|
return data_handle.Ptr() + entry_idx * sd.layout.GetRowWidth();
|
|
37446
37446
|
}
|
|
37447
37447
|
|
|
@@ -37453,7 +37453,7 @@ data_ptr_t SBScanState::BaseHeapPtr(SortedData &sd) const {
|
|
|
37453
37453
|
auto &heap_handle = sd.type == SortedDataType::BLOB ? blob_sorting_heap_handle : payload_heap_handle;
|
|
37454
37454
|
D_ASSERT(!sd.layout.AllConstant() && state.external);
|
|
37455
37455
|
D_ASSERT(sd.heap_blocks[block_idx]->block->Readers() != 0 &&
|
|
37456
|
-
heap_handle.
|
|
37456
|
+
heap_handle.GetBlockHandle() == sd.heap_blocks[block_idx]->block);
|
|
37457
37457
|
return heap_handle.Ptr();
|
|
37458
37458
|
}
|
|
37459
37459
|
|
|
@@ -45233,7 +45233,7 @@ void RowDataCollectionScanner::ScanState::PinData() {
|
|
|
45233
45233
|
auto &rows = scanner.rows;
|
|
45234
45234
|
D_ASSERT(block_idx < rows.blocks.size());
|
|
45235
45235
|
auto &data_block = rows.blocks[block_idx];
|
|
45236
|
-
if (!data_handle.IsValid() || data_handle.
|
|
45236
|
+
if (!data_handle.IsValid() || data_handle.GetBlockHandle() != data_block->block) {
|
|
45237
45237
|
data_handle = rows.buffer_manager.Pin(data_block->block);
|
|
45238
45238
|
}
|
|
45239
45239
|
if (scanner.layout.AllConstant() || !scanner.external) {
|
|
@@ -45243,7 +45243,7 @@ void RowDataCollectionScanner::ScanState::PinData() {
|
|
|
45243
45243
|
auto &heap = scanner.heap;
|
|
45244
45244
|
D_ASSERT(block_idx < heap.blocks.size());
|
|
45245
45245
|
auto &heap_block = heap.blocks[block_idx];
|
|
45246
|
-
if (!heap_handle.IsValid() || heap_handle.
|
|
45246
|
+
if (!heap_handle.IsValid() || heap_handle.GetBlockHandle() != heap_block->block) {
|
|
45247
45247
|
heap_handle = heap.buffer_manager.Pin(heap_block->block);
|
|
45248
45248
|
}
|
|
45249
45249
|
}
|
|
@@ -191560,17 +191560,11 @@ data_ptr_t BufferHandle::Ptr() {
|
|
|
191560
191560
|
return node->buffer;
|
|
191561
191561
|
}
|
|
191562
191562
|
|
|
191563
|
-
block_id_t BufferHandle::GetBlockId() const {
|
|
191564
|
-
D_ASSERT(handle);
|
|
191565
|
-
return handle->BlockId();
|
|
191566
|
-
}
|
|
191567
|
-
|
|
191568
191563
|
void BufferHandle::Destroy() {
|
|
191569
191564
|
if (!handle || !IsValid()) {
|
|
191570
191565
|
return;
|
|
191571
191566
|
}
|
|
191572
|
-
|
|
191573
|
-
buffer_manager.Unpin(handle);
|
|
191567
|
+
handle->block_manager.buffer_manager.Unpin(handle);
|
|
191574
191568
|
handle.reset();
|
|
191575
191569
|
node = nullptr;
|
|
191576
191570
|
}
|
|
@@ -191586,27 +191580,6 @@ FileBuffer &BufferHandle::GetFileBuffer() {
|
|
|
191586
191580
|
|
|
191587
191581
|
|
|
191588
191582
|
|
|
191589
|
-
|
|
191590
|
-
namespace duckdb {
|
|
191591
|
-
|
|
191592
|
-
ManagedBuffer::ManagedBuffer(DatabaseInstance &db, idx_t size, bool can_destroy, block_id_t id)
|
|
191593
|
-
: FileBuffer(Allocator::Get(db), FileBufferType::MANAGED_BUFFER, size), db(db), can_destroy(can_destroy), id(id) {
|
|
191594
|
-
D_ASSERT(id >= MAXIMUM_BLOCK);
|
|
191595
|
-
D_ASSERT(size >= Storage::BLOCK_SIZE);
|
|
191596
|
-
}
|
|
191597
|
-
|
|
191598
|
-
ManagedBuffer::ManagedBuffer(DatabaseInstance &db, FileBuffer &source, bool can_destroy, block_id_t id)
|
|
191599
|
-
: FileBuffer(source, FileBufferType::MANAGED_BUFFER), db(db), can_destroy(can_destroy), id(id) {
|
|
191600
|
-
D_ASSERT(id >= MAXIMUM_BLOCK);
|
|
191601
|
-
D_ASSERT(size >= Storage::BLOCK_SIZE);
|
|
191602
|
-
}
|
|
191603
|
-
|
|
191604
|
-
} // namespace duckdb
|
|
191605
|
-
|
|
191606
|
-
|
|
191607
|
-
|
|
191608
|
-
|
|
191609
|
-
|
|
191610
191583
|
//===----------------------------------------------------------------------===//
|
|
191611
191584
|
// DuckDB
|
|
191612
191585
|
//
|
|
@@ -191682,6 +191655,68 @@ public:
|
|
|
191682
191655
|
#endif
|
|
191683
191656
|
|
|
191684
191657
|
|
|
191658
|
+
//===----------------------------------------------------------------------===//
|
|
191659
|
+
// DuckDB
|
|
191660
|
+
//
|
|
191661
|
+
// duckdb/storage/in_memory_block_manager.hpp
|
|
191662
|
+
//
|
|
191663
|
+
//
|
|
191664
|
+
//===----------------------------------------------------------------------===//
|
|
191665
|
+
|
|
191666
|
+
|
|
191667
|
+
|
|
191668
|
+
|
|
191669
|
+
|
|
191670
|
+
|
|
191671
|
+
|
|
191672
|
+
namespace duckdb {
|
|
191673
|
+
|
|
191674
|
+
//! InMemoryBlockManager is an implementation for a BlockManager
|
|
191675
|
+
class InMemoryBlockManager : public BlockManager {
|
|
191676
|
+
public:
|
|
191677
|
+
using BlockManager::BlockManager;
|
|
191678
|
+
|
|
191679
|
+
// LCOV_EXCL_START
|
|
191680
|
+
void StartCheckpoint() override {
|
|
191681
|
+
throw InternalException("Cannot perform IO in in-memory database!");
|
|
191682
|
+
}
|
|
191683
|
+
unique_ptr<Block> CreateBlock(block_id_t block_id) override {
|
|
191684
|
+
throw InternalException("Cannot perform IO in in-memory database!");
|
|
191685
|
+
}
|
|
191686
|
+
block_id_t GetFreeBlockId() override {
|
|
191687
|
+
throw InternalException("Cannot perform IO in in-memory database!");
|
|
191688
|
+
}
|
|
191689
|
+
bool IsRootBlock(block_id_t root) override {
|
|
191690
|
+
throw InternalException("Cannot perform IO in in-memory database!");
|
|
191691
|
+
}
|
|
191692
|
+
void MarkBlockAsModified(block_id_t block_id) override {
|
|
191693
|
+
throw InternalException("Cannot perform IO in in-memory database!");
|
|
191694
|
+
}
|
|
191695
|
+
void IncreaseBlockReferenceCount(block_id_t block_id) override {
|
|
191696
|
+
throw InternalException("Cannot perform IO in in-memory database!");
|
|
191697
|
+
}
|
|
191698
|
+
block_id_t GetMetaBlock() override {
|
|
191699
|
+
throw InternalException("Cannot perform IO in in-memory database!");
|
|
191700
|
+
}
|
|
191701
|
+
void Read(Block &block) override {
|
|
191702
|
+
throw InternalException("Cannot perform IO in in-memory database!");
|
|
191703
|
+
}
|
|
191704
|
+
void Write(FileBuffer &block, block_id_t block_id) override {
|
|
191705
|
+
throw InternalException("Cannot perform IO in in-memory database!");
|
|
191706
|
+
}
|
|
191707
|
+
void WriteHeader(DatabaseHeader header) override {
|
|
191708
|
+
throw InternalException("Cannot perform IO in in-memory database!");
|
|
191709
|
+
}
|
|
191710
|
+
idx_t TotalBlocks() override {
|
|
191711
|
+
throw InternalException("Cannot perform IO in in-memory database!");
|
|
191712
|
+
}
|
|
191713
|
+
idx_t FreeBlocks() override {
|
|
191714
|
+
throw InternalException("Cannot perform IO in in-memory database!");
|
|
191715
|
+
}
|
|
191716
|
+
// LCOV_EXCL_STOP
|
|
191717
|
+
};
|
|
191718
|
+
} // namespace duckdb
|
|
191719
|
+
|
|
191685
191720
|
|
|
191686
191721
|
namespace duckdb {
|
|
191687
191722
|
|
|
@@ -191692,17 +191727,18 @@ struct BufferAllocatorData : PrivateAllocatorData {
|
|
|
191692
191727
|
BufferManager &manager;
|
|
191693
191728
|
};
|
|
191694
191729
|
|
|
191695
|
-
BlockHandle::BlockHandle(
|
|
191696
|
-
:
|
|
191697
|
-
unswizzled(nullptr) {
|
|
191730
|
+
BlockHandle::BlockHandle(BlockManager &block_manager, block_id_t block_id_p)
|
|
191731
|
+
: block_manager(block_manager), readers(0), block_id(block_id_p), buffer(nullptr), eviction_timestamp(0),
|
|
191732
|
+
can_destroy(false), unswizzled(nullptr) {
|
|
191698
191733
|
eviction_timestamp = 0;
|
|
191699
191734
|
state = BlockState::BLOCK_UNLOADED;
|
|
191700
191735
|
memory_usage = Storage::BLOCK_ALLOC_SIZE;
|
|
191701
191736
|
}
|
|
191702
191737
|
|
|
191703
|
-
BlockHandle::BlockHandle(
|
|
191738
|
+
BlockHandle::BlockHandle(BlockManager &block_manager, block_id_t block_id_p, unique_ptr<FileBuffer> buffer_p,
|
|
191704
191739
|
bool can_destroy_p, idx_t block_size)
|
|
191705
|
-
:
|
|
191740
|
+
: block_manager(block_manager), readers(0), block_id(block_id_p), eviction_timestamp(0), can_destroy(can_destroy_p),
|
|
191741
|
+
unswizzled(nullptr) {
|
|
191706
191742
|
D_ASSERT(block_size >= Storage::BLOCK_SIZE);
|
|
191707
191743
|
buffer = move(buffer_p);
|
|
191708
191744
|
state = BlockState::BLOCK_LOADED;
|
|
@@ -191710,16 +191746,16 @@ BlockHandle::BlockHandle(DatabaseInstance &db, block_id_t block_id_p, unique_ptr
|
|
|
191710
191746
|
}
|
|
191711
191747
|
|
|
191712
191748
|
BlockHandle::~BlockHandle() {
|
|
191713
|
-
auto &buffer_manager = BufferManager::GetBufferManager(db);
|
|
191714
191749
|
// being destroyed, so any unswizzled pointers are just binary junk now.
|
|
191715
191750
|
unswizzled = nullptr;
|
|
191751
|
+
auto &buffer_manager = block_manager.buffer_manager;
|
|
191716
191752
|
// no references remain to this block: erase
|
|
191717
191753
|
if (state == BlockState::BLOCK_LOADED) {
|
|
191718
191754
|
// the block is still loaded in memory: erase it
|
|
191719
191755
|
buffer.reset();
|
|
191720
191756
|
buffer_manager.current_memory -= memory_usage;
|
|
191721
191757
|
}
|
|
191722
|
-
|
|
191758
|
+
block_manager.UnregisterBlock(block_id, can_destroy);
|
|
191723
191759
|
}
|
|
191724
191760
|
|
|
191725
191761
|
unique_ptr<Block> AllocateBlock(Allocator &allocator, unique_ptr<FileBuffer> reusable_buffer, block_id_t block_id) {
|
|
@@ -191740,23 +191776,13 @@ unique_ptr<Block> AllocateBlock(Allocator &allocator, unique_ptr<FileBuffer> reu
|
|
|
191740
191776
|
}
|
|
191741
191777
|
}
|
|
191742
191778
|
|
|
191743
|
-
unique_ptr<
|
|
191744
|
-
idx_t size, bool can_destroy, block_id_t id) {
|
|
191779
|
+
unique_ptr<FileBuffer> AllocateManagedBuffer(DatabaseInstance &db, unique_ptr<FileBuffer> reusable_buffer, idx_t size) {
|
|
191745
191780
|
if (reusable_buffer) {
|
|
191746
|
-
|
|
191747
|
-
|
|
191748
|
-
// we can reuse the buffer entirely
|
|
191749
|
-
auto &managed = (ManagedBuffer &)*reusable_buffer;
|
|
191750
|
-
managed.id = id;
|
|
191751
|
-
managed.can_destroy = can_destroy;
|
|
191752
|
-
return unique_ptr_cast<FileBuffer, ManagedBuffer>(move(reusable_buffer));
|
|
191753
|
-
}
|
|
191754
|
-
auto buffer = make_unique<ManagedBuffer>(db, *reusable_buffer, can_destroy, id);
|
|
191755
|
-
reusable_buffer.reset();
|
|
191756
|
-
return buffer;
|
|
191781
|
+
auto tmp = move(reusable_buffer);
|
|
191782
|
+
return make_unique<FileBuffer>(*tmp, FileBufferType::MANAGED_BUFFER);
|
|
191757
191783
|
} else {
|
|
191758
191784
|
// no re-usable buffer: allocate a new buffer
|
|
191759
|
-
return make_unique<
|
|
191785
|
+
return make_unique<FileBuffer>(Allocator::Get(db), FileBufferType::MANAGED_BUFFER, size);
|
|
191760
191786
|
}
|
|
191761
191787
|
}
|
|
191762
191788
|
|
|
@@ -191767,17 +191793,17 @@ BufferHandle BlockHandle::Load(shared_ptr<BlockHandle> &handle, unique_ptr<FileB
|
|
|
191767
191793
|
return BufferHandle(handle, handle->buffer.get());
|
|
191768
191794
|
}
|
|
191769
191795
|
|
|
191770
|
-
auto &
|
|
191771
|
-
auto &block_manager = BlockManager::GetBlockManager(handle->db);
|
|
191796
|
+
auto &block_manager = handle->block_manager;
|
|
191772
191797
|
if (handle->block_id < MAXIMUM_BLOCK) {
|
|
191773
|
-
auto block = AllocateBlock(Allocator::Get(
|
|
191798
|
+
auto block = AllocateBlock(Allocator::Get(block_manager.buffer_manager.GetDatabase()), move(reusable_buffer),
|
|
191799
|
+
handle->block_id);
|
|
191774
191800
|
block_manager.Read(*block);
|
|
191775
191801
|
handle->buffer = move(block);
|
|
191776
191802
|
} else {
|
|
191777
191803
|
if (handle->can_destroy) {
|
|
191778
191804
|
return BufferHandle();
|
|
191779
191805
|
} else {
|
|
191780
|
-
handle->buffer = buffer_manager.ReadTemporaryBuffer(handle->block_id, move(reusable_buffer));
|
|
191806
|
+
handle->buffer = block_manager.buffer_manager.ReadTemporaryBuffer(handle->block_id, move(reusable_buffer));
|
|
191781
191807
|
}
|
|
191782
191808
|
}
|
|
191783
191809
|
handle->state = BlockState::BLOCK_LOADED;
|
|
@@ -191785,7 +191811,6 @@ BufferHandle BlockHandle::Load(shared_ptr<BlockHandle> &handle, unique_ptr<FileB
|
|
|
191785
191811
|
}
|
|
191786
191812
|
|
|
191787
191813
|
unique_ptr<FileBuffer> BlockHandle::UnloadAndTakeBlock() {
|
|
191788
|
-
auto &buffer_manager = BufferManager::GetBufferManager(db);
|
|
191789
191814
|
if (state == BlockState::BLOCK_UNLOADED) {
|
|
191790
191815
|
// already unloaded: nothing to do
|
|
191791
191816
|
return nullptr;
|
|
@@ -191796,9 +191821,9 @@ unique_ptr<FileBuffer> BlockHandle::UnloadAndTakeBlock() {
|
|
|
191796
191821
|
|
|
191797
191822
|
if (block_id >= MAXIMUM_BLOCK && !can_destroy) {
|
|
191798
191823
|
// temporary block that cannot be destroyed: write to temporary file
|
|
191799
|
-
buffer_manager.WriteTemporaryBuffer(
|
|
191824
|
+
block_manager.buffer_manager.WriteTemporaryBuffer(block_id, *buffer);
|
|
191800
191825
|
}
|
|
191801
|
-
buffer_manager.current_memory -= memory_usage;
|
|
191826
|
+
block_manager.buffer_manager.current_memory -= memory_usage;
|
|
191802
191827
|
state = BlockState::BLOCK_UNLOADED;
|
|
191803
191828
|
return move(buffer);
|
|
191804
191829
|
}
|
|
@@ -191817,8 +191842,7 @@ bool BlockHandle::CanUnload() {
|
|
|
191817
191842
|
// there are active readers
|
|
191818
191843
|
return false;
|
|
191819
191844
|
}
|
|
191820
|
-
|
|
191821
|
-
if (block_id >= MAXIMUM_BLOCK && !can_destroy && buffer_manager.temp_directory.empty()) {
|
|
191845
|
+
if (block_id >= MAXIMUM_BLOCK && !can_destroy && block_manager.buffer_manager.temp_directory.empty()) {
|
|
191822
191846
|
// in order to unload this block we need to write it to a temporary buffer
|
|
191823
191847
|
// however, no temporary directory is specified!
|
|
191824
191848
|
// hence we cannot unload the block
|
|
@@ -191894,12 +191918,13 @@ BufferManager::BufferManager(DatabaseInstance &db, string tmp, idx_t maximum_mem
|
|
|
191894
191918
|
queue(make_unique<EvictionQueue>()), temporary_id(MAXIMUM_BLOCK),
|
|
191895
191919
|
buffer_allocator(BufferAllocatorAllocate, BufferAllocatorFree, BufferAllocatorRealloc,
|
|
191896
191920
|
make_unique<BufferAllocatorData>(*this)) {
|
|
191921
|
+
temp_block_manager = make_unique<InMemoryBlockManager>(*this);
|
|
191897
191922
|
}
|
|
191898
191923
|
|
|
191899
191924
|
BufferManager::~BufferManager() {
|
|
191900
191925
|
}
|
|
191901
191926
|
|
|
191902
|
-
shared_ptr<BlockHandle>
|
|
191927
|
+
shared_ptr<BlockHandle> BlockManager::RegisterBlock(block_id_t block_id) {
|
|
191903
191928
|
lock_guard<mutex> lock(blocks_lock);
|
|
191904
191929
|
// check if the block already exists
|
|
191905
191930
|
auto entry = blocks.find(block_id);
|
|
@@ -191912,17 +191937,16 @@ shared_ptr<BlockHandle> BufferManager::RegisterBlock(block_id_t block_id) {
|
|
|
191912
191937
|
}
|
|
191913
191938
|
}
|
|
191914
191939
|
// create a new block pointer for this block
|
|
191915
|
-
auto result = make_shared<BlockHandle>(
|
|
191940
|
+
auto result = make_shared<BlockHandle>(*this, block_id);
|
|
191916
191941
|
// register the block pointer in the set of blocks as a weak pointer
|
|
191917
191942
|
blocks[block_id] = weak_ptr<BlockHandle>(result);
|
|
191918
191943
|
return result;
|
|
191919
191944
|
}
|
|
191920
191945
|
|
|
191921
|
-
shared_ptr<BlockHandle>
|
|
191922
|
-
shared_ptr<BlockHandle> old_block) {
|
|
191946
|
+
shared_ptr<BlockHandle> BlockManager::ConvertToPersistent(block_id_t block_id, shared_ptr<BlockHandle> old_block) {
|
|
191923
191947
|
|
|
191924
191948
|
// pin the old block to ensure we have it loaded in memory
|
|
191925
|
-
auto old_handle = Pin(old_block);
|
|
191949
|
+
auto old_handle = buffer_manager.Pin(old_block);
|
|
191926
191950
|
D_ASSERT(old_block->state == BlockState::BLOCK_LOADED);
|
|
191927
191951
|
D_ASSERT(old_block->buffer);
|
|
191928
191952
|
|
|
@@ -191943,9 +191967,9 @@ shared_ptr<BlockHandle> BufferManager::ConvertToPersistent(BlockManager &block_m
|
|
|
191943
191967
|
old_block.reset();
|
|
191944
191968
|
|
|
191945
191969
|
// persist the new block to disk
|
|
191946
|
-
|
|
191970
|
+
Write(*new_block->buffer, block_id);
|
|
191947
191971
|
|
|
191948
|
-
AddToEvictionQueue(new_block);
|
|
191972
|
+
buffer_manager.AddToEvictionQueue(new_block);
|
|
191949
191973
|
|
|
191950
191974
|
return new_block;
|
|
191951
191975
|
}
|
|
@@ -191959,11 +191983,10 @@ shared_ptr<BlockHandle> BufferManager::RegisterMemory(idx_t block_size, bool can
|
|
|
191959
191983
|
GetUsedMemory(), GetMaxMemory(), InMemoryWarning());
|
|
191960
191984
|
}
|
|
191961
191985
|
|
|
191962
|
-
auto
|
|
191963
|
-
auto buffer = AllocateManagedBuffer(db, move(reusable_buffer), block_size, can_destroy, temp_id);
|
|
191986
|
+
auto buffer = AllocateManagedBuffer(db, move(reusable_buffer), block_size);
|
|
191964
191987
|
|
|
191965
191988
|
// create a new block pointer for this block
|
|
191966
|
-
return make_shared<BlockHandle>(
|
|
191989
|
+
return make_shared<BlockHandle>(*temp_block_manager, ++temporary_id, move(buffer), can_destroy, block_size);
|
|
191967
191990
|
}
|
|
191968
191991
|
|
|
191969
191992
|
BufferHandle BufferManager::Allocate(idx_t block_size) {
|
|
@@ -192095,12 +192118,12 @@ void BufferManager::PurgeQueue() {
|
|
|
192095
192118
|
}
|
|
192096
192119
|
}
|
|
192097
192120
|
|
|
192098
|
-
void
|
|
192121
|
+
void BlockManager::UnregisterBlock(block_id_t block_id, bool can_destroy) {
|
|
192099
192122
|
if (block_id >= MAXIMUM_BLOCK) {
|
|
192100
192123
|
// in-memory buffer: destroy the buffer
|
|
192101
192124
|
if (!can_destroy) {
|
|
192102
192125
|
// buffer could have been offloaded to disk: remove the file
|
|
192103
|
-
DeleteTemporaryFile(block_id);
|
|
192126
|
+
buffer_manager.DeleteTemporaryFile(block_id);
|
|
192104
192127
|
}
|
|
192105
192128
|
} else {
|
|
192106
192129
|
lock_guard<mutex> lock(blocks_lock);
|
|
@@ -192108,6 +192131,7 @@ void BufferManager::UnregisterBlock(block_id_t block_id, bool can_destroy) {
|
|
|
192108
192131
|
blocks.erase(block_id);
|
|
192109
192132
|
}
|
|
192110
192133
|
}
|
|
192134
|
+
|
|
192111
192135
|
void BufferManager::SetLimit(idx_t limit) {
|
|
192112
192136
|
lock_guard<mutex> l_lock(limit_lock);
|
|
192113
192137
|
// try to evict until the limit is reached
|
|
@@ -192132,10 +192156,9 @@ void BufferManager::SetLimit(idx_t limit) {
|
|
|
192132
192156
|
//===--------------------------------------------------------------------===//
|
|
192133
192157
|
// Temporary File Management
|
|
192134
192158
|
//===--------------------------------------------------------------------===//
|
|
192135
|
-
unique_ptr<
|
|
192136
|
-
|
|
192137
|
-
|
|
192138
|
-
auto buffer = AllocateManagedBuffer(db, move(reusable_buffer), size, false, id);
|
|
192159
|
+
unique_ptr<FileBuffer> ReadTemporaryBufferInternal(DatabaseInstance &db, FileHandle &handle, idx_t position, idx_t size,
|
|
192160
|
+
unique_ptr<FileBuffer> reusable_buffer) {
|
|
192161
|
+
auto buffer = AllocateManagedBuffer(db, move(reusable_buffer), size);
|
|
192139
192162
|
buffer->Read(handle, position);
|
|
192140
192163
|
return buffer;
|
|
192141
192164
|
}
|
|
@@ -192249,14 +192272,14 @@ public:
|
|
|
192249
192272
|
return TemporaryFileIndex(file_index, block_index);
|
|
192250
192273
|
}
|
|
192251
192274
|
|
|
192252
|
-
void WriteTemporaryFile(
|
|
192275
|
+
void WriteTemporaryFile(FileBuffer &buffer, TemporaryFileIndex index) {
|
|
192253
192276
|
D_ASSERT(buffer.size == Storage::BLOCK_SIZE);
|
|
192254
192277
|
buffer.Write(*handle, GetPositionInFile(index.block_index));
|
|
192255
192278
|
}
|
|
192256
192279
|
|
|
192257
192280
|
unique_ptr<FileBuffer> ReadTemporaryBuffer(block_id_t id, idx_t block_index,
|
|
192258
192281
|
unique_ptr<FileBuffer> reusable_buffer) {
|
|
192259
|
-
auto buffer = ReadTemporaryBufferInternal(db, *handle, GetPositionInFile(block_index), Storage::BLOCK_SIZE,
|
|
192282
|
+
auto buffer = ReadTemporaryBufferInternal(db, *handle, GetPositionInFile(block_index), Storage::BLOCK_SIZE,
|
|
192260
192283
|
move(reusable_buffer));
|
|
192261
192284
|
{
|
|
192262
192285
|
// remove the block (and potentially truncate the temp file)
|
|
@@ -192264,7 +192287,7 @@ public:
|
|
|
192264
192287
|
D_ASSERT(handle);
|
|
192265
192288
|
RemoveTempBlockIndex(lock, block_index);
|
|
192266
192289
|
}
|
|
192267
|
-
return
|
|
192290
|
+
return buffer;
|
|
192268
192291
|
}
|
|
192269
192292
|
|
|
192270
192293
|
bool DeleteIfEmpty() {
|
|
@@ -192328,7 +192351,7 @@ public:
|
|
|
192328
192351
|
lock_guard<mutex> lock;
|
|
192329
192352
|
};
|
|
192330
192353
|
|
|
192331
|
-
void WriteTemporaryBuffer(
|
|
192354
|
+
void WriteTemporaryBuffer(block_id_t block_id, FileBuffer &buffer) {
|
|
192332
192355
|
D_ASSERT(buffer.size == Storage::BLOCK_SIZE);
|
|
192333
192356
|
TemporaryFileIndex index;
|
|
192334
192357
|
TemporaryFileHandle *handle = nullptr;
|
|
@@ -192353,8 +192376,8 @@ public:
|
|
|
192353
192376
|
|
|
192354
192377
|
index = handle->TryGetBlockIndex();
|
|
192355
192378
|
}
|
|
192356
|
-
D_ASSERT(used_blocks.find(
|
|
192357
|
-
used_blocks[
|
|
192379
|
+
D_ASSERT(used_blocks.find(block_id) == used_blocks.end());
|
|
192380
|
+
used_blocks[block_id] = index;
|
|
192358
192381
|
}
|
|
192359
192382
|
D_ASSERT(handle);
|
|
192360
192383
|
D_ASSERT(index.IsValid());
|
|
@@ -192464,16 +192487,16 @@ void BufferManager::RequireTemporaryDirectory() {
|
|
|
192464
192487
|
}
|
|
192465
192488
|
}
|
|
192466
192489
|
|
|
192467
|
-
void BufferManager::WriteTemporaryBuffer(
|
|
192490
|
+
void BufferManager::WriteTemporaryBuffer(block_id_t block_id, FileBuffer &buffer) {
|
|
192468
192491
|
RequireTemporaryDirectory();
|
|
192469
192492
|
if (buffer.size == Storage::BLOCK_SIZE) {
|
|
192470
|
-
temp_directory_handle->GetTempFile().WriteTemporaryBuffer(buffer);
|
|
192493
|
+
temp_directory_handle->GetTempFile().WriteTemporaryBuffer(block_id, buffer);
|
|
192471
192494
|
return;
|
|
192472
192495
|
}
|
|
192473
192496
|
|
|
192474
192497
|
D_ASSERT(buffer.size > Storage::BLOCK_SIZE);
|
|
192475
192498
|
// get the path to write to
|
|
192476
|
-
auto path = GetTemporaryPath(
|
|
192499
|
+
auto path = GetTemporaryPath(block_id);
|
|
192477
192500
|
// create the file and write the size followed by the buffer contents
|
|
192478
192501
|
auto &fs = FileSystem::GetFileSystem(db);
|
|
192479
192502
|
auto handle = fs.OpenFile(path, FileFlags::FILE_FLAGS_WRITE | FileFlags::FILE_FLAGS_FILE_CREATE);
|
|
@@ -192495,11 +192518,11 @@ unique_ptr<FileBuffer> BufferManager::ReadTemporaryBuffer(block_id_t id, unique_
|
|
|
192495
192518
|
handle->Read(&block_size, sizeof(idx_t), 0);
|
|
192496
192519
|
|
|
192497
192520
|
// now allocate a buffer of this size and read the data into that buffer
|
|
192498
|
-
auto buffer = ReadTemporaryBufferInternal(db, *handle, sizeof(idx_t), block_size,
|
|
192521
|
+
auto buffer = ReadTemporaryBufferInternal(db, *handle, sizeof(idx_t), block_size, move(reusable_buffer));
|
|
192499
192522
|
|
|
192500
192523
|
handle.reset();
|
|
192501
192524
|
DeleteTemporaryFile(id);
|
|
192502
|
-
return
|
|
192525
|
+
return buffer;
|
|
192503
192526
|
}
|
|
192504
192527
|
|
|
192505
192528
|
void BufferManager::DeleteTemporaryFile(block_id_t id) {
|
|
@@ -193527,12 +193550,11 @@ void CheckpointManager::FlushPartialSegments() {
|
|
|
193527
193550
|
}
|
|
193528
193551
|
|
|
193529
193552
|
void PartialBlock::FlushToDisk(DatabaseInstance &db) {
|
|
193530
|
-
auto &buffer_manager = BufferManager::GetBufferManager(db);
|
|
193531
193553
|
auto &block_manager = BlockManager::GetBlockManager(db);
|
|
193532
193554
|
|
|
193533
193555
|
// the data for the block might already exists in-memory of our block
|
|
193534
193556
|
// instead of copying the data we alter some metadata so the buffer points to an on-disk block
|
|
193535
|
-
block =
|
|
193557
|
+
block = block_manager.ConvertToPersistent(block_id, move(block));
|
|
193536
193558
|
|
|
193537
193559
|
// now set this block as the block for all segments
|
|
193538
193560
|
for (auto &seg : segments) {
|
|
@@ -197750,12 +197772,13 @@ string_t UncompressedStringStorage::ReadOverflowString(ColumnSegment &segment, V
|
|
|
197750
197772
|
D_ASSERT(block != INVALID_BLOCK);
|
|
197751
197773
|
D_ASSERT(offset < Storage::BLOCK_SIZE);
|
|
197752
197774
|
|
|
197775
|
+
auto &block_manager = BlockManager::GetBlockManager(segment.db);
|
|
197753
197776
|
auto &buffer_manager = BufferManager::GetBufferManager(segment.db);
|
|
197754
197777
|
auto &state = (UncompressedStringSegmentState &)*segment.GetSegmentState();
|
|
197755
197778
|
if (block < MAXIMUM_BLOCK) {
|
|
197756
197779
|
// read the overflow string from disk
|
|
197757
197780
|
// pin the initial handle and read the length
|
|
197758
|
-
auto block_handle =
|
|
197781
|
+
auto block_handle = block_manager.RegisterBlock(block);
|
|
197759
197782
|
auto handle = buffer_manager.Pin(block_handle);
|
|
197760
197783
|
|
|
197761
197784
|
// read header
|
|
@@ -197785,7 +197808,7 @@ string_t UncompressedStringStorage::ReadOverflowString(ColumnSegment &segment, V
|
|
|
197785
197808
|
if (remaining > 0) {
|
|
197786
197809
|
// read the next block
|
|
197787
197810
|
block_id_t next_block = Load<block_id_t>(handle.Ptr() + offset);
|
|
197788
|
-
block_handle =
|
|
197811
|
+
block_handle = block_manager.RegisterBlock(next_block);
|
|
197789
197812
|
handle = buffer_manager.Pin(block_handle);
|
|
197790
197813
|
offset = 0;
|
|
197791
197814
|
}
|
|
@@ -199911,7 +199934,7 @@ void MetaBlockReader::ReadNewBlock(block_id_t id) {
|
|
|
199911
199934
|
auto &buffer_manager = BufferManager::GetBufferManager(db);
|
|
199912
199935
|
|
|
199913
199936
|
block_manager.MarkBlockAsModified(id);
|
|
199914
|
-
block =
|
|
199937
|
+
block = block_manager.RegisterBlock(id);
|
|
199915
199938
|
handle = buffer_manager.Pin(block);
|
|
199916
199939
|
|
|
199917
199940
|
next_block = Load<block_id_t>(handle.Ptr());
|
|
@@ -200103,6 +200126,7 @@ private:
|
|
|
200103
200126
|
|
|
200104
200127
|
|
|
200105
200128
|
|
|
200129
|
+
|
|
200106
200130
|
#include <algorithm>
|
|
200107
200131
|
#include <cstring>
|
|
200108
200132
|
|
|
@@ -200178,7 +200202,7 @@ T DeserializeHeaderStructure(data_ptr_t ptr) {
|
|
|
200178
200202
|
|
|
200179
200203
|
SingleFileBlockManager::SingleFileBlockManager(DatabaseInstance &db, string path_p, bool read_only, bool create_new,
|
|
200180
200204
|
bool use_direct_io)
|
|
200181
|
-
: db(db), path(move(path_p)),
|
|
200205
|
+
: BlockManager(BufferManager::GetBufferManager(db)), db(db), path(move(path_p)),
|
|
200182
200206
|
header_buffer(Allocator::Get(db), FileBufferType::MANAGED_BUFFER, Storage::FILE_HEADER_SIZE), iteration_count(0),
|
|
200183
200207
|
read_only(read_only), use_direct_io(use_direct_io) {
|
|
200184
200208
|
uint8_t flags;
|
|
@@ -201613,65 +201637,6 @@ void StorageLock::ReleaseSharedLock() {
|
|
|
201613
201637
|
} // namespace duckdb
|
|
201614
201638
|
|
|
201615
201639
|
|
|
201616
|
-
//===----------------------------------------------------------------------===//
|
|
201617
|
-
// DuckDB
|
|
201618
|
-
//
|
|
201619
|
-
// duckdb/storage/in_memory_block_manager.hpp
|
|
201620
|
-
//
|
|
201621
|
-
//
|
|
201622
|
-
//===----------------------------------------------------------------------===//
|
|
201623
|
-
|
|
201624
|
-
|
|
201625
|
-
|
|
201626
|
-
|
|
201627
|
-
|
|
201628
|
-
|
|
201629
|
-
|
|
201630
|
-
namespace duckdb {
|
|
201631
|
-
|
|
201632
|
-
//! InMemoryBlockManager is an implementation for a BlockManager
|
|
201633
|
-
class InMemoryBlockManager : public BlockManager {
|
|
201634
|
-
public:
|
|
201635
|
-
// LCOV_EXCL_START
|
|
201636
|
-
void StartCheckpoint() override {
|
|
201637
|
-
throw InternalException("Cannot perform IO in in-memory database!");
|
|
201638
|
-
}
|
|
201639
|
-
unique_ptr<Block> CreateBlock(block_id_t block_id) override {
|
|
201640
|
-
throw InternalException("Cannot perform IO in in-memory database!");
|
|
201641
|
-
}
|
|
201642
|
-
block_id_t GetFreeBlockId() override {
|
|
201643
|
-
throw InternalException("Cannot perform IO in in-memory database!");
|
|
201644
|
-
}
|
|
201645
|
-
bool IsRootBlock(block_id_t root) override {
|
|
201646
|
-
throw InternalException("Cannot perform IO in in-memory database!");
|
|
201647
|
-
}
|
|
201648
|
-
void MarkBlockAsModified(block_id_t block_id) override {
|
|
201649
|
-
throw InternalException("Cannot perform IO in in-memory database!");
|
|
201650
|
-
}
|
|
201651
|
-
void IncreaseBlockReferenceCount(block_id_t block_id) override {
|
|
201652
|
-
throw InternalException("Cannot perform IO in in-memory database!");
|
|
201653
|
-
}
|
|
201654
|
-
block_id_t GetMetaBlock() override {
|
|
201655
|
-
throw InternalException("Cannot perform IO in in-memory database!");
|
|
201656
|
-
}
|
|
201657
|
-
void Read(Block &block) override {
|
|
201658
|
-
throw InternalException("Cannot perform IO in in-memory database!");
|
|
201659
|
-
}
|
|
201660
|
-
void Write(FileBuffer &block, block_id_t block_id) override {
|
|
201661
|
-
throw InternalException("Cannot perform IO in in-memory database!");
|
|
201662
|
-
}
|
|
201663
|
-
void WriteHeader(DatabaseHeader header) override {
|
|
201664
|
-
throw InternalException("Cannot perform IO in in-memory database!");
|
|
201665
|
-
}
|
|
201666
|
-
idx_t TotalBlocks() override {
|
|
201667
|
-
throw InternalException("Cannot perform IO in in-memory database!");
|
|
201668
|
-
}
|
|
201669
|
-
idx_t FreeBlocks() override {
|
|
201670
|
-
throw InternalException("Cannot perform IO in in-memory database!");
|
|
201671
|
-
}
|
|
201672
|
-
// LCOV_EXCL_STOP
|
|
201673
|
-
};
|
|
201674
|
-
} // namespace duckdb
|
|
201675
201640
|
|
|
201676
201641
|
|
|
201677
201642
|
|
|
@@ -201748,7 +201713,7 @@ void StorageManager::Initialize() {
|
|
|
201748
201713
|
// create or load the database from disk, if not in-memory mode
|
|
201749
201714
|
LoadDatabase();
|
|
201750
201715
|
} else {
|
|
201751
|
-
block_manager = make_unique<InMemoryBlockManager>();
|
|
201716
|
+
block_manager = make_unique<InMemoryBlockManager>(*buffer_manager);
|
|
201752
201717
|
}
|
|
201753
201718
|
}
|
|
201754
201719
|
|
|
@@ -203234,6 +203199,7 @@ ColumnSegment::ColumnSegment(DatabaseInstance &db, LogicalType type_p, ColumnSeg
|
|
|
203234
203199
|
segment_type(segment_type), function(function_p), stats(type, move(statistics)), block_id(block_id_p),
|
|
203235
203200
|
offset(offset_p) {
|
|
203236
203201
|
D_ASSERT(function);
|
|
203202
|
+
auto &block_manager = BlockManager::GetBlockManager(db);
|
|
203237
203203
|
auto &buffer_manager = BufferManager::GetBufferManager(db);
|
|
203238
203204
|
if (block_id == INVALID_BLOCK) {
|
|
203239
203205
|
// no block id specified
|
|
@@ -203245,7 +203211,7 @@ ColumnSegment::ColumnSegment(DatabaseInstance &db, LogicalType type_p, ColumnSeg
|
|
|
203245
203211
|
}
|
|
203246
203212
|
} else {
|
|
203247
203213
|
D_ASSERT(segment_type == ColumnSegmentType::PERSISTENT);
|
|
203248
|
-
this->block =
|
|
203214
|
+
this->block = block_manager.RegisterBlock(block_id);
|
|
203249
203215
|
}
|
|
203250
203216
|
if (function->init_segment) {
|
|
203251
203217
|
segment_state = function->init_segment(*this, block_id);
|
|
@@ -203339,12 +203305,11 @@ void ColumnSegment::ConvertToPersistent(block_id_t block_id_p) {
|
|
|
203339
203305
|
block.reset();
|
|
203340
203306
|
} else {
|
|
203341
203307
|
// non-constant block: write the block to disk
|
|
203342
|
-
auto &buffer_manager = BufferManager::GetBufferManager(db);
|
|
203343
203308
|
auto &block_manager = BlockManager::GetBlockManager(db);
|
|
203344
203309
|
|
|
203345
203310
|
// the data for the block already exists in-memory of our block
|
|
203346
203311
|
// instead of copying the data we alter some metadata so the buffer points to an on-disk block
|
|
203347
|
-
block =
|
|
203312
|
+
block = block_manager.ConvertToPersistent(block_id, move(block));
|
|
203348
203313
|
}
|
|
203349
203314
|
|
|
203350
203315
|
segment_state.reset();
|