0001-01-01 02:30:17 +02:30
# include <stdlib.h>
# include <stdio.h>
# include <fcntl.h>
# include <unistd.h>
# include <string.h>
# include <fcntl.h>
0001-01-01 02:30:17 +02:30
# include <stdarg.h>
0001-01-01 02:30:17 +02:30
# include <sys/mman.h>
# include <sys/stat.h>
# include <sys/time.h>
0001-01-01 02:30:17 +02:30
# include <signal.h>
0001-01-01 02:30:17 +02:30
# include "tdb.h"
# include <gdbm.h>
/* a test program for tdb - the trivial database */
# define DELETE_PROB 7
# define STORE_PROB 5
static TDB_CONTEXT * db ;
static GDBM_FILE gdbm ;
struct timeval tp1 , tp2 ;
0001-01-01 02:30:17 +02:30
static void start_timer ( void )
0001-01-01 02:30:17 +02:30
{
gettimeofday ( & tp1 , NULL ) ;
}
0001-01-01 02:30:17 +02:30
static double end_timer ( void )
0001-01-01 02:30:17 +02:30
{
gettimeofday ( & tp2 , NULL ) ;
return ( ( tp2 . tv_sec - tp1 . tv_sec ) +
( tp2 . tv_usec - tp1 . tv_usec ) * 1.0e-6 ) ;
}
static void fatal ( char * why )
{
perror ( why ) ;
exit ( 1 ) ;
}
0001-01-01 02:30:17 +02:30
static void tdb_log ( TDB_CONTEXT * tdb , int level , const char * format , . . . )
{
va_list ap ;
va_start ( ap , format ) ;
vfprintf ( stdout , format , ap ) ;
va_end ( ap ) ;
0001-01-01 02:30:17 +02:30
fflush ( stdout ) ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
static void compare_db ( void )
{
TDB_DATA d , key , nextkey ;
datum gd , gkey , gnextkey ;
key = tdb_firstkey ( db ) ;
while ( key . dptr ) {
d = tdb_fetch ( db , key ) ;
gkey . dptr = key . dptr ;
gkey . dsize = key . dsize ;
gd = gdbm_fetch ( gdbm , gkey ) ;
if ( ! gd . dptr ) fatal ( " key not in gdbm " ) ;
if ( gd . dsize ! = d . dsize ) fatal ( " data sizes differ " ) ;
if ( memcmp ( gd . dptr , d . dptr , d . dsize ) ) {
fatal ( " data differs " ) ;
}
nextkey = tdb_nextkey ( db , key ) ;
free ( key . dptr ) ;
free ( d . dptr ) ;
free ( gd . dptr ) ;
key = nextkey ;
}
gkey = gdbm_firstkey ( gdbm ) ;
while ( gkey . dptr ) {
gd = gdbm_fetch ( gdbm , gkey ) ;
key . dptr = gkey . dptr ;
key . dsize = gkey . dsize ;
d = tdb_fetch ( db , key ) ;
if ( ! d . dptr ) fatal ( " key not in db " ) ;
if ( d . dsize ! = gd . dsize ) fatal ( " data sizes differ " ) ;
if ( memcmp ( d . dptr , gd . dptr , gd . dsize ) ) {
fatal ( " data differs " ) ;
}
gnextkey = gdbm_nextkey ( gdbm , gkey ) ;
free ( gkey . dptr ) ;
free ( gd . dptr ) ;
free ( d . dptr ) ;
gkey = gnextkey ;
}
}
static char * randbuf ( int len )
{
char * buf ;
int i ;
buf = ( char * ) malloc ( len + 1 ) ;
for ( i = 0 ; i < len ; i + + ) {
buf [ i ] = ' a ' + ( rand ( ) % 26 ) ;
}
buf [ i ] = 0 ;
return buf ;
}
static void addrec_db ( void )
{
int klen , dlen ;
char * k , * d ;
TDB_DATA key , data ;
klen = 1 + ( rand ( ) % 4 ) ;
dlen = 1 + ( rand ( ) % 100 ) ;
k = randbuf ( klen ) ;
d = randbuf ( dlen ) ;
key . dptr = k ;
key . dsize = klen + 1 ;
data . dptr = d ;
data . dsize = dlen + 1 ;
if ( rand ( ) % DELETE_PROB = = 0 ) {
tdb_delete ( db , key ) ;
} else if ( rand ( ) % STORE_PROB = = 0 ) {
if ( tdb_store ( db , key , data , TDB_REPLACE ) ! = 0 ) {
fatal ( " tdb_store failed " ) ;
}
} else {
data = tdb_fetch ( db , key ) ;
if ( data . dptr ) free ( data . dptr ) ;
}
free ( k ) ;
free ( d ) ;
}
static void addrec_gdbm ( void )
{
int klen , dlen ;
char * k , * d ;
datum key , data ;
klen = 1 + ( rand ( ) % 4 ) ;
dlen = 1 + ( rand ( ) % 100 ) ;
k = randbuf ( klen ) ;
d = randbuf ( dlen ) ;
key . dptr = k ;
key . dsize = klen + 1 ;
data . dptr = d ;
data . dsize = dlen + 1 ;
if ( rand ( ) % DELETE_PROB = = 0 ) {
gdbm_delete ( gdbm , key ) ;
} else if ( rand ( ) % STORE_PROB = = 0 ) {
if ( gdbm_store ( gdbm , key , data , GDBM_REPLACE ) ! = 0 ) {
fatal ( " gdbm_store failed " ) ;
}
} else {
data = gdbm_fetch ( gdbm , key ) ;
if ( data . dptr ) free ( data . dptr ) ;
}
free ( k ) ;
free ( d ) ;
}
0001-01-01 02:30:17 +02:30
static int traverse_fn ( TDB_CONTEXT * tdb , TDB_DATA key , TDB_DATA dbuf , void * state )
0001-01-01 02:30:17 +02:30
{
#if 0
printf ( " [%s] [%s] \n " , key . dptr , dbuf . dptr ) ;
# endif
0001-01-01 02:30:17 +02:30
tdb_delete ( tdb , key ) ;
0001-01-01 02:30:17 +02:30
return 0 ;
}
0001-01-01 02:30:17 +02:30
static void merge_test ( void )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
int i ;
0001-01-01 02:30:17 +02:30
char keys [ 5 ] [ 2 ] ;
0001-01-01 02:30:17 +02:30
TDB_DATA key , data ;
0001-01-01 02:30:17 +02:30
for ( i = 0 ; i < 5 ; i + + ) {
sprintf ( keys [ i ] , " %d " , i ) ;
0001-01-01 02:30:17 +02:30
key . dptr = keys [ i ] ;
key . dsize = 2 ;
data . dptr = " test " ;
data . dsize = 4 ;
if ( tdb_store ( db , key , data , TDB_REPLACE ) ! = 0 ) {
fatal ( " tdb_store failed " ) ;
}
0001-01-01 02:30:17 +02:30
}
key . dptr = keys [ 0 ] ;
tdb_delete ( db , key ) ;
key . dptr = keys [ 4 ] ;
tdb_delete ( db , key ) ;
key . dptr = keys [ 2 ] ;
tdb_delete ( db , key ) ;
key . dptr = keys [ 1 ] ;
tdb_delete ( db , key ) ;
key . dptr = keys [ 3 ] ;
tdb_delete ( db , key ) ;
}
0001-01-01 02:30:17 +02:30
int main ( int argc , char * argv [ ] )
{
int i , seed = 0 ;
0001-01-01 02:30:17 +02:30
int loops = 10000 ;
0001-01-01 02:30:17 +02:30
unlink ( " test.gdbm " ) ;
0001-01-01 02:30:17 +02:30
db = tdb_open ( " test.tdb " , 0 , TDB_CLEAR_IF_FIRST ,
O_RDWR | O_CREAT | O_TRUNC , 0600 ) ;
0001-01-01 02:30:17 +02:30
gdbm = gdbm_open ( " test.gdbm " , 512 , GDBM_WRITER | GDBM_NEWDB | GDBM_FAST ,
0600 , NULL ) ;
if ( ! db | | ! gdbm ) {
fatal ( " db open failed " ) ;
}
0001-01-01 02:30:17 +02:30
tdb_logging_function ( db , tdb_log ) ;
0001-01-01 02:30:17 +02:30
# if 1
srand ( seed ) ;
start_timer ( ) ;
for ( i = 0 ; i < loops ; i + + ) addrec_gdbm ( ) ;
0001-01-01 02:30:17 +02:30
printf ( " gdbm got %.2f ops/sec \n " , i / end_timer ( ) ) ;
0001-01-01 02:30:17 +02:30
# endif
0001-01-01 02:30:17 +02:30
merge_test ( ) ;
0001-01-01 02:30:17 +02:30
srand ( seed ) ;
start_timer ( ) ;
for ( i = 0 ; i < loops ; i + + ) addrec_db ( ) ;
0001-01-01 02:30:17 +02:30
printf ( " tdb got %.2f ops/sec \n " , i / end_timer ( ) ) ;
0001-01-01 02:30:17 +02:30
compare_db ( ) ;
1) added void* state argument to tdb_traverse. guess what! there were
two places i found where it was appropriate to _use_ that third argument,
in locking.c and brlock.c! there was a static traverse_function and
i removed the static variable, typecast it to a void*, passed it to
tdb_traverse and re-cast it back to the traverse_function inside the
tdb_traverse function. this makes the use of tdb_traverse() reentrant,
which is never going to happen, i know, i just don't like to see
statics lying about when there's no need for them.
as i had to do in samba-tng, all uses of tdb_traverse modified to take
the new void* state argument.
2) disabled rpcclient: referring people to use SAMBA_TNG rpcclient.
i don't know how the other samba team members would react if i deleted
rpcclient from cvs main. damn, that code's so old, it's unreal.
20 rpcclient commands, instead of about 70 in SAMBA_TNG.
0001-01-01 02:30:17 +02:30
printf ( " traversed %d records \n " , tdb_traverse ( db , traverse_fn , NULL ) ) ;
printf ( " traversed %d records \n " , tdb_traverse ( db , traverse_fn , NULL ) ) ;
0001-01-01 02:30:17 +02:30
tdb_close ( db ) ;
gdbm_close ( gdbm ) ;
return 0 ;
}