~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();
1 by brian
clean slate
749
      if ((*field)->store(buffer.ptr(), buffer.length(), buffer.charset(),
750
                          CHECK_FIELD_WARN))
751
        goto err;
1089.1.3 by Brian Aker
Fix protobuf to release memory. Add in assert() for wrong column usage. Fix
752
1 by brian
clean slate
753
      if ((*field)->flags & BLOB_FLAG)
754
      {
755
        Field_blob *blob= *(Field_blob**) field;
481 by Brian Aker
Remove all of uchar.
756
        unsigned char *src, *tgt;
482 by Brian Aker
Remove uint.
757
        uint32_t length, packlength;
584.5.1 by Monty Taylor
Removed field includes from field.h.
758
1 by brian
clean slate
759
        packlength= blob->pack_length_no_ptr();
760
        length= blob->get_length(blob->ptr);
212.6.3 by Mats Kindahl
Removing deprecated functions from code and replacing them with C99 equivalents:
761
        memcpy(&src, blob->ptr + packlength, sizeof(char*));
1 by brian
clean slate
762
        if (src)
763
        {
1485 by Brian Aker
Updates to confine memroot
764
          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
765
          memmove(tgt, src, length);
212.6.3 by Mats Kindahl
Removing deprecated functions from code and replacing them with C99 equivalents:
766
          memcpy(blob->ptr + packlength, &tgt, sizeof(char*));
1 by brian
clean slate
767
        }
768
      }
769
    }
770
  }
771
  next_position= end_offset + eoln_len;
772
  error= 0;
773
774
err:
775
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
776
  return(error);
