~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
/*
17
  Make sure to look at ha_tina.h for more details.
18
19
  First off, this is a play thing for me, there are a number of things
20
  wrong with it:
21
    *) It was designed for csv and therefore its performance is highly
22
       questionable.
23
    *) Indexes have not been implemented. This is because the files can
24
       be traded in and out of the table directory without having to worry
25
       about rebuilding anything.
26
    *) NULLs and "" are treated equally (like a spreadsheet).
27
    *) There was in the beginning no point to anyone seeing this other
28
       then me, so there is a good chance that I haven't quite documented
29
       it well.
30
    *) Less design, more "make it work"
31
32
  Now there are a few cool things with it:
33
    *) Errors can result in corrupted data files.
34
    *) Data files can be read by spreadsheets directly.
35
36
TODO:
37
 *) Move to a block system for larger files
38
 *) Error recovery, its all there, just need to finish it
39
 *) Document how the chains work.
40
41
 -Brian
42
*/
1241.9.36 by Monty Taylor
ZOMG. I deleted drizzled/server_includes.h.
43
#include "config.h"
584.1.14 by Monty Taylor
Removed field.h from common_includes.
44
#include <drizzled/field.h>
584.5.1 by Monty Taylor
Removed field includes from field.h.
45
#include <drizzled/field/blob.h>
46
#include <drizzled/field/timestamp.h>
549 by Monty Taylor
Took gettext.h out of header files.
47
#include <drizzled/error.h>
584.1.15 by Monty Taylor
The mega-patch from hell. Renamed sql_class to session (since that's what it is) and removed it and field and table from common_includes.
48
#include <drizzled/table.h>
49
#include <drizzled/session.h>
1241.9.64 by Monty Taylor
Moved remaining non-public portions of mysys and mystrings to drizzled/internal.
50
#include "drizzled/internal/my_sys.h"
1 by brian
clean slate
51
992.1.31 by Monty Taylor
Moved csv.
52
#include "ha_tina.h"
53
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
54
#include <fcntl.h>
55
960.2.41 by Monty Taylor
Made StorageEngine name private. Added constructor param and accessor method.
56
#include <string>
1240.2.1 by Monty Taylor
Fixed the CSV tina_open_tables HASH to be a std::map.
57
#include <map>
960.2.41 by Monty Taylor
Made StorageEngine name private. Added constructor param and accessor method.
58
59
using namespace std;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
60
using namespace drizzled;
960.2.41 by Monty Taylor
Made StorageEngine name private. Added constructor param and accessor method.
61
1 by brian
clean slate
62
/*
481 by Brian Aker
Remove all of uchar.
63
  unsigned char + unsigned char + uint64_t + uint64_t + uint64_t + uint64_t + unsigned char
1 by brian
clean slate
64
*/
481 by Brian Aker
Remove all of uchar.
65
#define META_BUFFER_SIZE sizeof(unsigned char) + sizeof(unsigned char) + sizeof(uint64_t) \
66
  + sizeof(uint64_t) + sizeof(uint64_t) + sizeof(uint64_t) + sizeof(unsigned char)
1 by brian
clean slate
67
#define TINA_CHECK_HEADER 254 // The number we use to determine corruption
68
#define BLOB_MEMROOT_ALLOC_SIZE 8192
69
70
/* The file extension */
71
#define CSV_EXT ".CSV"               // The data file
72
#define CSN_EXT ".CSN"               // Files used during repair and update
73
#define CSM_EXT ".CSM"               // Meta file
74
75
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
76
static int read_meta_file(int meta_file, ha_rows *rows);
77
static int write_meta_file(int meta_file, ha_rows rows, bool dirty);
1 by brian
clean slate
78
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
79
void tina_get_status(void* param, int concurrent_insert);
80
void tina_update_status(void* param);
81
bool tina_check_status(void* param);
1 by brian
clean slate
82
83
/* Stuff for shares */
84
pthread_mutex_t tina_mutex;
85
86
/*****************************************************************************
87
 ** TINA tables
88
 *****************************************************************************/
89
90
/*
91
  Used for sorting chains with qsort().
92
*/
1085.1.2 by Monty Taylor
Fixed -Wmissing-declarations
93
static int sort_set (tina_set *a, tina_set *b)
1 by brian
clean slate
94
{
95
  /*
96
    We assume that intervals do not intersect. So, it is enought to compare
97
    any two points. Here we take start of intervals for comparison.
98
  */
99
  return ( a->begin > b->begin ? 1 : ( a->begin < b->begin ? -1 : 0 ) );
100
}
101
1039.3.1 by Stewart Smith
move bas_ext to StorageEngine instead of handler
102
103
/*
104
  If frm_error() is called in table.cc this is called to find out what file
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
105
  extensions exist for this Cursor.
1039.3.1 by Stewart Smith
move bas_ext to StorageEngine instead of handler
106
*/
107
static const char *ha_tina_exts[] = {
108
  CSV_EXT,
109
  CSM_EXT,
110
  NULL
111
};
112
1208 by Brian Aker
Merge Jay
113
class Tina : public drizzled::plugin::StorageEngine
960.2.30 by Monty Taylor
Tina done.
114
{
1240.2.2 by Monty Taylor
Turned TINA_SHARE into TinaShare.
115
  typedef std::map<string, TinaShare*> TinaMap;
1240.2.1 by Monty Taylor
Fixed the CSV tina_open_tables HASH to be a std::map.
116
  TinaMap tina_open_tables;
960.2.41 by Monty Taylor
Made StorageEngine name private. Added constructor param and accessor method.
117
public:
964.1.4 by Monty Taylor
Moved flags into private area.
118
  Tina(const string& name_arg)
1233.1.5 by Brian Aker
More table_flags converted.
119
   : drizzled::plugin::StorageEngine(name_arg,
120
                                     HTON_TEMPORARY_ONLY |
121
                                     HTON_NO_AUTO_INCREMENT |
122
                                     HTON_HAS_DATA_DICTIONARY |
1235.1.2 by Brian Aker
Added engine flag so that an engine can skip store_lock.
123
                                     HTON_SKIP_STORE_LOCK |
1240.2.1 by Monty Taylor
Fixed the CSV tina_open_tables HASH to be a std::map.
124
                                     HTON_FILE_BASED),
125
    tina_open_tables()
126
  {}
1324.2.3 by Monty Taylor
Remove plugin deinit.
127
  virtual ~Tina()
128
  {
129
    pthread_mutex_destroy(&tina_mutex);
130
  }
131
1208.3.2 by brian
Update for Cursor renaming.
132
  virtual Cursor *create(TableShare &table,
1253.1.3 by Monty Taylor
MEM_ROOT == memory::Root
133
                         drizzled::memory::Root *mem_root)
960.2.30 by Monty Taylor
Tina done.
134
  {
1208.3.2 by brian
Update for Cursor renaming.
135
    return new (mem_root) ha_tina(*this, table);
960.2.30 by Monty Taylor
Tina done.
136
  }
1039.3.1 by Stewart Smith
move bas_ext to StorageEngine instead of handler
137
138
  const char **bas_ext() const {
139
    return ha_tina_exts;
140
  }
141
1233.1.1 by Brian Aker
Remove HA_NO_TRANSACTIONS flag.
142
  int doCreateTable(Session *,
1183.1.18 by Brian Aker
Fixed references to doCreateTable()
143
                    Table& table_arg,
1358.1.2 by Brian Aker
Long pass through the system to use more of TableIdentifiers.
144
                    drizzled::TableIdentifier &identifier,
1222.1.7 by Brian Aker
Remove HA_CREATE_INFO from createTable()
145
                    drizzled::message::Table&);
1039.3.3 by Stewart Smith
Move handler::create to StorageEngine::create_table
146
1183.1.29 by Brian Aker
Clean up interface so that Truncate sets the propper engine when
147
  int doGetTableDefinition(Session& session,
1358.1.2 by Brian Aker
Long pass through the system to use more of TableIdentifiers.
148
                           TableIdentifier &identifier,
1354.1.1 by Brian Aker
Modify ptr to reference.
149
                           drizzled::message::Table &table_message);
1183.1.21 by Brian Aker
Fixed temp engines to no longer write out DFE. I have two designs right now
150
151
  /* Temp only engine, so do not return values. */
1241.9.44 by Monty Taylor
Made magic with cached_directory.
152
  void doGetTableNames(drizzled::CachedDirectory &, string& , set<string>&) { };
1183.1.21 by Brian Aker
Fixed temp engines to no longer write out DFE. I have two designs right now
153
1358.1.3 by Brian Aker
doDropTable() now only uses identifier.
154
  int doDropTable(Session&, TableIdentifier &identifier);
1240.2.2 by Monty Taylor
Turned TINA_SHARE into TinaShare.
155
  TinaShare *findOpenTable(const string table_name);
156
  void addOpenTable(const string &table_name, TinaShare *);
1240.2.1 by Monty Taylor
Fixed the CSV tina_open_tables HASH to be a std::map.
157
  void deleteOpenTable(const string &table_name);
158
1233.1.9 by Brian Aker
Move max key stuff up to engine.
159
160
  uint32_t max_keys()          const { return 0; }
161
  uint32_t max_key_parts()     const { return 0; }
162
  uint32_t max_key_length()    const { return 0; }
1358.1.1 by Brian Aker
Fixes regression in performance from Exists patch.
163
  bool doDoesTableExist(Session& session, TableIdentifier &identifier);
1390 by Brian Aker
Update interface to use Identifiers directly.
164
  int doRenameTable(Session&, TableIdentifier &from, TableIdentifier &to);
960.2.30 by Monty Taylor
Tina done.
165
};
166
1358.1.1 by Brian Aker
Fixes regression in performance from Exists patch.
167
1390 by Brian Aker
Update interface to use Identifiers directly.
168
int Tina::doRenameTable(Session&,
169
                        TableIdentifier &from, TableIdentifier &to)
1389 by Brian Aker
Large reord in ALTER TABLE for RENAME.
170
{
171
  int error= 0;
172
  for (const char **ext= bas_ext(); *ext ; ext++)
173
  {
1390 by Brian Aker
Update interface to use Identifiers directly.
174
    if (rename_file_ext(from.getPath().c_str(), to.getPath().c_str(), *ext))
1389 by Brian Aker
Large reord in ALTER TABLE for RENAME.
175
    {
176
      if ((error=errno) != ENOENT)
177
        break;
178
      error= 0;
179
    }
180
  }
181
  return error;
182
}
183
1372.1.4 by Brian Aker
Update to remove cache in enginges for per session (which also means... no
184
bool Tina::doDoesTableExist(Session &session, TableIdentifier &identifier)
1358.1.1 by Brian Aker
Fixes regression in performance from Exists patch.
185
{
1372.1.4 by Brian Aker
Update to remove cache in enginges for per session (which also means... no
186
  return session.doesTableMessageExist(identifier);
1358.1.1 by Brian Aker
Fixes regression in performance from Exists patch.
187
}
188
189
1372.1.4 by Brian Aker
Update to remove cache in enginges for per session (which also means... no
190
int Tina::doDropTable(Session &session,
1358.1.3 by Brian Aker
doDropTable() now only uses identifier.
191
                      TableIdentifier &identifier)
1183.1.21 by Brian Aker
Fixed temp engines to no longer write out DFE. I have two designs right now
192
{
193
  int error= 0;
194
  int enoent_or_zero= ENOENT;                   // Error if no file was deleted
195
  char buff[FN_REFLEN];
196
197
  for (const char **ext= bas_ext(); *ext ; ext++)
198
  {
1358.1.9 by Brian Aker
Update for std::string
199
    internal::fn_format(buff, identifier.getPath().c_str(), "", *ext,
200
                        MY_UNPACK_FILENAME|MY_APPEND_EXT);
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
201
    if (internal::my_delete_with_symlink(buff, MYF(0)))
1183.1.21 by Brian Aker
Fixed temp engines to no longer write out DFE. I have two designs right now
202
    {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
203
      if ((error= errno) != ENOENT)
1183.1.21 by Brian Aker
Fixed temp engines to no longer write out DFE. I have two designs right now
204
	break;
205
    }
206
    else
207
      enoent_or_zero= 0;                        // No error for ENOENT
208
    error= enoent_or_zero;
209
  }
210
1372.1.4 by Brian Aker
Update to remove cache in enginges for per session (which also means... no
211
  session.removeTableMessage(identifier);
1183.1.21 by Brian Aker
Fixed temp engines to no longer write out DFE. I have two designs right now
212
213
  return error;
214
}
215
1240.2.2 by Monty Taylor
Turned TINA_SHARE into TinaShare.
216
TinaShare *Tina::findOpenTable(const string table_name)
1240.2.1 by Monty Taylor
Fixed the CSV tina_open_tables HASH to be a std::map.
217
{
218
  TinaMap::iterator find_iter=
219
    tina_open_tables.find(table_name);
220
221
  if (find_iter != tina_open_tables.end())
222
    return (*find_iter).second;
223
  else
224
    return NULL;
225
}
226
1240.2.2 by Monty Taylor
Turned TINA_SHARE into TinaShare.
227
void Tina::addOpenTable(const string &table_name, TinaShare *share)
1240.2.1 by Monty Taylor
Fixed the CSV tina_open_tables HASH to be a std::map.
228
{
229
  tina_open_tables[table_name]= share;
230
}
231
232
void Tina::deleteOpenTable(const string &table_name)
233
{
234
  tina_open_tables.erase(table_name);
235
}
236
237
1372.1.4 by Brian Aker
Update to remove cache in enginges for per session (which also means... no
238
int Tina::doGetTableDefinition(Session &session,
1358.1.7 by Brian Aker
Remove interface bits around caller for internal lookup of create table.
239
                               drizzled::TableIdentifier &identifier,
1354.1.1 by Brian Aker
Modify ptr to reference.
240
                               drizzled::message::Table &table_message)
1183.1.21 by Brian Aker
Fixed temp engines to no longer write out DFE. I have two designs right now
241
{
1372.1.4 by Brian Aker
Update to remove cache in enginges for per session (which also means... no
242
  if (session.getTableMessage(identifier, table_message))
243
    return EEXIST;
244
245
  return ENOENT;
1183.1.21 by Brian Aker
Fixed temp engines to no longer write out DFE. I have two designs right now
246
}
247
248
971.1.51 by Monty Taylor
New-style plugin registration now works.
249
static Tina *tina_engine= NULL;
250
1324.2.2 by Monty Taylor
Use the plugin::Context everywhere.
251
static int tina_init_func(drizzled::plugin::Context &context)
1 by brian
clean slate
252
{
960.2.30 by Monty Taylor
Tina done.
253
1192.5.8 by Monty Taylor
Made csv dynamic
254
  tina_engine= new Tina("CSV");
1324.2.2 by Monty Taylor
Use the plugin::Context everywhere.
255
  context.add(tina_engine);
960.2.30 by Monty Taylor
Tina done.
256
398.1.10 by Monty Taylor
Actually removed VOID() this time.
257
  pthread_mutex_init(&tina_mutex,MY_MUTEX_INIT_FAST);
1 by brian
clean slate
258
  return 0;
259
}
260
261
262
1240.2.2 by Monty Taylor
Turned TINA_SHARE into TinaShare.
263
TinaShare::TinaShare(const char *table_name_arg)
264
  : table_name(table_name_arg), use_count(0), saved_data_file_length(0),
265
    update_file_opened(false), tina_write_opened(false),
266
    crashed(false), rows_recorded(0), data_file_version(0)
267
{
1240.2.3 by Monty Taylor
Fixed blackhole crashses on Spare - made Blackhole follow the pattern of CSV and Archive.
268
  thr_lock_init(&lock);
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
269
  internal::fn_format(data_file_name, table_name_arg, "", CSV_EXT,
1240.2.2 by Monty Taylor
Turned TINA_SHARE into TinaShare.
270
            MY_REPLACE_EXT|MY_UNPACK_FILENAME);
271
}
272
273
TinaShare::~TinaShare()
274
{
275
  thr_lock_delete(&lock);
276
  pthread_mutex_destroy(&mutex);
277
}
278
1 by brian
clean slate
279
/*
280
  Simple lock controls.
281
*/
1240.2.2 by Monty Taylor
Turned TINA_SHARE into TinaShare.
282
TinaShare *ha_tina::get_share(const char *table_name)
1 by brian
clean slate
283
{
1240.2.1 by Monty Taylor
Fixed the CSV tina_open_tables HASH to be a std::map.
284
  pthread_mutex_lock(&tina_mutex);
285
286
  Tina *a_tina= static_cast<Tina *>(engine);
287
  share= a_tina->findOpenTable(table_name);
288
1 by brian
clean slate
289
  char meta_file_name[FN_REFLEN];
15 by brian
Fix for stat, NETWARE removal
290
  struct stat file_stat;
1 by brian
clean slate
291
292
  /*
293
    If share is not present in the hash, create a new share and
294
    initialize its members.
295
  */
1240.2.1 by Monty Taylor
Fixed the CSV tina_open_tables HASH to be a std::map.
296
  if (! share)
1 by brian
clean slate
297
  {
1240.2.2 by Monty Taylor
Turned TINA_SHARE into TinaShare.
298
    share= new TinaShare(table_name);
299
300
    if (share == NULL)
1 by brian
clean slate
301
    {
302
      pthread_mutex_unlock(&tina_mutex);
303
      return NULL;
304
    }
305
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
306
    internal::fn_format(meta_file_name, table_name, "", CSM_EXT,
1 by brian
clean slate
307
              MY_REPLACE_EXT|MY_UNPACK_FILENAME);
308
15 by brian
Fix for stat, NETWARE removal
309
    if (stat(share->data_file_name, &file_stat))
1240.2.2 by Monty Taylor
Turned TINA_SHARE into TinaShare.
310
    {
311
      pthread_mutex_unlock(&tina_mutex);
312
      delete share;
313
      return NULL;
314
    }
315
  
1 by brian
clean slate
316
    share->saved_data_file_length= file_stat.st_size;
317
1240.2.1 by Monty Taylor
Fixed the CSV tina_open_tables HASH to be a std::map.
318
    a_tina->addOpenTable(share->table_name, share);
319
1 by brian
clean slate
320
    pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST);
321
322
    /*
323
      Open or create the meta file. In the latter case, we'll get
324
      an error during read_meta_file and mark the table as crashed.
325
      Usually this will result in auto-repair, and we will get a good
326
      meta-file in the end.
327
    */
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
328
    if ((share->meta_file= internal::my_open(meta_file_name,
1309.1.3 by Brian Aker
Cache for Schema.
329
                                             O_RDWR|O_CREAT, MYF(0))) == -1)
163 by Brian Aker
Merge Monty's code.
330
      share->crashed= true;
1 by brian
clean slate
331
332
    /*
333
      If the meta file will not open we assume it is crashed and
334
      mark it as such.
335
    */
336
    if (read_meta_file(share->meta_file, &share->rows_recorded))
163 by Brian Aker
Merge Monty's code.
337
      share->crashed= true;
1 by brian
clean slate
338
  }
339
  share->use_count++;
340
  pthread_mutex_unlock(&tina_mutex);
341
342
  return share;
343
}
344
345
346
/*
347
  Read CSV meta-file
348
349
  SYNOPSIS
350
    read_meta_file()
351
    meta_file   The meta-file filedes
352
    ha_rows     Pointer to the var we use to store rows count.
353
                These are read from the meta-file.
354
355
  DESCRIPTION
356
357
    Read the meta-file info. For now we are only interested in
358
    rows counf, crashed bit and magic number.
359
360
  RETURN
361
    0 - OK
362
    non-zero - error occurred
363
*/
364
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
365
static int read_meta_file(int meta_file, ha_rows *rows)
1 by brian
clean slate
366
{
481 by Brian Aker
Remove all of uchar.
367
  unsigned char meta_buffer[META_BUFFER_SIZE];
368
  unsigned char *ptr= meta_buffer;
1 by brian
clean slate
369
656.1.39 by Monty Taylor
Removed my_seek, my_tell, my_fwrite, my_fseek.
370
  lseek(meta_file, 0, SEEK_SET);
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
371
  if (internal::my_read(meta_file, (unsigned char*)meta_buffer, META_BUFFER_SIZE, 0)
1 by brian
clean slate
372
      != META_BUFFER_SIZE)
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
373
    return(HA_ERR_CRASHED_ON_USAGE);
1 by brian
clean slate
374
375
  /*
376
    Parse out the meta data, we ignore version at the moment
377
  */
378
481 by Brian Aker
Remove all of uchar.
379
  ptr+= sizeof(unsigned char)*2; // Move past header
1 by brian
clean slate
380
  *rows= (ha_rows)uint8korr(ptr);
381
  ptr+= sizeof(uint64_t); // Move past rows
382
  /*
383
    Move past check_point, auto_increment and forced_flushes fields.
384
    They are present in the format, but we do not use them yet.
385
  */
386
  ptr+= 3*sizeof(uint64_t);
387
388
  /* check crashed bit and magic number */
481 by Brian Aker
Remove all of uchar.
389
  if ((meta_buffer[0] != (unsigned char)TINA_CHECK_HEADER) ||
163 by Brian Aker
Merge Monty's code.
390
      ((bool)(*ptr)== true))
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
391
    return(HA_ERR_CRASHED_ON_USAGE);
1 by brian
clean slate
392
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
393
  internal::my_sync(meta_file, MYF(MY_WME));
1 by brian
clean slate
394
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
395
  return(0);
1 by brian
clean slate
396
}
397
398
399
/*
400
  Write CSV meta-file
401
402
  SYNOPSIS
403
    write_meta_file()
404
    meta_file   The meta-file filedes
405
    ha_rows     The number of rows we have in the datafile.
406
    dirty       A flag, which marks whether we have a corrupt table
407
408
  DESCRIPTION
409
410
    Write meta-info the the file. Only rows count, crashed bit and
411
    magic number matter now.
412
413
  RETURN
414
    0 - OK
415
    non-zero - error occurred
416
*/
417
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
418
static int write_meta_file(int meta_file, ha_rows rows, bool dirty)
1 by brian
clean slate
419
{
481 by Brian Aker
Remove all of uchar.
420
  unsigned char meta_buffer[META_BUFFER_SIZE];
421
  unsigned char *ptr= meta_buffer;
1 by brian
clean slate
422
481 by Brian Aker
Remove all of uchar.
423
  *ptr= (unsigned char)TINA_CHECK_HEADER;
424
  ptr+= sizeof(unsigned char);
425
  *ptr= (unsigned char)TINA_VERSION;
426
  ptr+= sizeof(unsigned char);
1 by brian
clean slate
427
  int8store(ptr, (uint64_t)rows);
428
  ptr+= sizeof(uint64_t);
429
  memset(ptr, 0, 3*sizeof(uint64_t));
430
  /*
431
     Skip over checkpoint, autoincrement and forced_flushes fields.
432
     We'll need them later.
433
  */
434
  ptr+= 3*sizeof(uint64_t);
481 by Brian Aker
Remove all of uchar.
435
  *ptr= (unsigned char)dirty;
1 by brian
clean slate
436
656.1.39 by Monty Taylor
Removed my_seek, my_tell, my_fwrite, my_fseek.
437
  lseek(meta_file, 0, SEEK_SET);
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
438
  if (internal::my_write(meta_file, (unsigned char *)meta_buffer, META_BUFFER_SIZE, 0)
1 by brian
clean slate
439
      != META_BUFFER_SIZE)
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
440
    return(-1);
1 by brian
clean slate
441
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
442
  internal::my_sync(meta_file, MYF(MY_WME));
1 by brian
clean slate
443
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
444
  return(0);
1 by brian
clean slate
445
}
446
447
int ha_tina::init_tina_writer()
448
{
449
  /*
450
    Mark the file as crashed. We will set the flag back when we close
451
    the file. In the case of the crash it will remain marked crashed,
452
    which enforce recovery.
453
  */
163 by Brian Aker
Merge Monty's code.
454
  (void)write_meta_file(share->meta_file, share->rows_recorded, true);
1 by brian
clean slate
455
456
  if ((share->tina_write_filedes=
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
457
        internal::my_open(share->data_file_name, O_RDWR|O_APPEND, MYF(0))) == -1)
1 by brian
clean slate
458
  {
163 by Brian Aker
Merge Monty's code.
459
    share->crashed= true;
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
460
    return(1);
1 by brian
clean slate
461
  }
163 by Brian Aker
Merge Monty's code.
462
  share->tina_write_opened= true;
1 by brian
clean slate
463
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
464
  return(0);
1 by brian
clean slate
465
}
466
467
468
/*
469
  Free lock controls.
470
*/
1240.2.1 by Monty Taylor
Fixed the CSV tina_open_tables HASH to be a std::map.
471
int ha_tina::free_share()
1 by brian
clean slate
472
{
473
  pthread_mutex_lock(&tina_mutex);
474
  int result_code= 0;
475
  if (!--share->use_count){
476
    /* Write the meta file. Mark it as crashed if needed. */
477
    (void)write_meta_file(share->meta_file, share->rows_recorded,
163 by Brian Aker
Merge Monty's code.
478
                          share->crashed ? true :false);
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
479
    if (internal::my_close(share->meta_file, MYF(0)))
1 by brian
clean slate
480
      result_code= 1;
481
    if (share->tina_write_opened)
482
    {
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
483
      if (internal::my_close(share->tina_write_filedes, MYF(0)))
1 by brian
clean slate
484
        result_code= 1;
163 by Brian Aker
Merge Monty's code.
485
      share->tina_write_opened= false;
1 by brian
clean slate
486
    }
487
1240.2.1 by Monty Taylor
Fixed the CSV tina_open_tables HASH to be a std::map.
488
    Tina *a_tina= static_cast<Tina *>(engine);
1240.2.2 by Monty Taylor
Turned TINA_SHARE into TinaShare.
489
    a_tina->deleteOpenTable(share->table_name);
490
    delete share;
1 by brian
clean slate
491
  }
492
  pthread_mutex_unlock(&tina_mutex);
493
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
494
  return(result_code);
1 by brian
clean slate
495
}
496
497
498
/*
499
  This function finds the end of a line and returns the length
500
  of the line ending.
501
502
  We support three kinds of line endings:
503
  '\r'     --  Old Mac OS line ending
504
  '\n'     --  Traditional Unix and Mac OS X line ending
505
  '\r''\n' --  DOS\Windows line ending
506
*/
507
1085.1.2 by Monty Taylor
Fixed -Wmissing-declarations
508
static off_t find_eoln_buff(Transparent_file *data_buff, off_t begin,
509
                            off_t end, int *eoln_len)
1 by brian
clean slate
510
{
511
  *eoln_len= 0;
512
513
  for (off_t x= begin; x < end; x++)
514
  {
515
    /* Unix (includes Mac OS X) */
516
    if (data_buff->get_value(x) == '\n')
517
      *eoln_len= 1;
518
    else
519
      if (data_buff->get_value(x) == '\r') // Mac or Dos
520
      {
521
        /* old Mac line ending */
522
        if (x + 1 == end || (data_buff->get_value(x + 1) != '\n'))
523
          *eoln_len= 1;
524
        else // DOS style ending
525
          *eoln_len= 2;
526
      }
527
528
    if (*eoln_len)  // end of line was found
529
      return x;
530
  }
531
532
  return 0;
533
}
534
535
536
1208.3.2 by brian
Update for Cursor renaming.
537
ha_tina::ha_tina(drizzled::plugin::StorageEngine &engine_arg, TableShare &table_arg)
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
538
  :Cursor(engine_arg, table_arg),
1 by brian
clean slate
539
  /*
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
540
    These definitions are found in Cursor.h
1 by brian
clean slate
541
    They are not probably completely right.
542
  */
543
  current_position(0), next_position(0), local_saved_data_file_length(0),
544
  file_buff(0), chain_alloced(0), chain_size(DEFAULT_CHAIN_LENGTH),
545
  local_data_file_version(0), records_is_known(0)
546
{
547
  /* Set our original buffers from pre-allocated memory */
548
  buffer.set((char*)byte_buffer, IO_SIZE, &my_charset_bin);
549
  chain= chain_buffer;
550
  file_buff= new Transparent_file();
551
}
552
553
554
/*
555
  Encode a buffer into the quoted format.
556
*/
557
653 by Brian Aker
More solaris bits
558
int ha_tina::encode_quote(unsigned char *)
1 by brian
clean slate
559
{
560
  char attribute_buffer[1024];
561
  String attribute(attribute_buffer, sizeof(attribute_buffer),
562
                   &my_charset_bin);
563
564
  buffer.length(0);
565
566
  for (Field **field=table->field ; *field ; field++)
567
  {
568
    const char *ptr;
569
    const char *end_ptr;
570
    const bool was_null= (*field)->is_null();
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
571
1 by brian
clean slate
572
    /*
573
      assistance for backwards compatibility in production builds.
574
      note: this will not work for ENUM columns.
575
    */
576
    if (was_null)
577
    {
578
      (*field)->set_default();
579
      (*field)->set_notnull();
580
    }
581
1089.1.3 by Brian Aker
Fix protobuf to release memory. Add in assert() for wrong column usage. Fix
582
    /* 
583
      Since we are needing to "translate" the type into a string we 
584
      will need to do a val_str(). This would cause an assert() to
585
      normally occur since we are onlying "writing" values.
586
    */
587
    (*field)->setReadSet();
1 by brian
clean slate
588
    (*field)->val_str(&attribute,&attribute);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
589
1 by brian
clean slate
590
    if (was_null)
591
      (*field)->set_null();
592
593
    if ((*field)->str_needs_quotes())
594
    {
595
      ptr= attribute.ptr();
596
      end_ptr= attribute.length() + ptr;
597
598
      buffer.append('"');
599
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
600
      while (ptr < end_ptr)
1 by brian
clean slate
601
      {
602
        if (*ptr == '"')
603
        {
604
          buffer.append('\\');
605
          buffer.append('"');
606
          *ptr++;
607
        }
608
        else if (*ptr == '\r')
609
        {
610
          buffer.append('\\');
611
          buffer.append('r');
612
          *ptr++;
613
        }
614
        else if (*ptr == '\\')
615
        {
616
          buffer.append('\\');
617
          buffer.append('\\');
618
          *ptr++;
619
        }
620
        else if (*ptr == '\n')
621
        {
622
          buffer.append('\\');
623
          buffer.append('n');
624
          *ptr++;
625
        }
626
        else
627
          buffer.append(*ptr++);
628
      }
629
      buffer.append('"');
630
    }
631
    else
632
    {
633
      buffer.append(attribute);
634
    }
635
636
    buffer.append(',');
637
  }
638
  // Remove the comma, add a line feed
639
  buffer.length(buffer.length() - 1);
640
  buffer.append('\n');
641
642
  //buffer.replace(buffer.length(), 0, "\n", 1);
643
644
  return (buffer.length());
645
}
646
647
/*
648
  chain_append() adds delete positions to the chain that we use to keep
649
  track of space. Then the chain will be used to cleanup "holes", occurred
650
  due to deletes and updates.
651
*/
652
int ha_tina::chain_append()
653
{
654
  if ( chain_ptr != chain && (chain_ptr -1)->end == current_position)
655
    (chain_ptr -1)->end= next_position;
656
  else
657
  {
658
    /* We set up for the next position */
659
    if ((off_t)(chain_ptr - chain) == (chain_size -1))
660
    {
661
      off_t location= chain_ptr - chain;
662
      chain_size += DEFAULT_CHAIN_LENGTH;
663
      if (chain_alloced)
664
      {
656.1.25 by Monty Taylor
Removed my_malloc stuff from storage/
665
        if ((chain= (tina_set *) realloc(chain, chain_size)) == NULL)
1 by brian
clean slate
666
          return -1;
667
      }
668
      else
669
      {
656.1.25 by Monty Taylor
Removed my_malloc stuff from storage/
670
        tina_set *ptr= (tina_set *) malloc(chain_size * sizeof(tina_set));
656.1.47 by Monty Taylor
More malloc return check fixes.
671
        if (ptr == NULL)
672
          return -1;
1 by brian
clean slate
673
        memcpy(ptr, chain, DEFAULT_CHAIN_LENGTH * sizeof(tina_set));
674
        chain= ptr;
675
        chain_alloced++;
676
      }
677
      chain_ptr= chain + location;
678
    }
679
    chain_ptr->begin= current_position;
680
    chain_ptr->end= next_position;
681
    chain_ptr++;
682
  }
683
684
  return 0;
685
}
686
687
688
/*
689
  Scans for a row.
690
*/
481 by Brian Aker
Remove all of uchar.
691
int ha_tina::find_current_row(unsigned char *buf)
1 by brian
clean slate
692
{
693
  off_t end_offset, curr_offset= current_position;
694
  int eoln_len;
695
  int error;
696
1253.1.1 by Monty Taylor
First bits of namespacing. Ugh. Why do I do this to myself.
697
  free_root(&blobroot, MYF(drizzled::memory::MARK_BLOCKS_FREE));
1 by brian
clean slate
698
699
  /*
700
    We do not read further then local_saved_data_file_length in order
701
    not to conflict with undergoing concurrent insert.
702
  */
703
  if ((end_offset=
704
        find_eoln_buff(file_buff, current_position,
705
                       local_saved_data_file_length, &eoln_len)) == 0)
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
706
    return(HA_ERR_END_OF_FILE);
1 by brian
clean slate
707
708
  error= HA_ERR_CRASHED_ON_USAGE;
709
710
  memset(buf, 0, table->s->null_bytes);
711
712
  for (Field **field=table->field ; *field ; field++)
713
  {
714
    char curr_char;
584.5.1 by Monty Taylor
Removed field includes from field.h.
715
1 by brian
clean slate
716
    buffer.length(0);
717
    if (curr_offset >= end_offset)
718
      goto err;
719
    curr_char= file_buff->get_value(curr_offset);
720
    if (curr_char == '"')
721
    {
722
      curr_offset++; // Incrementpast the first quote
723
724
      for(; curr_offset < end_offset; curr_offset++)
725
      {
726
        curr_char= file_buff->get_value(curr_offset);
727
        // Need to convert line feeds!
728
        if (curr_char == '"' &&
729
            (curr_offset == end_offset - 1 ||
730
             file_buff->get_value(curr_offset + 1) == ','))
731
        {
732
          curr_offset+= 2; // Move past the , and the "
733
          break;
734
        }
735
        if (curr_char == '\\' && curr_offset != (end_offset - 1))
736
        {
737
          curr_offset++;
738
          curr_char= file_buff->get_value(curr_offset);
739
          if (curr_char == 'r')
740
            buffer.append('\r');
741
          else if (curr_char == 'n' )
742
            buffer.append('\n');
743
          else if (curr_char == '\\' || curr_char == '"')
744
            buffer.append(curr_char);
745
          else  /* This could only happed with an externally created file */
746
          {
747
            buffer.append('\\');
748
            buffer.append(curr_char);
749
          }
750
        }
751
        else // ordinary symbol
752
        {
753
          /*
754
            We are at final symbol and no last quote was found =>
755
            we are working with a damaged file.
756
          */
757
          if (curr_offset == end_offset - 1)
758
            goto err;
759
          buffer.append(curr_char);
760
        }
761
      }
762
    }
584.5.1 by Monty Taylor
Removed field includes from field.h.
763
    else
1 by brian
clean slate
764
    {
765
      for(; curr_offset < end_offset; curr_offset++)
766
      {
767
        curr_char= file_buff->get_value(curr_offset);
768
        if (curr_char == ',')
769
        {
770
          curr_offset++;       // Skip the ,
771
          break;
772
        }
773
        buffer.append(curr_char);
774
      }
775
    }
776
1089.1.3 by Brian Aker
Fix protobuf to release memory. Add in assert() for wrong column usage. Fix
777
    if ((*field)->isReadSet() || (*field)->isWriteSet())
1 by brian
clean slate
778
    {
1089.1.3 by Brian Aker
Fix protobuf to release memory. Add in assert() for wrong column usage. Fix
779
      /* This masks a bug in the logic for a SELECT * */
780
      (*field)->setWriteSet();
1 by brian
clean slate
781
      if ((*field)->store(buffer.ptr(), buffer.length(), buffer.charset(),
782
                          CHECK_FIELD_WARN))
783
        goto err;
1089.1.3 by Brian Aker
Fix protobuf to release memory. Add in assert() for wrong column usage. Fix
784
1 by brian
clean slate
785
      if ((*field)->flags & BLOB_FLAG)
786
      {
787
        Field_blob *blob= *(Field_blob**) field;
481 by Brian Aker
Remove all of uchar.
788
        unsigned char *src, *tgt;
482 by Brian Aker
Remove uint.
789
        uint32_t length, packlength;
584.5.1 by Monty Taylor
Removed field includes from field.h.
790
1 by brian
clean slate
791
        packlength= blob->pack_length_no_ptr();
792
        length= blob->get_length(blob->ptr);
212.6.3 by Mats Kindahl
Removing deprecated functions from code and replacing them with C99 equivalents:
793
        memcpy(&src, blob->ptr + packlength, sizeof(char*));
1 by brian
clean slate
794
        if (src)
795
        {
481 by Brian Aker
Remove all of uchar.
796
          tgt= (unsigned char*) alloc_root(&blobroot, length);
629.3.4 by Kristian Nielsen
Take Mats'es changes from bmove()->memcpy(), and fix all of them to be
797
          memmove(tgt, src, length);
212.6.3 by Mats Kindahl
Removing deprecated functions from code and replacing them with C99 equivalents:
798
          memcpy(blob->ptr + packlength, &tgt, sizeof(char*));
1 by brian
clean slate
799
        }
800
      }
801
    }
802
  }
803
  next_position= end_offset + eoln_len;
804
  error= 0;
805
806
err:
807
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
808
  return(error);
1 by brian
clean slate
809
}
810
811
/*
812
  Three functions below are needed to enable concurrent insert functionality
813
  for CSV engine. For more details see mysys/thr_lock.c
814
*/
815
653 by Brian Aker
More solaris bits
816
void tina_get_status(void* param, int)
1 by brian
clean slate
817
{
818
  ha_tina *tina= (ha_tina*) param;
819
  tina->get_status();
820
}
821
822
void tina_update_status(void* param)
823
{
824
  ha_tina *tina= (ha_tina*) param;
825
  tina->update_status();
826
}
827
828
/* this should exist and return 0 for concurrent insert to work */
653 by Brian Aker
More solaris bits
829
bool tina_check_status(void *)
1 by brian
clean slate
830
{
831
  return 0;
832
}
833
834
/*
835
  Save the state of the table
836
837
  SYNOPSIS
838
    get_status()
839
840
  DESCRIPTION
841
    This function is used to retrieve the file length. During the lock
842
    phase of concurrent insert. For more details see comment to
843
    ha_tina::update_status below.
844
*/
845
846
void ha_tina::get_status()
847
{
848
  local_saved_data_file_length= share->saved_data_file_length;
849
}
850
851
852
/*
853
  Correct the state of the table. Called by unlock routines
854
  before the write lock is released.
855
856
  SYNOPSIS
857
    update_status()
858
859
  DESCRIPTION
860
    When we employ concurrent insert lock, we save current length of the file
861
    during the lock phase. We do not read further saved value, as we don't
862
    want to interfere with undergoing concurrent insert. Writers update file
863
    length info during unlock with update_status().
864
865
  NOTE
866
    For log tables concurrent insert works different. The reason is that
867
    log tables are always opened and locked. And as they do not unlock
868
    tables, the file length after writes should be updated in a different
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
869
    way.
1 by brian
clean slate
870
*/
871
872
void ha_tina::update_status()
873
{
874
  /* correct local_saved_data_file_length for writers */
875
  share->saved_data_file_length= local_saved_data_file_length;
876
}
877
878
879
/*
880
  Open a database file. Keep in mind that tables are caches, so
881
  this will not be called for every request. Any sort of positions
882
  that need to be reset should be kept in the ::extra() call.
883
*/
1237.6.2 by Brian Aker
Minor cleanup for dead code.
884
int ha_tina::open(const char *name, int, uint32_t)
1 by brian
clean slate
885
{
1240.2.1 by Monty Taylor
Fixed the CSV tina_open_tables HASH to be a std::map.
886
  if (!(share= get_share(name)))
820.3.1 by Padraig
Changed ha_tina::open to return the correct error code
887
    return(ENOENT);
1 by brian
clean slate
888
1237.6.2 by Brian Aker
Minor cleanup for dead code.
889
  if (share->crashed)
1 by brian
clean slate
890
  {
1240.2.1 by Monty Taylor
Fixed the CSV tina_open_tables HASH to be a std::map.
891
    free_share();
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
892
    return(HA_ERR_CRASHED_ON_USAGE);
1 by brian
clean slate
893
  }
894
895
  local_data_file_version= share->data_file_version;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
896
  if ((data_file= internal::my_open(share->data_file_name, O_RDONLY, MYF(0))) == -1)
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
897
    return(0);
1 by brian
clean slate
898
899
  /*
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
900
    Init locking. Pass Cursor object to the locking routines,
1 by brian
clean slate
901
    so that they could save/update local_saved_data_file_length value
902
    during locking. This is needed to enable concurrent inserts.
903
  */
904
  thr_lock_data_init(&share->lock, &lock, (void*) this);
905
  ref_length=sizeof(off_t);
906
907
  share->lock.get_status= tina_get_status;
908
  share->lock.update_status= tina_update_status;
909
  share->lock.check_status= tina_check_status;
910
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
911
  return(0);
1 by brian
clean slate
912
}
913
914
915
/*
916
  Close a database file. We remove ourselves from the shared strucutre.
917
  If it is empty we destroy it.
918
*/
919
int ha_tina::close(void)
920
{
921
  int rc= 0;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
922
  rc= internal::my_close(data_file, MYF(0));
1240.2.1 by Monty Taylor
Fixed the CSV tina_open_tables HASH to be a std::map.
923
  return(free_share() || rc);
1 by brian
clean slate
924
}
925
926
/*
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
927
  This is an INSERT. At the moment this Cursor just seeks to the end
1 by brian
clean slate
928
  of the file and appends the data. In an error case it really should
929
  just truncate to the original position (this is not done yet).
930
*/
481 by Brian Aker
Remove all of uchar.
931
int ha_tina::write_row(unsigned char * buf)
1 by brian
clean slate
932
{
933
  int size;
934
935
  if (share->crashed)
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
936
      return(HA_ERR_CRASHED_ON_USAGE);
1 by brian
clean slate
937
1273.16.8 by Brian Aker
Remove typedef.
938
  ha_statistic_increment(&system_status_var::ha_write_count);
1 by brian
clean slate
939
940
  size= encode_quote(buf);
941
942
  if (!share->tina_write_opened)
943
    if (init_tina_writer())
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
944
      return(-1);
1 by brian
clean slate
945
946
   /* use pwrite, as concurrent reader could have changed the position */
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
947
  if (internal::my_write(share->tina_write_filedes, (unsigned char*)buffer.ptr(), size,
1 by brian
clean slate
948
               MYF(MY_WME | MY_NABP)))
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
949
    return(-1);
1 by brian
clean slate
950
951
  /* update local copy of the max position to see our own changes */
952
  local_saved_data_file_length+= size;
953
954
  /* update shared info */
955
  pthread_mutex_lock(&share->mutex);
956
  share->rows_recorded++;
957
  /* update status for the log tables */
958
  pthread_mutex_unlock(&share->mutex);
959
960
  stats.records++;
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
961
  return(0);
1 by brian
clean slate
962
}
963
964
965
int ha_tina::open_update_temp_file_if_needed()
966
{
967
  char updated_fname[FN_REFLEN];
968
969
  if (!share->update_file_opened)
970
  {
971
    if ((update_temp_file=
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
972
           internal::my_create(internal::fn_format(updated_fname, share->table_name.c_str(),
1 by brian
clean slate
973
                               "", CSN_EXT,
974
                               MY_REPLACE_EXT | MY_UNPACK_FILENAME),
975
                     0, O_RDWR | O_TRUNC, MYF(MY_WME))) < 0)
976
      return 1;
163 by Brian Aker
Merge Monty's code.
977
    share->update_file_opened= true;
1 by brian
clean slate
978
    temp_file_length= 0;
979
  }
980
  return 0;
981
}
982
983
/*
984
  This is called for an update.
985
  Make sure you put in code to increment the auto increment, also
986
  update any timestamp data. Currently auto increment is not being
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
987
  fixed since autoincrements have yet to be added to this table Cursor.
1 by brian
clean slate
988
  This will be called in a table scan right before the previous ::rnd_next()
989
  call.
990
*/
653 by Brian Aker
More solaris bits
991
int ha_tina::update_row(const unsigned char *, unsigned char * new_data)
1 by brian
clean slate
992
{
993
  int size;
994
  int rc= -1;
995
1273.16.8 by Brian Aker
Remove typedef.
996
  ha_statistic_increment(&system_status_var::ha_update_count);
1 by brian
clean slate
997
998
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
999
    table->timestamp_field->set_time();
1000
1001
  size= encode_quote(new_data);
1002
1003
  /*
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1004
    During update we mark each updating record as deleted
1005
    (see the chain_append()) then write new one to the temporary data file.
1 by brian
clean slate
1006
    At the end of the sequence in the rnd_end() we append all non-marked
1007
    records from the data file to the temporary data file then rename it.
1008
    The temp_file_length is used to calculate new data file length.
1009
  */
1010
  if (chain_append())
1011
    goto err;
1012
1013
  if (open_update_temp_file_if_needed())
1014
    goto err;
1015
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1016
  if (internal::my_write(update_temp_file, (unsigned char*)buffer.ptr(), size,
1 by brian
clean slate
1017
               MYF(MY_WME | MY_NABP)))
1018
    goto err;
1019
  temp_file_length+= size;
1020
  rc= 0;
1021
1022
err:
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1023
  return(rc);
1 by brian
clean slate
1024
}
1025
1026
1027
/*
1028
  Deletes a row. First the database will find the row, and then call this
1029
  method. In the case of a table scan, the previous call to this will be
1030
  the ::rnd_next() that found this row.
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
1031
  The exception to this is an ORDER BY. This will cause the table Cursor
1 by brian
clean slate
1032
  to walk the table noting the positions of all rows that match a query.
1033
  The table will then be deleted/positioned based on the ORDER (so RANDOM,
1034
  DESC, ASC).
1035
*/
653 by Brian Aker
More solaris bits
1036
int ha_tina::delete_row(const unsigned char *)
1 by brian
clean slate
1037
{
1273.16.8 by Brian Aker
Remove typedef.
1038
  ha_statistic_increment(&system_status_var::ha_delete_count);
1 by brian
clean slate
1039
1040
  if (chain_append())
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1041
    return(-1);
1 by brian
clean slate
1042
1043
  stats.records--;
1044
  /* Update shared info */
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1045
  assert(share->rows_recorded);
1 by brian
clean slate
1046
  pthread_mutex_lock(&share->mutex);
1047
  share->rows_recorded--;
1048
  pthread_mutex_unlock(&share->mutex);
1049
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1050
  return(0);
1 by brian
clean slate
1051
}
1052
1053
1054
/**
1055
  @brief Initialize the data file.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1056
1 by brian
clean slate
1057
  @details Compare the local version of the data file with the shared one.
1058
  If they differ, there are some changes behind and we have to reopen
1059
  the data file to make the changes visible.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1060
  Call @c file_buff->init_buff() at the end to read the beginning of the
1 by brian
clean slate
1061
  data file into buffer.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1062
1 by brian
clean slate
1063
  @retval  0  OK.
1064
  @retval  1  There was an error.
1065
*/
1066
1067
int ha_tina::init_data_file()
1068
{
1069
  if (local_data_file_version != share->data_file_version)
1070
  {
1071
    local_data_file_version= share->data_file_version;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1072
    if (internal::my_close(data_file, MYF(0)) ||
1073
        (data_file= internal::my_open(share->data_file_name, O_RDONLY, MYF(0))) == -1)
1 by brian
clean slate
1074
      return 1;
1075
  }
1076
  file_buff->init_buff(data_file);
1077
  return 0;
1078
}
1079
1080
1081
/*
1082
  All table scans call this first.
1083
  The order of a table scan is:
1084
1085
  ha_tina::info
1086
  ha_tina::rnd_init
1087
  ha_tina::extra
1088
  ENUM HA_EXTRA_CACHE   Cash record in HA_rrnd()
1089
  ha_tina::rnd_next
1090
  ha_tina::rnd_next
1091
  ha_tina::rnd_next
1092
  ha_tina::rnd_next
1093
  ha_tina::rnd_next
1094
  ha_tina::rnd_next
1095
  ha_tina::rnd_next
1096
  ha_tina::rnd_next
1097
  ha_tina::rnd_next
1098
  ha_tina::extra
1099
  ENUM HA_EXTRA_NO_CACHE   End cacheing of records (def)
1100
  ha_tina::extra
1101
  ENUM HA_EXTRA_RESET   Reset database to after open
1102
1103
  Each call to ::rnd_next() represents a row returned in the can. When no more
1104
  rows can be returned, rnd_next() returns a value of HA_ERR_END_OF_FILE.
1105
  The ::info() call is just for the optimizer.
1106
1107
*/
1108
653 by Brian Aker
More solaris bits
1109
int ha_tina::rnd_init(bool)
1 by brian
clean slate
1110
{
1111
  /* set buffer to the beginning of the file */
1112
  if (share->crashed || init_data_file())
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1113
    return(HA_ERR_CRASHED_ON_USAGE);
1 by brian
clean slate
1114
1115
  current_position= next_position= 0;
1116
  stats.records= 0;
1117
  records_is_known= 0;
1118
  chain_ptr= chain;
1119
1253.1.2 by Monty Taylor
We have init_sql_alloc and init_alloc_root - and I can't tell the difference.
1120
  init_alloc_root(&blobroot, BLOB_MEMROOT_ALLOC_SIZE);
1 by brian
clean slate
1121
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1122
  return(0);
1 by brian
clean slate
1123
}
1124
1125
/*
1126
  ::rnd_next() does all the heavy lifting for a table scan. You will need to
1127
  populate *buf with the correct field data. You can walk the field to
1128
  determine at what position you should store the data (take a look at how
1129
  ::find_current_row() works). The structure is something like:
1130
  0Foo  Dog  Friend
1131
  The first offset is for the first attribute. All space before that is
1132
  reserved for null count.
1133
  Basically this works as a mask for which rows are nulled (compared to just
1134
  empty).
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
1135
  This table Cursor doesn't do nulls and does not know the difference between
1136
  NULL and "". This is ok since this table Cursor is for spreadsheets and
1 by brian
clean slate
1137
  they don't know about them either :)
1138
*/
481 by Brian Aker
Remove all of uchar.
1139
int ha_tina::rnd_next(unsigned char *buf)
1 by brian
clean slate
1140
{
1141
  int rc;
1142
1143
  if (share->crashed)
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1144
      return(HA_ERR_CRASHED_ON_USAGE);
1 by brian
clean slate
1145
1273.16.8 by Brian Aker
Remove typedef.
1146
  ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
1 by brian
clean slate
1147
1148
  current_position= next_position;
1149
1150
  /* don't scan an empty file */
1151
  if (!local_saved_data_file_length)
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1152
    return(HA_ERR_END_OF_FILE);
1 by brian
clean slate
1153
1154
  if ((rc= find_current_row(buf)))
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1155
    return(rc);
1 by brian
clean slate
1156
1157
  stats.records++;
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1158
  return(0);
1 by brian
clean slate
1159
}
1160
1161
/*
1162
  In the case of an order by rows will need to be sorted.
1163
  ::position() is called after each call to ::rnd_next(),
1164
  the data it stores is to a byte array. You can store this
1165
  data via my_store_ptr(). ref_length is a variable defined to the
1166
  class that is the sizeof() of position being stored. In our case
1167
  its just a position. Look at the bdb code if you want to see a case
1168
  where something other then a number is stored.
1169
*/
653 by Brian Aker
More solaris bits
1170
void ha_tina::position(const unsigned char *)
1 by brian
clean slate
1171
{
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1172
  internal::my_store_ptr(ref, ref_length, current_position);
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1173
  return;
1 by brian
clean slate
1174
}
1175
1176
1177
/*
1178
  Used to fetch a row from a posiion stored with ::position().
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1179
  internal::my_get_ptr() retrieves the data for you.
1 by brian
clean slate
1180
*/
1181
481 by Brian Aker
Remove all of uchar.
1182
int ha_tina::rnd_pos(unsigned char * buf, unsigned char *pos)
1 by brian
clean slate
1183
{
1273.16.8 by Brian Aker
Remove typedef.
1184
  ha_statistic_increment(&system_status_var::ha_read_rnd_count);
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1185
  current_position= (off_t)internal::my_get_ptr(pos,ref_length);
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1186
  return(find_current_row(buf));
1 by brian
clean slate
1187
}
1188
1189
/*
1190
  ::info() is used to return information to the optimizer.
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
1191
  Currently this table Cursor doesn't implement most of the fields
1 by brian
clean slate
1192
  really needed. SHOW also makes use of this data
1193
*/
653 by Brian Aker
More solaris bits
1194
int ha_tina::info(uint32_t)
1 by brian
clean slate
1195
{
1196
  /* This is a lie, but you don't want the optimizer to see zero or 1 */
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1197
  if (!records_is_known && stats.records < 2)
1 by brian
clean slate
1198
    stats.records= 2;
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1199
  return(0);
1 by brian
clean slate
1200
}
1201
1202
/*
1203
  Set end_pos to the last valid byte of continuous area, closest
1204
  to the given "hole", stored in the buffer. "Valid" here means,
1205
  not listed in the chain of deleted records ("holes").
1206
*/
1207
bool ha_tina::get_write_pos(off_t *end_pos, tina_set *closest_hole)
1208
{
1209
  if (closest_hole == chain_ptr) /* no more chains */
1210
    *end_pos= file_buff->end();
1211
  else
398.1.5 by Monty Taylor
Removed C++ includes and std namespace from global.h.
1212
    *end_pos= std::min(file_buff->end(),
1213
                       closest_hole->begin);
1 by brian
clean slate
1214
  return (closest_hole != chain_ptr) && (*end_pos == closest_hole->begin);
1215
}
1216
1217
1218
/*
1219
  Called after each table scan. In particular after deletes,
1220
  and updates. In the last case we employ chain of deleted
1221
  slots to clean up all of the dead space we have collected while
1222
  performing deletes/updates.
1223
*/
1224
int ha_tina::rnd_end()
1225
{
1226
  char updated_fname[FN_REFLEN];
1227
  off_t file_buffer_start= 0;
1228
1229
  free_root(&blobroot, MYF(0));
1230
  records_is_known= 1;
1231
1232
  if ((chain_ptr - chain)  > 0)
1233
  {
1234
    tina_set *ptr= chain;
1235
1236
    /*
1237
      Re-read the beginning of a file (as the buffer should point to the
1238
      end of file after the scan).
1239
    */
1240
    file_buff->init_buff(data_file);
1241
1242
    /*
1243
      The sort is needed when there were updates/deletes with random orders.
1244
      It sorts so that we move the firts blocks to the beginning.
1245
    */
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1246
    internal::my_qsort(chain, (size_t)(chain_ptr - chain), sizeof(tina_set),
1247
                       (qsort_cmp)sort_set);
1 by brian
clean slate
1248
1249
    off_t write_begin= 0, write_end;
1250
1251
    /* create the file to write updated table if it wasn't yet created */
1252
    if (open_update_temp_file_if_needed())
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1253
      return(-1);
1 by brian
clean slate
1254
1255
    /* write the file with updated info */
1256
    while ((file_buffer_start != -1))     // while not end of file
1257
    {
1258
      bool in_hole= get_write_pos(&write_end, ptr);
1259
      off_t write_length= write_end - write_begin;
779.3.21 by Monty Taylor
Fixed solaris fixes for linux. Oh, and I also seem to have fixed some more configure stuff.
1260
      if ((uint64_t)write_length > SIZE_MAX)
779.3.18 by Monty Taylor
Cleaned up warnings up through innodb.
1261
      {
1262
        goto error;
1263
      }
1 by brian
clean slate
1264
1265
      /* if there is something to write, write it */
1266
      if (write_length)
1267
      {
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1268
        if (internal::my_write(update_temp_file,
481 by Brian Aker
Remove all of uchar.
1269
                     (unsigned char*) (file_buff->ptr() +
1 by brian
clean slate
1270
                               (write_begin - file_buff->start())),
779.3.18 by Monty Taylor
Cleaned up warnings up through innodb.
1271
                     (size_t)write_length, MYF_RW))
1 by brian
clean slate
1272
          goto error;
1273
        temp_file_length+= write_length;
1274
      }
1275
      if (in_hole)
1276
      {
1277
        /* skip hole */
1278
        while (file_buff->end() <= ptr->end && file_buffer_start != -1)
1279
          file_buffer_start= file_buff->read_next();
1280
        write_begin= ptr->end;
1281
        ptr++;
1282
      }
1283
      else
1284
        write_begin= write_end;
1285
1286
      if (write_end == file_buff->end())
1287
        file_buffer_start= file_buff->read_next(); /* shift the buffer */
1288
1289
    }
1290
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1291
    if (internal::my_sync(update_temp_file, MYF(MY_WME)) ||
1292
        internal::my_close(update_temp_file, MYF(0)))
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1293
      return(-1);
1 by brian
clean slate
1294
163 by Brian Aker
Merge Monty's code.
1295
    share->update_file_opened= false;
1 by brian
clean slate
1296
1297
    if (share->tina_write_opened)
1298
    {
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1299
      if (internal::my_close(share->tina_write_filedes, MYF(0)))
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1300
        return(-1);
1 by brian
clean slate
1301
      /*
1302
        Mark that the writer fd is closed, so that init_tina_writer()
1303
        will reopen it later.
1304
      */
163 by Brian Aker
Merge Monty's code.
1305
      share->tina_write_opened= false;
1 by brian
clean slate
1306
    }
1307
1308
    /*
1309
      Close opened fildes's. Then move updated file in place
1310
      of the old datafile.
1311
    */
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1312
    if (internal::my_close(data_file, MYF(0)) ||
1313
        internal::my_rename(internal::fn_format(updated_fname,
1314
                                                share->table_name.c_str(),
1315
                                                "", CSN_EXT,
1316
                                                MY_REPLACE_EXT | MY_UNPACK_FILENAME),
1317
                            share->data_file_name, MYF(0)))
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1318
      return(-1);
1 by brian
clean slate
1319
1320
    /* Open the file again */
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1321
    if (((data_file= internal::my_open(share->data_file_name, O_RDONLY, MYF(0))) == -1))
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1322
      return(-1);
1 by brian
clean slate
1323
    /*
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1324
      As we reopened the data file, increase share->data_file_version
1325
      in order to force other threads waiting on a table lock and
1 by brian
clean slate
1326
      have already opened the table to reopen the data file.
1327
      That makes the latest changes become visible to them.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1328
      Update local_data_file_version as no need to reopen it in the
1 by brian
clean slate
1329
      current thread.
1330
    */
1331
    share->data_file_version++;
1332
    local_data_file_version= share->data_file_version;
1333
    /*
1334
      The datafile is consistent at this point and the write filedes is
1335
      closed, so nothing worrying will happen to it in case of a crash.
1336
      Here we record this fact to the meta-file.
1337
    */
163 by Brian Aker
Merge Monty's code.
1338
    (void)write_meta_file(share->meta_file, share->rows_recorded, false);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1339
    /*
1340
      Update local_saved_data_file_length with the real length of the
1 by brian
clean slate
1341
      data file.
1342
    */
1343
    local_saved_data_file_length= temp_file_length;
1344
  }
1345
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1346
  return(0);
1 by brian
clean slate
1347
error:
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1348
  internal::my_close(update_temp_file, MYF(0));
163 by Brian Aker
Merge Monty's code.
1349
  share->update_file_opened= false;
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1350
  return(-1);
1 by brian
clean slate
1351
}
1352
1353
1354
/*
1355
  DELETE without WHERE calls this
1356
*/
1357
1358
int ha_tina::delete_all_rows()
1359
{
1360
  int rc;
1361
1362
  if (!records_is_known)
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1363
    return(errno=HA_ERR_WRONG_COMMAND);
1 by brian
clean slate
1364
1365
  if (!share->tina_write_opened)
1366
    if (init_tina_writer())
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1367
      return(-1);
1 by brian
clean slate
1368
1369
  /* Truncate the file to zero size */
30 by Brian Aker
Large file and ftruncate() support
1370
  rc= ftruncate(share->tina_write_filedes, 0);
1 by brian
clean slate
1371
1372
  stats.records=0;
1373
  /* Update shared info */
1374
  pthread_mutex_lock(&share->mutex);
1375
  share->rows_recorded= 0;
1376
  pthread_mutex_unlock(&share->mutex);
1377
  local_saved_data_file_length= 0;
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1378
  return(rc);
1 by brian
clean slate
1379
}
1380
1381
/*
1382
  Create a table. You do not want to leave the table open after a call to
1383
  this (the database will call ::open() if it needs to).
1384
*/
1385
1372.1.4 by Brian Aker
Update to remove cache in enginges for per session (which also means... no
1386
int Tina::doCreateTable(Session *session,
1183.1.18 by Brian Aker
Fixed references to doCreateTable()
1387
                        Table& table_arg,
1358.1.6 by Brian Aker
Remove old calls for path.
1388
                        drizzled::TableIdentifier &identifier,
1372.1.4 by Brian Aker
Update to remove cache in enginges for per session (which also means... no
1389
                        drizzled::message::Table &create_proto)
1 by brian
clean slate
1390
{
1391
  char name_buff[FN_REFLEN];
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
1392
  int create_file;
1 by brian
clean slate
1393
1394
  /*
1395
    check columns
1396
  */
1183.1.18 by Brian Aker
Fixed references to doCreateTable()
1397
  for (Field **field= table_arg.s->field; *field; field++)
1 by brian
clean slate
1398
  {
1399
    if ((*field)->real_maybe_null())
1400
    {
1401
      my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "nullable columns");
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1402
      return(HA_ERR_UNSUPPORTED);
1 by brian
clean slate
1403
    }
1404
  }
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1405
1 by brian
clean slate
1406
1358.1.9 by Brian Aker
Update for std::string
1407
  if ((create_file= internal::my_create(internal::fn_format(name_buff, identifier.getPath().c_str(), "", CSM_EXT,
1408
                                                            MY_REPLACE_EXT|MY_UNPACK_FILENAME), 0,
1409
                                        O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1410
    return(-1);
1 by brian
clean slate
1411
163 by Brian Aker
Merge Monty's code.
1412
  write_meta_file(create_file, 0, false);
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1413
  internal::my_close(create_file, MYF(0));
1 by brian
clean slate
1414
1358.1.9 by Brian Aker
Update for std::string
1415
  if ((create_file= internal::my_create(internal::fn_format(name_buff, identifier.getPath().c_str(), "", CSV_EXT,
1416
                                                            MY_REPLACE_EXT|MY_UNPACK_FILENAME),0,
1417
                                        O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1418
    return(-1);
1 by brian
clean slate
1419
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1420
  internal::my_close(create_file, MYF(0));
1 by brian
clean slate
1421
1372.1.4 by Brian Aker
Update to remove cache in enginges for per session (which also means... no
1422
  session->storeTableMessage(identifier, create_proto);
1183.1.21 by Brian Aker
Fixed temp engines to no longer write out DFE. I have two designs right now
1423
1424
  return 0;
1 by brian
clean slate
1425
}
1426
1427
1228.1.5 by Monty Taylor
Merged in some naming things.
1428
DRIZZLE_DECLARE_PLUGIN
1 by brian
clean slate
1429
{
1241.10.2 by Monty Taylor
Added support for embedding the drizzle version number in the plugin file.
1430
  DRIZZLE_VERSION_ID,
1 by brian
clean slate
1431
  "CSV",
177.4.3 by mark
ripped out more plugin ABI and API version checking, and plugin versions are now strings
1432
  "1.0",
1 by brian
clean slate
1433
  "Brian Aker, MySQL AB",
1434
  "CSV storage engine",
1435
  PLUGIN_LICENSE_GPL,
1436
  tina_init_func, /* Plugin Init */
1437
  NULL,                       /* system variables                */
1438
  NULL                        /* config options                  */
1439
}
1228.1.5 by Monty Taylor
Merged in some naming things.
1440
DRIZZLE_DECLARE_PLUGIN_END;
1 by brian
clean slate
1441