~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/myisam/ha_myisam.cc

  • Committer: Olaf van der Spek
  • Date: 2011-02-12 18:24:24 UTC
  • mto: (2167.1.2 build) (2172.1.4 build)
  • mto: This revision was merged to the branch mainline in revision 2168.
  • Revision ID: olafvdspek@gmail.com-20110212182424-kgnm9osi7qo97at2
casts

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
   You should have received a copy of the GNU General Public License
13
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 */
 
14
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
15
15
 
16
16
 
17
17
 
28
28
#include "drizzled/errmsg_print.h"
29
29
#include "drizzled/gettext.h"
30
30
#include "drizzled/session.h"
31
 
#include "drizzled/set_var.h"
32
 
#include <drizzled/plugin.h>
 
31
#include "drizzled/plugin.h"
33
32
#include "drizzled/plugin/client.h"
34
33
#include "drizzled/table.h"
35
 
#include "drizzled/field/timestamp.h"
36
34
#include "drizzled/memory/multi_malloc.h"
37
35
#include "drizzled/plugin/daemon.h"
38
36
 
 
37
#include <boost/algorithm/string.hpp>
 
38
#include <boost/scoped_ptr.hpp>
 
39
 
39
40
#include <string>
40
41
#include <sstream>
41
42
#include <map>
42
43
#include <algorithm>
 
44
#include <memory>
 
45
#include <boost/program_options.hpp>
 
46
#include <drizzled/module/option_map.h>
 
47
 
 
48
namespace po= boost::program_options;
43
49
 
44
50
using namespace std;
45
51
using namespace drizzled;
46
52
 
47
 
extern pthread_mutex_t LOCK_global_system_variables;
48
53
static const string engine_name("MyISAM");
49
54
 
50
 
pthread_mutex_t THR_LOCK_myisam= PTHREAD_MUTEX_INITIALIZER;
 
55
boost::mutex THR_LOCK_myisam;
51
56
 
52
 
static uint32_t repair_threads;
53
 
static uint32_t myisam_key_cache_block_size;
 
57
static uint32_t myisam_key_cache_block_size= KEY_CACHE_BLOCK_SIZE;
54
58
static uint32_t myisam_key_cache_size;
55
59
static uint32_t myisam_key_cache_division_limit;
56
60
static uint32_t myisam_key_cache_age_threshold;
57
61
static uint64_t max_sort_file_size;
58
 
static uint64_t sort_buffer_size;
 
62
typedef constrained_check<size_t, SIZE_MAX, 1024, 1024> sort_buffer_constraint;
 
63
static sort_buffer_constraint sort_buffer_size;
 
64
 
 
65
void st_mi_isam_share::setKeyCache()
 
66
{
 
67
  (void)init_key_cache(&key_cache,
 
68
                       myisam_key_cache_block_size,
 
69
                       myisam_key_cache_size,
 
70
                       myisam_key_cache_division_limit, 
 
71
                       myisam_key_cache_age_threshold);
 
72
}
59
73
 
60
74
/*****************************************************************************
61
75
** MyISAM tables
82
96
                          HTON_HAS_RECORDS |
83
97
                          HTON_DUPLICATE_POS |
84
98
                          HTON_AUTO_PART_KEY |
85
 
                          HTON_SKIP_STORE_LOCK |
86
 
                          HTON_FILE_BASED )
 
99
                          HTON_SKIP_STORE_LOCK)
87
100
  {
88
 
    pthread_mutex_init(&THR_LOCK_myisam,MY_MUTEX_INIT_FAST);
89
101
  }
90
102
 
91
103
  virtual ~MyisamEngine()
92
104
  { 
93
 
    pthread_mutex_destroy(&THR_LOCK_myisam);
94
 
    end_key_cache(dflt_key_cache, 1);           // Can never fail
95
 
 
96
105
    mi_panic(HA_PANIC_CLOSE);
97
106
  }
98
107
 
99
 
  virtual Cursor *create(TableShare &table,
100
 
                         memory::Root *mem_root)
 
108
  virtual Cursor *create(Table &table)
101
109
  {
102
 
    return new (mem_root) ha_myisam(*this, table);
 
110
    return new ha_myisam(*this, table);
103
111
  }
104
112
 
105
113
  const char **bas_ext() const {
108
116
 
109
117
  int doCreateTable(Session&,
110
118
                    Table& table_arg,
111
 
                    drizzled::TableIdentifier &identifier,
 
119
                    const identifier::Table &identifier,
112
120
                    message::Table&);
113
121
 
114
 
  int doRenameTable(Session&, TableIdentifier &from, TableIdentifier &to);
 
122
  int doRenameTable(Session&, const identifier::Table &from, const identifier::Table &to);
115
123
 
116
 
  int doDropTable(Session&, drizzled::TableIdentifier &identifier);
 
124
  int doDropTable(Session&, const identifier::Table &identifier);
117
125
 
118
126
  int doGetTableDefinition(Session& session,
119
 
                           drizzled::TableIdentifier &identifier,
 
127
                           const identifier::Table &identifier,
120
128
                           message::Table &table_message);
121
129
 
122
 
  /* Temp only engine, so do not return values. */
123
 
  void doGetTableNames(CachedDirectory &, SchemaIdentifier &, set<string>&) { };
124
 
 
125
130
  uint32_t max_supported_keys()          const { return MI_MAX_KEY; }
126
131
  uint32_t max_supported_key_length()    const { return MI_MAX_KEY_LENGTH; }
127
132
  uint32_t max_supported_key_part_length() const { return MI_MAX_KEY_LENGTH; }
134
139
            HA_READ_ORDER |
135
140
            HA_KEYREAD_ONLY);
