| // 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); |
| } |