diff options
author | unknown <monty@narttu.mysql.fi> | 2000-11-15 23:00:06 +0200 |
---|---|---|
committer | unknown <monty@narttu.mysql.fi> | 2000-11-15 23:00:06 +0200 |
commit | 9a846a52ae62f701c2d54d3f468e2ead393acf91 (patch) | |
tree | 622092bf596b26a1f762020729c03d573a5b216d | |
parent | f3d2341f1f30384d92b285c1e421d8c599ee2b79 (diff) | |
download | mariadb-git-9a846a52ae62f701c2d54d3f468e2ead393acf91.tar.gz |
changed to use IO_CACHE instead of FILE
BitKeeper/deleted/.del-mf_reccache.c:
***MISSING WEAVE***
Docs/manual.texi:
Fix licence information + update changelog
client/mysqlimport.c:
Fixed typo
client/sql_string.cc:
Added support for IO_CACHE
client/sql_string.h:
Added support for IO_CACHE
include/my_sys.h:
More options for IO_CACHE
mysql.proj:
Update
mysys/Makefile.am:
Remoced mf_reccache.c
mysys/mf_cache.c:
Fixed return value on error and optimzed used of write cache files
mysys/mf_iocache.c:
More options for IO_CACHE
mysys/my_vsnprintf.c:
Optimized code
sql/mf_iocache.cc:
merge with mf_iocache.c
sql/net_pkg.cc:
cleanup
sql/sql_class.cc:
Support for transaction safe log files
sql/sql_string.cc:
Added support for IO_CACHE
sql/sql_string.h:
Added support for IO_CACHE
sql/time.cc:
cleanup
BitKeeper/etc/logging_ok:
Logging to logging@openlogging.org accepted
-rw-r--r-- | BitKeeper/etc/logging_ok | 2 | ||||
-rw-r--r-- | Docs/manual.texi | 14 | ||||
-rw-r--r-- | client/mysqlimport.c | 4 | ||||
-rw-r--r-- | client/sql_string.cc | 26 | ||||
-rw-r--r-- | client/sql_string.h | 18 | ||||
-rw-r--r-- | include/my_sys.h | 5 | ||||
-rw-r--r-- | mysql.proj | bin | 176128 -> 184320 bytes | |||
-rw-r--r-- | mysys/Makefile.am | 2 | ||||
-rw-r--r-- | mysys/mf_cache.c | 8 | ||||
-rw-r--r-- | mysys/mf_iocache.c | 43 | ||||
-rw-r--r-- | mysys/my_vsnprintf.c | 91 | ||||
-rw-r--r-- | sql/log.cc | 342 | ||||
-rw-r--r-- | sql/log_event.cc | 301 | ||||
-rw-r--r-- | sql/log_event.h | 63 | ||||
-rw-r--r-- | sql/mf_iocache.cc | 48 | ||||
-rw-r--r-- | sql/mysqlbinlog.cc | 144 | ||||
-rw-r--r-- | sql/net_pkg.cc | 10 | ||||
-rw-r--r-- | sql/sql_class.cc | 13 | ||||
-rw-r--r-- | sql/sql_class.h | 11 | ||||
-rw-r--r-- | sql/sql_parse.cc | 2 | ||||
-rw-r--r-- | sql/sql_repl.cc | 452 | ||||
-rw-r--r-- | sql/sql_string.cc | 26 | ||||
-rw-r--r-- | sql/sql_string.h | 2 | ||||
-rw-r--r-- | sql/time.cc | 10 |
24 files changed, 816 insertions, 821 deletions
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index a6b0f220269..f5cbc2ff8bf 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -1 +1 @@ -monty@tik.mysql.com +monty@narttu.mysql.fi diff --git a/Docs/manual.texi b/Docs/manual.texi index d49fddebc6c..ec6b04ab9ae 100644 --- a/Docs/manual.texi +++ b/Docs/manual.texi @@ -3610,10 +3610,13 @@ similar system. In the worst case, we may require access to your system to be able to create a binary distribution. @item -If you can provide accommodations and pay for traveler fares, you can even -get a @strong{MySQL} developer to visit you and offer you help with your -troubles. Extended login support entitles you to one personal -encounter per year, but we are always very flexible towards our customers! +If you can provide accommodations and pay for traveler fares, you can +even get a @strong{MySQL} developer to visit you and offer you help with +your troubles. Extended login support entitles you to one personal +encounter per year, but we are always very flexible towards our +customers! If the visit takes 16 hours or more, the first 8 hours is +without charge. For the hours above 8 hours, you will be charged with a +rate that is at least 20 % less than our standard rates. @end itemize @node Installing, Compatibility, Licensing and Support, Top @@ -38367,6 +38370,9 @@ though, so 3.23 is not released as a stable version yet. @appendixsubsec Changes in release 3.23.28 @itemize @bullet @item +Changed all log files to use our own IO_CACHE mechanism instead of +FILE:s to avoid OS problems when there is many files open. +@item Added options @code{--open-files} and @code{--timezone} to @code{safe_mysqld}. @item Fixed fatal bug in @code{CREATE TEMPORARY TABLE ...SELECT ...}. diff --git a/client/mysqlimport.c b/client/mysqlimport.c index 68cd84fbbb7..d00c99d4061 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -25,7 +25,7 @@ ** * * ** ************************* */ -#define IMPORT_VERSION "2.5" +#define IMPORT_VERSION "2.6" #include <global.h> #include <my_sys.h> @@ -125,7 +125,7 @@ file. The SQL command 'LOAD DATA INFILE' is used to import the rows.\n"); Give the column names in a comma separated list.\n\ This is same as giving columns to LOAD DATA INFILE.\n\ -C, --compress Use compression in server/client protocol\n\ - -d, --delete Deletes first all rows from table.\n\ + -d, --delete First delete all rows from table.\n\ -f, --force Continue even if we get an sql-error.\n\ -h, --host=... Connect to host.\n\ -i, --ignore If duplicate unique key was found, keep old row.\n\ diff --git a/client/sql_string.cc b/client/sql_string.cc index 7ca2d3c419e..4b9ebef21f1 100644 --- a/client/sql_string.cc +++ b/client/sql_string.cc @@ -95,17 +95,6 @@ bool String::realloc(uint32 alloc_length) return FALSE; } - -#ifdef NOT_NEEDED -bool String::set(long num) -{ - if (alloc(14)) - return TRUE; - str_length=(uint32) (int10_to_str(num,Ptr,-10)-Ptr); - return FALSE; -} -#endif - bool String::set(longlong num) { if (alloc(21)) @@ -274,6 +263,7 @@ bool String::append(const char *s,uint32 arg_length) return FALSE; } +#ifdef TO_BE_REMOVED bool String::append(FILE* file, uint32 arg_length, myf my_flags) { if (realloc(str_length+arg_length)) @@ -286,6 +276,20 @@ bool String::append(FILE* file, uint32 arg_length, myf my_flags) str_length+=arg_length; return FALSE; } +#endif + +bool String::append(IO_CACHE* file, uint32 arg_length) +{ + if (realloc(str_length+arg_length)) + return TRUE; + if (my_b_read(file, (byte*) Ptr + str_length, arg_length)) + { + shrink(str_length); + return TRUE; + } + str_length+=arg_length; + return FALSE; +} uint32 String::numchars() { diff --git a/client/sql_string.h b/client/sql_string.h index 8711cf314ad..74dbc4cc6bd 100644 --- a/client/sql_string.h +++ b/client/sql_string.h @@ -100,16 +100,16 @@ public: bool set(ulonglong num); bool set(double num,uint decimals=2); inline void free() + { + if (alloced) { - if (alloced) - { - alloced=0; - Alloced_length=0; - my_free(Ptr,MYF(0)); - Ptr=0; - } + alloced=0; + Alloced_length=0; + my_free(Ptr,MYF(0)); + Ptr=0; + str_length=0; /* Safety */ } - + } inline bool alloc(uint32 arg_length) { if (arg_length < Alloced_length) @@ -152,7 +152,7 @@ public: bool copy(const char *s,uint32 arg_length); // Allocate new string bool append(const String &s); bool append(const char *s,uint32 arg_length=0); - bool append(FILE* file, uint32 arg_length, myf my_flags); + bool append(IO_CACHE* file, uint32 arg_length); int strstr(const String &search,uint32 offset=0); // Returns offset to substring or -1 int strrstr(const String &search,uint32 offset=0); // Returns offset to substring or -1 bool replace(uint32 offset,uint32 arg_length,const String &to); diff --git a/include/my_sys.h b/include/my_sys.h index beee8e3dc1c..1d4673e1e79 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -59,6 +59,7 @@ extern int NEAR my_errno; /* Last error in mysys */ #define MY_WME 16 /* Write message on error */ #define MY_WAIT_IF_FULL 32 /* Wait and try again if disk full error */ #define MY_RAID 64 /* Support for RAID (not the "Johnson&Johnson"-s one ;) */ +#define MY_DONT_CHECK_FILESIZE 128 /* Option to init_io_cache() */ #define MY_LINK_WARNING 32 /* my_redel() gives warning if links */ #define MY_COPYTIME 64 /* my_redel() copys time */ #define MY_HOLD_ORIGINAL_MODES 128 /* my_copy() holds to file modes */ @@ -505,6 +506,10 @@ extern int my_block_write(IO_CACHE *info, const byte *Buffer, uint Count, my_off_t pos); extern int flush_io_cache(IO_CACHE *info); extern int end_io_cache(IO_CACHE *info); +extern uint my_b_fill(IO_CACHE *info); +extern void my_b_seek(IO_CACHE *info,my_off_t pos); +extern uint my_b_gets(IO_CACHE *info, char *to, uint max_length); +extern uint my_b_printf(IO_CACHE *info, const char* fmt, ...); extern my_bool open_cached_file(IO_CACHE *cache,const char *dir, const char *prefix, uint cache_size, myf cache_myflags); diff --git a/mysql.proj b/mysql.proj Binary files differindex ed591da265e..a6e5d9c5852 100644 --- a/mysql.proj +++ b/mysql.proj diff --git a/mysys/Makefile.am b/mysys/Makefile.am index 6b38d9364f6..3d60716e358 100644 --- a/mysys/Makefile.am +++ b/mysys/Makefile.am @@ -26,7 +26,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c\ mf_path.c mf_loadpath.c\ my_open.c my_create.c my_seek.c my_read.c \ my_pread.c my_write.c \ - mf_reccache.c mf_keycache.c \ + mf_keycache.c \ mf_iocache.c mf_cache.c mf_tempfile.c \ my_lock.c mf_brkhant.c my_alarm.c \ my_malloc.c my_realloc.c my_once.c mulalloc.c \ diff --git a/mysys/mf_cache.c b/mysys/mf_cache.c index 2c197f6fd20..ff29926ac50 100644 --- a/mysys/mf_cache.c +++ b/mysys/mf_cache.c @@ -74,7 +74,7 @@ my_bool open_cached_file(IO_CACHE *cache, const char* dir, const char *prefix, } my_free(cache->dir, MYF(MY_ALLOW_ZERO_PTR)); my_free(cache->prefix,MYF(MY_ALLOW_ZERO_PTR)); - DBUG_RETURN(0); + DBUG_RETURN(1); } /* Create the temporary file */ @@ -101,10 +101,12 @@ void close_cached_file(IO_CACHE *cache) DBUG_ENTER("close_cached_file"); if (my_b_inited(cache)) { + File file=cache->file; + cache->file= -1; /* Don't flush data */ (void) end_io_cache(cache); - if (cache->file >= 0) + if (file >= 0) { - (void) my_close(cache->file,MYF(0)); + (void) my_close(file,MYF(0)); #ifdef CANT_DELETE_OPEN_FILES if (cache->file_name) { diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c index 86cf5fc65e2..0d1c227c2b2 100644 --- a/mysys/mf_iocache.c +++ b/mysys/mf_iocache.c @@ -22,10 +22,13 @@ (and get a EOF-error). Possibly use of asyncronic io. macros for read and writes for faster io. - Used instead of FILE when reading or writing hole files. - This shall make mf_rec_cache obsolite. - One can change info->pos_in_file to a higer value to skipp bytes in file if + Used instead of FILE when reading or writing whole files. + This will make mf_rec_cache obsolete. + One can change info->pos_in_file to a higher value to skip bytes in file if also info->rc_pos is set to info->rc_end. + If called through open_cached_file(), then the temporary file will + only be created if a write exeeds the file buffer or if one calls + flush_io_cache(). */ #define MAP_TO_USE_RAID @@ -40,7 +43,7 @@ static void my_aiowait(my_aio_result *result); /* ** if cachesize == 0 then use default cachesize (from s-file) - ** if file == -1 then real_open_cached_file() will be called to + ** if file == -1 then real_open_cached_file() will be called. ** returns 0 if ok */ @@ -59,17 +62,24 @@ int init_io_cache(IO_CACHE *info, File file, uint cachesize, min_cache=use_async_io ? IO_SIZE*4 : IO_SIZE*2; if (type == READ_CACHE) { /* Assume file isn't growing */ - my_off_t file_pos,end_of_file; - if ((file_pos=my_tell(file,MYF(0)) == MY_FILEPOS_ERROR)) - DBUG_RETURN(1); - end_of_file=my_seek(file,0L,MY_SEEK_END,MYF(0)); - if (end_of_file < seek_offset) - end_of_file=seek_offset; - VOID(my_seek(file,file_pos,MY_SEEK_SET,MYF(0))); - if ((my_off_t) cachesize > end_of_file-seek_offset+IO_SIZE*2-1) + if (cache_myflags & MY_DONT_CHECK_FILESIZE) { - cachesize=(uint) (end_of_file-seek_offset)+IO_SIZE*2-1; - use_async_io=0; /* No nead to use async */ + cache_myflags &= ~MY_DONT_CHECK_FILESIZE; + } + else + { + my_off_t file_pos,end_of_file; + if ((file_pos=my_tell(file,MYF(0)) == MY_FILEPOS_ERROR)) + DBUG_RETURN(1); + end_of_file=my_seek(file,0L,MY_SEEK_END,MYF(0)); + if (end_of_file < seek_offset) + end_of_file=seek_offset; + VOID(my_seek(file,file_pos,MY_SEEK_SET,MYF(0))); + if ((my_off_t) cachesize > end_of_file-seek_offset+IO_SIZE*2-1) + { + cachesize=(uint) (end_of_file-seek_offset)+IO_SIZE*2-1; + use_async_io=0; /* No nead to use async */ + } } } @@ -545,7 +555,6 @@ int my_block_write(register IO_CACHE *info, const byte *Buffer, uint Count, return error; } - /* Flush write cache */ int flush_io_cache(IO_CACHE *info) @@ -565,7 +574,9 @@ int flush_io_cache(IO_CACHE *info) length=(uint) (info->rc_pos - info->buffer); if (info->seek_not_done) { /* File touched, do seek */ - VOID(my_seek(info->file,info->pos_in_file,MY_SEEK_SET,MYF(0))); + if (my_seek(info->file,info->pos_in_file,MY_SEEK_SET,MYF(0)) == + MY_FILEPOS_ERROR) + DBUG_RETURN((info->error= -1)); info->seek_not_done=0; } info->rc_pos=info->buffer; diff --git a/mysys/my_vsnprintf.c b/mysys/my_vsnprintf.c index 63730926156..b394adf2a96 100644 --- a/mysys/my_vsnprintf.c +++ b/mysys/my_vsnprintf.c @@ -21,74 +21,49 @@ #include <stdarg.h> #include <m_ctype.h> - - -int my_vsnprintf(char* str, size_t n, const char* fmt, va_list ap) +int my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap) { - uint olen = 0, plen; - const char *tpos; - reg1 char *endpos; - reg2 char * par; - char* ebuff = str; - - endpos=ebuff; - tpos = fmt; + char *start=to, *end=to+n-1; - while (*tpos) + for (; *fmt ; fmt++) { - if (tpos[0] != '%') + if (fmt[0] != '%') { - if(olen + 1 >= n) + if (to == end) /* End of buffer */ break; - - *endpos++= *tpos++; /* Copy ordinary char */ - olen++; + *to++= *fmt; /* Copy ordinary char */ continue; } - if (*++tpos == '%') /* test if %% */ - { - olen--; - } - else + /* Skipp if max size is used (to be compatible with printf) */ + while (isdigit(*fmt) || *fmt == '.' || *fmt == '-') + fmt++; + if (*fmt == 's') /* String parameter */ { - /* Skipp if max size is used (to be compatible with printf) */ - while (isdigit(*tpos) || *tpos == '.' || *tpos == '-') - tpos++; - if (*tpos == 's') /* String parameter */ - { - par = va_arg(ap, char *); - plen = (uint) strlen(par); - if (olen + plen < n) /* Replace if possible */ - { - endpos=strmov(endpos,par); - tpos++; - olen+=plen; - continue; - } - } - else if (*tpos == 'd' || *tpos == 'u') /* Integer parameter */ + reg2 char *par = va_arg(ap, char *); + uint plen = (uint) strlen(par); + if ((uint) (end-to) > plen) /* Replace if possible */ { - register int iarg; - iarg = va_arg(ap, int); - if(olen + 16 >= n) break; - - if (*tpos == 'd') - plen= (uint) (int2str((long) iarg,endpos, -10) - endpos); - else - plen= (uint) (int2str((long) (uint) iarg,endpos,10)- endpos); - if (olen + plen < n) /* Replace parameter if possible */ - { - endpos+=plen; - tpos++; - olen+=plen; - continue; - } + to=strmov(to,par); + continue; } } - *endpos++='%'; /* % used as % or unknown code */ + else if (*fmt == 'd' || *fmt == 'u') /* Integer parameter */ + { + register int iarg; + if ((uint) (end-to) < 16) + break; + iarg = va_arg(ap, int); + if (*fmt == 'd') + to=int10_to_str((long) iarg,to, -10); + else + to=int10_to_str((long) (uint) iarg,to,10); + continue; + } + /* We come here on '%%', unknown code or too long parameter */ + if (to == end) + break; + *to++='%'; /* % used as % or unknown code */ } - *endpos='\0'; - /* End of errmessage */ - return olen; + *to='\0'; /* End of errmessage */ + return (uint) (to - start); } - diff --git a/sql/log.cc b/sql/log.cc index c1e38a104ca..4ed48b18f0f 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -72,17 +72,16 @@ static int find_uniq_filename(char *name) DBUG_RETURN(0); } - - -MYSQL_LOG::MYSQL_LOG(): file(-1),index_file(-1),last_time(0),query_start(0), - name(0), log_type(LOG_CLOSED),write_error(0),inited(0), - no_rotate(0) +MYSQL_LOG::MYSQL_LOG(): last_time(0), query_start(0), + name(0), log_type(LOG_CLOSED),write_error(0), + inited(0), opened(0), no_rotate(0) { /* We don't want to intialize LOCK_Log here as the thread system may not have been initailized yet. We do it instead at 'open'. */ - index_file_name[0] = 0; + index_file_name[0] = 0; + bzero((char*) &log_file,sizeof(log_file)); } MYSQL_LOG::~MYSQL_LOG() @@ -103,6 +102,7 @@ void MYSQL_LOG::set_index_file_name(const char* index_file_name) this->index_file_name[0] = 0; } + int MYSQL_LOG::generate_new_name(char *new_name, const char *log_name) { if (log_type == LOG_NORMAL) @@ -128,6 +128,9 @@ void MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg, { MY_STAT tmp_stat; char buff[512]; + File file= -1; + bool do_magic; + if (!inited) { inited=1; @@ -136,29 +139,27 @@ void MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg, if (log_type_arg == LOG_BIN && *fn_ext(log_name)) no_rotate = 1; } - + log_type=log_type_arg; - name=my_strdup(log_name,MYF(0)); + if (!(name=my_strdup(log_name,MYF(MY_WME)))) + goto err; if (new_name) strmov(log_file_name,new_name); else if (generate_new_name(log_file_name, name)) - return; + goto err; if (log_type == LOG_BIN && !index_file_name[0]) fn_format(index_file_name, name, mysql_data_home, ".index", 6); db[0]=0; - bool do_magic = ((log_type == LOG_BIN) && !my_stat(log_file_name, - &tmp_stat, MYF(0))); + do_magic = ((log_type == LOG_BIN) && !my_stat(log_file_name, + &tmp_stat, MYF(0))); if ((file=my_open(log_file_name,O_APPEND | O_WRONLY | O_BINARY, - MYF(MY_WME | ME_WAITTANG)) < 0) - { - my_free(name,MYF(0)); - name=0; - log_type=LOG_CLOSED; - return; - } + MYF(MY_WME | ME_WAITTANG))) < 0 || + init_io_cache(&log_file, file, IO_SIZE, WRITE_CACHE, + my_tell(file,MYF(MY_WME)), 0, MYF(MY_WME | MY_NABP))) + goto err; if (log_type == LOG_NORMAL) { @@ -169,7 +170,9 @@ void MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg, sprintf(buff, "%s, Version: %s, started with:\nTcp port: %d Unix socket: %s\n", my_progname,server_version,mysql_port,mysql_unix_port); #endif end=strmov(strend(buff),"Time Id Command Argument\n"); - my_write(file,buff,(uint) (end-buff),MYF(0)); + if (my_b_write(&log_file,buff,(uint) (end-buff)) || + flush_io_cache(&log_file)) + goto err; } else if (log_type == LOG_NEW) { @@ -184,11 +187,12 @@ void MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg, tm_tmp.tm_hour, tm_tmp.tm_min, tm_tmp.tm_sec); - my_write(file,buff,(uint) strlen(buff),MYF(0)); + if (my_b_write(&log_file,buff,(uint) strlen(buff)) || + flush_io_cache(&log_file)) + goto err; } else if (log_type == LOG_BIN) { - // Explanation of the boolean black magic: // // if we are supposed to write magic number try write @@ -196,34 +200,36 @@ void MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg, // then if index_file has not been previously opened, try to open it // clean up if failed - if ((do_magic && my_write(file, (byte*) BINLOG_MAGIC, 4, - MYF(MY_NABP|MY_WME)) || + if ((do_magic && my_b_write(&log_file, (byte*) BINLOG_MAGIC, 4)) || (index_file < 0 && - (index_file = my_fopen(index_file_name,O_APPEND | O_BINARY | O_RDWR, - MYF(MY_WME))) < 0))) - { - my_close(file,MYF(MY_WME)); - my_free(name,MYF(0)); - name=0; - file= -1; - log_type=LOG_CLOSED; - return; - } + (index_file = my_open(index_file_name,O_APPEND | O_BINARY | O_RDWR, + MYF(MY_WME))) < 0)) + goto err; Start_log_event s; - s.write(file); + s.write(&log_file); pthread_mutex_lock(&LOCK_index); - my_seek(index_file, 0L, MY_SEEK_END, MYF(MY_WME)); my_write(index_file, log_file_name,strlen(log_file_name), MYF(0)); my_write(index_file, "\n",1, MYF(0)); pthread_mutex_unlock(&LOCK_index); } + return; + +err: + if (file >= 0) + my_close(file,MYF(0)); + end_io_cache(&log_file); + x_free(name); name=0; + log_type=LOG_CLOSED; + + return; + } int MYSQL_LOG::get_current_log(LOG_INFO* linfo) { pthread_mutex_lock(&LOCK_log); - strmake(linfo->log_file_name, log_file_name, sizeof(linfo->log_file_name)); - linfo->pos = my_tell(file, MYF(MY_WME)); + strmake(linfo->log_file_name, log_file_name, sizeof(linfo->log_file_name)-1); + linfo->pos = my_b_tell(&log_file); pthread_mutex_unlock(&LOCK_log); return 0; } @@ -231,46 +237,46 @@ int MYSQL_LOG::get_current_log(LOG_INFO* linfo) // if log_name is "" we stop at the first entry int MYSQL_LOG::find_first_log(LOG_INFO* linfo, const char* log_name) { - // mutex needed because we need to make sure the file pointer does not move - // from under our feet - if (index_file < 0) return LOG_INFO_INVALID; + if (index_file < 0) + return LOG_INFO_INVALID; int error = 0; char* fname = linfo->log_file_name; int log_name_len = (uint) strlen(log_name); + IO_CACHE io_cache; + // mutex needed because we need to make sure the file pointer does not move + // from under our feet pthread_mutex_lock(&LOCK_index); - if (my_seek(index_file, 0L, MY_SEEK_SET, MYF(MY_WME) ) == MY_FILEPOS_ERROR) + if (init_io_cache(&io_cache, index_file, IO_SIZE, READ_CACHE, (my_off_t) 0, + 0, MYF(MY_WME))) { error = LOG_INFO_SEEK; goto err; } - for(;;) { - if (!fgets(fname, FN_REFLEN, index_file)) + uint length; + if (!(length=my_b_gets(&io_cache, fname, FN_REFLEN))) { - error = feof(index_file) ? LOG_INFO_EOF : LOG_INFO_IO; + error = !io_cache.error ? LOG_INFO_EOF : LOG_INFO_IO; goto err; } // if the log entry matches, empty string matching anything if (!log_name_len || - (fname[log_name_len] == '\n' && + (log_name_len == length+1 && fname[log_name_len] == '\n' && !memcmp(fname, log_name, log_name_len))) { - if (log_name_len) - fname[log_name_len] = 0; // to kill \n - else - { - *(strend(fname) - 1) = 0; - } - linfo->index_file_offset = my_tell(index_file, MYF(MY_WME)); + fname[length-1]=0; // remove last \n + linfo->index_file_offset = my_b_tell(&io_cache); break; } } error = 0; + err: pthread_mutex_unlock(&LOCK_index); + end_io_cache(&io_cache); return error; } @@ -283,27 +289,29 @@ int MYSQL_LOG::find_next_log(LOG_INFO* linfo) if (!index_file) return LOG_INFO_INVALID; int error = 0; char* fname = linfo->log_file_name; - char* end ; - - pthread_mutex_lock(&LOCK_index); - if (my_fseek(index_file, linfo->index_file_offset, MY_SEEK_SET, MYF(MY_WME) ) == MY_FILEPOS_ERROR) - { - error = LOG_INFO_SEEK; - goto err; - } + IO_CACHE io_cache; + uint length; - if (!fgets(fname, FN_REFLEN, index_file)) - { - error = feof(index_file) ? LOG_INFO_EOF : LOG_INFO_IO; - goto err; - } - - end = strend(fname) - 1; - *end = 0; // kill /n - linfo->index_file_offset = ftell(index_file); + pthread_mutex_lock(&LOCK_index); + if (init_io_cache(&io_cache, index_file, IO_SIZE, + READ_CACHE, (my_off_t) linfo->index_file_offset, 0, + MYF(MY_WME))) + { + error = LOG_INFO_SEEK; + goto err; + } + if (!(length=my_b_gets(&io_cache, fname, FN_REFLEN))) + { + error = !io_cache.error ? LOG_INFO_EOF : LOG_INFO_IO; + goto err; + } + fname[length-1]=0; // kill /n + linfo->index_file_offset = my_b_tell(&io_cache); error = 0; + err: pthread_mutex_unlock(&LOCK_index); + end_io_cache(&io_cache); return error; } @@ -311,22 +319,18 @@ err: // we assume that buf has at least FN_REFLEN bytes alloced void MYSQL_LOG::make_log_name(char* buf, const char* log_ident) { + buf[0] = 0; // In case of error if (inited) - { - int dir_len = dirname_length(log_file_name); - int ident_len = (uint) strlen(log_ident); - if (dir_len + ident_len + 1 > FN_REFLEN) - { - buf[0] = 0; - return; // protection agains malicious buffer overflow - } + { + int dir_len = dirname_length(log_file_name); + int ident_len = (uint) strlen(log_ident); + if (dir_len + ident_len + 1 > FN_REFLEN) + return; // protection agains malicious buffer overflow - memcpy(buf, log_file_name, dir_len); - memcpy(buf + dir_len, log_ident, ident_len + 1); // this takes care of \0 - // at the end - } - else - buf[0] = 0; + memcpy(buf, log_file_name, dir_len); + // copy filename + end null + memcpy(buf + dir_len, log_ident, ident_len + 1); + } } bool MYSQL_LOG::is_active(const char* log_file_name) @@ -336,15 +340,17 @@ bool MYSQL_LOG::is_active(const char* log_file_name) void MYSQL_LOG::new_file() { - if (file) + // only rotate open logs that are marked non-rotatable + // (binlog with constant name are non-rotatable) + if (is_open() && ! no_rotate) { - if (no_rotate) // do not rotate logs that are marked non-rotatable - return; // ( for binlog with constant name) - char new_name[FN_REFLEN], *old_name=name; VOID(pthread_mutex_lock(&LOCK_log)); if (generate_new_name(new_name, name)) + { + VOID(pthread_mutex_unlock(&LOCK_log)); return; // Something went wrong + } if (log_type == LOG_BIN) { /* @@ -352,15 +358,13 @@ void MYSQL_LOG::new_file() to change base names at some point. */ Rotate_log_event r(new_name+dirname_length(new_name)); - r.write(file); + r.write(&log_file); VOID(pthread_cond_broadcast(&COND_binlog_update)); } name=0; close(); open(old_name, log_type, new_name); my_free(old_name,MYF(0)); - if (!file) // Something went wrong - log_type=LOG_CLOSED; last_time=query_start=0; write_error=0; VOID(pthread_mutex_unlock(&LOCK_log)); @@ -375,7 +379,10 @@ void MYSQL_LOG::write(THD *thd,enum enum_server_command command, { va_list args; va_start(args,format); + char buff[32]; VOID(pthread_mutex_lock(&LOCK_log)); + + /* Test if someone closed after the is_open test */ if (log_type != LOG_CLOSED) { time_t skr; @@ -405,28 +412,30 @@ void MYSQL_LOG::write(THD *thd,enum enum_server_command command, struct tm *start; localtime_r(&skr,&tm_tmp); start=&tm_tmp; - if (fprintf(file,"%02d%02d%02d %2d:%02d:%02d\t", - start->tm_year % 100, - start->tm_mon+1, - start->tm_mday, - start->tm_hour, - start->tm_min, - start->tm_sec) < 0) + /* Note that my_b_write() assumes it knows the length for this */ + sprintf(buff,"%02d%02d%02d %2d:%02d:%02d\t", + start->tm_year % 100, + start->tm_mon+1, + start->tm_mday, + start->tm_hour, + start->tm_min, + start->tm_sec); + if (my_b_write(&log_file,buff,16)) error=errno; } - else if (fputs("\t\t",file) < 0) + else if (my_b_write(&log_file,"\t\t",2) < 0) error=errno; - if (fprintf(file,"%7ld %-10.10s", - id,command_name[(uint) command]) < 0) + sprintf(buff,"%7ld %-10.10s", id,command_name[(uint) command]); + if (my_b_write(&log_file,buff,strlen(buff))) error=errno; if (format) { - if (fputc(' ',file) < 0 || vfprintf(file,format,args) < 0) + if (my_b_write(&log_file," ",1) || + my_b_printf(&log_file,format,args) == (uint) -1) error=errno; } - if (fputc('\n',file) < 0) - error=errno; - if (fflush(file) < 0) + if (my_b_write(&log_file,"\n",1) || + flush_io_cache(&log_file)) error=errno; if (error && ! write_error) { @@ -446,7 +455,7 @@ void MYSQL_LOG::write(Query_log_event* event_info) if (is_open()) { VOID(pthread_mutex_lock(&LOCK_log)); - if (file) + if (is_open()) { THD *thd=event_info->thd; if ((!(thd->options & OPTION_BIN_LOG) && @@ -460,43 +469,38 @@ void MYSQL_LOG::write(Query_log_event* event_info) if (thd->last_insert_id_used) { Intvar_log_event e((uchar)LAST_INSERT_ID_EVENT, thd->last_insert_id); - if (e.write(file)) + if (e.write(&log_file)) { sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno); goto err; } } - if (thd->insert_id_used) { Intvar_log_event e((uchar)INSERT_ID_EVENT, thd->last_insert_id); - if (e.write(file)) + if (e.write(&log_file)) { sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno); goto err; } } - if (thd->convert_set) + { + char buf[1024] = "SET CHARACTER SET "; + char* p = strend(buf); + p = strmov(p, thd->convert_set->name); + int save_query_length = thd->query_length; + // just in case somebody wants it later + thd->query_length = (uint)(p - buf); + Query_log_event e(thd, buf); + if (e.write(&log_file)) { - char buf[1024] = "SET CHARACTER SET "; - char* p = strend(buf); - p = strmov(p, thd->convert_set->name); - int save_query_length = thd->query_length; - // just in case somebody wants it later - thd->query_length = (uint)(p - buf); - Query_log_event e(thd, buf); - if (e.write(file)) - { - sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno); - goto err; - } - - thd->query_length = save_query_length; // clean up - + sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno); + goto err; } - - if (event_info->write(file)) + thd->query_length = save_query_length; // clean up + } + if (event_info->write(&log_file) || flush_io_cache(&log_file)) { sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno); } @@ -512,13 +516,13 @@ void MYSQL_LOG::write(Load_log_event* event_info) if (is_open()) { VOID(pthread_mutex_lock(&LOCK_log)); - if (file) + if (is_open()) { THD *thd=event_info->thd; if ((thd->options & OPTION_BIN_LOG) || !(thd->master_access & PROCESS_ACL)) { - if (event_info->write(file)) + if (event_info->write(&log_file) || flush_io_cache(&log_file)) sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno); VOID(pthread_cond_broadcast(&COND_binlog_update)); } @@ -537,7 +541,7 @@ void MYSQL_LOG::write(THD *thd,const char *query, uint query_length, { time_t current_time; VOID(pthread_mutex_lock(&LOCK_log)); - if (file) + if (is_open()) { // Safety agains reopen int error=0; char buff[80],*end; @@ -556,37 +560,42 @@ void MYSQL_LOG::write(THD *thd,const char *query, uint query_length, last_time=current_time; struct tm tm_tmp; struct tm *start; + char buff[32]; localtime_r(¤t_time,&tm_tmp); start=&tm_tmp; - if (fprintf(file,"# Time: %02d%02d%02d %2d:%02d:%02d\n", - start->tm_year % 100, - start->tm_mon+1, - start->tm_mday, - start->tm_hour, - start->tm_min, - start->tm_sec) < 0) + /* Note that my_b_write() assumes it knows the length for this */ + sprintf(buff,"# Time: %02d%02d%02d %2d:%02d:%02d\n", + start->tm_year % 100, + start->tm_mon+1, + start->tm_mday, + start->tm_hour, + start->tm_min, + start->tm_sec); + if (my_b_write(&log_file,buff,24)) error=errno; } - if (fprintf(file, "# User@Host: %s [%s] @ %s [%s]\n", - thd->priv_user, - thd->user, - thd->host ? thd->host : "", - thd->ip ? thd->ip : "") < 0) - error=errno;; + if (my_b_printf(&log_file, "# User@Host: %s [%s] @ %s [%s]\n", + thd->priv_user, + thd->user, + thd->host ? thd->host : "", + thd->ip ? thd->ip : "")) + error=errno; } if (query_start) { /* For slow query log */ if (!(specialflag & SPECIAL_LONG_LOG_FORMAT)) current_time=time(NULL); - fprintf(file,"# Time: %lu Lock_time: %lu Rows_sent: %lu\n", - (ulong) (current_time - query_start), - (ulong) (thd->time_after_lock - query_start), - (ulong) thd->sent_row_count); + if (my_b_printf(&log_file, + "# Time: %lu Lock_time: %lu Rows_sent: %lu\n", + (ulong) (current_time - query_start), + (ulong) (thd->time_after_lock - query_start), + (ulong) thd->sent_row_count)) + error=errno; } if (thd->db && strcmp(thd->db,db)) { // Database changed - if (fprintf(file,"use %s;\n",thd->db) < 0) + if (my_b_printf(&log_file,"use %s;\n",thd->db)) error=errno; strmov(db,thd->db); } @@ -618,7 +627,8 @@ void MYSQL_LOG::write(THD *thd,const char *query, uint query_length, *end++=';'; *end++='\n'; *end=0; - if (fputs("SET ",file) < 0 || fputs(buff+1,file) < 0) + if (my_b_write(&log_file,"SET ",4) || + my_b_write(&log_file,buff+1,(uint) (end-buff)-1)) error=errno; } if (!query) @@ -626,10 +636,9 @@ void MYSQL_LOG::write(THD *thd,const char *query, uint query_length, query="#adminstrator command"; query_length=21; } - if (my_fwrite(file,(byte*) query,query_length,MYF(MY_NABP)) || - fputc(';',file) < 0 || fputc('\n',file) < 0) - error=errno; - if (fflush(file) < 0) + if (my_b_write(&log_file,(byte*) query,query_length) || + my_b_write(&log_file,";\n",2) || + flush_io_cache(&log_file)) error=errno; if (error && ! write_error) { @@ -641,51 +650,48 @@ void MYSQL_LOG::write(THD *thd,const char *query, uint query_length, } } - - +#ifdef TO_BE_REMOVED void MYSQL_LOG::flush() { - if (file) - if (fflush(file) < 0 && ! write_error) + if (is_open()) + if (flush_io_cache(log_file) && ! write_error) { write_error=1; sql_print_error(ER(ER_ERROR_ON_WRITE),name,errno); } } +#endif void MYSQL_LOG::close(bool exiting) { // One can't set log_type here! - if (file) + if (is_open()) { + File file=log_file.file; if (log_type == LOG_BIN) { Stop_log_event s; - s.write(file); + s.write(&log_file); VOID(pthread_cond_broadcast(&COND_binlog_update)); } - if (my_fclose(file,MYF(0)) < 0 && ! write_error) + end_io_cache(&log_file); + if (my_close(file,MYF(0)) < 0 && ! write_error) { write_error=1; sql_print_error(ER(ER_ERROR_ON_WRITE),name,errno); } - file=0; - } - if (name) - { - my_free(name,MYF(0)); - name=0; + log_type=LOG_CLOSED; } - - if (exiting && index_file) + if (exiting && index_file >= 0) { - if (my_fclose(index_file,MYF(0)) < 0 && ! write_error) + if (my_close(index_file,MYF(0)) < 0 && ! write_error) { write_error=1; sql_print_error(ER(ER_ERROR_ON_WRITE),name,errno); } index_file=0; } + safeFree(name); } diff --git a/sql/log_event.cc b/sql/log_event.cc index 3e717ce4d6c..7d9f22dea62 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -26,84 +26,78 @@ static void pretty_print_char(FILE* file, int c) { fputc('\'', file); - switch(c) - { - case '\n': fprintf(file, "\\n"); break; - case '\r': fprintf(file, "\\r"); break; - case '\\': fprintf(file, "\\\\"); break; - case '\b': fprintf(file, "\\b"); break; - case '\'': fprintf(file, "\\'"); break; - case 0 : fprintf(file, "\\0"); break; - default: - fputc(c, file); - break; - } - fputc( '\'', file); + switch(c) { + case '\n': fprintf(file, "\\n"); break; + case '\r': fprintf(file, "\\r"); break; + case '\\': fprintf(file, "\\\\"); break; + case '\b': fprintf(file, "\\b"); break; + case '\'': fprintf(file, "\\'"); break; + case 0 : fprintf(file, "\\0"); break; + default: + fputc(c, file); + break; + } + fputc('\'', file); } -int Query_log_event::write(FILE* file) +int Query_log_event::write(IO_CACHE* file) { return query ? Log_event::write(file) : -1; } -int Log_event::write(FILE* file) +int Log_event::write(IO_CACHE* file) { - if (write_header(file) - || write_data(file) || fflush(file)) return -1; - return 0; + return (write_header(file) || write_data(file)) ? -1 : 0; } -int Log_event::write_header(FILE* file) +int Log_event::write_header(IO_CACHE* file) { - char buf[LOG_EVENT_HEADER_LEN]; // make sure to change this when the header gets bigger + char buf[LOG_EVENT_HEADER_LEN]; char* pos = buf; int4store(pos, when); // timestamp pos += 4; *pos++ = get_type_code(); // event type code int4store(pos, server_id); pos += 4; - int4store(pos, get_data_size() + LOG_EVENT_HEADER_LEN); + long tmp=get_data_size() + LOG_EVENT_HEADER_LEN; + int4store(pos, tmp); pos += 4; - return (my_fwrite(file, (byte*) buf, (uint) (pos - buf), - MYF(MY_NABP | MY_WME))); + return (my_b_write(file, (byte*) buf, (uint) (pos - buf))); } #ifndef MYSQL_CLIENT -int Log_event::read_log_event(FILE* file, String* packet, +int Log_event::read_log_event(IO_CACHE* file, String* packet, pthread_mutex_t* log_lock) { ulong data_len; char buf[LOG_EVENT_HEADER_LEN]; - if(log_lock) + if (log_lock) pthread_mutex_lock(log_lock); - if (my_fread(file, (byte*)buf, sizeof(buf), MYF(MY_NABP))) - { - if(log_lock) pthread_mutex_unlock(log_lock); - return feof(file) ? LOG_READ_EOF: LOG_READ_IO; - } + if (my_b_read(file, (byte*) buf, sizeof(buf))) + { + if (log_lock) pthread_mutex_unlock(log_lock); + return file->error >= 0 ? LOG_READ_TRUNC: LOG_READ_IO; + } data_len = uint4korr(buf + EVENT_LEN_OFFSET); if (data_len < LOG_EVENT_HEADER_LEN || data_len > MAX_EVENT_LEN) - { - if(log_lock) pthread_mutex_unlock(log_lock); - return LOG_READ_BOGUS; - } + { + if (log_lock) pthread_mutex_unlock(log_lock); + return LOG_READ_BOGUS; + } packet->append(buf, sizeof(buf)); data_len -= LOG_EVENT_HEADER_LEN; - if (!data_len) - { - if(log_lock) pthread_mutex_unlock(log_lock); - return 0; // the event does not have a data section - } - if (packet->append(file, data_len, MYF(MY_WME|MY_NABP))) + if (data_len) + { + if (packet->append(file, data_len)) { if(log_lock) pthread_mutex_unlock(log_lock); - return feof(file) ? LOG_READ_TRUNC: LOG_READ_IO; + return file->error >= 0 ? LOG_READ_TRUNC: LOG_READ_IO; } - - if(log_lock) pthread_mutex_unlock(log_lock); + } + if (log_lock) pthread_mutex_unlock(log_lock); return 0; } @@ -111,18 +105,18 @@ int Log_event::read_log_event(FILE* file, String* packet, // allocates memory - the caller is responsible for clean-up -Log_event* Log_event::read_log_event(FILE* file, pthread_mutex_t* log_lock) +Log_event* Log_event::read_log_event(IO_CACHE* file, pthread_mutex_t* log_lock) { time_t timestamp; uint32 server_id; char buf[LOG_EVENT_HEADER_LEN-4]; if(log_lock) pthread_mutex_lock(log_lock); - if (my_fread(file, (byte *) buf, sizeof(buf), MY_NABP)) - { - if(log_lock) pthread_mutex_unlock(log_lock); - return NULL; - } + if (my_b_read(file, (byte *) buf, sizeof(buf))) + { + if (log_lock) pthread_mutex_unlock(log_lock); + return NULL; + } timestamp = uint4korr(buf); server_id = uint4korr(buf + 5); @@ -132,13 +126,11 @@ Log_event* Log_event::read_log_event(FILE* file, pthread_mutex_t* log_lock) { Query_log_event* q = new Query_log_event(file, timestamp, server_id); if(log_lock) pthread_mutex_unlock(log_lock); - if (!q->query) { delete q; - return NULL; + q=NULL; } - return q; } @@ -146,13 +138,11 @@ Log_event* Log_event::read_log_event(FILE* file, pthread_mutex_t* log_lock) { Load_log_event* l = new Load_log_event(file, timestamp, server_id); if(log_lock) pthread_mutex_unlock(log_lock); - if (!l->table_name) { delete l; - return NULL; + l=NULL; } - return l; } @@ -165,9 +155,8 @@ Log_event* Log_event::read_log_event(FILE* file, pthread_mutex_t* log_lock) if (!r->new_log_ident) { delete r; - return NULL; + r=NULL; } - return r; } @@ -179,9 +168,8 @@ Log_event* Log_event::read_log_event(FILE* file, pthread_mutex_t* log_lock) if (e->type == INVALID_INT_EVENT) { delete e; - return NULL; + e=NULL; } - return e; } @@ -198,12 +186,11 @@ Log_event* Log_event::read_log_event(FILE* file, pthread_mutex_t* log_lock) return e; } default: - if(log_lock) pthread_mutex_unlock(log_lock); - return NULL; + break; } - //impossible - if(log_lock) pthread_mutex_unlock(log_lock); + // default + if (log_lock) pthread_mutex_unlock(log_lock); return NULL; } @@ -320,26 +307,24 @@ void Rotate_log_event::print(FILE* file, bool short_form) fflush(file); } -Rotate_log_event::Rotate_log_event(FILE* file, time_t when_arg, +Rotate_log_event::Rotate_log_event(IO_CACHE* file, time_t when_arg, uint32 server_id): Log_event(when_arg, 0, 0, server_id),new_log_ident(NULL),alloced(0) { char *tmp_ident; char buf[4]; - if (my_fread(file, (byte*) buf, sizeof(buf), MYF(MY_NABP | MY_WME))) + if (my_b_read(file, (byte*) buf, sizeof(buf))) return; - ulong event_len; event_len = uint4korr(buf); - if(event_len < ROTATE_EVENT_OVERHEAD) + if (event_len < ROTATE_EVENT_OVERHEAD) return; ident_len = (uchar)(event_len - ROTATE_EVENT_OVERHEAD); - if (!(tmp_ident = (char*) my_malloc((uint)ident_len, MYF(MY_WME)))) return; - if (my_fread( file, (byte*) tmp_ident, (uint)ident_len, MYF(MY_NABP | MY_WME))) + if (my_b_read( file, (byte*) tmp_ident, (uint) ident_len)) { my_free((gptr) tmp_ident, MYF(0)); return; @@ -373,21 +358,18 @@ Rotate_log_event::Rotate_log_event(const char* buf, int max_buf): alloced = 1; } -int Rotate_log_event::write_data(FILE* file) +int Rotate_log_event::write_data(IO_CACHE* file) { - if (my_fwrite(file, (byte*) new_log_ident, (uint) ident_len, - MYF(MY_NABP | MY_WME))) - return -1; - return 0; + return my_b_write(file, (byte*) new_log_ident, (uint) ident_len) ? -1 :0; } -Query_log_event::Query_log_event(FILE* file, time_t when_arg, +Query_log_event::Query_log_event(IO_CACHE* file, time_t when_arg, uint32 server_id): Log_event(when_arg,0,0,server_id),data_buf(0),query(NULL),db(NULL) { char buf[QUERY_HEADER_LEN + 4]; ulong data_len; - if (my_fread(file, (byte*) buf, sizeof(buf), MYF(MY_NABP | MY_WME))) + if (my_b_read(file, (byte*) buf, sizeof(buf))) return; // query == NULL will tell the // caller there was a problem data_len = uint4korr(buf); @@ -399,9 +381,10 @@ Query_log_event::Query_log_event(FILE* file, time_t when_arg, db_len = (uint)buf[12]; error_code = uint2korr(buf + 13); + /* Allocate one byte extra for end \0 */ if (!(data_buf = (char*) my_malloc(data_len+1, MYF(MY_WME)))) return; - if (my_fread( file, (byte*) data_buf, data_len, MYF(MY_NABP | MY_WME))) + if (my_b_read( file, (byte*) data_buf, data_len)) { my_free((gptr) data_buf, MYF(0)); data_buf = 0; @@ -412,7 +395,7 @@ Query_log_event::Query_log_event(FILE* file, time_t when_arg, db = data_buf; query=data_buf + db_len + 1; q_len = data_len - 1 - db_len; - *((char*)query + q_len) = 0; + *((char*) query + q_len) = 0; // Safety } Query_log_event::Query_log_event(const char* buf, int max_buf): @@ -428,7 +411,7 @@ Query_log_event::Query_log_event(const char* buf, int max_buf): exec_time = uint4korr(buf + 8); error_code = uint2korr(buf + 13); - if (!(data_buf = (char*) my_malloc( data_len + 1, MYF(MY_WME)))) + if (!(data_buf = (char*) my_malloc(data_len + 1, MYF(MY_WME)))) return; memcpy(data_buf, buf + QUERY_HEADER_LEN + 4, data_len); @@ -455,9 +438,9 @@ void Query_log_event::print(FILE* file, bool short_form) fprintf(file, ";\n"); } -int Query_log_event::write_data(FILE* file) +int Query_log_event::write_data(IO_CACHE* file) { - if(!query) return -1; + if (!query) return -1; char buf[QUERY_HEADER_LEN]; char* pos = buf; @@ -469,23 +452,21 @@ int Query_log_event::write_data(FILE* file) int2store(pos, error_code); pos += 2; - if (my_fwrite(file, (byte*) buf, (uint)(pos - buf), MYF(MY_NABP | MY_WME)) || - my_fwrite(file, (db) ? (byte*) db : (byte*)"", - db_len + 1, MYF(MY_NABP | MY_WME)) || - my_fwrite(file, (byte*) query, q_len, MYF(MY_NABP | MY_WME))) - return -1; - return 0; + return (my_b_write(file, (byte*) buf, (uint)(pos - buf)) || + my_b_write(file, (db) ? (byte*) db : (byte*)"", db_len + 1) || + my_b_write(file, (byte*) query, q_len)) ? -1 : 0; } -Intvar_log_event:: Intvar_log_event(FILE* file, time_t when_arg, +Intvar_log_event:: Intvar_log_event(IO_CACHE* file, time_t when_arg, uint32 server_id) :Log_event(when_arg,0,0,server_id), type(INVALID_INT_EVENT) { - my_fseek(file, 4L, MY_SEEK_CUR, MYF(MY_WME)); // skip the event length - char buf[9]; - if(my_fread(file, (byte*)buf, sizeof(buf), MYF(MY_NABP|MY_WME))) return; - type = buf[0]; - val = uint8korr(buf+1); + char buf[9+4]; + if (!my_b_read(file, (byte*) buf, sizeof(buf))) + { + type = buf[4]; + val = uint8korr(buf+1+4); + } } Intvar_log_event::Intvar_log_event(const char* buf):Log_event(buf) @@ -495,12 +476,12 @@ Intvar_log_event::Intvar_log_event(const char* buf):Log_event(buf) val = uint8korr(buf+1); } -int Intvar_log_event::write_data(FILE* file) +int Intvar_log_event::write_data(IO_CACHE* file) { char buf[9]; buf[0] = type; int8store(buf + 1, val); - return my_fwrite(file, (byte*) buf, sizeof(buf), MYF(MY_NABP|MY_WME)); + return my_b_write(file, (byte*) buf, sizeof(buf)); } void Intvar_log_event::print(FILE* file, bool short_form) @@ -527,7 +508,7 @@ void Intvar_log_event::print(FILE* file, bool short_form) } -int Load_log_event::write_data(FILE* file __attribute__((unused))) +int Load_log_event::write_data(IO_CACHE* file) { char buf[LOAD_HEADER_LEN]; int4store(buf, thread_id); @@ -537,77 +518,46 @@ int Load_log_event::write_data(FILE* file __attribute__((unused))) buf[13] = (char)db_len; int4store(buf + 14, num_fields); - if(my_fwrite(file, (byte*)buf, sizeof(buf), MYF(MY_NABP|MY_WME)) || - my_fwrite(file, (byte*)&sql_ex, sizeof(sql_ex), MYF(MY_NABP|MY_WME))) + if(my_b_write(file, (byte*)buf, sizeof(buf)) || + my_b_write(file, (byte*)&sql_ex, sizeof(sql_ex))) return 1; - if(num_fields && fields && field_lens) - { - if(my_fwrite(file, (byte*)field_lens, num_fields, MYF(MY_NABP|MY_WME)) || - my_fwrite(file, (byte*)fields, field_block_len, MYF(MY_NABP|MY_WME))) - return 1; - } - - if(my_fwrite(file, (byte*)table_name, table_name_len + 1, MYF(MY_NABP|MY_WME)) || - my_fwrite(file, (byte*)db, db_len + 1, MYF(MY_NABP|MY_WME)) || - my_fwrite(file, (byte*)fname, fname_len, MYF(MY_NABP|MY_WME)) ) + if (num_fields && fields && field_lens) + { + if(my_b_write(file, (byte*)field_lens, num_fields) || + my_b_write(file, (byte*)fields, field_block_len)) + return 1; + } + if(my_b_write(file, (byte*)table_name, table_name_len + 1) || + my_b_write(file, (byte*)db, db_len + 1) || + my_b_write(file, (byte*)fname, fname_len)) return 1; - - return 0; } -Load_log_event::Load_log_event(FILE* file, time_t when, uint32 server_id): +Load_log_event::Load_log_event(IO_CACHE* file, time_t when, uint32 server_id): Log_event(when,0,0,server_id),data_buf(0),num_fields(0), fields(0),field_lens(0),field_block_len(0), table_name(0),db(0),fname(0) - { char buf[LOAD_HEADER_LEN + 4]; ulong data_len; - if(my_fread(file, (byte*)buf, sizeof(buf), MYF(MY_NABP|MY_WME)) || - my_fread(file, (byte*)&sql_ex, sizeof(sql_ex), MYF(MY_NABP|MY_WME))) - return; - - data_len = uint4korr(buf); - thread_id = uint4korr(buf+4); - exec_time = uint4korr(buf+8); - skip_lines = uint4korr(buf + 12); - table_name_len = (uint)buf[16]; - db_len = (uint)buf[17]; - num_fields = uint4korr(buf + 18); - - data_len -= LOAD_EVENT_OVERHEAD; - if(!(data_buf = (char*)my_malloc(data_len + 1, MYF(MY_WME)))) + if (my_b_read(file, (byte*)buf, sizeof(buf)) || + my_b_read(file, (byte*)&sql_ex, sizeof(sql_ex))) return; - if(my_fread(file, (byte*)data_buf, data_len, MYF(MY_NABP|MY_WME))) + data_len = uint4korr(buf) - LOAD_EVENT_OVERHEAD; + if (!(data_buf = (char*)my_malloc(data_len + 1, MYF(MY_WME)))) return; - - if(num_fields > data_len) // simple sanity check against corruption + if (my_b_read(file, (byte*)data_buf, data_len)) return; - - field_lens = (uchar*)data_buf; - - uint i; - for(i = 0; i < num_fields; i++) - { - field_block_len += (uint)field_lens[i] + 1; - } - fields = (char*)field_lens + num_fields; - - *((char*)data_buf+data_len) = 0; - table_name = fields + field_block_len; - db = table_name + table_name_len + 1; - fname = db + db_len + 1; - fname_len = data_len - 2 - db_len - table_name_len - num_fields - field_block_len; + copy_log_event(buf,data_len); } Load_log_event::Load_log_event(const char* buf, int max_buf): Log_event(when,0,0,server_id),data_buf(0),num_fields(0),fields(0), field_lens(0),field_block_len(0), table_name(0),db(0),fname(0) - { ulong data_len; @@ -617,9 +567,19 @@ Load_log_event::Load_log_event(const char* buf, int max_buf): buf += EVENT_LEN_OFFSET; data_len = uint4korr(buf); - if((uint)data_len > (uint)max_buf) + if ((uint)data_len > (uint) max_buf) return; + data_len -= LOAD_EVENT_OVERHEAD; + memcpy(&sql_ex, buf + 22, sizeof(sql_ex)); + if(!(data_buf = (char*)my_malloc(data_len + 1, MYF(MY_WME)))) + return; + memcpy(data_buf, buf + 22 + sizeof(sql_ex), data_len); + copy_log_event(buf, data_len); +} + +void Load_log_event::copy_log_event(const char *buf, ulong data_len) +{ thread_id = uint4korr(buf+4); exec_time = uint4korr(buf+8); skip_lines = uint4korr(buf + 12); @@ -627,32 +587,23 @@ Load_log_event::Load_log_event(const char* buf, int max_buf): db_len = (uint)buf[17]; num_fields = uint4korr(buf + 18); - data_len -= LOAD_EVENT_OVERHEAD; - memcpy(&sql_ex, buf + 22, sizeof(sql_ex)); - - if(!(data_buf = (char*)my_malloc(data_len + 1, MYF(MY_WME)))) + if (num_fields > data_len) // simple sanity check against corruption return; - memcpy(data_buf, buf + 22 + sizeof(sql_ex), data_len); - - if(num_fields > data_len) // simple sanity check against corruption - return; - - field_lens = (uchar*)data_buf; - + field_lens = (uchar*) data_buf; uint i; - for(i = 0; i < num_fields; i++) - { - field_block_len += (uint)field_lens[i] + 1; - } + for (i = 0; i < num_fields; i++) + { + field_block_len += (uint)field_lens[i] + 1; + } fields = (char*)field_lens + num_fields; *((char*)data_buf+data_len) = 0; table_name = fields + field_block_len; db = table_name + table_name_len + 1; fname = db + db_len + 1; - fname_len = data_len - 2 - db_len - table_name_len - num_fields - field_block_len; - + fname_len = data_len - 2 - db_len - table_name_len - num_fields - + field_block_len; } @@ -711,21 +662,21 @@ void Load_log_event::print(FILE* file, bool short_form) if((int)skip_lines > 0) fprintf(file, " IGNORE %ld LINES ", skip_lines); - if(num_fields) + if (num_fields) + { + uint i; + const char* field = fields; + fprintf( file, " ("); + for(i = 0; i < num_fields; i++) { - uint i; - const char* field = fields; - fprintf( file, " ("); - for(i = 0; i < num_fields; i++) - { - if(i) - fputc(',', file); - fprintf(file, field); + if(i) + fputc(',', file); + fprintf(file, field); - field += field_lens[i] + 1; - } - fputc(')', file); + field += field_lens[i] + 1; } + fputc(')', file); + } fprintf(file, ";\n"); } diff --git a/sql/log_event.h b/sql/log_event.h index 4b2739d1592..e903e9b39d9 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -65,9 +65,9 @@ public: int valid_exec_time; // if false, the exec time setting is bogus uint32 server_id; - int write(FILE* file); - int write_header(FILE* file); - virtual int write_data(FILE* file __attribute__((unused))) { return 0; } + int write(IO_CACHE* file); + int write_header(IO_CACHE* file); + virtual int write_data(IO_CACHE* file __attribute__((unused))) { return 0; } virtual Log_event_type get_type_code() = 0; Log_event(time_t when_arg, ulong exec_time_arg = 0, int valid_exec_time_arg = 0, uint32 server_id = 0): when(when_arg), @@ -92,11 +92,11 @@ public: void print_header(FILE* file); // if mutex is 0, the read will proceed without mutex - static Log_event* read_log_event(FILE* file, pthread_mutex_t* log_lock); + static Log_event* read_log_event(IO_CACHE* file, pthread_mutex_t* log_lock); static Log_event* read_log_event(const char* buf, int max_buf); #ifndef MYSQL_CLIENT - static int read_log_event(FILE* file, String* packet, + static int read_log_event(IO_CACHE* file, String* packet, pthread_mutex_t* log_lock); #endif @@ -132,18 +132,18 @@ public: } #endif - Query_log_event(FILE* file, time_t when, uint32 server_id); + Query_log_event(IO_CACHE* file, time_t when, uint32 server_id); Query_log_event(const char* buf, int max_buf); ~Query_log_event() { if (data_buf) { - my_free((gptr)data_buf, MYF(0)); + my_free((gptr) data_buf, MYF(0)); } } Log_event_type get_type_code() { return QUERY_EVENT; } - int write(FILE* file); - int write_data(FILE* file); // returns 0 on success, -1 on error + int write(IO_CACHE* file); + int write_data(IO_CACHE* file); // returns 0 on success, -1 on error int get_data_size() { return q_len + db_len + 2 + @@ -183,6 +183,8 @@ class Load_log_event: public Log_event { protected: char* data_buf; + void Load_log_event::copy_log_event(const char *buf, ulong data_len); + public: int thread_id; uint32 table_name_len; @@ -272,17 +274,17 @@ public: void set_fields(List<Item> &fields); #endif - Load_log_event(FILE* file, time_t when, uint32 server_id); + Load_log_event(IO_CACHE * file, time_t when, uint32 server_id); Load_log_event(const char* buf, int max_buf); ~Load_log_event() { if (data_buf) { - my_free((gptr)data_buf, MYF(0)); + my_free((gptr) data_buf, MYF(0)); } } Log_event_type get_type_code() { return LOAD_EVENT; } - int write_data(FILE* file); // returns 0 on success, -1 on error + int write_data(IO_CACHE* file); // returns 0 on success, -1 on error int get_data_size() { return table_name_len + 2 + db_len + 2 + fname_len @@ -311,30 +313,26 @@ public: created = (uint32) when; memcpy(server_version, ::server_version, sizeof(server_version)); } - Start_log_event(FILE* file, time_t when_arg, uint32 server_id) : + Start_log_event(IO_CACHE* file, time_t when_arg, uint32 server_id) : Log_event(when_arg, 0, 0, server_id) { char buf[sizeof(server_version) + sizeof(binlog_version) + - sizeof(created)]; - my_fseek(file, 4L, MY_SEEK_CUR, MYF(MY_WME)); // skip the event length - if (my_fread(file, (byte*) buf, sizeof(buf), MYF(MY_NABP | MY_WME))) + sizeof(created)+4]; + if (my_b_read(file, (byte*) buf, sizeof(buf))) return; - binlog_version = uint2korr(buf); - memcpy(server_version, buf + 2, sizeof(server_version)); - created = uint4korr(buf + 2 + sizeof(server_version)); + binlog_version = uint2korr(buf+4); + memcpy(server_version, buf + 6, sizeof(server_version)); + created = uint4korr(buf + 6 + sizeof(server_version)); } Start_log_event(const char* buf); ~Start_log_event() {} Log_event_type get_type_code() { return START_EVENT;} - int write_data(FILE* file) + int write_data(IO_CACHE* file) { - if(my_fwrite(file, (byte*) &binlog_version, sizeof(binlog_version), - MYF(MY_NABP | MY_WME)) || - my_fwrite(file, (byte*) server_version, sizeof(server_version), - MYF(MY_NABP | MY_WME)) || - my_fwrite(file, (byte*) &created, sizeof(created), - MYF(MY_NABP | MY_WME))) + if (my_b_write(file, (byte*) &binlog_version, sizeof(binlog_version)) || + my_b_write(file, (byte*) server_version, sizeof(server_version)) || + my_b_write(file, (byte*) &created, sizeof(created))) return -1; return 0; } @@ -354,12 +352,12 @@ public: Intvar_log_event(uchar type_arg, ulonglong val_arg) :Log_event(time(NULL)),val(val_arg),type(type_arg) {} - Intvar_log_event(FILE* file, time_t when, uint32 server_id); + Intvar_log_event(IO_CACHE* file, time_t when, uint32 server_id); Intvar_log_event(const char* buf); ~Intvar_log_event() {} Log_event_type get_type_code() { return INTVAR_EVENT;} int get_data_size() { return sizeof(type) + sizeof(val);} - int write_data(FILE* file); + int write_data(IO_CACHE* file); void print(FILE* file, bool short_form = 0); @@ -370,10 +368,11 @@ class Stop_log_event: public Log_event public: Stop_log_event() :Log_event(time(NULL)) {} - Stop_log_event(FILE* file, time_t when_arg, uint32 server_id): + Stop_log_event(IO_CACHE* file, time_t when_arg, uint32 server_id): Log_event(when_arg,0,0,server_id) { - my_fseek(file, 4L, MY_SEEK_CUR, MYF(MY_WME)); // skip the event length + char skip[4]; + my_b_read(file, skip, sizeof(skip)); // skip the event length } Stop_log_event(const char* buf):Log_event(buf) { @@ -397,7 +396,7 @@ public: alloced(0) {} - Rotate_log_event(FILE* file, time_t when, uint32 server_id) ; + Rotate_log_event(IO_CACHE* file, time_t when, uint32 server_id) ; Rotate_log_event(const char* buf, int max_buf); ~Rotate_log_event() { @@ -406,7 +405,7 @@ public: } Log_event_type get_type_code() { return ROTATE_EVENT;} int get_data_size() { return ident_len;} - int write_data(FILE* file); + int write_data(IO_CACHE* file); void print(FILE* file, bool short_form = 0); }; diff --git a/sql/mf_iocache.cc b/sql/mf_iocache.cc index 49df40adaf6..47c00a8ac00 100644 --- a/sql/mf_iocache.cc +++ b/sql/mf_iocache.cc @@ -32,17 +32,19 @@ #define MAP_TO_USE_RAID #include "mysql_priv.h" -#include <mysys_err.h> #ifdef HAVE_AIOWAIT +#include <mysys_err.h> #include <errno.h> static void my_aiowait(my_aio_result *result); #endif - /* if cachesize == 0 then use default cachesize (from s-file) */ - /* returns 0 if we have enough memory */ - extern "C" { + /* + ** if cachesize == 0 then use default cachesize (from s-file) + ** if file == -1 then real_open_cached_file() will be called. + ** returns 0 if ok + */ int init_io_cache(IO_CACHE *info, File file, uint cachesize, enum cache_type type, my_off_t seek_offset, @@ -60,20 +62,26 @@ int init_io_cache(IO_CACHE *info, File file, uint cachesize, min_cache=use_async_io ? IO_SIZE*4 : IO_SIZE*2; if (type == READ_CACHE) { /* Assume file isn't growing */ - my_off_t file_pos,end_of_file; - if ((file_pos=my_tell(file,MYF(0)) == MY_FILEPOS_ERROR)) - DBUG_RETURN(1); - end_of_file=my_seek(file,0L,MY_SEEK_END,MYF(0)); - if (end_of_file < seek_offset) - end_of_file=seek_offset; - VOID(my_seek(file,file_pos,MY_SEEK_SET,MYF(0))); - if ((my_off_t) cachesize > end_of_file-seek_offset+IO_SIZE*2-1) + if (cache_myflags & MY_DONT_CHECK_FILESIZE) + { + cache_myflags &= ~MY_DONT_CHECK_FILESIZE; + } + else { - cachesize=(uint) (end_of_file-seek_offset)+IO_SIZE*2-1; - use_async_io=0; /* No nead to use async */ + my_off_t file_pos,end_of_file; + if ((file_pos=my_tell(file,MYF(0)) == MY_FILEPOS_ERROR)) + DBUG_RETURN(1); + end_of_file=my_seek(file,0L,MY_SEEK_END,MYF(0)); + if (end_of_file < seek_offset) + end_of_file=seek_offset; + VOID(my_seek(file,file_pos,MY_SEEK_SET,MYF(0))); + if ((my_off_t) cachesize > end_of_file-seek_offset+IO_SIZE*2-1) + { + cachesize=(uint) (end_of_file-seek_offset)+IO_SIZE*2-1; + use_async_io=0; /* No nead to use async */ + } } } - if ((int) type < (int) READ_NET) { for (;;) @@ -167,7 +175,8 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type, DBUG_ENTER("reinit_io_cache"); info->seek_not_done= test(info->file >= 0); /* Seek not done */ - if (!clear_cache && seek_offset >= info->pos_in_file && + if (! clear_cache && + seek_offset >= info->pos_in_file && seek_offset <= info->pos_in_file + (uint) (info->rc_end - info->rc_request_pos)) { /* use current buffer */ @@ -231,6 +240,7 @@ int _my_b_read(register IO_CACHE *info, byte *Buffer, uint Count) { uint length,diff_length,left_length; my_off_t max_length, pos_in_file; + memcpy(Buffer,info->rc_pos, (size_t) (left_length=(uint) (info->rc_end-info->rc_pos))); Buffer+=left_length; @@ -607,7 +617,9 @@ int flush_io_cache(IO_CACHE *info) length=(uint) (info->rc_pos - info->buffer); if (info->seek_not_done) { /* File touched, do seek */ - VOID(my_seek(info->file,info->pos_in_file,MY_SEEK_SET,MYF(0))); + if (my_seek(info->file,info->pos_in_file,MY_SEEK_SET,MYF(0)) == + MY_FILEPOS_ERROR) + DBUG_RETURN((info->error= -1)); info->seek_not_done=0; } info->rc_pos=info->buffer; @@ -644,4 +656,4 @@ int end_io_cache(IO_CACHE *info) DBUG_RETURN(error); } /* end_io_cache */ -} +} /* extern "C" */ diff --git a/sql/mysqlbinlog.cc b/sql/mysqlbinlog.cc index 179bc717093..6c543d0bbf6 100644 --- a/sql/mysqlbinlog.cc +++ b/sql/mysqlbinlog.cc @@ -55,7 +55,7 @@ static struct option long_options[] = {"password", required_argument,0, 'p'}, {"position", required_argument,0, 'j'}, #ifndef DBUG_OFF - {"debug", required_argument, 0, '#'} + {"debug", optional_argument, 0, '#'} #endif }; @@ -151,7 +151,7 @@ static int parse_args(int *argc, char*** argv) { int c, opt_index = 0; - while((c = getopt_long(*argc, *argv, "so:#:h:j:u:p:P:t:?", long_options, + while((c = getopt_long(*argc, *argv, "so:#::h:j:u:p:P:t:?", long_options, &opt_index)) != EOF) { switch(c) @@ -310,86 +310,106 @@ Unfortunately, no sweepstakes today, adjusted position to 4\n"); static void dump_local_log_entries(const char* logname) { - FILE* file; - int rec_count = 0; - - if(logname && logname[0] != '-') - file = my_fopen(logname, O_RDONLY|O_BINARY, MYF(MY_WME)); - else - file = stdin; - - if(!file) - die("Could not open log file %s", logname); - - if(my_fseek(file, position, MY_SEEK_SET, MYF(MY_WME))) - die("failed on my_fseek()"); - - if(!position) - { - char magic[4]; - if (my_fread(file, (byte*) magic, sizeof(magic), MYF(MY_NABP|MY_WME))) - die("I/O error reading binlog magic number"); - if(memcmp(magic, BINLOG_MAGIC, 4)) - die("Bad magic number"); + File fd; + IO_CACHE cache,*file= &cache; + int rec_count = 0; + + if (logname && logname[0] != '-') + { + if ((fd = my_open(logname, O_RDONLY | O_BINARY, MYF(MY_WME))) < 0) + exit(1); + if (init_io_cache(file, fd, 0, READ_CACHE, (my_off_t) position, 0, + MYF(MY_WME | MY_NABP))) + exit(1); + } + else + { + if (init_io_cache(file, fileno(stdout), 0, READ_CACHE, (my_off_t) 0, + 0, MYF(MY_WME | MY_NABP | MY_DONT_CHECK_FILESIZE))) + exit(1); + if (position) + { + /* skip 'position' characters from stdout */ + char buff[IO_SIZE]; + my_off_t length,tmp; + for (length=position ; length > 0 ; length-=tmp) + { + tmp=min(length,sizeof(buff)); + if (my_b_read(file,buff,tmp)) + exit(1); + } + } + file->pos_in_file=position; + file->seek_not_done=0; + } + + if (!position) + { + char magic[4]; + if (my_b_read(file, (byte*) magic, sizeof(magic))) + die("I/O error reading binlog magic number"); + if(memcmp(magic, BINLOG_MAGIC, 4)) + die("Bad magic number"); } - while(1) - { - Log_event* ev = Log_event::read_log_event(file, 0); - if(!ev) - if(!feof(file)) + while(1) + { + Log_event* ev = Log_event::read_log_event(file, 0); + if (!ev) + { + if (file->error) die("Could not read entry at offset %ld : Error in log format or \ read error", - my_ftell(file, MYF(MY_WME))); - else - break; - - if(rec_count >= offset) - ev->print(stdout, short_form); - rec_count++; - delete ev; - } - - my_fclose(file, MYF(MY_WME)); + my_b_tell(file)); + break; + } + if (rec_count >= offset) + ev->print(stdout, short_form); + rec_count++; + delete ev; + } + my_close(fd, MYF(MY_WME)); + end_io_cache(file); } + int main(int argc, char** argv) { MY_INIT(argv[0]); parse_args(&argc, (char***)&argv); if(!argc && !table) - { - usage(); - return -1; - } + { + usage(); + return -1; + } if(use_remote) - { - init_thr_alarm(10); // need to do this manually - mysql = safe_connect(); - } + { + init_thr_alarm(10); // need to do this manually + mysql = safe_connect(); + } - if(table) - { - if(!use_remote) - die("You must specify connection parameter to get table dump"); - char* db = (char*)table; - char* tbl = (char*) strchr(table, '.'); - if(!tbl) - die("You must use database.table syntax to specify the table"); - *tbl++ = 0; - dump_remote_table(&mysql->net, db, tbl); - } + if (table) + { + if(!use_remote) + die("You must specify connection parameter to get table dump"); + char* db = (char*)table; + char* tbl = (char*) strchr(table, '.'); + if(!tbl) + die("You must use database.table syntax to specify the table"); + *tbl++ = 0; + dump_remote_table(&mysql->net, db, tbl); + } else - while(--argc >= 0) + { + while(--argc >= 0) { dump_log_entries(*(argv++)); } - - if(use_remote) + } + if (use_remote) mc_mysql_close(mysql); - return 0; } diff --git a/sql/net_pkg.cc b/sql/net_pkg.cc index 2308aa40d52..d412b71b363 100644 --- a/sql/net_pkg.cc +++ b/sql/net_pkg.cc @@ -319,11 +319,11 @@ bool net_store_data(String* packet, I_List<i_string>* str_list) i_string* s; while((s=it++)) - { - if(tmp.length()) - tmp.append(','); - tmp.append(s->ptr); - } + { + if(tmp.length()) + tmp.append(','); + tmp.append(s->ptr); + } return net_store_data(packet, (char*)tmp.ptr(), tmp.length()); } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index b65c5d1978f..7c0ad74424c 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -113,11 +113,17 @@ THD::THD() ull=0; system_thread=0; bzero((char*) &mem_root,sizeof(mem_root)); +#if defined(HAVE_BDB) || defined(HAVE_INNOBASE) || defined(HAVE_GEMENI) + if (open_cached_file(&transactions.trans_log, + mysql_tempdir,LOG_PREFIX,0,MYF(MY_WME))) + killed=1; + transaction.bdb_lock_count=0; +#endif + transaction.bdb_tid=0; + #ifdef __WIN__ real_id = 0 ; #endif - transaction.bdb_lock_count=0; - transaction.bdb_tid=0; } THD::~THD() @@ -136,6 +142,9 @@ THD::~THD() close_thread_tables(this); } close_temporary_tables(this); +#if defined(HAVE_BDB) || defined(HAVE_INNOBASE) || defined(HAVE_GEMENI) + close_cached_file(transactions.trans_log); +#endif if (global_read_lock) { pthread_mutex_lock(&LOCK_open); diff --git a/sql/sql_class.h b/sql/sql_class.h index 23e518ab790..b18781ca72c 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -82,16 +82,16 @@ typedef struct st_master_info } MASTER_INFO; class MYSQL_LOG { - public: private: pthread_mutex_t LOCK_log, LOCK_index; - File file, index_file; time_t last_time,query_start; + IO_CACHE log_file; + File index_file; char *name; - enum_log_type log_type; + volatile enum_log_type log_type; char time_buff[20],db[NAME_LEN+1]; char log_file_name[FN_REFLEN],index_file_name[FN_REFLEN]; - bool write_error,inited; + bool write_error,inited,opened; bool no_rotate; // for binlog - if log name can never change // we should not try to rotate it or write any rotation events // the user should use FLUSH MASTER instead of FLUSH LOGS for @@ -114,7 +114,7 @@ public: int generate_new_name(char *new_name,const char *old_name); void make_log_name(char* buf, const char* log_ident); bool is_active(const char* log_file_name); - void flush(void); + // void flush(void); void close(bool exiting = 0); // if we are exiting, we also want to close the // index file @@ -270,6 +270,7 @@ public: thr_lock_type update_lock_default; delayed_insert *di; struct st_transactions { + IO_CACHE trans_log; void *bdb_tid; uint bdb_lock_count; } transaction; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c76a6be2d26..8322af7953e 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2439,7 +2439,7 @@ bool reload_acl_and_cache(THD *thd, uint options, TABLE_LIST *tables) bool result=0; select_errors=0; /* Write if more errors */ - mysql_log.flush(); // Flush log + // mysql_log.flush(); // Flush log if (options & REFRESH_GRANT) { acl_reload(); diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 53a5b00d084..b2b21468017 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -93,284 +93,284 @@ static int send_file(THD *thd) DBUG_RETURN(error); } + +static File open_log(IO_CACHE *log, const char *log_file_name, + const char **errmsg) +{ + File file; + char magic[4]; + if ((file = my_open(log_file_name, O_RDONLY | O_BINARY, MYF(MY_WME))) < 0 || + init_io_cache(log, file, IO_SIZE*2, READ_CACHE, 0, 0, + MYF(MY_WME))) + { + *errmsg = "Could not open log file"; // This will not be sent + goto err; + } + + if (my_b_read(log, (byte*) magic, sizeof(magic))) + { + *errmsg = "I/O error reading binlog magic number"; + goto err; + } + if (memcmp(magic, BINLOG_MAGIC, 4)) + { + *errmsg = "Binlog has bad magic number, fire your magician"; + goto err; + } + return file; + +err: + if (file > 0) + my_close(file,MYF(0)); + end_io_cache(log); + return -1; +} + + void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags) { LOG_INFO linfo; char *log_file_name = linfo.log_file_name; char search_file_name[FN_REFLEN]; - char magic[4]; - FILE* log = NULL; + IO_CACHE log; + File file = -1; String* packet = &thd->packet; int error; const char *errmsg = "Unknown error"; NET* net = &thd->net; - DBUG_ENTER("mysql_binlog_send"); + bzero((char*) &log,sizeof(log)); + if(!mysql_bin_log.is_open()) - { - errmsg = "Binary log is not open"; - goto err; - } + { + errmsg = "Binary log is not open"; + goto err; + } - if(log_ident[0]) + if (log_ident[0]) mysql_bin_log.make_log_name(search_file_name, log_ident); else search_file_name[0] = 0; - if(mysql_bin_log.find_first_log(&linfo, search_file_name)) - { - errmsg = "Could not find first log"; - goto err; - } - log = my_fopen(log_file_name, O_RDONLY|O_BINARY, MYF(MY_WME)); + if (mysql_bin_log.find_first_log(&linfo, search_file_name)) + { + errmsg = "Could not find first log"; + goto err; + } - if(!log) - { - errmsg = "Could not open log file"; - goto err; - } - - if(my_fread(log, (byte*) magic, sizeof(magic), MYF(MY_NABP|MY_WME))) - { - errmsg = "I/O error reading binlog magic number"; - goto err; - } - if(memcmp(magic, BINLOG_MAGIC, 4)) - { - errmsg = "Binlog has bad magic number, fire your magician"; - goto err; - } + if ((file=open_log(&log, log_file_name, &errmsg)) < 0) + goto err; if(pos < 4) - { - errmsg = "Contratulations! You have hit the magic number and can win \ + { + errmsg = "Contratulations! You have hit the magic number and can win \ sweepstakes if you report the bug"; - goto err; - } - - if(my_fseek(log, pos, MY_SEEK_SET, MYF(MY_WME)) == MY_FILEPOS_ERROR ) - { - errmsg = "Error on fseek()"; - goto err; - } - - + goto err; + } + + my_b_seek(&log, pos); // Seek will done on next read packet->length(0); packet->append("\0", 1); // we need to start a packet with something other than 255 // to distiquish it from error while(!net->error && net->vio != 0 && !thd->killed) - { - pthread_mutex_t *log_lock = mysql_bin_log.get_log_lock(); + { + pthread_mutex_t *log_lock = mysql_bin_log.get_log_lock(); - while(!(error = Log_event::read_log_event(log, packet, log_lock))) - { - if(my_net_write(net, (char*)packet->ptr(), packet->length()) ) - { - errmsg = "Failed on my_net_write()"; - goto err; - } - DBUG_PRINT("info", ("log event code %d", - (*packet)[LOG_EVENT_OFFSET+1] )); - if((*packet)[LOG_EVENT_OFFSET+1] == LOAD_EVENT) - { - if(send_file(thd)) - { - errmsg = "failed in send_file()"; - goto err; - } - } - packet->length(0); - packet->append("\0",1); - } - if(error != LOG_READ_EOF) + while (!(error = Log_event::read_log_event(&log, packet, log_lock))) + { + if(my_net_write(net, (char*)packet->ptr(), packet->length()) ) + { + errmsg = "Failed on my_net_write()"; + goto err; + } + DBUG_PRINT("info", ("log event code %d", + (*packet)[LOG_EVENT_OFFSET+1] )); + if((*packet)[LOG_EVENT_OFFSET+1] == LOAD_EVENT) + { + if(send_file(thd)) { - switch(error) - { - case LOG_READ_BOGUS: - errmsg = "bogus data in log event"; - break; - case LOG_READ_IO: - errmsg = "I/O error reading log event"; - break; - case LOG_READ_MEM: - errmsg = "memory allocation failed reading log event"; - break; - case LOG_READ_TRUNC: - errmsg = "binlog truncated in the middle of event"; - break; - } + errmsg = "failed in send_file()"; goto err; } + } + packet->length(0); + packet->append("\0",1); + } + if(error != LOG_READ_EOF) + { + switch(error) + { + case LOG_READ_BOGUS: + errmsg = "bogus data in log event"; + break; + case LOG_READ_IO: + errmsg = "I/O error reading log event"; + break; + case LOG_READ_MEM: + errmsg = "memory allocation failed reading log event"; + break; + case LOG_READ_TRUNC: + errmsg = "binlog truncated in the middle of event"; + break; + } + goto err; + } - if(!(flags & BINLOG_DUMP_NON_BLOCK) && - mysql_bin_log.is_active(log_file_name)) - // block until there is more data in the log - // unless non-blocking mode requested - { - if(net_flush(net)) - { - errmsg = "failed on net_flush()"; - goto err; - } + if(!(flags & BINLOG_DUMP_NON_BLOCK) && + mysql_bin_log.is_active(log_file_name)) + // block until there is more data in the log + // unless non-blocking mode requested + { + if(net_flush(net)) + { + errmsg = "failed on net_flush()"; + goto err; + } - // we may have missed the update broadcast from the log - // that has just happened, let's try to catch it if it did - // if we did not miss anything, we just wait for other threads - // to signal us - { - clearerr(log); - - // tell the kill thread how to wake us up - pthread_mutex_lock(&thd->mysys_var->mutex); - thd->mysys_var->current_mutex = log_lock; - thd->mysys_var->current_cond = &COND_binlog_update; - const char* proc_info = thd->proc_info; - thd->proc_info = "Waiting for update"; - pthread_mutex_unlock(&thd->mysys_var->mutex); - - bool read_packet = 0, fatal_error = 0; - - // no one will update the log while we are reading - // now, but we'll be quick and just read one record - switch(Log_event::read_log_event(log, packet, log_lock)) - { - case 0: - read_packet = 1; - // we read successfully, so we'll need to send it to the - // slave - break; - case LOG_READ_EOF: - pthread_mutex_lock(log_lock); - pthread_cond_wait(&COND_binlog_update, log_lock); - pthread_mutex_unlock(log_lock); - break; - - default: - fatal_error = 1; - break; - } - - - pthread_mutex_lock(&thd->mysys_var->mutex); - thd->mysys_var->current_mutex= 0; - thd->mysys_var->current_cond= 0; - thd->proc_info= proc_info; - pthread_mutex_unlock(&thd->mysys_var->mutex); - - if(read_packet) - { - thd->proc_info = "sending update to slave"; - if(my_net_write(net, (char*)packet->ptr(), packet->length()) ) - { - errmsg = "Failed on my_net_write()"; - goto err; - } - - if((*packet)[LOG_EVENT_OFFSET+1] == LOAD_EVENT) - { - if(send_file(thd)) - { - errmsg = "failed in send_file()"; - goto err; - } - } - packet->length(0); - packet->append("\0",1); - // no need to net_flush because we will get to flush later when - // we hit EOF pretty quick - } + // we may have missed the update broadcast from the log + // that has just happened, let's try to catch it if it did + // if we did not miss anything, we just wait for other threads + // to signal us + { + log.error=0; - if(fatal_error) - { - errmsg = "error reading log entry"; - goto err; - } + // tell the kill thread how to wake us up + pthread_mutex_lock(&thd->mysys_var->mutex); + thd->mysys_var->current_mutex = log_lock; + thd->mysys_var->current_cond = &COND_binlog_update; + const char* proc_info = thd->proc_info; + thd->proc_info = "Waiting for update"; + pthread_mutex_unlock(&thd->mysys_var->mutex); - clearerr(log); - } - } - else + bool read_packet = 0, fatal_error = 0; + + // no one will update the log while we are reading + // now, but we'll be quick and just read one record + switch(Log_event::read_log_event(&log, packet, log_lock)) { - bool loop_breaker = 0; - // need this to break out of the for loop from switch - thd->proc_info = "switching to next log"; - switch(mysql_bin_log.find_next_log(&linfo)) - { - case LOG_INFO_EOF: - loop_breaker = (flags & BINLOG_DUMP_NON_BLOCK); - break; - case 0: - break; - default: - errmsg = "could not find next log"; - goto err; - } + case 0: + read_packet = 1; + // we read successfully, so we'll need to send it to the + // slave + break; + case LOG_READ_EOF: + pthread_mutex_lock(log_lock); + pthread_cond_wait(&COND_binlog_update, log_lock); + pthread_mutex_unlock(log_lock); + break; + + default: + fatal_error = 1; + break; + } - if(loop_breaker) - break; - (void) my_fclose(log, MYF(MY_WME)); - log = my_fopen(log_file_name, O_RDONLY|O_BINARY, MYF(MY_WME)); - if(!log) - { - errmsg = "Could not open next log"; - goto err; - } + pthread_mutex_lock(&thd->mysys_var->mutex); + thd->mysys_var->current_mutex= 0; + thd->mysys_var->current_cond= 0; + thd->proc_info= proc_info; + pthread_mutex_unlock(&thd->mysys_var->mutex); - //check the magic - if(my_fread(log, (byte*) magic, sizeof(magic), MYF(MY_NABP|MY_WME))) - { - errmsg = "I/O error reading binlog magic number"; - goto err; - } - if(memcmp(magic, BINLOG_MAGIC, 4)) + if(read_packet) + { + thd->proc_info = "sending update to slave"; + if(my_net_write(net, (char*)packet->ptr(), packet->length()) ) + { + errmsg = "Failed on my_net_write()"; + goto err; + } + + if((*packet)[LOG_EVENT_OFFSET+1] == LOAD_EVENT) + { + if(send_file(thd)) { - errmsg = "Binlog has bad magic number, fire your magician"; + errmsg = "failed in send_file()"; goto err; } - - // fake Rotate_log event just in case it did not make it to the log - // otherwise the slave make get confused about the offset - { - char header[LOG_EVENT_HEADER_LEN]; - memset(header, 0, 4); // when does not matter - header[EVENT_TYPE_OFFSET] = ROTATE_EVENT; - char* p = strrchr(log_file_name, FN_LIBCHAR); - // find the last slash - if(p) - p++; - else - p = log_file_name; - - uint ident_len = (uint) strlen(p); - ulong event_len = ident_len + sizeof(header); - int4store(header + EVENT_TYPE_OFFSET + 1, server_id); - int4store(header + EVENT_LEN_OFFSET, event_len); - packet->append(header, sizeof(header)); - packet->append(p,ident_len); - if(my_net_write(net, (char*)packet->ptr(), packet->length())) - { - errmsg = "failed on my_net_write()"; - goto err; - } - packet->length(0); - packet->append("\0",1); } + packet->length(0); + packet->append("\0",1); + // no need to net_flush because we will get to flush later when + // we hit EOF pretty quick } + + if(fatal_error) + { + errmsg = "error reading log entry"; + goto err; + } + log.error=0; + } + } + else + { + bool loop_breaker = 0; + // need this to break out of the for loop from switch + thd->proc_info = "switching to next log"; + switch(mysql_bin_log.find_next_log(&linfo)) + { + case LOG_INFO_EOF: + loop_breaker = (flags & BINLOG_DUMP_NON_BLOCK); + break; + case 0: + break; + default: + errmsg = "could not find next log"; + goto err; + } + + if(loop_breaker) + break; + + end_io_cache(&log); + (void) my_close(file, MYF(MY_WME)); + if ((file=open_log(&log, log_file_name, &errmsg)) < 0) + goto err; + + // fake Rotate_log event just in case it did not make it to the log + // otherwise the slave make get confused about the offset + { + char header[LOG_EVENT_HEADER_LEN]; + memset(header, 0, 4); // when does not matter + header[EVENT_TYPE_OFFSET] = ROTATE_EVENT; + char* p = strrchr(log_file_name, FN_LIBCHAR); + // find the last slash + if(p) + p++; + else + p = log_file_name; + + uint ident_len = (uint) strlen(p); + ulong event_len = ident_len + sizeof(header); + int4store(header + EVENT_TYPE_OFFSET + 1, server_id); + int4store(header + EVENT_LEN_OFFSET, event_len); + packet->append(header, sizeof(header)); + packet->append(p,ident_len); + if(my_net_write(net, (char*)packet->ptr(), packet->length())) + { + errmsg = "failed on my_net_write()"; + goto err; + } + packet->length(0); + packet->append("\0",1); + } } + } - (void)my_fclose(log, MYF(MY_WME)); + end_io_cache(&log); + (void)my_close(file, MYF(MY_WME)); send_eof(&thd->net); thd->proc_info = "waiting to finalize termination"; DBUG_VOID_RETURN; err: thd->proc_info = "waiting to finalize termination"; - if(log) - (void) my_fclose(log, MYF(MY_WME)); + end_io_cache(&log); + if (file >= 0) + (void) my_close(file, MYF(MY_WME)); send_error(&thd->net, 0, errmsg); DBUG_VOID_RETURN; } diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 7ca2d3c419e..4b9ebef21f1 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -95,17 +95,6 @@ bool String::realloc(uint32 alloc_length) return FALSE; } - -#ifdef NOT_NEEDED -bool String::set(long num) -{ - if (alloc(14)) - return TRUE; - str_length=(uint32) (int10_to_str(num,Ptr,-10)-Ptr); - return FALSE; -} -#endif - bool String::set(longlong num) { if (alloc(21)) @@ -274,6 +263,7 @@ bool String::append(const char *s,uint32 arg_length) return FALSE; } +#ifdef TO_BE_REMOVED bool String::append(FILE* file, uint32 arg_length, myf my_flags) { if (realloc(str_length+arg_length)) @@ -286,6 +276,20 @@ bool String::append(FILE* file, uint32 arg_length, myf my_flags) str_length+=arg_length; return FALSE; } +#endif + +bool String::append(IO_CACHE* file, uint32 arg_length) +{ + if (realloc(str_length+arg_length)) + return TRUE; + if (my_b_read(file, (byte*) Ptr + str_length, arg_length)) + { + shrink(str_length); + return TRUE; + } + str_length+=arg_length; + return FALSE; +} uint32 String::numchars() { diff --git a/sql/sql_string.h b/sql/sql_string.h index 45c82b82dd0..74dbc4cc6bd 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -152,7 +152,7 @@ public: bool copy(const char *s,uint32 arg_length); // Allocate new string bool append(const String &s); bool append(const char *s,uint32 arg_length=0); - bool append(FILE* file, uint32 arg_length, myf my_flags); + bool append(IO_CACHE* file, uint32 arg_length); int strstr(const String &search,uint32 offset=0); // Returns offset to substring or -1 int strrstr(const String &search,uint32 offset=0); // Returns offset to substring or -1 bool replace(uint32 offset,uint32 arg_length,const String &to); diff --git a/sql/time.cc b/sql/time.cc index 17603d93dd4..ce4b5b0e30c 100644 --- a/sql/time.cc +++ b/sql/time.cc @@ -413,16 +413,6 @@ ulong convert_month_to_period(ulong month) return year*100+month%12+1; } -#ifdef NOT_NEEDED - -ulong add_to_period(ulong period,int months) -{ - if (period == 0L) - return 0L; - return convert_month_to_period(convert_period_to_month(period)+months); -} -#endif - /***************************************************************************** ** convert a timestamp string to a TIME value. |