~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/archive/ha_archive.cc

  • Committer: Stewart Smith
  • Date: 2009-10-08 13:49:11 UTC
  • mto: This revision was merged to the branch mainline in revision 1179.
  • Revision ID: stewart@flamingspork.com-20091008134911-72y6d480660udl83
remove unused tree_search() from mysys/my_tree.cc

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* Copyright (C) 2003 MySQL AB
2
 
   Copyright (C) 2010 Brian Aker
3
2
 
4
3
  This program is free software; you can redistribute it and/or modify
5
4
  it under the terms of the GNU General Public License as published by
12
11
 
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 */
16
 
 
17
 
 
18
 
#include "config.h"
19
 
 
20
 
#include "plugin/archive/archive_engine.h"
21
 
#include <memory>
22
 
#include <boost/scoped_ptr.hpp>
 
14
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
15
 
 
16
 
 
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 "plugin/myisam/myisam.h"
 
22
#include "drizzled/table.h"
 
23
#include "drizzled/session.h"
 
24
#include <mysys/my_dir.h>
 
25
 
 
26
#include "ha_archive.h"
 
27
 
 
28
#include <stdio.h>
 
29
#include <string>
 
30
#include <map>
23
31
 
24
32
using namespace std;
25
 
using namespace drizzled;
26
33
 
 
34
static const string engine_name("ARCHIVE");
27
35
 
28
36
/*
29
37
  First, if you want to understand storage engines you should look at
93
101
    -Brian
94
102
*/
95
103
 
96
 
/* When the engine starts up set the first version */
97
 
static uint64_t global_version= 1;
98
 
 
99
 
// We use this to find out the state of the archive aio option.
100
 
extern bool archive_aio_state(void);
 
104
/* Variables for archive share methods */
 
105
pthread_mutex_t archive_mutex= PTHREAD_MUTEX_INITIALIZER;
 
106
 
 
107
std::map<const char *, ArchiveShare *> archive_open_tables;
 
108
 
 
109
static unsigned int global_version;
 
110
 
 
111
/* The file extension */
 
112
#define ARZ ".ARZ"               // The data file
 
113
#define ARN ".ARN"               // Files used during an optimize call
 
114
 
 
115
 
 
116
 
 
117
static bool archive_use_aio= false;
101
118
 
102
119
/*
103
120
  Number of rows that will force a bulk insert.
109
126
*/
110
127
#define ARCHIVE_ROW_HEADER_SIZE 4
111
128
 
112
 
ArchiveShare *ArchiveEngine::findOpenTable(const string table_name)
113
 
{
114
 
  ArchiveMap::iterator find_iter=
115
 
    archive_open_tables.find(table_name);
116
 
 
117
 
  if (find_iter != archive_open_tables.end())
118
 
    return (*find_iter).second;
119
 
  else
120
 
    return NULL;
121
 
}
122
 
 
123
 
void ArchiveEngine::addOpenTable(const string &table_name, ArchiveShare *share)
124
 
{
125
 
  archive_open_tables[table_name]= share;
126
 
}
127
 
 
128
 
void ArchiveEngine::deleteOpenTable(const string &table_name)
129
 
{
130
 
  archive_open_tables.erase(table_name);
131
 
}
132
 
 
133
 
 
134
 
int ArchiveEngine::doDropTable(Session&, const TableIdentifier &identifier)
135
 
{
136
 
  string new_path(identifier.getPath());
137
 
 
138
 
  new_path+= ARZ;
139
 
 
140
 
  int error= unlink(new_path.c_str());
141
 
 
142
 
  if (error != 0)
143
 
  {
144
 
    error= errno= errno;
145
 
  }
146
 
 
147
 
  return error;
148
 
}
149
 
 
150
 
int ArchiveEngine::doGetTableDefinition(Session&,
151
 
                                        const TableIdentifier &identifier,
152
 
                                        drizzled::message::Table &table_proto)
 
129
/*
 
130
  We just implement one additional file extension.
 
131
*/
 
132
static const char *ha_archive_exts[] = {
 
133
  ARZ,
 
134
  NULL
 
135
};
 
136
 
 
137
class ArchiveTableNameIterator: public drizzled::plugin::TableNameIteratorImplementation
 
138
{
 
139
private:
 
140
  MY_DIR *dirp;
 
141
  uint32_t current_entry;
 
142
 
 
143
public:
 
144
  ArchiveTableNameIterator(const std::string &database)
 
145
    : drizzled::plugin::TableNameIteratorImplementation(database), dirp(NULL), current_entry(-1)
 
146
    {};
 
147
 
 
148
  ~ArchiveTableNameIterator();
 
149
 
 
150
  int next(std::string *name);
 
151
 
 
152
};
 
153
 
 
154
ArchiveTableNameIterator::~ArchiveTableNameIterator()
 
155
{
 
156
  if (dirp)
 
157
    my_dirend(dirp);
 
158
}
 
159
 
 
160
int ArchiveTableNameIterator::next(string *name)
 
161
{
 
162
  char uname[NAME_LEN + 1];
 
163
  FILEINFO *file;
 
164
  char *ext;
 
165
  uint32_t file_name_len;
 
166
  const char *wild= NULL;
 
167
 
 
168
  if (dirp == NULL)
 
169
  {
 
170
    bool dir= false;
 
171
    char path[FN_REFLEN];
 
172
 
 
173
    build_table_filename(path, sizeof(path), db.c_str(), "", false);
 
174
    dirp = my_dir(path,MYF(dir ? MY_WANT_STAT : 0));
 
175
    if (dirp == NULL)
 
176
    {
 
177
      if (my_errno == ENOENT)
 
178
        my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), db.c_str());
 
179
      else
 
180
        my_error(ER_CANT_READ_DIR, MYF(ME_BELL+ME_WAITTANG), path, my_errno);
 
181
      return(ENOENT);
 
182
    }
 
183
    current_entry= -1;
 
184
  }
 
185
 
 
186
  while(true)
 
187
  {
 
188
    current_entry++;
 
189
 
 
190
    if (current_entry == dirp->number_off_files)
 
191
    {
 
192
      my_dirend(dirp);
 
193
      dirp= NULL;
 
194
      return -1;
 
195
    }
 
196
 
 
197
    file= dirp->dir_entry + current_entry;
 
198
 
 
199
    if (my_strcasecmp(system_charset_info, ext=strchr(file->name,'.'), ARZ) ||
 
200
        is_prefix(file->name, TMP_FILE_PREFIX))
 
201
      continue;
 
202
    *ext=0;
 
203
 
 
204
    file_name_len= filename_to_tablename(file->name, uname, sizeof(uname));
 
205
 
 
206
    uname[file_name_len]= '\0';
 
207
 
 
208
    if (wild && wild_compare(uname, wild, 0))
 
209
      continue;
 
210
    if (name)
 
211
      name->assign(uname);
 
212
 
 
213
    return 0;
 
214
  }
 
