~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/handlerton.cc

  • Committer: Brian Aker
  • Date: 2008-11-07 23:16:58 UTC
  • mfrom: (575.1.14 devel)
  • Revision ID: brian@tangent.org-20081107231658-fboahr524d1or2ya
Merge from Monty.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 
3
 *
 
4
 *  Copyright (C) 2008 Sun Microsystems
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; version 2 of the License.
 
9
 *
 
10
 *  This program is distributed in the hope that it will be useful,
 
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *  GNU General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU General Public License
 
16
 *  along with this program; if not, write to the Free Software
 
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
18
 */
 
19
 
 
20
#include <drizzled/server_includes.h>
 
21
#include <drizzled/definitions.h>
 
22
#include <drizzled/base.h>
 
23
#include <drizzled/handler.h>
 
24
#include <drizzled/handlerton.h>
 
25
#include <drizzled/sql_class.h>
 
26
#include <drizzled/error.h>
 
27
#include <drizzled/gettext.h>
 
28
 
 
29
#include CSTDINT_H
 
30
 
 
31
/*
 
32
  While we have legacy_db_type, we have this array to
 
33
  check for dups and to find handlerton from legacy_db_type.
 
34
  Remove when legacy_db_type is finally gone
 
35
*/
 
36
st_plugin_int *hton2plugin[MAX_HA];
 
37
 
 
38
static handlerton *installed_htons[128];
 
39
 
 
40
static const LEX_STRING sys_table_aliases[]=
 
41
{
 
42
  { C_STRING_WITH_LEN("INNOBASE") },  { C_STRING_WITH_LEN("INNODB") },
 
43
  { C_STRING_WITH_LEN("HEAP") },      { C_STRING_WITH_LEN("MEMORY") },
 
44
  {NULL, 0}
 
45
};
 
46
 
 
47
 
 
48
handlerton *ha_resolve_by_legacy_type(Session *session,
 
49
                                      enum legacy_db_type db_type)
 
50
{
 
51
  plugin_ref plugin;
 
52
  switch (db_type) {
 
53
  case DB_TYPE_DEFAULT:
 
54
    return ha_default_handlerton(session);
 
55
  default:
 
56
    if (db_type > DB_TYPE_UNKNOWN && db_type < DB_TYPE_DEFAULT &&
 
57
        (plugin= ha_lock_engine(session, installed_htons[db_type])))
 
58
      return plugin_data(plugin, handlerton*);
 
59
    /* fall through */
 
60
  case DB_TYPE_UNKNOWN:
 
61
    return NULL;
 
62
  }
 
63
}
 
64
 
 
65
 
 
66
static plugin_ref ha_default_plugin(Session *session)
 
67
{
 
68
  if (session->variables.table_plugin)
 
69
    return session->variables.table_plugin;
 
70
  return my_plugin_lock(session, &global_system_variables.table_plugin);
 
71
}
 
72
 
 
73
 
 
74
/**
 
75
  Return the default storage engine handlerton for thread
 
76
 
 
77
  @param ha_default_handlerton(session)
 
78
  @param session         current thread
 
79
 
 
80
  @return
 
81
    pointer to handlerton
 
82
*/
 
83
handlerton *ha_default_handlerton(Session *session)
 
84
{
 
85
  plugin_ref plugin= ha_default_plugin(session);
 
86
  assert(plugin);
 
87
  handlerton *hton= plugin_data(plugin, handlerton*);
 
88
  assert(hton);
 
89
  return hton;
 
90
}
 
91
 
 
92
 
 
93
/**
 
94
  Return the storage engine handlerton for the supplied name
 
95
  
 
96
  @param session         current thread
 
97
  @param name        name of storage engine
 
98
  
 
99
  @return
 
100
    pointer to storage engine plugin handle
 
101
*/
 
102
plugin_ref ha_resolve_by_name(Session *session, const LEX_STRING *name)
 
