LTP GCOV extension - code coverage report
Current view: directory - storage/maria - ha_maria.cc
Test: maria-mtr.html
Date: 2009-03-04 Instrumented lines: 1135
Code covered: 11.3 % Executed lines: 128

       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              10 :                                      MEM_ROOT *mem_root)
     234                 : {
     235              10 :   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              10 : 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              10 : 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              18 : double ha_maria::scan_time()
     764                 : {
     765              18 :   if (file->s->data_file_type == BLOCK_RECORD)
     766              18 :     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               9 : 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               9 :   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               9 :   if (!(file= maria_open(name, mode, test_if_locked | HA_OPEN_FROM_SQL_LAYER)))
     908               0 :     return (my_errno ? my_errno : -1);
     909                 : 
     910               9 :   if (test_if_locked & (HA_OPEN_IGNORE_IF_LOCKED | HA_OPEN_TMP_TABLE))
     911               9 :     VOID(maria_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0));
     912                 : 
     913               9 :   info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
     914               9 :   if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED))
     915               9 :     VOID(maria_extra(file, HA_EXTRA_WAIT_LOCK, 0));
     916               9 :   if ((data_file_type= file->s->data_file_type) != STATIC_RECORD)
     917               9 :     int_table_flags |= HA_REC_NOT_IN_SEQ;
     918               9 :   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               9 :     int_table_flags|= HA_CAN_INSERT_DELAYED;
     928                 :   }
     929               9 :   if (file->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
     930               0 :     int_table_flags |= HA_HAS_NEW_CHECKSUM;
     931                 : 
     932               9 :   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               9 :   my_errno= 0;
     941               9 :   return my_errno;
     942                 : }
     943                 : 
     944                 : 
     945               9 : int ha_maria::close(void)
     946                 : {
     947               9 :   MARIA_HA *tmp= file;
     948               9 :   file= 0;
     949               9 :   return maria_close(tmp);
     950                 : }
     951                 : 
     952                 : 
     953            1917 : int ha_maria::write_row(uchar * buf)
     954                 : {
     955            1917 :   ha_statistic_increment(&SSV::ha_write_count);
     956                 : 
     957                 :   /* If we have a timestamp column, update it to the current time */
     958            1917 :   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            1917 :   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            1917 :   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(&param);
     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(&param, file);
    1007               0 :   (void) maria_chk_status(&param, file);                // Not fatal
    1008               0 :   error= maria_chk_size(&param, file);
    1009               0 :   if (!error)
    1010               0 :     error|= maria_chk_del(&param, file, param.testflag);
    1011               0 :   if (!error)
    1012               0 :     error= maria_chk_key(&param, 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(&param.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(&param, 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(&param, 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(&param);
    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(&param, file);
    1090               0 :   if (!error)
    1091                 :   {
    1092               0 :     pthread_mutex_lock(&share->intern_lock);
    1093               0 :     error= maria_update_state_info(&param, 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(&param);
    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(&param, 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(&param);
    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(&param, 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(&param);
    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, &param, 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(&param, "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(&param);
    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(&param, 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(&param, 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(&param);
    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, &param, 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, &param, 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(&param);
    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(&param, 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(&param);
    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(&param, 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(&param);
    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, &param, 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, &param, 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              18 : int ha_maria::rnd_init(bool scan)
    2100                 : {
    2101              18 :   if (scan)
    2102               9 :     return maria_scan_init(file);
    2103               9 :   return maria_reset(file);                        // Free buffers
    2104                 : }
    2105                 : 
    2106                 : 
    2107              18 : int ha_maria::rnd_end()
    2108                 : {
    2109                 :   /* Safe to call even if we don't have started a scan */
    2110              18 :   maria_scan_end(file);
    2111              18 :   return 0;
    2112                 : }
    2113                 : 
    2114                 : 
    2115            1926 : int ha_maria::rnd_next(uchar *buf)
    2116                 : {
    2117            1926 :   ha_statistic_increment(&SSV::ha_read_rnd_next_count);
    2118            1926 :   int error= maria_scan(file, buf);
    2119            1926 :   table->status= error ? STATUS_NOT_FOUND : 0;
    2120            1926 :   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            1917 : int ha_maria::rnd_pos(uchar *buf, uchar *pos)
    2138                 : {
    2139            1917 :   ha_statistic_increment(&SSV::ha_read_rnd_count);
    2140            1917 :   int error= maria_rrnd(file, buf, my_get_ptr(pos, ref_length));
    2141            1917 :   table->status= error ? STATUS_NOT_FOUND : 0;
    2142            1917 :   return error;
    2143                 : }
    2144                 : 
    2145                 : 
    2146            1917 : void ha_maria::position(const uchar *record)
    2147                 : {
    2148            1917 :   my_off_t row_position= maria_position(file);
    2149            1917 :   my_store_ptr(ref, ref_length, row_position);
    2150                 : }
    2151                 : 
    2152                 : 
    2153              27 : int ha_maria::info(uint flag)
    2154                 : {
    2155              27 :   return info(flag, table->s->tmp_table == NO_TMP_TABLE);
    2156                 : }
    2157                 : 
    2158              27 : 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              27 :   (void) maria_status(file, &maria_info, flag);
    2164              27 :   if (flag & HA_STATUS_VARIABLE)
    2165                 :   {
    2166              27 :     stats.records=           maria_info.records;
    2167              27 :     stats.deleted=           maria_info.deleted;
    2168              27 :     stats.data_file_length=  maria_info.data_file_length;
    2169              27 :     stats.index_file_length= maria_info.index_file_length;
    2170              27 :     stats.delete_length=     maria_info.delete_length;
    2171              27 :     stats.check_time=        maria_info.check_time;
    2172              27 :     stats.mean_rec_length=   maria_info.mean_reclength;
    2173                 :   }
    2174              27 :   if (flag & HA_STATUS_CONST)
    2175                 :   {
    2176               9 :     TABLE_SHARE *share= table->s;
    2177               9 :     stats.max_data_file_length=  maria_info.max_data_file_length;
    2178               9 :     stats.max_index_file_length= maria_info.max_index_file_length;
    2179               9 :     stats.create_time= maria_info.create_time;
    2180               9 :     ref_length= maria_info.reflength;
    2181               9 :     share->db_options_in_use= maria_info.options;
    2182               9 :     stats.block_size= maria_block_size;
    2183                 : 
    2184                 :     /* Update share */
    2185               9 :     if (lock_table_share)
    2186               0 :       pthread_mutex_lock(&share->mutex);
    2187               9 :     share->keys_in_use.set_prefix(share->keys);
    2188               9 :     share->keys_in_use.intersect_extended(maria_info.key_map);
    2189               9 :     share->keys_for_keyread.intersect(share->keys_in_use);
    2190               9 :     share->db_record_offset= maria_info.record_offset;
    2191               9 :     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               9 :     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               9 :     data_file_name= index_file_name= 0;
    2206                 :     fn_format(name_buff, file->s->open_file_name.str, "", MARIA_NAME_DEXT,
    2207               9 :               MY_APPEND_EXT | MY_UNPACK_FILENAME);
    2208               9 :     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               9 :               MY_APPEND_EXT | MY_UNPACK_FILENAME);
    2212               9 :     if (strcmp(name_buff, maria_info.index_file_name))
    2213               0 :       index_file_name=maria_info.index_file_name;
    2214                 :   }
    2215              27 :   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              27 :   stats.update_time= maria_info.update_time;
    2222              27 :   stats.auto_increment_value= maria_info.auto_increment;
    2223                 : 
    2224              27 :   return 0;
    2225                 : }
    2226                 : 
    2227                 : 
    2228              36 : int ha_maria::extra(enum ha_extra_function operation)
    2229                 : {
    2230              36 :   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              36 :   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              36 :   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               9 : int ha_maria::extra_opt(enum ha_extra_function operation, ulong cache_size)
    2259                 : {
    2260               9 :   if ((specialflag & SPECIAL_SAFE_MODE) && operation == HA_EXTRA_WRITE_CACHE)
    2261               0 :     return 0;
    2262               9 :   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               9 : int ha_maria::delete_table(const char *name)
    2286                 : {
    2287               9 :   THD *thd= current_thd;
    2288                 :   (void) translog_log_debug_info(0, LOGREC_DEBUG_INFO_QUERY,
    2289               9 :                                  (uchar*) thd->query, thd->query_length);
    2290               9 :   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             508 : 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             508 :   int error= 0;
    2496                 :   TABLE *table;
    2497             508 :   DBUG_ENTER("ha_maria::implicit_commit");
    2498             508 :   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               0 :     enum prelocked_mode_type prelocked_mode= thd->prelocked_mode;
    2509               0 :     if ((prelocked_mode == NON_PRELOCKED) ||
    2510                 :         (prelocked_mode == PRELOCKED_UNDER_LOCK_TABLES))
    2511                 :     {
    2512               0 :       DBUG_PRINT("info", ("locked_tables, skipping"));
    2513               0 :       DBUG_RETURN(0);
    2514                 :     }
    2515                 :   }
    2516             508 :   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             508 : end:
    2564             508 :   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               4 : 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               4 :           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               5 : static int ha_maria_init(void *p)
    3136                 : {
    3137                 :   int res;
    3138               5 :   const char *log_dir= maria_data_root;
    3139               5 :   maria_hton= (handlerton *)p;
    3140               5 :   maria_hton->state= SHOW_OPTION_YES;
    3141               5 :   maria_hton->db_type= DB_TYPE_UNKNOWN;
    3142               5 :   maria_hton->create= maria_create_handler;
    3143               5 :   maria_hton->panic= maria_hton_panic;
    3144               5 :   maria_hton->commit= maria_commit;
    3145               5 :   maria_hton->rollback= maria_rollback;
    3146               5 :   maria_hton->flush_logs= maria_flush_logs;
    3147               5 :   maria_hton->show_status= maria_show_status;
    3148                 :   /* TODO: decide if we support Maria being used for log tables */
    3149               5 :   maria_hton->flags= HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES;
    3150               5 :   bzero(maria_log_pagecache, sizeof(*maria_log_pagecache));
    3151               5 :   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               5 :     ma_checkpoint_init(checkpoint_interval);
    3167               5 :   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               5 :   maria_test_invalid_symlink= test_if_data_home_dir;
    3172                 : #endif
    3173               5 :   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;

Generated by: LTP GCOV extension version 1.4