Commit a9097ca3 authored by monty@donna.mysql.com's avatar monty@donna.mysql.com

changed to use IO_CACHE instead of FILE

parent b689a1a7
jcole@tetra.bedford.progress.com
jcole@tetra.spaceapes.com
monty@narttu.mysql.fi
mwagner@evoq.home.mwagner.org
sasha@laptop.slkc.uswest.net
sasha@mysql.sashanet.com
sasha@work.mysql.com
serg@serg.mysql.com
yfaktoro@nslinuxw2.bedford.progress.com
monty@donna.mysql.com
......@@ -16867,7 +16867,7 @@ This is an "RSA Data Security, Inc. MD5 Message-Digest Algorithm".
@item LAST_INSERT_ID([expr])
Returns the last automatically generated value that was inserted into an
@code{AUTO_INCREMENT} column.
@xref{mysql_insert_id,, @code{mysql_insert_id()}}:
@xref{mysql_insert_id,, @code{mysql_insert_id()}}.
@example
mysql> select LAST_INSERT_ID();
......@@ -17086,7 +17086,7 @@ mysql> select student_name, AVG(test_score)
@itemx MAX(expr)
Returns the minimum or maximum value of @code{expr}. @code{MIN()} and
@code{MAX()} may take a string argument; in such cases they return the
minimum or maximum string value. @xref{MySQL indexes}:
minimum or maximum string value. @xref{MySQL indexes}.
@example
mysql> select student_name, MIN(test_score), MAX(test_score)
......@@ -19753,8 +19753,8 @@ The status variables listed above have the following meaning:
@item @strong{Variable} @tab @strong{Meaning}
@item @code{Aborted_clients} @tab Number of connections that has been aborted because the client has died without closing the connection properly.
@item @code{Aborted_connects} @tab Number of tries to connect to the @strong{MySQL} server that has failed.
@item @code{Bytes_received} @tab Number of bytes received from the client
@item @code{Bytes_sent} @tab Number of bytes received from the client
@item @code{Bytes_received} @tab Number of bytes received from all clients
@item @code{Bytes_sent} @tab Number of bytes sent to all clients
@item @code{Connections} @tab Number of connection attempts to the @strong{MySQL} server.
@item @code{Created_tmp_disk_tables} @tab Number of implicit temporary tables on disk that have been created while executing statements.
@item @code{Created_tmp_tables} @tab Number of implicit temporary tables in memory that have been created while executing statements.
......@@ -417,6 +417,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
share.state.dellink = HA_OFFSET_ERROR;
share.state.process= (ulong) getpid();
share.state.unique= (ulong) 0;
share.state.update_count=(ulong) 0;
share.state.version= (ulong) time((time_t*) 0);
share.state.sortkey= (ushort) ~0;
share.state.auto_increment=ci->auto_increment;
......
......@@ -70,6 +70,7 @@ int mi_lock_database(MI_INFO *info, int lock_type)
{
share->state.process= share->last_process=share->this_process;
share->state.unique= info->last_unique= info->this_unique;
share->state.update_count= info->last_loop= ++info->this_loop;
if (mi_state_info_write(share->kfile, &share->state, 1))
error=my_errno;
share->changed=0;
......@@ -346,6 +347,7 @@ int _mi_writeinfo(register MI_INFO *info, uint operation)
{ /* Two threads can't be here */
share->state.process= share->last_process= share->this_process;
share->state.unique= info->last_unique= info->this_unique;
share->state.update_count= info->last_loop= ++info->this_loop;
if ((error=mi_state_info_write(share->kfile, &share->state, 1)))
olderror=my_errno;
#ifdef __WIN__
......@@ -377,12 +379,14 @@ int _mi_test_if_changed(register MI_INFO *info)
{
MYISAM_SHARE *share=info->s;
if (share->state.process != share->last_process ||
share->state.unique != info->last_unique)
share->state.unique != info->last_unique ||
share->state.update_count != info->last_loop)
{ /* Keyfile has changed */
if (share->state.process != share->this_process)
VOID(flush_key_blocks(share->kfile,FLUSH_RELEASE));
share->last_process=share->state.process;
info->last_unique= share->state.unique;
info->last_loop= share->state.update_count;
info->update|= HA_STATE_WRITTEN; /* Must use file on next */
info->data_changed= 1; /* For mi_is_changed */
return 1;
......
......@@ -445,8 +445,9 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
info.this_unique= (ulong) info.dfile; /* Uniq number in process */
if (share->data_file_type == COMPRESSED_RECORD)
info.this_unique= share->state.unique;
info.this_loop=0; /* Update counter */
info.this_loop=0; /* Update counter */
info.last_unique= share->state.unique;
info.last_loop= share->state.update_count;
if (mode == O_RDONLY)
share->options|=HA_OPTION_READ_ONLY_DATA;
info.lock_type=F_UNLCK;
......@@ -669,7 +670,7 @@ uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite)
mi_int4store(ptr,state->process); ptr +=4;
mi_int4store(ptr,state->unique); ptr +=4;
mi_int4store(ptr,state->status); ptr +=4;
*ptr++=0; *ptr++=0; *ptr++=0; *ptr++=0; /* extra */
mi_int4store(ptr,state->update_count); ptr +=4;
ptr+=state->state_diff_length;
......
......@@ -1214,7 +1214,11 @@ int _mi_search_next(register MI_INFO *info, register MI_KEYDEF *keyinfo,
DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,keyinfo->seg,key,key_length););
/* Force full read if we are at last key or if we are not on a leaf
and the key tree has changed since we used it last time */
and the key tree has changed since we used it last time
Note that even if the key tree has changed since last read, we can use
the last read data from the leaf if we haven't used the buffer for
something else.
*/
if (((nextflag & SEARCH_BIGGER) && info->int_keypos >= info->int_maxpos) ||
info->page_changed ||
......
......@@ -64,6 +64,7 @@ typedef struct st_mi_state_info
ulonglong auto_increment;
ulong process; /* process that updated table last */
ulong unique; /* Unique number for this process */
ulong update_count; /* Updated for each write lock */
ulong status;
my_off_t *key_root; /* Start of key trees */
my_off_t *key_del; /* delete links for trees */
......
......@@ -27,7 +27,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c\
my_open.c my_create.c my_seek.c my_read.c \
my_pread.c my_write.c \
mf_keycache.c \
mf_iocache.c mf_cache.c mf_tempfile.c \
mf_iocache.c mf_iocache2.c mf_cache.c mf_tempfile.c \
my_lock.c mf_brkhant.c my_alarm.c \
my_malloc.c my_realloc.c my_once.c mulalloc.c \
my_alloc.c safemalloc.c my_fopen.c my_fstream.c \
......
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
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 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
Library General Public License for more details.
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 */
/*
More functions to be used with IO_CACHE files
*/
#define MAP_TO_USE_RAID
#include "mysys_priv.h"
#include <m_string.h>
#include <stdarg.h>
#include <m_ctype.h>
/*
** Fix that next read will be made at certain position
** This only works with READ_CACHE
*/
void my_b_seek(IO_CACHE *info,my_off_t pos)
{
info->seek_not_done=0;
info->pos_in_file=pos;
info->rc_pos=info->rc_end=info->buffer;
}
/*
** Fill buffer
** return: 0 on error or EOF (info->error = -1 on error)
** number of characters
*/
uint my_b_fill(IO_CACHE *info)
{
my_off_t pos_in_file=info->pos_in_file+(uint) (info->rc_end - info->buffer);
my_off_t max_length;
uint diff_length,length;
if (info->seek_not_done)
{ /* File touched, do seek */
if (my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0)) ==
MY_FILEPOS_ERROR)
{
info->error= 0;
return 0;
}
info->seek_not_done=0;
}
diff_length=(uint) (pos_in_file & (IO_SIZE-1));
max_length= (my_off_t) (info->end_of_file - pos_in_file);
if (max_length > (my_off_t) (info->read_length-diff_length))
max_length=(my_off_t) (info->read_length-diff_length);
if (!max_length)
{
info->error= 0;
return 0; /* EOF */
}
else if ((length=my_read(info->file,info->buffer,(uint) max_length,
info->myflags)) == (uint) -1)
{
info->error= -1;
return 0;
}
info->rc_pos=info->buffer;
info->rc_end=info->buffer+length;
info->pos_in_file=pos_in_file;
return length;
}
/*
** Read a string ended by '\n' into a buffer of 'max_length' size.
** Returns number of characters read, 0 on error.
** last byte is set to '\0'
*/
uint my_b_gets(IO_CACHE *info, char *to, uint max_length)
{
uint length;
max_length--; /* Save place for end \0 */
/* Calculate number of characters in buffer */
if (!(length= (uint) (info->rc_end - info->rc_pos)))
if (!(length=my_b_fill(info)))
return 0;
for (;;)
{
char *pos,*end;
if (length > max_length)
length=max_length;
for (pos=info->rc_pos,end=pos+length ; pos < end ;)
{
if ((*to++ = *pos++) == '\n')
{
length= (uint) (pos-info->rc_pos);
info->rc_pos=pos;
*to='\0';
return length;
}
}
if (!(max_length-=length))
{
/* Found enough charcters; Return found string */
info->rc_pos=pos;
*to='\0';
return length;
}
if (!(length=my_b_fill(info)))
return 0;
}
}
/*
Simple printf version. Supports '%s', '%d', '%u', "%ld" and "%lu"
Used for logging in MySQL
returns number of written character, or (uint) -1 on error
*/
uint my_b_printf(IO_CACHE *info, const char* fmt, ...)
{
va_list args;
reg1 char *to= info->rc_pos;
char *end=info->rc_end;
uint out_length=0;
va_start(args,fmt);
for (; *fmt ; fmt++)
{
if (fmt[0] != '%')
{
/* Copy everything until '%' or end of string */
const char *start=fmt;
uint length;
for (fmt++ ; *fmt && *fmt != '%' ; fmt++ ) ;
length= (uint) (fmt - start);
out_length+=length;
if (my_b_write(info, start, length))
goto err;
if (!*fmt) /* End of format */
{
va_end(args);
return out_length;
}
/* Found one '%' */
}
/* Skipp if max size is used (to be compatible with printf) */
while (isdigit(*fmt) || *fmt == '.' || *fmt == '-')
fmt++;
if (*fmt == 's') /* String parameter */
{
reg2 char *par = va_arg(args, char *);
uint length = (uint) strlen(par);
out_length+=length;
if (my_b_write(info, par, length))
goto err;
}
else if (*fmt == 'd' || *fmt == 'u') /* Integer parameter */
{
register int iarg;
uint length;
char buff[17];
iarg = va_arg(args, int);
if (*fmt == 'd')
length= (uint) (int10_to_str((long) iarg,buff, -10) - buff);
else
length= (uint) (int10_to_str((long) (uint) iarg,buff,10)- buff);
out_length+=length;
if (my_b_write(info, buff, length))
goto err;
}
else if (*fmt == 'l' && fmt[1] == 'd' || fmt[1] == 'u')/* long parameter */
{
register long iarg;
uint length;
char buff[17];
iarg = va_arg(args, long);
if (*++fmt == 'd')
length= (uint) (int10_to_str(iarg,buff, -10) - buff);
else
length= (uint) (int10_to_str(iarg,buff,10)- buff);
out_length+=length;
if (my_b_write(info, buff, length))
goto err;
}
else
{
/* %% or unknown code */
if (my_b_write(info, "%", 1))
goto err;
out_length++;
}
}
va_end(args);
return out_length;
err:
return (uint) -1;
va_end(args);
}
......@@ -319,8 +319,8 @@ int MYSQL_LOG::find_next_log(LOG_INFO* linfo)
int MYSQL_LOG::purge_logs(THD* thd, const char* to_log)
{
if(!index_file) return LOG_INFO_INVALID;
if(no_rotate) return LOG_INFO_PURGE_NO_ROTATE;
if (index_file < 0) return LOG_INFO_INVALID;
if (no_rotate) return LOG_INFO_PURGE_NO_ROTATE;
int error;
char fname[FN_REFLEN];
char* fname_end, *p;
......@@ -329,125 +329,132 @@ int MYSQL_LOG::purge_logs(THD* thd, const char* to_log)
DYNAMIC_ARRAY logs_to_purge, logs_to_keep;
my_off_t purge_offset ;
LINT_INIT(purge_offset);
IO_CACHE io_cache;
pthread_mutex_lock(&LOCK_index);
if(my_fseek(index_file, 0, MY_SEEK_SET,
MYF(MY_WME) ) == MY_FILEPOS_ERROR)
{
error = LOG_INFO_SEEK;
goto err;
}
if(init_dynamic_array(&logs_to_purge, sizeof(char*), 1024, 1024))
{
error = LOG_INFO_MEM;
goto err;
}
if (init_io_cache(&io_cache,index_file, IO_SIZE*2, READ_CACHE, (my_off_t) 0,
0, MYF(MY_WME)))
{
error = LOG_INFO_MEM;
goto err;
}
if (init_dynamic_array(&logs_to_purge, sizeof(char*), 1024, 1024))
{
error = LOG_INFO_MEM;
goto err;
}
logs_to_purge_inited = 1;
if(init_dynamic_array(&logs_to_keep, sizeof(char*), 1024, 1024))
{
error = LOG_INFO_MEM;
goto err;
}
if (init_dynamic_array(&logs_to_keep, sizeof(char*), 1024, 1024))
{
error = LOG_INFO_MEM;
goto err;
}
logs_to_keep_inited = 1;
for(;;)
{
my_off_t init_purge_offset= my_b_tell(&io_cache);
if (!(fname_len=my_b_gets(&io_cache, fname, FN_REFLEN)))
{
if(!fgets(fname, FN_REFLEN, index_file))
{
if(feof(index_file))
break;
else
error = LOG_INFO_IO;
goto err;
}
if(!io_cache.error)
break;
error = LOG_INFO_IO;
goto err;
}
*(fname_end = (strend(fname) - 1)) = 0; // kill \n
fname_len = (uint)(fname_end - fname);
if(!memcmp(fname, to_log, fname_len + 1 ))
{
found_log = 1;
purge_offset = my_ftell(index_file, MYF(MY_WME)) - fname_len - 1;
}
fname[--fname_len]=0; // kill \n
if(!memcmp(fname, to_log, fname_len + 1 ))
{
found_log = 1;
purge_offset = init_purge_offset;
}
if(!found_log && log_in_use(fname))
// if one of the logs before the target is in use
{
error = LOG_INFO_IN_USE;
goto err;
}
// if one of the logs before the target is in use
if(!found_log && log_in_use(fname))
{
error = LOG_INFO_IN_USE;
goto err;
}
p = sql_memdup(fname, (uint)(fname_end - fname) + 1);
if((found_log) ?
insert_dynamic(&logs_to_keep, (gptr) &p) :
insert_dynamic(&logs_to_purge, (gptr) &p)
)
{
error = LOG_INFO_MEM;
goto err;
}
}
if(!found_log)
if (!(p = sql_memdup(fname, (uint)(fname_end - fname) + 1)) ||
insert_dynamic(found_log ? &logs_to_keep : &logs_to_purge,
(gptr) &p))
{
error = LOG_INFO_EOF;
error = LOG_INFO_MEM;
goto err;
}
}
end_io_cache(&io_cache);
if(!found_log)
{
error = LOG_INFO_EOF;
goto err;
}
for(i = 0; i < logs_to_purge.elements; i++)
{
char* l;
get_dynamic(&logs_to_purge, (gptr)&l, i);
if(my_delete(l, MYF(MY_WME)))
sql_print_error("Error deleting %s during purge", l);
}
{
char* l;
get_dynamic(&logs_to_purge, (gptr)&l, i);
if (my_delete(l, MYF(MY_WME)))
sql_print_error("Error deleting %s during purge", l);
}
// if we get killed -9 here, the sysadmin would have to do a small
// vi job on the log index file after restart - otherwise, this should
// be safe
my_fclose(index_file, MYF(MY_WME));
if(!(index_file = my_fopen(index_file_name, O_BINARY|O_WRONLY,
MYF(MY_WME))))
#ifdef HAVE_FTRUNCATE
if (ftruncate(index_file,0))
{
sql_print_error("Ouch! Could not truncate the binlog index file \
during log purge for write");
error = LOG_INFO_FATAL;
goto err;
}
my_seek(index_file, 0, MY_SEEK_CUR,MYF(MY_WME));
#else
my_close(index_file, MYF(MY_WME));
my_delete(index_file_name, MYF(MY_WME));
if(!(index_file = my_open(index_file_name, O_BINARY | O_RDWR | O_APPEND,
MYF(MY_WME))))
{
sql_print_error("Ouch! Could not re-open the binlog index file \
during log purge for write");
error = LOG_INFO_FATAL;
goto err;
}
#endif
for(i = 0; i < logs_to_keep.elements; i++)
{
char* l;
get_dynamic(&logs_to_keep, (gptr)&l, i);
if (my_write(index_file, l, strlen(l), MYF(MY_WME)) ||
my_write(index_file, "\n", 1, MYF(MY_WME)))
{
char* l;
get_dynamic(&logs_to_keep, (gptr)&l, i);
fprintf(index_file, "%s\n", l);
error = LOG_INFO_FATAL;
goto err;
}
my_fclose(index_file, MYF(MY_WME));
if(!(index_file = my_fopen(index_file_name, O_BINARY|O_RDWR|O_APPEND,
MYF(MY_WME))))
{
sql_print_error("Ouch! Could not re-open the binlog index file \
during log purge for append");
error = LOG_INFO_FATAL;
goto err;
}
// now update offsets
adjust_linfo_offsets(purge_offset);
error = 0;
err:
pthread_mutex_unlock(&LOCK_index);
if(logs_to_purge_inited)
delete_dynamic(&logs_to_purge);
if(logs_to_keep_inited)
delete_dynamic(&logs_to_keep);
end_io_cache(&io_cache);
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)
{
......
......@@ -98,7 +98,7 @@ class MYSQL_LOG {
char* get_log_fname() { return log_file_name; }
void lock_index() { pthread_mutex_lock(&LOCK_index);}
void unlock_index() { pthread_mutex_unlock(&LOCK_index);}
FILE* get_index_file() { return index_file;}
File get_index_file() { return index_file;}
};
/* character conversion tables */
......
......@@ -720,66 +720,66 @@ int show_binlog_info(THD* thd)
int show_binlogs(THD* thd)
{
const char* errmsg = 0;
FILE* index_file;
File index_file;
char fname[FN_REFLEN];
NET* net = &thd->net;
List<Item> field_list;
String* packet = &thd->packet;
IO_CACHE io_cache;
uint length;
if(!mysql_bin_log.is_open())
{
errmsg = "binlog is not open";
goto err;
}
{
errmsg = "binlog is not open";
goto err;
}
field_list.push_back(new Item_empty_string("Log_name", 128));
if(send_fields(thd, field_list, 1))
{
sql_print_error("Failed in send_fields");
return 1;
}
{
sql_print_error("Failed in send_fields");
return 1;
}
mysql_bin_log.lock_index();
index_file = mysql_bin_log.get_index_file();
if(!index_file)
{
errmsg = "Uninitialized index file pointer";
mysql_bin_log.unlock_index();
goto err;
}
if(my_fseek(index_file, 0, MY_SEEK_SET, MYF(MY_WME)))
{
errmsg = "Failed on fseek()";
mysql_bin_log.unlock_index();
goto err;
}
while(fgets(fname, sizeof(fname), index_file))
if (index_file < 0)
{
errmsg = "Uninitialized index file pointer";
goto err2;
}
if (init_io_cache(&io_cache, index_file, IO_SIZE, READ_CACHE, 0, 0,
MYF(MY_WME)))
{
errmsg = "Failed on init_io_cache()";
goto err2;
}
while ((length=my_b_gets(&io_cache, fname, sizeof(fname))))
{
fname[--length]=0;
int dir_len = dirname_length(fname);
packet->length(0);
net_store_data(packet, fname + dir_len, length-dir_len);
if(my_net_write(net, (char*) packet->ptr(), packet->length()))
{
char* fname_end;
*(fname_end = (strend(fname) - 1)) = 0;
int dir_len = dirname_length(fname);
packet->length(0);
net_store_data(packet, fname + dir_len, (fname_end - fname)-dir_len);
if(my_net_write(net, (char*) packet->ptr(), packet->length()))
{
sql_print_error("Failed in my_net_write");
mysql_bin_log.unlock_index();
return 1;
}
sql_print_error("Failed in my_net_write");
end_io_cache(&io_cache);
mysql_bin_log.unlock_index();
return 1;
}
}
mysql_bin_log.unlock_index();
end_io_cache(&io_cache);
send_eof(net);
err:
if(errmsg)
{
send_error(net, 0, errmsg);
return 1;
}
send_ok(net);
return 0;
err2:
mysql_bin_log.unlock_index();
end_io_cache(&io_cache);
err:
send_error(net, 0, errmsg);
return 1;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment