1 /*************************************************************************************************
2  * Test cases of Villa
3  *                                                      Copyright (C) 2000-2007 Mikio Hirabayashi
4  * This file is part of QDBM, Quick Database Manager.
5  * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU
6  * Lesser General Public License as published by the Free Software Foundation; either version
7  * 2.1 of the License or any later version.  QDBM is distributed in the hope that it will be
8  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
10  * details.
11  * You should have received a copy of the GNU Lesser General Public License along with QDBM; if
12  * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
13  * 02111-1307 USA.
14  *************************************************************************************************/
15 
16 
17 #include <depot.h>
18 #include <cabin.h>
19 #include <villa.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdarg.h>
24 #include <limits.h>
25 #include <time.h>
26 
27 #undef TRUE
28 #define TRUE           1                 /* boolean true */
29 #undef FALSE
30 #define FALSE          0                 /* boolean false */
31 
32 #define RECBUFSIZ      32                /* buffer for records */
33 
34 
35 /* for RISC OS */
36 #if defined(__riscos__) || defined(__riscos)
37 #include <unixlib/local.h>
38 int __riscosify_control = __RISCOSIFY_NO_PROCESS;
39 #endif
40 
41 
42 /* global variables */
43 const char *progname;                    /* program name */
44 
45 
46 /* function prototypes */
47 int main(int argc, char **argv);
48 void usage(void);
49 int runwrite(int argc, char **argv);
50 int runread(int argc, char **argv);
51 int runrdup(int argc, char **argv);
52 int runcombo(int argc, char **argv);
53 int runwicked(int argc, char **argv);
54 int printfflush(const char *format, ...);
55 void pdperror(const char *name);
56 int myrand(void);
57 int dowrite(const char *name, int rnum, int ii, int cmode,
58             int lrecmax, int nidxmax, int lcnum, int ncnum, int fbp);
59 int doread(const char *name, int ii, int vc);
60 int dordup(const char *name, int rnum, int pnum, int ii, int cmode, int cc,
61            int lrecmax, int nidxmax, int lcnum, int ncnum, int fbp);
62 int docombo(const char *name, int cmode);
63 int dowicked(const char *name, int rnum, int cb, int cmode);
64 
65 
66 /* main routine */
main(int argc,char ** argv)67 int main(int argc, char **argv){
68   char *env;
69   int rv;
70   cbstdiobin();
71   if((env = getenv("QDBMDBGFD")) != NULL) dpdbgfd = atoi(env);
72   progname = argv[0];
73   if(argc < 2) usage();
74   rv = 0;
75   if(!strcmp(argv[1], "write")){
76     rv = runwrite(argc, argv);
77   } else if(!strcmp(argv[1], "read")){
78     rv = runread(argc, argv);
79   } else if(!strcmp(argv[1], "rdup")){
80     rv = runrdup(argc, argv);
81   } else if(!strcmp(argv[1], "combo")){
82     rv = runcombo(argc, argv);
83   } else if(!strcmp(argv[1], "wicked")){
84     rv = runwicked(argc, argv);
85   } else {
86     usage();
87   }
88   return rv;
89 }
90 
91 
92 /* print the usage and exit */
usage(void)93 void usage(void){
94   fprintf(stderr, "%s: test cases for Villa\n", progname);
95   fprintf(stderr, "\n");
96   fprintf(stderr, "usage:\n");
97   fprintf(stderr, "  %s write [-int] [-cz|-cy|-cx] [-tune lrecmax nidxmax lcnum ncnum]"
98           " [-fbp num] name rnum\n", progname);
99   fprintf(stderr, "  %s read [-int] [-vc] name\n", progname);
100   fprintf(stderr, "  %s rdup [-int] [-cz|-cy|-cx] [-cc] [-tune lrecmax nidxmax lcnum ncnum]"
101           " [-fbp num] name rnum pnum\n", progname);
102   fprintf(stderr, "  %s combo [-cz|-cy|-cx] name\n", progname);
103   fprintf(stderr, "  %s wicked [-c] [-cz|-cy|-cx] name rnum\n", progname);
104   fprintf(stderr, "\n");
105   exit(1);
106 }
107 
108 
109 /* parse arguments of write command */
runwrite(int argc,char ** argv)110 int runwrite(int argc, char **argv){
111   char *name, *rstr;
112   int i, rnum, ii, cmode, lrecmax, nidxmax, lcnum, ncnum, fbp, rv;
113   name = NULL;
114   rstr = NULL;
115   rnum = 0;
116   ii = FALSE;
117   cmode = 0;
118   lrecmax = -1;
119   nidxmax = -1;
120   lcnum = -1;
121   ncnum = -1;
122   fbp = -1;
123   for(i = 2; i < argc; i++){
124     if(!name && argv[i][0] == '-'){
125       if(!strcmp(argv[i], "-int")){
126         ii = TRUE;
127       } else if(!strcmp(argv[i], "-cz")){
128         cmode |= VL_OZCOMP;
129       } else if(!strcmp(argv[i], "-cy")){
130         cmode |= VL_OYCOMP;
131       } else if(!strcmp(argv[i], "-cx")){
132         cmode |= VL_OXCOMP;
133       } else if(!strcmp(argv[i], "-tune")){
134         if(++i >= argc) usage();
135         lrecmax = atoi(argv[i]);
136         if(++i >= argc) usage();
137         nidxmax = atoi(argv[i]);
138         if(++i >= argc) usage();
139         lcnum = atoi(argv[i]);
140         if(++i >= argc) usage();
141         ncnum = atoi(argv[i]);
142       } else if(!strcmp(argv[i], "-fbp")){
143         if(++i >= argc) usage();
144         fbp = atoi(argv[i]);
145       } else {
146         usage();
147       }
148     } else if(!name){
149       name = argv[i];
150     } else if(!rstr){
151       rstr = argv[i];
152     } else {
153       usage();
154     }
155   }
156   if(!name || !rstr) usage();
157   rnum = atoi(rstr);
158   if(rnum < 1) usage();
159   rv = dowrite(name, rnum, ii, cmode, lrecmax, nidxmax, lcnum, ncnum, fbp);
160   return rv;
161 }
162 
163 
164 /* parse arguments of read command */
runread(int argc,char ** argv)165 int runread(int argc, char **argv){
166   char *name;
167   int i, ii, vc, rv;
168   name = NULL;
169   ii = FALSE;
170   vc = FALSE;
171   for(i = 2; i < argc; i++){
172     if(!name && argv[i][0] == '-'){
173       if(!strcmp(argv[i], "-int")){
174         ii = TRUE;
175       } else if(!strcmp(argv[i], "-vc")){
176         vc = TRUE;
177       } else {
178         usage();
179       }
180     } else if(!name){
181       name = argv[i];
182     } else {
183       usage();
184     }
185   }
186   if(!name) usage();
187   rv = doread(name, ii, vc);
188   return rv;
189 }
190 
191 
192 /* parse arguments of rdup command */
runrdup(int argc,char ** argv)193 int runrdup(int argc, char **argv){
194   char *name, *rstr, *pstr;
195   int i, rnum, pnum, ii, cmode, cc, lrecmax, nidxmax, lcnum, ncnum, fbp, rv;
196   name = NULL;
197   rstr = NULL;
198   pstr = NULL;
199   rnum = 0;
200   pnum = 0;
201   ii = FALSE;
202   cmode = 0;
203   cc = FALSE;
204   lrecmax = -1;
205   nidxmax = -1;
206   lcnum = -1;
207   ncnum = -1;
208   fbp = -1;
209   for(i = 2; i < argc; i++){
210     if(!name && argv[i][0] == '-'){
211       if(!strcmp(argv[i], "-int")){
212         ii = TRUE;
213       } else if(!strcmp(argv[i], "-cz")){
214         cmode |= VL_OZCOMP;
215       } else if(!strcmp(argv[i], "-cy")){
216         cmode |= VL_OYCOMP;
217       } else if(!strcmp(argv[i], "-cx")){
218         cmode |= VL_OXCOMP;
219       } else if(!strcmp(argv[i], "-cc")){
220         cc = TRUE;
221       } else if(!strcmp(argv[i], "-tune")){
222         if(++i >= argc) usage();
223         lrecmax = atoi(argv[i]);
224         if(++i >= argc) usage();
225         nidxmax = atoi(argv[i]);
226         if(++i >= argc) usage();
227         lcnum = atoi(argv[i]);
228         if(++i >= argc) usage();
229         ncnum = atoi(argv[i]);
230       } else if(!strcmp(argv[i], "-fbp")){
231         if(++i >= argc) usage();
232         fbp = atoi(argv[i]);
233       } else {
234         usage();
235       }
236     } else if(!name){
237       name = argv[i];
238     } else if(!rstr){
239       rstr = argv[i];
240     } else if(!pstr){
241       pstr = argv[i];
242     } else {
243       usage();
244     }
245   }
246   if(!name || !rstr || !pstr) usage();
247   rnum = atoi(rstr);
248   pnum = atoi(pstr);
249   if(rnum < 1 || pnum < 1) usage();
250   rv = dordup(name, rnum, pnum, ii, cmode, cc, lrecmax, nidxmax, lcnum, ncnum, fbp);
251   return rv;
252 }
253 
254 
255 /* parse arguments of combo command */
runcombo(int argc,char ** argv)256 int runcombo(int argc, char **argv){
257   char *name;
258   int i, cmode, rv;
259   name = NULL;
260   cmode = 0;
261   for(i = 2; i < argc; i++){
262     if(!name && argv[i][0] == '-'){
263       if(!strcmp(argv[i], "-cz")){
264         cmode |= VL_OZCOMP;
265       } else if(!strcmp(argv[i], "-cy")){
266         cmode |= VL_OYCOMP;
267       } else if(!strcmp(argv[i], "-cx")){
268         cmode |= VL_OXCOMP;
269       } else {
270         usage();
271       }
272     } else if(!name){
273       name = argv[i];
274     } else {
275       usage();
276     }
277   }
278   if(!name) usage();
279   rv = docombo(name, cmode);
280   return rv;
281 }
282 
283 
284 /* parse arguments of wicked command */
runwicked(int argc,char ** argv)285 int runwicked(int argc, char **argv){
286   char *name, *rstr;
287   int i, cb, cmode, rnum, rv;
288   name = NULL;
289   rstr = NULL;
290   cb = FALSE;
291   cmode = 0;
292   for(i = 2; i < argc; i++){
293     if(!name && argv[i][0] == '-'){
294       if(!strcmp(argv[i], "-c")){
295         cb = TRUE;
296       } else if(!strcmp(argv[i], "-cz")){
297         cmode |= VL_OZCOMP;
298       } else if(!strcmp(argv[i], "-cy")){
299         cmode |= VL_OYCOMP;
300       } else if(!strcmp(argv[i], "-cx")){
301         cmode |= VL_OXCOMP;
302       } else {
303         usage();
304       }
305     } else if(!name){
306       name = argv[i];
307     } else if(!rstr){
308       rstr = argv[i];
309     } else {
310       usage();
311     }
312   }
313   if(!name || !rstr) usage();
314   rnum = atoi(rstr);
315   if(rnum < 1) usage();
316   rv = dowicked(name, rnum, cb, cmode);
317   return rv;
318 }
319 
320 
321 /* print formatted string and flush the buffer */
printfflush(const char * format,...)322 int printfflush(const char *format, ...){
323   va_list ap;
324   int rv;
325   va_start(ap, format);
326   rv = vprintf(format, ap);
327   if(fflush(stdout) == EOF) rv = -1;
328   va_end(ap);
329   return rv;
330 }
331 
332 
333 /* print an error message */
pdperror(const char * name)334 void pdperror(const char *name){
335   fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode));
336 }
337 
338 
339 /* pseudo random number generator */
myrand(void)340 int myrand(void){
341   static int cnt = 0;
342   if(cnt == 0) srand(time(NULL));
343   return (rand() * rand() + (rand() >> (sizeof(int) * 4)) + (cnt++)) & INT_MAX;
344 }
345 
346 
347 /* perform write command */
dowrite(const char * name,int rnum,int ii,int cmode,int lrecmax,int nidxmax,int lcnum,int ncnum,int fbp)348 int dowrite(const char *name, int rnum, int ii, int cmode,
349             int lrecmax, int nidxmax, int lcnum, int ncnum, int fbp){
350   VILLA *villa;
351   int i, omode, err, len;
352   char buf[RECBUFSIZ];
353   printfflush("<Writing Test>\n  name=%s  rnum=%d  int=%d  cmode=%d  "
354               "lrecmax=%d  nidxmax=%d  lcnum=%d  ncnum=%d  fbp=%d\n\n",
355               name, rnum, ii, cmode, lrecmax, nidxmax, lcnum, ncnum, fbp);
356   /* open a database */
357   omode = VL_OWRITER | VL_OCREAT | VL_OTRUNC | cmode;
358   if(!(villa = vlopen(name, omode, ii ? VL_CMPINT : VL_CMPLEX))){
359     pdperror(name);
360     return 1;
361   }
362   err = FALSE;
363   /* set tuning parameters */
364   if(lrecmax > 0) vlsettuning(villa, lrecmax, nidxmax, lcnum, ncnum);
365   if(fbp >= 0) vlsetfbpsiz(villa, fbp);
366   /* loop for each record */
367   for(i = 1; i <= rnum; i++){
368     /* store a record */
369     if(ii){
370       if(!vlput(villa, (char *)&i, sizeof(int), (char *)&i, sizeof(int), VL_DOVER)){
371         pdperror(name);
372         err = TRUE;
373         break;
374       }
375     } else {
376       len = sprintf(buf, "%08d", i);
377       if(!vlput(villa, buf, len, buf, len, VL_DOVER)){
378         pdperror(name);
379         err = TRUE;
380         break;
381       }
382     }
383     /* print progression */
384     if(rnum > 250 && i % (rnum / 250) == 0){
385       putchar('.');
386       fflush(stdout);
387       if(i == rnum || i % (rnum / 10) == 0){
388         printfflush(" (%08d)\n", i);
389       }
390     }
391   }
392   /* close the database */
393   if(!vlclose(villa)){
394     pdperror(name);
395     return 1;
396   }
397   if(!err) printfflush("ok\n\n");
398   return 0;
399 }
400 
401 
402 /* perform read command */
doread(const char * name,int ii,int vc)403 int doread(const char *name, int ii, int vc){
404   VILLA *villa;
405   int i, rnum, err, len;
406   const char *cval;
407   char buf[RECBUFSIZ], *val;
408   printfflush("<Reading Test>\n  name=%s  int=%d\n\n", name, ii);
409   /* open a database */
410   if(!(villa = vlopen(name, VL_OREADER, ii ? VL_CMPINT : VL_CMPLEX))){
411     pdperror(name);
412     return 1;
413   }
414   /* get the number of records */
415   rnum = vlrnum(villa);
416   err = FALSE;
417   /* loop for each record */
418   for(i = 1; i <= rnum; i++){
419     /* retrieve a record */
420     if(ii){
421       if(vc){
422         if(!(cval = vlgetcache(villa, (char *)&i, sizeof(int), NULL))){
423           pdperror(name);
424           err = TRUE;
425           break;
426         }
427       } else {
428         if(!(val = vlget(villa, (char *)&i, sizeof(int), NULL))){
429           pdperror(name);
430           err = TRUE;
431           break;
432         }
433         free(val);
434       }
435     } else {
436       len = sprintf(buf, "%08d", i);
437       if(vc){
438         if(!(cval = vlgetcache(villa, buf, len, NULL))){
439           pdperror(name);
440           err = TRUE;
441           break;
442         }
443       } else {
444         if(!(val = vlget(villa, buf, len, NULL))){
445           pdperror(name);
446           err = TRUE;
447           break;
448         }
449         free(val);
450       }
451     }
452     /* print progression */
453     if(rnum > 250 && i % (rnum / 250) == 0){
454       putchar('.');
455       fflush(stdout);
456       if(i == rnum || i % (rnum / 10) == 0){
457         printfflush(" (%08d)\n", i);
458       }
459     }
460   }
461   /* close the database */
462   if(!vlclose(villa)){
463     pdperror(name);
464     return 1;
465   }
466   if(!err) printfflush("ok\n\n");
467   return 0;
468 }
469 
470 
471 /* perform rdup command */
dordup(const char * name,int rnum,int pnum,int ii,int cmode,int cc,int lrecmax,int nidxmax,int lcnum,int ncnum,int fbp)472 int dordup(const char *name, int rnum, int pnum, int ii, int cmode, int cc,
473            int lrecmax, int nidxmax, int lcnum, int ncnum, int fbp){
474   VILLA *villa;
475   int i, omode, err, dmode, vi, len;
476   char buf[RECBUFSIZ];
477   printfflush("<Random Writing Test>\n  name=%s  rnum=%d  int=%d  cmode=%d  "
478               "lrecmax=%d  nidxmax=%d  lcnum=%d  ncnum=%d  fbp=%d\n\n",
479               name, rnum, ii, cmode, lrecmax, nidxmax, lcnum, ncnum, fbp);
480   omode = VL_OWRITER | VL_OCREAT | VL_OTRUNC | cmode;
481   if(!(villa = vlopen(name, omode, ii ? VL_CMPINT : VL_CMPLEX))){
482     pdperror(name);
483     return 1;
484   }
485   err = FALSE;
486   if(lrecmax > 0) vlsettuning(villa, lrecmax, nidxmax, lcnum, ncnum);
487   if(fbp >= 0) vlsetfbpsiz(villa, fbp);
488   for(i = 1; i <= rnum; i++){
489     dmode = i % 3 == 0 ? VL_DDUPR : VL_DDUP;
490     if(cc && myrand() % 2 == 0) dmode = VL_DCAT;
491     vi = myrand() % pnum + 1;
492     if(ii){
493       if(!vlput(villa, (char *)&vi, sizeof(int), (char *)&vi, sizeof(int), dmode)){
494         pdperror(name);
495         err = TRUE;
496         break;
497       }
498     } else {
499       len = sprintf(buf, "%08d", vi);
500       if(!vlput(villa, buf, len, buf, len, dmode)){
501         pdperror(name);
502         err = TRUE;
503         break;
504       }
505     }
506     if(rnum > 250 && i % (rnum / 250) == 0){
507       putchar('.');
508       fflush(stdout);
509       if(i == rnum || i % (rnum / 10) == 0){
510         printfflush(" (%08d: fsiz=%d lnum=%d nnum=%d)\n",
511                     i, vlfsiz(villa), vllnum(villa), vlnnum(villa));
512       }
513     }
514   }
515   if(!vlclose(villa)){
516     pdperror(name);
517     return 1;
518   }
519   if(!err) printfflush("ok\n\n");
520   return 0;
521 }
522 
523 
524 /* perform combo command */
docombo(const char * name,int cmode)525 int docombo(const char *name, int cmode){
526   VILLA *villa;
527   VLMULCUR **mulcurs;
528   char buf[RECBUFSIZ], *vbuf, *kbuf;
529   int i, j, omode, len, vsiz, ksiz, fsiz, lnum, nnum, rnum;
530   CBLIST *alist, *dlist;
531   const char *ap, *dp;
532   printfflush("<Combination Test>\n  name=%s  cmode=%d\n\n", name, cmode);
533   printfflush("Creating a database with VL_CMPLEX ... ");
534   omode = VL_OWRITER | VL_OCREAT | VL_OTRUNC | cmode;
535   if(!(villa = vlopen(name, omode, VL_CMPLEX))){
536     pdperror(name);
537     return 1;
538   }
539   printfflush("ok\n");
540   printfflush("Setting tuning parameters with 3, 4, 16, 16 ... ");
541   vlsettuning(villa, 3, 4, 16, 16);
542   printfflush("ok\n");
543   printfflush("Adding 100 records with VL_DOVER ... ");
544   for(i = 1; i <= 100; i++){
545     len = sprintf(buf, "%08d", i);
546     if(!vlput(villa, buf, len, buf, len, VL_DOVER)){
547       pdperror(name);
548       vlclose(villa);
549       return 1;
550     }
551   }
552   printfflush("ok\n");
553   printfflush("Checking records ... ");
554   for(i = 1; i <= 100; i++){
555     len = sprintf(buf, "%08d", i);
556     if(!(vbuf = vlget(villa, buf, len, &vsiz))){
557       pdperror(name);
558       vlclose(villa);
559       return 1;
560     }
561     free(vbuf);
562     if(vsiz != 8 || vlvsiz(villa, buf, len) != 8){
563       fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name);
564       vlclose(villa);
565       return 1;
566     }
567     if(vlvnum(villa, buf, len) != 1){
568       fprintf(stderr, "%s: %s: invalid vnum\n", progname, name);
569       vlclose(villa);
570       return 1;
571     }
572   }
573   printfflush("ok\n");
574   printfflush("Deleting x1 - x5 records ... ");
575   for(i = 1; i <= 100; i++){
576     if(i % 10 < 1 || i % 10 > 5) continue;
577     len = sprintf(buf, "%08d", i);
578     if(!vlout(villa, buf, len)){
579       pdperror(name);
580       vlclose(villa);
581       return 1;
582     }
583   }
584   printfflush("ok\n");
585   printfflush("Adding 100 records with VL_DOVER ... ");
586   for(i = 1; i <= 100; i++){
587     len = sprintf(buf, "%08d", i);
588     if(!vlput(villa, buf, len, buf, len, VL_DOVER)){
589       pdperror(name);
590       vlclose(villa);
591       return 1;
592     }
593   }
594   printfflush("ok\n");
595   printfflush("Deleting x1 - x5 records ... ");
596   for(i = 1; i <= 100; i++){
597     if(i % 10 < 1 || i % 10 > 5) continue;
598     len = sprintf(buf, "%08d", i);
599     if(!vlout(villa, buf, len)){
600       pdperror(name);
601       vlclose(villa);
602       return 1;
603     }
604   }
605   printfflush("ok\n");
606   printfflush("Checking number of records ... ");
607   if(vlrnum(villa) != 50){
608     fprintf(stderr, "%s: %s: invalid rnum\n", progname, name);
609     vlclose(villa);
610     return 1;
611   }
612   printfflush("ok\n");
613   printfflush("Adding 100 records with VL_DDUP ... ");
614   for(i = 1; i <= 100; i++){
615     len = sprintf(buf, "%08d", i);
616     if(!vlput(villa, buf, len, buf, len, VL_DDUP)){
617       pdperror(name);
618       vlclose(villa);
619       return 1;
620     }
621   }
622   printfflush("ok\n");
623   printfflush("Deleting x6 - x0 records ... ");
624   for(i = 1; i <= 100; i++){
625     if(i % 10 >= 1 && i % 10 <= 5) continue;
626     len = sprintf(buf, "%08d", i);
627     if(!vlout(villa, buf, len)){
628       pdperror(name);
629       vlclose(villa);
630       return 1;
631     }
632   }
633   printfflush("ok\n");
634   printfflush("Optimizing the database ... ");
635   if(!vloptimize(villa)){
636     pdperror(name);
637     vlclose(villa);
638     return 1;
639   }
640   printfflush("ok\n");
641   printfflush("Checking number of records ... ");
642   if(vlrnum(villa) != 100){
643     fprintf(stderr, "%s: %s: invalid rnum\n", progname, name);
644     vlclose(villa);
645     return 1;
646   }
647   printfflush("ok\n");
648   printfflush("Checking records ... ");
649   for(i = 1; i <= 100; i++){
650     len = sprintf(buf, "%08d", i);
651     if(!(vbuf = vlget(villa, buf, len, &vsiz))){
652       pdperror(name);
653       vlclose(villa);
654       return 1;
655     }
656     free(vbuf);
657     if(vsiz != 8){
658       fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name);
659       vlclose(villa);
660       return 1;
661     }
662     if(vlvnum(villa, buf, len) != 1){
663       fprintf(stderr, "%s: %s: invalid vnum\n", progname, name);
664       vlclose(villa);
665       return 1;
666     }
667   }
668   printfflush("ok\n");
669   printfflush("Deleting x6 - x0 records ... ");
670   for(i = 1; i <= 100; i++){
671     if(i % 10 >= 1 && i % 10 <= 5) continue;
672     len = sprintf(buf, "%08d", i);
673     if(!vlout(villa, buf, len)){
674       pdperror(name);
675       vlclose(villa);
676       return 1;
677     }
678   }
679   printfflush("ok\n");
680   printfflush("Scanning with the cursor in ascending order ... ");
681   if(!vlcurfirst(villa)){
682     pdperror(name);
683     vlclose(villa);
684     return 1;
685   }
686   i = 0;
687   do {
688     kbuf = NULL;
689     vbuf = NULL;
690     if(!(kbuf = vlcurkey(villa, &ksiz)) || !(vbuf = vlcurval(villa, &vsiz))){
691       pdperror(name);
692       free(kbuf);
693       free(vbuf);
694       vlclose(villa);
695       return 1;
696     }
697     free(kbuf);
698     free(vbuf);
699     i++;
700   } while(vlcurnext(villa));
701   if(i != 50){
702     fprintf(stderr, "%s: %s: invalid cursor\n", progname, name);
703     vlclose(villa);
704     return 1;
705   }
706   if(dpecode != DP_ENOITEM){
707     pdperror(name);
708     vlclose(villa);
709     return 1;
710   }
711   printfflush("ok\n");
712   printfflush("Scanning with the cursor in decending order ... ");
713   if(!vlcurlast(villa)){
714     pdperror(name);
715     vlclose(villa);
716     return 1;
717   }
718   i = 0;
719   do {
720     kbuf = NULL;
721     vbuf = NULL;
722     if(!(kbuf = vlcurkey(villa, &ksiz)) || !(vbuf = vlcurval(villa, &vsiz))){
723       pdperror(name);
724       free(kbuf);
725       free(vbuf);
726       vlclose(villa);
727       return 1;
728     }
729     free(kbuf);
730     free(vbuf);
731     i++;
732   } while(vlcurprev(villa));
733   if(i != 50){
734     fprintf(stderr, "%s: %s: invalid cursor\n", progname, name);
735     vlclose(villa);
736     return 1;
737   }
738   if(dpecode != DP_ENOITEM){
739     pdperror(name);
740     vlclose(villa);
741     return 1;
742   }
743   printfflush("ok\n");
744   printfflush("Adding 50 random records with VL_DDUPR ... ");
745   for(i = 0; i < 50; i++){
746     len = sprintf(buf, "%08d", myrand() % 100 + 1);
747     if(!vlput(villa, buf, len, buf, len, VL_DDUPR)){
748       pdperror(name);
749       vlclose(villa);
750       return 1;
751     }
752   }
753   printfflush("ok\n");
754   printfflush("Deleting 80 random records ... ");
755   i = 0;
756   while(i < 80){
757     len = sprintf(buf, "%08d", myrand() % 100 + 1);
758     if(!vlout(villa, buf, len)){
759       if(dpecode == DP_ENOITEM) continue;
760       pdperror(name);
761       vlclose(villa);
762       return 1;
763     }
764     i++;
765   }
766   printfflush("ok\n");
767   alist = cblistopen();
768   dlist = cblistopen();
769   printfflush("Scanning with the cursor in ascending order ... ");
770   if(!vlcurfirst(villa)){
771     pdperror(name);
772     vlclose(villa);
773     return 1;
774   }
775   i = 0;
776   do {
777     kbuf = NULL;
778     vbuf = NULL;
779     if(!(kbuf = vlcurkey(villa, &ksiz)) || !(vbuf = vlcurval(villa, &vsiz))){
780       pdperror(name);
781       cblistclose(alist);
782       cblistclose(dlist);
783       free(kbuf);
784       free(vbuf);
785       vlclose(villa);
786       return 1;
787     }
788     cblistpush(alist, kbuf, ksiz);
789     free(kbuf);
790     free(vbuf);
791     i++;
792   } while(vlcurnext(villa));
793   if(i != 20){
794     fprintf(stderr, "%s: %s: invalid cursor\n", progname, name);
795     cblistclose(alist);
796     cblistclose(dlist);
797     vlclose(villa);
798     return 1;
799   }
800   if(dpecode != DP_ENOITEM){
801     pdperror(name);
802     cblistclose(alist);
803     cblistclose(dlist);
804     vlclose(villa);
805     return 1;
806   }
807   printfflush("ok\n");
808   printfflush("Scanning with the cursor in decending order ... ");
809   if(!vlcurlast(villa)){
810     pdperror(name);
811     cblistclose(alist);
812     cblistclose(dlist);
813     vlclose(villa);
814     return 1;
815   }
816   i = 0;
817   do {
818     kbuf = NULL;
819     vbuf = NULL;
820     if(!(kbuf = vlcurkey(villa, &ksiz)) || !(vbuf = vlcurval(villa, &vsiz))){
821       pdperror(name);
822       free(kbuf);
823       free(vbuf);
824       cblistclose(alist);
825       cblistclose(dlist);
826       vlclose(villa);
827       return 1;
828     }
829     cblistunshift(dlist, kbuf, ksiz);
830     free(kbuf);
831     free(vbuf);
832     i++;
833   } while(vlcurprev(villa));
834   if(i != 20){
835     fprintf(stderr, "%s: %s: invalid cursor\n", progname, name);
836     cblistclose(alist);
837     cblistclose(dlist);
838     vlclose(villa);
839     return 1;
840   }
841   if(dpecode != DP_ENOITEM){
842     pdperror(name);
843     cblistclose(alist);
844     cblistclose(dlist);
845     vlclose(villa);
846     return 1;
847   }
848   printfflush("ok\n");
849   printfflush("Matching result of ascending scan and desending scan  ... ");
850   for(i = 0; i < cblistnum(alist); i++){
851     ap = cblistval(alist, i, NULL);
852     dp = cblistval(dlist, i, NULL);
853     if(strcmp(ap, dp)){
854       fprintf(stderr, "%s: %s: not match\n", progname, name);
855       cblistclose(alist);
856       cblistclose(dlist);
857       vlclose(villa);
858       return 1;
859     }
860   }
861   cblistsort(alist);
862   for(i = 0; i < cblistnum(alist); i++){
863     ap = cblistval(alist, i, NULL);
864     dp = cblistval(dlist, i, NULL);
865     if(strcmp(ap, dp)){
866       fprintf(stderr, "%s: %s: not match\n", progname, name);
867       cblistclose(alist);
868       cblistclose(dlist);
869       vlclose(villa);
870       return 1;
871     }
872   }
873   printfflush("ok\n");
874   cblistclose(alist);
875   cblistclose(dlist);
876   printfflush("Resetting tuning parameters with 41, 80, 32, 32 ... ");
877   vlsettuning(villa, 41, 80, 32, 32);
878   printfflush("ok\n");
879   printfflush("Adding 1000 random records with VL_DDUP ... ");
880   for(i = 0; i < 1000; i++){
881     len = sprintf(buf, "%08d", myrand() % 1000 + 1);
882     if(!vlput(villa, buf, len, buf, len, VL_DDUP)){
883       pdperror(name);
884       vlclose(villa);
885       return 1;
886     }
887   }
888   printfflush("ok\n");
889   printfflush("Resetting tuning parameters with 8, 5, 16, 16 ... ");
890   vlsettuning(villa, 8, 5, 16, 16);
891   printfflush("ok\n");
892   printfflush("Adding 1000 random records with VL_DDUP ... ");
893   for(i = 0; i < 1000; i++){
894     len = sprintf(buf, "%08d", myrand() % 1000 + 1);
895     if(!vlput(villa, buf, len, buf, len, VL_DDUP)){
896       pdperror(name);
897       vlclose(villa);
898       return 1;
899     }
900   }
901   printfflush("ok\n");
902   printfflush("Beginning the transaction ... ");
903   if(!vltranbegin(villa)){
904     pdperror(name);
905     vlclose(villa);
906     return 1;
907   }
908   printfflush("ok\n");
909   printfflush("Adding 100 random records with VL_DDUP ... ");
910   for(i = 0; i < 100; i++){
911     len = sprintf(buf, "%08d", myrand() % 1000 + 1);
912     if(!vlput(villa, buf, len, buf, len, VL_DDUP)){
913       pdperror(name);
914       vlclose(villa);
915       return 1;
916     }
917   }
918   printfflush("ok\n");
919   printfflush("Scanning and checking ... ");
920   i = 0;
921   for(vlcurlast(villa); (kbuf = vlcurkey(villa, &ksiz)) != NULL; vlcurprev(villa)){
922     if(vlvnum(villa, kbuf, ksiz) < 1 || !(vbuf = vlcurval(villa, NULL))){
923       pdperror(name);
924       free(kbuf);
925       vlclose(villa);
926       return 1;
927     }
928     free(vbuf);
929     free(kbuf);
930     i++;
931   }
932   if(i != vlrnum(villa)){
933     fprintf(stderr, "%s: %s: invalid\n", progname, name);
934     vlclose(villa);
935     return 1;
936   }
937   printfflush("ok\n");
938   printfflush("Committing the transaction ... ");
939   if(!vltrancommit(villa)){
940     pdperror(name);
941     vlclose(villa);
942     return 1;
943   }
944   printfflush("ok\n");
945   printfflush("Scanning and checking ... ");
946   i = 0;
947   for(vlcurlast(villa); (kbuf = vlcurkey(villa, &ksiz)) != NULL; vlcurprev(villa)){
948     if(vlvnum(villa, kbuf, ksiz) < 1 || !(vbuf = vlcurval(villa, NULL))){
949       pdperror(name);
950       free(kbuf);
951       vlclose(villa);
952       return 1;
953     }
954     free(vbuf);
955     free(kbuf);
956     i++;
957   }
958   if(i != vlrnum(villa)){
959     fprintf(stderr, "%s: %s: invalid\n", progname, name);
960     vlclose(villa);
961     return 1;
962   }
963   printfflush("ok\n");
964   lnum = vllnum(villa);
965   nnum = vlnnum(villa);
966   rnum = vlrnum(villa);
967   fsiz = vlfsiz(villa);
968   printfflush("Beginning the transaction ... ");
969   if(!vltranbegin(villa)){
970     pdperror(name);
971     vlclose(villa);
972     return 1;
973   }
974   printfflush("ok\n");
975   printfflush("Adding 100 random records with VL_DDUP ... ");
976   for(i = 0; i < 100; i++){
977     len = sprintf(buf, "%08d", myrand() % 1000 + 1);
978     if(!vlput(villa, buf, len, buf, len, VL_DDUP)){
979       pdperror(name);
980       vlclose(villa);
981       return 1;
982     }
983   }
984   printfflush("ok\n");
985   printfflush("Aborting the transaction ... ");
986   if(!vltranabort(villa)){
987     pdperror(name);
988     vlclose(villa);
989     return 1;
990   }
991   printfflush("ok\n");
992   printfflush("Checking rollback ... ");
993   if(vlfsiz(villa) != fsiz || vllnum(villa) != lnum ||
994      vlnnum(villa) != nnum || vlrnum(villa) != rnum){
995     fprintf(stderr, "%s: %s: invalid\n", progname, name);
996     vlclose(villa);
997     return 1;
998   }
999   printfflush("ok\n");
1000   printfflush("Scanning and checking ... ");
1001   i = 0;
1002   for(vlcurlast(villa); (kbuf = vlcurkey(villa, &ksiz)) != NULL; vlcurprev(villa)){
1003     if(vlvnum(villa, kbuf, ksiz) < 1 || !(vbuf = vlcurval(villa, NULL))){
1004       pdperror(name);
1005       free(kbuf);
1006       vlclose(villa);
1007       return 1;
1008     }
1009     free(vbuf);
1010     free(kbuf);
1011     i++;
1012   }
1013   if(i != vlrnum(villa)){
1014     fprintf(stderr, "%s: %s: invalid\n", progname, name);
1015     vlclose(villa);
1016     return 1;
1017   }
1018   printfflush("ok\n");
1019   printfflush("Closing the database ... ");
1020   if(!vlclose(villa)){
1021     pdperror(name);
1022     return 1;
1023   }
1024   printfflush("ok\n");
1025   printfflush("Creating a database with VL_CMPLEX ... ");
1026   omode = VL_OWRITER | VL_OCREAT | VL_OTRUNC | cmode;
1027   if(!(villa = vlopen(name, omode, VL_CMPLEX))){
1028     pdperror(name);
1029     return 1;
1030   }
1031   printfflush("ok\n");
1032   printfflush("Setting tuning parameters with 5, 6, 16, 16 ... ");
1033   vlsettuning(villa, 5, 6, 16, 16);
1034   printfflush("ok\n");
1035   printfflush("Adding 3 * 3 records with VL_DDUP ... ");
1036   for(i = 0; i < 3; i++){
1037     for(j = 0; j < 3; j++){
1038       len = sprintf(buf, "%08d", j);
1039       if(!vlput(villa, buf, len, buf, -1, VL_DDUP)){
1040         pdperror(name);
1041         vlclose(villa);
1042         return 1;
1043       }
1044     }
1045   }
1046   printfflush("ok\n");
1047   printfflush("Inserting records with the cursor ... ");
1048   if(!vlcurjump(villa, "00000001", -1, VL_JFORWARD) ||
1049      !vlcurput(villa, "first", -1, VL_CPAFTER) || !vlcurput(villa, "second", -1, VL_CPAFTER) ||
1050      !vlcurnext(villa) ||
1051      !vlcurput(villa, "third", -1, VL_CPAFTER) ||
1052      strcmp(vlcurvalcache(villa, NULL), "third") ||
1053      !vlcurput(villa, "fourth", -1, VL_CPCURRENT) ||
1054      strcmp(vlcurvalcache(villa, NULL), "fourth") ||
1055      !vlcurjump(villa, "00000001", -1, VL_JFORWARD) ||
1056      strcmp(vlcurvalcache(villa, NULL), "00000001") ||
1057      !vlcurput(villa, "one", -1, VL_CPBEFORE) || !vlcurput(villa, "two", -1, VL_CPBEFORE) ||
1058      !vlcurput(villa, "three", -1, VL_CPBEFORE) || !vlcurput(villa, "five", -1, VL_CPBEFORE) ||
1059      !vlcurnext(villa) ||
1060      !vlcurput(villa, "four", -1, VL_CPBEFORE) ||
1061      strcmp(vlcurvalcache(villa, NULL), "four") ||
1062      !vlcurjump(villa, "00000001*", -1, VL_JBACKWARD) ||
1063      strcmp(vlcurvalcache(villa, NULL), "00000001") ||
1064      !vlcurput(villa, "omega", -1, VL_CPAFTER) ||
1065      strcmp(vlcurkeycache(villa, NULL), "00000001") ||
1066      strcmp(vlcurvalcache(villa, NULL), "omega") ||
1067      !vlcurjump(villa, "00000000*", -1, VL_JFORWARD) ||
1068      !vlcurput(villa, "alpha", -1, VL_CPBEFORE) ||
1069      strcmp(vlcurvalcache(villa, NULL), "alpha") ||
1070      !vlcurprev(villa) ||
1071      strcmp(vlcurkeycache(villa, NULL), "00000000") ||
1072      strcmp(vlcurvalcache(villa, NULL), "00000000") ||
1073      !vlcurput(villa, "before", -1, VL_CPAFTER) ||
1074      strcmp(vlcurvalcache(villa, NULL), "before") ||
1075      !vlcurjump(villa, "00000001*", -1, VL_JFORWARD) ||
1076      !vlcurput(villa, "after", -1, VL_CPBEFORE) ||
1077      strcmp(vlcurvalcache(villa, NULL), "after") ||
1078      !vlcurfirst(villa) ||
1079      strcmp(vlcurvalcache(villa, NULL), "00000000") ||
1080      !vlcurput(villa, "top", -1, VL_CPBEFORE) ||
1081      strcmp(vlcurvalcache(villa, NULL), "top") ||
1082      !vlcurlast(villa) ||
1083      !vlcurput(villa, "bottom", -1, VL_CPAFTER) ||
1084      strcmp(vlcurvalcache(villa, NULL), "bottom")){
1085     fprintf(stderr, "%s: %s: invalid\n", progname, name);
1086     vlclose(villa);
1087     return 1;
1088   }
1089   printfflush("ok\n");
1090   printfflush("Deleting records with the cursor ... ");
1091   if(!vlcurjump(villa, "00000000*", -1, VL_JBACKWARD) ||
1092      strcmp(vlcurvalcache(villa, NULL), "before") ||
1093      !vlcurout(villa) ||
1094      strcmp(vlcurvalcache(villa, NULL), "alpha") ||
1095      !vlcurout(villa) ||
1096      strcmp(vlcurvalcache(villa, NULL), "five") ||
1097      !vlcurfirst(villa) || !vlcurnext(villa) ||
1098      !vlcurout(villa) || !vlcurout(villa) || !vlcurout(villa) ||
1099      strcmp(vlcurvalcache(villa, NULL), "five") ||
1100      !vlcurprev(villa) ||
1101      strcmp(vlcurvalcache(villa, NULL), "top") ||
1102      !vlcurout(villa) ||
1103      strcmp(vlcurvalcache(villa, NULL), "five") ||
1104      !vlcurjump(villa, "00000002", -1, VL_JBACKWARD) ||
1105      strcmp(vlcurvalcache(villa, NULL), "bottom") ||
1106      !vlcurout(villa) ||
1107      !vlcurjump(villa, "00000001", -1, VL_JBACKWARD) ||
1108      !vlcurout(villa) ||
1109      !vlcurout(villa) || !vlcurout(villa) || !vlcurout(villa) ||
1110      strcmp(vlcurkeycache(villa, NULL), "00000002") ||
1111      strcmp(vlcurvalcache(villa, NULL), "00000002") ||
1112      !vlcurout(villa) || vlcurout(villa) ||
1113      !vlcurfirst(villa) ||
1114      strcmp(vlcurvalcache(villa, NULL), "five")){
1115     fprintf(stderr, "%s: %s: invalid\n", progname, name);
1116     vlclose(villa);
1117     return 1;
1118   }
1119   vlcurfirst(villa);
1120   while(vlcurout(villa)){
1121     free(vlcurval(villa, NULL));
1122   }
1123   if(vlrnum(villa) != 0){
1124     printf("%d\n", vlrnum(villa));
1125     fprintf(stderr, "%s: %s: invalid\n", progname, name);
1126     vlclose(villa);
1127     return 1;
1128   }
1129   for(i = 0; i < 1000; i++){
1130     len = sprintf(buf, "%08d", i);
1131     if(!vlput(villa, buf, len, buf, -1, VL_DKEEP)){
1132       pdperror(name);
1133       vlclose(villa);
1134       return 1;
1135     }
1136   }
1137   for(i = 200; i < 800; i++){
1138     len = sprintf(buf, "%08d", i);
1139     if(!vlout(villa, buf, len)){
1140       pdperror(name);
1141       vlclose(villa);
1142       return 1;
1143     }
1144   }
1145   vlcurfirst(villa);
1146   while(vlcurout(villa)){
1147     free(vlcurval(villa, NULL));
1148   }
1149   if(vlrnum(villa) != 0){
1150     printf("%d\n", vlrnum(villa));
1151     fprintf(stderr, "%s: %s: invalid\n", progname, name);
1152     vlclose(villa);
1153     return 1;
1154   }
1155   printfflush("ok\n");
1156   printfflush("Adding 3 * 100 records with VL_DDUP ... ");
1157   for(i = 1; i <= 100; i++){
1158     len = sprintf(buf, "%08d", i);
1159     for(j = 0; j < 3; j++){
1160       if(!vlput(villa, buf, len, buf, len, VL_DDUP)){
1161         pdperror(name);
1162         vlclose(villa);
1163         return 1;
1164       }
1165     }
1166   }
1167   printfflush("ok\n");
1168   printfflush("Closing the database ... ");
1169   if(!vlclose(villa)){
1170     pdperror(name);
1171     return 1;
1172   }
1173   printfflush("ok\n");
1174   printfflush("Opening the database as a reader ... ");
1175   if(!(villa = vlopen(name, VL_OREADER, VL_CMPLEX))){
1176     pdperror(name);
1177     return 1;
1178   }
1179   printfflush("ok\n");
1180   printfflush("Opening multiple cursors ... ");
1181   mulcurs = cbmalloc(sizeof(VLMULCUR *) * 8);
1182   for(i = 0; i < 8; i++){
1183     if(!(mulcurs[i] = vlmulcuropen(villa))){
1184       pdperror(name);
1185       vlclose(villa);
1186       return 1;
1187     }
1188   }
1189   printfflush("ok\n");
1190   printfflush("Scanning multiple cursors ... ");
1191   for(i = 0; i < 8; i++){
1192     if(i % 2 == 0){
1193       vlmulcurfirst(mulcurs[i]);
1194     } else {
1195       vlmulcurlast(mulcurs[i]);
1196     }
1197   }
1198   for(i = 0; i < 300; i++){
1199     for(j = 0; j < 8; j++){
1200       if(j % 2 == 0){
1201         if(!(vbuf = vlmulcurkey(mulcurs[j], &vsiz))){
1202           pdperror(name);
1203           vlclose(villa);
1204           return 1;
1205         }
1206         free(vbuf);
1207         vlmulcurnext(mulcurs[j]);
1208       } else {
1209         if(!(vbuf = vlmulcurval(mulcurs[j], &vsiz))){
1210           pdperror(name);
1211           vlclose(villa);
1212           return 1;
1213         }
1214         free(vbuf);
1215         vlmulcurprev(mulcurs[j]);
1216       }
1217     }
1218   }
1219   printfflush("ok\n");
1220   printfflush("Closing multiple cursors ... ");
1221   for(i = 0; i < 8; i++){
1222     vlmulcurclose(mulcurs[i]);
1223   }
1224   free(mulcurs);
1225   printfflush("ok\n");
1226   printfflush("Closing the database ... ");
1227   if(!vlclose(villa)){
1228     pdperror(name);
1229     return 1;
1230   }
1231   printfflush("ok\n");
1232   printfflush("all ok\n\n");
1233   return 0;
1234 }
1235 
1236 
1237 /* perform wicked command */
dowicked(const char * name,int rnum,int cb,int cmode)1238 int dowicked(const char *name, int rnum, int cb, int cmode){
1239   VILLA *villa;
1240   CBMAP *map;
1241   int i, j, omode, len, err, ksiz, vsiz, tran, mksiz, mvsiz, rsiz;
1242   const char *mkbuf, *mvbuf;
1243   char buf[32], *kbuf, *vbuf;
1244   CBLIST *list;
1245   printfflush("<Wicked Writing Test>\n  name=%s  rnum=%d\n\n", name, rnum);
1246   omode = VL_OWRITER | VL_OCREAT | VL_OTRUNC | cmode;
1247   if(!(villa = vlopen(name, omode, VL_CMPLEX))){
1248     pdperror(name);
1249     return 1;
1250   }
1251   err = FALSE;
1252   tran = FALSE;
1253   vlsettuning(villa, 5, 10, 64, 64);
1254   map = NULL;
1255   if(cb) map = cbmapopen();
1256   for(i = 1; i <= rnum; i++){
1257     len = sprintf(buf, "%08d", myrand() % rnum + 1);
1258     switch(cb ? (myrand() % 5) : myrand() % 16){
1259     case 0:
1260       putchar('O');
1261       if(!vlput(villa, buf, len, buf, len, VL_DOVER)) err = TRUE;
1262       if(map) cbmapput(map, buf, len, buf, len, TRUE);
1263       break;
1264     case 1:
1265       putchar('K');
1266       if(!vlput(villa, buf, len, buf, len, VL_DKEEP) && dpecode != DP_EKEEP) err = TRUE;
1267       if(map) cbmapput(map, buf, len, buf, len, FALSE);
1268       break;
1269     case 2:
1270       putchar('C');
1271       if(!vlput(villa, buf, len, buf, len, VL_DCAT)) err = TRUE;
1272       if(map) cbmapputcat(map, buf, len, buf, len);
1273       break;
1274     case 3:
1275       putchar('D');
1276       if(!vlout(villa, buf, len) && dpecode != DP_ENOITEM) err = TRUE;
1277       if(map) cbmapout(map, buf, len);
1278       break;
1279     case 4:
1280       putchar('G');
1281       if((vbuf = vlget(villa, buf, len, NULL)) != NULL){
1282         free(vbuf);
1283       } else if(dpecode != DP_ENOITEM){
1284         err = TRUE;
1285       }
1286       break;
1287     case 5:
1288       putchar('V');
1289       if(vlvsiz(villa, buf, len) < 0 && dpecode != DP_ENOITEM) err = TRUE;
1290       if(!vlvnum(villa, buf, len) && dpecode != DP_ENOITEM) err = TRUE;
1291       break;
1292     case 6:
1293       putchar('X');
1294       list = cblistopen();
1295       cblistpush(list, buf, len);
1296       cblistpush(list, buf, len);
1297       if(!vlputlist(villa, buf, len, list)) err = TRUE;
1298       cblistclose(list);
1299       break;
1300     case 7:
1301       putchar('Y');
1302       if(!vloutlist(villa, buf, len) && dpecode != DP_ENOITEM) err = TRUE;
1303       break;
1304     case 8:
1305       putchar('Z');
1306       if((list = vlgetlist(villa, buf, len)) != NULL){
1307         cblistclose(list);
1308       } else if(dpecode != DP_ENOITEM){
1309         err = TRUE;
1310       }
1311       if((vbuf = vlgetcat(villa, buf, len, NULL)) != NULL){
1312         free(vbuf);
1313       } else if(dpecode != DP_ENOITEM){
1314         err = TRUE;
1315       }
1316       break;
1317     case 9:
1318       putchar('Q');
1319       if(vlcurjump(villa, buf, len, VL_JFORWARD)){
1320         for(j = 0; j < 3 && (kbuf = vlcurkey(villa, &ksiz)); j++){
1321           if(VL_CMPLEX(buf, len, kbuf, ksiz) > 0) err = TRUE;
1322           if(strcmp(vlcurkeycache(villa, NULL), kbuf)) err = TRUE;
1323           if((vbuf = vlcurval(villa, &vsiz)) != NULL){
1324             if(strcmp(vlcurvalcache(villa, NULL), vbuf)) err = TRUE;
1325             free(vbuf);
1326           } else {
1327             err = TRUE;
1328           }
1329           free(kbuf);
1330           if(!vlcurnext(villa) && dpecode != DP_ENOITEM) err = TRUE;
1331         }
1332       } else {
1333         if(dpecode != DP_ENOITEM) err = TRUE;
1334       }
1335       break;
1336     case 10:
1337       putchar('W');
1338       if(vlcurjump(villa, buf, len, VL_JBACKWARD)){
1339         for(j = 0; j < 3 && (kbuf = vlcurkey(villa, &ksiz)); j++){
1340           if(VL_CMPLEX(buf, len, kbuf, ksiz) < 0) err = TRUE;
1341           if(strcmp(vlcurkeycache(villa, NULL), kbuf)) err = TRUE;
1342           if((vbuf = vlcurval(villa, &vsiz)) != NULL){
1343             if(strcmp(vlcurvalcache(villa, NULL), vbuf)) err = TRUE;
1344             free(vbuf);
1345           } else {
1346             err = TRUE;
1347           }
1348           free(kbuf);
1349           if(!vlcurprev(villa) && dpecode != DP_ENOITEM) err = TRUE;
1350         }
1351       } else {
1352         if(dpecode != DP_ENOITEM) err = TRUE;
1353       }
1354       break;
1355     case 11:
1356       putchar('L');
1357       if(myrand() % 3 == 0 &&
1358          !vlcurjump(villa, buf, len, i % 3 == 0 ? VL_JFORWARD : VL_JBACKWARD) &&
1359          dpecode != DP_ENOITEM) err = TRUE;
1360       for(j = myrand() % 5; j >= 0; j--){
1361         switch(myrand() % 6){
1362         case 0:
1363           if(!vlcurput(villa, buf, len, VL_CPAFTER) && dpecode != DP_ENOITEM) err = TRUE;
1364           break;
1365         case 1:
1366           if(!vlcurput(villa, buf, len, VL_CPBEFORE) && dpecode != DP_ENOITEM) err = TRUE;
1367           break;
1368         case 2:
1369           if(!vlcurput(villa, buf, len, VL_CPCURRENT) && dpecode != DP_ENOITEM) err = TRUE;
1370           break;
1371         default:
1372           if(!vlcurout(villa)){
1373             if(dpecode != DP_ENOITEM) err = TRUE;
1374             break;
1375           }
1376           break;
1377         }
1378       }
1379       break;
1380     case 12:
1381       if(tran ? myrand() % 32 != 0 : myrand() % 1024 != 0){
1382         putchar('N');
1383         break;
1384       }
1385       putchar('T');
1386       if(tran){
1387         if(myrand() % 5 == 0){
1388           if(!vltranabort(villa)) err = TRUE;
1389         } else {
1390           if(!vltrancommit(villa)) err = TRUE;
1391         }
1392         tran = FALSE;
1393       } else {
1394         if(!vltranbegin(villa)) err = TRUE;
1395         tran = TRUE;
1396       }
1397       break;
1398     default:
1399       putchar('P');
1400       if(!vlput(villa, buf, len, buf, len, myrand() % 3 == 0 ? VL_DDUPR : VL_DDUP)) err = TRUE;
1401       break;
1402     }
1403     if(i % 50 == 0) printfflush(" (%08d)\n", i);
1404     if(err){
1405       pdperror(name);
1406       break;
1407     }
1408   }
1409   if(tran){
1410     if(!vltranabort(villa)) err = TRUE;
1411   }
1412   if(!vloptimize(villa)){
1413     pdperror(name);
1414     err = TRUE;
1415   }
1416   if((rnum = vlrnum(villa)) == -1){
1417     pdperror(name);
1418     err = TRUE;
1419   }
1420   if(!vlcurfirst(villa)){
1421     pdperror(name);
1422     err = TRUE;
1423   }
1424   i = 0;
1425   do {
1426     kbuf = NULL;
1427     vbuf = NULL;
1428     if(!(kbuf = vlcurkey(villa, &ksiz)) || !(vbuf = vlcurval(villa, &vsiz)) ||
1429        ksiz != 8 || vsiz % 8 != 0 || vlvnum(villa, kbuf, ksiz) < 1){
1430       pdperror(name);
1431       free(kbuf);
1432       free(vbuf);
1433       err = TRUE;
1434       break;
1435     }
1436     free(kbuf);
1437     free(vbuf);
1438     i++;
1439   } while(vlcurnext(villa));
1440   if(i != rnum){
1441     fprintf(stderr, "%s: %s: invalid cursor\n", progname, name);
1442     err = TRUE;
1443   }
1444   if(dpecode != DP_ENOITEM){
1445     pdperror(name);
1446     err = TRUE;
1447   }
1448   if(!vlcurlast(villa)){
1449     pdperror(name);
1450     err = TRUE;
1451   }
1452   i = 0;
1453   do {
1454     kbuf = NULL;
1455     vbuf = NULL;
1456     if(!(kbuf = vlcurkey(villa, &ksiz)) || !(vbuf = vlcurval(villa, &vsiz)) ||
1457        ksiz != 8 || vsiz % 8 != 0 || vlvnum(villa, kbuf, ksiz) < 1){
1458       pdperror(name);
1459       free(kbuf);
1460       free(vbuf);
1461       err = TRUE;
1462       break;
1463     }
1464     free(kbuf);
1465     free(vbuf);
1466     i++;
1467   } while(vlcurprev(villa));
1468   if(i != rnum){
1469     fprintf(stderr, "%s: %s: invalid cursor\n", progname, name);
1470     err = TRUE;
1471   }
1472   if(dpecode != DP_ENOITEM){
1473     pdperror(name);
1474     err = TRUE;
1475   }
1476   if(map){
1477     printfflush("Matching records ... ");
1478     cbmapiterinit(map);
1479     while((mkbuf = cbmapiternext(map, &mksiz)) != NULL){
1480       mvbuf = cbmapget(map, mkbuf, mksiz, &mvsiz);
1481       if(!(vbuf = vlget(villa, mkbuf, mksiz, &rsiz))){
1482         pdperror(name);
1483         err = TRUE;
1484         break;
1485       }
1486       if(rsiz != mvsiz || memcmp(vbuf, mvbuf, rsiz)){
1487         fprintf(stderr, "%s: %s: unmatched record\n", progname, name);
1488         free(vbuf);
1489         err = TRUE;
1490         break;
1491       }
1492       free(vbuf);
1493     }
1494     cbmapclose(map);
1495     if(!err) printfflush("ok\n");
1496   }
1497   if(!vlclose(villa)){
1498     pdperror(name);
1499     return 1;
1500   }
1501   if(!err) printfflush("ok\n\n");
1502   return err ? 1 : 0;
1503 }
1504 
1505 
1506 
1507 /* END OF FILE */
1508