~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/csv/ha_tina.cc

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
40
40
 
41
41
 -Brian
42
42
*/
43
 
#include <drizzled/server_includes.h>
44
 
#include <drizzled/field.h>
45
 
#include <drizzled/field/blob.h>
46
 
#include <drizzled/field/timestamp.h>
47
 
#include <drizzled/error.h>
48
 
#include <drizzled/table.h>
49
 
#include <drizzled/session.h>
50
 
 
 
43
 
 
44
#ifdef USE_PRAGMA_IMPLEMENTATION
 
45
#pragma implementation        // gcc: Class implementation
 
46
#endif
 
47
 
 
48
#include "mysql_priv.h"
 
49
#include <mysql/plugin.h>
51
50
#include "ha_tina.h"
52
51
 
53
 
#include <string>
54
 
 
55
 
using namespace std;
56
 
 
57
 
static const string engine_name("CSV");
58
52
 
59
53
/*
60
 
  unsigned char + unsigned char + uint64_t + uint64_t + uint64_t + uint64_t + unsigned char
 
54
  uchar + uchar + uint64_t + uint64_t + uint64_t + uint64_t + uchar
61
55
*/
62
 
#define META_BUFFER_SIZE sizeof(unsigned char) + sizeof(unsigned char) + sizeof(uint64_t) \
63
 
  + sizeof(uint64_t) + sizeof(uint64_t) + sizeof(uint64_t) + sizeof(unsigned char)
 
56
#define META_BUFFER_SIZE sizeof(uchar) + sizeof(uchar) + sizeof(uint64_t) \
 
57
  + sizeof(uint64_t) + sizeof(uint64_t) + sizeof(uint64_t) + sizeof(uchar)
64
58
#define TINA_CHECK_HEADER 254 // The number we use to determine corruption
65
59
#define BLOB_MEMROOT_ALLOC_SIZE 8192
66
60
 
70
64
#define CSM_EXT ".CSM"               // Meta file
71
65
 
72
66
 
73
 
static TINA_SHARE *get_share(const char *table_name, Table *table);
 
67
static TINA_SHARE *get_share(const char *table_name, TABLE *table);
74
68
static int free_share(TINA_SHARE *share);
75
69
static int read_meta_file(File meta_file, ha_rows *rows);
76
70
static int write_meta_file(File meta_file, ha_rows rows, bool dirty);
77
71
 
78
72
extern "C" void tina_get_status(void* param, int concurrent_insert);
79
73
extern "C" void tina_update_status(void* param);
80
 
extern "C" bool tina_check_status(void* param);
 
74
extern "C" my_bool tina_check_status(void* param);
81
75
 
82
76
/* Stuff for shares */
83
77
pthread_mutex_t tina_mutex;
84
78
static HASH tina_open_tables;
 
79
static handler *tina_create_handler(handlerton *hton,
 
80
                                    TABLE_SHARE *table, 
 
81
                                    MEM_ROOT *mem_root);
 
82
 
85
83
 
86
84
/*****************************************************************************
87
85
 ** TINA tables
99
97
  return ( a->begin > b->begin ? 1 : ( a->begin < b->begin ? -1 : 0 ) );
100
98
}
101
99
 
102
 
static unsigned char* tina_get_key(TINA_SHARE *share, size_t *length, bool)
 
100
static uchar* tina_get_key(TINA_SHARE *share, size_t *length,
 
101
                          my_bool not_used __attribute__((unused)))
103
102
{
104
103
  *length=share->table_name_length;
105
 
  return (unsigned char*) share->table_name;
 
104
  return (uchar*) share->table_name;
106
105
}
107
106
 
108
 
 
109
 
/*
110
 
  If frm_error() is called in table.cc this is called to find out what file
111
 
  extensions exist for this handler.
112
 
*/
113
 
static const char *ha_tina_exts[] = {
114
 
  CSV_EXT,
115
 
  CSM_EXT,
116
 
  NULL
117
 
};
118
 
 
119
 
class Tina : public StorageEngine
120
 
{
121
 
public:
122
 
  Tina(const string& name_arg)
123
 
   : StorageEngine(name_arg, HTON_CAN_RECREATE | HTON_TEMPORARY_ONLY) {}
124
 
  virtual handler *create(TableShare *table,
125
 
                          MEM_ROOT *mem_root)
126
 
  {
127
 
    return new (mem_root) ha_tina(this, table);
128
 
  }
129
 
 
130
 
  const char **bas_ext() const {
131
 
    return ha_tina_exts;
132
 
  }
133
 
 
134
 
  int createTableImpl(Session *, const char *table_name, Table *table_arg,
135
 
                      HA_CREATE_INFO *);
136
 
 
137
 
};
138
 
 
139
 
static Tina *tina_engine= NULL;
140
 
 
141
 
static int tina_init_func(PluginRegistry &registry)
142
 
{
143
 
 
144
 
  tina_engine= new Tina(engine_name);
145
 
  registry.add(tina_engine);
146
 
 
147
 
  pthread_mutex_init(&tina_mutex,MY_MUTEX_INIT_FAST);
 
107
static int tina_init_func(void *p)
 
108
{
 
109
  handlerton *tina_hton;
 
110
 
 
111
  tina_hton= (handlerton *)p;
 
112
  VOID(pthread_mutex_init(&tina_mutex,MY_MUTEX_INIT_FAST));
148
113
  (void) hash_init(&tina_open_tables,system_charset_info,32,0,0,
149
114
                   (hash_get_key) tina_get_key,0,0);
 
115
  tina_hton->state= SHOW_OPTION_YES;
 
116
  tina_hton->db_type= DB_TYPE_CSV_DB;
 
117
  tina_hton->create= tina_create_handler;
 
118
  tina_hton->flags= (HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES | 
 
119
                     HTON_NO_PARTITION);
150
120
  return 0;
151
121
}
152
122
 
153
 
static int tina_done_func(PluginRegistry &registry)
 
123
static int tina_done_func(void *p)
154
124
{
155
 
  registry.remove(tina_engine);
156
 
  delete tina_engine;
157
 
 
158
125
  hash_free(&tina_open_tables);
159
126
  pthread_mutex_destroy(&tina_mutex);
160
127
 
165
132
/*
166
133
  Simple lock controls.
167
134
*/
168
 
static TINA_SHARE *get_share(const char *table_name, Table *)
 
135
static TINA_SHARE *get_share(const char *table_name, TABLE *table)
169
136
{
170
137
  TINA_SHARE *share;
171
138
  char meta_file_name[FN_REFLEN];
172
 
  struct stat file_stat;
 
139
  MY_STAT file_stat;                /* Stat information for the data file */
173
140
  char *tmp_name;
174
 
  uint32_t length;
 
141
  uint length;
175
142
 
176
143
  pthread_mutex_lock(&tina_mutex);
177
144
  length=(uint) strlen(table_name);
181
148
    initialize its members.
182
149
  */
183
150
  if (!(share=(TINA_SHARE*) hash_search(&tina_open_tables,
184
 
                                        (unsigned char*) table_name,
 
151
                                        (uchar*) table_name,
185
152
                                       length)))
186
153
  {
187
154
    if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
188
155
                         &share, sizeof(*share),
189
156
                         &tmp_name, length+1,
190
 
                         NULL))
 
157
                         NullS))
