1#pragma once
2
3#include "duckdb/common/mutex.hpp"
4#include "duckdb/common/file_buffer.hpp"
5#include "duckdb/storage/buffer/block_handle.hpp"
6
7namespace duckdb {
8
9struct EvictionQueue;
10
11struct BufferEvictionNode {
12 BufferEvictionNode() {
13 }
14 BufferEvictionNode(weak_ptr<BlockHandle> handle_p, idx_t timestamp_p)
15 : handle(std::move(handle_p)), timestamp(timestamp_p) {
16 D_ASSERT(!handle.expired());
17 }
18
19 weak_ptr<BlockHandle> handle;
20 idx_t timestamp;
21
22 bool CanUnload(BlockHandle &handle_p);
23
24 shared_ptr<BlockHandle> TryGetBlockHandle();
25};
26
27//! The BufferPool is in charge of handling memory management for one or more databases. It defines memory limits
28//! and implements priority eviction among all users of the pool.
29class BufferPool {
30 friend class BlockHandle;
31 friend class BlockManager;
32 friend class BufferManager;
33 friend class StandardBufferManager;
34
35public:
36 explicit BufferPool(idx_t maximum_memory);
37 virtual ~BufferPool();
38
39 //! Set a new memory limit to the buffer pool, throws an exception if the new limit is too low and not enough
40 //! blocks can be evicted
41 void SetLimit(idx_t limit, const char *exception_postscript);
42
43 void IncreaseUsedMemory(idx_t size);
44
45 idx_t GetUsedMemory();
46
47 idx_t GetMaxMemory();
48
49protected:
50 //! Evict blocks until the currently used memory + extra_memory fit, returns false if this was not possible
51 //! (i.e. not enough blocks could be evicted)
52 //! If the "buffer" argument is specified AND the system can find a buffer to re-use for the given allocation size
53 //! "buffer" will be made to point to the re-usable memory. Note that this is not guaranteed.
54 //! Returns a pair. result.first indicates if eviction was successful. result.second contains the
55 //! reservation handle, which can be moved to the BlockHandle that will own the reservation.
56 struct EvictionResult {
57 bool success;
58 TempBufferPoolReservation reservation;
59 };
60 virtual EvictionResult EvictBlocks(idx_t extra_memory, idx_t memory_limit,
61 unique_ptr<FileBuffer> *buffer = nullptr);
62
63 //! Garbage collect eviction queue
64 void PurgeQueue();
65 void AddToEvictionQueue(shared_ptr<BlockHandle> &handle);
66
67private:
68 //! The lock for changing the memory limit
69 mutex limit_lock;
70 //! The current amount of memory that is occupied by the buffer manager (in bytes)
71 atomic<idx_t> current_memory;
72 //! The maximum amount of memory that the buffer manager can keep (in bytes)
73 atomic<idx_t> maximum_memory;
74 //! Eviction queue
75 unique_ptr<EvictionQueue> queue;
76 //! Total number of insertions into the eviction queue. This guides the schedule for calling PurgeQueue.
77 atomic<uint32_t> queue_insertions;
78};
79
80} // namespace duckdb
81