lmdb 0.6 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/ext/lmdb_ext/extconf.rb +7 -3
  3. data/ext/lmdb_ext/lmdb_ext.c +120 -110
  4. data/lib/lmdb/version.rb +1 -1
  5. data/lmdb.gemspec +4 -4
  6. data/{ext/lmdb_ext → vendor/libraries}/liblmdb/.gitignore +8 -0
  7. data/{ext/lmdb_ext → vendor/libraries}/liblmdb/COPYRIGHT +1 -1
  8. data/vendor/libraries/liblmdb/Doxyfile +1631 -0
  9. data/{ext/lmdb_ext → vendor/libraries}/liblmdb/LICENSE +0 -0
  10. data/vendor/libraries/liblmdb/Makefile +118 -0
  11. data/vendor/libraries/liblmdb/intro.doc +192 -0
  12. data/{ext/lmdb_ext → vendor/libraries}/liblmdb/lmdb.h +161 -61
  13. data/{ext/lmdb_ext → vendor/libraries}/liblmdb/mdb.c +3244 -1302
  14. data/vendor/libraries/liblmdb/mdb_copy.1 +61 -0
  15. data/vendor/libraries/liblmdb/mdb_copy.c +84 -0
  16. data/vendor/libraries/liblmdb/mdb_drop.1 +40 -0
  17. data/vendor/libraries/liblmdb/mdb_drop.c +135 -0
  18. data/vendor/libraries/liblmdb/mdb_dump.1 +81 -0
  19. data/vendor/libraries/liblmdb/mdb_dump.c +319 -0
  20. data/vendor/libraries/liblmdb/mdb_load.1 +84 -0
  21. data/vendor/libraries/liblmdb/mdb_load.c +492 -0
  22. data/vendor/libraries/liblmdb/mdb_stat.1 +70 -0
  23. data/vendor/libraries/liblmdb/mdb_stat.c +264 -0
  24. data/{ext/lmdb_ext → vendor/libraries}/liblmdb/midl.c +66 -5
  25. data/{ext/lmdb_ext → vendor/libraries}/liblmdb/midl.h +19 -5
  26. data/vendor/libraries/liblmdb/mtest.c +177 -0
  27. data/vendor/libraries/liblmdb/mtest2.c +124 -0
  28. data/vendor/libraries/liblmdb/mtest3.c +133 -0
  29. data/vendor/libraries/liblmdb/mtest4.c +168 -0
  30. data/vendor/libraries/liblmdb/mtest5.c +135 -0
  31. data/vendor/libraries/liblmdb/mtest6.c +141 -0
  32. data/vendor/libraries/liblmdb/sample-bdb.txt +73 -0
  33. data/vendor/libraries/liblmdb/sample-mdb.txt +62 -0
  34. data/vendor/libraries/liblmdb/tooltag +27 -0
  35. metadata +34 -14
  36. data/.gitignore +0 -15
  37. data/.travis.yml +0 -14
  38. data/ext/lmdb_ext/liblmdb/CHANGES +0 -112