191
158
    {
192
159
      pthread_mutex_unlock(&tina_mutex);
193
160
      return NULL;
194
161
    }
195
162
 
196
163
    share->use_count= 0;
 
164
    share->is_log_table= FALSE;
197
165
    share->table_name_length= length;
198
166
    share->table_name= tmp_name;
199
 
    share->crashed= false;
 
167
    share->crashed= FALSE;
200
168
    share->rows_recorded= 0;
201
 
    share->update_file_opened= false;
202
 
    share->tina_write_opened= false;
 
169
    share->update_file_opened= FALSE;
 
170
    share->tina_write_opened= FALSE;
203
171
    share->data_file_version= 0;
204
 
    strcpy(share->table_name, table_name);
 
172
    strmov(share->table_name, table_name);
205
173
    fn_format(share->data_file_name, table_name, "", CSV_EXT,
206
174
              MY_REPLACE_EXT|MY_UNPACK_FILENAME);
207
175
    fn_format(meta_file_name, table_name, "", CSM_EXT,
208
176
              MY_REPLACE_EXT|MY_UNPACK_FILENAME);
209
177
 
210
 
    if (stat(share->data_file_name, &file_stat))
 
178
    if (my_stat(share->data_file_name, &file_stat, MYF(MY_WME)) == NULL)
211
179
      goto error;
212
180
    share->saved_data_file_length= file_stat.st_size;
213
181
 
214
 
    if (my_hash_insert(&tina_open_tables, (unsigned char*) share))
 
182
    if (my_hash_insert(&tina_open_tables, (uchar*) share))
215
183
      goto error;
216
184
    thr_lock_init(&share->lock);
217
185
    pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST);
224
192
    */
225
193
    if ((share->meta_file= my_open(meta_file_name,
226
194
                                   O_RDWR|O_CREAT, MYF(0))) == -1)
227
 
      share->crashed= true;
 
195
      share->crashed= TRUE;
228
196
 
229
197
    /*
230
198
      If the meta file will not open we assume it is crashed and
231
199
      mark it as such.
232
200
    */
233
201
    if (read_meta_file(share->meta_file, &share->rows_recorded))
234
 
      share->crashed= true;
 
202
      share->crashed= TRUE;
235
203
  }
236
204
  share->use_count++;
237
205
  pthread_mutex_unlock(&tina_mutex);
240
208
 
241
209
error:
242
210
  pthread_mutex_unlock(&tina_mutex);
243
 
  free((unsigned char*) share);
 
211
  my_free((uchar*) share, MYF(0));
244
212
 
245
213
  return NULL;
246
214
}
267
235
 
268
236
static int read_meta_file(File meta_file, ha_rows *rows)
269
237
{
270
 
  unsigned char meta_buffer[META_BUFFER_SIZE];
271
 
  unsigned char *ptr= meta_buffer;
272
 
 
273
 
  lseek(meta_file, 0, SEEK_SET);
274
 
  if (my_read(meta_file, (unsigned char*)meta_buffer, META_BUFFER_SIZE, 0)
 
238
  uchar meta_buffer[META_BUFFER_SIZE];
 
239
  uchar *ptr= meta_buffer;
 
240
 
 
241
  DBUG_ENTER("ha_tina::read_meta_file");
 
242
 
 
243
  VOID(my_seek(meta_file, 0, MY_SEEK_SET, MYF(0)));
 
244
  if (my_read(meta_file, (uchar*)meta_buffer, META_BUFFER_SIZE, 0)
275
245
      != META_BUFFER_SIZE)
276
 
    return(HA_ERR_CRASHED_ON_USAGE);
 
246
    DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
277
247
 
278
248
  /*
279
249
    Parse out the meta data, we ignore version at the moment
280
250
  */
281
251
 
282
 
  ptr+= sizeof(unsigned char)*2; // Move past header
 
252
  ptr+= sizeof(uchar)*2; // Move past header
283
253
  *rows= (ha_rows)uint8korr(ptr);
284
254
  ptr+= sizeof(uint64_t); // Move past rows
285
255
  /*
289
259
  ptr+= 3*sizeof(uint64_t);
290
260
 
291
261
  /* check crashed bit and magic number */
292
 
  if ((meta_buffer[0] != (unsigned char)TINA_CHECK_HEADER) ||
293
 
      ((bool)(*ptr)== true))
294
 
    return(HA_ERR_CRASHED_ON_USAGE);
 
262
  if ((meta_buffer[0] != (uchar)TINA_CHECK_HEADER) ||
 
263
      ((bool)(*ptr)== TRUE))
 
264
    DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
295
265
 
296
266
  my_sync(meta_file, MYF(MY_WME));
297
267
 
298
 
  return(0);
 
268
  DBUG_RETURN(0);
299
269
}
300
270
 
301
271
 
320
290
 
321
291
static int write_meta_file(File meta_file, ha_rows rows, bool dirty)
322
292
{
323
 
  unsigned char meta_buffer[META_BUFFER_SIZE];
324
 
  unsigned char *ptr= meta_buffer;
325
 
 
326
 
  *ptr= (unsigned char)TINA_CHECK_HEADER;
327
 
  ptr+= sizeof(unsigned char);
328
 
  *ptr= (unsigned char)TINA_VERSION;
329
 
  ptr+= sizeof(unsigned char);
 
293
  uchar meta_buffer[META_BUFFER_SIZE];
 
294
  uchar *ptr= meta_buffer;
 
295
 
 
296
  DBUG_ENTER("ha_tina::write_meta_file");
 
297
 
 
298
  *ptr= (uchar)TINA_CHECK_HEADER;
 
299
  ptr+= sizeof(uchar);
 
300
  *ptr= (uchar)TINA_VERSION;
 
301
  ptr+= sizeof(uchar);
330
302
  int8store(ptr, (uint64_t)rows);
331
303
  ptr+= sizeof(uint64_t);
332
304
  memset(ptr, 0, 3*sizeof(uint64_t));
335
307
     We'll need them later.
336
308
  */
337
309
  ptr+= 3*sizeof(uint64_t);
338
 
  *ptr= (unsigned char)dirty;
 
310
  *ptr= (uchar)dirty;
339
311
 
340
 
  lseek(meta_file, 0, SEEK_SET);
341
 
  if (my_write(meta_file, (unsigned char *)meta_buffer, META_BUFFER_SIZE, 0)
 
312
  VOID(my_seek(meta_file, 0, MY_SEEK_SET, MYF(0)));
 
313
  if (my_write(meta_file, (uchar *)meta_buffer, META_BUFFER_SIZE, 0)
342
314
      != META_BUFFER_SIZE)
343
 
    return(-1);
 
315
    DBUG_RETURN(-1);
344
316
 
345
317
  my_sync(meta_file, MYF(MY_WME));
346
318
 
347
 
  return(0);
 
319
  DBUG_RETURN(0);
348
320
}
349
321
 
350
 
bool ha_tina::check_and_repair(Session *session)
 
322
bool ha_tina::check_and_repair(THD *thd)
351
323
{
352
324
  HA_CHECK_OPT check_opt;
 
325
  DBUG_ENTER("ha_tina::check_and_repair");
353
326
 
354
327
  check_opt.init();
355
328
 
356
 
  return(repair(session, &check_opt));
 
329
  DBUG_RETURN(repair(thd, &check_opt));
357
330
}
358
331
 
359
332
 
360
333
int ha_tina::init_tina_writer()
361
334
{
 
335
  DBUG_ENTER("ha_tina::init_tina_writer");
 
336
 
362
337
  /*
363
338
    Mark the file as crashed. We will set the flag back when we close
364
339
    the file. In the case of the crash it will remain marked crashed,
365
340
    which enforce recovery.
366
341
  */
367
 
  (void)write_meta_file(share->meta_file, share->rows_recorded, true);
 
342
  (void)write_meta_file(share->meta_file, share->rows_recorded, TRUE);
368
343
 
369
344
  if ((share->tina_write_filedes=
370
345
        my_open(share->data_file_name, O_RDWR|O_APPEND, MYF(0))) == -1)
371
346
  {
372
 
    share->crashed= true;
373
 
    return(1);
 
347
    DBUG_PRINT("info", ("Could not open tina file writes"));
 
348
    share->crashed= TRUE;
 
349
    DBUG_RETURN(1);
374
350
  }
375
 
  share->tina_write_opened= true;
 
351
  share->tina_write_opened= TRUE;
376
352
 
377
 
  return(0);
 
353
  DBUG_RETURN(0);
378
354
}
379
355
 
380
356
 
381
357
bool ha_tina::is_crashed() const
382
358
{
383
 
  return(share->crashed);
 
359
  DBUG_ENTER("ha_tina::is_crashed");
 
360
  DBUG_RETURN(share->crashed);
384
361
}
385
362
 
386
363
/*
388
365
*/
389
366
static int free_share(TINA_SHARE *share)
390
367
{
 
368
  DBUG_ENTER("ha_tina::free_share");
391
369
  pthread_mutex_lock(&tina_mutex);
392
370
  int result_code= 0;
393
371
  if (!--share->use_count){
394
372
    /* Write the meta file. Mark it as crashed if needed. */
395
373
    (void)write_meta_file(share->meta_file, share->rows_recorded,
396
 
                          share->crashed ? true :false);
 
374
                          share->crashed ? TRUE :FALSE);
397
375
    if (my_close(share->meta_file, MYF(0)))
398
376
      result_code= 1;
399
377
    if (share->tina_write_opened)
400
378
    {
401
379
      if (my_close(share->tina_write_filedes, MYF(0)))
402
380
        result_code= 1;
403
 
      share->tina_write_opened= false;
 
381
      share->tina_write_opened= FALSE;
404
382
    }
405
383
 
406
 
    hash_delete(&tina_open_tables, (unsigned char*) share);
 
384
    hash_delete(&tina_open_tables, (uchar*) share);
407
385
    thr_lock_delete(&share->lock);
408
386
    pthread_mutex_destroy(&share->mutex);
409
 
    free((unsigned char*) share);
 
387
    my_free((uchar*) share, MYF(0));
410
388
  }
411
389
  pthread_mutex_unlock(&tina_mutex);
412
390
 
413
 
  return(result_code);
 
391
  DBUG_RETURN(result_code);
414
392
}
415
393
 
416
394
 
452
430
}
453
431
 
