Commit bec3feaa authored by unknown's avatar unknown

WL#1895 - Print message to error log in case of detected MyISAM corruption

Changed my_error() to print error messages, which come from
arbitrary registered ranges of error messages. Messages can
be unregistered (and should be at end of the program).
Added registration of handler error messages.
Added a new mi_print_error() macro and a new 
mi_report_error() function, which supply error
messages with a table name.
Added calls to mi_print_error() or mi_report_error()
at all places in MyISAM, where table corruption is detected.


extra/comp_err.c:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Added prints for ER_ERROR_FIRST and ER_ERROR_LAST.
  Removed print for ER_ERROR_MESSAGES.
include/errmsg.h:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Added declaration for a new function.
  Added first and last error number defines.
include/my_base.h:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Added first and last error number defines.
include/my_sys.h:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Removed obsolete defines.
  Removed a global variable, which held pointers to the error message arrays.
  Added declarations for new functions.
include/mysys_err.h:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Removed an obsolete define.
  Changed two defines to use the new defines.
  Added first and last error number defines.
libmysql/errmsg.c:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Replaced global array initialization by proper registration
  and unregistration of client error messages.
libmysql/libmysql.c:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Added a call for unregistration of client error messages.
myisam/mi_delete.c:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Added calls to the new error logging function at all places, where
  corruption is detected.
  Added a debugging call to pretend MyISAM corruption in case a special
  debug string is set.
  Added a debugging call to test undefined error numbers in case a special
  debug string is set.
myisam/mi_extra.c:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Added calls to the new error logging function at all places, where
  corruption is detected.
myisam/mi_info.c:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Added the error logging function.
myisam/mi_key.c:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Added calls to the new error logging function at all places, where
  corruption is detected.
myisam/mi_keycache.c:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Added calls to the new error logging function at all places, where
  corruption is detected.
myisam/mi_locking.c:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Added calls to the new error logging function at all places, where
  corruption is detected.
myisam/mi_open.c:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Added calls to the new error logging function at all places, where
  corruption is detected.
  Added a debugging call to pretend MyISAM corruption in case a special
  debug string is set.
myisam/mi_page.c:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Added calls to the new error logging function at all places, where
  corruption is detected.
myisam/mi_range.c:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Added calls to the new error logging function at all places, where
  corruption is detected.
myisam/mi_rkey.c:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Added calls to the new error logging function at all places, where
  corruption is detected.
myisam/mi_search.c:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Added calls to the new error logging function at all places, where
  corruption is detected.
myisam/mi_update.c:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Added calls to the new error logging function at all places, where
  corruption is detected.
  Added a debugging call to pretend MyISAM corruption in case a special
  debug string is set.
myisam/mi_write.c:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Added calls to the new error logging function at all places, where
  corruption is detected.
  Added a debugging call to pretend MyISAM corruption in case a special
  debug string is set.
myisam/myisamdef.h:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Added the declaration of the new error logging function
  and a new macro.
mysql-test/r/merge.result:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Changed test results. These come from the changed error reporting
  in openfrm().
mysql-test/r/repair.result:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Changed test results. These come from the changed error reporting
  in openfrm().
mysql-test/t/merge.test:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Changederror numbers. These come from the changed error reporting
  in openfrm().
mysys/errors.c:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Dropped the assignment of the global errors to the
  dropped global pointer array.
mysys/my_error.c:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Changed my_error() from using a static array of pointers to
  error message arrays to using a linked list of structures
  with pointers to array message arrays.
  Added functions for registering and unregistering error 
  message arrays to the chain.
sql/derror.cc:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Changed reading of mysqld error messages to using the new
  registering and unregistering functions.
sql/handler.cc:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Added initialization and deinitialization of handler error messages.
  Included more handler error messages in the mapping to
  mysqld error messages.
sql/mysqld.cc:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Changed deinitialization of error messages to proper
  unregistration.
sql/table.cc:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Changed error reporting in openfrm() so that error messages from
  handler::ha_open() are reported by handler::print_error(). This
  changed messages from "Can't open 't1.MYI' (errno: 130)" to
  "Incorrect file format 't1'" for example.
sql/unireg.h:
  WL#1895 - Print message to error log in case of detected MyISAM corruption
  Changed two defines to use the new defines.
