Drizzled Public API Documentation

mi_cache.cc
00001 /* Copyright (C) 2000-2003 MySQL AB
00002 
00003    This program is free software; you can redistribute it and/or modify
00004    it under the terms of the GNU General Public License as published by
00005    the Free Software Foundation; version 2 of the License.
00006 
00007    This program is distributed in the hope that it will be useful,
00008    but WITHOUT ANY WARRANTY; without even the implied warranty of
00009    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010    GNU General Public License for more details.
00011 
00012    You should have received a copy of the GNU General Public License
00013    along with this program; if not, write to the Free Software
00014    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
00015 
00016 /*
00017   Functions for read record cacheing with myisam
00018   Used for reading dynamic/compressed records from datafile.
00019 
00020   Can fetch data directly from file (outside cache),
00021   if reading a small chunk straight before the cached part (with possible
00022   overlap).
00023 
00024   Can be explicitly asked not to use cache (by not setting READING_NEXT in
00025   flag) - useful for occasional out-of-cache reads, when the next read is
00026   expected to hit the cache again.
00027 
00028   Allows "partial read" errors in the record header (when READING_HEADER flag
00029   is set) - unread part is zero'ed
00030 
00031   Note: out-of-cache reads are enabled for shared IO_CACHE's too,
00032   as these reads will be cached by OS cache (and my_pread is always atomic)
00033 */
00034 
00035 
00036 #include "myisam_priv.h"
00037 
00038 #include <algorithm>
00039 
00040 using namespace std;
00041 using namespace drizzled;
00042 
00043 
00044 int _mi_read_cache(internal::IO_CACHE *info, unsigned char *buff, internal::my_off_t pos, uint32_t length,
00045        int flag)
00046 {
00047   uint32_t read_length,in_buff_length;
00048   internal::my_off_t offset;
00049   unsigned char *in_buff_pos;
00050 
00051   if (pos < info->pos_in_file)
00052   {
00053     read_length=length;
00054     if ((internal::my_off_t) read_length > (internal::my_off_t) (info->pos_in_file-pos))
00055       read_length=(uint) (info->pos_in_file-pos);
00056     info->seek_not_done=1;
00057     if (my_pread(info->file,buff,read_length,pos,MYF(MY_NABP)))
00058       return(1);
00059     if (!(length-=read_length))
00060       return(0);
00061     pos+=read_length;
00062     buff+=read_length;
00063   }
00064   if (pos >= info->pos_in_file &&
00065       (offset= (internal::my_off_t) (pos - info->pos_in_file)) <
00066       (internal::my_off_t) (info->read_end - info->request_pos))
00067   {
00068     in_buff_pos=info->request_pos+(uint) offset;
00069     in_buff_length= min(length, (uint32_t) (info->read_end-in_buff_pos));
00070     memcpy(buff,info->request_pos+(uint) offset,(size_t) in_buff_length);
00071     if (!(length-=in_buff_length))
00072       return(0);
00073     pos+=in_buff_length;
00074     buff+=in_buff_length;
00075   }
00076   else
00077     in_buff_length=0;
00078   if (flag & READING_NEXT)
00079   {
00080     if (pos != (info->pos_in_file +
00081     (uint) (info->read_end - info->request_pos)))
00082     {
00083       info->pos_in_file=pos;        /* Force start here */
00084       info->read_pos=info->read_end=info->request_pos;  /* Everything used */
00085       info->seek_not_done=1;
00086     }
00087     else
00088       info->read_pos=info->read_end;      /* All block used */
00089     if (!(*info->read_function)(info,buff,length))
00090       return(0);
00091     read_length=info->error;
00092   }
00093   else
00094   {
00095     info->seek_not_done=1;
00096     if ((read_length=my_pread(info->file,buff,length,pos,MYF(0))) == length)
00097       return(0);
00098   }
00099   if (!(flag & READING_HEADER) || (int) read_length == -1 ||
00100       read_length+in_buff_length < 3)
00101   {
00102     if (!errno || errno == -1)
00103       errno=HA_ERR_WRONG_IN_RECORD;
00104     return(1);
00105   }
00106   memset(buff+read_length, 0,
00107          MI_BLOCK_INFO_HEADER_LENGTH - in_buff_length - read_length);
00108   return(0);
00109 } /* _mi_read_cache */