215
}
 
216
 
 
217
class ArchiveEngine : public drizzled::plugin::StorageEngine
 
218
{
 
219
public:
 
220
  ArchiveEngine(const string &name_arg)
 
221
   : drizzled::plugin::StorageEngine(name_arg,
 
222
                                     HTON_FILE_BASED
 
223
                                      | HTON_HAS_DATA_DICTIONARY) {}
 
224
 
 
225
  virtual handler *create(TableShare *table,
 
226
                          MEM_ROOT *mem_root)
 
227
  {
 
228
    return new (mem_root) ha_archive(this, table);
 
229
  }
 
230
 
 
231
  const char **bas_ext() const {
 
232
    return ha_archive_exts;
 
233
  }
 
234
 
 
235
  int createTableImplementation(Session *session, const char *table_name,
 
236
                                Table *table_arg, HA_CREATE_INFO *create_info,
 
237
                                drizzled::message::Table* proto);
 
238
 
 
239
  int getTableProtoImplementation(const char* path,
 
240
                                  drizzled::message::Table *table_proto);
 
241
 
 
242
  drizzled::plugin::TableNameIteratorImplementation* tableNameIterator(const std::string &database)
 
243
  {
 
244
    return new ArchiveTableNameIterator(database);
 
245
  }
 
246
};
 
247
 
 
248
int ArchiveEngine::getTableProtoImplementation(const char* path,
 
249
                                         drizzled::message::Table *table_proto)
153
250
{
154
251
  struct stat stat_info;
155
 
  int error= ENOENT;
 
252
  int error= 0;
156
253
  string proto_path;
157
254
 
158
255
  proto_path.reserve(FN_REFLEN);
159
 
  proto_path.assign(identifier.getPath());
 
256
  proto_path.assign(path);
160
257
 
161
258
  proto_path.append(ARZ);
162
259
 
163
260
  if (stat(proto_path.c_str(),&stat_info))
164
261
    return errno;
165
 
  else
166
 
    error= EEXIST;
167
262
 
 
263
  if (table_proto)
168
264
  {
169
 
    boost::scoped_ptr<azio_stream> proto_stream(new azio_stream);
 
265
    azio_stream proto_stream;
170
266
    char* proto_string;
171
 
    if (azopen(proto_stream.get(), proto_path.c_str(), O_RDONLY, AZ_METHOD_BLOCK) == 0)
 
267
    if(azopen(&proto_stream, proto_path.c_str(), O_RDONLY, AZ_METHOD_BLOCK) == 0)
172
268
      return HA_ERR_CRASHED_ON_USAGE;
173
269
 
174
 
    proto_string= (char*)malloc(sizeof(char) * proto_stream->frm_length);
 
270
    proto_string= (char*)malloc(sizeof(char) * proto_stream.frm_length);
175
271
    if (proto_string == NULL)
176
272
    {
177
 
      azclose(proto_stream.get());
 
273
      azclose(&proto_stream);
178
274
      return ENOMEM;
179
275
    }
180
276
 
181
 
    azread_frm(proto_stream.get(), proto_string);
 
277
    azread_frm(&proto_stream, proto_string);
182
278
 
183
 
    if (table_proto.ParseFromArray(proto_string, proto_stream->frm_length) == false)
 
279
    if(table_proto->ParseFromArray(proto_string, proto_stream.frm_length) == false)
184
280
      error= HA_ERR_CRASHED_ON_USAGE;
185
281
 
186
 
    azclose(proto_stream.get());
 
282
    azclose(&proto_stream);
187
283
    free(proto_string);
188
284
  }
189
285
 
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)
192
 
  */
193
 
  table_proto.set_schema(identifier.getSchemaName());
194
 
  table_proto.set_name(identifier.getTableName());
195
 
 
196
 
  return error;
197
 
}
198
 
 
199
 
 
200
 
ha_archive::ha_archive(drizzled::plugin::StorageEngine &engine_arg,
201
 
                       Table &table_arg)
202
 
  :Cursor(engine_arg, table_arg), delayed_insert(0), bulk_insert(0)
 
286
  return EEXIST;
 
287
}
 
288
 
 
289
static ArchiveEngine *archive_engine= NULL;
 
290
 
 
291
/*
 
292
  Initialize the archive handler.
 
293
 
 
294
  SYNOPSIS
 
295
    archive_db_init()
 
296
    void *
 
297
 
 
298
  RETURN
 
299
    false       OK
 
300
    true        Error
 
301
*/
 
302
 
 
303
static int archive_db_init(drizzled::plugin::Registry &registry)
 
304
{
 
305
 
 
306
  pthread_mutex_init(&archive_mutex, MY_MUTEX_INIT_FAST);
 
307
  archive_engine= new ArchiveEngine(engine_name);
 
308
  registry.add(archive_engine);
 
309
 
 
310
  /* When the engine starts up set the first version */
 
311
  global_version= 1;
 
312
 
 
313
  return false;
 
314
}
 
315
 
 
316
/*
 
317
  Release the archive handler.
 
318
 
 
319
  SYNOPSIS
 
320
    archive_db_done()
 
321
    void
 
322
 
 
323
  RETURN
 
324
    false       OK
 
325
*/
 
326
 
 
327
static int archive_db_done(drizzled::plugin::Registry &registry)
 
328
{
 
329
  registry.remove(archive_engine);
 
330
  delete archive_engine;
 
331
 
 
332
  pthread_mutex_destroy(&archive_mutex);
 
333
 
 
334
  return 0;
 
335
}
 
336
 
 
337
 
 
338
ha_archive::ha_archive(drizzled::plugin::StorageEngine *engine_arg,
 
339
                       TableShare *table_arg)
 
340
  :handler(engine_arg, table_arg), delayed_insert(0), bulk_insert(0)
203
341
{
204
342
  /* Set our original buffer from pre-allocated memory */
205
343
  buffer.set((char *)byte_buffer, IO_SIZE, system_charset_info);
206
344
 
207
345
  /* The size of the offset value we will use for position() */
208
 
  ref_length= sizeof(internal::my_off_t);
 
346
  ref_length= sizeof(my_off_t);
209
347
  archive_reader_open= false;
210
348
}
211
349
 