136
141
  }
137
 
  bool doDoesTableExist(Session& session, TableIdentifier &identifier);
 
142
  bool doDoesTableExist(Session& session, const identifier::Table &identifier);
138
143
 
139
144
  void doGetTableIdentifiers(drizzled::CachedDirectory &directory,
140
 
                             drizzled::SchemaIdentifier &schema_identifier,
141
 
                             drizzled::TableIdentifiers &set_of_identifiers);
 
145
                             const drizzled::identifier::Schema &schema_identifier,
 
146
                             drizzled::identifier::Table::vector &set_of_identifiers);
 
147
  bool validateCreateTableOption(const std::string &key, const std::string &state)
 
148
  {
 
149
    (void)state;
 
150
    if (boost::iequals(key, "ROW_FORMAT"))
 
151
    {
 
152
      return true;
 
153
    }
 
154
 
 
155
    return false;
 
156
  }
142
157
};
143
158
 
144
159
void MyisamEngine::doGetTableIdentifiers(drizzled::CachedDirectory&,
145
 
                                         drizzled::SchemaIdentifier&,
146
 
                                         drizzled::TableIdentifiers&)
 
160
                                         const drizzled::identifier::Schema&,
 
161
                                         drizzled::identifier::Table::vector&)
147
162
{
148
163
}
149
164
 
150
 
bool MyisamEngine::doDoesTableExist(Session &session, TableIdentifier &identifier)
 
165
bool MyisamEngine::doDoesTableExist(Session &session, const identifier::Table &identifier)
151
166
{
152
 
  return session.doesTableMessageExist(identifier);
 
167
  return session.getMessageCache().doesTableMessageExist(identifier);
153
168
}
154
169
 
155
170
int MyisamEngine::doGetTableDefinition(Session &session,
156
 
                                       drizzled::TableIdentifier &identifier,
 
171
                                       const identifier::Table &identifier,
157
172
                                       message::Table &table_message)
158
173
{
159
 
  if (session.getTableMessage(identifier, table_message))
 
174
  if (session.getMessageCache().getTableMessage(identifier, table_message))
160
175
    return EEXIST;
161
176
  return ENOENT;
162
177
}
201
216
  uint32_t i, j, recpos, minpos, fieldpos, temp_length, length;
202
217
  enum ha_base_keytype type= HA_KEYTYPE_BINARY;
203
218
  unsigned char *record;
204
 
  KEY *pos;
205
219
  MI_KEYDEF *keydef;
206
220
  MI_COLUMNDEF *recinfo, *recinfo_pos;
207
221
  HA_KEYSEG *keyseg;
208
 
  TableShare *share= table_arg->s;
 
222
  TableShare *share= table_arg->getMutableShare();
209
223
  uint32_t options= share->db_options_in_use;
210
224
  if (!(memory::multi_malloc(false,
211
 
          recinfo_out, (share->fields * 2 + 2) * sizeof(MI_COLUMNDEF),
212
 
          keydef_out, share->keys * sizeof(MI_KEYDEF),
213
 
          &keyseg, (share->key_parts + share->keys) * sizeof(HA_KEYSEG),
 
225
          recinfo_out, (share->sizeFields() * 2 + 2) * sizeof(MI_COLUMNDEF),
 
226
          keydef_out, share->sizeKeys() * sizeof(MI_KEYDEF),
 
227
          &keyseg, (share->key_parts + share->sizeKeys()) * sizeof(HA_KEYSEG),
214
228
          NULL)))
215
229
    return(HA_ERR_OUT_OF_MEM);
216
230
  keydef= *keydef_out;
217
231
  recinfo= *recinfo_out;
218
 
  pos= table_arg->key_info;
219
 
  for (i= 0; i < share->keys; i++, pos++)
 
232
  for (i= 0; i < share->sizeKeys(); i++)
220
233
  {
 
234
    KeyInfo *pos= &table_arg->key_info[i];
221
235
    keydef[i].flag= ((uint16_t) pos->flags & (HA_NOSAME));
222
236
    keydef[i].key_alg= HA_KEY_ALG_BTREE;
223
237
    keydef[i].block_length= pos->block_size;
258
272
      {
259
273
        keydef[i].seg[j].null_bit= field->null_bit;
260
274
        keydef[i].seg[j].null_pos= (uint) (field->null_ptr-
261
 
                                           (unsigned char*) table_arg->record[0]);
 
275
                                           (unsigned char*) table_arg->getInsertRecord());
262
276
      }
263
277
      else
264
278
      {
270
284
        keydef[i].seg[j].flag|= HA_BLOB_PART;
271
285
        /* save number of bytes used to pack length */
272
286
        keydef[i].seg[j].bit_start= (uint) (field->pack_length() -
273
 
                                            share->blob_ptr_size);
 
287
                                            share->sizeBlobPtr());
274
288
      }
275
289
    }
276
290
    keyseg+= pos->key_parts;
277
291
  }
278
292
  if (table_arg->found_next_number_field)
279
293
    keydef[share->next_number_index].flag|= HA_AUTO_KEY;
280
 
  record= table_arg->record[0];
 
294
  record= table_arg->getInsertRecord();
281
295
  recpos= 0;
282
296
  recinfo_pos= recinfo;
283
 
  while (recpos < (uint) share->stored_rec_length)
 
297
 
 
298
  while (recpos < (uint) share->sizeStoredRecord())