1 by brian
clean slate
777
}
778
779
/*
780
  Open a database file. Keep in mind that tables are caches, so
781
  this will not be called for every request. Any sort of positions
782
  that need to be reset should be kept in the ::extra() call.
783
*/
1633.4.1 by Brian Aker
Merge ha_open to have doOpen() which passes identifier.
784
int ha_tina::doOpen(const TableIdentifier &identifier, int , uint32_t )
1 by brian
clean slate
785
{
1749.3.18 by Brian Aker
Replace some of the CSV non-usage of identifier for path.
786
  if (not (share= get_share(identifier.getPath().c_str())))
820.3.1 by Padraig
Changed ha_tina::open to return the correct error code
787
    return(ENOENT);
1 by brian
clean slate
788
1237.6.2 by Brian Aker
Minor cleanup for dead code.
789
  if (share->crashed)
1 by brian
clean slate
790
  {
1240.2.1 by Monty Taylor
Fixed the CSV tina_open_tables HASH to be a std::map.
791
    free_share();
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
792
    return(HA_ERR_CRASHED_ON_USAGE);
1 by brian
clean slate
793
  }
794
795
  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.
796
  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
797
    return(0);
1 by brian
clean slate
798
799
  /*
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
800
    Init locking. Pass Cursor object to the locking routines,
1 by brian
clean slate
801
    so that they could save/update local_saved_data_file_length value
802
    during locking. This is needed to enable concurrent inserts.
803
  */
804
  ref_length=sizeof(off_t);
805
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
806
  return(0);
1 by brian
clean slate
807
}
808
809
/*
810
  Close a database file. We remove ourselves from the shared strucutre.
811
  If it is empty we destroy it.
812
*/
813
int ha_tina::close(void)
814
{
815
  int rc= 0;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
816
  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.
817
  return(free_share() || rc);
1 by brian
clean slate
818
}
819
820
/*
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
821
  This is an INSERT. At the moment this Cursor just seeks to the end
1 by brian
clean slate
822
  of the file and appends the data. In an error case it really should
823
  just truncate to the original position (this is not done yet).
824
*/
1491.1.2 by Jay Pipes
Cursor::write_row() -> Cursor::doInsertRecord(). Cursor::ha_write_row() -> Cursor::insertRecord()
825
int ha_tina::doInsertRecord(unsigned char * buf)
1 by brian
clean slate
826
{
827
  int size;
828
829
  if (share->crashed)
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
830
      return(HA_ERR_CRASHED_ON_USAGE);
1 by brian
clean slate
831
832
  size= encode_quote(buf);
833
834
  if (!share->tina_write_opened)
835
    if (init_tina_writer())
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
836
      return(-1);
1 by brian
clean slate
837
838
   /* use pwrite, as concurrent reader could have changed the position */
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
839
  if (internal::my_write(share->tina_write_filedes, (unsigned char*)buffer.ptr(), size,
1 by brian
clean slate
840
               MYF(MY_WME | MY_NABP)))
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
841
    return(-1);
1 by brian
clean slate
842
843
  /* update local copy of the max position to see our own changes */
844
  local_saved_data_file_length+= size;
845
846
  /* update shared info */
847
  pthread_mutex_lock(&share->mutex);
848
  share->rows_recorded++;
849
  /* update status for the log tables */
850
  pthread_mutex_unlock(&share->mutex);
851
852
  stats.records++;
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
853
  return(0);
1 by brian
clean slate
854
}
855
856
857
int ha_tina::open_update_temp_file_if_needed()
858
{
859
  char updated_fname[FN_REFLEN];
860
861
  if (!share->update_file_opened)
862
  {
863
    if ((update_temp_file=
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
864
           internal::my_create(internal::fn_format(updated_fname, share->table_name.c_str(),
1 by brian
clean slate
865
                               "", CSN_EXT,
866
                               MY_REPLACE_EXT | MY_UNPACK_FILENAME),
867
                     0, O_RDWR | O_TRUNC, MYF(MY_WME))) < 0)
868
      return 1;
163 by Brian Aker
Merge Monty's code.
869
    share->update_file_opened= true;
1 by brian
clean slate
870
    temp_file_length= 0;
871
  }
872
  return 0;
873
}
874
875
/*
876
  This is called for an update.
877
  Make sure you put in code to increment the auto increment, also
878
  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
879
  fixed since autoincrements have yet to be added to this table Cursor.
1 by brian
clean slate
880
  This will be called in a table scan right before the previous ::rnd_next()
881
  call.
882
*/
1491.1.3 by Jay Pipes
Cursor::update_row() changed to doUpdateRecord() and updateRecord()
883
int ha_tina::doUpdateRecord(const unsigned char *, unsigned char * new_data)
1 by brian
clean slate
884
{
885
  int size;
886
  int rc= -1;
887
888
  size= encode_quote(new_data);
889
890
  /*
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
891
    During update we mark each updating record as deleted
892
    (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
893
    At the end of the sequence in the doEndTableScan() we append all non-marked
1 by brian
clean slate
894
    records from the data file to the temporary data file then rename it.
895
    The temp_file_length is used to calculate new data file length.
896
  */
897
  if (chain_append())
898
    goto err;
899
900
  if (open_update_temp_file_if_needed())
901
    goto err;
902
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
903
  if (internal::my_write(update_temp_file, (unsigned char*)buffer.ptr(), size,
1 by brian
clean slate
904
               MYF(MY_WME | MY_NABP)))
905
    goto err;
906
  temp_file_length+= size;
907
  rc= 0;
908
909
err:
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
910
  return(rc);
1 by brian
clean slate
911
}
912
913
914
/*
915
  Deletes a row. First the database will find the row, and then call this
916
  method. In the case of a table scan, the previous call to this will be
917
  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
918
  The exception to this is an ORDER BY. This will cause the table Cursor
1 by brian
clean slate
919
  to walk the table noting the positions of all rows that match a query.
920
  The table will then be deleted/positioned based on the ORDER (so RANDOM,
921
  DESC, ASC).
922
*/
1491.1.4 by Jay Pipes
delete_row() is now deleteRecord() and doDeleteRecord() in Cursor
923
int ha_tina::doDeleteRecord(const unsigned char *)
1 by brian
clean slate
924
{
925
926
  if (chain_append())
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
927
    return(-1);
1 by brian
clean slate
928
929
  stats.records--;
930
  /* Update shared info */
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
931
  assert(share->rows_recorded);
1 by brian
clean slate
932
  pthread_mutex_lock(&share->mutex);
933
  share->rows_recorded--;
934
  pthread_mutex_unlock(&share->mutex);
935
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
936
  return(0);
1 by brian
clean slate
937
}
938
939
940
/**
941
  @brief Initialize the data file.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
942
1 by brian
clean slate
943
  @details Compare the local version of the data file with the shared one.
944
  If they differ, there are some changes behind and we have to reopen
945
  the data file to make the changes visible.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
946
  Call @c file_buff->init_buff() at the end to read the beginning of the
1 by brian
clean slate
947
  data file into buffer.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
948
1 by brian
clean slate
949
  @retval  0  OK.
950
  @retval  1  There was an error.
951
*/
952
953
int ha_tina::init_data_file()
954
{
955
  if (local_data_file_version != share->data_file_version)
956
  {
957
    local_data_file_version= share->data_file_version;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
958
    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.
959
        (data_file= internal::my_open(share->data_file_name.c_str(), O_RDONLY, MYF(0))) == -1)
1 by brian
clean slate
960
      return 1;
961
  }
