~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/archive/ha_archive.cc

  • Committer: Stewart Smith
  • Date: 2009-12-02 06:01:21 UTC
  • mto: (1237.1.2 push)
  • mto: This revision was merged to the branch mainline in revision 1238.
  • Revision ID: stewart@flamingspork.com-20091202060121-68gyfqifqcjcmi2v
my_end() no longer requires an argument (we removed them all)

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
33
 
 
34
static const string engine_name("ARCHIVE");
25
35
 
26
36
/*
27
37
  First, if you want to understand storage engines you should look at
94
104
/* Variables for archive share methods */
95
105
pthread_mutex_t archive_mutex= PTHREAD_MUTEX_INITIALIZER;
96
106
 
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);
 
107
static unsigned int global_version;
 
108
 
 
109
/* The file extension */
 
110
#define ARZ ".arz"               // The data file
 
111
#define ARN ".ARN"               // Files used during an optimize call
 
112
 
 
113
 
 
114
 
 
115
static bool archive_use_aio= false;
102
116
 
103
117
/*
104
118
  Number of rows that will force a bulk insert.
110
124
*/
111
125
#define ARCHIVE_ROW_HEADER_SIZE 4
112
126
 
 
127
/*
 
128
  We just implement one additional file extension.
 
129
*/
 
130
static const char *ha_archive_exts[] = {
 
131
  ARZ,
 
132
  NULL
 
133
};
 
134
 
 
135
class ArchiveEngine : public drizzled::plugin::StorageEngine
 
136
{
 
137
  typedef std::map<string, ArchiveShare*> ArchiveMap;
 
138
  ArchiveMap archive_open_tables;
 
139
 
 
140
public:
 
141
  ArchiveEngine(const string &name_arg)
 
142
   : drizzled::plugin::StorageEngine(name_arg,
 
143
                                     HTON_FILE_BASED |
 
144
                                     HTON_STATS_RECORDS_IS_EXACT |
 
145
                                     HTON_HAS_RECORDS |
 
146
                                     HTON_HAS_DATA_DICTIONARY)
 
147
  {
 
148
    table_definition_ext= ARZ;
 
149
  }
 
150
 
 
151
  virtual Cursor *create(TableShare &table,
 
152
                          MEM_ROOT *mem_root)
 
153
  {
 
154
    return new (mem_root) ha_archive(*this, table);
 
155
  }
 
156
 
 
157
  const char **bas_ext() const {
 
158
    return ha_archive_exts;
 
159
  }
 
160
 
 
161
  int doCreateTable(Session *session, const char *table_name,
 
162
                    Table& table_arg,
 
163
                    drizzled::message::Table& proto);
 
164
 
 
165
  int doGetTableDefinition(Session& session,
 
166
                           const char* path,
 
167
                           const char *db,
 
168
                           const char *table_name,
 
169
                           const bool is_tmp,
 
170
                           drizzled::message::Table *table_proto);
 
171
 
 
172
  void doGetTableNames(CachedDirectory &directory, string& , set<string>& set_of_names);
 
173
 
 
174
  int doDropTable(Session&, const string table_path);
 
175
  ArchiveShare *findOpenTable(const string table_name);
 
176
  void addOpenTable(const string &table_name, ArchiveShare *);
 
177
  void deleteOpenTable(const string &table_name);
 
178
 
 
179
  uint32_t max_supported_keys()          const { return 1; }
 
180
  uint32_t max_supported_key_length()    const { return sizeof(uint64_t); }
 
181
  uint32_t max_supported_key_part_length() const { return sizeof(uint64_t); }
 
182
};
 
183
 
 
184
 
113
185
ArchiveShare *ArchiveEngine::findOpenTable(const string table_name)
114
186
{
115
187
  ArchiveMap::iterator find_iter=
132
204
}
133
205
 
134
206
 
135
 