284
299
  {
285
300
    Field **field, *found= 0;
286
 
    minpos= share->reclength;
 
301
    minpos= share->getRecordLength();
287
302
    length= 0;
288
303
 
289
 
    for (field= table_arg->field; *field; field++)
 
304
    for (field= table_arg->getFields(); *field; field++)
290
305
    {
291
306
      if ((fieldpos= (*field)->offset(record)) >= recpos &&
292
307
          fieldpos <= minpos)
294
309
        /* skip null fields */
295
310
        if (!(temp_length= (*field)->pack_length_in_rec()))
296
311
          continue; /* Skip null-fields */
 
312
 
297
313
        if (! found || fieldpos < minpos ||
298
314
            (fieldpos == minpos && temp_length < length))
299
315
        {
326
342
    {
327
343
      recinfo_pos->null_bit= found->null_bit;
328
344
      recinfo_pos->null_pos= (uint) (found->null_ptr -
329
 
                                     (unsigned char*) table_arg->record[0]);
 
345
                                     (unsigned char*) table_arg->getInsertRecord());
330
346
    }
331
347
    else
332
348
    {
464
480
volatile int *killed_ptr(MI_CHECK *param)
465
481
{
466
482
  /* In theory Unsafe conversion, but should be ok for now */
467
 
  return (int*) &(((Session *)(param->session))->killed);
 
483
  return (int*) (((Session *)(param->session))->getKilledPtr());
468
484
}
469
485
 
470
486
void mi_check_print_error(MI_CHECK *param, const char *fmt,...)
514
530
                        const char *sfile, uint32_t sline)
515
531
{
516
532
  Session *cur_session;
517
 
  pthread_mutex_lock(&file->s->intern_lock);
518
533
  if ((cur_session= file->in_use))
519
 
    errmsg_printf(ERRMSG_LVL_ERROR, _("Got an error from thread_id=%"PRIu64", %s:%d"),
 
534
  {
 
535
    errmsg_printf(error::ERROR, _("Got an error from thread_id=%"PRIu64", %s:%d"),
520
536
                    cur_session->thread_id,
521
537
                    sfile, sline);
 
538
  }
522
539
  else
523
 
    errmsg_printf(ERRMSG_LVL_ERROR, _("Got an error from unknown thread, %s:%d"), sfile, sline);
 
540
  {
 
541
    errmsg_printf(error::ERROR, _("Got an error from unknown thread, %s:%d"), sfile, sline);
 
542
  }
 
543
 
524
544
  if (message)
525
 
    errmsg_printf(ERRMSG_LVL_ERROR, "%s", message);
 
545
    errmsg_printf(error::ERROR, "%s", message);
 
546
 
526
547
  list<Session *>::iterator it= file->s->in_use->begin();
527
548
  while (it != file->s->in_use->end())
528
549
  {
529
 
    errmsg_printf(ERRMSG_LVL_ERROR, "%s", _("Unknown thread accessing table"));
 
550
    errmsg_printf(error::ERROR, "%s", _("Unknown thread accessing table"));
530
551
    ++it;
531
552
  }
532
 
  pthread_mutex_unlock(&file->s->intern_lock);
533
553
}
534
554
 
535
555
ha_myisam::ha_myisam(plugin::StorageEngine &engine_arg,
536
 
                     TableShare &table_arg)
 
556
                     Table &table_arg)
537
557
  : Cursor(engine_arg, table_arg),
538
558
  file(0),
539
559
  can_enable_indexes(true),
554
574
}
555
575
 
556
576
/* Name is here without an extension */
557
 
int ha_myisam::open(const char *name, int mode, uint32_t test_if_locked)
 
577
int ha_myisam::doOpen(const drizzled::identifier::Table &identifier, int mode, uint32_t test_if_locked)
558
578
{
559
579
  MI_KEYDEF *keyinfo;
560
580
  MI_COLUMNDEF *recinfo= 0;
576
596
    open of a table that is in use by other threads already (if the
577
597
    MyISAM share exists already).
578
598
  */
579
 
  if (!(file=mi_open(name, mode, test_if_locked)))
 
599
  if (!(file= mi_open(identifier, mode, test_if_locked)))
580
600
    return (errno ? errno : -1);
581
601
 
582
 
  if (!table->s->tmp_table) /* No need to perform a check for tmp table */
 
602
  if (!getTable()->getShare()->getType()) /* No need to perform a check for tmp table */
583
603
  {
584
 
    if ((errno= table2myisam(table, &keyinfo, &recinfo, &recs)))
 
604
    if ((errno= table2myisam(getTable(), &keyinfo, &recinfo, &recs)))
585
605
    {
586
606
      goto err;
587
607
    }
588
 
    if (check_definition(keyinfo, recinfo, table->s->keys, recs,
 
608
    if (check_definition(keyinfo, recinfo, getTable()->getShare()->sizeKeys(), recs,
589
609
                         file->s->keyinfo, file->s->rec,
590
610
                         file->s->base.keys, file->s->base.fields, true))
591
611
    {
594
614
    }
595
615
  }
596
616
 
 
617
  assert(test_if_locked);
597
618
  if (test_if_locked & (HA_OPEN_IGNORE_IF_LOCKED | HA_OPEN_TMP_TABLE))
598
619
    mi_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0);
599
620
 
600
621
  info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
601
622
  if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED))
602
623
    mi_extra(file, HA_EXTRA_WAIT_LOCK, 0);
603
 
  if (!table->s->db_record_offset)
 
624
  if (!getTable()->getShare()->db_record_offset)
604
625
    is_ordered= false;
605
626
 
606
627
 
607
628
  keys_with_parts.reset();
608
 
  for (i= 0; i < table->s->keys; i++)
 
629
  for (i= 0; i < getTable()->getShare()->sizeKeys(); i++)
609
630
  {
610
 
    table->key_info[i].block_size= file->s->keyinfo[i].block_length;
 
631
    getTable()->key_info[i].block_size= file->s->keyinfo[i].block_length;
611
632
 
612
 
    KEY_PART_INFO *kp= table->key_info[i].key_part;
613
 
    KEY_PART_INFO *kp_end= kp + table->key_info[i].key_parts;
 
633
    KeyPartInfo *kp= getTable()->key_info[i].key_part;
 
634
    KeyPartInfo *kp_end= kp + getTable()->key_info[i].key_parts;
614
635
    for (; kp != kp_end; kp++)
615
636
    {
616
637
      if (!kp->field->part_of_key.test(i))
641
662
  return mi_close(tmp);
642
663
}
643
664
 
644
 
int ha_myisam::write_row(unsigned char *buf)
 
665
int ha_myisam::doInsertRecord(unsigned char *buf)
645
666
{
646
 
  ha_statistic_increment(&system_status_var::ha_write_count);
647
 
 
648
667
  /*
649
668
    If we have an auto_increment column and we are writing a changed row
650
669
    or a new row, then update the auto_increment value in the record.
651
670
  */
652
 
  if (table->next_number_field && buf == table->record[0])
 
671
  if (getTable()->next_number_field && buf == getTable()->getInsertRecord())
653
672
  {
654
673
    int error;
655
674
    if ((error= update_auto_increment()))
679
698
  */
680
699
  if (file->dfile == -1)
681
700
  {
682
 
    errmsg_printf(ERRMSG_LVL_INFO, "Retrying repair of: '%s' failed. "
683
 
                          "Please try REPAIR EXTENDED or myisamchk",
684
 
                          table->s->path.str);
 
701
    errmsg_printf(error::INFO, "Retrying repair of: '%s' failed. "
 
702
                  "Please try REPAIR EXTENDED or myisamchk",
 
703
                  getTable()->getShare()->getPath());
685
704
    return(HA_ADMIN_FAILED);
686
705
  }
687
706
 
688
 
  param.db_name=    table->s->getSchemaName();
689
 
  param.table_name= table->alias;
 
707
  param.db_name=    getTable()->getShare()->getSchemaName();
 
708
  param.table_name= getTable()->getAlias();
690
709
  param.tmpfile_createflag = O_RDWR | O_TRUNC;
691
710
  param.using_global_keycache = 1;
692
711
  param.session= session;
693
712
  param.out_flag= 0;
694
 
  param.sort_buffer_length= (size_t)sort_buffer_size;
 
713
  param.sort_buffer_length= static_cast<size_t>(sort_buffer_size);
695
714
  strcpy(fixed_name,file->filename);
696
715
 
697
716
  // Don't lock tables if we have used LOCK Table
698
 
  if (mi_lock_database(file, table->s->tmp_table ? F_EXTRA_LCK : F_WRLCK))
 
717
  if (mi_lock_database(file, getTable()->getShare()->getType() ? F_EXTRA_LCK : F_WRLCK))
699
718
  {
700
719
    mi_check_print_error(&param,ER(ER_CANT_LOCK),errno);
701
720
    return(HA_ADMIN_FAILED);
716
735
      local_testflag|= T_STATISTICS;
717
736
      param.testflag|= T_STATISTICS;            // We get this for free
718
737
      statistics_done=1;
719
 
      if (repair_threads > 1)
720
 
      {
721
 
        char buf[40];
722
 
        /* TODO: respect myisam_repair_threads variable */
723
 
        snprintf(buf, 40, "Repair with %d threads", internal::my_count_bits(key_map));
724
 
        session->set_proc_info(buf);
725
 
        error = mi_repair_parallel(&param, file, fixed_name,
726
 
            param.testflag & T_QUICK);
727
 
        session->set_proc_info("Repair done"); // to reset proc_info, as
728
 
                                      // it was pointing to local buffer
729
 
      }
730
 
      else
731
738
      {
732
739
        session->set_proc_info("Repair by sorting");
733
740
        error = mi_repair_by_sort(&param, file, fixed_name,
904
911
  }
905
912
  else if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE)
906
913
  {
907
 
    Session *session=current_session;
908
 
    MI_CHECK param;
 
914
    Session *session= getTable()->in_use;
 
915
    boost::scoped_ptr<MI_CHECK> param_ap(new MI_CHECK);
 
916
    MI_CHECK &param= *param_ap.get();
909
917
    const char *save_proc_info= session->get_proc_info();
910
918
    session->set_proc_info("Creating index");
911
919
    myisamchk_init(&param);
913
921
    param.testflag= (T_SILENT | T_REP_BY_SORT | T_QUICK |
914
922
                     T_CREATE_MISSING_KEYS);
915
923
    param.myf_rw&= ~MY_WAIT_IF_FULL;
916
 
    param.sort_buffer_length=  (size_t)sort_buffer_size;
 
924
    param.sort_buffer_length=  static_cast<size_t>(sort_buffer_size);
917
925
    param.stats_method= MI_STATS_METHOD_NULLS_NOT_EQUAL;
918
926
    if ((error= (repair(session,param,0) != HA_ADMIN_OK)) && param.retry_repair)
919
927
    {
920
 
      errmsg_printf(ERRMSG_LVL_WARN, "Warning: Enabling keys got errno %d on %s.%s, retrying",
 
928
      errmsg_printf(error::WARN, "Warning: Enabling keys got errno %d on %s.%s, retrying",
921
929
                        errno, param.db_name, param.table_name);
922
930
      /* Repairing by sort failed. Now try standard repair method. */
923
931
      param.testflag&= ~(T_REP_BY_SORT | T_QUICK);
927
935
        might have been set by the first repair. They can still be seen
928
936
        with SHOW WARNINGS then.
929
937
      */
930
 
      if (! error)
 
938
      if (not error)
931
939
        session->clear_error();
932
940
    }
933
941
    info(HA_STATUS_CONST);
980
988
 
981
989
void ha_myisam::start_bulk_insert(ha_rows rows)
982
990
{
983
 
  Session *session= current_session;
 
991
  Session *session= getTable()->in_use;
984
992
  ulong size= session->variables.read_buff_size;
985
993
 
986
994
  /* don't enable row cache if too few rows */
1032
1040
 
1033
1041
 
1034
1042
 
1035
 
int ha_myisam::update_row(const unsigned char *old_data, unsigned char *new_data)
 
1043
int ha_myisam::doUpdateRecord(const unsigned char *old_data, unsigned char *new_data)
1036
1044
{
1037
 
  ha_statistic_increment(&system_status_var::ha_update_count);
1038
 
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
1039
 
    table->timestamp_field->set_time();
1040
1045
  return mi_update(file,old_data,new_data);
1041
1046
}
1042
1047
 
1043
 
int ha_myisam::delete_row(const unsigned char *buf)
 
1048
int ha_myisam::doDeleteRecord(const unsigned char *buf)
1044
1049
{
1045
 
  ha_statistic_increment(&system_status_var::ha_delete_count);
1046
1050
  return mi_delete(file,buf);
1047
1051
}
1048
1052
 
1049
1053
 
1050
 
int ha_myisam::index_init(uint32_t idx, bool )
 
1054
int ha_myisam::doStartIndexScan(uint32_t idx, bool )
1051
1055
{
1052
1056
  active_index=idx;
1053
1057
  //in_range_read= false;
1055
1059
}
1056
1060
 
1057
1061
 
1058
 
int ha_myisam::index_end()
 
1062
int ha_myisam::doEndIndexScan()
1059
1063
{
1060
1064
  active_index=MAX_KEY;
1061
1065
  return 0;
1069
1073
  assert(inited==INDEX);
1070
1074
  ha_statistic_increment(&system_status_var::ha_read_key_count);
1071
1075
  int error=mi_rkey(file, buf, active_index, key, keypart_map, find_flag);
1072
 
  table->status=error ? STATUS_NOT_FOUND: 0;
 
1076
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
1073
1077
  return error;
1074
1078
}
1075
1079
 
1079
1083
{
1080
1084
  ha_statistic_increment(&system_status_var::ha_read_key_count);
1081
1085
  int error=mi_rkey(file, buf, index, key, keypart_map, find_flag);
1082
 
  table->status=error ? STATUS_NOT_FOUND: 0;
 
1086
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
1083
1087
  return error;
1084
1088
}
1085
1089
 
1090
1094
  ha_statistic_increment(&system_status_var::ha_read_key_count);
1091
1095
  int error=mi_rkey(file, buf, active_index, key, keypart_map,
1092
1096
                    HA_READ_PREFIX_LAST);
1093
 
  table->status=error ? STATUS_NOT_FOUND: 0;
 
1097
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
1094
1098
  return(error);
1095
1099
}
1096
1100
 
1099
1103
  assert(inited==INDEX);
1100
1104
  ha_statistic_increment(&system_status_var::ha_read_next_count);
1101
1105
  int error=mi_rnext(file,buf,active_index);
1102
 
  table->status=error ? STATUS_NOT_FOUND: 0;
 
1106
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
1103
1107
  return error;
1104
1108
}
1105
1109
 
1108
1112
  assert(inited==INDEX);
1109
1113
  ha_statistic_increment(&system_status_var::ha_read_prev_count);
1110
1114
  int error=mi_rprev(file,buf, active_index);
1111
 
  table->status=error ? STATUS_NOT_FOUND: 0;
 
1115
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
1112
1116
  return error;
1113
1117
}
1114
1118
 
1117
1121
  assert(inited==INDEX);
1118
1122
  ha_statistic_increment(&system_status_var::ha_read_first_count);
1119
1123
  int error=mi_rfirst(file, buf, active_index);
1120
 
  table->status=error ? STATUS_NOT_FOUND: 0;
 
1124
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
1121
1125
  return error;
1122
1126
}
1123
1127
 
1126
1130
  assert(inited==INDEX);
1127
1131
  ha_statistic_increment(&system_status_var::ha_read_last_count);
1128
1132
  int error=mi_rlast(file, buf, active_index);
1129
 
  table->status=error ? STATUS_NOT_FOUND: 0;
 
1133
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
1130
1134
  return error;
1131
1135
}
1132
1136
 
1141
1145
  {
1142
1146
    error= mi_rnext_same(file,buf);
1143
1147
  } while (error == HA_ERR_RECORD_DELETED);
1144
 
  table->status=error ? STATUS_NOT_FOUND: 0;
 
1148
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
1145
1149
  return error;
1146
1150
}
1147
1151
 
1171
1175
}
1172
1176
 
1173
1177
 
1174
 
int ha_myisam::rnd_init(bool scan)
 
1178
int ha_myisam::doStartTableScan(bool scan)
1175
1179
{
1176
1180
  if (scan)
1177
1181
    return mi_scan_init(file);
1182
1186
{
1183
1187
  ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
1184
1188
  int error=mi_scan(file, buf);
1185
 
  table->status=error ? STATUS_NOT_FOUND: 0;
 
1189
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
1186
1190
  return error;
1187
1191
}
1188
1192
 
1189
 
int ha_myisam::restart_rnd_next(unsigned char *buf, unsigned char *pos)
1190
 
{
1191
 
  return rnd_pos(buf,pos);
1192
 
}
1193
 
 
1194
1193
int ha_myisam::rnd_pos(unsigned char *buf, unsigned char *pos)
1195
1194
{
1196
1195
  ha_statistic_increment(&system_status_var::ha_read_rnd_count);
1197
1196
  int error=mi_rrnd(file, buf, internal::my_get_ptr(pos,ref_length));
1198
 
  table->status=error ? STATUS_NOT_FOUND: 0;
 
1197
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
1199
1198
  return error;
1200
1199
}
1201
1200
 
1224
1223
  }
1225
1224
  if (flag & HA_STATUS_CONST)
1226
1225
  {
1227
 
    TableShare *share= table->s;
 
1226
    TableShare *share= getTable()->getMutableShare();
1228
1227
    stats.max_data_file_length=  misam_info.max_data_file_length;
1229
1228
    stats.max_index_file_length= misam_info.max_index_file_length;
1230
1229
    stats.create_time= misam_info.create_time;
1232
1231
    share->db_options_in_use= misam_info.options;
1233
1232
    stats.block_size= myisam_key_cache_block_size;        /* record block size */
1234
1233
 
1235
 
    /* Update share */
1236
 
    if (share->tmp_table == message::Table::STANDARD)
1237
 
      pthread_mutex_lock(&share->mutex);
1238
 
    set_prefix(share->keys_in_use, share->keys);
 
1234
    set_prefix(share->keys_in_use, share->sizeKeys());
1239
1235
    /*
1240
1236
     * Due to bug 394932 (32-bit solaris build failure), we need
1241
1237
     * to convert the uint64_t key_map member of the misam_info
1284
1280
    share->keys_for_keyread&= share->keys_in_use;
1285
1281
    share->db_record_offset= misam_info.record_offset;
1286
1282
    if (share->key_parts)
1287
 
      memcpy(table->key_info[0].rec_per_key,
 
1283
      memcpy(getTable()->key_info[0].rec_per_key,
1288
1284
             misam_info.rec_per_key,
1289
 
             sizeof(table->key_info[0].rec_per_key)*share->key_parts);
1290
 
    if (share->tmp_table == message::Table::STANDARD)
1291
 
      pthread_mutex_unlock(&share->mutex);
 
1285
             sizeof(getTable()->key_info[0].rec_per_key)*share->key_parts);
 
1286
    assert(share->getType() != message::Table::STANDARD);
1292
1287
 
1293
1288
   /*
1294
1289
     Set data_file_name and index_file_name to point at the symlink value
1341
1336
}
1342
1337
 
1343
1338
int MyisamEngine::doDropTable(Session &session,
1344
 
                              drizzled::TableIdentifier &identifier)
 
1339
                              const identifier::Table &identifier)
1345
1340
{
1346
 
  session.removeTableMessage(identifier);
 
1341
  session.getMessageCache().removeTableMessage(identifier);
1347
1342
 
1348
1343
  return mi_delete_table(identifier.getPath().c_str());
1349
1344
}
1352
1347
int ha_myisam::external_lock(Session *session, int lock_type)
1353
1348
{
1354
1349
  file->in_use= session;
1355
 
  return mi_lock_database(file, !table->s->tmp_table ?
 
1350
  return mi_lock_database(file, !getTable()->getShare()->getType() ?
1356
1351
                          lock_type : ((lock_type == F_UNLCK) ?
1357
1352
                                       F_UNLCK : F_EXTRA_LCK));
1358
1353
}
1359
1354
 
1360
1355
int MyisamEngine::doCreateTable(Session &session,
1361
1356
                                Table& table_arg,
1362
 
                                drizzled::TableIdentifier &identifier,
 
1357
                                const identifier::Table &identifier,
1363
1358
                                message::Table& create_proto)
1364
1359
{
1365
1360
  int error;
1368
1363
  MI_KEYDEF *keydef;
1369
1364
  MI_COLUMNDEF *recinfo;
1370
1365
  MI_CREATE_INFO create_info;
1371
 
  TableShare *share= table_arg.s;
 
1366
  TableShare *share= table_arg.getMutableShare();
1372
1367
  uint32_t options= share->db_options_in_use;
1373
1368
  if ((error= table2myisam(&table_arg, &keydef, &recinfo, &create_records)))
1374
1369
    return(error);
1393
1388
  /* TODO: Check that the following internal::fn_format is really needed */
1394
1389
  error= mi_create(internal::fn_format(buff, identifier.getPath().c_str(), "", "",
1395
1390
                                       MY_UNPACK_FILENAME|MY_APPEND_EXT),
1396
 
                   share->keys, keydef,
 
1391
                   share->sizeKeys(), keydef,
1397
1392
                   create_records, recinfo,
1398
1393
                   0, (MI_UNIQUEDEF*) 0,
1399
1394
                   &create_info, create_flags);
1400
1395
  free((unsigned char*) recinfo);
1401
1396
 
1402
 
  session.storeTableMessage(identifier, create_proto);
 
1397
  session.getMessageCache().storeTableMessage(identifier, create_proto);
1403
1398
 
1404
1399
  return error;
1405
1400
}
1406
1401
 
1407
1402
 
1408
 
int MyisamEngine::doRenameTable(Session &session, TableIdentifier &from, TableIdentifier &to)
 
1403
int MyisamEngine::doRenameTable(Session &session, const identifier::Table &from, const identifier::Table &to)
1409
1404
{
1410
 
  session.renameTableMessage(from, to);
 
1405
  session.getMessageCache().renameTableMessage(from, to);
1411
1406
 
1412
1407
  return mi_rename(from.getPath().c_str(), to.getPath().c_str());
1413
1408
}
1423
1418
  int error;
1424
1419
  unsigned char key[MI_MAX_KEY_LENGTH];
1425
1420
 
1426
 
  if (!table->s->next_number_key_offset)
 
1421
  if (!getTable()->getShare()->next_number_key_offset)
1427
1422
  {                                             // Autoincrement at key-start
1428
1423
    ha_myisam::info(HA_STATUS_AUTO);
1429
1424
    *first_value= stats.auto_increment_value;
1433
1428
  }
1434
1429
 
1435
1430
  /* it's safe to call the following if bulk_insert isn't on */
1436
 
  mi_flush_bulk_insert(file, table->s->next_number_index);
 
1431
  mi_flush_bulk_insert(file, getTable()->getShare()->next_number_index);
1437
1432
 
1438
1433
  (void) extra(HA_EXTRA_KEYREAD);
1439
 
  key_copy(key, table->record[0],
1440
 
           table->key_info + table->s->next_number_index,
1441
 
           table->s->next_number_key_offset);
1442
 
  error= mi_rkey(file, table->record[1], (int) table->s->next_number_index,
1443
 
                 key, make_prev_keypart_map(table->s->next_number_keypart),
 
1434
  key_copy(key, getTable()->getInsertRecord(),
 
1435
           &getTable()->key_info[getTable()->getShare()->next_number_index],
 
1436
           getTable()->getShare()->next_number_key_offset);
 
1437
  error= mi_rkey(file, getTable()->getUpdateRecord(), (int) getTable()->getShare()->next_number_index,
 
1438
                 key, make_prev_keypart_map(getTable()->getShare()->next_number_keypart),
1444
1439
                 HA_READ_PREFIX_LAST);
1445
1440
  if (error)
1446
1441
    nr= 1;
1447
1442
  else
1448
1443
  {
1449
 
    /* Get data from record[1] */
1450
 
    nr= ((uint64_t) table->next_number_field->
1451
 
         val_int_offset(table->s->rec_buff_length)+1);
 
1444
    /* Get data from getUpdateRecord() */
 
1445
    nr= ((uint64_t) getTable()->next_number_field->
 
1446
         val_int_offset(getTable()->getShare()->rec_buff_length)+1);
1452
1447
  }
1453
1448
  extra(HA_EXTRA_NO_KEYREAD);
1454
1449
  *first_value= nr;
1499
1494
  return (uint)file->state->checksum;
1500
1495
}
1501
1496
 
1502
 
static MyisamEngine *engine= NULL;
1503
 
 
1504
 
static int myisam_init(plugin::Context &context)
1505
 
{
1506
 
  engine= new MyisamEngine(engine_name);
1507
 
  context.add(engine);
1508
 
 
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);
1515
 
 
1516
 
  if (error == 0)
1517
 
    exit(1); /* Memory Allocation Failure */
 
1497
static int myisam_init(module::Context &context)
 
1498
 
1499
  context.add(new MyisamEngine(engine_name));
 
1500
  context.registerVariable(new sys_var_constrained_value<size_t>("sort-buffer-size",
 
1501
                                                                 sort_buffer_size));
 
1502
  context.registerVariable(new sys_var_uint64_t_ptr("max_sort_file_size",
 
1503
                                                    &max_sort_file_size,
 
1504
                                                    context.getOptions()["max-sort-file-size"].as<uint64_t>()));
1518
1505
 
1519
1506
  return 0;
1520
1507
}
1521
1508
 
