~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/myisam/ha_myisam.cc

  • Committer: Padraig O'Sullivan
  • Date: 2009-09-13 01:03:01 UTC
  • mto: (1126.9.2 captain-20090915-01)
  • mto: This revision was merged to the branch mainline in revision 1133.
  • Revision ID: osullivan.padraig@gmail.com-20090913010301-tcvvezipx1124acy
Added calls to the dtrace delete begin/end probes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 
16
16
 
17
17
 
18
 
#include "config.h"
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"
 
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/plugin/protocol.h>
 
29
#include <drizzled/table.h>
 
30
#include <drizzled/field/timestamp.h>
38
31
 
39
32
#include <string>
40
 
#include <sstream>
41
 
#include <map>
42
33
#include <algorithm>
43
34
 
44
35
using namespace std;
45
 
using namespace drizzled;
46
36
 
47
 
extern pthread_mutex_t LOCK_global_system_variables;
48
37
static const string engine_name("MyISAM");
49
38
 
 
39
ulong myisam_recover_options= HA_RECOVER_NONE;
50
40
pthread_mutex_t THR_LOCK_myisam= PTHREAD_MUTEX_INITIALIZER;
51
41
 
52
42
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;
 
43
static uint32_t block_size;
57
44
static uint64_t max_sort_file_size;
58
45
static uint64_t sort_buffer_size;
59
46
 
 
47
/* bits in myisam_recover_options */
 
48
const char *myisam_recover_names[] =
 
49
{ "DEFAULT", "BACKUP", "FORCE", "QUICK", NULL};
 
50
TYPELIB myisam_recover_typelib= {array_elements(myisam_recover_names)-1,"",
 
51
                                 myisam_recover_names, NULL};
 
52
 
 
53
 
 
54
 
60
55
/*****************************************************************************
61
56
** MyISAM tables
62
57
*****************************************************************************/
67
62
  NULL
68
63
};
69
64
 
70
 
class MyisamEngine : public plugin::StorageEngine
 
65
class MyisamEngine : public StorageEngine
71
66
{
72
 
  MyisamEngine();
73
 
  MyisamEngine(const MyisamEngine&);
74
 
  MyisamEngine& operator=(const MyisamEngine&);
75
67
public:
76
 
  explicit MyisamEngine(string name_arg) :
77
 
    plugin::StorageEngine(name_arg,
78
 
                          HTON_CAN_INDEX_BLOBS |
79
 
                          HTON_STATS_RECORDS_IS_EXACT |
80
 
                          HTON_TEMPORARY_ONLY |
81
 
                          HTON_NULL_IN_KEY |
82
 
                          HTON_HAS_RECORDS |
83
 
                          HTON_DUPLICATE_POS |
84
 
                          HTON_AUTO_PART_KEY |
85
 
                          HTON_SKIP_STORE_LOCK |
86
 
                          HTON_FILE_BASED )
87
 
  {
88
 
    pthread_mutex_init(&THR_LOCK_myisam,MY_MUTEX_INIT_FAST);
89
 
  }
90
 
 
91
 
  virtual ~MyisamEngine()
92
 
  { 
93
 
    pthread_mutex_destroy(&THR_LOCK_myisam);
94
 
    end_key_cache(dflt_key_cache, 1);           // Can never fail
95
 
 
96
 
    mi_panic(HA_PANIC_CLOSE);
97
 
  }
98
 
 
99
 
  virtual Cursor *create(TableShare &table,
100
 
                         memory::Root *mem_root)
101
 
  {
102
 
    return new (mem_root) ha_myisam(*this, table);
 
68
  MyisamEngine(string name_arg)
 
69
   : StorageEngine(name_arg, 
 
70
                   HTON_CAN_RECREATE | 
 
71
                   HTON_TEMPORARY_ONLY | 
 
72
                   HTON_FILE_BASED ) {}
 
73
 
 
74
  virtual handler *create(TableShare *table,
 
75
                          MEM_ROOT *mem_root)
 
76
  {
 
77
    return new (mem_root) ha_myisam(this, table);
103
78
  }
104
79
 
105
80
  const char **bas_ext() const {
106
81
    return ha_myisam_exts;
107
82
  }
108
83
 
109
 
  int doCreateTable(Session&,
110
 
                    Table& table_arg,
111
 
                    drizzled::TableIdentifier &identifier,
112
 
                    message::Table&);
113
 
 
114
 
  int doRenameTable(Session&, TableIdentifier &from, TableIdentifier &to);
115
 
 
116
 
  int doDropTable(Session&, drizzled::TableIdentifier &identifier);
117
 
 
118
 
  int doGetTableDefinition(Session& session,
119
 
                           drizzled::TableIdentifier &identifier,
120
 
                           message::Table &table_message);
121
 
 
122
 
  /* Temp only engine, so do not return values. */
123
 
  void doGetTableNames(CachedDirectory &, SchemaIdentifier &, set<string>&) { };
124
 
 
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; }
128
 
 
129
 
  uint32_t index_flags(enum  ha_key_alg) const
130
 
  {
131
 
    return (HA_READ_NEXT |
132
 
            HA_READ_PREV |
133
 
            HA_READ_RANGE |
134
 
            HA_READ_ORDER |
135
 
            HA_KEYREAD_ONLY);
136
 
  }
137
 
  bool doDoesTableExist(Session& session, TableIdentifier &identifier);
138
 
 
139
 
  void doGetTableIdentifiers(drizzled::CachedDirectory &directory,
140
 
                             drizzled::SchemaIdentifier &schema_identifier,
141
 
                             drizzled::TableIdentifiers &set_of_identifiers);
 
84
  int createTableImplementation(Session *, const char *table_name,
 
85
                                Table *table_arg,
 
86
                                HA_CREATE_INFO *ha_create_info,
 
87
                                drizzled::message::Table*);
 
88
 
 
89
  int renameTableImplementation(Session*, const char *from, const char *to);
 
90
 
 
91
  int deleteTableImplementation(Session*, const string table_name);
142
92
};
143
93
 
