-
Notifications
You must be signed in to change notification settings - Fork 667
Expand file tree
/
Copy pathRocksDbReader.cs
More file actions
136 lines (116 loc) · 5.22 KB
/
RocksDbReader.cs
File metadata and controls
136 lines (116 loc) · 5.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// SPDX-FileCopyrightText: 2026 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only
using System;
using System.Runtime.InteropServices;
using Nethermind.Core;
using RocksDbSharp;
namespace Nethermind.Db.Rocks;
/// <summary>
/// Used by `DbOnTheRocks`, `ColumnDb` and `RocksDbSnapshot` to ensure all the methods of
/// `ISortedKeyValueStore` are implemented for the three classes. The three classes are expected
/// to create their relevant read options and create this class then call this class instead of
/// implementing `ISortedKeyValueStore` implementation themselves.
/// This tends to call `DbOnTheRocks` back though.
/// </summary>
public class RocksDbReader : ISortedKeyValueStore
{
private readonly DbOnTheRocks _mainDb;
private readonly Func<ReadOptions> _readOptionsFactory;
private readonly DbOnTheRocks.IteratorManager? _iteratorManager;
private readonly ColumnFamilyHandle? _columnFamily;
private readonly ReadOptions _options;
private readonly ReadOptions _hintCacheMissOptions;
public RocksDbReader(DbOnTheRocks mainDb,
Func<ReadOptions> readOptionsFactory,
DbOnTheRocks.IteratorManager? iteratorManager = null,
ColumnFamilyHandle? columnFamily = null)
: this(mainDb, readOptionsFactory(), readOptionsFactory(), readOptionsFactory, iteratorManager, columnFamily)
{
_hintCacheMissOptions.SetFillCache(false);
}
/// <summary>
/// Constructor that accepts pre-created <see cref="ReadOptions"/> instead of a factory.
/// Used by <see cref="ColumnsDb{T}.ColumnDbSnapshot"/> to share a single pair of ReadOptions
/// across all column readers, avoiding per-reader native handle allocation and finalizer pressure.
/// </summary>
public RocksDbReader(DbOnTheRocks mainDb,
ReadOptions options,
ReadOptions hintCacheMissOptions,
Func<ReadOptions> readOptionsFactory,
DbOnTheRocks.IteratorManager? iteratorManager = null,
ColumnFamilyHandle? columnFamily = null)
{
_mainDb = mainDb;
_readOptionsFactory = readOptionsFactory;
_iteratorManager = iteratorManager;
_columnFamily = columnFamily;
_options = options;
_hintCacheMissOptions = hintCacheMissOptions;
}
public byte[]? Get(scoped ReadOnlySpan<byte> key, ReadFlags flags = ReadFlags.None)
{
if ((flags & ReadFlags.HintReadAhead) != 0 && _iteratorManager is not null)
{
byte[]? result = _mainDb.GetWithIterator(key, _columnFamily, _iteratorManager, flags, out bool success);
if (success)
{
return result;
}
}
ReadOptions readOptions = ((flags & ReadFlags.HintCacheMiss) != 0 ? _hintCacheMissOptions : _options);
return _mainDb.Get(key, _columnFamily, readOptions);
}
public int Get(scoped ReadOnlySpan<byte> key, Span<byte> output, ReadFlags flags = ReadFlags.None)
{
ReadOptions readOptions = ((flags & ReadFlags.HintCacheMiss) != 0 ? _hintCacheMissOptions : _options);
return _mainDb.GetCStyleWithColumnFamily(key, output, _columnFamily, readOptions);
}
public Span<byte> GetSpan(scoped ReadOnlySpan<byte> key, ReadFlags flags = ReadFlags.None)
{
ReadOptions readOptions = ((flags & ReadFlags.HintCacheMiss) != 0 ? _hintCacheMissOptions : _options);
return _mainDb.GetSpanWithColumnFamily(key, _columnFamily, readOptions);
}
public void DangerousReleaseMemory(in ReadOnlySpan<byte> span)
{
_mainDb.DangerousReleaseMemory(span);
}
public bool KeyExists(ReadOnlySpan<byte> key)
{
return _mainDb.KeyExistsWithColumn(key, _columnFamily);
}
public byte[]? FirstKey
{
get
{
using Iterator iterator = _mainDb.CreateIterator(_options, _columnFamily);
iterator.SeekToFirst();
return iterator.Valid() ? iterator.GetKeySpan().ToArray() : null;
}
}
public byte[]? LastKey
{
get
{
using Iterator iterator = _mainDb.CreateIterator(_options, _columnFamily);
iterator.SeekToLast();
return iterator.Valid() ? iterator.GetKeySpan().ToArray() : null;
}
}
public ISortedView GetViewBetween(ReadOnlySpan<byte> firstKey, ReadOnlySpan<byte> lastKey)
{
ReadOptions readOptions = _readOptionsFactory();
IntPtr iterateLowerBound = IntPtr.Zero;
IntPtr iterateUpperBound = IntPtr.Zero;
unsafe
{
iterateLowerBound = Marshal.AllocHGlobal(firstKey.Length);
firstKey.CopyTo(new Span<byte>(iterateLowerBound.ToPointer(), firstKey.Length));
Native.Instance.rocksdb_readoptions_set_iterate_lower_bound(readOptions.Handle, iterateLowerBound, (UIntPtr)firstKey.Length);
iterateUpperBound = Marshal.AllocHGlobal(lastKey.Length);
lastKey.CopyTo(new Span<byte>(iterateUpperBound.ToPointer(), lastKey.Length));
Native.Instance.rocksdb_readoptions_set_iterate_upper_bound(readOptions.Handle, iterateUpperBound, (UIntPtr)lastKey.Length);
}
Iterator iterator = _mainDb.CreateIterator(readOptions, _columnFamily);
return new RocksdbSortedView(iterator, iterateLowerBound, iterateUpperBound);
}
}