1PMEMKV_ITERATOR(3) PMEMKV Programmer's Manual PMEMKV_ITERATOR(3)
2
3
4
6 pmemkv_iterator - Iterator API for libpmemkv
7
8 This API is EXPERIMENTAL and might change.
9
11 #include <libpmemkv.h>
12
13 int pmemkv_iterator_new(pmemkv_db *db, pmemkv_iterator **it);
14 int pmemkv_write_iterator_new(pmemkv_db *db, pmemkv_write_iterator **it);
15
16 void pmemkv_iterator_delete(pmemkv_iterator *it);
17 void pmemkv_write_iterator_delete(pmemkv_write_iterator *it);
18
19 int pmemkv_iterator_seek(pmemkv_iterator *it, const char *k, size_t kb);
20 int pmemkv_iterator_seek_lower(pmemkv_iterator *it, const char *k, size_t kb);
21 int pmemkv_iterator_seek_lower_eq(pmemkv_iterator *it, const char *k, size_t kb);
22 int pmemkv_iterator_seek_higher(pmemkv_iterator *it, const char *k, size_t kb);
23 int pmemkv_iterator_seek_higher_eq(pmemkv_iterator *it, const char *k, size_t kb);
24
25 int pmemkv_iterator_seek_to_first(pmemkv_iterator *it);
26 int pmemkv_iterator_seek_to_last(pmemkv_iterator *it);
27
28 int pmemkv_iterator_is_next(pmemkv_iterator *it);
29 int pmemkv_iterator_next(pmemkv_iterator *it);
30 int pmemkv_iterator_prev(pmemkv_iterator *it);
31
32 int pmemkv_iterator_key(pmemkv_iterator *it, const char **k, size_t *kb);
33
34 int pmemkv_iterator_read_range(pmemkv_iterator *it, size_t pos, size_t n,
35 const char **data, size_t *rb);
36 int pmemkv_write_iterator_write_range(pmemkv_write_iterator *it, size_t pos, size_t n,
37 char **data, size_t *wb);
38
39 int pmemkv_write_iterator_commit(pmemkv_write_iterator *it);
40 void pmemkv_write_iterator_abort(pmemkv_write_iterator *it);
41
42 For general description of pmemkv and available engines see libp‐
43 memkv(7). For description of pmemkv core API see libpmemkv(3).
44
46 Iterators provide methods to iterate over records in db.
47
48 Both iterator types (pmemkv_iterator (read) and pmemkv_write_iterator)
49 allow reading record’s key and value. To use pmemkv_write_iterator as
50 a pmemkv_iterator you need to get its member “iter” (write_it->iter).
51
52 Example of calling pmemkv_iterator_seek_to_first() with both iterator
53 types.
54
55 /* read_it is already created, by pmemkv_iterator */
56 int status = pmemkv_iterator_seek_to_first(read_it);
57
58 /* write_it is already created, by pmemkv_write_iterator */
59 int status = pmemkv_iterator_seek_to_first(write_it->iter);
60
61 A pmemkv_write_iterator additionally can modify record’s value transac‐
62 tionally.
63
64 Some of the functions are not guaranteed to be implemented by all en‐
65 gines. If an engine does not support a certain function, it will re‐
66 turn PMEMKV_STATUS_NOT_SUPPORTED.
67
68 Holding simultaneously in the same thread more than one iterator is un‐
69 defined behavior.
70
71 int pmemkv_iterator_new(pmemkv_db *db, pmemkv_iterator **it);
72 Creates a new pmemkv_iterator instance and stores a pointer to
73 it in *it.
74
75 int pmemkv_write_iterator_new(pmemkv_db *db, pmemkv_write_iterator
76 **it);
77 Creates a new pmemkv_write_iterator instance and stores a point‐
78 er to it in *it.
79
80 void pmemkv_iterator_delete(pmemkv_iterator *it);
81 Deletes pmemkv_iterator.
82
83 void pmemkv_write_iterator_delete(pmemkv_write_iterator *it);
84 Deletes pmemkv_write_iterator
85
86 int pmemkv_iterator_seek(pmemkv_iterator *it, const char *k, size_t
87 kb);
88 Changes iterator position to the record with given key k of
89 length kb. If the record is present and no errors occurred, re‐
90 turns PMEMKV_STATUS_OK. If the record does not exist,
91 PMEMKV_STATUS_NOT_FOUND is returned and the iterator position is
92 undefined. It internally aborts all changes made to an element
93 previously pointed by the iterator.
94
95 int pmemkv_iterator_seek_lower(pmemkv_iterator *it, const char *k,
96 size_t kb);
97 Changes iterator position to the record with key lower than giv‐
98 en key k of length kb. If the record is present and no errors
99 occurred, returns PMEMKV_STATUS_OK. If the record does not ex‐
100 ist, PMEMKV_STATUS_NOT_FOUND is returned and the iterator posi‐
101 tion is undefined. It internally aborts all changes made to an
102 element previously pointed by the iterator.
103
104 int pmemkv_iterator_seek_lower_eq(pmemkv_iterator *it, const char *k,
105 size_t kb);
106 Changes iterator position to the record with key equal or lower
107 than given key k of length kb. If the record is present and no
108 errors occurred, returns PMEMKV_STATUS_OK. If the record does
109 not exist, PMEMKV_STATUS_NOT_FOUND is returned and the iterator
110 position is undefined. It internally aborts all changes made to
111 an element previously pointed by the iterator.
112
113 int pmemkv_iterator_seek_higher(pmemkv_iterator *it, const char *k,
114 size_t kb);
115 Changes iterator position to the record with key higher than
116 given key k of length kb. If the record is present and no er‐
117 rors occurred, returns PMEMKV_STATUS_OK. If the record does not
118 exist, PMEMKV_STATUS_NOT_FOUND is returned and the iterator po‐
119 sition is undefined. It internally aborts all changes made to
120 an element previously pointed by the iterator.
121
122 int pmemkv_iterator_seek_higher_eq(pmemkv_iterator *it, const char *k,
123 size_t kb);
124 Changes iterator position to the record with key equal or higher
125 than given key k of length kb. If the record is present and no
126 errors occurred, returns PMEMKV_STATUS_OK. If the record does
127 not exist, PMEMKV_STATUS_NOT_FOUND is returned and the iterator
128 position is undefined. It internally aborts all changes made to
129 an element previously pointed by the iterator.
130
131 int pmemkv_iterator_seek_to_first(pmemkv_iterator *it);
132 Changes iterator position to the first record. If db isn’t emp‐
133 ty, and no errors occurred, returns PMEMKV_STATUS_OK. If db is
134 empty, PMEMKV_STATUS_NOT_FOUND is returned and the iterator po‐
135 sition is undefined. It internally aborts all changes made to
136 an element previously pointed by the iterator.
137
138 int pmemkv_iterator_seek_to_last(pmemkv_iterator *it);
139 Changes iterator position to the last record. If db isn’t emp‐
140 ty, and no errors occurred, returns PMEMKV_STATUS_OK. If db is
141 empty, PMEMKV_STATUS_NOT_FOUND is returned and the iterator po‐
142 sition is undefined. It internally aborts all changes made to
143 an element previously pointed by the iterator.
144
145 int pmemkv_iterator_is_next(pmemkv_iterator *it);
146 Checks if there is a next record available. If true is re‐
147 turned, it is guaranteed that pmemkv_iterator_next(it) will re‐
148 turn PMEMKV_STATUS_OK, otherwise iterator is already on the last
149 element and pmemkv_iterator_next(it) will return PMEMKV_STA‐
150 TUS_NOT_FOUND.
151
152 int pmemkv_iterator_next(pmemkv_iterator *it);
153 Changes iterator position to the next record. If the next
154 record exists, returns PMEMKV_STATUS_OK, otherwise PMEMKV_STA‐
155 TUS_NOT_FOUND is returned and the iterator position is unde‐
156 fined. It internally aborts all changes made to an element pre‐
157 viously pointed by the iterator.
158
159 int pmemkv_iterator_prev(pmemkv_iterator *it);
160 Changes iterator position to the previous record. If the previ‐
161 ous record exists, returns PMEMKV_STATUS_OK, otherwise
162 PMEMKV_STATUS_NOT_FOUND is returned and the iterator position is
163 undefined. It internally aborts all changes made to an element
164 previously pointed by the iterator.
165
166 int pmemkv_iterator_key(pmemkv_iterator *it, const char **k, size_t
167 *kb);
168 Assigns record’s key’s address to k and key’s length to kb. If
169 the iterator is on an undefined position, calling this method is
170 undefined behaviour.
171
172 int pmemkv_iterator_read_range(pmemkv_iterator *it, size_t pos, size_t
173 n, const char **data, size_t *rb);
174 Allows getting record’s value’s range which can be only read.
175 You can request for either full value or only value’s subrange
176 (n elements starting from pos). Assigns pointer to the begin‐
177 ning of the requested range to data, and number of elements in
178 range to rb. If n is bigger than length of a value it’s auto‐
179 matically shrunk. If the iterator is on an undefined position,
180 calling this method is undefined behaviour.
181
182 int pmemkv_write_iterator_write_range(pmemkv_write_iterator *it, size_t
183 pos, size_t n, char **data, size_t *wb);
184 Allows getting record’s value’s range which can be modified.
185 You can request for either full value or only value’s subrange
186 (n elements starting from pos). Assigns pointer to the begin‐
187 ning of the requested range to data, and number of elements in
188 range to wb. If n is bigger than length of a value it’s auto‐
189 matically shrunk. Changes made on a requested range are not
190 persistent until pmemkv_write_iterator_commit() is called. If
191 the iterator is on an undefined position, calling this method is
192 undefined behaviour.
193
194 int pmemkv_write_iterator_commit(pmemkv_write_iterator *it);
195 Commits modifications made on the current record. Calling this
196 method is the only way to save modifications made by the itera‐
197 tor on the current record. You need to call this method before
198 changing the iterator position, otherwise modifications will be
199 automatically aborted.
200
201 void pmemkv_write_iterator_abort(pmemkv_write_iterator *it);
202 Aborts uncommitted modifications made on the current record.
203
204 ERRORS
205 Each function, except for pmemkv_iterator_delete(), pmemkv_write_itera‐
206 tor_delete() and pmemkv_write_iterator_abort(), returns one of the
207 pmemkv status codes. To check possible options see libpmemkv(3).
208
210 The following example is taken from examples/pmemkv_iterator_c directo‐
211 ry.
212
213 Usage of basic iterator functions to iterate over all records and modi‐
214 fy one of them.
215
216 #include "libpmemkv.h"
217
218 #include <assert.h>
219 #include <stdio.h>
220 #include <stdlib.h>
221 #include <string.h>
222
223 #define ASSERT(expr) \
224 do { \
225 if (!(expr)) \
226 puts(pmemkv_errormsg()); \
227 assert(expr); \
228 } while (0)
229
230 #define LOG(msg) puts(msg)
231
232 static const uint64_t SIZE = 1024UL * 1024UL * 1024UL;
233
234 int main(int argc, char *argv[])
235 {
236 if (argc < 2) {
237 fprintf(stderr, "Usage: %s file\n", argv[0]);
238 exit(1);
239 }
240
241 const size_t n_elements = 10;
242 char buffer[64];
243
244 /* See libpmemkv_config(3) for more detailed example of config creation */
245 LOG("Creating config");
246 pmemkv_config *cfg = pmemkv_config_new();
247 ASSERT(cfg != NULL);
248
249 int s = pmemkv_config_put_path(cfg, argv[1]);
250 ASSERT(s == PMEMKV_STATUS_OK);
251 s = pmemkv_config_put_size(cfg, SIZE);
252 ASSERT(s == PMEMKV_STATUS_OK);
253 s = pmemkv_config_put_create_if_missing(cfg, true);
254 ASSERT(s == PMEMKV_STATUS_OK);
255
256 LOG("Opening pmemkv database with 'radix' engine");
257 pmemkv_db *db = NULL;
258 s = pmemkv_open("radix", cfg, &db);
259 ASSERT(s == PMEMKV_STATUS_OK);
260 ASSERT(db != NULL);
261
262 LOG("Putting new keys");
263 for (size_t i = 0; i < n_elements; ++i) {
264 char key[10];
265 const char *value = "value";
266 sprintf(key, "key%zu", i);
267 s = pmemkv_put(db, key, strlen(key), value, strlen(value));
268 ASSERT(s == PMEMKV_STATUS_OK);
269 }
270
271 /* get a new read iterator */
272 pmemkv_iterator *it;
273 s = pmemkv_iterator_new(db, &it);
274 ASSERT(s == PMEMKV_STATUS_OK);
275
276 LOG("Iterate from first to last element");
277 s = pmemkv_iterator_seek_to_first(it);
278 ASSERT(s == PMEMKV_STATUS_OK);
279
280 size_t element_number = 0;
281 do {
282 const char *str;
283 size_t cnt;
284 /* read a key */
285 s = pmemkv_iterator_key(it, &str, &cnt);
286 ASSERT(s == PMEMKV_STATUS_OK);
287 sprintf(buffer, "Key %zu = %s", element_number++, str);
288 LOG(buffer);
289 } while (pmemkv_iterator_next(it) != PMEMKV_STATUS_NOT_FOUND);
290
291 /* iterator must be deleted manually */
292 pmemkv_iterator_delete(it);
293
294 /* get a new write_iterator */
295 pmemkv_write_iterator *w_it;
296 s = pmemkv_write_iterator_new(db, &w_it);
297 ASSERT(s == PMEMKV_STATUS_OK);
298
299 /* if you want to get a pmemkv_iterator (read iterator) from a
300 * pmemkv_write_iterator, you should do: write_it->iter */
301 s = pmemkv_iterator_seek_to_last(w_it->iter);
302 ASSERT(s == PMEMKV_STATUS_OK);
303
304 /* get a write range, to modify last element's value */
305 char *data;
306 size_t cnt;
307 s = pmemkv_write_iterator_write_range(w_it, 0, 5, &data, &cnt);
308 ASSERT(s == PMEMKV_STATUS_OK);
309
310 for (size_t i = 0; i < cnt; ++i)
311 data[i] = 'x';
312
313 /* commit changes */
314 s = pmemkv_write_iterator_commit(w_it);
315 ASSERT(s == PMEMKV_STATUS_OK);
316
317 /* get a read range, to read modified value */
318 const char *str;
319 s = pmemkv_iterator_read_range(w_it->iter, 0, 5, &str, &cnt);
320 ASSERT(s == PMEMKV_STATUS_OK);
321
322 /* verify a modified value */
323 ASSERT(strcmp(str, "xxxxx") == 0);
324 sprintf(buffer, "Modified value = %s", str);
325 LOG(buffer);
326
327 /* iterator must be deleted manually */
328 pmemkv_write_iterator_delete(w_it);
329
330 LOG("Closing database");
331 pmemkv_close(db);
332
333 return 0;
334 }
335
337 libpmemkv(7), libpmemkv(3) and <https://pmem.io>
338
339
340
341PMEMKV - pmemkv version 1.5.0 2022-01-28 PMEMKV_ITERATOR(3)