-
Notifications
You must be signed in to change notification settings - Fork 72
Merge CoinDb implementations #1017
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
quantumagi
merged 6 commits into
stratisproject:release/1.4.0.0
from
quantumagi:commondb
Jul 12, 2022
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
e3440e1
Merge CoinDb implementations
quantumagi 639ac04
Reduce changes
quantumagi ae6663f
Update db variable name
quantumagi ec5c73a
Update db variable name
quantumagi 372a4a8
Merge branch 'release/1.4.0.0' into commondb
quantumagi 02e8ca1
Add comments to SeekToLast
quantumagi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
106 changes: 49 additions & 57 deletions
106
...nsensus/CoinViews/Coindb/LeveldbCoindb.cs → ...ures.Consensus/CoinViews/Coindb/Coindb.cs
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
385 changes: 0 additions & 385 deletions
385
src/Stratis.Bitcoin.Features.Consensus/CoinViews/Coindb/RocksDbCoindb.cs
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,126 @@ | ||
| using System; | ||
|
|
||
| namespace Stratis.Bitcoin.Database | ||
| { | ||
| /// <summary> | ||
| /// This interface and its relevant implementations provide a standardized interface to databases such as <see cref="RocksDb"/> and <see cref="LevelDb"/>, or other databases | ||
| /// capable of supporting key-based value retrieval and key iteration. | ||
| /// </summary> | ||
| /// <remarks> | ||
| /// The interface expects keys to be specified as separate table and key identifiers. Similarly iterators are expected to be constrained to operate within single tables. | ||
| /// </remarks> | ||
| public interface IDb : IDisposable | ||
| { | ||
| /// <summary> | ||
| /// Opens the database at the specified path. | ||
| /// </summary> | ||
| /// <param name="dbPath">The path where the database is located.</param> | ||
| void Open(string dbPath); | ||
|
|
||
| /// <summary> | ||
| /// Gets the value associated with a table and key. | ||
| /// </summary> | ||
| /// <param name="table">The table identifier.</param> | ||
| /// <param name="key">The key of the value to retrieve.</param> | ||
| /// <returns>The value for the specified table and key.</returns> | ||
| byte[] Get(byte table, byte[] key); | ||
|
|
||
| /// <summary> | ||
| /// Gets an iterator that allows iteration over keys in a table. | ||
| /// </summary> | ||
| /// <param name="table">The table that will be iterated.</param> | ||
| /// <returns>See <see cref="IDbIterator"/>.</returns> | ||
| IDbIterator GetIterator(byte table); | ||
|
|
||
| /// <summary> | ||
| /// Gets a batch that can be used to record changes that can be applied atomically. | ||
| /// </summary> | ||
| /// <remarks>The <see cref="IDb.Get"/> method will not reflect these changes until they are committed. Use | ||
| /// the <see cref="ReadWriteBatch"/> class if uncommitted changes need to be accessed.</remarks> | ||
| /// <returns>See <see cref="IDbBatch"/>.</returns> | ||
| IDbBatch GetWriteBatch(); | ||
|
|
||
| /// <summary> | ||
| /// Removes all tables and their contents. | ||
| /// </summary> | ||
| void Clear(); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// A batch that can be used to record changes that can be applied atomically. | ||
| /// </summary> | ||
| /// <remarks>The database's <see cref="Get"/> method will not reflect these changes until they are committed.</remarks> | ||
| public interface IDbBatch : IDisposable | ||
| { | ||
| /// <summary> | ||
| /// Records a value that will be written to the database when the <see cref="Write"/> method is invoked. | ||
| /// </summary> | ||
| /// <param name="table">The table that will be updated.</param> | ||
| /// <param name="key">The table key that identifies the value to be updated.</param> | ||
| /// <param name="value">The value to be written to the table.</param> | ||
| /// <returns>This class for fluent operations.</returns> | ||
| IDbBatch Put(byte table, byte[] key, byte[] value); | ||
|
|
||
| /// <summary> | ||
| /// Records a key that will be deleted from the database when the <see cref="Write"/> method is invoked. | ||
| /// </summary> | ||
| /// <param name="table">The table that will be updated.</param> | ||
| /// <param name="key">The table key that will be removed.</param> | ||
| /// <returns>This class for fluent operations.</returns> | ||
| IDbBatch Delete(byte table, byte[] key); | ||
|
|
||
| /// <summary> | ||
| /// Writes the recorded changes to the database. | ||
| /// </summary> | ||
| void Write(); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// An iterator that can be used to iterate the keys and values in an <see cref="IDb"/> compliant database. | ||
| /// </summary> | ||
| public interface IDbIterator : IDisposable | ||
| { | ||
| /// <summary> | ||
| /// Seeks to a first key >= <paramref name="key"/> in the relevant table. | ||
| /// If no such key is found then <see cref="IsValid"/> will return <c>false</c>. | ||
| /// </summary> | ||
| /// <param name="key">The key to find.</param> | ||
| void Seek(byte[] key); | ||
|
|
||
| /// <summary> | ||
| /// Seeks to the last key in the relevant table. | ||
| /// If no such key is found then <see cref="IsValid"/> will return <c>false</c>. | ||
| /// </summary> | ||
| void SeekToLast(); | ||
|
|
||
| /// <summary> | ||
| /// Seeks to the next key in the relevant table. | ||
| /// If no such key is found then <see cref="IsValid"/> will return <c>false</c>. | ||
| /// </summary> | ||
| void Next(); | ||
|
|
||
| /// <summary> | ||
| /// Seeks to the previous key in the relevant table. | ||
| /// If no such key is found then <see cref="IsValid"/> will return <c>false</c>. | ||
| /// </summary> | ||
| void Prev(); | ||
|
|
||
| /// <summary> | ||
| /// Determines if the current key is valid. | ||
| /// </summary> | ||
| /// <returns><c>true</c> if a <see cref="Seek"/>, <see cref="Next"/>, <see cref="SeekToLast"/> or <see cref="Prev"/> operation found a valid key. <c>false</c> otherwise.</returns> | ||
| bool IsValid(); | ||
|
|
||
| /// <summary> | ||
| /// The current key. | ||
| /// </summary> | ||
| /// <returns>The key.</returns> | ||
| byte[] Key(); | ||
|
|
||
| /// <summary> | ||
| /// The current value. | ||
| /// </summary> | ||
| /// <returns>The value.</returns> | ||
| byte[] Value(); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,130 @@ | ||
| using System.Linq; | ||
| using LevelDB; | ||
| using NBitcoin; | ||
|
|
||
| namespace Stratis.Bitcoin.Database | ||
| { | ||
| /// <summary>A minimal LevelDb wrapper that makes it compliant with the <see cref="IDb"/> interface.</summary> | ||
| public class LevelDb : IDb | ||
| { | ||
| private string dbPath; | ||
|
|
||
| private DB db; | ||
|
|
||
| public IDbIterator GetIterator(byte table) | ||
| { | ||
| return new LevelDbIterator(table, this.db.CreateIterator()); | ||
| } | ||
|
|
||
| public void Open(string dbPath) | ||
| { | ||
| this.dbPath = dbPath; | ||
| this.db = new DB(new Options() { CreateIfMissing = true }, dbPath); | ||
| } | ||
|
|
||
| public void Clear() | ||
| { | ||
| this.db.Dispose(); | ||
| System.IO.Directory.Delete(this.dbPath, true); | ||
| this.db = new DB(new Options() { CreateIfMissing = true }, this.dbPath); | ||
| } | ||
|
|
||
| public IDbBatch GetWriteBatch() => new LevelDbBatch(this.db); | ||
|
|
||
| public byte[] Get(byte table, byte[] key) | ||
| { | ||
| return this.db.Get(new[] { table }.Concat(key).ToArray()); | ||
| } | ||
|
|
||
| public void Dispose() | ||
| { | ||
| this.db.Dispose(); | ||
| } | ||
| } | ||
|
|
||
| /// <summary>A minimal LevelDb wrapper that makes it compliant with the <see cref="IDbBatch"/> interface.</summary> | ||
| public class LevelDbBatch : WriteBatch, IDbBatch | ||
| { | ||
| private DB db; | ||
|
|
||
| public LevelDbBatch(DB db) | ||
| { | ||
| this.db = db; | ||
| } | ||
|
|
||
| public IDbBatch Put(byte table, byte[] key, byte[] value) | ||
| { | ||
| return (IDbBatch)this.Put(new[] { table }.Concat(key).ToArray(), value); | ||
| } | ||
|
|
||
| public IDbBatch Delete(byte table, byte[] key) | ||
| { | ||
| return (IDbBatch)this.Delete(new[] { table }.Concat(key).ToArray()); | ||
| } | ||
|
|
||
| public void Write() | ||
| { | ||
| this.db.Write(this, new WriteOptions() { Sync = true }); | ||
| } | ||
| } | ||
|
|
||
| /// <summary>A minimal LevelDb wrapper that makes it compliant with the <see cref="IDbIterator"/> interface.</summary> | ||
| public class LevelDbIterator : IDbIterator | ||
| { | ||
| private byte table; | ||
| private Iterator iterator; | ||
|
|
||
| public LevelDbIterator(byte table, Iterator iterator) | ||
| { | ||
| this.table = table; | ||
| this.iterator = iterator; | ||
| } | ||
|
|
||
| public void Seek(byte[] key) | ||
| { | ||
| this.iterator.Seek(new[] { this.table }.Concat(key).ToArray()); | ||
| } | ||
|
|
||
| public void SeekToLast() | ||
| { | ||
| // First seek past the last record in the table by attempting to seek to the start of the next table (if any). | ||
| this.iterator.Seek(new[] { (byte)(this.table + 1) }); | ||
| if (!this.iterator.IsValid()) | ||
| // If there is no next table then simply seek to the last record in the db as that will be the last record of 'table'. | ||
| this.iterator.SeekToLast(); | ||
| else | ||
| // If we managed to seek to the start of the next table then go back one record to arrive at the last record of 'table'. | ||
| this.iterator.Prev(); | ||
| } | ||
|
|
||
| public void Next() | ||
| { | ||
| this.iterator.Next(); | ||
| } | ||
|
|
||
| public void Prev() | ||
| { | ||
| this.iterator.Prev(); | ||
| } | ||
|
|
||
| public bool IsValid() | ||
| { | ||
| return this.iterator.IsValid() && this.iterator.Key()[0] == this.table; | ||
| } | ||
|
|
||
| public byte[] Key() | ||
| { | ||
| return this.iterator.Key().Skip(1).ToArray(); | ||
| } | ||
|
|
||
| public byte[] Value() | ||
| { | ||
| return this.iterator.Value(); | ||
| } | ||
|
|
||
| public void Dispose() | ||
| { | ||
| this.iterator.Dispose(); | ||
| } | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you give a high-level description of how this method works? It is not entirely intuitive to me how seeking based on a single-byte table identifier gives the last record. Is it the last record within the current table? I presume it has something to do with how records are arranged below the table identifiers.