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