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