103
{
 
104
  const LEX_STRING *table_alias;
 
105
  plugin_ref plugin;
 
106
 
 
107
redo:
 
108
  /* my_strnncoll is a macro and gcc doesn't do early expansion of macro */
 
109
  if (session && !my_charset_utf8_general_ci.coll->strnncoll(&my_charset_utf8_general_ci,
 
110
                           (const unsigned char *)name->str, name->length,
 
111
                           (const unsigned char *)STRING_WITH_LEN("DEFAULT"), 0))
 
112
    return ha_default_plugin(session);
 
113
 
 
114
  if ((plugin= my_plugin_lock_by_name(session, name, DRIZZLE_STORAGE_ENGINE_PLUGIN)))
 
115
  {
 
116
    handlerton *hton= plugin_data(plugin, handlerton *);
 
117
    if (!(hton->flags & HTON_NOT_USER_SELECTABLE))
 
118
      return plugin;
 
119
      
 
120
    /*
 
121
      unlocking plugin immediately after locking is relatively low cost.
 
122
    */
 
123
    plugin_unlock(session, plugin);
 
124
  }
 
125
 
 
126
  /*
 
127
    We check for the historical aliases.
 
128
  */
 
129
  for (table_alias= sys_table_aliases; table_alias->str; table_alias+= 2)
 
130
  {
 
131
    if (!my_strnncoll(&my_charset_utf8_general_ci,
 
132
                      (const unsigned char *)name->str, name->length,
 
133
                      (const unsigned char *)table_alias->str,
 
134
                      table_alias->length))
 
135
    {
 
136
      name= table_alias + 1;
 
137
      goto redo;
 
138
    }
 
139
  }
 
140
 
 
141
  return NULL;
 
142
}
 
143
 
 
144
 
 
145
plugin_ref ha_lock_engine(Session *session, handlerton *hton)
 
146
{
 
147
  if (hton)
 
148
  {
 
149
    st_plugin_int **plugin= hton2plugin + hton->slot;
 
150
 
 
151
    return my_plugin_lock(session, &plugin);
 
152
  }
 
153
  return NULL;
 
154
}
 
155
 
 
156
 
 
157
/**
 
158
  Use other database handler if databasehandler is not compiled in.
 
159
*/
 
160
handlerton *ha_checktype(Session *session, enum legacy_db_type database_type,
 
161
                          bool no_substitute, bool report_error)
 
162
{
 
163
  handlerton *hton= ha_resolve_by_legacy_type(session, database_type);
 
164
  if (ha_storage_engine_is_enabled(hton))
 
165
    return hton;
 
166
 
 
167
  if (no_substitute)
 
168
  {
 
169
    if (report_error)
 
170
    {
 
171
      const char *engine_name= ha_resolve_storage_engine_name(hton);
 
172
      my_error(ER_FEATURE_DISABLED,MYF(0),engine_name,engine_name);
 
173
    }
 
174
    return NULL;
 
175
  }
 
176
 
 
177
  return ha_default_handlerton(session);
 
178
} /* ha_checktype */
 
179
 
 
180
 
 
181
handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc,
 
182
                         handlerton *db_type)
 
183
{
 
184
  handler *file;
 
185
 
 
186
  if (db_type && db_type->state == SHOW_OPTION_YES && db_type->create)
 
187
  {
 
188
    if ((file= db_type->create(db_type, share, alloc)))
 
189
      file->init();
 
190
    return(file);
 
191
  }
 
192
  /*
 
193
    Try the default table type
 
194
    Here the call to current_session() is ok as we call this function a lot of
 
195
    times but we enter this branch very seldom.
 
196
  */
 
197
  return(get_new_handler(share, alloc, ha_default_handlerton(current_session)));
 
198
}
 
199
 
 
200
 
 
201
int ha_finalize_handlerton(st_plugin_int *plugin)
 
202
{
 
203
  handlerton *hton= (handlerton *)plugin->data;
 
204
 
 
205
  switch (hton->state)
 
206
  {
 
207
  case SHOW_OPTION_NO:
 
208
  case SHOW_OPTION_DISABLED:
 
209
    break;
 
210
  case SHOW_OPTION_YES:
 
211
    if (installed_htons[hton->db_type] == hton)
 
212
      installed_htons[hton->db_type]= NULL;
 
213
    break;
 
214
  };
 
215
 
 
216
  if (hton && plugin->plugin->deinit)
 
217
    (void)plugin->plugin->deinit(hton);
 
218
 
 
219
  free((unsigned char*)hton);
 
220
 
 
221
  return(0);
 
222
}
 
223
 
 
224
 
 
225
int ha_initialize_handlerton(st_plugin_int *plugin)
 