@@ -0,0 +1,264 @@
1
+ /* mdb_stat.c - memory-mapped database status tool */
2
+ /*
3
+ * Copyright 2011-2021 Howard Chu, Symas Corp.
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted only as authorized by the OpenLDAP
8
+ * Public License.
9
+ *
10
+ * A copy of this license is available in the file LICENSE in the
11
+ * top-level directory of the distribution or, alternatively, at
12
+ * <http://www.OpenLDAP.org/license.html>.
13
+ */
14
+ #include <stdio.h>
15
+ #include <stdlib.h>
16
+ #include <string.h>
17
+ #include <unistd.h>
18
+ #include "lmdb.h"
19
+
20
+ #define Z MDB_FMT_Z
21
+ #define Yu MDB_PRIy(u)
22
+
23
+ static void prstat(MDB_stat *ms)
24
+ {
25
+ #if 0
26
+ printf(" Page size: %u\n", ms->ms_psize);
27
+ #endif
28
+ printf(" Tree depth: %u\n", ms->ms_depth);
29
+ printf(" Branch pages: %"Yu"\n", ms->ms_branch_pages);
30
+ printf(" Leaf pages: %"Yu"\n", ms->ms_leaf_pages);
31
+ printf(" Overflow pages: %"Yu"\n", ms->ms_overflow_pages);
32
+ printf(" Entries: %"Yu"\n", ms->ms_entries);
33
+ }
34
+
35
+ static void usage(char *prog)
36
+ {
37
+ fprintf(stderr, "usage: %s [-V] [-n] [-e] [-r[r]] [-f[f[f]]] [-v] [-a|-s subdb] dbpath\n", prog);
38
+ exit(EXIT_FAILURE);
39
+ }
40
+
41
+ int main(int argc, char *argv[])
42
+ {
43
+ int i, rc;
44
+ MDB_env *env;
45
+ MDB_txn *txn;
46
+ MDB_dbi dbi;
47
+ MDB_stat mst;
48
+ MDB_envinfo mei;
49
+ char *prog = argv[0];
50
+ char *envname;
51
+ char *subname = NULL;
52
+ int alldbs = 0, envinfo = 0, envflags = 0, freinfo = 0, rdrinfo = 0;
53
+
54
+ if (argc < 2) {
55
+ usage(prog);
56
+ }
57
+
58
+ /* -a: print stat of main DB and all subDBs
59
+ * -s: print stat of only the named subDB
60
+ * -e: print env info
61
+ * -f: print freelist info
62
+ * -r: print reader info
63
+ * -n: use NOSUBDIR flag on env_open
64
+ * -v: use previous snapshot
65
+ * -V: print version and exit
66
+ * (default) print stat of only the main DB
67
+ */
68
+ while ((i = getopt(argc, argv, "Vaefnrs:v")) != EOF) {
69
+ switch(i) {
70
+ case 'V':
71
+ printf("%s\n", MDB_VERSION_STRING);
72
+ exit(0);
73
+ break;
74
+ case 'a':
75
+ if (subname)
76
+ usage(prog);
77
+ alldbs++;
78
+ break;
79
+ case 'e':
80
+ envinfo++;
81
+ break;
82
+ case 'f':
83
+ freinfo++;
84
+ break;
85
+ case 'n':
86
+ envflags |= MDB_NOSUBDIR;
87
+ break;
88
+ case 'v':
89
+ envflags |= MDB_PREVSNAPSHOT;
90
+ break;
91
+ case 'r':
92
+ rdrinfo++;
93
+ break;
94
+ case 's':
95
+ if (alldbs)
96
+ usage(prog);
97
+ subname = optarg;
98
+ break;
99
+ default:
100
+ usage(prog);
101
+ }
102
+ }
103
+
104
+ if (optind != argc - 1)
105
+ usage(prog);
106
+
107
+ envname = argv[optind];
108
+ rc = mdb_env_create(&env);
109
+ if (rc) {
110
+ fprintf(stderr, "mdb_env_create failed, error %d %s\n", rc, mdb_strerror(rc));
111
+ return EXIT_FAILURE;
112
+ }
113
+
114
+ if (alldbs || subname) {
115
+ mdb_env_set_maxdbs(env, 4);
116
+ }
117
+
118
+ rc = mdb_env_open(env, envname, envflags | MDB_RDONLY, 0664);
119
+ if (rc) {
120
+ fprintf(stderr, "mdb_env_open failed, error %d %s\n", rc, mdb_strerror(rc));
121
+ goto env_close;
122
+ }
123
+
124
+ if (envinfo) {
125
+ (void)mdb_env_stat(env, &mst);
126
+ (void)mdb_env_info(env, &mei);
127
+ printf("Environment Info\n");
128
+ printf(" Map address: %p\n", mei.me_mapaddr);
129
+ printf(" Map size: %"Yu"\n", mei.me_mapsize);
130
+ printf(" Page size: %u\n", mst.ms_psize);
131
+ printf(" Max pages: %"Yu"\n", mei.me_mapsize / mst.ms_psize);
132
+ printf(" Number of pages used: %"Yu"\n", mei.me_last_pgno+1);
133
+ printf(" Last transaction ID: %"Yu"\n", mei.me_last_txnid);
134
+ printf(" Max readers: %u\n", mei.me_maxreaders);
135
+ printf(" Number of readers used: %u\n", mei.me_numreaders);
136
+ }
137
+
138
+ if (rdrinfo) {
139
+ printf("Reader Table Status\n");
140
+ rc = mdb_reader_list(env, (MDB_msg_func *)fputs, stdout);
141
+ if (rdrinfo > 1) {
142
+ int dead;
143
+ mdb_reader_check(env, &dead);
144
+ printf(" %d stale readers cleared.\n", dead);
145
+ rc = mdb_reader_list(env, (MDB_msg_func *)fputs, stdout);
146
+ }
147
+ if (!(subname || alldbs || freinfo))
148
+ goto env_close;
149
+ }
150
+
151
+ rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn);
152
+ if (rc) {
153
+ fprintf(stderr, "mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc));
154
+ goto env_close;
155
+ }
156
+
157
+ if (freinfo) {
158
+ MDB_cursor *cursor;
159
+ MDB_val key, data;
160
+ mdb_size_t pages = 0, *iptr;
161
+
162
+ printf("Freelist Status\n");
163
+ dbi = 0;
164
+ rc = mdb_cursor_open(txn, dbi, &cursor);
165
+ if (rc) {
166
+ fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc));
167
+ goto txn_abort;
168
+ }
169
+ rc = mdb_stat(txn, dbi, &mst);
170
+ if (rc) {
171
+ fprintf(stderr, "mdb_stat failed, error %d %s\n", rc, mdb_strerror(rc));
172
+ goto txn_abort;
173
+ }
174
+ prstat(&mst);
175
+ while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
176
+ iptr = data.mv_data;
177
+ pages += *iptr;
178
+ if (freinfo > 1) {
179
+ char *bad = "";
180
+ mdb_size_t pg, prev;
181
+ ssize_t i, j, span = 0;
182
+ j = *iptr++;
183
+ for (i = j, prev = 1; --i >= 0; ) {
184
+ pg = iptr[i];
185
+ if (pg <= prev)
186
+ bad = " [bad sequence]";
187
+ prev = pg;
188
+ pg += span;
189
+ for (; i >= span && iptr[i-span] == pg; span++, pg++) ;
190
+ }
191
+ printf(" Transaction %"Yu", %"Z"d pages, maxspan %"Z"d%s\n",
192
+ *(mdb_size_t *)key.mv_data, j, span, bad);
193
+ if (freinfo > 2) {
194
+ for (--j; j >= 0; ) {
195
+ pg = iptr[j];
196
+ for (span=1; --j >= 0 && iptr[j] == pg+span; span++) ;
197
+ printf(span>1 ? " %9"Yu"[%"Z"d]\n" : " %9"Yu"\n",
198
+ pg, span);
199
+ }
200
+ }
201
+ }
202
+ }
203
+ mdb_cursor_close(cursor);
204
+ printf(" Free pages: %"Yu"\n", pages);
205
+ }
206
+
207
+ rc = mdb_open(txn, subname, 0, &dbi);
208
+ if (rc) {
209
+ fprintf(stderr, "mdb_open failed, error %d %s\n", rc, mdb_strerror(rc));
210
+ goto txn_abort;
211
+ }
212
+
213
+ rc = mdb_stat(txn, dbi, &mst);
214
+ if (rc) {
215
+ fprintf(stderr, "mdb_stat failed, error %d %s\n", rc, mdb_strerror(rc));
216
+ goto txn_abort;
217
+ }
218
+ printf("Status of %s\n", subname ? subname : "Main DB");
219
+ prstat(&mst);
220
+
221
+ if (alldbs) {
222
+ MDB_cursor *cursor;
223
+ MDB_val key;
224
+
225
+ rc = mdb_cursor_open(txn, dbi, &cursor);
226
+ if (rc) {
227
+ fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc));
228
+ goto txn_abort;
229
+ }
230
+ while ((rc = mdb_cursor_get(cursor, &key, NULL, MDB_NEXT_NODUP)) == 0) {
231
+ char *str;
232
+ MDB_dbi db2;
233
+ if (memchr(key.mv_data, '\0', key.mv_size))
234
+ continue;
235
+ str = malloc(key.mv_size+1);
236
+ memcpy(str, key.mv_data, key.mv_size);
237
+ str[key.mv_size] = '\0';
238
+ rc = mdb_open(txn, str, 0, &db2);
239
+ if (rc == MDB_SUCCESS)
240
+ printf("Status of %s\n", str);
241
+ free(str);
242
+ if (rc) continue;
243
+ rc = mdb_stat(txn, db2, &mst);
244
+ if (rc) {
245
+ fprintf(stderr, "mdb_stat failed, error %d %s\n", rc, mdb_strerror(rc));
246
+ goto txn_abort;
247
+ }
248
+ prstat(&mst);
249
+ mdb_close(env, db2);
250
+ }
251
+ mdb_cursor_close(cursor);
252
+ }
253
+
254
+ if (rc == MDB_NOTFOUND)
255
+ rc = MDB_SUCCESS;
256
+
257
+ mdb_close(env, dbi);
258
+ txn_abort:
259
+ mdb_txn_abort(txn);
260
+ env_close:
261
+ mdb_env_close(env);
262
+
263
+ return rc ? EXIT_FAILURE : EXIT_SUCCESS;
264
+ }
@@ -3,7 +3,8 @@
3
3
  /* $OpenLDAP$ */
