home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win-source.exe / mysys / mf_reccache.c < prev    next >
C/C++ Source or Header  |  2000-08-31  |  8KB  |  291 lines

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    
  3.    This library is free software; you can redistribute it and/or
  4.    modify it under the terms of the GNU Library General Public
  5.    License as published by the Free Software Foundation; either
  6.    version 2 of the License, or (at your option) any later version.
  7.    
  8.    This library is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11.    Library General Public License for more details.
  12.    
  13.    You should have received a copy of the GNU Library General Public
  14.    License along with this library; if not, write to the Free
  15.    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  16.    MA 02111-1307, USA */
  17.  
  18. /*
  19.   This functions is to read a bunch of records in one read from a (locked?)
  20.   database for quick access when reading in postion order.
  21.   Uses asyncronic io if database is locked.
  22.   init_record_cache() is to init cache_handler.
  23.   read_cache_record() reads a record to buffert.
  24.   end_record_cache() frees cache-memory.
  25.   This is obsolite; Its only used with M-ISAM and P-ISAM.
  26.  */
  27.  
  28. #include "mysys_priv.h"
  29. #include <m_string.h>
  30. #include "my_nosys.h"
  31.  
  32. #ifdef HAVE_AIOWAIT
  33. #undef HAVE_AIOWAIT            /* Don't get new bugs in old code */
  34. #endif
  35.  
  36.     /* if cachesize == 0 then use default cachesize (from s-file) */
  37.     /* returns 0 if we have enough memory */
  38.  
  39. int init_record_cache(RECORD_CACHE *info, uint cachesize, File file,
  40.               uint reclength, enum cache_type type,
  41.               pbool use_async_io __attribute__((unused)))
  42. {
  43.   uint count;
  44.   DBUG_ENTER("init_record_cache");
  45.  
  46.   info->file=file;
  47.   if (cachesize == 0)
  48.     cachesize= my_default_record_cache_size;
  49.   for (;;)
  50.   {
  51.     if ((count=((cachesize-1)/reclength & (uint) ~1)) <= 1)
  52.     {
  53.       info->rc_length=0;            /* Set for test if cacheing */
  54.       info->rc_record_pos=MY_FILEPOS_ERROR;
  55.       DBUG_RETURN(2);                /* No nead for cacheing */
  56.     }
  57.     info->rc_length=count*reclength;
  58.     if ((info->rc_buff= (byte*) my_malloc(info->rc_length+1,MYF(0))) != 0)
  59.       break;                    /* Enough memory found */
  60.     cachesize= (uint) ((long) cachesize*3/4);    /* Try with less memory */
  61.   }
  62.   info->rc_record_pos=0L;
  63.   info->rc_seek=1;
  64.   info->rc_end= (type == READ_CACHE ? info->rc_buff :
  65.          info->rc_buff+info->rc_length);
  66.   info->rc_pos=info->rc_end;
  67.   info->read_length=info->rc_length;
  68.   info->reclength=reclength;
  69.   info->end_of_file=MY_FILEPOS_ERROR;        /* May be changed by user */
  70.   info->type=type;
  71.   info->error=info->inited=0;
  72. #ifdef HAVE_AIOWAIT
  73.   if ((info->use_async_io=(int) use_async_io))
  74.   {
  75.     info->rc_request_pos=info->rc_buff;
  76.     info->read_length/=2;
  77.     info->rc_buff2=info->rc_buff+info->read_length;
  78.   }
  79.   info->inited=info->aio_result.pending=0;
  80. #endif
  81.   DBUG_RETURN(0);
  82. } /* init_record_cache */
  83.  
  84.  
  85. #ifdef HAVE_AIOWAIT
  86. static void my_aiowait(result)
  87. my_aio_result *result;
  88. {
  89.   if (result->pending)
  90.   {
  91.     struct aio_result_t *tmp;
  92.     for (;;)
  93.     {
  94.       if ((int) (tmp=aiowait((struct timeval *) 0)) == -1)
  95.       {
  96.     if (errno == EINTR)
  97.       continue;
  98.     DBUG_PRINT("error",("No aio request, error: %d",errno));
  99.     tmp->aio_errno=errno;
  100.     result->pending=0;            /* Assume everythings is ok */
  101.     break;
  102.       }
  103.       ((my_aio_result*) tmp)->pending=0;
  104.       if ((my_aio_result*) tmp == result)
  105.     break;
  106.     }
  107.   }
  108.   return;
  109. }
  110. #endif
  111.  
  112.     /* Returns 0 if record read */
  113.  
  114. int read_cache_record(register RECORD_CACHE *info, byte *to)
  115.  
  116.                         /* Read record here */
  117. {
  118.   uint length;
  119.   long max_length;
  120.  
  121.   for ( ;; )                    /* Instead of tail-recursion */
  122.   {
  123. #ifdef MSDOS                    /* MSDOS and segments !!! */
  124.     if ((ulong) info->rc_pos+(ulong) info->reclength <= (ulong) info->rc_end)
  125. #else
  126.     if (info->rc_pos+info->reclength <= info->rc_end)
  127. #endif
  128.     {                        /* Record in cache */
  129.       memcpy(to,info->rc_pos,(size_t) info->reclength);
  130.       info->rc_pos+=info->reclength;
  131.       info->rc_record_pos+=info->reclength;
  132.       return 0;
  133.     }
  134.     if (info->rc_pos != info->rc_end)
  135.     {
  136.       info->error=0;                /* Not actual error */
  137.       return 2;                    /* End of file, chars left */
  138.     }
  139. #ifdef HAVE_AIOWAIT
  140.     if (info->inited)
  141.     {                /* wait for read block */
  142.       info->inited=0;
  143.       my_aiowait(&info->aio_result);
  144.       if (info->aio_result.aio_errno)
  145.       {
  146.     my_errno=info->aio_result.aio_errno;
  147.     return(info->aio_result.aio_errno);
  148.       }
  149.       if (! (length=info->aio_result.aio_return) || length == (uint) -1)
  150.       {
  151.     info->error=(int) length;
  152.     return(1);
  153.       }
  154.       info->rc_pos=info->rc_request_pos;
  155.       info->rc_end=info->rc_pos+length;
  156.     }
  157.     else
  158. #endif
  159.     {
  160.       max_length=(long) (info->end_of_file - info->rc_record_pos);
  161.       if (max_length > (long) info->read_length)
  162.     max_length=(long) info->read_length;
  163.       if (info->rc_seek)
  164.       {                        /* File touched, do seek */
  165.     VOID(my_seek(info->file,info->rc_record_pos,MY_SEEK_SET,MYF(0)));
  166.     info->rc_seek=0;
  167.       }
  168.       if ((length=my_read(info->file,info->rc_buff,(uint) max_length,
  169.                MYF(0))) == 0 ||
  170.       length == (uint) -1)
  171.       {
  172.     info->error= (int) length;            /* Got error */
  173.     return 1;
  174.       }
  175.       info->rc_pos=info->rc_buff;
  176.       info->rc_end=info->rc_buff+length;
  177. #ifdef HAVE_AIOWAIT
  178.       if (! info->use_async_io)
  179.     continue;
  180. #endif
  181.     }
  182.  
  183.     /* Read next block with asyncronic io */
  184. #ifdef HAVE_AIOWAIT
  185.     max_length=info->end_of_file - info->rc_record_pos - length;
  186.     if (max_length > (long) info->read_length)
  187.       max_length=(long) info->read_length;
  188.     if (info->rc_request_pos != info->rc_buff)
  189.       info->rc_request_pos=info->rc_buff;
  190.     else
  191.       info->rc_request_pos=info->rc_buff2;
  192.     info->aio_result.aio_errno=AIO_INPROGRESS;
  193.     if (!aioread(info->file,info->rc_request_pos,max_length,
  194.          info->rc_record_pos+length,MY_SEEK_SET,
  195.          &info->aio_result.result))
  196.     {                            /* Skipp async io */
  197.       info->inited=info->use_async_io=0;
  198.       info->read_length=info->rc_length;        /* Use hole buffer */
  199.     }
  200.     else
  201.       info->inited=info->aio_result.pending=1;
  202. #endif
  203.   }
  204. } /* read_cache_record */
  205.  
  206.  
  207. int end_record_cache(RECORD_CACHE *info)
  208. {
  209.   int error=0;
  210.   DBUG_ENTER("end_record_cache");
  211.   if (info->rc_buff)
  212.   {
  213.     if (info->type == WRITE_CACHE)
  214.       error=flush_write_cache(info);
  215. #ifdef HAVE_AIOWAIT
  216.     else
  217.       my_aiowait(&info->aio_result);
  218. #endif
  219.     my_free((gptr) info->rc_buff,MYF(MY_WME));
  220.     info->rc_buff=NullS;
  221.     info->rc_length=0;
  222.   }
  223.   DBUG_RETURN(error);
  224. } /* end_record_cache */
  225.  
  226.  
  227.     /* Returns != 0 if error on write */
  228.  
  229. int write_cache_record(register RECORD_CACHE *info, my_off_t filepos,
  230.                const byte *record, uint length)
  231. {
  232.   uint rest_length;
  233.   if (!info->rc_length)            /* Write with no cache */
  234.     return test(my_write(info->file,record,length,
  235.              MYF(MY_NABP | MY_WAIT_IF_FULL)));
  236.  
  237. #ifdef MSDOS                /* MSDOS and segments !!! */
  238.   if ((ulong) info->rc_pos+(ulong) length > (ulong) info->rc_end)
  239. #else
  240.   if (info->rc_pos+length > info->rc_end)
  241. #endif
  242.   {
  243.     rest_length=(uint) (info->rc_end - info->rc_pos);
  244.  
  245.     memcpy(info->rc_pos,record,(size_t) rest_length);
  246.     record+=rest_length;
  247.     length-=rest_length;
  248.     info->rc_pos+=rest_length;
  249.     info->rc_record_pos+=rest_length;
  250.     if (flush_write_cache(info))
  251.       return 1;
  252.     info->inited=1;
  253.     info->rc_pos=info->rc_buff;
  254.     info->rc_record_pos=filepos;
  255.   }
  256.   if (length > info->rc_length)
  257.   {                    /* Probably using blobs */
  258.     return test(my_write(info->file,record,length,
  259.              MYF(MY_NABP | MY_WAIT_IF_FULL)));
  260.   }
  261.   memcpy(info->rc_pos,record,(size_t) length);
  262.   info->rc_pos+=length;
  263.   info->rc_record_pos+=length;
  264.   return 0;
  265. } /* write_cache_record */
  266.  
  267.  
  268.     /* Flush write cache */
  269.  
  270. int flush_write_cache(RECORD_CACHE *info)
  271. {
  272.   uint length;
  273.   if (info->inited)
  274.   {
  275.     length=(uint) (info->rc_pos - info->rc_buff);
  276.     if (info->rc_seek)
  277.     {                        /* File touched, do seek */
  278.       VOID(my_seek(info->file,info->rc_record_pos-length,MY_SEEK_SET,MYF(0)));
  279.       info->rc_seek=0;
  280.     }
  281.     info->inited=0;
  282.     info->rc_pos=info->rc_end;
  283.     return test(my_write(info->file,info->rc_buff,length,
  284.              MYF(MY_NABP | MY_WAIT_IF_FULL)));
  285.   }
  286.   else
  287.     info->rc_seek=1;        /* We are here again after flush - seek may */
  288.                 /* be neaded */
  289.   return 0;
  290. } /* flush_write_cache */
  291.