144
 
void MyisamEngine::doGetTableIdentifiers(drizzled::CachedDirectory&,
145
 
                                         drizzled::SchemaIdentifier&,
146
 
                                         drizzled::TableIdentifiers&)
147
 
{
148
 
}
149
 
 
150
 
bool MyisamEngine::doDoesTableExist(Session &session, TableIdentifier &identifier)
151
 
{
152
 
  return session.doesTableMessageExist(identifier);
153
 
}
154
 
 
155
 
int MyisamEngine::doGetTableDefinition(Session &session,
156
 
                                       drizzled::TableIdentifier &identifier,
157
 
                                       message::Table &table_message)
158
 
{
159
 
  if (session.getTableMessage(identifier, table_message))
160
 
    return EEXIST;
161
 
  return ENOENT;
162
 
}
163
 
 
164
 
/* 
165
 
  Convert to push_Warnings if you ever care about this, otherwise, it is a no-op.
166
 
*/
167
 
 
168
 
static void mi_check_print_msg(MI_CHECK *,      const char* ,
169
 
                               const char *, va_list )
170
 
{
 
94
// collect errors printed by mi_check routines
 
95
 
 
96
static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
 
97
                               const char *fmt, va_list args)
 
98
{
 
99
  Session* session = (Session*)param->session;
 
100
  drizzled::plugin::Protocol *protocol= session->protocol;
 
101
  uint32_t length, msg_length;
 
102
  char msgbuf[MI_MAX_MSG_BUF];
 
103
  char name[NAME_LEN*2+2];
 
104
 
 
105
  msg_length= vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
 
106
  msgbuf[sizeof(msgbuf) - 1] = 0; // healthy paranoia
 
107
 
 
108
  if (!session->protocol->isConnected())
 
109
  {
 
110
    errmsg_printf(ERRMSG_LVL_ERROR, "%s",msgbuf);
 
111
    return;
 
112
  }
 
113
 
 
114
  if (param->testflag & (T_CREATE_MISSING_KEYS | T_SAFE_REPAIR |
 
115
                         T_AUTO_REPAIR))
 
116
  {
 
117
    my_message(ER_NOT_KEYFILE,msgbuf,MYF(MY_WME));
 
118
    return;
 
119
  }
 
120
  length= sprintf(name,"%s.%s",param->db_name,param->table_name);
 
121
 
 
122
  /*
 
123
    TODO: switch from protocol to push_warning here. The main reason we didn't
 
124
    it yet is parallel repair. Due to following trace:
 
125
    mi_check_print_msg/push_warning/sql_alloc/my_pthread_getspecific_ptr.
 
126
 
 
127
    Also we likely need to lock mutex here (in both cases with protocol and
 
128
    push_warning).
 
129
  */
 
130
  protocol->prepareForResend();
 
131
  protocol->store(name, length);
 
132
  protocol->store(param->op_name);
 
133
  protocol->store(msg_type);
 
134
  protocol->store(msgbuf, msg_length);
 
135
  if (protocol->write())
 
136
    errmsg_printf(ERRMSG_LVL_ERROR, "Failed on drizzleclient_net_write, writing to stderr instead: %s\n",
 
137
                    msgbuf);
 
138
  return;
171
139
}
172
140
 
173
141
 
187
155
    table conformance in merge engine.
188
156
 
189
157
    The caller needs to free *recinfo_out after use. Since *recinfo_out
190
 
    and *keydef_out are allocated with a multi_malloc, *keydef_out
 
158
    and *keydef_out are allocated with a my_multi_malloc, *keydef_out
191
159
    is freed automatically when *recinfo_out is freed.
192
160
 
193
161
  RETURN VALUE
207
175
  HA_KEYSEG *keyseg;
