lmdb 0.6 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }