19
#include "drizzled/internal/my_bit.h"
18
#include <drizzled/server_includes.h>
19
#include <mysys/my_bit.h>
20
20
#include "myisampack.h"
21
21
#include "ha_myisam.h"
22
#include "myisam_priv.h"
23
#include "drizzled/option.h"
24
#include "drizzled/internal/my_bit.h"
25
#include "drizzled/internal/m_string.h"
26
#include "drizzled/util/test.h"
27
#include "drizzled/error.h"
28
#include "drizzled/errmsg_print.h"
29
#include "drizzled/gettext.h"
30
#include "drizzled/session.h"
31
#include "drizzled/set_var.h"
32
#include <drizzled/plugin.h>
33
#include "drizzled/plugin/client.h"
34
#include "drizzled/table.h"
35
#include "drizzled/field/timestamp.h"
36
#include "drizzled/memory/multi_malloc.h"
37
#include "drizzled/plugin/daemon.h"
45
using namespace drizzled;
47
extern pthread_mutex_t LOCK_global_system_variables;
48
static const string engine_name("MyISAM");
22
#include "myisamdef.h"
23
#include <drizzled/util/test.h>
24
#include <drizzled/error.h>
25
#include <drizzled/errmsg_print.h>
26
#include <drizzled/gettext.h>
27
#include <drizzled/session.h>
28
#include <drizzled/protocol.h>
29
#include <drizzled/table.h>
30
#include <drizzled/field/timestamp.h>
32
ulong myisam_recover_options= HA_RECOVER_NONE;
50
33
pthread_mutex_t THR_LOCK_myisam= PTHREAD_MUTEX_INITIALIZER;
52
35
static uint32_t repair_threads;
53
static uint32_t myisam_key_cache_block_size;
54
static uint32_t myisam_key_cache_size;
55
static uint32_t myisam_key_cache_division_limit;
56
static uint32_t myisam_key_cache_age_threshold;
36
static uint32_t block_size;
57
37
static uint64_t max_sort_file_size;
58
38
static uint64_t sort_buffer_size;
40
/* bits in myisam_recover_options */
41
const char *myisam_recover_names[] =
42
{ "DEFAULT", "BACKUP", "FORCE", "QUICK", NULL};
43
TYPELIB myisam_recover_typelib= {array_elements(myisam_recover_names)-1,"",
44
myisam_recover_names, NULL};
46
const char *myisam_stats_method_names[] = {"nulls_unequal", "nulls_equal",
47
"nulls_ignored", NULL};
48
TYPELIB myisam_stats_method_typelib= {
49
array_elements(myisam_stats_method_names) - 1, "",
50
myisam_stats_method_names, NULL};
60
53
/*****************************************************************************
62
55
*****************************************************************************/
64
static const char *ha_myisam_exts[] = {
70
class MyisamEngine : public plugin::StorageEngine
73
MyisamEngine(const MyisamEngine&);
74
MyisamEngine& operator=(const MyisamEngine&);
76
explicit MyisamEngine(string name_arg) :
77
plugin::StorageEngine(name_arg,
78
HTON_CAN_INDEX_BLOBS |
79
HTON_STATS_RECORDS_IS_EXACT |
85
HTON_SKIP_STORE_LOCK |
88
pthread_mutex_init(&THR_LOCK_myisam,MY_MUTEX_INIT_FAST);
91
virtual ~MyisamEngine()
93
pthread_mutex_destroy(&THR_LOCK_myisam);
94
end_key_cache(dflt_key_cache, 1); // Can never fail
96
mi_panic(HA_PANIC_CLOSE);
99
virtual Cursor *create(TableShare &table,
100
memory::Root *mem_root)
102
return new (mem_root) ha_myisam(*this, table);
105
const char **bas_ext() const {
106
return ha_myisam_exts;
109
int doCreateTable(Session&,
111
drizzled::TableIdentifier &identifier,
114
int doRenameTable(Session&, TableIdentifier &from, TableIdentifier &to);
116
int doDropTable(Session&, drizzled::TableIdentifier &identifier);
118
int doGetTableDefinition(Session& session,
119
drizzled::TableIdentifier &identifier,
120
message::Table &table_message);
122
/* Temp only engine, so do not return values. */
123
void doGetTableNames(CachedDirectory &, SchemaIdentifier &, set<string>&) { };
125
uint32_t max_supported_keys() const { return MI_MAX_KEY; }
126
uint32_t max_supported_key_length() const { return MI_MAX_KEY_LENGTH; }
127
uint32_t max_supported_key_part_length() const { return MI_MAX_KEY_LENGTH; }
129
uint32_t index_flags(enum ha_key_alg) const
131
return (HA_READ_NEXT |
137
bool doDoesTableExist(Session& session, TableIdentifier &identifier);
139
void doGetTableIdentifiers(drizzled::CachedDirectory &directory,
140
drizzled::SchemaIdentifier &schema_identifier,
141
drizzled::TableIdentifiers &set_of_identifiers);
144
void MyisamEngine::doGetTableIdentifiers(drizzled::CachedDirectory&,
145
drizzled::SchemaIdentifier&,
146
drizzled::TableIdentifiers&)
150
bool MyisamEngine::doDoesTableExist(Session &session, TableIdentifier &identifier)
152
return session.doesTableMessageExist(identifier);
155
int MyisamEngine::doGetTableDefinition(Session &session,
156
drizzled::TableIdentifier &identifier,
157
message::Table &table_message)
159
if (session.getTableMessage(identifier, table_message))
165
Convert to push_Warnings if you ever care about this, otherwise, it is a no-op.
168
static void mi_check_print_msg(MI_CHECK *, const char* ,
169
const char *, va_list )
57
static handler *myisam_create_handler(handlerton *hton,
61
return new (mem_root) ha_myisam(hton, table);
64
// collect errors printed by mi_check routines
66
static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
67
const char *fmt, va_list args)
69
Session* session = (Session*)param->session;
70
Protocol *protocol= session->protocol;
71
uint32_t length, msg_length;
72
char msgbuf[MI_MAX_MSG_BUF];
73
char name[NAME_LEN*2+2];
75
msg_length= vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
76
msgbuf[sizeof(msgbuf) - 1] = 0; // healthy paranoia
78
if (!session->vio_ok())
80
errmsg_printf(ERRMSG_LVL_ERROR, "%s",msgbuf);
84
if (param->testflag & (T_CREATE_MISSING_KEYS | T_SAFE_REPAIR |
87
my_message(ER_NOT_KEYFILE,msgbuf,MYF(MY_WME));
90
length= sprintf(name,"%s.%s",param->db_name,param->table_name);
93
TODO: switch from protocol to push_warning here. The main reason we didn't
94
it yet is parallel repair. Due to following trace:
95
mi_check_print_msg/push_warning/sql_alloc/my_pthread_getspecific_ptr.
97
Also we likely need to lock mutex here (in both cases with protocol and
100
protocol->prepare_for_resend();
101
protocol->store(name, length, system_charset_info);
102
protocol->store(param->op_name, system_charset_info);
103
protocol->store(msg_type, system_charset_info);
104
protocol->store(msgbuf, msg_length, system_charset_info);
105
if (protocol->write())
106
errmsg_printf(ERRMSG_LVL_ERROR, "Failed on my_net_write, writing to stderr instead: %s\n",
658
626
return mi_write(file,buf);
629
int ha_myisam::check(Session* session, HA_CHECK_OPT* check_opt)
631
if (!file) return HA_ADMIN_INTERNAL_ERROR;
634
MYISAM_SHARE* share = file->s;
635
const char *old_proc_info= session->get_proc_info();
637
session->set_proc_info("Checking table");
638
myisamchk_init(¶m);
639
param.session = session;
640
param.op_name = "check";
641
param.db_name= table->s->db.str;
642
param.table_name= table->alias;
643
param.testflag = check_opt->flags | T_CHECK | T_SILENT;
644
param.stats_method= (enum_mi_stats_method)session->variables.myisam_stats_method;
646
if (!(table->db_stat & HA_READ_ONLY))
647
param.testflag|= T_STATISTICS;
648
param.using_global_keycache = 1;
650
if (!mi_is_crashed(file) &&
651
(((param.testflag & T_CHECK_ONLY_CHANGED) &&
652
!(share->state.changed & (STATE_CHANGED | STATE_CRASHED |
653
STATE_CRASHED_ON_REPAIR)) &&
654
share->state.open_count == 0) ||
655
((param.testflag & T_FAST) && (share->state.open_count ==
656
(uint) (share->global_changed ? 1 : 0)))))
657
return HA_ADMIN_ALREADY_DONE;
659
error = chk_status(¶m, file); // Not fatal
660
error = chk_size(¶m, file);
662
error |= chk_del(¶m, file, param.testflag);
664
error = chk_key(¶m, file);
667
if ((!(param.testflag & T_QUICK) &&
669
(HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ||
670
(param.testflag & (T_EXTEND | T_MEDIUM)))) ||
673
uint32_t old_testflag=param.testflag;
674
param.testflag|=T_MEDIUM;
675
if (!(error= init_io_cache(¶m.read_cache, file->dfile,
676
my_default_record_cache_size, READ_CACHE,
677
share->pack.header_length, 1, MYF(MY_WME))))
679
error= chk_data_link(¶m, file, param.testflag & T_EXTEND);
680
end_io_cache(&(param.read_cache));
682
param.testflag= old_testflag;
687
if ((share->state.changed & (STATE_CHANGED |
688
STATE_CRASHED_ON_REPAIR |
689
STATE_CRASHED | STATE_NOT_ANALYZED)) ||
690
(param.testflag & T_STATISTICS) ||
693
file->update|=HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
694
pthread_mutex_lock(&share->intern_lock);
695
share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED |
696
STATE_CRASHED_ON_REPAIR);
697
if (!(table->db_stat & HA_READ_ONLY))
698
error=update_state_info(¶m,file,UPDATE_TIME | UPDATE_OPEN_COUNT |
700
pthread_mutex_unlock(&share->intern_lock);
701
info(HA_STATUS_NO_LOCK | HA_STATUS_TIME | HA_STATUS_VARIABLE |
705
else if (!mi_is_crashed(file) && !session->killed)
707
mi_mark_crashed(file);
708
file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
711
session->set_proc_info(old_proc_info);
712
return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
717
analyze the key distribution in the table
718
As the table may be only locked for read, we have to take into account that
719
two threads may do an analyze at the same time!
722
int ha_myisam::analyze(Session *session,
723
HA_CHECK_OPT* check_opt __attribute__((unused)))
727
MYISAM_SHARE* share = file->s;
729
myisamchk_init(¶m);
730
param.session = session;
731
param.op_name= "analyze";
732
param.db_name= table->s->db.str;
733
param.table_name= table->alias;
734
param.testflag= (T_FAST | T_CHECK | T_SILENT | T_STATISTICS |
735
T_DONT_CHECK_CHECKSUM);
736
param.using_global_keycache = 1;
737
param.stats_method= (enum_mi_stats_method)session->variables.myisam_stats_method;
739
if (!(share->state.changed & STATE_NOT_ANALYZED))
740
return HA_ADMIN_ALREADY_DONE;
742
error = chk_key(¶m, file);
745
pthread_mutex_lock(&share->intern_lock);
746
error=update_state_info(¶m,file,UPDATE_STAT);
747
pthread_mutex_unlock(&share->intern_lock);
749
else if (!mi_is_crashed(file) && !session->killed)
750
mi_mark_crashed(file);
751
return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
755
int ha_myisam::repair(Session* session, HA_CHECK_OPT *check_opt)
759
ha_rows start_records;
761
if (!file) return HA_ADMIN_INTERNAL_ERROR;
763
myisamchk_init(¶m);
764
param.session = session;
765
param.op_name= "repair";
766
param.testflag= ((check_opt->flags & ~(T_EXTEND)) |
767
T_SILENT | T_FORCE_CREATE | T_CALC_CHECKSUM |
768
(check_opt->flags & T_EXTEND ? T_REP : T_REP_BY_SORT));
769
param.sort_buffer_length= sort_buffer_size;
770
start_records=file->state->records;
771
while ((error=repair(session,param,0)) && param.retry_repair)
773
param.retry_repair=0;
774
if (test_all_bits(param.testflag,
775
(uint) (T_RETRY_WITHOUT_QUICK | T_QUICK)))
777
param.testflag&= ~T_RETRY_WITHOUT_QUICK;
778
errmsg_printf(ERRMSG_LVL_INFO, "Retrying repair of: '%s' without quick",
782
param.testflag&= ~T_QUICK;
783
if ((param.testflag & T_REP_BY_SORT))
785
param.testflag= (param.testflag & ~T_REP_BY_SORT) | T_REP;
786
errmsg_printf(ERRMSG_LVL_INFO, "Retrying repair of: '%s' with keycache",
792
if (!error && start_records != file->state->records &&
793
!(check_opt->flags & T_VERY_SILENT))
795
char llbuff[22],llbuff2[22];
796
errmsg_printf(ERRMSG_LVL_INFO, "Found %s of %s rows when repairing '%s'",
797
llstr(file->state->records, llbuff),
798
llstr(start_records, llbuff2),
804
int ha_myisam::optimize(Session* session, HA_CHECK_OPT *check_opt)
807
if (!file) return HA_ADMIN_INTERNAL_ERROR;
810
myisamchk_init(¶m);
811
param.session = session;
812
param.op_name= "optimize";
813
param.testflag= (check_opt->flags | T_SILENT | T_FORCE_CREATE |
814
T_REP_BY_SORT | T_STATISTICS | T_SORT_INDEX);
815
param.sort_buffer_length= sort_buffer_size;
816
if ((error= repair(session,param,1)) && param.retry_repair)
818
errmsg_printf(ERRMSG_LVL_WARN, "Warning: Optimize table got errno %d on %s.%s, retrying",
819
my_errno, param.db_name, param.table_name);
820
param.testflag&= ~T_REP_BY_SORT;
821
error= repair(session,param,1);
662
827
int ha_myisam::repair(Session *session, MI_CHECK ¶m, bool do_optimize)
1247
bool ha_myisam::check_and_repair(Session *session)
1252
uint32_t old_query_length;
1253
HA_CHECK_OPT check_opt;
1256
check_opt.flags= T_MEDIUM | T_AUTO_REPAIR;
1257
// Don't use quick if deleted rows
1258
if (!file->state->del && (myisam_recover_options & HA_RECOVER_QUICK))
1259
check_opt.flags|=T_QUICK;
1260
errmsg_printf(ERRMSG_LVL_WARN, "Checking table: '%s'",table->s->path.str);
1262
old_query= session->query;
1263
old_query_length= session->query_length;
1264
pthread_mutex_lock(&LOCK_thread_count);
1265
session->query= table->s->table_name.str;
1266
session->query_length= table->s->table_name.length;
1267
pthread_mutex_unlock(&LOCK_thread_count);
1269
if ((marked_crashed= mi_is_crashed(file)) || check(session, &check_opt))
1271
errmsg_printf(ERRMSG_LVL_WARN, "Recovering table: '%s'",table->s->path.str);
1273
((myisam_recover_options & HA_RECOVER_BACKUP ? T_BACKUP_DATA : 0) |
1274
(marked_crashed ? 0 : T_QUICK) |
1275
(myisam_recover_options & HA_RECOVER_FORCE ? 0 : T_SAFE_REPAIR) |
1277
if (repair(session, &check_opt))
1280
pthread_mutex_lock(&LOCK_thread_count);
1281
session->query= old_query;
1282
session->query_length= old_query_length;
1283
pthread_mutex_unlock(&LOCK_thread_count);
1287
bool ha_myisam::is_crashed() const
1289
return (file->s->state.changed & STATE_CRASHED ||
1290
(file->s->state.open_count));
1035
1293
int ha_myisam::update_row(const unsigned char *old_data, unsigned char *new_data)
1037
ha_statistic_increment(&system_status_var::ha_update_count);
1295
ha_statistic_increment(&SSV::ha_update_count);
1038
1296
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
1039
1297
table->timestamp_field->set_time();
1040
1298
return mi_update(file,old_data,new_data);
1225
1518
if (flag & HA_STATUS_CONST)
1227
TableShare *share= table->s;
1520
TABLE_SHARE *share= table->s;
1228
1521
stats.max_data_file_length= misam_info.max_data_file_length;
1229
1522
stats.max_index_file_length= misam_info.max_index_file_length;
1230
1523
stats.create_time= misam_info.create_time;
1231
1524
ref_length= misam_info.reflength;
1232
1525
share->db_options_in_use= misam_info.options;
1233
stats.block_size= myisam_key_cache_block_size; /* record block size */
1526
stats.block_size= block_size; /* record block size */
1235
1528
/* Update share */
1236
if (share->tmp_table == message::Table::STANDARD)
1529
if (share->tmp_table == NO_TMP_TABLE)
1237
1530
pthread_mutex_lock(&share->mutex);
1238
set_prefix(share->keys_in_use, share->keys);
1240
* Due to bug 394932 (32-bit solaris build failure), we need
1241
* to convert the uint64_t key_map member of the misam_info
1242
* structure in to a std::bitset so that we can logically and
1243
* it with the share->key_in_use key_map.
1246
string binary_key_map;
1247
uint64_t num= misam_info.key_map;
1249
* Convert the uint64_t to a binary
1250
* string representation of it.
1254
uint64_t bin_digit= num % 2;
1258
binary_key_map.append(ostr.str());
1260
* Now we have the binary string representation of the
1261
* flags, we need to fill that string representation out
1262
* with the appropriate number of bits. This is needed
1263
* since key_map is declared as a std::bitset of a certain bit
1264
* width that depends on the MAX_INDEXES variable.
1266
if (MAX_INDEXES <= 64)
1268
size_t len= 72 - binary_key_map.length();
1269
string all_zeros(len, '0');
1270
binary_key_map.insert(binary_key_map.begin(),
1276
size_t len= (MAX_INDEXES + 7) / 8 * 8;
1277
string all_zeros(len, '0');
1278
binary_key_map.insert(binary_key_map.begin(),
1282
key_map tmp_map(binary_key_map);
1283
share->keys_in_use&= tmp_map;
1284
share->keys_for_keyread&= share->keys_in_use;
1531
share->keys_in_use.set_prefix(share->keys);
1532
share->keys_in_use.intersect_extended(misam_info.key_map);
1533
share->keys_for_keyread.intersect(share->keys_in_use);
1285
1534
share->db_record_offset= misam_info.record_offset;
1286
1535
if (share->key_parts)
1287
1536
memcpy(table->key_info[0].rec_per_key,
1288
1537
misam_info.rec_per_key,
1289
1538
sizeof(table->key_info[0].rec_per_key)*share->key_parts);
1290
if (share->tmp_table == message::Table::STANDARD)
1539
if (share->tmp_table == NO_TMP_TABLE)
1291
1540
pthread_mutex_unlock(&share->mutex);
1340
1593
return mi_delete_all_rows(file);
1343
int MyisamEngine::doDropTable(Session &session,
1344
drizzled::TableIdentifier &identifier)
1596
int ha_myisam::delete_table(const char *name)
1346
session.removeTableMessage(identifier);
1348
return mi_delete_table(identifier.getPath().c_str());
1598
return mi_delete_table(name);
1352
1602
int ha_myisam::external_lock(Session *session, int lock_type)
1354
file->in_use= session;
1604
file->in_use.data= session;
1355
1605
return mi_lock_database(file, !table->s->tmp_table ?
1356
1606
lock_type : ((lock_type == F_UNLCK) ?
1357
1607
F_UNLCK : F_EXTRA_LCK));
1360
int MyisamEngine::doCreateTable(Session &session,
1362
drizzled::TableIdentifier &identifier,
1363
message::Table& create_proto)
1610
THR_LOCK_DATA **ha_myisam::store_lock(Session *session __attribute__((unused)),
1612
enum thr_lock_type lock_type)
1614
if (lock_type != TL_IGNORE && file->lock.type == TL_UNLOCK)
1615
file->lock.type=lock_type;
1620
void ha_myisam::update_create_info(HA_CREATE_INFO *create_info)
1622
ha_myisam::info(HA_STATUS_AUTO | HA_STATUS_CONST);
1623
if (!(create_info->used_fields & HA_CREATE_USED_AUTO))
1625
create_info->auto_increment_value= stats.auto_increment_value;
1627
create_info->data_file_name=data_file_name;
1628
create_info->index_file_name=index_file_name;
1632
int ha_myisam::create(const char *name, register Table *table_arg,
1633
HA_CREATE_INFO *ha_create_info)
1366
uint32_t create_flags= 0, create_records;
1636
uint32_t create_flags= 0, records;
1367
1637
char buff[FN_REFLEN];
1368
1638
MI_KEYDEF *keydef;
1369
1639
MI_COLUMNDEF *recinfo;
1370
1640
MI_CREATE_INFO create_info;
1371
TableShare *share= table_arg.s;
1641
TABLE_SHARE *share= table_arg->s;
1372
1642
uint32_t options= share->db_options_in_use;
1373
if ((error= table2myisam(&table_arg, &keydef, &recinfo, &create_records)))
1643
if ((error= table2myisam(table_arg, &keydef, &recinfo, &records)))
1644
return(error); /* purecov: inspected */
1375
1645
memset(&create_info, 0, sizeof(create_info));
1376
create_info.max_rows= create_proto.options().max_rows();
1377
create_info.reloc_rows= create_proto.options().min_rows();
1646
create_info.max_rows= share->max_rows;
1647
create_info.reloc_rows= share->min_rows;
1378
1648
create_info.with_auto_increment= share->next_number_key_offset == 0;
1379
create_info.auto_increment= (create_proto.options().has_auto_increment_value() ?
1380
create_proto.options().auto_increment_value() -1 :
1649
create_info.auto_increment= (ha_create_info->auto_increment_value ?
1650
ha_create_info->auto_increment_value -1 :
1382
create_info.data_file_length= (create_proto.options().max_rows() *
1383
create_proto.options().avg_row_length());
1384
create_info.data_file_name= NULL;
1385
create_info.index_file_name= NULL;
1652
create_info.data_file_length= ((uint64_t) share->max_rows *
1653
share->avg_row_length);
1654
create_info.data_file_name= ha_create_info->data_file_name;
1655
create_info.index_file_name= ha_create_info->index_file_name;
1386
1656
create_info.language= share->table_charset->number;
1388
if (create_proto.type() == message::Table::TEMPORARY)
1658
if (ha_create_info->options & HA_LEX_CREATE_TMP_TABLE)
1389
1659
create_flags|= HA_CREATE_TMP_TABLE;
1660
if (ha_create_info->options & HA_CREATE_KEEP_FILES)
1661
create_flags|= HA_CREATE_KEEP_FILES;
1390
1662
if (options & HA_OPTION_PACK_RECORD)
1391
1663
create_flags|= HA_PACK_RECORD;
1664
if (options & HA_OPTION_CHECKSUM)
1665
create_flags|= HA_CREATE_CHECKSUM;
1666
if (options & HA_OPTION_DELAY_KEY_WRITE)
1667
create_flags|= HA_CREATE_DELAY_KEY_WRITE;
1393
/* TODO: Check that the following internal::fn_format is really needed */
1394
error= mi_create(internal::fn_format(buff, identifier.getPath().c_str(), "", "",
1395
MY_UNPACK_FILENAME|MY_APPEND_EXT),
1669
/* TODO: Check that the following fn_format is really needed */
1670
error= mi_create(fn_format(buff, name, "", "",
1671
MY_UNPACK_FILENAME|MY_APPEND_EXT),
1396
1672
share->keys, keydef,
1397
create_records, recinfo,
1398
1674
0, (MI_UNIQUEDEF*) 0,
1399
1675
&create_info, create_flags);
1400
1676
free((unsigned char*) recinfo);
1402
session.storeTableMessage(identifier, create_proto);
1408
int MyisamEngine::doRenameTable(Session &session, TableIdentifier &from, TableIdentifier &to)
1681
int ha_myisam::rename_table(const char * from, const char * to)
1410
session.renameTableMessage(from, to);
1412
return mi_rename(from.getPath().c_str(), to.getPath().c_str());
1683
return mi_rename(from,to);
1416
void ha_myisam::get_auto_increment(uint64_t ,
1687
void ha_myisam::get_auto_increment(uint64_t offset __attribute__((unused)),
1688
uint64_t increment __attribute__((unused)),
1689
uint64_t nb_desired_values __attribute__((unused)),
1419
1690
uint64_t *first_value,
1420
1691
uint64_t *nb_reserved_values)
1499
1770
return (uint)file->state->checksum;
1502
static MyisamEngine *engine= NULL;
1504
static int myisam_init(plugin::Context &context)
1506
engine= new MyisamEngine(engine_name);
1507
context.add(engine);
1509
/* call ha_init_key_cache() on all key caches to init them */
1510
int error= init_key_cache(dflt_key_cache,
1511
myisam_key_cache_block_size,
1512
myisam_key_cache_size,
1513
myisam_key_cache_division_limit,
1514
myisam_key_cache_age_threshold);
1517
exit(1); /* Memory Allocation Failure */
1774
bool ha_myisam::check_if_incompatible_data(HA_CREATE_INFO *info,
1775
uint32_t table_changes)
1777
uint32_t options= table->s->db_options_in_use;
1779
if (info->auto_increment_value != stats.auto_increment_value ||
1780
info->data_file_name != data_file_name ||
1781
info->index_file_name != index_file_name ||
1782
table_changes == IS_EQUAL_NO ||
1783
table_changes & IS_EQUAL_PACK_LENGTH) // Not implemented yet
1784
return COMPATIBLE_DATA_NO;
1786
if ((options & (HA_OPTION_PACK_RECORD | HA_OPTION_CHECKSUM |
1787
HA_OPTION_DELAY_KEY_WRITE)) !=
1788
(info->table_options & (HA_OPTION_PACK_RECORD | HA_OPTION_CHECKSUM |
1789
HA_OPTION_DELAY_KEY_WRITE)))
1790
return COMPATIBLE_DATA_NO;
1791
return COMPATIBLE_DATA_YES;
1794
int myisam_deinit(void *hton __attribute__((unused)))
1796
pthread_mutex_destroy(&THR_LOCK_myisam);
1798
return mi_panic(HA_PANIC_CLOSE);
1801
static int myisam_init(void *p)
1803
handlerton *myisam_hton;
1805
myisam_hton= (handlerton *)p;
1806
myisam_hton->state= SHOW_OPTION_YES;
1807
myisam_hton->create= myisam_create_handler;
1808
myisam_hton->flags= HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES;
1523
static void sys_var_key_cache_size_update(Session *session, drizzle_sys_var *var, void *, const void *save)
1525
uint32_t tmp= *static_cast<const uint32_t *>(save);
1528
struct option option_limits;
1529
plugin_opt_set_limits(&option_limits, var);
1530
option_limits.name= "myisam_key_cache_size";
1532
if (dflt_key_cache->in_init)
1535
myisam_key_cache_size= static_cast<uint32_t>(fix_unsigned(session, static_cast<uint64_t>(tmp), &option_limits));
1537
/* If key cache didn't existed initialize it, else resize it */
1538
dflt_key_cache->in_init= 1;
1540
error= ! resize_key_cache(dflt_key_cache,
1541
myisam_key_cache_block_size,
1542
myisam_key_cache_size,
1543
myisam_key_cache_division_limit,
1544
myisam_key_cache_age_threshold);
1545
dflt_key_cache->in_init= 0;
1548
static void sys_var_key_cache_block_size_update(Session *session, drizzle_sys_var *var, void *, const void *save)
1550
uint32_t tmp= *static_cast<const uint32_t *>(save);
1553
struct option option_limits;
1554
plugin_opt_set_limits(&option_limits, var);
1555
option_limits.name= "myisam_key_cache_block_size";
1557
if (dflt_key_cache->in_init)
1560
myisam_key_cache_block_size= static_cast<uint32_t>(fix_unsigned(session, static_cast<uint64_t>(tmp), &option_limits));
1562
dflt_key_cache->in_init= 1;
1564
error= ! resize_key_cache(dflt_key_cache,
1565
myisam_key_cache_block_size,
1566
myisam_key_cache_size,
1567
myisam_key_cache_division_limit,
1568
myisam_key_cache_age_threshold);
1570
dflt_key_cache->in_init= 0;
1573
static void sys_var_key_cache_division_limit_update(Session *session, drizzle_sys_var *var, void *, const void *save)
1575
uint32_t tmp= *static_cast<const uint32_t *>(save);
1578
struct option option_limits;
1579
plugin_opt_set_limits(&option_limits, var);
1580
option_limits.name= "myisam_key_cache_division_limit";
1582
if (dflt_key_cache->in_init)
1585
myisam_key_cache_division_limit= static_cast<uint32_t>(fix_unsigned(session, static_cast<uint64_t>(tmp), &option_limits));
1587
dflt_key_cache->in_init= 1;
1589
error= ! resize_key_cache(dflt_key_cache,
1590
myisam_key_cache_block_size,
1591
myisam_key_cache_size,
1592
myisam_key_cache_division_limit,
1593
myisam_key_cache_age_threshold);
1595
dflt_key_cache->in_init= 0;
1598
static void sys_var_key_cache_age_threshold_update(Session *session, drizzle_sys_var *var, void *, const void *save)
1600
uint32_t tmp= *static_cast<const uint32_t *>(save);
1603
struct option option_limits;
1604
plugin_opt_set_limits(&option_limits, var);
1605
option_limits.name= "myisam_key_cache_age_threshold";
1607
if (dflt_key_cache->in_init)
1610
myisam_key_cache_age_threshold= static_cast<uint32_t>(fix_unsigned(session, static_cast<uint64_t>(tmp), &option_limits));
1612
dflt_key_cache->in_init= 1;
1614
error= ! resize_key_cache(dflt_key_cache,
1615
myisam_key_cache_block_size,
1616
myisam_key_cache_size,
1617
myisam_key_cache_division_limit,
1618
myisam_key_cache_age_threshold);
1620
dflt_key_cache->in_init= 0;
1623
static DRIZZLE_SYSVAR_UINT(key_cache_block_size,
1624
myisam_key_cache_block_size,
1625
PLUGIN_VAR_RQCMDARG,
1626
N_("Block size to be used for MyISAM index pages."),
1628
sys_var_key_cache_block_size_update,
1629
KEY_CACHE_BLOCK_SIZE,
1634
static DRIZZLE_SYSVAR_UINT(key_cache_age_threshold, myisam_key_cache_age_threshold,
1635
PLUGIN_VAR_RQCMDARG,
1636
N_("This characterizes the number of hits a hot block has to be untouched "
1637
"until it is considered aged enough to be downgraded to a warm block. "
1638
"This specifies the percentage ratio of that number of hits to the "
1639
"total number of blocks in key cache"),
1641
sys_var_key_cache_age_threshold_update,
1647
static DRIZZLE_SYSVAR_UINT(key_cache_division_limit, myisam_key_cache_division_limit,
1648
PLUGIN_VAR_RQCMDARG,
1649
N_("The minimum percentage of warm blocks in key cache"),
1651
sys_var_key_cache_division_limit_update,
1657
static DRIZZLE_SYSVAR_UINT(key_cache_size,
1658
myisam_key_cache_size,
1659
PLUGIN_VAR_RQCMDARG,
1660
N_("The size of the buffer used for index blocks for MyISAM tables. "
1661
"Increase this to get better index handling (for all reads and multiple "
1662
"writes) to as much as you can afford;"),
1664
sys_var_key_cache_size_update,
1814
/****************************************************************************
1815
* MyISAM MRR implementation: use DS-MRR
1816
***************************************************************************/
1818
int ha_myisam::multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param,
1819
uint32_t n_ranges, uint32_t mode,
1820
HANDLER_BUFFER *buf)
1822
return ds_mrr.dsmrr_init(this, &table->key_info[active_index],
1823
seq, seq_init_param, n_ranges, mode, buf);
1826
int ha_myisam::multi_range_read_next(char **range_info)
1828
return ds_mrr.dsmrr_next(this, range_info);
1831
ha_rows ha_myisam::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
1832
void *seq_init_param,
1833
uint32_t n_ranges, uint32_t *bufsz,
1834
uint32_t *flags, COST_VECT *cost)
1837
This call is here because there is no location where this->table would
1839
TODO: consider moving it into some per-query initialization call.
1841
ds_mrr.init(this, table);
1842
return ds_mrr.dsmrr_info_const(keyno, seq, seq_init_param, n_ranges, bufsz,
1846
int ha_myisam::multi_range_read_info(uint32_t keyno, uint32_t n_ranges, uint32_t keys,
1847
uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
1849
ds_mrr.init(this, table);
1850
return ds_mrr.dsmrr_info(keyno, n_ranges, keys, bufsz, flags, cost);
1853
/* MyISAM MRR implementation ends */
1856
/* Index condition pushdown implementation*/
1859
Item *ha_myisam::idx_cond_push(uint32_t keyno_arg, Item* idx_cond_arg)
1861
pushed_idx_cond_keyno= keyno_arg;
1862
pushed_idx_cond= idx_cond_arg;
1863
in_range_check_pushed_down= true;
1864
if (active_index == pushed_idx_cond_keyno)
1865
mi_set_index_cond_func(file, index_cond_func_myisam, this);
1869
static DRIZZLE_SYSVAR_UINT(block_size, block_size,
1870
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
1871
N_("Block size to be used for MyISAM index pages."),
1872
NULL, NULL, MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH,
1873
MI_MAX_KEY_BLOCK_LENGTH, 0);
1670
1875
static DRIZZLE_SYSVAR_UINT(repair_threads, repair_threads,
1671
PLUGIN_VAR_RQCMDARG,
1672
N_("Number of threads to use when repairing MyISAM tables. The value of "
1673
"1 disables parallel repair."),
1674
NULL, NULL, 1, 1, UINT32_MAX, 0);
1876
PLUGIN_VAR_RQCMDARG,
1877
N_("Number of threads to use when repairing MyISAM tables. The value of "
1878
"1 disables parallel repair."),
1879
NULL, NULL, 1, 1, UINT32_MAX, 0);
1676
1881
static DRIZZLE_SYSVAR_ULONGLONG(max_sort_file_size, max_sort_file_size,
1677
1882
PLUGIN_VAR_RQCMDARG,