Skip to content

[wip] dont recreate database#299

Open
SWvheerden wants to merge 1 commit intodevelopmentfrom
sw_dont_recreate_db
Open

[wip] dont recreate database#299
SWvheerden wants to merge 1 commit intodevelopmentfrom
sw_dont_recreate_db

Conversation

@SWvheerden
Copy link
Contributor

@SWvheerden SWvheerden commented Mar 27, 2025

Description

Dont recreate the database on start

Summary by CodeRabbit

  • New Features

    • Block insertion now supports an optional control parameter that enables conditional overwriting, enhancing management of duplicate entries.
  • Refactor

    • Chain initialization has been streamlined by removing legacy backup handling.
    • The loading process now tracks performance timing for improved diagnostics.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 27, 2025

Walkthrough

The changes remove redundant backup file handling in the in-memory share chain, simplifying initialization by directly using the current block cache. The LMDB block storage’s insert method now accepts a force boolean parameter to manage duplicate insertions, and associated migration checks have been removed. In the P2Chain components, the chain load process now uses a unified block cache with time logging and a forced termination (panic) after logging, while the block addition methods in both P2Chain and P2ChainLevel have been updated to accept an extra boolean parameter.

Changes

File(s) Change Summary
p2pool/.../in_memory.rs Removed backup file handling by commenting out the construction, renaming, and removal of backup block cache files; now directly initializes the block cache from the current data path.
p2pool/.../lmdb_block_storage.rs Updated the insert method signature (in the trait and implementation) to include a force: bool parameter; added logic to conditionally skip duplicate insertion when force is true, and removed obsolete migration check code.
p2pool/.../p2chain.rs
p2pool/.../p2chain_level.rs
In P2Chain the try_load method now utilizes the block cache directly, logs load duration, and triggers a panic after logging; both files update the add_block method to include an additional boolean parameter, and calls to insert now pass a corresponding force flag.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant P2Chain
    participant BlockCache
    Client->>P2Chain: try_load(new_chain.block_cache)
    P2Chain->>BlockCache: Load chain data
    P2Chain->>P2Chain: Record and log load duration
    P2Chain->>Client: Trigger panic("close")
Loading
sequenceDiagram
    participant Client
    participant ChainLevel
    participant BlockCache
    Client->>ChainLevel: add_block(block, force)
    ChainLevel->>BlockCache: insert(hash, block, force)
    BlockCache-->>ChainLevel: Return insert result
    ChainLevel-->>Client: Block addition complete
Loading

Possibly related PRs

Suggested reviewers

  • hansieodendaal

Poem

In the digital meadow, I hop with delight,
Simplifying code from morning to night.
Backup files vanish like shadows in the sun,
With forced insertions, the job’s neatly done.
I scamper through bytes with a rhythmic beat,
Celebrating clean code—oh, so sweet!
🐇 Hopping with CodeRabbit cheer and tweet!

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🔭 Outside diff range comments (3)
p2pool/src/sharechain/p2chain.rs (1)

235-263: ⚠️ Potential issue

Critical issue: Panic statement will prevent application from functioning properly

The changes in the try_load method add timing and logging functionality, but the panic!("close") statement on line 263 will unconditionally terminate the program after loading the chain. This appears to be a debugging artifact that shouldn't be in production code.

-        panic!("close");
p2pool/src/sharechain/p2chain_level.rs (1)

139-163: ⚠️ Potential issue

Method updated to support force parameter

The add_block method has been updated to accept and propagate the force parameter to the block cache insertion. This change provides more control over whether to overwrite existing blocks.

However, the test code is not updated to match the new signature. The tests need to be fixed:

-        chain_level.add_block(block_2.clone()).unwrap();
+        chain_level.add_block(block_2.clone(), false).unwrap();

-        chain_level.add_block(block_3.clone()).unwrap();
+        chain_level.add_block(block_3.clone(), false).unwrap();
p2pool/src/sharechain/lmdb_block_storage.rs (1)

276-278: ⚠️ Potential issue

Tests need updating to use the new insert signature

The test cases call the insert method without the new force parameter. These need to be updated.