4
4
  /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5
5
  *
6
- * Copyright 2000-2014 The OpenLDAP Foundation.
6
+ * Copyright 2000-2021 The OpenLDAP Foundation.
7
+ * Portions Copyright 2001-2021 Howard Chu, Symas Corp.
7
8
  * All rights reserved.
8
9
  *
9
10
  * Redistribution and use in source and binary forms, with or without
@@ -116,17 +117,15 @@ void mdb_midl_free(MDB_IDL ids)
116
117
  free(ids-1);
117
118
  }
118
119
 
119
- int mdb_midl_shrink( MDB_IDL *idp )
120
+ void mdb_midl_shrink( MDB_IDL *idp )
120
121
  {
121
122
  MDB_IDL ids = *idp;
122
123
  if (*(--ids) > MDB_IDL_UM_MAX &&
123
- (ids = realloc(ids, (MDB_IDL_UM_MAX+1) * sizeof(MDB_ID))))
124
+ (ids = realloc(ids, (MDB_IDL_UM_MAX+2) * sizeof(MDB_ID))))
124
125
  {
125
126
  *ids++ = MDB_IDL_UM_MAX;
126
127
  *idp = ids;
127
- return 1;
128
128
  }
129
- return 0;
130
129
  }
131
130
 
132
131
  static int mdb_midl_grow( MDB_IDL *idp, int num )
