15 /* this tests tdb by doing lots of ops from several simultaneous
16 writers - that stresses the locking code. Build with TDB_DEBUG=1
21 #define REOPEN_PROB 30
24 #define LOCKSTORE_PROB 0
25 #define TRAVERSE_PROB 20
31 static TDB_CONTEXT
*db
;
33 static void tdb_log(TDB_CONTEXT
*tdb
, int level
, const char *format
, ...)
38 vfprintf(stdout
, format
, ap
);
44 asprintf(&ptr
,"xterm -e gdb /proc/%d/exe %d", getpid(), getpid());
51 static void fatal(char *why
)
57 static char *randbuf(int len
)
61 buf
= (char *)malloc(len
+1);
64 buf
[i
] = 'a' + (rand() % 26);
70 static int cull_traverse(TDB_CONTEXT
*tdb
, TDB_DATA key
, TDB_DATA dbuf
,
73 if (random() % CULL_PROB
== 0) {
79 static void addrec_db(void)
83 TDB_DATA key
, data
, lockkey
;
85 klen
= 1 + (rand() % KEYLEN
);
86 dlen
= 1 + (rand() % DATALEN
);
87 slen
= 1 + (rand() % LOCKLEN
);
100 lockkey
.dsize
= slen
+1;
103 if (random() % REOPEN_PROB
== 0) {
110 if (random() % DELETE_PROB
== 0) {
117 if (random() % STORE_PROB
== 0) {
118 if (tdb_store(db
, key
, data
, TDB_REPLACE
) != 0) {
119 fatal("tdb_store failed");
126 if (random() % LOCKSTORE_PROB
== 0) {
127 tdb_chainlock(db
, lockkey
);
128 data
= tdb_fetch(db
, key
);
129 if (tdb_store(db
, key
, data
, TDB_REPLACE
) != 0) {
130 fatal("tdb_store failed");
132 if (data
.dptr
) free(data
.dptr
);
133 tdb_chainunlock(db
, lockkey
);
139 if (random() % TRAVERSE_PROB
== 0) {
140 tdb_traverse(db
, cull_traverse
, NULL
);
145 data
= tdb_fetch(db
, key
);
146 if (data
.dptr
) free(data
.dptr
);
154 static int traverse_fn(TDB_CONTEXT
*tdb
, TDB_DATA key
, TDB_DATA dbuf
,
157 tdb_delete(tdb
, key
);
166 #define NLOOPS 200000
169 int main(int argc
, char *argv
[])
177 for (i
=0;i
<NPROC
-1;i
++) {
178 if ((pids
[i
+1]=fork()) == 0) break;
181 db
= tdb_open("torture.tdb", 2, TDB_CLEAR_IF_FIRST
,
182 O_RDWR
| O_CREAT
, 0600);
184 fatal("db open failed");
186 tdb_logging_function(db
, tdb_log
);
188 srand(seed
+ getpid());
189 srandom(seed
+ getpid() + time(NULL
));
190 for (i
=0;i
<loops
;i
++) addrec_db();
192 tdb_traverse(db
, NULL
, NULL
);
193 tdb_traverse(db
, traverse_fn
, NULL
);
194 tdb_traverse(db
, traverse_fn
, NULL
);
198 if (getpid() == pids
[0]) {
199 for (i
=0;i
<NPROC
-1;i
++) {
201 if (waitpid(pids
[i
+1], &status
, 0) != pids
[i
+1]) {
202 printf("failed to wait for %d\n",
206 if (WEXITSTATUS(status
) != 0) {
207 printf("child %d exited with status %d\n",
208 (int)pids
[i
+1], WEXITSTATUS(status
));