1 : /* Copyright (C) 2004-2008 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
2 : Copyright (C) 2008-2009 Sun Microsystems, Inc.
3 :
4 : This program is free software; you can redistribute it and/or modify
5 : it under the terms of the GNU General Public License as published by
6 : the Free Software Foundation; version 2 of the License.
7 :
8 : This program is distributed in the hope that it will be useful,
9 : but WITHOUT ANY WARRANTY; without even the implied warranty of
10 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 : GNU General Public License for more details.
12 :
13 : You should have received a copy of the GNU General Public License
14 : along with this program; if not, write to the Free Software
15 : Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16 :
17 :
18 : #ifdef USE_PRAGMA_IMPLEMENTATION
19 : #pragma implementation // gcc: Class implementation
20 : #endif
21 :
22 : #define MYSQL_SERVER 1
23 : #include "mysql_priv.h"
24 : #include <mysql/plugin.h>
25 : #include <m_ctype.h>
26 : #include <my_dir.h>
27 : #include <myisampack.h>
28 : #include <my_bit.h>
29 : #include "ha_maria.h"
30 : #include "trnman_public.h"
31 :
32 : C_MODE_START
33 : #include "maria_def.h"
34 : #include "ma_rt_index.h"
35 : #include "ma_blockrec.h"
36 : #include "ma_checkpoint.h"
37 : #include "ma_recovery.h"
38 : C_MODE_END
39 :
40 : /*
41 : Note that in future versions, only *transactional* Maria tables can
42 : rollback, so this flag should be up or down conditionally.
43 : */
44 : #ifdef MARIA_CANNOT_ROLLBACK
45 : #define CANNOT_ROLLBACK_FLAG HA_NO_TRANSACTIONS
46 : #define trans_register_ha(A, B, C) do { /* nothing */ } while(0)
47 : #else
48 : #define CANNOT_ROLLBACK_FLAG 0
49 : #endif
50 : #define THD_TRN (*(TRN **)thd_ha_data(thd, maria_hton))
51 :
52 : ulong pagecache_division_limit, pagecache_age_threshold;
53 : ulonglong pagecache_buffer_size;
54 :
55 : /**
56 : As the auto-repair is initiated when opened from the SQL layer
57 : (open_unireg_entry(), check_and_repair()), it does not happen when Maria's
58 : Recovery internally opens the table to apply log records to it, which is
59 : good. It would happen only after Recovery, if the table is still
60 : corrupted.
61 : */
62 : ulong maria_recover_options= HA_RECOVER_NONE;
63 : handlerton *maria_hton;
64 :
65 : /* bits in maria_recover_options */
66 : const char *maria_recover_names[]=
67 : {
68 : /*
69 : Compared to MyISAM, "default" was renamed to "normal" as it collided with
70 : SET var=default which sets to the var's default i.e. what happens when the
71 : var is not set i.e. HA_RECOVER_NONE.
72 : Another change is that OFF is used to disable, not ""; this is to have OFF
73 : display in SHOW VARIABLES which is better than "".
74 : */
75 : "OFF", "NORMAL", "BACKUP", "FORCE", "QUICK", NullS
76 : };
77 : TYPELIB maria_recover_typelib=
78 : {
79 : array_elements(maria_recover_names) - 1, "",
80 : maria_recover_names, NULL
81 : };
82 :
83 : const char *maria_stats_method_names[]=
84 : {
85 : "nulls_unequal", "nulls_equal",
86 : "nulls_ignored", NullS
87 : };
88 : TYPELIB maria_stats_method_typelib=
89 : {
90 : array_elements(maria_stats_method_names) - 1, "",
91 : maria_stats_method_names, NULL
92 : };
93 :
94 : /* transactions log purge mode */
95 : const char *maria_translog_purge_type_names[]=
96 : {
97 : "immediate", "external", "at_flush", NullS
98 : };
99 : TYPELIB maria_translog_purge_type_typelib=
100 : {
101 : array_elements(maria_translog_purge_type_names) - 1, "",
102 : maria_translog_purge_type_names, NULL
103 : };
104 : const char *maria_sync_log_dir_names[]=
105 : {
106 : "NEVER", "NEWFILE", "ALWAYS", NullS
107 : };
108 :
109 : TYPELIB maria_sync_log_dir_typelib=
110 : {
111 : array_elements(maria_sync_log_dir_names) - 1, "",
112 : maria_sync_log_dir_names, NULL
113 : };
114 :
115 : /** Interval between background checkpoints in seconds */
116 : static ulong checkpoint_interval;
117 : static void update_checkpoint_interval(MYSQL_THD thd,
118 : struct st_mysql_sys_var *var,
119 : void *var_ptr, const void *save);
120 : /** After that many consecutive recovery failures, remove logs */
121 : static ulong force_start_after_recovery_failures;
122 : static void update_log_file_size(MYSQL_THD thd,
123 : struct st_mysql_sys_var *var,
124 : void *var_ptr, const void *save);
125 :
126 : static MYSQL_SYSVAR_ULONG(block_size, maria_block_size,
127 : PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
128 : "Block size to be used for MARIA index pages.", 0, 0,
129 : MARIA_KEY_BLOCK_LENGTH, MARIA_MIN_KEY_BLOCK_LENGTH,
130 : MARIA_MAX_KEY_BLOCK_LENGTH, MARIA_MIN_KEY_BLOCK_LENGTH);
131 :
132 : static MYSQL_SYSVAR_ULONG(checkpoint_interval, checkpoint_interval,
133 : PLUGIN_VAR_RQCMDARG,
134 : "Interval between automatic checkpoints, in seconds; 0 means"
135 : " 'no automatic checkpoints' which makes sense only for testing.",
136 : NULL, update_checkpoint_interval, 30, 0, UINT_MAX, 1);
137 :
138 : static MYSQL_SYSVAR_ULONG(force_start_after_recovery_failures,
139 : force_start_after_recovery_failures,
140 : /*
141 : Read-only because setting it on the fly has no useful effect,
142 : should be set on command-line.
143 : */
144 : PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
145 : "Number of consecutive log recovery failures after which logs will be"
146 : " automatically deleted to cure the problem; 0 (the default) disables"
147 : " the feature.", NULL, NULL, 0, 0, UINT_MAX8, 1);
148 :
149 : static MYSQL_SYSVAR_BOOL(page_checksum, maria_page_checksums, 0,
150 : "Maintain page checksums (can be overridden per table "
151 : "with PAGE_CHECKSUM clause in CREATE TABLE)", 0, 0, 1);
152 :
153 : /* It is only command line argument */
154 : static MYSQL_SYSVAR_STR(log_dir_path, maria_data_root,
155 : PLUGIN_VAR_NOSYSVAR | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
156 : "Path to the directory where to store transactional log",
157 : NULL, NULL, mysql_real_data_home);
158 :
159 :
160 : static MYSQL_SYSVAR_ULONG(log_file_size, log_file_size,
161 : PLUGIN_VAR_RQCMDARG,
162 : "Limit for transaction log size",
163 : NULL, update_log_file_size, TRANSLOG_FILE_SIZE,
164 : TRANSLOG_MIN_FILE_SIZE, 0xffffffffL, TRANSLOG_PAGE_SIZE);
165 :
166 : static MYSQL_SYSVAR_ENUM(log_purge_type, log_purge_type,
167 : PLUGIN_VAR_RQCMDARG,
168 : "Specifies how maria transactional log will be purged. "
169 : "Possible values of name are \"immediate\", \"external\" "
170 : "and \"at_flush\"",
171 : NULL, NULL, TRANSLOG_PURGE_IMMIDIATE,
172 : &maria_translog_purge_type_typelib);
173 :
174 : static MYSQL_SYSVAR_ULONGLONG(max_sort_file_size,
175 : maria_max_temp_length, PLUGIN_VAR_RQCMDARG,
176 : "Don't use the fast sort index method to created index if the "
177 : "temporary file would get bigger than this.",
178 : 0, 0, MAX_FILE_SIZE, 0, MAX_FILE_SIZE, 1024*1024);
179 :
180 : static MYSQL_SYSVAR_ULONG(pagecache_age_threshold,
181 : pagecache_age_threshold, PLUGIN_VAR_RQCMDARG,
182 : "This characterizes the number of hits a hot block has to be untouched "
183 : "until it is considered aged enough to be downgraded to a warm block. "
184 : "This specifies the percentage ratio of that number of hits to the "
185 : "total number of blocks in the page cache.", 0, 0,
186 : 300, 100, ~0L, 100);
187 :
188 : static MYSQL_SYSVAR_ULONGLONG(pagecache_buffer_size, pagecache_buffer_size,
189 : PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
190 : "The size of the buffer used for index blocks for Maria tables. "
191 : "Increase this to get better index handling (for all reads and "
192 : "multiple writes) to as much as you can afford.", 0, 0,
193 : KEY_CACHE_SIZE, MALLOC_OVERHEAD, ~(ulong) 0, IO_SIZE);
194 :
195 : static MYSQL_SYSVAR_ULONG(pagecache_division_limit, pagecache_division_limit,
196 : PLUGIN_VAR_RQCMDARG,
197 : "The minimum percentage of warm blocks in key cache", 0, 0,
198 : 100, 1, 100, 1);
199 :
200 : static MYSQL_SYSVAR_ENUM(recover, maria_recover_options, PLUGIN_VAR_OPCMDARG,
201 : "Specifies how corrupted tables should be automatically repaired."
202 : " Possible values are \"NORMAL\" (the default), \"BACKUP\", \"FORCE\","
203 : " \"QUICK\", or \"OFF\" which is like not using the option.",
204 : NULL, NULL, HA_RECOVER_NONE, &maria_recover_typelib);
205 :
206 : static MYSQL_THDVAR_ULONG(repair_threads, PLUGIN_VAR_RQCMDARG,
207 : "Number of threads to use when repairing maria tables. The value of 1 "
208 : "disables parallel repair.",
209 : 0, 0, 1, 1, ~0L, 1);
210 :
211 : static MYSQL_THDVAR_ULONG(sort_buffer_size, PLUGIN_VAR_RQCMDARG,
212 : "The buffer that is allocated when sorting the index when doing a "
213 : "REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE.",
214 : 0, 0, 8192*1024, 4, ~0L, 1);
215 :
216 : static MYSQL_THDVAR_ENUM(stats_method, PLUGIN_VAR_RQCMDARG,
217 : "Specifies how maria index statistics collection code should treat "
218 : "NULLs. Possible values are \"nulls_unequal\", \"nulls_equal\", "
219 : "and \"nulls_ignored\".", 0, 0, 0, &maria_stats_method_typelib);
220 :
221 : static MYSQL_SYSVAR_ENUM(sync_log_dir, sync_log_dir, PLUGIN_VAR_RQCMDARG,
222 : "Controls syncing directory after log file growth and new file "
223 : "creation. Possible values are \"never\", \"newfile\" and "
224 : "\"always\").", NULL, NULL, TRANSLOG_SYNC_DIR_NEWFILE,
225 : &maria_sync_log_dir_typelib);
226 :
227 : /*****************************************************************************
228 : ** MARIA tables
229 : *****************************************************************************/
230 :
231 : static handler *maria_create_handler(handlerton *hton,
232 : TABLE_SHARE * table,
233 56 : MEM_ROOT *mem_root)
234 : {
235 56 : return new (mem_root) ha_maria(hton, table);
236 : }
237 :
238 :
239 : // collect errors printed by maria_check routines
240 :
241 : static void _ma_check_print_msg(HA_CHECK *param, const char *msg_type,
242 0 : const char *fmt, va_list args)
243 : {
244 0 : THD *thd= (THD *) param->thd;
245 0 : Protocol *protocol= thd->protocol;
246 : uint length, msg_length;
247 : char msgbuf[HA_MAX_MSG_BUF];
248 : char name[NAME_LEN * 2 + 2];
249 :
250 0 : msg_length= my_vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
251 0 : msgbuf[sizeof(msgbuf) - 1]= 0; // healthy paranoia
252 :
253 0 : DBUG_PRINT(msg_type, ("message: %s", msgbuf));
254 :
255 0 : if (!thd->vio_ok())
256 : {
257 0 : sql_print_error(msgbuf);
258 0 : return;
259 : }
260 :
261 0 : if (param->testflag &
262 : (T_CREATE_MISSING_KEYS | T_SAFE_REPAIR | T_AUTO_REPAIR))
263 : {
264 0 : my_message(ER_NOT_KEYFILE, msgbuf, MYF(MY_WME));
265 0 : return;
266 : }
267 : length= (uint) (strxmov(name, param->db_name, ".", param->table_name,
268 0 : NullS) - name);
269 : /*
270 : TODO: switch from protocol to push_warning here. The main reason we didn't
271 : it yet is parallel repair. Due to following trace:
272 : ma_check_print_msg/push_warning/sql_alloc/my_pthread_getspecific_ptr.
273 :
274 : Also we likely need to lock mutex here (in both cases with protocol and
275 : push_warning).
276 : */
277 0 : protocol->prepare_for_resend();
278 0 : protocol->store(name, length, system_charset_info);
279 0 : protocol->store(param->op_name, system_charset_info);
280 0 : protocol->store(msg_type, system_charset_info);
281 0 : protocol->store(msgbuf, msg_length, system_charset_info);
282 0 : if (protocol->write())
283 : sql_print_error("Failed on my_net_write, writing to stderr instead: %s\n",
284 0 : msgbuf);
285 : return;
286 : }
287 :
288 :
289 : /*
290 : Convert TABLE object to Maria key and column definition
291 :
292 : SYNOPSIS
293 : table2maria()
294 : table_arg in TABLE object.
295 : keydef_out out Maria key definition.
296 : recinfo_out out Maria column definition.
297 : records_out out Number of fields.
298 :
299 : DESCRIPTION
300 : This function will allocate and initialize Maria key and column
301 : definition for further use in ma_create or for a check for underlying
302 : table conformance in merge engine.
303 :
304 : The caller needs to free *recinfo_out after use. Since *recinfo_out
305 : and *keydef_out are allocated with a my_multi_malloc, *keydef_out
306 : is freed automatically when *recinfo_out is freed.
307 :
308 : RETURN VALUE
309 : 0 OK
310 : # error code
311 : */
312 :
313 : static int table2maria(TABLE *table_arg, data_file_type row_type,
314 : MARIA_KEYDEF **keydef_out,
315 : MARIA_COLUMNDEF **recinfo_out, uint *records_out,
316 0 : MARIA_CREATE_INFO *create_info)
317 : {
318 : uint i, j, recpos, minpos, fieldpos, temp_length, length;
319 0 : enum ha_base_keytype type= HA_KEYTYPE_BINARY;
320 : uchar *record;
321 : KEY *pos;
322 : MARIA_KEYDEF *keydef;
323 : MARIA_COLUMNDEF *recinfo, *recinfo_pos;
324 : HA_KEYSEG *keyseg;
325 0 : TABLE_SHARE *share= table_arg->s;
326 0 : uint options= share->db_options_in_use;
327 0 : DBUG_ENTER("table2maria");
328 :
329 0 : if (row_type == BLOCK_RECORD)
330 0 : options|= HA_OPTION_PACK_RECORD;
331 :
332 0 : if (!(my_multi_malloc(MYF(MY_WME),
333 : recinfo_out, (share->fields * 2 + 2) * sizeof(MARIA_COLUMNDEF),
334 : keydef_out, share->keys * sizeof(MARIA_KEYDEF),
335 : &keyseg,
336 : (share->key_parts + share->keys) * sizeof(HA_KEYSEG),
337 : NullS)))
338 0 : DBUG_RETURN(HA_ERR_OUT_OF_MEM); /* purecov: inspected */
339 0 : keydef= *keydef_out;
340 0 : recinfo= *recinfo_out;
341 0 : pos= table_arg->key_info;
342 0 : for (i= 0; i < share->keys; i++, pos++)
343 : {
344 : keydef[i].flag= (uint16) (pos->flags & (HA_NOSAME | HA_FULLTEXT |
345 0 : HA_SPATIAL));
346 : keydef[i].key_alg= pos->algorithm == HA_KEY_ALG_UNDEF ?
347 : (pos->flags & HA_SPATIAL ? HA_KEY_ALG_RTREE : HA_KEY_ALG_BTREE) :
348 0 : pos->algorithm;
349 0 : keydef[i].block_length= pos->block_size;
350 0 : keydef[i].seg= keyseg;
351 0 : keydef[i].keysegs= pos->key_parts;
352 0 : for (j= 0; j < pos->key_parts; j++)
353 : {
354 0 : Field *field= pos->key_part[j].field;
355 0 : type= field->key_type();
356 0 : keydef[i].seg[j].flag= pos->key_part[j].key_part_flag;
357 :
358 0 : if (options & HA_OPTION_PACK_KEYS ||
359 : (pos->flags & (HA_PACK_KEY | HA_BINARY_PACK_KEY |
360 : HA_SPACE_PACK_USED)))
361 : {
362 0 : if (pos->key_part[j].length > 8 &&
363 : (type == HA_KEYTYPE_TEXT ||
364 : type == HA_KEYTYPE_NUM ||
365 : (type == HA_KEYTYPE_BINARY && !field->zero_pack())))
366 : {
367 : /* No blobs here */
368 0 : if (j == 0)
369 0 : keydef[i].flag|= HA_PACK_KEY;
370 0 : if (!(field->flags & ZEROFILL_FLAG) &&
371 : (field->type() == MYSQL_TYPE_STRING ||
372 : field->type() == MYSQL_TYPE_VAR_STRING ||
373 : ((int) (pos->key_part[j].length - field->decimals())) >= 4))
374 0 : keydef[i].seg[j].flag|= HA_SPACE_PACK;
375 : }
376 0 : else if (j == 0 && (!(pos->flags & HA_NOSAME) || pos->key_length > 16))
377 0 : keydef[i].flag|= HA_BINARY_PACK_KEY;
378 : }
379 0 : keydef[i].seg[j].type= (int) type;
380 0 : keydef[i].seg[j].start= pos->key_part[j].offset;
381 0 : keydef[i].seg[j].length= pos->key_part[j].length;
382 : keydef[i].seg[j].bit_start= keydef[i].seg[j].bit_end=
383 0 : keydef[i].seg[j].bit_length= 0;
384 0 : keydef[i].seg[j].bit_pos= 0;
385 0 : keydef[i].seg[j].language= field->charset()->number;
386 :
387 0 : if (field->null_ptr)
388 : {
389 0 : keydef[i].seg[j].null_bit= field->null_bit;
390 : keydef[i].seg[j].null_pos= (uint) (field->null_ptr-
391 0 : (uchar*) table_arg->record[0]);
392 : }
393 : else
394 : {
395 0 : keydef[i].seg[j].null_bit= 0;
396 0 : keydef[i].seg[j].null_pos= 0;
397 : }
398 0 : if (field->type() == MYSQL_TYPE_BLOB ||
399 : field->type() == MYSQL_TYPE_GEOMETRY)
400 : {
401 0 : keydef[i].seg[j].flag|= HA_BLOB_PART;
402 : /* save number of bytes used to pack length */
403 : keydef[i].seg[j].bit_start= (uint) (field->pack_length() -
404 0 : share->blob_ptr_size);
405 : }
406 0 : else if (field->type() == MYSQL_TYPE_BIT)
407 : {
408 0 : keydef[i].seg[j].bit_length= ((Field_bit *) field)->bit_len;
409 0 : keydef[i].seg[j].bit_start= ((Field_bit *) field)->bit_ofs;
410 : keydef[i].seg[j].bit_pos= (uint) (((Field_bit *) field)->bit_ptr -
411 0 : (uchar*) table_arg->record[0]);
412 : }
413 : }
414 0 : keyseg+= pos->key_parts;
415 : }
416 0 : if (table_arg->found_next_number_field)
417 0 : keydef[share->next_number_index].flag|= HA_AUTO_KEY;
418 0 : record= table_arg->record[0];
419 0 : recpos= 0;
420 0 : recinfo_pos= recinfo;
421 0 : create_info->null_bytes= table_arg->s->null_bytes;
422 :
423 0 : while (recpos < (uint) share->reclength)
424 : {
425 0 : Field **field, *found= 0;
426 0 : minpos= share->reclength;
427 0 : length= 0;
428 :
429 0 : for (field= table_arg->field; *field; field++)
430 : {
431 0 : if ((fieldpos= (*field)->offset(record)) >= recpos &&
432 : fieldpos <= minpos)
433 : {
434 : /* skip null fields */
435 0 : if (!(temp_length= (*field)->pack_length_in_rec()))
436 0 : continue; /* Skip null-fields */
437 0 : if (! found || fieldpos < minpos ||
438 : (fieldpos == minpos && temp_length < length))
439 : {
440 0 : minpos= fieldpos;
441 0 : found= *field;
442 0 : length= temp_length;
443 : }
444 : }
445 : }
446 0 : DBUG_PRINT("loop", ("found: 0x%lx recpos: %d minpos: %d length: %d",
447 : (long) found, recpos, minpos, length));
448 0 : if (!found)
449 0 : break;
450 :
451 0 : if (found->flags & BLOB_FLAG)
452 0 : recinfo_pos->type= FIELD_BLOB;
453 0 : else if (found->type() == MYSQL_TYPE_VARCHAR)
454 0 : recinfo_pos->type= FIELD_VARCHAR;
455 0 : else if (!(options & HA_OPTION_PACK_RECORD) ||
456 : (found->zero_pack() && (found->flags & PRI_KEY_FLAG)))
457 0 : recinfo_pos->type= FIELD_NORMAL;
458 0 : else if (found->zero_pack())
459 0 : recinfo_pos->type= FIELD_SKIP_ZERO;
460 : else
461 : recinfo_pos->type= ((length <= 3 ||
462 : (found->flags & ZEROFILL_FLAG)) ?
463 : FIELD_NORMAL :
464 : found->type() == MYSQL_TYPE_STRING ||
465 : found->type() == MYSQL_TYPE_VAR_STRING ?
466 : FIELD_SKIP_ENDSPACE :
467 0 : FIELD_SKIP_PRESPACE);
468 0 : if (found->null_ptr)
469 : {
470 0 : recinfo_pos->null_bit= found->null_bit;
471 : recinfo_pos->null_pos= (uint) (found->null_ptr -
472 0 : (uchar*) table_arg->record[0]);
473 : }
474 : else
475 : {
476 0 : recinfo_pos->null_bit= 0;
477 0 : recinfo_pos->null_pos= 0;
478 : }
479 0 : (recinfo_pos++)->length= (uint16) length;
480 0 : recpos= minpos + length;
481 0 : DBUG_PRINT("loop", ("length: %d type: %d",
482 : recinfo_pos[-1].length,recinfo_pos[-1].type));
483 : }
484 0 : *records_out= (uint) (recinfo_pos - recinfo);
485 0 : DBUG_RETURN(0);
486 : }
487 :
488 :
489 : /*
490 : Check for underlying table conformance
491 :
492 : SYNOPSIS
493 : maria_check_definition()
494 : t1_keyinfo in First table key definition
495 : t1_recinfo in First table record definition
496 : t1_keys in Number of keys in first table
497 : t1_recs in Number of records in first table
498 : t2_keyinfo in Second table key definition
499 : t2_recinfo in Second table record definition
500 : t2_keys in Number of keys in second table
501 : t2_recs in Number of records in second table
502 : strict in Strict check switch
503 :
504 : DESCRIPTION
505 : This function compares two Maria definitions. By intention it was done
506 : to compare merge table definition against underlying table definition.
507 : It may also be used to compare dot-frm and MAI definitions of Maria
508 : table as well to compare different Maria table definitions.
509 :
510 : For merge table it is not required that number of keys in merge table
511 : must exactly match number of keys in underlying table. When calling this
512 : function for underlying table conformance check, 'strict' flag must be
513 : set to false, and converted merge definition must be passed as t1_*.
514 :
515 : Otherwise 'strict' flag must be set to 1 and it is not required to pass
516 : converted dot-frm definition as t1_*.
517 :
518 : RETURN VALUE
519 : 0 - Equal definitions.
520 : 1 - Different definitions.
521 :
522 : TODO
523 : - compare FULLTEXT keys;
524 : - compare SPATIAL keys;
525 : - compare FIELD_SKIP_ZERO which is converted to FIELD_NORMAL correctly
526 : (should be correctly detected in table2maria).
527 : */
528 :
529 : int maria_check_definition(MARIA_KEYDEF *t1_keyinfo,
530 : MARIA_COLUMNDEF *t1_recinfo,
531 : uint t1_keys, uint t1_recs,
532 : MARIA_KEYDEF *t2_keyinfo,
533 : MARIA_COLUMNDEF *t2_recinfo,
534 0 : uint t2_keys, uint t2_recs, bool strict)
535 : {
536 : uint i, j;
537 0 : DBUG_ENTER("maria_check_definition");
538 0 : if ((strict ? t1_keys != t2_keys : t1_keys > t2_keys))
539 : {
540 0 : DBUG_PRINT("error", ("Number of keys differs: t1_keys=%u, t2_keys=%u",
541 : t1_keys, t2_keys));
542 0 : DBUG_RETURN(1);
543 : }
544 0 : if (t1_recs != t2_recs)
545 : {
546 0 : DBUG_PRINT("error", ("Number of recs differs: t1_recs=%u, t2_recs=%u",
547 : t1_recs, t2_recs));
548 0 : DBUG_RETURN(1);
549 : }
550 0 : for (i= 0; i < t1_keys; i++)
551 : {
552 0 : HA_KEYSEG *t1_keysegs= t1_keyinfo[i].seg;
553 0 : HA_KEYSEG *t2_keysegs= t2_keyinfo[i].seg;
554 0 : if (t1_keyinfo[i].flag & HA_FULLTEXT && t2_keyinfo[i].flag & HA_FULLTEXT)
555 : continue;
556 0 : else if (t1_keyinfo[i].flag & HA_FULLTEXT ||
557 : t2_keyinfo[i].flag & HA_FULLTEXT)
558 : {
559 0 : DBUG_PRINT("error", ("Key %d has different definition", i));
560 0 : DBUG_PRINT("error", ("t1_fulltext= %d, t2_fulltext=%d",
561 : test(t1_keyinfo[i].flag & HA_FULLTEXT),
562 : test(t2_keyinfo[i].flag & HA_FULLTEXT)));
563 0 : DBUG_RETURN(1);
564 : }
565 0 : if (t1_keyinfo[i].flag & HA_SPATIAL && t2_keyinfo[i].flag & HA_SPATIAL)
566 : continue;
567 0 : else if (t1_keyinfo[i].flag & HA_SPATIAL ||
568 : t2_keyinfo[i].flag & HA_SPATIAL)
569 : {
570 0 : DBUG_PRINT("error", ("Key %d has different definition", i));
571 0 : DBUG_PRINT("error", ("t1_spatial= %d, t2_spatial=%d",
572 : test(t1_keyinfo[i].flag & HA_SPATIAL),
573 : test(t2_keyinfo[i].flag & HA_SPATIAL)));
574 0 : DBUG_RETURN(1);
575 : }
576 0 : if (t1_keyinfo[i].keysegs != t2_keyinfo[i].keysegs ||
577 : t1_keyinfo[i].key_alg != t2_keyinfo[i].key_alg)
578 : {
579 0 : DBUG_PRINT("error", ("Key %d has different definition", i));
580 0 : DBUG_PRINT("error", ("t1_keysegs=%d, t1_key_alg=%d",
581 : t1_keyinfo[i].keysegs, t1_keyinfo[i].key_alg));
582 0 : DBUG_PRINT("error", ("t2_keysegs=%d, t2_key_alg=%d",
583 : t2_keyinfo[i].keysegs, t2_keyinfo[i].key_alg));
584 0 : DBUG_RETURN(1);
585 : }
586 0 : for (j= t1_keyinfo[i].keysegs; j--;)
587 : {
588 0 : uint8 t1_keysegs_j__type= t1_keysegs[j].type;
589 : /*
590 : Table migration from 4.1 to 5.1. In 5.1 a *TEXT key part is
591 : always HA_KEYTYPE_VARTEXT2. In 4.1 we had only the equivalent of
592 : HA_KEYTYPE_VARTEXT1. Since we treat both the same on MyISAM
593 : level, we can ignore a mismatch between these types.
594 : */
595 0 : if ((t1_keysegs[j].flag & HA_BLOB_PART) &&
596 : (t2_keysegs[j].flag & HA_BLOB_PART))
597 : {
598 0 : if ((t1_keysegs_j__type == HA_KEYTYPE_VARTEXT2) &&
599 : (t2_keysegs[j].type == HA_KEYTYPE_VARTEXT1))
600 0 : t1_keysegs_j__type= HA_KEYTYPE_VARTEXT1; /* purecov: tested */
601 0 : else if ((t1_keysegs_j__type == HA_KEYTYPE_VARBINARY2) &&
602 : (t2_keysegs[j].type == HA_KEYTYPE_VARBINARY1))
603 0 : t1_keysegs_j__type= HA_KEYTYPE_VARBINARY1; /* purecov: inspected */
604 : }
605 :
606 0 : if (t1_keysegs_j__type != t2_keysegs[j].type ||
607 : t1_keysegs[j].language != t2_keysegs[j].language ||
608 : t1_keysegs[j].null_bit != t2_keysegs[j].null_bit ||
609 : t1_keysegs[j].length != t2_keysegs[j].length)
610 : {
611 0 : DBUG_PRINT("error", ("Key segment %d (key %d) has different "
612 : "definition", j, i));
613 0 : DBUG_PRINT("error", ("t1_type=%d, t1_language=%d, t1_null_bit=%d, "
614 : "t1_length=%d",
615 : t1_keysegs[j].type, t1_keysegs[j].language,
616 : t1_keysegs[j].null_bit, t1_keysegs[j].length));
617 0 : DBUG_PRINT("error", ("t2_type=%d, t2_language=%d, t2_null_bit=%d, "
618 : "t2_length=%d",
619 : t2_keysegs[j].type, t2_keysegs[j].language,
620 : t2_keysegs[j].null_bit, t2_keysegs[j].length));
621 :
622 0 : DBUG_RETURN(1);
623 : }
624 : }
625 : }
626 :
627 0 : for (i= 0; i < t1_recs; i++)
628 : {
629 0 : MARIA_COLUMNDEF *t1_rec= &t1_recinfo[i];
630 0 : MARIA_COLUMNDEF *t2_rec= &t2_recinfo[i];
631 : /*
632 : FIELD_SKIP_ZERO can be changed to FIELD_NORMAL in maria_create,
633 : see NOTE1 in ma_create.c
634 : */
635 0 : if ((t1_rec->type != t2_rec->type &&
636 : !(t1_rec->type == (int) FIELD_SKIP_ZERO &&
637 : t1_rec->length == 1 &&
638 : t2_rec->type == (int) FIELD_NORMAL)) ||
639 : t1_rec->length != t2_rec->length ||
640 : t1_rec->null_bit != t2_rec->null_bit)
641 : {
642 0 : DBUG_PRINT("error", ("Field %d has different definition", i));
643 0 : DBUG_PRINT("error", ("t1_type=%d, t1_length=%d, t1_null_bit=%d",
644 : t1_rec->type, t1_rec->length, t1_rec->null_bit));
645 0 : DBUG_PRINT("error", ("t2_type=%d, t2_length=%d, t2_null_bit=%d",
646 : t2_rec->type, t2_rec->length, t2_rec->null_bit));
647 0 : DBUG_RETURN(1);
648 : }
649 : }
650 0 : DBUG_RETURN(0);
651 : }
652 :
653 :
654 : extern "C" {
655 :
656 0 : volatile int *_ma_killed_ptr(HA_CHECK *param)
657 : {
658 : /* In theory Unsafe conversion, but should be ok for now */
659 0 : return (int*) &(((THD *) (param->thd))->killed);
660 : }
661 :
662 :
663 0 : void _ma_check_print_error(HA_CHECK *param, const char *fmt, ...)
664 : {
665 : va_list args;
666 0 : DBUG_ENTER("_ma_check_print_error");
667 0 : param->error_printed |= 1;
668 0 : param->out_flag |= O_DATA_LOST;
669 0 : va_start(args, fmt);
670 0 : _ma_check_print_msg(param, "error", fmt, args);
671 0 : va_end(args);
672 0 : DBUG_VOID_RETURN;
673 : }
674 :
675 :
676 0 : void _ma_check_print_info(HA_CHECK *param, const char *fmt, ...)
677 : {
678 : va_list args;
679 0 : DBUG_ENTER("_ma_check_print_info");
680 0 : va_start(args, fmt);
681 0 : _ma_check_print_msg(param, "info", fmt, args);
682 0 : va_end(args);
683 0 : DBUG_VOID_RETURN;
684 : }
685 :
686 :
687 0 : void _ma_check_print_warning(HA_CHECK *param, const char *fmt, ...)
688 : {
689 : va_list args;
690 0 : DBUG_ENTER("_ma_check_print_warning");
691 0 : param->warning_printed= 1;
692 0 : param->out_flag |= O_DATA_LOST;
693 0 : va_start(args, fmt);
694 0 : _ma_check_print_msg(param, "warning", fmt, args);
695 0 : va_end(args);
696 0 : DBUG_VOID_RETURN;
697 : }
698 :
699 : }
700 :
701 : /**
702 : Transactional table doing bulk insert with one single UNDO
703 : (UNDO_BULK_INSERT) and with repair.
704 : */
705 : #define BULK_INSERT_SINGLE_UNDO_AND_REPAIR 1
706 : /**
707 : Transactional table doing bulk insert with one single UNDO
708 : (UNDO_BULK_INSERT) and without repair.
709 : */
710 : #define BULK_INSERT_SINGLE_UNDO_AND_NO_REPAIR 2
711 : /**
712 : None of BULK_INSERT_SINGLE_UNDO_AND_REPAIR and
713 : BULK_INSERT_SINGLE_UNDO_AND_NO_REPAIR.
714 : */
715 : #define BULK_INSERT_NONE 0
716 :
717 56 : ha_maria::ha_maria(handlerton *hton, TABLE_SHARE *table_arg):
718 : handler(hton, table_arg), file(0),
719 : int_table_flags(HA_NULL_IN_KEY | HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER |
720 : HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
721 : HA_DUPLICATE_POS | HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY |
722 : HA_FILE_BASED | HA_CAN_GEOMETRY | CANNOT_ROLLBACK_FLAG |
723 : HA_CAN_BIT_FIELD | HA_CAN_RTREEKEYS |
724 : HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT),
725 56 : can_enable_indexes(1), bulk_insert_single_undo(BULK_INSERT_NONE)
726 : {}
727 :
728 :
729 0 : handler *ha_maria::clone(MEM_ROOT *mem_root)
730 : {
731 0 : ha_maria *new_handler= static_cast <ha_maria *>(handler::clone(mem_root));
732 0 : if (new_handler)
733 0 : new_handler->file->state= file->state;
734 0 : return new_handler;
735 : }
736 :
737 :
738 : static const char *ha_maria_exts[]=
739 : {
740 : MARIA_NAME_IEXT,
741 : MARIA_NAME_DEXT,
742 : NullS
743 : };
744 :
745 :
746 1 : const char **ha_maria::bas_ext() const
747 : {
748 1 : return ha_maria_exts;
749 : }
750 :
751 :
752 0 : const char *ha_maria::index_type(uint key_number)
753 : {
754 : return ((table->key_info[key_number].flags & HA_FULLTEXT) ?
755 : "FULLTEXT" :
756 : (table->key_info[key_number].flags & HA_SPATIAL) ?
757 : "SPATIAL" :
758 : (table->key_info[key_number].algorithm == HA_KEY_ALG_RTREE) ?
759 0 : "RTREE" : "BTREE");
760 : }
761 :
762 :
763 52 : double ha_maria::scan_time()
764 : {
765 52 : if (file->s->data_file_type == BLOCK_RECORD)
766 52 : return ulonglong2double(stats.data_file_length - file->s->block_size) / max(file->s->block_size / 2, IO_SIZE) + 2;
767 0 : return handler::scan_time();
768 : }
769 :
770 : /*
771 : We need to be able to store at least two keys on an index page as the
772 : splitting algorithms depends on this. (With only one key on a page
773 : we also can't use any compression, which may make the index file much
774 : larger)
775 : We use HA_MAX_KEY_BUFF as this is a stack restriction imposed by the
776 : handler interface.
777 :
778 : We also need to reserve place for a record pointer (8) and 3 bytes
779 : per key segment to store the length of the segment + possible null bytes.
780 : These extra bytes are required here so that maria_create() will surely
781 : accept any keys created which the returned key data storage length.
782 : */
783 :
784 0 : uint ha_maria::max_supported_key_length() const
785 : {
786 0 : uint tmp= (maria_max_key_length() - 8 - HA_MAX_KEY_SEG*3);
787 0 : return min(HA_MAX_KEY_BUFF, tmp);
788 : }
789 :
790 :
791 : #ifdef HAVE_REPLICATION
792 0 : int ha_maria::net_read_dump(NET * net)
793 : {
794 0 : int data_fd= file->dfile.file;
795 0 : int error= 0;
796 :
797 0 : my_seek(data_fd, 0L, MY_SEEK_SET, MYF(MY_WME));
798 : for (;;)
799 : {
800 0 : ulong packet_len= my_net_read(net);
801 0 : if (!packet_len)
802 0 : break; // end of file
803 0 : if (packet_len == packet_error)
804 : {
805 0 : sql_print_error("ha_maria::net_read_dump - read error ");
806 0 : error= -1;
807 0 : goto err;
808 : }
809 0 : if (my_write(data_fd, (uchar *) net->read_pos, (uint) packet_len,
810 : MYF(MY_WME | MY_FNABP)))
811 : {
812 0 : error= errno;
813 : goto err;
814 : }
815 : }
816 0 : err:
817 0 : return error;
818 : }
819 :
820 :
821 0 : int ha_maria::dump(THD * thd, int fd)
822 : {
823 0 : MARIA_SHARE *share= file->s;
824 0 : NET *net= &thd->net;
825 0 : uint block_size= share->block_size;
826 0 : my_off_t bytes_to_read= share->state.state.data_file_length;
827 0 : int data_fd= file->dfile.file;
828 0 : uchar *buf= (uchar *) my_malloc(block_size, MYF(MY_WME));
829 0 : if (!buf)
830 0 : return ENOMEM;
831 :
832 0 : int error= 0;
833 0 : my_seek(data_fd, 0L, MY_SEEK_SET, MYF(MY_WME));
834 0 : for (; bytes_to_read > 0;)
835 : {
836 0 : size_t bytes= my_read(data_fd, buf, block_size, MYF(MY_WME));
837 0 : if (bytes == MY_FILE_ERROR)
838 : {
839 0 : error= errno;
840 0 : goto err;
841 : }
842 :
843 0 : if (fd >= 0)
844 : {
845 0 : if (my_write(fd, buf, bytes, MYF(MY_WME | MY_FNABP)))
846 : {
847 0 : error= errno ? errno : EPIPE;
848 0 : goto err;
849 : }
850 : }
851 : else
852 : {
853 0 : if (my_net_write(net, buf, bytes))
854 : {
855 0 : error= errno ? errno : EPIPE;
856 0 : goto err;
857 : }
858 : }
859 0 : bytes_to_read -= bytes;
860 : }
861 :
862 0 : if (fd < 0)
863 : {
864 0 : if (my_net_write(net, (uchar*) "", 0))
865 0 : error= errno ? errno : EPIPE;
866 0 : net_flush(net);
867 : }
868 :
869 0 : err:
870 0 : my_free((uchar*) buf, MYF(0));
871 0 : return error;
872 : }
873 : #endif /* HAVE_REPLICATION */
874 :
875 : /* Name is here without an extension */
876 :
877 55 : int ha_maria::open(const char *name, int mode, uint test_if_locked)
878 : {
879 : uint i;
880 :
881 : #ifdef NOT_USED
882 : /*
883 : If the user wants to have memory mapped data files, add an
884 : open_flag. Do not memory map temporary tables because they are
885 : expected to be inserted and thus extended a lot. Memory mapping is
886 : efficient for files that keep their size, but very inefficient for
887 : growing files. Using an open_flag instead of calling ma_extra(...
888 : HA_EXTRA_MMAP ...) after maxs_open() has the advantage that the
889 : mapping is not repeated for every open, but just done on the initial
890 : open, when the MyISAM share is created. Every time the server
891 : requires to open a new instance of a table it calls this method. We
892 : will always supply HA_OPEN_MMAP for a permanent table. However, the
893 : Maria storage engine will ignore this flag if this is a secondary
894 : open of a table that is in use by other threads already (if the
895 : Maria share exists already).
896 : */
897 : if (!(test_if_locked & HA_OPEN_TMP_TABLE) && opt_maria_use_mmap)
898 : test_if_locked|= HA_OPEN_MMAP;
899 : #endif
900 :
901 55 : if (unlikely(maria_recover_options != HA_RECOVER_NONE))
902 : {
903 : /* user asked to trigger a repair if table was not properly closed */
904 0 : test_if_locked|= HA_OPEN_ABORT_IF_CRASHED;
905 : }
906 :
907 55 : if (!(file= maria_open(name, mode, test_if_locked | HA_OPEN_FROM_SQL_LAYER)))
908 0 : return (my_errno ? my_errno : -1);
909 :
910 55 : if (test_if_locked & (HA_OPEN_IGNORE_IF_LOCKED | HA_OPEN_TMP_TABLE))
911 55 : VOID(maria_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0));
912 :
913 55 : info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
914 55 : if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED))
915 55 : VOID(maria_extra(file, HA_EXTRA_WAIT_LOCK, 0));
916 55 : if ((data_file_type= file->s->data_file_type) != STATIC_RECORD)
917 55 : int_table_flags |= HA_REC_NOT_IN_SEQ;
918 55 : if (!file->s->base.born_transactional)
919 : {
920 : /*
921 : INSERT DELAYED cannot work with transactional tables (because it cannot
922 : stand up to "when client gets ok the data is safe on disk": the record
923 : may not even be inserted). In the future, we could enable it back (as a
924 : client doing INSERT DELAYED knows the specificities; but we then should
925 : make sure to regularly commit in the delayed_insert thread).
926 : */
927 55 : int_table_flags|= HA_CAN_INSERT_DELAYED;
928 : }
929 55 : if (file->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
930 0 : int_table_flags |= HA_HAS_NEW_CHECKSUM;
931 :
932 55 : for (i= 0; i < table->s->keys; i++)
933 : {
934 0 : plugin_ref parser= table->key_info[i].parser;
935 0 : if (table->key_info[i].flags & HA_USES_PARSER)
936 : file->s->keyinfo[i].parser=
937 0 : (struct st_mysql_ftparser *)plugin_decl(parser)->info;
938 0 : table->key_info[i].block_size= file->s->keyinfo[i].block_length;
939 : }
940 55 : my_errno= 0;
941 55 : return my_errno;
942 : }
943 :
944 :
945 53 : int ha_maria::close(void)
946 : {
947 53 : MARIA_HA *tmp= file;
948 53 : file= 0;
949 53 : return maria_close(tmp);
950 : }
951 :
952 :
953 102151 : int ha_maria::write_row(uchar * buf)
954 : {
955 102151 : ha_statistic_increment(&SSV::ha_write_count);
956 :
957 : /* If we have a timestamp column, update it to the current time */
958 102151 : if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
959 0 : table->timestamp_field->set_time();
960 :
961 : /*
962 : If we have an auto_increment column and we are writing a changed row
963 : or a new row, then update the auto_increment value in the record.
964 : */
965 102151 : if (table->next_number_field && buf == table->record[0])
966 : {
967 : int error;
968 0 : if ((error= update_auto_increment()))
969 0 : return error;
970 : }
971 102151 : return maria_write(file, buf);
972 : }
973 :
974 :
975 0 : int ha_maria::check(THD * thd, HA_CHECK_OPT * check_opt)
976 : {
977 0 : if (!file)
978 0 : return HA_ADMIN_INTERNAL_ERROR;
979 : int error;
980 : HA_CHECK param;
981 0 : MARIA_SHARE *share= file->s;
982 0 : const char *old_proc_info= thd_proc_info(thd, "Checking table");
983 :
984 0 : maria_chk_init(¶m);
985 0 : param.thd= thd;
986 0 : param.op_name= "check";
987 0 : param.db_name= table->s->db.str;
988 0 : param.table_name= table->alias;
989 0 : param.testflag= check_opt->flags | T_CHECK | T_SILENT;
990 0 : param.stats_method= (enum_handler_stats_method)THDVAR(thd,stats_method);
991 :
992 0 : if (!(table->db_stat & HA_READ_ONLY))
993 0 : param.testflag |= T_STATISTICS;
994 0 : param.using_global_keycache= 1;
995 :
996 0 : if (!maria_is_crashed(file) &&
997 : (((param.testflag & T_CHECK_ONLY_CHANGED) &&
998 : !(share->state.changed & (STATE_CHANGED | STATE_CRASHED |
999 : STATE_CRASHED_ON_REPAIR)) &&
1000 : share->state.open_count == 0) ||
1001 : ((param.testflag & T_FAST) && (share->state.open_count ==
1002 : (uint) (share->global_changed ? 1 :
1003 : 0)))))
1004 0 : return HA_ADMIN_ALREADY_DONE;
1005 :
1006 0 : maria_chk_init_for_check(¶m, file);
1007 0 : (void) maria_chk_status(¶m, file); // Not fatal
1008 0 : error= maria_chk_size(¶m, file);
1009 0 : if (!error)
1010 0 : error|= maria_chk_del(¶m, file, param.testflag);
1011 0 : if (!error)
1012 0 : error= maria_chk_key(¶m, file);
1013 0 : if (!error)
1014 : {
1015 0 : if ((!(param.testflag & T_QUICK) &&
1016 : ((share->options &
1017 : (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ||
1018 : (param.testflag & (T_EXTEND | T_MEDIUM)))) || maria_is_crashed(file))
1019 : {
1020 0 : ulonglong old_testflag= param.testflag;
1021 0 : param.testflag |= T_MEDIUM;
1022 0 : if (!(error= init_io_cache(¶m.read_cache, file->dfile.file,
1023 : my_default_record_cache_size, READ_CACHE,
1024 : share->pack.header_length, 1, MYF(MY_WME))))
1025 : {
1026 : error= maria_chk_data_link(¶m, file,
1027 0 : test(param.testflag & T_EXTEND));
1028 0 : end_io_cache(&(param.read_cache));
1029 : }
1030 0 : param.testflag= old_testflag;
1031 : }
1032 : }
1033 0 : if (!error)
1034 : {
1035 0 : if ((share->state.changed & (STATE_CHANGED |
1036 : STATE_CRASHED_ON_REPAIR |
1037 : STATE_CRASHED | STATE_NOT_ANALYZED)) ||
1038 : (param.testflag & T_STATISTICS) || maria_is_crashed(file))
1039 : {
1040 0 : file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
1041 0 : pthread_mutex_lock(&share->intern_lock);
1042 : share->state.changed &= ~(STATE_CHANGED | STATE_CRASHED |
1043 0 : STATE_CRASHED_ON_REPAIR);
1044 0 : if (!(table->db_stat & HA_READ_ONLY))
1045 : error= maria_update_state_info(¶m, file,
1046 : UPDATE_TIME | UPDATE_OPEN_COUNT |
1047 0 : UPDATE_STAT);
1048 0 : pthread_mutex_unlock(&share->intern_lock);
1049 : info(HA_STATUS_NO_LOCK | HA_STATUS_TIME | HA_STATUS_VARIABLE |
1050 0 : HA_STATUS_CONST);
1051 : }
1052 : }
1053 0 : else if (!maria_is_crashed(file) && !thd->killed)
1054 : {
1055 0 : maria_mark_crashed(file);
1056 0 : file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
1057 : }
1058 :
1059 0 : thd_proc_info(thd, old_proc_info);
1060 0 : return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
1061 : }
1062 :
1063 :
1064 : /*
1065 : Analyze the key distribution in the table
1066 : As the table may be only locked for read, we have to take into account that
1067 : two threads may do an analyze at the same time!
1068 : */
1069 :
1070 0 : int ha_maria::analyze(THD *thd, HA_CHECK_OPT * check_opt)
1071 : {
1072 0 : int error= 0;
1073 : HA_CHECK param;
1074 0 : MARIA_SHARE *share= file->s;
1075 :
1076 0 : maria_chk_init(¶m);
1077 0 : param.thd= thd;
1078 0 : param.op_name= "analyze";
1079 0 : param.db_name= table->s->db.str;
1080 0 : param.table_name= table->alias;
1081 : param.testflag= (T_FAST | T_CHECK | T_SILENT | T_STATISTICS |
1082 0 : T_DONT_CHECK_CHECKSUM);
1083 0 : param.using_global_keycache= 1;
1084 0 : param.stats_method= (enum_handler_stats_method)THDVAR(thd,stats_method);
1085 :
1086 0 : if (!(share->state.changed & STATE_NOT_ANALYZED))
1087 0 : return HA_ADMIN_ALREADY_DONE;
1088 :
1089 0 : error= maria_chk_key(¶m, file);
1090 0 : if (!error)
1091 : {
1092 0 : pthread_mutex_lock(&share->intern_lock);
1093 0 : error= maria_update_state_info(¶m, file, UPDATE_STAT);
1094 0 : pthread_mutex_unlock(&share->intern_lock);
1095 : }
1096 0 : else if (!maria_is_crashed(file) && !thd->killed)
1097 0 : maria_mark_crashed(file);
1098 0 : return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
1099 : }
1100 :
1101 :
1102 0 : int ha_maria::restore(THD * thd, HA_CHECK_OPT *check_opt)
1103 : {
1104 0 : HA_CHECK_OPT tmp_check_opt;
1105 0 : char *backup_dir= thd->lex->backup_dir;
1106 : char src_path[FN_REFLEN], dst_path[FN_REFLEN];
1107 : char table_name[FN_REFLEN];
1108 : int error;
1109 : const char *errmsg;
1110 0 : DBUG_ENTER("restore");
1111 :
1112 0 : VOID(tablename_to_filename(table->s->table_name.str, table_name,
1113 : sizeof(table_name)));
1114 :
1115 0 : if (fn_format_relative_to_data_home(src_path, table_name, backup_dir,
1116 : MARIA_NAME_DEXT))
1117 0 : DBUG_RETURN(HA_ADMIN_INVALID);
1118 :
1119 0 : strxmov(dst_path, table->s->normalized_path.str, MARIA_NAME_DEXT, NullS);
1120 0 : if (my_copy(src_path, dst_path, MYF(MY_WME)))
1121 : {
1122 0 : error= HA_ADMIN_FAILED;
1123 0 : errmsg= "Failed in my_copy (Error %d)";
1124 0 : goto err;
1125 : }
1126 :
1127 0 : tmp_check_opt.init();
1128 0 : tmp_check_opt.flags |= T_VERY_SILENT | T_CALC_CHECKSUM | T_QUICK;
1129 0 : DBUG_RETURN(repair(thd, &tmp_check_opt));
1130 :
1131 0 : err:
1132 : {
1133 : HA_CHECK param;
1134 0 : maria_chk_init(¶m);
1135 0 : param.thd= thd;
1136 0 : param.op_name= "restore";
1137 0 : param.db_name= table->s->db.str;
1138 0 : param.table_name= table->s->table_name.str;
1139 0 : param.testflag= 0;
1140 0 : _ma_check_print_error(¶m, errmsg, my_errno);
1141 0 : DBUG_RETURN(error);
1142 : }
1143 : }
1144 :
1145 :
1146 0 : int ha_maria::backup(THD * thd, HA_CHECK_OPT *check_opt)
1147 : {
1148 0 : char *backup_dir= thd->lex->backup_dir;
1149 : char src_path[FN_REFLEN], dst_path[FN_REFLEN];
1150 : char table_name[FN_REFLEN];
1151 : int error;
1152 : const char *errmsg;
1153 0 : DBUG_ENTER("ha_maria::backup");
1154 :
1155 0 : VOID(tablename_to_filename(table->s->table_name.str, table_name,
1156 : sizeof(table_name)));
1157 :
1158 0 : if (fn_format_relative_to_data_home(dst_path, table_name, backup_dir,
1159 : reg_ext))
1160 : {
1161 0 : errmsg= "Failed in fn_format() for .frm file (errno: %d)";
1162 0 : error= HA_ADMIN_INVALID;
1163 0 : goto err;
1164 : }
1165 :
1166 0 : strxmov(src_path, table->s->normalized_path.str, reg_ext, NullS);
1167 0 : if (my_copy(src_path, dst_path,
1168 : MYF(MY_WME | MY_HOLD_ORIGINAL_MODES | MY_DONT_OVERWRITE_FILE)))
1169 : {
1170 0 : error= HA_ADMIN_FAILED;
1171 0 : errmsg= "Failed copying .frm file (errno: %d)";
1172 0 : goto err;
1173 : }
1174 :
1175 : /* Change extension */
1176 0 : if (fn_format_relative_to_data_home(dst_path, table_name, backup_dir,
1177 : MARIA_NAME_DEXT))
1178 : {
1179 0 : errmsg= "Failed in fn_format() for .MYD file (errno: %d)";
1180 0 : error= HA_ADMIN_INVALID;
1181 0 : goto err;
1182 : }
1183 :
1184 0 : strxmov(src_path, table->s->normalized_path.str, MARIA_NAME_DEXT, NullS);
1185 0 : if (_ma_flush_table_files(file, MARIA_FLUSH_DATA, FLUSH_FORCE_WRITE,
1186 : FLUSH_KEEP))
1187 : {
1188 0 : error= HA_ADMIN_FAILED;
1189 0 : errmsg= "Failed in flush (Error %d)";
1190 0 : goto err;
1191 : }
1192 0 : if (my_copy(src_path, dst_path,
1193 : MYF(MY_WME | MY_HOLD_ORIGINAL_MODES | MY_DONT_OVERWRITE_FILE)))
1194 : {
1195 0 : errmsg= "Failed copying .MYD file (errno: %d)";
1196 0 : error= HA_ADMIN_FAILED;
1197 0 : goto err;
1198 : }
1199 0 : DBUG_RETURN(HA_ADMIN_OK);
1200 :
1201 0 : err:
1202 : {
1203 : HA_CHECK param;
1204 0 : maria_chk_init(¶m);
1205 0 : param.thd= thd;
1206 0 : param.op_name= "backup";
1207 0 : param.db_name= table->s->db.str;
1208 0 : param.table_name= table->s->table_name.str;
1209 0 : param.testflag= 0;
1210 0 : _ma_check_print_error(¶m, errmsg, my_errno);
1211 0 : DBUG_RETURN(error);
1212 : }
1213 : }
1214 :
1215 :
1216 0 : int ha_maria::repair(THD * thd, HA_CHECK_OPT *check_opt)
1217 : {
1218 : int error;
1219 : HA_CHECK param;
1220 : ha_rows start_records;
1221 :
1222 0 : if (!file)
1223 0 : return HA_ADMIN_INTERNAL_ERROR;
1224 :
1225 0 : maria_chk_init(¶m);
1226 0 : param.thd= thd;
1227 0 : param.op_name= "repair";
1228 : param.testflag= ((check_opt->flags & ~(T_EXTEND)) |
1229 : T_SILENT | T_FORCE_CREATE | T_CALC_CHECKSUM |
1230 0 : (check_opt->flags & T_EXTEND ? T_REP : T_REP_BY_SORT));
1231 0 : param.sort_buffer_length= THDVAR(thd, sort_buffer_size);
1232 0 : start_records= file->state->records;
1233 0 : while ((error= repair(thd, ¶m, 0)) && param.retry_repair)
1234 : {
1235 0 : param.retry_repair= 0;
1236 0 : if (test_all_bits(param.testflag,
1237 : (uint) (T_RETRY_WITHOUT_QUICK | T_QUICK)))
1238 : {
1239 0 : param.testflag&= ~(T_RETRY_WITHOUT_QUICK | T_QUICK);
1240 : /* Ensure we don't loose any rows when retrying without quick */
1241 0 : param.testflag|= T_SAFE_REPAIR;
1242 0 : if (thd->vio_ok())
1243 0 : _ma_check_print_info(¶m, "Retrying repair without quick");
1244 : else
1245 : sql_print_information("Retrying repair of: '%s' without quick",
1246 0 : table->s->path.str);
1247 : continue;
1248 : }
1249 0 : param.testflag &= ~T_QUICK;
1250 0 : if ((param.testflag & T_REP_BY_SORT))
1251 : {
1252 0 : param.testflag= (param.testflag & ~T_REP_BY_SORT) | T_REP;
1253 : sql_print_information("Retrying repair of: '%s' with keycache",
1254 0 : table->s->path.str);
1255 : continue;
1256 : }
1257 : break;
1258 : }
1259 0 : if (!error && start_records != file->state->records &&
1260 : !(check_opt->flags & T_VERY_SILENT))
1261 : {
1262 : char llbuff[22], llbuff2[22];
1263 : sql_print_information("Found %s of %s rows when repairing '%s'",
1264 : llstr(file->state->records, llbuff),
1265 : llstr(start_records, llbuff2),
1266 0 : table->s->path.str);
1267 : }
1268 0 : return error;
1269 : }
1270 :
1271 0 : int ha_maria::zerofill(THD * thd, HA_CHECK_OPT *check_opt)
1272 : {
1273 : int error;
1274 : HA_CHECK param;
1275 0 : MARIA_SHARE *share= file->s;
1276 :
1277 0 : if (!file)
1278 0 : return HA_ADMIN_INTERNAL_ERROR;
1279 :
1280 0 : maria_chk_init(¶m);
1281 0 : param.thd= thd;
1282 0 : param.op_name= "zerofill";
1283 0 : param.testflag= check_opt->flags | T_SILENT | T_ZEROFILL;
1284 0 : param.sort_buffer_length= THDVAR(thd, sort_buffer_size);
1285 0 : error=maria_zerofill(¶m, file, share->open_file_name.str);
1286 :
1287 0 : if (!error)
1288 : {
1289 0 : pthread_mutex_lock(&share->intern_lock);
1290 0 : maria_update_state_info(¶m, file, UPDATE_TIME | UPDATE_OPEN_COUNT);
1291 0 : pthread_mutex_unlock(&share->intern_lock);
1292 : }
1293 0 : return error;
1294 : }
1295 :
1296 0 : int ha_maria::optimize(THD * thd, HA_CHECK_OPT *check_opt)
1297 : {
1298 : int error;
1299 : HA_CHECK param;
1300 0 : if (!file)
1301 0 : return HA_ADMIN_INTERNAL_ERROR;
1302 :
1303 0 : maria_chk_init(¶m);
1304 0 : param.thd= thd;
1305 0 : param.op_name= "optimize";
1306 : param.testflag= (check_opt->flags | T_SILENT | T_FORCE_CREATE |
1307 0 : T_REP_BY_SORT | T_STATISTICS | T_SORT_INDEX);
1308 0 : param.sort_buffer_length= THDVAR(thd, sort_buffer_size);
1309 0 : if ((error= repair(thd, ¶m, 1)) && param.retry_repair)
1310 : {
1311 : sql_print_warning("Warning: Optimize table got errno %d on %s.%s, retrying",
1312 0 : my_errno, param.db_name, param.table_name);
1313 0 : param.testflag &= ~T_REP_BY_SORT;
1314 0 : error= repair(thd, ¶m, 1);
1315 : }
1316 0 : return error;
1317 : }
1318 :
1319 :
1320 0 : int ha_maria::repair(THD *thd, HA_CHECK *param, bool do_optimize)
1321 : {
1322 0 : int error= 0;
1323 0 : ulonglong local_testflag= param->testflag;
1324 0 : bool optimize_done= !do_optimize, statistics_done= 0;
1325 0 : const char *old_proc_info= thd->proc_info;
1326 : char fixed_name[FN_REFLEN];
1327 0 : MARIA_SHARE *share= file->s;
1328 0 : ha_rows rows= file->state->records;
1329 0 : DBUG_ENTER("ha_maria::repair");
1330 :
1331 : /*
1332 : Normally this method is entered with a properly opened table. If the
1333 : repair fails, it can be repeated with more elaborate options. Under
1334 : special circumstances it can happen that a repair fails so that it
1335 : closed the data file and cannot re-open it. In this case file->dfile
1336 : is set to -1. We must not try another repair without an open data
1337 : file. (Bug #25289)
1338 : */
1339 0 : if (file->dfile.file == -1)
1340 : {
1341 : sql_print_information("Retrying repair of: '%s' failed. "
1342 : "Please try REPAIR EXTENDED or maria_chk",
1343 0 : table->s->path.str);
1344 0 : DBUG_RETURN(HA_ADMIN_FAILED);
1345 : }
1346 :
1347 : /*
1348 : If transactions was not enabled for a transactional table then
1349 : file->s->status is not up to date. This is needed for repair_by_sort
1350 : to work
1351 : */
1352 0 : if (share->base.born_transactional && !share->now_transactional)
1353 0 : _ma_copy_nontrans_state_information(file);
1354 :
1355 0 : param->db_name= table->s->db.str;
1356 0 : param->table_name= table->alias;
1357 0 : param->tmpfile_createflag= O_RDWR | O_TRUNC;
1358 0 : param->using_global_keycache= 1;
1359 0 : param->thd= thd;
1360 0 : param->tmpdir= &mysql_tmpdir_list;
1361 0 : param->out_flag= 0;
1362 0 : strmov(fixed_name, share->open_file_name.str);
1363 :
1364 : // Don't lock tables if we have used LOCK TABLE
1365 0 : if (!thd->locked_tables &&
1366 : maria_lock_database(file, table->s->tmp_table ? F_EXTRA_LCK : F_WRLCK))
1367 : {
1368 0 : _ma_check_print_error(param, ER(ER_CANT_LOCK), my_errno);
1369 0 : DBUG_RETURN(HA_ADMIN_FAILED);
1370 : }
1371 :
1372 0 : if (!do_optimize ||
1373 : (((share->data_file_type == BLOCK_RECORD) ?
1374 : (share->state.changed & STATE_NOT_OPTIMIZED_ROWS) :
1375 : (file->state->del ||
1376 : share->state.split != file->state->records)) &&
1377 : (!(param->testflag & T_QUICK) ||
1378 : (share->state.changed & (STATE_NOT_OPTIMIZED_KEYS |
1379 : STATE_NOT_OPTIMIZED_ROWS)))))
1380 : {
1381 : ulonglong key_map= ((local_testflag & T_CREATE_MISSING_KEYS) ?
1382 : maria_get_mask_all_keys_active(share->base.keys) :
1383 0 : share->state.key_map);
1384 0 : ulonglong save_testflag= param->testflag;
1385 0 : if (maria_test_if_sort_rep(file, file->state->records, key_map, 0) &&
1386 : (local_testflag & T_REP_BY_SORT))
1387 : {
1388 0 : local_testflag |= T_STATISTICS;
1389 0 : param->testflag |= T_STATISTICS; // We get this for free
1390 0 : statistics_done= 1;
1391 : /* TODO: Remove BLOCK_RECORD test when parallel works with blocks */
1392 0 : if (THDVAR(thd,repair_threads) > 1 &&
1393 : share->data_file_type != BLOCK_RECORD)
1394 : {
1395 : char buf[40];
1396 : /* TODO: respect maria_repair_threads variable */
1397 0 : my_snprintf(buf, 40, "Repair with %d threads", my_count_bits(key_map));
1398 0 : thd_proc_info(thd, buf);
1399 0 : param->testflag|= T_REP_PARALLEL;
1400 : error= maria_repair_parallel(param, file, fixed_name,
1401 0 : test(param->testflag & T_QUICK));
1402 : /* to reset proc_info, as it was pointing to local buffer */
1403 0 : thd_proc_info(thd, "Repair done");
1404 : }
1405 : else
1406 : {
1407 0 : thd_proc_info(thd, "Repair by sorting");
1408 0 : param->testflag|= T_REP_BY_SORT;
1409 : error= maria_repair_by_sort(param, file, fixed_name,
1410 0 : test(param->testflag & T_QUICK));
1411 : }
1412 : }
1413 : else
1414 : {
1415 0 : thd_proc_info(thd, "Repair with keycache");
1416 0 : param->testflag &= ~(T_REP_BY_SORT | T_REP_PARALLEL);
1417 : error= maria_repair(param, file, fixed_name,
1418 0 : test(param->testflag & T_QUICK));
1419 : }
1420 0 : param->testflag= save_testflag | (param->testflag & T_RETRY_WITHOUT_QUICK);
1421 0 : optimize_done= 1;
1422 : }
1423 0 : if (!error)
1424 : {
1425 0 : if ((local_testflag & T_SORT_INDEX) &&
1426 : (share->state.changed & STATE_NOT_SORTED_PAGES))
1427 : {
1428 0 : optimize_done= 1;
1429 0 : thd_proc_info(thd, "Sorting index");
1430 0 : error= maria_sort_index(param, file, fixed_name);
1431 : }
1432 0 : if (!statistics_done && (local_testflag & T_STATISTICS))
1433 : {
1434 0 : if (share->state.changed & STATE_NOT_ANALYZED)
1435 : {
1436 0 : optimize_done= 1;
1437 0 : thd_proc_info(thd, "Analyzing");
1438 0 : error= maria_chk_key(param, file);
1439 : }
1440 : else
1441 0 : local_testflag &= ~T_STATISTICS; // Don't update statistics
1442 : }
1443 : }
1444 0 : thd_proc_info(thd, "Saving state");
1445 0 : pthread_mutex_lock(&share->intern_lock);
1446 0 : if (!error)
1447 : {
1448 0 : if ((share->state.changed & STATE_CHANGED) || maria_is_crashed(file))
1449 : {
1450 : share->state.changed &= ~(STATE_CHANGED | STATE_CRASHED |
1451 0 : STATE_CRASHED_ON_REPAIR);
1452 0 : file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
1453 : }
1454 : /*
1455 : repair updates share->state.state. Ensure that file->state is up to date
1456 : */
1457 0 : if (file->state != &share->state.state)
1458 0 : *file->state= share->state.state;
1459 0 : if (share->base.auto_key)
1460 0 : _ma_update_auto_increment_key(param, file, 1);
1461 0 : if (optimize_done)
1462 : error= maria_update_state_info(param, file,
1463 : UPDATE_TIME | UPDATE_OPEN_COUNT |
1464 : (local_testflag &
1465 0 : T_STATISTICS ? UPDATE_STAT : 0));
1466 : info(HA_STATUS_NO_LOCK | HA_STATUS_TIME | HA_STATUS_VARIABLE |
1467 0 : HA_STATUS_CONST, 0);
1468 0 : if (rows != file->state->records && !(param->testflag & T_VERY_SILENT))
1469 : {
1470 : char llbuff[22], llbuff2[22];
1471 : _ma_check_print_warning(param, "Number of rows changed from %s to %s",
1472 : llstr(rows, llbuff),
1473 0 : llstr(file->state->records, llbuff2));
1474 : /* Abort if warning was converted to error */
1475 0 : if (current_thd->is_error())
1476 0 : error= 1;
1477 : }
1478 : }
1479 : else
1480 : {
1481 0 : maria_mark_crashed_on_repair(file);
1482 0 : file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
1483 0 : maria_update_state_info(param, file, 0);
1484 : }
1485 0 : pthread_mutex_unlock(&share->intern_lock);
1486 0 : thd_proc_info(thd, old_proc_info);
1487 0 : if (!thd->locked_tables)
1488 0 : maria_lock_database(file, F_UNLCK);
1489 : error= error ? HA_ADMIN_FAILED :
1490 : (optimize_done ?
1491 : (write_log_record_for_repair(param, file) ? HA_ADMIN_FAILED :
1492 0 : HA_ADMIN_OK) : HA_ADMIN_ALREADY_DONE);
1493 0 : DBUG_RETURN(error);
1494 : }
1495 :
1496 :
1497 : /*
1498 : Assign table indexes to a specific key cache.
1499 : */
1500 :
1501 0 : int ha_maria::assign_to_keycache(THD * thd, HA_CHECK_OPT *check_opt)
1502 : {
1503 : #if 0 && NOT_IMPLEMENTED
1504 : PAGECACHE *new_pagecache= check_opt->pagecache;
1505 : const char *errmsg= 0;
1506 : int error= HA_ADMIN_OK;
1507 : ulonglong map;
1508 : TABLE_LIST *table_list= table->pos_in_table_list;
1509 : DBUG_ENTER("ha_maria::assign_to_keycache");
1510 :
1511 :
1512 : table->keys_in_use_for_query.clear_all();
1513 :
1514 : if (table_list->process_index_hints(table))
1515 : DBUG_RETURN(HA_ADMIN_FAILED);
1516 : map= ~(ulonglong) 0;
1517 : if (!table->keys_in_use_for_query.is_clear_all())
1518 : /* use all keys if there's no list specified by the user through hints */
1519 : map= table->keys_in_use_for_query.to_ulonglong();
1520 :
1521 : if ((error= maria_assign_to_pagecache(file, map, new_pagecache)))
1522 : {
1523 : char buf[STRING_BUFFER_USUAL_SIZE];
1524 : my_snprintf(buf, sizeof(buf),
1525 : "Failed to flush to index file (errno: %d)", error);
1526 : errmsg= buf;
1527 : error= HA_ADMIN_CORRUPT;
1528 : }
1529 :
1530 : if (error != HA_ADMIN_OK)
1531 : {
1532 : /* Send error to user */
1533 : HA_CHECK param;
1534 : maria_chk_init(¶m);
1535 : param.thd= thd;
1536 : param.op_name= "assign_to_keycache";
1537 : param.db_name= table->s->db.str;
1538 : param.table_name= table->s->table_name.str;
1539 : param.testflag= 0;
1540 : _ma_check_print_error(¶m, errmsg);
1541 : }
1542 : DBUG_RETURN(error);
1543 : #else
1544 0 : return HA_ADMIN_NOT_IMPLEMENTED;
1545 : #endif
1546 : }
1547 :
1548 :
1549 : /*
1550 : Preload pages of the index file for a table into the key cache.
1551 : */
1552 :
1553 0 : int ha_maria::preload_keys(THD * thd, HA_CHECK_OPT *check_opt)
1554 : {
1555 : ulonglong map;
1556 0 : TABLE_LIST *table_list= table->pos_in_table_list;
1557 :
1558 0 : DBUG_ENTER("ha_maria::preload_keys");
1559 :
1560 0 : table->keys_in_use_for_query.clear_all();
1561 :
1562 0 : if (table_list->process_index_hints(table))
1563 0 : DBUG_RETURN(HA_ADMIN_FAILED);
1564 :
1565 0 : map= ~(ulonglong) 0;
1566 : /* Check validity of the index references */
1567 0 : if (!table->keys_in_use_for_query.is_clear_all())
1568 : /* use all keys if there's no list specified by the user through hints */
1569 0 : map= table->keys_in_use_for_query.to_ulonglong();
1570 :
1571 : maria_extra(file, HA_EXTRA_PRELOAD_BUFFER_SIZE,
1572 0 : (void*) &thd->variables.preload_buff_size);
1573 :
1574 : int error;
1575 :
1576 0 : if ((error= maria_preload(file, map, table_list->ignore_leaves)))
1577 : {
1578 : char buf[ERRMSGSIZE+20];
1579 : const char *errmsg;
1580 :
1581 0 : switch (error) {
1582 : case HA_ERR_NON_UNIQUE_BLOCK_SIZE:
1583 0 : errmsg= "Indexes use different block sizes";
1584 0 : break;
1585 : case HA_ERR_OUT_OF_MEM:
1586 0 : errmsg= "Failed to allocate buffer";
1587 0 : break;
1588 : default:
1589 : my_snprintf(buf, ERRMSGSIZE,
1590 0 : "Failed to read from index file (errno: %d)", my_errno);
1591 0 : errmsg= buf;
1592 : }
1593 :
1594 : HA_CHECK param;
1595 0 : maria_chk_init(¶m);
1596 0 : param.thd= thd;
1597 0 : param.op_name= "preload_keys";
1598 0 : param.db_name= table->s->db.str;
1599 0 : param.table_name= table->s->table_name.str;
1600 0 : param.testflag= 0;
1601 0 : _ma_check_print_error(¶m, errmsg);
1602 0 : DBUG_RETURN(HA_ADMIN_FAILED);
1603 : }
1604 0 : DBUG_RETURN(HA_ADMIN_OK);
1605 : }
1606 :
1607 :
1608 : /*
1609 : Disable indexes, making it persistent if requested.
1610 :
1611 : SYNOPSIS
1612 : disable_indexes()
1613 : mode mode of operation:
1614 : HA_KEY_SWITCH_NONUNIQ disable all non-unique keys
1615 : HA_KEY_SWITCH_ALL disable all keys
1616 : HA_KEY_SWITCH_NONUNIQ_SAVE dis. non-uni. and make persistent
1617 : HA_KEY_SWITCH_ALL_SAVE dis. all keys and make persistent
1618 :
1619 : IMPLEMENTATION
1620 : HA_KEY_SWITCH_NONUNIQ is not implemented.
1621 : HA_KEY_SWITCH_ALL_SAVE is not implemented.
1622 :
1623 : RETURN
1624 : 0 ok
1625 : HA_ERR_WRONG_COMMAND mode not implemented.
1626 : */
1627 :
1628 0 : int ha_maria::disable_indexes(uint mode)
1629 : {
1630 : int error;
1631 :
1632 0 : if (mode == HA_KEY_SWITCH_ALL)
1633 : {
1634 : /* call a storage engine function to switch the key map */
1635 0 : error= maria_disable_indexes(file);
1636 : }
1637 0 : else if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE)
1638 : {
1639 0 : maria_extra(file, HA_EXTRA_NO_KEYS, 0);
1640 0 : info(HA_STATUS_CONST); // Read new key info
1641 0 : error= 0;
1642 : }
1643 : else
1644 : {
1645 : /* mode not implemented */
1646 0 : error= HA_ERR_WRONG_COMMAND;
1647 : }
1648 0 : return error;
1649 : }
1650 :
1651 :
1652 : /*
1653 : Enable indexes, making it persistent if requested.
1654 :
1655 : SYNOPSIS
1656 : enable_indexes()
1657 : mode mode of operation:
1658 : HA_KEY_SWITCH_NONUNIQ enable all non-unique keys
1659 : HA_KEY_SWITCH_ALL enable all keys
1660 : HA_KEY_SWITCH_NONUNIQ_SAVE en. non-uni. and make persistent
1661 : HA_KEY_SWITCH_ALL_SAVE en. all keys and make persistent
1662 :
1663 : DESCRIPTION
1664 : Enable indexes, which might have been disabled by disable_index() before.
1665 : The modes without _SAVE work only if both data and indexes are empty,
1666 : since the MARIA repair would enable them persistently.
1667 : To be sure in these cases, call handler::delete_all_rows() before.
1668 :
1669 : IMPLEMENTATION
1670 : HA_KEY_SWITCH_NONUNIQ is not implemented.
1671 : HA_KEY_SWITCH_ALL_SAVE is not implemented.
1672 :
1673 : RETURN
1674 : 0 ok
1675 : !=0 Error, among others:
1676 : HA_ERR_CRASHED data or index is non-empty. Delete all rows and retry.
1677 : HA_ERR_WRONG_COMMAND mode not implemented.
1678 : */
1679 :
1680 0 : int ha_maria::enable_indexes(uint mode)
1681 : {
1682 : int error;
1683 0 : DBUG_PRINT("info", ("ha_maria::enable_indexes mode: %d", mode));
1684 0 : if (maria_is_all_keys_active(file->s->state.key_map, file->s->base.keys))
1685 : {
1686 : /* All indexes are enabled already. */
1687 0 : return 0;
1688 : }
1689 :
1690 0 : if (mode == HA_KEY_SWITCH_ALL)
1691 : {
1692 0 : error= maria_enable_indexes(file);
1693 : /*
1694 : Do not try to repair on error,
1695 : as this could make the enabled state persistent,
1696 : but mode==HA_KEY_SWITCH_ALL forbids it.
1697 : */
1698 : }
1699 0 : else if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE)
1700 : {
1701 0 : THD *thd= current_thd;
1702 : HA_CHECK param;
1703 0 : const char *save_proc_info= thd_proc_info(thd, "Creating index");
1704 0 : maria_chk_init(¶m);
1705 0 : param.op_name= "recreating_index";
1706 : param.testflag= (T_SILENT | T_REP_BY_SORT | T_QUICK |
1707 0 : T_CREATE_MISSING_KEYS | T_SAFE_REPAIR);
1708 0 : if (bulk_insert_single_undo == BULK_INSERT_SINGLE_UNDO_AND_NO_REPAIR)
1709 : {
1710 0 : bulk_insert_single_undo= BULK_INSERT_SINGLE_UNDO_AND_REPAIR;
1711 : /*
1712 : Don't bump create_rename_lsn, because UNDO_BULK_INSERT
1713 : should not be skipped in case of crash during repair.
1714 : */
1715 0 : param.testflag|= T_NO_CREATE_RENAME_LSN;
1716 : }
1717 0 : param.myf_rw &= ~MY_WAIT_IF_FULL;
1718 0 : param.sort_buffer_length= THDVAR(thd,sort_buffer_size);
1719 0 : param.stats_method= (enum_handler_stats_method)THDVAR(thd,stats_method);
1720 0 : param.tmpdir= &mysql_tmpdir_list;
1721 0 : if ((error= (repair(thd, ¶m, 0) != HA_ADMIN_OK)) && param.retry_repair)
1722 : {
1723 : sql_print_warning("Warning: Enabling keys got errno %d on %s.%s, "
1724 : "retrying",
1725 0 : my_errno, param.db_name, param.table_name);
1726 : /* This should never fail normally */
1727 0 : DBUG_ASSERT(0);
1728 : /* Repairing by sort failed. Now try standard repair method. */
1729 : param.testflag &= ~T_REP_BY_SORT;
1730 : error= (repair(thd, ¶m, 0) != HA_ADMIN_OK);
1731 : /*
1732 : If the standard repair succeeded, clear all error messages which
1733 : might have been set by the first repair. They can still be seen
1734 : with SHOW WARNINGS then.
1735 : */
1736 : if (!error)
1737 : thd->clear_error();
1738 : }
1739 0 : info(HA_STATUS_CONST);
1740 0 : thd_proc_info(thd, save_proc_info);
1741 : }
1742 : else
1743 : {
1744 : /* mode not implemented */
1745 0 : error= HA_ERR_WRONG_COMMAND;
1746 : }
1747 0 : DBUG_EXECUTE_IF("maria_flush_whole_log",
1748 : {
1749 : DBUG_PRINT("maria_flush_whole_log", ("now"));
1750 : translog_flush(translog_get_horizon());
1751 : });
1752 0 : DBUG_EXECUTE_IF("maria_crash_enable_index",
1753 : {
1754 : DBUG_PRINT("maria_crash_enable_index", ("now"));
1755 : DBUG_ABORT();
1756 : });
1757 0 : return error;
1758 : }
1759 :
1760 :
1761 : /*
1762 : Test if indexes are disabled.
1763 :
1764 :
1765 : SYNOPSIS
1766 : indexes_are_disabled()
1767 : no parameters
1768 :
1769 :
1770 : RETURN
1771 : 0 indexes are not disabled
1772 : 1 all indexes are disabled
1773 : [2 non-unique indexes are disabled - NOT YET IMPLEMENTED]
1774 : */
1775 :
1776 0 : int ha_maria::indexes_are_disabled(void)
1777 : {
1778 0 : return maria_indexes_are_disabled(file);
1779 : }
1780 :
1781 :
1782 : /*
1783 : prepare for a many-rows insert operation
1784 : e.g. - disable indexes (if they can be recreated fast) or
1785 : activate special bulk-insert optimizations
1786 :
1787 : SYNOPSIS
1788 : start_bulk_insert(rows)
1789 : rows Rows to be inserted
1790 : 0 if we don't know
1791 :
1792 : NOTICE
1793 : Do not forget to call end_bulk_insert() later!
1794 : */
1795 :
1796 0 : void ha_maria::start_bulk_insert(ha_rows rows)
1797 : {
1798 0 : DBUG_ENTER("ha_maria::start_bulk_insert");
1799 0 : THD *thd= current_thd;
1800 0 : ulong size= min(thd->variables.read_buff_size,
1801 : (ulong) (table->s->avg_row_length * rows));
1802 0 : MARIA_SHARE *share= file->s;
1803 0 : DBUG_PRINT("info", ("start_bulk_insert: rows %lu size %lu",
1804 : (ulong) rows, size));
1805 :
1806 : /* don't enable row cache if too few rows */
1807 0 : if (!rows || (rows > MARIA_MIN_ROWS_TO_USE_WRITE_CACHE))
1808 0 : maria_extra(file, HA_EXTRA_WRITE_CACHE, (void*) &size);
1809 :
1810 0 : can_enable_indexes= (maria_is_all_keys_active(share->state.key_map,
1811 : share->base.keys));
1812 0 : bulk_insert_single_undo= BULK_INSERT_NONE;
1813 :
1814 0 : if (!(specialflag & SPECIAL_SAFE_MODE))
1815 : {
1816 : /*
1817 : Only disable old index if the table was empty and we are inserting
1818 : a lot of rows.
1819 : We should not do this for only a few rows as this is slower and
1820 : we don't want to update the key statistics based of only a few rows.
1821 : Index file rebuild requires an exclusive lock, so if versioning is on
1822 : don't do it (see how ha_maria::store_lock() tries to predict repair).
1823 : We can repair index only if we have an exclusive (TL_WRITE) lock. To
1824 : see if table is empty, we shouldn't rely on the old records' count from
1825 : our transaction's start (if that old count is 0 but now there are
1826 : records in the table, we would wrongly destroy them).
1827 : So we need to look at share->state.state.records.
1828 : As a safety net for now, we don't remove the test of
1829 : file->state->records, because there is uncertainty on what will happen
1830 : during repair if the two states disagree.
1831 : */
1832 0 : if ((file->state->records == 0) &&
1833 : (share->state.state.records == 0) && can_enable_indexes &&
1834 : (!rows || rows >= MARIA_MIN_ROWS_TO_DISABLE_INDEXES) &&
1835 : (file->lock.type == TL_WRITE))
1836 : {
1837 : /**
1838 : @todo for a single-row INSERT SELECT, we will go into repair, which
1839 : is more costly (flushes, syncs) than a row write.
1840 : */
1841 0 : maria_disable_non_unique_index(file, rows);
1842 0 : if (share->now_transactional)
1843 : {
1844 0 : bulk_insert_single_undo= BULK_INSERT_SINGLE_UNDO_AND_NO_REPAIR;
1845 0 : write_log_record_for_bulk_insert(file);
1846 0 : _ma_tmp_disable_logging_for_table(file, TRUE);
1847 : /*
1848 : Pages currently in the page cache have type PAGECACHE_LSN_PAGE, we
1849 : are not allowed to overwrite them with PAGECACHE_PLAIN_PAGE, so
1850 : throw them away. It is not losing data, because we just wrote and
1851 : forced an UNDO which will for sure empty the table if we crash. The
1852 : upcoming unique-key insertions however need a proper index, so we
1853 : cannot leave the corrupted on-disk index file, thus we truncate it.
1854 : */
1855 0 : maria_delete_all_rows(file);
1856 : }
1857 : }
1858 0 : else if (!file->bulk_insert &&
1859 : (!rows || rows >= MARIA_MIN_ROWS_TO_USE_BULK_INSERT))
1860 : {
1861 0 : maria_init_bulk_insert(file, thd->variables.bulk_insert_buff_size, rows);
1862 : }
1863 : }
1864 0 : DBUG_VOID_RETURN;
1865 : }
1866 :
1867 :
1868 : /*
1869 : end special bulk-insert optimizations,
1870 : which have been activated by start_bulk_insert().
1871 :
1872 : SYNOPSIS
1873 : end_bulk_insert()
1874 : no arguments
1875 :
1876 : RETURN
1877 : 0 OK
1878 : != 0 Error
1879 : */
1880 :
1881 0 : int ha_maria::end_bulk_insert(bool table_will_be_deleted)
1882 : {
1883 : int err;
1884 0 : DBUG_ENTER("ha_maria::end_bulk_insert");
1885 0 : maria_end_bulk_insert(file, table_will_be_deleted);
1886 0 : if ((err= maria_extra(file, HA_EXTRA_NO_CACHE, 0)))
1887 0 : goto end;
1888 0 : if (can_enable_indexes && !table_will_be_deleted)
1889 0 : err= enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
1890 0 : end:
1891 0 : if (bulk_insert_single_undo != BULK_INSERT_NONE)
1892 : {
1893 0 : DBUG_ASSERT(can_enable_indexes);
1894 : /*
1895 : Table was transactional just before start_bulk_insert().
1896 : No need to flush pages if we did a repair (which already flushed).
1897 : */
1898 : err|=
1899 : _ma_reenable_logging_for_table(file,
1900 : bulk_insert_single_undo ==
1901 0 : BULK_INSERT_SINGLE_UNDO_AND_NO_REPAIR);
1902 : }
1903 0 : DBUG_RETURN(err);
1904 : }
1905 :
1906 :
1907 0 : bool ha_maria::check_and_repair(THD *thd)
1908 : {
1909 : int error, crashed;
1910 : char *old_query;
1911 : uint old_query_length;
1912 0 : HA_CHECK_OPT check_opt;
1913 0 : DBUG_ENTER("ha_maria::check_and_repair");
1914 :
1915 0 : check_opt.init();
1916 :
1917 0 : if (file->s->state.changed & STATE_MOVED)
1918 : {
1919 0 : sql_print_information("Zerofilling table: '%s'", table->s->path.str);
1920 0 : if (!(error= zerofill(thd, &check_opt)))
1921 0 : DBUG_RETURN(0);
1922 : }
1923 : else
1924 0 : error= 1;
1925 :
1926 : /*
1927 : if we got this far - the table is crashed.
1928 : but don't auto-repair if maria_recover_options is not set
1929 : */
1930 0 : if (!maria_recover_options)
1931 0 : DBUG_RETURN(error);
1932 :
1933 0 : error= 0;
1934 0 : check_opt.flags= T_MEDIUM | T_AUTO_REPAIR;
1935 : // Don't use quick if deleted rows
1936 0 : if (!file->state->del && (maria_recover_options & HA_RECOVER_QUICK))
1937 0 : check_opt.flags |= T_QUICK;
1938 :
1939 0 : old_query= thd->query;
1940 0 : old_query_length= thd->query_length;
1941 0 : pthread_mutex_lock(&LOCK_thread_count);
1942 0 : thd->query= table->s->table_name.str;
1943 0 : thd->query_length= table->s->table_name.length;
1944 0 : pthread_mutex_unlock(&LOCK_thread_count);
1945 :
1946 0 : if (!(crashed= maria_is_crashed(file)))
1947 : {
1948 0 : sql_print_warning("Checking table: '%s'", table->s->path.str);
1949 0 : crashed= check(thd, &check_opt);
1950 : }
1951 :
1952 0 : if (crashed)
1953 : {
1954 0 : sql_print_warning("Recovering table: '%s'", table->s->path.str);
1955 : check_opt.flags=
1956 : ((maria_recover_options & HA_RECOVER_BACKUP ? T_BACKUP_DATA : 0) |
1957 : (maria_recover_options & HA_RECOVER_FORCE ? 0 : T_SAFE_REPAIR) |
1958 0 : T_AUTO_REPAIR);
1959 0 : if (repair(thd, &check_opt))
1960 0 : error= 1;
1961 : }
1962 0 : pthread_mutex_lock(&LOCK_thread_count);
1963 0 : thd->query= old_query;
1964 0 : thd->query_length= old_query_length;
1965 0 : pthread_mutex_unlock(&LOCK_thread_count);
1966 0 : DBUG_RETURN(error);
1967 : }
1968 :
1969 :
1970 0 : bool ha_maria::is_crashed() const
1971 : {
1972 : return (file->s->state.changed & (STATE_CRASHED | STATE_MOVED) ||
1973 0 : (my_disable_locking && file->s->state.open_count));
1974 : }
1975 :
1976 : #define CHECK_UNTIL_WE_FULLY_IMPLEMENTED_VERSIONING(msg) \
1977 : do { \
1978 : if (file->lock.type == TL_WRITE_CONCURRENT_INSERT) \
1979 : { \
1980 : my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), msg); \
1981 : return 1; \
1982 : } \
1983 : } while(0)
1984 :
1985 0 : int ha_maria::update_row(const uchar * old_data, uchar * new_data)
1986 : {
1987 0 : CHECK_UNTIL_WE_FULLY_IMPLEMENTED_VERSIONING("UPDATE in WRITE CONCURRENT");
1988 0 : ha_statistic_increment(&SSV::ha_update_count);
1989 0 : if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
1990 0 : table->timestamp_field->set_time();
1991 0 : return maria_update(file, old_data, new_data);
1992 : }
1993 :
1994 :
1995 0 : int ha_maria::delete_row(const uchar * buf)
1996 : {
1997 0 : CHECK_UNTIL_WE_FULLY_IMPLEMENTED_VERSIONING("DELETE in WRITE CONCURRENT");
1998 0 : ha_statistic_increment(&SSV::ha_delete_count);
1999 0 : return maria_delete(file, buf);
2000 : }
2001 :
2002 :
2003 : int ha_maria::index_read_map(uchar * buf, const uchar * key,
2004 : key_part_map keypart_map,
2005 0 : enum ha_rkey_function find_flag)
2006 : {
2007 0 : DBUG_ASSERT(inited == INDEX);
2008 0 : ha_statistic_increment(&SSV::ha_read_key_count);
2009 0 : int error= maria_rkey(file, buf, active_index, key, keypart_map, find_flag);
2010 0 : table->status= error ? STATUS_NOT_FOUND : 0;
2011 0 : return error;
2012 : }
2013 :
2014 :
2015 : int ha_maria::index_read_idx_map(uchar * buf, uint index, const uchar * key,
2016 : key_part_map keypart_map,
2017 0 : enum ha_rkey_function find_flag)
2018 : {
2019 0 : ha_statistic_increment(&SSV::ha_read_key_count);
2020 0 : int error= maria_rkey(file, buf, index, key, keypart_map, find_flag);
2021 0 : table->status= error ? STATUS_NOT_FOUND : 0;
2022 0 : return error;
2023 : }
2024 :
2025 :
2026 : int ha_maria::index_read_last_map(uchar * buf, const uchar * key,
2027 0 : key_part_map keypart_map)
2028 : {
2029 0 : DBUG_ENTER("ha_maria::index_read_last_map");
2030 0 : DBUG_ASSERT(inited == INDEX);
2031 0 : ha_statistic_increment(&SSV::ha_read_key_count);
2032 : int error= maria_rkey(file, buf, active_index, key, keypart_map,
2033 0 : HA_READ_PREFIX_LAST);
2034 0 : table->status= error ? STATUS_NOT_FOUND : 0;
2035 0 : DBUG_RETURN(error);
2036 : }
2037 :
2038 :
2039 0 : int ha_maria::index_next(uchar * buf)
2040 : {
2041 0 : DBUG_ASSERT(inited == INDEX);
2042 0 : ha_statistic_increment(&SSV::ha_read_next_count);
2043 0 : int error= maria_rnext(file, buf, active_index);
2044 0 : table->status= error ? STATUS_NOT_FOUND : 0;
2045 0 : return error;
2046 : }
2047 :
2048 :
2049 0 : int ha_maria::index_prev(uchar * buf)
2050 : {
2051 0 : DBUG_ASSERT(inited == INDEX);
2052 0 : ha_statistic_increment(&SSV::ha_read_prev_count);
2053 0 : int error= maria_rprev(file, buf, active_index);
2054 0 : table->status= error ? STATUS_NOT_FOUND : 0;
2055 0 : return error;
2056 : }
2057 :
2058 :
2059 0 : int ha_maria::index_first(uchar * buf)
2060 : {
2061 0 : DBUG_ASSERT(inited == INDEX);
2062 0 : ha_statistic_increment(&SSV::ha_read_first_count);
2063 0 : int error= maria_rfirst(file, buf, active_index);
2064 0 : table->status= error ? STATUS_NOT_FOUND : 0;
2065 0 : return error;
2066 : }
2067 :
2068 :
2069 0 : int ha_maria::index_last(uchar * buf)
2070 : {
2071 0 : DBUG_ASSERT(inited == INDEX);
2072 0 : ha_statistic_increment(&SSV::ha_read_last_count);
2073 0 : int error= maria_rlast(file, buf, active_index);
2074 0 : table->status= error ? STATUS_NOT_FOUND : 0;
2075 0 : return error;
2076 : }
2077 :
2078 :
2079 : int ha_maria::index_next_same(uchar * buf,
2080 : const uchar *key __attribute__ ((unused)),
2081 0 : uint length __attribute__ ((unused)))
2082 : {
2083 : int error;
2084 0 : DBUG_ASSERT(inited == INDEX);
2085 0 : ha_statistic_increment(&SSV::ha_read_next_count);
2086 : /*
2087 : TODO: Delete this loop in Maria 1.5 as versioning will ensure this never
2088 : happens
2089 : */
2090 0 : do
2091 : {
2092 0 : error= maria_rnext_same(file,buf);
2093 : } while (error == HA_ERR_RECORD_DELETED);
2094 0 : table->status= error ? STATUS_NOT_FOUND : 0;
2095 0 : return error;
2096 : }
2097 :
2098 :
2099 73 : int ha_maria::rnd_init(bool scan)
2100 : {
2101 73 : if (scan)
2102 55 : return maria_scan_init(file);
2103 18 : return maria_reset(file); // Free buffers
2104 : }
2105 :
2106 :
2107 71 : int ha_maria::rnd_end()
2108 : {
2109 : /* Safe to call even if we don't have started a scan */
2110 71 : maria_scan_end(file);
2111 71 : return 0;
2112 : }
2113 :
2114 :
2115 89771 : int ha_maria::rnd_next(uchar *buf)
2116 : {
2117 89771 : ha_statistic_increment(&SSV::ha_read_rnd_next_count);
2118 89771 : int error= maria_scan(file, buf);
2119 89771 : table->status= error ? STATUS_NOT_FOUND : 0;
2120 89771 : return error;
2121 : }
2122 :
2123 :
2124 0 : int ha_maria::remember_rnd_pos()
2125 : {
2126 0 : return (*file->s->scan_remember_pos)(file, &remember_pos);
2127 : }
2128 :
2129 :
2130 0 : int ha_maria::restart_rnd_next(uchar *buf)
2131 : {
2132 0 : (*file->s->scan_restore_pos)(file, remember_pos);
2133 0 : return rnd_next(buf);
2134 : }
2135 :
2136 :
2137 3834 : int ha_maria::rnd_pos(uchar *buf, uchar *pos)
2138 : {
2139 3834 : ha_statistic_increment(&SSV::ha_read_rnd_count);
2140 3834 : int error= maria_rrnd(file, buf, my_get_ptr(pos, ref_length));
2141 3834 : table->status= error ? STATUS_NOT_FOUND : 0;
2142 3834 : return error;
2143 : }
2144 :
2145 :
2146 3834 : void ha_maria::position(const uchar *record)
2147 : {
2148 3834 : my_off_t row_position= maria_position(file);
2149 3834 : my_store_ptr(ref, ref_length, row_position);
2150 : }
2151 :
2152 :
2153 128 : int ha_maria::info(uint flag)
2154 : {
2155 128 : return info(flag, table->s->tmp_table == NO_TMP_TABLE);
2156 : }
2157 :
2158 128 : int ha_maria::info(uint flag, my_bool lock_table_share)
2159 : {
2160 : MARIA_INFO maria_info;
2161 : char name_buff[FN_REFLEN];
2162 :
2163 128 : (void) maria_status(file, &maria_info, flag);
2164 128 : if (flag & HA_STATUS_VARIABLE)
2165 : {
2166 128 : stats.records= maria_info.records;
2167 128 : stats.deleted= maria_info.deleted;
2168 128 : stats.data_file_length= maria_info.data_file_length;
2169 128 : stats.index_file_length= maria_info.index_file_length;
2170 128 : stats.delete_length= maria_info.delete_length;
2171 128 : stats.check_time= maria_info.check_time;
2172 128 : stats.mean_rec_length= maria_info.mean_reclength;
2173 : }
2174 128 : if (flag & HA_STATUS_CONST)
2175 : {
2176 55 : TABLE_SHARE *share= table->s;
2177 55 : stats.max_data_file_length= maria_info.max_data_file_length;
2178 55 : stats.max_index_file_length= maria_info.max_index_file_length;
2179 55 : stats.create_time= maria_info.create_time;
2180 55 : ref_length= maria_info.reflength;
2181 55 : share->db_options_in_use= maria_info.options;
2182 55 : stats.block_size= maria_block_size;
2183 :
2184 : /* Update share */
2185 55 : if (lock_table_share)
2186 0 : pthread_mutex_lock(&share->mutex);
2187 55 : share->keys_in_use.set_prefix(share->keys);
2188 55 : share->keys_in_use.intersect_extended(maria_info.key_map);
2189 55 : share->keys_for_keyread.intersect(share->keys_in_use);
2190 55 : share->db_record_offset= maria_info.record_offset;
2191 55 : if (share->key_parts)
2192 : {
2193 0 : ulong *to= table->key_info[0].rec_per_key, *end;
2194 0 : double *from= maria_info.rec_per_key;
2195 0 : for (end= to+ share->key_parts ; to < end ; to++, from++)
2196 0 : *to= (ulong) (*from + 0.5);
2197 : }
2198 55 : if (lock_table_share)
2199 0 : pthread_mutex_unlock(&share->mutex);
2200 :
2201 : /*
2202 : Set data_file_name and index_file_name to point at the symlink value
2203 : if table is symlinked (Ie; Real name is not same as generated name)
2204 : */
2205 55 : data_file_name= index_file_name= 0;
2206 : fn_format(name_buff, file->s->open_file_name.str, "", MARIA_NAME_DEXT,
2207 55 : MY_APPEND_EXT | MY_UNPACK_FILENAME);
2208 55 : if (strcmp(name_buff, maria_info.data_file_name))
2209 0 : data_file_name =maria_info.data_file_name;
2210 : fn_format(name_buff, file->s->open_file_name.str, "", MARIA_NAME_IEXT,
2211 55 : MY_APPEND_EXT | MY_UNPACK_FILENAME);
2212 55 : if (strcmp(name_buff, maria_info.index_file_name))
2213 0 : index_file_name=maria_info.index_file_name;
2214 : }
2215 128 : if (flag & HA_STATUS_ERRKEY)
2216 : {
2217 0 : errkey= maria_info.errkey;
2218 0 : my_store_ptr(dup_ref, ref_length, maria_info.dup_key_pos);
2219 : }
2220 : /* Faster to always update, than to do it based on flag */
2221 128 : stats.update_time= maria_info.update_time;
2222 128 : stats.auto_increment_value= maria_info.auto_increment;
2223 :
2224 128 : return 0;
2225 : }
2226 :
2227 :
2228 239 : int ha_maria::extra(enum ha_extra_function operation)
2229 : {
2230 239 : if ((specialflag & SPECIAL_SAFE_MODE) && operation == HA_EXTRA_KEYREAD)
2231 0 : return 0;
2232 :
2233 : /*
2234 : We have to set file->trn here because in some cases we call
2235 : extern_lock(F_UNLOCK) (which resets file->trn) followed by maria_close()
2236 : without calling commit/rollback in between. If file->trn is not set
2237 : we can't remove file->share from the transaction list in the extra() call.
2238 : */
2239 :
2240 239 : if (!file->trn &&
2241 : (operation == HA_EXTRA_PREPARE_FOR_DROP ||
2242 : operation == HA_EXTRA_PREPARE_FOR_RENAME))
2243 : {
2244 0 : THD *thd= table->in_use;
2245 0 : TRN *trn= THD_TRN;
2246 0 : _ma_set_trn_for_table(file, trn);
2247 : }
2248 239 : return maria_extra(file, operation, 0);
2249 : }
2250 :
2251 0 : int ha_maria::reset(void)
2252 : {
2253 0 : return maria_reset(file);
2254 : }
2255 :
2256 : /* To be used with WRITE_CACHE and EXTRA_CACHE */
2257 :
2258 55 : int ha_maria::extra_opt(enum ha_extra_function operation, ulong cache_size)
2259 : {
2260 55 : if ((specialflag & SPECIAL_SAFE_MODE) && operation == HA_EXTRA_WRITE_CACHE)
2261 0 : return 0;
2262 55 : return maria_extra(file, operation, (void*) &cache_size);
2263 : }
2264 :
2265 :
2266 0 : int ha_maria::delete_all_rows()
2267 : {
2268 0 : THD *thd= current_thd;
2269 : (void) translog_log_debug_info(file->trn, LOGREC_DEBUG_INFO_QUERY,
2270 0 : (uchar*) thd->query, thd->query_length);
2271 0 : if (file->s->now_transactional &&
2272 : ((table->in_use->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) ||
2273 : table->in_use->locked_tables))
2274 : {
2275 : /*
2276 : We are not in autocommit mode or user have done LOCK TABLES.
2277 : We must do the delete row by row to be able to rollback the command
2278 : */
2279 0 : return HA_ERR_WRONG_COMMAND;
2280 : }
2281 0 : return maria_delete_all_rows(file);
2282 : }
2283 :
2284 :
2285 53 : int ha_maria::delete_table(const char *name)
2286 : {
2287 53 : THD *thd= current_thd;
2288 : (void) translog_log_debug_info(0, LOGREC_DEBUG_INFO_QUERY,
2289 53 : (uchar*) thd->query, thd->query_length);
2290 53 : return maria_delete_table(name);
2291 : }
2292 :
2293 0 : int ha_maria::external_lock(THD *thd, int lock_type)
2294 : {
2295 0 : TRN *trn= THD_TRN;
2296 0 : DBUG_ENTER("ha_maria::external_lock");
2297 : /*
2298 : We don't test now_transactional because it may vary between lock/unlock
2299 : and thus confuse our reference counting.
2300 : It is critical to skip non-transactional tables: user-visible temporary
2301 : tables get an external_lock() when read/written for the first time, but no
2302 : corresponding unlock (they just stay locked and are later dropped while
2303 : locked); if a tmp table was transactional, "SELECT FROM non_tmp, tmp"
2304 : would never commit as its "locked_tables" count would stay 1.
2305 : When Maria has has_transactions()==TRUE, open_temporary_table()
2306 : (sql_base.cc) will use TRANSACTIONAL_TMP_TABLE and thus the
2307 : external_lock(F_UNLCK) will happen and we can then allow the user to
2308 : create transactional temporary tables.
2309 : */
2310 0 : if (file->s->base.born_transactional)
2311 : {
2312 : /* Transactional table */
2313 0 : if (lock_type != F_UNLCK)
2314 : {
2315 : /* Start of new statement */
2316 0 : if (!trn) /* no transaction yet - open it now */
2317 : {
2318 0 : trn= trnman_new_trn(& thd->transaction.wt);
2319 0 : if (unlikely(!trn))
2320 0 : DBUG_RETURN(HA_ERR_OUT_OF_MEM);
2321 0 : THD_TRN= trn;
2322 0 : if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
2323 : trans_register_ha(thd, TRUE, maria_hton);
2324 : }
2325 0 : _ma_set_trn_for_table(file, trn);
2326 0 : if (!trnman_increment_locked_tables(trn))
2327 : {
2328 : trans_register_ha(thd, FALSE, maria_hton);
2329 0 : trnman_new_statement(trn);
2330 : }
2331 :
2332 0 : if (!file->s->lock_key_trees) // If we don't use versioning
2333 : {
2334 : /*
2335 : We come here in the following cases:
2336 : - The table is a temporary table
2337 : - It's a table which is crash safe but not yet versioned, for
2338 : example a table with fulltext or rtree keys
2339 :
2340 : Set the current state to point to save_state so that the
2341 : block_format code don't count the same record twice.
2342 : Copy also the current state. This may have been wrong if the
2343 : same file was used several times in the last statement
2344 : */
2345 0 : file->state= file->state_start;
2346 0 : *file->state= file->s->state.state;
2347 : }
2348 :
2349 0 : if (!thd->transaction.on)
2350 : {
2351 : /*
2352 : No need to log REDOs/UNDOs. If this is an internal temporary table
2353 : which will be renamed to a permanent table (like in ALTER TABLE),
2354 : the rename happens after unlocking so will be durable (and the table
2355 : will get its create_rename_lsn).
2356 : Note: if we wanted to enable users to have an old backup and apply
2357 : tons of archived logs to roll-forward, we could then not disable
2358 : REDOs/UNDOs in this case.
2359 : */
2360 0 : DBUG_PRINT("info", ("Disabling logging for table"));
2361 0 : _ma_tmp_disable_logging_for_table(file, TRUE);
2362 : }
2363 : #ifdef EXTRA_DEBUG
2364 0 : if (lock_type == F_WRLCK &&
2365 : ! (trnman_get_flags(trn) & TRN_STATE_INFO_LOGGED))
2366 : {
2367 : trnman_set_flags(trn, trnman_get_flags(trn) | TRN_STATE_INFO_LOGGED |
2368 0 : TRN_STATE_TABLES_CAN_CHANGE);
2369 : (void) translog_log_debug_info(trn, LOGREC_DEBUG_INFO_QUERY,
2370 0 : (uchar*) thd->query, thd->query_length);
2371 : }
2372 : #endif
2373 : }
2374 : else
2375 : {
2376 : /* End of transaction */
2377 :
2378 : /*
2379 : We always re-enable, don't rely on thd->transaction.on as it is
2380 : sometimes reset to true after unlocking (see mysql_truncate() for a
2381 : partitioned table based on Maria).
2382 : Note that we can come here without having an exclusive lock on the
2383 : table, for example in this case:
2384 : external_lock(F_(WR|RD)LCK); thr_lock() which fails due to lock
2385 : abortion; external_lock(F_UNLCK). Fortunately, the re-enabling happens
2386 : only if we were the thread which disabled logging.
2387 : */
2388 0 : if (_ma_reenable_logging_for_table(file, TRUE))
2389 0 : DBUG_RETURN(1);
2390 : /** @todo zero file->trn also in commit and rollback */
2391 0 : _ma_set_trn_for_table(file, NULL); // Safety
2392 : /*
2393 : Ensure that file->state points to the current number of rows. This
2394 : is needed if someone calls maria_info() without first doing an
2395 : external lock of the table
2396 : */
2397 0 : file->state= &file->s->state.state;
2398 0 : if (trn)
2399 : {
2400 0 : if (trnman_has_locked_tables(trn) &&
2401 : !trnman_decrement_locked_tables(trn))
2402 : {
2403 : /*
2404 : OK should not have been sent to client yet (ACID).
2405 : This is a bit excessive, ACID requires this only if there are some
2406 : changes to commit (rollback shouldn't be tested).
2407 : */
2408 0 : DBUG_ASSERT(!thd->main_da.is_sent ||
2409 : thd->killed == THD::KILL_CONNECTION);
2410 : /* autocommit ? rollback a transaction */
2411 : #ifdef MARIA_CANNOT_ROLLBACK
2412 0 : if (ma_commit(trn))
2413 0 : DBUG_RETURN(1);
2414 0 : THD_TRN= 0;
2415 : #else
2416 : if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
2417 : {
2418 : trnman_rollback_trn(trn);
2419 : DBUG_PRINT("info", ("THD_TRN set to 0x0"));
2420 : THD_TRN= 0;
2421 : }
2422 : #endif
2423 : }
2424 0 : trnman_set_flags(trn, trnman_get_flags(trn) & ~ TRN_STATE_INFO_LOGGED);
2425 : }
2426 : }
2427 : } /* if transactional table */
2428 0 : DBUG_RETURN(maria_lock_database(file, !table->s->tmp_table ?
2429 : lock_type : ((lock_type == F_UNLCK) ?
2430 : F_UNLCK : F_EXTRA_LCK)));
2431 : }
2432 :
2433 0 : int ha_maria::start_stmt(THD *thd, thr_lock_type lock_type)
2434 : {
2435 : TRN *trn;
2436 0 : if (file->s->base.born_transactional)
2437 : {
2438 0 : trn= THD_TRN;
2439 0 : DBUG_ASSERT(trn); // this may be called only after external_lock()
2440 0 : DBUG_ASSERT(trnman_has_locked_tables(trn));
2441 0 : DBUG_ASSERT(lock_type != TL_UNLOCK);
2442 0 : DBUG_ASSERT(file->trn == trn);
2443 :
2444 : /*
2445 : If there was an implicit commit under this LOCK TABLES by a previous
2446 : statement (like a DDL), at least if that previous statement was about a
2447 : different ha_maria than 'this' then this->file->trn is a stale
2448 : pointer. We fix it:
2449 : */
2450 0 : _ma_set_trn_for_table(file, trn);
2451 : /*
2452 : As external_lock() was already called, don't increment locked_tables.
2453 : Note that we call the function below possibly several times when
2454 : statement starts (once per table). This is ok as long as that function
2455 : does cheap operations. Otherwise, we will need to do it only on first
2456 : call to start_stmt().
2457 : */
2458 0 : trnman_new_statement(trn);
2459 :
2460 : #ifdef EXTRA_DEBUG
2461 0 : if (!(trnman_get_flags(trn) & TRN_STATE_INFO_LOGGED) &&
2462 : trnman_get_flags(trn) & TRN_STATE_TABLES_CAN_CHANGE)
2463 : {
2464 0 : trnman_set_flags(trn, trnman_get_flags(trn) | TRN_STATE_INFO_LOGGED);
2465 : (void) translog_log_debug_info(trn, LOGREC_DEBUG_INFO_QUERY,
2466 0 : (uchar*) thd->query, thd->query_length);
2467 : }
2468 : #endif
2469 : }
2470 0 : return 0;
2471 : }
2472 :
2473 :
2474 : /**
2475 : Performs an implicit commit of the Maria transaction and creates a new
2476 : one.
2477 :
2478 : This can be considered a hack. When Maria loses HA_NO_TRANSACTIONS it will
2479 : be participant in the connection's transaction and so the implicit commits
2480 : (ha_commit()) (like in end_active_trans()) will do the implicit commit
2481 : without need to call this function which can then be removed.
2482 :
2483 : @param thd THD object
2484 : @param new_trn if a new transaction should be created; a new
2485 : transaction is not needed when we know that the
2486 : tables will be unlocked very soon.
2487 : */
2488 :
2489 1378 : int ha_maria::implicit_commit(THD *thd, bool new_trn)
2490 : {
2491 : #ifndef MARIA_CANNOT_ROLLBACK
2492 : #error this method should be removed
2493 : #endif
2494 : TRN *trn;
2495 1378 : int error= 0;
2496 : TABLE *table;
2497 1378 : DBUG_ENTER("ha_maria::implicit_commit");
2498 1378 : if (!new_trn && thd->locked_tables)
2499 : {
2500 : /*
2501 : "we are under LOCK TABLES" <=> "we shouldn't commit".
2502 : As thd->locked_tables is true, we are either under LOCK TABLES, or in
2503 : prelocking; prelocking can be under LOCK TABLES, or not (and in this
2504 : latter case only we should commit).
2505 : Note that we come here only at the end of the top statement
2506 : (dispatch_command()), we are never committing inside a sub-statement./
2507 : */
2508 41 : enum prelocked_mode_type prelocked_mode= thd->prelocked_mode;
2509 41 : if ((prelocked_mode == NON_PRELOCKED) ||
2510 : (prelocked_mode == PRELOCKED_UNDER_LOCK_TABLES))
2511 : {
2512 41 : DBUG_PRINT("info", ("locked_tables, skipping"));
2513 41 : DBUG_RETURN(0);
2514 : }
2515 : }
2516 1337 : if ((trn= THD_TRN) != NULL)
2517 : {
2518 0 : uint locked_tables= trnman_has_locked_tables(trn);
2519 0 : if (unlikely(ma_commit(trn)))
2520 0 : error= 1;
2521 0 : if (!new_trn)
2522 : {
2523 0 : THD_TRN= NULL;
2524 0 : goto end;
2525 : }
2526 : /*
2527 : We need to create a new transaction and put it in THD_TRN. Indeed,
2528 : tables may be under LOCK TABLES, and so they will start the next
2529 : statement assuming they have a trn (see ha_maria::start_stmt()).
2530 : */
2531 0 : trn= trnman_new_trn(& thd->transaction.wt);
2532 : /* This is just a commit, tables stay locked if they were: */
2533 0 : trnman_reset_locked_tables(trn, locked_tables);
2534 0 : THD_TRN= trn;
2535 0 : if (unlikely(trn == NULL))
2536 0 : error= HA_ERR_OUT_OF_MEM;
2537 :
2538 : /*
2539 : Move all locked tables to the new transaction
2540 : We must do it here as otherwise file->thd and file->state may be
2541 : stale pointers. We can't do this in start_stmt() as we don't know
2542 : when we should call _ma_setup_live_state() and in some cases, like
2543 : in check table, we use the table without calling start_stmt().
2544 : */
2545 0 : for (table=thd->open_tables; table ; table=table->next)
2546 : {
2547 0 : if (table->db_stat && table->file->ht == maria_hton)
2548 : {
2549 0 : MARIA_HA *handler= ((ha_maria*) table->file)->file;
2550 0 : if (handler->s->base.born_transactional)
2551 : {
2552 0 : _ma_set_trn_for_table(handler, trn);
2553 : /* If handler uses versioning */
2554 0 : if (handler->s->lock_key_trees)
2555 : {
2556 0 : if (_ma_setup_live_state(handler))
2557 0 : error= HA_ERR_OUT_OF_MEM;
2558 : }
2559 : }
2560 : }
2561 : }
2562 : }
2563 1337 : end:
2564 1337 : DBUG_RETURN(error);
2565 : }
2566 :
2567 :
2568 : THR_LOCK_DATA **ha_maria::store_lock(THD *thd,
2569 : THR_LOCK_DATA **to,
2570 0 : enum thr_lock_type lock_type)
2571 : {
2572 : /* Test if we can fix test below */
2573 0 : DBUG_ASSERT(lock_type != TL_UNLOCK &&
2574 : (lock_type == TL_IGNORE || file->lock.type == TL_UNLOCK));
2575 0 : if (lock_type != TL_IGNORE && file->lock.type == TL_UNLOCK)
2576 : {
2577 0 : const enum enum_sql_command sql_command= thd->lex->sql_command;
2578 : /*
2579 : We have to disable concurrent inserts for INSERT ... SELECT or
2580 : INSERT/UPDATE/DELETE with sub queries if we are using statement based
2581 : logging. We take the safe route here and disable this for all commands
2582 : that only does reading that are not SELECT.
2583 : */
2584 0 : if (lock_type <= TL_READ_HIGH_PRIORITY &&
2585 : !thd->current_stmt_binlog_row_based &&
2586 : (sql_command != SQLCOM_SELECT &&
2587 : sql_command != SQLCOM_LOCK_TABLES) &&
2588 : (thd->options & OPTION_BIN_LOG) &&
2589 : mysql_bin_log.is_open())
2590 0 : lock_type= TL_READ_NO_INSERT;
2591 0 : else if (lock_type == TL_WRITE_CONCURRENT_INSERT)
2592 : {
2593 0 : const enum enum_duplicates duplicates= thd->lex->duplicates;
2594 : /*
2595 : Explanation for the 3 conditions below, in order:
2596 :
2597 : - Bulk insert may use repair, which will cause problems if other
2598 : threads try to read/insert to the table: disable versioning.
2599 : Note that our read of file->state->records is incorrect, as such
2600 : variable may have changed when we come to start_bulk_insert() (worse
2601 : case: we see != 0 so allow versioning, start_bulk_insert() sees 0 and
2602 : uses repair). This is prevented because start_bulk_insert() will not
2603 : try repair if we enabled versioning.
2604 : - INSERT SELECT ON DUPLICATE KEY UPDATE comes here with
2605 : TL_WRITE_CONCURRENT_INSERT but shouldn't because it can do
2606 : update/delete of a row and versioning doesn't support that
2607 : - same for LOAD DATA CONCURRENT REPLACE.
2608 : */
2609 0 : if ((file->state->records == 0) ||
2610 : (sql_command == SQLCOM_INSERT_SELECT && duplicates == DUP_UPDATE) ||
2611 : (sql_command == SQLCOM_LOAD && duplicates == DUP_REPLACE))
2612 0 : lock_type= TL_WRITE;
2613 : }
2614 0 : file->lock.type= lock_type;
2615 : }
2616 0 : *to++= &file->lock;
2617 0 : return to;
2618 : }
2619 :
2620 :
2621 0 : void ha_maria::update_create_info(HA_CREATE_INFO *create_info)
2622 : {
2623 0 : ha_maria::info(HA_STATUS_AUTO | HA_STATUS_CONST);
2624 0 : if (!(create_info->used_fields & HA_CREATE_USED_AUTO))
2625 : {
2626 0 : create_info->auto_increment_value= stats.auto_increment_value;
2627 : }
2628 0 : create_info->data_file_name= data_file_name;
2629 0 : create_info->index_file_name= index_file_name;
2630 : /* We need to restore the row type as Maria can change it */
2631 0 : if (create_info->row_type != ROW_TYPE_DEFAULT &&
2632 : !(create_info->used_fields & HA_CREATE_USED_ROW_FORMAT))
2633 0 : create_info->row_type= get_row_type();
2634 : /*
2635 : Show always page checksums, as this can be forced with
2636 : maria_page_checksums variable
2637 : */
2638 0 : if (create_info->page_checksum == HA_CHOICE_UNDEF)
2639 : create_info->page_checksum=
2640 : (file->s->options & HA_OPTION_PAGE_CHECKSUM) ? HA_CHOICE_YES :
2641 0 : HA_CHOICE_NO;
2642 : }
2643 :
2644 :
2645 0 : enum row_type ha_maria::get_row_type() const
2646 : {
2647 0 : switch (file->s->data_file_type) {
2648 0 : case STATIC_RECORD: return ROW_TYPE_FIXED;
2649 0 : case DYNAMIC_RECORD: return ROW_TYPE_DYNAMIC;
2650 0 : case BLOCK_RECORD: return ROW_TYPE_PAGE;
2651 0 : case COMPRESSED_RECORD: return ROW_TYPE_COMPRESSED;
2652 0 : default: return ROW_TYPE_NOT_USED;
2653 : }
2654 : }
2655 :
2656 :
2657 0 : static enum data_file_type maria_row_type(HA_CREATE_INFO *info)
2658 : {
2659 0 : if (info->transactional == HA_CHOICE_YES)
2660 0 : return BLOCK_RECORD;
2661 0 : switch (info->row_type) {
2662 0 : case ROW_TYPE_FIXED: return STATIC_RECORD;
2663 0 : case ROW_TYPE_DYNAMIC: return DYNAMIC_RECORD;
2664 0 : default: return BLOCK_RECORD;
2665 : }
2666 : }
2667 :
2668 :
2669 : int ha_maria::create(const char *name, register TABLE *table_arg,
2670 0 : HA_CREATE_INFO *ha_create_info)
2671 : {
2672 : int error;
2673 0 : uint create_flags= 0, record_count, i;
2674 : char buff[FN_REFLEN];
2675 : MARIA_KEYDEF *keydef;
2676 : MARIA_COLUMNDEF *recinfo;
2677 : MARIA_CREATE_INFO create_info;
2678 0 : TABLE_SHARE *share= table_arg->s;
2679 0 : uint options= share->db_options_in_use;
2680 : enum data_file_type row_type;
2681 0 : THD *thd= current_thd;
2682 0 : DBUG_ENTER("ha_maria::create");
2683 :
2684 0 : for (i= 0; i < share->keys; i++)
2685 : {
2686 0 : if (table_arg->key_info[i].flags & HA_USES_PARSER)
2687 : {
2688 0 : create_flags|= HA_CREATE_RELIES_ON_SQL_LAYER;
2689 0 : break;
2690 : }
2691 : }
2692 : /* Note: BLOCK_RECORD is used if table is transactional */
2693 0 : row_type= maria_row_type(ha_create_info);
2694 0 : if (ha_create_info->transactional == HA_CHOICE_YES &&
2695 : ha_create_info->row_type != ROW_TYPE_PAGE &&
2696 : ha_create_info->row_type != ROW_TYPE_NOT_USED &&
2697 : ha_create_info->row_type != ROW_TYPE_DEFAULT)
2698 : push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
2699 : ER_ILLEGAL_HA_CREATE_OPTION,
2700 0 : "Row format set to PAGE because of TRANSACTIONAL=1 option");
2701 :
2702 0 : bzero((char*) &create_info, sizeof(create_info));
2703 0 : if ((error= table2maria(table_arg, row_type, &keydef, &recinfo,
2704 : &record_count, &create_info)))
2705 0 : DBUG_RETURN(error); /* purecov: inspected */
2706 0 : create_info.max_rows= share->max_rows;
2707 0 : create_info.reloc_rows= share->min_rows;
2708 0 : create_info.with_auto_increment= share->next_number_key_offset == 0;
2709 : create_info.auto_increment= (ha_create_info->auto_increment_value ?
2710 : ha_create_info->auto_increment_value -1 :
2711 0 : (ulonglong) 0);
2712 : create_info.data_file_length= ((ulonglong) share->max_rows *
2713 0 : share->avg_row_length);
2714 0 : create_info.data_file_name= ha_create_info->data_file_name;
2715 0 : create_info.index_file_name= ha_create_info->index_file_name;
2716 0 : create_info.language= share->table_charset->number;
2717 :
2718 : /*
2719 : Table is transactional:
2720 : - If the user specify that table is transactional (in this case
2721 : row type is forced to BLOCK_RECORD)
2722 : - If they specify BLOCK_RECORD without specifying transactional behaviour
2723 :
2724 : Shouldn't this test be pushed down to maria_create()? Because currently,
2725 : ma_test1 -T crashes: it creates a table with DYNAMIC_RECORD but has
2726 : born_transactional==1, which confuses some recovery-related code.
2727 : */
2728 : create_info.transactional= (row_type == BLOCK_RECORD &&
2729 0 : ha_create_info->transactional != HA_CHOICE_NO);
2730 :
2731 0 : if (ha_create_info->options & HA_LEX_CREATE_TMP_TABLE)
2732 0 : create_flags|= HA_CREATE_TMP_TABLE;
2733 0 : if (ha_create_info->options & HA_CREATE_KEEP_FILES)
2734 0 : create_flags|= HA_CREATE_KEEP_FILES;
2735 0 : if (options & HA_OPTION_PACK_RECORD)
2736 0 : create_flags|= HA_PACK_RECORD;
2737 0 : if (options & HA_OPTION_CHECKSUM)
2738 0 : create_flags|= HA_CREATE_CHECKSUM;
2739 0 : if (options & HA_OPTION_DELAY_KEY_WRITE)
2740 0 : create_flags|= HA_CREATE_DELAY_KEY_WRITE;
2741 0 : if ((ha_create_info->page_checksum == HA_CHOICE_UNDEF &&
2742 : maria_page_checksums) ||
2743 : ha_create_info->page_checksum == HA_CHOICE_YES)
2744 0 : create_flags|= HA_CREATE_PAGE_CHECKSUM;
2745 :
2746 : (void) translog_log_debug_info(0, LOGREC_DEBUG_INFO_QUERY,
2747 0 : (uchar*) thd->query, thd->query_length);
2748 :
2749 : /* TODO: Check that the following fn_format is really needed */
2750 : error=
2751 : maria_create(fn_format(buff, name, "", "",
2752 : MY_UNPACK_FILENAME | MY_APPEND_EXT),
2753 : row_type, share->keys, keydef,
2754 : record_count, recinfo,
2755 : 0, (MARIA_UNIQUEDEF *) 0,
2756 0 : &create_info, create_flags);
2757 :
2758 0 : my_free((uchar*) recinfo, MYF(0));
2759 0 : DBUG_RETURN(error);
2760 : }
2761 :
2762 :
2763 0 : int ha_maria::rename_table(const char *from, const char *to)
2764 : {
2765 0 : THD *thd= current_thd;
2766 : (void) translog_log_debug_info(0, LOGREC_DEBUG_INFO_QUERY,
2767 0 : (uchar*) thd->query, thd->query_length);
2768 0 : return maria_rename(from, to);
2769 : }
2770 :
2771 :
2772 : void ha_maria::get_auto_increment(ulonglong offset, ulonglong increment,
2773 : ulonglong nb_desired_values,
2774 : ulonglong *first_value,
2775 0 : ulonglong *nb_reserved_values)
2776 : {
2777 : ulonglong nr;
2778 : int error;
2779 : uchar key[HA_MAX_KEY_LENGTH];
2780 :
2781 0 : if (!table->s->next_number_key_offset)
2782 : { // Autoincrement at key-start
2783 0 : ha_maria::info(HA_STATUS_AUTO);
2784 0 : *first_value= stats.auto_increment_value;
2785 : /* Maria has only table-level lock for now, so reserves to +inf */
2786 0 : *nb_reserved_values= ULONGLONG_MAX;
2787 0 : return;
2788 : }
2789 :
2790 : /* it's safe to call the following if bulk_insert isn't on */
2791 0 : maria_flush_bulk_insert(file, table->s->next_number_index);
2792 :
2793 0 : (void) extra(HA_EXTRA_KEYREAD);
2794 : key_copy(key, table->record[0],
2795 : table->key_info + table->s->next_number_index,
2796 0 : table->s->next_number_key_offset);
2797 : error= maria_rkey(file, table->record[1], (int) table->s->next_number_index,
2798 : key, make_prev_keypart_map(table->s->next_number_keypart),
2799 0 : HA_READ_PREFIX_LAST);
2800 0 : if (error)
2801 0 : nr= 1;
2802 : else
2803 : {
2804 : /* Get data from record[1] */
2805 : nr= ((ulonglong) table->next_number_field->
2806 0 : val_int_offset(table->s->rec_buff_length) + 1);
2807 : }
2808 0 : extra(HA_EXTRA_NO_KEYREAD);
2809 0 : *first_value= nr;
2810 : /*
2811 : MySQL needs to call us for next row: assume we are inserting ("a",null)
2812 : here, we return 3, and next this statement will want to insert ("b",null):
2813 : there is no reason why ("b",3+1) would be the good row to insert: maybe it
2814 : already exists, maybe 3+1 is too large...
2815 : */
2816 0 : *nb_reserved_values= 1;
2817 : }
2818 :
2819 :
2820 : /*
2821 : Find out how many rows there is in the given range
2822 :
2823 : SYNOPSIS
2824 : records_in_range()
2825 : inx Index to use
2826 : min_key Start of range. Null pointer if from first key
2827 : max_key End of range. Null pointer if to last key
2828 :
2829 : NOTES
2830 : min_key.flag can have one of the following values:
2831 : HA_READ_KEY_EXACT Include the key in the range
2832 : HA_READ_AFTER_KEY Don't include key in range
2833 :
2834 : max_key.flag can have one of the following values:
2835 : HA_READ_BEFORE_KEY Don't include key in range
2836 : HA_READ_AFTER_KEY Include all 'end_key' values in the range
2837 :
2838 : RETURN
2839 : HA_POS_ERROR Something is wrong with the index tree.
2840 : 0 There is no matching keys in the given range
2841 : number > 0 There is approximately 'number' matching rows in
2842 : the range.
2843 : */
2844 :
2845 : ha_rows ha_maria::records_in_range(uint inx, key_range *min_key,
2846 0 : key_range *max_key)
2847 : {
2848 0 : return (ha_rows) maria_records_in_range(file, (int) inx, min_key, max_key);
2849 : }
2850 :
2851 :
2852 0 : int ha_maria::ft_read(uchar * buf)
2853 : {
2854 : int error;
2855 :
2856 0 : if (!ft_handler)
2857 0 : return -1;
2858 :
2859 0 : thread_safe_increment(table->in_use->status_var.ha_read_next_count,
2860 : &LOCK_status); // why ?
2861 :
2862 0 : error= ft_handler->please->read_next(ft_handler, (char*) buf);
2863 :
2864 0 : table->status= error ? STATUS_NOT_FOUND : 0;
2865 0 : return error;
2866 : }
2867 :
2868 :
2869 0 : uint ha_maria::checksum() const
2870 : {
2871 0 : return (uint) file->state->checksum;
2872 : }
2873 :
2874 :
2875 : bool ha_maria::check_if_incompatible_data(HA_CREATE_INFO *create_info,
2876 0 : uint table_changes)
2877 : {
2878 0 : DBUG_ENTER("check_if_incompatible_data");
2879 0 : uint options= table->s->db_options_in_use;
2880 :
2881 0 : if (create_info->auto_increment_value != stats.auto_increment_value ||
2882 : create_info->data_file_name != data_file_name ||
2883 : create_info->index_file_name != index_file_name ||
2884 : (maria_row_type(create_info) != data_file_type &&
2885 : create_info->row_type != ROW_TYPE_DEFAULT) ||
2886 : table_changes == IS_EQUAL_NO ||
2887 : (table_changes & IS_EQUAL_PACK_LENGTH)) // Not implemented yet
2888 0 : DBUG_RETURN(COMPATIBLE_DATA_NO);
2889 :
2890 0 : if ((options & (HA_OPTION_CHECKSUM |
2891 : HA_OPTION_DELAY_KEY_WRITE)) !=
2892 : (create_info->table_options & (HA_OPTION_CHECKSUM |
2893 : HA_OPTION_DELAY_KEY_WRITE)))
2894 0 : DBUG_RETURN(COMPATIBLE_DATA_NO);
2895 0 : DBUG_RETURN(COMPATIBLE_DATA_YES);
2896 : }
2897 :
2898 :
2899 1 : static int maria_hton_panic(handlerton *hton, ha_panic_function flag)
2900 : {
2901 : /* If no background checkpoints, we need to do one now */
2902 : return ((checkpoint_interval == 0) ?
2903 1 : ma_checkpoint_execute(CHECKPOINT_FULL, FALSE) : 0) | maria_panic(flag);
2904 : }
2905 :
2906 :
2907 : static int maria_commit(handlerton *hton __attribute__ ((unused)),
2908 0 : THD *thd, bool all)
2909 : {
2910 0 : TRN *trn= THD_TRN;
2911 0 : DBUG_ENTER("maria_commit");
2912 0 : trnman_reset_locked_tables(trn, 0);
2913 0 : trnman_set_flags(trn, trnman_get_flags(trn) & ~TRN_STATE_INFO_LOGGED);
2914 :
2915 : /* statement or transaction ? */
2916 0 : if ((thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && !all)
2917 0 : DBUG_RETURN(0); // end of statement
2918 0 : DBUG_PRINT("info", ("THD_TRN set to 0x0"));
2919 0 : THD_TRN= 0;
2920 0 : DBUG_RETURN(ma_commit(trn)); // end of transaction
2921 : }
2922 :
2923 :
2924 : static int maria_rollback(handlerton *hton __attribute__ ((unused)),
2925 0 : THD *thd, bool all)
2926 : {
2927 0 : TRN *trn= THD_TRN;
2928 0 : DBUG_ENTER("maria_rollback");
2929 0 : trnman_reset_locked_tables(trn, 0);
2930 : /* statement or transaction ? */
2931 0 : if ((thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && !all)
2932 : {
2933 0 : trnman_rollback_statement(trn);
2934 0 : DBUG_RETURN(0); // end of statement
2935 : }
2936 0 : DBUG_PRINT("info", ("THD_TRN set to 0x0"));
2937 0 : THD_TRN= 0;
2938 0 : DBUG_RETURN(trnman_rollback_trn(trn) ?
2939 : HA_ERR_OUT_OF_MEM : 0); // end of transaction
2940 : }
2941 :
2942 :
2943 :
2944 : /**
2945 : @brief flush log handler
2946 :
2947 : @param hton maria handlerton (unused)
2948 :
2949 : @retval FALSE OK
2950 : @retval TRUE Error
2951 : */
2952 :
2953 0 : bool maria_flush_logs(handlerton *hton)
2954 : {
2955 0 : return test(translog_purge_at_flush());
2956 : }
2957 :
2958 :
2959 : #define SHOW_MSG_LEN (FN_REFLEN + 20)
2960 : /**
2961 : @brief show status handler
2962 :
2963 : @param hton maria handlerton
2964 : @param thd thread handler
2965 : @param print print function
2966 : @param stat type of status
2967 : */
2968 :
2969 : bool maria_show_status(handlerton *hton,
2970 : THD *thd,
2971 : stat_print_fn *print,
2972 0 : enum ha_stat_type stat)
2973 : {
2974 0 : const LEX_STRING *engine_name= hton_name(hton);
2975 0 : switch (stat) {
2976 : case HA_ENGINE_LOGS:
2977 : {
2978 0 : TRANSLOG_ADDRESS horizon= translog_get_horizon();
2979 0 : uint32 last_file= LSN_FILE_NO(horizon);
2980 0 : uint32 first_needed= translog_get_first_needed_file();
2981 0 : uint32 first_file= translog_get_first_file(horizon);
2982 : uint32 i;
2983 0 : const char unknown[]= "unknown";
2984 0 : const char needed[]= "in use";
2985 0 : const char unneeded[]= "free";
2986 : char path[FN_REFLEN];
2987 :
2988 0 : if (first_file == 0)
2989 : {
2990 0 : const char error[]= "error";
2991 : print(thd, engine_name->str, engine_name->length,
2992 0 : STRING_WITH_LEN(""), error, sizeof(error) - 1);
2993 0 : break;
2994 : }
2995 :
2996 0 : for (i= first_file; i <= last_file; i++)
2997 : {
2998 : char *file;
2999 : const char *status;
3000 : uint length, status_len;
3001 : MY_STAT stat_buff, *stat;
3002 0 : const char error[]= "can't stat";
3003 : char object[SHOW_MSG_LEN];
3004 0 : file= translog_filename_by_fileno(i, path);
3005 0 : if (!(stat= my_stat(file, &stat_buff, MYF(0))))
3006 : {
3007 0 : status= error;
3008 0 : status_len= sizeof(error) - 1;
3009 0 : length= my_snprintf(object, SHOW_MSG_LEN, "Size unknown ; %s", file);
3010 : }
3011 : else
3012 : {
3013 0 : if (first_needed == 0)
3014 : {
3015 0 : status= unknown;
3016 0 : status_len= sizeof(unknown) - 1;
3017 : }
3018 0 : else if (i < first_needed)
3019 : {
3020 0 : status= unneeded;
3021 0 : status_len= sizeof(unneeded) - 1;
3022 : }
3023 : else
3024 : {
3025 0 : status= needed;
3026 0 : status_len= sizeof(needed) - 1;
3027 : }
3028 : length= my_snprintf(object, SHOW_MSG_LEN, "Size %12lu ; %s",
3029 0 : (ulong) stat->st_size, file);
3030 : }
3031 :
3032 : print(thd, engine_name->str, engine_name->length,
3033 0 : object, length, status, status_len);
3034 : }
3035 : break;
3036 : }
3037 : case HA_ENGINE_STATUS:
3038 : case HA_ENGINE_MUTEX:
3039 : default:
3040 : break;
3041 : }
3042 0 : return 0;
3043 : }
3044 :
3045 :
3046 : /**
3047 : Callback to delete all logs in directory. This is lower-level than other
3048 : functions in ma_loghandler.c which delete logs, as it does not rely on
3049 : translog_init() having been called first.
3050 :
3051 : @param directory directory where file is
3052 : @param filename base name of the file to delete
3053 : */
3054 :
3055 : static my_bool translog_callback_delete_all(const char *directory,
3056 0 : const char *filename)
3057 : {
3058 : char complete_name[FN_REFLEN];
3059 0 : fn_format(complete_name, filename, directory, "", MYF(MY_UNPACK_FILENAME));
3060 0 : return my_delete(complete_name, MYF(MY_WME));
3061 : }
3062 :
3063 :
3064 : /**
3065 : Helper function for option maria-force-start-after-recovery-failures.
3066 : Deletes logs if too many failures. Otherwise, increments the counter of
3067 : failures in the control file.
3068 : Notice how this has to be called _before_ translog_init() (if log is
3069 : corrupted, translog_init() might crash the server, so we need to remove logs
3070 : before).
3071 :
3072 : @param log_dir directory where logs to be deleted are
3073 : */
3074 :
3075 0 : static int mark_recovery_start(const char* log_dir)
3076 : {
3077 : int res;
3078 0 : DBUG_ENTER("mark_recovery_start");
3079 0 : if (unlikely(maria_recover_options == HA_RECOVER_NONE))
3080 0 : ma_message_no_user(ME_JUST_WARNING, "Please consider using option"
3081 : " --maria-recover[=...] to automatically check and"
3082 : " repair tables when logs are removed by option"
3083 : " --maria-force-start-after-recovery-failures=#");
3084 0 : if (recovery_failures >= force_start_after_recovery_failures)
3085 : {
3086 : /*
3087 : Remove logs which cause the problem; keep control file which has
3088 : critical info like uuid, max_trid (removing control file may make
3089 : correct tables look corrupted!).
3090 : */
3091 : char msg[100];
3092 0 : res= translog_walk_filenames(log_dir, &translog_callback_delete_all);
3093 : my_snprintf(msg, sizeof(msg),
3094 : "%s logs after %u consecutive failures of"
3095 : " recovery from logs",
3096 : (res ? "failed to remove some" : "removed all"),
3097 0 : recovery_failures);
3098 0 : ma_message_no_user((res ? 0 : ME_JUST_WARNING), msg);
3099 : }
3100 : else
3101 : res= ma_control_file_write_and_force(last_checkpoint_lsn, last_logno,
3102 : max_trid_in_control_file,
3103 0 : recovery_failures + 1);
3104 0 : DBUG_RETURN(res);
3105 : }
3106 :
3107 :
3108 : /**
3109 : Helper function for option maria-force-start-after-recovery-failures.
3110 : Records in the control file that recovery was a success, so that it's not
3111 : counted for maria-force-start-after-recovery-failures.
3112 : */
3113 :
3114 0 : static int mark_recovery_success(void)
3115 : {
3116 : /* success of recovery, reset recovery_failures: */
3117 : int res;
3118 0 : DBUG_ENTER("mark_recovery_success");
3119 : res= ma_control_file_write_and_force(last_checkpoint_lsn, last_logno,
3120 0 : max_trid_in_control_file, 0);
3121 0 : DBUG_RETURN(res);
3122 : }
3123 :
3124 :
3125 : /*
3126 : Return 1 if table has changed during the current transaction
3127 : */
3128 :
3129 0 : bool ha_maria::is_changed() const
3130 : {
3131 0 : return file->state->changed;
3132 : }
3133 :
3134 :
3135 3 : static int ha_maria_init(void *p)
3136 : {
3137 : int res;
3138 3 : const char *log_dir= maria_data_root;
3139 3 : maria_hton= (handlerton *)p;
3140 3 : maria_hton->state= SHOW_OPTION_YES;
3141 3 : maria_hton->db_type= DB_TYPE_UNKNOWN;
3142 3 : maria_hton->create= maria_create_handler;
3143 3 : maria_hton->panic= maria_hton_panic;
3144 3 : maria_hton->commit= maria_commit;
3145 3 : maria_hton->rollback= maria_rollback;
3146 3 : maria_hton->flush_logs= maria_flush_logs;
3147 3 : maria_hton->show_status= maria_show_status;
3148 : /* TODO: decide if we support Maria being used for log tables */
3149 3 : maria_hton->flags= HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES;
3150 3 : bzero(maria_log_pagecache, sizeof(*maria_log_pagecache));
3151 3 : maria_tmpdir= &mysql_tmpdir_list; /* For REDO */
3152 : res= maria_init() || ma_control_file_open(TRUE, TRUE) ||
3153 : ((force_start_after_recovery_failures != 0) &&
3154 : mark_recovery_start(log_dir)) ||
3155 : !init_pagecache(maria_pagecache,
3156 : (size_t) pagecache_buffer_size, pagecache_division_limit,
3157 : pagecache_age_threshold, maria_block_size, 0) ||
3158 : !init_pagecache(maria_log_pagecache,
3159 : TRANSLOG_PAGECACHE_SIZE, 0, 0,
3160 : TRANSLOG_PAGE_SIZE, 0) ||
3161 : translog_init(maria_data_root, log_file_size,
3162 : MYSQL_VERSION_ID, server_id, maria_log_pagecache,
3163 : TRANSLOG_DEFAULT_FLAGS, 0) ||
3164 : maria_recovery_from_log() ||
3165 : ((force_start_after_recovery_failures != 0) && mark_recovery_success()) ||
3166 3 : ma_checkpoint_init(checkpoint_interval);
3167 3 : maria_multi_threaded= maria_in_ha_maria= TRUE;
3168 :
3169 : #if defined(HAVE_REALPATH) && !defined(HAVE_purify) && !defined(HAVE_BROKEN_REALPATH)
3170 : /* We can only test for sub paths if my_symlink.c is using realpath */
3171 3 : maria_test_invalid_symlink= test_if_data_home_dir;
3172 : #endif
3173 3 : return res ? HA_ERR_INITIALIZATION : 0;
3174 : }
3175 :
3176 :
3177 : #ifdef HAVE_QUERY_CACHE
3178 : /**
3179 : @brief Register a named table with a call back function to the query cache.
3180 :
3181 : @param thd The thread handle
3182 : @param table_key A pointer to the table name in the table cache
3183 : @param key_length The length of the table name
3184 : @param[out] engine_callback The pointer to the storage engine call back
3185 : function, currently 0
3186 : @param[out] engine_data Engine data will be set to 0.
3187 :
3188 : @note Despite the name of this function, it is used to check each statement
3189 : before it is cached and not to register a table or callback function.
3190 :
3191 : @see handler::register_query_cache_table
3192 :
3193 : @return The error code. The engine_data and engine_callback will be set to 0.
3194 : @retval TRUE Success
3195 : @retval FALSE An error occurred
3196 : */
3197 :
3198 : my_bool ha_maria::register_query_cache_table(THD *thd, char *table_name,
3199 : uint table_name_len,
3200 : qc_engine_callback
3201 : *engine_callback,
3202 0 : ulonglong *engine_data)
3203 : {
3204 : ulonglong actual_data_file_length;
3205 : ulonglong current_data_file_length;
3206 0 : DBUG_ENTER("ha_maria::register_query_cache_table");
3207 :
3208 : /*
3209 : No call back function is needed to determine if a cached statement
3210 : is valid or not.
3211 : */
3212 0 : *engine_callback= 0;
3213 :
3214 : /*
3215 : No engine data is needed.
3216 : */
3217 0 : *engine_data= 0;
3218 :
3219 : /*
3220 : If a concurrent INSERT has happened just before the currently processed
3221 : SELECT statement, the total size of the table is unknown.
3222 :
3223 : To determine if the table size is known, the current thread's snap shot of
3224 : the table size with the actual table size are compared.
3225 :
3226 : If the table size is unknown the SELECT statement can't be cached.
3227 : */
3228 :
3229 : /*
3230 : POSIX visibility rules specify that "2. Whatever memory values a
3231 : thread can see when it unlocks a mutex <...> can also be seen by any
3232 : thread that later locks the same mutex". In this particular case,
3233 : concurrent insert thread had modified the data_file_length in
3234 : MYISAM_SHARE before it has unlocked (or even locked)
3235 : structure_guard_mutex. So, here we're guaranteed to see at least that
3236 : value after we've locked the same mutex. We can see a later value
3237 : (modified by some other thread) though, but it's ok, as we only want
3238 : to know if the variable was changed, the actual new value doesn't matter
3239 : */
3240 0 : actual_data_file_length= file->s->state.state.data_file_length;
3241 0 : current_data_file_length= file->state->data_file_length;
3242 :
3243 : /* Return whether is ok to try to cache current statement. */
3244 0 : DBUG_RETURN(!(file->s->non_transactional_concurrent_insert &&
3245 : current_data_file_length != actual_data_file_length));
3246 : }
3247 : #endif
3248 :
3249 : static struct st_mysql_sys_var* system_variables[]= {
3250 : MYSQL_SYSVAR(block_size),
3251 : MYSQL_SYSVAR(checkpoint_interval),
3252 : MYSQL_SYSVAR(force_start_after_recovery_failures),
3253 : MYSQL_SYSVAR(page_checksum),
3254 : MYSQL_SYSVAR(log_dir_path),
3255 : MYSQL_SYSVAR(log_file_size),
3256 : MYSQL_SYSVAR(log_purge_type),
3257 : MYSQL_SYSVAR(max_sort_file_size),
3258 : MYSQL_SYSVAR(pagecache_age_threshold),
3259 : MYSQL_SYSVAR(pagecache_buffer_size),
3260 : MYSQL_SYSVAR(pagecache_division_limit),
3261 : MYSQL_SYSVAR(recover),
3262 : MYSQL_SYSVAR(repair_threads),
3263 : MYSQL_SYSVAR(sort_buffer_size),
3264 : MYSQL_SYSVAR(stats_method),
3265 : MYSQL_SYSVAR(sync_log_dir),
3266 : NULL
3267 : };
3268 :
3269 :
3270 : /**
3271 : @brief Updates the checkpoint interval and restarts the background thread.
3272 : */
3273 :
3274 : static void update_checkpoint_interval(MYSQL_THD thd,
3275 : struct st_mysql_sys_var *var,
3276 0 : void *var_ptr, const void *save)
3277 : {
3278 0 : ma_checkpoint_end();
3279 0 : ma_checkpoint_init(*(ulong *)var_ptr= (ulong)(*(long *)save));
3280 : }
3281 :
3282 : /**
3283 : @brief Updates the transaction log file limit.
3284 : */
3285 :
3286 : static void update_log_file_size(MYSQL_THD thd,
3287 : struct st_mysql_sys_var *var,
3288 0 : void *var_ptr, const void *save)
3289 : {
3290 0 : uint32 size= (uint32)((ulong)(*(long *)save));
3291 0 : translog_set_file_size(size);
3292 0 : *(ulong *)var_ptr= size;
3293 : }
3294 :
3295 :
3296 : static SHOW_VAR status_variables[]= {
3297 : {"Maria_pagecache_blocks_not_flushed", (char*) &maria_pagecache_var.global_blocks_changed, SHOW_LONG_NOFLUSH},
3298 : {"Maria_pagecache_blocks_unused", (char*) &maria_pagecache_var.blocks_unused, SHOW_LONG_NOFLUSH},
3299 : {"Maria_pagecache_blocks_used", (char*) &maria_pagecache_var.blocks_used, SHOW_LONG_NOFLUSH},
3300 : {"Maria_pagecache_read_requests", (char*) &maria_pagecache_var.global_cache_r_requests, SHOW_LONGLONG},
3301 : {"Maria_pagecache_reads", (char*) &maria_pagecache_var.global_cache_read, SHOW_LONGLONG},
3302 : {"Maria_pagecache_write_requests", (char*) &maria_pagecache_var.global_cache_w_requests, SHOW_LONGLONG},
3303 : {"Maria_pagecache_writes", (char*) &maria_pagecache_var.global_cache_write, SHOW_LONGLONG},
3304 : {NullS, NullS, SHOW_LONG}
3305 : };
3306 :
3307 : struct st_mysql_storage_engine maria_storage_engine=
3308 : { MYSQL_HANDLERTON_INTERFACE_VERSION };
3309 :
3310 : mysql_declare_plugin(maria)
3311 : {
3312 : MYSQL_STORAGE_ENGINE_PLUGIN,
3313 : &maria_storage_engine,
3314 : "MARIA",
3315 : "MySQL AB",
3316 : "Crash-safe tables with MyISAM heritage",
3317 : PLUGIN_LICENSE_GPL,
3318 : ha_maria_init, /* Plugin Init */
3319 : NULL, /* Plugin Deinit */
3320 : 0x0100, /* 1.0 */
3321 : status_variables, /* status variables */
3322 : system_variables, /* system variables */
3323 : NULL
3324 : }
3325 : mysql_declare_plugin_end;
|