@@ -356,5 +355,67 @@ int mdb_mid2l_append( MDB_ID2L ids, MDB_ID2 *id )
356
355
  return 0;
357
356
  }
358
357
 
358
+ #ifdef MDB_VL32
359
+ unsigned mdb_mid3l_search( MDB_ID3L ids, MDB_ID id )
360
+ {
361
+ /*
362
+ * binary search of id in ids
363
+ * if found, returns position of id
364
+ * if not found, returns first position greater than id
365
+ */
366
+ unsigned base = 0;
367
+ unsigned cursor = 1;
368
+ int val = 0;
369
+ unsigned n = (unsigned)ids[0].mid;
370
+
371
+ while( 0 < n ) {
372
+ unsigned pivot = n >> 1;
373
+ cursor = base + pivot + 1;
374
+ val = CMP( id, ids[cursor].mid );
375
+
376
+ if( val < 0 ) {
377
+ n = pivot;
378
+
379
+ } else if ( val > 0 ) {
380
+ base = cursor;
381
+ n -= pivot + 1;
382
+
383
+ } else {
384
+ return cursor;
385
+ }
386
+ }
387
+
388
+ if( val > 0 ) {
389
+ ++cursor;
390
+ }
391
+ return cursor;
392
+ }
393
+
394
+ int mdb_mid3l_insert( MDB_ID3L ids, MDB_ID3 *id )
395
+ {
396
+ unsigned x, i;
397
+
398
+ x = mdb_mid3l_search( ids, id->mid );
399
+
400
+ if( x < 1 ) {
401
+ /* internal error */
402
+ return -2;
403
+ }
404
+
405
+ if ( x <= ids[0].mid && ids[x].mid == id->mid ) {
406
+ /* duplicate */
407
+ return -1;
408
+ }
409
+
410
+ /* insert id */
411
+ ids[0].mid++;
412
+ for (i=(unsigned)ids[0].mid; i>x; i--)
413
+ ids[i] = ids[i-1];
414
+ ids[x] = *id;
415
+
416
+ return 0;
417
+ }
418
+ #endif /* MDB_VL32 */
419
+
359
420
  /** @} */
