1
/* Copyright (C) 2005 MySQL AB
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.
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.
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 */
17
#ifdef USE_PRAGMA_IMPLEMENTATION
18
#pragma implementation // gcc: Class implementation
21
#include "mysql_priv.h"
22
#include "ha_blackhole.h"
24
/* Static declarations for handlerton */
26
static handler *blackhole_create_handler(handlerton *hton,
30
return new (mem_root) ha_blackhole(hton, table);
34
/* Static declarations for shared structures */
36
static pthread_mutex_t blackhole_mutex;
37
static HASH blackhole_open_tables;
39
static st_blackhole_share *get_share(const char *table_name);
40
static void free_share(st_blackhole_share *share);
42
/*****************************************************************************
44
*****************************************************************************/
46
ha_blackhole::ha_blackhole(handlerton *hton,
47
TABLE_SHARE *table_arg)
48
:handler(hton, table_arg)
52
static const char *ha_blackhole_exts[] = {
56
const char **ha_blackhole::bas_ext() const
58
return ha_blackhole_exts;
61
int ha_blackhole::open(const char *name, int mode, uint test_if_locked)
63
DBUG_ENTER("ha_blackhole::open");
65
if (!(share= get_share(name)))
66
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
68
thr_lock_data_init(&share->lock, &lock, NULL);
72
int ha_blackhole::close(void)
74
DBUG_ENTER("ha_blackhole::close");
79
int ha_blackhole::create(const char *name, TABLE *table_arg,
80
HA_CREATE_INFO *create_info)
82
DBUG_ENTER("ha_blackhole::create");
86
const char *ha_blackhole::index_type(uint key_number)
88
DBUG_ENTER("ha_blackhole::index_type");
89
DBUG_RETURN((table_share->key_info[key_number].flags & HA_FULLTEXT) ?
91
(table_share->key_info[key_number].flags & HA_SPATIAL) ?
93
(table_share->key_info[key_number].algorithm ==
94
HA_KEY_ALG_RTREE) ? "RTREE" : "BTREE");
97
int ha_blackhole::write_row(uchar * buf)
99
DBUG_ENTER("ha_blackhole::write_row");
100
DBUG_RETURN(table->next_number_field ? update_auto_increment() : 0);
103
int ha_blackhole::rnd_init(bool scan)
105
DBUG_ENTER("ha_blackhole::rnd_init");
110
int ha_blackhole::rnd_next(uchar *buf)
112
DBUG_ENTER("ha_blackhole::rnd_next");
113
DBUG_RETURN(HA_ERR_END_OF_FILE);
117
int ha_blackhole::rnd_pos(uchar * buf, uchar *pos)
119
DBUG_ENTER("ha_blackhole::rnd_pos");
125
void ha_blackhole::position(const uchar *record)
127
DBUG_ENTER("ha_blackhole::position");
133
int ha_blackhole::info(uint flag)
135
DBUG_ENTER("ha_blackhole::info");
137
bzero((char*) &stats, sizeof(stats));
138
if (flag & HA_STATUS_AUTO)
139
stats.auto_increment_value= 1;
143
int ha_blackhole::external_lock(THD *thd, int lock_type)
145
DBUG_ENTER("ha_blackhole::external_lock");
150
THR_LOCK_DATA **ha_blackhole::store_lock(THD *thd,
152
enum thr_lock_type lock_type)
154
DBUG_ENTER("ha_blackhole::store_lock");
155
if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK)
158
Here is where we get into the guts of a row level lock.
160
If we are not doing a LOCK TABLE or DISCARD/IMPORT
161
TABLESPACE, then allow multiple writers
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;
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.
177
if (lock_type == TL_READ_NO_INSERT && !thd_in_lock_tables(thd))
180
lock.type= lock_type;
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)
191
DBUG_ENTER("ha_blackhole::index_read");
192
DBUG_RETURN(HA_ERR_END_OF_FILE);
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)
200
DBUG_ENTER("ha_blackhole::index_read_idx");
201
DBUG_RETURN(HA_ERR_END_OF_FILE);
205
int ha_blackhole::index_read_last_map(uchar * buf, const uchar * key,
206
key_part_map keypart_map)
208
DBUG_ENTER("ha_blackhole::index_read_last");
209
DBUG_RETURN(HA_ERR_END_OF_FILE);
213
int ha_blackhole::index_next(uchar * buf)
215
DBUG_ENTER("ha_blackhole::index_next");
216
DBUG_RETURN(HA_ERR_END_OF_FILE);
220
int ha_blackhole::index_prev(uchar * buf)
222
DBUG_ENTER("ha_blackhole::index_prev");
223
DBUG_RETURN(HA_ERR_END_OF_FILE);
227
int ha_blackhole::index_first(uchar * buf)
229
DBUG_ENTER("ha_blackhole::index_first");
230
DBUG_RETURN(HA_ERR_END_OF_FILE);
234
int ha_blackhole::index_last(uchar * buf)
236
DBUG_ENTER("ha_blackhole::index_last");
237
DBUG_RETURN(HA_ERR_END_OF_FILE);
241
static st_blackhole_share *get_share(const char *table_name)
243
st_blackhole_share *share;
246
length= (uint) strlen(table_name);
247
pthread_mutex_lock(&blackhole_mutex);
249
if (!(share= (st_blackhole_share*) hash_search(&blackhole_open_tables,
250
(uchar*) table_name, length)))
252
if (!(share= (st_blackhole_share*) my_malloc(sizeof(st_blackhole_share) +
254
MYF(MY_WME | MY_ZEROFILL))))
257
share->table_name_length= length;
258
strmov(share->table_name, table_name);
260
if (my_hash_insert(&blackhole_open_tables, (uchar*) share))
262
my_free((uchar*) share, MYF(0));
267
thr_lock_init(&share->lock);
272
pthread_mutex_unlock(&blackhole_mutex);
276
static void free_share(st_blackhole_share *share)
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);
284
static void blackhole_free_key(st_blackhole_share *share)
286
thr_lock_delete(&share->lock);
287
my_free((uchar*) share, MYF(0));
290
static uchar* blackhole_get_key(st_blackhole_share *share, size_t *length,
291
my_bool not_used __attribute__((unused)))
293
*length= share->table_name_length;
294
return (uchar*) share->table_name;
297
static int blackhole_init(void *p)
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;
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);
314
static int blackhole_fini(void *p)
316
hash_free(&blackhole_open_tables);
317
pthread_mutex_destroy(&blackhole_mutex);
322
struct st_mysql_storage_engine blackhole_storage_engine=
323
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
325
mysql_declare_plugin(blackhole)
327
MYSQL_STORAGE_ENGINE_PLUGIN,
328
&blackhole_storage_engine,
331
"/dev/null storage engine (anything you write to it disappears)",
333
blackhole_init, /* Plugin Init */
334
blackhole_fini, /* Plugin Deinit */
336
NULL, /* status variables */
337
NULL, /* system variables */
338
NULL /* config options */
340
mysql_declare_plugin_end;