diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 18:07:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 18:07:14 +0000 |
commit | a175314c3e5827eb193872241446f2f8f5c9d33c (patch) | |
tree | cd3d60ca99ae00829c52a6ca79150a5b6e62528b /storage/blackhole | |
parent | Initial commit. (diff) | |
download | mariadb-10.5-upstream/1%10.5.12.tar.xz mariadb-10.5-upstream/1%10.5.12.zip |
Adding upstream version 1:10.5.12.upstream/1%10.5.12upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'storage/blackhole')
-rw-r--r-- | storage/blackhole/CMakeLists.txt | 17 | ||||
-rw-r--r-- | storage/blackhole/ha_blackhole.cc | 442 | ||||
-rw-r--r-- | storage/blackhole/ha_blackhole.h | 107 |
3 files changed, 566 insertions, 0 deletions
diff --git a/storage/blackhole/CMakeLists.txt b/storage/blackhole/CMakeLists.txt new file mode 100644 index 00000000..c58ca125 --- /dev/null +++ b/storage/blackhole/CMakeLists.txt @@ -0,0 +1,17 @@ +# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA + +SET(BLACKHOLE_SOURCES ha_blackhole.cc ha_blackhole.h) +MYSQL_ADD_PLUGIN(blackhole ${BLACKHOLE_SOURCES} STORAGE_ENGINE) diff --git a/storage/blackhole/ha_blackhole.cc b/storage/blackhole/ha_blackhole.cc new file mode 100644 index 00000000..01340323 --- /dev/null +++ b/storage/blackhole/ha_blackhole.cc @@ -0,0 +1,442 @@ +/* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + + +#ifdef USE_PRAGMA_IMPLEMENTATION +#pragma implementation // gcc: Class implementation +#endif + +#define MYSQL_SERVER 1 +#include <my_global.h> +#include "sql_priv.h" +#include "unireg.h" +#include "ha_blackhole.h" +#include "sql_class.h" // THD, SYSTEM_THREAD_SLAVE_SQL + +/** + Checks if the param 'thd' is pointing to slave applier thread and row based + replication is in use. + + A row event will have its thd->query() == NULL except in cases where + replicate_annotate_row_events is enabled. In the later case the thd->query() + will be pointing to the query, received through replicated annotate event + from master. + + @param thd pointer to a THD instance + + @return TRUE if thread is slave applier and row based replication is in use +*/ +static bool is_row_based_replication(THD *thd) +{ + return thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && + (thd->query() == NULL || thd->variables.binlog_annotate_row_events); +} +/* Static declarations for handlerton */ + +static handler *blackhole_create_handler(handlerton *hton, + TABLE_SHARE *table, + MEM_ROOT *mem_root) +{ + return new (mem_root) ha_blackhole(hton, table); +} + + +/* Static declarations for shared structures */ + +static mysql_mutex_t blackhole_mutex; +static HASH blackhole_open_tables; + +static st_blackhole_share *get_share(const char *table_name); +static void free_share(st_blackhole_share *share); + +/***************************************************************************** +** BLACKHOLE tables +*****************************************************************************/ + +ha_blackhole::ha_blackhole(handlerton *hton, + TABLE_SHARE *table_arg) + :handler(hton, table_arg) +{} + + +int ha_blackhole::open(const char *name, int mode, uint test_if_locked) +{ + DBUG_ENTER("ha_blackhole::open"); + + if (!(share= get_share(name))) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + + thr_lock_data_init(&share->lock, &lock, NULL); + DBUG_RETURN(0); +} + +int ha_blackhole::close(void) +{ + DBUG_ENTER("ha_blackhole::close"); + free_share(share); + DBUG_RETURN(0); +} + +int ha_blackhole::create(const char *name, TABLE *table_arg, + HA_CREATE_INFO *create_info) +{ + DBUG_ENTER("ha_blackhole::create"); + DBUG_RETURN(0); +} + +/* + Intended to support partitioning. + Allows a particular partition to be truncated. +*/ +int ha_blackhole::truncate() +{ + DBUG_ENTER("ha_blackhole::truncate"); + DBUG_RETURN(0); +} + +const char *ha_blackhole::index_type(uint key_number) +{ + DBUG_ENTER("ha_blackhole::index_type"); + DBUG_RETURN((table_share->key_info[key_number].flags & HA_FULLTEXT) ? + "FULLTEXT" : + (table_share->key_info[key_number].flags & HA_SPATIAL) ? + "SPATIAL" : + (table_share->key_info[key_number].algorithm == + HA_KEY_ALG_RTREE) ? "RTREE" : "BTREE"); +} + +int ha_blackhole::write_row(const uchar * buf) +{ + DBUG_ENTER("ha_blackhole::write_row"); + DBUG_RETURN(table->next_number_field ? update_auto_increment() : 0); +} + +int ha_blackhole::update_row(const uchar *old_data, const uchar *new_data) +{ + DBUG_ENTER("ha_blackhole::update_row"); + THD *thd= ha_thd(); + if (is_row_based_replication(thd)) + DBUG_RETURN(0); + DBUG_RETURN(HA_ERR_WRONG_COMMAND); +} + +int ha_blackhole::delete_row(const uchar *buf) +{ + DBUG_ENTER("ha_blackhole::delete_row"); + THD *thd= ha_thd(); + if (is_row_based_replication(thd)) + DBUG_RETURN(0); + DBUG_RETURN(HA_ERR_WRONG_COMMAND); +} + +int ha_blackhole::rnd_init(bool scan) +{ + DBUG_ENTER("ha_blackhole::rnd_init"); + DBUG_RETURN(0); +} + + +int ha_blackhole::rnd_next(uchar *buf) +{ + int rc; + DBUG_ENTER("ha_blackhole::rnd_next"); + THD *thd= ha_thd(); + if (is_row_based_replication(thd)) + rc= 0; + else + rc= HA_ERR_END_OF_FILE; + DBUG_RETURN(rc); +} + + +int ha_blackhole::rnd_pos(uchar * buf, uchar *pos) +{ + DBUG_ENTER("ha_blackhole::rnd_pos"); + DBUG_ASSERT(0); + DBUG_RETURN(0); +} + + +void ha_blackhole::position(const uchar *record) +{ + DBUG_ENTER("ha_blackhole::position"); + DBUG_ASSERT(0); + DBUG_VOID_RETURN; +} + + +int ha_blackhole::info(uint flag) +{ + DBUG_ENTER("ha_blackhole::info"); + + bzero((char*) &stats, sizeof(stats)); + if (flag & HA_STATUS_AUTO) + stats.auto_increment_value= 1; + DBUG_RETURN(0); +} + +int ha_blackhole::external_lock(THD *thd, int lock_type) +{ + DBUG_ENTER("ha_blackhole::external_lock"); + DBUG_RETURN(0); +} + + +THR_LOCK_DATA **ha_blackhole::store_lock(THD *thd, + THR_LOCK_DATA **to, + enum thr_lock_type lock_type) +{ + DBUG_ENTER("ha_blackhole::store_lock"); + if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) + { + /* + Here is where we get into the guts of a row level lock. + If TL_UNLOCK is set + If we are not doing a LOCK TABLE or DISCARD/IMPORT + TABLESPACE, then allow multiple writers + */ + + if ((lock_type >= TL_WRITE_CONCURRENT_INSERT && + lock_type <= TL_WRITE) && !thd_in_lock_tables(thd) + && !thd_tablespace_op(thd)) + lock_type = TL_WRITE_ALLOW_WRITE; + + /* + In queries of type INSERT INTO t1 SELECT ... FROM t2 ... + MySQL would use the lock TL_READ_NO_INSERT on t2, and that + would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts + to t2. Convert the lock to a normal read lock to allow + concurrent inserts to t2. + */ + + if (lock_type == TL_READ_NO_INSERT && !thd_in_lock_tables(thd)) + lock_type = TL_READ; + + lock.type= lock_type; + } + *to++= &lock; + DBUG_RETURN(to); +} + + +int ha_blackhole::index_read_map(uchar * buf, const uchar * key, + key_part_map keypart_map, + enum ha_rkey_function find_flag) +{ + int rc; + DBUG_ENTER("ha_blackhole::index_read"); + THD *thd= ha_thd(); + if (is_row_based_replication(thd)) + rc= 0; + else + rc= HA_ERR_END_OF_FILE; + DBUG_RETURN(rc); +} + + +int ha_blackhole::index_read_idx_map(uchar * buf, uint idx, const uchar * key, + key_part_map keypart_map, + enum ha_rkey_function find_flag) +{ + int rc; + DBUG_ENTER("ha_blackhole::index_read_idx"); + THD *thd= ha_thd(); + if (is_row_based_replication(thd)) + rc= 0; + else + rc= HA_ERR_END_OF_FILE; + DBUG_RETURN(rc); +} + + +int ha_blackhole::index_read_last_map(uchar * buf, const uchar * key, + key_part_map keypart_map) +{ + int rc; + DBUG_ENTER("ha_blackhole::index_read_last"); + THD *thd= ha_thd(); + if (is_row_based_replication(thd)) + rc= 0; + else + rc= HA_ERR_END_OF_FILE; + DBUG_RETURN(rc); +} + + +int ha_blackhole::index_next(uchar * buf) +{ + int rc; + DBUG_ENTER("ha_blackhole::index_next"); + rc= HA_ERR_END_OF_FILE; + DBUG_RETURN(rc); +} + + +int ha_blackhole::index_prev(uchar * buf) +{ + int rc; + DBUG_ENTER("ha_blackhole::index_prev"); + rc= HA_ERR_END_OF_FILE; + DBUG_RETURN(rc); +} + + +int ha_blackhole::index_first(uchar * buf) +{ + int rc; + DBUG_ENTER("ha_blackhole::index_first"); + rc= HA_ERR_END_OF_FILE; + DBUG_RETURN(rc); +} + + +int ha_blackhole::index_last(uchar * buf) +{ + int rc; + DBUG_ENTER("ha_blackhole::index_last"); + rc= HA_ERR_END_OF_FILE; + DBUG_RETURN(rc); +} + + +static st_blackhole_share *get_share(const char *table_name) +{ + st_blackhole_share *share; + uint length; + + length= (uint) strlen(table_name); + mysql_mutex_lock(&blackhole_mutex); + + if (!(share= (st_blackhole_share*) + my_hash_search(&blackhole_open_tables, + (uchar*) table_name, length))) + { + if (!(share= (st_blackhole_share*) my_malloc(PSI_INSTRUMENT_ME, + sizeof(st_blackhole_share) + length, MYF(MY_WME | MY_ZEROFILL)))) + goto error; + + share->table_name_length= length; + strmov(share->table_name, table_name); + + if (my_hash_insert(&blackhole_open_tables, (uchar*) share)) + { + my_free(share); + share= NULL; + goto error; + } + + thr_lock_init(&share->lock); + } + share->use_count++; + +error: + mysql_mutex_unlock(&blackhole_mutex); + return share; +} + +static void free_share(st_blackhole_share *share) +{ + mysql_mutex_lock(&blackhole_mutex); + if (!--share->use_count) + my_hash_delete(&blackhole_open_tables, (uchar*) share); + mysql_mutex_unlock(&blackhole_mutex); +} + +static void blackhole_free_key(st_blackhole_share *share) +{ + thr_lock_delete(&share->lock); + my_free(share); +} + +static uchar* blackhole_get_key(st_blackhole_share *share, size_t *length, + my_bool not_used __attribute__((unused))) +{ + *length= share->table_name_length; + return (uchar*) share->table_name; +} + +#ifdef HAVE_PSI_INTERFACE +static PSI_mutex_key bh_key_mutex_blackhole; + +static PSI_mutex_info all_blackhole_mutexes[]= +{ + { &bh_key_mutex_blackhole, "blackhole", PSI_FLAG_GLOBAL} +}; + +void init_blackhole_psi_keys() +{ + const char* category= "blackhole"; + int count; + + if (PSI_server == NULL) + return; + + count= array_elements(all_blackhole_mutexes); + PSI_server->register_mutex(category, all_blackhole_mutexes, count); +} +#endif + +static int blackhole_init(void *p) +{ + handlerton *blackhole_hton; + +#ifdef HAVE_PSI_INTERFACE + init_blackhole_psi_keys(); +#endif + + blackhole_hton= (handlerton *)p; + blackhole_hton->db_type= DB_TYPE_BLACKHOLE_DB; + blackhole_hton->create= blackhole_create_handler; + blackhole_hton->drop_table= [](handlerton *, const char*) { return -1; }; + blackhole_hton->flags= HTON_CAN_RECREATE; + + mysql_mutex_init(bh_key_mutex_blackhole, + &blackhole_mutex, MY_MUTEX_INIT_FAST); + (void) my_hash_init(PSI_INSTRUMENT_ME, &blackhole_open_tables, + system_charset_info, 32, 0, 0, + (my_hash_get_key) blackhole_get_key, + (my_hash_free_key) blackhole_free_key, 0); + + return 0; +} + +static int blackhole_fini(void *p) +{ + my_hash_free(&blackhole_open_tables); + mysql_mutex_destroy(&blackhole_mutex); + + return 0; +} + +struct st_mysql_storage_engine blackhole_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION }; + +maria_declare_plugin(blackhole) +{ + MYSQL_STORAGE_ENGINE_PLUGIN, + &blackhole_storage_engine, + "BLACKHOLE", + "MySQL AB", + "/dev/null storage engine (anything you write to it disappears)", + PLUGIN_LICENSE_GPL, + blackhole_init, /* Plugin Init */ + blackhole_fini, /* Plugin Deinit */ + 0x0100 /* 1.0 */, + NULL, /* status variables */ + NULL, /* system variables */ + "1.0", /* string version */ + MariaDB_PLUGIN_MATURITY_STABLE /* maturity */ +} +maria_declare_plugin_end; diff --git a/storage/blackhole/ha_blackhole.h b/storage/blackhole/ha_blackhole.h new file mode 100644 index 00000000..baa140bc --- /dev/null +++ b/storage/blackhole/ha_blackhole.h @@ -0,0 +1,107 @@ +/* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifdef USE_PRAGMA_INTERFACE +#pragma interface /* gcc class implementation */ +#endif + +#include "thr_lock.h" /* THR_LOCK */ +#include "handler.h" /* handler */ +#include "table.h" /* TABLE_SHARE */ +#include "sql_const.h" /* MAX_KEY */ + +/* + Shared structure for correct LOCK operation +*/ +struct st_blackhole_share { + THR_LOCK lock; + uint use_count; + uint table_name_length; + char table_name[1]; +}; + + +/* + Class definition for the blackhole storage engine + "Dumbest named feature ever" +*/ +class ha_blackhole final : public handler +{ + THR_LOCK_DATA lock; /* MySQL lock */ + st_blackhole_share *share; + +public: + ha_blackhole(handlerton *hton, TABLE_SHARE *table_arg); + ~ha_blackhole() + { + } + /* + The name of the index type that will be used for display + don't implement this method unless you really have indexes + */ + const char *index_type(uint key_number); + ulonglong table_flags() const + { + return(HA_NULL_IN_KEY | HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER | + HA_BINLOG_STMT_CAPABLE | HA_BINLOG_ROW_CAPABLE | + HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY | HA_CAN_ONLINE_BACKUPS | + HA_FILE_BASED | HA_CAN_GEOMETRY | HA_CAN_INSERT_DELAYED); + } + ulong index_flags(uint inx, uint part, bool all_parts) const + { + return ((table_share->key_info[inx].algorithm == HA_KEY_ALG_FULLTEXT) ? + 0 : HA_READ_NEXT | HA_READ_PREV | HA_READ_RANGE | + HA_READ_ORDER | HA_KEYREAD_ONLY); + } + /* The following defines can be increased if necessary */ +#define BLACKHOLE_MAX_KEY MAX_KEY /* Max allowed keys */ +#define BLACKHOLE_MAX_KEY_SEG 16 /* Max segments for key */ +#define BLACKHOLE_MAX_KEY_LENGTH 3500 /* Like in InnoDB */ + uint max_supported_keys() const { return BLACKHOLE_MAX_KEY; } + uint max_supported_key_length() const { return BLACKHOLE_MAX_KEY_LENGTH; } + uint max_supported_key_part_length() const { return BLACKHOLE_MAX_KEY_LENGTH; } + int open(const char *name, int mode, uint test_if_locked); + int close(void); + int truncate(); + int rnd_init(bool scan); + int rnd_next(uchar *buf); + int rnd_pos(uchar * buf, uchar *pos); + int index_read_map(uchar * buf, const uchar * key, key_part_map keypart_map, + enum ha_rkey_function find_flag); + int index_read_idx_map(uchar * buf, uint idx, const uchar * key, + key_part_map keypart_map, + enum ha_rkey_function find_flag); + int index_read_last_map(uchar * buf, const uchar * key, key_part_map keypart_map); + int index_next(uchar * buf); + int index_prev(uchar * buf); + int index_first(uchar * buf); + int index_last(uchar * buf); + void position(const uchar *record); + int info(uint flag); + int external_lock(THD *thd, int lock_type); + int create(const char *name, TABLE *table_arg, + HA_CREATE_INFO *create_info); + THR_LOCK_DATA **store_lock(THD *thd, + THR_LOCK_DATA **to, + enum thr_lock_type lock_type); + int delete_table(const char *name) + { + return 0; + } +private: + virtual int write_row(const uchar *buf); + virtual int update_row(const uchar *old_data, const uchar *new_data); + virtual int delete_row(const uchar *buf); +}; |