~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2005 MySQL AB
2
3
  This program is free software; you can redistribute it and/or modify
4
  it under the terms of the GNU General Public License as published by
5
  the Free Software Foundation; version 2 of the License.
6
7
  This program is distributed in the hope that it will be useful,
8
  but WITHOUT ANY WARRANTY; without even the implied warranty of
9
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
  GNU General Public License for more details.
11
12
  You should have received a copy of the GNU General Public License
13
  along with this program; if not, write to the Free Software
14
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
16
17
#ifdef USE_PRAGMA_IMPLEMENTATION
18
#pragma implementation				// gcc: Class implementation
19
#endif
20
21
#include "mysql_priv.h"
22
#include "ha_blackhole.h"
23
24
/* Static declarations for handlerton */
25
26
static handler *blackhole_create_handler(handlerton *hton,
27
                                         TABLE_SHARE *table,
28
                                         MEM_ROOT *mem_root)
29
{
30
  return new (mem_root) ha_blackhole(hton, table);
31
}
32
33
34
/* Static declarations for shared structures */
35
36
static pthread_mutex_t blackhole_mutex;
37
static HASH blackhole_open_tables;
38
39
static st_blackhole_share *get_share(const char *table_name);
40
static void free_share(st_blackhole_share *share);
41
42
/*****************************************************************************
43
** BLACKHOLE tables
44
*****************************************************************************/
45
46
ha_blackhole::ha_blackhole(handlerton *hton,
47
                           TABLE_SHARE *table_arg)
48
  :handler(hton, table_arg)
49
{}
50
51
52
static const char *ha_blackhole_exts[] = {
53
  NullS
54
};
55
56
const char **ha_blackhole::bas_ext() const
57
{
58
  return ha_blackhole_exts;
59
}
60
61
int ha_blackhole::open(const char *name, int mode, uint test_if_locked)
62
{
63
  DBUG_ENTER("ha_blackhole::open");
64
65
  if (!(share= get_share(name)))
66
    DBUG_RETURN(HA_ERR_OUT_OF_MEM);
67
68
  thr_lock_data_init(&share->lock, &lock, NULL);
69
  DBUG_RETURN(0);
70
}
71
72
int ha_blackhole::close(void)
73
{
74
  DBUG_ENTER("ha_blackhole::close");
75
  free_share(share);
76
  DBUG_RETURN(0);
77
}
78
79
int ha_blackhole::create(const char *name, TABLE *table_arg,
80
                         HA_CREATE_INFO *create_info)
81
{
82
  DBUG_ENTER("ha_blackhole::create");
83
  DBUG_RETURN(0);
84
}
85
86
const char *ha_blackhole::index_type(uint key_number)
87
{
88
  DBUG_ENTER("ha_blackhole::index_type");
89
  DBUG_RETURN((table_share->key_info[key_number].flags & HA_FULLTEXT) ? 
90
              "FULLTEXT" :
91
              (table_share->key_info[key_number].flags & HA_SPATIAL) ?
92
              "SPATIAL" :
93
              (table_share->key_info[key_number].algorithm ==
94
               HA_KEY_ALG_RTREE) ? "RTREE" : "BTREE");
95
}
96
97
int ha_blackhole::write_row(uchar * buf)
98
{
99
  DBUG_ENTER("ha_blackhole::write_row");
100
  DBUG_RETURN(table->next_number_field ? update_auto_increment() : 0);
101
}
102
103
int ha_blackhole::rnd_init(bool scan)
104
{
105
  DBUG_ENTER("ha_blackhole::rnd_init");
106
  DBUG_RETURN(0);
107
}
108
109
110
int ha_blackhole::rnd_next(uchar *buf)
111
{
112
  DBUG_ENTER("ha_blackhole::rnd_next");
113
  DBUG_RETURN(HA_ERR_END_OF_FILE);
114
}
115
116
117
int ha_blackhole::rnd_pos(uchar * buf, uchar *pos)
118
{
119
  DBUG_ENTER("ha_blackhole::rnd_pos");
120
  DBUG_ASSERT(0);
121
  DBUG_RETURN(0);
122
}
123
124
125
void ha_blackhole::position(const uchar *record)
126
{
127
  DBUG_ENTER("ha_blackhole::position");
128
  DBUG_ASSERT(0);
129
  DBUG_VOID_RETURN;
130
}
131
132
133
int ha_blackhole::info(uint flag)
134
{
135
  DBUG_ENTER("ha_blackhole::info");
136
137
  bzero((char*) &stats, sizeof(stats));
138
  if (flag & HA_STATUS_AUTO)
139
    stats.auto_increment_value= 1;
140
  DBUG_RETURN(0);
141
}
142
143
int ha_blackhole::external_lock(THD *thd, int lock_type)
144
{
145
  DBUG_ENTER("ha_blackhole::external_lock");
146
  DBUG_RETURN(0);
147
}
148
149
150
THR_LOCK_DATA **ha_blackhole::store_lock(THD *thd,
151
                                         THR_LOCK_DATA **to,
152
                                         enum thr_lock_type lock_type)
