1 /* $NetBSD: mtest4.c,v 1.1.1.1 2014/05/28 09:58:42 tron Exp $ */ 2 3 /* mtest4.c - memory-mapped database tester/toy */ 4 /* 5 * Copyright 2011 Howard Chu, Symas Corp. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted only as authorized by the OpenLDAP 10 * Public License. 11 * 12 * A copy of this license is available in the file LICENSE in the 13 * top-level directory of the distribution or, alternatively, at 14 * <http://www.OpenLDAP.org/license.html>. 15 */ 16 17 /* Tests for sorted duplicate DBs with fixed-size keys */ 18 #define _XOPEN_SOURCE 500 /* srandom(), random() */ 19 #include <stdio.h> 20 #include <stdlib.h> 21 #include <string.h> 22 #include <time.h> 23 #include "lmdb.h" 24 25 int main(int argc,char * argv[]) 26 { 27 int i = 0, j = 0, rc; 28 MDB_env *env; 29 MDB_dbi dbi; 30 MDB_val key, data; 31 MDB_txn *txn; 32 MDB_stat mst; 33 MDB_cursor *cursor; 34 int count; 35 int *values; 36 char sval[8]; 37 char kval[sizeof(int)]; 38 39 memset(sval, 0, sizeof(sval)); 40 41 count = 510; 42 values = (int *)malloc(count*sizeof(int)); 43 44 for(i = 0;i<count;i++) { 45 values[i] = i*5; 46 } 47 48 rc = mdb_env_create(&env); 49 rc = mdb_env_set_mapsize(env, 10485760); 50 rc = mdb_env_set_maxdbs(env, 4); 51 rc = mdb_env_open(env, "./testdb", MDB_FIXEDMAP|MDB_NOSYNC, 0664); 52 rc = mdb_txn_begin(env, NULL, 0, &txn); 53 rc = mdb_open(txn, "id2", MDB_CREATE|MDB_DUPSORT|MDB_DUPFIXED, &dbi); 54 55 key.mv_size = sizeof(int); 56 key.mv_data = kval; 57 data.mv_size = sizeof(sval); 58 data.mv_data = sval; 59 60 printf("Adding %d values\n", count); 61 strcpy(kval, "001"); 62 for (i=0;i<count;i++) { 63 sprintf(sval, "%07x", values[i]); 64 rc = mdb_put(txn, dbi, &key, &data, MDB_NODUPDATA); 65 if (rc) j++; 66 } 67 if (j) printf("%d duplicates skipped\n", j); 68 rc = mdb_txn_commit(txn); 69 rc = mdb_env_stat(env, &mst); 70 71 /* there should be one full page of dups now. 72 */ 73 rc = mdb_txn_begin(env, NULL, 1, &txn); 74 rc = mdb_cursor_open(txn, dbi, &cursor); 75 while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { 76 printf("key: %p %.*s, data: %p %.*s\n", 77 key.mv_data, (int) key.mv_size, (char *) key.mv_data, 78 data.mv_data, (int) data.mv_size, (char *) data.mv_data); 79 } 80 mdb_cursor_close(cursor); 81 mdb_txn_abort(txn); 82 83 /* test all 3 branches of split code: 84 * 1: new key in lower half 85 * 2: new key at split point 86 * 3: new key in upper half 87 */ 88 89 key.mv_size = sizeof(int); 90 key.mv_data = kval; 91 data.mv_size = sizeof(sval); 92 data.mv_data = sval; 93 94 sprintf(sval, "%07x", values[3]+1); 95 rc = mdb_txn_begin(env, NULL, 0, &txn); 96 rc = mdb_put(txn, dbi, &key, &data, MDB_NODUPDATA); 97 mdb_txn_abort(txn); 98 99 sprintf(sval, "%07x", values[255]+1); 100 rc = mdb_txn_begin(env, NULL, 0, &txn); 101 rc = mdb_put(txn, dbi, &key, &data, MDB_NODUPDATA); 102 mdb_txn_abort(txn); 103 104 sprintf(sval, "%07x", values[500]+1); 105 rc = mdb_txn_begin(env, NULL, 0, &txn); 106 rc = mdb_put(txn, dbi, &key, &data, MDB_NODUPDATA); 107 rc = mdb_txn_commit(txn); 108 109 /* Try MDB_NEXT_MULTIPLE */ 110 rc = mdb_txn_begin(env, NULL, 0, &txn); 111 rc = mdb_cursor_open(txn, dbi, &cursor); 112 while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT_MULTIPLE)) == 0) { 113 printf("key: %.*s, data: %.*s\n", 114 (int) key.mv_size, (char *) key.mv_data, 115 (int) data.mv_size, (char *) data.mv_data); 116 } 117 mdb_cursor_close(cursor); 118 mdb_txn_abort(txn); 119 j=0; 120 121 for (i= count - 1; i > -1; i-= (random()%3)) { 122 j++; 123 txn=NULL; 124 rc = mdb_txn_begin(env, NULL, 0, &txn); 125 sprintf(sval, "%07x", values[i]); 126 key.mv_size = sizeof(int); 127 key.mv_data = kval; 128 data.mv_size = sizeof(sval); 129 data.mv_data = sval; 130 rc = mdb_del(txn, dbi, &key, &data); 131 if (rc) { 132 j--; 133 mdb_txn_abort(txn); 134 } else { 135 rc = mdb_txn_commit(txn); 136 } 137 } 138 free(values); 139 printf("Deleted %d values\n", j); 140 141 rc = mdb_env_stat(env, &mst); 142 rc = mdb_txn_begin(env, NULL, 1, &txn); 143 rc = mdb_cursor_open(txn, dbi, &cursor); 144 printf("Cursor next\n"); 145 while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { 146 printf("key: %.*s, data: %.*s\n", 147 (int) key.mv_size, (char *) key.mv_data, 148 (int) data.mv_size, (char *) data.mv_data); 149 } 150 printf("Cursor prev\n"); 151 while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) { 152 printf("key: %.*s, data: %.*s\n", 153 (int) key.mv_size, (char *) key.mv_data, 154 (int) data.mv_size, (char *) data.mv_data); 155 } 156 mdb_cursor_close(cursor); 157 mdb_close(env, dbi); 158 159 mdb_txn_abort(txn); 160 mdb_env_close(env); 161 162 return 0; 163 } 164