~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/archive/ha_archive.cc

Updated an include guard thanks to a nice catch during code review from Jay. Thanks Jay!

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
15
14
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
16
15
 
17
16
 
18
 
#include "config.h"
19
 
 
20
 
#include "plugin/archive/archive_engine.h"
 
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>
21
31
 
22
32
using namespace std;
23
 
using namespace drizzled;
24
 
 
25
33
 
26
34
/*
27
35
  First, if you want to understand storage engines you should look at
94
102
/* Variables for archive share methods */
95
103
pthread_mutex_t archive_mutex= PTHREAD_MUTEX_INITIALIZER;
96
104
 
97
 
/* When the engine starts up set the first version */
98
 
static uint64_t global_version= 1;
99
 
 
100
 
// We use this to find out the state of the archive aio option.
101
 
extern bool archive_aio_state(void);
 
105
static unsigned int global_version;
 
106
 
 
107
/* The file extension */
 
108
#define ARZ ".arz"               // The data file
 
109
#define ARN ".ARN"               // Files used during an optimize call
 
110
 
 
111
 
 
112
 
 
113
static bool archive_use_aio= false;
102
114
 
103
115
/*
104
116
  Number of rows that will force a bulk insert.
110
122
*/
111
123
#define ARCHIVE_ROW_HEADER_SIZE 4
112
124
 
 
125
/*
 
126
  We just implement one additional file extension.
 
127
*/
 
128
static const char *ha_archive_exts[] = {
 
129
  ARZ,
 
130
  NULL
 
131
};
 
132
 
 
133
class ArchiveEngine : public drizzled::plugin::StorageEngine
 
134
{
 
135
  typedef std::map<string, ArchiveShare*> ArchiveMap;
 
136
  ArchiveMap archive_open_tables;
 
137
 
 
138
public:
 
139
  ArchiveEngine(const string &name_arg)
 
140
   : drizzled::plugin::StorageEngine(name_arg,
 
141
                                     HTON_FILE_BASED |
 
142
                                     HTON_STATS_RECORDS_IS_EXACT |
 
143
                                     HTON_HAS_RECORDS |
 
144
                                     HTON_HAS_DATA_DICTIONARY),
 
145
     archive_open_tables()
 
146
  {
 
147
    table_definition_ext= ARZ;
 
148
  }
 
149
 
 
150
  virtual Cursor *create(TableShare &table,
 
151
                          MEM_ROOT *mem_root)
 
152
  {
 
153
    return new (mem_root) ha_archive(*this, table);
 
154
  }
 
155
 
 
156
  const char **bas_ext() const {
 
157
    return ha_archive_exts;
 
158
  }
 
159
 
 
160
  int doCreateTable(Session *session, const char *table_name,
 
161
                    Table& table_arg,
 
162
                    drizzled::message::Table& proto);
 
163
 
 
164
  int doGetTableDefinition(Session& session,
 
165
                           const char* path,
 
166
                           const char *db,
 
167
                           const char *table_name,
 
168
                           const bool is_tmp,
 
169
                           drizzled::message::Table *table_proto);
 
170
 
 
171
  void doGetTableNames(CachedDirectory &directory, string& , set<string>& set_of_names);
 
172
 
 
173
  int doDropTable(Session&, const string table_path);
 
174
  ArchiveShare *findOpenTable(const string table_name);
 
175
  void addOpenTable(const string &table_name, ArchiveShare *);
 
176
  void deleteOpenTable(const string &table_name);
 
177
 
 
178
  uint32_t max_supported_keys()          const { return 1; }
 
179
  uint32_t max_supported_key_length()    const { return sizeof(uint64_t); }
 
180
  uint32_t max_supported_key_part_length() const { return sizeof(uint64_t); }
 
181
 
 
182
  uint32_t index_flags(enum  ha_key_alg) const
 
183
  {
 
184
    return HA_ONLY_WHOLE_INDEX;
 
185
  }
 
186
};
 
187
 
113
188
ArchiveShare *ArchiveEngine::findOpenTable(const string table_name)
114
189
{
115
190
  ArchiveMap::iterator find_iter=
132
207
}
133
208
 
134
209
 
135
 