-        cache.insert(hash, block.clone());
+        cache.insert(hash, block.clone(), false);

-        cache.insert(hash, block.clone());
+        cache.insert(hash, block.clone(), false);
🧹 Nitpick comments (1)
p2pool/src/sharechain/in_memory.rs (1)

92-107: Removed Legacy Backup File Handling Logic

The lines that previously constructed, managed, and renamed a backup block cache file have been entirely commented out. This simplification aligns with the PR objective of "Don't recreate the database on start" by directly relying on the current block cache file without making a backup.

Points to Consider:

  • Ensure that this removal does not compromise recovery in situations where the block cache might be damaged or inconsistent, as there is no longer a fallback backup.
  • Verify that any related error handling upstream (e.g., in P2Chain::try_load) appropriately handles potential database corruption.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d376334 and 76698fc.

📒 Files selected for processing (4)
  • p2pool/src/sharechain/in_memory.rs (1 hunks)
  • p2pool/src/sharechain/lmdb_block_storage.rs (3 hunks)
  • p2pool/src/sharechain/p2chain.rs (5 hunks)
  • p2pool/src/sharechain/p2chain_level.rs (3 hunks)
🧰 Additional context used
🧬 Code Definitions (2)
p2pool/src/sharechain/in_memory.rs (2)
p2pool/src/sharechain/lmdb_block_storage.rs (1)
  • new_from_path (68-114)
p2pool/src/sharechain/p2chain.rs (1)
  • try_load (202-265)
p2pool/src/sharechain/p2chain.rs (4)
p2pool/src/sharechain/in_memory.rs (2)
  • new_chain (953-991)
  • new (74-176)
p2pool/src/sharechain/p2chain_level.rs (1)
  • new (64-92)
p2pool/src/sharechain/p2block.rs (2)
  • new (163-180)
  • new (299-301)
p2pool/src/sharechain/mod.rs (1)
  • new (63-73)
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: ci
  • GitHub Check: cargo check with stable
  • GitHub Check: test (esmeralda)
  • GitHub Check: Cucumber tests / Base Layer
🔇 Additional comments (5)
p2pool/src/sharechain/in_memory.rs (1)

108-109: Direct Initialization of the Block Cache

With the legacy backup code removed, the block cache is now initialized using:

let block_cache = LmdbBlockStorage::new_from_path(&data_path);

This ensures that the system loads the block cache directly from the current data path without attempting to manage an old backup.

Action:

  • Double-check that this direct initialization meets the overall system resilience requirements and that any issues (e.g., corruption) can still be detected and handled gracefully.
p2pool/src/sharechain/p2chain.rs (2)

712-712: Update to add_block call with new force parameter

The addition of the true parameter to level.add_block ensures that during block verification, updated blocks will always be inserted into the cache regardless of whether they already exist, which is necessary for updating verification status.


1089-1089: Update to add_block call with new force parameter

The addition of the false parameter to level.add_block indicates that during normal block addition, we don't want to force-write blocks that already exist in the cache, which prevents overwriting blocks unnecessarily.

p2pool/src/sharechain/p2chain_level.rs (1)

84-84: Update to insert call with new force parameter

The code now passes false to the block cache insert method, indicating that during initialization of a new chain level, blocks should not be force-inserted if they already exist.

p2pool/src/sharechain/lmdb_block_storage.rs (1)

231-231: Updated trait definition to include force parameter

The BlockCache trait's insert method now includes a force parameter, which is a good interface change that allows for more flexible block insertion behavior.

