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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
16
#include <drizzled/common_includes.h>
17
17
#include <drizzled/table.h>
18
#include <drizzled/error.h>
19
#include "drizzled/internal/my_pthread.h"
18
21
#include "ha_blackhole.h"
20
/* Static declarations for handlerton */
22
static handler *blackhole_create_handler(handlerton *hton,
26
return new (mem_root) ha_blackhole(hton, table);
30
/* Static declarations for shared structures */
28
#include <drizzled/message/table.pb.h>
29
#include "drizzled/internal/m_string.h"
30
#include <google/protobuf/io/zero_copy_stream.h>
31
#include <google/protobuf/io/zero_copy_stream_impl.h>
32
#include "drizzled/global_charset_info.h"
36
using namespace google;
37
using namespace drizzled;
39
#define BLACKHOLE_EXT ".blk"
32
41
static pthread_mutex_t blackhole_mutex;
33
static HASH blackhole_open_tables;
35
static st_blackhole_share *get_share(const char *table_name);
36
static void free_share(st_blackhole_share *share);
44
static const char *ha_blackhole_exts[] = {
49
class BlackholeEngine : public drizzled::plugin::StorageEngine
51
typedef map<string, BlackholeShare*> BlackholeMap;
52
BlackholeMap blackhole_open_tables;
55
BlackholeEngine(const string &name_arg)
56
: drizzled::plugin::StorageEngine(name_arg,
58
HTON_CAN_INDEX_BLOBS |
59
HTON_SKIP_STORE_LOCK |
61
blackhole_open_tables()
63
table_definition_ext= BLACKHOLE_EXT;
66
virtual ~BlackholeEngine()
68
pthread_mutex_destroy(&blackhole_mutex);
71
virtual Cursor *create(Table &table)
73
return new ha_blackhole(*this, table);
76
const char **bas_ext() const {
77
return ha_blackhole_exts;
80
int doCreateTable(Session&,
82
const drizzled::TableIdentifier &identifier,
83
drizzled::message::Table&);
85
int doDropTable(Session&, const drizzled::TableIdentifier &identifier);
87
BlackholeShare *findOpenTable(const string table_name);
88
void addOpenTable(const string &table_name, BlackholeShare *);
89
void deleteOpenTable(const string &table_name);
91
int doGetTableDefinition(Session& session,
92
const drizzled::TableIdentifier &identifier,
93
drizzled::message::Table &table_message);
95
/* The following defines can be increased if necessary */
96
uint32_t max_supported_keys() const { return BLACKHOLE_MAX_KEY; }
97
uint32_t max_supported_key_length() const { return BLACKHOLE_MAX_KEY_LENGTH; }
98
uint32_t max_supported_key_part_length() const { return BLACKHOLE_MAX_KEY_LENGTH; }
100
uint32_t index_flags(enum ha_key_alg) const
102
return (HA_READ_NEXT |
109
bool doDoesTableExist(Session& session, const drizzled::TableIdentifier &identifier);
110
int doRenameTable(Session&, const drizzled::TableIdentifier &from, const drizzled::TableIdentifier &to);
111
void doGetTableIdentifiers(drizzled::CachedDirectory &directory,
112
const drizzled::SchemaIdentifier &schema_identifier,
113
drizzled::TableIdentifiers &set_of_identifiers);
117
void BlackholeEngine::doGetTableIdentifiers(drizzled::CachedDirectory &directory,
118
const drizzled::SchemaIdentifier &schema_identifier,
119
drizzled::TableIdentifiers &set_of_identifiers)
121
drizzled::CachedDirectory::Entries entries= directory.getEntries();
123
for (drizzled::CachedDirectory::Entries::iterator entry_iter= entries.begin();
124
entry_iter != entries.end(); ++entry_iter)
126
drizzled::CachedDirectory::Entry *entry= *entry_iter;
127
const string *filename= &entry->filename;
129
assert(filename->size());
131
const char *ext= strchr(filename->c_str(), '.');
133
if (ext == NULL || my_strcasecmp(system_charset_info, ext, BLACKHOLE_EXT) ||
134
(filename->compare(0, strlen(TMP_FILE_PREFIX), TMP_FILE_PREFIX) == 0))
138
char uname[NAME_LEN + 1];
139
uint32_t file_name_len;
141
file_name_len= TableIdentifier::filename_to_tablename(filename->c_str(), uname, sizeof(uname));
142
// TODO: Remove need for memory copy here
143
uname[file_name_len - sizeof(BLACKHOLE_EXT) + 1]= '\0'; // Subtract ending, place NULL
145
set_of_identifiers.push_back(TableIdentifier(schema_identifier, uname));
150
int BlackholeEngine::doRenameTable(Session&, const drizzled::TableIdentifier &from, const drizzled::TableIdentifier &to)
154
for (const char **ext= bas_ext(); *ext ; ext++)
156
if (rename_file_ext(from.getPath().c_str(), to.getPath().c_str(), *ext))
158
if ((error=errno) != ENOENT)
166
BlackholeShare *BlackholeEngine::findOpenTable(const string table_name)
168
BlackholeMap::iterator find_iter=
169
blackhole_open_tables.find(table_name);
171
if (find_iter != blackhole_open_tables.end())
172
return (*find_iter).second;
177
void BlackholeEngine::addOpenTable(const string &table_name, BlackholeShare *share)
179
blackhole_open_tables[table_name]= share;
182
void BlackholeEngine::deleteOpenTable(const string &table_name)
184
blackhole_open_tables.erase(table_name);
38
189
/*****************************************************************************
39
190
** BLACKHOLE tables
40
191
*****************************************************************************/
42
ha_blackhole::ha_blackhole(handlerton *hton,
43
TABLE_SHARE *table_arg)
44
:handler(hton, table_arg)
48
static const char *ha_blackhole_exts[] = {
52
const char **ha_blackhole::bas_ext() const
54
return ha_blackhole_exts;
58
uint32_t ha_blackhole::index_flags(uint32_t inx, uint32_t, bool) const
60
return ((table_share->key_info[inx].algorithm == HA_KEY_ALG_FULLTEXT) ?
61
0 : HA_READ_NEXT | HA_READ_PREV | HA_READ_RANGE |
62
HA_READ_ORDER | HA_KEYREAD_ONLY);
65
int ha_blackhole::open(const char *name, int mode __attribute__((unused)),
66
uint32_t test_if_locked __attribute__((unused)))
193
ha_blackhole::ha_blackhole(drizzled::plugin::StorageEngine &engine_arg,
195
:Cursor(engine_arg, table_arg), share(NULL)
198
int ha_blackhole::open(const char *name, int, uint32_t)
68
200
if (!(share= get_share(name)))
69
201
return(HA_ERR_OUT_OF_MEM);
71
thr_lock_data_init(&share->lock, &lock, NULL);
203
lock.init(&share->lock);
75
207
int ha_blackhole::close(void)
81
int ha_blackhole::create(const char *name __attribute__((unused)),
82
Table *table_arg __attribute__((unused)),
83
HA_CREATE_INFO *create_info __attribute__((unused)))
88
const char *ha_blackhole::index_type(uint32_t key_number __attribute__((unused)))
213
int BlackholeEngine::doCreateTable(Session&,
215
const drizzled::TableIdentifier &identifier,
216
drizzled::message::Table& proto)
218
string serialized_proto;
221
new_path= identifier.getPath();
222
new_path+= BLACKHOLE_EXT;
223
fstream output(new_path.c_str(), ios::out | ios::binary);
229
if (! proto.SerializeToOstream(&output))
232
unlink(new_path.c_str());
240
int BlackholeEngine::doDropTable(Session&,
241
const drizzled::TableIdentifier &identifier)
243
string new_path(identifier.getPath());
245
new_path+= BLACKHOLE_EXT;
247
int error= unlink(new_path.c_str());
258
bool BlackholeEngine::doDoesTableExist(Session&,
259
const drizzled::TableIdentifier &identifier)
261
string proto_path(identifier.getPath());
262
proto_path.append(BLACKHOLE_EXT);
264
if (access(proto_path.c_str(), F_OK))
273
int BlackholeEngine::doGetTableDefinition(Session&,
274
const drizzled::TableIdentifier &identifier,
275
drizzled::message::Table &table_proto)
279
new_path= identifier.getPath();
280
new_path+= BLACKHOLE_EXT;
282
int fd= open(new_path.c_str(), O_RDONLY);
289
google::protobuf::io::ZeroCopyInputStream* input=
290
new google::protobuf::io::FileInputStream(fd);
293
return HA_ERR_CRASHED_ON_USAGE;
295
if (not table_proto.ParseFromZeroCopyStream(input))
299
if (not table_proto.IsInitialized())
301
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
302
table_proto.InitializationErrorString().c_str());
303
return ER_CORRUPT_TABLE_DEFINITION;
306
return HA_ERR_CRASHED_ON_USAGE;
314
const char *ha_blackhole::index_type(uint32_t)
93
int ha_blackhole::write_row(unsigned char * buf __attribute__((unused)))
319
int ha_blackhole::doInsertRecord(unsigned char *)
95
return(table->next_number_field ? update_auto_increment() : 0);
321
return(getTable()->next_number_field ? update_auto_increment() : 0);
98
int ha_blackhole::rnd_init(bool scan __attribute__((unused)))
324
int ha_blackhole::doStartTableScan(bool)
104
int ha_blackhole::rnd_next(unsigned char *buf __attribute__((unused)))
330
int ha_blackhole::rnd_next(unsigned char *)
106
332
return(HA_ERR_END_OF_FILE);
110
int ha_blackhole::rnd_pos(unsigned char * buf __attribute__((unused)),
111
unsigned char *pos __attribute__((unused)))
336
int ha_blackhole::rnd_pos(unsigned char *, unsigned char *)
118
void ha_blackhole::position(const unsigned char *record __attribute__((unused)))
343
void ha_blackhole::position(const unsigned char *)
133
int ha_blackhole::external_lock(Session *session __attribute__((unused)),
134
int lock_type __attribute__((unused)))
140
THR_LOCK_DATA **ha_blackhole::store_lock(Session *session,
142
enum thr_lock_type lock_type)
144
if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK)
147
Here is where we get into the guts of a row level lock.
149
If we are not doing a LOCK Table or DISCARD/IMPORT
150
TABLESPACE, then allow multiple writers
153
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT &&
154
lock_type <= TL_WRITE) && !session_in_lock_tables(session)
155
&& !session_tablespace_op(session))
156
lock_type = TL_WRITE_ALLOW_WRITE;
159
In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
160
MySQL would use the lock TL_READ_NO_INSERT on t2, and that
161
would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
162
to t2. Convert the lock to a normal read lock to allow
163
concurrent inserts to t2.
166
if (lock_type == TL_READ_NO_INSERT && !session_in_lock_tables(session))
169
lock.type= lock_type;
176
int ha_blackhole::index_read_map(unsigned char * buf __attribute__((unused)),
177
const unsigned char * key __attribute__((unused)),
178
key_part_map keypart_map __attribute__((unused)),
179
enum ha_rkey_function find_flag __attribute__((unused)))
181
return(HA_ERR_END_OF_FILE);
185
int ha_blackhole::index_read_idx_map(unsigned char * buf __attribute__((unused)),
186
uint32_t idx __attribute__((unused)),
187
const unsigned char * key __attribute__((unused)),
188
key_part_map keypart_map __attribute__((unused)),
189
enum ha_rkey_function find_flag __attribute__((unused)))
191
return(HA_ERR_END_OF_FILE);
195
int ha_blackhole::index_read_last_map(unsigned char * buf __attribute__((unused)),
196
const unsigned char * key __attribute__((unused)),
197
key_part_map keypart_map __attribute__((unused)))
199
return(HA_ERR_END_OF_FILE);
203
int ha_blackhole::index_next(unsigned char * buf __attribute__((unused)))
205
return(HA_ERR_END_OF_FILE);
209
int ha_blackhole::index_prev(unsigned char * buf __attribute__((unused)))
211
return(HA_ERR_END_OF_FILE);
215
int ha_blackhole::index_first(unsigned char * buf __attribute__((unused)))
217
return(HA_ERR_END_OF_FILE);
221
int ha_blackhole::index_last(unsigned char * buf __attribute__((unused)))
223
return(HA_ERR_END_OF_FILE);
227
static st_blackhole_share *get_share(const char *table_name)
229
st_blackhole_share *share;
232
length= (uint) strlen(table_name);
359
int ha_blackhole::index_read_map(unsigned char *, const unsigned char *,
360
key_part_map, enum ha_rkey_function)
362
return(HA_ERR_END_OF_FILE);
366
int ha_blackhole::index_read_idx_map(unsigned char *, uint32_t, const unsigned char *,
367
key_part_map, enum ha_rkey_function)
369
return(HA_ERR_END_OF_FILE);
373
int ha_blackhole::index_read_last_map(unsigned char *, const unsigned char *, key_part_map)
375
return(HA_ERR_END_OF_FILE);
379
int ha_blackhole::index_next(unsigned char *)
381
return(HA_ERR_END_OF_FILE);
385
int ha_blackhole::index_prev(unsigned char *)
387
return(HA_ERR_END_OF_FILE);
391
int ha_blackhole::index_first(unsigned char *)
393
return(HA_ERR_END_OF_FILE);
397
int ha_blackhole::index_last(unsigned char *)
399
return(HA_ERR_END_OF_FILE);
403
BlackholeShare *ha_blackhole::get_share(const char *table_name)
233
405
pthread_mutex_lock(&blackhole_mutex);
235
if (!(share= (st_blackhole_share*) hash_search(&blackhole_open_tables,
236
(unsigned char*) table_name, length)))
407
BlackholeEngine *a_engine= static_cast<BlackholeEngine *>(getEngine());
408
share= a_engine->findOpenTable(table_name);
238
if (!(share= (st_blackhole_share*) my_malloc(sizeof(st_blackhole_share) +
240
MYF(MY_WME | MY_ZEROFILL))))
243
share->table_name_length= length;
244
my_stpcpy(share->table_name, table_name);
246
if (my_hash_insert(&blackhole_open_tables, (unsigned char*) share))
412
share= new (nothrow) BlackholeShare(table_name);
248
free((unsigned char*) share);
415
pthread_mutex_unlock(&blackhole_mutex);
253
thr_lock_init(&share->lock);
419
a_engine->addOpenTable(share->table_name, share);
255
421
share->use_count++;
258
422
pthread_mutex_unlock(&blackhole_mutex);
262
static void free_share(st_blackhole_share *share)
427
void ha_blackhole::free_share()
264
429
pthread_mutex_lock(&blackhole_mutex);
265
430
if (!--share->use_count)
266
hash_delete(&blackhole_open_tables, (unsigned char*) share);
432
BlackholeEngine *a_engine= static_cast<BlackholeEngine *>(getEngine());
433
a_engine->deleteOpenTable(share->table_name);
267
436
pthread_mutex_unlock(&blackhole_mutex);
270
static void blackhole_free_key(st_blackhole_share *share)
272
thr_lock_delete(&share->lock);
273
free((unsigned char*) share);
276
static unsigned char* blackhole_get_key(st_blackhole_share *share, size_t *length,
277
bool not_used __attribute__((unused)))
279
*length= share->table_name_length;
280
return (unsigned char*) share->table_name;
283
static int blackhole_init(void *p)
285
handlerton *blackhole_hton;
286
blackhole_hton= (handlerton *)p;
287
blackhole_hton->state= SHOW_OPTION_YES;
288
blackhole_hton->create= blackhole_create_handler;
289
blackhole_hton->flags= HTON_CAN_RECREATE;
439
BlackholeShare::BlackholeShare(const string table_name_arg)
440
: use_count(0), table_name(table_name_arg)
442
thr_lock_init(&lock);
445
BlackholeShare::~BlackholeShare()
451
static drizzled::plugin::StorageEngine *blackhole_engine= NULL;
453
static int blackhole_init(drizzled::module::Context &context)
456
blackhole_engine= new BlackholeEngine("BLACKHOLE");
457
context.add(blackhole_engine);
291
459
pthread_mutex_init(&blackhole_mutex, MY_MUTEX_INIT_FAST);
292
(void) hash_init(&blackhole_open_tables, system_charset_info,32,0,0,
293
(hash_get_key) blackhole_get_key,
294
(hash_free_key) blackhole_free_key, 0);
299
static int blackhole_fini(void *p __attribute__((unused)))
301
hash_free(&blackhole_open_tables);
302
pthread_mutex_destroy(&blackhole_mutex);
307
mysql_declare_plugin(blackhole)
309
DRIZZLE_STORAGE_ENGINE_PLUGIN,
465
DRIZZLE_DECLARE_PLUGIN
313
471
"/dev/null storage engine (anything you write to it disappears)",
314
472
PLUGIN_LICENSE_GPL,
315
blackhole_init, /* Plugin Init */
316
blackhole_fini, /* Plugin Deinit */
317
NULL, /* status variables */
318
NULL, /* system variables */
319
NULL /* config options */
473
blackhole_init, /* Plugin Init */
474
NULL, /* system variables */
475
NULL /* config options */
321
mysql_declare_plugin_end;
477
DRIZZLE_DECLARE_PLUGIN_END;