void ArchiveEngine::doGetTableNames(drizzled::CachedDirectory &directory, 
136
 
                                    SchemaIdentifier&,
 
210
void ArchiveEngine::doGetTableNames(CachedDirectory &directory, 
 
211
                                    string&, 
137
212
                                    set<string>& set_of_names)
138
213
{
139
 
  drizzled::CachedDirectory::Entries entries= directory.getEntries();
 
214
  CachedDirectory::Entries entries= directory.getEntries();
140
215
 
141
 
  for (drizzled::CachedDirectory::Entries::iterator entry_iter= entries.begin(); 
 
216
  for (CachedDirectory::Entries::iterator entry_iter= entries.begin(); 
142
217
       entry_iter != entries.end(); ++entry_iter)
143
218
  {
144
 
    drizzled::CachedDirectory::Entry *entry= *entry_iter;
145
 
    const string *filename= &entry->filename;
 
219
    CachedDirectory::Entry *entry= *entry_iter;
 
220
    string *filename= &entry->filename;
146
221
 
147
222
    assert(filename->size());
148
223
 
149
224
    const char *ext= strchr(filename->c_str(), '.');
150
225
 
151
226
    if (ext == NULL || my_strcasecmp(system_charset_info, ext, ARZ) ||
152
 
        (filename->compare(0, strlen(TMP_FILE_PREFIX), TMP_FILE_PREFIX) == 0))
 
227
        is_prefix(filename->c_str(), TMP_FILE_PREFIX))
153
228
    {  }
154
229
    else
155
230
    {
165
240
}
166
241
 
167
242
 
168
 
int ArchiveEngine::doDropTable(Session&, TableIdentifier &identifier)
 
243
int ArchiveEngine::doDropTable(Session&,
 
244
                               const string table_path)
169
245
{
170
 
  string new_path(identifier.getPath());
 
246
  string new_path(table_path);
171
247
 
172
248
  new_path+= ARZ;
173
249
 
175
251
 
176
252
  if (error != 0)
177
253
  {
178
 
    error= errno= errno;
 
254
    error= my_errno= errno;
179
255
  }
180
256
 
181
257
  return error;
182
258
}
183
259
 
184
260
int ArchiveEngine::doGetTableDefinition(Session&,
185
 
                                        TableIdentifier &identifier,
186
 
                                        drizzled::message::Table &table_proto)
 
261
                                        const char* path,
 
262
                                        const char *,
 
263
                                        const char *,
 
264
                                        const bool,
 
265
                                        drizzled::message::Table *table_proto)
187
266
{
188
267
  struct stat stat_info;
189
268
  int error= ENOENT;
190
269
  string proto_path;
191
270
 
192
271
  proto_path.reserve(FN_REFLEN);
193
 
  proto_path.assign(identifier.getPath());
 
272
  proto_path.assign(path);
194
273
 
195
274
  proto_path.append(ARZ);
196
275
 
199
278
  else
200
279
    error= EEXIST;
201
280
 
 
281
  if (table_proto)
202
282
  {
203
283
    azio_stream proto_stream;
204
284
    char* proto_string;
214
294
 
215
295
    azread_frm(&proto_stream, proto_string);
216
296
 
217
 
    if (table_proto.ParseFromArray(proto_string, proto_stream.frm_length) == false)
 
297
    if (table_proto->ParseFromArray(proto_string, proto_stream.frm_length) == false)
218
298
      error= HA_ERR_CRASHED_ON_USAGE;
219
299
 
220
300
    azclose(&proto_stream);
224
304
  return error;
225
305
}
226
306
 
 
307
static ArchiveEngine *archive_engine= NULL;
 
308
 
 
309
/*
 
310
  Initialize the archive Cursor.
 
311
 
 
312
  SYNOPSIS
 
313
    archive_db_init()
 
314
    void *
 
315
 
 
316
  RETURN
 
317
    false       OK
 
318
    true        Error
 
319
*/
 
320
 
 
321
static int archive_db_init(drizzled::plugin::Registry &registry)
 
322
{
 
323
 
 
324
  pthread_mutex_init(&archive_mutex, MY_MUTEX_INIT_FAST);
 
325
  archive_engine= new ArchiveEngine("ARCHIVE");
 
326
  registry.add(archive_engine);
 
327
 
 
328
  /* When the engine starts up set the first version */
 
329
  global_version= 1;
 
330
 
 
331
  return false;
 
332
}
 
333
 
 
334
/*
 
335
  Release the archive Cursor.
 
336
 
 
337
  SYNOPSIS
 
338
    archive_db_done()
 
339
    void
 
340
 
 
341
  RETURN
 
342
    false       OK
 
343
*/
 
344
 
 
345
static int archive_db_done(drizzled::plugin::Registry &registry)
 
346
{
 
347
  registry.remove(archive_engine);
 
348
  delete archive_engine;
 
349
 
 
350
  pthread_mutex_destroy(&archive_mutex);
 
351
 
 
352
  return 0;
 
353
}
 
354
 
227
355
 
228
356
ha_archive::ha_archive(drizzled::plugin::StorageEngine &engine_arg,
229
357
                       TableShare &table_arg)
233
361
  buffer.set((char *)byte_buffer, IO_SIZE, system_charset_info);
234
362
 
235
363
  /* The size of the offset value we will use for position() */
236
 
  ref_length= sizeof(internal::my_off_t);
 
364
  ref_length= sizeof(my_off_t);
237
365
  archive_reader_open= false;
238
366
}
239
367
 
264
392
{
265
393
  memset(&archive_write, 0, sizeof(azio_stream));     /* Archive file we are working with */
266
394
  table_name.append(name);
267
 
  internal::fn_format(data_file_name, table_name.c_str(), "",
 
395
  fn_format(data_file_name, table_name.c_str(), "",
268
396
            ARZ, MY_REPLACE_EXT | MY_UNPACK_FILENAME);
269
397
  /*
270
398
    We will use this lock for rows.
285
413
  */
286
414
  if (archive_write_open == true)
287
415
    (void)azclose(&archive_write);
288
 
  pthread_mutex_destroy(&archive_mutex);
289
416
}
290
417
 
291
418
bool ArchiveShare::prime(uint64_t *auto_increment)
414
541
  {
415
542
    az_method method;
416
543
 
417
 
    switch (archive_aio_state())
 
544
    switch (archive_use_aio)
418
545
    {
419
546
    case false:
420
547
      method= AZ_METHOD_BLOCK;
527
654
  of creation.
528
655
*/
529
656
 
530
 
int ArchiveEngine::doCreateTable(Session &,
 
657
int ArchiveEngine::doCreateTable(Session *,
 
658
                                 const char *table_name,
531
659
                                 Table& table_arg,
532
 
                                 drizzled::TableIdentifier &identifier,
533
660
                                 drizzled::message::Table& proto)
534
661
{
535
662
  char name_buff[FN_REFLEN];
561
688
  /*
562
689
    We reuse name_buff since it is available.
563
690
  */
564
 
  internal::fn_format(name_buff, identifier.getPath().c_str(), "", ARZ,
565
 
                      MY_REPLACE_EXT | MY_UNPACK_FILENAME);
 
691
  fn_format(name_buff, table_name, "", ARZ,
 
692
            MY_REPLACE_EXT | MY_UNPACK_FILENAME);
566
693
 
567
 
  errno= 0;
 
694
  my_errno= 0;
568
695
  if (azopen(&create_stream, name_buff, O_CREAT|O_RDWR,
569
696
             AZ_METHOD_BLOCK) == 0)
570
697
  {
702
829
  if (share->crashed)
703
830
    return(HA_ERR_CRASHED_ON_USAGE);
704
831
 
705
 
  ha_statistic_increment(&system_status_var::ha_write_count);
 
832
  ha_statistic_increment(&SSV::ha_write_count);
706
833
  pthread_mutex_lock(&share->mutex);
707
834
 
708
835
  if (share->archive_write_open == false)
936
1063
    return(HA_ERR_END_OF_FILE);
937
1064
  scan_rows--;
938
1065
 
939
 
  ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
 
1066
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
940
1067
  current_position= aztell(&archive);
941
1068
  rc= get_row(&archive, buf);
942
1069
 
954
1081
 
955
1082
void ha_archive::position(const unsigned char *)
956
1083
{
957
 
  internal::my_store_ptr(ref, ref_length, current_position);
 
1084
  my_store_ptr(ref, ref_length, current_position);
958
1085
  return;
959
1086
}
960
1087
 
968
1095
 
969
1096
int ha_archive::rnd_pos(unsigned char * buf, unsigned char *pos)
970
1097
{
971
 
  ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
972
 
  current_position= (internal::my_off_t)internal::my_get_ptr(pos, ref_length);
 
1098
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
 
1099
  current_position= (my_off_t)my_get_ptr(pos, ref_length);
973
1100
  if (azseek(&archive, (size_t)current_position, SEEK_SET) == (size_t)(-1L))
974
1101
    return(HA_ERR_CRASHED_ON_USAGE);
975
1102
  return(get_row(&archive, buf));
1019
1146
  azread_frm(&archive, proto_string);
1020
1147
 
1021
1148
  /* Lets create a file to contain the new data */
1022
 
  internal::fn_format(writer_filename, share->table_name.c_str(), "", ARN,
 
1149
  fn_format(writer_filename, share->table_name.c_str(), "", ARN,
1023
1150
            MY_REPLACE_EXT | MY_UNPACK_FILENAME);
1024
1151
 
1025
1152
  if (!(azopen(&writer, writer_filename, O_CREAT|O_RDWR, AZ_METHOD_BLOCK)))
1102
1229
  azclose(&archive);
1103
1230
 
1104
1231
  // make the file we just wrote be our data file
1105
 
  rc = internal::my_rename(writer_filename,share->data_file_name,MYF(0));
 
1232
  rc = my_rename(writer_filename,share->data_file_name,MYF(0));
1106
1233
 
1107
1234
  free(proto_string);
1108
1235
  return(rc);
1322
1449
  return;
1323
1450
}
1324
1451
 
1325
 
int ArchiveEngine::doRenameTable(Session&, TableIdentifier &from, TableIdentifier &to)
1326
 
{
1327
 
  int error= 0;
1328
 
 
1329
 
  for (const char **ext= bas_ext(); *ext ; ext++)
1330
 
  {
1331
 
    if (rename_file_ext(from.getPath().c_str(), to.getPath().c_str(), *ext))
1332
 
    {
1333
 
      if ((error=errno) != ENOENT)
1334
 
        break;
1335
 
      error= 0;
1336
 
    }
1337
 
  }
1338
 
 
1339
 
  return error;
1340
 
}
1341
 
 
1342
 
bool ArchiveEngine::doDoesTableExist(Session&,
1343
 
                                     TableIdentifier &identifier)
1344
 
{
1345
 
  string proto_path(identifier.getPath());
1346
 
  proto_path.append(ARZ);
1347
 
 
1348
 
  if (access(proto_path.c_str(), F_OK))
1349
 
  {
1350
 
    return false;
1351
 
  }
1352
 
 
1353
 
  return true;
1354
 
}
1355
 
 
1356
 
void ArchiveEngine::doGetTableIdentifiers(drizzled::CachedDirectory &directory,
1357
 
                                          drizzled::SchemaIdentifier &schema_identifier,
1358
 
                                          drizzled::TableIdentifiers &set_of_identifiers)
1359
 
{
1360
 
  drizzled::CachedDirectory::Entries entries= directory.getEntries();
1361
 
 
1362
 
  for (drizzled::CachedDirectory::Entries::iterator entry_iter= entries.begin(); 
1363
 
       entry_iter != entries.end(); ++entry_iter)
1364
 
  {
1365
 
    drizzled::CachedDirectory::Entry *entry= *entry_iter;
1366
 
    const string *filename= &entry->filename;
1367
 
 
1368
 
    assert(filename->size());
1369
 
 
1370
 
    const char *ext= strchr(filename->c_str(), '.');
1371
 
 
1372
 
    if (ext == NULL || my_strcasecmp(system_charset_info, ext, ARZ) ||
1373
 
        (filename->compare(0, strlen(TMP_FILE_PREFIX), TMP_FILE_PREFIX) == 0))
1374
 
    {  }
1375
 
    else
1376
 
    {
1377
 
      char uname[NAME_LEN + 1];
1378
 
      uint32_t file_name_len;
1379
 
 
1380
 
      file_name_len= filename_to_tablename(filename->c_str(), uname, sizeof(uname));
1381
 
      // TODO: Remove need for memory copy here
1382
 
      uname[file_name_len - sizeof(ARZ) + 1]= '\0'; // Subtract ending, place NULL 
1383
 
 
1384
 
      set_of_identifiers.push_back(TableIdentifier(schema_identifier, uname));
1385
 
    }
1386
 
  }
1387
 
}
 
1452
static DRIZZLE_SYSVAR_BOOL(aio, archive_use_aio,
 
1453
  PLUGIN_VAR_NOCMDOPT,
 
1454
  "Whether or not to use asynchronous IO.",
 
1455
  NULL, NULL, true);
 
1456
 
 
1457
static drizzle_sys_var* archive_system_variables[]= {
 
1458
  DRIZZLE_SYSVAR(aio),
 
1459
  NULL
 
1460
};
 
1461
 
 
1462
DRIZZLE_DECLARE_PLUGIN
 
1463
{
 
1464
  "ARCHIVE",
 
1465
  "3.5",
 
1466
  "Brian Aker, MySQL AB",
 
1467
  "Archive storage engine",
 
1468
  PLUGIN_LICENSE_GPL,
 
1469
  archive_db_init, /* Plugin Init */
 
1470
  archive_db_done, /* Plugin Deinit */
 
1471
  NULL,                       /* status variables                */
 
1472
  archive_system_variables,   /* system variables                */
 
1473
  NULL                        /* config options                  */
 
1474
}
 
1475
DRIZZLE_DECLARE_PLUGIN_END;
1388
1476