208
176
  TableShare *share= table_arg->s;
209
177
  uint32_t options= share->db_options_in_use;
210
 
  if (!(memory::multi_malloc(false,
 
178
  if (!(my_multi_malloc(MYF(MY_WME),
211
179
          recinfo_out, (share->fields * 2 + 2) * sizeof(MI_COLUMNDEF),
212
180
          keydef_out, share->keys * sizeof(MI_KEYDEF),
213
 
          &keyseg, (share->key_parts + share->keys) * sizeof(HA_KEYSEG),
 
181
          &keyseg,
 
182
          (share->key_parts + share->keys) * sizeof(HA_KEYSEG),
214
183
          NULL)))
215
 
    return(HA_ERR_OUT_OF_MEM);
 
184
    return(HA_ERR_OUT_OF_MEM); /* purecov: inspected */
216
185
  keydef= *keydef_out;
217
186
  recinfo= *recinfo_out;
218
187
  pos= table_arg->key_info;
235
204
      {
236
205
        if (pos->key_part[j].length > 8 &&
237
206
            (type == HA_KEYTYPE_TEXT ||
 
207
             type == HA_KEYTYPE_NUM ||
238
208
             (type == HA_KEYTYPE_BINARY && !field->zero_pack())))
239
209
        {
240
210
          /* No blobs here */
340
310
  return(0);
341
311
}
342
312
 
343
 
int ha_myisam::reset_auto_increment(uint64_t value)
344
 
{
345
 
  file->s->state.auto_increment= value;
346
 
  return 0;
347
 
}
348
313
 
349
314
/*
350
315
  Check for underlying table conformance
424
389
      {
425
390
        if ((t1_keysegs_j__type == HA_KEYTYPE_VARTEXT2) &&
426
391
            (t2_keysegs[j].type == HA_KEYTYPE_VARTEXT1))
427
 
          t1_keysegs_j__type= HA_KEYTYPE_VARTEXT1;
 
392
          t1_keysegs_j__type= HA_KEYTYPE_VARTEXT1; /* purecov: tested */
428
393
        else if ((t1_keysegs_j__type == HA_KEYTYPE_VARBINARY2) &&
429
394
                 (t2_keysegs[j].type == HA_KEYTYPE_VARBINARY1))
430
 
          t1_keysegs_j__type= HA_KEYTYPE_VARBINARY1;
 
395
          t1_keysegs_j__type= HA_KEYTYPE_VARBINARY1; /* purecov: inspected */
431
396
      }
432
397
 
433
398
      if (t1_keysegs_j__type != t2_keysegs[j].type ||
461
426
}
462
427
 
463
428
 
 
429
extern "C" {
 
430
 
464
431
volatile int *killed_ptr(MI_CHECK *param)
465
432
{
466
433
  /* In theory Unsafe conversion, but should be ok for now */
532
499
  pthread_mutex_unlock(&file->s->intern_lock);
533
500
}
534
501
 
535
 
ha_myisam::ha_myisam(plugin::StorageEngine &engine_arg,
536
 
                     TableShare &table_arg)
537
 
  : Cursor(engine_arg, table_arg),
538
 
  file(0),
539
 
  can_enable_indexes(true),
540
 
  is_ordered(true)
541
 
{ }
542
 
 
543
 
Cursor *ha_myisam::clone(memory::Root *mem_root)
 
502
}
 
503
 
 
504
ha_myisam::ha_myisam(StorageEngine *engine_arg, TableShare *table_arg)
 
505
  :handler(engine_arg, table_arg), file(0),
 
506
  int_table_flags(HA_NULL_IN_KEY |
 
507
                  HA_DUPLICATE_POS |
 
508
                  HA_CAN_INDEX_BLOBS |
 
509
                  HA_AUTO_PART_KEY |
 
510
                  HA_NO_TRANSACTIONS |
 
511
                  HA_HAS_RECORDS |
 
512
                  HA_STATS_RECORDS_IS_EXACT |
 
513
                  HA_NEED_READ_RANGE_BUFFER |
 
514
                  HA_MRR_CANT_SORT),
 
515
   can_enable_indexes(1)
 
516
{}
 
517
 
 
518
handler *ha_myisam::clone(MEM_ROOT *mem_root)
544
519
{
545
 
  ha_myisam *new_handler= static_cast <ha_myisam *>(Cursor::clone(mem_root));
 
520
  ha_myisam *new_handler= static_cast <ha_myisam *>(handler::clone(mem_root));
546
521
  if (new_handler)
547
522
    new_handler->file->state= file->state;
548
523
  return new_handler;
577
552
    MyISAM share exists already).
578
553
  */
579
554
  if (!(file=mi_open(name, mode, test_if_locked)))
580
 
    return (errno ? errno : -1);
 
555
    return (my_errno ? my_errno : -1);
581
556
 
582
557
  if (!table->s->tmp_table) /* No need to perform a check for tmp table */
583
558
  {
584
 
    if ((errno= table2myisam(table, &keyinfo, &recinfo, &recs)))
 
559
    if ((my_errno= table2myisam(table, &keyinfo, &recinfo, &recs)))
585
560
    {
 
561
      /* purecov: begin inspected */
586
562
      goto err;
 
563
      /* purecov: end */
587
564
    }
588
565
    if (check_definition(keyinfo, recinfo, table->s->keys, recs,
589
566
                         file->s->keyinfo, file->s->rec,
590
567
                         file->s->base.keys, file->s->base.fields, true))
591
568
    {
592
 
      errno= HA_ERR_CRASHED;
 
569
      /* purecov: begin inspected */
 
570
      my_errno= HA_ERR_CRASHED;
593
571
      goto err;
 
572
      /* purecov: end */
594
573
    }
595
574
  }
596
575
 
601
580
  if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED))
602
581
    mi_extra(file, HA_EXTRA_WAIT_LOCK, 0);
603
582
  if (!table->s->db_record_offset)
604
 
    is_ordered= false;
605
 
 
 
583
    int_table_flags|=HA_REC_NOT_IN_SEQ;
606
584
 
607
585
  keys_with_parts.reset();
608
586
  for (i= 0; i < table->s->keys; i++)
620
598
      }