454
432
 
455
 
 
456
 
ha_tina::ha_tina(StorageEngine *engine_arg, TableShare *table_arg)
457
 
  :handler(engine_arg, table_arg),
 
433
static handler *tina_create_handler(handlerton *hton,
 
434
                                    TABLE_SHARE *table, 
 
435
                                    MEM_ROOT *mem_root)
 
436
{
 
437
  return new (mem_root) ha_tina(hton, table);
 
438
}
 
439
 
 
440
 
 
441
ha_tina::ha_tina(handlerton *hton, TABLE_SHARE *table_arg)
 
442
  :handler(hton, table_arg),
458
443
  /*
459
444
    These definitions are found in handler.h
460
445
    They are not probably completely right.
474
459
  Encode a buffer into the quoted format.
475
460
*/
476
461
 
477
 
int ha_tina::encode_quote(unsigned char *)
 
462
int ha_tina::encode_quote(uchar *buf)
478
463
{
479
464
  char attribute_buffer[1024];
480
465
  String attribute(attribute_buffer, sizeof(attribute_buffer),
481
466
                   &my_charset_bin);
482
467
 
 
468
  my_bitmap_map *org_bitmap= dbug_tmp_use_all_columns(table, table->read_set);
483
469
  buffer.length(0);
484
470
 
485
471
  for (Field **field=table->field ; *field ; field++)
487
473
    const char *ptr;
488
474
    const char *end_ptr;
489
475
    const bool was_null= (*field)->is_null();
490
 
 
 
476
    
491
477
    /*
492
478
      assistance for backwards compatibility in production builds.
493
479
      note: this will not work for ENUM columns.
499
485
    }
500
486
 
501
487
    (*field)->val_str(&attribute,&attribute);
502
 
 
 
488
    
503
489
    if (was_null)
504
490
      (*field)->set_null();
505
491
 
510
496
 
511
497
      buffer.append('"');
512
498
 
513
 
      while (ptr < end_ptr)
 
499
      while (ptr < end_ptr) 
514
500
      {
515
501
        if (*ptr == '"')
516
502
        {
554
540
 
555
541
  //buffer.replace(buffer.length(), 0, "\n", 1);
556
542
 
 
543
  dbug_tmp_restore_column_map(table->read_set, org_bitmap);
557
544
  return (buffer.length());
558
545
}
559
546
 
575
562
      chain_size += DEFAULT_CHAIN_LENGTH;
576
563
      if (chain_alloced)
577
564
      {
578
 
        if ((chain= (tina_set *) realloc(chain, chain_size)) == NULL)
 
565
        /* Must cast since my_malloc unlike malloc doesn't have a void ptr */
 
566
        if ((chain= (tina_set *) my_realloc((uchar*)chain,
 
567
                                            chain_size, MYF(MY_WME))) == NULL)
579
568
          return -1;
580
569
      }
581
570
      else
582
571
      {
583
 
        tina_set *ptr= (tina_set *) malloc(chain_size * sizeof(tina_set));
584
 
        if (ptr == NULL)
585
 
          return -1;
 
572
        tina_set *ptr= (tina_set *) my_malloc(chain_size * sizeof(tina_set),
 
573
                                              MYF(MY_WME));
586
574
        memcpy(ptr, chain, DEFAULT_CHAIN_LENGTH * sizeof(tina_set));
587
575
        chain= ptr;
588
576
        chain_alloced++;
601
589
/*
602
590
  Scans for a row.
603
591
*/
604
 
int ha_tina::find_current_row(unsigned char *buf)
 
592
int ha_tina::find_current_row(uchar *buf)
605
593
{
606
594
  off_t end_offset, curr_offset= current_position;
607
595
  int eoln_len;
 
596
  my_bitmap_map *org_bitmap;
608
597
  int error;
609
 
  bool read_all= false;
 
598
  bool read_all;
 
599
  DBUG_ENTER("ha_tina::find_current_row");
610
600
 
611
601
  free_root(&blobroot, MYF(MY_MARK_BLOCKS_FREE));
612
602
 
617
607
  if ((end_offset=
618
608
        find_eoln_buff(file_buff, current_position,
619
609
                       local_saved_data_file_length, &eoln_len)) == 0)
620
 
    return(HA_ERR_END_OF_FILE);
 
610
    DBUG_RETURN(HA_ERR_END_OF_FILE);
621
611
 
 
612
  /* We must read all columns in case a table is opened for update */
 
613
  read_all= !bitmap_is_clear_all(table->write_set);
 
614
  /* Avoid asserts in ::store() for columns that are not going to be updated */
 
615
  org_bitmap= dbug_tmp_use_all_columns(table, table->write_set);
622
616
  error= HA_ERR_CRASHED_ON_USAGE;
623
617
 
624
618
  memset(buf, 0, table->s->null_bytes);
625
619
 
626
 
  /* We need to first check to see if this is a write (rewrite this to something sane that knows if we are doing an update) */
627
 
  for (Field **field=table->field ; *field ; field++)
628
 
  {
629
 
    if ((*field)->isWriteSet())
630
 
    {
631
 
      read_all= true;
632
 
      break;
633
 
    }
634
 
  }
635
 
 
636
620
  for (Field **field=table->field ; *field ; field++)
637
621
  {
638
622
    char curr_char;
639
 
 
 
623
    
640
624
    buffer.length(0);
641
625
    if (curr_offset >= end_offset)
642
626
      goto err;
684
668
        }
685
669
      }
686
670
    }