226
{
 
227
  handlerton *hton;
 
228
 
 
229
  hton= (handlerton *)my_malloc(sizeof(handlerton),
 
230
                                MYF(MY_WME | MY_ZEROFILL));
 
231
  /*
 
232
    FIXME: the MY_ZEROFILL flag above doesn't zero all the bytes.
 
233
 
 
234
    This was detected after adding get_backup_engine member to handlerton
 
235
    structure. Apparently get_backup_engine was not NULL even though it was
 
236
    not initialized.
 
237
   */
 
238
  memset(hton, 0, sizeof(hton));
 
239
  /* Historical Requirement */
 
240
  plugin->data= hton; // shortcut for the future
 
241
  if (plugin->plugin->init)
 
242
  {
 
243
    if (plugin->plugin->init(hton))
 
244
    {
 
245
      sql_print_error(_("Plugin '%s' init function returned error."),
 
246
                      plugin->name.str);
 
247
      goto err;
 
248
    }
 
249
  }
 
250
 
 
251
  /*
 
252
    the switch below and hton->state should be removed when
 
253
    command-line options for plugins will be implemented
 
254
  */
 
255
  switch (hton->state) {
 
256
  case SHOW_OPTION_NO:
 
257
    break;
 
258
  case SHOW_OPTION_YES:
 
259
    {
 
260
      uint32_t tmp;
 
261
      /* now check the db_type for conflict */
 
262
      if (hton->db_type <= DB_TYPE_UNKNOWN ||
 
263
          hton->db_type >= DB_TYPE_DEFAULT ||
 
264
          installed_htons[hton->db_type])
 
265
      {
 
266
        int idx= (int) DB_TYPE_FIRST_DYNAMIC;
 
267
 
 
268
        while (idx < (int) DB_TYPE_DEFAULT && installed_htons[idx])
 
269
          idx++;
 
270
 
 
271
        if (idx == (int) DB_TYPE_DEFAULT)
 
272
        {
 
273
          sql_print_warning(_("Too many storage engines!"));
 
274
          return(1);
 
275
        }
 
276
        if (hton->db_type != DB_TYPE_UNKNOWN)
 
277
          sql_print_warning(_("Storage engine '%s' has conflicting typecode. "
 
278
                            "Assigning value %d."), plugin->plugin->name, idx);
 
279
        hton->db_type= (enum legacy_db_type) idx;
 
280
      }
 
281
      installed_htons[hton->db_type]= hton;
 
282
      tmp= hton->savepoint_offset;
 
283
      hton->savepoint_offset= savepoint_alloc_size;
 
284
      savepoint_alloc_size+= tmp;
 
285
      hton->slot= total_ha++;
 
286
      hton2plugin[hton->slot]=plugin;
 
287
      if (hton->prepare)
 
288
        total_ha_2pc++;
 
289
      break;
 
290
    }
 
291
    /* fall through */
 
292
  default:
 
293
    hton->state= SHOW_OPTION_DISABLED;
 
294
    break;
 
295
  }
 
296
 
 
297
  /*
 
298
    This is entirely for legacy. We will create a new "disk based" hton and a
 
299
    "memory" hton which will be configurable longterm. We should be able to
 
300
    remove partition and myisammrg.
 
301
  */
 
302
  if (strcmp(plugin->plugin->name, "MEMORY") == 0)
 
303
    heap_hton= hton;
 
304
 
 
305
  if (strcmp(plugin->plugin->name, "MyISAM") == 0)
 
306
    myisam_hton= hton;
 
307
 
 
308
  return(0);
 
309
err:
 
310
  return(1);
 
311
}
 
312
 
 
313
enum legacy_db_type ha_legacy_type(const handlerton *db_type)
 
314
{
 
315
  return (db_type == NULL) ? DB_TYPE_UNKNOWN : db_type->db_type;
 
316
}
 
317
 
 
318
const char *ha_resolve_storage_engine_name(const handlerton *db_type)
 
319
{
 
320
  return db_type == NULL ? "UNKNOWN" : hton2plugin[db_type->slot]->name.str;
 
321
}
 
322
 
 
323
bool ha_check_storage_engine_flag(const handlerton *db_type, uint32_t flag)
 
324
{
 
325
  return db_type == NULL ? false : test(db_type->flags & flag);
 
326
}
 
327
 
 
328
bool ha_storage_engine_is_enabled(const handlerton *db_type)
 
329
{
 
330
  return (db_type && db_type->create) ?
 
331
         (db_type->state == SHOW_OPTION_YES) : false;
 
332
}
 
333
 
 
334
LEX_STRING *ha_storage_engine_name(const handlerton *hton)
 
335
{
 
336
  return &hton2plugin[hton->slot]->name;
 
337
}