236
374
{
237
375
  memset(&archive_write, 0, sizeof(azio_stream));     /* Archive file we are working with */
238
376
  table_name.append(name);
239
 
  data_file_name.assign(table_name);
240
 
  data_file_name.append(ARZ);
 
377
  fn_format(data_file_name, table_name.c_str(), "",
 
378
            ARZ, MY_REPLACE_EXT | MY_UNPACK_FILENAME);
241
379
  /*
242
380
    We will use this lock for rows.
243
381
  */
244
 
  pthread_mutex_init(&_mutex,MY_MUTEX_INIT_FAST);
 
382
  pthread_mutex_init(&mutex,MY_MUTEX_INIT_FAST);
245
383
}
246
384
 
247
385
ArchiveShare::~ArchiveShare()
248
386
{
249
 
  _lock.deinit();
250
 
  pthread_mutex_destroy(&_mutex);
 
387
  thr_lock_delete(&lock);
 
388
  pthread_mutex_destroy(&mutex);
251
389
  /*
252
390
    We need to make sure we don't reset the crashed state.
253
391
    If we open a crashed file, wee need to close it as crashed unless
261
399
 
262
400
bool ArchiveShare::prime(uint64_t *auto_increment)
263
401
{
264
 
  boost::scoped_ptr<azio_stream> archive_tmp(new azio_stream);
 
402
  azio_stream archive_tmp;
265
403
 
266
404
  /*
267
405
    We read the meta file, but do not mark it dirty. Since we are not
269
407
    anything but reading... open it for write and we will generate null
270
408
    compression writes).
271
409
  */
272
 
  if (!(azopen(archive_tmp.get(), data_file_name.c_str(), O_RDONLY,
 
410
  if (!(azopen(&archive_tmp, data_file_name, O_RDONLY,
273
411
               AZ_METHOD_BLOCK)))
274
412
    return false;
275
413
 
276
 
  *auto_increment= archive_tmp->auto_increment + 1;
277
 
  rows_recorded= (ha_rows)archive_tmp->rows;
278
 
  crashed= archive_tmp->dirty;
 
414
  *auto_increment= archive_tmp.auto_increment + 1;
 
415
  rows_recorded= (ha_rows)archive_tmp.rows;
 
416
  crashed= archive_tmp.dirty;
279
417
  if (version < global_version)
280
418
  {
281
419
    version_rows= rows_recorded;
282
420
    version= global_version;
283
421
  }
284
 
  azclose(archive_tmp.get());
 
422
  azclose(&archive_tmp);
285
423
 
286
424
  return true;
287
425
}
296
434
*/
297
435
ArchiveShare *ha_archive::get_share(const char *table_name, int *rc)
298
436
{
299
 
  ArchiveEngine *a_engine= static_cast<ArchiveEngine *>(getEngine());
300
 
 
301
 
  pthread_mutex_lock(&a_engine->mutex());
302
 
 
303
 
  share= a_engine->findOpenTable(table_name);
 
437
  uint32_t length;
 
438
  map<const char *, ArchiveShare *> ::iterator find_iter;
 
439
 
 
440
  pthread_mutex_lock(&archive_mutex);
 
441
  length=(uint) strlen(table_name);
 
442
 
 
443
  find_iter= archive_open_tables.find(table_name);
 
444
 
 
445
  if (find_iter != archive_open_tables.end())
 
446
    share= (*find_iter).second;
 
447
  else
 
448
    share= NULL;
304
449
 
305
450
  if (!share)
306
451
  {
308
453
 
309
454
    if (share == NULL)
310
455
    {
311
 
      pthread_mutex_unlock(&a_engine->mutex());
 
456
      pthread_mutex_unlock(&archive_mutex);
312
457
      *rc= HA_ERR_OUT_OF_MEM;
313
458
      return(NULL);
314
459
    }
315
460
 
316
461
    if (share->prime(&stats.auto_increment_value) == false)
317
462
    {
318
 
      pthread_mutex_unlock(&a_engine->mutex());
 
463
      pthread_mutex_unlock(&archive_mutex);
319
464
      *rc= HA_ERR_CRASHED_ON_REPAIR;
320
465
      delete share;
321
466
 
322
467
      return NULL;
323
468
    }
324
469
 
325
 
    a_engine->addOpenTable(share->table_name, share);
326
 
    thr_lock_init(&share->_lock);
 
470
    archive_open_tables[share->table_name.c_str()]= share; 
 
471
    thr_lock_init(&share->lock);
327
472
  }
328
473
  share->use_count++;
329
 
 
330
474
  if (share->crashed)
331
475
    *rc= HA_ERR_CRASHED_ON_USAGE;
332
 
  pthread_mutex_unlock(&a_engine->mutex());
 
476
  pthread_mutex_unlock(&archive_mutex);
333
477
 
334
478
  return(share);
335
479
}
341
485
*/
342
486
int ha_archive::free_share()
343
487
{
344
 
  ArchiveEngine *a_engine= static_cast<ArchiveEngine *>(getEngine());
345
 
 
346
 
  pthread_mutex_lock(&a_engine->mutex());
 
488
  pthread_mutex_lock(&archive_mutex);
347
489
  if (!--share->use_count)
348
490
  {
349
 
    a_engine->deleteOpenTable(share->table_name);
 
491
    archive_open_tables.erase(share->table_name.c_str());
350
492
    delete share;
351
493
  }
352
 
  pthread_mutex_unlock(&a_engine->mutex());
 
494
  pthread_mutex_unlock(&archive_mutex);
353
495
 
354
496
  return 0;
355
497
}
361
503
    a gzip file that can be both read and written we keep a writer open
362
504
    that is shared amoung all open tables.
363
505
  */
364
 
  if (!(azopen(&(share->archive_write), share->data_file_name.c_str(),
 
506
  if (!(azopen(&(share->archive_write), share->data_file_name,
365
507
               O_RDWR, AZ_METHOD_BLOCK)))
366
508
  {
367
509
    share->crashed= true;
374
516
 
375
517
 
376
518
/*
377
 
  No locks are required because it is associated with just one Cursor instance
 
519
  No locks are required because it is associated with just one handler instance
378
520
*/
379
521
int ha_archive::init_archive_reader()
380
522
{
387
529
  {
388
530
    az_method method;
389
531
 
390
 
    if (archive_aio_state())
 
532
    switch (archive_use_aio)
391
533
    {
 
534
    case false:
 
535
      method= AZ_METHOD_BLOCK;
 
536
      break;
 
537
    case true:
392
538
      method= AZ_METHOD_AIO;
393
 
    }
394
 
    else
395
 
    {
 
539
      break;
 
540
    default:
396
541
      method= AZ_METHOD_BLOCK;
397
542
    }
398
 
    if (!(azopen(&archive, share->data_file_name.c_str(), O_RDONLY,
 
543
    if (!(azopen(&archive, share->data_file_name, O_RDONLY,
399
544
                 method)))
400
545
    {
401
546
      share->crashed= true;
413
558
  Init out lock.
414
559
  We open the file we will read from.
415
560
*/
416
 
int ha_archive::doOpen(const TableIdentifier &identifier, int , uint32_t )
 
561
int ha_archive::open(const char *name, int, uint32_t open_options)
417
562
{
418
563
  int rc= 0;
419
 
  share= get_share(identifier.getPath().c_str(), &rc);
420
 
 
421
 
  /** 
422
 
    We either fix it ourselves, or we just take it offline 
423
 
 
424
 
    @todo Create some documentation in the recovery tools shipped with the engine.
425
 
  */
426
 
  if (rc == HA_ERR_CRASHED_ON_USAGE)
 
564
  share= get_share(name, &rc);
 
565
 
 
566
  if (rc == HA_ERR_CRASHED_ON_USAGE && !(open_options & HA_OPEN_FOR_REPAIR))
427
567
  {
428
568
    free_share();
429
 
    rc= repair();
430
 
 
431
 
    return 0;
 
569
    return(rc);
432
570
  }
433
571
  else if (rc == HA_ERR_OUT_OF_MEM)
434
572
  {
437
575
 
438
576
  assert(share);
439
577
 
440
 
  record_buffer.resize(getTable()->getShare()->getRecordLength() + ARCHIVE_ROW_HEADER_SIZE);
441
 
 
442
 
  lock.init(&share->_lock);
443
 
 
444
 
  return(rc);
445
 
}
446
 
 
447
 
// Should never be called
448
 
int ha_archive::open(const char *, int, uint32_t)
449
 
{
450
 
  assert(0);
451
 
  return -1;
 
578
  record_buffer= create_record_buffer(table->s->reclength +
 
579
                                      ARCHIVE_ROW_HEADER_SIZE);
 
580
 
 
581
  if (!record_buffer)
 
582
  {
 
583
    free_share();
 
584
    return(HA_ERR_OUT_OF_MEM);
 
585
  }
 
586
 
 
587
  thr_lock_data_init(&share->lock, &lock, NULL);
 
588
 
 
589
  if (rc == HA_ERR_CRASHED_ON_USAGE && open_options & HA_OPEN_FOR_REPAIR)
 
590
  {
 
591
    return(0);
 
592
  }
 
593
  else
 
594
    return(rc);
452
595
}
453
596
 
454
597
 
473
616
{
474
617
  int rc= 0;
475
618
 
476
 
  record_buffer.clear();
 
619
  destroy_record_buffer(record_buffer);
477
620
 
478
621
  /* First close stream */
479
622
  if (archive_reader_open == true)
497
640
  of creation.
498
641
*/
499
642
 
500
 
int ArchiveEngine::doCreateTable(Session &,
501
 
                                 Table& table_arg,
502
 
                                 const drizzled::TableIdentifier &identifier,
503
 
                                 drizzled::message::Table& proto)
 
643
int ArchiveEngine::createTableImplementation(Session *session,
 
644
                                             const char *table_name,
 
645
                                             Table *table_arg,
 
646
                                             HA_CREATE_INFO *create_info,
 
647
                                             drizzled::message::Table *proto)
504
648
{
 
649
  char name_buff[FN_REFLEN];
505
650
  int error= 0;
506
 
  boost::scoped_ptr<azio_stream> create_stream(new azio_stream);
 
651
  azio_stream create_stream;            /* Archive file we are working with */
507
652
  uint64_t auto_increment_value;
508
653
  string serialized_proto;
509
654
 
510
 
  auto_increment_value= proto.options().auto_increment_value();
 
655
  auto_increment_value= create_info->auto_increment_value;
511
656
 
512
 
  for (uint32_t key= 0; key < table_arg.sizeKeys(); key++)
 
657
  for (uint32_t key= 0; key < table_arg->sizeKeys(); key++)
513
658
  {
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;
 
659
    KEY *pos= table_arg->key_info+key;
 
660
    KEY_PART_INFO *key_part=     pos->key_part;
 
661
    KEY_PART_INFO *key_part_end= key_part + pos->key_parts;
517
662
 
518
663
    for (; key_part != key_part_end; key_part++)
519
664
    {
521
666
 
522
667
      if (!(field->flags & AUTO_INCREMENT_FLAG))
523
668
      {
524
 
        return -1;
 
669
        error= -1;
 
670
        goto error;
525
671
      }
526
672
    }
527
673
  }
528
674
 
529
 
  std::string named_file= identifier.getPath();
530
 
  named_file.append(ARZ);
 
675
  /*
 
676
    We reuse name_buff since it is available.
 
677
  */
 
678
  fn_format(name_buff, table_name, "", ARZ,
 
679
            MY_REPLACE_EXT | MY_UNPACK_FILENAME);
531
680
 
532
 
  errno= 0;
533
 
  if (azopen(create_stream.get(), named_file.c_str(), O_CREAT|O_RDWR,
 
681
  my_errno= 0;
 
682
  if (azopen(&create_stream, name_buff, O_CREAT|O_RDWR,
534
683
             AZ_METHOD_BLOCK) == 0)
535
684
  {
536
685
    error= errno;
537
 
    unlink(named_file.c_str());
538
 
 
539
 
    return(error ? error : -1);
540
 
  }
541
 
 
542
 
  try {
543
 
    proto.SerializeToString(&serialized_proto);
544
 
  }
545
 
  catch (...)
546
 
  {
547
 
    unlink(named_file.c_str());
548
 
 
549
 
    return(error ? error : -1);
550
 
  }
551
 
 
552
 
  if (azwrite_frm(create_stream.get(), serialized_proto.c_str(),
 
686
    goto error2;
 
687
  }
 
688
 
 
689
  proto->SerializeToString(&serialized_proto);
 
690
 
 
691
  if (azwrite_frm(&create_stream, serialized_proto.c_str(),
553
692
                  serialized_proto.length()))
554
 
  {
555
 
    unlink(named_file.c_str());
556
 
 
557
 
    return(error ? error : -1);
558
 
  }
559
 
 
560
 
  if (proto.options().has_comment())
 
693
    goto error2;
 
694
 
 
695
  if (proto->options().has_comment())
561
696
  {
562
697
    int write_length;
563
698
 
564
 
    write_length= azwrite_comment(create_stream.get(),
565
 
                                  proto.options().comment().c_str(),
566
 
                                  proto.options().comment().length());
 
699
    write_length= azwrite_comment(&create_stream,
 
700
                                  proto->options().comment().c_str(),
 
701
                                  proto->options().comment().length());
567
702
 
568
703
    if (write_length < 0)
569
704
    {
570
705
      error= errno;
571
 
      unlink(named_file.c_str());
572
 
 
573
 
      return(error ? error : -1);
 
706
      goto error2;
574
707
    }
575
708
  }
576
709
 
578
711
    Yes you need to do this, because the starting value
579
712
    for the autoincrement may not be zero.
580
713
  */
581
 
  create_stream->auto_increment= auto_increment_value ?
 
714
  create_stream.auto_increment= auto_increment_value ?
582
715
    auto_increment_value - 1 : 0;
583
716
 
584
 
  if (azclose(create_stream.get()))
 
717
  if (azclose(&create_stream))
585
718
  {
586
719
    error= errno;
587
 
    unlink(named_file.c_str());
588
 
 
589
 
    return(error ? error : -1);
 
720
    goto error2;
590
721
  }
591
722
 
592
723
  return(0);
 
724
 
 
725
error2:
 
726
  deleteTable(session, table_name);
 
727
error:
 
728
  /* Return error number, if we got one */
 
729
  return(error ? error : -1);
593
730
}
594
731
 
595
732
/*
603
740
  /* We pack the row for writing */
604
741
  r_pack_length= pack_row(buf);
605
742
 
606
 
  written= azwrite_row(writer, &record_buffer[0], r_pack_length);
 
743
  written= azwrite_row(writer, record_buffer->buffer, r_pack_length);
607
744
  if (written != r_pack_length)
608
745
  {
609
746
    return(-1);
623
760
 
624
761
uint32_t ha_archive::max_row_length(const unsigned char *)
625
762
{
626
 
  uint32_t length= (uint32_t)(getTable()->getRecordLength() + getTable()->sizeFields()*2);
 
763
  uint32_t length= (uint32_t)(table->getRecordLength() + table->sizeFields()*2);
627
764
  length+= ARCHIVE_ROW_HEADER_SIZE;
628
765
 
629
766
  uint32_t *ptr, *end;
630
 
  for (ptr= getTable()->getBlobField(), end=ptr + getTable()->sizeBlobFields();
 
767
  for (ptr= table->getBlobField(), end=ptr + table->sizeBlobFields();
631
768
       ptr != end ;
632
769
       ptr++)
633
770
  {
634
 
      length += 2 + ((Field_blob*)getTable()->getField(*ptr))->get_length();
 
771
      length += 2 + ((Field_blob*)table->field[*ptr])->get_length();
635
772
  }
636
773
 
637
774
  return length;
646
783
    return(HA_ERR_OUT_OF_MEM);
647
784
 
648
785
  /* Copy null bits */
649
 
  memcpy(&record_buffer[0], record, getTable()->getShare()->null_bytes);
650
 
  ptr= &record_buffer[0] + getTable()->getShare()->null_bytes;
 
786
  memcpy(record_buffer->buffer, record, table->s->null_bytes);
 
787
  ptr= record_buffer->buffer + table->s->null_bytes;
651
788
 
652
 
  for (Field **field=getTable()->getFields() ; *field ; field++)
 
789
  for (Field **field=table->field ; *field ; field++)
653
790
  {
654
791
    if (!((*field)->is_null()))
655
792
      ptr= (*field)->pack(ptr, record + (*field)->offset(record));
656
793
  }
657
794
 
658
 
  return((unsigned int) (ptr - &record_buffer[0]));
 
795
  return((unsigned int) (ptr - record_buffer->buffer));
659
796
}
660
797
 
661
798
 
668
805
  for implementing start_bulk_insert() is that we could skip
669
806
  setting dirty to true each time.
670
807
*/
671
 
int ha_archive::doInsertRecord(unsigned char *buf)
 
808
int ha_archive::write_row(unsigned char *buf)
672
809
{
673
810
  int rc;
674
811
  unsigned char *read_buf= NULL;
675
812
  uint64_t temp_auto;
676
 
  unsigned char *record=  getTable()->getInsertRecord();
 
813
  unsigned char *record=  table->record[0];
677
814
 
678
815
  if (share->crashed)
679
816
    return(HA_ERR_CRASHED_ON_USAGE);
680
817
 
681
 
  pthread_mutex_lock(&share->mutex());
 
818
  ha_statistic_increment(&SSV::ha_write_count);
 
819
  pthread_mutex_lock(&share->mutex);
682
820
 
683
821
  if (share->archive_write_open == false)
684
822
    if (init_archive_writer())
685
823
      return(HA_ERR_CRASHED_ON_USAGE);
686
824
 
687
825
 
688
 
  if (getTable()->next_number_field && record == getTable()->getInsertRecord())
 
826
  if (table->next_number_field && record == table->record[0])
689
827
  {
 
828
    KEY *mkey= &table->s->key_info[0]; // We only support one key right now
690
829
    update_auto_increment();
691
 
    temp_auto= getTable()->next_number_field->val_int();
 
830
    temp_auto= table->next_number_field->val_int();
692
831
 
693
832
    /*
694
833
      We don't support decremening auto_increment. They make the performance
695
834
      just cry.
696
835
    */
697
836
    if (temp_auto <= share->archive_write.auto_increment &&
698
 
        getTable()->getShare()->getKeyInfo(0).flags & HA_NOSAME)
 
837
        mkey->flags & HA_NOSAME)
699
838
    {
700
839
      rc= HA_ERR_FOUND_DUPP_KEY;
701
840
      goto error;
715
854
  share->rows_recorded++;
716
855
  rc= real_write_row(buf,  &(share->archive_write));
717
856
error:
718
 
  pthread_mutex_unlock(&share->mutex());
 
857
  pthread_mutex_unlock(&share->mutex);
719
858
  if (read_buf)
720
859
    free((unsigned char*) read_buf);
721
860
 
730
869
  *first_value= share->archive_write.auto_increment + 1;
731
870
}
732
871
 
733
 
/* Initialized at each key walk (called multiple times unlike doStartTableScan()) */
734
 
int ha_archive::doStartIndexScan(uint32_t keynr, bool)
 
872
/* Initialized at each key walk (called multiple times unlike rnd_init()) */
 
873
int ha_archive::index_init(uint32_t keynr, bool)
735
874
{
736
875
  active_index= keynr;
737
876
  return(0);
743
882
  the optimizer that we have unique indexes, we scan
744
883
*/
745
884
int ha_archive::index_read(unsigned char *buf, const unsigned char *key,
746
 
                             uint32_t key_len, enum ha_rkey_function)
 
885
                             uint32_t key_len, enum ha_rkey_function find_flag)
 
886
{
 
887
  int rc;
 
888
  rc= index_read_idx(buf, active_index, key, key_len, find_flag);
 
889
  return(rc);
 
890
}
 
891
 
 
892
 
 
893
int ha_archive::index_read_idx(unsigned char *buf, uint32_t index, const unsigned char *key,
 
894
                               uint32_t key_len, enum ha_rkey_function)
747
895
{
748
896
  int rc;
749
897
  bool found= 0;
750
 
  current_k_offset= getTable()->getShare()->getKeyInfo(0).key_part->offset;
 
898
  KEY *mkey= &table->s->key_info[index];
 
899
  current_k_offset= mkey->key_part->offset;
751
900
  current_key= key;
752
901
  current_key_len= key_len;
753
902
 
754
 
  rc= doStartTableScan(true);
 
903
  rc= rnd_init(true);
755
904
 
756
905
  if (rc)
757
906
    goto error;
795
944
  we assume the position will be set.
796
945
*/
797
946
 
798
 
int ha_archive::doStartTableScan(bool scan)
 
947
int ha_archive::rnd_init(bool scan)
799
948
{
800
949
  if (share->crashed)
801
950
      return(HA_ERR_CRASHED_ON_USAGE);
832
981
/* Reallocate buffer if needed */
833
982
bool ha_archive::fix_rec_buff(unsigned int length)
834
983
{
835
 
  record_buffer.resize(length);
836
 
 
837
 
  return false;
 
984
  assert(record_buffer->buffer);
 
985
 
 
986
  if (length > record_buffer->length)
 
987
  {
 
988
    unsigned char *newptr;
 
989
    if (!(newptr= (unsigned char *)realloc(record_buffer->buffer, length)))
 
990
      return(1);
 
991
    record_buffer->buffer= newptr;
 
992
    record_buffer->length= length;
 
993
  }
 
994
 
 
995
  assert(length <= record_buffer->length);
 
996
 
 
997
  return(0);
838
998
}
839
999
 
840
1000
int ha_archive::unpack_row(azio_stream *file_to_read, unsigned char *record)
852
1012
  }
853
1013
 
854
1014
  /* Copy null bits */
855
 
  memcpy(record, ptr, getTable()->getNullBytes());
856
 
  ptr+= getTable()->getNullBytes();
857
 
  for (Field **field= getTable()->getFields() ; *field ; field++)
 
1015
  memcpy(record, ptr, table->getNullBytes());
 
1016
  ptr+= table->getNullBytes();
 
1017
  for (Field **field=table->field ; *field ; field++)
858
1018
  {
859
1019
    if (!((*field)->is_null()))
860
1020
    {
861
 
      ptr= (*field)->unpack(record + (*field)->offset(getTable()->getInsertRecord()), ptr);
 
1021
      ptr= (*field)->unpack(record + (*field)->offset(table->record[0]), ptr);
862
1022
    }
863
1023
  }
864
1024
  return(0);
889
1049
    return(HA_ERR_END_OF_FILE);
890
1050
  scan_rows--;
891
1051
 
892
 
  ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
 
1052
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
893
1053
  current_position= aztell(&archive);
894
1054
  rc= get_row(&archive, buf);
895
1055
 
896
 
  getTable()->status=rc ? STATUS_NOT_FOUND: 0;
 
1056
  table->status=rc ? STATUS_NOT_FOUND: 0;
897
1057
 
898
1058
  return(rc);
899
1059
}
900
1060
 
901
1061
 
902
1062
/*
903
 
  Thanks to the table bool is_ordered this will be called after
 
1063
  Thanks to the table flag HA_REC_NOT_IN_SEQ this will be called after
904
1064
  each call to ha_archive::rnd_next() if an ordering of the rows is
905
1065
  needed.
906
1066
*/
907
1067
 
908
1068
void ha_archive::position(const unsigned char *)
909
1069
{
910
 
  internal::my_store_ptr(ref, ref_length, current_position);
 
1070
  my_store_ptr(ref, ref_length, current_position);
911
1071
  return;
912
1072
}
913
1073
 
921
1081
 
922
1082
int ha_archive::rnd_pos(unsigned char * buf, unsigned char *pos)
923
1083
{
924
 
  ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
925
 
  current_position= (internal::my_off_t)internal::my_get_ptr(pos, ref_length);
 
1084
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
 
1085
  current_position= (my_off_t)my_get_ptr(pos, ref_length);
926
1086
  if (azseek(&archive, (size_t)current_position, SEEK_SET) == (size_t)(-1L))
927
1087
    return(HA_ERR_CRASHED_ON_USAGE);
928
1088
  return(get_row(&archive, buf));
933
1093
  rewriting the meta file. Currently it does this by calling optimize with
934
1094
  the extended flag.
935
1095
*/
936
 
int ha_archive::repair()
 
1096
int ha_archive::repair(Session* session, HA_CHECK_OPT* check_opt)
937
1097
{
938
 
  int rc= optimize();
 
1098
  check_opt->flags= T_EXTEND;
 
1099
  int rc= optimize(session, check_opt);
939
1100
 
940
1101
  if (rc)
941
1102
    return(HA_ERR_CRASHED_ON_REPAIR);
948
1109
  The table can become fragmented if data was inserted, read, and then
949
1110
  inserted again. What we do is open up the file and recompress it completely.
950
1111
*/
951
 
int ha_archive::optimize()
 
1112
int ha_archive::optimize(Session *, HA_CHECK_OPT *)
952
1113
{
953
1114
  int rc= 0;
954
 
  boost::scoped_ptr<azio_stream> writer(new azio_stream);
 
1115
  azio_stream writer;
 
1116
  char writer_filename[FN_REFLEN];
955
1117
 
956
1118
  init_archive_reader();
957
1119
 
971
1133
  azread_frm(&archive, proto_string);
972
1134
 
973
1135
  /* Lets create a file to contain the new data */
974
 
  std::string writer_filename= share->table_name;
975
 
  writer_filename.append(ARN);
 
1136
  fn_format(writer_filename, share->table_name.c_str(), "", ARN,
 
1137
            MY_REPLACE_EXT | MY_UNPACK_FILENAME);
976
1138
 
977
 
  if (!(azopen(writer.get(), writer_filename.c_str(), O_CREAT|O_RDWR, AZ_METHOD_BLOCK)))
 
1139
  if (!(azopen(&writer, writer_filename, O_CREAT|O_RDWR, AZ_METHOD_BLOCK)))
978
1140
  {
979
1141
    free(proto_string);
980
1142
    return(HA_ERR_CRASHED_ON_USAGE);
981
1143
  }
982
1144
 
983
 
  azwrite_frm(writer.get(), proto_string, archive.frm_length);
 
1145
  azwrite_frm(&writer, proto_string, archive.frm_length);
984
1146
 
985
1147
  /*
986
1148
    An extended rebuild is a lot more effort. We open up each row and re-record it.
1004
1166
    */
1005
1167
    if (!rc)
1006
1168
    {
 
1169
      uint64_t x;
1007
1170
      uint64_t rows_restored;
1008
1171
      share->rows_recorded= 0;
1009
1172
      stats.auto_increment_value= 1;
1011
1174
 
1012
1175
      rows_restored= archive.rows;
1013
1176
 
1014
 
      for (uint64_t x= 0; x < rows_restored ; x++)
 
1177
      for (x= 0; x < rows_restored ; x++)
1015
1178
      {
1016
 
        rc= get_row(&archive, getTable()->getInsertRecord());
 
1179
        rc= get_row(&archive, table->record[0]);
1017
1180
 
1018
1181
        if (rc != 0)
1019
1182
          break;
1020
1183
 
1021
 
        real_write_row(getTable()->getInsertRecord(), writer.get());
 
1184
        real_write_row(table->record[0], &writer);
1022
1185
        /*
1023
1186
          Long term it should be possible to optimize this so that
1024
1187
          it is not called on each row.
1025
1188
        */
1026
 
        if (getTable()->found_next_number_field)
 
1189
        if (table->found_next_number_field)
1027
1190
        {
1028
 
          Field *field= getTable()->found_next_number_field;
 
1191
          Field *field= table->found_next_number_field;
1029
1192
 
1030
1193
          /* Since we will need to use field to translate, we need to flip its read bit */
1031
1194
          field->setReadSet();
1032
1195
 
1033
1196
          uint64_t auto_value=
1034
 
            (uint64_t) field->val_int_internal(getTable()->getInsertRecord() +
1035
 
                                               field->offset(getTable()->getInsertRecord()));
 
1197
            (uint64_t) field->val_int(table->record[0] +
 
1198
                                       field->offset(table->record[0]));
1036
1199
          if (share->archive_write.auto_increment < auto_value)
1037
1200
            stats.auto_increment_value=
1038
1201
              (share->archive_write.auto_increment= auto_value) + 1;
1039
1202
        }
1040
1203
      }
1041
 
      share->rows_recorded= (ha_rows)writer->rows;
 
1204
      share->rows_recorded= (ha_rows)writer.rows;
1042
1205
    }
1043
1206
 
1044
1207
    if (rc && rc != HA_ERR_END_OF_FILE)
1047
1210
    }
1048
1211
  }
1049
1212
 
1050
 
  azclose(writer.get());
 
1213
  azclose(&writer);
1051
1214
  share->dirty= false;
1052
1215
 
1053
1216
  azclose(&archive);
1054
1217
 
1055
1218
  // make the file we just wrote be our data file
1056
 
  rc = internal::my_rename(writer_filename.c_str(), share->data_file_name.c_str(), MYF(0));
 
1219
  rc = my_rename(writer_filename,share->data_file_name,MYF(0));
1057
1220
 
1058
1221
  free(proto_string);
1059
1222
  return(rc);
1060
1223
error:
1061
1224
  free(proto_string);
1062
 
  azclose(writer.get());
 
1225
  azclose(&writer);
1063
1226
 
1064
1227
  return(rc);
1065
1228
}
1115
1278
    If dirty, we lock, and then reset/flush the data.
1116
1279
    I found that just calling azflush() doesn't always work.
1117
1280
  */
1118
 
  pthread_mutex_lock(&share->mutex());
 
1281
  pthread_mutex_lock(&share->mutex);
1119
1282
  if (share->dirty == true)
1120
1283
  {
1121
1284
    azflush(&(share->archive_write), Z_SYNC_FLUSH);
1134
1297
    cause the number to be inaccurate.
1135
1298
  */
1136
1299
  stats.records= share->rows_recorded;
1137
 
  pthread_mutex_unlock(&share->mutex());
 
1300
  pthread_mutex_unlock(&share->mutex);
1138
1301
 
1139
1302
  scan_rows= stats.records;
1140
1303
  stats.deleted= 0;
1144
1307
  {
1145
1308
    struct stat file_stat;  // Stat information for the data file
1146
1309
 
1147
 
    stat(share->data_file_name.c_str(), &file_stat);
 
1310
    stat(share->data_file_name, &file_stat);
1148
1311
 
1149
 
    stats.mean_rec_length= getTable()->getRecordLength()+ buffer.alloced_length();
 
1312
    stats.mean_rec_length= table->getRecordLength()+ buffer.alloced_length();
1150
1313
    stats.data_file_length= file_stat.st_size;
1151
1314
    stats.create_time= file_stat.st_ctime;
1152
1315
    stats.update_time= file_stat.st_mtime;
1158
1321
  if (flag & HA_STATUS_AUTO)
1159
1322
  {
1160
1323
    init_archive_reader();
1161
 
    pthread_mutex_lock(&share->mutex());
 
1324
    pthread_mutex_lock(&share->mutex);
1162
1325
    azflush(&archive, Z_SYNC_FLUSH);
1163
 
    pthread_mutex_unlock(&share->mutex());
 
1326
    pthread_mutex_unlock(&share->mutex);
1164
1327
    stats.auto_increment_value= archive.auto_increment + 1;
1165
1328
  }
1166
1329
 
1170
1333
 
1171
1334
/*
1172
1335
  This method tells us that a bulk insert operation is about to occur. We set
1173
 
  a flag which will keep doInsertRecord from saying that its data is dirty. This in
 
1336
  a flag which will keep write_row from saying that its data is dirty. This in
1174
1337
  turn will keep selects from causing a sync to occur.
1175
1338
  Basically, yet another optimizations to keep compression working well.
1176
1339
*/
1204
1367
}
1205
1368
 
1206
1369
/*
 
1370
  We just return state if asked.
 
1371
*/
 
1372
bool ha_archive::is_crashed() const
 
1373
{
 
1374
  return(share->crashed);
 
1375
}
 
1376
 
 
1377
/*
1207
1378
  Simple scan of the tables to make sure everything is ok.
1208
1379
*/
1209
1380
 
1210
 
int ha_archive::check(Session* session)
 
1381
int ha_archive::check(Session* session, HA_CHECK_OPT *)
1211
1382
{
1212
1383
  int rc= 0;
1213
1384
  const char *old_proc_info;
 
1385
  uint64_t x;
1214
1386
 
1215
1387
  old_proc_info= get_session_proc_info(session);
1216
1388
  set_session_proc_info(session, "Checking table");
1217
1389
  /* Flush any waiting data */
1218
 
  pthread_mutex_lock(&share->mutex());
 
1390
  pthread_mutex_lock(&share->mutex);
1219
1391
  azflush(&(share->archive_write), Z_SYNC_FLUSH);
1220
 
  pthread_mutex_unlock(&share->mutex());
 
1392
  pthread_mutex_unlock(&share->mutex);
1221
1393
 
1222
1394
  /*
1223
1395
    Now we will rewind the archive file so that we are positioned at the
1226
1398
  init_archive_reader();
1227
1399
  azflush(&archive, Z_SYNC_FLUSH);
1228
1400
  read_data_header(&archive);
1229
 
  for (uint64_t x= 0; x < share->archive_write.rows; x++)
 
1401
  for (x= 0; x < share->archive_write.rows; x++)
1230
1402
  {
1231
 
    rc= get_row(&archive, getTable()->getInsertRecord());
 
1403
    rc= get_row(&archive, table->record[0]);
1232
1404
 
1233
1405
    if (rc != 0)
1234
1406
      break;
1247
1419
  }
1248
1420
}
1249
1421
 
1250
 
int ArchiveEngine::doRenameTable(Session&, const TableIdentifier &from, const TableIdentifier &to)
1251
 
{
1252
 
  int error= 0;
1253
 
 
1254
 
  for (const char **ext= bas_ext(); *ext ; ext++)
1255
 
  {
1256
 
    if (rename_file_ext(from.getPath().c_str(), to.getPath().c_str(), *ext))
1257
 
    {
1258
 
      if ((error=errno) != ENOENT)
1259
 
        break;
1260
 
      error= 0;
1261
 
    }
1262
 
  }
1263
 
 
1264
 
  return error;
1265
 
}
1266
 
 
1267
 
bool ArchiveEngine::doDoesTableExist(Session&,
1268
 
                                     const TableIdentifier &identifier)
1269
 
{
1270
 
  string proto_path(identifier.getPath());
1271
 
  proto_path.append(ARZ);
1272
 
 
1273
 
  if (access(proto_path.c_str(), F_OK))
1274
 
  {
1275
 
    return false;
1276
 
  }
1277
 
 
1278
 
  return true;
1279
 
}
1280
 
 
1281
 
void ArchiveEngine::doGetTableIdentifiers(drizzled::CachedDirectory &directory,
1282
 
                                          const drizzled::SchemaIdentifier &schema_identifier,
1283
 
                                          drizzled::TableIdentifier::vector &set_of_identifiers)
1284
 
{
1285
 
  drizzled::CachedDirectory::Entries entries= directory.getEntries();
1286
 
 
1287
 
  for (drizzled::CachedDirectory::Entries::iterator entry_iter= entries.begin(); 
1288
 
       entry_iter != entries.end(); ++entry_iter)
1289
 
  {
1290
 
    drizzled::CachedDirectory::Entry *entry= *entry_iter;
1291
 
    const string *filename= &entry->filename;
1292
 
 
1293
 
    assert(filename->size());
1294
 
 
1295
 
    const char *ext= strchr(filename->c_str(), '.');
1296
 
 
1297
 
    if (ext == NULL || my_strcasecmp(system_charset_info, ext, ARZ) ||
1298
 
        (filename->compare(0, strlen(TMP_FILE_PREFIX), TMP_FILE_PREFIX) == 0))
1299
 
    {  }
1300
 
    else
1301
 
    {
1302
 
      char uname[NAME_LEN + 1];
1303
 
      uint32_t file_name_len;
1304
 
 
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 
1308
 
 
1309
 
      set_of_identifiers.push_back(TableIdentifier(schema_identifier, uname));
1310
 
    }
1311
 
  }
1312
 
}
 
1422
archive_record_buffer *ha_archive::create_record_buffer(unsigned int length)
 
1423
{
 
1424
  archive_record_buffer *r;
 
1425
  if (!(r= (archive_record_buffer*) malloc(sizeof(archive_record_buffer))))
 
1426
  {
 
1427
    return(NULL);
 
1428
  }
 
1429
  r->length= (int)length;
 
1430
 
 
1431
  if (!(r->buffer= (unsigned char*) malloc(r->length)))
 
1432
  {
 
1433
    free((char*) r);
 
1434
    return(NULL);
 
1435
  }
 
1436
 
 
1437
  return(r);
 
1438
}
 
1439
 
 
1440
void ha_archive::destroy_record_buffer(archive_record_buffer *r)
 
1441
{
 
1442
  free((char*) r->buffer);
 
1443
  free((char*) r);
 
1444
  return;
 
1445
}
 
1446
 
 
1447
static DRIZZLE_SYSVAR_BOOL(aio, archive_use_aio,
 
1448
  PLUGIN_VAR_NOCMDOPT,
 
1449
  "Whether or not to use asynchronous IO.",
 
1450
  NULL, NULL, true);
 
1451
 
 
1452
static struct st_mysql_sys_var* archive_system_variables[]= {
 
1453
  DRIZZLE_SYSVAR(aio),
 
1454
  NULL
 
1455
};
 
1456
 
 
1457
drizzle_declare_plugin(archive)
 
1458
{
 
1459
  "ARCHIVE",
 
1460
  "3.5",
 
1461
  "Brian Aker, MySQL AB",
 
1462
  "Archive storage engine",
 
1463
  PLUGIN_LICENSE_GPL,
 
1464
  archive_db_init, /* Plugin Init */
 
1465
  archive_db_done, /* Plugin Deinit */
 
1466
  NULL,                       /* status variables                */
 
1467
  archive_system_variables,   /* system variables                */
 
1468
  NULL                        /* config options                  */
 
1469
}
 
1470
drizzle_declare_plugin_end;
 
1471