~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>
549 by Monty Taylor
Took gettext.h out of header files.
46
#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.
47
#include <drizzled/table.h>
48
#include <drizzled/session.h>
1241.9.64 by Monty Taylor
Moved remaining non-public portions of mysys and mystrings to drizzled/internal.
49
#include "drizzled/internal/my_sys.h"
1 by brian
clean slate
50
992.1.31 by Monty Taylor
Moved csv.
51
#include "ha_tina.h"
52
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
53
#include <fcntl.h>
54
1608.3.1 by Zimin
refactor CSV engine's tina_set
55
#include <algorithm>
56
#include <vector>
960.2.41 by Monty Taylor
Made StorageEngine name private. Added constructor param and accessor method.
57
#include <string>
1240.2.1 by Monty Taylor
Fixed the CSV tina_open_tables HASH to be a std::map.
58
#include <map>
960.2.41 by Monty Taylor
Made StorageEngine name private. Added constructor param and accessor method.
59
60
using namespace std;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
61
using namespace drizzled;
960.2.41 by Monty Taylor
Made StorageEngine name private. Added constructor param and accessor method.
62
1 by brian
clean slate
63
/*
481 by Brian Aker
Remove all of uchar.
64
  unsigned char + unsigned char + uint64_t + uint64_t + uint64_t + uint64_t + unsigned char
1 by brian
clean slate
65
*/
481 by Brian Aker
Remove all of uchar.
66
#define META_BUFFER_SIZE sizeof(unsigned char) + sizeof(unsigned char) + sizeof(uint64_t) \
67
  + sizeof(uint64_t) + sizeof(uint64_t) + sizeof(uint64_t) + sizeof(unsigned char)
1 by brian
clean slate
68
#define TINA_CHECK_HEADER 254 // The number we use to determine corruption
69
#define BLOB_MEMROOT_ALLOC_SIZE 8192
70
71
/* The file extension */
72
#define CSV_EXT ".CSV"               // The data file
73
#define CSN_EXT ".CSN"               // Files used during repair and update
74
#define CSM_EXT ".CSM"               // Meta file
75
76
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
77
static int read_meta_file(int meta_file, ha_rows *rows);
78
static int write_meta_file(int meta_file, ha_rows rows, bool dirty);
1 by brian
clean slate
79
80
/* Stuff for shares */
81
pthread_mutex_t tina_mutex;
82
83
/*****************************************************************************
84
 ** TINA tables
85
 *****************************************************************************/
