~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/archive/ha_archive.cc

  • Committer: Padraig O'Sullivan
  • Date: 2009-10-02 02:15:04 UTC
  • mto: This revision was merged to the branch mainline in revision 1167.
  • Revision ID: osullivan.padraig@gmail.com-20091002021504-6zho7rfkdhn0g1jy
Added a test suite for the memcached stats I_S tables. The test suite is
pretty simple at the moment.

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