1522
1509
 
1523
 
static void sys_var_key_cache_size_update(Session *session, drizzle_sys_var *var, void *, const void *save)
1524
 
{
1525
 
  uint32_t tmp= *static_cast<const uint32_t *>(save);
1526
 
  bool error= 0;
1527
 
 
1528
 
        struct option option_limits;
1529
 
  plugin_opt_set_limits(&option_limits, var);
1530
 
        option_limits.name= "myisam_key_cache_size";
1531
 
 
1532
 
  if (dflt_key_cache->in_init)
1533
 
    return;
1534
 
 
1535
 
  myisam_key_cache_size= static_cast<uint32_t>(fix_unsigned(session, static_cast<uint64_t>(tmp), &option_limits));
1536
 
 
1537
 
  /* If key cache didn't existed initialize it, else resize it */
1538
 
  dflt_key_cache->in_init= 1;
1539
 
 
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;
1546
 
}
1547
 
 
1548
 
static void sys_var_key_cache_block_size_update(Session *session, drizzle_sys_var *var, void *, const void *save)
1549
 
{
1550
 
  uint32_t tmp= *static_cast<const uint32_t *>(save);
1551
 
  bool error= 0;
1552
 
 
1553
 
        struct option option_limits;
1554
 
  plugin_opt_set_limits(&option_limits, var);
1555
 
        option_limits.name= "myisam_key_cache_block_size";
1556
 
 
1557
 
  if (dflt_key_cache->in_init)
1558
 
    return;
1559
 
 
1560
 
  myisam_key_cache_block_size= static_cast<uint32_t>(fix_unsigned(session, static_cast<uint64_t>(tmp), &option_limits));
1561
 
 
1562
 
  dflt_key_cache->in_init= 1;
1563
 
 
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);
1569
 
 
1570
 
  dflt_key_cache->in_init= 0;
