Skip to content

Commit c39be2d

Browse files
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.
1 parent 1ea48a2 commit c39be2d

31 files changed

Lines changed: 518 additions & 56 deletions

extra/comp_err.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -191,10 +191,11 @@ int main(int argc, char *argv[])
191191

192192
static int create_header_files(struct errors *error_head)
193193
{
194-
uint er_count= 0;
194+
uint er_last;
195195
FILE *er_definef, *sql_statef;
196196
struct errors *tmp_error;
197197
DBUG_ENTER("create_header_files");
198+
LINT_INIT(er_last);
198199

199200
if (!(er_definef= my_fopen(HEADERFILE, O_WRONLY, MYF(MY_WME))))
200201
{
@@ -209,6 +210,8 @@ static int create_header_files(struct errors *error_head)
209210
fprintf(er_definef, "/* Autogenerated file, please don't edit */\n\n");
210211
fprintf(sql_statef, "/* Autogenerated file, please don't edit */\n\n");
211212

213+
fprintf(er_definef, "#define ER_ERROR_FIRST %d\n", error_head->d_code);
214+
212215
for (tmp_error= error_head; tmp_error; tmp_error= tmp_error->next_error)
213216
{
214217
/*
@@ -217,16 +220,16 @@ static int create_header_files(struct errors *error_head)
217220
*/
218221
fprintf(er_definef, "#define %s %d\n", tmp_error->er_name,
219222
tmp_error->d_code);
223+
er_last= tmp_error->d_code;
220224

221225
/* generating sql_state.h file */
222226
if (tmp_error->sql_code1[0] || tmp_error->sql_code2[0])
223227
fprintf(sql_statef,
224228
"%-40s,\"%s\", \"%s\",\n", tmp_error->er_name,
225229
tmp_error->sql_code1, tmp_error->sql_code2);
226-
er_count++;
227230
}
228231
/* finishing off with mysqld_error.h */
229-
fprintf(er_definef, "#define ER_ERROR_MESSAGES %d\n", er_count);
232+
fprintf(er_definef, "#define ER_ERROR_LAST %d\n", er_last);
230233
my_fclose(er_definef, MYF(0));
231234
my_fclose(sql_statef, MYF(0));
232235
DBUG_RETURN(0);

include/errmsg.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
extern "C" {
2222
#endif
2323
void init_client_errs(void);
24+
void finish_client_errs(void);
2425
extern const char *client_errors[]; /* Error messages */
2526
#ifdef __cplusplus
2627
}
@@ -35,6 +36,9 @@ extern const char *client_errors[]; /* Error messages */
3536
#endif
3637
#define CLIENT_ERRMAP 2 /* Errormap used by my_error() */
3738

39+
/* Do not add error numbers before CR_ERROR_FIRST. */
40+
/* If necessary to add lower numbers, change CR_ERROR_FIRST accordingly. */
41+
#define CR_ERROR_FIRST 2000 /*Copy first error nr.*/
3842
#define CR_UNKNOWN_ERROR 2000
3943
#define CR_SOCKET_CREATE_ERROR 2001
4044
#define CR_CONNECTION_ERROR 2002
@@ -90,3 +94,6 @@ extern const char *client_errors[]; /* Error messages */
9094
#define CR_SECURE_AUTH 2049
9195
#define CR_FETCH_CANCELED 2050
9296
#define CR_NO_DATA 2051
97+
#define CR_ERROR_LAST /*Copy last error nr:*/ 2051
98+
/* Add error numbers before CR_ERROR_LAST and change it accordingly. */
99+

include/my_base.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,9 @@ enum ha_base_keytype {
273273
/* Errorcodes given by functions */
274274

275275
/* opt_sum_query() assumes these codes are > 1 */
276+
/* Do not add error numbers before HA_ERR_FIRST. */
277+
/* If necessary to add lower numbers, change HA_ERR_FIRST accordingly. */
278+
#define HA_ERR_FIRST 120 /*Copy first error nr.*/
276279
#define HA_ERR_KEY_NOT_FOUND 120 /* Didn't find key on read or update */
277280
#define HA_ERR_FOUND_DUPP_KEY 121 /* Dupplicate key on write */
278281
#define HA_ERR_RECORD_CHANGED 123 /* Uppdate with is recoverable */
@@ -308,6 +311,9 @@ enum ha_base_keytype {
308311
#define HA_ERR_NO_SUCH_TABLE 155 /* The table does not exist in engine */
309312
#define HA_ERR_TABLE_EXIST 156 /* The table existed in storage engine */
310313
#define HA_ERR_NO_CONNECTION 157 /* Could not connect to storage engine */
314+
#define HA_ERR_LAST 157 /*Copy last error nr.*/
315+
/* Add error numbers before HA_ERR_LAST and change it accordingly. */
316+
#define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1)
311317

312318
/* Other constants */
313319

include/my_sys.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@ extern int NEAR my_errno; /* Last error in mysys */
4343
#define MYSYS_PROGRAM_DONT_USE_CURSES() { error_handler_hook = my_message_no_curses; mysys_uses_curses=0;}
4444
#define MY_INIT(name); { my_progname= name; my_init(); }
4545

46-
#define MAXMAPS (4) /* Number of error message maps */
47-
#define ERRMOD (1000) /* Max number of errors in a map */
4846
#define ERRMSGSIZE (SC_MAXWIDTH) /* Max length of a error message */
4947
#define NRERRBUFFS (2) /* Buffers for parameters */
5048
#define MY_FILE_ERROR ((uint) ~0)
@@ -213,7 +211,6 @@ void __CDECL hfree(void *ptr);
213211
#else
214212
extern int errno; /* declare errno */
215213
#endif
216-
extern const char ** NEAR my_errmsg[];
217214
extern char NEAR errbuff[NRERRBUFFS][ERRMSGSIZE];
218215
extern char *home_dir; /* Home directory for user */
219216
extern char *my_progname; /* program-name (printed in errors) */
@@ -610,6 +607,8 @@ extern int my_error _VARARGS((int nr,myf MyFlags, ...));
610607
extern int my_printf_error _VARARGS((uint my_err, const char *format,
611608
myf MyFlags, ...)
612609
__attribute__ ((format (printf, 2, 4))));
610+
extern int my_error_register(const char **errmsgs, int first, int last);
611+
extern const char **my_error_unregister(int first, int last);
613612
extern int my_message(uint my_err, const char *str,myf MyFlags);
614613
extern int my_message_no_curses(uint my_err, const char *str,myf MyFlags);
615614
extern int my_message_curses(uint my_err, const char *str,myf MyFlags);

include/mysys_err.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@
2020
extern "C" {
2121
#endif
2222

23-
#define GLOB 0 /* Error maps */
24-
#define GLOBERRS 28 /* Max number of error messages in map's */
25-
#define EE(X) globerrs[ X ] /* Defines to add error to right map */
23+
#define GLOBERRS (EE_ERROR_LAST - EE_ERROR_FIRST + 1) /* Nr of global errors */
24+
#define EE(X) (globerrs[(X) - EE_ERROR_FIRST])
2625

2726
extern const char * NEAR globerrs[]; /* my_error_messages is here */
2827

2928
/* Error message numbers in global map */
29+
/* Do not add error numbers before EE_ERROR_FIRST. */
30+
/* If necessary to add lower numbers, change EE_ERROR_FIRST accordingly. */
31+
#define EE_ERROR_FIRST 0 /*Copy first error nr.*/
3032
#define EE_FILENOTFOUND 0
3133
#define EE_CANTCREATEFILE 1
3234
#define EE_READ 2
@@ -54,6 +56,8 @@ extern const char * NEAR globerrs[]; /* my_error_messages is here */
5456
#define EE_CANT_SYMLINK 25
5557
#define EE_REALPATH 26
5658
#define EE_SYNC 27
59+
#define EE_ERROR_LAST 27 /*Copy last error nr.*/
60+
/* Add error numbers before EE_ERROR_LAST and change it accordingly. */
5761

5862
/* exit codes for all MySQL programs */
5963

libmysql/errmsg.c

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,33 @@ const char *client_errors[]=
199199
#endif
200200

201201

202+
/*
203+
Register client error messages for use with my_error().
204+
205+
SYNOPSIS
206+
init_client_errs()
207+
208+
RETURN
209+
void
210+
*/
211+
202212
void init_client_errs(void)
203213
{
204-
my_errmsg[CLIENT_ERRMAP] = &client_errors[0];
214+
(void) my_error_register(client_errors, CR_ERROR_FIRST, CR_ERROR_LAST);
215+
}
216+
217+
218+
/*
219+
Unregister client error messages.
220+
221+
SYNOPSIS
222+
finish_client_errs()
223+
224+
RETURN
225+
void
226+
*/
227+
228+
void finish_client_errs(void)
229+
{
230+
(void) my_error_unregister(CR_ERROR_FIRST, CR_ERROR_LAST);
205231
}

libmysql/libmysql.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ void STDCALL mysql_server_end()
185185
}
186186
else
187187
mysql_thread_end();
188+
finish_client_errs();
188189
mysql_client_init= org_my_init_done= 0;
189190
}
190191

myisam/mi_delete.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ int mi_delete(MI_INFO *info,const byte *record)
4545

4646
/* Test if record is in datafile */
4747

48+
DBUG_EXECUTE_IF("myisam_pretend_crashed_table_on_usage",
49+
mi_print_error(info, HA_ERR_CRASHED);
50+
DBUG_RETURN(my_errno= HA_ERR_CRASHED););
51+
DBUG_EXECUTE_IF("my_error_test_undefined_error",
52+
mi_print_error(info, INT_MAX);
53+
DBUG_RETURN(my_errno= INT_MAX););
4854
if (!(info->update & HA_STATE_AKTIV))
4955
{
5056
DBUG_RETURN(my_errno=HA_ERR_KEY_NOT_FOUND); /* No database read */
@@ -109,13 +115,19 @@ int mi_delete(MI_INFO *info,const byte *record)
109115
mi_sizestore(lastpos,info->lastpos);
110116
myisam_log_command(MI_LOG_DELETE,info,(byte*) lastpos, sizeof(lastpos),0);
111117
if (save_errno != HA_ERR_RECORD_CHANGED)
118+
{
119+
mi_print_error(info, HA_ERR_CRASHED);
112120
mi_mark_crashed(info); /* mark table crashed */
121+
}
113122
VOID(_mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
114123
info->update|=HA_STATE_WRITTEN; /* Buffer changed */
115124
allow_break(); /* Allow SIGHUP & SIGINT */
116125
my_errno=save_errno;
117126
if (save_errno == HA_ERR_KEY_NOT_FOUND)
127+
{
128+
mi_print_error(info, HA_ERR_CRASHED);
118129
my_errno=HA_ERR_CRASHED;
130+
}
119131

120132
DBUG_RETURN(my_errno);
121133
} /* mi_delete */
@@ -142,6 +154,7 @@ static int _mi_ck_real_delete(register MI_INFO *info, MI_KEYDEF *keyinfo,
142154

143155
if ((old_root=*root) == HA_OFFSET_ERROR)
144156
{
157+
mi_print_error(info, HA_ERR_CRASHED);
145158
DBUG_RETURN(my_errno=HA_ERR_CRASHED);
146159
}
147160
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,
253266
my_off_t root;
254267
uchar *kpos=keypos;
255268

256-
tmp_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&kpos,lastkey);
269+
if (!(tmp_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&kpos,lastkey))
270+
&& (my_errno == HA_ERR_CRASHED))
271+
mi_print_error(info, HA_ERR_CRASHED);
257272
root=_mi_dpos(info,nod_flag,kpos);
258273
if (subkeys == -1)
259274
{
@@ -302,6 +317,7 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
302317
if (!nod_flag)
303318
{
304319
DBUG_PRINT("error",("Didn't find key"));
320+
mi_print_error(info, HA_ERR_CRASHED);
305321
my_errno=HA_ERR_CRASHED; /* This should newer happend */
306322
goto err;
307323
}
@@ -317,6 +333,8 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
317333
&next_block);
318334
if (tmp == 0)
319335
{
336+
if (my_errno == HA_ERR_CRASHED)
337+
mi_print_error(info, HA_ERR_CRASHED);
320338
DBUG_PRINT("exit",("Return: %d",0));
321339
DBUG_RETURN(0);
322340
}
@@ -473,6 +491,8 @@ static int del(register MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *key,
473491
(info->quick_mode ? MI_MIN_KEYBLOCK_LENGTH :
474492
(uint) keyinfo->underflow_block_length));
475493
err:
494+
if (my_errno == HA_ERR_CRASHED)
495+
mi_print_error(info, HA_ERR_CRASHED);
476496
DBUG_RETURN(-1);
477497
} /* del */
478498

@@ -562,7 +582,11 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo,
562582
s_length=remove_key(keyinfo,key_reflength,keypos,anc_key,
563583
anc_buff+anc_length,(my_off_t *) 0);
564584
if (!s_length)
585+
{
586+
if (my_errno == HA_ERR_CRASHED)
587+
mi_print_error(info, HA_ERR_CRASHED);
565588
goto err;
589+
}
566590
anc_length-=s_length;
567591
mi_putint(anc_buff,anc_length,key_reflength);
568592

@@ -671,7 +695,11 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo,
671695
s_length=remove_key(keyinfo,key_reflength,keypos,anc_key,
672696
anc_buff+anc_length,(my_off_t *) 0);
673697
if (!s_length)
698+
{
699+
if (my_errno == HA_ERR_CRASHED)
700+
mi_print_error(info, HA_ERR_CRASHED);
674701
goto err;
702+
}
675703
anc_length-=s_length;
676704
mi_putint(anc_buff,anc_length,key_reflength);
677705

@@ -732,6 +760,8 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo,
732760
goto err;
733761
DBUG_RETURN(anc_length <= (uint) keyinfo->block_length/2);
734762
err:
763+
if (my_errno == HA_ERR_CRASHED)
764+
mi_print_error(info, HA_ERR_CRASHED);
735765
DBUG_RETURN(-1);
736766
} /* underflow */
737767

myisam/mi_extra.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,10 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
186186
if (info->opt_flag & WRITE_CACHE_USED)
187187
{
188188
if ((error=flush_io_cache(&info->rec_cache)))
189+
{
190+
mi_print_error(info, HA_ERR_CRASHED);
189191
mi_mark_crashed(info); /* Fatal error found */
192+
}
190193
}
191194
break;
192195
case HA_EXTRA_NO_READCHECK:
@@ -285,6 +288,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
285288
{
286289
error=my_errno;
287290
share->changed=1;
291+
mi_print_error(info, HA_ERR_CRASHED);
288292
mi_mark_crashed(info); /* Fatal error found */
289293
}
290294
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)
339343
if (error)
340344
{
341345
share->changed=1;
346+
mi_print_error(info, HA_ERR_CRASHED);
342347
mi_mark_crashed(info); /* Fatal error found */
343348
}
344349
}

