1 /* Copyright (c) 2000-2008 MySQL AB
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
21 #include <sys/types.h>
22 #ifdef HAVE_SYS_WAIT_H
23 # include <sys/wait.h>
26 # define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
29 # define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
33 #if defined(HAVE_LRAND48)
34 #define rnd(X) (lrand48() % X)
35 #define rnd_init(X) srand48(X)
37 #define rnd(X) (random() % X)
38 #define rnd_init(X) srandom(X)
42 const char *filename
= "test3";
43 uint tests
=10,forks
=10,key_cacheing
=0,use_log
=0;
45 static void get_options(int argc
, char *argv
[]);
46 void start_test(int id
);
47 int test_read(MI_INFO
*,int),test_write(MI_INFO
*,int,int),
48 test_update(MI_INFO
*,int,int),test_rrnd(MI_INFO
*,int);
57 int main(int argc
,char **argv
)
61 MI_KEYDEF keyinfo
[10];
62 MI_COLUMNDEF recinfo
[10];
63 HA_KEYSEG keyseg
[10][2];
65 get_options(argc
,argv
);
67 bzero((char*) keyinfo
,sizeof(keyinfo
));
68 bzero((char*) recinfo
,sizeof(recinfo
));
69 bzero((char*) keyseg
,sizeof(keyseg
));
70 keyinfo
[0].seg
= &keyseg
[0][0];
71 keyinfo
[0].seg
[0].start
=0;
72 keyinfo
[0].seg
[0].length
=8;
73 keyinfo
[0].seg
[0].type
=HA_KEYTYPE_TEXT
;
74 keyinfo
[0].seg
[0].flag
=HA_SPACE_PACK
;
75 keyinfo
[0].key_alg
=HA_KEY_ALG_BTREE
;
77 keyinfo
[0].flag
= (uint8
) HA_PACK_KEY
;
78 keyinfo
[0].block_length
= 0; /* Default block length */
79 keyinfo
[1].seg
= &keyseg
[1][0];
80 keyinfo
[1].seg
[0].start
=8;
81 keyinfo
[1].seg
[0].length
=4; /* Long is always 4 in myisam */
82 keyinfo
[1].seg
[0].type
=HA_KEYTYPE_LONG_INT
;
83 keyinfo
[1].seg
[0].flag
=0;
84 keyinfo
[1].key_alg
=HA_KEY_ALG_BTREE
;
86 keyinfo
[1].flag
=HA_NOSAME
;
87 keyinfo
[1].block_length
= 0; /* Default block length */
90 recinfo
[0].length
=sizeof(record
.id
);
92 recinfo
[1].length
=sizeof(record
.nr
);
94 recinfo
[2].length
=sizeof(record
.text
);
96 puts("- Creating myisam-file");
97 my_delete(filename
,MYF(0)); /* Remove old locks under gdb */
98 if (mi_create(filename
,2,&keyinfo
[0],2,&recinfo
[0],0,(MI_UNIQUEDEF
*) 0,
99 (MI_CREATE_INFO
*) 0,0))
103 printf("- Starting %d processes\n",forks
); fflush(stdout
);
104 for (i
=0 ; i
< forks
; i
++)
115 for (i
=0 ; i
< forks
; i
++)
116 while ((wait_ret
=wait(&status
)) && wait_ret
== -1);
121 static void get_options(int argc
, char **argv
)
127 while (--argc
>0 && *(pos
= *(++argv
)) == '-' ) {
138 case 'K': /* Use key cacheing */
141 case 'A': /* All flags */
142 use_log
=key_cacheing
=1;
147 printf("%s Ver 1.0 for %s at %s\n",progname
,SYSTEM_TYPE
,MACHINE_TYPE
);
148 puts("By Monty, for your professional use\n");
149 puts("Test av locking with threads\n");
150 printf("Usage: %s [-?lKA] [-f#] [-t#]\n",progname
);
156 printf("Illegal option: '%c'\n",*pos
);
164 void start_test(int id
)
168 MI_ISAMINFO isam_info
;
169 MI_INFO
*file
,*file1
,*file2
=0,*lock
;
173 if (!(file1
=mi_open(filename
,O_RDWR
,HA_OPEN_WAIT_IF_LOCKED
)) ||
174 !(file2
=mi_open(filename
,O_RDWR
,HA_OPEN_WAIT_IF_LOCKED
)))
176 fprintf(stderr
,"Can't open isam-file: %s\n",filename
);
179 if (key_cacheing
&& rnd(2) == 0)
180 init_key_cache(dflt_key_cache
, KEY_CACHE_BLOCK_SIZE
, 65536L, 0, 0);
181 printf("Process %d, pid: %d\n",id
,getpid()); fflush(stdout
);
183 for (error
=i
=0 ; i
< tests
&& !error
; i
++)
185 file
= (rnd(2) == 1) ? file1
: file2
;
186 lock
=0 ; lock_type
=0;
189 if (mi_lock_database(lock
=(rnd(2) ? file1
: file2
),
190 lock_type
=(rnd(2) == 0 ? F_RDLCK
: F_WRLCK
)))
192 fprintf(stderr
,"%2d: start: Can't lock table %d\n",id
,my_errno
);
198 case 0: error
=test_read(file
,id
); break;
199 case 1: error
=test_rrnd(file
,id
); break;
200 case 2: error
=test_write(file
,id
,lock_type
); break;
201 case 3: error
=test_update(file
,id
,lock_type
); break;
204 mi_lock_database(lock
,F_UNLCK
);
208 mi_status(file1
,&isam_info
,HA_STATUS_VARIABLE
);
209 printf("%2d: End of test. Records: %ld Deleted: %ld\n",
210 id
,(long) isam_info
.records
, (long) isam_info
.deleted
);
220 printf("%2d: Aborted\n",id
); fflush(stdout
);
226 int test_read(MI_INFO
*file
,int id
)
228 uint i
,lock
,found
,next
,prev
;
235 if (mi_lock_database(file
,F_RDLCK
))
237 fprintf(stderr
,"%2d: Can't lock table %d\n",id
,my_errno
);
243 for (i
=0 ; i
< 100 ; i
++)
246 if (!mi_rkey(file
,record
.id
,1,(uchar
*) &find
, HA_WHOLE_KEY
,
251 if (my_errno
!= HA_ERR_KEY_NOT_FOUND
)
253 fprintf(stderr
,"%2d: Got error %d from read in read\n",id
,my_errno
);
256 else if (!mi_rnext(file
,record
.id
,1))
260 if (my_errno
!= HA_ERR_END_OF_FILE
)
262 fprintf(stderr
,"%2d: Got error %d from rnext in read\n",id
,my_errno
);
265 else if (!mi_rprev(file
,record
.id
,1))
269 if (my_errno
!= HA_ERR_END_OF_FILE
)
271 fprintf(stderr
,"%2d: Got error %d from rnext in read\n",
281 if (mi_lock_database(file
,F_UNLCK
))
283 fprintf(stderr
,"%2d: Can't unlock table\n",id
);
287 printf("%2d: read: found: %5d next: %5d prev: %5d\n",
294 int test_rrnd(MI_INFO
*file
,int id
)
302 if (mi_lock_database(file
,F_RDLCK
))
304 fprintf(stderr
,"%2d: Can't lock table (%d)\n",id
,my_errno
);
309 mi_extra(file
,HA_EXTRA_CACHE
,0);
313 if (mi_rrnd(file
,record
.id
,0L))
315 if (my_errno
== HA_ERR_END_OF_FILE
)
317 fprintf(stderr
,"%2d: Can't read first record (%d)\n",id
,my_errno
);
320 for (count
=1 ; !mi_rrnd(file
,record
.id
,HA_OFFSET_ERROR
) ;count
++) ;
321 if (my_errno
!= HA_ERR_END_OF_FILE
)
323 fprintf(stderr
,"%2d: Got error %d from rrnd\n",id
,my_errno
);
330 mi_extra(file
,HA_EXTRA_NO_CACHE
,0);
331 if (mi_lock_database(file
,F_UNLCK
))
333 fprintf(stderr
,"%2d: Can't unlock table\n",id
);
337 printf("%2d: rrnd: %5d\n",id
,count
); fflush(stdout
);
342 int test_write(MI_INFO
*file
,int id
,int lock_type
)
344 uint i
,tries
,count
,lock
;
347 if (rnd(2) == 0 || lock_type
== F_RDLCK
)
350 if (mi_lock_database(file
,F_WRLCK
))
352 if (lock_type
== F_RDLCK
&& my_errno
== EDEADLK
)
354 printf("%2d: write: deadlock\n",id
); fflush(stdout
);
357 fprintf(stderr
,"%2d: Can't lock table (%d)\n",id
,my_errno
);
362 mi_extra(file
,HA_EXTRA_WRITE_CACHE
,0);
365 sprintf((char*) record
.id
,"%7d",getpid());
366 strnmov((char*) record
.text
,"Testing...", sizeof(record
.text
));
368 tries
=(uint
) rnd(100)+10;
369 for (i
=count
=0 ; i
< tries
; i
++)
371 uint32 tmp
=rnd(80000)+20000;
372 int4store(record
.nr
,tmp
);
373 if (!mi_write(file
,record
.id
))
377 if (my_errno
!= HA_ERR_FOUND_DUPP_KEY
)
379 fprintf(stderr
,"%2d: Got error %d (errno %d) from write\n",id
,my_errno
,
387 mi_extra(file
,HA_EXTRA_NO_CACHE
,0);
388 if (mi_lock_database(file
,F_UNLCK
))
390 fprintf(stderr
,"%2d: Can't unlock table\n",id
);
394 printf("%2d: write: %5d\n",id
,count
); fflush(stdout
);
399 int test_update(MI_INFO
*file
,int id
,int lock_type
)
401 uint i
,lock
,found
,next
,prev
,update
;
404 struct record new_record
;
407 if (rnd(2) == 0 || lock_type
== F_RDLCK
)
410 if (mi_lock_database(file
,F_WRLCK
))
412 if (lock_type
== F_RDLCK
&& my_errno
== EDEADLK
)
414 printf("%2d: write: deadlock\n",id
); fflush(stdout
);
417 fprintf(stderr
,"%2d: Can't lock table (%d)\n",id
,my_errno
);
421 bzero((char*) &new_record
,sizeof(new_record
));
422 strmov((char*) new_record
.text
,"Updated");
424 found
=next
=prev
=update
=0;
425 for (i
=0 ; i
< 100 ; i
++)
429 if (!mi_rkey(file
,record
.id
,1,(uchar
*) find
, HA_WHOLE_KEY
,
434 if (my_errno
!= HA_ERR_KEY_NOT_FOUND
)
436 fprintf(stderr
,"%2d: Got error %d from read in update\n",id
,my_errno
);
439 else if (!mi_rnext(file
,record
.id
,1))
443 if (my_errno
!= HA_ERR_END_OF_FILE
)
445 fprintf(stderr
,"%2d: Got error %d from rnext in update\n",
449 else if (!mi_rprev(file
,record
.id
,1))
453 if (my_errno
!= HA_ERR_END_OF_FILE
)
455 fprintf(stderr
,"%2d: Got error %d from rnext in update\n",
463 memcpy_fixed(new_record
.id
,record
.id
,sizeof(record
.id
));
464 tmp
=rnd(20000)+40000;
465 int4store(new_record
.nr
,tmp
);
466 if (!mi_update(file
,record
.id
,new_record
.id
))
470 if (my_errno
!= HA_ERR_RECORD_CHANGED
&&
471 my_errno
!= HA_ERR_RECORD_DELETED
&&
472 my_errno
!= HA_ERR_FOUND_DUPP_KEY
)
474 fprintf(stderr
,"%2d: Got error %d from update\n",id
,my_errno
);
481 if (mi_lock_database(file
,F_UNLCK
))
483 fprintf(stderr
,"Can't unlock table,id, error%d\n",my_errno
);
487 printf("%2d: update: %5d\n",id
,update
); fflush(stdout
);
491 #else /* __NETWARE__ */
497 fprintf(stderr
,"this test has not been ported to NetWare\n");
501 #endif /* __NETWARE__ */