Skip to content
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

[Plugin LevelDB] First step of 3414 - Comments and style #3575

Merged
merged 8 commits into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
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
23 changes: 23 additions & 0 deletions src/Plugins/LevelDBStore/IO/Data/LevelDB/DB.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@

namespace Neo.IO.Data.LevelDB
{
/// <summary>
/// A DB is a persistent ordered map from keys to values.
/// A DB is safe for concurrent access from multiple threads without any external synchronization.
/// </summary>
public class DB : IDisposable
{
private IntPtr handle;
Expand All @@ -37,12 +41,21 @@ public void Dispose()
}
}

/// <summary>
/// Remove the database entry (if any) for "key".
/// It is not an error if "key" did not exist in the database.
/// Note: consider setting new WriteOptions{ Sync = true }.
/// </summary>
public void Delete(WriteOptions options, byte[] key)
{
Native.leveldb_delete(handle, options.handle, key, (UIntPtr)key.Length, out IntPtr error);
NativeHelper.CheckError(error);
}

/// <summary>
/// If the database contains an entry for "key" return the value,
/// otherwise return null.
/// </summary>
public byte[] Get(ReadOptions options, byte[] key)
{
IntPtr value = Native.leveldb_get(handle, options.handle, key, (UIntPtr)key.Length, out UIntPtr length, out IntPtr error);
Expand Down Expand Up @@ -93,12 +106,22 @@ public static DB Open(string name, Options options)
return new DB(handle);
}

/// <summary>
/// Set the database entry for "key" to "value".
/// Note: consider setting new WriteOptions{ Sync = true }.
/// </summary>
public void Put(WriteOptions options, byte[] key, byte[] value)
{
Native.leveldb_put(handle, options.handle, key, (UIntPtr)key.Length, value, (UIntPtr)value.Length, out IntPtr error);
NativeHelper.CheckError(error);
}