86
87
/*
1039.3.1 by Stewart Smith
move bas_ext to StorageEngine instead of handler
88
  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
89
  extensions exist for this Cursor.
1039.3.1 by Stewart Smith
move bas_ext to StorageEngine instead of handler
90
*/
91
static const char *ha_tina_exts[] = {
92
  CSV_EXT,
93
  CSM_EXT,
94
  NULL
95
};
96
1208 by Brian Aker
Merge Jay
97
class Tina : public drizzled::plugin::StorageEngine
960.2.30 by Monty Taylor
Tina done.
98
{
1240.2.2 by Monty Taylor
Turned TINA_SHARE into TinaShare.
99
  typedef std::map<string, TinaShare*> TinaMap;
1240.2.1 by Monty Taylor
Fixed the CSV tina_open_tables HASH to be a std::map.
100
  TinaMap tina_open_tables;
960.2.41 by Monty Taylor
Made StorageEngine name private. Added constructor param and accessor method.
101
public:
964.1.4 by Monty Taylor
Moved flags into private area.
102
  Tina(const string& name_arg)
1233.1.5 by Brian Aker
More table_flags converted.
103
   : drizzled::plugin::StorageEngine(name_arg,
104
                                     HTON_TEMPORARY_ONLY |
105
                                     HTON_NO_AUTO_INCREMENT |
1461.1.1 by Stewart Smith
remove HTON_FILE_BASED: it's unused now.
106
                                     HTON_SKIP_STORE_LOCK),
1240.2.1 by Monty Taylor
Fixed the CSV tina_open_tables HASH to be a std::map.
107
    tina_open_tables()
108
  {}
1324.2.3 by Monty Taylor
Remove plugin deinit.
109
  virtual ~Tina()
110
  {
111
    pthread_mutex_destroy(&tina_mutex);
112
  }
113
1869.1.4 by Brian Aker
TableShare is no longer in the house (i.e. we no longer directly have a copy
114
  virtual Cursor *create(Table &table)
960.2.30 by Monty Taylor
Tina done.
115
  {
1680.6.1 by Brian Aker
Remove call for using special new for a cursor.
116
    return new ha_tina(*this, table);
960.2.30 by Monty Taylor
Tina done.
117
  }
1039.3.1 by Stewart Smith
move bas_ext to StorageEngine instead of handler
118
119
  const char **bas_ext() const {
120
    return ha_tina_exts;
121
  }
122
1413 by Brian Aker
doCreateTable() was still taking a pointer instead of a session reference.
123
  int doCreateTable(Session &,
124
                    Table &table_arg,
1618.1.1 by Brian Aker
Modify TableIdentifier to be const
125
                    const drizzled::TableIdentifier &identifier,
1222.1.7 by Brian Aker
Remove HA_CREATE_INFO from createTable()
126
                    drizzled::message::Table&);
1039.3.3 by Stewart Smith
Move handler::create to StorageEngine::create_table
127
1183.1.29 by Brian Aker
Clean up interface so that Truncate sets the propper engine when
128
  int doGetTableDefinition(Session& session,
1618.1.1 by Brian Aker
Modify TableIdentifier to be const
129
                           const drizzled::TableIdentifier &identifier,
1354.1.1 by Brian Aker
Modify ptr to reference.
130
                           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
131
1618.1.1 by Brian Aker
Modify TableIdentifier to be const
132
  int doDropTable(Session&, const drizzled::TableIdentifier &identifier);
1240.2.2 by Monty Taylor
Turned TINA_SHARE into TinaShare.
133
  TinaShare *findOpenTable(const string table_name);
134
  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.
135
  void deleteOpenTable(const string &table_name);
136
1233.1.9 by Brian Aker
Move max key stuff up to engine.
137
138
  uint32_t max_keys()          const { return 0; }
139
  uint32_t max_key_parts()     const { return 0; }
140
  uint32_t max_key_length()    const { return 0; }
1618.1.1 by Brian Aker
Modify TableIdentifier to be const
141
  bool doDoesTableExist(Session& session, const drizzled::TableIdentifier &identifier);
142
  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.
143
144
  void doGetTableIdentifiers(drizzled::CachedDirectory &directory,
1642 by Brian Aker
This adds const to SchemaIdentifier.
145
                             const drizzled::SchemaIdentifier &schema_identifier,
1966.2.4 by Brian Aker
Style cleanup.
146
                             drizzled::TableIdentifier::vector &set_of_identifiers);
960.2.30 by Monty Taylor
Tina done.
147
};
148
1429.1.3 by Brian Aker
Merge in work for fetching a list of table identifiers.
149
void Tina::doGetTableIdentifiers(drizzled::CachedDirectory&,
1642 by Brian Aker
This adds const to SchemaIdentifier.
150
                                 const drizzled::SchemaIdentifier&,
1966.2.4 by Brian Aker
Style cleanup.
151
                                 drizzled::TableIdentifier::vector&)
1429.1.3 by Brian Aker
Merge in work for fetching a list of table identifiers.
152
{
153
}
1358.1.1 by Brian Aker
Fixes regression in performance from Exists patch.
154
1391 by Brian Aker
Updating interface.
155
int Tina::doRenameTable(Session &session,
1618.1.1 by Brian Aker
Modify TableIdentifier to be const
156
                        const drizzled::TableIdentifier &from, const drizzled::TableIdentifier &to)
1389 by Brian Aker
Large reord in ALTER TABLE for RENAME.
157
{
158
  int error= 0;
159
  for (const char **ext= bas_ext(); *ext ; ext++)
160
  {
1390 by Brian Aker
Update interface to use Identifiers directly.
161
    if (rename_file_ext(from.getPath().c_str(), to.getPath().c_str(), *ext))
1389 by Brian Aker
Large reord in ALTER TABLE for RENAME.
162
    {
163
      if ((error=errno) != ENOENT)
164
        break;
165
      error= 0;
166
    }
167
  }
1391 by Brian Aker
Updating interface.
168
1923.1.4 by Brian Aker
Encapsulate up the cache we use in Session for tracking table proto for temp
169
  session.getMessageCache().renameTableMessage(from, to);
1391 by Brian Aker
Updating interface.
170
1389 by Brian Aker
Large reord in ALTER TABLE for RENAME.
171
  return error;
172
}
173
1618.1.1 by Brian Aker
Modify TableIdentifier to be const
174
bool Tina::doDoesTableExist(Session &session, const drizzled::TableIdentifier &identifier)
1358.1.1 by Brian Aker
Fixes regression in performance from Exists patch.
175
{
1923.1.4 by Brian Aker
Encapsulate up the cache we use in Session for tracking table proto for temp
176
  return session.getMessageCache().doesTableMessageExist(identifier);
1358.1.1 by Brian Aker
Fixes regression in performance from Exists patch.
177
}
178
179
1372.1.4 by Brian Aker
Update to remove cache in enginges for per session (which also means... no
180
int Tina::doDropTable(Session &session,
1618.1.1 by Brian Aker
Modify TableIdentifier to be const
181
                      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
182
{
183
  int error= 0;
184
  int enoent_or_zero= ENOENT;                   // Error if no file was deleted
185
186
  for (const char **ext= bas_ext(); *ext ; ext++)
187
  {
1749.3.18 by Brian Aker
Replace some of the CSV non-usage of identifier for path.
188
    std::string full_name= identifier.getPath();
189
    full_name.append(*ext);
190
191
    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
192
    {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
193
      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
194
	break;
195
    }
196
    else
1749.3.18 by Brian Aker
Replace some of the CSV non-usage of identifier for path.
197
    {
1183.1.21 by Brian Aker
Fixed temp engines to no longer write out DFE. I have two designs right now
198
      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.
199
    }
1183.1.21 by Brian Aker
Fixed temp engines to no longer write out DFE. I have two designs right now
200
    error= enoent_or_zero;
201
  }
202
1923.1.4 by Brian Aker
Encapsulate up the cache we use in Session for tracking table proto for temp
203
  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
204
205
  return error;
206
}
207
1240.2.2 by Monty Taylor
Turned TINA_SHARE into TinaShare.
208
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.
209
{
210
  TinaMap::iterator find_iter=
211
    tina_open_tables.find(table_name);
212
213
  if (find_iter != tina_open_tables.end())
214
    return (*find_iter).second;
215
  else
216
    return NULL;
217
}
218
1240.2.2 by Monty Taylor
Turned TINA_SHARE into TinaShare.
219
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.
220
{
221
  tina_open_tables[table_name]= share;
222
}
223
224
void Tina::deleteOpenTable(const string &table_name)
225
{
226
  tina_open_tables.erase(table_name);
227
}
228
229
1372.1.4 by Brian Aker
Update to remove cache in enginges for per session (which also means... no
230
int Tina::doGetTableDefinition(Session &session,
1618.1.1 by Brian Aker
Modify TableIdentifier to be const
231
                               const drizzled::TableIdentifier &identifier,
1354.1.1 by Brian Aker
Modify ptr to reference.
232
                               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
233
{
1923.1.4 by Brian Aker
Encapsulate up the cache we use in Session for tracking table proto for temp
234
  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
235
    return EEXIST;
236
237
  return ENOENT;
1183.1.21 by Brian Aker
Fixed temp engines to no longer write out DFE. I have two designs right now
238
}
239
240
971.1.51 by Monty Taylor
New-style plugin registration now works.
241
static Tina *tina_engine= NULL;
242
1530.2.6 by Monty Taylor
Moved plugin::Context to module::Context.
243
static int tina_init_func(drizzled::module::Context &context)
1 by brian
clean slate
244
{
960.2.30 by Monty Taylor
Tina done.
245
1192.5.8 by Monty Taylor
Made csv dynamic
246
  tina_engine= new Tina("CSV");
1324.2.2 by Monty Taylor
Use the plugin::Context everywhere.
247
  context.add(tina_engine);
960.2.30 by Monty Taylor
Tina done.
248
398.1.10 by Monty Taylor
Actually removed VOID() this time.
249
  pthread_mutex_init(&tina_mutex,MY_MUTEX_INIT_FAST);
1 by brian
clean slate
250
  return 0;
251
}
252
253
254
1749.3.18 by Brian Aker
Replace some of the CSV non-usage of identifier for path.
255
TinaShare::TinaShare(const std::string &table_name_arg) : 
256
  table_name(table_name_arg),
257
  data_file_name(table_name_arg),
258
  use_count(0),
259
  saved_data_file_length(0),
260
  update_file_opened(false),
261
  tina_write_opened(false),
262
  crashed(false),
263
  rows_recorded(0),
264
  data_file_version(0)
1240.2.2 by Monty Taylor
Turned TINA_SHARE into TinaShare.
265
{
1749.3.18 by Brian Aker
Replace some of the CSV non-usage of identifier for path.
266
  data_file_name.append(CSV_EXT);
1240.2.2 by Monty Taylor
Turned TINA_SHARE into TinaShare.
267
}
268
269
TinaShare::~TinaShare()
270
{
271
  pthread_mutex_destroy(&mutex);
272
}
273
1 by brian
clean slate
274
/*
275
  Simple lock controls.
276
*/
1749.3.18 by Brian Aker
Replace some of the CSV non-usage of identifier for path.
277
TinaShare *ha_tina::get_share(const std::string &table_name)
1 by brian
clean slate
278
{
1240.2.1 by Monty Taylor
Fixed the CSV tina_open_tables HASH to be a std::map.
279
  pthread_mutex_lock(&tina_mutex);
280
1869.1.3 by Brian Aker
Engine now as a referene.
281
  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.
282
  share= a_tina->findOpenTable(table_name);
283
1749.3.18 by Brian Aker
Replace some of the CSV non-usage of identifier for path.
284
  std::string meta_file_name;
15 by brian
Fix for stat, NETWARE removal
285
  struct stat file_stat;
1 by brian
clean slate
286
287
  /*
288
    If share is not present in the hash, create a new share and
289
    initialize its members.
290
  */
1240.2.1 by Monty Taylor
Fixed the CSV tina_open_tables HASH to be a std::map.
291
  if (! share)
1 by brian
clean slate
292
  {
1240.2.2 by Monty Taylor
Turned TINA_SHARE into TinaShare.
293
    share= new TinaShare(table_name);
294
295
    if (share == NULL)
1 by brian
clean slate
296
    {
297
      pthread_mutex_unlock(&tina_mutex);
298
      return NULL;
299
    }
300
1749.3.18 by Brian Aker
Replace some of the CSV non-usage of identifier for path.
301
    meta_file_name.assign(table_name);
302
    meta_file_name.append(CSM_EXT);
1 by brian
clean slate
303
1749.3.18 by Brian Aker
Replace some of the CSV non-usage of identifier for path.
304
    if (stat(share->data_file_name.c_str(), &file_stat))
1240.2.2 by Monty Taylor
Turned TINA_SHARE into TinaShare.
305
    {
306
      pthread_mutex_unlock(&tina_mutex);
307
      delete share;
308
      return NULL;
309
    }
310
  
1 by brian
clean slate
311
    share->saved_data_file_length= file_stat.st_size;
312
1240.2.1 by Monty Taylor
Fixed the CSV tina_open_tables HASH to be a std::map.
313
    a_tina->addOpenTable(share->table_name, share);
314
1 by brian
clean slate
315
    pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST);
316
317
    /*
318
      Open or create the meta file. In the latter case, we'll get
319
      an error during read_meta_file and mark the table as crashed.
320
      Usually this will result in auto-repair, and we will get a good
321
      meta-file in the end.
322
    */
1749.3.18 by Brian Aker
Replace some of the CSV non-usage of identifier for path.
323
    if ((share->meta_file= internal::my_open(meta_file_name.c_str(),
1309.1.3 by Brian Aker
Cache for Schema.
324
                                             O_RDWR|O_CREAT, MYF(0))) == -1)
163 by Brian Aker
Merge Monty's code.
325
      share->crashed= true;
1 by brian
clean slate
326
327
    /*
328
      If the meta file will not open we assume it is crashed and
329
      mark it as such.
330
    */
331
    if (read_meta_file(share->meta_file, &share->rows_recorded))
163 by Brian Aker
Merge Monty's code.
332
      share->crashed= true;
1 by brian
clean slate
333
  }
334
  share->use_count++;
335
  pthread_mutex_unlock(&tina_mutex);
336
337
  return share;
338
}
339
340
341
/*
342
  Read CSV meta-file
343
344
  SYNOPSIS
345
    read_meta_file()
346
    meta_file   The meta-file filedes
347
    ha_rows     Pointer to the var we use to store rows count.
348
                These are read from the meta-file.
349
350
  DESCRIPTION
351
352
    Read the meta-file info. For now we are only interested in
353
    rows counf, crashed bit and magic number.
354
355
  RETURN
356
    0 - OK
357
    non-zero - error occurred
358
*/
359
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
360
static int read_meta_file(int meta_file, ha_rows *rows)
1 by brian
clean slate
361
{
481 by Brian Aker
Remove all of uchar.
362
  unsigned char meta_buffer[META_BUFFER_SIZE];
363
  unsigned char *ptr= meta_buffer;
1 by brian
clean slate
364
656.1.39 by Monty Taylor
Removed my_seek, my_tell, my_fwrite, my_fseek.
365
  lseek(meta_file, 0, SEEK_SET);
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
366
  if (internal::my_read(meta_file, (unsigned char*)meta_buffer, META_BUFFER_SIZE, 0)
1 by brian
clean slate
367
      != META_BUFFER_SIZE)
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
368
    return(HA_ERR_CRASHED_ON_USAGE);
1 by brian
clean slate
369
370
  /*
371
    Parse out the meta data, we ignore version at the moment
372
  */
373
481 by Brian Aker
Remove all of uchar.
374
  ptr+= sizeof(unsigned char)*2; // Move past header
1 by brian
clean slate
375
  *rows= (ha_rows)uint8korr(ptr);
376
  ptr+= sizeof(uint64_t); // Move past rows
377
  /*
378
    Move past check_point, auto_increment and forced_flushes fields.
379
    They are present in the format, but we do not use them yet.
380
  */
381
  ptr+= 3*sizeof(uint64_t);
382
383
  /* check crashed bit and magic number */
481 by Brian Aker
Remove all of uchar.
384
  if ((meta_buffer[0] != (unsigned char)TINA_CHECK_HEADER) ||
163 by Brian Aker
Merge Monty's code.
385
      ((bool)(*ptr)== true))
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
386
    return(HA_ERR_CRASHED_ON_USAGE);
1 by brian
clean slate
387
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
388
  internal::my_sync(meta_file, MYF(MY_WME));
1 by brian
clean slate
389
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
390
  return(0);
1 by brian
clean slate
391
}
392
393
394
/*
395
  Write CSV meta-file
396
397
  SYNOPSIS
398
    write_meta_file()
399
    meta_file   The meta-file filedes
400
    ha_rows     The number of rows we have in the datafile.
401
    dirty       A flag, which marks whether we have a corrupt table
402
403
  DESCRIPTION
404
405
    Write meta-info the the file. Only rows count, crashed bit and
406
    magic number matter now.
407
408
  RETURN
409
    0 - OK
410
    non-zero - error occurred
411
*/
412
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
413
static int write_meta_file(int meta_file, ha_rows rows, bool dirty)
1 by brian
clean slate
414
{
481 by Brian Aker
Remove all of uchar.
415
  unsigned char meta_buffer[META_BUFFER_SIZE];
416
  unsigned char *ptr= meta_buffer;
1 by brian
clean slate
417
481 by Brian Aker
Remove all of uchar.
418
  *ptr= (unsigned char)TINA_CHECK_HEADER;
419
  ptr+= sizeof(unsigned char);
420
  *ptr= (unsigned char)TINA_VERSION;
421
  ptr+= sizeof(unsigned char);
1 by brian
clean slate
422
  int8store(ptr, (uint64_t)rows);
423
  ptr+= sizeof(uint64_t);
424
  memset(ptr, 0, 3*sizeof(uint64_t));
425
  /*
426
     Skip over checkpoint, autoincrement and forced_flushes fields.
427
     We'll need them later.
428
  */
429
  ptr+= 3*sizeof(uint64_t);
481 by Brian Aker
Remove all of uchar.
430
  *ptr= (unsigned char)dirty;
1 by brian
clean slate
431
656.1.39 by Monty Taylor
Removed my_seek, my_tell, my_fwrite, my_fseek.
432
  lseek(meta_file, 0, SEEK_SET);
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
433
  if (internal::my_write(meta_file, (unsigned char *)meta_buffer, META_BUFFER_SIZE, 0)
1 by brian
clean slate
434
      != META_BUFFER_SIZE)
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
435
    return(-1);
1 by brian
clean slate
436
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
437
  internal::my_sync(meta_file, MYF(MY_WME));
1 by brian
clean slate
438
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
439
  return(0);
1 by brian
clean slate
440
}
441
442
int ha_tina::init_tina_writer()
443
{
444
  /*
445
    Mark the file as crashed. We will set the flag back when we close
446
    the file. In the case of the crash it will remain marked crashed,
447
    which enforce recovery.
448
  */
163 by Brian Aker
Merge Monty's code.
449
  (void)write_meta_file(share->meta_file, share->rows_recorded, true);
1 by brian
clean slate
450
451
  if ((share->tina_write_filedes=
1749.3.18 by Brian Aker
Replace some of the CSV non-usage of identifier for path.
452
        internal::my_open(share->data_file_name.c_str(), O_RDWR|O_APPEND, MYF(0))) == -1)
1 by brian
clean slate
453
  {
163 by Brian Aker
Merge Monty's code.
454
    share->crashed= true;
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
455
    return(1);
1 by brian
clean slate
456
  }
163 by Brian Aker
Merge Monty's code.
457
  share->tina_write_opened= true;
1 by brian
clean slate
458
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
459
  return(0);
1 by brian
clean slate
460
}
461
462
463
/*
464
  Free lock controls.
465
*/
1240.2.1 by Monty Taylor
Fixed the CSV tina_open_tables HASH to be a std::map.
466
int ha_tina::free_share()
1 by brian
clean slate
467
{
468
  pthread_mutex_lock(&tina_mutex);
469
  int result_code= 0;
470
  if (!--share->use_count){
471
    /* Write the meta file. Mark it as crashed if needed. */
472
    (void)write_meta_file(share->meta_file, share->rows_recorded,
163 by Brian Aker
Merge Monty's code.
473
                          share->crashed ? true :false);
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
474
    if (internal::my_close(share->meta_file, MYF(0)))
1 by brian
clean slate
475
      result_code= 1;
476
    if (share->tina_write_opened)
477
    {
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
478
      if (internal::my_close(share->tina_write_filedes, MYF(0)))
1 by brian
clean slate
479
        result_code= 1;
163 by Brian Aker
Merge Monty's code.
480
      share->tina_write_opened= false;
1 by brian
clean slate
481
    }
482
1869.1.3 by Brian Aker
Engine now as a referene.
483
    Tina *a_tina= static_cast<Tina *>(getEngine());
1240.2.2 by Monty Taylor
Turned TINA_SHARE into TinaShare.
484
    a_tina->deleteOpenTable(share->table_name);
485
    delete share;
1 by brian
clean slate
486
  }
487
  pthread_mutex_unlock(&tina_mutex);
488
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
489
  return(result_code);
1 by brian
clean slate
490
}
491
492
493
/*
494
  This function finds the end of a line and returns the length
495
  of the line ending.
496
497
  We support three kinds of line endings:
498
  '\r'     --  Old Mac OS line ending
499
  '\n'     --  Traditional Unix and Mac OS X line ending
500
  '\r''\n' --  DOS\Windows line ending
501
*/
502
1085.1.2 by Monty Taylor
Fixed -Wmissing-declarations
503
static off_t find_eoln_buff(Transparent_file *data_buff, off_t begin,
504
                            off_t end, int *eoln_len)
1 by brian
clean slate
505
{
506
  *eoln_len= 0;
507
508
  for (off_t x= begin; x < end; x++)
509
  {
510
    /* Unix (includes Mac OS X) */
511
    if (data_buff->get_value(x) == '\n')
512
      *eoln_len= 1;
513
    else
514
      if (data_buff->get_value(x) == '\r') // Mac or Dos
515
      {
516
        /* old Mac line ending */
517
        if (x + 1 == end || (data_buff->get_value(x + 1) != '\n'))
518
          *eoln_len= 1;
519
        else // DOS style ending
520
          *eoln_len= 2;
521
      }
522
523
    if (*eoln_len)  // end of line was found
524
      return x;
525
  }
526
527
  return 0;
528
}
529
530
531
1869.1.4 by Brian Aker
TableShare is no longer in the house (i.e. we no longer directly have a copy
532
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
533
  :Cursor(engine_arg, table_arg),
1 by brian
clean slate
534
  /*
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
535
    These definitions are found in Cursor.h
1 by brian
clean slate
536
    They are not probably completely right.
537
  */
538
  current_position(0), next_position(0), local_saved_data_file_length(0),
1608.3.1 by Zimin
refactor CSV engine's tina_set
539
  file_buff(0), local_data_file_version(0), records_is_known(0)
1 by brian
clean slate
540
{
541
  /* Set our original buffers from pre-allocated memory */
542
  buffer.set((char*)byte_buffer, IO_SIZE, &my_charset_bin);
543
  file_buff= new Transparent_file();
544
}
545
546
547
/*
548
  Encode a buffer into the quoted format.
549
*/
550
653 by Brian Aker
More solaris bits
551
int ha_tina::encode_quote(unsigned char *)
1 by brian
clean slate
552
{
553
  char attribute_buffer[1024];
554
  String attribute(attribute_buffer, sizeof(attribute_buffer),
555
                   &my_charset_bin);
556
557
  buffer.length(0);
558
1869.1.5 by Brian Aker
getTable()
559
  for (Field **field= getTable()->getFields() ; *field ; field++)
1 by brian
clean slate
560
  {
561
    const char *ptr;
562
    const char *end_ptr;
563
    const bool was_null= (*field)->is_null();
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
564
1 by brian
clean slate
565
    /*
566
      assistance for backwards compatibility in production builds.
567
      note: this will not work for ENUM columns.
568
    */
569
    if (was_null)
570
    {
571
      (*field)->set_default();
572
      (*field)->set_notnull();
573
    }
574
1089.1.3 by Brian Aker
Fix protobuf to release memory. Add in assert() for wrong column usage. Fix
575
    /* 
576
      Since we are needing to "translate" the type into a string we 
577
      will need to do a val_str(). This would cause an assert() to
578
      normally occur since we are onlying "writing" values.
579
    */
580
    (*field)->setReadSet();
1 by brian
clean slate
581
    (*field)->val_str(&attribute,&attribute);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
582
1 by brian
clean slate
583
    if (was_null)
584
      (*field)->set_null();
585
586
    if ((*field)->str_needs_quotes())
587
    {
588
      ptr= attribute.ptr();
589
      end_ptr= attribute.length() + ptr;
590
591
      buffer.append('"');
592
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
593
      while (ptr < end_ptr)
1 by brian
clean slate
594
      {
595
        if (*ptr == '"')
596
        {
597
          buffer.append('\\');
598
          buffer.append('"');
1831.1.1 by Andrew Hutchings
Fix new warnings in GCC 4.5
599
          (void) *ptr++;
1 by brian
clean slate
600
        }
601
        else if (*ptr == '\r')
602
        {
603
          buffer.append('\\');
604
          buffer.append('r');
1831.1.1 by Andrew Hutchings
Fix new warnings in GCC 4.5
605
          (void) *ptr++;
1 by brian
clean slate
606
        }
607
        else if (*ptr == '\\')
608
        {
609
          buffer.append('\\');
610
          buffer.append('\\');
1831.1.1 by Andrew Hutchings
Fix new warnings in GCC 4.5
611
          (void) *ptr++;
1 by brian
clean slate
612
        }
613
        else if (*ptr == '\n')
614
        {
615
          buffer.append('\\');
616
          buffer.append('n');
1831.1.1 by Andrew Hutchings
Fix new warnings in GCC 4.5
617
          (void) *ptr++;
1 by brian
clean slate
618
        }
619
        else
620
          buffer.append(*ptr++);
621
      }
622
      buffer.append('"');
623
    }
624
    else
625
    {
626
      buffer.append(attribute);
627
    }
628
629
    buffer.append(',');
630
  }
631
  // Remove the comma, add a line feed
632
  buffer.length(buffer.length() - 1);
633
  buffer.append('\n');
634
635
  //buffer.replace(buffer.length(), 0, "\n", 1);
636
637
  return (buffer.length());
638
}
639
640
/*
641
  chain_append() adds delete positions to the chain that we use to keep
642
  track of space. Then the chain will be used to cleanup "holes", occurred
643
  due to deletes and updates.
644
*/
645
int ha_tina::chain_append()
646
{
1608.3.1 by Zimin
refactor CSV engine's tina_set
647
  if (chain.size() > 0 && chain.back().second == current_position)
648
    chain.back().second= next_position;
1 by brian
clean slate
649
  else
1608.3.1 by Zimin
refactor CSV engine's tina_set
650
    chain.push_back(make_pair(current_position, next_position));
1 by brian
clean slate
651
  return 0;
652
}
653
654
655
/*
656
  Scans for a row.
657
*/
481 by Brian Aker
Remove all of uchar.
658
int ha_tina::find_current_row(unsigned char *buf)
1 by brian
clean slate
659
{
660
  off_t end_offset, curr_offset= current_position;
661
  int eoln_len;
662
  int error;
663
1487 by Brian Aker
More updates for memory::Root
664
  blobroot.free_root(MYF(drizzled::memory::MARK_BLOCKS_FREE));
1 by brian
clean slate
665
666
  /*
667
    We do not read further then local_saved_data_file_length in order
668
    not to conflict with undergoing concurrent insert.
669
  */
670
  if ((end_offset=
671
        find_eoln_buff(file_buff, current_position,
672
                       local_saved_data_file_length, &eoln_len)) == 0)
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
673
    return(HA_ERR_END_OF_FILE);
1 by brian
clean slate
674
675
  error= HA_ERR_CRASHED_ON_USAGE;
676
1869.1.5 by Brian Aker
getTable()
677
  memset(buf, 0, getTable()->getShare()->null_bytes);
1 by brian
clean slate
678
1869.1.5 by Brian Aker
getTable()
679
  for (Field **field= getTable()->getFields() ; *field ; field++)
1 by brian
clean slate
680
  {
681
    char curr_char;
584.5.1 by Monty Taylor
Removed field includes from field.h.
682
1 by brian
clean slate
683
    buffer.length(0);
684
    if (curr_offset >= end_offset)
685
      goto err;
686
    curr_char= file_buff->get_value(curr_offset);
687
    if (curr_char == '"')
688
    {
689
      curr_offset++; // Incrementpast the first quote
690
691
      for(; curr_offset < end_offset; curr_offset++)
692
      {
693
        curr_char= file_buff->get_value(curr_offset);
694
        // Need to convert line feeds!
695
        if (curr_char == '"' &&
696
            (curr_offset == end_offset - 1 ||
697
             file_buff->get_value(curr_offset + 1) == ','))
698
        {
699
          curr_offset+= 2; // Move past the , and the "
700
          break;
701
        }
702
        if (curr_char == '\\' && curr_offset != (end_offset - 1))
703
        {
704
          curr_offset++;
705
          curr_char= file_buff->get_value(curr_offset);
706
          if (curr_char == 'r')
707
            buffer.append('\r');
708
          else if (curr_char == 'n' )
709
            buffer.append('\n');
710
          else if (curr_char == '\\' || curr_char == '"')
711
            buffer.append(curr_char);
712
          else  /* This could only happed with an externally created file */
713
          {
714
            buffer.append('\\');
715
            buffer.append(curr_char);
716
          }
717
        }
718
        else // ordinary symbol
719
        {
720
          /*
721
            We are at final symbol and no last quote was found =>
722
            we are working with a damaged file.
723
          */
724
          if (curr_offset == end_offset - 1)
725
            goto err;
726
          buffer.append(curr_char);
727
        }
728
      }
729
    }
584.5.1 by Monty Taylor
Removed field includes from field.h.
730
    else
1 by brian
clean slate
731
    {
732
      for(; curr_offset < end_offset; curr_offset++)
733
      {
734
        curr_char= file_buff->get_value(curr_offset);
735
        if (curr_char == ',')
736
        {
737
          curr_offset++;       // Skip the ,
738
          break;
739
        }
740
        buffer.append(curr_char);
741
      }
742
    }
743
1089.1.3 by Brian Aker
Fix protobuf to release memory. Add in assert() for wrong column usage. Fix
744
    if ((*field)->isReadSet() || (*field)->isWriteSet())
1 by brian
clean slate
745
    {
1089.1.3 by Brian Aker
Fix protobuf to release memory. Add in assert() for wrong column usage. Fix
746
      /* This masks a bug in the logic for a SELECT * */
747
      (*field)->setWriteSet();
1996.2.1 by Brian Aker
uuid type code.
748
      if ((*field)->store_and_check(CHECK_FIELD_WARN, buffer.c_ptr(), buffer.length(), buffer.charset()))
749
      {
1 by brian
clean slate
750
        goto err;
1996.2.1 by Brian Aker
uuid type code.
751
      }
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