-
-
Notifications
You must be signed in to change notification settings - Fork 901
Expand file tree
/
Copy pathrocksdb_set_view.h
More file actions
222 lines (196 loc) · 7.71 KB
/
rocksdb_set_view.h
File metadata and controls
222 lines (196 loc) · 7.71 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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
/********************************************************************************
* *
* This file is part of IfcOpenShell. *
* *
* IfcOpenShell is free software: you can redistribute it and/or modify *
* it under the terms of the Lesser GNU General Public License as published by *
* the Free Software Foundation, either version 3.0 of the License, or *
* (at your option) any later version. *
* *
* IfcOpenShell is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* Lesser GNU General Public License for more details. *
* *
* You should have received a copy of the Lesser GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#ifndef ROCKSDB_SET_VIEW_H
#define ROCKSDB_SET_VIEW_H
#ifdef IFOPSH_WITH_ROCKSDB
#include <rocksdb/db.h>
#include <rocksdb/options.h>
#endif
#include <memory>
#include <string>
#include <iterator>
#include <cstddef>
#include <cstring>
#include <stdexcept>
template <typename KeyT>
class rocksdb_set_view {
public:
using key_type = KeyT;
using value_type = key_type;
private:
rocksdb::DB* db_;
std::string prefix_;
public:
// Constructor: provide a pointer to an open RocksDB instance and the key-space prefix,
// e.g. "i|"
rocksdb_set_view(rocksdb::DB* db, const std::string& prefix)
: db_(db), prefix_(prefix) {}
// --- Iterator ---
class iterator {
public:
using value_type = key_type;
using difference_type = std::ptrdiff_t;
using iterator_category = std::forward_iterator_tag;
using pointer = const value_type*;
using reference = const value_type&;
private:
rocksdb::DB* db_;
std::string prefix_;
std::unique_ptr<rocksdb::Iterator> it_;
mutable value_type cached_value_;
// Helper: extract the key (i.e. the value) from the current RocksDB key.
value_type extract_current_value() const {
#ifdef IFOPSH_WITH_ROCKSDB
std::string full_key = it_->key().ToString();
std::string remainder = full_key.substr(prefix_.size());
size_t pos = remainder.find('|');
std::string key_str = (pos != std::string::npos) ? remainder.substr(0, pos) : remainder;
return key_from_string<key_type>(key_str);
#else
return cached_value_;
#endif
}
// Validates the current iterator state.
void check_valid() {
#ifdef IFOPSH_WITH_ROCKSDB
if (!it_ || !it_->Valid() || !it_->key().starts_with(prefix_))
it_.reset();
#endif
}
public:
iterator() : db_(nullptr), prefix_(), it_(nullptr) {}
iterator(rocksdb::DB* db, const std::string& prefix,
std::unique_ptr<rocksdb::Iterator> iter)
: db_(db), prefix_(prefix), it_(std::move(iter))
{
check_valid();
}
iterator(const iterator& other)
: db_(other.db_), prefix_(other.prefix_)
{
#ifdef IFOPSH_WITH_ROCKSDB
if (other.it_) {
std::string curr = other.it_->key().ToString();
it_.reset(db_->NewIterator(rocksdb::ReadOptions{}));
it_->Seek(curr);
if (!it_->Valid() || it_->key().ToString() != curr)
it_.reset();
}
#endif
}
iterator& operator=(const iterator& other) {
#ifdef IFOPSH_WITH_ROCKSDB
if (this != &other) {
db_ = other.db_;
prefix_ = other.prefix_;
if (other.it_) {
std::string curr = other.it_->key().ToString();
it_.reset(db_->NewIterator(rocksdb::ReadOptions{}));
it_->Seek(curr);
if (!it_->Valid() || it_->key().ToString() != curr)
it_.reset();
} else {
it_.reset();
}
}
#endif
return *this;
}
// Dereference: extract the key part from the RocksDB key.
value_type operator*() const {
return extract_current_value();
}
// Pointer access (via a cached value)
const value_type* operator->() const {
cached_value_ = **this;
return &cached_value_;
}
// Pre-increment: advance the iterator and skip over any duplicate keys.
iterator& operator++() {
#ifdef IFOPSH_WITH_ROCKSDB
if (it_) {
// Record the current key value.
value_type curr = extract_current_value();
do {
it_->Next();
} while (it_ && it_->Valid() && it_->key().starts_with(prefix_) &&
(extract_current_value() == curr));
if (!it_ || !it_->Valid() || !it_->key().starts_with(prefix_))
it_.reset();
}
#endif
return *this;
}
iterator operator++(int) {
iterator tmp(*this);
++(*this);
return tmp;
}
bool operator==(const iterator& other) const {
#ifdef IFOPSH_WITH_ROCKSDB
if (!it_ && !other.it_)
return true;
if (it_ && other.it_)
return it_->key().ToString() == other.it_->key().ToString();
#endif
return false;
}
bool operator!=(const iterator& other) const {
return !(*this == other);
}
};
// Returns an iterator to the first element in the key-space (or end() if none exist).
iterator begin() const {
#ifdef IFOPSH_WITH_ROCKSDB
auto iter = std::unique_ptr<rocksdb::Iterator>(db_->NewIterator(rocksdb::ReadOptions{}));
iter->Seek(prefix_);
if (iter->Valid() && iter->key().starts_with(prefix_))
return iterator(db_, prefix_, std::move(iter));
#endif
return end();
}
// Returns an iterator representing the end of the key-space.
iterator end() const {
return iterator();
}
// Read-only find: returns an iterator to the element with the given key if it exists.
iterator find(const key_type& key) const {
#ifdef IFOPSH_WITH_ROCKSDB
std::string key_str = key_to_string(key);
// Construct the search key: prefix + key_str + separator.
std::string start_key = prefix_ + key_str + "|";
auto iter = std::unique_ptr<rocksdb::Iterator>(db_->NewIterator(rocksdb::ReadOptions{}));
iter->Seek(start_key);
if (iter->Valid() && iter->key().starts_with(prefix_)) {
std::string full_key = iter->key().ToString();
std::string remainder = full_key.substr(prefix_.size());
size_t pos = remainder.find('|');
std::string found_key_str = (pos != std::string::npos) ? remainder.substr(0, pos) : remainder;
if (key_from_string<key_type>(found_key_str) == key)
return iterator(db_, prefix_, std::move(iter));
}
#endif
return end();
}
size_t erase(const key_type& key) {
// @todo
return 0;
}
};
#endif