diff options
author | unknown <monty@narttu.mysql.fi> | 2000-11-16 00:24:11 +0200 |
---|---|---|
committer | unknown <monty@narttu.mysql.fi> | 2000-11-16 00:24:11 +0200 |
commit | c7d2c59ceb4e3548eb74e5d8fba16e0f41ffc7d9 (patch) | |
tree | 31119bae32d48d3c415144eb5aed588455eefa1a /sql | |
parent | dcf4e49369d91b78ab73b9de038d2729afb3a2a6 (diff) | |
parent | 9a846a52ae62f701c2d54d3f468e2ead393acf91 (diff) | |
download | mariadb-git-c7d2c59ceb4e3548eb74e5d8fba16e0f41ffc7d9.tar.gz |
merge
configure.in:
Auto merged
include/my_sys.h:
Auto merged
libmysql/libmysql.c:
Auto merged
sql/ha_berkeley.cc:
Auto merged
sql/handler.h:
Auto merged
sql/item_strfunc.cc:
Auto merged
sql/lex.h:
Auto merged
sql/mysqld.cc:
Auto merged
sql/sql_class.cc:
Auto merged
sql/sql_insert.cc:
Auto merged
sql/sql_lex.h:
Auto merged
sql/sql_select.cc:
Auto merged
sql/sql_string.h:
Auto merged
BitKeeper/etc/logging_ok:
Auto merged
Diffstat (limited to 'sql')
-rw-r--r-- | sql/filesort.cc | 22 | ||||
-rw-r--r-- | sql/ha_berkeley.cc | 26 | ||||
-rw-r--r-- | sql/ha_berkeley.h | 3 | ||||
-rw-r--r-- | sql/handler.h | 1 | ||||
-rw-r--r-- | sql/item_create.cc | 5 | ||||
-rw-r--r-- | sql/item_create.h | 1 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 2 | ||||
-rw-r--r-- | sql/lex.h | 2 | ||||
-rw-r--r-- | sql/lock.cc | 4 | ||||
-rw-r--r-- | sql/log.cc | 439 | ||||
-rw-r--r-- | sql/log_event.cc | 298 | ||||
-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/mysqld.cc | 20 | ||||
-rw-r--r-- | sql/net_pkg.cc | 10 | ||||
-rw-r--r-- | sql/sql_class.cc | 13 | ||||
-rw-r--r-- | sql/sql_class.h | 10 | ||||
-rw-r--r-- | sql/sql_insert.cc | 8 | ||||
-rw-r--r-- | sql/sql_lex.h | 24 | ||||
-rw-r--r-- | sql/sql_load.cc | 2 | ||||
-rw-r--r-- | sql/sql_parse.cc | 36 | ||||
-rw-r--r-- | sql/sql_repl.cc | 454 | ||||
-rw-r--r-- | sql/sql_select.cc | 11 | ||||
-rw-r--r-- | sql/sql_string.cc | 26 | ||||
-rw-r--r-- | sql/sql_string.h | 2 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 18 | ||||
-rw-r--r-- | sql/time.cc | 10 | ||||
-rw-r--r-- | sql/violite.c | 46 |
29 files changed, 900 insertions, 848 deletions
diff --git a/sql/filesort.cc b/sql/filesort.cc index 6d6bbe00182..220ff69a3e8 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -38,8 +38,8 @@ if (my_b_write((file),(byte*) (from),param->ref_length)) \ typedef struct st_buffpek { /* Struktur om sorteringsbuffrarna */ my_off_t file_pos; /* Where we are in the sort file */ - ha_rows count; /* Number of rows in table */ uchar *base,*key; /* key pointers */ + ha_rows count; /* Number of rows in table */ ulong mem_count; /* numbers of keys in memory */ ulong max_keys; /* Max keys in buffert */ } BUFFPEK; @@ -98,7 +98,6 @@ ha_rows filesort(TABLE **table, SORT_FIELD *sortorder, uint s_length, BUFFPEK *buffpek; ha_rows records; uchar **sort_keys; - gptr save_1,save_2; IO_CACHE tempfile,*selected_records_file,*outfile; SORTPARAM param; DBUG_ENTER("filesort"); @@ -109,7 +108,6 @@ ha_rows filesort(TABLE **table, SORT_FIELD *sortorder, uint s_length, outfile= table[0]->io_cache; my_b_clear(&tempfile); - save_1=save_2=0; buffpek= (BUFFPEK *) NULL; sort_keys= (uchar **) NULL; error= 1; maxbuffer=1; param.ref_length= table[0]->file->ref_length; @@ -148,7 +146,7 @@ ha_rows filesort(TABLE **table, SORT_FIELD *sortorder, uint s_length, else { table[0]->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);/* Get record-count */ - records=table[0]->file->records+EXTRA_RECORDS; + records=table[0]->file->estimate_number_of_rows(); selected_records_file= 0; } if (param.sort_length == param.ref_length && records > param.max_rows) @@ -160,16 +158,11 @@ ha_rows filesort(TABLE **table, SORT_FIELD *sortorder, uint s_length, goto err; #endif - /* Reserve memory for IO_CACHE files */ - if (! (save_1=my_malloc(DISK_BUFFER_SIZE,MYF(MY_WME))) || - ! (save_2=my_malloc(DISK_BUFFER_SIZE,MYF(MY_WME)))) - goto err; - memavl=sortbuff_size; while (memavl >= MIN_SORT_MEMORY) { - if ((records+1)*(param.sort_length+sizeof(char*))+sizeof(BUFFPEK)*10 < - (ulong) memavl) + if ((ulonglong) (records+1)*(param.sort_length+sizeof(char*))+sizeof(BUFFPEK)*10 < + (ulonglong) memavl) param.keys=(uint) records+1; else { @@ -207,10 +200,6 @@ ha_rows filesort(TABLE **table, SORT_FIELD *sortorder, uint s_length, my_error(ER_OUTOFMEMORY,MYF(ME_ERROR+ME_WAITTANG),sortbuff_size); goto err; } - my_free(save_1,MYF(0)); /* Free for later use */ - my_free(save_2,MYF(0)); - save_1=save_2=0; - param.sort_form= table[0]; param.end=(param.local_sortorder=sortorder)+s_length; if ((records=find_all_keys(¶m,select,sort_keys,buffpek,&maxbuffer, @@ -252,8 +241,6 @@ ha_rows filesort(TABLE **table, SORT_FIELD *sortorder, uint s_length, #endif x_free((gptr) sort_keys); x_free((gptr) buffpek); - x_free(save_1); - x_free(save_2); close_cached_file(&tempfile); if (my_b_inited(outfile)) { @@ -382,6 +369,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, } if (*killed) { + DBUG_PRINT("info",("Sort killed by user")); (void) file->extra(HA_EXTRA_NO_CACHE); file->rnd_end(); DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */ diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc index 6cf97f16bb8..490a6db89e5 100644 --- a/sql/ha_berkeley.cc +++ b/sql/ha_berkeley.cc @@ -25,8 +25,9 @@ We will need an updated Berkeley DB version for this. - Killing threads that has got a 'deadlock' - SHOW TABLE STATUS should give more information about the table. - - Get a more accurate count of the number of rows. - We could store the found number of rows when the table is scanned. + - Get a more accurate count of the number of rows (estimate_number_of_rows()). + We could store the found number of rows when the table is scanned and + then increment the counter for each attempted write. - We will need a manager thread that calls flush_logs, removes old logs and makes checkpoints at given intervals. - When not using UPDATE IGNORE, don't make a sub transaction but abort @@ -42,7 +43,6 @@ - LOCK TABLES - CHAR keys - BLOBS - - delete from t1; */ @@ -60,6 +60,7 @@ #define HA_BERKELEY_ROWS_IN_TABLE 10000 /* to get optimization right */ #define HA_BERKELEY_RANGE_COUNT 100 +#define HA_BERKELEY_MAX_ROWS 10000000 /* Max rows in table */ const char *ha_berkeley_ext=".db"; bool berkeley_skip=0; @@ -1297,7 +1298,7 @@ void ha_berkeley::info(uint flag) DBUG_ENTER("info"); if (flag & HA_STATUS_VARIABLE) { - records = HA_BERKELEY_ROWS_IN_TABLE; // Just to get optimisations right + records = estimate_number_of_rows(); // Just to get optimisations right deleted = 0; } else if (flag & HA_STATUS_ERRKEY) @@ -1607,4 +1608,21 @@ void ha_berkeley::update_auto_primary_key() pthread_mutex_unlock(&share->mutex); } +/* + Return an estimated of the number of rows in the table. + Used when sorting to allocate buffers and by the optimizer. +*/ + +ha_rows ha_berkeley::estimate_number_of_rows() +{ + ulonglong max_ident; + ulonglong max_rows=table->max_rows ? table->max_rows : HA_BERKELEY_MAX_ROWS; + if (!hidden_primary_key) + return (ha_rows) max_rows; + pthread_mutex_lock(&share->mutex); + max_ident=share->auto_ident+EXTRA_RECORDS; + pthread_mutex_unlock(&share->mutex); + return (ha_rows) min(max_ident,max_rows); +} + #endif /* HAVE_BERKELEY_DB */ diff --git a/sql/ha_berkeley.h b/sql/ha_berkeley.h index 84061ae09be..1d1de613ce0 100644 --- a/sql/ha_berkeley.h +++ b/sql/ha_berkeley.h @@ -91,7 +91,8 @@ class ha_berkeley: public handler uint max_keys() const { return MAX_KEY-1; } uint max_key_parts() const { return MAX_REF_PARTS; } uint max_key_length() const { return MAX_KEY_LENGTH; } - uint extra_rec_buf_length() { return BDB_HIDDEN_PRIMARY_KEY_LENGTH; } + uint extra_rec_buf_length() { return BDB_HIDDEN_PRIMARY_KEY_LENGTH; } + ha_rows estimate_number_of_rows(); bool fast_key_read() { return 1;} bool has_transactions() { return 1;} diff --git a/sql/handler.h b/sql/handler.h index 84c14538f4b..bdc58ee7356 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -203,6 +203,7 @@ public: virtual bool fast_key_read() { return 0;} virtual bool has_transactions(){ return 0;} virtual uint extra_rec_buf_length() { return 0; } + virtual ha_rows estimate_number_of_rows() { return records+EXTRA_RECORDS; } virtual int index_init(uint idx) { active_index=idx; return 0;} virtual int index_end() {return 0; } diff --git a/sql/item_create.cc b/sql/item_create.cc index 8c62643b35a..8e6332d4e16 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -352,11 +352,6 @@ Item *create_func_to_days(Item* a) return new Item_func_to_days(a); } -Item *create_func_truncate (Item *a, Item *b) -{ - return new Item_func_round(a,b,1); -} - Item *create_func_ucase(Item* a) { return new Item_func_ucase(a); diff --git a/sql/item_create.h b/sql/item_create.h index aa617946d98..de2726b32b0 100644 --- a/sql/item_create.h +++ b/sql/item_create.h @@ -81,7 +81,6 @@ Item *create_func_tan(Item* a);; Item *create_func_time_format(Item *a, Item *b); Item *create_func_time_to_sec(Item* a); Item *create_func_to_days(Item* a); -Item *create_func_truncate (Item *a, Item *b); Item *create_func_ucase(Item* a); Item *create_func_version(void); Item *create_func_weekday(Item* a); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 6b8b3762aa1..39bbdcaff1f 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1598,7 +1598,7 @@ String *Item_load_file::val_str(String *str) if (!(file_name= args[0]->val_str(str)) || !(current_thd->master_access & FILE_ACL) || - !my_stat(file_name->c_ptr(), &stat_info, MYF(MY_FAE))) + !my_stat(file_name->c_ptr(), &stat_info, MYF(MY_WME))) goto err; if (!(stat_info.st_mode & S_IROTH)) { diff --git a/sql/lex.h b/sql/lex.h index a75fa07c3b7..503ce6998bb 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -302,6 +302,7 @@ static SYMBOL symbols[] = { { "TINYTEXT", SYM(TINYTEXT),0,0}, { "TINYINT", SYM(TINYINT),0,0}, { "TRAILING", SYM(TRAILING),0,0}, + { "TRUNCATE", SYM(TRUNCATE_SYM),0,0}, { "TO", SYM(TO_SYM),0,0}, { "TYPE", SYM(TYPE_SYM),0,0}, { "UNION", SYM(UNION_SYM),0,0}, @@ -443,7 +444,6 @@ static SYMBOL sql_functions[] = { { "TIME_TO_SEC", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_time_to_sec)}, { "TO_DAYS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_to_days)}, { "TRIM", SYM(TRIM),0,0}, - { "TRUNCATE", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_truncate )}, { "UCASE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ucase)}, { "UPPER", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ucase)}, { "UNIQUE_USERS", SYM(UNIQUE_USERS),0,0}, diff --git a/sql/lock.cc b/sql/lock.cc index 4c7ae8e950b..c85983b65d6 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -70,8 +70,8 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd,TABLE **tables,uint count) thd->proc_info="Waiting for table"; pthread_mutex_unlock(&thd->mysys_var->mutex); - while (global_read_lock && ! thd->killed || - thd->version != refresh_version) + while (global_read_lock && ! thd->killed && + thd->version == refresh_version) { (void) pthread_cond_wait(&COND_refresh,&LOCK_open); } diff --git a/sql/log.cc b/sql/log.cc index bf99bb32f09..7172d043552 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -25,8 +25,6 @@ #include <stdarg.h> #include <m_ctype.h> // For test_if_number - - MYSQL_LOG mysql_log,mysql_update_log,mysql_slow_log,mysql_bin_log; extern I_List<i_string> binlog_do_db, binlog_ignore_db; @@ -75,26 +73,25 @@ static int find_uniq_filename(char *name) DBUG_RETURN(0); } - - -MYSQL_LOG::MYSQL_LOG(): file(0),index_file(0),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() { if (inited) - { - (void) pthread_mutex_destroy(&LOCK_log); - (void) pthread_mutex_destroy(&LOCK_index); - } + { + (void) pthread_mutex_destroy(&LOCK_log); + (void) pthread_mutex_destroy(&LOCK_index); + } } void MYSQL_LOG::set_index_file_name(const char* index_file_name) @@ -106,6 +103,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) @@ -129,58 +127,60 @@ int MYSQL_LOG::generate_new_name(char *new_name, const char *log_name) void MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg, const char *new_name) { + MY_STAT tmp_stat; + char buff[512]; + File file= -1; + bool do_magic; if (!inited) { inited=1; (void) pthread_mutex_init(&LOCK_log,NULL); (void) pthread_mutex_init(&LOCK_index, NULL); - if(log_type_arg == LOG_BIN && *fn_ext(log_name)) + 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; - MY_STAT tmp_stat; - 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))); - file=my_fopen(log_file_name,O_APPEND | O_WRONLY | O_BINARY, - MYF(MY_WME | ME_WAITTANG)); - if (!file) - { - my_free(name,MYF(0)); - name=0; - log_type=LOG_CLOSED; - return; - } + if ((file=my_open(log_file_name,O_APPEND | O_WRONLY | O_BINARY, + 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) { + char *end; #ifdef __NT__ - fprintf(file, "%s, Version: %s, started with:\nTCP Port: %d, Named Pipe: %s\n", my_progname, server_version, mysql_port, mysql_unix_port); + sprintf(buff, "%s, Version: %s, started with:\nTCP Port: %d, Named Pipe: %s\n", my_progname, server_version, mysql_port, mysql_unix_port); #else - fprintf(file, "%s, Version: %s, started with:\nTcp port: %d Unix socket: %s\n", my_progname,server_version,mysql_port,mysql_unix_port); + sprintf(buff, "%s, Version: %s, started with:\nTcp port: %d Unix socket: %s\n", my_progname,server_version,mysql_port,mysql_unix_port); #endif - fprintf(file,"Time Id Command Argument\n"); - (void) fflush(file); + end=strmov(strend(buff),"Time Id Command Argument\n"); + if (my_b_write(&log_file,buff,(uint) (end-buff)) || + flush_io_cache(&log_file)) + goto err; } else if (log_type == LOG_NEW) { time_t skr=time(NULL); struct tm tm_tmp; localtime_r(&skr,&tm_tmp); - - fprintf(file,"# %s, Version: %s at %02d%02d%02d %2d:%02d:%02d\n", + sprintf(buff,"# %s, Version: %s at %02d%02d%02d %2d:%02d:%02d\n", my_progname,server_version, tm_tmp.tm_year % 100, tm_tmp.tm_mon+1, @@ -188,45 +188,49 @@ 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); - (void) fflush(file); + 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 // clean up if failed // then if index_file has not been previously opened, try to open it // clean up if failed - if((do_magic && my_fwrite(file, (byte*)BINLOG_MAGIC, 4, - MYF(MY_NABP|MY_WME)) || - (!index_file && - !(index_file = my_fopen(index_file_name,O_APPEND | O_BINARY | O_RDWR, - MYF(MY_WME)))))) - { - my_fclose(file,MYF(MY_WME)); - my_free(name,MYF(0)); - name=0; - file=0; - log_type=LOG_CLOSED; - return; - } + + if ((do_magic && my_b_write(&log_file, (byte*) BINLOG_MAGIC, 4)) || + (index_file < 0 && + (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_fseek(index_file, 0L, MY_SEEK_END, MYF(MY_WME)); - fprintf(index_file, "%s\n", log_file_name); - fflush(index_file); + 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_ftell(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; } @@ -234,50 +238,85 @@ 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) 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_fseek(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(;;) + { + uint length; + if (!(length=my_b_gets(&io_cache, fname, FN_REFLEN))) { - error = LOG_INFO_SEEK; + error = !io_cache.error ? LOG_INFO_EOF : LOG_INFO_IO; goto err; } - for(;;) + // if the log entry matches, empty string matching anything + if (!log_name_len || + (log_name_len == length+1 && fname[log_name_len] == '\n' && + !memcmp(fname, log_name, log_name_len))) { - if(!fgets(fname, FN_REFLEN, index_file)) - { - error = feof(index_file) ? 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' && - !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_ftell(index_file, MYF(MY_WME)); - break; - } + 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; } + +int MYSQL_LOG::find_next_log(LOG_INFO* linfo) +{ + // mutex needed because we need to make sure the file pointer does not move + // from under our feet + if (!index_file) return LOG_INFO_INVALID; + int error = 0; + char* fname = linfo->log_file_name; + IO_CACHE io_cache; + uint length; + + 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; +} + + int MYSQL_LOG::purge_logs(THD* thd, const char* to_log) { if(!index_file) return LOG_INFO_INVALID; @@ -409,63 +448,21 @@ err: } -int MYSQL_LOG::find_next_log(LOG_INFO* linfo) -{ - // mutex needed because we need to make sure the file pointer does not move - // from under our feet - if(!index_file) return LOG_INFO_INVALID; - int error = 0; - char* fname = linfo->log_file_name; - char* end ; - - pthread_mutex_lock(&LOCK_index); - if(linfo->fatal) - { - error = LOG_INFO_FATAL; - goto err; - } - - if(my_fseek(index_file, linfo->index_file_offset, MY_SEEK_SET, MYF(MY_WME) ) == MY_FILEPOS_ERROR) - { - error = LOG_INFO_SEEK; - goto err; - } - - 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); - error = 0; -err: - pthread_mutex_unlock(&LOCK_index); - return error; -} - - // we assume that buf has at least FN_REFLEN bytes alloced void MYSQL_LOG::make_log_name(char* buf, const char* log_ident) { - 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 - } + 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) + 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) @@ -475,15 +472,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) { /* @@ -491,15 +490,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)); @@ -514,7 +511,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; @@ -544,28 +544,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) { @@ -585,7 +587,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) && @@ -599,43 +601,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) + 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); } @@ -651,13 +648,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)); } @@ -676,7 +673,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; @@ -695,37 +692,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); } @@ -757,7 +759,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) @@ -765,10 +768,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) { @@ -780,51 +782,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 62a3658bc9f..9e739da1c9d 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; } @@ -323,26 +310,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; @@ -376,21 +361,18 @@ Rotate_log_event::Rotate_log_event(const char* buf, int event_len): 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); @@ -402,9 +384,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; @@ -415,7 +398,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 event_len): @@ -430,7 +413,7 @@ Query_log_event::Query_log_event(const char* buf, int event_len): 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); @@ -457,9 +440,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; @@ -471,23 +454,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) @@ -497,12 +478,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) @@ -529,7 +510,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); @@ -539,77 +520,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 event_len): 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,16 @@ Load_log_event::Load_log_event(const char* buf, int event_len): return; buf += EVENT_LEN_OFFSET; - data_len = event_len; + 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 +584,23 @@ Load_log_event::Load_log_event(const char* buf, int event_len): 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 +659,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 33fcab4fea9..3a571c0f9a4 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 event_len); #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 event_len); ~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 event_len); ~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 event_len); ~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 3756d8bf712..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)) == MY_FILEPOS_ERROR) - 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/mysqld.cc b/sql/mysqld.cc index e9389727e9a..db67eb1f6ea 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -131,7 +131,7 @@ extern "C" int gethostname(char *name, int namelen); #ifndef DBUG_OFF static const char* default_dbug_option=IF_WIN("d:t:i:O,\\mysqld.trace", - "d:t:i:o,/tmp/mysqld.trace"); + "d:t:i:o,/tmp/mysqld.trace"); #endif #ifdef __NT__ @@ -157,7 +157,7 @@ static pthread_t select_thread; static pthread_t flush_thread; // Used when debugging static bool opt_log,opt_update_log,opt_bin_log,opt_slow_log,opt_noacl, opt_disable_networking=0, opt_bootstrap=0,opt_skip_show_db=0, - opt_ansi_mode=0,opt_myisam_log=0; + opt_ansi_mode=0,opt_myisam_log=0, opt_large_files=sizeof(my_off_t) > 4; bool opt_sql_bin_update = 0, opt_log_slave_updates = 0; extern MASTER_INFO glob_mi; extern int init_master_info(MASTER_INFO* mi); @@ -579,8 +579,8 @@ void unireg_abort(int exit_code) { if (exit_code) sql_print_error("Aborting\n"); - (void) my_delete(pidfile_name,MYF(0)); // This may not always exist clean_up(); /* purecov: inspected */ + (void) my_delete(pidfile_name,MYF(0)); // This may not always exist exit(exit_code); /* purecov: inspected */ } @@ -2436,20 +2436,21 @@ struct show_var_st init_vars[]= { #endif {"character_set", default_charset, SHOW_CHAR}, {"character_sets", (char*) &charsets_list, SHOW_CHAR_PTR}, - {"connect_timeout", (char*) &connect_timeout, SHOW_LONG}, {"concurrent_insert", (char*) &myisam_concurrent_insert, SHOW_MY_BOOL}, + {"connect_timeout", (char*) &connect_timeout, SHOW_LONG}, {"datadir", mysql_real_data_home, SHOW_CHAR}, {"delay_key_write", (char*) &myisam_delay_key_write, SHOW_MY_BOOL}, {"delayed_insert_limit", (char*) &delayed_insert_limit, SHOW_LONG}, {"delayed_insert_timeout", (char*) &delayed_insert_timeout, SHOW_LONG}, {"delayed_queue_size", (char*) &delayed_queue_size, SHOW_LONG}, - {"join_buffer_size", (char*) &join_buff_size, SHOW_LONG}, {"flush", (char*) &myisam_flush, SHOW_MY_BOOL}, {"flush_time", (char*) &flush_time, SHOW_LONG}, {"init_file", (char*) &opt_init_file, SHOW_CHAR_PTR}, {"interactive_timeout", (char*) &net_interactive_timeout, SHOW_LONG}, + {"join_buffer_size", (char*) &join_buff_size, SHOW_LONG}, {"key_buffer_size", (char*) &keybuff_size, SHOW_LONG}, {"language", language, SHOW_CHAR}, + {"large_files_support", (char*) &opt_large_files, SHOW_BOOL}, #ifdef HAVE_MLOCKALL {"locked_in_memory", (char*) &locked_in_memory, SHOW_BOOL}, #endif @@ -2472,12 +2473,15 @@ struct show_var_st init_vars[]= { {"myisam_recover_options", (char*) &myisam_recover_options_str, SHOW_CHAR_PTR}, {"myisam_sort_buffer_size", (char*) &myisam_sort_buffer_size, SHOW_LONG}, {"net_buffer_length", (char*) &net_buffer_length, SHOW_LONG}, + {"net_read_timeout", (char*) &net_read_timeout, SHOW_LONG}, {"net_retry_count", (char*) &mysqld_net_retry_count, SHOW_LONG}, + {"net_write_timeout", (char*) &net_write_timeout, SHOW_LONG}, {"pid_file", (char*) pidfile_name, SHOW_CHAR}, {"port", (char*) &mysql_port, SHOW_INT}, {"protocol_version", (char*) &protocol_version, SHOW_INT}, {"record_buffer", (char*) &my_default_record_cache_size,SHOW_LONG}, - {"server_id", (char*) &server_id, SHOW_LONG}, + {"query_buffer_size", (char*) &query_buff_size, SHOW_LONG}, + {"server_id", (char*) &server_id, SHOW_LONG}, {"skip_locking", (char*) &my_disable_locking, SHOW_MY_BOOL}, {"skip_networking", (char*) &opt_disable_networking, SHOW_BOOL}, {"skip_show_database", (char*) &opt_skip_show_db, SHOW_BOOL}, @@ -2486,11 +2490,11 @@ struct show_var_st init_vars[]= { {"sort_buffer", (char*) &sortbuff_size, SHOW_LONG}, {"table_cache", (char*) &table_cache_size, SHOW_LONG}, {"table_type", (char*) &default_table_type_name, SHOW_CHAR_PTR}, + {"thread_cache_size", (char*) &thread_cache_size, SHOW_LONG}, #ifdef HAVE_THR_SETCONCURRENCY {"thread_concurrency", (char*) &concurrency, SHOW_LONG}, #endif {"thread_stack", (char*) &thread_stack, SHOW_LONG}, - {"thread_cache_size", (char*) &thread_cache_size, SHOW_LONG}, #ifdef HAVE_TZNAME {"timezone", time_zone, SHOW_CHAR}, #endif @@ -3414,7 +3418,7 @@ static int get_service_parameters() else if ( lstrcmp(szKeyValueName, TEXT("ShowDatabase")) == 0 ) { CHECK_KEY_TYPE( REG_DWORD, szKeyValueName ); - opt_disable_networking = !(*lpdwValue); + opt_skip_show_db = !(*lpdwValue); } else if ( lstrcmp(szKeyValueName, TEXT("HostnameCaching")) == 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 f86c0cf7461..cd685cb3437 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -114,11 +114,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() @@ -137,6 +143,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 e53ce950c1f..2af98d6fbf0 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -52,16 +52,16 @@ typedef struct st_log_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 @@ -85,7 +85,6 @@ public: void make_log_name(char* buf, const char* log_ident); bool is_active(const char* log_file_name); int purge_logs(THD* thd, const char* to_log); - void flush(void); void close(bool exiting = 0); // if we are exiting, we also want to close the // index file @@ -244,6 +243,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_insert.cc b/sql/sql_insert.cc index 7195caca176..b552479bfe2 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -571,7 +571,7 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list) thread_count++; pthread_mutex_unlock(&LOCK_thread_count); if (!(tmp->thd.db=my_strdup(table_list->db,MYF(MY_WME))) || - !(tmp->thd.query=my_strdup(table_list->real_name,MYF(MY_FAE)))) + !(tmp->thd.query=my_strdup(table_list->real_name,MYF(MY_WME)))) { delete tmp; thd->fatal_error=1; @@ -1325,7 +1325,8 @@ bool select_create::send_eof() { VOID(pthread_mutex_lock(&LOCK_open)); mysql_unlock_tables(thd, lock); - hash_delete(&open_cache,(byte*) table); + if (!table->tmp_table) + hash_delete(&open_cache,(byte*) table); lock=0; table=0; VOID(pthread_mutex_unlock(&LOCK_open)); } @@ -1343,7 +1344,8 @@ void select_create::abort() if (table) { enum db_type table_type=table->db_type; - hash_delete(&open_cache,(byte*) table); + if (!table->tmp_table) + hash_delete(&open_cache,(byte*) table); quick_rm_table(table_type,db,name); table=0; } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 674da73ba5d..dd7e1cf7b30 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -34,19 +34,23 @@ class LEX_COLUMN; #endif enum enum_sql_command { - SQLCOM_SELECT,SQLCOM_CREATE_TABLE,SQLCOM_CREATE_INDEX,SQLCOM_ALTER_TABLE, - SQLCOM_UPDATE,SQLCOM_INSERT,SQLCOM_INSERT_SELECT,SQLCOM_DELETE, - SQLCOM_DROP_TABLE,SQLCOM_DROP_INDEX,SQLCOM_SHOW_DATABASES, - SQLCOM_SHOW_TABLES,SQLCOM_SHOW_FIELDS,SQLCOM_SHOW_KEYS, + SQLCOM_SELECT, SQLCOM_CREATE_TABLE, SQLCOM_CREATE_INDEX, SQLCOM_ALTER_TABLE, + SQLCOM_UPDATE, SQLCOM_INSERT, SQLCOM_INSERT_SELECT, + SQLCOM_DELETE, SQLCOM_TRUNCATE, SQLCOM_DROP_TABLE, SQLCOM_DROP_INDEX, + + SQLCOM_SHOW_DATABASES, SQLCOM_SHOW_TABLES, SQLCOM_SHOW_FIELDS, + SQLCOM_SHOW_KEYS, SQLCOM_SHOW_VARIABLES, SQLCOM_SHOW_STATUS, + SQLCOM_SHOW_PROCESSLIST, SQLCOM_SHOW_MASTER_STAT, SQLCOM_SHOW_SLAVE_STAT, + SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, + SQLCOM_LOAD,SQLCOM_SET_OPTION,SQLCOM_LOCK_TABLES,SQLCOM_UNLOCK_TABLES, SQLCOM_GRANT, SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, - SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT, SQLCOM_SHOW_VARIABLES, - SQLCOM_SHOW_STATUS, SQLCOM_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION, - SQLCOM_SHOW_PROCESSLIST,SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK, - SQLCOM_FLUSH, SQLCOM_KILL, SQLCOM_SHOW_GRANTS, SQLCOM_ANALYZE, + SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT, + SQLCOM_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION, + SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK, + SQLCOM_FLUSH, SQLCOM_KILL, SQLCOM_ANALYZE, SQLCOM_ROLLBACK, SQLCOM_COMMIT, SQLCOM_SLAVE_START, SQLCOM_SLAVE_STOP, - SQLCOM_BEGIN, SQLCOM_LOAD_MASTER_TABLE, SQLCOM_SHOW_CREATE, - SQLCOM_SHOW_MASTER_STAT, SQLCOM_SHOW_SLAVE_STAT, SQLCOM_CHANGE_MASTER, + SQLCOM_BEGIN, SQLCOM_LOAD_MASTER_TABLE, SQLCOM_CHANGE_MASTER, SQLCOM_RENAME_TABLE, SQLCOM_BACKUP_TABLE, SQLCOM_RESTORE_TABLE, SQLCOM_RESET, SQLCOM_PURGE, SQLCOM_SHOW_BINLOGS }; diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 633855a18fa..9bf3346e61d 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -158,7 +158,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, unpack_filename(name,ex->file_name); #ifndef __WIN__ MY_STAT stat_info; - if (!my_stat(name,&stat_info,MYF(MY_FAE))) + if (!my_stat(name,&stat_info,MYF(MY_WME))) DBUG_RETURN(-1); // the file must be: diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 066885ef30a..b12bdcb4d98 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -71,6 +71,20 @@ static void init_signals(void) } #endif +static inline bool end_active_trans(THD *thd) +{ + if (!(thd->options & OPTION_AUTO_COMMIT) || + (thd->options & OPTION_BEGIN)) + { + if (ha_commit(thd)) + return 1; + thd->options&= ~OPTION_BEGIN; + thd->server_status&= ~SERVER_STATUS_IN_TRANS; + } + return 0; +} + + /* ** Check if user is ok ** Updates: @@ -1150,8 +1164,7 @@ mysql_execute_command(void) } } /* ALTER TABLE ends previous transaction */ - if ((!(thd->options & OPTION_AUTO_COMMIT) || - (thd->options & OPTION_BEGIN)) && ha_commit(thd)) + if (end_active_trans(thd)) res= -1; else res= mysql_alter_table(thd, lex->db, lex->name, @@ -1369,6 +1382,7 @@ mysql_execute_command(void) break; } case SQLCOM_DELETE: + case SQLCOM_TRUNCATE: { if (check_access(thd,DELETE_ACL,tables->db,&tables->grant.privilege)) goto error; /* purecov: inspected */ @@ -1376,11 +1390,12 @@ mysql_execute_command(void) goto error; // Set privilege for the WHERE clause tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege); - res = mysql_delete(thd,tables,lex->where,lex->select_limit, - lex->lock_option, lex->options); -#ifdef DELETE_ITEMS - delete lex->where; -#endif + /* TRUNCATE ends previous transaction */ + if (lex->sql_command == SQLCOM_TRUNCATE && end_active_trans(thd)) + res= -1; + else + res = mysql_delete(thd,tables,lex->where,lex->select_limit, + lex->lock_option, lex->options); break; } case SQLCOM_DROP_TABLE: @@ -1722,6 +1737,11 @@ mysql_execute_command(void) send_ok(&thd->net); break; case SQLCOM_COMMIT: + /* + We don't use end_active_trans() here to ensure that this works + even if there is a problem with the OPTION_AUTO_COMMIT flag + (Which of course should never happen...) + */ thd->options&= ~OPTION_BEGIN; thd->server_status&= ~SERVER_STATUS_IN_TRANS; if (!ha_commit(thd)) @@ -2441,7 +2461,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 4142c003d4d..5cdb5ab0706 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -93,6 +93,40 @@ 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 adjust_linfo_offsets(my_off_t purge_offset) { THD *tmp; @@ -119,6 +153,7 @@ void adjust_linfo_offsets(my_off_t purge_offset) pthread_mutex_unlock(&LOCK_thread_count); } + bool log_in_use(const char* log_name) { int log_name_len = strlen(log_name) + 1; @@ -144,6 +179,7 @@ bool log_in_use(const char* log_name) return result; } + int purge_master_logs(THD* thd, const char* to_log) { char search_file_name[FN_REFLEN]; @@ -179,27 +215,29 @@ binlog purge"; break; return 0; } + 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; @@ -207,251 +245,214 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags) linfo.index_file_offset = 0; thd->current_linfo = &linfo; - 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 = "Congratulations! 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; + 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); - (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; - } + 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; + } - //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((*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"; @@ -461,6 +462,7 @@ sweepstakes if you report the bug"; DBUG_VOID_RETURN; err: thd->proc_info = "waiting to finalize termination"; + end_io_cache(&log); pthread_mutex_lock(&LOCK_thread_count); // exclude iteration through thread list // this is needed for purge_logs() - it will iterate through @@ -469,8 +471,8 @@ sweepstakes if you report the bug"; // after we return from this stack frame thd->current_linfo = 0; pthread_mutex_unlock(&LOCK_thread_count); - if(log) - (void) my_fclose(log, MYF(MY_WME)); + if (file >= 0) + (void) my_close(file, MYF(MY_WME)); send_error(&thd->net, my_errno, errmsg); DBUG_VOID_RETURN; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index c9de4998899..f38b1a52b65 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2735,7 +2735,7 @@ return_zero_rows(select_result *result,TABLE_LIST *tables,List<Item> &fields, { for (TABLE_LIST *table=tables; table ; table=table->next) mark_as_null_row(table->table); // All fields are NULL - if (having && having->val_int() == 0.0) + if (having && having->val_int() == 0) send_row=0; } if (!tables || !(result->send_fields(fields,1))) @@ -3214,6 +3214,7 @@ Field *create_tmp_field(TABLE *table,Item *item, Item::Type type, case Item::REAL_ITEM: case Item::STRING_ITEM: case Item::REF_ITEM: + case Item::NULL_ITEM: { bool maybe_null=item->maybe_null; Field *new_field; @@ -4499,7 +4500,7 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), if (!end_of_records) { int error; - if (join->having && join->having->val_int() == 0.0) + if (join->having && join->having->val_int() == 0) DBUG_RETURN(0); // Didn't match having if (join->procedure) error=join->procedure->send_row(*join->fields); @@ -4539,7 +4540,7 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), int error; if (join->procedure) { - if (join->having && join->having->val_int() == 0.0) + if (join->having && join->having->val_int() == 0) error= -1; // Didn't satisfy having else error=join->procedure->send_row(*join->fields) ? 1 : 0; @@ -4550,7 +4551,7 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), { if (!join->first_record) clear_tables(join); - if (join->having && join->having->val_int() == 0.0) + if (join->having && join->having->val_int() == 0) error= -1; // Didn't satisfy having else error=join->result->send_data(*join->fields) ? 1 : 0; @@ -5109,7 +5110,7 @@ create_sort_index(JOIN_TAB *tab,ORDER *order,ha_rows select_limit) goto err; /* purecov: inspected */ /* It's not fatal if the following alloc fails */ table->io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE), - MYF(MY_FAE | MY_ZEROFILL)); + MYF(MY_WME | MY_ZEROFILL)); table->status=0; // May be wrong if quick_select // If table has a range, move it to select 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 1c9e822cce5..f327618ffdd 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/sql_yacc.yy b/sql/sql_yacc.yy index 5d62fbe84ba..4923be08a49 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -111,6 +111,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token SLAVE %token START_SYM %token STOP_SYM +%token TRUNCATE_SYM %token ROLLBACK_SYM %token OPTIMIZE %token SHOW @@ -493,9 +494,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %type <NONE> query verb_clause create change select drop insert replace insert2 - insert_values update delete show describe load alter optimize flush + insert_values update delete truncate rename + show describe load alter optimize flush reset purge begin commit rollback slave master_def master_defs - repair restore backup analyze check rename + repair restore backup analyze check field_list field_list_item field_spec kill select_item_list select_item values_list no_braces limit_clause delete_limit_clause fields opt_values values @@ -562,6 +564,7 @@ verb_clause: | set | slave | show + | truncate | unlock | update | use @@ -789,7 +792,7 @@ field_list_item: Lex->key_list.push_back(new Key($1,$2,Lex->col_list)); Lex->col_list.empty(); /* Alloced by sql_alloc */ } - | opt_constraint FOREIGN KEY_SYM '(' key_list ')' references + | opt_constraint FOREIGN KEY_SYM opt_ident '(' key_list ')' references { Lex->col_list.empty(); /* Alloced by sql_alloc */ } @@ -1559,7 +1562,8 @@ simple_expr: { $$= new Item_func_trim($6,$4); } | TRIM '(' expr FROM expr ')' { $$= new Item_func_trim($5,$3); } - + | TRUNCATE_SYM '(' expr ',' expr ')' + { $$= new Item_func_round($3,$5,1); } | UDA_CHAR_SUM '(' udf_expr_list ')' { if ($3 != NULL) @@ -2131,6 +2135,11 @@ opt_delete_option: QUICK { Lex->options|= OPTION_QUICK; } | LOW_PRIORITY { Lex->lock_option= TL_WRITE_LOW_PRIORITY; } +truncate: + TRUNCATE_SYM TABLE_SYM table + { Lex->sql_command= SQLCOM_TRUNCATE; Lex->options=0; + Lex->lock_option= current_thd->update_lock_default; } + /* Show things */ show: SHOW { Lex->wild=0;} show_param @@ -2530,6 +2539,7 @@ keyword: | STRING_SYM {} | TEMPORARY {} | TEXT_SYM {} + | TRUNCATE_SYM {} | TIMESTAMP {} | TIME_SYM {} | TYPE_SYM {} 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. diff --git a/sql/violite.c b/sql/violite.c index b18de053b5a..4efda9f3b90 100644 --- a/sql/violite.c +++ b/sql/violite.c @@ -1,18 +1,19 @@ /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ /* Note that we can't have assertion on file descriptors; The reason for @@ -31,6 +32,9 @@ #include <my_sys.h> #include <my_net.h> #include <m_string.h> +#ifdef HAVE_POLL +#include <sys/poll.h> +#endif #if defined(__EMX__) #include <sys/ioctl.h> @@ -398,4 +402,26 @@ void vio_in_addr(Vio *vio, struct in_addr *in) DBUG_VOID_RETURN; } + +/* Return 0 if there is data to be read */ + +my_bool vio_poll_read(Vio *vio,uint timeout) +{ +#ifndef HAVE_POLL + return 0; +#else + struct pollfd fds; + int res; + DBUG_ENTER("vio_poll"); + fds.fd=vio->sd; + fds.events=POLLIN; + fds.revents=0; + if ((res=poll(&fds,1,(int) timeout*1000)) <= 0) + { + DBUG_RETURN(res < 0 ? 0 : 1); /* Don't return 1 on errors */ + } + DBUG_RETURN(fds.revents & POLLIN ? 0 : 1); +#endif +} + #endif /* HAVE_VIO */ |