621
599
    }
622
600
  }
623
 
  errno= 0;
 
601
  my_errno= 0;
624
602
  goto end;
625
603
 err:
626
604
  this->close();
627
605
 end:
628
606
  /*
629
 
    Both recinfo and keydef are allocated by multi_malloc(), thus only
 
607
    Both recinfo and keydef are allocated by my_multi_malloc(), thus only
630
608
    recinfo must be freed.
631
609
  */
632
610
  if (recinfo)
633
611
    free((unsigned char*) recinfo);
634
 
  return errno;
 
612
  return my_errno;
635
613
}
636
614
 
637
615
int ha_myisam::close(void)
643
621
 
644
622
int ha_myisam::write_row(unsigned char *buf)
645
623
{
646
 
  ha_statistic_increment(&system_status_var::ha_write_count);
 
624
  ha_statistic_increment(&SSV::ha_write_count);
647
625
 
648
626
  /*
649
627
    If we have an auto_increment column and we are writing a changed row
685
663
    return(HA_ADMIN_FAILED);
686
664
  }
687
665
 
688
 
  param.db_name=    table->s->getSchemaName();
 
666
  param.db_name=    table->s->db.str;
689
667
  param.table_name= table->alias;
690
668
  param.tmpfile_createflag = O_RDWR | O_TRUNC;
691
669
  param.using_global_keycache = 1;
697
675
  // Don't lock tables if we have used LOCK Table
698
676
  if (mi_lock_database(file, table->s->tmp_table ? F_EXTRA_LCK : F_WRLCK))
699
677
  {
700
 
    mi_check_print_error(&param,ER(ER_CANT_LOCK),errno);
 
678
    mi_check_print_error(&param,ER(ER_CANT_LOCK),my_errno);
701
679
    return(HA_ADMIN_FAILED);
702
680
  }
703
681
 
720
698
      {
721
699
        char buf[40];
722
700
        /* TODO: respect myisam_repair_threads variable */
723
 
        snprintf(buf, 40, "Repair with %d threads", internal::my_count_bits(key_map));
 
701
        snprintf(buf, 40, "Repair with %d threads", my_count_bits(key_map));
724
702
        session->set_proc_info(buf);
725
703
        error = mi_repair_parallel(&param, file, fixed_name,
726
704
            param.testflag & T_QUICK);
793
771
    {
794
772
      char llbuff[22],llbuff2[22];
795
773
      mi_check_print_warning(&param,"Number of rows changed from %s to %s",
796
 
                             internal::llstr(rows,llbuff),
797
 
                             internal::llstr(file->state->records,llbuff2));
 
774
                             llstr(rows,llbuff),
 
775
                             llstr(file->state->records,llbuff2));
798
776
    }
799
777
  }
800
778
  else
870
848
    Enable indexes, which might have been disabled by disable_index() before.
871
849
    The modes without _SAVE work only if both data and indexes are empty,
872
850
    since the MyISAM repair would enable them persistently.
873
 
    To be sure in these cases, call Cursor::delete_all_rows() before.
 
851
    To be sure in these cases, call handler::delete_all_rows() before.
874
852
 
875
853
  IMPLEMENTATION
876
854
    HA_KEY_SWITCH_NONUNIQ       is not implemented.
918
896
    if ((error= (repair(session,param,0) != HA_ADMIN_OK)) && param.retry_repair)
919
897
    {
920
898
      errmsg_printf(ERRMSG_LVL_WARN, "Warning: Enabling keys got errno %d on %s.%s, retrying",
921
 
                        errno, param.db_name, param.table_name);
 
899
                        my_errno, param.db_name, param.table_name);