/// <summary>
/// If a DB cannot be opened, you may attempt to call this method to
/// resurrect as much of the contents of the database as possible.
/// Some data may be lost, so be careful when calling this function
/// on a database that contains important information.
/// </summary>
public static void Repair(string name, Options options)
{
Native.leveldb_repair_db(options.handle, Path.GetFullPath(name), out IntPtr error);
Expand Down
21 changes: 21 additions & 0 deletions src/Plugins/LevelDBStore/IO/Data/LevelDB/Iterator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@

namespace Neo.IO.Data.LevelDB
{
/// <summary>
/// An iterator yields a sequence of key/value pairs from a database.
/// </summary>
public class Iterator : IDisposable
{
private IntPtr handle;
Expand All @@ -37,13 +40,22 @@ public void Dispose()
}
}

/// <summary>
/// Return the key for the current entry.
/// REQUIRES: Valid()
/// </summary>
public byte[] Key()
{
IntPtr key = Native.leveldb_iter_key(handle, out UIntPtr length);
CheckError();
return key.ToByteArray(length);
}

/// <summary>
/// Moves to the next entry in the source.
/// After this call, Valid() is true if the iterator was not positioned at the last entry in the source.
/// REQUIRES: Valid()
/// </summary>
public void Next()
{
Native.leveldb_iter_next(handle);
Expand All @@ -56,6 +68,11 @@ public void Prev()
CheckError();
}

/// <summary>
/// Position at the first key in the source that at or past target
/// The iterator is Valid() after this call if the source contains
/// an entry that comes at or past target.
/// </summary>
public void Seek(byte[] target)
{
Native.leveldb_iter_seek(handle, target, (UIntPtr)target.Length);
Expand All @@ -66,6 +83,10 @@ public void SeekToFirst()
Native.leveldb_iter_seek_to_first(handle);
}

/// <summary>
/// Position at the last key in the source.
/// The iterator is Valid() after this call if the source is not empty.
/// </summary>
public void SeekToLast()
{
Native.leveldb_iter_seek_to_last(handle);
Expand Down
117 changes: 81 additions & 36 deletions src/Plugins/LevelDBStore/IO/Data/LevelDB/Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,81 +13,126 @@

namespace Neo.IO.Data.LevelDB
{
/// <summary>
/// Options to control the behavior of a database (passed to Open)
///
/// the setter methods for InfoLogger, Env, and Cache only "safe to clean up guarantee". Do not
/// use Option object if throws.
/// </summary>
public class Options
{
public static readonly Options Default = new Options();
internal readonly IntPtr handle = Native.leveldb_options_create();

/// <summary>
/// If true, the database will be created if it is missing.
/// </summary>
public bool CreateIfMissing
{
set
{
Native.leveldb_options_set_create_if_missing(handle, value);
}
set { Native.leveldb_options_set_create_if_missing(handle, value); }
}

/// <summary>
/// If true, an error is raised if the database already exists.
/// </summary>
public bool ErrorIfExists
{
set
{
Native.leveldb_options_set_error_if_exists(handle, value);
}
set { Native.leveldb_options_set_error_if_exists(handle, value); }
}

/// <summary>
/// If true, the implementation will do aggressive checking of the
/// data it is processing and will stop early if it detects any
/// errors. This may have unforeseen ramifications: for example, a
/// corruption of one DB entry may cause a large number of entries to
/// become unreadable or for the entire DB to become unopenable.
/// </summary>
public bool ParanoidChecks
{
set
{
Native.leveldb_options_set_paranoid_checks(handle, value);
}
set { Native.leveldb_options_set_paranoid_checks(handle, value); }
}

// Any internal progress/error information generated by the db will
// be written to info_log if it is non-NULL, or to a file stored
// in the same directory as the DB contents if info_log is NULL.

/// <summary>
/// Amount of data to build up in memory (backed by an unsorted log
/// on disk) before converting to a sorted on-disk file.
///
/// Larger values increase performance, especially during bulk loads.
/// Up to two write buffers may be held in memory at the same time,
/// so you may wish to adjust this parameter to control memory usage.
/// Also, a larger write buffer will result in a longer recovery time
/// the next time the database is opened.
///
/// Default: 4MB
/// </summary>
public int WriteBufferSize
{
set
{
Native.leveldb_options_set_write_buffer_size(handle, (UIntPtr)value);
}
set { Native.leveldb_options_set_write_buffer_size(handle, (UIntPtr)value); }
}

/// <summary>
/// Number of open files that can be used by the DB. You may need to
/// increase this if your database has a large working set (budget
/// one open file per 2MB of working set).
///
/// Default: 1000
/// </summary>
public int MaxOpenFiles
{
set
{
Native.leveldb_options_set_max_open_files(handle, value);
}
set { Native.leveldb_options_set_max_open_files(handle, value); }
}

/// <summary>
/// Approximate size of user data packed per block. Note that the
/// block size specified here corresponds to uncompressed data. The
/// actual size of the unit read from disk may be smaller if
/// compression is enabled. This parameter can be changed dynamically.
///
/// Default: 4K
/// </summary>
public int BlockSize
{
set
{
Native.leveldb_options_set_block_size(handle, (UIntPtr)value);
}
set { Native.leveldb_options_set_block_size(handle, (UIntPtr)value); }
}

/// <summary>
/// Number of keys between restart points for delta encoding of keys.
/// This parameter can be changed dynamically.
/// Most clients should leave this parameter alone.
///
/// Default: 16
/// </summary>
public int BlockRestartInterval
{
set
{
Native.leveldb_options_set_block_restart_interval(handle, value);
}
set { Native.leveldb_options_set_block_restart_interval(handle, value); }
}

/// <summary>
/// Compress blocks using the specified compression algorithm.
/// This parameter can be changed dynamically.
///
/// Default: kSnappyCompression, which gives lightweight but fast compression.
///
/// Typical speeds of kSnappyCompression on an Intel(R) Core(TM)2 2.4GHz:
/// ~200-500MB/s compression
/// ~400-800MB/s decompression
/// Note that these speeds are significantly faster than most
/// persistent storage speeds, and therefore it is typically never
/// worth switching to kNoCompression. Even if the input data is
/// incompressible, the kSnappyCompression implementation will
/// efficiently detect that and will switch to uncompressed mode.
/// </summary>
public CompressionType Compression
{
set
{
Native.leveldb_options_set_compression(handle, value);
}
set { Native.leveldb_options_set_compression(handle, value); }
}

public IntPtr FilterPolicy
{
set
{
Native.leveldb_options_set_filter_policy(handle, value);
}
set { Native.leveldb_options_set_filter_policy(handle, value); }
}

~Options()
Expand Down
34 changes: 22 additions & 12 deletions src/Plugins/LevelDBStore/IO/Data/LevelDB/ReadOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,43 @@

namespace Neo.IO.Data.LevelDB
{
/// <summary>
/// Options that control read operations.
/// </summary>
public class ReadOptions
{
public static readonly ReadOptions Default = new ReadOptions();
internal readonly IntPtr handle = Native.leveldb_readoptions_create();

/// <summary>
/// If true, all data read from underlying storage will be
/// verified against corresponding checksums.
/// </summary>
public bool VerifyChecksums
{
set
{
Native.leveldb_readoptions_set_verify_checksums(handle, value);
}
set { Native.leveldb_readoptions_set_verify_checksums(handle, value); }
}

/// <summary>
/// Should the data read for this iteration be cached in memory?
/// Callers may wish to set this field to false for bulk scans.
/// Default: true
/// </summary>
public bool FillCache
{
set
{
Native.leveldb_readoptions_set_fill_cache(handle, value);
}
set { Native.leveldb_readoptions_set_fill_cache(handle, value); }
}

/// <summary>
/// If "snapshot" is provides, read as of the supplied snapshot
/// (which must belong to the DB that is being read and which must
/// not have been released).
/// If "snapshot" is not set, use an implicit
/// snapshot of the state at the beginning of this read operation.
/// </summary>
public Snapshot Snapshot
{
set
{
Native.leveldb_readoptions_set_snapshot(handle, value.handle);
}
set { Native.leveldb_readoptions_set_snapshot(handle, value.handle); }
}

~ReadOptions()
Expand Down
4 changes: 4 additions & 0 deletions src/Plugins/LevelDBStore/IO/Data/LevelDB/Snapshot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@

namespace Neo.IO.Data.LevelDB
{
/// <summary>
/// A Snapshot is an immutable object and can therefore be safely
/// accessed from multiple threads without any external synchronization.
/// </summary>
public class Snapshot : IDisposable
{
internal IntPtr db, handle;
Expand Down
30 changes: 26 additions & 4 deletions src/Plugins/LevelDBStore/IO/Data/LevelDB/WriteBatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@

namespace Neo.IO.Data.LevelDB
{
/// <summary>
/// WriteBatch holds a collection of updates to apply atomically to a DB.
///
/// The updates are applied in the order in which they are added
/// to the WriteBatch. For example, the value of "key" will be "v3"
/// after the following batch is written:
///
/// batch.Put("key", "v1");
/// batch.Delete("key");
/// batch.Put("key", "v2");
/// batch.Put("key", "v3");
/// </summary>
public class WriteBatch
{
internal readonly IntPtr handle = Native.leveldb_writebatch_create();
Expand All @@ -22,19 +34,29 @@ public class WriteBatch
Native.leveldb_writebatch_destroy(handle);
}

/// <summary>
/// Clear all updates buffered in this batch.
/// </summary>
public void Clear()
{
Native.leveldb_writebatch_clear(handle);
}

public void Delete(byte[] key)
/// <summary>
/// Store the mapping "key->value" in the database.
/// </summary>
public void Put(byte[] key, byte[] value)
{
Native.leveldb_writebatch_delete(handle, key, (UIntPtr)key.Length);
Native.leveldb_writebatch_put(handle, key, (UIntPtr)key.Length, value, (UIntPtr)value.Length);
}

public void Put(byte[] key, byte[] value)
/// <summary>
/// If the database contains a mapping for "key", erase it.
/// Else do nothing.
/// </summary>
public void Delete(byte[] key)
{
Native.leveldb_writebatch_put(handle, key, (UIntPtr)key.Length, value, (UIntPtr)value.Length);
Native.leveldb_writebatch_delete(handle, key, (UIntPtr)key.Length);
}
}
}
Loading
Loading