Comment on lines +147 to +158
fn insert(&self, hash: BlockHash, block: Arc<P2Block>, force: bool) {
//First we check if the block already exists, if it does we don't insert it, if force is set, we overwrite it
if force {
let env = self.file_handle.read().expect("reader");
let store = env.open_single("block_cache_v2", StoreOptions::create()).unwrap();
let reader = env.read().expect("reader");
let block = store.get(&reader, hash.as_bytes()).unwrap();
// we dont want to deserialise this block, so we just check if it exists
if block.is_some() {
return;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Improved block insertion logic with force parameter

The updated insert method now includes a force parameter that determines whether to check for existing blocks before insertion. This is the key change that prevents recreating the database on start.

However, the implementation logic seems inverted:

  • If force is true, it checks if the block exists and returns early if it does
  • This means force is actually preventing insertion rather than forcing it

The parameter should be renamed for clarity or the logic should be inverted:

-    fn insert(&self, hash: BlockHash, block: Arc<P2Block>, force: bool) {
-        //First we check if the block already exists, if it does we don't insert it, if force is set, we overwrite it
-        if force {
+    fn insert(&self, hash: BlockHash, block: Arc<P2Block>, skip_if_exists: bool) {
+        //First we check if the block already exists, if it does we don't insert it
+        if skip_if_exists {
             let env = self.file_handle.read().expect("reader");
             let store = env.open_single("block_cache_v2", StoreOptions::create()).unwrap();
             let reader = env.read().expect("reader");
             let block = store.get(&reader, hash.as_bytes()).unwrap();
             // we dont want to deserialise this block, so we just check if it exists
             if block.is_some() {
                 return;
             }
         }

Alternatively, invert the logic if "force" should mean "overwrite existing":

-    fn insert(&self, hash: BlockHash, block: Arc<P2Block>, force: bool) {
-        //First we check if the block already exists, if it does we don't insert it, if force is set, we overwrite it
-        if force {
+    fn insert(&self, hash: BlockHash, block: Arc<P2Block>, force: bool) {
+        //Check if block exists and skip insertion unless force is set
+        if !force {
             let env = self.file_handle.read().expect("reader");
             let store = env.open_single("block_cache_v2", StoreOptions::create()).unwrap();
             let reader = env.read().expect("reader");
             let block = store.get(&reader, hash.as_bytes()).unwrap();
             // we dont want to deserialise this block, so we just check if it exists
             if block.is_some() {
                 return;
             }
         }
📝 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
fn insert(&self, hash: BlockHash, block: Arc<P2Block>, force: bool) {
//First we check if the block already exists, if it does we don't insert it, if force is set, we overwrite it
if force {
let env = self.file_handle.read().expect("reader");
let store = env.open_single("block_cache_v2", StoreOptions::create()).unwrap();
let reader = env.read().expect("reader");
let block = store.get(&reader, hash.as_bytes()).unwrap();
// we dont want to deserialise this block, so we just check if it exists
if block.is_some() {
return;
}
}
fn insert(&self, hash: BlockHash, block: Arc<P2Block>, skip_if_exists: bool) {
//First we check if the block already exists, if it does we don't insert it
if skip_if_exists {
let env = self.file_handle.read().expect("reader");
let store = env.open_single("block_cache_v2", StoreOptions::create()).unwrap();
let reader = env.read().expect("reader");
let block = store.get(&reader, hash.as_bytes()).unwrap();
// we dont want to deserialise this block, so we just check if it exists
if block.is_some() {
return;
}
}

Comment on lines +262 to 264
fn insert(&self, hash: BlockHash, block: Arc<P2Block>, force: bool) {
self.blocks.write().unwrap().insert(hash, block);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Needs implementation of force parameter

The InMemoryBlockCache implementation of the insert method includes the new force parameter but doesn't implement the conditional behavior seen in the LmdbBlockStorage implementation. This inconsistency could lead to different behavior between test and production code.

-        fn insert(&self, hash: BlockHash, block: Arc<P2Block>, force: bool) {
-            self.blocks.write().unwrap().insert(hash, block);
+        fn insert(&self, hash: BlockHash, block: Arc<P2Block>, force: bool) {
+            if !force {
+                if self.blocks.read().unwrap().contains_key(&hash) {
+                    return;
+                }
+            }
+            self.blocks.write().unwrap().insert(hash, block);
         }
📝 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
fn insert(&self, hash: BlockHash, block: Arc<P2Block>, force: bool) {
self.blocks.write().unwrap().insert(hash, block);
}
fn insert(&self, hash: BlockHash, block: Arc<P2Block>, force: bool) {
if !force {
if self.blocks.read().unwrap().contains_key(&hash) {
return;
}
}
self.blocks.write().unwrap().insert(hash, block);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant