in storage/myisam/myisamlog.c [318:697]
static int examine_log(char * file_name, char **table_names)
{
uint command,result,files_open;
ulong access_time,length;
my_off_t filepos;
int lock_command,mi_result;
char isam_file_name[FN_REFLEN],llbuff[21],llbuff2[21];
uchar head[20];
uchar* buff;
struct test_if_open_param open_param;
IO_CACHE cache;
File file;
FILE *write_file;
enum ha_extra_function extra_command;
TREE tree;
struct file_info file_info,*curr_file_info;
DBUG_ENTER("examine_log");
if ((file=my_open(file_name,O_RDONLY,MYF(MY_WME))) < 0)
DBUG_RETURN(1);
write_file=0;
if (write_filename)
{
if (!(write_file=my_fopen(write_filename,O_WRONLY,MYF(MY_WME))))
{
my_close(file,MYF(0));
DBUG_RETURN(1);
}
}
init_io_cache(&cache,file,0,READ_CACHE,start_offset,0,MYF(0));
memset(com_count, 0, sizeof(com_count));
init_tree(&tree,0,0,sizeof(file_info),file_info_compare,1,
(tree_element_free) file_info_free, NULL);
(void) init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,KEY_CACHE_SIZE,
0, 0);
files_open=0; access_time=0;
while (access_time++ != number_of_commands &&
!my_b_read(&cache,(uchar*) head,9))
{
isamlog_filepos=my_b_tell(&cache)-9L;
file_info.filenr= mi_uint2korr(head+1);
isamlog_process=file_info.process=(long) mi_uint4korr(head+3);
if (!opt_processes)
file_info.process=0;
result= mi_uint2korr(head+7);
if ((curr_file_info=(struct file_info*) tree_search(&tree, &file_info,
tree.custom_arg)))
{
curr_file_info->accessed=access_time;
if (update && curr_file_info->used && curr_file_info->closed)
{
if (reopen_closed_file(&tree,curr_file_info))
{
command=sizeof(com_count)/sizeof(com_count[0][0])/3;
result=0;
goto com_err;
}
}
}
command=(uint) head[0];
if (command < sizeof(com_count)/sizeof(com_count[0][0])/3 &&
(!table_names[0] || (curr_file_info && curr_file_info->used)))
{
com_count[command][0]++;
if (result)
com_count[command][1]++;
}
switch ((enum myisam_log_commands) command) {
case MI_LOG_OPEN:
if (!table_names[0])
{
com_count[command][0]--; /* Must be counted explicite */
if (result)
com_count[command][1]--;
}
if (curr_file_info)
printf("\nWarning: %s is opened with same process and filenumber\n"
"Maybe you should use the -P option ?\n",
curr_file_info->show_name);
if (my_b_read(&cache,(uchar*) head,2))
goto err;
buff= 0;
file_info.name=0;
file_info.show_name=0;
file_info.record=0;
if (read_string(&cache, &buff, (uint) mi_uint2korr(head)))
goto err;
{
uint i;
char *pos,*to;
/* Fix if old DOS files to new format */
for (pos=file_info.name=(char*)buff; (pos=strchr(pos,'\\')) ; pos++)
*pos= '/';
pos=file_info.name;
for (i=0 ; i < prefix_remove ; i++)
{
char *next;
if (!(next=strchr(pos,'/')))
break;
pos=next+1;
}
to=isam_file_name;
if (filepath)
to=convert_dirname(isam_file_name,filepath,NullS);
my_stpcpy(to,pos);
fn_ext(isam_file_name)[0]=0; /* Remove extension */
}
open_param.name=file_info.name;
open_param.max_id=0;
(void) tree_walk(&tree,(tree_walk_action) test_if_open,(void*) &open_param,
left_root_right);
file_info.id=open_param.max_id+1;
/*
* In the line below +10 is added to accomodate '<' and '>' chars
* plus '\0' at the end, so that there is place for 7 digits.
* It is improbable that same table can have that many entries in
* the table cache.
* The additional space is needed for the sprintf commands two lines
* below.
*/
file_info.show_name=my_memdup(PSI_NOT_INSTRUMENTED,
isam_file_name,
(uint) strlen(isam_file_name)+10,
MYF(MY_WME));
if (file_info.id > 1)
sprintf(strend(file_info.show_name),"<%d>",file_info.id);
file_info.closed=1;
file_info.accessed=access_time;
file_info.used=1;
if (table_names[0])
{
char **name;
file_info.used=0;
for (name=table_names ; *name ; name++)
{
if (!strcmp(*name,isam_file_name))
file_info.used=1; /* Update/log only this */
}
}
if (update && file_info.used)
{
if (files_open >= max_files)
{
if (close_some_file(&tree))
goto com_err;
files_open--;
}
if (!(file_info.isam= mi_open(isam_file_name,O_RDWR,
HA_OPEN_WAIT_IF_LOCKED)))
goto com_err;
if (!(file_info.record=my_malloc(PSI_NOT_INSTRUMENTED,
file_info.isam->s->base.reclength,
MYF(MY_WME))))
goto end;
files_open++;
file_info.closed=0;
}
(void) tree_insert(&tree, (uchar*) &file_info, 0, tree.custom_arg);
if (file_info.used)
{
if (verbose && !record_pos_file)
printf_log("%s: open -> %d",file_info.show_name, file_info.filenr);
com_count[command][0]++;
if (result)
com_count[command][1]++;
}
break;
case MI_LOG_CLOSE:
if (verbose && !record_pos_file &&
(!table_names[0] || (curr_file_info && curr_file_info->used)))
printf_log("%s: %s -> %d",FILENAME(curr_file_info),
command_name[command],result);
if (curr_file_info)
{
if (!curr_file_info->closed)
files_open--;
(void) tree_delete(&tree, (uchar*) curr_file_info, 0, tree.custom_arg);
}
break;
case MI_LOG_EXTRA:
if (my_b_read(&cache,(uchar*) head,1))
goto err;
extra_command=(enum ha_extra_function) head[0];
if (verbose && !record_pos_file &&
(!table_names[0] || (curr_file_info && curr_file_info->used)))
printf_log("%s: %s(%d) -> %d",FILENAME(curr_file_info),
command_name[command], (int) extra_command,result);
if (update && curr_file_info && !curr_file_info->closed)
{
if (mi_extra(curr_file_info->isam, extra_command, 0) != (int) result)
{
fflush(stdout);
(void) fprintf(stderr,
"Warning: error %d, expected %d on command %s at %s\n",
my_errno(),result,command_name[command],
llstr(isamlog_filepos,llbuff));
fflush(stderr);
}
}
break;
case MI_LOG_DELETE:
if (my_b_read(&cache,(uchar*) head,8))
goto err;
filepos=mi_sizekorr(head);
if (verbose && (!record_pos_file ||
((record_pos == filepos || record_pos == NO_FILEPOS) &&
!cmp_filename(curr_file_info,record_pos_file))) &&
(!table_names[0] || (curr_file_info && curr_file_info->used)))
printf_log("%s: %s at %ld -> %d",FILENAME(curr_file_info),
command_name[command],(long) filepos,result);
if (update && curr_file_info && !curr_file_info->closed)
{
if (mi_rrnd(curr_file_info->isam,curr_file_info->record,filepos))
{
if (!recover)
goto com_err;
if (verbose)
printf_log("error: Didn't find row to delete with mi_rrnd");
com_count[command][2]++; /* Mark error */
}
mi_result=mi_delete(curr_file_info->isam,curr_file_info->record);
if ((mi_result == 0 && result) ||
(mi_result && (uint) my_errno() != result))
{
if (!recover)
goto com_err;
if (mi_result)
com_count[command][2]++; /* Mark error */
if (verbose)
printf_log("error: Got result %d from mi_delete instead of %d",
mi_result, result);
}
}
break;
case MI_LOG_WRITE:
case MI_LOG_UPDATE:
if (my_b_read(&cache,(uchar*) head,12))
goto err;
filepos=mi_sizekorr(head);
length=mi_uint4korr(head+8);
buff=0;
if (read_string(&cache,&buff,(uint) length))
goto err;
if ((!record_pos_file ||
((record_pos == filepos || record_pos == NO_FILEPOS) &&
!cmp_filename(curr_file_info,record_pos_file))) &&
(!table_names[0] || (curr_file_info && curr_file_info->used)))
{
if (write_file &&
(my_fwrite(write_file,buff,length,MYF(MY_WAIT_IF_FULL | MY_NABP))))
goto end;
if (verbose)
printf_log("%s: %s at %ld, length=%ld -> %d",
FILENAME(curr_file_info),
command_name[command], (long)filepos,length,result);
}
if (update && curr_file_info && !curr_file_info->closed)
{
if (curr_file_info->isam->s->base.blobs)
fix_blob_pointers(curr_file_info->isam,buff);
if ((enum myisam_log_commands) command == MI_LOG_UPDATE)
{
if (mi_rrnd(curr_file_info->isam,curr_file_info->record,filepos))
{
if (!recover)
{
result=0;
goto com_err;
}
if (verbose)
printf_log("error: Didn't find row to update with mi_rrnd");
if (recover == 1 || result ||
find_record_with_key(curr_file_info,buff))
{
com_count[command][2]++; /* Mark error */
break;
}
}
mi_result=mi_update(curr_file_info->isam,curr_file_info->record,
buff);
if ((mi_result == 0 && result) ||
(mi_result && (uint) my_errno() != result))
{
if (!recover)
goto com_err;
if (verbose)
printf_log("error: Got result %d from mi_update instead of %d",
mi_result, result);
if (mi_result)
com_count[command][2]++; /* Mark error */
}
}
else
{
mi_result=mi_write(curr_file_info->isam,buff);
if ((mi_result == 0 && result) ||
(mi_result && (uint) my_errno() != result))
{
if (!recover)
goto com_err;
if (verbose)
printf_log("error: Got result %d from mi_write instead of %d",
mi_result, result);
if (mi_result)
com_count[command][2]++; /* Mark error */
}
if (!recover && filepos != curr_file_info->isam->lastpos)
{
printf("error: Wrote at position: %s, should have been %s",
llstr(curr_file_info->isam->lastpos,llbuff),
llstr(filepos,llbuff2));
goto end;
}
}
}
my_free(buff);
break;
case MI_LOG_LOCK:
if (my_b_read(&cache,(uchar*) head,sizeof(lock_command)))
goto err;
memcpy(&lock_command, head, sizeof(lock_command));
if (verbose && !record_pos_file &&
(!table_names[0] || (curr_file_info && curr_file_info->used)))
printf_log("%s: %s(%d) -> %d\n",FILENAME(curr_file_info),
command_name[command],lock_command,result);
if (update && curr_file_info && !curr_file_info->closed)
{
if (mi_lock_database(curr_file_info->isam,lock_command) !=
(int) result)
goto com_err;
}
break;
case MI_LOG_DELETE_ALL:
if (verbose && !record_pos_file &&
(!table_names[0] || (curr_file_info && curr_file_info->used)))
printf_log("%s: %s -> %d\n",FILENAME(curr_file_info),
command_name[command],result);
break;
default:
fflush(stdout);
(void) fprintf(stderr,
"Error: found unknown command %d in logfile, aborted\n",
command);
fflush(stderr);
goto end;
}
}
end_key_cache(dflt_key_cache,1);
delete_tree(&tree);
(void) end_io_cache(&cache);
(void) my_close(file,MYF(0));
if (write_file && my_fclose(write_file,MYF(MY_WME)))
DBUG_RETURN(1);
DBUG_RETURN(0);
err:
fflush(stdout);
(void) fprintf(stderr,"Got error %d when reading from logfile\n",my_errno());
fflush(stderr);
goto end;
com_err:
fflush(stdout);
(void) fprintf(stderr,"Got error %d, expected %d on command %s at %s\n",
my_errno(),result,command_name[command],
llstr(isamlog_filepos,llbuff));
fflush(stderr);
end:
end_key_cache(dflt_key_cache, 1);
delete_tree(&tree);
(void) end_io_cache(&cache);
(void) my_close(file,MYF(0));
if (write_file)
(void) my_fclose(write_file,MYF(MY_WME));
DBUG_RETURN(1);
}