1 : /* Copyright (C) 2006-2008 MySQL AB
2 :
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.
6 :
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.
11 :
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
15 :
16 : /*
17 : TODO: use pthread_join instead of wait_for_thread_count_to_be_zero, like in
18 : my_atomic-t.c (see BUG#22320).
19 : Use diag() instead of fprintf(stderr).
20 : */
21 : #include <tap.h>
22 : #include <my_sys.h>
23 : #include <m_string.h>
24 : #include "test_file.h"
25 : #include <tap.h>
26 :
27 : #define PCACHE_SIZE (TEST_PAGE_SIZE*1024*10)
28 :
29 : #ifndef DBUG_OFF
30 : static const char* default_dbug_option;
31 : #endif
32 :
33 : #ifndef BIG
34 : #undef SKIP_BIG_TESTS
35 : #define SKIP_BIG_TESTS(X) /* no-op */
36 : #endif
37 :
38 : static char *file1_name= (char*)"page_cache_test_file_1";
39 : static char *file2_name= (char*)"page_cache_test_file_2";
40 : static PAGECACHE_FILE file1;
41 : static pthread_cond_t COND_thread_count;
42 : static pthread_mutex_t LOCK_thread_count;
43 : static uint thread_count;
44 : static PAGECACHE pagecache;
45 :
46 : /*
47 : File contance descriptors
48 : */
49 : static struct file_desc simple_read_write_test_file[]=
50 : {
51 : { TEST_PAGE_SIZE, '\1'},
52 : {0, 0}
53 : };
54 : static struct file_desc simple_read_change_write_read_test_file[]=
55 : {
56 : { TEST_PAGE_SIZE/2, '\65'},
57 : { TEST_PAGE_SIZE/2, '\1'},
58 : {0, 0}
59 : };
60 : static struct file_desc simple_pin_test_file1[]=
61 : {
62 : { TEST_PAGE_SIZE*2, '\1'},
63 : {0, 0}
64 : };
65 : static struct file_desc simple_pin_test_file2[]=
66 : {
67 : { TEST_PAGE_SIZE/2, '\1'},
68 : { TEST_PAGE_SIZE/2, (unsigned char)129},
69 : { TEST_PAGE_SIZE, '\1'},
70 : {0, 0}
71 : };
72 : static struct file_desc simple_pin_no_lock_test_file1[]=
73 : {
74 : { TEST_PAGE_SIZE, '\4'},
75 : {0, 0}
76 : };
77 : static struct file_desc simple_pin_no_lock_test_file2[]=
78 : {
79 : { TEST_PAGE_SIZE, '\5'},
80 : {0, 0}
81 : };
82 : static struct file_desc simple_pin_no_lock_test_file3[]=
83 : {
84 : { TEST_PAGE_SIZE, '\6'},
85 : {0, 0}
86 : };
87 : static struct file_desc simple_delete_forget_test_file[]=
88 : {
89 : { TEST_PAGE_SIZE, '\1'},
90 : {0, 0}
91 : };
92 : static struct file_desc simple_delete_flush_test_file[]=
93 : {
94 : { TEST_PAGE_SIZE, '\2'},
95 : {0, 0}
96 : };
97 :
98 :
99 : /**
100 : @brief Dummy pagecache callback.
101 : */
102 :
103 : static my_bool
104 : dummy_callback(uchar *page __attribute__((unused)),
105 : pgcache_page_no_t page_no __attribute__((unused)),
106 : uchar* data_ptr __attribute__((unused)))
107 134170 : {
108 134170 : return 0;
109 : }
110 :
111 :
112 : /**
113 : @brief Dummy pagecache callback.
114 : */
115 :
116 : static void
117 : dummy_fail_callback(uchar* data_ptr __attribute__((unused)))
118 0 : {
119 : return;
120 : }
121 :
122 :
123 : /*
124 : Recreate and reopen a file for test
125 :
126 : SYNOPSIS
127 : reset_file()
128 : file File to reset
129 : file_name Path (and name) of file which should be reset
130 : */
131 :
132 : void reset_file(PAGECACHE_FILE *file, const char *file_name)
133 14 : {
134 14 : flush_pagecache_blocks(&pagecache, file, FLUSH_RELEASE);
135 14 : if (my_close(file->file, MYF(MY_WME)))
136 0 : exit(1);
137 14 : my_delete(file_name, MYF(MY_WME));
138 14 : if ((file->file= my_open(file_name,
139 : O_CREAT | O_TRUNC | O_RDWR, MYF(0))) == -1)
140 : {
141 0 : diag("Got error during %s creation from open() (errno: %d)\n",
142 : file_name, my_errno);
143 0 : exit(1);
144 : }
145 : }
146 :
147 : /*
148 : Write then read page, check file on disk
149 : */
150 :
151 : int simple_read_write_test()
152 2 : {
153 2 : unsigned char *buffw= malloc(TEST_PAGE_SIZE);
154 2 : unsigned char *buffr= malloc(TEST_PAGE_SIZE);
155 : int res;
156 2 : DBUG_ENTER("simple_read_write_test");
157 2 : bfill(buffw, TEST_PAGE_SIZE, '\1');
158 2 : pagecache_write(&pagecache, &file1, 0, 3, buffw,
159 : PAGECACHE_PLAIN_PAGE,
160 : PAGECACHE_LOCK_LEFT_UNLOCKED,
161 : PAGECACHE_PIN_LEFT_UNPINNED,
162 : PAGECACHE_WRITE_DELAY,
163 : 0, LSN_IMPOSSIBLE);
164 2 : pagecache_read(&pagecache, &file1, 0, 3, buffr,
165 : PAGECACHE_PLAIN_PAGE,
166 : PAGECACHE_LOCK_LEFT_UNLOCKED,
167 : 0);
168 2 : ok((res= test(memcmp(buffr, buffw, TEST_PAGE_SIZE) == 0)),
169 : "Simple write-read page ");
170 2 : if (flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE))
171 : {
172 0 : diag("Got error during flushing pagecache\n");
173 0 : exit(1);
174 : }
175 2 : ok((res&= test(test_file(file1, file1_name, TEST_PAGE_SIZE, TEST_PAGE_SIZE,
176 : simple_read_write_test_file))),
177 : "Simple write-read page file");
178 2 : if (res)
179 2 : reset_file(&file1, file1_name);
180 2 : free(buffw);
181 2 : free(buffr);
182 2 : DBUG_RETURN(res);
183 : }
184 :
185 :
186 : /*
187 : Prepare page, then read (and lock), change (write new value and unlock),
188 : then check the page in the cache and on the disk
189 : */
190 : int simple_read_change_write_read_test()
191 2 : {
192 2 : unsigned char *buffw= malloc(TEST_PAGE_SIZE);
193 2 : unsigned char *buffr= malloc(TEST_PAGE_SIZE);
194 : int res, res2;
195 2 : DBUG_ENTER("simple_read_change_write_read_test");
196 :
197 : /* prepare the file */
198 2 : bfill(buffw, TEST_PAGE_SIZE, '\1');
199 2 : pagecache_write(&pagecache, &file1, 0, 3, buffw,
200 : PAGECACHE_PLAIN_PAGE,
201 : PAGECACHE_LOCK_LEFT_UNLOCKED,
202 : PAGECACHE_PIN_LEFT_UNPINNED,
203 : PAGECACHE_WRITE_DELAY,
204 : 0, LSN_IMPOSSIBLE);
205 2 : if (flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE))
206 : {
207 0 : diag("Got error during flushing pagecache\n");
208 0 : exit(1);
209 : }
210 : /* test */
211 2 : pagecache_read(&pagecache, &file1, 0, 3, buffw,
212 : PAGECACHE_PLAIN_PAGE,
213 : PAGECACHE_LOCK_WRITE,
214 : 0);
215 2 : bfill(buffw, TEST_PAGE_SIZE/2, '\65');
216 2 : pagecache_write(&pagecache, &file1, 0, 3, buffw,
217 : PAGECACHE_PLAIN_PAGE,
218 : PAGECACHE_LOCK_WRITE_UNLOCK,
219 : PAGECACHE_UNPIN,
220 : PAGECACHE_WRITE_DELAY,
221 : 0, LSN_IMPOSSIBLE);
222 :
223 2 : pagecache_read(&pagecache, &file1, 0, 3, buffr,
224 : PAGECACHE_PLAIN_PAGE,
225 : PAGECACHE_LOCK_LEFT_UNLOCKED,
226 : 0);
227 2 : ok((res= test(memcmp(buffr, buffw, TEST_PAGE_SIZE) == 0)),
228 : "Simple read-change-write-read page ");
229 2 : DBUG_ASSERT(pagecache.blocks_changed == 1);
230 2 : if (flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE))
231 : {
232 0 : diag("Got error during flushing pagecache\n");
233 0 : exit(1);
234 : }
235 2 : DBUG_ASSERT(pagecache.blocks_changed == 0);
236 2 : ok((res2= test(test_file(file1, file1_name, TEST_PAGE_SIZE, TEST_PAGE_SIZE,
237 : simple_read_change_write_read_test_file))),
238 : "Simple read-change-write-read page file");
239 2 : if (res && res2)
240 2 : reset_file(&file1, file1_name);
241 2 : free(buffw);
242 2 : free(buffr);
243 2 : DBUG_RETURN(res && res2);
244 : }
245 :
246 :
247 : /*
248 : Prepare page, read page 0 (and pin) then write page 1 and page 0.
249 : Flush the file (shold flush only page 1 and return 1 (page 0 is
250 : still pinned).
251 : Check file on the disk.
252 : Unpin and flush.
253 : Check file on the disk.
254 : */
255 : int simple_pin_test()
256 2 : {
257 2 : unsigned char *buffw= malloc(TEST_PAGE_SIZE);
258 : int res;
259 2 : DBUG_ENTER("simple_pin_test");
260 : /* prepare the file */
261 2 : bfill(buffw, TEST_PAGE_SIZE, '\1');
262 2 : pagecache_write(&pagecache, &file1, 0, 3, buffw,
263 : PAGECACHE_PLAIN_PAGE,
264 : PAGECACHE_LOCK_LEFT_UNLOCKED,
265 : PAGECACHE_PIN_LEFT_UNPINNED,
266 : PAGECACHE_WRITE_DELAY,
267 : 0, LSN_IMPOSSIBLE);
268 : /* test */
269 2 : if (flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE))
270 : {
271 0 : diag("Got error during flushing pagecache\n");
272 0 : exit(1);
273 : }
274 2 : pagecache_read(&pagecache, &file1, 0, 3, buffw,
275 : PAGECACHE_PLAIN_PAGE,
276 : PAGECACHE_LOCK_WRITE,
277 : 0);
278 2 : pagecache_write(&pagecache, &file1, 1, 3, buffw,
279 : PAGECACHE_PLAIN_PAGE,
280 : PAGECACHE_LOCK_LEFT_UNLOCKED,
281 : PAGECACHE_PIN_LEFT_UNPINNED,
282 : PAGECACHE_WRITE_DELAY,
283 : 0, LSN_IMPOSSIBLE);
284 2 : bfill(buffw + TEST_PAGE_SIZE/2, TEST_PAGE_SIZE/2, ((unsigned char) 129));
285 2 : pagecache_write(&pagecache, &file1, 0, 3, buffw,
286 : PAGECACHE_PLAIN_PAGE,
287 : PAGECACHE_LOCK_WRITE_TO_READ,
288 : PAGECACHE_PIN_LEFT_PINNED,
289 : PAGECACHE_WRITE_DELAY,
290 : 0, LSN_IMPOSSIBLE);
291 : /*
292 : We have to get error because one page of the file is pinned,
293 : other page should be flushed
294 : */
295 2 : if (!flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE))
296 : {
297 0 : diag("Did not get error in flush_pagecache_blocks\n");
298 0 : res= 0;
299 0 : goto err;
300 : }
301 2 : ok((res= test(test_file(file1, file1_name, TEST_PAGE_SIZE*2, TEST_PAGE_SIZE*2,
302 : simple_pin_test_file1))),
303 : "Simple pin page file with pin");
304 2 : pagecache_unlock(&pagecache,
305 : &file1,
306 : 0,
307 : PAGECACHE_LOCK_READ_UNLOCK,
308 : PAGECACHE_UNPIN,
309 : 0, 0, 0);
310 2 : if (flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE))
311 : {
312 0 : diag("Got error in flush_pagecache_blocks\n");
313 0 : res= 0;
314 0 : goto err;
315 : }
316 2 : ok((res&= test(test_file(file1, file1_name, TEST_PAGE_SIZE*2, TEST_PAGE_SIZE,
317 : simple_pin_test_file2))),
318 : "Simple pin page result file");
319 2 : if (res)
320 2 : reset_file(&file1, file1_name);
321 2 : err:
322 2 : free(buffw);
323 2 : DBUG_RETURN(res);
324 : }
325 :
326 : /*
327 : Checks pins without lock.
328 : */
329 : int simple_pin_no_lock_test()
330 2 : {
331 2 : unsigned char *buffw= malloc(TEST_PAGE_SIZE);
332 : PAGECACHE_BLOCK_LINK *link;
333 : int res;
334 2 : DBUG_ENTER("simple_pin_no_lock_test");
335 : /* prepare the file */
336 2 : bfill(buffw, TEST_PAGE_SIZE, '\4');
337 2 : pagecache_write(&pagecache, &file1, 0, 3, buffw,
338 : PAGECACHE_PLAIN_PAGE,
339 : PAGECACHE_LOCK_LEFT_UNLOCKED,
340 : PAGECACHE_PIN_LEFT_UNPINNED,
341 : PAGECACHE_WRITE_DELAY,
342 : 0, LSN_IMPOSSIBLE);
343 : /* test */
344 2 : if (flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE))
345 : {
346 0 : diag("Got error during flushing pagecache 2\n");
347 0 : exit(1);
348 : }
349 2 : bfill(buffw, TEST_PAGE_SIZE, '\5');
350 2 : pagecache_write(&pagecache, &file1, 0, 3, buffw,
351 : PAGECACHE_PLAIN_PAGE,
352 : PAGECACHE_LOCK_LEFT_UNLOCKED,
353 : PAGECACHE_PIN,
354 : PAGECACHE_WRITE_DELAY,
355 : 0, LSN_IMPOSSIBLE);
356 : /*
357 : We have to get error because one page of the file is pinned,
358 : other page should be flushed
359 : */
360 2 : if (!flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE))
361 : {
362 0 : diag("Did not get error in flush_pagecache_blocks 2\n");
363 0 : res= 0;
364 0 : goto err;
365 : }
366 2 : ok((res= test(test_file(file1, file1_name, TEST_PAGE_SIZE, TEST_PAGE_SIZE,
367 : simple_pin_no_lock_test_file1))),
368 : "Simple pin (no lock) page file with pin 2");
369 2 : pagecache_unlock(&pagecache,
370 : &file1,
371 : 0,
372 : PAGECACHE_LOCK_LEFT_UNLOCKED,
373 : PAGECACHE_UNPIN,
374 : 0, 0, 0);
375 2 : if (flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE))
376 : {
377 0 : diag("Got error in flush_pagecache_blocks 2\n");
378 0 : res= 0;
379 0 : goto err;
380 : }
381 2 : ok((res&= test(test_file(file1, file1_name, TEST_PAGE_SIZE, TEST_PAGE_SIZE,
382 : simple_pin_no_lock_test_file2))),
383 : "Simple pin (no lock) page result file 2");
384 :
385 2 : bfill(buffw, TEST_PAGE_SIZE, '\6');
386 2 : pagecache_write(&pagecache, &file1, 0, 3, buffw,
387 : PAGECACHE_PLAIN_PAGE,
388 : PAGECACHE_LOCK_WRITE,
389 : PAGECACHE_PIN,
390 : PAGECACHE_WRITE_DELAY,
391 : &link, LSN_IMPOSSIBLE);
392 2 : pagecache_unlock_by_link(&pagecache, link,
393 : PAGECACHE_LOCK_WRITE_UNLOCK,
394 : PAGECACHE_PIN_LEFT_PINNED, 0, 0, 1, FALSE);
395 2 : if (!flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE))
396 : {
397 0 : diag("Did not get error in flush_pagecache_blocks 3\n");
398 0 : res= 0;
399 0 : goto err;
400 : }
401 2 : ok((res= test(test_file(file1, file1_name, TEST_PAGE_SIZE, TEST_PAGE_SIZE,
402 : simple_pin_no_lock_test_file2))),
403 : "Simple pin (no lock) page file with pin 3");
404 2 : pagecache_unpin_by_link(&pagecache, link, 0);
405 2 : if (flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE))
406 : {
407 0 : diag("Got error in flush_pagecache_blocks 3\n");
408 0 : res= 0;
409 0 : goto err;
410 : }
411 2 : ok((res&= test(test_file(file1, file1_name, TEST_PAGE_SIZE, TEST_PAGE_SIZE,
412 : simple_pin_no_lock_test_file3))),
413 : "Simple pin (no lock) page result file 3");
414 2 : if (res)
415 2 : reset_file(&file1, file1_name);
416 2 : err:
417 2 : free(buffw);
418 2 : DBUG_RETURN(res);
419 : }
420 : /*
421 : Prepare page, write new value, then delete page from cache without flush,
422 : on the disk should be page with old content written during preparation
423 : */
424 :
425 : int simple_delete_forget_test()
426 2 : {
427 2 : unsigned char *buffw= malloc(TEST_PAGE_SIZE);
428 2 : unsigned char *buffr= malloc(TEST_PAGE_SIZE);
429 : int res;
430 2 : DBUG_ENTER("simple_delete_forget_test");
431 : /* prepare the file */
432 2 : bfill(buffw, TEST_PAGE_SIZE, '\1');
433 2 : pagecache_write(&pagecache, &file1, 0, 3, buffw,
434 : PAGECACHE_PLAIN_PAGE,
435 : PAGECACHE_LOCK_LEFT_UNLOCKED,
436 : PAGECACHE_PIN_LEFT_UNPINNED,
437 : PAGECACHE_WRITE_DELAY,
438 : 0, LSN_IMPOSSIBLE);
439 2 : flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE);
440 : /* test */
441 2 : bfill(buffw, TEST_PAGE_SIZE, '\2');
442 2 : pagecache_write(&pagecache, &file1, 0, 3, buffw,
443 : PAGECACHE_PLAIN_PAGE,
444 : PAGECACHE_LOCK_LEFT_UNLOCKED,
445 : PAGECACHE_PIN_LEFT_UNPINNED,
446 : PAGECACHE_WRITE_DELAY,
447 : 0, LSN_IMPOSSIBLE);
448 2 : pagecache_delete(&pagecache, &file1, 0,
449 : PAGECACHE_LOCK_WRITE, 0);
450 2 : flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE);
451 2 : ok((res= test(test_file(file1, file1_name, TEST_PAGE_SIZE, TEST_PAGE_SIZE,
452 : simple_delete_forget_test_file))),
453 : "Simple delete-forget page file");
454 2 : if (res)
455 2 : reset_file(&file1, file1_name);
456 2 : free(buffw);
457 2 : free(buffr);
458 2 : DBUG_RETURN(res);
459 : }
460 :
461 : /*
462 : Prepare page with locking, write new content to the page,
463 : delete page with flush and on existing lock,
464 : check that page on disk contain new value.
465 : */
466 :
467 : int simple_delete_flush_test()
468 2 : {
469 2 : unsigned char *buffw= malloc(TEST_PAGE_SIZE);
470 2 : unsigned char *buffr= malloc(TEST_PAGE_SIZE);
471 : PAGECACHE_BLOCK_LINK *link;
472 : int res;
473 2 : DBUG_ENTER("simple_delete_flush_test");
474 : /* prepare the file */
475 2 : bfill(buffw, TEST_PAGE_SIZE, '\1');
476 2 : pagecache_write(&pagecache, &file1, 0, 3, buffw,
477 : PAGECACHE_PLAIN_PAGE,
478 : PAGECACHE_LOCK_WRITE,
479 : PAGECACHE_PIN,
480 : PAGECACHE_WRITE_DELAY,
481 : &link, LSN_IMPOSSIBLE);
482 2 : flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE);
483 : /* test */
484 2 : bfill(buffw, TEST_PAGE_SIZE, '\2');
485 2 : pagecache_write(&pagecache, &file1, 0, 3, buffw,
486 : PAGECACHE_PLAIN_PAGE,
487 : PAGECACHE_LOCK_LEFT_WRITELOCKED,
488 : PAGECACHE_PIN_LEFT_PINNED,
489 : PAGECACHE_WRITE_DELAY,
490 : 0, LSN_IMPOSSIBLE);
491 2 : if (pagecache_delete_by_link(&pagecache, link,
492 : PAGECACHE_LOCK_LEFT_WRITELOCKED, 1))
493 : {
494 0 : diag("simple_delete_flush_test: error during delete");
495 0 : exit(1);
496 : }
497 2 : flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE);
498 2 : ok((res= test(test_file(file1, file1_name, TEST_PAGE_SIZE, TEST_PAGE_SIZE,
499 : simple_delete_flush_test_file))),
500 : "Simple delete flush (link) page file");
501 2 : if (res)
502 2 : reset_file(&file1, file1_name);
503 2 : free(buffw);
504 2 : free(buffr);
505 2 : DBUG_RETURN(res);
506 : }
507 :
508 :
509 : /*
510 : write then read file bigger then cache
511 : */
512 :
513 : int simple_big_test()
514 2 : {
515 2 : unsigned char *buffw= (unsigned char *) my_malloc(TEST_PAGE_SIZE, MYF(MY_WME));
516 2 : unsigned char *buffr= (unsigned char *) my_malloc(TEST_PAGE_SIZE, MYF(MY_WME));
517 : struct file_desc *desc= ((struct file_desc *)
518 2 : my_malloc((PCACHE_SIZE/(TEST_PAGE_SIZE/2) + 1) *
519 : sizeof(struct file_desc), MYF(MY_WME)));
520 : int res, i;
521 2 : DBUG_ENTER("simple_big_test");
522 :
523 : /* prepare the file twice larger then cache */
524 40962 : for (i= 0; i < PCACHE_SIZE/(TEST_PAGE_SIZE/2); i++)
525 : {
526 40960 : bfill(buffw, TEST_PAGE_SIZE, (unsigned char) (i & 0xff));
527 40960 : desc[i].length= TEST_PAGE_SIZE;
528 40960 : desc[i].content= (i & 0xff);
529 40960 : pagecache_write(&pagecache, &file1, i, 3, buffw,
530 : PAGECACHE_PLAIN_PAGE,
531 : PAGECACHE_LOCK_LEFT_UNLOCKED,
532 : PAGECACHE_PIN_LEFT_UNPINNED,
533 : PAGECACHE_WRITE_DELAY,
534 : 0, LSN_IMPOSSIBLE);
535 : }
536 2 : desc[i].length= 0;
537 2 : desc[i].content= '\0';
538 2 : ok(1, "Simple big file write");
539 : /* check written pages sequentally read */
540 40962 : for (i= 0; i < PCACHE_SIZE/(TEST_PAGE_SIZE/2); i++)
541 : {
542 : int j;
543 40960 : pagecache_read(&pagecache, &file1, i, 3, buffr,
544 : PAGECACHE_PLAIN_PAGE,
545 : PAGECACHE_LOCK_LEFT_UNLOCKED,
546 : 0);
547 188784640 : for(j= 0; j < TEST_PAGE_SIZE; j++)
548 : {
549 188743680 : if (buffr[j] != (i & 0xff))
550 : {
551 0 : diag("simple_big_test seq: page %u byte %u mismatch\n", i, j);
552 0 : res= 0;
553 0 : goto err;
554 : }
555 : }
556 : }
557 2 : ok(1, "Simple big file sequential read");
558 : /* chack random reads */
559 20482 : for (i= 0; i < PCACHE_SIZE/(TEST_PAGE_SIZE); i++)
560 : {
561 : int j, page;
562 20480 : page= rand() % (PCACHE_SIZE/(TEST_PAGE_SIZE/2));
563 20480 : pagecache_read(&pagecache, &file1, page, 3, buffr,
564 : PAGECACHE_PLAIN_PAGE,
565 : PAGECACHE_LOCK_LEFT_UNLOCKED,
566 : 0);
567 94392320 : for(j= 0; j < TEST_PAGE_SIZE; j++)
568 : {
569 94371840 : if (buffr[j] != (page & 0xff))
570 : {
571 0 : diag("simple_big_test rnd: page %u byte %u mismatch\n", page, j);
572 0 : res= 0;
573 0 : goto err;
574 : }
575 : }
576 : }
577 2 : ok(1, "Simple big file random read");
578 2 : flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE);
579 :
580 2 : ok((res= test(test_file(file1, file1_name, PCACHE_SIZE*2, TEST_PAGE_SIZE,
581 : desc))),
582 : "Simple big file");
583 2 : if (res)
584 2 : reset_file(&file1, file1_name);
585 :
586 2 : err:
587 2 : my_free(buffw, 0);
588 2 : my_free(buffr, 0);
589 2 : my_free(desc, 0);
590 2 : DBUG_RETURN(res);
591 : }
592 :
593 :
594 : /*
595 : Thread function
596 : */
597 :
598 : static void *test_thread(void *arg)
599 2 : {
600 : #ifndef DBUG_OFF
601 2 : int param= *((int*) arg);
602 : #endif
603 :
604 2 : my_thread_init();
605 : {
606 2 : DBUG_ENTER("test_thread");
607 2 : DBUG_PRINT("enter", ("param: %d", param));
608 :
609 2 : if (!simple_read_write_test() ||
610 : !simple_read_change_write_read_test() ||
611 : !simple_pin_test() ||
612 : !simple_pin_no_lock_test() ||
613 : !simple_delete_forget_test() ||
614 : !simple_delete_flush_test())
615 0 : exit(1);
616 :
617 0 : SKIP_BIG_TESTS(4)
618 : {
619 2 : if (!simple_big_test())
620 0 : exit(1);
621 : }
622 :
623 2 : DBUG_PRINT("info", ("Thread %s ended\n", my_thread_name()));
624 2 : pthread_mutex_lock(&LOCK_thread_count);
625 2 : thread_count--;
626 2 : VOID(pthread_cond_signal(&COND_thread_count)); /* Tell main we are ready */
627 2 : pthread_mutex_unlock(&LOCK_thread_count);
628 2 : free((uchar*) arg);
629 2 : my_thread_end();
630 2 : DBUG_RETURN(0);
631 : }
632 : }
633 :
634 :
635 : int main(int argc __attribute__((unused)),
636 : char **argv __attribute__((unused)))
637 3 : {
638 : pthread_t tid;
639 : pthread_attr_t thr_attr;
640 : int *param, error, pagen;
641 : File tmp_file;
642 3 : MY_INIT(argv[0]);
643 :
644 : #ifndef DBUG_OFF
645 : #if defined(__WIN__)
646 : default_dbug_option= "d:t:i:O,\\test_pagecache_single.trace";
647 : #else
648 3 : default_dbug_option= "d:t:i:o,/tmp/test_pagecache_single.trace";
649 : #endif
650 3 : if (argc > 1)
651 : {
652 0 : DBUG_SET(default_dbug_option);
653 0 : DBUG_SET_INITIAL(default_dbug_option);
654 : }
655 : #endif
656 : {
657 3 : DBUG_ENTER("main");
658 3 : DBUG_PRINT("info", ("Main thread: %s\n", my_thread_name()));
659 :
660 3 : plan(16);
661 1 : SKIP_BIG_TESTS(16)
662 : {
663 :
664 2 : if ((tmp_file= my_open(file2_name, O_CREAT | O_TRUNC | O_RDWR,
665 : MYF(MY_WME))) < 0)
666 0 : exit(1);
667 :
668 2 : if ((file1.file= my_open(file1_name,
669 : O_CREAT | O_TRUNC | O_RDWR, MYF(0))) == -1)
670 : {
671 0 : fprintf(stderr, "Got error during file1 creation from open() (errno: %d)\n",
672 : errno);
673 0 : exit(1);
674 : }
675 2 : pagecache_file_init(file1, &dummy_callback, &dummy_callback,
676 : &dummy_fail_callback, &dummy_callback, NULL);
677 2 : my_close(tmp_file, MYF(0));
678 2 : my_delete(file2_name, MYF(0));
679 :
680 2 : DBUG_PRINT("info", ("file1: %d", file1.file));
681 2 : if (my_chmod(file1_name, S_IRWXU | S_IRWXG | S_IRWXO, MYF(MY_WME)))
682 0 : exit(1);
683 2 : my_pwrite(file1.file, (const uchar*)"test file", 9, 0, MYF(MY_WME));
684 :
685 2 : if ((error= pthread_cond_init(&COND_thread_count, NULL)))
686 : {
687 0 : fprintf(stderr, "Got error: %d from pthread_cond_init (errno: %d)\n",
688 : error, errno);
689 0 : exit(1);
690 : }
691 2 : if ((error= pthread_mutex_init(&LOCK_thread_count, MY_MUTEX_INIT_FAST)))
692 : {
693 0 : fprintf(stderr, "Got error: %d from pthread_cond_init (errno: %d)\n",
694 : error, errno);
695 0 : exit(1);
696 : }
697 :
698 2 : if ((error= pthread_attr_init(&thr_attr)))
699 : {
700 0 : fprintf(stderr,"Got error: %d from pthread_attr_init (errno: %d)\n",
701 : error,errno);
702 0 : exit(1);
703 : }
704 2 : if ((error= pthread_attr_setdetachstate(&thr_attr, PTHREAD_CREATE_DETACHED)))
705 : {
706 0 : fprintf(stderr,
707 : "Got error: %d from pthread_attr_setdetachstate (errno: %d)\n",
708 : error,errno);
709 0 : exit(1);
710 : }
711 :
712 : #ifdef HAVE_THR_SETCONCURRENCY
713 : VOID(thr_setconcurrency(2));
714 : #endif
715 :
716 2 : if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0,
717 : TEST_PAGE_SIZE, MYF(MY_WME))) == 0)
718 : {
719 0 : fprintf(stderr,"Got error: init_pagecache() (errno: %d)\n",
720 : errno);
721 0 : exit(1);
722 : }
723 2 : DBUG_PRINT("info", ("Page cache %d pages", pagen));
724 :
725 2 : pthread_mutex_lock(&LOCK_thread_count);
726 2 : param=(int*) malloc(sizeof(int));
727 2 : *param= 1;
728 2 : if ((error= pthread_create(&tid, &thr_attr, test_thread, (void*) param)))
729 : {
730 0 : fprintf(stderr,"Got error: %d from pthread_create (errno: %d)\n",
731 : error,errno);
732 0 : exit(1);
733 : }
734 2 : thread_count++;
735 2 : DBUG_PRINT("info", ("Thread started"));
736 2 : pthread_mutex_unlock(&LOCK_thread_count);
737 :
738 2 : pthread_attr_destroy(&thr_attr);
739 :
740 2 : pthread_mutex_lock(&LOCK_thread_count);
741 6 : while (thread_count)
742 : {
743 2 : if ((error= pthread_cond_wait(&COND_thread_count,&LOCK_thread_count)))
744 0 : fprintf(stderr,"Got error: %d from pthread_cond_wait\n",error);
745 : }
746 2 : pthread_mutex_unlock(&LOCK_thread_count);
747 2 : DBUG_PRINT("info", ("thread ended"));
748 :
749 2 : end_pagecache(&pagecache, 1);
750 2 : DBUG_PRINT("info", ("Page cache ended"));
751 :
752 2 : if (my_close(file1.file, MYF(MY_WME)))
753 0 : exit(1);
754 :
755 2 : my_delete(file1_name, MYF(0));
756 :
757 : } /* SKIP_BIG_TESTS */
758 3 : DBUG_PRINT("info", ("file1 (%d) closed", file1.file));
759 3 : DBUG_PRINT("info", ("Program end"));
760 :
761 3 : my_end(0);
762 :
763 : }
764 3 : return exit_status();
765 : }
|