922
900
      /* Repairing by sort failed. Now try standard repair method. */
923
901
      param.testflag&= ~(T_REP_BY_SORT | T_QUICK);
924
902
      error= (repair(session,param,0) != HA_ADMIN_OK);
1034
1012
 
1035
1013
int ha_myisam::update_row(const unsigned char *old_data, unsigned char *new_data)
1036
1014
{
1037
 
  ha_statistic_increment(&system_status_var::ha_update_count);
 
1015
  ha_statistic_increment(&SSV::ha_update_count);
1038
1016
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
1039
1017
    table->timestamp_field->set_time();
1040
1018
  return mi_update(file,old_data,new_data);
1042
1020
 
1043
1021
int ha_myisam::delete_row(const unsigned char *buf)
1044
1022
{
1045
 
  ha_statistic_increment(&system_status_var::ha_delete_count);
 
1023
  ha_statistic_increment(&SSV::ha_delete_count);
1046
1024
  return mi_delete(file,buf);
1047
1025
}
1048
1026
 
1062
1040
}
1063
1041
 
1064
1042
 
 
1043
uint32_t ha_myisam::index_flags(uint32_t inx, uint32_t, bool) const
 
1044
{
 
1045
  return ((table_share->key_info[inx].algorithm == HA_KEY_ALG_FULLTEXT) ?
 
1046
          0 : HA_READ_NEXT | HA_READ_PREV | HA_READ_RANGE |
 
1047
          HA_READ_ORDER | HA_KEYREAD_ONLY |
 
1048
          (keys_with_parts.test(inx)?0:HA_DO_INDEX_COND_PUSHDOWN));
 
1049
}
 
1050
 
 
1051
 
1065
1052
int ha_myisam::index_read_map(unsigned char *buf, const unsigned char *key,
1066
1053
                              key_part_map keypart_map,
1067
1054
                              enum ha_rkey_function find_flag)
1068
1055
{
1069
1056
  assert(inited==INDEX);
1070
 
  ha_statistic_increment(&system_status_var::ha_read_key_count);
 
1057
  ha_statistic_increment(&SSV::ha_read_key_count);
1071
1058
  int error=mi_rkey(file, buf, active_index, key, keypart_map, find_flag);
1072
1059
  table->status=error ? STATUS_NOT_FOUND: 0;
1073
1060
  return error;
1077
1064
                                  key_part_map keypart_map,
1078
1065
                                  enum ha_rkey_function find_flag)
1079
1066
{
1080
 
  ha_statistic_increment(&system_status_var::ha_read_key_count);
 
1067
  ha_statistic_increment(&SSV::ha_read_key_count);
1081
1068
  int error=mi_rkey(file, buf, index, key, keypart_map, find_flag);
1082
1069
  table->status=error ? STATUS_NOT_FOUND: 0;
1083
1070
  return error;
1087
1074
                                   key_part_map keypart_map)
