~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/archive/ha_archive.cc

  • Committer: Brian Aker
  • Date: 2009-07-28 20:12:26 UTC
  • mfrom: (1093.1.32 captain)
  • Revision ID: brian@gaz-20090728201226-k94ilbrkkwet1fdx
Merge Stewart

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
#include "plugin/myisam/myisam.h"
22
22
#include "drizzled/table.h"
23
23
#include "drizzled/session.h"
 
24
#include <mysys/my_dir.h>
24
25
 
25
26
#include "ha_archive.h"
26
27
 
133
134
  NULL
134
135
};
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
 
136
217
class ArchiveEngine : public StorageEngine
137
218
{
138
219
public:
139
 
  ArchiveEngine(const string &name_arg) : StorageEngine(name_arg) {}
 
220
  ArchiveEngine(const string &name_arg) : StorageEngine(name_arg,
 
221
                                      HTON_FILE_BASED
 
222
                                    | HTON_HAS_DATA_DICTIONARY) {}
 
223
 
140
224
  virtual handler *create(TableShare *table,
141
225
                          MEM_ROOT *mem_root)
142
226
  {
147
231
    return ha_archive_exts;
148
232
  }
149
233
 
150
 
  int createTableImpl(Session *session, const char *table_name,
151
 
                      Table *table_arg, HA_CREATE_INFO *create_info);
 
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
  }
152
245
};
153
246
 
 
247
int ArchiveEngine::getTableProtoImplementation(const char* path,
 
248
                                         drizzled::message::Table *table_proto)
 
249
{
 
250
  struct stat stat_info;
 
251
  int error= 0;
 
252
  string proto_path;
 
253
 
 
254
  proto_path.reserve(FN_REFLEN);
 
255
  proto_path.assign(path);
 
256
 
 
257
  proto_path.append(ARZ);
 
258
 
 
259
  if (stat(proto_path.c_str(),&stat_info))
 
260
    return errno;
 
261
 
 
262
  if (table_proto)
 
263
  {
 
264
    azio_stream proto_stream;
 
265
    char* proto_string;
 
266
    if(azopen(&proto_stream, proto_path.c_str(), O_RDONLY, AZ_METHOD_BLOCK) == 0)
 
267
      return HA_ERR_CRASHED_ON_USAGE;
 
268
 
 
269
    proto_string= (char*)malloc(sizeof(char) * proto_stream.frm_length);
 
270
    if (proto_string == NULL)
 
271
    {
 
272
      azclose(&proto_stream);
 
273
      return ENOMEM;
 
274
    }
 
275
 
 
276
    azread_frm(&proto_stream, proto_string);
 
277
 
 
278
    if(table_proto->ParseFromArray(proto_string, proto_stream.frm_length) == false)
 
279
      error= HA_ERR_CRASHED_ON_USAGE;
 
280
 
 
281
    azclose(&proto_stream);
 
282
    free(proto_string);
 
283
  }
 
284
 
 
285
  return EEXIST;
 
286
}
 
287
 
154
288
static ArchiveEngine *archive_engine= NULL;
155
289
 
156
290
/*
506
640
  of creation.
507
641
*/
508
642
 
509
 
int ArchiveEngine::createTableImpl(Session *session, const char *table_name,
510
 
                                   Table *table_arg,
511
 
                                   HA_CREATE_INFO *create_info)
 
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)
512
648
{
513
649
  char name_buff[FN_REFLEN];
514
650
  char linkname[FN_REFLEN];
515
651
  int error= 0;
516
652
  azio_stream create_stream;            /* Archive file we are working with */
517
 
  FILE *frm_file;                   /* File handler for readers */
518
 
  struct stat file_stat;
519
 
  unsigned char *frm_ptr;
520
 
  int r;
521
653
  uint64_t auto_increment_value;
 
654
  string serialized_proto;
522
655
 
523
656
  auto_increment_value= create_info->auto_increment_value;
524
657
 
557
690
    linkname[0]= 0;
558
691
  }
559
692
 
560
 
  /*
561
 
    There is a chance that the file was "discovered". In this case
562
 
    just use whatever file is there.
563
 
  */
564
 
  r= stat(name_buff, &file_stat);
565
 
  if (r == -1 && errno!=ENOENT)