parent 1a197454
......@@ -191,10 +191,11 @@ int main(int argc, char *argv[])
static int create_header_files(struct errors *error_head)
{
uint er_count= 0;
uint er_last;
FILE *er_definef, *sql_statef;
struct errors *tmp_error;
DBUG_ENTER("create_header_files");
LINT_INIT(er_last);
if (!(er_definef= my_fopen(HEADERFILE, O_WRONLY, MYF(MY_WME))))
{
......@@ -209,6 +210,8 @@ static int create_header_files(struct errors *error_head)
fprintf(er_definef, "/* Autogenerated file, please don't edit */\n\n");
fprintf(sql_statef, "/* Autogenerated file, please don't edit */\n\n");
fprintf(er_definef, "#define ER_ERROR_FIRST %d\n", error_head->d_code);
for (tmp_error= error_head; tmp_error; tmp_error= tmp_error->next_error)
{
/*
......@@ -217,16 +220,16 @@ static int create_header_files(struct errors *error_head)
*/
fprintf(er_definef, "#define %s %d\n", tmp_error->er_name,
tmp_error->d_code);
er_last= tmp_error->d_code;
/* generating sql_state.h file */
if (tmp_error->sql_code1[0] || tmp_error->sql_code2[0])
fprintf(sql_statef,
"%-40s,\"%s\", \"%s\",\n", tmp_error->er_name,
tmp_error->sql_code1, tmp_error->sql_code2);
er_count++;
}
/* finishing off with mysqld_error.h */
fprintf(er_definef, "#define ER_ERROR_MESSAGES %d\n", er_count);
fprintf(er_definef, "#define ER_ERROR_LAST %d\n", er_last);
my_fclose(er_definef, MYF(0));
my_fclose(sql_statef, MYF(0));
DBUG_RETURN(0);
......
......@@ -21,6 +21,7 @@
extern "C" {
#endif
void init_client_errs(void);
void finish_client_errs(void);
extern const char *client_errors[]; /* Error messages */
#ifdef __cplusplus
}
......@@ -35,6 +36,9 @@ extern const char *client_errors[]; /* Error messages */
#endif
#define CLIENT_ERRMAP 2 /* Errormap used by my_error() */
/* Do not add error numbers before CR_ERROR_FIRST. */
/* If necessary to add lower numbers, change CR_ERROR_FIRST accordingly. */
#define CR_ERROR_FIRST 2000 /*Copy first error nr.*/
#define CR_UNKNOWN_ERROR 2000
#define CR_SOCKET_CREATE_ERROR 2001
#define CR_CONNECTION_ERROR 2002
......@@ -90,3 +94,6 @@ extern const char *client_errors[]; /* Error messages */
#define CR_SECURE_AUTH 2049
#define CR_FETCH_CANCELED 2050
#define CR_NO_DATA 2051
#define CR_ERROR_LAST /*Copy last error nr:*/ 2051
/* Add error numbers before CR_ERROR_LAST and change it accordingly. */
......@@ -273,6 +273,9 @@ enum ha_base_keytype {
/* Errorcodes given by functions */
/* opt_sum_query() assumes these codes are > 1 */
/* Do not add error numbers before HA_ERR_FIRST. */
/* If necessary to add lower numbers, change HA_ERR_FIRST accordingly. */
#define HA_ERR_FIRST 120 /*Copy first error nr.*/
#define HA_ERR_KEY_NOT_FOUND 120 /* Didn't find key on read or update */
#define HA_ERR_FOUND_DUPP_KEY 121 /* Dupplicate key on write */
#define HA_ERR_RECORD_CHANGED 123 /* Uppdate with is recoverable */
......@@ -308,6 +311,9 @@ enum ha_base_keytype {
#define HA_ERR_NO_SUCH_TABLE 155 /* The table does not exist in engine */
#define HA_ERR_TABLE_EXIST 156 /* The table existed in storage engine */
#define HA_ERR_NO_CONNECTION 157 /* Could not connect to storage engine */
#define HA_ERR_LAST 157 /*Copy last error nr.*/
/* Add error numbers before HA_ERR_LAST and change it accordingly. */
#define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1)
/* Other constants */
......
......@@ -43,8 +43,6 @@ extern int NEAR my_errno; /* Last error in mysys */
#define MYSYS_PROGRAM_DONT_USE_CURSES() { error_handler_hook = my_message_no_curses; mysys_uses_curses=0;}
#define MY_INIT(name); { my_progname= name; my_init(); }
#define MAXMAPS (4) /* Number of error message maps */
#define ERRMOD (1000) /* Max number of errors in a map */
#define ERRMSGSIZE (SC_MAXWIDTH) /* Max length of a error message */
#define NRERRBUFFS (2) /* Buffers for parameters */
#define MY_FILE_ERROR ((uint) ~0)
......@@ -213,7 +211,6 @@ void __CDECL hfree(void *ptr);
#else
extern int errno; /* declare errno */
#endif
extern const char ** NEAR my_errmsg[];
extern char NEAR errbuff[NRERRBUFFS][ERRMSGSIZE];
extern char *home_dir; /* Home directory for user */
extern char *my_progname; /* program-name (printed in errors) */
......@@ -610,6 +607,8 @@ extern int my_error _VARARGS((int nr,myf MyFlags, ...));
extern int my_printf_error _VARARGS((uint my_err, const char *format,
myf MyFlags, ...)
__attribute__ ((format (printf, 2, 4))));
extern int my_error_register(const char **errmsgs, int first, int last);
extern const char **my_error_unregister(int first, int last);
extern int my_message(uint my_err, const char *str,myf MyFlags);
extern int my_message_no_curses(uint my_err, const char *str,myf MyFlags);
extern int my_message_curses(uint my_err, const char *str,myf MyFlags);
......
......@@ -20,13 +20,15 @@
extern "C" {
#endif
#define GLOB 0 /* Error maps */
#define GLOBERRS 28 /* Max number of error messages in map's */
#define EE(X) globerrs[ X ] /* Defines to add error to right map */
#define GLOBERRS (EE_ERROR_LAST - EE_ERROR_FIRST + 1) /* Nr of global errors */
#define EE(X) (globerrs[(X) - EE_ERROR_FIRST])
extern const char * NEAR globerrs[]; /* my_error_messages is here */
/* Error message numbers in global map */
/* Do not add error numbers before EE_ERROR_FIRST. */
/* If necessary to add lower numbers, change EE_ERROR_FIRST accordingly. */
#define EE_ERROR_FIRST 0 /*Copy first error nr.*/
#define EE_FILENOTFOUND 0
#define EE_CANTCREATEFILE 1
#define EE_READ 2
......@@ -54,6 +56,8 @@ extern const char * NEAR globerrs[]; /* my_error_messages is here */
#define EE_CANT_SYMLINK 25
#define EE_REALPATH 26
#define EE_SYNC 27
#define EE_ERROR_LAST 27 /*Copy last error nr.*/
/* Add error numbers before EE_ERROR_LAST and change it accordingly. */
/* exit codes for all MySQL programs */
......
......@@ -199,7 +199,33 @@ const char *client_errors[]=
#endif
/*
Register client error messages for use with my_error().
SYNOPSIS
init_client_errs()
RETURN
void
*/
void init_client_errs(void)
{
my_errmsg[CLIENT_ERRMAP] = &client_errors[0];
(void) my_error_register(client_errors, CR_ERROR_FIRST, CR_ERROR_LAST);
}
/*
Unregister client error messages.
SYNOPSIS
finish_client_errs()
RETURN
void
*/
void finish_client_errs(void)
{
(void) my_error_unregister(CR_ERROR_FIRST, CR_ERROR_LAST);
}
......@@ -185,6 +185,7 @@ void STDCALL mysql_server_end()
}
else
mysql_thread_end();
finish_client_errs();
mysql_client_init= org_my_init_done= 0;
}
......
......@@ -45,6 +45,12 @@ int mi_delete(MI_INFO *info,const byte *record)
/* Test if record is in datafile */
DBUG_EXECUTE_IF("myisam_pretend_crashed_table_on_usage",
mi_print_error(info, HA_ERR_CRASHED);
DBUG_RETURN(my_errno= HA_ERR_CRASHED););
DBUG_EXECUTE_IF("my_error_test_undefined_error",
mi_print_error(info, INT_MAX);
DBUG_RETURN(my_errno= INT_MAX););
if (!(info->update & HA_STATE_AKTIV))
{
DBUG_RETURN(my_errno=HA_ERR_KEY_NOT_FOUND); /* No database read */
......@@ -109,13 +115,19 @@ err:
mi_sizestore(lastpos,info->lastpos);
myisam_log_command(MI_LOG_DELETE,info,(byte*) lastpos, sizeof(lastpos),0);
if (save_errno != HA_ERR_RECORD_CHANGED)
{
mi_print_error(info, HA_ERR_CRASHED);
mi_mark_crashed(info); /* mark table crashed */
}
VOID(_mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
info->update|=HA_STATE_WRITTEN; /* Buffer changed */
allow_break(); /* Allow SIGHUP & SIGINT */
my_errno=save_errno;
if (save_errno == HA_ERR_KEY_NOT_FOUND)
{
mi_print_error(info, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
}
DBUG_RETURN(my_errno);
} /* mi_delete */
......@@ -142,6 +154,7 @@ static int _mi_ck_real_delete(register MI_INFO *info, MI_KEYDEF *keyinfo,
if ((old_root=*root) == HA_OFFSET_ERROR)
{
mi_print_error(info, HA_ERR_CRASHED);
DBUG_RETURN(my_errno=HA_ERR_CRASHED);
}
if (!(root_buff= (uchar*) my_alloca((uint) keyinfo->block_length+
......@@ -253,7 +266,9 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
my_off_t root;
uchar *kpos=keypos;
tmp_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&kpos,lastkey);
if (!(tmp_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&kpos,lastkey))
&& (my_errno == HA_ERR_CRASHED))
mi_print_error(info, HA_ERR_CRASHED);
root=_mi_dpos(info,nod_flag,kpos);
if (subkeys == -1)
{
......@@ -302,6 +317,7 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
if (!nod_flag)
{
DBUG_PRINT("error",("Didn't find key"));
mi_print_error(info, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED; /* This should newer happend */
goto err;
}
......@@ -317,6 +333,8 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
&next_block);
if (tmp == 0)
{
if (my_errno == HA_ERR_CRASHED)
mi_print_error(info, HA_ERR_CRASHED);
DBUG_PRINT("exit",("Return: %d",0));
DBUG_RETURN(0);
}
......@@ -473,6 +491,8 @@ static int del(register MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *key,
(info->quick_mode ? MI_MIN_KEYBLOCK_LENGTH :
(uint) keyinfo->underflow_block_length));
err:
if (my_errno == HA_ERR_CRASHED)
mi_print_error(info, HA_ERR_CRASHED);
DBUG_RETURN(-1);
} /* del */
......@@ -562,7 +582,11 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo,
s_length=remove_key(keyinfo,key_reflength,keypos,anc_key,
anc_buff+anc_length,(my_off_t *) 0);
if (!s_length)
{
if (my_errno == HA_ERR_CRASHED)
mi_print_error(info, HA_ERR_CRASHED);
goto err;
}
anc_length-=s_length;
mi_putint(anc_buff,anc_length,key_reflength);
......@@ -671,7 +695,11 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo,
s_length=remove_key(keyinfo,key_reflength,keypos,anc_key,
anc_buff+anc_length,(my_off_t *) 0);
if (!s_length)
{
if (my_errno == HA_ERR_CRASHED)
mi_print_error(info, HA_ERR_CRASHED);
goto err;
}
anc_length-=s_length;
mi_putint(anc_buff,anc_length,key_reflength);
......@@ -732,6 +760,8 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo,
goto err;
DBUG_RETURN(anc_length <= (uint) keyinfo->block_length/2);
err:
if (my_errno == HA_ERR_CRASHED)
mi_print_error(info, HA_ERR_CRASHED);
DBUG_RETURN(-1);
} /* underflow */
......
......@@ -186,7 +186,10 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
if (info->opt_flag & WRITE_CACHE_USED)
{
if ((error=flush_io_cache(&info->rec_cache)))
{
mi_print_error(info, HA_ERR_CRASHED);
mi_mark_crashed(info); /* Fatal error found */
}
}
break;
case HA_EXTRA_NO_READCHECK:
......@@ -285,6 +288,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
{
error=my_errno;
share->changed=1;
mi_print_error(info, HA_ERR_CRASHED);
mi_mark_crashed(info); /* Fatal error found */
}
if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
......@@ -339,6 +343,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
if (error)
{
share->changed=1;
mi_print_error(info, HA_ERR_CRASHED);
mi_mark_crashed(info); /* Fatal error found */
}
}
......
......@@ -105,3 +105,36 @@ int mi_status(MI_INFO *info, register MI_ISAMINFO *x, uint flag)
}
DBUG_RETURN(0);
}
/*
Write a message to the error log.
SYNOPSIS
mi_report_error()
file_name Name of table file (e.g. index_file_name).
errcode Error number.
DESCRIPTION
This function supplies my_error() with a table name. Most error
messages need one. Since string arguments in error messages are limited
to 64 characters by convention, we ensure that in case of truncation,
that the end of the index file path is in the message. This contains
the most valuable information (the table name and the database name).
RETURN
void
*/
void mi_report_error(int errcode, const char *file_name)
{
size_t lgt;
DBUG_ENTER("mi_report_error");
DBUG_PRINT("enter",("errcode %d, table '%s'", errcode, file_name));
if ((lgt= strlen(file_name)) > 64)
file_name+= lgt - 64;
my_error(errcode, MYF(ME_NOREFRESH), file_name);
DBUG_VOID_RETURN;
}
......@@ -477,6 +477,7 @@ int _mi_read_key_record(MI_INFO *info, my_off_t filepos, byte *buf)
{ /* Read only key */
if (_mi_put_key_in_record(info,(uint) info->lastinx,buf))
{
mi_print_error(info, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
return -1;
}
......
......@@ -79,6 +79,7 @@ int mi_assign_to_key_cache(MI_INFO *info,
if (flush_key_blocks(share->key_cache, share->kfile, FLUSH_RELEASE))
{
error= my_errno;
mi_print_error(info, HA_ERR_CRASHED);
mi_mark_crashed(info); /* Mark that table must be checked */
}
......
......@@ -66,6 +66,7 @@ int mi_lock_database(MI_INFO *info, int lock_type)
share->kfile,FLUSH_KEEP))
{
error=my_errno;
mi_print_error(info, HA_ERR_CRASHED);
mi_mark_crashed(info); /* Mark that table must be checked */
}
if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
......@@ -73,6 +74,7 @@ int mi_lock_database(MI_INFO *info, int lock_type)
if (end_io_cache(&info->rec_cache))
{
error=my_errno;
mi_print_error(info, HA_ERR_CRASHED);
mi_mark_crashed(info);
}
}
......@@ -98,7 +100,10 @@ int mi_lock_database(MI_INFO *info, int lock_type)
else
share->not_flushed=1;
if (error)
{
mi_print_error(info, HA_ERR_CRASHED);
mi_mark_crashed(info);
}
}
if (info->lock_type != F_EXTRA_LCK)
{
......@@ -285,6 +290,7 @@ void mi_update_status(void* param)
{
if (end_io_cache(&info->rec_cache))
{
mi_print_error(info, HA_ERR_CRASHED);
mi_mark_crashed(info);
}
info->opt_flag&= ~WRITE_CACHE_USED;
......
......@@ -106,6 +106,12 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
share_buff.state.key_del=key_del;
share_buff.key_cache= multi_key_cache_search(name_buff, strlen(name_buff));
DBUG_EXECUTE_IF("myisam_pretend_crashed_table_on_open",
if (strstr(name, "/t1"))
{
my_errno= HA_ERR_CRASHED;
goto err;
});
if ((kfile=my_open(name_buff,(open_mode=O_RDWR) | O_SHARE,MYF(0))) < 0)
{
if ((errno != EROFS && errno != EACCES) ||
......@@ -601,6 +607,10 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
err:
save_errno=my_errno ? my_errno : HA_ERR_END_OF_FILE;
if ((save_errno == HA_ERR_CRASHED) ||
(save_errno == HA_ERR_CRASHED_ON_USAGE) ||
(save_errno == HA_ERR_CRASHED_ON_REPAIR))
mi_report_error(save_errno, name);
switch (errpos) {
case 6:
my_free((gptr) m_info,MYF(0));
......@@ -1223,7 +1233,10 @@ int mi_enable_indexes(MI_INFO *info)
if (share->state.state.data_file_length ||
(share->state.state.key_file_length != share->base.keystart))
{
mi_print_error(info, HA_ERR_CRASHED);
error= HA_ERR_CRASHED;
}
else
share->state.key_map= ((ulonglong) 1L << share->base.keys) - 1;
return error;
......
......@@ -40,6 +40,7 @@ uchar *_mi_fetch_keypage(register MI_INFO *info, MI_KEYDEF *keyinfo,
{
DBUG_PRINT("error",("Got errno: %d from key_cache_read",my_errno));
info->last_keypage=HA_OFFSET_ERROR;
mi_print_error(info, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(0);
}
......@@ -51,6 +52,7 @@ uchar *_mi_fetch_keypage(register MI_INFO *info, MI_KEYDEF *keyinfo,
(ulong) page, page_size));
DBUG_DUMP("page", (char*) tmp, keyinfo->block_length);
info->last_keypage = HA_OFFSET_ERROR;
mi_print_error(info, HA_ERR_CRASHED);
my_errno = HA_ERR_CRASHED;
tmp = 0;
}
......
......@@ -233,7 +233,11 @@ static uint _mi_keynr(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, u
while (page < end)
{
if (!(*keyinfo->get_key)(keyinfo,nod_flag,&page,t_buff))
{
if (my_errno == HA_ERR_CRASHED)
mi_print_error(info, HA_ERR_CRASHED);
return 0; /* Error */
}
max_key++;
if (page == keypos)
keynr=max_key;
......
......@@ -78,6 +78,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
case HA_KEY_ALG_RTREE:
if (rtree_find_first(info,inx,key_buff,use_key_length,nextflag) < 0)
{
mi_print_error(info, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
goto err;
}
......
......@@ -161,6 +161,8 @@ int _mi_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
DBUG_RETURN(0);
err:
DBUG_PRINT("exit",("Error: %d",my_errno));
if (my_errno == HA_ERR_CRASHED)
mi_print_error(info, HA_ERR_CRASHED);
info->lastpos= HA_OFFSET_ERROR;
info->page_changed=1;
DBUG_RETURN (-1);
......@@ -234,6 +236,7 @@ int _mi_seq_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,t_buff);
if (length == 0 || page > end)
{
mi_print_error(info, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_PRINT("error",("Found wrong key: length: %u page: %p end: %p",
length, page, end));
......@@ -380,6 +383,7 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
if (page > end)
{
mi_print_error(info, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_PRINT("error",("Found wrong key: length: %u page: %p end: %p",
length, page, end));
......@@ -969,6 +973,7 @@ uchar *_mi_get_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
*return_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,key);
if (*return_key_length == 0)
{
mi_print_error(info, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(0);
}
......@@ -1006,6 +1011,7 @@ static my_bool _mi_get_prev_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
*return_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,key);
if (*return_key_length == 0)
{
mi_print_error(info, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(1);
}
......@@ -1046,6 +1052,7 @@ uchar *_mi_get_last_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
if (*return_key_length == 0)
{
DBUG_PRINT("error",("Couldn't find last key: page: %p", page));
mi_print_error(info, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(0);
}
......@@ -1178,7 +1185,11 @@ int _mi_search_next(register MI_INFO *info, register MI_KEYDEF *keyinfo,
memcpy(lastkey,key,key_length);
if (!(info->lastkey_length=(*keyinfo->get_key)(keyinfo,nod_flag,
&info->int_keypos,lastkey)))
{
if (my_errno == HA_ERR_CRASHED)
mi_print_error(info, HA_ERR_CRASHED);
DBUG_RETURN(-1);
}
}
else /* Previous key */
{
......@@ -1236,8 +1247,10 @@ int _mi_search_first(register MI_INFO *info, register MI_KEYDEF *keyinfo,
page=info->buff+2+nod_flag;
} while ((pos=_mi_kpos(nod_flag,page)) != HA_OFFSET_ERROR);
info->lastkey_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,
info->lastkey);
if (!(info->lastkey_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,
info->lastkey)) &&
(my_errno == HA_ERR_CRASHED))
mi_print_error(info, HA_ERR_CRASHED);
info->int_keypos=page; info->int_maxpos=info->buff+mi_getint(info->buff)-1;
info->int_nod_flag=nod_flag;
info->int_keytree_version=keyinfo->version;
......
......@@ -34,6 +34,9 @@ int mi_update(register MI_INFO *info, const byte *oldrec, byte *newrec)
LINT_INIT(changed);
LINT_INIT(old_checksum);
DBUG_EXECUTE_IF("myisam_pretend_crashed_table_on_usage",
mi_print_error(info, HA_ERR_CRASHED);
DBUG_RETURN(my_errno= HA_ERR_CRASHED););
if (!(info->update & HA_STATE_AKTIV))
{
DBUG_RETURN(my_errno=HA_ERR_KEY_NOT_FOUND);
......@@ -205,7 +208,10 @@ err:
} while (i-- != 0);
}
else
{
mi_print_error(info, HA_ERR_CRASHED);
mi_mark_crashed(info);
}
info->update= (HA_STATE_CHANGED | HA_STATE_AKTIV | HA_STATE_ROW_CHANGED |
key_changed);
......@@ -214,6 +220,9 @@ err:
VOID(_mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
allow_break(); /* Allow SIGHUP & SIGINT */
if (save_errno == HA_ERR_KEY_NOT_FOUND)
{
mi_print_error(info, HA_ERR_CRASHED);
save_errno=HA_ERR_CRASHED;
}
DBUG_RETURN(my_errno=save_errno);
} /* mi_update */
......@@ -52,6 +52,9 @@ int mi_write(MI_INFO *info, byte *record)
DBUG_ENTER("mi_write");
DBUG_PRINT("enter",("isam: %d data: %d",info->s->kfile,info->dfile));
DBUG_EXECUTE_IF("myisam_pretend_crashed_table_on_usage",
mi_print_error(info, HA_ERR_CRASHED);
DBUG_RETURN(my_errno= HA_ERR_CRASHED););
if (share->options & HA_OPTION_READ_ONLY_DATA)
{
DBUG_RETURN(my_errno=EACCES);
......@@ -202,7 +205,10 @@ err:
}
}
else
{
mi_print_error(info, HA_ERR_CRASHED);
mi_mark_crashed(info);
}
info->update= (HA_STATE_CHANGED | HA_STATE_WRITTEN | HA_STATE_ROW_CHANGED);
my_errno=save_errno;
err2:
......@@ -346,7 +352,11 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
if (tmp_key_length)
dupp_key_pos=_mi_dpos(info,0,keybuff+tmp_key_length);
else
{
if (my_errno == HA_ERR_CRASHED)
mi_print_error(info, HA_ERR_CRASHED);
dupp_key_pos= HA_OFFSET_ERROR;
}
if (keyinfo->flag & HA_FULLTEXT)
{
uint off;
......@@ -455,6 +465,7 @@ int _mi_insert(register MI_INFO *info, register MI_KEYDEF *keyinfo,
{
if (t_length >= keyinfo->maxlength*2+MAX_POINTER_LENGTH)
{
mi_print_error(info, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(-1);
}
......@@ -464,6 +475,7 @@ int _mi_insert(register MI_INFO *info, register MI_KEYDEF *keyinfo,
{
if (-t_length >= keyinfo->maxlength*2+MAX_POINTER_LENGTH)
{
mi_print_error(info, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(-1);
}
......@@ -558,7 +570,11 @@ int _mi_split_page(register MI_INFO *info, register MI_KEYDEF *keyinfo,
key_pos=_mi_find_half_pos(nod_flag,keyinfo,buff,key_buff, &key_length,
&after_key);
if (!key_pos)
{
if (my_errno == HA_ERR_CRASHED)
mi_print_error(info, HA_ERR_CRASHED);
DBUG_RETURN(-1);
}
length=(uint) (key_pos-buff);
a_length=mi_getint(buff);
mi_putint(buff,length,nod_flag);
......@@ -578,7 +594,11 @@ int _mi_split_page(register MI_INFO *info, register MI_KEYDEF *keyinfo,
/* Store new page */
if (!(*keyinfo->get_key)(keyinfo,nod_flag,&key_pos,key_buff))
{
if (my_errno == HA_ERR_CRASHED)
mi_print_error(info, HA_ERR_CRASHED);
DBUG_RETURN(-1);
}
t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,(uchar *) 0,
(uchar*) 0, (uchar*) 0,
key_buff, &s_temp);
......
......@@ -356,6 +356,8 @@ typedef struct st_mi_sort_param
#define mi_mark_crashed_on_repair(x) { (x)->s->state.changed|=STATE_CRASHED|STATE_CRASHED_ON_REPAIR ; (x)->update|= HA_STATE_CHANGED; }
#define mi_is_crashed(x) ((x)->s->state.changed & STATE_CRASHED)
#define mi_is_crashed_on_repair(x) ((x)->s->state.changed & STATE_CRASHED_ON_REPAIR)
#define mi_print_error(INFO, ERRNO) \
mi_report_error((ERRNO), (INFO)->s->index_file_name)
/* Functions to store length of space packed keys, VARCHAR or BLOB keys */
......@@ -667,6 +669,7 @@ extern void _myisam_log_command(enum myisam_log_commands command,
extern void _myisam_log_record(enum myisam_log_commands command,MI_INFO *info,
const byte *record,my_off_t filepos,
int result);
extern void mi_report_error(int errcode, const char *file_name);
extern my_bool _mi_memmap_file(MI_INFO *info);
extern void _mi_unmap_file(MI_INFO *info);
extern uint save_pack_length(byte *block_buff,ulong length);
......
......@@ -178,9 +178,9 @@ t3 CREATE TABLE `t3` (
) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t1`,`t2`)
create table t4 (a int not null, b char(10), key(a)) engine=MERGE UNION=(t1,t2);
select * from t4;
ERROR HY000: Can't open file: 't4.MRG' (errno: 143)
ERROR HY000: All tables in the MERGE table are not identically defined
alter table t4 add column c int;
ERROR HY000: Can't open file: 't4.MRG' (errno: 143)
ERROR HY000: All tables in the MERGE table are not identically defined
create database mysqltest;
create table mysqltest.t6 (a int not null primary key auto_increment, message char(20));
create table t5 (a int not null, b char(20), key(a)) engine=MERGE UNION=(test.t1,mysqltest.t6);
......
......@@ -31,7 +31,7 @@ create table t1 engine=myisam SELECT 1,"table 1";
flush tables;
repair table t1;
Table Op Msg_type Msg_text
test.t1 repair error Can't open file: 't1.MYI' (errno: 130)
test.t1 repair error Incorrect file format 't1'
repair table t1 use_frm;
Table Op Msg_type Msg_text
test.t1 repair warning Number of rows changed from 0 to 1
......
......@@ -47,9 +47,9 @@ show create table t3;
# The following should give errors
create table t4 (a int not null, b char(10), key(a)) engine=MERGE UNION=(t1,t2);
--error 1016
--error 1168
select * from t4;
--error 1016
--error 1168
alter table t4 add column c int;
#
......
......@@ -53,15 +53,13 @@ const char * NEAR globerrs[GLOBERRS]=
void init_glob_errs(void)
{
my_errmsg[GLOB] = & globerrs[0];
} /* init_glob_errs */
/* This is now done statically. */
}
#else
void init_glob_errs()
{
my_errmsg[GLOB] = & globerrs[0];
EE(EE_FILENOTFOUND) = "File '%s' not found (Errcode: %d)";
EE(EE_CANTCREATEFILE) = "Can't create/write to file '%s' (Errcode: %d)";
EE(EE_READ) = "Error reading file '%s' (Errcode: %d)";
......
......@@ -31,9 +31,30 @@
my_printf_error(ER_CODE, format, MYF(N), ...)
*/
const char ** NEAR my_errmsg[MAXMAPS]={0,0,0,0};
char NEAR errbuff[NRERRBUFFS][ERRMSGSIZE];
/*
Message texts are registered into a linked list of 'my_err_head' structs.
Each struct contains (1.) an array of pointers to C character strings with
'\0' termination, (2.) the error number for the first message in the array
(array index 0) and (3.) the error number for the last message in the array
(array index (last - first)).
The array may contain gaps with NULL pointers and pointers to empty strings.
Both kinds of gaps will be translated to "Unknown error %d.", if my_error()
is called with a respective error number.
The list of header structs is sorted in increasing order of error numbers.
Negative error numbers are allowed. Overlap of error numbers is not allowed.
Not registered error numbers will be translated to "Unknown error %d.".
*/
static struct my_err_head
{
struct my_err_head *meh_next; /* chain link */
const char **meh_errmsgs; /* error messages array */
int meh_first; /* error number matching array slot 0 */
int meh_last; /* error number matching last slot */
} my_errmsgs_globerrs = {NULL, globerrs, EE_ERROR_FIRST, EE_ERROR_LAST};
static struct my_err_head *my_errmsgs_list= &my_errmsgs_globerrs;
/*
Error message to user
......@@ -42,30 +63,42 @@ char NEAR errbuff[NRERRBUFFS][ERRMSGSIZE];
nr Errno
MyFlags Flags
... variable list
NOTE
The following subset of printf format is supported:
"%[0-9.-]*l?[sdu]", where all length flags are parsed but ignored.
Additionally "%.*s" is supported and "%.*[ud]" is correctly parsed but
the length value is ignored.
RETURN
What (*error_handler_hook)() returns:
0 OK
*/
int my_error(int nr, myf MyFlags, ...)
{
const char *format;
struct my_err_head *meh_p;
va_list args;
char ebuff[ERRMSGSIZE + 20];
DBUG_ENTER("my_error");
DBUG_PRINT("my", ("nr: %d MyFlags: %d errno: %d", nr, MyFlags, errno));
if (nr / ERRMOD == GLOB && my_errmsg[GLOB] == 0)
init_glob_errs();
format= my_errmsg[nr / ERRMOD][nr % ERRMOD];
/* Search for the error messages array, which could contain the message. */
for (meh_p= my_errmsgs_list; meh_p; meh_p= meh_p->meh_next)
if (nr <= meh_p->meh_last)
break;
va_start(args,MyFlags);
(void) my_vsnprintf (ebuff, sizeof(ebuff), format, args);
va_end(args);
#ifdef SHARED_LIBRARY
if ((meh_p == &my_errmsgs_globerrs) && ! globerrs[0])
init_glob_errs();
#endif
/* get the error message string. Default, if NULL or empty string (""). */
if (! (format= (meh_p && (nr >= meh_p->meh_first)) ?
meh_p->meh_errmsgs[nr - meh_p->meh_first] : NULL) || ! *format)
(void) my_snprintf (ebuff, sizeof(ebuff), "Unknown error %d", nr);
else
{
va_start(args,MyFlags);
(void) my_vsnprintf (ebuff, sizeof(ebuff), format, args);
va_end(args);
}
DBUG_RETURN((*error_handler_hook)(nr, ebuff, MyFlags));
}
......@@ -108,3 +141,109 @@ int my_message(uint error, const char *str, register myf MyFlags)
{
return (*error_handler_hook)(error, str, MyFlags);
}
/*
Register error messages for use with my_error().
SYNOPSIS
my_error_register()
errmsgs array of pointers to error messages
first error number of first message in the array
last error number of last message in the array
DESCRIPTION
The pointer array is expected to contain addresses to NUL-terminated
C character strings. The array contains (last - first + 1) pointers.
NULL pointers and empty strings ("") are allowed. These will be mapped to
"Unknown error" when my_error() is called with a matching error number.
This function registers the error numbers 'first' to 'last'.
No overlapping with previously registered error numbers is allowed.
RETURN
0 OK
!= 0 Error
*/
int my_error_register(const char **errmsgs, int first, int last)
{
struct my_err_head *meh_p;
struct my_err_head **search_meh_pp;
/* Allocate a new header structure. */
if (! (meh_p= (struct my_err_head*) my_malloc(sizeof(struct my_err_head),
MYF(MY_WME))))
return 1;
meh_p->meh_errmsgs= errmsgs;
meh_p->meh_first= first;
meh_p->meh_last= last;
/* Search for the right position in the list. */
for (search_meh_pp= &my_errmsgs_list;
*search_meh_pp;
search_meh_pp= &(*search_meh_pp)->meh_next)
{
if ((*search_meh_pp)->meh_last > first)
break;
}
/* Error numbers must be unique. No overlapping is allowed. */
if (*search_meh_pp && ((*search_meh_pp)->meh_first <= last))
return 1;
/* Insert header into the chain. */
meh_p->meh_next= *search_meh_pp;
*search_meh_pp= meh_p;
return 0;
}
/*
Unregister formerly registered error messages.
SYNOPSIS
my_error_unregister()
first error number of first message
last error number of last message
DESCRIPTION
This function unregisters the error numbers 'first' to 'last'.
These must have been previously registered by my_error_register().
'first' and 'last' must exactly match the registration.
If a matching registration is present, the header is removed from the
list and the pointer to the error messages pointers array is returned.
Otherwise, NULL is returned.
RETURN
non-NULL OK, returns address of error messages pointers array.
NULL Error, no such number range registered.
*/
const char **my_error_unregister(int first, int last)
{
struct my_err_head *meh_p;
struct my_err_head **search_meh_pp;
const char **errmsgs;
/* Search for the registration in the list. */
for (search_meh_pp= &my_errmsgs_list;
*search_meh_pp;
search_meh_pp= &(*search_meh_pp)->meh_next)
{
if (((*search_meh_pp)->meh_first == first) &&
((*search_meh_pp)->meh_last == last))
break;
}
if (! *search_meh_pp)
return NULL;
/* Remove header from the chain. */
meh_p= *search_meh_pp;
*search_meh_pp= meh_p->meh_next;
/* Save the return value and free the header. */
errmsgs= meh_p->meh_errmsgs;
my_free((gptr) meh_p, MYF(0));
return errmsgs;
}
......@@ -24,15 +24,43 @@ static bool read_texts(const char *file_name,const char ***point,
uint error_messages);
static void init_myfunc_errs(void);
/* Read messages from errorfile */
/*
Read messages from errorfile.
SYNOPSIS
init_errmessage()
DESCRIPTION
This function can be called multiple times to reload the messages.
RETURN
FALSE OK
TRUE Error
*/
bool init_errmessage(void)
{
const char **errmsgs;
DBUG_ENTER("init_errmessage");
if (read_texts(ERRMSG_FILE,&my_errmsg[ERRMAPP],ER_ERROR_MESSAGES))
/*
Get a pointer to the old error messages pointer array.
read_texts() tries to free it.
*/
errmsgs= my_error_unregister(ER_ERROR_FIRST, ER_ERROR_LAST);
/* Read messages from file. */
if (read_texts(ERRMSG_FILE, &errmsgs, ER_ERROR_LAST - ER_ERROR_FIRST + 1))
DBUG_RETURN(TRUE);
errmesg=my_errmsg[ERRMAPP]; /* Init global variabel */
/* Register messages for use with my_error(). */
if (my_error_register(errmsgs, ER_ERROR_FIRST, ER_ERROR_LAST))
{
x_free((gptr) errmsgs);
DBUG_RETURN(TRUE);
}
errmesg= errmsgs; /* Init global variabel */
init_myfunc_errs(); /* Init myfunc messages */
DBUG_RETURN(FALSE);
}
......@@ -148,20 +176,20 @@ static void init_myfunc_errs()
init_glob_errs(); /* Initiate english errors */
if (!(specialflag & SPECIAL_ENGLISH))
{
globerrs[EE_FILENOTFOUND % ERRMOD] = ER(ER_FILE_NOT_FOUND);
globerrs[EE_CANTCREATEFILE % ERRMOD]= ER(ER_CANT_CREATE_FILE);
globerrs[EE_READ % ERRMOD] = ER(ER_ERROR_ON_READ);
globerrs[EE_WRITE % ERRMOD] = ER(ER_ERROR_ON_WRITE);
globerrs[EE_BADCLOSE % ERRMOD] = ER(ER_ERROR_ON_CLOSE);
globerrs[EE_OUTOFMEMORY % ERRMOD] = ER(ER_OUTOFMEMORY);
globerrs[EE_DELETE % ERRMOD] = ER(ER_CANT_DELETE_FILE);
globerrs[EE_LINK % ERRMOD] = ER(ER_ERROR_ON_RENAME);
globerrs[EE_EOFERR % ERRMOD] = ER(ER_UNEXPECTED_EOF);
globerrs[EE_CANTLOCK % ERRMOD] = ER(ER_CANT_LOCK);
globerrs[EE_DIR % ERRMOD] = ER(ER_CANT_READ_DIR);
globerrs[EE_STAT % ERRMOD] = ER(ER_CANT_GET_STAT);
globerrs[EE_GETWD % ERRMOD] = ER(ER_CANT_GET_WD);
globerrs[EE_SETWD % ERRMOD] = ER(ER_CANT_SET_WD);
globerrs[EE_DISK_FULL % ERRMOD] = ER(ER_DISK_FULL);
EE(EE_FILENOTFOUND) = ER(ER_FILE_NOT_FOUND);
EE(EE_CANTCREATEFILE) = ER(ER_CANT_CREATE_FILE);
EE(EE_READ) = ER(ER_ERROR_ON_READ);
EE(EE_WRITE) = ER(ER_ERROR_ON_WRITE);
EE(EE_BADCLOSE) = ER(ER_ERROR_ON_CLOSE);
EE(EE_OUTOFMEMORY) = ER(ER_OUTOFMEMORY);
EE(EE_DELETE) = ER(ER_CANT_DELETE_FILE);
EE(EE_LINK) = ER(ER_ERROR_ON_RENAME);
EE(EE_EOFERR) = ER(ER_UNEXPECTED_EOF);
EE(EE_CANTLOCK) = ER(ER_CANT_LOCK);
EE(EE_DIR) = ER(ER_CANT_READ_DIR);
EE(EE_STAT) = ER(ER_CANT_GET_STAT);
EE(EE_GETWD) = ER(ER_CANT_GET_WD);
EE(EE_SETWD) = ER(ER_CANT_SET_WD);
EE(EE_DISK_FULL) = ER(ER_DISK_FULL);
}
}
......@@ -244,9 +244,99 @@ bool ha_caching_allowed(THD* thd, char* table_key,
return 1;
}
/*
Register handler error messages for use with my_error().
SYNOPSIS
ha_init_errors()
RETURN
0 OK
!= 0 Error
*/
static int ha_init_errors(void)
{
#define SETMSG(nr, msg) errmsgs[(nr) - HA_ERR_FIRST]= (msg)
const char **errmsgs;
/* Allocate a pointer array for the error message strings. */
/* Zerofill it to avoid uninitialized gaps. */
if (! (errmsgs= (const char**) my_malloc(HA_ERR_ERRORS * sizeof(char*),
MYF(MY_WME | MY_ZEROFILL))))
return 1;
/* Set the dedicated error messages. */
SETMSG(HA_ERR_KEY_NOT_FOUND, ER(ER_KEY_NOT_FOUND));
SETMSG(HA_ERR_FOUND_DUPP_KEY, ER(ER_DUP_KEY));
SETMSG(HA_ERR_RECORD_CHANGED, "Update wich is recoverable");
SETMSG(HA_ERR_WRONG_INDEX, "Wrong index given to function");
SETMSG(HA_ERR_CRASHED, ER(ER_NOT_KEYFILE));
SETMSG(HA_ERR_WRONG_IN_RECORD, ER(ER_CRASHED_ON_USAGE));
SETMSG(HA_ERR_OUT_OF_MEM, "Table handler out of memory");
SETMSG(HA_ERR_NOT_A_TABLE, "Incorrect file format '%.64s'");
SETMSG(HA_ERR_WRONG_COMMAND, "Command not supported");
SETMSG(HA_ERR_OLD_FILE, ER(ER_OLD_KEYFILE));
SETMSG(HA_ERR_NO_ACTIVE_RECORD, "No record read in update");
SETMSG(HA_ERR_RECORD_DELETED, "Intern record deleted");
SETMSG(HA_ERR_RECORD_FILE_FULL, ER(ER_RECORD_FILE_FULL));
SETMSG(HA_ERR_INDEX_FILE_FULL, "No more room in index file '%.64s'");
SETMSG(HA_ERR_END_OF_FILE, "End in next/prev/first/last");
SETMSG(HA_ERR_UNSUPPORTED, ER(ER_ILLEGAL_HA));
SETMSG(HA_ERR_TO_BIG_ROW, "Too big row");
SETMSG(HA_WRONG_CREATE_OPTION, "Wrong create option");
SETMSG(HA_ERR_FOUND_DUPP_UNIQUE, ER(ER_DUP_UNIQUE));
SETMSG(HA_ERR_UNKNOWN_CHARSET, "Can't open charset");
SETMSG(HA_ERR_WRONG_MRG_TABLE_DEF, ER(ER_WRONG_MRG_TABLE));
SETMSG(HA_ERR_CRASHED_ON_REPAIR, ER(ER_CRASHED_ON_REPAIR));
SETMSG(HA_ERR_CRASHED_ON_USAGE, ER(ER_CRASHED_ON_USAGE));
SETMSG(HA_ERR_LOCK_WAIT_TIMEOUT, ER(ER_LOCK_WAIT_TIMEOUT));
SETMSG(HA_ERR_LOCK_TABLE_FULL, ER(ER_LOCK_TABLE_FULL));
SETMSG(HA_ERR_READ_ONLY_TRANSACTION, ER(ER_READ_ONLY_TRANSACTION));
SETMSG(HA_ERR_LOCK_DEADLOCK, ER(ER_LOCK_DEADLOCK));
SETMSG(HA_ERR_CANNOT_ADD_FOREIGN, ER(ER_CANNOT_ADD_FOREIGN));
SETMSG(HA_ERR_NO_REFERENCED_ROW, ER(ER_NO_REFERENCED_ROW));
SETMSG(HA_ERR_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED));
SETMSG(HA_ERR_NO_SAVEPOINT, "No savepoint with that name");
SETMSG(HA_ERR_NON_UNIQUE_BLOCK_SIZE, "Non unique key block size");
SETMSG(HA_ERR_NO_SUCH_TABLE, "No such table: '%.64s'");
SETMSG(HA_ERR_TABLE_EXIST, ER(ER_TABLE_EXISTS_ERROR));
SETMSG(HA_ERR_NO_CONNECTION, "Could not connect to storage engine");
/* Register the error messages for use with my_error(). */
return my_error_register(errmsgs, HA_ERR_FIRST, HA_ERR_LAST);
}
/*
Unregister handler error messages.
SYNOPSIS
ha_finish_errors()
RETURN
0 OK
!= 0 Error
*/
static int ha_finish_errors(void)
{
const char **errmsgs;
/* Allocate a pointer array for the error message strings. */
if (! (errmsgs= my_error_unregister(HA_ERR_FIRST, HA_ERR_LAST)))
return 1;
my_free((gptr) errmsgs, MYF(0));
return 0;
}
int ha_init()
{
int error= 0;
if (ha_init_errors())
return 1;
#ifdef HAVE_BERKELEY_DB
if (have_berkeley_db == SHOW_OPTION_YES)
{
......@@ -314,6 +404,8 @@ int ha_panic(enum ha_panic_function flag)
if (have_ndbcluster == SHOW_OPTION_YES)
error|=ndbcluster_end();
#endif
if (ha_finish_errors())
error= 1;
return error;
} /* ha_panic */
......@@ -1241,9 +1333,15 @@ void handler::print_error(int error, myf errflag)
case HA_ERR_CRASHED:
textno=ER_NOT_KEYFILE;
break;
case HA_ERR_WRONG_IN_RECORD:
textno= ER_CRASHED_ON_USAGE;
break;
case HA_ERR_CRASHED_ON_USAGE:
textno=ER_CRASHED_ON_USAGE;
break;
case HA_ERR_NOT_A_TABLE:
textno= error;
break;
case HA_ERR_CRASHED_ON_REPAIR:
textno=ER_CRASHED_ON_REPAIR;
break;
......@@ -1262,6 +1360,9 @@ void handler::print_error(int error, myf errflag)
case HA_ERR_RECORD_FILE_FULL:
textno=ER_RECORD_FILE_FULL;
break;
case HA_ERR_INDEX_FILE_FULL:
textno= errno;
break;
case HA_ERR_LOCK_WAIT_TIMEOUT:
textno=ER_LOCK_WAIT_TIMEOUT;
break;
......
......@@ -1005,7 +1005,9 @@ void clean_up(bool print_message)
if (!opt_bootstrap)
(void) my_delete(pidfile_name,MYF(0)); // This may not always exist
#endif
x_free((gptr) my_errmsg[ERRMAPP]); /* Free messages */
finish_client_errs();
const char **errmsgs= my_error_unregister(ER_ERROR_FIRST, ER_ERROR_LAST);
x_free((gptr) errmsgs); /* Free messages */
DBUG_PRINT("quit", ("Error messages freed"));
/* Tell main we are ready */
(void) pthread_mutex_lock(&LOCK_thread_count);
......
......@@ -76,6 +76,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
my_string record;
const char **int_array;
bool use_hash, null_field_first;
bool error_reported= FALSE;
File file;
Field **field_ptr,*reg_field;
KEY *keyinfo;
......@@ -788,6 +789,11 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
error= 1;
my_errno= ENOENT;
}
else
{
outparam->file->print_error(err, MYF(0));
error_reported= TRUE;
}
goto err_not_open; /* purecov: inspected */
}
}
......@@ -814,7 +820,8 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
err_end: /* Here when no file */
delete crypted;
*root_ptr= old_root;
frm_error(error,outparam,name,ME_ERROR+ME_WAITTANG);
if (! error_reported)
frm_error(error,outparam,name,ME_ERROR+ME_WAITTANG);
delete outparam->file;
outparam->file=0; // For easier errorchecking
outparam->db_stat=0;
......
......@@ -37,8 +37,8 @@
#define SHAREDIR "share/"
#endif
#define ER(X) errmesg[(X)-1000]
#define ER_SAFE(X) (((X) >= 1000 && (X) < ER_ERROR_MESSAGES + 1000) ? ER(X) : "Invalid error code")
#define ER(X) errmesg[(X) - ER_ERROR_FIRST]
#define ER_SAFE(X) (((X) >= ER_ERROR_FIRST && (X) <= ER_ERROR_LAST) ? ER(X) : "Invalid error code")
#define ERRMAPP 1 /* Errormap f|r my_error */
......
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