2 Copyright (c) 2005-2008 MySQL AB, 2008, 2009 Sun Microsystems, Inc.
3 Use is subject to license terms.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; version 2 of the License.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 #ifdef USE_PRAGMA_IMPLEMENTATION
21 #pragma implementation // gcc: Class implementation
24 #define MYSQL_SERVER 1
25 #include "mysql_priv.h"
26 #include "ha_blackhole.h"
28 /* Static declarations for handlerton */
30 static handler
*blackhole_create_handler(handlerton
*hton
,
34 return new (mem_root
) ha_blackhole(hton
, table
);
38 /* Static declarations for shared structures */
40 static pthread_mutex_t blackhole_mutex
;
41 static HASH blackhole_open_tables
;
43 static st_blackhole_share
*get_share(const char *table_name
);
44 static void free_share(st_blackhole_share
*share
);
46 /*****************************************************************************
48 *****************************************************************************/
50 ha_blackhole::ha_blackhole(handlerton
*hton
,
51 TABLE_SHARE
*table_arg
)
52 :handler(hton
, table_arg
)
56 static const char *ha_blackhole_exts
[] = {
60 const char **ha_blackhole::bas_ext() const
62 return ha_blackhole_exts
;
65 int ha_blackhole::open(const char *name
, int mode
, uint test_if_locked
)
67 DBUG_ENTER("ha_blackhole::open");
69 if (!(share
= get_share(name
)))
70 DBUG_RETURN(HA_ERR_OUT_OF_MEM
);
72 thr_lock_data_init(&share
->lock
, &lock
, NULL
);
76 int ha_blackhole::close(void)
78 DBUG_ENTER("ha_blackhole::close");
83 int ha_blackhole::create(const char *name
, TABLE
*table_arg
,
84 HA_CREATE_INFO
*create_info
)
86 DBUG_ENTER("ha_blackhole::create");
90 const char *ha_blackhole::index_type(uint key_number
)
92 DBUG_ENTER("ha_blackhole::index_type");
93 DBUG_RETURN((table_share
->key_info
[key_number
].flags
& HA_FULLTEXT
) ?
95 (table_share
->key_info
[key_number
].flags
& HA_SPATIAL
) ?
97 (table_share
->key_info
[key_number
].algorithm
==
98 HA_KEY_ALG_RTREE
) ? "RTREE" : "BTREE");
101 int ha_blackhole::write_row(uchar
* buf
)
103 DBUG_ENTER("ha_blackhole::write_row");
104 DBUG_RETURN(table
->next_number_field
? update_auto_increment() : 0);
107 int ha_blackhole::update_row(const uchar
*old_data
, uchar
*new_data
)
109 DBUG_ENTER("ha_blackhole::update_row");
111 if (thd
->system_thread
== SYSTEM_THREAD_SLAVE_SQL
&& thd
->query() == NULL
)
113 DBUG_RETURN(HA_ERR_WRONG_COMMAND
);
116 int ha_blackhole::delete_row(const uchar
*buf
)
118 DBUG_ENTER("ha_blackhole::delete_row");
120 if (thd
->system_thread
== SYSTEM_THREAD_SLAVE_SQL
&& thd
->query() == NULL
)
122 DBUG_RETURN(HA_ERR_WRONG_COMMAND
);
125 int ha_blackhole::rnd_init(bool scan
)
127 DBUG_ENTER("ha_blackhole::rnd_init");
132 int ha_blackhole::rnd_next(uchar
*buf
)
134 DBUG_ENTER("ha_blackhole::rnd_next");
136 if (thd
->system_thread
== SYSTEM_THREAD_SLAVE_SQL
&& thd
->query() == NULL
)
138 DBUG_RETURN(HA_ERR_END_OF_FILE
);
142 int ha_blackhole::rnd_pos(uchar
* buf
, uchar
*pos
)
144 DBUG_ENTER("ha_blackhole::rnd_pos");
150 void ha_blackhole::position(const uchar
*record
)
152 DBUG_ENTER("ha_blackhole::position");
158 int ha_blackhole::info(uint flag
)
160 DBUG_ENTER("ha_blackhole::info");
162 bzero((char*) &stats
, sizeof(stats
));
163 if (flag
& HA_STATUS_AUTO
)
164 stats
.auto_increment_value
= 1;
168 int ha_blackhole::external_lock(THD
*thd
, int lock_type
)
170 DBUG_ENTER("ha_blackhole::external_lock");
175 THR_LOCK_DATA
**ha_blackhole::store_lock(THD
*thd
,
177 enum thr_lock_type lock_type
)
179 DBUG_ENTER("ha_blackhole::store_lock");
180 if (lock_type
!= TL_IGNORE
&& lock
.type
== TL_UNLOCK
)
183 Here is where we get into the guts of a row level lock.
185 If we are not doing a LOCK TABLE or DISCARD/IMPORT
186 TABLESPACE, then allow multiple writers
189 if ((lock_type
>= TL_WRITE_CONCURRENT_INSERT
&&
190 lock_type
<= TL_WRITE
) && !thd_in_lock_tables(thd
)
191 && !thd_tablespace_op(thd
))
192 lock_type
= TL_WRITE_ALLOW_WRITE
;
195 In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
196 MySQL would use the lock TL_READ_NO_INSERT on t2, and that
197 would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
198 to t2. Convert the lock to a normal read lock to allow
199 concurrent inserts to t2.
202 if (lock_type
== TL_READ_NO_INSERT
&& !thd_in_lock_tables(thd
))
205 lock
.type
= lock_type
;
212 int ha_blackhole::index_read_map(uchar
* buf
, const uchar
* key
,
213 key_part_map keypart_map
,
214 enum ha_rkey_function find_flag
)
216 DBUG_ENTER("ha_blackhole::index_read");
218 if (thd
->system_thread
== SYSTEM_THREAD_SLAVE_SQL
&& thd
->query() == NULL
)
220 DBUG_RETURN(HA_ERR_END_OF_FILE
);
224 int ha_blackhole::index_read_idx_map(uchar
* buf
, uint idx
, const uchar
* key
,
225 key_part_map keypart_map
,
226 enum ha_rkey_function find_flag
)
228 DBUG_ENTER("ha_blackhole::index_read_idx");
230 if (thd
->system_thread
== SYSTEM_THREAD_SLAVE_SQL
&& thd
->query() == NULL
)
232 DBUG_RETURN(HA_ERR_END_OF_FILE
);
236 int ha_blackhole::index_read_last_map(uchar
* buf
, const uchar
* key
,
237 key_part_map keypart_map
)
239 DBUG_ENTER("ha_blackhole::index_read_last");
241 if (thd
->system_thread
== SYSTEM_THREAD_SLAVE_SQL
&& thd
->query() == NULL
)
243 DBUG_RETURN(HA_ERR_END_OF_FILE
);
247 int ha_blackhole::index_next(uchar
* buf
)
249 DBUG_ENTER("ha_blackhole::index_next");
250 DBUG_RETURN(HA_ERR_END_OF_FILE
);
254 int ha_blackhole::index_prev(uchar
* buf
)
256 DBUG_ENTER("ha_blackhole::index_prev");
257 DBUG_RETURN(HA_ERR_END_OF_FILE
);
261 int ha_blackhole::index_first(uchar
* buf
)
263 DBUG_ENTER("ha_blackhole::index_first");
264 DBUG_RETURN(HA_ERR_END_OF_FILE
);
268 int ha_blackhole::index_last(uchar
* buf
)
270 DBUG_ENTER("ha_blackhole::index_last");
271 DBUG_RETURN(HA_ERR_END_OF_FILE
);
275 static st_blackhole_share
*get_share(const char *table_name
)
277 st_blackhole_share
*share
;
280 length
= (uint
) strlen(table_name
);
281 pthread_mutex_lock(&blackhole_mutex
);
283 if (!(share
= (st_blackhole_share
*) hash_search(&blackhole_open_tables
,
284 (uchar
*) table_name
, length
)))
286 if (!(share
= (st_blackhole_share
*) my_malloc(sizeof(st_blackhole_share
) +
288 MYF(MY_WME
| MY_ZEROFILL
))))
291 share
->table_name_length
= length
;
292 strmov(share
->table_name
, table_name
);
294 if (my_hash_insert(&blackhole_open_tables
, (uchar
*) share
))
296 my_free((uchar
*) share
, MYF(0));
301 thr_lock_init(&share
->lock
);
306 pthread_mutex_unlock(&blackhole_mutex
);
310 static void free_share(st_blackhole_share
*share
)
312 pthread_mutex_lock(&blackhole_mutex
);
313 if (!--share
->use_count
)
314 hash_delete(&blackhole_open_tables
, (uchar
*) share
);
315 pthread_mutex_unlock(&blackhole_mutex
);
318 static void blackhole_free_key(st_blackhole_share
*share
)
320 thr_lock_delete(&share
->lock
);
321 my_free((uchar
*) share
, MYF(0));
324 static uchar
* blackhole_get_key(st_blackhole_share
*share
, size_t *length
,
325 my_bool not_used
__attribute__((unused
)))
327 *length
= share
->table_name_length
;
328 return (uchar
*) share
->table_name
;
331 static int blackhole_init(void *p
)
333 handlerton
*blackhole_hton
;
334 blackhole_hton
= (handlerton
*)p
;
335 blackhole_hton
->state
= SHOW_OPTION_YES
;
336 blackhole_hton
->db_type
= DB_TYPE_BLACKHOLE_DB
;
337 blackhole_hton
->create
= blackhole_create_handler
;
338 blackhole_hton
->flags
= HTON_CAN_RECREATE
;
340 VOID(pthread_mutex_init(&blackhole_mutex
, MY_MUTEX_INIT_FAST
));
341 (void) hash_init(&blackhole_open_tables
, system_charset_info
,32,0,0,
342 (hash_get_key
) blackhole_get_key
,
343 (hash_free_key
) blackhole_free_key
, 0);
348 static int blackhole_fini(void *p
)
350 hash_free(&blackhole_open_tables
);
351 pthread_mutex_destroy(&blackhole_mutex
);
356 struct st_mysql_storage_engine blackhole_storage_engine
=
357 { MYSQL_HANDLERTON_INTERFACE_VERSION
};
359 mysql_declare_plugin(blackhole
)
361 MYSQL_STORAGE_ENGINE_PLUGIN
,
362 &blackhole_storage_engine
,
365 "/dev/null storage engine (anything you write to it disappears)",
367 blackhole_init
, /* Plugin Init */
368 blackhole_fini
, /* Plugin Deinit */
370 NULL
, /* status variables */
371 NULL
, /* system variables */
372 NULL
/* config options */
374 mysql_declare_plugin_end
;