~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2003 MySQL AB
2
3
  This program is free software; you can redistribute it and/or modify
4
  it under the terms of the GNU General Public License as published by
5
  the Free Software Foundation; version 2 of the License.
6
7
  This program is distributed in the hope that it will be useful,
8
  but WITHOUT ANY WARRANTY; without even the implied warranty of
9
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
  GNU General Public License for more details.
11
12
  You should have received a copy of the GNU General Public License
13
  along with this program; if not, write to the Free Software
14
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
16
971.1.55 by Monty Taylor
Removed now meaningless plugin_type.
17
#include "drizzled/server_includes.h"
18
#include "drizzled/field.h"
19
#include "drizzled/field/blob.h"
20
#include "drizzled/field/timestamp.h"
992.1.25 by Monty Taylor
Moved myisam to new plugin system.
21
#include "plugin/myisam/myisam.h"
971.1.55 by Monty Taylor
Removed now meaningless plugin_type.
22
#include "drizzled/table.h"
23
#include "drizzled/session.h"
960.2.41 by Monty Taylor
Made StorageEngine name private. Added constructor param and accessor method.
24
992.1.29 by Monty Taylor
Migrated archive.
25
#include "ha_archive.h"
960.2.41 by Monty Taylor
Made StorageEngine name private. Added constructor param and accessor method.
26
875 by Brian Aker
Remove my_open() call for Archive.
27
#include <stdio.h>
960.2.41 by Monty Taylor
Made StorageEngine name private. Added constructor param and accessor method.
28
#include <string>
983 by Brian Aker
Modified Archive to use std:map
29
#include <map>
960.2.41 by Monty Taylor
Made StorageEngine name private. Added constructor param and accessor method.
30
31
using namespace std;
32
33
static const string engine_name("ARCHIVE");
1 by brian
clean slate
34
35
/*
584.5.1 by Monty Taylor
Removed field includes from field.h.
36
  First, if you want to understand storage engines you should look at
37
  ha_example.cc and ha_example.h.
1 by brian
clean slate
38
39
  This example was written as a test case for a customer who needed
40
  a storage engine without indexes that could compress data very well.
41
  So, welcome to a completely compressed storage engine. This storage
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
42
  engine only does inserts. No replace, deletes, or updates. All reads are
1 by brian
clean slate
43
  complete table scans. Compression is done through a combination of packing
44
  and making use of the zlib library
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
45
1 by brian
clean slate
46
  We keep a file pointer open for each instance of ha_archive for each read
47
  but for writes we keep one open file handle just for that. We flush it
48
  only if we have a read occur. azip handles compressing lots of records
49
  at once much better then doing lots of little records between writes.
50
  It is possible to not lock on writes but this would then mean we couldn't
51
  handle bulk inserts as well (that is if someone was trying to read at
52
  the same time since we would want to flush).
53
54
  A "meta" file is kept alongside the data file. This file serves two purpose.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
55
  The first purpose is to track the number of rows in the table. The second
56
  purpose is to determine if the table was closed properly or not. When the
57
  meta file is first opened it is marked as dirty. It is opened when the table
58
  itself is opened for writing. When the table is closed the new count for rows
59
  is written to the meta file and the file is marked as clean. If the meta file
60
  is opened and it is marked as dirty, it is assumed that a crash occured. At
1 by brian
clean slate
61
  this point an error occurs and the user is told to rebuild the file.
62
  A rebuild scans the rows and rewrites the meta file. If corruption is found
63
  in the data file then the meta file is not repaired.
64
65
  At some point a recovery method for such a drastic case needs to be divised.
66
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
67
  Locks are row level, and you will get a consistant read.
1 by brian
clean slate
68
69
  For performance as far as table scans go it is quite fast. I don't have
70
  good numbers but locally it has out performed both Innodb and MyISAM. For
71
  Innodb the question will be if the table can be fit into the buffer
72
  pool. For MyISAM its a question of how much the file system caches the
73
  MyISAM file. With enough free memory MyISAM is faster. Its only when the OS
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
74
  doesn't have enough memory to cache entire table that archive turns out
75
  to be any faster.
1 by brian
clean slate
76
77
  Examples between MyISAM (packed) and Archive.
78
79
  Table with 76695844 identical rows:
80
  29680807 a_archive.ARZ
81
  920350317 a.MYD
82
83
84
  Table with 8991478 rows (all of Slashdot's comments):
85
  1922964506 comment_archive.ARZ
86
  2944970297 comment_text.MYD
87
88
89
  TODO:
90
   Allow users to set compression level.
91
   Allow adjustable block size.
92
   Implement versioning, should be easy.
93
   Allow for errors, find a way to mark bad rows.
94
   Add optional feature so that rows can be flushed at interval (which will cause less
95
     compression but may speed up ordered searches).
96
   Checkpoint the meta file to allow for faster rebuilds.
97
   Option to allow for dirty reads, this would lower the sync calls, which would make
98
     inserts a lot faster, but would mean highly arbitrary reads.
99
100
    -Brian
101
*/
102
103
/* Variables for archive share methods */
983 by Brian Aker
Modified Archive to use std:map
104
pthread_mutex_t archive_mutex= PTHREAD_MUTEX_INITIALIZER;
105
1002 by Brian Aker
Refactored out the share to being an object (playing with the structure to
106
std::map<const char *, ArchiveShare *> archive_open_tables;
983 by Brian Aker
Modified Archive to use std:map
107
1 by brian
clean slate
108
static unsigned int global_version;
109
110
/* The file extension */
111
#define ARZ ".ARZ"               // The data file
112
#define ARN ".ARN"               // Files used during an optimize call
113
114
115
278 by Brian Aker
Fixed my_bool issue in options.
116
static bool archive_use_aio= false;
1 by brian
clean slate
117
118
/*
119
  Number of rows that will force a bulk insert.
120
*/
121
#define ARCHIVE_MIN_ROWS_TO_USE_BULK_INSERT 2
122
123
/*
124
  Size of header used for row
125
*/
126
#define ARCHIVE_ROW_HEADER_SIZE 4
127
1039.3.1 by Stewart Smith
move bas_ext to StorageEngine instead of handler
128
/*
129
  We just implement one additional file extension.
130
*/
131
static const char *ha_archive_exts[] = {
132
  ARZ,
133
  NULL
134
};
135
960.2.28 by Monty Taylor
Updated archive to new StorageEngine clas.
136
class ArchiveEngine : public StorageEngine
1 by brian
clean slate
137
{
960.2.41 by Monty Taylor
Made StorageEngine name private. Added constructor param and accessor method.
138
public:
139
  ArchiveEngine(const string &name_arg) : StorageEngine(name_arg) {}
1000.1.3 by Brian Aker
Renamed TABLE_SHARE to TableShare
140
  virtual handler *create(TableShare *table,
960.2.28 by Monty Taylor
Updated archive to new StorageEngine clas.
141
                          MEM_ROOT *mem_root)
142
  {
960.2.38 by Monty Taylor
Removed extraneous send myself to myself argument.
143
    return new (mem_root) ha_archive(this, table);
960.2.28 by Monty Taylor
Updated archive to new StorageEngine clas.
144
  }
1039.3.1 by Stewart Smith
move bas_ext to StorageEngine instead of handler
145
146
  const char **bas_ext() const {
147
    return ha_archive_exts;
148
  }
1039.3.3 by Stewart Smith
Move handler::create to StorageEngine::create_table
149
1039.3.9 by Stewart Smith
beat identifiers with an ugly stick (otherwise known as "coding standards" and s/create_table/createTable/)
150
  int createTableImpl(Session *session, const char *table_name,
151
                      Table *table_arg, HA_CREATE_INFO *create_info);
960.2.28 by Monty Taylor
Updated archive to new StorageEngine clas.
152
};
1 by brian
clean slate
153
971.1.51 by Monty Taylor
New-style plugin registration now works.
154
static ArchiveEngine *archive_engine= NULL;
1 by brian
clean slate
155
156
/*
157
  Initialize the archive handler.
158
159
  SYNOPSIS
160
    archive_db_init()
161
    void *
162
163
  RETURN
163 by Brian Aker
Merge Monty's code.
164
    false       OK
165
    true        Error
1 by brian
clean slate
166
*/
167
1085.1.2 by Monty Taylor
Fixed -Wmissing-declarations
168
static int archive_db_init(PluginRegistry &registry)
1 by brian
clean slate
169
{
971.1.51 by Monty Taylor
New-style plugin registration now works.
170
171
  pthread_mutex_init(&archive_mutex, MY_MUTEX_INIT_FAST);
172
  archive_engine= new ArchiveEngine(engine_name);
971.1.52 by Monty Taylor
Did the finalizers. Renamed plugin_registry.
173
  registry.add(archive_engine);
960.2.28 by Monty Taylor
Updated archive to new StorageEngine clas.
174
1 by brian
clean slate
175
  /* When the engine starts up set the first version */
176
  global_version= 1;
177
983 by Brian Aker
Modified Archive to use std:map
178
  return false;
1 by brian
clean slate
179
}
180
181
/*
182
  Release the archive handler.
183
184
  SYNOPSIS
185
    archive_db_done()
186
    void
187
188
  RETURN
163 by Brian Aker
Merge Monty's code.
189
    false       OK
1 by brian
clean slate
190
*/
191
1085.1.2 by Monty Taylor
Fixed -Wmissing-declarations
192
static int archive_db_done(PluginRegistry &registry)
1 by brian
clean slate
193
{
971.1.52 by Monty Taylor
Did the finalizers. Renamed plugin_registry.
194
  registry.remove(archive_engine);
960.2.28 by Monty Taylor
Updated archive to new StorageEngine clas.
195
  delete archive_engine;
196
398.1.10 by Monty Taylor
Actually removed VOID() this time.
197
  pthread_mutex_destroy(&archive_mutex);
1 by brian
clean slate
198
199
  return 0;
200
}
201
202
1000.1.3 by Brian Aker
Renamed TABLE_SHARE to TableShare
203
ha_archive::ha_archive(StorageEngine *engine_arg, TableShare *table_arg)
960.2.37 by Monty Taylor
More naming fixes.
204
  :handler(engine_arg, table_arg), delayed_insert(0), bulk_insert(0)
1 by brian
clean slate
205
{
206
  /* Set our original buffer from pre-allocated memory */
207
  buffer.set((char *)byte_buffer, IO_SIZE, system_charset_info);
208
209
  /* The size of the offset value we will use for position() */
210
  ref_length= sizeof(my_off_t);
163 by Brian Aker
Merge Monty's code.
211
  archive_reader_open= false;
1 by brian
clean slate
212
}
213
214
/*
215
  This method reads the header of a datafile and returns whether or not it was successful.
216
*/
217
int ha_archive::read_data_header(azio_stream *file_to_read)
218
{
219
  if (azread_init(file_to_read) == -1)
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
220
    return(HA_ERR_CRASHED_ON_USAGE);
1 by brian
clean slate
221
222
  if (file_to_read->version >= 3)
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
223
    return(0);
1 by brian
clean slate
224
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
225
  return(1);
1 by brian
clean slate
226
}
227
1002 by Brian Aker
Refactored out the share to being an object (playing with the structure to
228
ArchiveShare::ArchiveShare():
229
  use_count(0), archive_write_open(false), dirty(false), crashed(false),
230
  mean_rec_length(0), version(0), rows_recorded(0), version_rows(0)
231
{
232
  assert(1);
233
}
234
235
ArchiveShare::ArchiveShare(const char *name):
236
  use_count(0), archive_write_open(false), dirty(false), crashed(false),
237
  mean_rec_length(0), version(0), rows_recorded(0), version_rows(0)
238
{
239
  memset(&archive_write, 0, sizeof(azio_stream));     /* Archive file we are working with */
240
  table_name.append(name);
241
  fn_format(data_file_name, table_name.c_str(), "",
242
            ARZ, MY_REPLACE_EXT | MY_UNPACK_FILENAME);
243
  /*
244
    We will use this lock for rows.
245
  */
246
  pthread_mutex_init(&mutex,MY_MUTEX_INIT_FAST);
247
}
248
249
ArchiveShare::~ArchiveShare()
250
{
251
  thr_lock_delete(&lock);
252
  pthread_mutex_destroy(&mutex);
253
  /*
254
    We need to make sure we don't reset the crashed state.
255
    If we open a crashed file, wee need to close it as crashed unless
256
    it has been repaired.
257
    Since we will close the data down after this, we go on and count
258
    the flush on close;
259
  */
260
  if (archive_write_open == true)
261
    (void)azclose(&archive_write);
262
}
263
264
bool ArchiveShare::prime(uint64_t *auto_increment)
265
{
266
  azio_stream archive_tmp;
267
268
  /*
269
    We read the meta file, but do not mark it dirty. Since we are not
270
    doing a write we won't mark it dirty (and we won't open it for
271
    anything but reading... open it for write and we will generate null
272
    compression writes).
273
  */
274
  if (!(azopen(&archive_tmp, data_file_name, O_RDONLY,
275
               AZ_METHOD_BLOCK)))
276
    return false;
277
278
  *auto_increment= archive_tmp.auto_increment + 1;
279
  rows_recorded= (ha_rows)archive_tmp.rows;
280
  crashed= archive_tmp.dirty;
281
  if (version < global_version)
282
  {
283
    version_rows= rows_recorded;
284
    version= global_version;
285
  }
286
  azclose(&archive_tmp);
287
288
  return true;
289
}
290
1 by brian
clean slate
291
292
/*
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
293
  We create the shared memory space that we will use for the open table.
1 by brian
clean slate
294
  No matter what we try to get or create a share. This is so that a repair
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
295
  table operation can occur.
1 by brian
clean slate
296
297
  See ha_example.cc for a longer description.
298
*/
1002 by Brian Aker
Refactored out the share to being an object (playing with the structure to
299
ArchiveShare *ha_archive::get_share(const char *table_name, int *rc)
1 by brian
clean slate
300
{
482 by Brian Aker
Remove uint.
301
  uint32_t length;
1002 by Brian Aker
Refactored out the share to being an object (playing with the structure to
302
  map<const char *, ArchiveShare *> ::iterator find_iter;
1 by brian
clean slate
303
304
  pthread_mutex_lock(&archive_mutex);
305
  length=(uint) strlen(table_name);
306
1002 by Brian Aker
Refactored out the share to being an object (playing with the structure to
307
  find_iter= archive_open_tables.find(table_name);
983 by Brian Aker
Modified Archive to use std:map
308
309
  if (find_iter != archive_open_tables.end())
310
    share= (*find_iter).second;
311
  else
312
    share= NULL;
313
314
  if (!share)
1 by brian
clean slate
315
  {
1002 by Brian Aker
Refactored out the share to being an object (playing with the structure to
316
    share= new ArchiveShare(table_name);
1 by brian
clean slate
317
1002 by Brian Aker
Refactored out the share to being an object (playing with the structure to
318
    if (share == NULL)
1 by brian
clean slate
319
    {
320
      pthread_mutex_unlock(&archive_mutex);
321
      *rc= HA_ERR_OUT_OF_MEM;
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
322
      return(NULL);
1 by brian
clean slate
323
    }
324
1002 by Brian Aker
Refactored out the share to being an object (playing with the structure to
325
    if (share->prime(&stats.auto_increment_value) == false)
1 by brian
clean slate
326
    {
327
      pthread_mutex_unlock(&archive_mutex);
328
      *rc= HA_ERR_CRASHED_ON_REPAIR;
1002 by Brian Aker
Refactored out the share to being an object (playing with the structure to
329
      delete share;
330
331
      return NULL;
332
    }
333
334
    archive_open_tables[share->table_name.c_str()]= share; 
1 by brian
clean slate
335
    thr_lock_init(&share->lock);
336
  }
337
  share->use_count++;
338
  if (share->crashed)
339
    *rc= HA_ERR_CRASHED_ON_USAGE;
340
  pthread_mutex_unlock(&archive_mutex);
341
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
342
  return(share);
1 by brian
clean slate
343
}
344
345
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
346
/*
1 by brian
clean slate
347
  Free the share.
348
  See ha_example.cc for a description.
349
*/
350
int ha_archive::free_share()
351
{
352
  pthread_mutex_lock(&archive_mutex);
353
  if (!--share->use_count)
354
  {
1002 by Brian Aker
Refactored out the share to being an object (playing with the structure to
355
    archive_open_tables.erase(share->table_name.c_str());
356
    delete share;
1 by brian
clean slate
357
  }
358
  pthread_mutex_unlock(&archive_mutex);
359
1002 by Brian Aker
Refactored out the share to being an object (playing with the structure to
360
  return 0;
1 by brian
clean slate
361
}
362
363
int ha_archive::init_archive_writer()
364
{
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
365
  /*
1 by brian
clean slate
366
    It is expensive to open and close the data files and since you can't have
367
    a gzip file that can be both read and written we keep a writer open
368
    that is shared amoung all open tables.
369
  */
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
370
  if (!(azopen(&(share->archive_write), share->data_file_name,
492.1.14 by Monty Taylor
Removed O_BINARY and FILE_BINARY.
371
               O_RDWR, AZ_METHOD_BLOCK)))
1 by brian
clean slate
372
  {
163 by Brian Aker
Merge Monty's code.
373
    share->crashed= true;
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
374
    return(1);
1 by brian
clean slate
375
  }
163 by Brian Aker
Merge Monty's code.
376
  share->archive_write_open= true;
1 by brian
clean slate
377
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
378
  return(0);
1 by brian
clean slate
379
}
380
381
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
382
/*
1 by brian
clean slate
383
  No locks are required because it is associated with just one handler instance
384
*/
385
int ha_archive::init_archive_reader()
386
{
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
387
  /*
1 by brian
clean slate
388
    It is expensive to open and close the data files and since you can't have
389
    a gzip file that can be both read and written we keep a writer open
390
    that is shared amoung all open tables.
391
  */
163 by Brian Aker
Merge Monty's code.
392
  if (archive_reader_open == false)
1 by brian
clean slate
393
  {
394
    az_method method;
395
396
    switch (archive_use_aio)
397
    {
163 by Brian Aker
Merge Monty's code.
398
    case false:
1 by brian
clean slate
399
      method= AZ_METHOD_BLOCK;
400
      break;
163 by Brian Aker
Merge Monty's code.
401
    case true:
1 by brian
clean slate
402
      method= AZ_METHOD_AIO;
403
      break;
404
    default:
405
      method= AZ_METHOD_BLOCK;
406
    }
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
407
    if (!(azopen(&archive, share->data_file_name, O_RDONLY,
1 by brian
clean slate
408
                 method)))
409
    {
163 by Brian Aker
Merge Monty's code.
410
      share->crashed= true;
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
411
      return(1);
1 by brian
clean slate
412
    }
163 by Brian Aker
Merge Monty's code.
413
    archive_reader_open= true;
1 by brian
clean slate
414
  }
415
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
416
  return(0);
1 by brian
clean slate
417
}
418
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
419
/*
1 by brian
clean slate
420
  When opening a file we:
421
  Create/get our shared structure.
422
  Init out lock.
423
  We open the file we will read from.
424
*/
653 by Brian Aker
More solaris bits
425
int ha_archive::open(const char *name, int, uint32_t open_options)
1 by brian
clean slate
426
{
427
  int rc= 0;
428
  share= get_share(name, &rc);
429
430
  if (rc == HA_ERR_CRASHED_ON_USAGE && !(open_options & HA_OPEN_FOR_REPAIR))
431
  {
432
    /* purecov: begin inspected */
433
    free_share();
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
434
    return(rc);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
435
    /* purecov: end */
1 by brian
clean slate
436
  }
437
  else if (rc == HA_ERR_OUT_OF_MEM)
438
  {
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
439
    return(rc);
1 by brian
clean slate
440
  }
441
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
442
  assert(share);
1 by brian
clean slate
443
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
444
  record_buffer= create_record_buffer(table->s->reclength +
1 by brian
clean slate
445
                                      ARCHIVE_ROW_HEADER_SIZE);
446
447
  if (!record_buffer)
448
  {
449
    free_share();
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
450
    return(HA_ERR_OUT_OF_MEM);
1 by brian
clean slate
451
  }
452
453
  thr_lock_data_init(&share->lock, &lock, NULL);
454
455
  if (rc == HA_ERR_CRASHED_ON_USAGE && open_options & HA_OPEN_FOR_REPAIR)
456
  {
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
457
    return(0);
1 by brian
clean slate
458
  }
459
  else
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
460
    return(rc);
1 by brian
clean slate
461
}
462
463
464
/*
465
  Closes the file.
466
467
  SYNOPSIS
468
    close();
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
469
1 by brian
clean slate
470
  IMPLEMENTATION:
471
472
  We first close this storage engines file handle to the archive and
473
  then remove our reference count to the table (and possibly free it
474
  as well).
475
476
  RETURN
477
    0  ok
478
    1  Error
479
*/
480
481
int ha_archive::close(void)
482
{
483
  int rc= 0;
484
485
  destroy_record_buffer(record_buffer);
486
487
  /* First close stream */
163 by Brian Aker
Merge Monty's code.
488
  if (archive_reader_open == true)
1 by brian
clean slate
489
  {
490
    if (azclose(&archive))
491
      rc= 1;
492
  }
493
  /* then also close share */
494
  rc|= free_share();
495
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
496
  return(rc);
1 by brian
clean slate
497
}
498
499
500
/*
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
501
  We create our data file here. The format is pretty simple.
1 by brian
clean slate
502
  You can read about the format of the data file above.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
503
  Unlike other storage engines we do not "pack" our data. Since we
504
  are about to do a general compression, packing would just be a waste of
505
  CPU time. If the table has blobs they are written after the row in the order
1 by brian
clean slate
506
  of creation.
507
*/
508
1039.3.9 by Stewart Smith
beat identifiers with an ugly stick (otherwise known as "coding standards" and s/create_table/createTable/)
509
int ArchiveEngine::createTableImpl(Session *session, const char *table_name,
510
                                   Table *table_arg,
511
                                   HA_CREATE_INFO *create_info)
1 by brian
clean slate
512
{
513
  char name_buff[FN_REFLEN];
514
  char linkname[FN_REFLEN];
875 by Brian Aker
Remove my_open() call for Archive.
515
  int error= 0;
1 by brian
clean slate
516
  azio_stream create_stream;            /* Archive file we are working with */
875 by Brian Aker
Remove my_open() call for Archive.
517
  FILE *frm_file;                   /* File handler for readers */
15 by brian
Fix for stat, NETWARE removal
518
  struct stat file_stat;
481 by Brian Aker
Remove all of uchar.
519
  unsigned char *frm_ptr;
784.1.1 by Stewart Smith
fix ARCHIVE table creation and archive test
520
  int r;
1039.3.3 by Stewart Smith
Move handler::create to StorageEngine::create_table
521
  uint64_t auto_increment_value;
1 by brian
clean slate
522
1039.3.3 by Stewart Smith
Move handler::create to StorageEngine::create_table
523
  auto_increment_value= create_info->auto_increment_value;
1 by brian
clean slate
524
482 by Brian Aker
Remove uint.
525
  for (uint32_t key= 0; key < table_arg->sizeKeys(); key++)
1 by brian
clean slate
526
  {
527
    KEY *pos= table_arg->key_info+key;
528
    KEY_PART_INFO *key_part=     pos->key_part;
529
    KEY_PART_INFO *key_part_end= key_part + pos->key_parts;
530
531
    for (; key_part != key_part_end; key_part++)
532
    {
533
      Field *field= key_part->field;
534
535
      if (!(field->flags & AUTO_INCREMENT_FLAG))
536
      {
537
        error= -1;
538
        goto error;
539
      }
540
    }
541
  }
542
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
543
  /*
1 by brian
clean slate
544
    We reuse name_buff since it is available.
545
  */
546
  if (create_info->data_file_name && create_info->data_file_name[0] != '#')
547
  {
548
    fn_format(name_buff, create_info->data_file_name, "", ARZ,
549
              MY_REPLACE_EXT | MY_UNPACK_FILENAME);
1039.3.3 by Stewart Smith
Move handler::create to StorageEngine::create_table
550
    fn_format(linkname, table_name, "", ARZ,
1 by brian
clean slate
551
              MY_REPLACE_EXT | MY_UNPACK_FILENAME);
552
  }
553
  else
554
  {
1039.3.3 by Stewart Smith
Move handler::create to StorageEngine::create_table
555
    fn_format(name_buff, table_name, "", ARZ,
1 by brian
clean slate
556
              MY_REPLACE_EXT | MY_UNPACK_FILENAME);
557
    linkname[0]= 0;
558
  }
559
560
  /*
561
    There is a chance that the file was "discovered". In this case
562
    just use whatever file is there.
563
  */
784.1.1 by Stewart Smith
fix ARCHIVE table creation and archive test
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
  my_errno= 0;
573
  if (!(azopen(&create_stream, name_buff, O_CREAT|O_RDWR,
574
	       AZ_METHOD_BLOCK)))
575
  {
576
    error= errno;
577
    goto error2;
578
  }
579
580
  if (linkname[0])
1060.2.7 by Eric Lambert
-it appears that the result from symlink() in ha_archive can not be
581
    if(symlink(name_buff, linkname) != 0)
582
      goto error2;
1039.3.3 by Stewart Smith
Move handler::create to StorageEngine::create_table
583
  fn_format(name_buff, table_name, "", ".frm",
784.1.1 by Stewart Smith
fix ARCHIVE table creation and archive test
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
  */
875 by Brian Aker
Remove my_open() call for Archive.
589
  if ((frm_file= fopen(name_buff, "r")) > 0)
784.1.1 by Stewart Smith
fix ARCHIVE table creation and archive test
590
  {
875 by Brian Aker
Remove my_open() call for Archive.
591
    if (fstat(fileno(frm_file), &file_stat))
784.1.1 by Stewart Smith
fix ARCHIVE table creation and archive test
592
    {
779.3.21 by Monty Taylor
Fixed solaris fixes for linux. Oh, and I also seem to have fixed some more configure stuff.
593
      if ((uint64_t)file_stat.st_size > SIZE_MAX)
779.3.18 by Monty Taylor
Cleaned up warnings up through innodb.
594
      {
595
        error= ENOMEM;
596
        goto error2;
597
      }
598
      frm_ptr= (unsigned char *)malloc((size_t)file_stat.st_size);
784.1.1 by Stewart Smith
fix ARCHIVE table creation and archive test
599
      if (frm_ptr)
1 by brian
clean slate
600
      {
875 by Brian Aker
Remove my_open() call for Archive.
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
779.3.18 by Monty Taylor
Cleaned up warnings up through innodb.
618
	free(frm_ptr);
1 by brian
clean slate
619
      }
784.1.1 by Stewart Smith
fix ARCHIVE table creation and archive test
620
    }
875 by Brian Aker
Remove my_open() call for Archive.
621
    fclose(frm_file);
784.1.1 by Stewart Smith
fix ARCHIVE table creation and archive test
622
  }
623
624
  if (create_info->comment.str)
875 by Brian Aker
Remove my_open() call for Archive.
625
  {
626
    size_t write_length;
627
628
    write_length= azwrite_comment(&create_stream, create_info->comment.str,
629
                                  (unsigned int)create_info->comment.length);
630
631
    if (write_length == (size_t)create_info->comment.length)
632
      goto error2;
633
  }
784.1.1 by Stewart Smith
fix ARCHIVE table creation and archive test
634
635
  /*
636
    Yes you need to do this, because the starting value
637
    for the autoincrement may not be zero.
638
  */
1039.3.3 by Stewart Smith
Move handler::create to StorageEngine::create_table
639
  create_stream.auto_increment= auto_increment_value ?
640
    auto_increment_value - 1 : 0;
641
784.1.1 by Stewart Smith
fix ARCHIVE table creation and archive test
642
  if (azclose(&create_stream))
643
  {
644
    error= errno;
645
    goto error2;
646
  }
1 by brian
clean slate
647
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
648
  return(0);
1 by brian
clean slate
649
650
error2:
1039.3.12 by Stewart Smith
remove handler::ha_delete_table and have StorageEngine::deleteTable instead
651
  deleteTable(session, table_name);
1 by brian
clean slate
652
error:
653
  /* Return error number, if we got one */
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
654
  return(error ? error : -1);
1 by brian
clean slate
655
}
656
657
/*
658
  This is where the actual row is written out.
659
*/
481 by Brian Aker
Remove all of uchar.
660
int ha_archive::real_write_row(unsigned char *buf, azio_stream *writer)
1 by brian
clean slate
661
{
875 by Brian Aker
Remove my_open() call for Archive.
662
  off_t written;
1 by brian
clean slate
663
  unsigned int r_pack_length;
664
665
  /* We pack the row for writing */
666
  r_pack_length= pack_row(buf);
667
668
  written= azwrite_row(writer, record_buffer->buffer, r_pack_length);
669
  if (written != r_pack_length)
670
  {
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
671
    return(-1);
1 by brian
clean slate
672
  }
673
674
  if (!delayed_insert || !bulk_insert)
163 by Brian Aker
Merge Monty's code.
675
    share->dirty= true;
1 by brian
clean slate
676
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
677
  return(0);
1 by brian
clean slate
678
}
679
680
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
681
/*
1 by brian
clean slate
682
  Calculate max length needed for row. This includes
683
  the bytes required for the length in the header.
684
*/
685
653 by Brian Aker
More solaris bits
686
uint32_t ha_archive::max_row_length(const unsigned char *)
1 by brian
clean slate
687
{
327.1.1 by Brian Aker
First pass in encapsulating table (it is now an object, no longer a structure).
688
  uint32_t length= (uint32_t)(table->getRecordLength() + table->sizeFields()*2);
1 by brian
clean slate
689
  length+= ARCHIVE_ROW_HEADER_SIZE;
690
482 by Brian Aker
Remove uint.
691
  uint32_t *ptr, *end;
327.1.1 by Brian Aker
First pass in encapsulating table (it is now an object, no longer a structure).
692
  for (ptr= table->getBlobField(), end=ptr + table->sizeBlobFields();
1 by brian
clean slate
693
       ptr != end ;
694
       ptr++)
695
  {
696
      length += 2 + ((Field_blob*)table->field[*ptr])->get_length();
697
  }
698
699
  return length;
700
}
701
702
481 by Brian Aker
Remove all of uchar.
703
unsigned int ha_archive::pack_row(unsigned char *record)
1 by brian
clean slate
704
{
481 by Brian Aker
Remove all of uchar.
705
  unsigned char *ptr;
1 by brian
clean slate
706
707
  if (fix_rec_buff(max_row_length(record)))
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
708
    return(HA_ERR_OUT_OF_MEM); /* purecov: inspected */
1 by brian
clean slate
709
710
  /* Copy null bits */
711
  memcpy(record_buffer->buffer, record, table->s->null_bytes);
712
  ptr= record_buffer->buffer + table->s->null_bytes;
713
714
  for (Field **field=table->field ; *field ; field++)
715
  {
716
    if (!((*field)->is_null()))
717
      ptr= (*field)->pack(ptr, record + (*field)->offset(record));
718
  }
719
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
720
  return((unsigned int) (ptr - record_buffer->buffer));
1 by brian
clean slate
721
}
722
723
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
724
/*
1 by brian
clean slate
725
  Look at ha_archive::open() for an explanation of the row format.
726
  Here we just write out the row.
727
728
  Wondering about start_bulk_insert()? We don't implement it for
729
  archive since it optimizes for lots of writes. The only save
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
730
  for implementing start_bulk_insert() is that we could skip
1 by brian
clean slate
731
  setting dirty to true each time.
732
*/
481 by Brian Aker
Remove all of uchar.
733
int ha_archive::write_row(unsigned char *buf)
1 by brian
clean slate
734
{
735
  int rc;
481 by Brian Aker
Remove all of uchar.
736
  unsigned char *read_buf= NULL;
1 by brian
clean slate
737
  uint64_t temp_auto;
481 by Brian Aker
Remove all of uchar.
738
  unsigned char *record=  table->record[0];
1 by brian
clean slate
739
740
  if (share->crashed)
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
741
    return(HA_ERR_CRASHED_ON_USAGE);
1 by brian
clean slate
742
743
  ha_statistic_increment(&SSV::ha_write_count);
744
  pthread_mutex_lock(&share->mutex);
745
163 by Brian Aker
Merge Monty's code.
746
  if (share->archive_write_open == false)
1 by brian
clean slate
747
    if (init_archive_writer())
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
748
      return(HA_ERR_CRASHED_ON_USAGE);
1 by brian
clean slate
749
750
751
  if (table->next_number_field && record == table->record[0])
752
  {
753
    KEY *mkey= &table->s->key_info[0]; // We only support one key right now
754
    update_auto_increment();
755
    temp_auto= table->next_number_field->val_int();
756
757
    /*
758
      We don't support decremening auto_increment. They make the performance
759
      just cry.
760
    */
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
761
    if (temp_auto <= share->archive_write.auto_increment &&
1 by brian
clean slate
762
        mkey->flags & HA_NOSAME)
763
    {
764
      rc= HA_ERR_FOUND_DUPP_KEY;
765
      goto error;
766
    }
767
    else
768
    {
769
      if (temp_auto > share->archive_write.auto_increment)
770
        stats.auto_increment_value=
771
          (share->archive_write.auto_increment= temp_auto) + 1;
772
    }
773
  }
774
775
  /*
776
    Notice that the global auto_increment has been increased.
777
    In case of a failed row write, we will never try to reuse the value.
778
  */
779
  share->rows_recorded++;
780
  rc= real_write_row(buf,  &(share->archive_write));
781
error:
782
  pthread_mutex_unlock(&share->mutex);
783
  if (read_buf)
481 by Brian Aker
Remove all of uchar.
784
    free((unsigned char*) read_buf);
1 by brian
clean slate
785
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
786
  return(rc);
1 by brian
clean slate
787
}
788
789
653 by Brian Aker
More solaris bits
790
void ha_archive::get_auto_increment(uint64_t, uint64_t, uint64_t,
791
                                    uint64_t *first_value, uint64_t *nb_reserved_values)
1 by brian
clean slate
792
{
163 by Brian Aker
Merge Monty's code.
793
  *nb_reserved_values= UINT64_MAX;
1 by brian
clean slate
794
  *first_value= share->archive_write.auto_increment + 1;
795
}
796
797
/* Initialized at each key walk (called multiple times unlike rnd_init()) */
653 by Brian Aker
More solaris bits
798
int ha_archive::index_init(uint32_t keynr, bool)
1 by brian
clean slate
799
{
800
  active_index= keynr;
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
801
  return(0);
1 by brian
clean slate
802
}
803
804
805
/*
806
  No indexes, so if we get a request for an index search since we tell
807
  the optimizer that we have unique indexes, we scan
808
*/
481 by Brian Aker
Remove all of uchar.
809
int ha_archive::index_read(unsigned char *buf, const unsigned char *key,
482 by Brian Aker
Remove uint.
810
                             uint32_t key_len, enum ha_rkey_function find_flag)
1 by brian
clean slate
811
{
812
  int rc;
813
  rc= index_read_idx(buf, active_index, key, key_len, find_flag);
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
814
  return(rc);
1 by brian
clean slate
815
}
816
817
482 by Brian Aker
Remove uint.
818
int ha_archive::index_read_idx(unsigned char *buf, uint32_t index, const unsigned char *key,
653 by Brian Aker
More solaris bits
819
                               uint32_t key_len, enum ha_rkey_function)
1 by brian
clean slate
820
{
821
  int rc;
822
  bool found= 0;
823
  KEY *mkey= &table->s->key_info[index];
824
  current_k_offset= mkey->key_part->offset;
825
  current_key= key;
826
  current_key_len= key_len;
827
163 by Brian Aker
Merge Monty's code.
828
  rc= rnd_init(true);
1 by brian
clean slate
829
830
  if (rc)
831
    goto error;
832
833
  while (!(get_row(&archive, buf)))
834
  {
835
    if (!memcmp(current_key, buf + current_k_offset, current_key_len))
836
    {
837
      found= 1;
838
      break;
839
    }
840
  }
841
842
  if (found)
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
843
    return(0);
1 by brian
clean slate
844
845
error:
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
846
  return(rc ? rc : HA_ERR_END_OF_FILE);
1 by brian
clean slate
847
}
848
849
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
850
int ha_archive::index_next(unsigned char * buf)
851
{
1 by brian
clean slate
852
  bool found= 0;
853
854
  while (!(get_row(&archive, buf)))
855
  {
856
    if (!memcmp(current_key, buf+current_k_offset, current_key_len))
857
    {
858
      found= 1;
859
      break;
860
    }
861
  }
862
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
863
  return(found ? 0 : HA_ERR_END_OF_FILE);
1 by brian
clean slate
864
}
865
866
/*
867
  All calls that need to scan the table start with this method. If we are told
868
  that it is a table scan we rewind the file to the beginning, otherwise
869
  we assume the position will be set.
870
*/
871
872
int ha_archive::rnd_init(bool scan)
873
{
874
  if (share->crashed)
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
875
      return(HA_ERR_CRASHED_ON_USAGE);
1 by brian
clean slate
876
877
  init_archive_reader();
878
879
  /* We rewind the file so that we can read from the beginning if scan */
880
  if (scan)
881
  {
882
    if (read_data_header(&archive))
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
883
      return(HA_ERR_CRASHED_ON_USAGE);
1 by brian
clean slate
884
  }
885
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
886
  return(0);
1 by brian
clean slate
887
}
888
889
890
/*
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
891
  This is the method that is used to read a row. It assumes that the row is
1 by brian
clean slate
892
  positioned where you want it.
893
*/
481 by Brian Aker
Remove all of uchar.
894
int ha_archive::get_row(azio_stream *file_to_read, unsigned char *buf)
1 by brian
clean slate
895
{
896
  int rc;
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
897
1 by brian
clean slate
898
  if (file_to_read->version == ARCHIVE_VERSION)
899
    rc= get_row_version3(file_to_read, buf);
900
  else
901
    rc= -1;
902
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
903
  return(rc);
1 by brian
clean slate
904
}
905
906
/* Reallocate buffer if needed */
907
bool ha_archive::fix_rec_buff(unsigned int length)
908
{
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
909
  assert(record_buffer->buffer);
1 by brian
clean slate
910
911
  if (length > record_buffer->length)
912
  {
481 by Brian Aker
Remove all of uchar.
913
    unsigned char *newptr;
656.1.46 by Monty Taylor
More malloc return cleanups.
914
    if (!(newptr= (unsigned char *)realloc(record_buffer->buffer, length)))
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
915
      return(1);
1 by brian
clean slate
916
    record_buffer->buffer= newptr;
917
    record_buffer->length= length;
918
  }
919
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
920
  assert(length <= record_buffer->length);
1 by brian
clean slate
921
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
922
  return(0);
1 by brian
clean slate
923
}
924
481 by Brian Aker
Remove all of uchar.
925
int ha_archive::unpack_row(azio_stream *file_to_read, unsigned char *record)
1 by brian
clean slate
926
{
927
  unsigned int read;
928
  int error;
481 by Brian Aker
Remove all of uchar.
929
  const unsigned char *ptr;
1 by brian
clean slate
930
931
  read= azread_row(file_to_read, &error);
481 by Brian Aker
Remove all of uchar.
932
  ptr= (const unsigned char *)file_to_read->row_ptr;
1 by brian
clean slate
933
934
  if (error || read == 0)
935
  {
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
936
    return(-1);
1 by brian
clean slate
937
  }
938
939
  /* Copy null bits */
327.1.1 by Brian Aker
First pass in encapsulating table (it is now an object, no longer a structure).
940
  memcpy(record, ptr, table->getNullBytes());
941
  ptr+= table->getNullBytes();
1 by brian
clean slate
942
  for (Field **field=table->field ; *field ; field++)
943
  {
944
    if (!((*field)->is_null()))
945
    {
946
      ptr= (*field)->unpack(record + (*field)->offset(table->record[0]), ptr);
947
    }
948
  }
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
949
  return(0);
1 by brian
clean slate
950
}
951
952
481 by Brian Aker
Remove all of uchar.
953
int ha_archive::get_row_version3(azio_stream *file_to_read, unsigned char *buf)
1 by brian
clean slate
954
{
955
  int returnable= unpack_row(file_to_read, buf);
956
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
957
  return(returnable);
1 by brian
clean slate
958
}
959
960
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
961
/*
1 by brian
clean slate
962
  Called during ORDER BY. Its position is either from being called sequentially
963
  or by having had ha_archive::rnd_pos() called before it is called.
964
*/
965
481 by Brian Aker
Remove all of uchar.
966
int ha_archive::rnd_next(unsigned char *buf)
1 by brian
clean slate
967
{
968
  int rc;
969
970
  if (share->crashed)
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
971
      return(HA_ERR_CRASHED_ON_USAGE);
1 by brian
clean slate
972
973
  if (!scan_rows)
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
974
    return(HA_ERR_END_OF_FILE);
1 by brian
clean slate
975
  scan_rows--;
976
977
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
978
  current_position= aztell(&archive);
979
  rc= get_row(&archive, buf);
980
981
  table->status=rc ? STATUS_NOT_FOUND: 0;
982
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
983
  return(rc);
1 by brian
clean slate
984
}
985
986
987
/*
988
  Thanks to the table flag HA_REC_NOT_IN_SEQ this will be called after
989
  each call to ha_archive::rnd_next() if an ordering of the rows is
990
  needed.
991
*/
992
653 by Brian Aker
More solaris bits
993
void ha_archive::position(const unsigned char *)
1 by brian
clean slate
994
{
995
  my_store_ptr(ref, ref_length, current_position);
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
996
  return;
1 by brian
clean slate
997
}
998
999
1000
/*
1001
  This is called after a table scan for each row if the results of the
1002
  scan need to be ordered. It will take *pos and use it to move the
1003
  cursor in the file so that the next row that is called is the
1004
  correctly ordered row.
1005
*/
1006
481 by Brian Aker
Remove all of uchar.
1007
int ha_archive::rnd_pos(unsigned char * buf, unsigned char *pos)
1 by brian
clean slate
1008
{
1009
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
1010
  current_position= (my_off_t)my_get_ptr(pos, ref_length);
1011
  if (azseek(&archive, (size_t)current_position, SEEK_SET) == (size_t)(-1L))
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1012
    return(HA_ERR_CRASHED_ON_USAGE);
1013
  return(get_row(&archive, buf));
1 by brian
clean slate
1014
}
1015
1016
/*
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1017
  This method repairs the meta file. It does this by walking the datafile and
1 by brian
clean slate
1018
  rewriting the meta file. Currently it does this by calling optimize with
1019
  the extended flag.
1020
*/
520.1.22 by Brian Aker
Second pass of thd cleanup
1021
int ha_archive::repair(Session* session, HA_CHECK_OPT* check_opt)
1 by brian
clean slate
1022
{
1023
  check_opt->flags= T_EXTEND;
520.1.22 by Brian Aker
Second pass of thd cleanup
1024
  int rc= optimize(session, check_opt);
1 by brian
clean slate
1025
1026
  if (rc)
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1027
    return(HA_ERR_CRASHED_ON_REPAIR);
1 by brian
clean slate
1028
163 by Brian Aker
Merge Monty's code.
1029
  share->crashed= false;
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1030
  return(0);
1 by brian
clean slate
1031
}
1032
1033
/*
1034
  The table can become fragmented if data was inserted, read, and then
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1035
  inserted again. What we do is open up the file and recompress it completely.
1 by brian
clean slate
1036
*/
653 by Brian Aker
More solaris bits
1037
int ha_archive::optimize(Session *, HA_CHECK_OPT *)
1 by brian
clean slate
1038
{
1039
  int rc= 0;
1040
  azio_stream writer;
1041
  char writer_filename[FN_REFLEN];
1042
1043
  init_archive_reader();
1044
1045
  // now we close both our writer and our reader for the rename
1046
  if (share->archive_write_open)
1047
  {
1048
    azclose(&(share->archive_write));
163 by Brian Aker
Merge Monty's code.
1049
    share->archive_write_open= false;
1 by brian
clean slate
1050
  }
1051
1052
  /* Lets create a file to contain the new data */
1002 by Brian Aker
Refactored out the share to being an object (playing with the structure to
1053
  fn_format(writer_filename, share->table_name.c_str(), "", ARN,
1 by brian
clean slate
1054
            MY_REPLACE_EXT | MY_UNPACK_FILENAME);
1055
492.1.14 by Monty Taylor
Removed O_BINARY and FILE_BINARY.
1056
  if (!(azopen(&writer, writer_filename, O_CREAT|O_RDWR, AZ_METHOD_BLOCK)))
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1057
    return(HA_ERR_CRASHED_ON_USAGE);
1 by brian
clean slate
1058
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1059
  /*
1060
    An extended rebuild is a lot more effort. We open up each row and re-record it.
1061
    Any dead rows are removed (aka rows that may have been partially recorded).
1 by brian
clean slate
1062
1063
    As of Archive format 3, this is the only type that is performed, before this
1064
    version it was just done on T_EXTEND
1065
  */
1066
  if (1)
1067
  {
1068
    /*
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1069
      Now we will rewind the archive file so that we are positioned at the
1 by brian
clean slate
1070
      start of the file.
1071
    */
1072
    azflush(&archive, Z_SYNC_FLUSH);
1073
    rc= read_data_header(&archive);
1074
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1075
    /*
1 by brian
clean slate
1076
      On success of writing out the new header, we now fetch each row and
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1077
      insert it into the new archive file.
1 by brian
clean slate
1078
    */
1079
    if (!rc)
1080
    {
53.2.2 by Monty Taylor
Updated everything that needs updating to compile with -std=gnu99 -pedantic
1081
      uint64_t x;
1082
      uint64_t rows_restored;
1 by brian
clean slate
1083
      share->rows_recorded= 0;
1084
      stats.auto_increment_value= 1;
1085
      share->archive_write.auto_increment= 0;
1086
1087
      rows_restored= archive.rows;
1088
1089
      for (x= 0; x < rows_restored ; x++)
1090
      {
1091
        rc= get_row(&archive, table->record[0]);
1092
1093
        if (rc != 0)
1094
          break;
1095
1096
        real_write_row(table->record[0], &writer);
1097
        /*
1098
          Long term it should be possible to optimize this so that
1099
          it is not called on each row.
1100
        */
1101
        if (table->found_next_number_field)
1102
        {
1103
          Field *field= table->found_next_number_field;
1089.1.3 by Brian Aker
Fix protobuf to release memory. Add in assert() for wrong column usage. Fix
1104
1105
          /* Since we will need to use field to translate, we need to flip its read bit */
1106
          field->setReadSet();
1107
1 by brian
clean slate
1108
          uint64_t auto_value=
1109
            (uint64_t) field->val_int(table->record[0] +
1110
                                       field->offset(table->record[0]));
1111
          if (share->archive_write.auto_increment < auto_value)
1112
            stats.auto_increment_value=
1113
              (share->archive_write.auto_increment= auto_value) + 1;
1114
        }
1115
      }
1116
      share->rows_recorded= (ha_rows)writer.rows;
1117
    }
1118
1119
    if (rc && rc != HA_ERR_END_OF_FILE)
1120
    {
1121
      goto error;
1122
    }
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1123
  }
1 by brian
clean slate
1124
1125
  azclose(&writer);
163 by Brian Aker
Merge Monty's code.
1126
  share->dirty= false;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1127
1 by brian
clean slate
1128
  azclose(&archive);
1129
1130
  // make the file we just wrote be our data file
1131
  rc = my_rename(writer_filename,share->data_file_name,MYF(0));
1132
1133
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1134
  return(rc);
1 by brian
clean slate
1135
error:
1136
  azclose(&writer);
1137
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1138
  return(rc);
1 by brian
clean slate
1139
}
1140
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1141
/*
1 by brian
clean slate
1142
  Below is an example of how to setup row level locking.
1143
*/
520.1.22 by Brian Aker
Second pass of thd cleanup
1144
THR_LOCK_DATA **ha_archive::store_lock(Session *session,
1 by brian
clean slate
1145
                                       THR_LOCK_DATA **to,
1146
                                       enum thr_lock_type lock_type)
1147
{
1008.1.1 by Brian Aker
Remove dead lock code around delayed INSERT.
1148
  delayed_insert= false;
1 by brian
clean slate
1149
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1150
  if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK)
1 by brian
clean slate
1151
  {
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1152
    /*
1 by brian
clean slate
1153
      Here is where we get into the guts of a row level lock.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1154
      If TL_UNLOCK is set
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
1155
      If we are not doing a LOCK Table or DISCARD/IMPORT
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1156
      TABLESPACE, then allow multiple writers
1 by brian
clean slate
1157
    */
1158
1159
    if ((lock_type >= TL_WRITE_CONCURRENT_INSERT &&
1054.1.6 by Brian Aker
Removed internal logic/dead variables for LOCK TABLES.
1160
         lock_type <= TL_WRITE)
520.1.22 by Brian Aker
Second pass of thd cleanup
1161
        && !session_tablespace_op(session))
1 by brian
clean slate
1162
      lock_type = TL_WRITE_ALLOW_WRITE;
1163
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1164
    /*
1 by brian
clean slate
1165
      In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
1166
      MySQL would use the lock TL_READ_NO_INSERT on t2, and that
1167
      would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
1168
      to t2. Convert the lock to a normal read lock to allow
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1169
      concurrent inserts to t2.
1 by brian
clean slate
1170
    */
1171
1054.1.6 by Brian Aker
Removed internal logic/dead variables for LOCK TABLES.
1172
    if (lock_type == TL_READ_NO_INSERT)
1 by brian
clean slate
1173
      lock_type = TL_READ;
1174
1175
    lock.type=lock_type;
1176
  }
1177
1178
  *to++= &lock;
1179
1180
  return to;
1181
}
1182
1183
void ha_archive::update_create_info(HA_CREATE_INFO *create_info)
1184
{
1185
  ha_archive::info(HA_STATUS_AUTO);
1186
  if (!(create_info->used_fields & HA_CREATE_USED_AUTO))
1187
  {
1188
    create_info->auto_increment_value= stats.auto_increment_value;
1189
  }
1190
1060.2.1 by Eric Lambert
-replace calls to my_readlink with readlink
1191
  ssize_t sym_link_size= readlink(share->data_file_name,share->real_path,FN_REFLEN-1);
1192
  if (sym_link_size >= 0) {
1193
    share->real_path[sym_link_size]= '\0';
1 by brian
clean slate
1194
    create_info->data_file_name= share->real_path;
1060.2.1 by Eric Lambert
-replace calls to my_readlink with readlink
1195
  }
1 by brian
clean slate
1196
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1197
  return;
1 by brian
clean slate
1198
}
1199
1200
1201
/*
1202
  Hints for optimizer, see ha_tina for more information
1203
*/
482 by Brian Aker
Remove uint.
1204
int ha_archive::info(uint32_t flag)
1 by brian
clean slate
1205
{
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1206
  /*
1 by brian
clean slate
1207
    If dirty, we lock, and then reset/flush the data.
1208
    I found that just calling azflush() doesn't always work.
1209
  */
1210
  pthread_mutex_lock(&share->mutex);
163 by Brian Aker
Merge Monty's code.
1211
  if (share->dirty == true)
1 by brian
clean slate
1212
  {
1213
    azflush(&(share->archive_write), Z_SYNC_FLUSH);
1214
    share->rows_recorded= share->archive_write.rows;
163 by Brian Aker
Merge Monty's code.
1215
    share->dirty= false;
1 by brian
clean slate
1216
    if (share->version < global_version)
1217
    {
1218
      share->version_rows= share->rows_recorded;
1219
      share->version= global_version;
1220
    }
1221
1222
  }
1223
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1224
  /*
1 by brian
clean slate
1225
    This should be an accurate number now, though bulk and delayed inserts can
1226
    cause the number to be inaccurate.
1227
  */
1228
  stats.records= share->rows_recorded;
1229
  pthread_mutex_unlock(&share->mutex);
1230
1231
  scan_rows= stats.records;
1232
  stats.deleted= 0;
1233
1234
  /* Costs quite a bit more to get all information */
1235
  if (flag & HA_STATUS_TIME)
1236
  {
15 by brian
Fix for stat, NETWARE removal
1237
    struct stat file_stat;  // Stat information for the data file
1 by brian
clean slate
1238
398.1.10 by Monty Taylor
Actually removed VOID() this time.
1239
    stat(share->data_file_name, &file_stat);
1 by brian
clean slate
1240
327.1.1 by Brian Aker
First pass in encapsulating table (it is now an object, no longer a structure).
1241
    stats.mean_rec_length= table->getRecordLength()+ buffer.alloced_length();
1 by brian
clean slate
1242
    stats.data_file_length= file_stat.st_size;
1243
    stats.create_time= file_stat.st_ctime;
1244
    stats.update_time= file_stat.st_mtime;
1245
    stats.max_data_file_length= share->rows_recorded * stats.mean_rec_length;
1246
  }
1247
  stats.delete_length= 0;
1248
  stats.index_file_length=0;
1249
1250
  if (flag & HA_STATUS_AUTO)
1251
  {
1252
    init_archive_reader();
1253
    pthread_mutex_lock(&share->mutex);
1254
    azflush(&archive, Z_SYNC_FLUSH);
1255
    pthread_mutex_unlock(&share->mutex);
1256
    stats.auto_increment_value= archive.auto_increment + 1;
1257
  }
1258
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1259
  return(0);
1 by brian
clean slate
1260
}
1261
1262
1263
/*
1264
  This method tells us that a bulk insert operation is about to occur. We set
1265
  a flag which will keep write_row from saying that its data is dirty. This in
1266
  turn will keep selects from causing a sync to occur.
1267
  Basically, yet another optimizations to keep compression working well.
1268
*/
1269
void ha_archive::start_bulk_insert(ha_rows rows)
1270
{
1271
  if (!rows || rows >= ARCHIVE_MIN_ROWS_TO_USE_BULK_INSERT)
163 by Brian Aker
Merge Monty's code.
1272
    bulk_insert= true;
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1273
  return;
1 by brian
clean slate
1274
}
1275
1276
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1277
/*
1 by brian
clean slate
1278
  Other side of start_bulk_insert, is end_bulk_insert. Here we turn off the bulk insert
1279
  flag, and set the share dirty so that the next select will call sync for us.
1280
*/
1281
int ha_archive::end_bulk_insert()
1282
{
163 by Brian Aker
Merge Monty's code.
1283
  bulk_insert= false;
1284
  share->dirty= true;
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1285
  return(0);
1 by brian
clean slate
1286
}
1287
1288
/*
1289
  We cancel a truncate command. The only way to delete an archive table is to drop it.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1290
  This is done for security reasons. In a later version we will enable this by
1 by brian
clean slate
1291
  allowing the user to select a different row format.
1292
*/
1293
int ha_archive::delete_all_rows()
1294
{
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1295
  return(HA_ERR_WRONG_COMMAND);
1 by brian
clean slate
1296
}
1297
1298
/*
1299
  We just return state if asked.
1300
*/
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1301
bool ha_archive::is_crashed() const
1 by brian
clean slate
1302
{
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1303
  return(share->crashed);
1 by brian
clean slate
1304
}
1305
1306
/*
1307
  Simple scan of the tables to make sure everything is ok.
1308
*/
1309
653 by Brian Aker
More solaris bits
1310
int ha_archive::check(Session* session, HA_CHECK_OPT *)
1 by brian
clean slate
1311
{
1312
  int rc= 0;
1313
  const char *old_proc_info;
53.2.2 by Monty Taylor
Updated everything that needs updating to compile with -std=gnu99 -pedantic
1314
  uint64_t x;
1 by brian
clean slate
1315
520.1.22 by Brian Aker
Second pass of thd cleanup
1316
  old_proc_info= get_session_proc_info(session);
1317
  set_session_proc_info(session, "Checking table");
1 by brian
clean slate
1318
  /* Flush any waiting data */
1319
  pthread_mutex_lock(&share->mutex);
1320
  azflush(&(share->archive_write), Z_SYNC_FLUSH);
1321
  pthread_mutex_unlock(&share->mutex);
1322
1323
  /*
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1324
    Now we will rewind the archive file so that we are positioned at the
1 by brian
clean slate
1325
    start of the file.
1326
  */
1327
  init_archive_reader();
1328
  azflush(&archive, Z_SYNC_FLUSH);
1329
  read_data_header(&archive);
1330
  for (x= 0; x < share->archive_write.rows; x++)
1331
  {
1332
    rc= get_row(&archive, table->record[0]);
1333
1334
    if (rc != 0)
1335
      break;
1336
  }
1337
520.1.22 by Brian Aker
Second pass of thd cleanup
1338
  set_session_proc_info(session, old_proc_info);
1 by brian
clean slate
1339
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1340
  if ((rc && rc != HA_ERR_END_OF_FILE))
1 by brian
clean slate
1341
  {
163 by Brian Aker
Merge Monty's code.
1342
    share->crashed= false;
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1343
    return(HA_ADMIN_CORRUPT);
1 by brian
clean slate
1344
  }
1345
  else
1346
  {
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1347
    return(HA_ADMIN_OK);
1 by brian
clean slate
1348
  }
1349
}
1350
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1351
archive_record_buffer *ha_archive::create_record_buffer(unsigned int length)
1 by brian
clean slate
1352
{
1353
  archive_record_buffer *r;
656.1.25 by Monty Taylor
Removed my_malloc stuff from storage/
1354
  if (!(r= (archive_record_buffer*) malloc(sizeof(archive_record_buffer))))
1 by brian
clean slate
1355
  {
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1356
    return(NULL); /* purecov: inspected */
1 by brian
clean slate
1357
  }
1358
  r->length= (int)length;
1359
656.1.25 by Monty Taylor
Removed my_malloc stuff from storage/
1360
  if (!(r->buffer= (unsigned char*) malloc(r->length)))
1 by brian
clean slate
1361
  {
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
1362
    free((char*) r);
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1363
    return(NULL); /* purecov: inspected */
1 by brian
clean slate
1364
  }
1365
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1366
  return(r);
1 by brian
clean slate
1367
}
1368
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1369
void ha_archive::destroy_record_buffer(archive_record_buffer *r)
1 by brian
clean slate
1370
{
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
1371
  free((char*) r->buffer);
1372
  free((char*) r);
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1373
  return;
1 by brian
clean slate
1374
}
1375
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
1376
static DRIZZLE_SYSVAR_BOOL(aio, archive_use_aio,
1 by brian
clean slate
1377
  PLUGIN_VAR_NOCMDOPT,
1378
  "Whether or not to use asynchronous IO.",
163 by Brian Aker
Merge Monty's code.
1379
  NULL, NULL, true);
1 by brian
clean slate
1380
1381
static struct st_mysql_sys_var* archive_system_variables[]= {
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
1382
  DRIZZLE_SYSVAR(aio),
1 by brian
clean slate
1383
  NULL
1384
};
1385
813.2.1 by Toru Maesaka
Renamed mysql_declare_plugin to drizzle_declare_plugin
1386
drizzle_declare_plugin(archive)
1 by brian
clean slate
1387
{
1388
  "ARCHIVE",
177.4.3 by mark
ripped out more plugin ABI and API version checking, and plugin versions are now strings
1389
  "3.5",
1 by brian
clean slate
1390
  "Brian Aker, MySQL AB",
1391
  "Archive storage engine",
1392
  PLUGIN_LICENSE_GPL,
1393
  archive_db_init, /* Plugin Init */
1394
  archive_db_done, /* Plugin Deinit */
1395
  NULL,                       /* status variables                */
1396
  archive_system_variables,   /* system variables                */
1397
  NULL                        /* config options                  */
1398
}
813.2.2 by Toru Maesaka
Renamed mysql_declare_plugin_end to drizzle_declare_plugin_end
1399
drizzle_declare_plugin_end;
1 by brian
clean slate
1400