Commit d556096f authored by unknown's avatar unknown

mi_check flags cleanup

CHECK/REPAIR syntax cleanup
REPAIR ... USE_FRM syntax


include/myisam.h:
  mi_check flags cleanup
myisam/mi_check.c:
  mi_check flags cleanup
myisam/myisamchk.c:
  mi_check flags cleanup
mysql-test/r/check.result:
  CHECK/REPAIR syntax cleanup
mysql-test/r/show_check.result:
  CHECK/REPAIR syntax cleanup
mysql-test/t/check.test:
  CHECK/REPAIR syntax cleanup
mysql-test/t/show_check.test:
  CHECK/REPAIR syntax cleanup
sql/ha_myisam.cc:
  mi_check flags cleanup
sql/handler.h:
  mi_check flags cleanup
sql/lex.h:
  REPAIR ... USE_FRM syntax
sql/slave.cc:
  mi_check flags cleanup
parent 1b1f5263
......@@ -255,36 +255,45 @@ extern uint mi_get_pointer_length(ulonglong file_length, uint def);
/* definitions needed for myisamchk.c -- by Sasha Pachev */
/* entries marked as "QQ to be removed" are NOT used to
* pass check/repair options to mi_check.c. They are used
* internally by myisamchk.c or/and ha_myisam.cc and should NOT
* be stored together with other flags. They should be removed
* from the following list to make adding of new flags possible.
* -- Sergei */
#define T_VERBOSE 1
#define T_SILENT 2
#define T_DESCRIPT 4
#define T_EXTEND 8
#define T_INFO 16
#define T_REP 32
#define T_OPT 64 /* Not currently used */
#define T_FORCE_UNIQUENESS 64
#define T_FORCE_CREATE 128
#define T_WRITE_LOOP 256
#define T_UNPACK 512
#define T_STATISTICS 1024
#define T_VERY_SILENT 2048
#define T_SORT_RECORDS 4096
#define T_SORT_INDEX 8192
#define T_WAIT_FOREVER 16384
#define T_REP_BY_SORT 32768L
#define T_FAST 65536L
#define T_READONLY 131072L
#define T_MEDIUM T_READONLY*2
#define T_AUTO_INC T_MEDIUM*2
#define T_CHECK T_AUTO_INC*2
#define T_UPDATE_STATE T_CHECK*2
#define T_CHECK_ONLY_CHANGED T_UPDATE_STATE*2
#define T_DONT_CHECK_CHECKSUM T_CHECK_ONLY_CHANGED*2
#define T_TRUST_HEADER T_DONT_CHECK_CHECKSUM*2
#define T_CREATE_MISSING_KEYS T_TRUST_HEADER*2
#define T_SAFE_REPAIR T_CREATE_MISSING_KEYS*2
#define T_AUTO_REPAIR T_SAFE_REPAIR*2
#define T_BACKUP_DATA T_AUTO_REPAIR*2
#define T_CALC_CHECKSUM T_BACKUP_DATA*2
#define T_STATISTICS (1L << 10)
#define T_VERY_SILENT (1L << 11)
#define T_SORT_RECORDS (1L << 12) /* QQ to be removed */
#define T_SORT_INDEX (1L << 13) /* QQ to be removed */
#define T_WAIT_FOREVER (1L << 14)
#define T_REP_BY_SORT (1L << 15)
#define T_FAST (1L << 16) /* QQ to be removed */
#define T_READONLY (1L << 17) /* QQ to be removed */
#define T_MEDIUM (1L << 18)
#define T_AUTO_INC (1L << 19)
#define T_CHECK (1L << 20) /* QQ to be removed */
#define T_UPDATE_STATE (1L << 21)
#define T_CHECK_ONLY_CHANGED (1L << 22) /* QQ to be removed */
#define T_DONT_CHECK_CHECKSUM (1L << 23)
#define T_TRUST_HEADER (1L << 24)
#define T_CREATE_MISSING_KEYS (1L << 25)
#define T_SAFE_REPAIR (1L << 26)
#define T_AUTO_REPAIR (1L << 27) /* QQ to be removed */
#define T_BACKUP_DATA (1L << 28)
#define T_CALC_CHECKSUM (1L << 29)
#define T_QUICK (1L << 30)
#define T_RETRY_WITHOUT_QUICK (1L << 31)
#define O_NEW_INDEX 1 /* Bits set in out_flag */
#define O_NEW_DATA 2
......@@ -329,13 +338,12 @@ typedef struct st_mi_check_param
ha_checksum record_checksum,glob_crc;
ulong use_buffers,read_buffer_length,write_buffer_length,
sort_buffer_length,sort_key_blocks;
uint out_flag,warning_printed,error_printed,
opt_rep_quick,verbose;
uint out_flag,warning_printed,error_printed,verbose;
uint opt_sort_key,total_files,max_level;
uint testflag;
uint8 language;
my_bool using_global_keycache, opt_lock_memory, opt_follow_links;
my_bool retry_repair,retry_without_quick, force_sort, calc_checksum;
my_bool retry_repair, force_sort, calc_checksum;
char temp_filename[FN_REFLEN],*isam_file_name,*tmpdir;
int tmpfile_createflag;
myf myf_rw;
......
......@@ -221,7 +221,7 @@ int chk_del(MI_CHECK *param, register MI_INFO *info, uint test_flag)
}
DBUG_RETURN(0);
wrong:
param->retry_without_quick=1; /* Don't use quick repair */
param->testflag|=T_RETRY_WITHOUT_QUICK;
if (test_flag & T_VERBOSE) puts("");
mi_check_print_error(param,"record delete-link-chain corrupted");
DBUG_RETURN(1);
......@@ -321,7 +321,7 @@ int chk_size(MI_CHECK *param, register MI_INFO *info)
error=1;
mi_check_print_error(param,"Size of datafile is: %-9s Should be: %s",
llstr(size,buff), llstr(skr,buff2));
param->retry_without_quick=1; /* Don't use quick repair */
param->testflag|=T_RETRY_WITHOUT_QUICK;
}
else
{
......@@ -1094,7 +1094,7 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend)
mi_check_print_error(param,"got error: %d when reading datafile at record: %s",my_errno, llstr(records,llbuff));
err2:
my_free((gptr) record,MYF(0));
param->retry_without_quick=1;
param->testflag|=T_RETRY_WITHOUT_QUICK;
DBUG_RETURN(1);
} /* chk_data_link */
......@@ -1238,9 +1238,10 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
USE_WHOLE_KEY);
}
sort_info->dupp++;
if (rep_quick == 1)
if (!(rep_quick & T_FORCE_UNIQUENESS))
{
param->error_printed=param->retry_without_quick=1;
param->testflag|=T_RETRY_WITHOUT_QUICK;
param->error_printed=1;
goto err;
}
continue;
......@@ -1269,7 +1270,8 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
mi_check_print_error(param,"Couldn't fix table with quick recovery: Found wrong number of deleted records");
mi_check_print_error(param,"Run recovery again without -q");
got_error=1;
param->retry_repair=param->retry_without_quick=1;
param->retry_repair=1;
param->testflag|=T_RETRY_WITHOUT_QUICK;
goto err;
}
if (param->testflag & T_SAFE_REPAIR)
......@@ -1987,11 +1989,12 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
mi_check_print_error(param,"Couldn't fix table with quick recovery: Found wrong number of deleted records");
mi_check_print_error(param,"Run recovery again without -q");
got_error=1;
param->retry_repair=param->retry_without_quick=1;
param->retry_repair=1;
param->testflag|=T_RETRY_WITHOUT_QUICK;
goto err;
}
if (rep_quick != 1)
if (rep_quick & T_FORCE_UNIQUENESS)
{
my_off_t skr=info->state->data_file_length+
(share->options & HA_OPTION_COMPRESS_RECORD ?
......@@ -2175,7 +2178,8 @@ static int sort_get_next_record(SORT_INFO *sort_info)
{
if (param->read_cache.error)
param->out_flag |= O_DATA_LOST;
param->retry_repair=param->retry_without_quick=1;
param->retry_repair=1;
param->testflag|=T_RETRY_WITHOUT_QUICK;
DBUG_RETURN(-1);
}
sort_info->start_recpos=sort_info->pos;
......@@ -2209,7 +2213,7 @@ static int sort_get_next_record(SORT_INFO *sort_info)
if (searching)
{
pos=MY_ALIGN(pos,MI_DYN_ALIGN_SIZE);
param->retry_without_quick=1;
param->testflag|=T_RETRY_WITHOUT_QUICK;
sort_info->start_recpos=pos;
}
do
......@@ -2245,7 +2249,8 @@ static int sort_get_next_record(SORT_INFO *sort_info)
if (searching && ! sort_info->fix_datafile)
{
param->error_printed=1;
param->retry_repair=param->retry_without_quick=1;
param->retry_repair=1;
param->testflag|=T_RETRY_WITHOUT_QUICK;
DBUG_RETURN(1); /* Something wrong with data */
}
if (((b_type=_mi_get_block_info(&block_info,-1,pos)) &
......@@ -2456,7 +2461,8 @@ static int sort_get_next_record(SORT_INFO *sort_info)
if (searching && ! sort_info->fix_datafile)
{
param->error_printed=1;
param->retry_repair=param->retry_without_quick=1;
param->retry_repair=1;
param->testflag|=T_RETRY_WITHOUT_QUICK;
DBUG_RETURN(1); /* Something wrong with data */
}
sort_info->start_recpos=sort_info->pos;
......@@ -2655,7 +2661,7 @@ static int sort_key_write(SORT_INFO *sort_info, const void *a)
sort_info->key_block->
lastkey),
llbuff2));
param->retry_without_quick=1;
param->testflag|=T_RETRY_WITHOUT_QUICK;
if (sort_info->param->testflag & T_VERBOSE)
_mi_print_key(stdout,sort_info->keyseg,(uchar*) a, USE_WHOLE_KEY);
return (sort_delete_record(param));
......@@ -2778,10 +2784,10 @@ static int sort_delete_record(MI_CHECK *param)
SORT_INFO *sort_info= &param->sort_info;
DBUG_ENTER("sort_delete_record");
if (param->opt_rep_quick == 1)
if (!(param->testflag & T_FORCE_UNIQUENESS))
{
mi_check_print_error(param,
"Quick-recover aborted; Run recovery without switch 'q' or with switch -qq");
"Quick-recover aborted; Run recovery without switch -q or with switch -qq");
DBUG_RETURN(1);
}
info=sort_info->info;
......
......@@ -517,9 +517,10 @@ get_one_option(int optid,
break;
case 'q':
if (argument && *argument == '0')
check_param.opt_rep_quick=0;
check_param.testflag&= ~(T_QUICK | T_FORCE_UNIQUENESS);
else
check_param.opt_rep_quick++;
check_param.testflag|=
(check_param.testflag & T_QUICK) ? T_FORCE_UNIQUENESS : T_QUICK;
break;
case 'u':
if (argument && *argument == '0')
......@@ -627,7 +628,7 @@ static void get_options(register int *argc,register char ***argv)
}
if ((check_param.testflag & T_UNPACK) &&
(check_param.opt_rep_quick || (check_param.testflag & T_SORT_RECORDS)))
(check_param.testflag & (T_QUICK | T_SORT_RECORDS)))
{
VOID(fprintf(stderr,
"%s: --unpack can't be used with --quick or --sort-records\n",
......@@ -659,7 +660,7 @@ static void get_options(register int *argc,register char ***argv)
static int myisamchk(MI_CHECK *param, my_string filename)
{
int error,lock_type,recreate;
int rep_quick= param->opt_rep_quick;
int rep_quick= param->testflag & (T_QUICK | T_FORCE_UNIQUENESS);
uint raid_chunks;
MI_INFO *info;
File datafile;
......@@ -794,8 +795,7 @@ static int myisamchk(MI_CHECK *param, my_string filename)
param->testflag|=T_REP_BY_SORT; /* if only STATISTICS */
if (!(param->testflag & T_SILENT))
printf("- '%s' has old table-format. Recreating index\n",filename);
if (!rep_quick)
rep_quick=1;
rep_quick|=T_QUICK;
}
share=info->s;
share->r_locks=0;
......
drop table if exists t1;
create table t1(n int not null, key(n), key(n), key(n), key(n));
check table t1 type=extended;
check table t1 extended;
insert into t1 values (200000);
Table Op Msg_type Msg_text
test.t1 check status OK
......
drop table if exists t1,t2;
create table t1 (a int not null primary key, b int not null,c int not null, key(b,c));
insert into t1 values (1,2,2),(2,2,3),(3,2,4),(4,2,4);
check table t1 type=fast;
check table t1 fast;
Table Op Msg_type Msg_text
test.t1 check status Table is already up to date
check table t1 type=fast;
check table t1 fast;
Table Op Msg_type Msg_text
test.t1 check status Table is already up to date
check table t1 type=changed;
check table t1 changed;
Table Op Msg_type Msg_text
test.t1 check status OK
insert into t1 values (5,5,5);
check table t1 type=changed;
check table t1 changed;
Table Op Msg_type Msg_text
test.t1 check status OK
check table t1 type=medium;
check table t1 medium;
Table Op Msg_type Msg_text
test.t1 check status OK
check table t1 type=extended;
check table t1 extended;
Table Op Msg_type Msg_text
test.t1 check status OK
show index from t1;
......
......@@ -12,7 +12,7 @@ while ($1)
dec $1;
}
enable_query_log;
send check table t1 type=extended;
send check table t1 extended;
connection con2;
insert into t1 values (200000);
connection con1;
......
......@@ -5,13 +5,13 @@
drop table if exists t1,t2;
create table t1 (a int not null primary key, b int not null,c int not null, key(b,c));
insert into t1 values (1,2,2),(2,2,3),(3,2,4),(4,2,4);
check table t1 type=fast;
check table t1 type=fast;
check table t1 type=changed;
check table t1 fast;
check table t1 fast;
check table t1 changed;
insert into t1 values (5,5,5);
check table t1 type=changed;
check table t1 type=medium;
check table t1 type=extended;
check table t1 changed;
check table t1 medium;
check table t1 extended;
show index from t1;
!$1062 insert into t1 values (5,5,5);
optimize table t1;
......
......@@ -289,7 +289,7 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt)
error = chk_key(&param, file);
if (!error)
{
if ((!check_opt->quick &&
if ((!(param.testflag & T_QUICK) &&
((share->options &
(HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ||
(param.testflag & (T_EXTEND | T_MEDIUM)))) ||
......@@ -330,7 +330,6 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt)
mi_mark_crashed(file);
file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
}
check_opt->retry_without_quick=param.retry_without_quick;
thd->proc_info=old_proc_info;
return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
......@@ -397,8 +396,7 @@ int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt)
}
tmp_check_opt.init();
tmp_check_opt.quick = 1;
tmp_check_opt.flags |= T_VERY_SILENT | T_CALC_CHECKSUM;
tmp_check_opt.flags |= T_VERY_SILENT | T_CALC_CHECKSUM | T_QUICK;
DBUG_RETURN(repair(thd, &tmp_check_opt));
err:
......@@ -491,21 +489,20 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt)
param.testflag = ((check_opt->flags & ~(T_EXTEND)) |
T_SILENT | T_FORCE_CREATE |
(check_opt->flags & T_EXTEND ? T_REP : T_REP_BY_SORT));
if (check_opt->quick)
param.opt_rep_quick++;
param.sort_buffer_length= check_opt->sort_buffer_size;
start_records=file->state->records;
while ((error=repair(thd,param,0)) && param.retry_repair)
{
param.retry_repair=0;
if (param.retry_without_quick && param.opt_rep_quick)
if ((param.testflag & T_RETRY_WITHOUT_QUICK) &&
(param.testflag & T_QUICK))
{
param.opt_rep_quick=0;
param.testflag&= ~T_RETRY_WITHOUT_QUICK;
sql_print_error("Warning: Retrying repair of: '%s' without quick",
table->path);
continue;
}
param.opt_rep_quick=0; // Safety
param.testflag&= ~T_QUICK;
if ((param.testflag & T_REP_BY_SORT))
{
param.testflag= (param.testflag & ~T_REP_BY_SORT) | T_REP;
......@@ -537,8 +534,6 @@ int ha_myisam::optimize(THD* thd, HA_CHECK_OPT *check_opt)
param.op_name = (char*) "optimize";
param.testflag = (check_opt->flags | T_SILENT | T_FORCE_CREATE |
T_REP_BY_SORT | T_STATISTICS | T_SORT_INDEX);
if (check_opt->quick)
param.opt_rep_quick++;
param.sort_buffer_length= check_opt->sort_buffer_size;
return repair(thd,param,1);
}
......@@ -573,7 +568,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
if (!optimize ||
((file->state->del || share->state.split != file->state->records) &&
(!param.opt_rep_quick ||
(!(param.testflag & T_QUICK) ||
!(share->state.changed & STATE_NOT_OPTIMIZED_KEYS))))
{
ulonglong key_map= ((local_testflag & T_CREATE_MISSING_KEYS) ?
......@@ -587,13 +582,15 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
param.testflag|= T_STATISTICS; // We get this for free
thd->proc_info="Repair by sorting";
statistics_done=1;
error = mi_repair_by_sort(&param, file, fixed_name, param.opt_rep_quick);
error = mi_repair_by_sort(&param, file, fixed_name,
param.testflag & T_QUICK);
}
else
{
thd->proc_info="Repair with keycache";
param.testflag &= ~T_REP_BY_SORT;
error= mi_repair(&param, file, fixed_name, param.opt_rep_quick);
error= mi_repair(&param, file, fixed_name,
param.testflag & T_QUICK);
}
param.testflag=testflag;
optimize_done=1;
......@@ -697,11 +694,10 @@ bool ha_myisam::activate_all_index(THD *thd)
thd->proc_info="Creating index";
myisamchk_init(&param);
param.op_name = (char*) "recreating_index";
param.testflag = (T_SILENT | T_REP_BY_SORT |
param.testflag = (T_SILENT | T_REP_BY_SORT | T_QUICK |
T_CREATE_MISSING_KEYS | T_TRUST_HEADER);
param.myf_rw&= ~MY_WAIT_IF_FULL;
param.sort_buffer_length= myisam_sort_buffer_size;
param.opt_rep_quick++; // Don't copy data file
param.tmpdir=mysql_tmpdir;
error=repair(thd,param,0) != HA_ADMIN_OK;
thd->proc_info=save_proc_info;
......@@ -723,16 +719,16 @@ bool ha_myisam::check_and_repair(THD *thd)
check_opt.flags= T_MEDIUM | T_AUTO_REPAIR;
// Don't use quick if deleted rows
if (!file->state->del && (myisam_recover_options & HA_RECOVER_QUICK))
check_opt.quick=1;
check_opt.flags|=T_QUICK;
sql_print_error("Warning: Checking table: '%s'",table->path);
if ((marked_crashed=mi_is_crashed(file)) || check(thd, &check_opt))
{
sql_print_error("Warning: Recovering table: '%s'",table->path);
check_opt.quick= !check_opt.retry_without_quick && !marked_crashed;
check_opt.flags=(((myisam_recover_options & HA_RECOVER_BACKUP) ?
T_BACKUP_DATA : 0) |
(!(myisam_recover_options & HA_RECOVER_FORCE) ?
T_SAFE_REPAIR : 0)) | T_AUTO_REPAIR;
check_opt.flags=
(myisam_recover_options & HA_RECOVER_BACKUP ? T_BACKUP_DATA : 0)
| (marked_crashed ? 0 : T_QUICK)
| (myisam_recover_options & HA_RECOVER_FORCE ? 0 : T_SAFE_REPAIR)
| T_AUTO_REPAIR;
if (repair(thd, &check_opt))
error=1;
}
......
......@@ -174,14 +174,11 @@ extern ulong myisam_sort_buffer_size;
typedef struct st_ha_check_opt
{
ulong sort_buffer_size;
uint flags;
bool quick;
bool changed_files;
bool optimize;
bool retry_without_quick;
uint flags; /* isam layer flags (e.g. for myisamchk) */
uint sql_flags; /* sql layer flags - for something myisamchk cannot do */
inline void init()
{
flags= 0; quick= optimize= retry_without_quick=0;
flags= sql_flags= 0;
sort_buffer_size = myisam_sort_buffer_size;
}
} HA_CHECK_OPT;
......
......@@ -359,6 +359,7 @@ static SYMBOL symbols[] = {
{ "UNLOCK", SYM(UNLOCK_SYM),0,0},
{ "UNSIGNED", SYM(UNSIGNED),0,0},
{ "USE", SYM(USE_SYM),0,0},
{ "USE_FRM", SYM(USE_FRM),0,0},
{ "USING", SYM(USING),0,0},
{ "UPDATE", SYM(UPDATE_SYM),0,0},
{ "USAGE", SYM(USAGE),0,0},
......
......@@ -859,8 +859,7 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db,
}
check_opt.init();
check_opt.flags|= T_VERY_SILENT | T_CALC_CHECKSUM;
check_opt.quick = 1;
check_opt.flags|= T_VERY_SILENT | T_CALC_CHECKSUM | T_QUICK;
thd->proc_info = "Rebuilding the index on master dump table";
// we do not want repair() to spam us with messages
// just send them to the error log, and report the failure in case of
......
......@@ -322,6 +322,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token UNION_SYM
%token UNIQUE_SYM
%token USAGE
%token USE_FRM
%token USE_SYM
%token USING
%token VALUES
......@@ -1289,7 +1290,6 @@ backup:
Lex->backup_dir = $6.str;
}
repair:
REPAIR table_or_tables
{
......@@ -1297,24 +1297,20 @@ repair:
lex->sql_command = SQLCOM_REPAIR;
lex->check_opt.init();
}
table_list opt_mi_check_type
table_list opt_mi_repair_type
opt_mi_check_type:
opt_mi_repair_type:
/* empty */ { Lex->check_opt.flags = T_MEDIUM; }
| TYPE_SYM EQ mi_check_types {}
| mi_check_types {}
| mi_repair_types {}
mi_check_types:
mi_check_type {}
| mi_check_type mi_check_types {}
mi_repair_types:
mi_repair_type {}
| mi_repair_type mi_repair_types {}
mi_check_type:
QUICK { Lex->check_opt.quick = 1; }
| FAST_SYM { Lex->check_opt.flags|= T_FAST; }
| MEDIUM_SYM { Lex->check_opt.flags|= T_MEDIUM; }
mi_repair_type:
QUICK { Lex->check_opt.flags|= T_QUICK; }
| EXTENDED_SYM { Lex->check_opt.flags|= T_EXTEND; }
| CHANGED { Lex->check_opt.flags|= T_CHECK_ONLY_CHANGED; }
| USE_FRM { /*Lex->check_opt.flags|= T_USEFRM;*/ }
analyze:
ANALYZE_SYM table_or_tables
......@@ -1334,6 +1330,21 @@ check:
}
table_list opt_mi_check_type
opt_mi_check_type:
/* empty */ { Lex->check_opt.flags = T_MEDIUM; }
| mi_check_types {}
mi_check_types:
mi_check_type {}
| mi_check_type mi_check_types {}
mi_check_type:
QUICK { Lex->check_opt.flags|= T_QUICK; }
| FAST_SYM { Lex->check_opt.flags|= T_FAST; }
| MEDIUM_SYM { Lex->check_opt.flags|= T_MEDIUM; }
| EXTENDED_SYM { Lex->check_opt.flags|= T_EXTEND; }
| CHANGED { Lex->check_opt.flags|= T_CHECK_ONLY_CHANGED; }
optimize:
OPTIMIZE table_or_tables
{
......@@ -3061,10 +3072,10 @@ keyword:
| TYPE_SYM {}
| UDF_SYM {}
| UNCOMMITTED_SYM {}
| USE_FRM {}
| VARIABLES {}
| WORK_SYM {}
| YEAR_SYM {}
| SLAVE {}
/* Option functions */
......
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