1571
 
}
1572
 
 
1573
 
static void sys_var_key_cache_division_limit_update(Session *session, drizzle_sys_var *var, void *, const void *save)
1574
 
{
1575
 
  uint32_t tmp= *static_cast<const uint32_t *>(save);
1576
 
  bool error= 0;
1577
 
 
1578
 
        struct option option_limits;
1579
 
  plugin_opt_set_limits(&option_limits, var);
1580
 
        option_limits.name= "myisam_key_cache_division_limit";
1581
 
 
1582
 
  if (dflt_key_cache->in_init)
1583
 
    return;
1584
 
 
1585
 
  myisam_key_cache_division_limit= static_cast<uint32_t>(fix_unsigned(session, static_cast<uint64_t>(tmp), &option_limits));
1586
 
 
1587
 
  dflt_key_cache->in_init= 1;
1588
 
 
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);
1594
 
 
1595
 
  dflt_key_cache->in_init= 0;
1596
 
}
1597
 
 
1598
 
static void sys_var_key_cache_age_threshold_update(Session *session, drizzle_sys_var *var, void *, const void *save)
1599
 
{
1600
 
  uint32_t tmp= *static_cast<const uint32_t *>(save);
1601
 
  bool error= 0;
1602
 
 
1603
 
        struct option option_limits;
1604
 
  plugin_opt_set_limits(&option_limits, var);
1605
 
        option_limits.name= "myisam_key_cache_age_threshold";
1606
 
 
1607
 
  if (dflt_key_cache->in_init)
1608
 
    return;
1609
 
 
1610
 
  myisam_key_cache_age_threshold= static_cast<uint32_t>(fix_unsigned(session, static_cast<uint64_t>(tmp), &option_limits));
1611
 
 
1612
 
  dflt_key_cache->in_init= 1;
1613
 
 
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);
1619
 
 
1620
 
  dflt_key_cache->in_init= 0;