962
  file_buff->init_buff(data_file);
963
  return 0;
964
}
965
966
967
/*
968
  All table scans call this first.
969
  The order of a table scan is:
970
971
  ha_tina::info
972
  ha_tina::rnd_init
973
  ha_tina::extra
974
  ENUM HA_EXTRA_CACHE   Cash record in HA_rrnd()
975
  ha_tina::rnd_next
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::extra
985
  ENUM HA_EXTRA_NO_CACHE   End cacheing of records (def)
986
  ha_tina::extra
987
  ENUM HA_EXTRA_RESET   Reset database to after open
988
989
  Each call to ::rnd_next() represents a row returned in the can. When no more
990
  rows can be returned, rnd_next() returns a value of HA_ERR_END_OF_FILE.
991
  The ::info() call is just for the optimizer.
992
993
*/
994
1491.1.10 by Jay Pipes
ha_rnd_init -> startTableScan, rnd_init -> doStartTableScan, ha_rnd_end -> endTableScan, rnd_end -> doEndTableScan
995
int ha_tina::doStartTableScan(bool)
1 by brian
clean slate
996
{
997
  /* set buffer to the beginning of the file */
998
  if (share->crashed || init_data_file())
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
999
    return(HA_ERR_CRASHED_ON_USAGE);
1 by brian
clean slate
1000
1001
  current_position= next_position= 0;
1002
  stats.records= 0;
1003
  records_is_known= 0;
1608.3.1 by Zimin
refactor CSV engine's tina_set
1004
  chain.clear();
1 by brian
clean slate
1005
1487 by Brian Aker
More updates for memory::Root
1006
  blobroot.init_alloc_root(BLOB_MEMROOT_ALLOC_SIZE);
1 by brian
clean slate
1007
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1008
  return(0);
1 by brian
clean slate
1009
}
1010
1011
/*
1012
  ::rnd_next() does all the heavy lifting for a table scan. You will need to
1013
  populate *buf with the correct field data. You can walk the field to
1014
  determine at what position you should store the data (take a look at how
1015
  ::find_current_row() works). The structure is something like:
1016
  0Foo  Dog  Friend
1017
  The first offset is for the first attribute. All space before that is
1018
  reserved for null count.
1019
  Basically this works as a mask for which rows are nulled (compared to just
1020
  empty).
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
1021
  This table Cursor doesn't do nulls and does not know the difference between
1022
  NULL and "". This is ok since this table Cursor is for spreadsheets and
1 by brian
clean slate
1023
  they don't know about them either :)
1024
*/
481 by Brian Aker
Remove all of uchar.
1025
int ha_tina::rnd_next(unsigned char *buf)
1 by brian
clean slate
1026
{
1027
  int rc;
1028
1029
  if (share->crashed)
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1030
      return(HA_ERR_CRASHED_ON_USAGE);
1 by brian
clean slate
1031
1273.16.8 by Brian Aker
Remove typedef.
1032
  ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
1 by brian
clean slate
1033
1034
  current_position= next_position;
1035
1036
  /* don't scan an empty file */
1037
  if (!local_saved_data_file_length)
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1038
    return(HA_ERR_END_OF_FILE);
1 by brian
clean slate
1039
1040
  if ((rc= find_current_row(buf)))
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1041
    return(rc);
1 by brian
clean slate
1042
1043
  stats.records++;
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1044
  return(0);
1 by brian
clean slate
1045
}
1046
1047
/*
1048
  In the case of an order by rows will need to be sorted.
1049
  ::position() is called after each call to ::rnd_next(),
1050
  the data it stores is to a byte array. You can store this
1051
  data via my_store_ptr(). ref_length is a variable defined to the
1052
  class that is the sizeof() of position being stored. In our case
1053
  its just a position. Look at the bdb code if you want to see a case
1054
  where something other then a number is stored.
1055
*/
653 by Brian Aker
More solaris bits
1056
void ha_tina::position(const unsigned char *)
1 by brian
clean slate
1057
{
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1058
  internal::my_store_ptr(ref, ref_length, current_position);
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1059
  return;
1 by brian
clean slate
1060
}
1061
1062
1063
/*
1064
  Used to fetch a row from a posiion stored with ::position().
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1065
  internal::my_get_ptr() retrieves the data for you.
1 by brian
clean slate
1066
*/
1067
481 by Brian Aker
Remove all of uchar.
1068
int ha_tina::rnd_pos(unsigned char * buf, unsigned char *pos)
1 by brian
clean slate
1069
{
1273.16.8 by Brian Aker
Remove typedef.
1070
  ha_statistic_increment(&system_status_var::ha_read_rnd_count);
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1071
  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
1072
  return(find_current_row(buf));
1 by brian
clean slate
1073
}
1074
1075
/*
1076
  ::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
1077
  Currently this table Cursor doesn't implement most of the fields
1 by brian
clean slate
1078
  really needed. SHOW also makes use of this data
1079
*/
653 by Brian Aker
More solaris bits
1080
int ha_tina::info(uint32_t)
1 by brian
clean slate
1081
{
1082
  /* 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:
1083
  if (!records_is_known && stats.records < 2)
1 by brian
clean slate
1084
    stats.records= 2;
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1085
  return(0);
1 by brian
clean slate
1086
}
1087
1088
/*
1089
  Set end_pos to the last valid byte of continuous area, closest
1090
  to the given "hole", stored in the buffer. "Valid" here means,
1091
  not listed in the chain of deleted records ("holes").
1092
*/
1608.3.1 by Zimin
refactor CSV engine's tina_set
1093
bool ha_tina::get_write_pos(off_t *end_pos, vector< pair<off_t, off_t> >::iterator &closest_hole)
1 by brian
clean slate
1094
{
1608.3.1 by Zimin
refactor CSV engine's tina_set
1095
  if (closest_hole == chain.end()) /* no more chains */
1 by brian
clean slate
1096
    *end_pos= file_buff->end();
1097
  else
398.1.5 by Monty Taylor
Removed C++ includes and std namespace from global.h.
1098
    *end_pos= std::min(file_buff->end(),
1608.3.1 by Zimin
refactor CSV engine's tina_set
1099
                       closest_hole->first);
1100
  return (closest_hole != chain.end()) && (*end_pos == closest_hole->first);
1 by brian
clean slate
1101
}
1102
1103
1104
/*
1105
  Called after each table scan. In particular after deletes,
1106
  and updates. In the last case we employ chain of deleted
1107
  slots to clean up all of the dead space we have collected while
1108
  performing deletes/updates.
1109
*/
1491.1.10 by Jay Pipes
ha_rnd_init -> startTableScan, rnd_init -> doStartTableScan, ha_rnd_end -> endTableScan, rnd_end -> doEndTableScan
1110
int ha_tina::doEndTableScan()
1 by brian
clean slate
1111
{
1112
  off_t file_buffer_start= 0;
1113
1487 by Brian Aker
More updates for memory::Root
1114
  blobroot.free_root(MYF(0));
1 by brian
clean slate
1115
  records_is_known= 1;
1116
1608.3.1 by Zimin
refactor CSV engine's tina_set
1117
  if (chain.size() > 0)
1 by brian
clean slate
1118
  {
1608.3.1 by Zimin
refactor CSV engine's tina_set
1119
    vector< pair<off_t, off_t> >::iterator ptr= chain.begin();
1 by brian
clean slate
1120
1121
    /*
1122
      Re-read the beginning of a file (as the buffer should point to the
1123
      end of file after the scan).
1124
    */
1125
    file_buff->init_buff(data_file);
1126
1127
    /*
1128
      The sort is needed when there were updates/deletes with random orders.
1129
      It sorts so that we move the firts blocks to the beginning.
1130
    */
1608.3.1 by Zimin
refactor CSV engine's tina_set
1131
    sort(chain.begin(), chain.end());
1 by brian
clean slate
1132
1133
    off_t write_begin= 0, write_end;
1134
1135
    /* create the file to write updated table if it wasn't yet created */
1136
    if (open_update_temp_file_if_needed())
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1137
      return(-1);
1 by brian
clean slate
1138
1139
    /* write the file with updated info */
1140
    while ((file_buffer_start != -1))     // while not end of file
1141
    {
1142
      bool in_hole= get_write_pos(&write_end, ptr);
1143
      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.
1144
      if ((uint64_t)write_length > SIZE_MAX)
779.3.18 by Monty Taylor
Cleaned up warnings up through innodb.
1145
      {
1146
        goto error;
1147
      }
1 by brian
clean slate
1148
1149
      /* if there is something to write, write it */
1150
      if (write_length)
1151
      {
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1152
        if (internal::my_write(update_temp_file,
481 by Brian Aker
Remove all of uchar.
1153
                     (unsigned char*) (file_buff->ptr() +
1 by brian
clean slate
1154
                               (write_begin - file_buff->start())),
779.3.18 by Monty Taylor
Cleaned up warnings up through innodb.
1155
                     (size_t)write_length, MYF_RW))
1 by brian
clean slate
1156
          goto error;
1157
        temp_file_length+= write_length;
1158
      }
1159
      if (in_hole)
1160
      {
1161
        /* skip hole */
1608.3.1 by Zimin
refactor CSV engine's tina_set
1162
        while (file_buff->end() <= ptr->second && file_buffer_start != -1)
1 by brian
clean slate
1163
          file_buffer_start= file_buff->read_next();
1608.3.1 by Zimin
refactor CSV engine's tina_set
1164
        write_begin= ptr->second;
1165
        ++ptr;
1 by brian
clean slate
1166
      }
1167
      else
1168
        write_begin= write_end;
1169
1170
      if (write_end == file_buff->end())
1171
        file_buffer_start= file_buff->read_next(); /* shift the buffer */
1172
1173
    }
1174
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1175
    if (internal::my_sync(update_temp_file, MYF(MY_WME)) ||
1176
        internal::my_close(update_temp_file, MYF(0)))
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1177
      return(-1);
1 by brian
clean slate
1178
163 by Brian Aker
Merge Monty's code.
1179
    share->update_file_opened= false;
1 by brian
clean slate
1180
1181
    if (share->tina_write_opened)
1182
    {
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1183
      if (internal::my_close(share->tina_write_filedes, MYF(0)))
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1184
        return(-1);
1 by brian
clean slate
1185
      /*
1186
        Mark that the writer fd is closed, so that init_tina_writer()
1187
        will reopen it later.
1188
      */
163 by Brian Aker
Merge Monty's code.
1189
      share->tina_write_opened= false;
1 by brian
clean slate
1190
    }
1191
1192
    /*
1193
      Close opened fildes's. Then move updated file in place
1194
      of the old datafile.
1195
    */
1749.3.18 by Brian Aker
Replace some of the CSV non-usage of identifier for path.
1196
    std::string rename_file= share->table_name;
1197
    rename_file.append(CSN_EXT);
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1198
    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.
1199
        internal::my_rename(rename_file.c_str(),
1200
                            share->data_file_name.c_str(), MYF(0)))
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1201
      return(-1);
1 by brian
clean slate
1202
1203
    /* Open the file again */
1749.3.18 by Brian Aker
Replace some of the CSV non-usage of identifier for path.
1204
    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
1205
      return(-1);
1 by brian
clean slate
1206
    /*
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1207
      As we reopened the data file, increase share->data_file_version
1208
      in order to force other threads waiting on a table lock and
1 by brian
clean slate
1209
      have already opened the table to reopen the data file.
1210
      That makes the latest changes become visible to them.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1211
      Update local_data_file_version as no need to reopen it in the
1 by brian
clean slate
1212
      current thread.
1213
    */
1214
    share->data_file_version++;
1215
    local_data_file_version= share->data_file_version;
1216
    /*
1217
      The datafile is consistent at this point and the write filedes is
1218
      closed, so nothing worrying will happen to it in case of a crash.
1219
      Here we record this fact to the meta-file.
1220
    */
163 by Brian Aker
Merge Monty's code.
1221
    (void)write_meta_file(share->meta_file, share->rows_recorded, false);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1222
    /*
1223
      Update local_saved_data_file_length with the real length of the
1 by brian
clean slate
1224
      data file.
1225
    */
1226
    local_saved_data_file_length= temp_file_length;
1227
  }
1228
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1229
  return(0);
1 by brian
clean slate
1230
error:
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1231
  internal::my_close(update_temp_file, MYF(0));
163 by Brian Aker
Merge Monty's code.
1232
  share->update_file_opened= false;
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1233
  return(-1);
1 by brian
clean slate
1234
}
1235
1236
1237
/*
1238
  DELETE without WHERE calls this
1239
*/
1240
1241
int ha_tina::delete_all_rows()
1242
{
1243
  int rc;
1244
1245
  if (!records_is_known)
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1246
    return(errno=HA_ERR_WRONG_COMMAND);
1 by brian
clean slate
1247
1248
  if (!share->tina_write_opened)
1249
    if (init_tina_writer())
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1250
      return(-1);
1 by brian
clean slate
1251
1252
  /* Truncate the file to zero size */
30 by Brian Aker
Large file and ftruncate() support
1253
  rc= ftruncate(share->tina_write_filedes, 0);
1 by brian
clean slate
1254
1255
  stats.records=0;
1256
  /* Update shared info */
1257
  pthread_mutex_lock(&share->mutex);
1258
  share->rows_recorded= 0;
1259
  pthread_mutex_unlock(&share->mutex);
1260
  local_saved_data_file_length= 0;
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1261
  return(rc);
1 by brian
clean slate
1262
}
1263
1264
/*
1265
  Create a table. You do not want to leave the table open after a call to
1266
  this (the database will call ::open() if it needs to).
1267
*/
1268
1413 by Brian Aker
doCreateTable() was still taking a pointer instead of a session reference.
1269
int Tina::doCreateTable(Session &session,
1183.1.18 by Brian Aker
Fixed references to doCreateTable()
1270
                        Table& table_arg,
1618.1.1 by Brian Aker
Modify TableIdentifier to be const
1271
                        const drizzled::TableIdentifier &identifier,
1372.1.4 by Brian Aker
Update to remove cache in enginges for per session (which also means... no
1272
                        drizzled::message::Table &create_proto)
1 by brian
clean slate
1273
{
1274
  char name_buff[FN_REFLEN];
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
1275
  int create_file;
1 by brian
clean slate
1276
1277
  /*
1278
    check columns
1279
  */
1591 by Brian Aker
Small bits of field abstraction.
1280
  const drizzled::TableShare::Fields fields(table_arg.getShare()->getFields());
1281
  for (drizzled::TableShare::Fields::const_iterator iter= fields.begin();
1282
       iter != fields.end();
1578.2.14 by Brian Aker
Additional pass through to remove raw field access.
1283
       iter++)
1 by brian
clean slate
1284
  {
1591 by Brian Aker
Small bits of field abstraction.
1285
    if (not *iter) // Historical legacy for NULL array end.
1286
      continue;
1287
1578.2.14 by Brian Aker
Additional pass through to remove raw field access.
1288
    if ((*iter)->real_maybe_null())
1 by brian
clean slate
1289
    {
1290
      my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "nullable columns");
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1291
      return(HA_ERR_UNSUPPORTED);
1 by brian
clean slate
1292
    }
1293
  }
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1294
1 by brian
clean slate
1295
1358.1.9 by Brian Aker
Update for std::string
1296
  if ((create_file= internal::my_create(internal::fn_format(name_buff, identifier.getPath().c_str(), "", CSM_EXT,
1297
                                                            MY_REPLACE_EXT|MY_UNPACK_FILENAME), 0,
1298
                                        O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1299
    return(-1);
1 by brian
clean slate
1300
163 by Brian Aker
Merge Monty's code.
1301
  write_meta_file(create_file, 0, false);
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1302
  internal::my_close(create_file, MYF(0));
1 by brian
clean slate
1303
1358.1.9 by Brian Aker
Update for std::string
1304
  if ((create_file= internal::my_create(internal::fn_format(name_buff, identifier.getPath().c_str(), "", CSV_EXT,
1305
                                                            MY_REPLACE_EXT|MY_UNPACK_FILENAME),0,
1306
                                        O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
1307
    return(-1);
1 by brian
clean slate
1308
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1309
  internal::my_close(create_file, MYF(0));
1 by brian
clean slate
1310
1923.1.4 by Brian Aker
Encapsulate up the cache we use in Session for tracking table proto for temp
1311
  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
1312
1313
  return 0;
1 by brian
clean slate
1314
}
1315
1316
1228.1.5 by Monty Taylor
Merged in some naming things.
1317
DRIZZLE_DECLARE_PLUGIN
1 by brian
clean slate
1318
{
1241.10.2 by Monty Taylor
Added support for embedding the drizzle version number in the plugin file.
1319
  DRIZZLE_VERSION_ID,
1 by brian
clean slate
1320
  "CSV",
177.4.3 by mark
ripped out more plugin ABI and API version checking, and plugin versions are now strings
1321
  "1.0",
1 by brian
clean slate
1322
  "Brian Aker, MySQL AB",
1323
  "CSV storage engine",
1324
  PLUGIN_LICENSE_GPL,
1325
  tina_init_func, /* Plugin Init */
1326
  NULL,                       /* system variables                */
1327
  NULL                        /* config options                  */
1328
}
1228.1.5 by Monty Taylor
Merged in some naming things.
1329
DRIZZLE_DECLARE_PLUGIN_END;
1 by brian
clean slate
1330