Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
1fe09d7
storage: fix btree_index lint issues and optimize search
poyrazK Feb 24, 2026
781f414
storage: address heap_table warnings and improve visibility checks
poyrazK Feb 24, 2026
9db9531
executor: fix query_executor signatures and lifecycle management
poyrazK Feb 24, 2026
f0d19c4
executor: fix unchecked optional access in hash join operator
poyrazK Feb 24, 2026
a87e40c
transaction: fix transaction_manager const correctness and snapshot l…
poyrazK Feb 24, 2026
3970f69
network: fix server shutdown stability and PostgreSQL protocol linting
poyrazK Feb 24, 2026
063dbdc
build: enable strict linting globally and fix main exception escape
poyrazK Feb 24, 2026
5c059a1
tests: modernize test macros and migrate network tests
poyrazK Feb 24, 2026
1bb00ba
ci: fix style violations and address Page/Server linting issues
poyrazK Feb 24, 2026
095daf4
ci: enforce project-wide clang-format compliance
poyrazK Feb 24, 2026
6da1b69
ci: resolve remaining style violations in tests and server
poyrazK Feb 24, 2026
cf9f8b6
ci: remove spaces from empty brace initializers to match clang-format 18
poyrazK Feb 24, 2026
4f52041
ci: add spaces to brace initializers to match clang-format 18 expecta…
poyrazK Feb 24, 2026
b9bc812
ci: remove spaces from initializers to match clang-format 18
poyrazK Feb 24, 2026
ee83845
ci: add spaces before braces and split test results lines to match cl…
poyrazK Feb 24, 2026
c524caf
ci: aggressively fix whitespace and initializer formatting for clang-…
poyrazK Feb 24, 2026
41699c4
ci: restore lost tests and fix main function formatting across all te…
poyrazK Feb 24, 2026
663e661
ci: try yet another formatting variation for clang-format 18
poyrazK Feb 24, 2026
411ed55
ci: update style-check to show diff on failure
poyrazK Feb 24, 2026
1832684
build: restore CMakeLists.txt and refactor test macros
poyrazK Feb 25, 2026
a2fc8fc
feat(storage): implement LRUReplacer for buffer pool management
poyrazK Feb 25, 2026
dc8bca5
feat(storage): implement BufferPoolManager
poyrazK Feb 25, 2026
20618ed
feat(recovery): add RecoveryManager framework
poyrazK Feb 25, 2026
2b5d41d
feat(recovery): enhance LogRecord implementation
poyrazK Feb 25, 2026
e273a01
refactor(transaction): update transaction management for buffer pool …
poyrazK Feb 25, 2026
2d6b89b
refactor(storage): update storage headers for page-based access
poyrazK Feb 25, 2026
ab7bb77
refactor(storage): implement page-based access in storage components
poyrazK Feb 25, 2026
e14ffd9
refactor(parser): modernize parser headers and resolve warnings
poyrazK Feb 25, 2026
f7c8167
refactor(parser): finalize parser implementation and catalog updates
poyrazK Feb 25, 2026
e201350
refactor(executor): enhance query operators and resolve warnings
poyrazK Feb 25, 2026
6e977e0
refactor(network): resolve persistent server warnings and modernize v…
poyrazK Feb 25, 2026
b806074
refactor: finalize main entry point and query executor
poyrazK Feb 25, 2026
53e04b0
test: update primary cloudSQL test suite
poyrazK Feb 25, 2026
01373d4
test: update server and transaction manager unit tests
poyrazK Feb 25, 2026
1e35425
test: add buffer pool and recovery manager unit tests
poyrazK Feb 25, 2026
f31c54d
test: add test execution script and E2E tests
poyrazK Feb 25, 2026
7dda2cb
style: apply clang-format to parser headers
poyrazK Feb 25, 2026
94ee26c
style: apply clang-format to parser and recovery implementation
poyrazK Feb 25, 2026
aa6dd02
style: apply clang-format to recovery and transaction headers
poyrazK Feb 25, 2026
4a01b35
style: apply clang-format to storage implementation
poyrazK Feb 25, 2026
6f460d2
style: apply clang-format to storage headers
poyrazK Feb 25, 2026
1af2b55
style: apply clang-format to executor components
poyrazK Feb 25, 2026
966cdc2
style: apply clang-format to core components
poyrazK Feb 25, 2026
d39abf1
style: apply clang-format to network and tests
poyrazK Feb 25, 2026
aaf2480
style: manually align formatting with clang-format 18 for CI compliance
poyrazK Feb 25, 2026
5cc33e0
style: final manual style alignment for CI (clang-format 18) v2
poyrazK Feb 25, 2026
2589c03
style: fix logic error in manual style alignment for storage_manager.cpp
poyrazK Feb 25, 2026
ec6cf73
style: fix indentation in manual style alignment for server_tests.cpp
poyrazK Feb 25, 2026
db4a77d
style: fix remaining clang-format issues in server.cpp
poyrazK Feb 25, 2026
e8c1f21
style: finalize manual style alignment for storage_manager.cpp
poyrazK Feb 25, 2026
79476f6
fix: resolve shadowing errors and finalize manual style alignment
poyrazK Feb 25, 2026
467290a
fix: resolve macro expansion errors and robust to_string in tests
poyrazK Feb 25, 2026
cf58a30
fix: finalize test macro expansion and robust string conversion
poyrazK Feb 25, 2026
ab473cf
style: manually align cloudSQL_tests.cpp with clang-format 18 for CI
poyrazK Feb 25, 2026
55f363e
style: manually align cloudSQL_tests.cpp with clang-format 18 line br…
poyrazK Feb 25, 2026
4a5f40a
style: manually align cloudSQL_tests.cpp with clang-format 18 line br…
poyrazK Feb 25, 2026
7912e59
style: final manual alignment for cloudSQL_tests.cpp (clang-format 18)
poyrazK Feb 25, 2026
08fb671
style: manually align cloudSQL_tests.cpp with clang-format 18 line br…
poyrazK Feb 25, 2026
40a3f45
style: manually align cloudSQL_tests.cpp with clang-format 18 line br…
poyrazK Feb 25, 2026
a5c6c77
fix: resolve remaining build and linting issues identified in CI
poyrazK Feb 25, 2026
418c108
fix: resolve CI build errors and improve test robustness
poyrazK Feb 25, 2026
dc9e15f
style: manually align test_utils.hpp with clang-format 18
poyrazK Feb 26, 2026
3d90873
fix: address build and lint warnings in core and tests
poyrazK Feb 26, 2026
bc52bc3
fix: add missing include in storage_manager.cpp
poyrazK Feb 26, 2026
132a92a
fix: resolve deadlock in LogManager by introducing internal flush
poyrazK Feb 26, 2026
e531604
fix: resolve deadlock in Server::wait by joining accept_thread withou…
poyrazK Feb 26, 2026
1b1851a
fix: add timeouts to LockManager waits to prevent permanent hangs in …
poyrazK Feb 26, 2026
311b23d
fix: resolve heap-use-after-free in TransactionManager by delaying de…
poyrazK Feb 26, 2026
8ac71f5
ci: ignore unused pattern errors in lcov
poyrazK Feb 26, 2026
273317f
feat: finalize e2e tests and minor storage fixes
poyrazK Feb 26, 2026
56c3310
refactor: address CodeRabbit feedback on safety, portability, and tes…
poyrazK Feb 26, 2026
f413cbd
style: manually apply clang-format 18 fixes to src/main.cpp, src/netw…
poyrazK Feb 26, 2026
3e81daf
style: manually fix indentation in server.cpp and cloudSQL_tests.cpp
poyrazK Feb 26, 2026
f640393
fix: resolve build errors and clang-format issues in storage and tests
poyrazK Feb 26, 2026
8f28256
fix: final build and warning resolutions across storage, transaction,…
poyrazK Feb 26, 2026
3d284ef
fix: address final build warnings, missing headers, and clang-format …
poyrazK Feb 26, 2026
a5ec37e
fix: manual apply of clang-format 18 and final header/warning fixes
poyrazK Feb 26, 2026
c0ebc2d
fix: resolve all build warnings and clang-format mismatches across th…
poyrazK Feb 26, 2026
7229d36
fix: resolve all build warnings, magic numbers, and EXPECT_THROW macr…
poyrazK Feb 26, 2026
004062e
fix: address final build warnings, magic numbers, and EXPECT_THROW ma…
poyrazK Feb 26, 2026
9a773c9
fix: align EXPECT_THROW macro, add missing network headers, and resol…
poyrazK Feb 26, 2026
6a113c1
fix: final comprehensive build, style and warning resolutions
poyrazK Feb 26, 2026
b520186
fix: resolve compiler errors in test_utils and address final build wa…
poyrazK Feb 26, 2026
9943f43
fix: address final build warnings, connection closure handling, and s…
poyrazK Feb 26, 2026
2e1d485
fix: add EXPECT_LE to test_utils.hpp
poyrazK Feb 26, 2026
8230821
fix: implement physical file removal in drop() and fix test macro ali…
poyrazK Feb 26, 2026
f304e2a
fix: comprehensive stability and safety fixes addressing CodeRabbit f…
poyrazK Feb 26, 2026
b426603
fix: implement physical file removal in drop() and fix test macro ali…
poyrazK Feb 26, 2026
a4c9d9e
style: fix clang-format alignment in tests
poyrazK Feb 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,14 @@ if(BUILD_TESTS)
add_executable(recovery_tests tests/recovery_tests.cpp)
target_link_libraries(recovery_tests PRIVATE sqlEngineCore)

