duckdb 0.7.2-dev1803.0 → 0.7.2-dev1898.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/catalog/catalog.cpp +27 -27
- package/src/duckdb/src/catalog/catalog_entry/duck_schema_entry.cpp +6 -6
- package/src/duckdb/src/catalog/catalog_set.cpp +27 -25
- package/src/duckdb/src/catalog/default/default_functions.cpp +6 -6
- package/src/duckdb/src/catalog/default/default_types.cpp +4 -4
- package/src/duckdb/src/catalog/default/default_views.cpp +4 -4
- package/src/duckdb/src/catalog/dependency_list.cpp +7 -6
- package/src/duckdb/src/catalog/dependency_manager.cpp +44 -38
- package/src/duckdb/src/common/serializer/buffered_file_reader.cpp +11 -6
- package/src/duckdb/src/common/sort/sorted_block.cpp +9 -4
- package/src/duckdb/src/common/types/batched_data_collection.cpp +2 -1
- package/src/duckdb/src/common/types/column_data_allocator.cpp +1 -0
- package/src/duckdb/src/common/types/vector.cpp +2 -2
- package/src/duckdb/src/common/vector_operations/vector_copy.cpp +14 -11
- package/src/duckdb/src/execution/operator/aggregate/distinct_aggregate_data.cpp +1 -1
- package/src/duckdb/src/execution/operator/aggregate/physical_window.cpp +51 -50
- package/src/duckdb/src/execution/operator/join/physical_iejoin.cpp +4 -0
- package/src/duckdb/src/execution/operator/persistent/physical_batch_insert.cpp +14 -13
- package/src/duckdb/src/execution/operator/persistent/physical_insert.cpp +20 -20
- package/src/duckdb/src/execution/operator/schema/physical_create_table.cpp +2 -2
- package/src/duckdb/src/execution/physical_plan/plan_create_index.cpp +1 -1
- package/src/duckdb/src/execution/physical_plan/plan_create_table.cpp +3 -3
- package/src/duckdb/src/execution/physical_plan/plan_delete.cpp +1 -1
- package/src/duckdb/src/execution/physical_plan/plan_insert.cpp +1 -1
- package/src/duckdb/src/execution/physical_plan/plan_update.cpp +1 -1
- package/src/duckdb/src/function/aggregate/sorted_aggregate_function.cpp +172 -63
- package/src/duckdb/src/function/cast/cast_function_set.cpp +2 -1
- package/src/duckdb/src/function/scalar/operators/arithmetic.cpp +15 -9
- package/src/duckdb/src/function/scalar/sequence/nextval.cpp +29 -29
- package/src/duckdb/src/function/scalar/string/damerau_levenshtein.cpp +106 -0
- package/src/duckdb/src/function/scalar/string/regexp.cpp +145 -28
- package/src/duckdb/src/function/scalar/string_functions.cpp +1 -0
- package/src/duckdb/src/function/table/checkpoint.cpp +4 -4
- package/src/duckdb/src/function/table/system/duckdb_columns.cpp +24 -24
- package/src/duckdb/src/function/table/system/duckdb_constraints.cpp +7 -6
- package/src/duckdb/src/function/table/system/duckdb_databases.cpp +1 -1
- package/src/duckdb/src/function/table/system/duckdb_dependencies.cpp +11 -11
- package/src/duckdb/src/function/table/system/pragma_database_size.cpp +1 -1
- package/src/duckdb/src/function/table/system/pragma_table_info.cpp +17 -18
- package/src/duckdb/src/function/table/table_scan.cpp +8 -11
- package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
- package/src/duckdb/src/include/duckdb/catalog/catalog.hpp +9 -9
- package/src/duckdb/src/include/duckdb/catalog/catalog_entry_map.hpp +38 -0
- package/src/duckdb/src/include/duckdb/catalog/catalog_transaction.hpp +4 -3
- package/src/duckdb/src/include/duckdb/catalog/default/default_functions.hpp +2 -2
- package/src/duckdb/src/include/duckdb/catalog/default/default_types.hpp +2 -2
- package/src/duckdb/src/include/duckdb/catalog/default/default_views.hpp +2 -2
- package/src/duckdb/src/include/duckdb/catalog/dependency.hpp +4 -5
- package/src/duckdb/src/include/duckdb/catalog/dependency_list.hpp +4 -5
- package/src/duckdb/src/include/duckdb/catalog/dependency_manager.hpp +10 -9
- package/src/duckdb/src/include/duckdb/common/allocator.hpp +2 -1
- package/src/duckdb/src/include/duckdb/common/field_writer.hpp +1 -1
- package/src/duckdb/src/include/duckdb/common/helper.hpp +9 -0
- package/src/duckdb/src/include/duckdb/common/optional_ptr.hpp +29 -6
- package/src/duckdb/src/include/duckdb/common/serializer/buffered_file_reader.hpp +6 -5
- package/src/duckdb/src/include/duckdb/common/serializer.hpp +1 -1
- package/src/duckdb/src/include/duckdb/common/types/row_data_collection.hpp +1 -0
- package/src/duckdb/src/include/duckdb/execution/operator/persistent/physical_batch_insert.hpp +2 -2
- package/src/duckdb/src/include/duckdb/execution/operator/persistent/physical_insert.hpp +5 -5
- package/src/duckdb/src/include/duckdb/execution/operator/schema/physical_create_table.hpp +2 -2
- package/src/duckdb/src/include/duckdb/function/cast/default_casts.hpp +3 -2
- package/src/duckdb/src/include/duckdb/function/scalar/string_functions.hpp +4 -0
- package/src/duckdb/src/include/duckdb/main/client_config.hpp +5 -0
- package/src/duckdb/src/include/duckdb/main/database_manager.hpp +4 -3
- package/src/duckdb/src/include/duckdb/main/query_result.hpp +3 -2
- package/src/duckdb/src/include/duckdb/main/settings.hpp +19 -0
- package/src/duckdb/src/include/duckdb/optimizer/filter_combiner.hpp +7 -7
- package/src/duckdb/src/include/duckdb/optimizer/matcher/expression_matcher.hpp +11 -11
- package/src/duckdb/src/include/duckdb/optimizer/matcher/set_matcher.hpp +8 -8
- package/src/duckdb/src/include/duckdb/optimizer/rule/arithmetic_simplification.hpp +1 -1
- package/src/duckdb/src/include/duckdb/optimizer/rule/case_simplification.hpp +1 -1
- package/src/duckdb/src/include/duckdb/optimizer/rule/comparison_simplification.hpp +1 -1
- package/src/duckdb/src/include/duckdb/optimizer/rule/conjunction_simplification.hpp +2 -2
- package/src/duckdb/src/include/duckdb/optimizer/rule/constant_folding.hpp +1 -1
- package/src/duckdb/src/include/duckdb/optimizer/rule/date_part_simplification.hpp +1 -1
- package/src/duckdb/src/include/duckdb/optimizer/rule/distributivity.hpp +1 -1
- package/src/duckdb/src/include/duckdb/optimizer/rule/empty_needle_removal.hpp +1 -1
- package/src/duckdb/src/include/duckdb/optimizer/rule/enum_comparison.hpp +1 -1
- package/src/duckdb/src/include/duckdb/optimizer/rule/equal_or_null_simplification.hpp +1 -1
- package/src/duckdb/src/include/duckdb/optimizer/rule/in_clause_simplification.hpp +1 -1
- package/src/duckdb/src/include/duckdb/optimizer/rule/like_optimizations.hpp +1 -1
- package/src/duckdb/src/include/duckdb/optimizer/rule/move_constants.hpp +1 -1
- package/src/duckdb/src/include/duckdb/optimizer/rule/ordered_aggregate_optimizer.hpp +1 -1
- package/src/duckdb/src/include/duckdb/optimizer/rule/regex_optimizations.hpp +1 -1
- package/src/duckdb/src/include/duckdb/optimizer/rule.hpp +2 -2
- package/src/duckdb/src/include/duckdb/parser/base_expression.hpp +1 -1
- package/src/duckdb/src/include/duckdb/parser/expression_map.hpp +19 -6
- package/src/duckdb/src/include/duckdb/parser/expression_util.hpp +1 -1
- package/src/duckdb/src/include/duckdb/parser/parser.hpp +1 -7
- package/src/duckdb/src/include/duckdb/parser/parser_options.hpp +23 -0
- package/src/duckdb/src/include/duckdb/parser/transformer.hpp +5 -3
- package/src/duckdb/src/include/duckdb/planner/expression.hpp +5 -2
- package/src/duckdb/src/include/duckdb/planner/expression_binder/base_select_binder.hpp +1 -1
- package/src/duckdb/src/include/duckdb/planner/expression_binder/order_binder.hpp +3 -3
- package/src/duckdb/src/include/duckdb/storage/buffer/block_handle.hpp +10 -2
- package/src/duckdb/src/include/duckdb/storage/buffer/buffer_pool.hpp +1 -0
- package/src/duckdb/src/include/duckdb/storage/buffer_manager.hpp +49 -126
- package/src/duckdb/src/include/duckdb/storage/meta_block_reader.hpp +5 -5
- package/src/duckdb/src/include/duckdb/storage/standard_buffer_manager.hpp +159 -0
- package/src/duckdb/src/include/duckdb/storage/table/column_segment.hpp +1 -0
- package/src/duckdb/src/include/duckdb/transaction/meta_transaction.hpp +6 -5
- package/src/duckdb/src/main/client_context.cpp +5 -3
- package/src/duckdb/src/main/config.cpp +2 -0
- package/src/duckdb/src/main/database.cpp +2 -1
- package/src/duckdb/src/main/database_manager.cpp +4 -4
- package/src/duckdb/src/main/settings/settings.cpp +36 -0
- package/src/duckdb/src/optimizer/common_aggregate_optimizer.cpp +2 -2
- package/src/duckdb/src/optimizer/cse_optimizer.cpp +4 -4
- package/src/duckdb/src/optimizer/deliminator.cpp +13 -11
- package/src/duckdb/src/optimizer/expression_rewriter.cpp +2 -2
- package/src/duckdb/src/optimizer/filter_combiner.cpp +67 -65
- package/src/duckdb/src/optimizer/join_order/cardinality_estimator.cpp +1 -0
- package/src/duckdb/src/optimizer/join_order/join_order_optimizer.cpp +26 -25
- package/src/duckdb/src/optimizer/matcher/expression_matcher.cpp +23 -21
- package/src/duckdb/src/optimizer/rule/arithmetic_simplification.cpp +7 -6
- package/src/duckdb/src/optimizer/rule/case_simplification.cpp +2 -2
- package/src/duckdb/src/optimizer/rule/comparison_simplification.cpp +6 -7
- package/src/duckdb/src/optimizer/rule/conjunction_simplification.cpp +9 -8
- package/src/duckdb/src/optimizer/rule/constant_folding.cpp +7 -7
- package/src/duckdb/src/optimizer/rule/date_part_simplification.cpp +3 -3
- package/src/duckdb/src/optimizer/rule/distributivity.cpp +5 -5
- package/src/duckdb/src/optimizer/rule/empty_needle_removal.cpp +6 -6
- package/src/duckdb/src/optimizer/rule/enum_comparison.cpp +4 -4
- package/src/duckdb/src/optimizer/rule/equal_or_null_simplification.cpp +23 -26
- package/src/duckdb/src/optimizer/rule/in_clause_simplification_rule.cpp +2 -3
- package/src/duckdb/src/optimizer/rule/like_optimizations.cpp +3 -3
- package/src/duckdb/src/optimizer/rule/move_constants.cpp +6 -6
- package/src/duckdb/src/optimizer/rule/ordered_aggregate_optimizer.cpp +2 -2
- package/src/duckdb/src/optimizer/rule/regex_optimizations.cpp +3 -3
- package/src/duckdb/src/parser/expression_util.cpp +6 -6
- package/src/duckdb/src/parser/parser.cpp +1 -1
- package/src/duckdb/src/parser/transform/expression/transform_operator.cpp +7 -3
- package/src/duckdb/src/parser/transform/helpers/transform_groupby.cpp +3 -3
- package/src/duckdb/src/parser/transformer.cpp +6 -5
- package/src/duckdb/src/planner/binder/expression/bind_aggregate_expression.cpp +2 -2
- package/src/duckdb/src/planner/binder/query_node/bind_select_node.cpp +3 -3
- package/src/duckdb/src/planner/binder/query_node/bind_setop_node.cpp +5 -5
- package/src/duckdb/src/planner/binder/statement/bind_create_table.cpp +2 -2
- package/src/duckdb/src/planner/expression_binder/base_select_binder.cpp +4 -4
- package/src/duckdb/src/planner/expression_binder/order_binder.cpp +3 -3
- package/src/duckdb/src/storage/buffer/block_handle.cpp +3 -2
- package/src/duckdb/src/storage/buffer/block_manager.cpp +3 -1
- package/src/duckdb/src/storage/buffer/buffer_handle.cpp +1 -0
- package/src/duckdb/src/storage/buffer/buffer_pool_reservation.cpp +3 -0
- package/src/duckdb/src/storage/buffer_manager.cpp +35 -726
- package/src/duckdb/src/storage/checkpoint_manager.cpp +2 -2
- package/src/duckdb/src/storage/meta_block_reader.cpp +6 -5
- package/src/duckdb/src/storage/standard_buffer_manager.cpp +801 -0
- package/src/duckdb/src/storage/wal_replay.cpp +2 -2
- package/src/duckdb/src/transaction/meta_transaction.cpp +13 -13
- package/src/duckdb/src/transaction/transaction.cpp +1 -1
- package/src/duckdb/src/transaction/transaction_context.cpp +1 -1
- package/src/duckdb/third_party/libpg_query/include/parser/gram.hpp +949 -947
- package/src/duckdb/third_party/libpg_query/src_backend_parser_gram.cpp +16431 -16385
- package/src/duckdb/third_party/libpg_query/src_backend_parser_scan.cpp +503 -493
- package/src/duckdb/ub_src_function_scalar_string.cpp +2 -0
- package/src/duckdb/ub_src_storage.cpp +2 -0
@@ -1,770 +1,79 @@
|
|
1
1
|
#include "duckdb/storage/buffer_manager.hpp"
|
2
|
-
|
3
2
|
#include "duckdb/common/allocator.hpp"
|
4
3
|
#include "duckdb/common/exception.hpp"
|
5
|
-
#include "duckdb/common/
|
6
|
-
#include "duckdb/storage/
|
7
|
-
#include "duckdb/storage/storage_manager.hpp"
|
8
|
-
#include "duckdb/main/attached_database.hpp"
|
9
|
-
#include "duckdb/main/database.hpp"
|
4
|
+
#include "duckdb/common/file_buffer.hpp"
|
5
|
+
#include "duckdb/storage/standard_buffer_manager.hpp"
|
10
6
|
|
11
7
|
namespace duckdb {
|
12
8
|
|
13
|
-
|
14
|
-
|
15
|
-
}
|
16
|
-
|
17
|
-
BufferManager &manager;
|
18
|
-
};
|
19
|
-
|
20
|
-
idx_t GetAllocSize(idx_t size) {
|
21
|
-
return AlignValue<idx_t, Storage::SECTOR_SIZE>(size + Storage::BLOCK_HEADER_SIZE);
|
22
|
-
}
|
23
|
-
|
24
|
-
unique_ptr<FileBuffer> BufferManager::ConstructManagedBuffer(idx_t size, unique_ptr<FileBuffer> &&source,
|
25
|
-
FileBufferType type) {
|
26
|
-
if (source) {
|
27
|
-
auto tmp = std::move(source);
|
28
|
-
D_ASSERT(tmp->AllocSize() == BufferManager::GetAllocSize(size));
|
29
|
-
return make_uniq<FileBuffer>(*tmp, type);
|
30
|
-
} else {
|
31
|
-
// no re-usable buffer: allocate a new buffer
|
32
|
-
return make_uniq<FileBuffer>(Allocator::Get(db), type, size);
|
33
|
-
}
|
34
|
-
}
|
35
|
-
|
36
|
-
class TemporaryFileManager;
|
37
|
-
|
38
|
-
class TemporaryDirectoryHandle {
|
39
|
-
public:
|
40
|
-
TemporaryDirectoryHandle(DatabaseInstance &db, string path_p);
|
41
|
-
~TemporaryDirectoryHandle();
|
42
|
-
|
43
|
-
TemporaryFileManager &GetTempFile();
|
44
|
-
|
45
|
-
private:
|
46
|
-
DatabaseInstance &db;
|
47
|
-
string temp_directory;
|
48
|
-
bool created_directory = false;
|
49
|
-
unique_ptr<TemporaryFileManager> temp_file;
|
50
|
-
};
|
51
|
-
|
52
|
-
void BufferManager::SetTemporaryDirectory(string new_dir) {
|
53
|
-
if (temp_directory_handle) {
|
54
|
-
throw NotImplementedException("Cannot switch temporary directory after the current one has been used");
|
55
|
-
}
|
56
|
-
this->temp_directory = std::move(new_dir);
|
57
|
-
}
|
58
|
-
|
59
|
-
BufferManager::BufferManager(DatabaseInstance &db, string tmp)
|
60
|
-
: db(db), buffer_pool(db.GetBufferPool()), temp_directory(std::move(tmp)), temporary_id(MAXIMUM_BLOCK),
|
61
|
-
buffer_allocator(BufferAllocatorAllocate, BufferAllocatorFree, BufferAllocatorRealloc,
|
62
|
-
make_uniq<BufferAllocatorData>(*this)) {
|
63
|
-
temp_block_manager = make_uniq<InMemoryBlockManager>(*this);
|
64
|
-
}
|
65
|
-
|
66
|
-
BufferManager::~BufferManager() {
|
67
|
-
}
|
68
|
-
|
69
|
-
template <typename... ARGS>
|
70
|
-
TempBufferPoolReservation BufferManager::EvictBlocksOrThrow(idx_t memory_delta, unique_ptr<FileBuffer> *buffer,
|
71
|
-
ARGS... args) {
|
72
|
-
auto r = buffer_pool.EvictBlocks(memory_delta, buffer_pool.maximum_memory, buffer);
|
73
|
-
if (!r.success) {
|
74
|
-
throw OutOfMemoryException(args..., InMemoryWarning());
|
75
|
-
}
|
76
|
-
return std::move(r.reservation);
|
9
|
+
unique_ptr<BufferManager> BufferManager::CreateStandardBufferManager(DatabaseInstance &db, DBConfig &config) {
|
10
|
+
return make_uniq<StandardBufferManager>(db, config.options.temporary_directory);
|
77
11
|
}
|
78
12
|
|
79
13
|
shared_ptr<BlockHandle> BufferManager::RegisterSmallMemory(idx_t block_size) {
|
80
|
-
|
81
|
-
auto res = EvictBlocksOrThrow(block_size, nullptr, "could not allocate block of %lld bytes (%lld/%lld used) %s",
|
82
|
-
block_size, GetUsedMemory(), GetMaxMemory());
|
83
|
-
|
84
|
-
auto buffer = ConstructManagedBuffer(block_size, nullptr, FileBufferType::TINY_BUFFER);
|
85
|
-
|
86
|
-
// create a new block pointer for this block
|
87
|
-
return make_shared<BlockHandle>(*temp_block_manager, ++temporary_id, std::move(buffer), false, block_size,
|
88
|
-
std::move(res));
|
14
|
+
throw NotImplementedException("This type of BufferManager can not create 'small-memory' blocks");
|
89
15
|
}
|
90
16
|
|
91
|
-
|
92
|
-
|
93
|
-
auto alloc_size = GetAllocSize(block_size);
|
94
|
-
// first evict blocks until we have enough memory to store this buffer
|
95
|
-
unique_ptr<FileBuffer> reusable_buffer;
|
96
|
-
auto res =
|
97
|
-
EvictBlocksOrThrow(alloc_size, &reusable_buffer, "could not allocate block of %lld bytes (%lld/%lld used) %s",
|
98
|
-
alloc_size, GetUsedMemory(), GetMaxMemory());
|
99
|
-
|
100
|
-
auto buffer = ConstructManagedBuffer(block_size, std::move(reusable_buffer));
|
101
|
-
|
102
|
-
// create a new block pointer for this block
|
103
|
-
return make_shared<BlockHandle>(*temp_block_manager, ++temporary_id, std::move(buffer), can_destroy, alloc_size,
|
104
|
-
std::move(res));
|
17
|
+
Allocator &BufferManager::GetBufferAllocator() {
|
18
|
+
throw NotImplementedException("This type of BufferManager does not have an Allocator");
|
105
19
|
}
|
106
20
|
|
107
|
-
|
108
|
-
|
109
|
-
auto block_ptr = block ? block : &local_block;
|
110
|
-
*block_ptr = RegisterMemory(block_size, can_destroy);
|
111
|
-
return Pin(*block_ptr);
|
21
|
+
void BufferManager::ReserveMemory(idx_t size) {
|
22
|
+
throw NotImplementedException("This type of BufferManager can not reserve memory");
|
112
23
|
}
|
113
|
-
|
114
|
-
|
115
|
-
D_ASSERT(block_size >= Storage::BLOCK_SIZE);
|
116
|
-
lock_guard<mutex> lock(handle->lock);
|
117
|
-
D_ASSERT(handle->state == BlockState::BLOCK_LOADED);
|
118
|
-
D_ASSERT(handle->memory_usage == handle->buffer->AllocSize());
|
119
|
-
D_ASSERT(handle->memory_usage == handle->memory_charge.size);
|
120
|
-
|
121
|
-
auto req = handle->buffer->CalculateMemory(block_size);
|
122
|
-
int64_t memory_delta = (int64_t)req.alloc_size - handle->memory_usage;
|
123
|
-
|
124
|
-
if (memory_delta == 0) {
|
125
|
-
return;
|
126
|
-
} else if (memory_delta > 0) {
|
127
|
-
// evict blocks until we have space to resize this block
|
128
|
-
auto reservation = EvictBlocksOrThrow(memory_delta, nullptr, "failed to resize block from %lld to %lld%s",
|
129
|
-
handle->memory_usage, req.alloc_size);
|
130
|
-
// EvictBlocks decrements 'current_memory' for us.
|
131
|
-
handle->memory_charge.Merge(std::move(reservation));
|
132
|
-
} else {
|
133
|
-
// no need to evict blocks, but we do need to decrement 'current_memory'.
|
134
|
-
handle->memory_charge.Resize(req.alloc_size);
|
135
|
-
}
|
136
|
-
|
137
|
-
// resize and adjust current memory
|
138
|
-
handle->buffer->Resize(block_size);
|
139
|
-
handle->memory_usage += memory_delta;
|
140
|
-
D_ASSERT(handle->memory_usage == handle->buffer->AllocSize());
|
24
|
+
void BufferManager::FreeReservedMemory(idx_t size) {
|
25
|
+
throw NotImplementedException("This type of BufferManager can not free reserved memory");
|
141
26
|
}
|
142
27
|
|
143
|
-
|
144
|
-
|
145
|
-
{
|
146
|
-
// lock the block
|
147
|
-
lock_guard<mutex> lock(handle->lock);
|
148
|
-
// check if the block is already loaded
|
149
|
-
if (handle->state == BlockState::BLOCK_LOADED) {
|
150
|
-
// the block is loaded, increment the reader count and return a pointer to the handle
|
151
|
-
handle->readers++;
|
152
|
-
return handle->Load(handle);
|
153
|
-
}
|
154
|
-
required_memory = handle->memory_usage;
|
155
|
-
}
|
156
|
-
// evict blocks until we have space for the current block
|
157
|
-
unique_ptr<FileBuffer> reusable_buffer;
|
158
|
-
auto reservation =
|
159
|
-
EvictBlocksOrThrow(required_memory, &reusable_buffer, "failed to pin block of size %lld%s", required_memory);
|
160
|
-
// lock the handle again and repeat the check (in case anybody loaded in the mean time)
|
161
|
-
lock_guard<mutex> lock(handle->lock);
|
162
|
-
// check if the block is already loaded
|
163
|
-
if (handle->state == BlockState::BLOCK_LOADED) {
|
164
|
-
// the block is loaded, increment the reader count and return a pointer to the handle
|
165
|
-
handle->readers++;
|
166
|
-
reservation.Resize(0);
|
167
|
-
return handle->Load(handle);
|
168
|
-
}
|
169
|
-
// now we can actually load the current block
|
170
|
-
D_ASSERT(handle->readers == 0);
|
171
|
-
handle->readers = 1;
|
172
|
-
auto buf = handle->Load(handle, std::move(reusable_buffer));
|
173
|
-
handle->memory_charge = std::move(reservation);
|
174
|
-
// In the case of a variable sized block, the buffer may be smaller than a full block.
|
175
|
-
int64_t delta = handle->buffer->AllocSize() - handle->memory_usage;
|
176
|
-
if (delta) {
|
177
|
-
D_ASSERT(delta < 0);
|
178
|
-
handle->memory_usage += delta;
|
179
|
-
handle->memory_charge.Resize(handle->memory_usage);
|
180
|
-
}
|
181
|
-
D_ASSERT(handle->memory_usage == handle->buffer->AllocSize());
|
182
|
-
return buf;
|
28
|
+
void BufferManager::SetLimit(idx_t limit) {
|
29
|
+
throw NotImplementedException("This type of BufferManager can not set a limit");
|
183
30
|
}
|
184
31
|
|
185
|
-
|
186
|
-
|
187
|
-
auto replacement_buffer = make_uniq<FileBuffer>(Allocator::Get(db), handle->buffer->type,
|
188
|
-
handle->memory_usage - Storage::BLOCK_HEADER_SIZE);
|
189
|
-
memcpy(replacement_buffer->buffer, handle->buffer->buffer, handle->buffer->size);
|
190
|
-
memset(handle->buffer->buffer, 165, handle->buffer->size); // 165 is default memory in debug mode
|
191
|
-
handle->buffer = std::move(replacement_buffer);
|
192
|
-
#endif
|
32
|
+
vector<TemporaryFileInformation> BufferManager::GetTemporaryFiles() {
|
33
|
+
throw InternalException("This type of BufferManager does not allow temporary files");
|
193
34
|
}
|
194
35
|
|
195
|
-
|
196
|
-
|
197
|
-
if (!handle->buffer || handle->buffer->type == FileBufferType::TINY_BUFFER) {
|
198
|
-
return;
|
199
|
-
}
|
200
|
-
D_ASSERT(handle->readers > 0);
|
201
|
-
handle->readers--;
|
202
|
-
if (handle->readers == 0) {
|
203
|
-
VerifyZeroReaders(handle);
|
204
|
-
buffer_pool.AddToEvictionQueue(handle);
|
205
|
-
}
|
36
|
+
const string &BufferManager::GetTemporaryDirectory() {
|
37
|
+
throw InternalException("This type of BufferManager does not allow a temporary directory");
|
206
38
|
}
|
207
39
|
|
208
|
-
|
209
|
-
|
40
|
+
BufferPool &BufferManager::GetBufferPool() {
|
41
|
+
throw InternalException("This type of BufferManager does not have a buffer pool");
|
210
42
|
}
|
211
43
|
|
212
|
-
void BufferManager::
|
213
|
-
|
44
|
+
void BufferManager::SetTemporaryDirectory(const string &new_dir) {
|
45
|
+
throw NotImplementedException("This type of BufferManager can not set a temporary directory");
|
214
46
|
}
|
215
47
|
|
216
|
-
|
217
|
-
|
218
|
-
//===--------------------------------------------------------------------===//
|
219
|
-
unique_ptr<FileBuffer> ReadTemporaryBufferInternal(BufferManager &buffer_manager, FileHandle &handle, idx_t position,
|
220
|
-
idx_t size, block_id_t id, unique_ptr<FileBuffer> reusable_buffer) {
|
221
|
-
auto buffer = buffer_manager.ConstructManagedBuffer(size, std::move(reusable_buffer));
|
222
|
-
buffer->Read(handle, position);
|
223
|
-
return buffer;
|
48
|
+
DatabaseInstance &BufferManager::GetDatabase() {
|
49
|
+
throw NotImplementedException("This type of BufferManager is not linked to a DatabaseInstance");
|
224
50
|
}
|
225
51
|
|
226
|
-
|
227
|
-
|
228
|
-
idx_t block_index = DConstants::INVALID_INDEX)
|
229
|
-
: file_index(file_index), block_index(block_index) {
|
230
|
-
}
|
231
|
-
|
232
|
-
idx_t file_index;
|
233
|
-
idx_t block_index;
|
234
|
-
|
235
|
-
public:
|
236
|
-
bool IsValid() {
|
237
|
-
return block_index != DConstants::INVALID_INDEX;
|
238
|
-
}
|
239
|
-
};
|
240
|
-
|
241
|
-
struct BlockIndexManager {
|
242
|
-
BlockIndexManager() : max_index(0) {
|
243
|
-
}
|
244
|
-
|
245
|
-
public:
|
246
|
-
//! Obtains a new block index from the index manager
|
247
|
-
idx_t GetNewBlockIndex() {
|
248
|
-
auto index = GetNewBlockIndexInternal();
|
249
|
-
indexes_in_use.insert(index);
|
250
|
-
return index;
|
251
|
-
}
|
252
|
-
|
253
|
-
//! Removes an index from the block manager
|
254
|
-
//! Returns true if the max_index has been altered
|
255
|
-
bool RemoveIndex(idx_t index) {
|
256
|
-
// remove this block from the set of blocks
|
257
|
-
auto entry = indexes_in_use.find(index);
|
258
|
-
if (entry == indexes_in_use.end()) {
|
259
|
-
throw InternalException("RemoveIndex - index %llu not found in indexes_in_use", index);
|
260
|
-
}
|
261
|
-
indexes_in_use.erase(entry);
|
262
|
-
free_indexes.insert(index);
|
263
|
-
// check if we can truncate the file
|
264
|
-
|
265
|
-
// get the max_index in use right now
|
266
|
-
auto max_index_in_use = indexes_in_use.empty() ? 0 : *indexes_in_use.rbegin();
|
267
|
-
if (max_index_in_use < max_index) {
|
268
|
-
// max index in use is lower than the max_index
|
269
|
-
// reduce the max_index
|
270
|
-
max_index = indexes_in_use.empty() ? 0 : max_index_in_use + 1;
|
271
|
-
// we can remove any free_indexes that are larger than the current max_index
|
272
|
-
while (!free_indexes.empty()) {
|
273
|
-
auto max_entry = *free_indexes.rbegin();
|
274
|
-
if (max_entry < max_index) {
|
275
|
-
break;
|
276
|
-
}
|
277
|
-
free_indexes.erase(max_entry);
|
278
|
-
}
|
279
|
-
return true;
|
280
|
-
}
|
281
|
-
return false;
|
282
|
-
}
|
283
|
-
|
284
|
-
idx_t GetMaxIndex() {
|
285
|
-
return max_index;
|
286
|
-
}
|
287
|
-
|
288
|
-
bool HasFreeBlocks() {
|
289
|
-
return !free_indexes.empty();
|
290
|
-
}
|
291
|
-
|
292
|
-
private:
|
293
|
-
idx_t GetNewBlockIndexInternal() {
|
294
|
-
if (free_indexes.empty()) {
|
295
|
-
return max_index++;
|
296
|
-
}
|
297
|
-
auto entry = free_indexes.begin();
|
298
|
-
auto index = *entry;
|
299
|
-
free_indexes.erase(entry);
|
300
|
-
return index;
|
301
|
-
}
|
302
|
-
|
303
|
-
idx_t max_index;
|
304
|
-
set<idx_t> free_indexes;
|
305
|
-
set<idx_t> indexes_in_use;
|
306
|
-
};
|
307
|
-
|
308
|
-
class TemporaryFileHandle {
|
309
|
-
constexpr static idx_t MAX_ALLOWED_INDEX = 4000;
|
310
|
-
|
311
|
-
public:
|
312
|
-
TemporaryFileHandle(DatabaseInstance &db, const string &temp_directory, idx_t index)
|
313
|
-
: db(db), file_index(index), path(FileSystem::GetFileSystem(db).JoinPath(
|
314
|
-
temp_directory, "duckdb_temp_storage-" + to_string(index) + ".tmp")) {
|
315
|
-
}
|
316
|
-
|
317
|
-
public:
|
318
|
-
struct TemporaryFileLock {
|
319
|
-
explicit TemporaryFileLock(mutex &mutex) : lock(mutex) {
|
320
|
-
}
|
321
|
-
|
322
|
-
lock_guard<mutex> lock;
|
323
|
-
};
|
324
|
-
|
325
|
-
public:
|
326
|
-
TemporaryFileIndex TryGetBlockIndex() {
|
327
|
-
TemporaryFileLock lock(file_lock);
|
328
|
-
if (index_manager.GetMaxIndex() >= MAX_ALLOWED_INDEX && index_manager.HasFreeBlocks()) {
|
329
|
-
// file is at capacity
|
330
|
-
return TemporaryFileIndex();
|
331
|
-
}
|
332
|
-
// open the file handle if it does not yet exist
|
333
|
-
CreateFileIfNotExists(lock);
|
334
|
-
// fetch a new block index to write to
|
335
|
-
auto block_index = index_manager.GetNewBlockIndex();
|
336
|
-
return TemporaryFileIndex(file_index, block_index);
|
337
|
-
}
|
338
|
-
|
339
|
-
void WriteTemporaryFile(FileBuffer &buffer, TemporaryFileIndex index) {
|
340
|
-
D_ASSERT(buffer.size == Storage::BLOCK_SIZE);
|
341
|
-
buffer.Write(*handle, GetPositionInFile(index.block_index));
|
342
|
-
}
|
343
|
-
|
344
|
-
unique_ptr<FileBuffer> ReadTemporaryBuffer(block_id_t id, idx_t block_index,
|
345
|
-
unique_ptr<FileBuffer> reusable_buffer) {
|
346
|
-
return ReadTemporaryBufferInternal(BufferManager::GetBufferManager(db), *handle, GetPositionInFile(block_index),
|
347
|
-
Storage::BLOCK_SIZE, id, std::move(reusable_buffer));
|
348
|
-
}
|
349
|
-
|
350
|
-
void EraseBlockIndex(block_id_t block_index) {
|
351
|
-
// remove the block (and potentially truncate the temp file)
|
352
|
-
TemporaryFileLock lock(file_lock);
|
353
|
-
D_ASSERT(handle);
|
354
|
-
RemoveTempBlockIndex(lock, block_index);
|
355
|
-
}
|
356
|
-
|
357
|
-
bool DeleteIfEmpty() {
|
358
|
-
TemporaryFileLock lock(file_lock);
|
359
|
-
if (index_manager.GetMaxIndex() > 0) {
|
360
|
-
// there are still blocks in this file
|
361
|
-
return false;
|
362
|
-
}
|
363
|
-
// the file is empty: delete it
|
364
|
-
handle.reset();
|
365
|
-
auto &fs = FileSystem::GetFileSystem(db);
|
366
|
-
fs.RemoveFile(path);
|
367
|
-
return true;
|
368
|
-
}
|
369
|
-
|
370
|
-
TemporaryFileInformation GetTemporaryFile() {
|
371
|
-
TemporaryFileLock lock(file_lock);
|
372
|
-
TemporaryFileInformation info;
|
373
|
-
info.path = path;
|
374
|
-
info.size = GetPositionInFile(index_manager.GetMaxIndex());
|
375
|
-
return info;
|
376
|
-
}
|
377
|
-
|
378
|
-
private:
|
379
|
-
void CreateFileIfNotExists(TemporaryFileLock &) {
|
380
|
-
if (handle) {
|
381
|
-
return;
|
382
|
-
}
|
383
|
-
auto &fs = FileSystem::GetFileSystem(db);
|
384
|
-
handle = fs.OpenFile(path, FileFlags::FILE_FLAGS_READ | FileFlags::FILE_FLAGS_WRITE |
|
385
|
-
FileFlags::FILE_FLAGS_FILE_CREATE);
|
386
|
-
}
|
387
|
-
|
388
|
-
void RemoveTempBlockIndex(TemporaryFileLock &, idx_t index) {
|
389
|
-
// remove the block index from the index manager
|
390
|
-
if (index_manager.RemoveIndex(index)) {
|
391
|
-
// the max_index that is currently in use has decreased
|
392
|
-
// as a result we can truncate the file
|
393
|
-
#ifndef WIN32 // this ended up causing issues when sorting
|
394
|
-
auto max_index = index_manager.GetMaxIndex();
|
395
|
-
auto &fs = FileSystem::GetFileSystem(db);
|
396
|
-
fs.Truncate(*handle, GetPositionInFile(max_index + 1));
|
397
|
-
#endif
|
398
|
-
}
|
399
|
-
}
|
400
|
-
|
401
|
-
idx_t GetPositionInFile(idx_t index) {
|
402
|
-
return index * Storage::BLOCK_ALLOC_SIZE;
|
403
|
-
}
|
404
|
-
|
405
|
-
private:
|
406
|
-
DatabaseInstance &db;
|
407
|
-
unique_ptr<FileHandle> handle;
|
408
|
-
idx_t file_index;
|
409
|
-
string path;
|
410
|
-
mutex file_lock;
|
411
|
-
BlockIndexManager index_manager;
|
412
|
-
};
|
413
|
-
|
414
|
-
class TemporaryFileManager {
|
415
|
-
public:
|
416
|
-
TemporaryFileManager(DatabaseInstance &db, const string &temp_directory_p)
|
417
|
-
: db(db), temp_directory(temp_directory_p) {
|
418
|
-
}
|
419
|
-
|
420
|
-
public:
|
421
|
-
struct TemporaryManagerLock {
|
422
|
-
explicit TemporaryManagerLock(mutex &mutex) : lock(mutex) {
|
423
|
-
}
|
424
|
-
|
425
|
-
lock_guard<mutex> lock;
|
426
|
-
};
|
427
|
-
|
428
|
-
void WriteTemporaryBuffer(block_id_t block_id, FileBuffer &buffer) {
|
429
|
-
D_ASSERT(buffer.size == Storage::BLOCK_SIZE);
|
430
|
-
TemporaryFileIndex index;
|
431
|
-
TemporaryFileHandle *handle = nullptr;
|
432
|
-
|
433
|
-
{
|
434
|
-
TemporaryManagerLock lock(manager_lock);
|
435
|
-
// first check if we can write to an open existing file
|
436
|
-
for (auto &entry : files) {
|
437
|
-
auto &temp_file = entry.second;
|
438
|
-
index = temp_file->TryGetBlockIndex();
|
439
|
-
if (index.IsValid()) {
|
440
|
-
handle = entry.second.get();
|
441
|
-
break;
|
442
|
-
}
|
443
|
-
}
|
444
|
-
if (!handle) {
|
445
|
-
// no existing handle to write to; we need to create & open a new file
|
446
|
-
auto new_file_index = index_manager.GetNewBlockIndex();
|
447
|
-
auto new_file = make_uniq<TemporaryFileHandle>(db, temp_directory, new_file_index);
|
448
|
-
handle = new_file.get();
|
449
|
-
files[new_file_index] = std::move(new_file);
|
450
|
-
|
451
|
-
index = handle->TryGetBlockIndex();
|
452
|
-
}
|
453
|
-
D_ASSERT(used_blocks.find(block_id) == used_blocks.end());
|
454
|
-
used_blocks[block_id] = index;
|
455
|
-
}
|
456
|
-
D_ASSERT(handle);
|
457
|
-
D_ASSERT(index.IsValid());
|
458
|
-
handle->WriteTemporaryFile(buffer, index);
|
459
|
-
}
|
460
|
-
|
461
|
-
bool HasTemporaryBuffer(block_id_t block_id) {
|
462
|
-
lock_guard<mutex> lock(manager_lock);
|
463
|
-
return used_blocks.find(block_id) != used_blocks.end();
|
464
|
-
}
|
465
|
-
|
466
|
-
unique_ptr<FileBuffer> ReadTemporaryBuffer(block_id_t id, unique_ptr<FileBuffer> reusable_buffer) {
|
467
|
-
TemporaryFileIndex index;
|
468
|
-
TemporaryFileHandle *handle;
|
469
|
-
{
|
470
|
-
TemporaryManagerLock lock(manager_lock);
|
471
|
-
index = GetTempBlockIndex(lock, id);
|
472
|
-
handle = GetFileHandle(lock, index.file_index);
|
473
|
-
}
|
474
|
-
auto buffer = handle->ReadTemporaryBuffer(id, index.block_index, std::move(reusable_buffer));
|
475
|
-
{
|
476
|
-
// remove the block (and potentially erase the temp file)
|
477
|
-
TemporaryManagerLock lock(manager_lock);
|
478
|
-
EraseUsedBlock(lock, id, handle, index);
|
479
|
-
}
|
480
|
-
return buffer;
|
481
|
-
}
|
482
|
-
|
483
|
-
void DeleteTemporaryBuffer(block_id_t id) {
|
484
|
-
TemporaryManagerLock lock(manager_lock);
|
485
|
-
auto index = GetTempBlockIndex(lock, id);
|
486
|
-
auto handle = GetFileHandle(lock, index.file_index);
|
487
|
-
EraseUsedBlock(lock, id, handle, index);
|
488
|
-
}
|
489
|
-
|
490
|
-
vector<TemporaryFileInformation> GetTemporaryFiles() {
|
491
|
-
lock_guard<mutex> lock(manager_lock);
|
492
|
-
vector<TemporaryFileInformation> result;
|
493
|
-
for (auto &file : files) {
|
494
|
-
result.push_back(file.second->GetTemporaryFile());
|
495
|
-
}
|
496
|
-
return result;
|
497
|
-
}
|
498
|
-
|
499
|
-
private:
|
500
|
-
void EraseUsedBlock(TemporaryManagerLock &lock, block_id_t id, TemporaryFileHandle *handle,
|
501
|
-
TemporaryFileIndex index) {
|
502
|
-
auto entry = used_blocks.find(id);
|
503
|
-
if (entry == used_blocks.end()) {
|
504
|
-
throw InternalException("EraseUsedBlock - Block %llu not found in used blocks", id);
|
505
|
-
}
|
506
|
-
used_blocks.erase(entry);
|
507
|
-
handle->EraseBlockIndex(index.block_index);
|
508
|
-
if (handle->DeleteIfEmpty()) {
|
509
|
-
EraseFileHandle(lock, index.file_index);
|
510
|
-
}
|
511
|
-
}
|
512
|
-
|
513
|
-
TemporaryFileHandle *GetFileHandle(TemporaryManagerLock &, idx_t index) {
|
514
|
-
return files[index].get();
|
515
|
-
}
|
516
|
-
|
517
|
-
TemporaryFileIndex GetTempBlockIndex(TemporaryManagerLock &, block_id_t id) {
|
518
|
-
D_ASSERT(used_blocks.find(id) != used_blocks.end());
|
519
|
-
return used_blocks[id];
|
520
|
-
}
|
521
|
-
|
522
|
-
void EraseFileHandle(TemporaryManagerLock &, idx_t file_index) {
|
523
|
-
files.erase(file_index);
|
524
|
-
index_manager.RemoveIndex(file_index);
|
525
|
-
}
|
526
|
-
|
527
|
-
private:
|
528
|
-
DatabaseInstance &db;
|
529
|
-
mutex manager_lock;
|
530
|
-
//! The temporary directory
|
531
|
-
string temp_directory;
|
532
|
-
//! The set of active temporary file handles
|
533
|
-
unordered_map<idx_t, unique_ptr<TemporaryFileHandle>> files;
|
534
|
-
//! map of block_id -> temporary file position
|
535
|
-
unordered_map<block_id_t, TemporaryFileIndex> used_blocks;
|
536
|
-
//! Manager of in-use temporary file indexes
|
537
|
-
BlockIndexManager index_manager;
|
538
|
-
};
|
539
|
-
|
540
|
-
TemporaryDirectoryHandle::TemporaryDirectoryHandle(DatabaseInstance &db, string path_p)
|
541
|
-
: db(db), temp_directory(std::move(path_p)), temp_file(make_uniq<TemporaryFileManager>(db, temp_directory)) {
|
542
|
-
auto &fs = FileSystem::GetFileSystem(db);
|
543
|
-
if (!temp_directory.empty()) {
|
544
|
-
if (!fs.DirectoryExists(temp_directory)) {
|
545
|
-
fs.CreateDirectory(temp_directory);
|
546
|
-
created_directory = true;
|
547
|
-
}
|
548
|
-
}
|
549
|
-
}
|
550
|
-
TemporaryDirectoryHandle::~TemporaryDirectoryHandle() {
|
551
|
-
// first release any temporary files
|
552
|
-
temp_file.reset();
|
553
|
-
// then delete the temporary file directory
|
554
|
-
auto &fs = FileSystem::GetFileSystem(db);
|
555
|
-
if (!temp_directory.empty()) {
|
556
|
-
bool delete_directory = created_directory;
|
557
|
-
vector<string> files_to_delete;
|
558
|
-
if (!created_directory) {
|
559
|
-
bool deleted_everything = true;
|
560
|
-
fs.ListFiles(temp_directory, [&](const string &path, bool isdir) {
|
561
|
-
if (isdir) {
|
562
|
-
deleted_everything = false;
|
563
|
-
return;
|
564
|
-
}
|
565
|
-
if (!StringUtil::StartsWith(path, "duckdb_temp_")) {
|
566
|
-
deleted_everything = false;
|
567
|
-
return;
|
568
|
-
}
|
569
|
-
files_to_delete.push_back(path);
|
570
|
-
});
|
571
|
-
}
|
572
|
-
if (delete_directory) {
|
573
|
-
// we want to remove all files in the directory
|
574
|
-
fs.RemoveDirectory(temp_directory);
|
575
|
-
} else {
|
576
|
-
for (auto &file : files_to_delete) {
|
577
|
-
fs.RemoveFile(fs.JoinPath(temp_directory, file));
|
578
|
-
}
|
579
|
-
}
|
580
|
-
}
|
52
|
+
bool BufferManager::HasTemporaryDirectory() const {
|
53
|
+
return false;
|
581
54
|
}
|
582
55
|
|
583
|
-
|
584
|
-
|
56
|
+
unique_ptr<FileBuffer> BufferManager::ConstructManagedBuffer(idx_t size, unique_ptr<FileBuffer> &&source,
|
57
|
+
FileBufferType type) {
|
58
|
+
throw NotImplementedException("This type of BufferManager can not construct managed buffers");
|
585
59
|
}
|
586
60
|
|
587
|
-
|
588
|
-
auto &fs = FileSystem::GetFileSystem(db);
|
589
|
-
return fs.JoinPath(temp_directory, "duckdb_temp_block-" + to_string(id) + ".block");
|
590
|
-
}
|
61
|
+
// Protected methods
|
591
62
|
|
592
|
-
void BufferManager::
|
593
|
-
|
594
|
-
throw Exception(
|
595
|
-
"Out-of-memory: cannot write buffer because no temporary directory is specified!\nTo enable "
|
596
|
-
"temporary buffer eviction set a temporary directory using PRAGMA temp_directory='/path/to/tmp.tmp'");
|
597
|
-
}
|
598
|
-
lock_guard<mutex> temp_handle_guard(temp_handle_lock);
|
599
|
-
if (!temp_directory_handle) {
|
600
|
-
// temp directory has not been created yet: initialize it
|
601
|
-
temp_directory_handle = make_uniq<TemporaryDirectoryHandle>(db, temp_directory);
|
602
|
-
}
|
63
|
+
void BufferManager::AddToEvictionQueue(shared_ptr<BlockHandle> &handle) {
|
64
|
+
throw NotImplementedException("This type of BufferManager does not support 'AddToEvictionQueue");
|
603
65
|
}
|
604
66
|
|
605
67
|
void BufferManager::WriteTemporaryBuffer(block_id_t block_id, FileBuffer &buffer) {
|
606
|
-
|
607
|
-
if (buffer.size == Storage::BLOCK_SIZE) {
|
608
|
-
temp_directory_handle->GetTempFile().WriteTemporaryBuffer(block_id, buffer);
|
609
|
-
return;
|
610
|
-
}
|
611
|
-
// get the path to write to
|
612
|
-
auto path = GetTemporaryPath(block_id);
|
613
|
-
D_ASSERT(buffer.size > Storage::BLOCK_SIZE);
|
614
|
-
// create the file and write the size followed by the buffer contents
|
615
|
-
auto &fs = FileSystem::GetFileSystem(db);
|
616
|
-
auto handle = fs.OpenFile(path, FileFlags::FILE_FLAGS_WRITE | FileFlags::FILE_FLAGS_FILE_CREATE);
|
617
|
-
handle->Write(&buffer.size, sizeof(idx_t), 0);
|
618
|
-
buffer.Write(*handle, sizeof(idx_t));
|
68
|
+
throw NotImplementedException("This type of BufferManager does not support 'WriteTemporaryBuffer");
|
619
69
|
}
|
620
70
|
|
621
|
-
unique_ptr<FileBuffer> BufferManager::ReadTemporaryBuffer(block_id_t id, unique_ptr<FileBuffer>
|
622
|
-
|
623
|
-
D_ASSERT(temp_directory_handle.get());
|
624
|
-
if (temp_directory_handle->GetTempFile().HasTemporaryBuffer(id)) {
|
625
|
-
return temp_directory_handle->GetTempFile().ReadTemporaryBuffer(id, std::move(reusable_buffer));
|
626
|
-
}
|
627
|
-
idx_t block_size;
|
628
|
-
// open the temporary file and read the size
|
629
|
-
auto path = GetTemporaryPath(id);
|
630
|
-
auto &fs = FileSystem::GetFileSystem(db);
|
631
|
-
auto handle = fs.OpenFile(path, FileFlags::FILE_FLAGS_READ);
|
632
|
-
handle->Read(&block_size, sizeof(idx_t), 0);
|
633
|
-
|
634
|
-
// now allocate a buffer of this size and read the data into that buffer
|
635
|
-
auto buffer =
|
636
|
-
ReadTemporaryBufferInternal(*this, *handle, sizeof(idx_t), block_size, id, std::move(reusable_buffer));
|
637
|
-
|
638
|
-
handle.reset();
|
639
|
-
DeleteTemporaryFile(id);
|
640
|
-
return buffer;
|
71
|
+
unique_ptr<FileBuffer> BufferManager::ReadTemporaryBuffer(block_id_t id, unique_ptr<FileBuffer> buffer) {
|
72
|
+
throw NotImplementedException("This type of BufferManager does not support 'ReadTemporaryBuffer");
|
641
73
|
}
|
642
74
|
|
643
75
|
void BufferManager::DeleteTemporaryFile(block_id_t id) {
|
644
|
-
|
645
|
-
// no temporary directory specified: nothing to delete
|
646
|
-
return;
|
647
|
-
}
|
648
|
-
{
|
649
|
-
lock_guard<mutex> temp_handle_guard(temp_handle_lock);
|
650
|
-
if (!temp_directory_handle) {
|
651
|
-
// temporary directory was not initialized yet: nothing to delete
|
652
|
-
return;
|
653
|
-
}
|
654
|
-
}
|
655
|
-
// check if we should delete the file from the shared pool of files, or from the general file system
|
656
|
-
if (temp_directory_handle->GetTempFile().HasTemporaryBuffer(id)) {
|
657
|
-
temp_directory_handle->GetTempFile().DeleteTemporaryBuffer(id);
|
658
|
-
return;
|
659
|
-
}
|
660
|
-
auto &fs = FileSystem::GetFileSystem(db);
|
661
|
-
auto path = GetTemporaryPath(id);
|
662
|
-
if (fs.FileExists(path)) {
|
663
|
-
fs.RemoveFile(path);
|
664
|
-
}
|
665
|
-
}
|
666
|
-
|
667
|
-
vector<TemporaryFileInformation> BufferManager::GetTemporaryFiles() {
|
668
|
-
vector<TemporaryFileInformation> result;
|
669
|
-
if (temp_directory.empty()) {
|
670
|
-
return result;
|
671
|
-
}
|
672
|
-
{
|
673
|
-
lock_guard<mutex> temp_handle_guard(temp_handle_lock);
|
674
|
-
if (temp_directory_handle) {
|
675
|
-
result = temp_directory_handle->GetTempFile().GetTemporaryFiles();
|
676
|
-
}
|
677
|
-
}
|
678
|
-
auto &fs = FileSystem::GetFileSystem(db);
|
679
|
-
fs.ListFiles(temp_directory, [&](const string &name, bool is_dir) {
|
680
|
-
if (is_dir) {
|
681
|
-
return;
|
682
|
-
}
|
683
|
-
if (!StringUtil::EndsWith(name, ".block")) {
|
684
|
-
return;
|
685
|
-
}
|
686
|
-
TemporaryFileInformation info;
|
687
|
-
info.path = name;
|
688
|
-
auto handle = fs.OpenFile(name, FileFlags::FILE_FLAGS_READ);
|
689
|
-
info.size = fs.GetFileSize(*handle);
|
690
|
-
handle.reset();
|
691
|
-
result.push_back(info);
|
692
|
-
});
|
693
|
-
return result;
|
694
|
-
}
|
695
|
-
|
696
|
-
const char *BufferManager::InMemoryWarning() {
|
697
|
-
if (!temp_directory.empty()) {
|
698
|
-
return "";
|
699
|
-
}
|
700
|
-
return "\nDatabase is launched in in-memory mode and no temporary directory is specified."
|
701
|
-
"\nUnused blocks cannot be offloaded to disk."
|
702
|
-
"\n\nLaunch the database with a persistent storage back-end"
|
703
|
-
"\nOr set PRAGMA temp_directory='/path/to/tmp.tmp'";
|
704
|
-
}
|
705
|
-
|
706
|
-
void BufferManager::ReserveMemory(idx_t size) {
|
707
|
-
if (size == 0) {
|
708
|
-
return;
|
709
|
-
}
|
710
|
-
auto reservation = EvictBlocksOrThrow(size, nullptr, "failed to reserve memory data of size %lld%s", size);
|
711
|
-
reservation.size = 0;
|
712
|
-
}
|
713
|
-
|
714
|
-
void BufferManager::FreeReservedMemory(idx_t size) {
|
715
|
-
if (size == 0) {
|
716
|
-
return;
|
717
|
-
}
|
718
|
-
buffer_pool.current_memory -= size;
|
719
|
-
}
|
720
|
-
|
721
|
-
//===--------------------------------------------------------------------===//
|
722
|
-
// Buffer Allocator
|
723
|
-
//===--------------------------------------------------------------------===//
|
724
|
-
data_ptr_t BufferManager::BufferAllocatorAllocate(PrivateAllocatorData *private_data, idx_t size) {
|
725
|
-
auto &data = (BufferAllocatorData &)*private_data;
|
726
|
-
auto reservation = data.manager.EvictBlocksOrThrow(size, nullptr, "failed to allocate data of size %lld%s", size);
|
727
|
-
// We rely on manual tracking of this one. :(
|
728
|
-
reservation.size = 0;
|
729
|
-
return Allocator::Get(data.manager.db).AllocateData(size);
|
730
|
-
}
|
731
|
-
|
732
|
-
void BufferManager::BufferAllocatorFree(PrivateAllocatorData *private_data, data_ptr_t pointer, idx_t size) {
|
733
|
-
auto &data = (BufferAllocatorData &)*private_data;
|
734
|
-
BufferPoolReservation r(data.manager.GetBufferPool());
|
735
|
-
r.size = size;
|
736
|
-
r.Resize(0);
|
737
|
-
return Allocator::Get(data.manager.db).FreeData(pointer, size);
|
738
|
-
}
|
739
|
-
|
740
|
-
data_ptr_t BufferManager::BufferAllocatorRealloc(PrivateAllocatorData *private_data, data_ptr_t pointer, idx_t old_size,
|
741
|
-
idx_t size) {
|
742
|
-
if (old_size == size) {
|
743
|
-
return pointer;
|
744
|
-
}
|
745
|
-
auto &data = (BufferAllocatorData &)*private_data;
|
746
|
-
BufferPoolReservation r(data.manager.GetBufferPool());
|
747
|
-
r.size = old_size;
|
748
|
-
r.Resize(size);
|
749
|
-
r.size = 0;
|
750
|
-
return Allocator::Get(data.manager.db).ReallocateData(pointer, old_size, size);
|
751
|
-
}
|
752
|
-
|
753
|
-
Allocator &BufferAllocator::Get(ClientContext &context) {
|
754
|
-
auto &manager = BufferManager::GetBufferManager(context);
|
755
|
-
return manager.GetBufferAllocator();
|
756
|
-
}
|
757
|
-
|
758
|
-
Allocator &BufferAllocator::Get(DatabaseInstance &db) {
|
759
|
-
return BufferManager::GetBufferManager(db).GetBufferAllocator();
|
760
|
-
}
|
761
|
-
|
762
|
-
Allocator &BufferAllocator::Get(AttachedDatabase &db) {
|
763
|
-
return BufferAllocator::Get(db.GetDatabase());
|
764
|
-
}
|
765
|
-
|
766
|
-
Allocator &BufferManager::GetBufferAllocator() {
|
767
|
-
return buffer_allocator;
|
76
|
+
throw NotImplementedException("This type of BufferManager does not support 'DeleteTemporaryFile");
|
768
77
|
}
|
769
78
|
|
770
79
|
} // namespace duckdb
|