LTP GCOV extension - code coverage report
Current view: directory - storage/maria/unittest - ma_pagecache_rwconsist2.c
Test: maria-unit-test.html
Date: 2009-03-04 Instrumented lines: 135
Code covered: 7.4 % Executed lines: 10

       1                 : /* Copyright (C) 2006-2008 MySQL AB, 2008 Sun Microsystems, Inc.
       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                 : /**
      18                 :   @file this unit tests consistence of  long block writing under write lock
      19                 :   and simultaneous reading of this block with read request without read lock
      20                 :   requirement.
      21                 : */
      22                 : 
      23                 : /*
      24                 :   TODO: use pthread_join instead of wait_for_thread_count_to_be_zero, like in
      25                 :   my_atomic-t.c (see BUG#22320).
      26                 : */
      27                 : 
      28                 : #include <tap.h>
      29                 : #include <my_sys.h>
      30                 : #include <m_string.h>
      31                 : #include "test_file.h"
      32                 : #include <tap.h>
      33                 : 
      34                 : #define PCACHE_SIZE (TEST_PAGE_SIZE*1024*8)
      35                 : 
      36                 : #ifndef DBUG_OFF
      37                 : static const char* default_dbug_option;
      38                 : #endif
      39                 : 
      40                 : 
      41                 : #define SLEEP my_sleep(5)
      42                 : 
      43                 : static char *file1_name= (char*)"page_cache_test_file_1";
      44                 : static PAGECACHE_FILE file1;
      45                 : static pthread_cond_t COND_thread_count;
      46                 : static pthread_mutex_t LOCK_thread_count;
      47                 : static uint thread_count= 0;
      48                 : static PAGECACHE pagecache;
      49                 : 
      50                 : static uint number_of_readers= 5;
      51                 : static uint number_of_writers= 5;
      52                 : static uint number_of_read_tests= 20000;
      53                 : static uint number_of_write_tests= 1000;
      54                 : static uint report_divisor= 50;
      55                 : 
      56                 : /**
      57                 :   @brief Dummy pagecache callback.
      58                 : */
      59                 : 
      60                 : static my_bool
      61                 : dummy_callback(uchar *page __attribute__((unused)),
      62                 :                pgcache_page_no_t page_no __attribute__((unused)),
      63                 :                uchar* data_ptr __attribute__((unused)))
      64               0 : {
      65               0 :   return 0;
      66                 : }
      67                 : 
      68                 : 
      69                 : /**
      70                 :   @brief Dummy pagecache callback.
      71                 : */
      72                 : 
      73                 : static void
      74                 : dummy_fail_callback(uchar* data_ptr __attribute__((unused)))
      75               0 : {
      76                 :   return;
      77                 : }
      78                 : 
      79                 : 
      80                 : /**
      81                 :   @brief Checks page consistency
      82                 : 
      83                 :   @param buff            pointer to the page content
      84                 :   @param task            task ID
      85                 : */
      86                 : void check_page(uchar *buff, int task)
      87               0 : {
      88                 :   uint i;
      89               0 :   DBUG_ENTER("check_page");
      90                 : 
      91               0 :   for (i= 1; i < TEST_PAGE_SIZE; i++)
      92                 :   {
      93               0 :     if (buff[0] != buff[i])
      94               0 :       goto err;
      95                 :   }
      96               0 :   DBUG_VOID_RETURN;
      97               0 : err:
      98               0 :   diag("Task %d char #%u '%u' != '%u'", task, i, (uint) buff[0],
      99                 :        (uint) buff[i]);
     100               0 :   DBUG_PRINT("err", ("try to flush"));
     101               0 :   exit(1);
     102                 : }
     103                 : 
     104                 : 
     105                 : 
     106                 : void reader(int num)
     107               0 : {
     108                 :   unsigned char buff[TEST_PAGE_SIZE];
     109                 :   uint i;
     110                 : 
     111               0 :   for (i= 0; i < number_of_read_tests; i++)
     112                 :   {
     113               0 :     if (i % report_divisor == 0)
     114               0 :       diag("Reader %d - %u", num, i);
     115               0 :     pagecache_read(&pagecache, &file1, 0, 3, buff,
     116                 :                    PAGECACHE_PLAIN_PAGE,
     117                 :                    PAGECACHE_LOCK_LEFT_UNLOCKED,
     118                 :                    NULL);
     119               0 :     check_page(buff, num);
     120                 :   }
     121                 : }
     122                 : 
     123                 : 
     124                 : void writer(int num)
     125               0 : {
     126                 :   uint i;
     127                 :   uchar *buff;
     128                 :   PAGECACHE_BLOCK_LINK *link;
     129                 : 
     130               0 :   for (i= 0; i < number_of_write_tests; i++)
     131                 :   {
     132               0 :     uchar c= (uchar) rand() % 256;
     133                 : 
     134               0 :     if (i % report_divisor == 0)
     135               0 :       diag("Writer %d - %u", num, i);
     136               0 :     buff= pagecache_read(&pagecache, &file1, 0, 3, NULL,
     137                 :                          PAGECACHE_PLAIN_PAGE,
     138                 :                          PAGECACHE_LOCK_WRITE,
     139                 :                          &link);
     140                 : 
     141               0 :     check_page(buff, num);
     142               0 :     bfill(buff, TEST_PAGE_SIZE / 2, c);
     143               0 :     SLEEP;
     144               0 :     bfill(buff + TEST_PAGE_SIZE/2, TEST_PAGE_SIZE / 2, c);
     145               0 :     check_page(buff, num);
     146               0 :     pagecache_unlock_by_link(&pagecache, link,
     147                 :                              PAGECACHE_LOCK_WRITE_UNLOCK,
     148                 :                              PAGECACHE_UNPIN, 0, 0, 1, FALSE);
     149               0 :     SLEEP;
     150                 :   }
     151                 : }
     152                 : 
     153                 : 
     154                 : static void *test_thread_reader(void *arg)
     155               0 : {
     156               0 :   int param=*((int*) arg);
     157               0 :   my_thread_init();
     158                 :   {
     159               0 :     DBUG_ENTER("test_reader");
     160                 : 
     161               0 :     DBUG_PRINT("enter", ("param: %d", param));
     162                 : 
     163               0 :     reader(param);
     164                 : 
     165               0 :     DBUG_PRINT("info", ("Thread %s ended", my_thread_name()));
     166               0 :     pthread_mutex_lock(&LOCK_thread_count);
     167               0 :     ok(1, "reader%d: done", param);
     168               0 :     thread_count--;
     169               0 :     VOID(pthread_cond_signal(&COND_thread_count)); /* Tell main we are ready */
     170               0 :     pthread_mutex_unlock(&LOCK_thread_count);
     171               0 :     free((uchar*) arg);
     172               0 :     my_thread_end();
     173                 :   }
     174               0 :   return 0;
     175                 : }
     176                 : 
     177                 : 
     178                 : static void *test_thread_writer(void *arg)
     179               0 : {
     180               0 :   int param=*((int*) arg);
     181               0 :   my_thread_init();
     182                 :   {
     183               0 :     DBUG_ENTER("test_writer");
     184                 : 
     185               0 :     writer(param);
     186                 : 
     187               0 :     DBUG_PRINT("info", ("Thread %s ended", my_thread_name()));
     188               0 :     pthread_mutex_lock(&LOCK_thread_count);
     189               0 :     ok(1, "writer%d: done", param);
     190               0 :     thread_count--;
     191               0 :     VOID(pthread_cond_signal(&COND_thread_count)); /* Tell main we are ready */
     192               0 :     pthread_mutex_unlock(&LOCK_thread_count);
     193               0 :     free((uchar*) arg);
     194               0 :     my_thread_end();
     195                 :   }
     196               0 :   return 0;
     197                 : }
     198                 : 
     199                 : 
     200                 : int main(int argc __attribute__((unused)),
     201                 :          char **argv __attribute__((unused)))
     202               1 : {
     203                 :   pthread_t tid;
     204                 :   pthread_attr_t thr_attr;
     205                 :   int *param, error, pagen;
     206                 : 
     207               1 :   MY_INIT(argv[0]);
     208                 : 
     209                 : #ifndef DBUG_OFF
     210                 : #if defined(__WIN__)
     211                 :   default_dbug_option= "d:t:i:O,\\test_pagecache_consist.trace";
     212                 : #else
     213               1 :   default_dbug_option= "d:t:i:O,/tmp/test_pagecache_consist.trace";
     214                 : #endif
     215               1 :   if (argc > 1)
     216                 :   {
     217               0 :     DBUG_SET(default_dbug_option);
     218               0 :     DBUG_SET_INITIAL(default_dbug_option);
     219                 :   }
     220                 : #endif
     221                 : 
     222                 :   {
     223               1 :   DBUG_ENTER("main");
     224               1 :   DBUG_PRINT("info", ("Main thread: %s\n", my_thread_name()));
     225               1 :   plan(number_of_writers + number_of_readers);
     226               1 :   SKIP_BIG_TESTS(number_of_writers + number_of_readers)
     227                 :   {
     228                 : 
     229               0 :   if ((file1.file= my_open(file1_name,
     230                 :                            O_CREAT | O_TRUNC | O_RDWR, MYF(0))) == -1)
     231                 :   {
     232               0 :     diag( "Got error during file1 creation from open() (errno: %d)\n",
     233                 :             errno);
     234               0 :     exit(1);
     235                 :   }
     236               0 :   pagecache_file_init(file1, &dummy_callback, &dummy_callback,
     237                 :                       &dummy_fail_callback, &dummy_callback, NULL);
     238               0 :   DBUG_PRINT("info", ("file1: %d", file1.file));
     239               0 :   if (my_chmod(file1_name, S_IRWXU | S_IRWXG | S_IRWXO, MYF(MY_WME)))
     240               0 :     exit(1);
     241               0 :   my_pwrite(file1.file, (const uchar*) "test file", 9, 0, MYF(0));
     242                 : 
     243               0 :   if ((error= pthread_cond_init(&COND_thread_count, NULL)))
     244                 :   {
     245               0 :     diag( "COND_thread_count: %d from pthread_cond_init (errno: %d)\n",
     246                 :             error, errno);
     247               0 :     exit(1);
     248                 :   }
     249               0 :   if ((error= pthread_mutex_init(&LOCK_thread_count, MY_MUTEX_INIT_FAST)))
     250                 :   {
     251               0 :     diag( "LOCK_thread_count: %d from pthread_cond_init (errno: %d)\n",
     252                 :             error, errno);
     253               0 :     exit(1);
     254                 :   }
     255                 : 
     256               0 :   if ((error= pthread_attr_init(&thr_attr)))
     257                 :   {
     258               0 :     diag("Got error: %d from pthread_attr_init (errno: %d)\n",
     259                 :             error,errno);
     260               0 :     exit(1);
     261                 :   }
     262               0 :   if ((error= pthread_attr_setdetachstate(&thr_attr, PTHREAD_CREATE_DETACHED)))
     263                 :   {
     264               0 :     diag(
     265                 :             "Got error: %d from pthread_attr_setdetachstate (errno: %d)\n",
     266                 :             error,errno);
     267               0 :     exit(1);
     268                 :   }
     269                 : 
     270                 : #ifdef HAVE_THR_SETCONCURRENCY
     271                 :   VOID(thr_setconcurrency(2));
     272                 : #endif
     273                 : 
     274               0 :   if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0,
     275                 :                              TEST_PAGE_SIZE, 0)) == 0)
     276                 :   {
     277               0 :     diag("Got error: init_pagecache() (errno: %d)\n",
     278                 :             errno);
     279               0 :     exit(1);
     280                 :   }
     281               0 :   DBUG_PRINT("info", ("Page cache %d pages", pagen));
     282                 :   {
     283               0 :     unsigned char *buffr= malloc(TEST_PAGE_SIZE);
     284               0 :     memset(buffr, '\0', TEST_PAGE_SIZE);
     285               0 :     pagecache_write(&pagecache, &file1, 0, 3, buffr,
     286                 :                     PAGECACHE_PLAIN_PAGE,
     287                 :                     PAGECACHE_LOCK_LEFT_UNLOCKED,
     288                 :                     PAGECACHE_PIN_LEFT_UNPINNED,
     289                 :                     PAGECACHE_WRITE_DELAY,
     290                 :                     0, LSN_IMPOSSIBLE);
     291                 :   }
     292               0 :   pthread_mutex_lock(&LOCK_thread_count);
     293                 : 
     294               0 :   while (number_of_readers != 0 || number_of_writers != 0)
     295                 :   {
     296               0 :     if (number_of_readers != 0)
     297                 :     {
     298               0 :       param=(int*) malloc(sizeof(int));
     299               0 :       *param= number_of_readers + number_of_writers;
     300               0 :       if ((error= pthread_create(&tid, &thr_attr, test_thread_reader,
     301                 :                                  (void*) param)))
     302                 :       {
     303               0 :         diag("Got error: %d from pthread_create (errno: %d)\n",
     304                 :                 error,errno);
     305               0 :         exit(1);
     306                 :       }
     307               0 :       thread_count++;
     308               0 :       number_of_readers--;
     309                 :     }
     310               0 :     if (number_of_writers != 0)
     311                 :     {
     312               0 :       param=(int*) malloc(sizeof(int));
     313               0 :       *param= number_of_writers + number_of_readers;
     314               0 :       if ((error= pthread_create(&tid, &thr_attr, test_thread_writer,
     315                 :                                  (void*) param)))
     316                 :       {
     317               0 :         diag("Got error: %d from pthread_create (errno: %d)\n",
     318                 :                 error,errno);
     319               0 :         exit(1);
     320                 :       }
     321               0 :       thread_count++;
     322               0 :       number_of_writers--;
     323                 :     }
     324                 :   }
     325               0 :   DBUG_PRINT("info", ("Thread started"));
     326               0 :   pthread_mutex_unlock(&LOCK_thread_count);
     327                 : 
     328               0 :   pthread_attr_destroy(&thr_attr);
     329                 : 
     330                 :   /* wait finishing */
     331               0 :   pthread_mutex_lock(&LOCK_thread_count);
     332               0 :   while (thread_count)
     333                 :   {
     334               0 :     if ((error= pthread_cond_wait(&COND_thread_count, &LOCK_thread_count)))
     335               0 :       diag("COND_thread_count: %d from pthread_cond_wait\n", error);
     336                 :   }
     337               0 :   pthread_mutex_unlock(&LOCK_thread_count);
     338               0 :   DBUG_PRINT("info", ("thread ended"));
     339                 : 
     340               0 :   end_pagecache(&pagecache, 1);
     341               0 :   DBUG_PRINT("info", ("Page cache ended"));
     342                 : 
     343               0 :   if (my_close(file1.file, MYF(0)) != 0)
     344                 :   {
     345               0 :     diag( "Got error during file1 closing from close() (errno: %d)\n",
     346                 :             errno);
     347               0 :     exit(1);
     348                 :   }
     349               0 :   my_delete(file1_name, MYF(0));
     350                 : 
     351               0 :   DBUG_PRINT("info", ("file1 (%d) closed", file1.file));
     352               0 :   DBUG_PRINT("info", ("Program end"));
     353                 :   } /* SKIP_BIG_TESTS */
     354               1 :   my_end(0);
     355                 : 
     356               1 :   return exit_status();
     357                 :   }
     358                 : }

Generated by: LTP GCOV extension version 1.4