1088
1075
{
1089
1076
  assert(inited==INDEX);
1090
 
  ha_statistic_increment(&system_status_var::ha_read_key_count);
 
1077
  ha_statistic_increment(&SSV::ha_read_key_count);
1091
1078
  int error=mi_rkey(file, buf, active_index, key, keypart_map,
1092
1079
                    HA_READ_PREFIX_LAST);
1093
1080
  table->status=error ? STATUS_NOT_FOUND: 0;
1097
1084
int ha_myisam::index_next(unsigned char *buf)
1098
1085
{
1099
1086
  assert(inited==INDEX);
1100
 
  ha_statistic_increment(&system_status_var::ha_read_next_count);
 
1087
  ha_statistic_increment(&SSV::ha_read_next_count);
1101
1088
  int error=mi_rnext(file,buf,active_index);
1102
1089
  table->status=error ? STATUS_NOT_FOUND: 0;
1103
1090
  return error;
1106
1093
int ha_myisam::index_prev(unsigned char *buf)
1107
1094
{
1108
1095
  assert(inited==INDEX);
1109
 
  ha_statistic_increment(&system_status_var::ha_read_prev_count);
 
1096
  ha_statistic_increment(&SSV::ha_read_prev_count);
1110
1097
  int error=mi_rprev(file,buf, active_index);
1111
1098
  table->status=error ? STATUS_NOT_FOUND: 0;
1112
1099
  return error;
1115
1102
int ha_myisam::index_first(unsigned char *buf)
1116
1103
{
1117
1104
  assert(inited==INDEX);
1118
 
  ha_statistic_increment(&system_status_var::ha_read_first_count);
 
1105
  ha_statistic_increment(&SSV::ha_read_first_count);
1119
1106
  int error=mi_rfirst(file, buf, active_index);
1120
1107
  table->status=error ? STATUS_NOT_FOUND: 0;
1121
1108
  return error;
1124
1111
int ha_myisam::index_last(unsigned char *buf)
1125
1112
{
1126
1113
  assert(inited==INDEX);
1127
 
  ha_statistic_increment(&system_status_var::ha_read_last_count);
 
1114
  ha_statistic_increment(&SSV::ha_read_last_count);
1128
1115
  int error=mi_rlast(file, buf, active_index);
1129
1116
  table->status=error ? STATUS_NOT_FOUND: 0;
1130
1117
  return error;
1136
1123
{
1137
1124
  int error;
1138
1125
  assert(inited==INDEX);
1139
 
  ha_statistic_increment(&system_status_var::ha_read_next_count);
 
1126
  ha_statistic_increment(&SSV::ha_read_next_count);
1140
1127
  do
1141
1128
  {
1142
1129
    error= mi_rnext_same(file,buf);
1154
1141
  //if (!eq_range_arg)
1155
1142
  //  in_range_read= true;
1156
1143
 
1157
 
  res= Cursor::read_range_first(start_key, end_key, eq_range_arg, sorted);
 
1144
  res= handler::read_range_first(start_key, end_key, eq_range_arg, sorted);
1158
1145
 
1159
1146
  //if (res)
1160
1147
  //  in_range_read= false;
1164
1151
 
1165
1152
int ha_myisam::read_range_next()
1166
1153
{
1167
 
  int res= Cursor::read_range_next();
 
1154
  int res= handler::read_range_next();
1168
1155
  //if (res)
1169
1156
  //  in_range_read= false;
1170
1157
  return res;
1180
1167
 
1181
1168
int ha_myisam::rnd_next(unsigned char *buf)
1182
1169
{
1183
 
  ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
 
1170
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
1184
1171
  int error=mi_scan(file, buf);
1185
1172
  table->status=error ? STATUS_NOT_FOUND: 0;
1186
1173
  return error;
1193
1180
 
1194
1181
int ha_myisam::rnd_pos(unsigned char *buf, unsigned char *pos)
1195
1182
{
1196
 
  ha_statistic_increment(&system_status_var::ha_read_rnd_count);
1197
 
  int error=mi_rrnd(file, buf, internal::my_get_ptr(pos,ref_length));
 
1183
  ha_statistic_increment(&SSV::ha_read_rnd_count);
 
1184
  int error=mi_rrnd(file, buf, my_get_ptr(pos,ref_length));
1198
1185
  table->status=error ? STATUS_NOT_FOUND: 0;
1199
1186
  return error;
1200
1187
}
1202
1189
 
1203
1190
void ha_myisam::position(const unsigned char *)
1204
1191
{
1205
 
  internal::my_off_t row_position= mi_position(file);
1206
 
  internal::my_store_ptr(ref, ref_length, row_position);
 
1192
  my_off_t row_position= mi_position(file);
 
1193
  my_store_ptr(ref, ref_length, row_position);
1207
1194
}
1208
1195
 
1209
1196
int ha_myisam::info(uint32_t flag)
1230
1217
    stats.create_time= misam_info.create_time;
1231
1218
    ref_length= misam_info.reflength;
1232
1219
    share->db_options_in_use= misam_info.options;
1233
 
    stats.block_size= myisam_key_cache_block_size;        /* record block size */
 
1220
    stats.block_size= block_size;        /* record block size */
1234
1221
 
1235
1222
    /* Update share */
1236
 
    if (share->tmp_table == message::Table::STANDARD)
 
1223
    if (share->tmp_table == NO_TMP_TABLE)
1237
1224
      pthread_mutex_lock(&share->mutex);
1238
1225
    set_prefix(share->keys_in_use, share->keys);
1239
1226
    /*
1287
1274
      memcpy(table->key_info[0].rec_per_key,
1288
1275
             misam_info.rec_per_key,
1289
1276
             sizeof(table->key_info[0].rec_per_key)*share->key_parts);
1290
 
    if (share->tmp_table == message::Table::STANDARD)
 
1277
    if (share->tmp_table == NO_TMP_TABLE)
1291
1278
      pthread_mutex_unlock(&share->mutex);
1292
1279
 
1293
1280
   /*
1295
1282
     if table is symlinked (Ie;  Real name is not same as generated name)
1296
1283
   */
1297
1284
    data_file_name= index_file_name= 0;
1298
 
    internal::fn_format(name_buff, file->filename, "", MI_NAME_DEXT,
 
1285
    fn_format(name_buff, file->filename, "", MI_NAME_DEXT,
1299
1286
              MY_APPEND_EXT | MY_UNPACK_FILENAME);
1300
1287
    if (strcmp(name_buff, misam_info.data_file_name))
1301
1288
      data_file_name=misam_info.data_file_name;
1302
 
    internal::fn_format(name_buff, file->filename, "", MI_NAME_IEXT,
 
1289
    fn_format(name_buff, file->filename, "", MI_NAME_IEXT,
1303
1290
              MY_APPEND_EXT | MY_UNPACK_FILENAME);
1304
1291
    if (strcmp(name_buff, misam_info.index_file_name))
1305
1292
      index_file_name=misam_info.index_file_name;
1307
1294
  if (flag & HA_STATUS_ERRKEY)
1308
1295
  {
1309
1296
    errkey  = misam_info.errkey;
1310
 
    internal::my_store_ptr(dup_ref, ref_length, misam_info.dupp_key_pos);
 
1297
    my_store_ptr(dup_ref, ref_length, misam_info.dupp_key_pos);
1311
1298
  }
1312
1299
  if (flag & HA_STATUS_TIME)
1313
1300
    stats.update_time = misam_info.update_time;
1340
1327
  return mi_delete_all_rows(file);
1341
1328
}
1342
1329
 
1343
 
int MyisamEngine::doDropTable(Session &session,
1344
 
                              drizzled::TableIdentifier &identifier)
 
1330
int MyisamEngine::deleteTableImplementation(Session*, const string table_name)
1345
1331
{
1346
 
  session.removeTableMessage(identifier);
1347
 
 
1348
 
  return mi_delete_table(identifier.getPath().c_str());
 
1332
  return mi_delete_table(table_name.c_str());
1349
1333
}
1350
1334
 
1351
1335
 
1357
1341
                                       F_UNLCK : F_EXTRA_LCK));
1358
1342
}
1359
1343
 
1360
 
int MyisamEngine::doCreateTable(Session &session,
1361
 
                                Table& table_arg,
1362
 
                                drizzled::TableIdentifier &identifier,
1363
 
                                message::Table& create_proto)
 
1344
THR_LOCK_DATA **ha_myisam::store_lock(Session *,
 
1345
                                      THR_LOCK_DATA **to,
 
1346
                                      enum thr_lock_type lock_type)
 
1347
{
 
1348
  if (lock_type != TL_IGNORE && file->lock.type == TL_UNLOCK)
 
1349
    file->lock.type=lock_type;
 
1350
  *to++= &file->lock;
 
1351
 
 
1352
  return to;
 
1353
}
 
1354
 
 
1355
int MyisamEngine::createTableImplementation(Session *, const char *table_name,
 
1356
                                            Table *table_arg,
 
1357
                                            HA_CREATE_INFO *ha_create_info,
 
1358
                                            drizzled::message::Table* create_proto)
1364
1359
{
1365
1360
  int error;
1366
1361
  uint32_t create_flags= 0, create_records;
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->s;
1372
1367
  uint32_t options= share->db_options_in_use;
1373
 
  if ((error= table2myisam(&table_arg, &keydef, &recinfo, &create_records)))
1374
 
    return(error);
 
1368
  if ((error= table2myisam(table_arg, &keydef, &recinfo, &create_records)))
 
1369
    return(error); /* purecov: inspected */
1375
1370
  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();
 
1371
  create_info.max_rows= create_proto->options().max_rows();
 
1372
  create_info.reloc_rows= create_proto->options().min_rows();
1378
1373
  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 :
 
1374
  create_info.auto_increment= (ha_create_info->auto_increment_value ?
 
1375
                               ha_create_info->auto_increment_value -1 :
1381
1376
                               (uint64_t) 0);
1382
 
  create_info.data_file_length= (create_proto.options().max_rows() *
1383
 
                                 create_proto.options().avg_row_length());
 
1377
  create_info.data_file_length= (create_proto->options().max_rows() *
 
1378
                                 create_proto->options().avg_row_length());
1384
1379
  create_info.data_file_name= NULL;
1385
1380
  create_info.index_file_name=  NULL;
1386
1381
  create_info.language= share->table_charset->number;
1387
1382
 
1388
 
  if (create_proto.type() == message::Table::TEMPORARY)
 
1383
  if (ha_create_info->options & HA_LEX_CREATE_TMP_TABLE)
1389
1384
    create_flags|= HA_CREATE_TMP_TABLE;
 
1385
  if (ha_create_info->options & HA_CREATE_KEEP_FILES)
 
1386
    create_flags|= HA_CREATE_KEEP_FILES;
1390
1387
  if (options & HA_OPTION_PACK_RECORD)
1391
1388
    create_flags|= HA_PACK_RECORD;
1392
1389
 
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),
 
1390
  /* TODO: Check that the following fn_format is really needed */
 
1391
  error= mi_create(fn_format(buff, table_name, "", "",
 
1392
                             MY_UNPACK_FILENAME|MY_APPEND_EXT),
1396
1393
                   share->keys, keydef,
1397
1394
                   create_records, recinfo,
1398
1395
                   0, (MI_UNIQUEDEF*) 0,
1399
1396
                   &create_info, create_flags);
1400
1397
  free((unsigned char*) recinfo);
1401
 
 
1402
 
  session.storeTableMessage(identifier, create_proto);
1403
 
 
1404
 
  return error;
 
1398
  return(error);
1405
1399
}
1406
1400
 
1407
1401
 
1408
 
int MyisamEngine::doRenameTable(Session &session, TableIdentifier &from, TableIdentifier &to)
 
1402
int MyisamEngine::renameTableImplementation(Session*,
 
1403
                                            const char *from, const char *to)
1409
1404
{
1410
 
  session.renameTableMessage(from, to);
1411
 
 
1412
 
  return mi_rename(from.getPath().c_str(), to.getPath().c_str());
 
1405
  return mi_rename(from,to);
1413
1406
}
1414
1407
 
1415
1408
 
1501
1494
 
1502
1495
static MyisamEngine *engine= NULL;
1503
1496
 
1504
 
static int myisam_init(plugin::Context &context)
 
1497
static int myisam_init(drizzled::plugin::Registry &registry)
1505
1498
{
 
1499
  int error;
1506
1500
  engine= new MyisamEngine(engine_name);
1507
 
  context.add(engine);
 
1501
  registry.add(engine);
 
1502
 
 
1503
  pthread_mutex_init(&THR_LOCK_myisam,MY_MUTEX_INIT_FAST);
1508
1504
 
1509
1505
  /* 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);
 
1506
  error= init_key_cache(dflt_key_cache,
 
1507
                        (uint32_t) dflt_key_cache->param_block_size,
 
1508
                        (uint32_t) dflt_key_cache->param_buff_size,
 
1509
                        dflt_key_cache->param_division_limit, 
 
1510
                        dflt_key_cache->param_age_threshold);
1515
1511
 
1516
1512
  if (error == 0)
1517
1513
    exit(1); /* Memory Allocation Failure */
1519
1515
  return 0;
1520
1516
}
1521
1517
 
1522
 
 
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);
 
1518
static int myisam_deinit(drizzled::plugin::Registry &registry)
 
1519
{
 
1520
  registry.remove(engine);
 
1521
  delete engine;
 
1522
 
 
1523
  pthread_mutex_destroy(&THR_LOCK_myisam);
 
1524
  end_key_cache(dflt_key_cache, 1);             // Can never fail
 
1525
 
 
1526
  return mi_panic(HA_PANIC_CLOSE);
 
1527
}
 
1528
 
 
1529
static DRIZZLE_SYSVAR_UINT(block_size, block_size,
 
1530
                           PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
1531
                           N_("Block size to be used for MyISAM index pages."),
 
1532
                           NULL, NULL, MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH, 
 
1533
                           MI_MAX_KEY_BLOCK_LENGTH, 0);
1669
1534
 
1670
1535
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);
 
1536
                           PLUGIN_VAR_RQCMDARG,
 
1537
                           N_("Number of threads to use when repairing MyISAM tables. The value of "
 
1538
                              "1 disables parallel repair."),
 
1539
                           NULL, NULL, 1, 1, UINT32_MAX, 0);
1675
1540
 
1676
1541
static DRIZZLE_SYSVAR_ULONGLONG(max_sort_file_size, max_sort_file_size,
1677
1542
                                PLUGIN_VAR_RQCMDARG,
1685
1550
 
1686
1551
extern uint32_t data_pointer_size;
1687
1552
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);
 
1553
                           PLUGIN_VAR_RQCMDARG,
 
1554
                           N_("Default pointer size to be used for MyISAM tables."),
 
1555
                           NULL, NULL, 6, 2, 7, 0);
1691
1556
 
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),
 
1557
static struct st_mysql_sys_var* system_variables[]= {
 
1558
  DRIZZLE_SYSVAR(block_size),
1697
1559
  DRIZZLE_SYSVAR(repair_threads),
1698
1560
  DRIZZLE_SYSVAR(max_sort_file_size),
1699
1561
  DRIZZLE_SYSVAR(sort_buffer_size),
1702
1564
};
1703
1565
 
1704
1566
 
1705
 
DRIZZLE_DECLARE_PLUGIN
 
1567
drizzle_declare_plugin(myisam)
1706
1568
{
1707
 
  DRIZZLE_VERSION_ID,
1708
1569
  "MyISAM",
1709
1570
  "1.0",
1710
1571
  "MySQL AB",
1711
1572
  "Default engine as of MySQL 3.23 with great performance",
1712
1573
  PLUGIN_LICENSE_GPL,
1713
1574
  myisam_init, /* Plugin Init */
1714
 
  sys_variables,           /* system variables */
 
1575
  myisam_deinit, /* Plugin Deinit */
 
1576
  NULL,                       /* status variables                */
 
1577
  system_variables,           /* system variables */
1715
1578
  NULL                        /* config options                  */
1716
1579
}
1717
 
DRIZZLE_DECLARE_PLUGIN_END;
 
1580
drizzle_declare_plugin_end;