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