Conversation
|
@greptile |
Greptile SummaryThis PR replaces the existing Key Changes:
Critical Issues Found:
These bugs can cause crashes, memory corruption, and resource exhaustion in production. Confidence Score: 1/5
Important Files Changed
Class Diagram%%{init: {'theme': 'neutral'}}%%
classDiagram
class VecBufferPool {
-int fd_
-size_t file_size_
-size_t pool_capacity_
+LPMap lp_map_
-mutex mutex_
-ConcurrentQueue~char*~ free_buffers_
+init(pool_capacity, block_size)
+acquire_buffer(block_id, offset, size, retry)
+get_meta(offset, length, buffer)
+get_handle()
}
class VecBufferPoolHandle {
+VecBufferPool& pool
+get_block(offset, size, block_id)
+get_meta(offset, length, buffer)
+release_one(block_id)
+acquire_one(block_id)
}
class LPMap {
-size_t entry_num_
-Entry* entries_
-LRUCache cache_
+init(entry_num)
+acquire_block(block_id)
+release_block(block_id)
+evict_block(block_id)
+set_block_acquired(block_id, buffer)
+recycle(free_buffers)
}
class LRUCache {
-int block_size_
-vector~ConcurrentQueue~ queues_
-atomic~size_t~ evict_queue_insertions_
+init(block_size)
+evict_single_block(item)
+add_single_block(lp_map, block, block_type)
+clear_dead_node(lp_map)
}
class MemoryBlock {
-MemoryBlockType type_
-void* data_
-VecBufferPoolHandle* buffer_pool_handle_
-int buffer_block_id_
+data()
+reset(buffer_pool_handle, block_id, data)
}
class BufferStorage {
-VecBufferPool::Pointer buffer_pool_
-VecBufferPoolHandle::Pointer buffer_pool_handle_
-map~string,SegmentInfo~ segments_
-map~string,size_t~ id_hash_
+open(path, create)
+get_buffer(offset, length, block_id)
+get_meta(offset, length, out)
}
VecBufferPool "1" --o "1" VecBufferPoolHandle : creates
VecBufferPool "1" *-- "1" LPMap : contains
LPMap "1" *-- "1" LRUCache : contains
BufferStorage "1" --> "1" VecBufferPool : uses
BufferStorage "1" --> "1" VecBufferPoolHandle : uses
MemoryBlock --> VecBufferPoolHandle : references
LPMap --> LRUCache : eviction policy
Last reviewed commit: 95b1c16 |
| for (size_t i = 0; i < buffer_num; i++) { | ||
| char *buffer = (char *)aligned_alloc(64, block_size); | ||
| if (buffer != nullptr) { | ||
| bool ok = free_buffers_.try_enqueue(buffer); |
There was a problem hiding this comment.
unused variable ok
| bool ok = free_buffers_.try_enqueue(buffer); | |
| free_buffers_.try_enqueue(buffer); |
| char *buffer = (char *)aligned_alloc(64, block_size); | ||
| if (buffer != nullptr) { | ||
| bool ok = free_buffers_.try_enqueue(buffer); | ||
| } |
There was a problem hiding this comment.
memory leak when aligned_alloc fails - allocated buffers are not freed on failure, and no error is returned
| if (entry.ref_count.load(std::memory_order_relaxed) == 0) { | ||
| entry.load_count.fetch_add(1, std::memory_order_relaxed); | ||
| } | ||
| entry.ref_count.fetch_add(1, std::memory_order_relaxed); | ||
| if (entry.ref_count.load(std::memory_order_relaxed) < 0) { | ||
| return nullptr; | ||
| } | ||
| return entry.buffer; |
There was a problem hiding this comment.
race condition: ref_count is checked at line 75, incremented at 78, then checked again at 79 - another thread could evict the block between these operations, making entry.buffer invalid by line 82
| ssize_t read_bytes = pread(fd_, buffer, size, offset); | ||
| if (read_bytes != static_cast<ssize_t>(size)) { | ||
| LOG_ERROR("Buffer pool failed to read file at offset: %zu", offset); | ||
| return nullptr; | ||
| } |
There was a problem hiding this comment.
memory leak when pread fails - buffer is not returned to free_buffers_, causing the pool to permanently lose this buffer
Additional Comments (2)
|
resolve #64