153
{
154
  DBUG_ENTER("ha_blackhole::store_lock");
155
  if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK)
156
  {
157
    /*
158
      Here is where we get into the guts of a row level lock.
159
      If TL_UNLOCK is set
160
      If we are not doing a LOCK TABLE or DISCARD/IMPORT
161
      TABLESPACE, then allow multiple writers
162
    */
163
164
    if ((lock_type >= TL_WRITE_CONCURRENT_INSERT &&
165
         lock_type <= TL_WRITE) && !thd_in_lock_tables(thd)
166
        && !thd_tablespace_op(thd))
167
      lock_type = TL_WRITE_ALLOW_WRITE;
168
169
    /*
170
      In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
171
      MySQL would use the lock TL_READ_NO_INSERT on t2, and that
172
      would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
173
      to t2. Convert the lock to a normal read lock to allow
174
      concurrent inserts to t2.
175
    */
176
177
    if (lock_type == TL_READ_NO_INSERT && !thd_in_lock_tables(thd))
178
      lock_type = TL_READ;
179
180
    lock.type= lock_type;
181
  }
182
  *to++= &lock;
183
  DBUG_RETURN(to);
184
}
185
186
187
int ha_blackhole::index_read_map(uchar * buf, const uchar * key,
188
                                 key_part_map keypart_map,
189
                             enum ha_rkey_function find_flag)
190
{
191
  DBUG_ENTER("ha_blackhole::index_read");
192
  DBUG_RETURN(HA_ERR_END_OF_FILE);
193
}
194
195
196
int ha_blackhole::index_read_idx_map(uchar * buf, uint idx, const uchar * key,
197
                                 key_part_map keypart_map,
198
                                 enum ha_rkey_function find_flag)
199
{
200
  DBUG_ENTER("ha_blackhole::index_read_idx");
201
  DBUG_RETURN(HA_ERR_END_OF_FILE);
202
}
203
204
205
int ha_blackhole::index_read_last_map(uchar * buf, const uchar * key,
206
                                      key_part_map keypart_map)
