blob: f063e83516694fe41b95ab7673b53c4b91dcd3e5 [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2001 Silicon Graphics, Inc.
* All Rights Reserved.
*/
#include "global.h"
#ifdef HAVE_GDBM_NDBM_H_
#include <gdbm/ndbm.h>
#elif HAVE_GDBM_NDBM_H
#include <gdbm-ndbm.h>
#elif HAVE_NDBM_H
#include <ndbm.h>
#else
bozo!
#endif
/* #define WorkDir "/xfs" */
#define DBNAME "DBtest"
#define DBRECS 100000
#define LOOPS 100
typedef struct _myDB {
char data[976];
unsigned short checksum;
long align;
} myDB;
int InitDbmLookup(int);
int DoDbmLookup(void);
void CleanupDbmLookup(void);
void DoSysError(char *, int);
int creatDbRec(myDB *);
unsigned short calccksum(char *, int);
void CkSumError(char *, unsigned short, unsigned short);
int InsertKey(unsigned short *, int, unsigned short);
void DumpKeys(int, unsigned short);
DBM *dbm;
int numDbmEntries, keyIdx, Dups = 0, Errors = 0;
unsigned short *KeyArray, *DupsArray;
int debugflg = 0; /* are we in debugging mode? */
int errflg = 0; /* usage option errors */
int ignoreflg = 1; /* ignore errors in lookup; default = on */
int loops = LOOPS;
int randseed = 0;
int
main(int argc, char *argv[])
{
int numrecs = DBRECS, c, l;
while ((c = getopt(argc, argv, "idn:l:s:")) != EOF) {
switch(c) {
case 'i':
ignoreflg++; break;
case 'd':
debugflg++; break;
case 'n':
numrecs = atoi(optarg);
numrecs = (numrecs < 1) ? DBRECS : numrecs;
break;
case 'l':
loops = atoi(optarg);
loops = (loops < 1) ? LOOPS : loops;
break;
case 's':
randseed = atoi(optarg);
randseed = (randseed < 0) ? 0 : randseed;
break;
case '?':
errflg++;
break;
}
}
if (errflg) {
printf("Usage: dbtest [-di] [-n number] [-l loop] [-s randseed]\n");
exit(0);
}
if (optind > argc) {
printf("Extra arguments ignored\n");
for ( ; optind<argc; optind++)
printf("\t%s\n", argv[optind]);
}
printf("dbtest v1.0\n\n");
printf("Creating database containing %d records...\n", numrecs);
printf("\tperforming lookups for %d iterations...\n", loops);
if (randseed)
printf("\tusing %d as seed for srandom()...\n\n", randseed);
fflush(stdout);
InitDbmLookup(numrecs);
printf("\t\nThere were %d duplicate checksums generated\n", Dups);
for (l=0; l<loops; l++) {
printf("\nPerforming lookups on database...\n");
if (DoDbmLookup() != numrecs)
printf("\nError performing lookups!\n");
else
printf("\nLookups succeeded...\n");
}
printf("\nCleaning up database...\n");
printf("\t\nThere were %d duplicate checksums generated\n", Dups);
fflush(stdout);
CleanupDbmLookup();
if (debugflg)
for (l=0; l<Dups; l++) {
if ((l % 8) == 0)
putchar('\n');
printf("0x%x\t", DupsArray[l]);
}
return 0;
}
int InitDbmLookup(int howmany)
{
char filename[100];
datum key, content;
int i, rc;
myDB dbRec;
sprintf(filename, "%s-%d", DBNAME, (int)getpid());
if (debugflg) {
printf("dbm_open(%s, O_RDWR|O_CREAT, 0644)\n", filename);
fflush(stdout);
}
dbm = dbm_open(filename, O_RDWR|O_CREAT, 0644);
if(dbm == NULL)
DoSysError("\ndbm_open", -1);
if ((KeyArray = (unsigned short *)calloc( howmany,
sizeof(unsigned short))) == NULL)
DoSysError("\ncalloc:KeyArray", -1);
if ((DupsArray = (unsigned short *)calloc( 100,
sizeof(unsigned short))) == NULL)
DoSysError("\ncalloc:DupsArray", -1);
keyIdx = 0;
for(i=0; i<howmany; i++) {
if ( creatDbRec(&dbRec) )
DoSysError("\ncreatDbRec", -1);
if (debugflg) {
printf("created rec #%-7d\t%x\r", i+1, dbRec.checksum);
fflush(stdout);
}
if (InsertKey(KeyArray, keyIdx, dbRec.checksum))
keyIdx++;
key.dptr = (char *)&(dbRec.checksum);
key.dsize = sizeof(dbRec.checksum);
content.dptr = (char *)&dbRec;
content.dsize = sizeof(dbRec);
write(2, NULL, 0);
if (debugflg) {
printf("dbm_store(dbm, key, content, DBM_INSERT)\n");
}
rc = dbm_store(dbm, key, content, DBM_INSERT);
if (rc < 0)
DoSysError("\ndbm_store", rc);
else if (rc == 1) {
keyIdx--; /* key is already in database */
DupsArray[Dups++] = dbRec.checksum;
}
}
numDbmEntries = i;
if (debugflg) {
printf("dbm_close(dbm)\n");
fflush(stdout);
}
dbm_close(dbm); /* close to eliminate chance of in-memory caching */
if (debugflg) {
printf("dbm_open(%s, O_RDONLY, 0)\n", filename);
fflush(stdout);
}
dbm = dbm_open(filename, O_RDONLY, 0);
if(dbm == NULL)
DoSysError("\ndbm_open", -1);
return 0;
}
int DoDbmLookup(void)
{
datum key, content;
int i, j, n;
myDB *dbp;
unsigned tmpck;
printf("\n\tSequential lookups...\n");
fflush(stdout);
for(i=0, j=0; i<numDbmEntries; i++) {
key.dptr = (char *)(KeyArray+j);
key.dsize = sizeof(KeyArray[0]);
write(2, NULL, 0);
if (debugflg) {
printf("dbm_fetch(dbm, key = %d)\n", j);
fflush(stdout);
}
content = dbm_fetch(dbm, key);
dbp = (myDB *)content.dptr;
if ( !content.dptr ) {
n = dbm_error(dbm);
if (n) printf("\n\ndbm_error: %d\n", n);
printf("\n%d: Sequential Lookup of key %4x failed!\n",
i, KeyArray[j]);
DumpKeys(i, KeyArray[j]);
Errors++;
if (ignoreflg) {
j++;
continue;
}
assert( dbp );
}
if (debugflg && dbp) {
printf("Seq rec #%-6d: checksum %4x (%4x)\r", i,
dbp->checksum, KeyArray[j]);
fflush(stdout);
}
if (content.dsize == 0) {
printf("\nrec #%-8d: key = %4x (%d)\n", i, KeyArray[j], j);
fflush(stdout);
DoSysError("\ndbm_fetch", content.dsize);
}
if (dbp->checksum != KeyArray[j])
CkSumError("KeySequential", dbp->checksum, KeyArray[j]);
if ((tmpck = calccksum(dbp->data, sizeof(dbp->data))) != KeyArray[j])
CkSumError("DataSequential", tmpck, KeyArray[j]);
if (++j >= keyIdx)
j = 0;
}
printf("\n\n\tRandom lookups...\n");
fflush(stdout);
for(i=0; i<numDbmEntries; i++) {
n = random() % keyIdx;
key.dptr = (char *)(KeyArray+n);
key.dsize = sizeof(KeyArray[0]);
if (debugflg) {
printf("dbm_fetch(dbm, key = %d)\n", n);
fflush(stdout);
}
content = dbm_fetch(dbm, key);
dbp = (myDB *)content.dptr;
if ( !content.dptr ) {
n = dbm_error(dbm);
if (n) printf("\n\ndbm_error: %d\n", n);
printf("\n%d: Random Lookup of key %4x failed!\n",
i, KeyArray[n]);
DumpKeys(n, KeyArray[n]);
Errors++;
if (ignoreflg) {
continue;
}
assert( dbp );
}
if (debugflg && dbp) {
printf("Rnd rec #%-6d: checksum %4x (%4x)\r", i,
dbp->checksum, KeyArray[n]);
fflush(stdout);
}
if (content.dsize == 0)
DoSysError("\ndbm_fetch", content.dsize);
if (dbp->checksum != KeyArray[n])
CkSumError("KeyRand", dbp->checksum, KeyArray[n]);
if ((tmpck = calccksum(dbp->data, sizeof(dbp->data))) != KeyArray[n])
CkSumError("DataRand", tmpck, KeyArray[n]);
}
return i;
}
void CleanupDbmLookup(void)
{
char filename[100];
int rc;
if (debugflg) {
printf("dbm_close(dbm)\n");
fflush(stdout);
}
dbm_close(dbm);
sprintf(filename, "%s-%d.dir", DBNAME, (int)getpid());
rc = unlink(filename);
if (rc) DoSysError("\nunlink", rc);
sprintf(filename, "%s-%d.pag", DBNAME, (int)getpid());
rc = unlink(filename);
if (rc) DoSysError("\nunlink", rc);
}
void DoSysError(char *msg, int rc)
{
perror(msg);
fprintf(stderr, "Bailing out! status = %d\n", rc);
exit(-1);
}
int creatDbRec(myDB *dbp)
{
static int once = 0;
int i, j;
long *ptr;
long timeseed;
if (!once) {
once++;
if ( !randseed ) {
timeseed = time(0);
printf("\tusing %ld as seed for srandom()...\n\n",
timeseed);
srandom(timeseed);
} else
srandom(randseed);
}
ptr = (long *)&(dbp->data);
j = sizeof(dbp->data) / sizeof(long);
for (i=0; i < j; i++, ptr++) {
*ptr = random();
}
for (i=(j*sizeof(long)); i<sizeof(dbp->data); i++)
dbp->data[i] = (char)time(0);
dbp->checksum = calccksum(dbp->data, sizeof(dbp->data));
return 0;
}
unsigned short calccksum(char *ptr, int size)
{
unsigned short sum;
int i, n;
sum = 0;
n = ((size > 100) ? 100 : size);
for (i=0; i<n && ptr; i++, ptr++) {
if (sum & 01)
sum = (sum >> 1) + 0x8000;
else
sum >>= 1;
sum += (unsigned short)*ptr;
sum &= 0xffff;
}
return sum;
}
/*ARGSUSED*/
void CkSumError(char *msg, unsigned short ck1, unsigned short ck2)
{
Errors++;
printf("%s\n\tChecksum error, %u != %u, Total errors = %d\n",
msg, ck1, ck2, Errors);
exit(1);
}
int InsertKey(unsigned short *k, int idx, unsigned short val)
{
/*
int i, found=0;
*/
return( (k[idx] = val) );
/*
for (i=0; i<idx; i++) {
if (k[i] == val) {
found++;
break;
}
}
if (!found)
k[idx] = val;
return(!found);
*/
}
void DumpKeys(int n, unsigned short key)
{
/*
int i;
unsigned short *p;
*/
FILE *f;
if ((f = fopen("keys", "a")) == NULL) {
perror("open(keys)");
exit(1);
}
/*
for (i=0, p=arr; i<keyIdx && p; i++, p++)
*/
fprintf(f, "%d: 0x%x\n", n, key);
fclose(f);
}