687
 
    else
 
671
    else 
688
672
    {
689
673
      for(; curr_offset < end_offset; curr_offset++)
690
674
      {
698
682
      }
699
683
    }
700
684
 
701
 
    if (read_all || (*field)->isReadSet())
 
685
    if (read_all || bitmap_is_set(table->read_set, (*field)->field_index))
702
686
    {
703
687
      if ((*field)->store(buffer.ptr(), buffer.length(), buffer.charset(),
704
688
                          CHECK_FIELD_WARN))
706
690
      if ((*field)->flags & BLOB_FLAG)
707
691
      {
708
692
        Field_blob *blob= *(Field_blob**) field;
709
 
        unsigned char *src, *tgt;
710
 
        uint32_t length, packlength;
711
 
 
 
693
        uchar *src, *tgt;
 
694
        uint length, packlength;
 
695
        
712
696
        packlength= blob->pack_length_no_ptr();
713
697
        length= blob->get_length(blob->ptr);
714
 
        memcpy(&src, blob->ptr + packlength, sizeof(char*));
 
698
        memcpy_fixed(&src, blob->ptr + packlength, sizeof(char*));
715
699
        if (src)
716
700
        {
717
 
          tgt= (unsigned char*) alloc_root(&blobroot, length);
718
 
          memmove(tgt, src, length);
719
 
          memcpy(blob->ptr + packlength, &tgt, sizeof(char*));
 
701
          tgt= (uchar*) alloc_root(&blobroot, length);
 
702
          bmove(tgt, src, length);
 
703
          memcpy_fixed(blob->ptr + packlength, &tgt, sizeof(char*));
720
704
        }
721
705
      }
722
706
    }
725
709
  error= 0;
726
710
 
727
711
err:
728
 
 
729
 
  return(error);
 
712
  dbug_tmp_restore_column_map(table->write_set, org_bitmap);
 
713
 
 
714
  DBUG_RETURN(error);
 
715
}
 
716
 
 
717
/*
 
718
  If frm_error() is called in table.cc this is called to find out what file
 
719
  extensions exist for this handler.
 
720
*/
 
721
static const char *ha_tina_exts[] = {
 
722
  CSV_EXT,
 
723
  CSM_EXT,
 
724
  NullS
 
725
};
 
726
 
 
727
const char **ha_tina::bas_ext() const
 
728
{
 
729
  return ha_tina_exts;
730
730
}
731
731
 
732
732
/*
734
734
  for CSV engine. For more details see mysys/thr_lock.c
735
735
*/
736
736
 
737
 
void tina_get_status(void* param, int)
 
737
void tina_get_status(void* param, int concurrent_insert)
738
738
{
739
739
  ha_tina *tina= (ha_tina*) param;
740
740
  tina->get_status();
747
747
}
748
748
 
749
749
/* this should exist and return 0 for concurrent insert to work */
750
 
bool tina_check_status(void *)
 
750
my_bool tina_check_status(void* param)
751
751
{
752
752
  return 0;
753
753
}
766
766
 
767
767
void ha_tina::get_status()
768
768
{
 
769
  if (share->is_log_table)
 
770
  {
 
771
    /*
 
772
      We have to use mutex to follow pthreads memory visibility
 
773
      rules for share->saved_data_file_length
 
774
    */
 
775
    pthread_mutex_lock(&share->mutex);
 
776
    local_saved_data_file_length= share->saved_data_file_length;
 
777
    pthread_mutex_unlock(&share->mutex);
 
778
    return;
 
779
  }
769
780
  local_saved_data_file_length= share->saved_data_file_length;
770
781
}
771
782
 
787
798
    For log tables concurrent insert works different. The reason is that
788
799
    log tables are always opened and locked. And as they do not unlock
789
800
    tables, the file length after writes should be updated in a different
790
 
    way.
 
801
    way. For this purpose we need is_log_table flag. When this flag is set
 
802
    we call update_status() explicitly after each row write.
791
803
*/
792
804
 
793
805
void ha_tina::update_status()
802
814
  this will not be called for every request. Any sort of positions
803
815
  that need to be reset should be kept in the ::extra() call.
804
816
*/
805
 
int ha_tina::open(const char *name, int, uint32_t open_options)
 
817
int ha_tina::open(const char *name, int mode, uint open_options)
806
818
{
 
819
  DBUG_ENTER("ha_tina::open");
 
820
 
807
821
  if (!(share= get_share(name, table)))
808
 
    return(ENOENT);
 
822
    DBUG_RETURN(HA_ERR_OUT_OF_MEM);
809
823
 
810
824
  if (share->crashed && !(open_options & HA_OPEN_FOR_REPAIR))
811
825
  {
812
826
    free_share(share);
813
 
    return(HA_ERR_CRASHED_ON_USAGE);
 
827
    DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
814
828
  }
815
829
 
816
830
  local_data_file_version= share->data_file_version;
817
831
  if ((data_file= my_open(share->data_file_name, O_RDONLY, MYF(0))) == -1)
818
 
    return(0);
 
832
    DBUG_RETURN(0);
819
833
 
820
834
  /*
821
835
    Init locking. Pass handler object to the locking routines,
829
843
  share->lock.update_status= tina_update_status;
830
844
  share->lock.check_status= tina_check_status;
831
845
 
832
 
  return(0);
 
846
  DBUG_RETURN(0);
833
847
}
834
848
 
835
849
 
840
854
int ha_tina::close(void)
841
855
{
842
856
  int rc= 0;
 
857
  DBUG_ENTER("ha_tina::close");
843
858
  rc= my_close(data_file, MYF(0));
844
 
  return(free_share(share) || rc);
 
859
  DBUG_RETURN(free_share(share) || rc);
845
860
}
846
861
 
847
862
/*
849
864
  of the file and appends the data. In an error case it really should
850
865
  just truncate to the original position (this is not done yet).
851
866
*/
852
 
int ha_tina::write_row(unsigned char * buf)
 
867
int ha_tina::write_row(uchar * buf)
853
868
{
854
869
  int size;
 
870
  DBUG_ENTER("ha_tina::write_row");
855
871
 
856
872
  if (share->crashed)
857
 
      return(HA_ERR_CRASHED_ON_USAGE);
 
873
      DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
858
874
 
859
875
  ha_statistic_increment(&SSV::ha_write_count);
860
876
 
 
877
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
 
878
    table->timestamp_field->set_time();
 
879
 
861
880
  size= encode_quote(buf);
862
881
 
863
882
  if (!share->tina_write_opened)
864
883
    if (init_tina_writer())
865
 
      return(-1);
 
884
      DBUG_RETURN(-1);
866
885
 
867
886
   /* use pwrite, as concurrent reader could have changed the position */
868
 
  if (my_write(share->tina_write_filedes, (unsigned char*)buffer.ptr(), size,
 
887
  if (my_write(share->tina_write_filedes, (uchar*)buffer.ptr(), size,
869
888
               MYF(MY_WME | MY_NABP)))
870
 
    return(-1);
 
889
    DBUG_RETURN(-1);
871
890
 
872
891
  /* update local copy of the max position to see our own changes */
873
892
  local_saved_data_file_length+= size;
876
895
  pthread_mutex_lock(&share->mutex);
877
896
  share->rows_recorded++;
878
897
  /* update status for the log tables */
 
898
  if (share->is_log_table)
 
899
    update_status();
879
900
  pthread_mutex_unlock(&share->mutex);
880
901
 
881
902
  stats.records++;
882
 
  return(0);
 
903
  DBUG_RETURN(0);
883
904
}
884
905
 
885
906
 
895
916
                               MY_REPLACE_EXT | MY_UNPACK_FILENAME),
896
917
                     0, O_RDWR | O_TRUNC, MYF(MY_WME))) < 0)