566
 
  {
567
 
    return errno;
568
 
  }
569
 
  if (!r)
570
 
    return HA_ERR_TABLE_EXIST;
571
 
 
572
693
  my_errno= 0;
573
 
  if (!(azopen(&create_stream, name_buff, O_CREAT|O_RDWR,
574
 
               AZ_METHOD_BLOCK)))
 
694
  if (azopen(&create_stream, name_buff, O_CREAT|O_RDWR,
 
695
             AZ_METHOD_BLOCK) == 0)
575
696
  {
576
697
    error= errno;
577
698
    goto error2;
580
701
  if (linkname[0])
581
702
    if(symlink(name_buff, linkname) != 0)
582
703
      goto error2;
583
 
  fn_format(name_buff, table_name, "", ".frm",
584
 
            MY_REPLACE_EXT | MY_UNPACK_FILENAME);
585
 
 
586
 
  /*
587
 
    Here is where we open up the frm and pass it to archive to store
588
 
  */
589
 
  if ((frm_file= fopen(name_buff, "r")) > 0)
590
 
  {
591
 
    if (fstat(fileno(frm_file), &file_stat))
592
 
    {
593
 
      if ((uint64_t)file_stat.st_size > SIZE_MAX)
594
 
      {
595
 
        error= ENOMEM;
596
 
        goto error2;
597
 
      }
598
 
      frm_ptr= (unsigned char *)malloc((size_t)file_stat.st_size);
599
 
      if (frm_ptr)
600
 
      {
601
 
        size_t length_io;
602
 
        length_io= read(fileno(frm_file), frm_ptr, (size_t)file_stat.st_size);
603
 
 
604
 
        if (length_io != (size_t)file_stat.st_size)
605
 
        {
606
 
          free(frm_ptr);
607
 
          goto error2;
608
 
        }
609
 
 
610
 
        length_io= azwrite_frm(&create_stream, (char *)frm_ptr, (size_t)file_stat.st_size);
611
 
 
612
 
        if (length_io != (size_t)file_stat.st_size)
613
 
        {
614
 
          free(frm_ptr);
615
 
          goto error2;
616
 
        }
617
 
 
618
 
        free(frm_ptr);
619
 
      }
620
 
    }
621
 
    fclose(frm_file);
622
 
  }
 
704
 
 
705
  proto->SerializeToString(&serialized_proto);
 
706
 
 
707
  if (azwrite_frm(&create_stream, serialized_proto.c_str(),
 
708
                  serialized_proto.length()))
 
709
    goto error2;
623
710
 
624
711
  if (create_info->comment.str)
625
712
  {
1049
1136
    share->archive_write_open= false;
1050
1137
  }
1051
1138
 
 
1139
  char* proto_string;
 
1140
  proto_string= (char*)malloc(sizeof(char) * archive.frm_length);
 
1141
  if (proto_string == NULL)
 
1142
  {
 
1143
    return ENOMEM;
 
1144
  }
 
1145
  azread_frm(&archive, proto_string);
 
1146
 
1052
1147
  /* Lets create a file to contain the new data */
1053
1148
  fn_format(writer_filename, share->table_name.c_str(), "", ARN,
1054
1149
            MY_REPLACE_EXT | MY_UNPACK_FILENAME);
1055
1150
 
1056
1151
  if (!(azopen(&writer, writer_filename, O_CREAT|O_RDWR, AZ_METHOD_BLOCK)))
 
1152
  {
 
1153
    free(proto_string);
1057
1154
    return(HA_ERR_CRASHED_ON_USAGE);
 
1155
  }
 
1156
 
 
1157
  azwrite_frm(&writer, proto_string, archive.frm_length);
1058
1158
 
1059
1159
  /*
1060
1160
    An extended rebuild is a lot more effort. We open up each row and re-record it.
1130
1230
  // make the file we just wrote be our data file
1131
1231
  rc = my_rename(writer_filename,share->data_file_name,MYF(0));
1132
1232
 
1133
 
 
 
1233
  free(proto_string);
1134
1234
  return(rc);
1135
1235
error:
 
1236
  free(proto_string);
1136
1237
  azclose(&writer);
1137
1238
 
1138
1239
  return(rc);