207
{
208
  DBUG_ENTER("ha_blackhole::index_read_last");
209
  DBUG_RETURN(HA_ERR_END_OF_FILE);
210
}
211
212
213
int ha_blackhole::index_next(uchar * buf)
214
{
215
  DBUG_ENTER("ha_blackhole::index_next");
216
  DBUG_RETURN(HA_ERR_END_OF_FILE);
217
}
218
219
220
int ha_blackhole::index_prev(uchar * buf)
221
{
222
  DBUG_ENTER("ha_blackhole::index_prev");
223
  DBUG_RETURN(HA_ERR_END_OF_FILE);
224
}
225
226
227
int ha_blackhole::index_first(uchar * buf)
228
{
229
  DBUG_ENTER("ha_blackhole::index_first");
230
  DBUG_RETURN(HA_ERR_END_OF_FILE);
231
}
232
233
234
int ha_blackhole::index_last(uchar * buf)
235
{
236
  DBUG_ENTER("ha_blackhole::index_last");
237
  DBUG_RETURN(HA_ERR_END_OF_FILE);
238
}
239
240
241
static st_blackhole_share *get_share(const char *table_name)
242
{
243
  st_blackhole_share *share;
244
  uint length;
245
246
  length= (uint) strlen(table_name);
247
  pthread_mutex_lock(&blackhole_mutex);
248
    
249
  if (!(share= (st_blackhole_share*) hash_search(&blackhole_open_tables,
250
                                                 (uchar*) table_name, length)))
251
  {
252
    if (!(share= (st_blackhole_share*) my_malloc(sizeof(st_blackhole_share) +
253
                                                 length,
254
                                                 MYF(MY_WME | MY_ZEROFILL))))
255
      goto error;
256
257
    share->table_name_length= length;
258
    strmov(share->table_name, table_name);
259
    
260
    if (my_hash_insert(&blackhole_open_tables, (uchar*) share))
261
    {
262
      my_free((uchar*) share, MYF(0));
263
      share= NULL;
264
      goto error;
265
    }
266
    
267
    thr_lock_init(&share->lock);
268
  }
269
  share->use_count++;
270
  
271
error:
272
  pthread_mutex_unlock(&blackhole_mutex);
273
  return share;
274
}
275
276
static void free_share(st_blackhole_share *share)
277
{
278
  pthread_mutex_lock(&blackhole_mutex);
279
  if (!--share->use_count)
280
    hash_delete(&blackhole_open_tables, (uchar*) share);
281
  pthread_mutex_unlock(&blackhole_mutex);
282
}
283
284
static void blackhole_free_key(st_blackhole_share *share)
285
{
286
  thr_lock_delete(&share->lock);
287
  my_free((uchar*) share, MYF(0));
288
}
289
290
static uchar* blackhole_get_key(st_blackhole_share *share, size_t *length,
291
                                my_bool not_used __attribute__((unused)))
292
{
293
  *length= share->table_name_length;
294
  return (uchar*) share->table_name;
295
}
296
297
static int blackhole_init(void *p)
298
{
299
  handlerton *blackhole_hton;
300
  blackhole_hton= (handlerton *)p;
301
  blackhole_hton->state= SHOW_OPTION_YES;
302
  blackhole_hton->db_type= DB_TYPE_BLACKHOLE_DB;
303
  blackhole_hton->create= blackhole_create_handler;
304
  blackhole_hton->flags= HTON_CAN_RECREATE;
305
  
306
  VOID(pthread_mutex_init(&blackhole_mutex, MY_MUTEX_INIT_FAST));
307
  (void) hash_init(&blackhole_open_tables, system_charset_info,32,0,0,
308
                   (hash_get_key) blackhole_get_key,
309
                   (hash_free_key) blackhole_free_key, 0);
310
311
  return 0;
312
}
313
314
static int blackhole_fini(void *p)
315
{
316
  hash_free(&blackhole_open_tables);
317
  pthread_mutex_destroy(&blackhole_mutex);
318
319
  return 0;
320
}
321
322
struct st_mysql_storage_engine blackhole_storage_engine=
323
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
324
325
mysql_declare_plugin(blackhole)
326
{
327
  MYSQL_STORAGE_ENGINE_PLUGIN,
328
  &blackhole_storage_engine,
329
  "BLACKHOLE",
330
  "MySQL AB",
331
  "/dev/null storage engine (anything you write to it disappears)",
332
  PLUGIN_LICENSE_GPL,
333
  blackhole_init, /* Plugin Init */
334
  blackhole_fini, /* Plugin Deinit */
335
  0x0100 /* 1.0 */,
336
  NULL,                       /* status variables                */
337
  NULL,                       /* system variables                */
338
  NULL                        /* config options                  */
339
}
340
mysql_declare_plugin_end;