00001 /* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- 00002 * vim:expandtab:shiftwidth=2:tabstop=2:smarttab: 00003 * 00004 * Copyright (C) 2008 MySQL 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00019 */ 00020 00021 #pragma once 00022 00023 #include <drizzled/internal/my_sys.h> 00024 00025 namespace drizzled { 00026 namespace internal { 00027 00028 #define my_b_EOF INT_MIN 00029 00030 class io_cache_st /* Used when cacheing files */ 00031 { 00032 public: 00033 typedef int (*IO_CACHE_CALLBACK)(io_cache_st*); 00034 00035 /* Offset in file corresponding to the first byte of unsigned char* buffer. */ 00036 my_off_t pos_in_file; 00037 /* 00038 The offset of end of file for READ_CACHE and WRITE_CACHE. 00039 For SEQ_READ_APPEND it the maximum of the actual end of file and 00040 the position represented by read_end. 00041 */ 00042 my_off_t end_of_file; 00043 /* Points to current read position in the buffer */ 00044 unsigned char *read_pos; 00045 /* the non-inclusive boundary in the buffer for the currently valid read */ 00046 unsigned char *read_end; 00047 unsigned char *buffer; /* The read buffer */ 00048 /* Used in ASYNC_IO */ 00049 unsigned char *request_pos; 00050 00051 /* Only used in WRITE caches and in SEQ_READ_APPEND to buffer writes */ 00052 unsigned char *write_buffer; 00053 /* 00054 Only used in SEQ_READ_APPEND, and points to the current read position 00055 in the write buffer. Note that reads in SEQ_READ_APPEND caches can 00056 happen from both read buffer (unsigned char* buffer) and write buffer 00057 (unsigned char* write_buffer). 00058 */ 00059 unsigned char *append_read_pos; 00060 /* Points to current write position in the write buffer */ 00061 unsigned char *write_pos; 00062 /* The non-inclusive boundary of the valid write area */ 00063 unsigned char *write_end; 00064 00065 /* 00066 Current_pos and current_end are convenience variables used by 00067 my_b_tell() and other routines that need to know the current offset 00068 current_pos points to &write_pos, and current_end to &write_end in a 00069 WRITE_CACHE, and &read_pos and &read_end respectively otherwise 00070 */ 00071 unsigned char **current_pos, **current_end; 00072 /* 00073 A caller will use my_b_read() macro to read from the cache 00074 if the data is already in cache, it will be simply copied with 00075 memcpy() and internal variables will be accordinging updated with 00076 no functions invoked. However, if the data is not fully in the cache, 00077 my_b_read() will call read_function to fetch the data. read_function 00078 must never be invoked directly. 00079 */ 00080 int (*read_function)(io_cache_st* ,unsigned char *,size_t); 00081 /* 00082 Same idea as in the case of read_function, except my_b_write() needs to 00083 be replaced with my_b_append() for a SEQ_READ_APPEND cache 00084 */ 00085 int (*write_function)(io_cache_st* ,const unsigned char *,size_t); 00086 /* 00087 Specifies the type of the cache. Depending on the type of the cache 00088 certain operations might not be available and yield unpredicatable 00089 results. Details to be documented later 00090 */ 00091 cache_type type; 00092 int error; 00093 /* 00094 Callbacks when the actual read I/O happens. These were added and 00095 are currently used for binary logging of LOAD DATA INFILE - when a 00096 block is read from the file, we create a block create/append event, and 00097 when io_cache_st is closed, we create an end event. These functions could, 00098 of course be used for other things 00099 */ 00100 IO_CACHE_CALLBACK pre_read; 00101 IO_CACHE_CALLBACK post_read; 00102 IO_CACHE_CALLBACK pre_close; 00103 void* arg; /* for use by pre/post_read */ 00104 char *file_name; /* if used with 'open_cached_file' */ 00105 char *dir,*prefix; 00106 int file; /* file descriptor */ 00107 /* 00108 seek_not_done is set by my_b_seek() to inform the upcoming read/write 00109 operation that a seek needs to be preformed prior to the actual I/O 00110 error is 0 if the cache operation was successful, -1 if there was a 00111 "hard" error, and the actual number of I/O-ed bytes if the read/write was 00112 partial. 00113 */ 00114 int seek_not_done; 00115 /* buffer_length is memory size allocated for buffer or write_buffer */ 00116 size_t buffer_length; 00117 /* read_length is the same as buffer_length except when we use async io */ 00118 size_t read_length; 00119 myf myflags; /* Flags used to my_read/my_write */ 00120 /* 00121 alloced_buffer is 1 if the buffer was allocated by init_io_cache() and 00122 0 if it was supplied by the user. 00123 Currently READ_NET is the only one that will use a buffer allocated 00124 somewhere else 00125 */ 00126 bool alloced_buffer; 00127 00128 io_cache_st() : 00129 pos_in_file(0), 00130 end_of_file(0), 00131 read_pos(0), 00132 read_end(0), 00133 buffer(0), 00134 request_pos(0), 00135 write_buffer(0), 00136 append_read_pos(0), 00137 write_pos(0), 00138 write_end(0), 00139 current_pos(0), 00140 current_end(0), 00141 read_function(0), 00142 write_function(0), 00143 type(TYPE_NOT_SET), 00144 error(0), 00145 pre_read(0), 00146 post_read(0), 00147 pre_close(0), 00148 arg(0), 00149 file_name(0), 00150 dir(0), 00151 prefix(0), 00152 file(0), 00153 seek_not_done(0), 00154 buffer_length(0), 00155 read_length(0), 00156 myflags(0), 00157 alloced_buffer(0) 00158 { } 00159 00160 int get(); 00161 int block_write(const void*, size_t, my_off_t); 00162 void close_cached_file(); 00163 bool real_open_cached_file(); 00164 int end_io_cache(); 00165 int init_io_cache(int file, size_t cachesize, cache_type type, my_off_t seek_offset, bool use_async_io, myf cache_myflags); 00166 void init_functions(); 00167 00168 bool reinit_io_cache(cache_type type_arg, my_off_t seek_offset, bool use_async_io, bool clear_cache); 00169 void setup_io_cache(); 00170 bool open_cached_file(const char *dir, const char *prefix, size_t cache_size, myf cache_myflags); 00171 int flush(int need_append_buffer_lock= 1); 00172 00173 void clear() 00174 { 00175 buffer= NULL; 00176 } 00177 00178 bool inited() const 00179 { 00180 return buffer; 00181 } 00182 00183 my_off_t tell() const 00184 { 00185 return pos_in_file + *current_pos - request_pos; 00186 } 00187 00188 int read(void* Buffer0, size_t Count) 00189 { 00190 unsigned char* Buffer= reinterpret_cast<unsigned char*>(Buffer0); 00191 if (read_pos + Count > read_end) 00192 return read_function(this, Buffer, Count); 00193 memcpy(Buffer, read_pos, Count); 00194 read_pos += Count; 00195 return 0; 00196 } 00197 00198 int write(const void* Buffer0, size_t Count) 00199 { 00200 const unsigned char* Buffer= reinterpret_cast<const unsigned char*>(Buffer0); 00201 if (write_pos + Count > write_end) 00202 return write_function(this, Buffer, Count); 00203 memcpy(write_pos, Buffer, Count); 00204 write_pos += Count; 00205 return 0; 00206 } 00207 }; 00208 00209 } /* namespace internal */ 00210 } /* namespace drizzled */