myisam/mi_info.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,3 +105,36 @@ int mi_status(MI_INFO *info, register MI_ISAMINFO *x, uint flag)
105105
}
106106
DBUG_RETURN(0);
107107
}
108+
109+
110+
/*
111+
Write a message to the error log.
112+
113+
SYNOPSIS
114+
mi_report_error()
115+
file_name Name of table file (e.g. index_file_name).
116+
errcode Error number.
117+
118+
DESCRIPTION
119+
This function supplies my_error() with a table name. Most error
120+
messages need one. Since string arguments in error messages are limited
121+
to 64 characters by convention, we ensure that in case of truncation,
122+
that the end of the index file path is in the message. This contains
123+
the most valuable information (the table name and the database name).
124+
125+
RETURN
126+
void
127+
*/
128+
129+
void mi_report_error(int errcode, const char *file_name)
130+
{
131+
size_t lgt;
132+
DBUG_ENTER("mi_report_error");
133+
DBUG_PRINT("enter",("errcode %d, table '%s'", errcode, file_name));
134+
135+
if ((lgt= strlen(file_name)) > 64)
136+
file_name+= lgt - 64;
137+
my_error(errcode, MYF(ME_NOREFRESH), file_name);
138+
DBUG_VOID_RETURN;
139+
}
140+

0 commit comments

Comments
 (0)