13
12
You should have received a copy of the GNU General Public License
14
13
along with this program; if not, write to the Free Software
15
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
20
#include "plugin/archive/archive_engine.h"
22
#include <boost/scoped_ptr.hpp>
25
using namespace drizzled;
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
#include <drizzled/server_includes.h>
18
#include <drizzled/field.h>
19
#include <drizzled/field/blob.h>
20
#include <drizzled/field/timestamp.h>
21
#include <storage/myisam/myisam.h>
22
#include <drizzled/table.h>
23
#include <drizzled/session.h>
26
#include <storage/archive/ha_archive.h>
29
29
First, if you want to understand storage engines you should look at
96
/* When the engine starts up set the first version */
97
static uint64_t global_version= 1;
99
// We use this to find out the state of the archive aio option.
100
extern bool archive_aio_state(void);
96
/* Variables for archive share methods */
97
pthread_mutex_t archive_mutex;
98
static HASH archive_open_tables;
99
static unsigned int global_version;
101
/* The file extension */
102
#define ARZ ".ARZ" // The data file
103
#define ARN ".ARN" // Files used during an optimize call
106
/* Static declarations for handerton */
107
static handler *archive_create_handler(handlerton *hton,
111
static bool archive_use_aio= false;
103
114
Number of rows that will force a bulk insert.
110
121
#define ARCHIVE_ROW_HEADER_SIZE 4
112
ArchiveShare *ArchiveEngine::findOpenTable(const string table_name)
114
ArchiveMap::iterator find_iter=
115
archive_open_tables.find(table_name);
117
if (find_iter != archive_open_tables.end())
118
return (*find_iter).second;
123
void ArchiveEngine::addOpenTable(const string &table_name, ArchiveShare *share)
125
archive_open_tables[table_name]= share;
128
void ArchiveEngine::deleteOpenTable(const string &table_name)
130
archive_open_tables.erase(table_name);
134
int ArchiveEngine::doDropTable(Session&, const TableIdentifier &identifier)
136
string new_path(identifier.getPath());
140
int error= unlink(new_path.c_str());
150
int ArchiveEngine::doGetTableDefinition(Session&,
151
const TableIdentifier &identifier,
152
drizzled::message::Table &table_proto)
154
struct stat stat_info;
158
proto_path.reserve(FN_REFLEN);
159
proto_path.assign(identifier.getPath());
161
proto_path.append(ARZ);
163
if (stat(proto_path.c_str(),&stat_info))
169
boost::scoped_ptr<azio_stream> proto_stream(new azio_stream);
171
if (azopen(proto_stream.get(), proto_path.c_str(), O_RDONLY, AZ_METHOD_BLOCK) == 0)
172
return HA_ERR_CRASHED_ON_USAGE;
174
proto_string= (char*)malloc(sizeof(char) * proto_stream->frm_length);
175
if (proto_string == NULL)
177
azclose(proto_stream.get());
181
azread_frm(proto_stream.get(), proto_string);
183
if (table_proto.ParseFromArray(proto_string, proto_stream->frm_length) == false)
184
error= HA_ERR_CRASHED_ON_USAGE;
186
azclose(proto_stream.get());
190
/* We set the name from what we've asked for as in RENAME TABLE for ARCHIVE
191
we do not rewrite the table proto (as it's wedged in the file header)
193
table_proto.set_schema(identifier.getSchemaName());
194
table_proto.set_name(identifier.getTableName());
200
ha_archive::ha_archive(drizzled::plugin::StorageEngine &engine_arg,
202
:Cursor(engine_arg, table_arg), delayed_insert(0), bulk_insert(0)
123
static handler *archive_create_handler(handlerton *hton,
127
return new (mem_root) ha_archive(hton, table);
131
Used for hash table that tracks open tables.
133
static unsigned char* archive_get_key(ARCHIVE_SHARE *share, size_t *length, bool)
135
*length=share->table_name_length;
136
return (unsigned char*) share->table_name;
141
Initialize the archive handler.
152
int archive_db_init(void *p)
154
handlerton *archive_hton;
156
archive_hton= (handlerton *)p;
157
archive_hton->state= SHOW_OPTION_YES;
158
archive_hton->create= archive_create_handler;
159
archive_hton->flags= HTON_NO_FLAGS;
161
/* When the engine starts up set the first version */
164
if (pthread_mutex_init(&archive_mutex, MY_MUTEX_INIT_FAST))
166
if (hash_init(&archive_open_tables, system_charset_info, 32, 0, 0,
167
(hash_get_key) archive_get_key, 0, 0))
169
pthread_mutex_destroy(&archive_mutex);
180
Release the archive handler.
190
int archive_db_done(void *)
192
hash_free(&archive_open_tables);
193
pthread_mutex_destroy(&archive_mutex);
199
ha_archive::ha_archive(handlerton *hton, TABLE_SHARE *table_arg)
200
:handler(hton, table_arg), delayed_insert(0), bulk_insert(0)
204
202
/* Set our original buffer from pre-allocated memory */
205
203
buffer.set((char *)byte_buffer, IO_SIZE, system_charset_info);
207
205
/* The size of the offset value we will use for position() */
208
ref_length= sizeof(internal::my_off_t);
206
ref_length= sizeof(my_off_t);
209
207
archive_reader_open= false;
226
ArchiveShare::ArchiveShare():
227
use_count(0), archive_write_open(false), dirty(false), crashed(false),
228
mean_rec_length(0), version(0), rows_recorded(0), version_rows(0)
233
ArchiveShare::ArchiveShare(const char *name):
234
use_count(0), archive_write_open(false), dirty(false), crashed(false),
235
mean_rec_length(0), version(0), rows_recorded(0), version_rows(0)
237
memset(&archive_write, 0, sizeof(azio_stream)); /* Archive file we are working with */
238
table_name.append(name);
239
data_file_name.assign(table_name);
240
data_file_name.append(ARZ);
242
We will use this lock for rows.
244
pthread_mutex_init(&_mutex,MY_MUTEX_INIT_FAST);
247
ArchiveShare::~ArchiveShare()
250
pthread_mutex_destroy(&_mutex);
252
We need to make sure we don't reset the crashed state.
253
If we open a crashed file, wee need to close it as crashed unless
254
it has been repaired.
255
Since we will close the data down after this, we go on and count
258
if (archive_write_open == true)
259
(void)azclose(&archive_write);
262
bool ArchiveShare::prime(uint64_t *auto_increment)
264
boost::scoped_ptr<azio_stream> archive_tmp(new azio_stream);
267
We read the meta file, but do not mark it dirty. Since we are not
268
doing a write we won't mark it dirty (and we won't open it for
269
anything but reading... open it for write and we will generate null
272
if (!(azopen(archive_tmp.get(), data_file_name.c_str(), O_RDONLY,
276
*auto_increment= archive_tmp->auto_increment + 1;
277
rows_recorded= (ha_rows)archive_tmp->rows;
278
crashed= archive_tmp->dirty;
279
if (version < global_version)
281
version_rows= rows_recorded;
282
version= global_version;
284
azclose(archive_tmp.get());
291
226
We create the shared memory space that we will use for the open table.
295
230
See ha_example.cc for a longer description.
297
ArchiveShare *ha_archive::get_share(const char *table_name, int *rc)
232
ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, int *rc)
299
ArchiveEngine *a_engine= static_cast<ArchiveEngine *>(getEngine());
301
pthread_mutex_lock(&a_engine->mutex());
303
share= a_engine->findOpenTable(table_name);
236
pthread_mutex_lock(&archive_mutex);
237
length=(uint) strlen(table_name);
239
if (!(share=(ARCHIVE_SHARE*) hash_search(&archive_open_tables,
240
(unsigned char*) table_name,
307
share= new ArchiveShare(table_name);
244
azio_stream archive_tmp;
246
if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
247
&share, sizeof(*share),
311
pthread_mutex_unlock(&a_engine->mutex());
251
pthread_mutex_unlock(&archive_mutex);
312
252
*rc= HA_ERR_OUT_OF_MEM;
316
if (share->prime(&stats.auto_increment_value) == false)
257
share->table_name_length= length;
258
share->table_name= tmp_name;
259
share->crashed= false;
260
share->archive_write_open= false;
261
fn_format(share->data_file_name, table_name, "",
262
ARZ, MY_REPLACE_EXT | MY_UNPACK_FILENAME);
263
strcpy(share->table_name, table_name);
265
We will use this lock for rows.
267
pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST);
270
We read the meta file, but do not mark it dirty. Since we are not
271
doing a write we won't mark it dirty (and we won't open it for
272
anything but reading... open it for write and we will generate null
275
if (!(azopen(&archive_tmp, share->data_file_name, O_RDONLY,
318
pthread_mutex_unlock(&a_engine->mutex());
278
pthread_mutex_destroy(&share->mutex);
280
pthread_mutex_unlock(&archive_mutex);
319
281
*rc= HA_ERR_CRASHED_ON_REPAIR;
325
a_engine->addOpenTable(share->table_name, share);
326
thr_lock_init(&share->_lock);
284
stats.auto_increment_value= archive_tmp.auto_increment + 1;
285
share->rows_recorded= (ha_rows)archive_tmp.rows;
286
share->crashed= archive_tmp.dirty;
287
if (share->version < global_version)
289
share->version_rows= share->rows_recorded;
290
share->version= global_version;
292
azclose(&archive_tmp);
294
my_hash_insert(&archive_open_tables, (unsigned char*) share);
295
thr_lock_init(&share->lock);
328
297
share->use_count++;
330
298
if (share->crashed)
331
299
*rc= HA_ERR_CRASHED_ON_USAGE;
332
pthread_mutex_unlock(&a_engine->mutex());
300
pthread_mutex_unlock(&archive_mutex);
342
310
int ha_archive::free_share()
344
ArchiveEngine *a_engine= static_cast<ArchiveEngine *>(getEngine());
346
pthread_mutex_lock(&a_engine->mutex());
314
pthread_mutex_lock(&archive_mutex);
347
315
if (!--share->use_count)
349
a_engine->deleteOpenTable(share->table_name);
317
hash_delete(&archive_open_tables, (unsigned char*) share);
318
thr_lock_delete(&share->lock);
319
pthread_mutex_destroy(&share->mutex);
321
We need to make sure we don't reset the crashed state.
322
If we open a crashed file, wee need to close it as crashed unless
323
it has been repaired.
324
Since we will close the data down after this, we go on and count
327
if (share->archive_write_open == true)
329
if (azclose(&(share->archive_write)))
332
free((unsigned char*) share);
352
pthread_mutex_unlock(&a_engine->mutex());
334
pthread_mutex_unlock(&archive_mutex);
357
339
int ha_archive::init_archive_writer()
397
We just implement one additional file extension.
399
static const char *ha_archive_exts[] = {
404
const char **ha_archive::bas_ext() const
406
return ha_archive_exts;
411
411
When opening a file we:
412
412
Create/get our shared structure.
414
414
We open the file we will read from.
416
int ha_archive::doOpen(const TableIdentifier &identifier, int , uint32_t )
416
int ha_archive::open(const char *name, int, uint32_t open_options)
419
share= get_share(identifier.getPath().c_str(), &rc);
422
We either fix it ourselves, or we just take it offline
424
@todo Create some documentation in the recovery tools shipped with the engine.
426
if (rc == HA_ERR_CRASHED_ON_USAGE)
419
share= get_share(name, &rc);
421
if (rc == HA_ERR_CRASHED_ON_USAGE && !(open_options & HA_OPEN_FOR_REPAIR))
423
/* purecov: begin inspected */
433
428
else if (rc == HA_ERR_OUT_OF_MEM)
500
int ArchiveEngine::doCreateTable(Session &,
502
const drizzled::TableIdentifier &identifier,
503
drizzled::message::Table& proto)
500
int ha_archive::create(const char *name, Table *table_arg,
501
HA_CREATE_INFO *create_info)
503
char name_buff[FN_REFLEN];
504
char linkname[FN_REFLEN];
506
boost::scoped_ptr<azio_stream> create_stream(new azio_stream);
507
uint64_t auto_increment_value;
508
string serialized_proto;
510
auto_increment_value= proto.options().auto_increment_value();
512
for (uint32_t key= 0; key < table_arg.sizeKeys(); key++)
506
azio_stream create_stream; /* Archive file we are working with */
507
FILE *frm_file; /* File handler for readers */
508
struct stat file_stat;
509
unsigned char *frm_ptr;
512
stats.auto_increment_value= create_info->auto_increment_value;
514
for (uint32_t key= 0; key < table_arg->sizeKeys(); key++)
514
KeyInfo *pos= &table_arg.key_info[key];
515
KeyPartInfo *key_part= pos->key_part;
516
KeyPartInfo *key_part_end= key_part + pos->key_parts;
516
KEY *pos= table_arg->key_info+key;
517
KEY_PART_INFO *key_part= pos->key_part;
518
KEY_PART_INFO *key_part_end= key_part + pos->key_parts;
518
520
for (; key_part != key_part_end; key_part++)
522
524
if (!(field->flags & AUTO_INCREMENT_FLAG))
529
std::string named_file= identifier.getPath();
530
named_file.append(ARZ);
533
if (azopen(create_stream.get(), named_file.c_str(), O_CREAT|O_RDWR,
534
AZ_METHOD_BLOCK) == 0)
533
We reuse name_buff since it is available.
535
if (create_info->data_file_name && create_info->data_file_name[0] != '#')
537
fn_format(name_buff, create_info->data_file_name, "", ARZ,
538
MY_REPLACE_EXT | MY_UNPACK_FILENAME);
539
fn_format(linkname, name, "", ARZ,
540
MY_REPLACE_EXT | MY_UNPACK_FILENAME);
544
fn_format(name_buff, name, "", ARZ,
545
MY_REPLACE_EXT | MY_UNPACK_FILENAME);
550
There is a chance that the file was "discovered". In this case
551
just use whatever file is there.
553
r= stat(name_buff, &file_stat);
554
if (r == -1 && errno!=ENOENT)
559
return HA_ERR_TABLE_EXIST;
562
if (!(azopen(&create_stream, name_buff, O_CREAT|O_RDWR,
537
unlink(named_file.c_str());
539
return(error ? error : -1);
543
proto.SerializeToString(&serialized_proto);
547
unlink(named_file.c_str());
549
return(error ? error : -1);
552
if (azwrite_frm(create_stream.get(), serialized_proto.c_str(),
553
serialized_proto.length()))
555
unlink(named_file.c_str());
557
return(error ? error : -1);
560
if (proto.options().has_comment())
564
write_length= azwrite_comment(create_stream.get(),
565
proto.options().comment().c_str(),
566
proto.options().comment().length());
568
if (write_length < 0)
570
my_symlink(name_buff, linkname, MYF(0));
571
fn_format(name_buff, name, "", ".frm",
572
MY_REPLACE_EXT | MY_UNPACK_FILENAME);
575
Here is where we open up the frm and pass it to archive to store
577
if ((frm_file= fopen(name_buff, "r")) > 0)
579
if (fstat(fileno(frm_file), &file_stat))
571
unlink(named_file.c_str());
573
return(error ? error : -1);
581
if ((uint64_t)file_stat.st_size > SIZE_MAX)
586
frm_ptr= (unsigned char *)malloc((size_t)file_stat.st_size);
590
length_io= read(fileno(frm_file), frm_ptr, (size_t)file_stat.st_size);
592
if (length_io != (size_t)file_stat.st_size)
598
length_io= azwrite_frm(&create_stream, (char *)frm_ptr, (size_t)file_stat.st_size);
600
if (length_io != (size_t)file_stat.st_size)
612
if (create_info->comment.str)
616
write_length= azwrite_comment(&create_stream, create_info->comment.str,
617
(unsigned int)create_info->comment.length);
619
if (write_length == (size_t)create_info->comment.length)
578
624
Yes you need to do this, because the starting value
579
625
for the autoincrement may not be zero.
581
create_stream->auto_increment= auto_increment_value ?
582
auto_increment_value - 1 : 0;
584
if (azclose(create_stream.get()))
627
create_stream.auto_increment= stats.auto_increment_value ?
628
stats.auto_increment_value - 1 : 0;
629
if (azclose(&create_stream))
587
unlink(named_file.c_str());
589
return(error ? error : -1);
640
/* Return error number, if we got one */
641
return(error ? error : -1);
643
692
unsigned char *ptr;
645
694
if (fix_rec_buff(max_row_length(record)))
646
return(HA_ERR_OUT_OF_MEM);
695
return(HA_ERR_OUT_OF_MEM); /* purecov: inspected */
648
697
/* Copy null bits */
649
memcpy(&record_buffer[0], record, getTable()->getShare()->null_bytes);
650
ptr= &record_buffer[0] + getTable()->getShare()->null_bytes;
698
memcpy(record_buffer->buffer, record, table->s->null_bytes);
699
ptr= record_buffer->buffer + table->s->null_bytes;
652
for (Field **field=getTable()->getFields() ; *field ; field++)
701
for (Field **field=table->field ; *field ; field++)
654
703
if (!((*field)->is_null()))
655
704
ptr= (*field)->pack(ptr, record + (*field)->offset(record));
658
return((unsigned int) (ptr - &record_buffer[0]));
707
return((unsigned int) (ptr - record_buffer->buffer));
668
717
for implementing start_bulk_insert() is that we could skip
669
718
setting dirty to true each time.
671
int ha_archive::doInsertRecord(unsigned char *buf)
720
int ha_archive::write_row(unsigned char *buf)
674
723
unsigned char *read_buf= NULL;
675
724
uint64_t temp_auto;
676
unsigned char *record= getTable()->getInsertRecord();
725
unsigned char *record= table->record[0];
678
727
if (share->crashed)
679
728
return(HA_ERR_CRASHED_ON_USAGE);
681
pthread_mutex_lock(&share->mutex());
730
ha_statistic_increment(&SSV::ha_write_count);
731
pthread_mutex_lock(&share->mutex);
683
733
if (share->archive_write_open == false)
684
734
if (init_archive_writer())
685
735
return(HA_ERR_CRASHED_ON_USAGE);
688
if (getTable()->next_number_field && record == getTable()->getInsertRecord())
738
if (table->next_number_field && record == table->record[0])
740
KEY *mkey= &table->s->key_info[0]; // We only support one key right now
690
741
update_auto_increment();
691
temp_auto= getTable()->next_number_field->val_int();
742
temp_auto= table->next_number_field->val_int();
694
745
We don't support decremening auto_increment. They make the performance
697
748
if (temp_auto <= share->archive_write.auto_increment &&
698
getTable()->getShare()->getKeyInfo(0).flags & HA_NOSAME)
749
mkey->flags & HA_NOSAME)
700
751
rc= HA_ERR_FOUND_DUPP_KEY;
756
Bad news, this will cause a search for the unique value which is very
757
expensive since we will have to do a table scan which will lock up
758
all other writers during this period. This could perhaps be optimized
763
First we create a buffer that we can use for reading rows, and can pass
766
if (!(read_buf= (unsigned char*) malloc(table->s->reclength)))
768
rc= HA_ERR_OUT_OF_MEM;
772
All of the buffer must be written out or we won't see all of the
775
azflush(&(share->archive_write), Z_SYNC_FLUSH);
777
Set the position of the local read thread to the beginning postion.
779
if (read_data_header(&archive))
781
rc= HA_ERR_CRASHED_ON_USAGE;
785
Field *mfield= table->next_number_field;
787
while (!(get_row(&archive, read_buf)))
789
if (!memcmp(read_buf + mfield->offset(record),
790
table->next_number_field->ptr,
791
mfield->max_display_length()))
793
rc= HA_ERR_FOUND_DUPP_KEY;
705
801
if (temp_auto > share->archive_write.auto_increment)
743
839
the optimizer that we have unique indexes, we scan
745
841
int ha_archive::index_read(unsigned char *buf, const unsigned char *key,
746
uint32_t key_len, enum ha_rkey_function)
842
uint32_t key_len, enum ha_rkey_function find_flag)
845
rc= index_read_idx(buf, active_index, key, key_len, find_flag);
850
int ha_archive::index_read_idx(unsigned char *buf, uint32_t index, const unsigned char *key,
851
uint32_t key_len, enum ha_rkey_function)
750
current_k_offset= getTable()->getShare()->getKeyInfo(0).key_part->offset;
855
KEY *mkey= &table->s->key_info[index];
856
current_k_offset= mkey->key_part->offset;
751
857
current_key= key;
752
858
current_key_len= key_len;
754
rc= doStartTableScan(true);
889
1006
return(HA_ERR_END_OF_FILE);
892
ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
1009
ha_statistic_increment(&SSV::ha_read_rnd_next_count);
893
1010
current_position= aztell(&archive);
894
1011
rc= get_row(&archive, buf);
896
getTable()->status=rc ? STATUS_NOT_FOUND: 0;
1013
table->status=rc ? STATUS_NOT_FOUND: 0;
903
Thanks to the table bool is_ordered this will be called after
1020
Thanks to the table flag HA_REC_NOT_IN_SEQ this will be called after
904
1021
each call to ha_archive::rnd_next() if an ordering of the rows is
908
1025
void ha_archive::position(const unsigned char *)
910
internal::my_store_ptr(ref, ref_length, current_position);
1027
my_store_ptr(ref, ref_length, current_position);
962
1081
share->archive_write_open= false;
966
proto_string= (char*)malloc(sizeof(char) * archive.frm_length);
967
if (proto_string == NULL)
971
azread_frm(&archive, proto_string);
973
1084
/* Lets create a file to contain the new data */
974
std::string writer_filename= share->table_name;
975
writer_filename.append(ARN);
1085
fn_format(writer_filename, share->table_name, "", ARN,
1086
MY_REPLACE_EXT | MY_UNPACK_FILENAME);
977
if (!(azopen(writer.get(), writer_filename.c_str(), O_CREAT|O_RDWR, AZ_METHOD_BLOCK)))
1088
if (!(azopen(&writer, writer_filename, O_CREAT|O_RDWR, AZ_METHOD_BLOCK)))
980
1089
return(HA_ERR_CRASHED_ON_USAGE);
983
azwrite_frm(writer.get(), proto_string, archive.frm_length);
986
1092
An extended rebuild is a lot more effort. We open up each row and re-record it.
1012
1119
rows_restored= archive.rows;
1014
for (uint64_t x= 0; x < rows_restored ; x++)
1121
for (x= 0; x < rows_restored ; x++)
1016
rc= get_row(&archive, getTable()->getInsertRecord());
1123
rc= get_row(&archive, table->record[0]);
1021
real_write_row(getTable()->getInsertRecord(), writer.get());
1128
real_write_row(table->record[0], &writer);
1023
1130
Long term it should be possible to optimize this so that
1024
1131
it is not called on each row.
1026
if (getTable()->found_next_number_field)
1133
if (table->found_next_number_field)
1028
Field *field= getTable()->found_next_number_field;
1030
/* Since we will need to use field to translate, we need to flip its read bit */
1031
field->setReadSet();
1135
Field *field= table->found_next_number_field;
1033
1136
uint64_t auto_value=
1034
(uint64_t) field->val_int_internal(getTable()->getInsertRecord() +
1035
field->offset(getTable()->getInsertRecord()));
1137
(uint64_t) field->val_int(table->record[0] +
1138
field->offset(table->record[0]));
1036
1139
if (share->archive_write.auto_increment < auto_value)
1037
1140
stats.auto_increment_value=
1038
1141
(share->archive_write.auto_increment= auto_value) + 1;
1041
share->rows_recorded= (ha_rows)writer->rows;
1144
share->rows_recorded= (ha_rows)writer.rows;
1044
1147
if (rc && rc != HA_ERR_END_OF_FILE)
1327
We just return state if asked.
1329
bool ha_archive::is_crashed() const
1331
return(share->crashed);
1207
1335
Simple scan of the tables to make sure everything is ok.
1210
int ha_archive::check(Session* session)
1338
int ha_archive::check(Session* session, HA_CHECK_OPT *)
1213
1341
const char *old_proc_info;
1215
1344
old_proc_info= get_session_proc_info(session);
1216
1345
set_session_proc_info(session, "Checking table");
1217
1346
/* Flush any waiting data */
1218
pthread_mutex_lock(&share->mutex());
1347
pthread_mutex_lock(&share->mutex);
1219
1348
azflush(&(share->archive_write), Z_SYNC_FLUSH);
1220
pthread_mutex_unlock(&share->mutex());
1349
pthread_mutex_unlock(&share->mutex);
1223
1352
Now we will rewind the archive file so that we are positioned at the
1250
int ArchiveEngine::doRenameTable(Session&, const TableIdentifier &from, const TableIdentifier &to)
1254
for (const char **ext= bas_ext(); *ext ; ext++)
1256
if (rename_file_ext(from.getPath().c_str(), to.getPath().c_str(), *ext))
1258
if ((error=errno) != ENOENT)
1267
bool ArchiveEngine::doDoesTableExist(Session&,
1268
const TableIdentifier &identifier)
1270
string proto_path(identifier.getPath());
1271
proto_path.append(ARZ);
1273
if (access(proto_path.c_str(), F_OK))
1281
void ArchiveEngine::doGetTableIdentifiers(drizzled::CachedDirectory &directory,
1282
const drizzled::SchemaIdentifier &schema_identifier,
1283
drizzled::TableIdentifier::vector &set_of_identifiers)
1285
drizzled::CachedDirectory::Entries entries= directory.getEntries();
1287
for (drizzled::CachedDirectory::Entries::iterator entry_iter= entries.begin();
1288
entry_iter != entries.end(); ++entry_iter)
1290
drizzled::CachedDirectory::Entry *entry= *entry_iter;
1291
const string *filename= &entry->filename;
1293
assert(filename->size());
1295
const char *ext= strchr(filename->c_str(), '.');
1297
if (ext == NULL || my_strcasecmp(system_charset_info, ext, ARZ) ||
1298
(filename->compare(0, strlen(TMP_FILE_PREFIX), TMP_FILE_PREFIX) == 0))
1302
char uname[NAME_LEN + 1];
1303
uint32_t file_name_len;
1305
file_name_len= TableIdentifier::filename_to_tablename(filename->c_str(), uname, sizeof(uname));
1306
// TODO: Remove need for memory copy here
1307
uname[file_name_len - sizeof(ARZ) + 1]= '\0'; // Subtract ending, place NULL
1309
set_of_identifiers.push_back(TableIdentifier(schema_identifier, uname));
1380
Check and repair the table if needed.
1382
bool ha_archive::check_and_repair(Session *session)
1384
HA_CHECK_OPT check_opt;
1388
return(repair(session, &check_opt));
1391
archive_record_buffer *ha_archive::create_record_buffer(unsigned int length)
1393
archive_record_buffer *r;
1394
if (!(r= (archive_record_buffer*) malloc(sizeof(archive_record_buffer))))
1396
return(NULL); /* purecov: inspected */
1398
r->length= (int)length;
1400
if (!(r->buffer= (unsigned char*) malloc(r->length)))
1403
return(NULL); /* purecov: inspected */
1409
void ha_archive::destroy_record_buffer(archive_record_buffer *r)
1411
free((char*) r->buffer);
1416
static DRIZZLE_SYSVAR_BOOL(aio, archive_use_aio,
1417
PLUGIN_VAR_NOCMDOPT,
1418
"Whether or not to use asynchronous IO.",
1421
static struct st_mysql_sys_var* archive_system_variables[]= {
1422
DRIZZLE_SYSVAR(aio),
1426
drizzle_declare_plugin(archive)
1428
DRIZZLE_STORAGE_ENGINE_PLUGIN,
1431
"Brian Aker, MySQL AB",
1432
"Archive storage engine",
1434
archive_db_init, /* Plugin Init */
1435
archive_db_done, /* Plugin Deinit */
1436
NULL, /* status variables */
1437
archive_system_variables, /* system variables */
1438
NULL /* config options */
1440
drizzle_declare_plugin_end;