1621
 
}
1622
 
 
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."),
1627
 
                            NULL,
1628
 
                            sys_var_key_cache_block_size_update,
1629
 
                            KEY_CACHE_BLOCK_SIZE,
1630
 
                            512, 
1631
 
                            16 * 1024,
1632
 
                            0);
1633
 
 
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"),
1640
 
                            NULL,
1641
 
                            sys_var_key_cache_age_threshold_update,
1642
 
                            300,
1643
 
                            100, 
1644
 
                            UINT32_MAX,
1645
 
                            0);
1646
 
 
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"),
1650
 
                            NULL,
1651
 
                            sys_var_key_cache_division_limit_update,
1652
 
                            100,
1653
 
                            1, 
1654
 
                            100,
1655
 
                            0);
1656
 
 
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;"),
1663
 
                            NULL,
1664
 
                            sys_var_key_cache_size_update,
1665
 
                            KEY_CACHE_SIZE,
1666
 
                            1 * 1024 * 1024, 
1667
 
                            UINT32_MAX,
1668
 
                            IO_SIZE);
1669
 
 
1670
 
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);
1675
 
 
1676
 
static DRIZZLE_SYSVAR_ULONGLONG(max_sort_file_size, max_sort_file_size,
1677
 
                                PLUGIN_VAR_RQCMDARG,
1678
 
                                N_("Don't use the fast sort index method to created index if the temporary file would get bigger than this."),
1679
 
                                NULL, NULL, INT32_MAX, 0, UINT64_MAX, 0);
