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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
17
#include <drizzled/table.h>
18
#include <drizzled/error.h>
19
#include "drizzled/internal/my_pthread.h"
21
#include "ha_blackhole.h"
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"
41
static pthread_mutex_t blackhole_mutex;
44
static const char *ha_blackhole_exts[] = {
49
class BlackholeEngine : public drizzled::plugin::StorageEngine
51
typedef std::map<std::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::TableIdentifier::vector &set_of_identifiers);
117
void BlackholeEngine::doGetTableIdentifiers(drizzled::CachedDirectory &directory,
118
const drizzled::SchemaIdentifier &schema_identifier,
119
drizzled::TableIdentifier::vector &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);
189
/*****************************************************************************
191
*****************************************************************************/
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)
200
if (!(share= get_share(name)))
201
return(HA_ERR_OUT_OF_MEM);
203
lock.init(&share->lock);
207
int ha_blackhole::close(void)
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)
319
int ha_blackhole::doInsertRecord(unsigned char *)
321
return(getTable()->next_number_field ? update_auto_increment() : 0);
324
int ha_blackhole::doStartTableScan(bool)
330
int ha_blackhole::rnd_next(unsigned char *)
332
return(HA_ERR_END_OF_FILE);
336
int ha_blackhole::rnd_pos(unsigned char *, unsigned char *)
343
void ha_blackhole::position(const unsigned char *)
350
int ha_blackhole::info(uint32_t flag)
352
memset(&stats, 0, sizeof(stats));
353
if (flag & HA_STATUS_AUTO)
354
stats.auto_increment_value= 1;
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)
405
pthread_mutex_lock(&blackhole_mutex);
407
BlackholeEngine *a_engine= static_cast<BlackholeEngine *>(getEngine());
408
share= a_engine->findOpenTable(table_name);
412
share= new (nothrow) BlackholeShare(table_name);
415
pthread_mutex_unlock(&blackhole_mutex);
419
a_engine->addOpenTable(share->table_name, share);
422
pthread_mutex_unlock(&blackhole_mutex);
427
void ha_blackhole::free_share()
429
pthread_mutex_lock(&blackhole_mutex);
430
if (!--share->use_count)
432
BlackholeEngine *a_engine= static_cast<BlackholeEngine *>(getEngine());
433
a_engine->deleteOpenTable(share->table_name);
436
pthread_mutex_unlock(&blackhole_mutex);
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);
459
pthread_mutex_init(&blackhole_mutex, MY_MUTEX_INIT_FAST);
465
DRIZZLE_DECLARE_PLUGIN
471
"/dev/null storage engine (anything you write to it disappears)",
473
blackhole_init, /* Plugin Init */
474
NULL, /* system variables */
475
NULL /* config options */
477
DRIZZLE_DECLARE_PLUGIN_END;