12
12
You should have received a copy of the GNU General Public License
13
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
18
#include <drizzled/error.h>
19
#include <drizzled/global_charset_info.h>
20
#include <drizzled/internal/m_string.h>
21
#include <drizzled/internal/my_pthread.h>
22
#include <drizzled/message/table.h>
23
#include <drizzled/plugin/storage_engine.h>
24
#include <drizzled/table.h>
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
#include <drizzled/common_includes.h>
27
17
#include "ha_blackhole.h"
35
#include <google/protobuf/io/zero_copy_stream.h>
36
#include <google/protobuf/io/zero_copy_stream_impl.h>
40
using namespace google;
41
using namespace drizzled;
43
#define BLACKHOLE_EXT ".blk"
19
/* Static declarations for handlerton */
21
static handler *blackhole_create_handler(handlerton *hton,
25
return new (mem_root) ha_blackhole(hton, table);
29
/* Static declarations for shared structures */
45
31
static pthread_mutex_t blackhole_mutex;
48
static const char *ha_blackhole_exts[] = {
53
class BlackholeEngine : public drizzled::plugin::StorageEngine
55
typedef std::map<std::string, BlackholeShare*> BlackholeMap;
56
BlackholeMap blackhole_open_tables;
59
BlackholeEngine(const string &name_arg)
60
: drizzled::plugin::StorageEngine(name_arg,
62
HTON_CAN_INDEX_BLOBS |
63
HTON_SKIP_STORE_LOCK |
65
blackhole_open_tables()
67
table_definition_ext= BLACKHOLE_EXT;
70
virtual ~BlackholeEngine()
72
pthread_mutex_destroy(&blackhole_mutex);
75
virtual Cursor *create(Table &table)
77
return new ha_blackhole(*this, table);
80
const char **bas_ext() const {
81
return ha_blackhole_exts;
84
int doCreateTable(Session&,
86
const drizzled::identifier::Table &identifier,
87
drizzled::message::Table&);
89
int doDropTable(Session&, const drizzled::identifier::Table &identifier);
91
BlackholeShare *findOpenTable(const string table_name);
92
void addOpenTable(const string &table_name, BlackholeShare *);
93
void deleteOpenTable(const string &table_name);
95
int doGetTableDefinition(Session& session,
96
const drizzled::identifier::Table &identifier,
97
drizzled::message::Table &table_message);
99
/* The following defines can be increased if necessary */
100
uint32_t max_supported_keys() const { return BLACKHOLE_MAX_KEY; }
101
uint32_t max_supported_key_length() const { return BLACKHOLE_MAX_KEY_LENGTH; }
102
uint32_t max_supported_key_part_length() const { return BLACKHOLE_MAX_KEY_LENGTH; }
104
uint32_t index_flags(enum ha_key_alg) const
106
return (HA_READ_NEXT |
113
bool doDoesTableExist(Session& session, const drizzled::identifier::Table &identifier);
114
int doRenameTable(Session&, const drizzled::identifier::Table &from, const drizzled::identifier::Table &to);
115
void doGetTableIdentifiers(drizzled::CachedDirectory &directory,
116
const drizzled::identifier::Schema &schema_identifier,
117
drizzled::identifier::Table::vector &set_of_identifiers);
121
void BlackholeEngine::doGetTableIdentifiers(drizzled::CachedDirectory &directory,
122
const drizzled::identifier::Schema &schema_identifier,
123
drizzled::identifier::Table::vector &set_of_identifiers)
125
drizzled::CachedDirectory::Entries entries= directory.getEntries();
127
for (drizzled::CachedDirectory::Entries::iterator entry_iter= entries.begin();
128
entry_iter != entries.end(); ++entry_iter)
130
drizzled::CachedDirectory::Entry *entry= *entry_iter;
131
const string *filename= &entry->filename;
133
assert(filename->size());
135
const char *ext= strchr(filename->c_str(), '.');
137
if (ext == NULL || my_strcasecmp(system_charset_info, ext, BLACKHOLE_EXT) ||
138
(filename->compare(0, strlen(TMP_FILE_PREFIX), TMP_FILE_PREFIX) == 0))
142
char uname[NAME_LEN + 1];
143
uint32_t file_name_len;
145
file_name_len= identifier::Table::filename_to_tablename(filename->c_str(), uname, sizeof(uname));
146
// TODO: Remove need for memory copy here
147
uname[file_name_len - sizeof(BLACKHOLE_EXT) + 1]= '\0'; // Subtract ending, place NULL
149
set_of_identifiers.push_back(identifier::Table(schema_identifier, uname));
154
int BlackholeEngine::doRenameTable(Session&, const drizzled::identifier::Table &from, const drizzled::identifier::Table &to)
158
for (const char **ext= bas_ext(); *ext ; ext++)
160
if (rename_file_ext(from.getPath().c_str(), to.getPath().c_str(), *ext))
162
if ((error=errno) != ENOENT)
170
BlackholeShare *BlackholeEngine::findOpenTable(const string table_name)
172
BlackholeMap::iterator find_iter=
173
blackhole_open_tables.find(table_name);
175
if (find_iter != blackhole_open_tables.end())
176
return (*find_iter).second;
181
void BlackholeEngine::addOpenTable(const string &table_name, BlackholeShare *share)
183
blackhole_open_tables[table_name]= share;
186
void BlackholeEngine::deleteOpenTable(const string &table_name)
188
blackhole_open_tables.erase(table_name);
32
static HASH blackhole_open_tables;
34
static st_blackhole_share *get_share(const char *table_name);
35
static void free_share(st_blackhole_share *share);
193
37
/*****************************************************************************
194
38
** BLACKHOLE tables
195
39
*****************************************************************************/
197
ha_blackhole::ha_blackhole(drizzled::plugin::StorageEngine &engine_arg,
199
:Cursor(engine_arg, table_arg), share(NULL)
202
int ha_blackhole::open(const char *name, int, uint32_t)
41
ha_blackhole::ha_blackhole(handlerton *hton,
42
TABLE_SHARE *table_arg)
43
:handler(hton, table_arg)
47
static const char *ha_blackhole_exts[] = {
51
const char **ha_blackhole::bas_ext() const
53
return ha_blackhole_exts;
56
int ha_blackhole::open(const char *name, int mode __attribute__((unused)),
57
uint32_t test_if_locked __attribute__((unused)))
204
59
if (!(share= get_share(name)))
205
60
return(HA_ERR_OUT_OF_MEM);
207
lock.init(&share->lock);
62
thr_lock_data_init(&share->lock, &lock, NULL);
211
66
int ha_blackhole::close(void)
217
int BlackholeEngine::doCreateTable(Session&,
219
const drizzled::identifier::Table &identifier,
220
drizzled::message::Table& proto)
222
string serialized_proto;
225
new_path= identifier.getPath();
226
new_path+= BLACKHOLE_EXT;
227
fstream output(new_path.c_str(), ios::out | ios::binary);
233
if (! proto.SerializeToOstream(&output))
236
unlink(new_path.c_str());
244
int BlackholeEngine::doDropTable(Session&,
245
const drizzled::identifier::Table &identifier)
247
string new_path(identifier.getPath());
249
new_path+= BLACKHOLE_EXT;
251
int error= unlink(new_path.c_str());
262
bool BlackholeEngine::doDoesTableExist(Session&,
263
const drizzled::identifier::Table &identifier)
265
string proto_path(identifier.getPath());
266
proto_path.append(BLACKHOLE_EXT);
268
if (access(proto_path.c_str(), F_OK))
277
int BlackholeEngine::doGetTableDefinition(Session&,
278
const drizzled::identifier::Table &identifier,
279
drizzled::message::Table &table_proto)
283
new_path= identifier.getPath();
284
new_path+= BLACKHOLE_EXT;
286
int fd= open(new_path.c_str(), O_RDONLY);
293
google::protobuf::io::ZeroCopyInputStream* input=
294
new google::protobuf::io::FileInputStream(fd);
297
return HA_ERR_CRASHED_ON_USAGE;
299
if (not table_proto.ParseFromZeroCopyStream(input))
303
if (not table_proto.IsInitialized())
305
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
306
table_proto.name().empty() ? " " : table_proto.name().c_str(),
307
table_proto.InitializationErrorString().c_str());
309
return ER_CORRUPT_TABLE_DEFINITION;
312
return HA_ERR_CRASHED_ON_USAGE;
320
const char *ha_blackhole::index_type(uint32_t)
72
int ha_blackhole::create(const char *name __attribute__((unused)),
73
Table *table_arg __attribute__((unused)),
74
HA_CREATE_INFO *create_info __attribute__((unused)))
79
const char *ha_blackhole::index_type(uint32_t key_number __attribute__((unused)))
325
int ha_blackhole::doInsertRecord(unsigned char *)
84
int ha_blackhole::write_row(unsigned char * buf __attribute__((unused)))
327
return(getTable()->next_number_field ? update_auto_increment() : 0);
86
return(table->next_number_field ? update_auto_increment() : 0);
330
int ha_blackhole::doStartTableScan(bool)
89
int ha_blackhole::rnd_init(bool scan __attribute__((unused)))
336
int ha_blackhole::rnd_next(unsigned char *)
95
int ha_blackhole::rnd_next(unsigned char *buf __attribute__((unused)))
338
97
return(HA_ERR_END_OF_FILE);
342
int ha_blackhole::rnd_pos(unsigned char *, unsigned char *)
101
int ha_blackhole::rnd_pos(unsigned char * buf __attribute__((unused)),
102
unsigned char *pos __attribute__((unused)))
349
void ha_blackhole::position(const unsigned char *)
109
void ha_blackhole::position(const unsigned char *record __attribute__((unused)))
365
int ha_blackhole::index_read_map(unsigned char *, const unsigned char *,
366
key_part_map, enum ha_rkey_function)
368
return(HA_ERR_END_OF_FILE);
372
int ha_blackhole::index_read_idx_map(unsigned char *, uint32_t, const unsigned char *,
373
key_part_map, enum ha_rkey_function)
375
return(HA_ERR_END_OF_FILE);
379
int ha_blackhole::index_read_last_map(unsigned char *, const unsigned char *, key_part_map)
381
return(HA_ERR_END_OF_FILE);
385
int ha_blackhole::index_next(unsigned char *)
387
return(HA_ERR_END_OF_FILE);
391
int ha_blackhole::index_prev(unsigned char *)
393
return(HA_ERR_END_OF_FILE);
397
int ha_blackhole::index_first(unsigned char *)
399
return(HA_ERR_END_OF_FILE);
403
int ha_blackhole::index_last(unsigned char *)
405
return(HA_ERR_END_OF_FILE);
409
BlackholeShare *ha_blackhole::get_share(const char *table_name)
124
int ha_blackhole::external_lock(Session *session __attribute__((unused)),
125
int lock_type __attribute__((unused)))
131
THR_LOCK_DATA **ha_blackhole::store_lock(Session *session,
133
enum thr_lock_type lock_type)
135
if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK)
138
Here is where we get into the guts of a row level lock.
140
If we are not doing a LOCK Table or DISCARD/IMPORT
141
TABLESPACE, then allow multiple writers
144
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT &&
145
lock_type <= TL_WRITE) && !session_in_lock_tables(session)
146
&& !session_tablespace_op(session))
147
lock_type = TL_WRITE_ALLOW_WRITE;
150
In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
151
MySQL would use the lock TL_READ_NO_INSERT on t2, and that
152
would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
153
to t2. Convert the lock to a normal read lock to allow
154
concurrent inserts to t2.
157
if (lock_type == TL_READ_NO_INSERT && !session_in_lock_tables(session))
160
lock.type= lock_type;
167
int ha_blackhole::index_read_map(unsigned char * buf __attribute__((unused)),
168
const unsigned char * key __attribute__((unused)),
169
key_part_map keypart_map __attribute__((unused)),
170
enum ha_rkey_function find_flag __attribute__((unused)))
172
return(HA_ERR_END_OF_FILE);
176
int ha_blackhole::index_read_idx_map(unsigned char * buf __attribute__((unused)),
177
uint32_t idx __attribute__((unused)),
178
const unsigned char * key __attribute__((unused)),
179
key_part_map keypart_map __attribute__((unused)),
180
enum ha_rkey_function find_flag __attribute__((unused)))
182
return(HA_ERR_END_OF_FILE);
186
int ha_blackhole::index_read_last_map(unsigned char * buf __attribute__((unused)),
187
const unsigned char * key __attribute__((unused)),
188
key_part_map keypart_map __attribute__((unused)))
190
return(HA_ERR_END_OF_FILE);
194
int ha_blackhole::index_next(unsigned char * buf __attribute__((unused)))
196
return(HA_ERR_END_OF_FILE);
200
int ha_blackhole::index_prev(unsigned char * buf __attribute__((unused)))
202
return(HA_ERR_END_OF_FILE);
206
int ha_blackhole::index_first(unsigned char * buf __attribute__((unused)))
208
return(HA_ERR_END_OF_FILE);
212
int ha_blackhole::index_last(unsigned char * buf __attribute__((unused)))
214
return(HA_ERR_END_OF_FILE);
218
static st_blackhole_share *get_share(const char *table_name)
220
st_blackhole_share *share;
223
length= (uint) strlen(table_name);
411
224
pthread_mutex_lock(&blackhole_mutex);
413
BlackholeEngine *a_engine= static_cast<BlackholeEngine *>(getEngine());
414
share= a_engine->findOpenTable(table_name);
226
if (!(share= (st_blackhole_share*) hash_search(&blackhole_open_tables,
227
(unsigned char*) table_name, length)))
418
share= new (nothrow) BlackholeShare(table_name);
229
if (!(share= (st_blackhole_share*) my_malloc(sizeof(st_blackhole_share) +
231
MYF(MY_WME | MY_ZEROFILL))))
234
share->table_name_length= length;
235
my_stpcpy(share->table_name, table_name);
237
if (my_hash_insert(&blackhole_open_tables, (unsigned char*) share))
421
pthread_mutex_unlock(&blackhole_mutex);
239
free((unsigned char*) share);
425
a_engine->addOpenTable(share->table_name, share);
244
thr_lock_init(&share->lock);
427
246
share->use_count++;
428
249
pthread_mutex_unlock(&blackhole_mutex);
433
void ha_blackhole::free_share()
253
static void free_share(st_blackhole_share *share)
435
255
pthread_mutex_lock(&blackhole_mutex);
436
256
if (!--share->use_count)
438
BlackholeEngine *a_engine= static_cast<BlackholeEngine *>(getEngine());
439
a_engine->deleteOpenTable(share->table_name);
257
hash_delete(&blackhole_open_tables, (unsigned char*) share);
442
258
pthread_mutex_unlock(&blackhole_mutex);
445
BlackholeShare::BlackholeShare(const string table_name_arg)
446
: use_count(0), table_name(table_name_arg)
448
thr_lock_init(&lock);
451
BlackholeShare::~BlackholeShare()
457
static drizzled::plugin::StorageEngine *blackhole_engine= NULL;
459
static int blackhole_init(drizzled::module::Context &context)
462
blackhole_engine= new BlackholeEngine("BLACKHOLE");
463
context.add(blackhole_engine);
261
static void blackhole_free_key(st_blackhole_share *share)
263
thr_lock_delete(&share->lock);
264
free((unsigned char*) share);
267
static unsigned char* blackhole_get_key(st_blackhole_share *share, size_t *length,
268
bool not_used __attribute__((unused)))
270
*length= share->table_name_length;
271
return (unsigned char*) share->table_name;
274
static int blackhole_init(void *p)
276
handlerton *blackhole_hton;
277
blackhole_hton= (handlerton *)p;
278
blackhole_hton->state= SHOW_OPTION_YES;
279
blackhole_hton->create= blackhole_create_handler;
280
blackhole_hton->flags= HTON_CAN_RECREATE;
465
282
pthread_mutex_init(&blackhole_mutex, MY_MUTEX_INIT_FAST);
471
DRIZZLE_DECLARE_PLUGIN
283
(void) hash_init(&blackhole_open_tables, system_charset_info,32,0,0,
284
(hash_get_key) blackhole_get_key,
285
(hash_free_key) blackhole_free_key, 0);
290
static int blackhole_fini(void *p __attribute__((unused)))
292
hash_free(&blackhole_open_tables);
293
pthread_mutex_destroy(&blackhole_mutex);
298
mysql_declare_plugin(blackhole)
300
DRIZZLE_STORAGE_ENGINE_PLUGIN,
477
304
"/dev/null storage engine (anything you write to it disappears)",
478
305
PLUGIN_LICENSE_GPL,
479
blackhole_init, /* Plugin Init */
481
NULL /* config options */
306
blackhole_init, /* Plugin Init */
307
blackhole_fini, /* Plugin Deinit */
308
NULL, /* status variables */
309
NULL, /* system variables */
310
NULL /* config options */
483
DRIZZLE_DECLARE_PLUGIN_END;
312
mysql_declare_plugin_end;