1680
 
 
1681
 
static DRIZZLE_SYSVAR_ULONGLONG(sort_buffer_size, sort_buffer_size,
1682
 
                                PLUGIN_VAR_RQCMDARG,
1683
 
                                N_("The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE."),
1684
 
                                NULL, NULL, 8192*1024, 1024, SIZE_MAX, 0);
1685
 
 
1686
 
extern uint32_t data_pointer_size;
1687
 
static DRIZZLE_SYSVAR_UINT(data_pointer_size, data_pointer_size,
1688
 
                            PLUGIN_VAR_RQCMDARG,
1689
 
                            N_("Default pointer size to be used for MyISAM tables."),
1690
 
                            NULL, NULL, 6, 2, 7, 0);
1691
 
 
1692
 
static drizzle_sys_var* sys_variables[]= {
1693
 
  DRIZZLE_SYSVAR(key_cache_block_size),
1694
 
  DRIZZLE_SYSVAR(key_cache_size),
1695
 
  DRIZZLE_SYSVAR(key_cache_division_limit),
1696
 
  DRIZZLE_SYSVAR(key_cache_age_threshold),
1697
 
  DRIZZLE_SYSVAR(repair_threads),
1698
 
  DRIZZLE_SYSVAR(max_sort_file_size),
1699
 
  DRIZZLE_SYSVAR(sort_buffer_size),
1700
 
  DRIZZLE_SYSVAR(data_pointer_size),
1701
 
  NULL
1702
 
};
 