void ArchiveEngine::doGetTableNames(drizzled::CachedDirectory &directory, 
136
 
                                    SchemaIdentifier&,
 
207
void ArchiveEngine::doGetTableNames(CachedDirectory &directory, 
 
208
                                    string&, 
137
209
                                    set<string>& set_of_names)
138
210
{
139
 
  drizzled::CachedDirectory::Entries entries= directory.getEntries();
 
211
  CachedDirectory::Entries entries= directory.getEntries();
140
212
 
141
 
  for (drizzled::CachedDirectory::Entries::iterator entry_iter= entries.begin(); 
 
213
  for (CachedDirectory::Entries::iterator entry_iter= entries.begin(); 
142
214
       entry_iter != entries.end(); ++entry_iter)
143
215
  {
144
 
    drizzled::CachedDirectory::Entry *entry= *entry_iter;
145
 
    const string *filename= &entry->filename;
 
216
    CachedDirectory::Entry *entry= *entry_iter;
 
217
    string *filename= &entry->filename;
146
218
 
147
219
    assert(filename->size());
148
220
 
149
221
    const char *ext= strchr(filename->c_str(), '.');
150
222
 
151
223
    if (ext == NULL || my_strcasecmp(system_charset_info, ext, ARZ) ||
152
 
        (filename->compare(0, strlen(TMP_FILE_PREFIX), TMP_FILE_PREFIX) == 0))
 
224
        is_prefix(filename->c_str(), TMP_FILE_PREFIX))
153
225
    {  }
154
226
    else
155
227
    {
165
237
}
166
238
 
167
239
 
168
 
int ArchiveEngine::doDropTable(Session&, TableIdentifier &identifier)
 
240
int ArchiveEngine::doDropTable(Session&,
 
241
                               const string table_path)
169
242
{
170
 
  string new_path(identifier.getPath());
 
243
  string new_path(table_path);
171
244
 
172
245
  new_path+= ARZ;
173
246
 
175
248
 
176
249
  if (error != 0)
177
250
  {
178
 
    error= errno= errno;
 
251
    error= my_errno= errno;
179
252
  }
180
253
 
181
254
  return error;
182
255
}
183
256
 
184
257
int ArchiveEngine::doGetTableDefinition(Session&,
185
 
                                        TableIdentifier &identifier,
186
 
                                        drizzled::message::Table &table_proto)
 
258
                                        const char* path,
 
259
                                        const char *,
 
260
                                        const char *,
 
261
                                        const bool,
 
262
                                        drizzled::message::Table *table_proto)
187
263
{
188
264
  struct stat stat_info;
189
265
  int error= ENOENT;
190
266
  string proto_path;
191
267
 
192
268
  proto_path.reserve(FN_REFLEN);
193
 
  proto_path.assign(identifier.getPath());
 
269
  proto_path.assign(path);
194
270
 
195
271
  proto_path.append(ARZ);
196
272
 
199
275
  else
200
276
    error= EEXIST;
201
277
 
 
278
  if (table_proto)
202
279
  {
203
280
    azio_stream proto_stream;
204
281
    char* proto_string;
214
291
 
215
292
    azread_frm(&proto_stream, proto_string);
216
293
 
217
 
    if (table_proto.ParseFromArray(proto_string, proto_stream.frm_length) == false)
 
294
    if (table_proto->ParseFromArray(proto_string, proto_stream.frm_length) == false)
218
295
      error= HA_ERR_CRASHED_ON_USAGE;
219
296
 
220
297
    azclose(&proto_stream);
224
301
  return error;
225
302
}
226
303
 
 
304
static ArchiveEngine *archive_engine= NULL;
 
305
 
 
306
/*
 
307
  Initialize the archive Cursor.
 
308
 
 
309
  SYNOPSIS
 
310
    archive_db_init()
 
311
    void *
 
312
 
 
313
  RETURN
 
314
    false       OK
 
315
    true        Error
 
316
*/
 
317
 
 
318
static int archive_db_init(drizzled::plugin::Registry &registry)
 
319
{
 
320
 
 
321
  pthread_mutex_init(&archive_mutex, MY_MUTEX_INIT_FAST);
 
322
  archive_engine= new ArchiveEngine(engine_name);
 
323
  registry.add(archive_engine);
 
324
 
 
325
  /* When the engine starts up set the first version */
 
326
  global_version= 1;
 
327
 
 
328
  return false;
 
329
}
 
330
 
 
331
/*
 
332
  Release the archive Cursor.
 
333
 
 
334
  SYNOPSIS
 
335
    archive_db_done()
 
336
    void
 
337
 
 
338
  RETURN
 
339
    false       OK
 
340
*/
 
341
 
 
342
static int archive_db_done(drizzled::plugin::Registry &registry)
 
343
{
 
344
  registry.remove(archive_engine);
 
345
  delete archive_engine;
 
346
 
 
347
  pthread_mutex_destroy(&archive_mutex);
 
348
 
 
349
  return 0;
 
350
}
 
351
 
227
352
 
228
353
ha_archive::ha_archive(drizzled::plugin::StorageEngine &engine_arg,
229
354
                       TableShare &table_arg)
233
358
  buffer.set((char *)byte_buffer, IO_SIZE, system_charset_info);
234
359
 
235
360
  /* The size of the offset value we will use for position() */
236
 
  ref_length= sizeof(internal::my_off_t);
 
361
  ref_length= sizeof(my_off_t);
237
362
  archive_reader_open= false;
238
363
}
239
364
 
264
389
{
265
390
  memset(&archive_write, 0, sizeof(azio_stream));     /* Archive file we are working with */
266
391
  table_name.append(name);
267
 
  internal::fn_format(data_file_name, table_name.c_str(), "",
 
392
  fn_format(data_file_name, table_name.c_str(), "",
268
393
            ARZ, MY_REPLACE_EXT | MY_UNPACK_FILENAME);
269
394
  /*
270
395
    We will use this lock for rows.
285
410
  */
286
411
  if (archive_write_open == true)
287
412
    (void)azclose(&archive_write);
288
 
  pthread_mutex_destroy(&archive_mutex);
289
413
}
290
414
 
291
415
bool ArchiveShare::prime(uint64_t *auto_increment)
374
498
  {
375
499
    ArchiveEngine *a_engine= static_cast<ArchiveEngine *>(engine);
376
500
    a_engine->deleteOpenTable(share->table_name);
377
 
    delete share;
 
501
     delete share;
378
502
  }
379
503
  pthread_mutex_unlock(&archive_mutex);
380
504
 
414
538
  {
415
539
    az_method method;
416
540
 
417
 
    switch (archive_aio_state())
 
541
    switch (archive_use_aio)
418
542
    {
419
543
    case false:
420
544
      method= AZ_METHOD_BLOCK;
527
651
  of creation.
528
652
*/
529
653
 
530
 
int ArchiveEngine::doCreateTable(Session &,
 
654
int ArchiveEngine::doCreateTable(Session *,
 
655
                                 const char *table_name,
531
656
                                 Table& table_arg,
532
 
                                 drizzled::TableIdentifier &identifier,
533
657
                                 drizzled::message::Table& proto)
534
658
{
535
659
  char name_buff[FN_REFLEN];
561
685
  /*
562
686
    We reuse name_buff since it is available.
563
687
  */
564
 
  internal::fn_format(name_buff, identifier.getPath().c_str(), "", ARZ,
565
 
                      MY_REPLACE_EXT | MY_UNPACK_FILENAME);
 
688
  fn_format(name_buff, table_name, "", ARZ,
 
689
            MY_REPLACE_EXT | MY_UNPACK_FILENAME);
566
690
 
567
 
  errno= 0;
 
691
  my_errno= 0;
568
692
  if (azopen(&create_stream, name_buff, O_CREAT|O_RDWR,
569
693
             AZ_METHOD_BLOCK) == 0)
570
694
  {
702
826
  if (share->crashed)
703
827
    return(HA_ERR_CRASHED_ON_USAGE);
704
828
 
705
 
  ha_statistic_increment(&system_status_var::ha_write_count);
 
829
  ha_statistic_increment(&SSV::ha_write_count);
706
830
  pthread_mutex_lock(&share->mutex);
707
831
 
708
832
  if (share->archive_write_open == false)
936
1060
    return(HA_ERR_END_OF_FILE);
937
1061
  scan_rows--;
938
1062
 
939
 
  ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
 
1063
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
940
1064
  current_position= aztell(&archive);
941
1065
  rc= get_row(&archive, buf);
942
1066
 
954
1078
 
955
1079
void ha_archive::position(const unsigned char *)
956
1080
{
957
 
  internal::my_store_ptr(ref, ref_length, current_position);
 
1081
  my_store_ptr(ref, ref_length, current_position);
958
1082
  return;
959
1083
}
960
1084
 
968
1092
 
969
1093
int ha_archive::rnd_pos(unsigned char * buf, unsigned char *pos)
970
1094
{
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);
 
1095
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
 
1096
  current_position= (my_off_t)my_get_ptr(pos, ref_length);
973
1097
  if (azseek(&archive, (size_t)current_position, SEEK_SET) == (size_t)(-1L))
974
1098
    return(HA_ERR_CRASHED_ON_USAGE);
975
1099
  return(get_row(&archive, buf));
1019
1143
  azread_frm(&archive, proto_string);
1020
1144
 
1021
1145
  /* Lets create a file to contain the new data */
1022
 
  internal::fn_format(writer_filename, share->table_name.c_str(), "", ARN,
 
1146
  fn_format(writer_filename, share->table_name.c_str(), "", ARN,
1023
1147
            MY_REPLACE_EXT | MY_UNPACK_FILENAME);
1024
1148
 
1025
1149
  if (!(azopen(&writer, writer_filename, O_CREAT|O_RDWR, AZ_METHOD_BLOCK)))
1102
1226
  azclose(&archive);
1103
1227
 
1104
1228
  // make the file we just wrote be our data file
1105
 
  rc = internal::my_rename(writer_filename,share->data_file_name,MYF(0));
 
1229
  rc = my_rename(writer_filename,share->data_file_name,MYF(0));
1106
1230
 
1107
1231
  free(proto_string);
1108
1232
  return(rc);
1322
1446
  return;
1323
1447
}
1324
1448
 
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
 
}
 
1449
static DRIZZLE_SYSVAR_BOOL(aio, archive_use_aio,
 
1450
  PLUGIN_VAR_NOCMDOPT,
 
1451
  "Whether or not to use asynchronous IO.",
 
1452
  NULL, NULL, true);
 
1453
 
 
1454
static struct st_mysql_sys_var* archive_system_variables[]= {
 
1455
  DRIZZLE_SYSVAR(aio),
 
1456
  NULL
 
1457
};
 
1458
 
 
1459
drizzle_declare_plugin
 
1460
{
 
1461
  "ARCHIVE",
 
1462
  "3.5",
 
1463
  "Brian Aker, MySQL AB",
 
1464
  "Archive storage engine",
 
1465
  PLUGIN_LICENSE_GPL,
 
1466
  archive_db_init, /* Plugin Init */
 
1467
  archive_db_done, /* Plugin Deinit */
 
1468
  NULL,                       /* status variables                */
 
1469
  archive_system_variables,   /* system variables                */
 
1470
  NULL                        /* config options                  */
 
1471
}
 
1472
drizzle_declare_plugin_end;
1388
1473