LTP GCOV extension - code coverage report
Current view: directory - storage/maria - maria_chk.c
Test: maria-unit-test.html
Date: 2009-03-04 Instrumented lines: 767
Code covered: 43.0 % Executed lines: 330

       1                 : /* Copyright (C) 2006-2003 MySQL AB
       2                 : 
       3                 :    This program is free software; you can redistribute it and/or modify
       4                 :    it under the terms of the GNU General Public License as published by
       5                 :    the Free Software Foundation; version 2 of the License.
       6                 : 
       7                 :    This program is distributed in the hope that it will be useful,
       8                 :    but WITHOUT ANY WARRANTY; without even the implied warranty of
       9                 :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      10                 :    GNU General Public License for more details.
      11                 : 
      12                 :    You should have received a copy of the GNU General Public License
      13                 :    along with this program; if not, write to the Free Software
      14                 :    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
      15                 : 
      16                 : /* Describe, check and repair of MARIA tables */
      17                 : 
      18                 : #include "ma_fulltext.h"
      19                 : #include <myisamchk.h>
      20                 : #include <my_bit.h>
      21                 : #include <m_ctype.h>
      22                 : #include <stdarg.h>
      23                 : #include <my_getopt.h>
      24                 : #ifdef HAVE_SYS_VADVICE_H
      25                 : #include <sys/vadvise.h>
      26                 : #endif
      27                 : #ifdef HAVE_SYS_MMAN_H
      28                 : #include <sys/mman.h>
      29                 : #endif
      30                 : SET_STACK_SIZE(9000)                    /* Minimum stack size for program */
      31                 : 
      32                 : #ifndef USE_RAID
      33                 : #define my_raid_create(A,B,C,D,E,F,G) my_create(A,B,C,G)
      34                 : #define my_raid_delete(A,B,C) my_delete(A,B)
      35                 : #endif
      36                 : 
      37                 : static uint decode_bits;
      38                 : static char **default_argv;
      39                 : static const char *load_default_groups[]= { "maria_chk", 0 };
      40                 : static const char *set_collation_name, *opt_tmpdir, *opt_log_dir;
      41                 : static CHARSET_INFO *set_collation;
      42                 : static int stopwords_inited= 0;
      43                 : static MY_TMPDIR maria_chk_tmpdir;
      44                 : static my_bool opt_transaction_logging, opt_debug, opt_require_control_file;
      45                 : 
      46                 : static const char *type_names[]=
      47                 : {
      48                 :   "impossible","char","binary", "short", "long", "float",
      49                 :   "double","number","unsigned short",
      50                 :   "unsigned long","longlong","ulonglong","int24",
      51                 :   "uint24","int8","varchar", "varbin", "varchar2", "varbin2", "bit",
      52                 :   "?","?"
      53                 : };
      54                 : 
      55                 : static const char *prefix_packed_txt="packed ",
      56                 :                   *bin_packed_txt="prefix ",
      57                 :                   *diff_txt="stripped ",
      58                 :                   *null_txt="NULL",
      59                 :                   *blob_txt="BLOB ";
      60                 : 
      61                 : static const char *field_pack[]=
      62                 : {
      63                 :   "","no endspace", "no prespace",
      64                 :  "no zeros", "blob", "constant", "table-lockup",
      65                 :  "always zero","varchar","unique-hash","?","?"
      66                 : };
      67                 : 
      68                 : static const char *record_formats[]=
      69                 : {
      70                 :   "Fixed length", "Packed", "Compressed", "Block", "?"
      71                 : };
      72                 : 
      73                 : static const char *maria_stats_method_str="nulls_unequal";
      74                 : static char default_open_errmsg[]=  "%d when opening MARIA-table '%s'";
      75                 : static char default_close_errmsg[]= "%d when closing MARIA-table '%s'";
      76                 : 
      77                 : static void get_options(int *argc,char * * *argv);
      78                 : static void print_version(void);
      79                 : static void usage(void);
      80                 : static int maria_chk(HA_CHECK *param, char *filename);
      81                 : static void descript(HA_CHECK *param, register MARIA_HA *info, char *name);
      82                 : static int maria_sort_records(HA_CHECK *param, register MARIA_HA *info,
      83                 :                               char *name, uint sort_key,
      84                 :                               my_bool write_info, my_bool update_index);
      85                 : static int sort_record_index(MARIA_SORT_PARAM *sort_param, MARIA_PAGE *page,
      86                 :                              uint sortkey, File new_file,
      87                 :                              my_bool update_index);
      88                 : static my_bool write_log_record(HA_CHECK *param);
      89                 : 
      90                 : HA_CHECK check_param;
      91                 : 
      92                 :         /* Main program */
      93                 : 
      94                 : int main(int argc, char **argv)
      95            1743 : {
      96                 :   int error;
      97            1743 :   MY_INIT(argv[0]);
      98                 : 
      99            1743 :   opt_log_dir= maria_data_root= (char *)".";
     100            1743 :   maria_chk_init(&check_param);
     101            1743 :   check_param.opt_lock_memory= 1;               /* Lock memory if possible */
     102            1743 :   check_param.using_global_keycache = 0;
     103            1743 :   get_options(&argc,(char***) &argv);
     104            1743 :   maria_quick_table_bits=decode_bits;
     105            1743 :   error=0;
     106            1743 :   maria_init();
     107                 : 
     108            1743 :   if (ma_control_file_open(FALSE, opt_require_control_file) &&
     109                 :       (opt_require_control_file ||
     110                 :        (opt_transaction_logging && (check_param.testflag & T_REP_ANY))))
     111                 :   {
     112               0 :     error= 1;
     113               0 :     goto end;
     114                 :   }
     115                 : 
     116                 :   /*
     117                 :     If we are doing a repair, user may want to store this repair into the log
     118                 :     so that the log has a complete history and can be used to replay.
     119                 :   */
     120            1743 :   if (opt_transaction_logging && (check_param.testflag & T_REP_ANY))
     121                 :   {
     122               5 :     if (init_pagecache(maria_log_pagecache,
     123                 :                        TRANSLOG_PAGECACHE_SIZE, 0, 0,
     124                 :                        TRANSLOG_PAGE_SIZE, MY_WME) == 0 ||
     125                 :         translog_init(opt_log_dir, TRANSLOG_FILE_SIZE,
     126                 :                       0, 0, maria_log_pagecache,
     127                 :                       TRANSLOG_DEFAULT_FLAGS, 0))
     128                 :     {
     129               0 :       _ma_check_print_error(&check_param,
     130                 :                             "Can't initialize transaction logging. Run "
     131                 :                             "recovery with switch --skip-transaction-log");
     132               0 :       error= 1;
     133               0 :       goto end;
     134                 :     }
     135                 :   }
     136                 : 
     137            3486 :   while (--argc >= 0)
     138                 :   {
     139            1743 :     int new_error=maria_chk(&check_param, *(argv++));
     140            1743 :     if ((check_param.testflag & T_REP_ANY) != T_REP)
     141            1718 :       check_param.testflag&= ~T_REP;
     142            1743 :     VOID(fflush(stdout));
     143            1743 :     VOID(fflush(stderr));
     144            1743 :     if ((check_param.error_printed | check_param.warning_printed) &&
     145                 :         (check_param.testflag & T_FORCE_CREATE) &&
     146                 :         (!(check_param.testflag & (T_REP | T_REP_BY_SORT | T_SORT_RECORDS |
     147                 :                                    T_SORT_INDEX))))
     148                 :     {
     149               0 :       ulonglong old_testflag=check_param.testflag;
     150               0 :       if (!(check_param.testflag & T_REP))
     151               0 :         check_param.testflag|= T_REP_BY_SORT;
     152               0 :       check_param.testflag&= ~T_EXTEND;                     /* Not needed  */
     153               0 :       error|=maria_chk(&check_param, argv[-1]);
     154               0 :       check_param.testflag= old_testflag;
     155               0 :       VOID(fflush(stdout));
     156               0 :       VOID(fflush(stderr));
     157                 :     }
     158                 :     else
     159            1743 :       error|=new_error;
     160            1743 :     if (argc && (!(check_param.testflag & T_SILENT) ||
     161                 :                  check_param.testflag & T_INFO))
     162                 :     {
     163               0 :       puts("\n---------\n");
     164               0 :       VOID(fflush(stdout));
     165                 :     }
     166                 :   }
     167            1743 : end:
     168            1743 :   if (check_param.total_files > 1)
     169                 :   {                                     /* Only if descript */
     170                 :     char buff[22],buff2[22];
     171               0 :     if (!(check_param.testflag & T_SILENT) || check_param.testflag & T_INFO)
     172               0 :       puts("\n---------");
     173               0 :     printf("\nTotal of all %d MARIA-files:\nData records: %9s   Deleted blocks: %9s\n",check_param.total_files,llstr(check_param.total_records,buff),
     174                 :            llstr(check_param.total_deleted,buff2));
     175                 :   }
     176            1743 :   free_defaults(default_argv);
     177            1743 :   free_tmpdir(&maria_chk_tmpdir);
     178            1743 :   maria_end();
     179            1743 :   my_end(check_param.testflag & T_INFO ?
     180                 :          MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR);
     181            1743 :   exit(error);
     182                 : #ifndef _lint
     183                 :   return 0;                             /* No compiler warning */
     184                 : #endif
     185                 : } /* main */
     186                 : 
     187                 : enum options_mc {
     188                 :   OPT_CHARSETS_DIR=256, OPT_SET_COLLATION,OPT_START_CHECK_POS,
     189                 :   OPT_CORRECT_CHECKSUM, OPT_PAGE_BUFFER_SIZE,
     190                 :   OPT_KEY_CACHE_BLOCK_SIZE, OPT_MARIA_BLOCK_SIZE,
     191                 :   OPT_READ_BUFFER_SIZE, OPT_WRITE_BUFFER_SIZE, OPT_SORT_BUFFER_SIZE,
     192                 :   OPT_SORT_KEY_BLOCKS, OPT_DECODE_BITS, OPT_FT_MIN_WORD_LEN,
     193                 :   OPT_FT_MAX_WORD_LEN, OPT_FT_STOPWORD_FILE,
     194                 :   OPT_MAX_RECORD_LENGTH, OPT_AUTO_CLOSE, OPT_STATS_METHOD, OPT_TRANSACTION_LOG,
     195                 :   OPT_SKIP_SAFEMALLOC, OPT_ZEROFILL_KEEP_LSN, OPT_REQUIRE_CONTROL_FILE,
     196                 :   OPT_LOG_DIR, OPT_DATADIR
     197                 : };
     198                 : 
     199                 : static struct my_option my_long_options[] =
     200                 : {
     201                 :   {"analyze", 'a',
     202                 :    "Analyze distribution of keys. Will make some joins in MySQL faster. You can check the calculated distribution.",
     203                 :    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
     204                 : #ifdef __NETWARE__
     205                 :   {"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
     206                 :    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
     207                 : #endif
     208                 :   {"block-search", 'b',
     209                 :    "No help available.",
     210                 :    0, 0, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
     211                 :   {"backup", 'B',
     212                 :    "Make a backup of the .MAD file as 'filename-time.BAK'.",
     213                 :    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
     214                 :   {"character-sets-dir", OPT_CHARSETS_DIR,
     215                 :    "Directory where character sets are.",
     216                 :    (uchar**) &charsets_dir, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
     217                 :   {"check", 'c',
     218                 :    "Check table for errors.",
     219                 :    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
     220                 :   {"check-only-changed", 'C',
     221                 :    "Check only tables that have changed since last check. It also applies to other requested actions (e.g. --analyze will be ignored if the table is already analyzed).",
     222                 :    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
     223                 :   {"correct-checksum", OPT_CORRECT_CHECKSUM,
     224                 :    "Correct checksum information for table.",
     225                 :    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
     226                 : #ifndef DBUG_OFF
     227                 :   {"debug", '#',
     228                 :    "Output debug log. Often this is 'd:t:o,filename'.",
     229                 :    0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
     230                 : #endif
     231                 :   {"description", 'd',
     232                 :    "Prints some information about table.",
     233                 :    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
     234                 :   {"data-file-length", 'D',
     235                 :    "Max length of data file (when recreating data-file when it's full).",
     236                 :    (uchar**) &check_param.max_data_file_length,
     237                 :    (uchar**) &check_param.max_data_file_length,
     238                 :    0, GET_LL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
     239                 :   {"extend-check", 'e',
     240                 :    "If used when checking a table, ensure that the table is 100 percent consistent, which will take a long time. If used when repairing a table, try to recover every possible row from the data file. Normally this will also find a lot of garbage rows; Don't use this option with repair if you are not totally desperate.",
     241                 :    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
     242                 :   {"fast", 'F',
     243                 :    "Check only tables that haven't been closed properly. It also applies to other requested actions (e.g. --analyze will be ignored if the table is already analyzed).",
     244                 :    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
     245                 :   {"force", 'f',
     246                 :    "Restart with -r if there are any errors in the table. States will be updated as with --update-state.",
     247                 :    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
     248                 :   {"HELP", 'H',
     249                 :    "Display this help and exit.",
     250                 :    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
     251                 :   {"help", '?',
     252                 :    "Display this help and exit.",
     253                 :    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
     254                 :   {"information", 'i',
     255                 :    "Print statistics information about table that is checked.",
     256                 :    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
     257                 :   {"keys-used", 'k',
     258                 :    "Tell MARIA to update only some specific keys. # is a bit mask of which keys to use. This can be used to get faster inserts.",
     259                 :    (uchar**) &check_param.keys_in_use,
     260                 :    (uchar**) &check_param.keys_in_use,
     261                 :    0, GET_ULL, REQUIRED_ARG, -1, 0, 0, 0, 0, 0},
     262                 :   {"datadir", OPT_DATADIR,
     263                 :    "Path for control file (and logs if --log-dir not used).",
     264                 :    (uchar**) &maria_data_root, 0, 0, GET_STR, REQUIRED_ARG,
     265                 :    0, 0, 0, 0, 0, 0},
     266                 :   {"log-dir", OPT_LOG_DIR,
     267                 :    "Path for log files.",
     268                 :    (uchar**) &opt_log_dir, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
     269                 :   {"max-record-length", OPT_MAX_RECORD_LENGTH,
     270                 :    "Skip rows bigger than this if maria_chk can't allocate memory to hold it",
     271                 :    (uchar**) &check_param.max_record_length,
     272                 :    (uchar**) &check_param.max_record_length,
     273                 :    0, GET_ULL, REQUIRED_ARG, LONGLONG_MAX, 0, LONGLONG_MAX, 0, 0, 0},
     274                 :   {"medium-check", 'm',
     275                 :    "Faster than extend-check, but only finds 99.99% of all errors. Should be good enough for most cases.",
     276                 :    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
     277                 :   {"quick", 'q', "Faster repair by not modifying the data file.",
     278                 :    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
     279                 :   {"read-only", 'T',
     280                 :    "Don't mark table as checked.",
     281                 :    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
     282                 :   {"recover", 'r',
     283                 :    "Can fix almost anything except unique keys that aren't unique.",
     284                 :    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
     285                 :   {"parallel-recover", 'p',
     286                 :    "Same as '-r' but creates all the keys in parallel.",
     287                 :    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
     288                 :   {"safe-recover", 'o',
     289                 :    "Uses old recovery method; Slower than '-r' but can handle a couple of cases where '-r' reports that it can't fix the data file.",
     290                 :    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
     291                 :   {"sort-recover", 'n',
     292                 :    "Force recovering with sorting even if the temporary file was very big.",
     293                 :    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
     294                 :   { "require-control-file", OPT_REQUIRE_CONTROL_FILE,
     295                 :     "Abort if cannot find control file",
     296                 :     (uchar**)&opt_require_control_file, 0, 0, GET_BOOL, NO_ARG,
     297                 :     0, 0, 0, 0, 0, 0},
     298                 : #ifdef DEBUG
     299                 :   {"start-check-pos", OPT_START_CHECK_POS,
     300                 :    "No help available.",
     301                 :    0, 0, 0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
     302                 : #endif
     303                 :   {"set-auto-increment", 'A',
     304                 :    "Force auto_increment to start at this or higher value. If no value is given, then sets the next auto_increment value to the highest used value for the auto key + 1.",
     305                 :    (uchar**) &check_param.auto_increment_value,
     306                 :    (uchar**) &check_param.auto_increment_value,
     307                 :    0, GET_ULL, OPT_ARG, 0, 0, 0, 0, 0, 0},
     308                 :   {"set-collation", OPT_SET_COLLATION,
     309                 :    "Change the collation used by the index",
     310                 :    (uchar**) &set_collation_name, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
     311                 :   {"set-variable", 'O',
     312                 :    "Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value.",
     313                 :    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
     314                 :   {"silent", 's',
     315                 :    "Only print errors. One can use two -s to make maria_chk very silent.",
     316                 :    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
     317                 : #ifndef DBUG_OFF
     318                 : #ifdef SAFEMALLOC
     319                 :   {"skip-safemalloc", OPT_SKIP_SAFEMALLOC,
     320                 :    "Don't use the memory allocation checking.", 0, 0, 0, GET_NO_ARG, NO_ARG,
     321                 :    0, 0, 0, 0, 0, 0},
     322                 : #endif
     323                 : #endif
     324                 :   {"sort-index", 'S',
     325                 :    "Sort index blocks. This speeds up 'read-next' in applications.",
     326                 :    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
     327                 :   {"sort-records", 'R',
     328                 :    "Sort records according to an index. This makes your data much more localized and may speed up things. (It may be VERY slow to do a sort the first time!)",
     329                 :    (uchar**) &check_param.opt_sort_key,
     330                 :    (uchar**) &check_param.opt_sort_key,
     331                 :    0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
     332                 :   {"tmpdir", 't',
     333                 :    "Path for temporary files.",
     334                 :    (uchar**) &opt_tmpdir,
     335                 :    0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
     336                 :   {"transaction-log", OPT_TRANSACTION_LOG,
     337                 :    "Log repair command to transaction log",
     338                 :    (uchar**) &opt_transaction_logging, (uchar**) &opt_transaction_logging,
     339                 :    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
     340                 :   {"update-state", 'U',
     341                 :    "Mark tables as crashed if any errors were found.",
     342                 :    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
     343                 :   {"unpack", 'u',
     344                 :    "Unpack file packed with mariapack.",
     345                 :    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
     346                 :   {"verbose", 'v',
     347                 :    "Print more information. This can be used with --description and --check. Use many -v for more verbosity!",
     348                 :    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
     349                 :   {"version", 'V', "Print version and exit.",
     350                 :    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
     351                 :   {"wait", 'w', "Wait if table is locked.",
     352                 :    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
     353                 :   { "page_buffer_size", OPT_PAGE_BUFFER_SIZE,
     354                 :     "Size of page buffer. Used by --safe-repair",
     355                 :     (uchar**) &check_param.use_buffers, (uchar**) &check_param.use_buffers, 0,
     356                 :     GET_ULONG, REQUIRED_ARG, (long) USE_BUFFER_INIT, 1024L*1024L,
     357                 :     (long) ~0L, (long) MALLOC_OVERHEAD, (long) IO_SIZE, 0},
     358                 :   { "read_buffer_size", OPT_READ_BUFFER_SIZE, "",
     359                 :     (uchar**) &check_param.read_buffer_length,
     360                 :     (uchar**) &check_param.read_buffer_length, 0, GET_ULONG, REQUIRED_ARG,
     361                 :     (long) READ_BUFFER_INIT, (long) MALLOC_OVERHEAD,
     362                 :     (long) ~0L, (long) MALLOC_OVERHEAD, (long) 1L, 0},
     363                 :   { "write_buffer_size", OPT_WRITE_BUFFER_SIZE, "",
     364                 :     (uchar**) &check_param.write_buffer_length,
     365                 :     (uchar**) &check_param.write_buffer_length, 0, GET_ULONG, REQUIRED_ARG,
     366                 :     (long) READ_BUFFER_INIT, (long) MALLOC_OVERHEAD,
     367                 :     (long) ~0L, (long) MALLOC_OVERHEAD, (long) 1L, 0},
     368                 :   { "sort_buffer_size", OPT_SORT_BUFFER_SIZE,
     369                 :     "Size of sort buffer. Used by --recover",
     370                 :     (uchar**) &check_param.sort_buffer_length,
     371                 :     (uchar**) &check_param.sort_buffer_length, 0, GET_ULONG, REQUIRED_ARG,
     372                 :     (long) SORT_BUFFER_INIT, (long) (MIN_SORT_BUFFER + MALLOC_OVERHEAD),
     373                 :     (long) ~0L, (long) MALLOC_OVERHEAD, (long) 1L, 0},
     374                 :   { "sort_key_blocks", OPT_SORT_KEY_BLOCKS, "",
     375                 :     (uchar**) &check_param.sort_key_blocks,
     376                 :     (uchar**) &check_param.sort_key_blocks, 0, GET_ULONG, REQUIRED_ARG,
     377                 :     BUFFERS_WHEN_SORTING, 4L, 100L, 0L, 1L, 0},
     378                 :   { "decode_bits", OPT_DECODE_BITS, "", (uchar**) &decode_bits,
     379                 :     (uchar**) &decode_bits, 0, GET_UINT, REQUIRED_ARG, 9L, 4L, 17L, 0L, 1L, 0},
     380                 :   { "ft_min_word_len", OPT_FT_MIN_WORD_LEN, "", (uchar**) &ft_min_word_len,
     381                 :     (uchar**) &ft_min_word_len, 0, GET_ULONG, REQUIRED_ARG, 4, 1, HA_FT_MAXCHARLEN,
     382                 :     0, 1, 0},
     383                 :   { "ft_max_word_len", OPT_FT_MAX_WORD_LEN, "", (uchar**) &ft_max_word_len,
     384                 :     (uchar**) &ft_max_word_len, 0, GET_ULONG, REQUIRED_ARG, HA_FT_MAXCHARLEN, 10,
     385                 :     HA_FT_MAXCHARLEN, 0, 1, 0},
     386                 :   { "maria_ft_stopword_file", OPT_FT_STOPWORD_FILE,
     387                 :     "Use stopwords from this file instead of built-in list.",
     388                 :     (uchar**) &ft_stopword_file, (uchar**) &ft_stopword_file, 0, GET_STR,
     389                 :     REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
     390                 :   { "stats_method", OPT_STATS_METHOD,
     391                 :     "Specifies how index statistics collection code should treat NULLs. "
     392                 :     "Possible values of name are \"nulls_unequal\" (default behavior for 4.1/5.0), "
     393                 :     "\"nulls_equal\" (emulate 4.0 behavior), and \"nulls_ignored\".",
     394                 :    (uchar**) &maria_stats_method_str, (uchar**) &maria_stats_method_str, 0,
     395                 :     GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
     396                 :   { "zerofill", 'z',
     397                 :     "Fill empty space in data and index files with zeroes",
     398                 :     0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
     399                 :   { "zerofill-keep-lsn", OPT_ZEROFILL_KEEP_LSN,
     400                 :     "Like --zerofill but does not zero out LSN of data/index pages;"
     401                 :     " used only for testing and debugging",
     402                 :     0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
     403                 :   { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
     404                 : };
     405                 : 
     406                 : 
     407                 : #include <help_start.h>
     408                 : 
     409                 : static void print_version(void)
     410               0 : {
     411               0 :   printf("%s  Ver 1.0 for %s at %s\n", my_progname, SYSTEM_TYPE,
     412                 :          MACHINE_TYPE);
     413                 :   NETWARE_SET_SCREEN_MODE(1);
     414                 : }
     415                 : 
     416                 : 
     417                 : static void usage(void)
     418               0 : {
     419               0 :   print_version();
     420               0 :   puts("By Monty, for your professional use");
     421               0 :   puts("This software comes with NO WARRANTY: see the PUBLIC for details.\n");
     422               0 :   puts("Description, check and repair of MARIA tables.");
     423               0 :   puts("Used without options all tables on the command will be checked for errors");
     424               0 :   printf("Usage: %s [OPTIONS] tables[.MAI]\n", my_progname_short);
     425               0 :   printf("\nGlobal options:\n");
     426                 : #ifndef DBUG_OFF
     427               0 :   printf("\
     428                 :   -#, --debug=...     Output debug log. Often this is 'd:t:o,filename'.\n");
     429                 : #endif
     430               0 :   printf("\
     431                 :   -?, --help          Display this help and exit.\n\
     432                 :   -O, --set-variable var=option.\n\
     433                 :                       Change the value of a variable. Please note that\n\
     434                 :                       this option is deprecated; you can set variables\n\
     435                 :                       directly with '--variable-name=value'.\n\
     436                 :   -t, --tmpdir=path   Path for temporary files. Multiple paths can be\n\
     437                 :                       specified, separated by ");
     438                 : #if defined( __WIN__) || defined(__NETWARE__)
     439                 :    printf("semicolon (;)");
     440                 : #else
     441               0 :    printf("colon (:)");
     442                 : #endif
     443               0 :                       printf(", they will be used\n\
     444                 :                       in a round-robin fashion.\n\
     445                 :   --require-control-file  Abort if we can't find/read the maria_log_control\n\
     446                 :                           file\n\
     447                 :   -s, --silent        Only print errors.  One can use two -s to make\n\
     448                 :                       maria_chk very silent.\n\
     449                 :   -v, --verbose       Print more information. This can be used with\n\
     450                 :                       --description and --check. Use many -v for more verbosity.\n\
     451                 :   -V, --version       Print version and exit.\n\
     452                 :   -w, --wait          Wait if table is locked.\n\n");
     453                 : #ifdef DEBUG
     454                 :   puts("  --start-check-pos=# Start reading file at given offset.\n");
     455                 : #endif
     456                 : 
     457               0 :   puts("Check options (check is the default action for maria_chk):\n\
     458                 :   -c, --check         Check table for errors.\n\
     459                 :   -e, --extend-check  Check the table VERY throughly.  Only use this in\n\
     460                 :                       extreme cases as maria_chk should normally be able to\n\
     461                 :                       find out if the table is ok even without this switch.\n\
     462                 :   -F, --fast          Check only tables that haven't been closed properly.\n\
     463                 :   -C, --check-only-changed\n\
     464                 :                       Check only tables that have changed since last check.\n\
     465                 :   -f, --force         Restart with '-r' if there are any errors in the table.\n\
     466                 :                       States will be updated as with '--update-state'.\n\
     467                 :   -i, --information   Print statistics information about table that is checked.\n\
     468                 :   -m, --medium-check  Faster than extend-check, but only finds 99.99% of\n\
     469                 :                       all errors.  Should be good enough for most cases.\n\
     470                 :   -U  --update-state  Mark tables as crashed if you find any errors.\n\
     471                 :   -T, --read-only     Don't mark table as checked.\n");
     472                 : 
     473               0 :   puts("Recover (repair)/ options (When using '-r' or '-o'):\n\
     474                 :   -B, --backup        Make a backup of the .MAD file as 'filename-time.BAK'.\n\
     475                 :   --correct-checksum  Correct checksum information for table.\n\
     476                 :   -D, --data-file-length=#  Max length of data file (when recreating data\n\
     477                 :                       file when it's full).\n\
     478                 :   -e, --extend-check  Try to recover every possible row from the data file\n\
     479                 :                       Normally this will also find a lot of garbage rows;\n\
     480                 :                       Don't use this option if you are not totally desperate.\n\
     481                 :   -f, --force         Overwrite old temporary files.\n\
     482                 :   -k, --keys-used=#   Tell MARIA to update only some specific keys. # is a\n\
     483                 :                       bit mask of which keys to use. This can be used to\n\
     484                 :                       get faster inserts.\n\
     485                 :   --max-record-length=#\n\
     486                 :                       Skip rows bigger than this if maria_chk can't allocate\n\
     487                 :                       memory to hold it.\n\
     488                 :   -r, --recover       Can fix almost anything except unique keys that aren't\n\
     489                 :                       unique.\n\
     490                 :   -n, --sort-recover  Forces recovering with sorting even if the temporary\n\
     491                 :                       file would be very big.\n\
     492                 :   -p, --parallel-recover\n\
     493                 :                       Uses the same technique as '-r' and '-n', but creates\n\
     494                 :                       all the keys in parallel, in different threads.");
     495               0 :   puts("\
     496                 :   -o, --safe-recover  Uses old recovery method; Slower than '-r' but can\n \
     497                 :                       handle a couple of cases where '-r' reports that it\n\
     498                 :                       can't fix the data file.\n\
     499                 :   --transaction-log   Log repair command to transaction log. This is needed\n\
     500                 :                       if one wants to use the maria_read_log to repeat the \n\
     501                 :                       repair\n\
     502                 :   --character-sets-dir=...\n\
     503                 :                       Directory where character sets are.\n\
     504                 :   --set-collation=name\n\
     505                 :                       Change the collation used by the index.\n\
     506                 :   -q, --quick         Faster repair by not modifying the data file.\n\
     507                 :                       One can give a second '-q' to force maria_chk to\n\
     508                 :                       modify the original datafile in case of duplicate keys.\n\
     509                 :                       NOTE: Tables where the data file is currupted can't be\n\
     510                 :                       fixed with this option.\n\
     511                 :   -u, --unpack        Unpack file packed with mariapack.\n\
     512                 : ");
     513                 : 
     514               0 :   puts("Other actions:\n\
     515                 :   -a, --analyze       Analyze distribution of keys. Will make some joins in\n\
     516                 :                       MySQL faster.  You can check the calculated distribution\n\
     517                 :                       by using '--description --verbose table_name'.\n\
     518                 :   --stats_method=name Specifies how index statistics collection code should\n\
     519                 :                       treat NULLs. Possible values of name are \"nulls_unequal\"\n\
     520                 :                       (default for 4.1/5.0), \"nulls_equal\" (emulate 4.0), and \n\
     521                 :                       \"nulls_ignored\".\n\
     522                 :   -d, --description   Prints some information about table.\n\
     523                 :   -A, --set-auto-increment[=value]\n\
     524                 :                       Force auto_increment to start at this or higher value\n\
     525                 :                       If no value is given, then sets the next auto_increment\n\
     526                 :                       value to the highest used value for the auto key + 1.\n\
     527                 :   -S, --sort-index    Sort index blocks.  This speeds up 'read-next' in\n\
     528                 :                       applications.\n\
     529                 :   -R, --sort-records=#\n\
     530                 :                       Sort records according to an index.  This makes your\n\
     531                 :                       data much more localized and may speed up things\n\
     532                 :                       (It may be VERY slow to do a sort the first time!).\n\
     533                 :   -b,  --block-search=#\n\
     534                 :                       Find a record, a block at given offset belongs to.\n\
     535                 :   -z,  --zerofill     Fill empty space in data and index files with zeroes\n\
     536                 :   --zerofill-keep-lsn Like --zerofill but does not zero out LSN of\n\
     537                 :                       data/index pages.");
     538                 : 
     539               0 :   print_defaults("my", load_default_groups);
     540               0 :   my_print_variables(my_long_options);
     541                 : }
     542                 : 
     543                 : #include <help_end.h>
     544                 : 
     545                 : const char *maria_stats_method_names[] = {"nulls_unequal", "nulls_equal",
     546                 :                                            "nulls_ignored", NullS};
     547                 : TYPELIB maria_stats_method_typelib= {
     548                 :   array_elements(maria_stats_method_names) - 1, "",
     549                 :   maria_stats_method_names, NULL};
     550                 : 
     551                 :          /* Read options */
     552                 : 
     553                 : static my_bool
     554                 : get_one_option(int optid,
     555                 :                const struct my_option *opt __attribute__((unused)),
     556                 :                char *argument)
     557            4701 : {
     558            4701 :   switch (optid) {
     559                 : #ifdef __NETWARE__
     560                 :   case OPT_AUTO_CLOSE:
     561                 :     setscreenmode(SCR_AUTOCLOSE_ON_EXIT);
     562                 :     break;
     563                 : #endif
     564                 :   case 'a':
     565               0 :     if (argument == disabled_my_option)
     566               0 :       check_param.testflag&= ~T_STATISTICS;
     567                 :     else
     568               0 :       check_param.testflag|= T_STATISTICS;
     569                 :     break;
     570                 :   case 'A':
     571               0 :     if (argument)
     572               0 :       check_param.auto_increment_value= strtoull(argument, NULL, 0);
     573                 :     else
     574               0 :       check_param.auto_increment_value= 0;      /* Set to max used value */
     575               0 :     check_param.testflag|= T_AUTO_INC;
     576               0 :     break;
     577                 :   case 'b':
     578               0 :     check_param.search_after_block= strtoul(argument, NULL, 10);
     579               0 :     break;
     580                 :   case 'B':
     581               0 :     if (argument == disabled_my_option)
     582               0 :       check_param.testflag&= ~T_BACKUP_DATA;
     583                 :     else
     584               0 :       check_param.testflag|= T_BACKUP_DATA;
     585                 :     break;
     586                 :   case 'c':
     587               0 :     if (argument == disabled_my_option)
     588               0 :       check_param.testflag&= ~T_CHECK;
     589                 :     else
     590               0 :       check_param.testflag|= T_CHECK;
     591                 :     break;
     592                 :   case 'C':
     593               0 :     if (argument == disabled_my_option)
     594               0 :       check_param.testflag&= ~(T_CHECK | T_CHECK_ONLY_CHANGED);
     595                 :     else
     596               0 :       check_param.testflag|= T_CHECK | T_CHECK_ONLY_CHANGED;
     597                 :     break;
     598                 :   case 'D':
     599               0 :     check_param.max_data_file_length=strtoll(argument, NULL, 10);
     600               0 :     break;
     601                 :   case 's':                             /* silent */
     602            1754 :     if (argument == disabled_my_option)
     603               0 :       check_param.testflag&= ~(T_SILENT | T_VERY_SILENT);
     604                 :     else
     605                 :     {
     606            1754 :       if (check_param.testflag & T_SILENT)
     607             413 :         check_param.testflag|= T_VERY_SILENT;
     608            1754 :       check_param.testflag|= T_SILENT;
     609            1754 :       check_param.testflag&= ~T_WRITE_LOOP;
     610                 :     }
     611                 :     break;
     612                 :   case 'w':
     613               0 :     if (argument == disabled_my_option)
     614               0 :       check_param.testflag&= ~T_WAIT_FOREVER;
     615                 :     else
     616               0 :       check_param.testflag|= T_WAIT_FOREVER;
     617                 :     break;
     618                 :   case 'd':                             /* description if isam-file */
     619             804 :     if (argument == disabled_my_option)
     620               0 :       check_param.testflag&= ~T_DESCRIPT;
     621                 :     else
     622             804 :       check_param.testflag|= T_DESCRIPT;
     623                 :     break;
     624                 :   case 'e':                             /* extend check */
     625             482 :     if (argument == disabled_my_option)
     626               0 :       check_param.testflag&= ~T_EXTEND;
     627                 :     else
     628             482 :       check_param.testflag|= T_EXTEND;
     629                 :     break;
     630                 :   case 'i':
     631               0 :     if (argument == disabled_my_option)
     632               0 :       check_param.testflag&= ~T_INFO;
     633                 :     else
     634               0 :       check_param.testflag|= T_INFO;
     635                 :     break;
     636                 :   case 'f':
     637               0 :     if (argument == disabled_my_option)
     638                 :     {
     639               0 :       check_param.tmpfile_createflag= O_RDWR | O_TRUNC | O_EXCL;
     640               0 :       check_param.testflag&= ~(T_FORCE_CREATE | T_UPDATE_STATE);
     641                 :     }
     642                 :     else
     643                 :     {
     644               0 :       check_param.tmpfile_createflag= O_RDWR | O_TRUNC;
     645               0 :       check_param.testflag|= T_FORCE_CREATE | T_UPDATE_STATE;
     646                 :     }
     647                 :     break;
     648                 :   case 'F':
     649               0 :     if (argument == disabled_my_option)
     650               0 :       check_param.testflag&= ~T_FAST;
     651                 :     else
     652               0 :       check_param.testflag|= T_FAST;
     653                 :     break;
     654                 :   case 'k':
     655               0 :     check_param.keys_in_use= (ulonglong) strtoll(argument, NULL, 10);
     656               0 :     break;
     657                 :   case 'm':
     658             188 :     if (argument == disabled_my_option)
     659               0 :       check_param.testflag&= ~T_MEDIUM;
     660                 :     else
     661             188 :       check_param.testflag|= T_MEDIUM;          /* Medium check */
     662                 :     break;
     663                 :   case 'r':                             /* Repair table */
     664              80 :     check_param.testflag&= ~T_REP_ANY;
     665              80 :     if (argument != disabled_my_option)
     666              80 :       check_param.testflag|= T_REP_BY_SORT;
     667                 :     break;
     668                 :   case 'p':
     669              25 :     check_param.testflag&= ~T_REP_ANY;
     670              25 :     if (argument != disabled_my_option)
     671              25 :       check_param.testflag|= T_REP_PARALLEL;
     672                 :     break;
     673                 :   case 'o':
     674              25 :     check_param.testflag&= ~T_REP_ANY;
     675              25 :     check_param.force_sort= 0;
     676              25 :     if (argument != disabled_my_option)
     677                 :     {
     678              25 :       check_param.testflag|= T_REP;
     679              25 :       my_disable_async_io= 1;           /* More safety */
     680                 :     }
     681                 :     break;
     682                 :   case 'n':
     683               0 :     check_param.testflag&= ~T_REP_ANY;
     684               0 :     if (argument == disabled_my_option)
     685               0 :       check_param.force_sort= 0;
     686                 :     else
     687                 :     {
     688               0 :       check_param.testflag|= T_REP_BY_SORT;
     689               0 :       check_param.force_sort= 1;
     690                 :     }
     691                 :     break;
     692                 :   case 'q':
     693              35 :     if (argument == disabled_my_option)
     694               0 :       check_param.testflag&= ~(T_QUICK | T_FORCE_UNIQUENESS);
     695                 :     else
     696              35 :       check_param.testflag|=
     697                 :         (check_param.testflag & T_QUICK) ? T_FORCE_UNIQUENESS : T_QUICK;
     698                 :     break;
     699                 :   case 'u':
     700              25 :     if (argument == disabled_my_option)
     701               0 :       check_param.testflag&= ~T_UNPACK;
     702                 :     else
     703                 :     {
     704              25 :       check_param.testflag|= T_UNPACK;
     705              25 :       if (!(check_param.testflag & T_REP_ANY))
     706              10 :         check_param.testflag|= T_REP_BY_SORT;
     707                 :     }
     708                 :     break;
     709                 :   case 'v':                             /* Verbose */
     710             804 :     if (argument == disabled_my_option)
     711                 :     {
     712               0 :       check_param.testflag&= ~T_VERBOSE;
     713               0 :       check_param.verbose=0;
     714                 :     }
     715                 :     else
     716                 :     {
     717             804 :       check_param.testflag|= T_VERBOSE;
     718             804 :       check_param.verbose++;
     719                 :     }
     720                 :     break;
     721                 :   case 'R':                             /* Sort records */
     722               0 :     if (argument == disabled_my_option)
     723               0 :       check_param.testflag&= ~T_SORT_RECORDS;
     724                 :     else
     725                 :     {
     726               0 :       check_param.testflag|= T_SORT_RECORDS;
     727               0 :       check_param.opt_sort_key= (uint) atoi(argument) - 1;
     728               0 :       if (check_param.opt_sort_key >= MARIA_MAX_KEY)
     729                 :       {
     730               0 :         fprintf(stderr,
     731                 :                 "The value of the sort key is bigger than max key: %d.\n",
     732                 :                 MARIA_MAX_KEY);
     733               0 :         exit(1);
     734                 :       }
     735                 :     }
     736                 :     break;
     737                 :   case 'S':                           /* Sort index */
     738               0 :     if (argument == disabled_my_option)
     739               0 :       check_param.testflag&= ~T_SORT_INDEX;
     740                 :     else
     741               0 :       check_param.testflag|= T_SORT_INDEX;
     742                 :     break;
     743                 :   case 'T':
     744             300 :     if (argument == disabled_my_option)
     745               0 :       check_param.testflag&= ~T_READONLY;
     746                 :     else
     747             300 :       check_param.testflag|= T_READONLY;
     748                 :     break;
     749                 :   case 'U':
     750               0 :     if (argument == disabled_my_option)
     751               0 :       check_param.testflag&= ~T_UPDATE_STATE;
     752                 :     else
     753               0 :       check_param.testflag|= T_UPDATE_STATE;
     754                 :     break;
     755                 :   case '#':
     756               0 :     DBUG_SET_INITIAL(argument ? argument : "d:t:o,/tmp/maria_chk.trace");
     757               0 :     opt_debug= 1;
     758               0 :     break;
     759                 :   case OPT_SKIP_SAFEMALLOC:
     760                 : #ifdef SAFEMALLOC
     761               0 :     sf_malloc_quick=1;
     762                 : #endif
     763               0 :     break;
     764                 :   case 'V':
     765               0 :     print_version();
     766               0 :     exit(0);
     767                 :   case OPT_CORRECT_CHECKSUM:
     768              20 :     if (argument == disabled_my_option)
     769               0 :       check_param.testflag&= ~T_CALC_CHECKSUM;
     770                 :     else
     771              20 :       check_param.testflag|= T_CALC_CHECKSUM;
     772                 :     break;
     773                 :   case OPT_STATS_METHOD:
     774                 :   {
     775                 :     int method;
     776                 :     enum_handler_stats_method method_conv;
     777               0 :     LINT_INIT(method_conv);
     778               0 :     maria_stats_method_str= argument;
     779               0 :     if ((method=find_type(argument, &maria_stats_method_typelib, 2)) <= 0)
     780                 :     {
     781               0 :       fprintf(stderr, "Invalid value of stats_method: %s.\n", argument);
     782               0 :       exit(1);
     783                 :     }
     784               0 :     switch (method-1) {
     785                 :     case 0:
     786               0 :       method_conv= MI_STATS_METHOD_NULLS_EQUAL;
     787               0 :       break;
     788                 :     case 1:
     789               0 :       method_conv= MI_STATS_METHOD_NULLS_NOT_EQUAL;
     790               0 :       break;
     791                 :     case 2:
     792               0 :       method_conv= MI_STATS_METHOD_IGNORE_NULLS;
     793               0 :       break;
     794               0 :     default: assert(0);                         /* Impossible */
     795                 :     }
     796               0 :     check_param.stats_method= method_conv;
     797               0 :     break;
     798                 :   }
     799                 : #ifdef DEBUG                                    /* Only useful if debugging */
     800                 :   case OPT_START_CHECK_POS:
     801                 :     check_param.start_check_pos= strtoull(argument, NULL, 0);
     802                 :     break;
     803                 : #endif
     804                 :   case 'z':
     805              10 :     if (argument == disabled_my_option)
     806               0 :       check_param.testflag&= ~T_ZEROFILL;
     807                 :     else
     808              10 :       check_param.testflag|= T_ZEROFILL;
     809                 :     break;
     810                 :   case OPT_ZEROFILL_KEEP_LSN:
     811             144 :     if (argument == disabled_my_option)
     812               0 :       check_param.testflag&= ~(T_ZEROFILL_KEEP_LSN | T_ZEROFILL);
     813                 :     else
     814             144 :       check_param.testflag|= (T_ZEROFILL_KEEP_LSN | T_ZEROFILL);
     815                 :     break;
     816                 :   case 'H':
     817               0 :     my_print_help(my_long_options);
     818               0 :     exit(0);
     819                 :   case '?':
     820               0 :     usage();
     821               0 :     exit(0);
     822                 :   }
     823            4701 :   return 0;
     824                 : }
     825                 : 
     826                 : 
     827                 : static void get_options(register int *argc,register char ***argv)
     828            1743 : {
     829                 :   int ho_error;
     830                 : 
     831            1743 :   load_defaults("my", load_default_groups, argc, argv);
     832            1743 :   default_argv= *argv;
     833            1743 :   if (isatty(fileno(stdout)))
     834               0 :     check_param.testflag|=T_WRITE_LOOP;
     835                 : 
     836            1743 :   if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
     837               0 :     exit(ho_error);
     838                 : 
     839                 :   /* If using repair, then update checksum if one uses --update-state */
     840            1743 :   if ((check_param.testflag & T_UPDATE_STATE) &&
     841                 :       (check_param.testflag & T_REP_ANY))
     842               0 :     check_param.testflag|= T_CALC_CHECKSUM;
     843                 : 
     844            1743 :   if (*argc == 0)
     845                 :   {
     846               0 :     usage();
     847               0 :     exit(-1);
     848                 :   }
     849                 : 
     850            1743 :   if ((check_param.testflag & T_UNPACK) &&
     851                 :       (check_param.testflag & (T_QUICK | T_SORT_RECORDS)))
     852                 :   {
     853               0 :     VOID(fprintf(stderr,
     854                 :                  "%s: --unpack can't be used with --quick or --sort-records\n",
     855                 :                  my_progname_short));
     856               0 :     exit(1);
     857                 :   }
     858            1743 :   if ((check_param.testflag & T_READONLY) &&
     859                 :       (check_param.testflag &
     860                 :        (T_REP_ANY | T_STATISTICS | T_AUTO_INC |
     861                 :         T_SORT_RECORDS | T_SORT_INDEX | T_FORCE_CREATE)))
     862                 :   {
     863               0 :     VOID(fprintf(stderr,
     864                 :                  "%s: Can't use --readonly when repairing or sorting\n",
     865                 :                  my_progname_short));
     866               0 :     exit(1);
     867                 :   }
     868                 : 
     869            1743 :   if (!opt_debug)
     870                 :   {
     871            1743 :     DEBUGGER_OFF;                               /* Speed up things a bit */
     872                 :   }
     873            1743 :   if (init_tmpdir(&maria_chk_tmpdir, opt_tmpdir))
     874               0 :     exit(1);
     875                 : 
     876            1743 :   check_param.tmpdir=&maria_chk_tmpdir;
     877                 : 
     878            1743 :   if (set_collation_name)
     879               0 :     if (!(set_collation= get_charset_by_name(set_collation_name,
     880                 :                                              MYF(MY_WME))))
     881               0 :       exit(1);
     882                 : 
     883                 :   return;
     884                 : } /* get options */
     885                 : 
     886                 : 
     887                 :         /* Check table */
     888                 : 
     889                 : static int maria_chk(HA_CHECK *param, char *filename)
     890            1743 : {
     891                 :   int error,lock_type,recreate;
     892            1743 :   my_bool rep_quick= test(param->testflag & (T_QUICK | T_FORCE_UNIQUENESS));
     893                 :   MARIA_HA *info;
     894                 :   File datafile;
     895                 :   char llbuff[22],llbuff2[22];
     896            1743 :   my_bool state_updated=0;
     897                 :   MARIA_SHARE *share;
     898            1743 :   DBUG_ENTER("maria_chk");
     899                 : 
     900            1743 :   param->out_flag=error=param->warning_printed=param->error_printed=
     901                 :     recreate=0;
     902            1743 :   datafile=0;
     903            1743 :   param->isam_file_name=filename;            /* For error messages */
     904            1743 :   if (!(info=maria_open(filename,
     905                 :                         (param->testflag & (T_DESCRIPT | T_READONLY)) ?
     906                 :                         O_RDONLY : O_RDWR,
     907                 :                         HA_OPEN_FOR_REPAIR |
     908                 :                         ((param->testflag & T_WAIT_FOREVER) ?
     909                 :                          HA_OPEN_WAIT_IF_LOCKED :
     910                 :                          (param->testflag & T_DESCRIPT) ?
     911                 :                          HA_OPEN_IGNORE_IF_LOCKED : HA_OPEN_ABORT_IF_LOCKED))))
     912                 :   {
     913                 :     /* Avoid twice printing of isam file name */
     914               0 :     param->error_printed=1;
     915               0 :     switch (my_errno) {
     916                 :     case HA_ERR_CRASHED:
     917               0 :       _ma_check_print_error(param,"'%s' doesn't have a correct index definition. You need to recreate it before you can do a repair",filename);
     918               0 :       break;
     919                 :     case HA_ERR_NOT_A_TABLE:
     920               0 :       _ma_check_print_error(param,"'%s' is not a MARIA-table",filename);
     921               0 :       break;
     922                 :     case HA_ERR_CRASHED_ON_USAGE:
     923               0 :       _ma_check_print_error(param,"'%s' is marked as crashed",filename);
     924               0 :       break;
     925                 :     case HA_ERR_CRASHED_ON_REPAIR:
     926               0 :       _ma_check_print_error(param,"'%s' is marked as crashed after last repair",filename);
     927               0 :       break;
     928                 :     case HA_ERR_OLD_FILE:
     929               0 :       _ma_check_print_error(param,"'%s' is a old type of MARIA-table", filename);
     930               0 :       break;
     931                 :     case HA_ERR_NEW_FILE:
     932               0 :       _ma_check_print_error(param,"'%s' uses new features not supported by this version of the MARIA library", filename);
     933               0 :       break;
     934                 :     case HA_ERR_END_OF_FILE:
     935               0 :       _ma_check_print_error(param,"Couldn't read complete header from '%s'", filename);
     936               0 :       break;
     937                 :     case EAGAIN:
     938               0 :       _ma_check_print_error(param,"'%s' is locked. Use -w to wait until unlocked",filename);
     939               0 :       break;
     940                 :     case ENOENT:
     941               0 :       _ma_check_print_error(param,"File '%s' doesn't exist",filename);
     942               0 :       break;
     943                 :     case EACCES:
     944               0 :       _ma_check_print_error(param,"You don't have permission to use '%s'",
     945                 :                             filename);
     946               0 :       break;
     947                 :     default:
     948               0 :       _ma_check_print_error(param,"%d when opening MARIA-table '%s'",
     949                 :                   my_errno,filename);
     950                 :       break;
     951                 :     }
     952               0 :     DBUG_RETURN(1);
     953                 :   }
     954            1743 :   share= info->s;
     955            1743 :   share->tot_locks-= share->r_locks;
     956            1743 :   share->r_locks=0;
     957            1743 :   maria_block_size= share->base.block_size;
     958                 : 
     959            1743 :   if (share->data_file_type == BLOCK_RECORD ||
     960                 :       ((param->testflag & T_UNPACK) &&
     961                 :        share->state.header.org_data_file_type == BLOCK_RECORD))
     962                 :   {
     963            1519 :     if (param->testflag & T_SORT_RECORDS)
     964                 :     {
     965               0 :       _ma_check_print_error(param,
     966                 :                             "Record format used by '%s' is is not yet supported with sort-records",
     967                 :                             filename);
     968               0 :       param->error_printed= 0;
     969               0 :       error= 1;
     970               0 :       goto end2;
     971                 :     }
     972                 :     /* We can't do parallell repair with BLOCK_RECORD yet */
     973            1519 :     if (param->testflag & T_REP_PARALLEL)
     974                 :     {
     975              15 :       param->testflag&= ~T_REP_PARALLEL;
     976              15 :       param->testflag|= T_REP_BY_SORT;
     977                 :     }
     978                 :   }
     979                 : 
     980                 :   /*
     981                 :     Skip the checking of the file if:
     982                 :     We are using --fast and the table is closed properly
     983                 :     We are using --check-only-changed-tables and the table hasn't changed
     984                 :   */
     985            1743 :   if (param->testflag & (T_FAST | T_CHECK_ONLY_CHANGED))
     986                 :   {
     987                 :     my_bool need_to_check= (maria_is_crashed(info) ||
     988               0 :                             share->state.open_count != 0);
     989                 : 
     990               0 :     if ((param->testflag & (T_REP_ANY | T_SORT_RECORDS)) &&
     991                 :         ((share->state.changed & (STATE_CHANGED | STATE_CRASHED |
     992                 :                                   STATE_CRASHED_ON_REPAIR) ||
     993                 :           !(param->testflag & T_CHECK_ONLY_CHANGED))))
     994               0 :       need_to_check=1;
     995                 : 
     996               0 :     if (info->s->base.keys && info->state->records)
     997                 :     {
     998               0 :       if ((param->testflag & T_STATISTICS) &&
     999                 :           (share->state.changed & STATE_NOT_ANALYZED))
    1000               0 :         need_to_check=1;
    1001               0 :       if ((param->testflag & T_SORT_INDEX) &&
    1002                 :           (share->state.changed & STATE_NOT_SORTED_PAGES))
    1003               0 :         need_to_check=1;
    1004               0 :       if ((param->testflag & T_REP_BY_SORT) &&
    1005                 :           (share->state.changed & STATE_NOT_OPTIMIZED_KEYS))
    1006               0 :         need_to_check=1;
    1007                 :     }
    1008               0 :     if ((param->testflag & T_CHECK_ONLY_CHANGED) &&
    1009                 :         (share->state.changed & (STATE_CHANGED | STATE_CRASHED |
    1010                 :                                  STATE_CRASHED_ON_REPAIR)))
    1011               0 :       need_to_check=1;
    1012               0 :     if (!need_to_check)
    1013                 :     {
    1014               0 :       if (!(param->testflag & T_SILENT) || param->testflag & T_INFO)
    1015               0 :         printf("MARIA file: %s is already checked\n",filename);
    1016               0 :       if (maria_close(info))
    1017                 :       {
    1018               0 :         _ma_check_print_error(param,"%d when closing MARIA-table '%s'",
    1019                 :                              my_errno,filename);
    1020               0 :         DBUG_RETURN(1);
    1021                 :       }
    1022               0 :       DBUG_RETURN(0);
    1023                 :     }
    1024                 :   }
    1025            1743 :   if ((param->testflag & (T_REP_ANY | T_STATISTICS |
    1026                 :                           T_SORT_RECORDS | T_SORT_INDEX)) &&
    1027                 :       (((param->testflag & T_UNPACK) &&
    1028                 :         share->data_file_type == COMPRESSED_RECORD) ||
    1029                 :        mi_uint2korr(share->state.header.state_info_length) !=
    1030                 :        MARIA_STATE_INFO_SIZE ||
    1031                 :        mi_uint2korr(share->state.header.base_info_length) !=
    1032                 :        MARIA_BASE_INFO_SIZE ||
    1033                 :        maria_is_any_intersect_keys_active(param->keys_in_use, share->base.keys,
    1034                 :                                        ~share->state.key_map) ||
    1035                 :        maria_test_if_almost_full(info) ||
    1036                 :        info->s->state.header.file_version[3] != maria_file_magic[3] ||
    1037                 :        (set_collation &&
    1038                 :         set_collation->number != share->state.header.language)))
    1039                 :   {
    1040              30 :     if (set_collation)
    1041               0 :       param->language= set_collation->number;
    1042              30 :     if (maria_recreate_table(param, &info,filename))
    1043                 :     {
    1044               0 :       VOID(fprintf(stderr,
    1045                 :                    "MARIA-table '%s' is not fixed because of errors\n",
    1046                 :               filename));
    1047               0 :       return(-1);
    1048                 :     }
    1049              30 :     recreate=1;
    1050              30 :     if (!(param->testflag & T_REP_ANY))
    1051                 :     {
    1052               0 :       param->testflag|=T_REP_BY_SORT;                /* if only STATISTICS */
    1053               0 :       if (!(param->testflag & T_SILENT))
    1054               0 :         printf("- '%s' has old table-format. Recreating index\n",filename);
    1055               0 :       rep_quick= 1;
    1056                 :     }
    1057              30 :     share= info->s;
    1058              30 :     share->tot_locks-= share->r_locks;
    1059              30 :     share->r_locks=0;
    1060                 :   }
    1061                 : 
    1062            1743 :   if (param->testflag & T_DESCRIPT)
    1063                 :   {
    1064             804 :     param->total_files++;
    1065             804 :     param->total_records+=info->state->records;
    1066             804 :     param->total_deleted+=info->state->del;
    1067             804 :     descript(param, info, filename);
    1068             804 :     maria_close(info);                          /* Should always succeed */
    1069             804 :     return(0);
    1070                 :   }
    1071                 : 
    1072             939 :   if (!stopwords_inited++)
    1073             939 :     ft_init_stopwords();
    1074                 : 
    1075             939 :   if (!(param->testflag & T_READONLY))
    1076             639 :     lock_type = F_WRLCK;                        /* table is changed */
    1077                 :   else
    1078             300 :     lock_type= F_RDLCK;
    1079             939 :   if (info->lock_type == F_RDLCK)
    1080             370 :     info->lock_type=F_UNLCK;                 /* Read only table */
    1081             939 :   if (_ma_readinfo(info,lock_type,0))
    1082                 :   {
    1083               0 :     _ma_check_print_error(param,"Can't lock indexfile of '%s', error: %d",
    1084                 :                           filename,my_errno);
    1085               0 :     param->error_printed=0;
    1086               0 :     error= 1;
    1087               0 :     goto end2;
    1088                 :   }
    1089                 :   /*
    1090                 :     _ma_readinfo() has locked the table.
    1091                 :     We mark the table as locked (without doing file locks) to be able to
    1092                 :     use functions that only works on locked tables (like row caching).
    1093                 :   */
    1094             939 :   maria_lock_database(info, F_EXTRA_LCK);
    1095             939 :   datafile= info->dfile.file;
    1096             939 :   if (init_pagecache(maria_pagecache, param->use_buffers, 0, 0,
    1097                 :                      maria_block_size, MY_WME) == 0)
    1098                 :   {
    1099               0 :     _ma_check_print_error(param, "Can't initialize page cache with %lu memory",
    1100                 :                           (ulong) param->use_buffers);
    1101               0 :     error= 1;
    1102               0 :     goto end2;
    1103                 :   }
    1104                 : 
    1105             939 :   if (param->testflag & (T_REP_ANY | T_SORT_RECORDS | T_SORT_INDEX |
    1106                 :                          T_ZEROFILL))
    1107                 :   {
    1108                 :     /*
    1109                 :       Mark table as not transactional to avoid logging. Should not be needed,
    1110                 :       maria_repair and maria_zerofill do it already.
    1111                 :     */
    1112             264 :     _ma_tmp_disable_logging_for_table(info, FALSE);
    1113                 : 
    1114             264 :     if (param->testflag & T_REP_ANY)
    1115                 :     {
    1116             110 :       ulonglong tmp=share->state.key_map;
    1117             110 :       maria_copy_keys_active(share->state.key_map, share->base.keys,
    1118                 :                              param->keys_in_use);
    1119             110 :       if (tmp != share->state.key_map)
    1120               0 :         info->update|=HA_STATE_CHANGED;
    1121                 : 
    1122             110 :       if (rep_quick &&
    1123                 :           maria_chk_del(param, info, param->testflag & ~T_VERBOSE))
    1124                 :       {
    1125               0 :         if (param->testflag & T_FORCE_CREATE)
    1126                 :         {
    1127               0 :           rep_quick=0;
    1128               0 :           _ma_check_print_info(param,"Creating new data file\n");
    1129                 :         }
    1130                 :         else
    1131                 :         {
    1132               0 :           error=1;
    1133               0 :           _ma_check_print_error(param,
    1134                 :                                 "Quick-recover aborted; Run recovery without switch 'q'");
    1135                 :         }
    1136                 :       }
    1137                 :     }
    1138             264 :     if (!error)
    1139                 :     {
    1140                 :       /*
    1141                 :         Unless this was only --zerofill-keep-lsn, old REDOs are not
    1142                 :         applicable, tell the server's Recovery to ignore them; we don't
    1143                 :         know what the log's end LSN is now, so we just let the server know
    1144                 :         that it will have to find and store it.
    1145                 :         This is the only case where create_rename_lsn can be a horizon and not
    1146                 :         a LSN.
    1147                 :         If this was only --zerofill-keep-lsn, the table can be used in
    1148                 :         Recovery and especially in this scenario: do a dirty-copy-based backup
    1149                 :         (snapshot-like), --zerofill-keep-lsn on the copies to achieve better
    1150                 :         compression, compress the copies with an external tool, and after a
    1151                 :         restore, Recovery still works (because pages and state still have
    1152                 :         their correct LSNs).
    1153                 :       */
    1154             264 :       if (share->base.born_transactional &&
    1155                 :           ((param->testflag & (T_REP_ANY | T_SORT_RECORDS | T_SORT_INDEX |
    1156                 :                                T_ZEROFILL | T_ZEROFILL_KEEP_LSN)) !=
    1157                 :            (T_ZEROFILL | T_ZEROFILL_KEEP_LSN)))
    1158              48 :         share->state.create_rename_lsn= share->state.is_of_horizon=
    1159                 :           share->state.skip_redo_lsn= LSN_NEEDS_NEW_STATE_LSNS;
    1160                 :     }
    1161             264 :     if (!error && (param->testflag & T_REP_ANY))
    1162                 :     {
    1163             195 :       if ((param->testflag & (T_REP_BY_SORT | T_REP_PARALLEL)) &&
    1164                 :           (maria_is_any_key_active(share->state.key_map) ||
    1165                 :            (rep_quick && !param->keys_in_use && !recreate)) &&
    1166                 :           maria_test_if_sort_rep(info, info->state->records,
    1167                 :                                  info->s->state.key_map,
    1168                 :                                  param->force_sort))
    1169                 :       {
    1170              85 :         if (param->testflag & T_REP_BY_SORT)
    1171              75 :           error=maria_repair_by_sort(param,info,filename,rep_quick);
    1172                 :         else
    1173              10 :           error=maria_repair_parallel(param,info,filename,rep_quick);
    1174              85 :         state_updated=1;
    1175                 :       }
    1176                 :       else
    1177              25 :         error=maria_repair(param, info,filename,rep_quick);
    1178                 :     }
    1179             264 :     if (!error && (param->testflag & T_SORT_RECORDS))
    1180                 :     {
    1181                 :       /*
    1182                 :         The data file is nowadays reopened in the repair code so we should
    1183                 :         soon remove the following reopen-code
    1184                 :       */
    1185                 : #ifndef TO_BE_REMOVED
    1186               0 :       if (param->out_flag & O_NEW_DATA)
    1187                 :       {                 /* Change temp file to org file */
    1188               0 :         VOID(my_close(info->dfile.file, MYF(MY_WME))); /* Close new file */
    1189               0 :         error|=maria_change_to_newfile(filename,MARIA_NAME_DEXT,DATA_TMP_EXT,
    1190                 :                                        MYF(0));
    1191               0 :         if (_ma_open_datafile(info,info->s, NullS, -1))
    1192               0 :           error=1;
    1193               0 :         param->out_flag&= ~O_NEW_DATA; /* We are using new datafile */
    1194               0 :         param->read_cache.file= info->dfile.file;
    1195                 :       }
    1196                 : #endif
    1197               0 :       if (! error)
    1198                 :       {
    1199                 :         uint key;
    1200                 :         /*
    1201                 :           We can't update the index in maria_sort_records if we have a
    1202                 :           prefix compressed or fulltext index
    1203                 :         */
    1204               0 :         my_bool update_index=1;
    1205               0 :         for (key=0 ; key < share->base.keys; key++)
    1206               0 :           if (share->keyinfo[key].flag & (HA_BINARY_PACK_KEY|HA_FULLTEXT))
    1207               0 :             update_index=0;
    1208                 : 
    1209               0 :         error=maria_sort_records(param,info,filename,param->opt_sort_key,
    1210                 :                                  /* what is the following parameter for ? */
    1211                 :                                  (my_bool) !(param->testflag & T_REP),
    1212                 :                                  update_index);
    1213               0 :         datafile= info->dfile.file;  /* This is now locked */
    1214               0 :         if (!error && !update_index)
    1215                 :         {
    1216               0 :           if (param->verbose)
    1217               0 :             puts("Table had a compressed index;  We must now recreate the index");
    1218               0 :           error=maria_repair_by_sort(param,info,filename,1);
    1219                 :         }
    1220                 :       }
    1221                 :     }
    1222             264 :     if (!error && (param->testflag & T_SORT_INDEX))
    1223               0 :       error= maria_sort_index(param,info,filename);
    1224             264 :     if (!error && (param->testflag & T_ZEROFILL))
    1225             154 :       error= maria_zerofill(param, info, filename);
    1226             264 :     if (!error)
    1227             264 :       share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED |
    1228                 :                                STATE_CRASHED_ON_REPAIR);
    1229                 :     else
    1230               0 :       maria_mark_crashed(info);
    1231                 :   }
    1232             675 :   else if ((param->testflag & T_CHECK) || !(param->testflag & T_AUTO_INC))
    1233                 :   {
    1234             675 :     if (!(param->testflag & T_SILENT) || param->testflag & T_INFO)
    1235               0 :       printf("Checking MARIA file: %s\n",filename);
    1236             675 :     if (!(param->testflag & T_SILENT))
    1237               0 :       printf("Data records: %7s   Deleted blocks: %7s\n",
    1238                 :              llstr(info->state->records,llbuff),
    1239                 :              llstr(info->state->del,llbuff2));
    1240             675 :     maria_chk_init_for_check(param, info);
    1241             675 :     error= maria_chk_status(param,info);
    1242             675 :     maria_intersect_keys_active(share->state.key_map, param->keys_in_use);
    1243             675 :     error|= maria_chk_size(param,info);
    1244             675 :     if (!error || !(param->testflag & (T_FAST | T_FORCE_CREATE)))
    1245             675 :       error|=maria_chk_del(param, info,param->testflag);
    1246             675 :     if ((!error || (!(param->testflag & (T_FAST | T_FORCE_CREATE)) &&
    1247                 :                     !param->start_check_pos)))
    1248                 :     {
    1249             675 :       error|=maria_chk_key(param, info);
    1250             675 :       if (!error && (param->testflag & (T_STATISTICS | T_AUTO_INC)))
    1251               0 :         error=maria_update_state_info(param, info,
    1252                 :                                       ((param->testflag & T_STATISTICS) ?
    1253                 :                                        UPDATE_STAT : 0) |
    1254                 :                                       ((param->testflag & T_AUTO_INC) ?
    1255                 :                                        UPDATE_AUTO_INC : 0));
    1256                 :     }
    1257             675 :     if ((!rep_quick && !error) ||
    1258                 :         !(param->testflag & (T_FAST | T_FORCE_CREATE)))
    1259                 :     {
    1260             675 :       VOID(init_io_cache(&param->read_cache,datafile,
    1261                 :                          (uint) param->read_buffer_length,
    1262                 :                          READ_CACHE,
    1263                 :                          (param->start_check_pos ?
    1264                 :                           param->start_check_pos :
    1265                 :                           share->pack.header_length),
    1266                 :                          1,
    1267                 :                          MYF(MY_WME)));
    1268             675 :       maria_lock_memory(param);
    1269             675 :       if ((info->s->data_file_type != STATIC_RECORD) ||
    1270                 :           (param->testflag & (T_EXTEND | T_MEDIUM)))
    1271             675 :         error|=maria_chk_data_link(param, info,
    1272                 :                                    test(param->testflag & T_EXTEND));
    1273             675 :       VOID(end_io_cache(&param->read_cache));
    1274                 :     }
    1275             675 :     if (!error)
    1276                 :     {
    1277             675 :       if ((share->state.changed & STATE_CHANGED) &&
    1278                 :           (param->testflag & T_UPDATE_STATE))
    1279               0 :         info->update|=HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
    1280             675 :       share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED |
    1281                 :                                STATE_CRASHED_ON_REPAIR);
    1282                 :     }
    1283               0 :     else if (!maria_is_crashed(info) &&
    1284                 :              (param->testflag & T_UPDATE_STATE))
    1285                 :     {                                           /* Mark crashed */
    1286               0 :       maria_mark_crashed(info);
    1287               0 :       info->update|=HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
    1288                 :     }
    1289                 :   }
    1290                 : 
    1291             939 :   if ((param->testflag & T_AUTO_INC) ||
    1292                 :       ((param->testflag & T_REP_ANY) && info->s->base.auto_key))
    1293               0 :     _ma_update_auto_increment_key(param, info,
    1294                 :                                   (my_bool) !test(param->testflag & T_AUTO_INC));
    1295                 : 
    1296             939 :   if (info->update & HA_STATE_CHANGED && ! (param->testflag & T_READONLY))
    1297             264 :     error|=maria_update_state_info(param, info,
    1298                 :                                    UPDATE_OPEN_COUNT |
    1299                 :                                    (((param->testflag & T_REP_ANY) ?
    1300                 :                                      UPDATE_TIME : 0) |
    1301                 :                                     (state_updated ? UPDATE_STAT : 0) |
    1302                 :                                     ((param->testflag & T_SORT_RECORDS) ?
    1303                 :                                      UPDATE_SORT : 0)));
    1304             939 :   info->update&= ~HA_STATE_CHANGED;
    1305             939 :   _ma_reenable_logging_for_table(info, FALSE);
    1306             939 :   maria_lock_database(info, F_UNLCK);
    1307                 : 
    1308             939 : end2:
    1309             939 :   end_pagecache(maria_pagecache, 1);
    1310             939 :   if (maria_close(info))
    1311                 :   {
    1312               0 :     _ma_check_print_error(param, default_close_errmsg, my_errno, filename);
    1313               0 :     DBUG_RETURN(1);
    1314                 :   }
    1315             939 :   if (error == 0)
    1316                 :   {
    1317             939 :     if (param->out_flag & O_NEW_DATA)
    1318               0 :       error|=maria_change_to_newfile(filename,MARIA_NAME_DEXT,DATA_TMP_EXT,
    1319                 :                                      ((param->testflag & T_BACKUP_DATA) ?
    1320                 :                                       MYF(MY_REDEL_MAKE_BACKUP) : MYF(0)));
    1321             939 :     if (param->out_flag & O_NEW_INDEX)
    1322               0 :       error|=maria_change_to_newfile(filename,MARIA_NAME_IEXT,INDEX_TMP_EXT,
    1323                 :                                      MYF(0));
    1324                 :   }
    1325             939 :   if (opt_transaction_logging &&
    1326                 :       share->base.born_transactional && !error &&
    1327                 :       (param->testflag & (T_REP_ANY | T_SORT_RECORDS | T_SORT_INDEX |
    1328                 :                           T_ZEROFILL)))
    1329               5 :     error= write_log_record(param);
    1330                 : 
    1331             939 :   if (param->not_visible_rows_found && (param->testflag & T_VERBOSE))
    1332                 :   {
    1333                 :     char buff[22];
    1334               0 :     printf("Max transaction id found: %s\n",
    1335                 :            llstr(param->max_found_trid, buff));
    1336                 :   }
    1337                 : 
    1338             939 :   VOID(fflush(stdout)); VOID(fflush(stderr));
    1339                 : 
    1340             939 :   if (param->error_printed)
    1341                 :   {
    1342               0 :     if (param->testflag & (T_REP_ANY | T_SORT_RECORDS | T_SORT_INDEX))
    1343                 :     {
    1344               0 :       VOID(fprintf(stderr,
    1345                 :                    "MARIA-table '%s' is not fixed because of errors\n",
    1346                 :                    filename));
    1347               0 :       if (param->testflag & T_REP_ANY)
    1348               0 :         VOID(fprintf(stderr,
    1349                 :                      "Try fixing it by using the --safe-recover (-o), the --force (-f) option or by not using the --quick (-q) flag\n"));
    1350                 :     }
    1351               0 :     else if (!(param->error_printed & 2) &&
    1352                 :              !(param->testflag & T_FORCE_CREATE))
    1353               0 :       VOID(fprintf(stderr,
    1354                 :       "MARIA-table '%s' is corrupted\nFix it using switch \"-r\" or \"-o\"\n",
    1355                 :               filename));
    1356                 :   }
    1357             939 :   else if (param->warning_printed &&
    1358                 :            ! (param->testflag & (T_REP_ANY | T_SORT_RECORDS | T_SORT_INDEX |
    1359                 :                           T_FORCE_CREATE)))
    1360               6 :     VOID(fprintf(stderr, "MARIA-table '%s' is usable but should be fixed\n",
    1361                 :                  filename));
    1362             939 :   VOID(fflush(stderr));
    1363             939 :   DBUG_RETURN(error);
    1364                 : } /* maria_chk */
    1365                 : 
    1366                 : 
    1367                 : /* Write info about table */
    1368                 : 
    1369                 : static void descript(HA_CHECK *param, register MARIA_HA *info, char *name)
    1370             804 : {
    1371                 :   uint key,keyseg_nr,field;
    1372                 :   reg3 MARIA_KEYDEF *keyinfo;
    1373                 :   reg2 HA_KEYSEG *keyseg;
    1374                 :   reg4 const char *text;
    1375                 :   char buff[200],length[10],*pos,*end;
    1376                 :   enum en_fieldtype type;
    1377             804 :   MARIA_SHARE *share= info->s;
    1378                 :   char llbuff[22],llbuff2[22];
    1379             804 :   DBUG_ENTER("descript");
    1380                 : 
    1381             804 :   if (param->testflag & T_VERY_SILENT)
    1382                 :   {
    1383             402 :     longlong checksum= info->state->checksum;
    1384             402 :     if (!(share->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)))
    1385               0 :       checksum= 0;
    1386             402 :     printf("%s %s %s\n", name, llstr(info->state->records,llbuff),
    1387                 :            llstr(checksum, llbuff2));
    1388             402 :     DBUG_VOID_RETURN;
    1389                 :   }
    1390                 : 
    1391             402 :   printf("MARIA file:          %s\n",name);
    1392             402 :   printf("Record format:       %s\n", record_formats[share->data_file_type]);
    1393             402 :   printf("Crashsafe:           %s\n",
    1394                 :          share->base.born_transactional ? "yes" : "no");
    1395             402 :   printf("Character set:       %s (%d)\n",
    1396                 :          get_charset_name(share->state.header.language),
    1397                 :          share->state.header.language);
    1398                 : 
    1399             402 :   if (param->testflag & T_VERBOSE)
    1400                 :   {
    1401             402 :     printf("File-version:        %d\n",
    1402                 :            (int) share->state.header.file_version[3]);
    1403             402 :     if (share->state.create_time)
    1404                 :     {
    1405             402 :       get_date(buff,1,share->state.create_time);
    1406             402 :       printf("Creation time:       %s\n",buff);
    1407                 :     }
    1408             402 :     if (share->state.check_time)
    1409                 :     {
    1410               0 :       get_date(buff,1,share->state.check_time);
    1411               0 :       printf("Recover time:        %s\n",buff);
    1412                 :     }
    1413             402 :     if (share->base.born_transactional)
    1414                 :     {
    1415             402 :       printf("LSNs:                create_rename (%lu,0x%lx),"
    1416                 :              " state_horizon (%lu,0x%lx), skip_redo (%lu,0x%lx)\n",
    1417                 :              LSN_IN_PARTS(share->state.create_rename_lsn),
    1418                 :              LSN_IN_PARTS(share->state.is_of_horizon),
    1419                 :              LSN_IN_PARTS(share->state.skip_redo_lsn));
    1420                 :     }
    1421                 :     compile_time_assert((MY_UUID_STRING_LENGTH + 1) <= sizeof(buff));
    1422             402 :     buff[MY_UUID_STRING_LENGTH]= 0;
    1423             402 :     my_uuid2str(share->base.uuid, buff);
    1424             402 :     printf("UUID:                %s\n", buff);
    1425             402 :     pos=buff;
    1426             402 :     if (share->state.changed & STATE_CRASHED)
    1427               0 :       strmov(buff,"crashed");
    1428                 :     else
    1429                 :     {
    1430             402 :       if (share->state.open_count)
    1431               0 :         pos=strmov(pos,"open,");
    1432             402 :       if (share->state.changed & STATE_CHANGED)
    1433             370 :         pos=strmov(pos,"changed,");
    1434                 :       else
    1435              32 :         pos=strmov(pos,"checked,");
    1436             402 :       if (!(share->state.changed & STATE_NOT_ANALYZED))
    1437              32 :         pos=strmov(pos,"analyzed,");
    1438             402 :       if (!(share->state.changed & STATE_NOT_OPTIMIZED_KEYS))
    1439              32 :         pos=strmov(pos,"optimized keys,");
    1440             402 :       if (!(share->state.changed & STATE_NOT_SORTED_PAGES))
    1441              32 :         pos=strmov(pos,"sorted index pages,");
    1442             402 :       if (!(share->state.changed & STATE_NOT_ZEROFILLED))
    1443              32 :         pos=strmov(pos,"zerofilled,");
    1444             402 :       if (!(share->state.changed & STATE_NOT_MOVABLE))
    1445              32 :         pos=strmov(pos,"movable,");
    1446             402 :       pos[-1]=0;                                /* Remove extra ',' */
    1447                 :     }
    1448             402 :     printf("Status:              %s\n",buff);
    1449             402 :     if (share->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
    1450             402 :       printf("Checksum:  %26s\n",llstr(info->state->checksum,llbuff));
    1451                 : ;
    1452             402 :     if (share->options & HA_OPTION_DELAY_KEY_WRITE)
    1453               0 :       printf("Keys are only flushed at close\n");
    1454                 : 
    1455             402 :     if (share->options & HA_OPTION_PAGE_CHECKSUM)
    1456             402 :       printf("Page checksums are used\n");
    1457             402 :     if (share->base.auto_key)
    1458                 :     {
    1459               0 :       printf("Auto increment key:  %16d  Last value:         %18s\n",
    1460                 :              share->base.auto_key,
    1461                 :              llstr(share->state.auto_increment,llbuff));
    1462                 :     }
    1463                 :   }
    1464             402 :   printf("Data records:        %16s  Deleted blocks:     %18s\n",
    1465                 :          llstr(info->state->records,llbuff),llstr(info->state->del,llbuff2));
    1466             402 :   if (param->testflag & T_SILENT)
    1467               0 :     DBUG_VOID_RETURN;                           /* This is enough */
    1468                 : 
    1469             402 :   if (param->testflag & T_VERBOSE)
    1470                 :   {
    1471                 : #ifdef USE_RELOC
    1472                 :     printf("Init-relocation:     %16s\n",llstr(share->base.reloc,llbuff));
    1473                 : #endif
    1474             402 :     printf("Datafile parts:      %16s  Deleted data:       %18s\n",
    1475                 :            llstr(share->state.split,llbuff),
    1476                 :            llstr(info->state->empty,llbuff2));
    1477             402 :     printf("Datafile pointer (bytes): %11d  Keyfile pointer (bytes): %13d\n",
    1478                 :            share->rec_reflength,share->base.key_reflength);
    1479             402 :     printf("Datafile length:     %16s  Keyfile length:     %18s\n",
    1480                 :            llstr(info->state->data_file_length,llbuff),
    1481                 :            llstr(info->state->key_file_length,llbuff2));
    1482                 : 
    1483             402 :     if (info->s->base.reloc == 1L && info->s->base.records == 1L)
    1484               0 :       puts("This is a one-record table");
    1485                 :     else
    1486                 :     {
    1487             402 :       if (share->base.max_data_file_length != HA_OFFSET_ERROR ||
    1488                 :           share->base.max_key_file_length != HA_OFFSET_ERROR)
    1489             402 :         printf("Max datafile length: %16s  Max keyfile length: %18s\n",
    1490                 :                llstr(share->base.max_data_file_length-1,llbuff),
    1491                 :                llstr(share->base.max_key_file_length-1,llbuff2));
    1492                 :     }
    1493                 :   }
    1494             402 :   printf("Block_size:          %16d\n",(int) share->block_size);
    1495             402 :   printf("Recordlength:        %16d\n",(int) share->base.pack_reclength);
    1496             402 :   if (! maria_is_all_keys_active(share->state.key_map, share->base.keys))
    1497                 :   {
    1498               0 :     longlong2str(share->state.key_map,buff,2);
    1499               0 :     printf("Using only keys '%s' of %d possibly keys\n",
    1500                 :            buff, share->base.keys);
    1501                 :   }
    1502             402 :   puts("\ntable description:");
    1503             402 :   printf("Key Start Len Index   Type");
    1504             402 :   if (param->testflag & T_VERBOSE)
    1505             402 :     printf("                     Rec/key         Root  Blocksize");
    1506             402 :   VOID(putchar('\n'));
    1507                 : 
    1508             402 :   for (key=keyseg_nr=0, keyinfo= &share->keyinfo[0] ;
    1509            1906 :        key < share->base.keys;
    1510            1102 :        key++,keyinfo++)
    1511                 :   {
    1512            1102 :     keyseg=keyinfo->seg;
    1513            1102 :     if (keyinfo->flag & HA_NOSAME) text="unique ";
    1514             700 :     else if (keyinfo->flag & HA_FULLTEXT) text="fulltext ";
    1515             700 :     else text="multip.";
    1516                 : 
    1517            1102 :     pos=buff;
    1518            1102 :     if (keyseg->flag & HA_REVERSE_SORT)
    1519             140 :       *pos++ = '-';
    1520            1102 :     pos=strmov(pos,type_names[keyseg->type]);
    1521            1102 :     *pos++ = ' ';
    1522            1102 :     *pos=0;
    1523            1102 :     if (keyinfo->flag & HA_PACK_KEY)
    1524              18 :       pos=strmov(pos,prefix_packed_txt);
    1525            1102 :     if (keyinfo->flag & HA_BINARY_PACK_KEY)
    1526               6 :       pos=strmov(pos,bin_packed_txt);
    1527            1102 :     if (keyseg->flag & HA_SPACE_PACK)
    1528              18 :       pos=strmov(pos,diff_txt);
    1529            1102 :     if (keyseg->flag & HA_BLOB_PART)
    1530             128 :       pos=strmov(pos,blob_txt);
    1531            1102 :     if (keyseg->flag & HA_NULL_PART)
    1532             256 :       pos=strmov(pos,null_txt);
    1533            1102 :     *pos=0;
    1534                 : 
    1535            1102 :     printf("%-4d%-6ld%-3d %-8s%-23s",
    1536                 :            key+1,(long) keyseg->start+1,keyseg->length,text,buff);
    1537            1102 :     if (share->state.key_root[key] != HA_OFFSET_ERROR)
    1538             316 :       llstr(share->state.key_root[key],buff);
    1539                 :     else
    1540             786 :       buff[0]=0;
    1541            1102 :     if (param->testflag & T_VERBOSE)
    1542            1102 :       printf("%9.0f %12s %10d",
    1543                 :              share->state.rec_per_key_part[keyseg_nr++],
    1544                 :              buff,keyinfo->block_length);
    1545            1102 :     VOID(putchar('\n'));
    1546            2344 :     while ((++keyseg)->type != HA_KEYTYPE_END)
    1547                 :     {
    1548             140 :       pos=buff;
    1549             140 :       if (keyseg->flag & HA_REVERSE_SORT)
    1550             140 :         *pos++ = '-';
    1551             140 :       pos=strmov(pos,type_names[keyseg->type]);
    1552             140 :       *pos++= ' ';
    1553             140 :       if (keyseg->flag & HA_SPACE_PACK)
    1554               0 :         pos=strmov(pos,diff_txt);
    1555             140 :       if (keyseg->flag & HA_BLOB_PART)
    1556               0 :         pos=strmov(pos,blob_txt);
    1557             140 :       if (keyseg->flag & HA_NULL_PART)
    1558               0 :         pos=strmov(pos,null_txt);
    1559             140 :       *pos=0;
    1560             140 :       printf("    %-6ld%-3d         %-21s",
    1561                 :              (long) keyseg->start+1,keyseg->length,buff);
    1562             140 :       if (param->testflag & T_VERBOSE)
    1563             140 :         printf("%11.0f", share->state.rec_per_key_part[keyseg_nr++]);
    1564             140 :       VOID(putchar('\n'));
    1565                 :     }
    1566            1102 :     keyseg++;
    1567                 :   }
    1568             402 :   if (share->state.header.uniques)
    1569                 :   {
    1570                 :     MARIA_UNIQUEDEF *uniqueinfo;
    1571               0 :     puts("\nUnique  Key  Start  Len  Nullpos  Nullbit  Type");
    1572               0 :     for (key=0,uniqueinfo= &share->uniqueinfo[0] ;
    1573               0 :          key < share->state.header.uniques; key++, uniqueinfo++)
    1574                 :     {
    1575               0 :       my_bool new_row=0;
    1576                 :       char null_bit[8],null_pos[8];
    1577               0 :       printf("%-8d%-5d",key+1,uniqueinfo->key+1);
    1578               0 :       for (keyseg=uniqueinfo->seg ; keyseg->type != HA_KEYTYPE_END ; keyseg++)
    1579                 :       {
    1580               0 :         if (new_row)
    1581               0 :           fputs("             ",stdout);
    1582               0 :         null_bit[0]=null_pos[0]=0;
    1583               0 :         if (keyseg->null_bit)
    1584                 :         {
    1585               0 :           sprintf(null_bit,"%d",keyseg->null_bit);
    1586               0 :           sprintf(null_pos,"%ld",(long) keyseg->null_pos+1);
    1587                 :         }
    1588               0 :         printf("%-7ld%-5d%-9s%-10s%-30s\n",
    1589                 :                (long) keyseg->start+1,keyseg->length,
    1590                 :                null_pos,null_bit,
    1591                 :                type_names[keyseg->type]);
    1592               0 :         new_row=1;
    1593                 :       }
    1594                 :     }
    1595                 :   }
    1596             402 :   if (param->verbose > 1)
    1597                 :   {
    1598                 :     char null_bit[8],null_pos[8];
    1599             402 :     printf("\nField Start Length Nullpos Nullbit Type");
    1600             402 :     if (share->options & HA_OPTION_COMPRESS_RECORD)
    1601               0 :       printf("                         Huff tree  Bits");
    1602             402 :     VOID(putchar('\n'));
    1603                 : 
    1604            1836 :     for (field=0 ; field < share->base.fields ; field++)
    1605                 :     {
    1606            1434 :       if (share->options & HA_OPTION_COMPRESS_RECORD)
    1607               0 :         type=share->columndef[field].base_type;
    1608                 :       else
    1609            1434 :         type=(enum en_fieldtype) share->columndef[field].type;
    1610            1434 :       end=strmov(buff,field_pack[type]);
    1611            1434 :       if (share->options & HA_OPTION_COMPRESS_RECORD)
    1612                 :       {
    1613               0 :         if (share->columndef[field].pack_type & PACK_TYPE_SELECTED)
    1614               0 :           end=strmov(end,", not_always");
    1615               0 :         if (share->columndef[field].pack_type & PACK_TYPE_SPACE_FIELDS)
    1616               0 :           end=strmov(end,", no empty");
    1617               0 :         if (share->columndef[field].pack_type & PACK_TYPE_ZERO_FILL)
    1618                 :         {
    1619               0 :           sprintf(end,", zerofill(%d)",share->columndef[field].space_length_bits);
    1620               0 :           end=strend(end);
    1621                 :         }
    1622                 :       }
    1623            1434 :       if (buff[0] == ',')
    1624               0 :         strmov(buff,buff+2);
    1625            1434 :       int10_to_str((long) share->columndef[field].length,length,10);
    1626            1434 :       null_bit[0]=null_pos[0]=0;
    1627            1434 :       if (share->columndef[field].null_bit)
    1628                 :       {
    1629             256 :         sprintf(null_bit,"%d",share->columndef[field].null_bit);
    1630             256 :         sprintf(null_pos,"%d",share->columndef[field].null_pos+1);
    1631                 :       }
    1632            1434 :       printf("%-6d%-6u%-7s%-8s%-8s%-35s",field+1,
    1633                 :              (uint) share->columndef[field].offset+1,
    1634                 :              length, null_pos, null_bit, buff);
    1635            1434 :       if (share->options & HA_OPTION_COMPRESS_RECORD)
    1636                 :       {
    1637               0 :         if (share->columndef[field].huff_tree)
    1638               0 :           printf("%3d    %2d",
    1639                 :                  (uint) (share->columndef[field].huff_tree-share->decode_trees)+1,
    1640                 :                  share->columndef[field].huff_tree->quick_table_bits);
    1641                 :       }
    1642            1434 :       VOID(putchar('\n'));
    1643                 :     }
    1644                 :   }
    1645             402 :   DBUG_VOID_RETURN;
    1646                 : } /* describe */
    1647                 : 
    1648                 : 
    1649                 :         /* Sort records according to one key */
    1650                 : 
    1651                 : static int maria_sort_records(HA_CHECK *param,
    1652                 :                            register MARIA_HA *info, char *name,
    1653                 :                            uint sort_key,
    1654                 :                            my_bool write_info,
    1655                 :                            my_bool update_index)
    1656               0 : {
    1657                 :   int got_error;
    1658                 :   uint key;
    1659                 :   MARIA_KEYDEF *keyinfo;
    1660                 :   File new_file;
    1661                 :   uchar *temp_buff;
    1662                 :   ha_rows old_record_count;
    1663               0 :   MARIA_SHARE *share= info->s;
    1664                 :   char llbuff[22],llbuff2[22];
    1665                 :   MARIA_SORT_INFO sort_info;
    1666                 :   MARIA_SORT_PARAM sort_param;
    1667                 :   MARIA_PAGE page;
    1668               0 :   DBUG_ENTER("sort_records");
    1669                 : 
    1670               0 :   bzero((char*)&sort_info,sizeof(sort_info));
    1671               0 :   bzero((char*)&sort_param,sizeof(sort_param));
    1672               0 :   sort_param.sort_info=&sort_info;
    1673               0 :   sort_info.param=param;
    1674               0 :   keyinfo= &share->keyinfo[sort_key];
    1675               0 :   got_error=1;
    1676               0 :   temp_buff=0;
    1677               0 :   new_file= -1;
    1678                 : 
    1679               0 :   if (! maria_is_key_active(share->state.key_map, sort_key))
    1680                 :   {
    1681               0 :     _ma_check_print_warning(param,
    1682                 :                            "Can't sort table '%s' on key %d;  No such key",
    1683                 :                 name,sort_key+1);
    1684               0 :     param->error_printed=0;
    1685               0 :     DBUG_RETURN(0);                             /* Nothing to do */
    1686                 :   }
    1687               0 :   if (keyinfo->flag & HA_FULLTEXT)
    1688                 :   {
    1689               0 :     _ma_check_print_warning(param,"Can't sort table '%s' on FULLTEXT key %d",
    1690                 :                            name,sort_key+1);
    1691               0 :     param->error_printed=0;
    1692               0 :     DBUG_RETURN(0);                             /* Nothing to do */
    1693                 :   }
    1694               0 :   if (keyinfo->flag & HA_BINARY_PACK_KEY)
    1695                 :   {
    1696               0 :     _ma_check_print_warning(param,
    1697                 :                             "Can't sort table '%s' on a key with prefix "
    1698                 :                             "packing %d",
    1699                 :                             name,sort_key+1);
    1700               0 :     param->error_printed=0;
    1701               0 :     DBUG_RETURN(0);
    1702                 :   }
    1703                 : 
    1704                 : 
    1705               0 :   if (share->data_file_type == COMPRESSED_RECORD)
    1706                 :   {
    1707               0 :     _ma_check_print_warning(param,"Can't sort read-only table '%s'", name);
    1708               0 :     param->error_printed=0;
    1709               0 :     DBUG_RETURN(0);                             /* Nothing to do */
    1710                 :   }
    1711               0 :   if (!(param->testflag & T_SILENT))
    1712                 :   {
    1713               0 :     printf("- Sorting records for MARIA-table '%s'\n",name);
    1714               0 :     if (write_info)
    1715               0 :       printf("Data records: %9s   Deleted: %9s\n",
    1716                 :              llstr(info->state->records,llbuff),
    1717                 :              llstr(info->state->del,llbuff2));
    1718                 :   }
    1719               0 :   if (share->state.key_root[sort_key] == HA_OFFSET_ERROR)
    1720               0 :     DBUG_RETURN(0);                             /* Nothing to do */
    1721                 : 
    1722               0 :   if (init_io_cache(&info->rec_cache,-1,(uint) param->write_buffer_length,
    1723                 :                    WRITE_CACHE,share->pack.header_length,1,
    1724                 :                    MYF(MY_WME | MY_WAIT_IF_FULL)))
    1725               0 :     goto err;
    1726               0 :   info->opt_flag|=WRITE_CACHE_USED;
    1727                 : 
    1728               0 :   if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
    1729                 :   {
    1730               0 :     _ma_check_print_error(param,"Not enough memory for key block");
    1731               0 :     goto err;
    1732                 :   }
    1733                 : 
    1734               0 :   if (!(sort_param.record=
    1735                 :         (uchar*) my_malloc((uint) share->base.default_rec_buff_size, MYF(0))))
    1736                 :   {
    1737               0 :     _ma_check_print_error(param,"Not enough memory for record");
    1738               0 :     goto err;
    1739                 :   }
    1740                 : 
    1741               0 :   fn_format(param->temp_filename,name,"", MARIA_NAME_DEXT,2+4+32);
    1742               0 :   new_file= my_create(fn_format(param->temp_filename,
    1743                 :                                 param->temp_filename,"",
    1744                 :                                 DATA_TMP_EXT,
    1745                 :                                 MY_REPLACE_EXT | MY_UNPACK_FILENAME),
    1746                 :                       0, param->tmpfile_createflag,
    1747                 :                       MYF(0));
    1748               0 :   if (new_file < 0)
    1749                 :   {
    1750               0 :     _ma_check_print_error(param,"Can't create new tempfile: '%s'",
    1751                 :                          param->temp_filename);
    1752               0 :     goto err;
    1753                 :   }
    1754               0 :   if (share->pack.header_length)
    1755               0 :     if (maria_filecopy(param, new_file, info->dfile.file, 0L,
    1756                 :                        share->pack.header_length,
    1757                 :                        "datafile-header"))
    1758               0 :       goto err;
    1759               0 :   info->rec_cache.file=new_file;             /* Use this file for cacheing*/
    1760                 : 
    1761               0 :   maria_lock_memory(param);
    1762               0 :   for (key=0 ; key < share->base.keys ; key++)
    1763               0 :     share->keyinfo[key].flag|= HA_SORT_ALLOWS_SAME;
    1764                 : 
    1765               0 :   if (my_pread(share->kfile.file, temp_buff,
    1766                 :                (uint) keyinfo->block_length,
    1767                 :                share->state.key_root[sort_key],
    1768                 :                MYF(MY_NABP+MY_WME)))
    1769                 :   {
    1770               0 :     _ma_check_print_error(param, "Can't read indexpage from filepos: %s",
    1771                 :                           llstr(share->state.key_root[sort_key], llbuff));
    1772               0 :     goto err;
    1773                 :   }
    1774                 : 
    1775                 :   /* Setup param for _ma_sort_write_record */
    1776               0 :   sort_info.info=info;
    1777               0 :   sort_info.new_data_file_type=share->data_file_type;
    1778               0 :   sort_param.fix_datafile=1;
    1779               0 :   sort_param.master=1;
    1780               0 :   sort_param.filepos=share->pack.header_length;
    1781               0 :   old_record_count=info->state->records;
    1782               0 :   info->state->records=0;
    1783               0 :   if (sort_info.new_data_file_type != COMPRESSED_RECORD)
    1784               0 :     info->state->checksum=0;
    1785                 : 
    1786               0 :   _ma_page_setup(&page, info, keyinfo, share->state.key_root[sort_key],
    1787                 :                  temp_buff);
    1788               0 :   if (sort_record_index(&sort_param, &page, sort_key,new_file,update_index) ||
    1789                 :       maria_write_data_suffix(&sort_info,1) ||
    1790                 :       flush_io_cache(&info->rec_cache))
    1791                 :     goto err;
    1792                 : 
    1793               0 :   if (info->state->records != old_record_count)
    1794                 :   {
    1795               0 :     _ma_check_print_error(param,"found %s of %s records",
    1796                 :                 llstr(info->state->records,llbuff),
    1797                 :                 llstr(old_record_count,llbuff2));
    1798               0 :     goto err;
    1799                 :   }
    1800                 : 
    1801               0 :   VOID(my_close(info->dfile.file, MYF(MY_WME)));
    1802               0 :   param->out_flag|=O_NEW_DATA;                       /* Data in new file */
    1803               0 :   info->dfile.file= new_file;                   /* Use new datafile */
    1804               0 :   _ma_set_data_pagecache_callbacks(&info->dfile, info->s);
    1805                 : 
    1806               0 :   info->state->del=0;
    1807               0 :   info->state->empty=0;
    1808               0 :   share->state.dellink= HA_OFFSET_ERROR;
    1809               0 :   info->state->data_file_length=sort_param.filepos;
    1810               0 :   share->state.split=info->state->records;     /* Only hole records */
    1811               0 :   share->state.version=(ulong) time((time_t*) 0);
    1812                 : 
    1813               0 :   info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
    1814                 : 
    1815               0 :   if (param->testflag & T_WRITE_LOOP)
    1816                 :   {
    1817               0 :     VOID(fputs("          \r",stdout)); VOID(fflush(stdout));
    1818                 :   }
    1819               0 :   got_error=0;
    1820                 : 
    1821               0 : err:
    1822               0 :   if (got_error && new_file >= 0)
    1823                 :   {
    1824               0 :     VOID(end_io_cache(&info->rec_cache));
    1825               0 :     (void) my_close(new_file,MYF(MY_WME));
    1826               0 :     (void) my_delete(param->temp_filename, MYF(MY_WME));
    1827                 :   }
    1828                 :   if (temp_buff)
    1829                 :   {
    1830                 :     my_afree(temp_buff);
    1831                 :   }
    1832               0 :   my_free(sort_param.record,MYF(MY_ALLOW_ZERO_PTR));
    1833               0 :   info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
    1834               0 :   VOID(end_io_cache(&info->rec_cache));
    1835               0 :   my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
    1836               0 :   sort_info.buff=0;
    1837               0 :   share->state.sortkey=sort_key;
    1838               0 :   DBUG_RETURN(got_error);
    1839                 : } /* sort_records */
    1840                 : 
    1841                 : 
    1842                 : /* Sort records recursive using one index */
    1843                 : 
    1844                 : static int sort_record_index(MARIA_SORT_PARAM *sort_param,
    1845                 :                              MARIA_PAGE *ma_page, uint sort_key,
    1846                 :                              File new_file,my_bool update_index)
    1847               0 : {
    1848               0 :   MARIA_HA *info= ma_page->info;
    1849               0 :   MARIA_SHARE *share= info->s;
    1850                 :   uint  page_flag, nod_flag,used_length;
    1851                 :   uchar *temp_buff,*keypos,*endpos;
    1852                 :   my_off_t next_page,rec_pos;
    1853                 :   uchar lastkey[MARIA_MAX_KEY_BUFF];
    1854                 :   char llbuff[22];
    1855               0 :   MARIA_SORT_INFO *sort_info= sort_param->sort_info;
    1856               0 :   HA_CHECK *param=sort_info->param;
    1857                 :   MARIA_KEY tmp_key;
    1858                 :   MARIA_PAGE new_page;
    1859               0 :   const MARIA_KEYDEF *keyinfo= ma_page->keyinfo;
    1860               0 :   DBUG_ENTER("sort_record_index");
    1861                 : 
    1862               0 :   page_flag= ma_page->flag;
    1863               0 :   nod_flag=  ma_page->node;
    1864               0 :   temp_buff=0;
    1865               0 :   tmp_key.keyinfo= (MARIA_KEYDEF*) keyinfo;
    1866               0 :   tmp_key.data=    lastkey;
    1867                 : 
    1868               0 :   if (nod_flag)
    1869                 :   {
    1870               0 :     if (!(temp_buff= (uchar*) my_alloca(tmp_key.keyinfo->block_length)))
    1871                 :     {
    1872               0 :       _ma_check_print_error(param,"Not Enough memory");
    1873               0 :       DBUG_RETURN(-1);
    1874                 :     }
    1875                 :   }
    1876               0 :   used_length= ma_page->size;
    1877               0 :   keypos= ma_page->buff + share->keypage_header + nod_flag;
    1878               0 :   endpos= ma_page->buff + used_length;
    1879                 :   for ( ;; )
    1880                 :   {
    1881               0 :     _sanity(__FILE__,__LINE__);
    1882               0 :     if (nod_flag)
    1883                 :     {
    1884               0 :       next_page= _ma_kpos(nod_flag, keypos);
    1885               0 :       if (my_pread(share->kfile.file, temp_buff,
    1886                 :                   (uint) tmp_key.keyinfo->block_length, next_page,
    1887                 :                    MYF(MY_NABP+MY_WME)))
    1888                 :       {
    1889               0 :         _ma_check_print_error(param,"Can't read keys from filepos: %s",
    1890                 :                     llstr(next_page,llbuff));
    1891               0 :         goto err;
    1892                 :       }
    1893               0 :       _ma_page_setup(&new_page, info, ma_page->keyinfo, next_page, temp_buff);
    1894                 : 
    1895               0 :       if (sort_record_index(sort_param, &new_page, sort_key,
    1896                 :                             new_file, update_index))
    1897               0 :         goto err;
    1898                 :     }
    1899               0 :     _sanity(__FILE__,__LINE__);
    1900               0 :     if (keypos >= endpos ||
    1901                 :         !(*keyinfo->get_key)(&tmp_key, page_flag, nod_flag, &keypos))
    1902                 :       break;
    1903               0 :     rec_pos= _ma_row_pos_from_key(&tmp_key);
    1904                 : 
    1905               0 :     if ((*share->read_record)(info,sort_param->record,rec_pos))
    1906                 :     {
    1907               0 :       _ma_check_print_error(param,"%d when reading datafile",my_errno);
    1908               0 :       goto err;
    1909                 :     }
    1910               0 :     if (rec_pos != sort_param->filepos && update_index)
    1911                 :     {
    1912               0 :       _ma_dpointer(share, keypos - nod_flag - tmp_key.ref_length,
    1913                 :                    sort_param->filepos);
    1914               0 :       if (maria_movepoint(info,sort_param->record,rec_pos,sort_param->filepos,
    1915                 :                           sort_key))
    1916                 :       {
    1917               0 :         _ma_check_print_error(param,"%d when updating key-pointers",my_errno);
    1918               0 :         goto err;
    1919                 :       }
    1920                 :     }
    1921               0 :     if (_ma_sort_write_record(sort_param))
    1922                 :       goto err;
    1923                 :   }
    1924                 :   /* Clear end of block to get better compression if the table is backuped */
    1925               0 :   bzero(ma_page->buff + used_length, keyinfo->block_length - used_length);
    1926               0 :   if (my_pwrite(share->kfile.file, ma_page->buff, (uint)keyinfo->block_length,
    1927                 :                 ma_page->pos, param->myf_rw))
    1928                 :   {
    1929               0 :     _ma_check_print_error(param,"%d when updating keyblock",my_errno);
    1930               0 :     goto err;
    1931                 :   }
    1932                 :   if (temp_buff)
    1933                 :     my_afree(temp_buff);
    1934               0 :   DBUG_RETURN(0);
    1935               0 : err:
    1936                 :   if (temp_buff)
    1937                 :     my_afree(temp_buff);
    1938               0 :   DBUG_RETURN(1);
    1939                 : } /* sort_record_index */
    1940                 : 
    1941                 : 
    1942                 : static my_bool write_log_record(HA_CHECK *param)
    1943               5 : {
    1944                 :   /*
    1945                 :     Now that all operations including O_NEW_DATA|INDEX are successfully
    1946                 :     done, we can write a log record.
    1947                 :   */
    1948               5 :   MARIA_HA *info= maria_open(param->isam_file_name, O_RDWR, 0);
    1949               5 :   if (info == NULL)
    1950               0 :     _ma_check_print_error(param, default_open_errmsg, my_errno,
    1951                 :                           param->isam_file_name);
    1952                 :   else
    1953                 :   {
    1954               5 :     if (write_log_record_for_repair(param, info))
    1955               0 :       _ma_check_print_error(param, "%d when writing log record for"
    1956                 :                             " MARIA-table '%s'", my_errno,
    1957                 :                             param->isam_file_name);
    1958               5 :     else if (maria_close(info))
    1959               0 :       _ma_check_print_error(param, default_close_errmsg, my_errno,
    1960                 :                             param->isam_file_name);
    1961                 :     else
    1962               5 :       return FALSE;
    1963                 :   }
    1964               0 :   return TRUE;
    1965                 : }
    1966                 : 
    1967                 : #include "ma_check_standalone.h"

Generated by: LTP GCOV extension version 1.4