mf_iocache2.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:8k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. /*
  14.   More functions to be used with IO_CACHE files
  15. */
  16. #define MAP_TO_USE_RAID
  17. #include "mysys_priv.h"
  18. #include <m_string.h>
  19. #include <stdarg.h>
  20. #include <m_ctype.h>
  21. my_off_t my_b_append_tell(IO_CACHE* info)
  22. {
  23.   /*
  24.     Prevent optimizer from putting res in a register when debugging
  25.     we need this to be able to see the value of res when the assert fails
  26.   */
  27.   dbug_volatile my_off_t res; 
  28.   /*
  29.     We need to lock the append buffer mutex to keep flush_io_cache()
  30.     from messing with the variables that we need in order to provide the
  31.     answer to the question.
  32.   */
  33. #ifdef THREAD
  34.   pthread_mutex_lock(&info->append_buffer_lock);
  35. #endif
  36. #ifndef DBUG_OFF
  37.   /*
  38.     Make sure EOF is where we think it is. Note that we cannot just use
  39.     my_tell() because we have a reader thread that could have left the
  40.     file offset in a non-EOF location
  41.   */
  42.   {
  43.     volatile my_off_t save_pos;
  44.     save_pos = my_tell(info->file,MYF(0));
  45.     my_seek(info->file,(my_off_t)0,MY_SEEK_END,MYF(0));
  46.     /*
  47.       Save the value of my_tell in res so we can see it when studying coredump
  48.     */
  49.     DBUG_ASSERT(info->end_of_file - (info->append_read_pos-info->write_buffer)
  50. == (res=my_tell(info->file,MYF(0))));
  51.     my_seek(info->file,save_pos,MY_SEEK_SET,MYF(0));
  52.   }
  53. #endif  
  54.   res = info->end_of_file + (info->write_pos-info->append_read_pos);
  55. #ifdef THREAD
  56.   pthread_mutex_unlock(&info->append_buffer_lock);
  57. #endif
  58.   return res;
  59. }
  60. /*
  61.   Make next read happen at the given position
  62.   For write cache, make next write happen at the given position
  63. */
  64. void my_b_seek(IO_CACHE *info,my_off_t pos)
  65. {
  66.   my_off_t offset;  
  67.   DBUG_ENTER("my_b_seek");
  68.   DBUG_PRINT("enter",("pos: %lu", (ulong) pos));
  69.   /*
  70.     TODO:
  71.        Verify that it is OK to do seek in the non-append
  72.        area in SEQ_READ_APPEND cache
  73.      a) see if this always works
  74.      b) see if there is a better way to make it work
  75.   */
  76.   if (info->type == SEQ_READ_APPEND)
  77.     flush_io_cache(info);
  78.   
  79.   offset=(pos - info->pos_in_file);
  80.   
  81.   if (info->type == READ_CACHE || info->type == SEQ_READ_APPEND)
  82.   {
  83.     /* TODO: explain why this works if pos < info->pos_in_file */
  84.     if ((ulonglong) offset < (ulonglong) (info->read_end - info->buffer))
  85.     {
  86.       /* The read is in the current buffer; Reuse it */
  87.       info->read_pos = info->buffer + offset;
  88.       DBUG_VOID_RETURN;
  89.     }
  90.     else
  91.     {
  92.       /* Force a new read on next my_b_read */
  93.       info->read_pos=info->read_end=info->buffer;
  94.     }
  95.   }
  96.   else if (info->type == WRITE_CACHE)
  97.   {
  98.     /* If write is in current buffer, reuse it */
  99.     if ((ulonglong) offset <
  100. (ulonglong) (info->write_end - info->write_buffer))
  101.     {
  102.       info->write_pos = info->write_buffer + offset;
  103.       DBUG_VOID_RETURN;
  104.     }
  105.     flush_io_cache(info);
  106.     /* Correct buffer end so that we write in increments of IO_SIZE */
  107.     info->write_end=(info->write_buffer+info->buffer_length-
  108.      (pos & (IO_SIZE-1)));
  109.   }
  110.   info->pos_in_file=pos;
  111.   info->seek_not_done=1;
  112.   DBUG_VOID_RETURN;
  113. }
  114. /*
  115.   Fill buffer.  Note that this assumes that you have already used
  116.   all characters in the CACHE, independent of the read_pos value!
  117.   return:  0 on error or EOF (info->error = -1 on error)
  118.   number of characters
  119. */
  120. uint my_b_fill(IO_CACHE *info)
  121. {
  122.   my_off_t pos_in_file=(info->pos_in_file+
  123. (uint) (info->read_end - info->buffer));
  124.   my_off_t max_length;
  125.   uint diff_length,length;
  126.   if (info->seek_not_done)
  127.   { /* File touched, do seek */
  128.     if (my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0)) ==
  129. MY_FILEPOS_ERROR)
  130.     {
  131.       info->error= 0;
  132.       return 0;
  133.     }
  134.     info->seek_not_done=0;
  135.   }
  136.   diff_length=(uint) (pos_in_file & (IO_SIZE-1));
  137.   max_length= (my_off_t) (info->end_of_file - pos_in_file);
  138.   if (max_length > (my_off_t) (info->read_length-diff_length))
  139.     max_length=(my_off_t) (info->read_length-diff_length);
  140.   if (!max_length)
  141.   {
  142.     info->error= 0;
  143.     return 0; /* EOF */
  144.   }
  145.    else if ((length=my_read(info->file,info->buffer,(uint) max_length,
  146.    info->myflags)) == (uint) -1)
  147.   {
  148.     info->error= -1;
  149.     return 0;
  150.   }
  151.   info->read_pos=info->buffer;
  152.   info->read_end=info->buffer+length;
  153.   info->pos_in_file=pos_in_file;
  154.   return length;
  155. }
  156. /*
  157.   Read a string ended by 'n' into a buffer of 'max_length' size.
  158.   Returns number of characters read, 0 on error.
  159.   last byte is set to ''
  160.   If buffer is full then to[max_length-1] will be set to .
  161. */
  162. uint my_b_gets(IO_CACHE *info, char *to, uint max_length)
  163. {
  164.   char *start = to;
  165.   uint length;
  166.   max_length--; /* Save place for end  */
  167.   /* Calculate number of characters in buffer */
  168.   if (!(length= my_b_bytes_in_cache(info)) &&
  169.       !(length= my_b_fill(info)))
  170.     return 0;
  171.   for (;;)
  172.   {
  173.     char *pos,*end;
  174.     if (length > max_length)
  175.       length=max_length;
  176.     for (pos=info->read_pos,end=pos+length ; pos < end ;)
  177.     {
  178.       if ((*to++ = *pos++) == 'n')
  179.       {
  180. info->read_pos=pos;
  181. *to='';
  182. return (uint) (to-start);
  183.       }
  184.     }
  185.     if (!(max_length-=length))
  186.     {
  187.      /* Found enough charcters;  Return found string */
  188.       info->read_pos=pos;
  189.       *to='';
  190.       return (uint) (to-start);
  191.     }
  192.     if (!(length=my_b_fill(info)))
  193.       return 0;
  194.   }
  195. }
  196. my_off_t my_b_filelength(IO_CACHE *info)
  197. {
  198.   if (info->type == WRITE_CACHE)
  199.   {
  200.     return my_b_tell(info);
  201.   }
  202.   else
  203.   {
  204.     info->seek_not_done=1;
  205.     return my_seek(info->file,0L,MY_SEEK_END,MYF(0));
  206.   }
  207. }
  208. /*
  209.   Simple printf version.  Supports '%s', '%d', '%u', "%ld" and "%lu"
  210.   Used for logging in MySQL
  211.   returns number of written character, or (uint) -1 on error
  212. */
  213. uint my_b_printf(IO_CACHE *info, const char* fmt, ...)
  214. {
  215.   int result;
  216.   va_list args;
  217.   va_start(args,fmt);
  218.   result=my_b_vprintf(info, fmt, args);
  219.   va_end(args);
  220.   return result;
  221. }
  222. uint my_b_vprintf(IO_CACHE *info, const char* fmt, va_list args)
  223. {
  224.   uint out_length=0;
  225.   for (; *fmt ; fmt++)
  226.   {
  227.     if (*fmt++ != '%')
  228.     {
  229.       /* Copy everything until '%' or end of string */
  230.       const char *start=fmt-1;
  231.       uint length;
  232.       for (; *fmt && *fmt != '%' ; fmt++ ) ;
  233.       length= (uint) (fmt - start);
  234.       out_length+=length;
  235.       if (my_b_write(info, start, length))
  236. goto err;
  237.       if (!*fmt) /* End of format */
  238.       {
  239. return out_length;
  240.       }
  241.       fmt++;
  242.       /* Found one '%' */
  243.     }
  244.     /* Skip if max size is used (to be compatible with printf) */
  245.     while (my_isdigit(&my_charset_latin1, *fmt) || *fmt == '.' || *fmt == '-')
  246.       fmt++;
  247.     if (*fmt == 's') /* String parameter */
  248.     {
  249.       reg2 char *par = va_arg(args, char *);
  250.       uint length = (uint) strlen(par);
  251.       out_length+=length;
  252.       if (my_b_write(info, par, length))
  253. goto err;
  254.     }
  255.     else if (*fmt == 'd' || *fmt == 'u') /* Integer parameter */
  256.     {
  257.       register int iarg;
  258.       uint length;
  259.       char buff[17];
  260.       iarg = va_arg(args, int);
  261.       if (*fmt == 'd')
  262. length= (uint) (int10_to_str((long) iarg,buff, -10) - buff);
  263.       else
  264. length= (uint) (int10_to_str((long) (uint) iarg,buff,10)- buff);
  265.       out_length+=length;
  266.       if (my_b_write(info, buff, length))
  267. goto err;
  268.     }
  269.     else if ((*fmt == 'l' && fmt[1] == 'd') || fmt[1] == 'u')
  270.       /* long parameter */
  271.     {
  272.       register long iarg;
  273.       uint length;
  274.       char buff[17];
  275.       iarg = va_arg(args, long);
  276.       if (*++fmt == 'd')
  277. length= (uint) (int10_to_str(iarg,buff, -10) - buff);
  278.       else
  279. length= (uint) (int10_to_str(iarg,buff,10)- buff);
  280.       out_length+=length;
  281.       if (my_b_write(info, buff, length))
  282. goto err;
  283.     }
  284.     else
  285.     {
  286.       /* %% or unknown code */
  287.       if (my_b_write(info, "%", 1))
  288. goto err;
  289.       out_length++;
  290.     }
  291.   }
  292.   return out_length;
  293. err:
  294.   return (uint) -1;
  295. }