360
421
  /** @} */
@@ -11,7 +11,8 @@
11
11
  /* $OpenLDAP$ */
12
12
  /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
13
13
  *
14
- * Copyright 2000-2014 The OpenLDAP Foundation.
14
+ * Copyright 2000-2021 The OpenLDAP Foundation.
15
+ * Portions Copyright 2001-2021 Howard Chu, Symas Corp.
15
16
  * All rights reserved.
16
17
  *
17
18
  * Redistribution and use in source and binary forms, with or without
@@ -26,7 +27,7 @@
26
27
  #ifndef _MDB_MIDL_H_
27
28
  #define _MDB_MIDL_H_
28
29
 
29
- #include <stddef.h>
30
+ #include "lmdb.h"
30
31
 
31
32
  #ifdef __cplusplus
32
33
  extern "C" {
@@ -42,7 +43,7 @@ extern "C" {
42
43
  /** A generic unsigned ID number. These were entryIDs in back-bdb.
43
44
  * Preferably it should have the same size as a pointer.
44
45
  */
45
- typedef size_t MDB_ID;
46
+ typedef mdb_size_t MDB_ID;
46
47
 
47
48
  /** An IDL is an ID List, a sorted array of IDs. The first
48
49
  * element of the array is a counter for how many actual
@@ -98,9 +99,8 @@ void mdb_midl_free(MDB_IDL ids);
98
99
  /** Shrink an IDL.
99
100
  * Return the IDL to the default size if it has grown larger.
100
101
  * @param[in,out] idp Address of the IDL to shrink.
101
- * @return 0 on no change, non-zero if shrunk.
102
102
  */
103
- int mdb_midl_shrink(MDB_IDL *idp);
103
+ void mdb_midl_shrink(MDB_IDL *idp);
104
104
 
105
105
  /** Make room for num additional elements in an IDL.
106
106
  * @param[in,out] idp Address of the IDL.
@@ -178,6 +178,20 @@ int mdb_mid2l_insert( MDB_ID2L ids, MDB_ID2 *id );
178
178
  */
179
179
  int mdb_mid2l_append( MDB_ID2L ids, MDB_ID2 *id );
180
180
 
181
+ #ifdef MDB_VL32
182
+ typedef struct MDB_ID3 {
183
+ MDB_ID mid; /**< The ID */
184
+ void *mptr; /**< The pointer */
185
+ unsigned int mcnt; /**< Number of pages */
186
+ unsigned int mref; /**< Refcounter */
187
+ } MDB_ID3;
188
+
189
+ typedef MDB_ID3 *MDB_ID3L;
190
+
191
+ unsigned mdb_mid3l_search( MDB_ID3L ids, MDB_ID id );
192
+ int mdb_mid3l_insert( MDB_ID3L ids, MDB_ID3 *id );
193
+
194
+ #endif /* MDB_VL32 */
181
195
  /** @} */
182
196
  /** @} */
183
197
  #ifdef __cplusplus
@@ -0,0 +1,177 @@
1
+ /* mtest.c - memory-mapped database tester/toy */
2
+ /*
3
+ * Copyright 2011-2021 Howard Chu, Symas Corp.
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted only as authorized by the OpenLDAP
8
+ * Public License.
9
+ *
10
+ * A copy of this license is available in the file LICENSE in the
11
+ * top-level directory of the distribution or, alternatively, at
12
+ * <http://www.OpenLDAP.org/license.html>.
13
+ */
14
+ #include <stdio.h>
15
+ #include <stdlib.h>
16
+ #include <time.h>
17
+ #include "lmdb.h"
18
+
19
+ #define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr)
20
+ #define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0))
21
+ #define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \
22
+ "%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort()))
23
+
24
+ int main(int argc,char * argv[])
25
+ {
26
+ int i = 0, j = 0, rc;
27
+ MDB_env *env;
28
+ MDB_dbi dbi;
29
+ MDB_val key, data;
30
+ MDB_txn *txn;
31
+ MDB_stat mst;
32
+ MDB_cursor *cursor, *cur2;
33
+ MDB_cursor_op op;
34
+ int count;
35
+ int *values;
36
+ char sval[32] = "";
37
+
38
+ srand(time(NULL));
39
+
40
+ count = (rand()%384) + 64;
41
+ values = (int *)malloc(count*sizeof(int));
42
+
43
+ for(i = 0;i<count;i++) {
44
+ values[i] = rand()%1024;
45
+ }
46
+
47
+ E(mdb_env_create(&env));
48
+ E(mdb_env_set_maxreaders(env, 1));
49
+ E(mdb_env_set_mapsize(env, 10485760));
50
+ E(mdb_env_open(env, "./testdb", MDB_FIXEDMAP /*|MDB_NOSYNC*/, 0664));
51
+
52
+ E(mdb_txn_begin(env, NULL, 0, &txn));
53
+ E(mdb_dbi_open(txn, NULL, 0, &dbi));
54
+
55
+ key.mv_size = sizeof(int);
56
+ key.mv_data = sval;
57
+
58
+ printf("Adding %d values\n", count);
59
+ for (i=0;i<count;i++) {
60
+ sprintf(sval, "%03x %d foo bar", values[i], values[i]);
61
+ /* Set <data> in each iteration, since MDB_NOOVERWRITE may modify it */
62
+ data.mv_size = sizeof(sval);
63
+ data.mv_data = sval;
64
+ if (RES(MDB_KEYEXIST, mdb_put(txn, dbi, &key, &data, MDB_NOOVERWRITE))) {
65
+ j++;
66
+ data.mv_size = sizeof(sval);
67
+ data.mv_data = sval;
68
+ }
69
+ }
70
+ if (j) printf("%d duplicates skipped\n", j);
71
+ E(mdb_txn_commit(txn));
72
+ E(mdb_env_stat(env, &mst));
73
+
74
+ E(mdb_txn_begin(env, NULL, MDB_RDONLY, &txn));
75
+ E(mdb_cursor_open(txn, dbi, &cursor));
76
+ while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
77
+ printf("key: %p %.*s, data: %p %.*s\n",
78
+ key.mv_data, (int) key.mv_size, (char *) key.mv_data,
79
+ data.mv_data, (int) data.mv_size, (char *) data.mv_data);
80
+ }
81
+ CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
82
+ mdb_cursor_close(cursor);
83
+ mdb_txn_abort(txn);
84
+
85
+ j=0;
86
+ key.mv_data = sval;
87
+ for (i= count - 1; i > -1; i-= (rand()%5)) {
88
+ j++;
89
+ txn=NULL;
90
+ E(mdb_txn_begin(env, NULL, 0, &txn));
91
+ sprintf(sval, "%03x ", values[i]);
92
+ if (RES(MDB_NOTFOUND, mdb_del(txn, dbi, &key, NULL))) {
93
+ j--;
94
+ mdb_txn_abort(txn);
95
+ } else {
96
+ E(mdb_txn_commit(txn));
97
+ }
98
+ }
99
+ free(values);
100
+ printf("Deleted %d values\n", j);
101
+
102
+ E(mdb_env_stat(env, &mst));
103
+ E(mdb_txn_begin(env, NULL, MDB_RDONLY, &txn));
104
+ E(mdb_cursor_open(txn, dbi, &cursor));
105
+ printf("Cursor next\n");
106
+ while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
107
+ printf("key: %.*s, data: %.*s\n",
108
+ (int) key.mv_size, (char *) key.mv_data,
109
+ (int) data.mv_size, (char *) data.mv_data);
110
+ }
111
+ CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
112
+ printf("Cursor last\n");
113
+ E(mdb_cursor_get(cursor, &key, &data, MDB_LAST));
114
+ printf("key: %.*s, data: %.*s\n",
115
+ (int) key.mv_size, (char *) key.mv_data,
116
+ (int) data.mv_size, (char *) data.mv_data);
117
+ printf("Cursor prev\n");
118
+ while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) {
119
+ printf("key: %.*s, data: %.*s\n",
120
+ (int) key.mv_size, (char *) key.mv_data,
121
+ (int) data.mv_size, (char *) data.mv_data);
122
+ }
123
+ CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
124
+ printf("Cursor last/prev\n");
125
+ E(mdb_cursor_get(cursor, &key, &data, MDB_LAST));
126
+ printf("key: %.*s, data: %.*s\n",
127
+ (int) key.mv_size, (char *) key.mv_data,
128
+ (int) data.mv_size, (char *) data.mv_data);
129
+ E(mdb_cursor_get(cursor, &key, &data, MDB_PREV));
130
+ printf("key: %.*s, data: %.*s\n",
131
+ (int) key.mv_size, (char *) key.mv_data,
132
+ (int) data.mv_size, (char *) data.mv_data);
133
+
134
+ mdb_cursor_close(cursor);
135
+ mdb_txn_abort(txn);
136
+
137
+ printf("Deleting with cursor\n");
138
+ E(mdb_txn_begin(env, NULL, 0, &txn));
139
+ E(mdb_cursor_open(txn, dbi, &cur2));
140
+ for (i=0; i<50; i++) {
141
+ if (RES(MDB_NOTFOUND, mdb_cursor_get(cur2, &key, &data, MDB_NEXT)))
142
+ break;
143
+ printf("key: %p %.*s, data: %p %.*s\n",
144
+ key.mv_data, (int) key.mv_size, (char *) key.mv_data,
145
+ data.mv_data, (int) data.mv_size, (char *) data.mv_data);
146
+ E(mdb_del(txn, dbi, &key, NULL));
147
+ }
148
+
149
+ printf("Restarting cursor in txn\n");
150
+ for (op=MDB_FIRST, i=0; i<=32; op=MDB_NEXT, i++) {
151
+ if (RES(MDB_NOTFOUND, mdb_cursor_get(cur2, &key, &data, op)))
152
+ break;
153
+ printf("key: %p %.*s, data: %p %.*s\n",
154
+ key.mv_data, (int) key.mv_size, (char *) key.mv_data,
155
+ data.mv_data, (int) data.mv_size, (char *) data.mv_data);
156
+ }
157
+ mdb_cursor_close(cur2);
158
+ E(mdb_txn_commit(txn));
159
+
160
+ printf("Restarting cursor outside txn\n");
161
+ E(mdb_txn_begin(env, NULL, 0, &txn));
162
+ E(mdb_cursor_open(txn, dbi, &cursor));
163
+ for (op=MDB_FIRST, i=0; i<=32; op=MDB_NEXT, i++) {
164
+ if (RES(MDB_NOTFOUND, mdb_cursor_get(cursor, &key, &data, op)))
165
+ break;
166
+ printf("key: %p %.*s, data: %p %.*s\n",
167
+ key.mv_data, (int) key.mv_size, (char *) key.mv_data,
168
+ data.mv_data, (int) data.mv_size, (char *) data.mv_data);
169
+ }
170
+ mdb_cursor_close(cursor);
171
+ mdb_txn_abort(txn);
172
+
173
+ mdb_dbi_close(env, dbi);
174
+ mdb_env_close(env);
175
+
176
+ return 0;
177
+ }