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.
- checksums.yaml +4 -4
- data/ext/lmdb_ext/extconf.rb +7 -3
- data/ext/lmdb_ext/lmdb_ext.c +120 -110
- data/lib/lmdb/version.rb +1 -1
- data/lmdb.gemspec +4 -4
- data/{ext/lmdb_ext → vendor/libraries}/liblmdb/.gitignore +8 -0
- data/{ext/lmdb_ext → vendor/libraries}/liblmdb/COPYRIGHT +1 -1
- data/vendor/libraries/liblmdb/Doxyfile +1631 -0
- data/{ext/lmdb_ext → vendor/libraries}/liblmdb/LICENSE +0 -0
- data/vendor/libraries/liblmdb/Makefile +118 -0
- data/vendor/libraries/liblmdb/intro.doc +192 -0
- data/{ext/lmdb_ext → vendor/libraries}/liblmdb/lmdb.h +161 -61
- data/{ext/lmdb_ext → vendor/libraries}/liblmdb/mdb.c +3244 -1302
- data/vendor/libraries/liblmdb/mdb_copy.1 +61 -0
- data/vendor/libraries/liblmdb/mdb_copy.c +84 -0
- data/vendor/libraries/liblmdb/mdb_drop.1 +40 -0
- data/vendor/libraries/liblmdb/mdb_drop.c +135 -0
- data/vendor/libraries/liblmdb/mdb_dump.1 +81 -0
- data/vendor/libraries/liblmdb/mdb_dump.c +319 -0
- data/vendor/libraries/liblmdb/mdb_load.1 +84 -0
- data/vendor/libraries/liblmdb/mdb_load.c +492 -0
- data/vendor/libraries/liblmdb/mdb_stat.1 +70 -0
- data/vendor/libraries/liblmdb/mdb_stat.c +264 -0
- data/{ext/lmdb_ext → vendor/libraries}/liblmdb/midl.c +66 -5
- data/{ext/lmdb_ext → vendor/libraries}/liblmdb/midl.h +19 -5
- data/vendor/libraries/liblmdb/mtest.c +177 -0
- data/vendor/libraries/liblmdb/mtest2.c +124 -0
- data/vendor/libraries/liblmdb/mtest3.c +133 -0
- data/vendor/libraries/liblmdb/mtest4.c +168 -0
- data/vendor/libraries/liblmdb/mtest5.c +135 -0
- data/vendor/libraries/liblmdb/mtest6.c +141 -0
- data/vendor/libraries/liblmdb/sample-bdb.txt +73 -0
- data/vendor/libraries/liblmdb/sample-mdb.txt +62 -0
- data/vendor/libraries/liblmdb/tooltag +27 -0
- metadata +34 -14
- data/.gitignore +0 -15
- data/.travis.yml +0 -14
- 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-
|
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
|
-
|
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+
|
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-
|
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
|
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
|
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
|
-
|
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
|
+
}
|