897
918
      return 1;
898
 
    share->update_file_opened= true;
 
919
    share->update_file_opened= TRUE;
899
920
    temp_file_length= 0;
900
921
  }
901
922
  return 0;
909
930
  This will be called in a table scan right before the previous ::rnd_next()
910
931
  call.
911
932
*/
912
 
int ha_tina::update_row(const unsigned char *, unsigned char * new_data)
 
933
int ha_tina::update_row(const uchar * old_data, uchar * new_data)
913
934
{
914
935
  int size;
915
936
  int rc= -1;
 
937
  DBUG_ENTER("ha_tina::update_row");
916
938
 
917
939
  ha_statistic_increment(&SSV::ha_update_count);
918
940
 
922
944
  size= encode_quote(new_data);
923
945
 
924
946
  /*
925
 
    During update we mark each updating record as deleted
926
 
    (see the chain_append()) then write new one to the temporary data file.
 
947
    During update we mark each updating record as deleted 
 
948
    (see the chain_append()) then write new one to the temporary data file. 
927
949
    At the end of the sequence in the rnd_end() we append all non-marked
928
950
    records from the data file to the temporary data file then rename it.
929
951
    The temp_file_length is used to calculate new data file length.
934
956
  if (open_update_temp_file_if_needed())
935
957
    goto err;
936
958
 
937
 
  if (my_write(update_temp_file, (unsigned char*)buffer.ptr(), size,
 
959
  if (my_write(update_temp_file, (uchar*)buffer.ptr(), size,
938
960
               MYF(MY_WME | MY_NABP)))
939
961
    goto err;
940
962
  temp_file_length+= size;
941
963
  rc= 0;
942
964
 
 
965
  /* UPDATE should never happen on the log tables */
 
966
  DBUG_ASSERT(!share->is_log_table);
 
967
 
943
968
err:
944
 
  return(rc);
 
969
  DBUG_PRINT("info",("rc = %d", rc));
 
970
  DBUG_RETURN(rc);
945
971
}
946
972
 
947
973
 
954
980
  The table will then be deleted/positioned based on the ORDER (so RANDOM,
955
981
  DESC, ASC).
956
982
*/
957
 
int ha_tina::delete_row(const unsigned char *)
 
983
int ha_tina::delete_row(const uchar * buf)
958
984
{
 
985
  DBUG_ENTER("ha_tina::delete_row");
959
986
  ha_statistic_increment(&SSV::ha_delete_count);
960
987
 
961
988
  if (chain_append())
962
 
    return(-1);
 
989
    DBUG_RETURN(-1);
963
990
 
964
991
  stats.records--;
965
992
  /* Update shared info */
966
 
  assert(share->rows_recorded);
 
993
  DBUG_ASSERT(share->rows_recorded);
967
994
  pthread_mutex_lock(&share->mutex);
968
995
  share->rows_recorded--;
969
996
  pthread_mutex_unlock(&share->mutex);
970
997
 
971
 
  return(0);
 
998
  /* DELETE should never happen on the log table */
 
999
  DBUG_ASSERT(!share->is_log_table);
 
1000
 
 
1001
  DBUG_RETURN(0);
972
1002
}
973
1003
 
974
1004
 
975
1005
/**
976
1006
  @brief Initialize the data file.
977
 
 
 
1007
  
978
1008
  @details Compare the local version of the data file with the shared one.
979
1009
  If they differ, there are some changes behind and we have to reopen
980
1010
  the data file to make the changes visible.
981
 
  Call @c file_buff->init_buff() at the end to read the beginning of the
 
1011
  Call @c file_buff->init_buff() at the end to read the beginning of the 
982
1012
  data file into buffer.
983
 
 
 
1013
  
984
1014
  @retval  0  OK.
985
1015
  @retval  1  There was an error.
986
1016
*/
1030
1060
 
1031
1061
*/
1032
1062
 
1033
 
int ha_tina::rnd_init(bool)
 
1063
int ha_tina::rnd_init(bool scan)
1034
1064
{
 
1065
  DBUG_ENTER("ha_tina::rnd_init");
 
1066
 
1035
1067
  /* set buffer to the beginning of the file */
1036
1068
  if (share->crashed || init_data_file())
1037
 
    return(HA_ERR_CRASHED_ON_USAGE);
 
1069
    DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
1038
1070
 
1039
1071
  current_position= next_position= 0;
1040
1072
  stats.records= 0;
1043
1075
 
1044
1076
  init_alloc_root(&blobroot, BLOB_MEMROOT_ALLOC_SIZE, 0);
1045
1077
 
1046
 
  return(0);
 
1078
  DBUG_RETURN(0);
1047
1079
}
1048
1080
 
1049
1081
/*
1060
1092
  NULL and "". This is ok since this table handler is for spreadsheets and
1061
1093
  they don't know about them either :)
1062
1094
*/
1063
 
int ha_tina::rnd_next(unsigned char *buf)
 
1095
int ha_tina::rnd_next(uchar *buf)
1064
1096
{
1065
1097
  int rc;
 
1098
  DBUG_ENTER("ha_tina::rnd_next");
1066
1099
 
1067
1100
  if (share->crashed)
1068
 
      return(HA_ERR_CRASHED_ON_USAGE);
 
1101
      DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
1069
1102
 
1070
1103
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
1071
1104
 
1073
1106
 
1074
1107
  /* don't scan an empty file */
1075
1108
  if (!local_saved_data_file_length)
1076
 
    return(HA_ERR_END_OF_FILE);
 
1109
    DBUG_RETURN(HA_ERR_END_OF_FILE);
1077
1110
 
1078
1111
  if ((rc= find_current_row(buf)))
1079
 
    return(rc);
 
1112
    DBUG_RETURN(rc);
1080
1113
 
1081
1114
  stats.records++;
1082
 
  return(0);
 
1115
  DBUG_RETURN(0);
1083
1116
}
1084
1117
 
