build: update AC_PACKAGE_WANT_GDBM() and src/dbtest.c to build
[xfstests-dev.git] / src / dbtest.c
1 /*
2  * Copyright (c) 2000-2001 Silicon Graphics, Inc.
3  * All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it would be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write the Free Software Foundation,
16  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18  
19 #include "global.h"
20
21 #ifdef HAVE_GDBM_NDBM_H_
22 #include <gdbm/ndbm.h>
23 #elif HAVE_GDBM_NDBM_H
24 #include <gdbm-ndbm.h>
25 #elif HAVE_GDBM_H
26 #include <gdbm.h>
27 #include <ndbm.h>
28 #elif HAVE_NDBM_H
29 #include <ndbm.h>
30 #else
31 bozo!
32 #endif
33
34
35 /* #define WorkDir      "/xfs" */
36 #define DBNAME  "DBtest"
37 #define DBRECS  100000
38 #define LOOPS   100
39
40 typedef struct _myDB {
41         char            data[976];
42         unsigned short  checksum;
43         long            align;
44 } myDB; 
45
46 int InitDbmLookup(int);
47 int DoDbmLookup(void);
48 void CleanupDbmLookup(void);
49 void DoSysError(char *, int);
50 int creatDbRec(myDB *);
51 unsigned short calccksum(char *, int);
52 void CkSumError(char *, unsigned short, unsigned short);
53 int InsertKey(unsigned short *, int, unsigned short);
54 void DumpKeys(int, unsigned short);
55
56 DBM *dbm;
57 int numDbmEntries, keyIdx, Dups = 0, Errors = 0;
58 unsigned short *KeyArray, *DupsArray;
59 int debugflg = 0;       /* are we in debugging mode? */
60 int errflg = 0;         /* usage option errors */
61 int ignoreflg = 1;      /* ignore errors in lookup; default = on */
62 int loops = LOOPS;
63 int randseed = 0;
64
65 int
66 main(int argc, char *argv[])
67 {
68         int     numrecs = DBRECS, c, l;
69
70         while ((c = getopt(argc, argv, "idn:l:s:")) != EOF) {
71                 switch(c) {
72                         case 'i':
73                                 ignoreflg++; break;
74                         case 'd':
75                                 debugflg++; break;
76                         case 'n':
77                                 numrecs = atoi(optarg);
78                                 numrecs = (numrecs < 1) ? DBRECS : numrecs;
79                                 break;
80                         case 'l':
81                                 loops = atoi(optarg);
82                                 loops = (loops < 1) ? LOOPS : loops;
83                                 break;
84                         case 's':
85                                 randseed = atoi(optarg);
86                                 randseed = (randseed < 0) ? 0 : randseed;
87                                 break;
88                         case '?':
89                                 errflg++;
90                                 break;
91                 }
92         }
93         if (errflg) {
94                 printf("Usage: dbtest [-di] [-n number] [-l loop] [-s randseed]\n");
95                 exit(0);
96         }
97         if (optind > argc) {
98                 printf("Extra arguments ignored\n");
99                 for ( ; optind<argc; optind++)
100                         printf("\t%s\n", argv[optind]);
101         }
102
103         printf("dbtest v1.0\n\n");
104         printf("Creating database containing %d records...\n", numrecs);
105         printf("\tperforming lookups for %d iterations...\n", loops);
106         if (randseed)
107                 printf("\tusing %d as seed for srandom()...\n\n", randseed);
108         fflush(stdout);
109         InitDbmLookup(numrecs);
110         printf("\t\nThere were %d duplicate checksums generated\n", Dups);
111         for (l=0; l<loops; l++) {
112                 printf("\nPerforming lookups on database...\n");
113                 if (DoDbmLookup() != numrecs)
114                         printf("\nError performing lookups!\n");
115                 else
116                         printf("\nLookups succeeded...\n");
117         }
118         printf("\nCleaning up database...\n");
119         printf("\t\nThere were %d duplicate checksums generated\n", Dups);
120         fflush(stdout);
121         CleanupDbmLookup();
122         if (debugflg)
123                 for (l=0; l<Dups; l++) {
124                         if ((l % 8) == 0)
125                                 putchar('\n');
126                         printf("0x%x\t", DupsArray[l]);
127                 }
128
129         return 0;
130 }
131
132
133 int InitDbmLookup(int howmany)
134 {
135         char    filename[100];
136         datum   key, content;
137         int     i, rc;
138         myDB    dbRec;
139
140         sprintf(filename, "%s-%d", DBNAME, (int)getpid());
141         if (debugflg) {
142                 printf("dbm_open(%s, O_RDWR|O_CREAT, 0644)\n", filename);
143                 fflush(stdout);
144         }
145         dbm = dbm_open(filename, O_RDWR|O_CREAT, 0644);
146         if(dbm == NULL)
147                 DoSysError("\ndbm_open", -1);
148
149         if ((KeyArray = (unsigned short *)calloc( howmany,
150                                 sizeof(unsigned short))) == NULL)
151                 DoSysError("\ncalloc:KeyArray", -1);
152         if ((DupsArray = (unsigned short *)calloc( 100,
153                                 sizeof(unsigned short))) == NULL)
154                 DoSysError("\ncalloc:DupsArray", -1);
155
156         keyIdx = 0;
157         for(i=0; i<howmany; i++) {
158
159                 if ( creatDbRec(&dbRec) )
160                         DoSysError("\ncreatDbRec", -1);
161                 if (debugflg) {
162                         printf("created rec #%-7d\t%x\r", i+1, dbRec.checksum);
163                         fflush(stdout);
164                 }
165
166                 if (InsertKey(KeyArray, keyIdx, dbRec.checksum))
167                         keyIdx++;
168
169                 key.dptr = (char *)&(dbRec.checksum);
170                 key.dsize = sizeof(dbRec.checksum);
171                 content.dptr = (char *)&dbRec;
172                 content.dsize = sizeof(dbRec);
173
174                 write(2, NULL, 0);
175
176                 if (debugflg) {
177                         printf("dbm_store(dbm, key, content, DBM_INSERT)\n");
178                 }
179                 rc = dbm_store(dbm, key, content, DBM_INSERT);
180                 if (rc < 0)
181                         DoSysError("\ndbm_store", rc);
182                 else if (rc == 1) {
183                         keyIdx--;       /* key is already in database */
184                         DupsArray[Dups++] = dbRec.checksum;
185                 }
186         }
187         numDbmEntries = i;
188         if (debugflg) {
189                 printf("dbm_close(dbm)\n");
190                 fflush(stdout);
191         }
192         dbm_close(dbm); /* close to eliminate chance of in-memory caching */
193         if (debugflg) {
194                 printf("dbm_open(%s, O_RDONLY, 0)\n", filename);
195                 fflush(stdout);
196         }
197         dbm = dbm_open(filename, O_RDONLY, 0);
198         if(dbm == NULL)
199                 DoSysError("\ndbm_open", -1);
200         return 0;
201 }
202
203 int DoDbmLookup(void)
204 {
205         datum key, content;
206         int i, j, n;
207         myDB *dbp;
208         unsigned tmpck;
209
210         printf("\n\tSequential lookups...\n");
211         fflush(stdout);
212         for(i=0, j=0; i<numDbmEntries; i++) {
213                 key.dptr = (char *)(KeyArray+j);
214                 key.dsize = sizeof(KeyArray[0]);
215
216 write(2, NULL, 0);
217                 if (debugflg) {
218                         printf("dbm_fetch(dbm, key = %d)\n", j);
219                         fflush(stdout);
220                 }
221                 content = dbm_fetch(dbm, key);
222                 dbp = (myDB *)content.dptr;
223                 if ( !content.dptr ) {
224                         n = dbm_error(dbm);
225                         if (n) printf("\n\ndbm_error: %d\n", n);
226                         printf("\n%d: Sequential Lookup of key %4x failed!\n",
227                                 i, KeyArray[j]);
228                         DumpKeys(i, KeyArray[j]);
229                         Errors++;
230                         if (ignoreflg) {
231                                 j++;
232                                 continue;
233                         }
234                         assert( dbp );
235                 }
236
237                 if (debugflg && dbp) {
238                         printf("Seq rec #%-6d: checksum %4x (%4x)\r", i,
239                                 dbp->checksum, KeyArray[j]);
240                         fflush(stdout);
241                 }
242
243                 if (content.dsize == 0) {
244                         printf("\nrec #%-8d: key = %4x (%d)\n", i, KeyArray[j], j);
245                         fflush(stdout);
246                         DoSysError("\ndbm_fetch", content.dsize);
247                 }
248                 if (dbp->checksum != KeyArray[j])
249                         CkSumError("KeySequential", dbp->checksum, KeyArray[j]);
250                 if ((tmpck = calccksum(dbp->data, sizeof(dbp->data))) != KeyArray[j])
251                         CkSumError("DataSequential", tmpck, KeyArray[j]);
252                 if (++j >= keyIdx)
253                         j = 0;
254         }
255         printf("\n\n\tRandom lookups...\n");
256         fflush(stdout);
257         for(i=0; i<numDbmEntries; i++) {
258                 n = random() % keyIdx;
259                 key.dptr = (char *)(KeyArray+n);
260                 key.dsize = sizeof(KeyArray[0]);
261                 if (debugflg) {
262                         printf("dbm_fetch(dbm, key = %d)\n", n);
263                         fflush(stdout);
264                 }
265                 content = dbm_fetch(dbm, key);
266                 dbp = (myDB *)content.dptr;
267                 if ( !content.dptr ) {
268                         n = dbm_error(dbm);
269                         if (n) printf("\n\ndbm_error: %d\n", n);
270                         printf("\n%d: Random Lookup of key %4x failed!\n",
271                                 i, KeyArray[n]);
272                         DumpKeys(n, KeyArray[n]);
273                         Errors++;
274                         if (ignoreflg) {
275                                 continue;
276                         }
277                         assert( dbp );
278                 }
279
280                 if (debugflg && dbp) {
281                         printf("Rnd rec #%-6d: checksum %4x (%4x)\r", i,
282                                 dbp->checksum, KeyArray[n]);
283                         fflush(stdout);
284                 }
285
286                 if (content.dsize == 0)
287                         DoSysError("\ndbm_fetch", content.dsize);
288                 if (dbp->checksum != KeyArray[n])
289                         CkSumError("KeyRand", dbp->checksum, KeyArray[n]);
290                 if ((tmpck = calccksum(dbp->data, sizeof(dbp->data))) != KeyArray[n])
291                         CkSumError("DataRand", tmpck, KeyArray[n]);
292         }
293         return i;
294 }
295
296 void CleanupDbmLookup(void)
297 {
298         char filename[100];
299         int rc;
300
301         if (debugflg) {
302                 printf("dbm_close(dbm)\n");
303                 fflush(stdout);
304         }
305         dbm_close(dbm);
306         sprintf(filename, "%s-%d.dir", DBNAME, (int)getpid());
307         rc = unlink(filename);
308         if (rc) DoSysError("\nunlink", rc);
309         sprintf(filename, "%s-%d.pag", DBNAME, (int)getpid());
310         rc = unlink(filename);
311         if (rc) DoSysError("\nunlink", rc);
312 }
313
314 void DoSysError(char *msg, int rc)
315 {
316         perror(msg);
317         fprintf(stderr, "Bailing out! status = %d\n", rc);
318         exit(-1);
319 }
320
321 int creatDbRec(myDB *dbp)
322 {
323         static int once = 0;
324         int     i, j;
325         long    *ptr;
326         long    timeseed;
327
328         if (!once) {
329                 once++;
330                 if ( !randseed ) {
331                         timeseed = time(0);
332                         printf("\tusing %ld as seed for srandom()...\n\n",
333                                 timeseed);
334                         srandom(timeseed);
335                 } else
336                         srandom(randseed);
337         }
338         ptr = (long *)&(dbp->data);
339         j = sizeof(dbp->data) / sizeof(long);
340         for (i=0; i < j; i++, ptr++) {
341                 *ptr = random();
342         }
343         for (i=(j*sizeof(long)); i<sizeof(dbp->data); i++)
344                 dbp->data[i] = (char)time(0);
345
346         dbp->checksum = calccksum(dbp->data, sizeof(dbp->data));
347         return 0;
348 }
349
350 unsigned short calccksum(char *ptr, int size)
351 {
352         unsigned short sum;
353         int i, n;
354
355         sum = 0;
356         n = ((size > 100) ? 100 : size);
357         for (i=0; i<n && ptr; i++, ptr++) {
358                 if (sum & 01)
359                         sum = (sum >> 1) + 0x8000;
360                 else
361                         sum >>= 1;
362                 sum += (unsigned short)*ptr;
363                 sum &= 0xffff;
364         }
365         return sum;
366 }
367
368 /*ARGSUSED*/
369 void CkSumError(char *msg, unsigned short ck1, unsigned short ck2)
370 {
371         Errors++;
372         printf("%s\n\tChecksum error, %u != %u, Total errors = %d\n",
373                 msg, ck1, ck2, Errors);
374         exit(1);
375 }
376
377 int InsertKey(unsigned short *k, int idx, unsigned short val)
378 {
379 /*
380         int i, found=0;
381 */
382
383         return( (k[idx] = val) );
384
385 /*
386         for (i=0; i<idx; i++) {
387                 if (k[i] == val) {
388                         found++;
389                         break;
390                 }
391         }
392
393         if (!found)
394                 k[idx] = val;
395
396         return(!found);
397 */
398 }
399
400 void DumpKeys(int n, unsigned short key)
401 {
402 /*
403         int     i;
404         unsigned short *p;
405 */
406         FILE    *f;
407
408         if ((f = fopen("keys", "a")) == NULL) {
409                 perror("open(keys)");
410                 exit(1);
411         }
412 /*
413         for (i=0, p=arr; i<keyIdx && p; i++, p++)
414 */
415                 fprintf(f, "%d: 0x%x\n", n, key);
416
417         fclose(f);
418 }