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