1085
1118
/*
1091
1124
  its just a position. Look at the bdb code if you want to see a case
1092
1125
  where something other then a number is stored.
1093
1126
*/
1094
 
void ha_tina::position(const unsigned char *)
 
1127
void ha_tina::position(const uchar *record)
1095
1128
{
 
1129
  DBUG_ENTER("ha_tina::position");
1096
1130
  my_store_ptr(ref, ref_length, current_position);
1097
 
  return;
 
1131
  DBUG_VOID_RETURN;
1098
1132
}
1099
1133
 
1100
1134
 
1103
1137
  my_get_ptr() retrieves the data for you.
1104
1138
*/
1105
1139
 
1106
 
int ha_tina::rnd_pos(unsigned char * buf, unsigned char *pos)
 
1140
int ha_tina::rnd_pos(uchar * buf, uchar *pos)
1107
1141
{
 
1142
  DBUG_ENTER("ha_tina::rnd_pos");
1108
1143
  ha_statistic_increment(&SSV::ha_read_rnd_count);
1109
1144
  current_position= (off_t)my_get_ptr(pos,ref_length);
1110
 
  return(find_current_row(buf));
 
1145
  DBUG_RETURN(find_current_row(buf));
1111
1146
}
1112
1147
 
1113
1148
/*
1115
1150
  Currently this table handler doesn't implement most of the fields
1116
1151
  really needed. SHOW also makes use of this data
1117
1152
*/
1118
 
int ha_tina::info(uint32_t)
 
1153
int ha_tina::info(uint flag)
1119
1154
{
 
1155
  DBUG_ENTER("ha_tina::info");
1120
1156
  /* This is a lie, but you don't want the optimizer to see zero or 1 */
1121
 
  if (!records_is_known && stats.records < 2)
 
1157
  if (!records_is_known && stats.records < 2) 
1122
1158
    stats.records= 2;
1123
 
  return(0);
 
1159
  DBUG_RETURN(0);
 
1160
}
 
1161
 
 
1162
/*
 
1163
  Grab bag of flags that are sent to the able handler every so often.
 
1164
  HA_EXTRA_RESET and HA_EXTRA_RESET_STATE are the most frequently called.
 
1165
  You are not required to implement any of these.
 
1166
*/
 
1167
int ha_tina::extra(enum ha_extra_function operation)
 
1168
{
 
1169
  DBUG_ENTER("ha_tina::extra");
 
1170
 if (operation == HA_EXTRA_MARK_AS_LOG_TABLE)
 
1171
 {
 
1172
   pthread_mutex_lock(&share->mutex);
 
1173
   share->is_log_table= TRUE;
 
1174
   pthread_mutex_unlock(&share->mutex);
 
1175
 }
 
1176
  DBUG_RETURN(0);
1124
1177
}
1125
1178
 
1126
1179
/*
1133
1186
  if (closest_hole == chain_ptr) /* no more chains */
1134
1187
    *end_pos= file_buff->end();
1135
1188
  else
1136
 
    *end_pos= std::min(file_buff->end(),
1137
 
                       closest_hole->begin);
 
1189
    *end_pos= min(file_buff->end(),
 
1190
                  closest_hole->begin);
1138
1191
  return (closest_hole != chain_ptr) && (*end_pos == closest_hole->begin);
1139
1192
}
1140
1193
 