# Create recovery manager unit tests
add_executable(recovery_manager_tests tests/recovery_manager_tests.cpp)
target_link_libraries(recovery_manager_tests PRIVATE sqlEngineCore)

# Create buffer pool unit tests
add_executable(buffer_pool_tests tests/buffer_pool_tests.cpp)
target_link_libraries(buffer_pool_tests PRIVATE sqlEngineCore)

# Check if GoogleTest is available
find_package(GTest QUIET)
if(GTest_FOUND)
Expand Down
6 changes: 3 additions & 3 deletions include/executor/query_executor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include "executor/types.hpp"
#include "parser/statement.hpp"
#include "recovery/log_manager.hpp"
#include "storage/storage_manager.hpp"
#include "storage/buffer_pool_manager.hpp"
#include "transaction/transaction_manager.hpp"

namespace cloudsql::executor {
Expand All @@ -21,7 +21,7 @@ namespace cloudsql::executor {
*/
class QueryExecutor {
public:
QueryExecutor(Catalog& catalog, storage::StorageManager& storage_manager,
QueryExecutor(Catalog& catalog, storage::BufferPoolManager& bpm,
transaction::LockManager& lock_manager,
transaction::TransactionManager& transaction_manager,
recovery::LogManager* log_manager = nullptr);
Expand All @@ -40,7 +40,7 @@ class QueryExecutor {

private:
Catalog& catalog_;
storage::StorageManager& storage_manager_;
storage::BufferPoolManager& bpm_;
transaction::LockManager& lock_manager_;
transaction::TransactionManager& transaction_manager_;
recovery::LogManager* log_manager_;
Expand Down
8 changes: 4 additions & 4 deletions include/network/server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

#include "catalog/catalog.hpp"
#include "executor/query_executor.hpp"
#include "storage/storage_manager.hpp"
#include "storage/buffer_pool_manager.hpp"
#include "transaction/lock_manager.hpp"
#include "transaction/transaction_manager.hpp"

Expand Down Expand Up @@ -57,7 +57,7 @@ class Server {
/**
* @brief Constructor
*/
Server(uint16_t port, Catalog& catalog, storage::StorageManager& storage_manager);
Server(uint16_t port, Catalog& catalog, storage::BufferPoolManager& bpm);

/**
* @brief Destructor
Expand All @@ -83,7 +83,7 @@ class Server {
* @brief Create a new server instance
*/
[[nodiscard]] static std::unique_ptr<Server> create(uint16_t port, Catalog& catalog,
storage::StorageManager& storage_manager);
storage::BufferPoolManager& bpm);

/**
* @brief Start the server
Expand Down Expand Up @@ -117,7 +117,7 @@ class Server {
ServerStatus status_ = ServerStatus::Stopped;

Catalog& catalog_;
storage::StorageManager& storage_manager_;
storage::BufferPoolManager& bpm_;
transaction::LockManager lock_manager_;
transaction::TransactionManager transaction_manager_;

Expand Down
6 changes: 3 additions & 3 deletions include/storage/btree_index.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

#include "common/value.hpp"
#include "storage/heap_table.hpp"
#include "storage/storage_manager.hpp"
#include "storage/buffer_pool_manager.hpp"

namespace cloudsql::storage {

Expand Down Expand Up @@ -68,12 +68,12 @@ class BTreeIndex {
private:
std::string index_name_;
std::string filename_;
StorageManager& storage_manager_;
BufferPoolManager& bpm_;
common::ValueType key_type_;
uint32_t root_page_ = 0;

public:
BTreeIndex(std::string index_name, StorageManager& storage_manager, common::ValueType key_type);
BTreeIndex(std::string index_name, BufferPoolManager& bpm, common::ValueType key_type);

~BTreeIndex() = default;

Expand Down
8 changes: 4 additions & 4 deletions include/storage/heap_table.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#include <vector>

#include "executor/types.hpp"
#include "storage/storage_manager.hpp"
#include "storage/buffer_pool_manager.hpp"

namespace cloudsql::storage {

Expand Down Expand Up @@ -120,17 +120,17 @@ class HeapTable {
private:
std::string table_name_;
std::string filename_;
StorageManager& storage_manager_;
BufferPoolManager& bpm_;
executor::Schema schema_;

public:
/**
* @brief Constructor
* @param table_name Logical name of the table
* @param storage_manager Reference to the global storage manager
* @param bpm Reference to the global buffer pool manager
* @param schema Table schema definition
*/
HeapTable(std::string table_name, StorageManager& storage_manager, executor::Schema schema);
HeapTable(std::string table_name, BufferPoolManager& bpm, executor::Schema schema);

~HeapTable() = default;

Expand Down
74 changes: 74 additions & 0 deletions include/storage/page.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* @file page.hpp
* @brief Base page class for the buffer pool manager
*/

#ifndef CLOUDSQL_STORAGE_PAGE_HPP
#define CLOUDSQL_STORAGE_PAGE_HPP

#include <cstring>
#include <shared_mutex>
#include <string>
#include <array>

namespace cloudsql::storage {

/**
* @class Page
* @brief Represents a single page in memory managed by the Buffer Pool
*/
class Page {
public:
static constexpr uint32_t PAGE_SIZE = 4096;

Page() { reset_memory(); }

Page(const Page&) = delete;
Page& operator=(const Page&) = delete;
Page(Page&&) = delete;
Page& operator=(Page&&) = delete;
virtual ~Page() = default;

// Output raw pointer
[[nodiscard]] char* get_data() { return data_.data(); }

[[nodiscard]] uint32_t get_page_id() const { return page_id_; }

[[nodiscard]] int get_pin_count() const { return pin_count_; }

[[nodiscard]] bool is_dirty() const { return is_dirty_; }

[[nodiscard]] std::string get_file_name() const { return file_name_; }

// Read/Write Latch for concurrent access
void r_lock() { rwlatch_.lock_shared(); }
void r_unlock() { rwlatch_.unlock_shared(); }
void w_lock() { rwlatch_.lock(); }
void w_unlock() { rwlatch_.unlock(); }

// Get Page LSN (for recovery/WAL)
// Assuming page layout reserves first 8 bytes (or 4 bytes) for PageLSN depending on implementation
// We will store LSN explicitly here to avoid parsing the header if not strictly needed,
// but typically it's written in the first 4 bytes of data_.
[[nodiscard]] int32_t get_lsn() const { return lsn_; }
void set_lsn(int32_t lsn) { lsn_ = lsn; }
Comment on lines +49 to +54

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, find all relevant files
find . -type f -name "*.hpp" -o -name "*.cpp" | grep -E "(buffer_pool|page)" | head -20

Repository: poyrazK/cloudSQL

Length of output: 86


🏁 Script executed:

# Search for BufferPoolManager class and flush-related methods
rg -n 'class BufferPoolManager' --type=cpp -A 20

Repository: poyrazK/cloudSQL

Length of output: 1135


🏁 Script executed:

# Search for flush, write, or persistence operations related to pages and LSN
rg -n 'flush|writePage|write_page' --type=cpp -C 3

Repository: poyrazK/cloudSQL

Length of output: 16323


🏁 Script executed:

# Check page.hpp for LSN comments and member declarations
fd page.hpp -x cat -n {}

Repository: poyrazK/cloudSQL

Length of output: 2789


🏁 Script executed:

# Search for any LSN serialization or deserialization logic
rg -n 'lsn_.*=|memcpy.*lsn|lsn.*data' --type=cpp -C 2

Repository: poyrazK/cloudSQL

Length of output: 6912


🏁 Script executed:

# Find BufferPoolManager definition
find . -type f \( -name "*.hpp" -o -name "*.cpp" \) | xargs grep -l "class BufferPoolManager"

Repository: poyrazK/cloudSQL

Length of output: 86


🏁 Script executed:

# Search for BufferPoolManager in header files
fd -e hpp -e cpp | xargs grep -n "BufferPoolManager" | head -30

Repository: poyrazK/cloudSQL

Length of output: 2713


🏁 Script executed:

# Look for buffer_pool or bpm files
fd buffer_pool -e hpp -e cpp

Repository: poyrazK/cloudSQL

Length of output: 42


🏁 Script executed:

# Search for BufferPoolManager class definition (not just references)
rg -n "class BufferPoolManager" --type=cpp --type=hpp

Repository: poyrazK/cloudSQL

Length of output: 87


🏁 Script executed:

# List all files in include/storage
ls -la include/storage/

Repository: poyrazK/cloudSQL

Length of output: 433


🏁 Script executed:

# Check if BufferPoolManager is defined in page.hpp or another file
rg -n "^class BufferPoolManager|^struct BufferPoolManager" --type=cpp --type=hpp -B 2

Repository: poyrazK/cloudSQL

Length of output: 87


🏁 Script executed:

# Search for BufferPoolManager class definition without file type
rg -n "class BufferPoolManager" -B 2 -A 30

Repository: poyrazK/cloudSQL

Length of output: 1204


🏁 Script executed:

# List all header and cpp files
find include src -type f -name "*.hpp" -o -name "*.cpp" | sort

Repository: poyrazK/cloudSQL

Length of output: 1150


🏁 Script executed:

# Search in storage_manager.hpp for BufferPoolManager
rg -n "BufferPoolManager" include/storage/storage_manager.hpp -B 3 -A 20

Repository: poyrazK/cloudSQL

Length of output: 42


🏁 Script executed:

# Check if BufferPoolManager is defined inline or in a separate location
rg -n "BufferPoolManager.*{" -A 50

Repository: poyrazK/cloudSQL

Length of output: 163


🏁 Script executed:

# List what's in storage_manager.hpp
cat include/storage/storage_manager.hpp

Repository: poyrazK/cloudSQL

Length of output: 2639


🏁 Script executed:

# Search for BufferPoolManager in all files
rg "BufferPoolManager" -l

Repository: poyrazK/cloudSQL

Length of output: 461


🏁 Script executed:

# Check if BufferPoolManager might be a typedef or alias
rg "BufferPoolManager\s*="

Repository: poyrazK/cloudSQL

Length of output: 42


🏁 Script executed:

# Search more broadly for "Buffer" or "Pool" in filenames
find . -type f -name "*buffer*" -o -name "*pool*"

Repository: poyrazK/cloudSQL

Length of output: 42


🏁 Script executed:

# Check main.cpp where BufferPoolManager is instantiated
cat src/main.cpp | grep -A 20 "BufferPoolManager"

Repository: poyrazK/cloudSQL

Length of output: 963


🏁 Script executed:

# Search for the full definition with line numbers
rg -n "BufferPoolManager" src/main.cpp -B 5 -A 10

Repository: poyrazK/cloudSQL

Length of output: 818


🏁 Script executed:

# Check if there's a header file we missed
find . -type f \( -name "*.h" -o -name "*.hpp" \)

Repository: poyrazK/cloudSQL

Length of output: 764


🏁 Script executed:

# Search all cpp files for BufferPoolManager class definition
rg "class BufferPoolManager" --type-list

Repository: poyrazK/cloudSQL

Length of output: 449


🏁 Script executed:

# Try a simpler search - look for where BufferPoolManager is defined
rg "class BufferPoolManager"

Repository: poyrazK/cloudSQL

Length of output: 120


🏁 Script executed:

# Check if BufferPoolManager is perhaps an alias for StorageManager
rg "using BufferPoolManager"

Repository: poyrazK/cloudSQL

Length of output: 42


🏁 Script executed:

# Search in all text for BufferPoolManager definition
grep -r "class BufferPoolManager" .

Repository: poyrazK/cloudSQL

Length of output: 122


🏁 Script executed:

# Look for any file containing "BufferPoolManager" content
find . -type f -exec grep -l "BufferPoolManager" {} \;

Repository: poyrazK/cloudSQL

Length of output: 489


🏁 Script executed:

# Check all files in include/storage more carefully
ls -la include/storage/
cat include/storage/*.hpp

Repository: poyrazK/cloudSQL

Length of output: 15134


🏁 Script executed:

# Check if there are any files without standard extensions
find include/storage -type f

Repository: poyrazK/cloudSQL

Length of output: 183


🏁 Script executed:

# Try to find buffer_pool_manager specifically
find . -iname "*buffer*"

Repository: poyrazK/cloudSQL

Length of output: 42


🏁 Script executed:

# Found it! Check buffer_pool_manager.hpp which is referenced but not in ls output
cat include/storage/buffer_pool_manager.hpp

Repository: poyrazK/cloudSQL

Length of output: 131


🏁 Script executed:

# Also search for its implementation
find . -name "*buffer_pool_manager*"

Repository: poyrazK/cloudSQL

Length of output: 42


🏁 Script executed:

# Search for all includes of buffer_pool_manager
rg "buffer_pool_manager" -n

Repository: poyrazK/cloudSQL

Length of output: 1034


🏁 Script executed:

# Check what files reference BufferPoolManager
rg "include.*buffer" -n

Repository: poyrazK/cloudSQL

Length of output: 1034


🏁 Script executed:

# Look for any errors or TODOs about BufferPoolManager
rg "BufferPoolManager|buffer.pool" -n -B 2 -A 2

Repository: poyrazK/cloudSQL

Length of output: 24131


🏁 Script executed:

# Check btree_index.hpp line 14 more carefully
head -20 include/storage/btree_index.hpp

Repository: poyrazK/cloudSQL

Length of output: 430


🏁 Script executed:

# The header file is referenced but doesn't exist. Let's check if there's a cpp file
find . -name "*buffer_pool*"

Repository: poyrazK/cloudSQL

Length of output: 42


🏁 Script executed:

# Check CMakeLists to see how the project is being compiled
cat CMakeLists.txt | grep -i buffer -B 3 -A 3

Repository: poyrazK/cloudSQL

Length of output: 447


🏁 Script executed:

# See what tests reference buffer_pool_tests
cat tests/buffer_pool_tests.cpp 2>/dev/null | head -100

Repository: poyrazK/cloudSQL

Length of output: 42


🏁 Script executed:

# Check if buffer_pool_tests.cpp exists
ls -la tests/buffer_pool_tests.cpp

Repository: poyrazK/cloudSQL

Length of output: 134


🏁 Script executed:

# List all test files
ls tests/*.cpp

Repository: poyrazK/cloudSQL

Length of output: 223


🏁 Script executed:

# Verify that buffer_pool_manager.hpp is truly missing
ls -la include/storage/buffer_pool_manager.hpp

Repository: poyrazK/cloudSQL

Length of output: 146


🏁 Script executed:

# Check if there's a src/storage/buffer_pool_manager.cpp
ls -la src/storage/

Repository: poyrazK/cloudSQL

Length of output: 379


BufferPoolManager must serialize page LSN to persist it with page data.

The Page class stores lsn_ as a separate member, not as part of data_. Your comment correctly notes that LSNs are "typically written in the first 4 bytes of data_," but this implementation keeps them separate. When BufferPoolManager flushes dirty pages to disk, it will write only the data_ buffer—the lsn_ value will remain in memory and be lost on crash. Recovery will lack page LSNs needed to check durability of modifications.

Ensure BufferPoolManager.flush_page() serializes the current lsn_ value into data_ before calling StorageManager.write_page(), and deserializes it back on read, or document why a different recovery strategy is used.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@include/storage/page.hpp` around lines 49 - 54, The Page currently keeps LSN
in lsn_ separate from data_, so update the flush/read paths to persist the LSN:
before BufferPoolManager::flush_page() calls StorageManager::write_page(),
serialize get_lsn() into the agreed bytes at the start of the Page::data_ buffer
(e.g., first 4 bytes) so the on-disk page contains the LSN, and likewise when
pages are read back from StorageManager::read_page() deserialize those bytes
into Page::set_lsn(); modify BufferPoolManager::flush_page() and the page load
path to perform this packing/unpacking, ensuring get_lsn()/set_lsn() remain
authoritative and consistent with data_ prior to any disk I/O.


private:
friend class BufferPoolManager;

void reset_memory() { data_.fill(0); }

std::array<char, PAGE_SIZE> data_{}; // Fixed size page array
uint32_t page_id_ = 0; // The logical page id within the file
std::string file_name_; // File this page belongs to

int pin_count_ = 0; // Number of concurrent accesses
bool is_dirty_ = false; // Whether page has been modified
int32_t lsn_ = -1; // Page LSN, last modified operation

std::shared_mutex rwlatch_;
Comment on lines +56 to +69

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check how BufferPoolManager uses reset_memory and whether it manually resets other fields
rg -n "reset_memory|page_id_\s*=|pin_count_\s*=|is_dirty_\s*=|file_name_\s*=" --type=cpp -C 3 -g '!tests/*'

Repository: poyrazK/cloudSQL

Length of output: 6138


reset_memory() only zeroes data_, requiring BufferPoolManager to manually reset all metadata fields — introducing risk of inconsistency.

While FetchPage and NewPage do reset all metadata fields (page_id_, file_name_, pin_count_, is_dirty_, lsn_) after calling reset_memory(), the DeletePage function doesn't explicitly reset pin_count_. This inconsistency suggests fragility: the code relies on distributed manual resets across three locations instead of centralizing cleanup in reset_memory(). The proposed fix consolidates these resets into one place, making the code clearer and safer against future oversights.

Proposed fix
     void reset_memory() {
         data_.fill(0);
+        page_id_ = 0;
+        file_name_.clear();
+        pin_count_ = 0;
+        is_dirty_ = false;
+        lsn_ = -1;
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
private:
friend class BufferPoolManager;
void reset_memory() { data_.fill(0); }
std::array<char, PAGE_SIZE> data_{}; // Fixed size page array
uint32_t page_id_ = 0; // The logical page id within the file
std::string file_name_; // File this page belongs to
int pin_count_ = 0; // Number of concurrent accesses
bool is_dirty_ = false; // Whether page has been modified
int32_t lsn_ = -1; // Page LSN, last modified operation
std::shared_mutex rwlatch_;
private:
friend class BufferPoolManager;
void reset_memory() {
data_.fill(0);
page_id_ = 0;
file_name_.clear();
pin_count_ = 0;
is_dirty_ = false;
lsn_ = -1;
}
std::array<char, PAGE_SIZE> data_{}; // Fixed size page array
uint32_t page_id_ = 0; // The logical page id within the file
std::string file_name_; // File this page belongs to
int pin_count_ = 0; // Number of concurrent accesses
bool is_dirty_ = false; // Whether page has been modified
int32_t lsn_ = -1; // Page LSN, last modified operation
std::shared_mutex rwlatch_;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@include/storage/page.hpp` around lines 56 - 69, The reset_memory() helper
currently only zeroes data_ causing metadata resets to be scattered (in
FetchPage, NewPage, but not DeletePage); modify reset_memory() to also reset
page_id_, file_name_, pin_count_, is_dirty_, and lsn_ (e.g. page_id_ = 0;
file_name_.clear(); pin_count_ = 0; is_dirty_ = false; lsn_ = -1) so all page
state is centralized, then remove redundant manual metadata resets from
FetchPage and NewPage (and ensure DeletePage no longer relies on a missing
manual reset).

};

} // namespace cloudsql::storage

#endif // CLOUDSQL_STORAGE_PAGE_HPP
8 changes: 4 additions & 4 deletions include/transaction/transaction_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

#include "catalog/catalog.hpp"
#include "recovery/log_manager.hpp"
#include "storage/storage_manager.hpp"
#include "storage/buffer_pool_manager.hpp"
#include "transaction/lock_manager.hpp"
#include "transaction/transaction.hpp"

Expand All @@ -24,19 +24,19 @@ class TransactionManager {
std::unordered_map<txn_id_t, std::unique_ptr<Transaction>> active_transactions_;
LockManager& lock_manager_;
Catalog& catalog_;
storage::StorageManager& storage_manager_;
storage::BufferPoolManager& bpm_;
recovery::LogManager* log_manager_;
std::mutex manager_latch_;

void undo_transaction(Transaction* txn);

public:
explicit TransactionManager(LockManager& lock_manager, Catalog& catalog,
storage::StorageManager& storage_manager,
storage::BufferPoolManager& bpm,
recovery::LogManager* log_manager = nullptr)
: lock_manager_(lock_manager),
catalog_(catalog),
storage_manager_(storage_manager),
bpm_(bpm),
log_manager_(log_manager) {}

Transaction* begin(IsolationLevel level = IsolationLevel::REPEATABLE_READ);
Expand Down
2 changes: 1 addition & 1 deletion src/executor/operator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ bool HashJoinOperator::next(Tuple& out_tuple) {

/* Concatenate left and right tuples */
if (left_tuple_.has_value()) {
std::vector<common::Value> joined_values = left_tuple_->value().values();
std::vector<common::Value> joined_values = left_tuple_->values();
joined_values.insert(joined_values.end(), right_tuple.values().begin(),
right_tuple.values().end());

Expand Down
24 changes: 12 additions & 12 deletions src/executor/query_executor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,19 @@
#include "recovery/log_record.hpp"
#include "storage/btree_index.hpp"
#include "storage/heap_table.hpp"
#include "storage/storage_manager.hpp"
#include "storage/buffer_pool_manager.hpp"
#include "transaction/lock_manager.hpp"
#include "transaction/transaction.hpp"
#include "transaction/transaction_manager.hpp"

namespace cloudsql::executor {

QueryExecutor::QueryExecutor(Catalog& catalog, storage::StorageManager& storage_manager,
QueryExecutor::QueryExecutor(Catalog& catalog, storage::BufferPoolManager& bpm,
transaction::LockManager& lock_manager,
transaction::TransactionManager& transaction_manager,
recovery::LogManager* log_manager)
: catalog_(catalog),
storage_manager_(storage_manager),
bpm_(bpm),
lock_manager_(lock_manager),
transaction_manager_(transaction_manager),
log_manager_(log_manager) {}
Expand Down Expand Up @@ -209,7 +209,7 @@ QueryResult QueryExecutor::execute_create_table(const parser::CreateTableStateme
return result;
}
const auto* table_info = table_info_opt.value();
storage::HeapTable table(table_info->name, storage_manager_, executor::Schema());
storage::HeapTable table(table_info->name, bpm_, executor::Schema());
if (!table.create()) {
static_cast<void>(catalog_.drop_table(table_id));
result.set_error("Failed to create table file");
Expand Down Expand Up @@ -243,7 +243,7 @@ QueryResult QueryExecutor::execute_insert(const parser::InsertStatement& stmt,
schema.add_column(col.name, col.type);
}

storage::HeapTable table(table_name, storage_manager_, schema);
storage::HeapTable table(table_name, bpm_, schema);

uint64_t rows_inserted = 0;
const uint64_t xmin = (txn != nullptr) ? txn->get_id() : 0;
Expand Down Expand Up @@ -298,7 +298,7 @@ QueryResult QueryExecutor::execute_delete(const parser::DeleteStatement& stmt,
schema.add_column(col.name, col.type);
}

storage::HeapTable table(table_name, storage_manager_, schema);
storage::HeapTable table(table_name, bpm_, schema);
const uint64_t xmax = (txn != nullptr) ? txn->get_id() : 0;
uint64_t rows_deleted = 0;

Expand Down Expand Up @@ -362,7 +362,7 @@ QueryResult QueryExecutor::execute_update(const parser::UpdateStatement& stmt,
schema.add_column(col.name, col.type);
}

storage::HeapTable table(table_name, storage_manager_, schema);
storage::HeapTable table(table_name, bpm_, schema);
const uint64_t txn_id = (txn != nullptr) ? txn->get_id() : 0;
uint64_t rows_updated = 0;

Expand Down Expand Up @@ -456,7 +456,7 @@ std::unique_ptr<Operator> QueryExecutor::build_plan(const parser::SelectStatemen
}

std::unique_ptr<Operator> current_root = std::make_unique<SeqScanOperator>(
std::make_unique<storage::HeapTable>(base_table_name, storage_manager_, base_schema), txn,
std::make_unique<storage::HeapTable>(base_table_name, bpm_, base_schema), txn,
&lock_manager_);

/* 2. Add JOINs */
Expand All @@ -474,7 +474,7 @@ std::unique_ptr<Operator> QueryExecutor::build_plan(const parser::SelectStatemen
}

auto join_scan = std::make_unique<SeqScanOperator>(
std::make_unique<storage::HeapTable>(join_table_name, storage_manager_, join_schema),
std::make_unique<storage::HeapTable>(join_table_name, bpm_, join_schema),
txn, &lock_manager_);

/* For now, we use HashJoin if a condition exists, otherwise NestedLoop would be needed.
Expand Down Expand Up @@ -640,12 +640,12 @@ QueryResult QueryExecutor::execute_drop_table(const parser::DropTableStatement&
/* 1. Drop associated indexes from physical storage */
const auto indexes = catalog_.get_table_indexes(table_id);
for (const auto& idx_info : indexes) {
storage::BTreeIndex idx(idx_info->name, storage_manager_, common::ValueType::TYPE_NULL);
storage::BTreeIndex idx(idx_info->name, bpm_, common::ValueType::TYPE_NULL);
static_cast<void>(idx.drop());
}

/* 2. Drop table physical file */
storage::HeapTable table(stmt.table_name(), storage_manager_, executor::Schema());
storage::HeapTable table(stmt.table_name(), bpm_, executor::Schema());
static_cast<void>(table.drop());

/* 3. Update catalog */
Expand Down Expand Up @@ -685,7 +685,7 @@ QueryResult QueryExecutor::execute_drop_index(const parser::DropIndexStatement&
}

/* 1. Drop physical file */
storage::BTreeIndex idx(stmt.index_name(), storage_manager_, common::ValueType::TYPE_NULL);
storage::BTreeIndex idx(stmt.index_name(), bpm_, common::ValueType::TYPE_NULL);
static_cast<void>(idx.drop());

/* 2. Update catalog */
Expand Down
24 changes: 19 additions & 5 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@
#include "catalog/catalog.hpp"
#include "common/config.hpp"
#include "network/server.hpp"
#include "storage/storage_manager.hpp"
#include "parser/lexer.hpp" // Added by user instruction
#include "recovery/log_manager.hpp" // Added by user instruction
#include "recovery/recovery_manager.hpp" // Added by user instruction
#include "storage/buffer_pool_manager.hpp"
#include "storage/storage_manager.hpp" // Added by user instruction

namespace {

Expand Down Expand Up @@ -117,18 +121,28 @@ int main(int argc, char* argv[]) { // NOLINT(bugprone-exception-escape)
static_cast<void>(std::signal(SIGTERM, signal_handler));

try {
/* Initialize storage manager */
const auto storage_manager = std::make_unique<cloudsql::storage::StorageManager>(config.data_dir);

/* Initialize storage manager & buffer pool */
auto disk_manager = std::make_unique<cloudsql::storage::StorageManager>(config.data_dir);
auto bpm = std::make_unique<cloudsql::storage::BufferPoolManager>(128, *disk_manager);
/* Initialize catalog */
const auto catalog = cloudsql::Catalog::create();
if (!catalog) {
std::cerr << "Failed to initialize catalog\n";
return 1;
}

/* Initialize log manager & run recovery */
auto log_manager = std::make_unique<cloudsql::recovery::LogManager>(config.data_dir + "/wal.log");

std::cout << "Running Crash Recovery..." << std::endl;
cloudsql::recovery::RecoveryManager rm(*bpm, *catalog, *log_manager);
if (!rm.recover()) {
std::cerr << "Crash recovery failed. Restarting anyway.\n";
}
log_manager->run_flush_thread();
Comment on lines +166 to +174

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Log flush thread is started but never explicitly stopped — use-after-free / UB on shutdown.

log_manager->run_flush_thread() launches a background thread that presumably holds references into log_manager (and possibly bpm_). When the try block exits, log_manager (a unique_ptr) is destroyed in reverse-construction order, but the flush thread may still be running at that point. There is no stop_flush_thread() or join call before log_manager goes out of scope.

Add an explicit stop/join of the flush thread before log_manager is destroyed (or before server->stop() at minimum).

🐛 Suggested teardown ordering
     /* Cleanup */
     std::cout << "Shutting down...\n";
     static_cast<void>(server->stop());
     server.reset();
+
+    log_manager->stop_flush_thread();  // join before log_manager is destroyed
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main.cpp` around lines 142 - 150, The background flush thread started by
log_manager->run_flush_thread() can outlive the log_manager unique_ptr and cause
use-after-free; ensure the thread is explicitly stopped/joined before
log_manager is destroyed (for example add and call
log_manager->stop_flush_thread() or log_manager->join_flush_thread() after
recovery and before exiting the try-block or before server->stop()), and if
run_flush_thread returns or stores a joinable handle, join that handle before
letting log_manager go out of scope; update teardown ordering around
cloudsql::recovery::LogManager, RecoveryManager rm, and server->stop()
accordingly.


/* Initialize server */
g_server = cloudsql::network::Server::create(config.port, *catalog, *storage_manager);
g_server = cloudsql::network::Server::create(config.port, *catalog, *bpm);
if (!g_server) {
std::cerr << "Failed to create server\n";
return 1;
Expand Down
Loading
Loading