1510
static void init_options(drizzled::module::option_context &context)
 
1511
{
 
1512
  context("max-sort-file-size",
 
1513
          po::value<uint64_t>(&max_sort_file_size)->default_value(INT32_MAX),
 
1514
          _("Don't use the fast sort index method to created index if the temporary file would get bigger than this."));
 
1515
  context("sort-buffer-size",
 
1516
          po::value<sort_buffer_constraint>(&sort_buffer_size)->default_value(8192*1024),
 
1517
          _("The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE."));
 
1518
}
1703
1519
 
1704
1520
 
1705
1521
DRIZZLE_DECLARE_PLUGIN
1706
1522
{
1707
1523
  DRIZZLE_VERSION_ID,
1708
1524
  "MyISAM",
1709
 
  "1.0",
 
1525
  "2.0",
1710
1526
  "MySQL AB",
1711
1527
  "Default engine as of MySQL 3.23 with great performance",
1712
1528
  PLUGIN_LICENSE_GPL,
1713
1529
  myisam_init, /* Plugin Init */
1714
 
  sys_variables,           /* system variables */
1715
 
  NULL                        /* config options                  */
 
1530
  NULL,           /* depends */
 
1531
  init_options                        /* config options                  */
1716
1532
}
1717
1533
DRIZZLE_DECLARE_PLUGIN_END;