1149
1202
{
1150
1203
  char updated_fname[FN_REFLEN];
1151
1204
  off_t file_buffer_start= 0;
 
1205
  DBUG_ENTER("ha_tina::rnd_end");
1152
1206
 
1153
1207
  free_root(&blobroot, MYF(0));
1154
1208
  records_is_known= 1;
1174
1228
 
1175
1229
    /* create the file to write updated table if it wasn't yet created */
1176
1230
    if (open_update_temp_file_if_needed())
1177
 
      return(-1);
 
1231
      DBUG_RETURN(-1);
1178
1232
 
1179
1233
    /* write the file with updated info */
1180
1234
    while ((file_buffer_start != -1))     // while not end of file
1181
1235
    {
1182
1236
      bool in_hole= get_write_pos(&write_end, ptr);
1183
1237
      off_t write_length= write_end - write_begin;
1184
 
      if ((uint64_t)write_length > SIZE_MAX)
1185
 
      {
1186
 
        goto error;
1187
 
      }
1188
1238
 
1189
1239
      /* if there is something to write, write it */
1190
1240
      if (write_length)
1191
1241
      {
1192
 
        if (my_write(update_temp_file,
1193
 
                     (unsigned char*) (file_buff->ptr() +
 
1242
        if (my_write(update_temp_file, 
 
1243
                     (uchar*) (file_buff->ptr() +
1194
1244
                               (write_begin - file_buff->start())),
1195
 
                     (size_t)write_length, MYF_RW))
 
1245
                     write_length, MYF_RW))
1196
1246
          goto error;
1197
1247
        temp_file_length+= write_length;
1198
1248
      }
1214
1264
 
1215
1265
    if (my_sync(update_temp_file, MYF(MY_WME)) ||
1216
1266
        my_close(update_temp_file, MYF(0)))
1217
 
      return(-1);
 
1267
      DBUG_RETURN(-1);
1218
1268
 
1219
 
    share->update_file_opened= false;
 
1269
    share->update_file_opened= FALSE;
1220
1270
 
1221
1271
    if (share->tina_write_opened)
1222
1272
    {
1223
1273
      if (my_close(share->tina_write_filedes, MYF(0)))
1224
 
        return(-1);
 
1274
        DBUG_RETURN(-1);
1225
1275
      /*
1226
1276
        Mark that the writer fd is closed, so that init_tina_writer()
1227
1277
        will reopen it later.
1228
1278
      */
1229
 
      share->tina_write_opened= false;
 
1279
      share->tina_write_opened= FALSE;
1230
1280
    }
1231
1281
 
1232
1282
    /*
1237
1287
        my_rename(fn_format(updated_fname, share->table_name, "", CSN_EXT,
1238
1288
                            MY_REPLACE_EXT | MY_UNPACK_FILENAME),
1239
1289
                  share->data_file_name, MYF(0)))
1240
 
      return(-1);
 
1290
      DBUG_RETURN(-1);
1241
1291
 
1242
1292
    /* Open the file again */
1243
1293
    if (((data_file= my_open(share->data_file_name, O_RDONLY, MYF(0))) == -1))
1244
 
      return(-1);
 
1294
      DBUG_RETURN(-1);
1245
1295
    /*
1246
 
      As we reopened the data file, increase share->data_file_version
1247
 
      in order to force other threads waiting on a table lock and
 
1296
      As we reopened the data file, increase share->data_file_version 
 
1297
      in order to force other threads waiting on a table lock and  
1248
1298
      have already opened the table to reopen the data file.
1249
1299
      That makes the latest changes become visible to them.
1250
 
      Update local_data_file_version as no need to reopen it in the
 
1300
      Update local_data_file_version as no need to reopen it in the 
1251
1301
      current thread.
1252
1302
    */
1253
1303
    share->data_file_version++;
1257
1307
      closed, so nothing worrying will happen to it in case of a crash.
1258
1308
      Here we record this fact to the meta-file.
1259
1309
    */
1260
 
    (void)write_meta_file(share->meta_file, share->rows_recorded, false);
1261
 
    /*
1262
 
      Update local_saved_data_file_length with the real length of the
 
1310
    (void)write_meta_file(share->meta_file, share->rows_recorded, FALSE);
 
1311
    /* 
 
1312
      Update local_saved_data_file_length with the real length of the 
1263
1313
      data file.
1264
1314
    */
1265
1315
    local_saved_data_file_length= temp_file_length;
1266
1316
  }
1267
1317
 
1268
 
  return(0);
 
1318
  DBUG_RETURN(0);
1269
1319
error:
1270
1320
  my_close(update_temp_file, MYF(0));
1271
 
  share->update_file_opened= false;
1272
 
  return(-1);
 
1321
  share->update_file_opened= FALSE;
 
1322
  DBUG_RETURN(-1);
1273
1323
}
1274
1324
 
1275
1325
 
1278
1328
 
1279
1329
  SYNOPSIS
1280
1330
    repair()
1281
 
    session         The thread, performing repair
 
1331
    thd         The thread, performing repair
1282
1332
    check_opt   The options for repair. We do not use it currently.
1283
1333
 
1284
1334
  DESCRIPTION
1291
1341
         rows (after the first bad one) as well.
1292
1342
*/
1293
1343
 
1294
 
int ha_tina::repair(Session* session, HA_CHECK_OPT *)
 
1344
int ha_tina::repair(THD* thd, HA_CHECK_OPT* check_opt)
1295
1345
{
1296
1346
  char repaired_fname[FN_REFLEN];
1297
 
  unsigned char *buf;
 
1347
  uchar *buf;
1298
1348
  File repair_file;
1299
1349
  int rc;
1300
1350
  ha_rows rows_repaired= 0;
1301
1351
  off_t write_begin= 0, write_end;
 
1352
  DBUG_ENTER("ha_tina::repair");
1302
1353
 
1303
1354
  /* empty file */
1304
1355
  if (!share->saved_data_file_length)
1309
1360
 
1310
1361
  /* Don't assert in field::val() functions */
1311
1362
  table->use_all_columns();
1312
 
  if (!(buf= (unsigned char*) malloc(table->s->reclength)))
1313
 
    return(HA_ERR_OUT_OF_MEM);
 
1363
  if (!(buf= (uchar*) my_malloc(table->s->reclength, MYF(MY_WME))))
 
1364
    DBUG_RETURN(HA_ERR_OUT_OF_MEM);
1314
1365
 
1315
1366
  /* position buffer to the start of the file */
1316
1367
  if (init_data_file())
1317
 
    return(HA_ERR_CRASHED_ON_REPAIR);
 
1368
    DBUG_RETURN(HA_ERR_CRASHED_ON_REPAIR);
1318
1369
 
1319
1370
  /*
1320
1371
    Local_saved_data_file_length is initialized during the lock phase.
1330
1381
  /* Read the file row-by-row. If everything is ok, repair is not needed. */
1331
1382
  while (!(rc= find_current_row(buf)))
1332
1383
  {
1333
 
    session_inc_row_count(session);
 
1384
    thd_inc_row_count(thd);
1334
1385
    rows_repaired++;
1335
1386
    current_position= next_position;
1336
1387
  }
1337
1388
 
1338
1389
  free_root(&blobroot, MYF(0));
1339
1390
 
1340
 
  free((char*)buf);
 
1391
  my_free((char*)buf, MYF(0));
1341
1392
 
1342
1393
  if (rc == HA_ERR_END_OF_FILE)
1343
1394
  {
1358
1409
                                        "", CSN_EXT,
1359
1410
                                        MY_REPLACE_EXT|MY_UNPACK_FILENAME),
1360
1411
                           0, O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
1361
 
    return(HA_ERR_CRASHED_ON_REPAIR);
 
1412
    DBUG_RETURN(HA_ERR_CRASHED_ON_REPAIR);
1362
1413
 
1363
1414
  file_buff->init_buff(data_file);
1364
1415
 
1369
1420
  /* write repaired file */
1370
1421
  while (1)
1371
1422
  {
1372
 
    write_end= std::min(file_buff->end(), current_position);
1373
 
 
1374
 
    off_t write_length= write_end - write_begin;
1375
 
    if ((uint64_t)write_length > SIZE_MAX)
1376
 
    {
1377
 
      return -1;
1378
 
    }
1379
 
    if ((write_length) &&
1380
 
        (my_write(repair_file, (unsigned char*)file_buff->ptr(),
1381
 
                  (size_t)write_length, MYF_RW)))
1382
 
      return(-1);
 
1423
    write_end= min(file_buff->end(), current_position);
 
1424
    if ((write_end - write_begin) &&
 
1425
        (my_write(repair_file, (uchar*)file_buff->ptr(),
 
1426
                  write_end - write_begin, MYF_RW)))
 
1427
      DBUG_RETURN(-1);
1383
1428
 
1384
1429
    write_begin= write_end;
1385
1430
    if (write_end== current_position)
1396
1441
  */
1397
1442
  if (my_close(data_file,MYF(0)) || my_close(repair_file, MYF(0)) ||
1398
1443
      my_rename(repaired_fname, share->data_file_name, MYF(0)))
1399
 
    return(-1);
 
1444
    DBUG_RETURN(-1);
1400
1445
 
1401
1446
  /* Open the file again, it should now be repaired */
1402
1447
  if ((data_file= my_open(share->data_file_name, O_RDWR|O_APPEND,
1403
1448
                          MYF(0))) == -1)
1404
 
     return(-1);
 
1449
     DBUG_RETURN(-1);
1405
1450
 
1406
1451
  /* Set new file size. The file size will be updated by ::update_status() */
1407
1452
  local_saved_data_file_length= (size_t) current_position;
1408
1453
 
1409
1454
end:
1410
 
  share->crashed= false;
1411
 
  return(HA_ADMIN_OK);
 
1455
  share->crashed= FALSE;
 
1456
  DBUG_RETURN(HA_ADMIN_OK);
1412
1457
}
1413
1458
 
1414
1459
/*
1418
1463
int ha_tina::delete_all_rows()
1419
1464
{
1420
1465
  int rc;
 
1466
  DBUG_ENTER("ha_tina::delete_all_rows");
1421
1467
 
1422
1468
  if (!records_is_known)
1423
 
    return(my_errno=HA_ERR_WRONG_COMMAND);
 
1469
    DBUG_RETURN(my_errno=HA_ERR_WRONG_COMMAND);
1424
1470
 
1425
1471
  if (!share->tina_write_opened)
1426
1472
    if (init_tina_writer())
1427
 
      return(-1);
 
1473
      DBUG_RETURN(-1);
1428
1474
 
1429
1475
  /* Truncate the file to zero size */
1430
 
  rc= ftruncate(share->tina_write_filedes, 0);
 
1476
  rc= my_chsize(share->tina_write_filedes, 0, 0, MYF(MY_WME));
1431
1477
 
1432
1478
  stats.records=0;
1433
1479
  /* Update shared info */
1435
1481
  share->rows_recorded= 0;
1436
1482
  pthread_mutex_unlock(&share->mutex);
1437
1483
  local_saved_data_file_length= 0;
1438
 
  return(rc);
 
1484
  DBUG_RETURN(rc);
1439
1485
}
1440
1486
 
1441
1487
/*
1442
1488
  Called by the database to lock the table. Keep in mind that this
1443
1489
  is an internal lock.
1444
1490
*/
1445
 
THR_LOCK_DATA **ha_tina::store_lock(Session *,
 
1491
THR_LOCK_DATA **ha_tina::store_lock(THD *thd,
1446
1492
                                    THR_LOCK_DATA **to,
1447
1493
                                    enum thr_lock_type lock_type)
1448
1494
{
1452
1498
  return to;
1453
1499
}
1454
1500
 
1455
 
/*
 
1501
/* 
1456
1502
  Create a table. You do not want to leave the table open after a call to
1457
1503
  this (the database will call ::open() if it needs to).
1458
1504
*/
1459
1505
 
1460
 
int Tina::createTableImpl(Session *, const char *table_name, Table *table_arg,
1461
 
                          HA_CREATE_INFO *)
 
1506
int ha_tina::create(const char *name, TABLE *table_arg,
 
1507
                    HA_CREATE_INFO *create_info)
1462
1508
{
1463
1509
  char name_buff[FN_REFLEN];
1464
1510
  File create_file;
 
1511
  DBUG_ENTER("ha_tina::create");
1465
1512
 
1466
1513
  /*
1467
1514
    check columns
1471
1518
    if ((*field)->real_maybe_null())
1472
1519
    {
1473
1520
      my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "nullable columns");
1474
 
      return(HA_ERR_UNSUPPORTED);
 
1521
      DBUG_RETURN(HA_ERR_UNSUPPORTED);
1475
1522
    }
1476
1523
  }
1477
 
 
1478
 
 
1479
 
  if ((create_file= my_create(fn_format(name_buff, table_name, "", CSM_EXT,
 
1524
  
 
1525
 
 
1526
  if ((create_file= my_create(fn_format(name_buff, name, "", CSM_EXT,
1480
1527
                                        MY_REPLACE_EXT|MY_UNPACK_FILENAME), 0,
1481
1528
                              O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
1482
 
    return(-1);
 
1529
    DBUG_RETURN(-1);
1483
1530
 
1484
 
  write_meta_file(create_file, 0, false);
 
1531
  write_meta_file(create_file, 0, FALSE);
1485
1532
  my_close(create_file, MYF(0));
1486
1533
 
1487
 
  if ((create_file= my_create(fn_format(name_buff, table_name, "", CSV_EXT,
 
1534
  if ((create_file= my_create(fn_format(name_buff, name, "", CSV_EXT,
1488
1535
                                        MY_REPLACE_EXT|MY_UNPACK_FILENAME),0,
1489
1536
                              O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
1490
 
    return(-1);
 
1537
    DBUG_RETURN(-1);
1491
1538
 
1492
1539
  my_close(create_file, MYF(0));
1493
1540
 
1494
 
  return(0);
 
1541
  DBUG_RETURN(0);
1495
1542
}
1496
1543
 
1497
 
int ha_tina::check(Session* session, HA_CHECK_OPT *)
 
1544
int ha_tina::check(THD* thd, HA_CHECK_OPT* check_opt)
1498
1545
{
1499
1546
  int rc= 0;
1500
 
  unsigned char *buf;
 
1547
  uchar *buf;
1501
1548
  const char *old_proc_info;
1502
1549
  ha_rows count= share->rows_recorded;
 
1550
  DBUG_ENTER("ha_tina::check");
1503
1551
 
1504
 
  old_proc_info= get_session_proc_info(session);
1505
 
  set_session_proc_info(session, "Checking table");
1506
 
  if (!(buf= (unsigned char*) malloc(table->s->reclength)))
1507
 
    return(HA_ERR_OUT_OF_MEM);
 
1552
  old_proc_info= thd_proc_info(thd, "Checking table");
 
1553
  if (!(buf= (uchar*) my_malloc(table->s->reclength, MYF(MY_WME))))
 
1554
    DBUG_RETURN(HA_ERR_OUT_OF_MEM);
1508
1555
 
1509
1556
  /* position buffer to the start of the file */
1510
1557
   if (init_data_file())
1511
 
     return(HA_ERR_CRASHED);
 
1558
     DBUG_RETURN(HA_ERR_CRASHED);
1512
1559
 
1513
1560
  /*
1514
1561
    Local_saved_data_file_length is initialized during the lock phase.
1524
1571
  /* Read the file row-by-row. If everything is ok, repair is not needed. */
1525
1572
  while (!(rc= find_current_row(buf)))
1526
1573
  {
1527
 
    session_inc_row_count(session);
 
1574
    thd_inc_row_count(thd);
1528
1575
    count--;
1529
1576
    current_position= next_position;
1530
1577
  }
1531
 
 
 
1578
  
1532
1579
  free_root(&blobroot, MYF(0));
1533
1580
 
1534
 
  free((char*)buf);
1535
 
  set_session_proc_info(session, old_proc_info);
 
1581
  my_free((char*)buf, MYF(0));
 
1582
  thd_proc_info(thd, old_proc_info);
1536
1583
 
1537
1584
  if ((rc != HA_ERR_END_OF_FILE) || count)
1538
1585
  {
1539
 
    share->crashed= true;
1540
 
    return(HA_ADMIN_CORRUPT);
 
1586
    share->crashed= TRUE;
 
1587
    DBUG_RETURN(HA_ADMIN_CORRUPT);
1541
1588
  }
1542
1589
  else
1543
 
    return(HA_ADMIN_OK);
1544
 
}
1545
 
 
1546
 
 
1547
 
drizzle_declare_plugin(csv)
1548
 
{
 
1590
    DBUG_RETURN(HA_ADMIN_OK);
 
1591
}
 
1592
 
 
1593
 
 
1594
bool ha_tina::check_if_incompatible_data(HA_CREATE_INFO *info,
 
1595
                                           uint table_changes)
 
1596
{
 
1597
  return COMPATIBLE_DATA_YES;
 
1598
}
 
1599
 
 
1600
struct st_mysql_storage_engine csv_storage_engine=
 
1601
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
 
1602
 
 
1603
mysql_declare_plugin(csv)
 
1604
{
 
1605
  MYSQL_STORAGE_ENGINE_PLUGIN,
 
1606
  &csv_storage_engine,
1549
1607
  "CSV",
1550
 
  "1.0",
1551
1608
  "Brian Aker, MySQL AB",
1552
1609
  "CSV storage engine",
1553
1610
  PLUGIN_LICENSE_GPL,
1554
1611
  tina_init_func, /* Plugin Init */
1555
1612
  tina_done_func, /* Plugin Deinit */
 
1613
  0x0100 /* 1.0 */,
1556
1614
  NULL,                       /* status variables                */
1557
1615
  NULL,                       /* system variables                */
1558
1616
  NULL                        /* config options                  */
1559
1617
}
1560
 
drizzle_declare_plugin_end;
 
1618
mysql_declare_plugin_end;
1561
1619