~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/blitzdb/blitzdata.cc

Merge Stewart's dead code removal

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 
 *
4
 
 *  Copyright (C) 2009 - 2010 Toru Maesaka
5
 
 *
6
 
 *  This program is free software; you can redistribute it and/or modify
7
 
 *  it under the terms of the GNU General Public License as published by
8
 
 *  the Free Software Foundation; version 2 of the License.
9
 
 *
10
 
 *  This program is distributed in the hope that it will be useful,
11
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 *  GNU General Public License for more details.
14
 
 *
15
 
 *  You should have received a copy of the GNU General Public License
16
 
 *  along with this program; if not, write to the Free Software
17
 
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 
 */
19
 
 
20
 
#include "config.h"
21
 
#include "ha_blitz.h"
22
 
 
23
 
using namespace std;
24
 
using namespace drizzled;
25
 
 
26
 
int BlitzData::startup(const char *path) {
27
 
  int rv = 0;
28
 
 
29
 
  if ((rv = open_data_table(path, HDBOWRITER)) != 0)
30
 
    return rv;
31
 
 
32
 
  current_hidden_row_id = read_meta_row_id();
33
 
  return rv;
34
 
}
35
 
 
36
 
int BlitzData::shutdown() {
37
 
  int rv = 0;
38
 
 
39
 
  /* Copy the latest autogenerated ID back to TC's metadata buffer.
40
 
     This data will be sync'd by TC. */
41
 
  write_meta_row_id(current_hidden_row_id);
42
 
 
43
 
  if ((rv = close_data_table()) != 0)
44
 
    return rv;
45
 
 
46
 
  return rv;
47
 
}
48
 
 
49
 
/* Similar to UNIX touch(1) but generates a tuned TCHDB file. */
50
 
int BlitzData::create_data_table(drizzled::message::Table &proto,
51
 
                                 drizzled::Table &table_info,
52
 
                                 const drizzled::identifier::Table &identifier) {
53
 
 
54
 
  std::string path = identifier.getPath() + BLITZ_DATA_EXT;
55
 
 
56
 
  uint64_t autoinc = (proto.options().has_auto_increment_value())
57
 
                     ? proto.options().auto_increment_value() - 1 : 0;
58
 
 
59
 
  uint64_t hash_buckets = (blitz_estimated_rows == 0) ? BLITZ_TC_BUCKETS
60
 
                                                      : blitz_estimated_rows;
61
 
  int n_options = proto.engine().options_size();
62
 
 
63
 
  for (int i = 0; i < n_options; i++) {
64
 
    if (proto.engine().options(i).name() == "estimated_rows" ||
65
 
        proto.engine().options(i).name() == "ESTIMATED_ROWS") {
66
 
      std::istringstream stream(proto.engine().options(i).state());
67
 
      stream >> hash_buckets;
68
 
 
69
 
      if (hash_buckets <= 0)
70
 
        hash_buckets = BLITZ_TC_BUCKETS;
71
 
    }
72
 
  }
73
 
 
74
 
  if (data_table != NULL)
75
 
    return HA_ERR_GENERIC;
76
 
 
77
 
  if ((data_table = tchdbnew()) == NULL)
78
 
    return HA_ERR_OUT_OF_MEM;
79
 
 
80
 
  if (!tchdbtune(data_table, hash_buckets, -1, -1, 0)) {
81
 
    tchdbdel(data_table);
82
 
    return HA_ERR_CRASHED_ON_USAGE;
83
 
  }
84
 
 
85
 
  if (!tchdbopen(data_table, path.c_str(), (HDBOWRITER | HDBOCREAT))) {
86
 
    tchdbdel(data_table);
87
 
    return HA_ERR_CRASHED_ON_USAGE;
88
 
  }
89
 
 
90
 
  /* Write the Meta Data for this Table. */
91
 
  tc_meta_buffer = tchdbopaque(data_table);
92
 
  write_meta_autoinc(autoinc);
93
 
  write_meta_keycount(table_info.getShare()->keys);
94
 
 
95
 
  /* We're Done. */
96
 
  if (close_data_table() != 0)
97
 
    return HA_ERR_CRASHED_ON_USAGE;
98
 
 
99
 
  return 0;
100
 
}
101
 
 
102
 
int BlitzData::open_data_table(const char *path, const int mode) {
103
 
  char buf[FN_REFLEN];
104
 
 
105
 
  if ((data_table = tchdbnew()) == NULL)
106
 
    return HA_ERR_OUT_OF_MEM;
107
 
 
108
 
  if (!tchdbsetmutex(data_table)) {
109
 
    tchdbdel(data_table);
110
 
    return HA_ERR_CRASHED_ON_USAGE;
111
 
  }
112
 
 
113
 
  if (!tchdbsetxmsiz(data_table, BLITZ_TC_EXTRA_MMAP_SIZE)) {
114
 
    tchdbdel(data_table);
115
 
    return HA_ERR_CRASHED_ON_USAGE;
116
 
  }
117
 
 
118
 
  snprintf(buf, FN_REFLEN, "%s%s", path, BLITZ_DATA_EXT);
119
 
 
120
 
  if (!tchdbopen(data_table, buf, mode)) {
121
 
    tchdbdel(data_table);
122
 
    return HA_ERR_CRASHED_ON_USAGE;
123
 
  }
124
 
 
125
 
  tc_meta_buffer = tchdbopaque(data_table);
126
 
  return 0;
127
 
}
128
 
 
129
 
bool BlitzData::rename_table(const char *from, const char *to) {
130
 
  char from_buf[FN_REFLEN];
131
 
  char to_buf[FN_REFLEN];
132
 
 
133
 
  snprintf(from_buf, FN_REFLEN, "%s%s", from, BLITZ_DATA_EXT);
134
 
  snprintf(to_buf, FN_REFLEN, "%s%s", to, BLITZ_DATA_EXT);
135
 
 
136
 
  if (rename(from_buf, to_buf) != 0)
137
 
    return false;
138
 
 
139
 
  snprintf(from_buf, FN_REFLEN, "%s%s", from, BLITZ_SYSTEM_EXT);
140
 
  snprintf(to_buf, FN_REFLEN, "%s%s", to, BLITZ_SYSTEM_EXT);
141
 
 
142
 
  if (rename(from_buf, to_buf) != 0)
143
 
    return false;
144
 
 
145
 
  return true;
146
 
}
147
 
 
148
 
int BlitzData::close_data_table(void) {
149
 
  assert(data_table);
150
 
 
151
 
  if (!tchdbclose(data_table)) {
152
 
    tchdbdel(data_table);
153
 
    return HA_ERR_CRASHED_ON_USAGE;
154
 
  }
155
 
 
156
 
  tchdbdel(data_table);
157
 
  data_table = NULL;
158
 
  tc_meta_buffer = NULL;
159
 
  return 0;
160
 
}
161
 
 
162
 
uint64_t BlitzData::nrecords(void) {
163
 
  return tchdbrnum(data_table);
164
 
}
165
 
 
166
 
uint64_t BlitzData::table_size(void) {
167
 
  return tchdbfsiz(data_table);
168
 
}
169
 
 
170
 
uint64_t BlitzData::read_meta_row_id(void) {
171
 
  assert(tc_meta_buffer);
172
 
  return (uint64_t)uint8korr(tc_meta_buffer);
173
 
}
174
 
 
175
 
uint64_t BlitzData::read_meta_autoinc(void) {
176
 
  assert(tc_meta_buffer);
177
 
  char *pos = tc_meta_buffer + sizeof (current_hidden_row_id);
178
 
  return (uint64_t)uint8korr(pos);
179
 
}
180
 
 
181
 
uint32_t BlitzData::read_meta_keycount(void) {
182
 
  assert(tc_meta_buffer);
183
 
  char *pos = tc_meta_buffer;
184
 
  pos += sizeof(current_hidden_row_id) + sizeof(uint64_t);
185
 
  return (uint32_t)uint4korr(pos);
186
 
}
187
 
 
188
 
void BlitzData::write_meta_row_id(uint64_t row_id) {
189
 
  assert(tc_meta_buffer);
190
 
  int8store(tc_meta_buffer, row_id);
191
 
}
192
 
 
193
 
void BlitzData::write_meta_autoinc(uint64_t num) {
194
 
  assert(tc_meta_buffer);
195
 
  char *pos = tc_meta_buffer + sizeof(current_hidden_row_id);
196
 
  int8store(pos, num);
197
 
}
198
 
 
199
 
void BlitzData::write_meta_keycount(uint32_t nkeys) {
200
 
  assert(tc_meta_buffer);
201
 
  char *pos = tc_meta_buffer;
202
 
  pos += sizeof(current_hidden_row_id) + sizeof(uint64_t);
203
 
  int4store(pos, nkeys);
204
 
}
205
 
 
206
 
char *BlitzData::get_row(const char *key, const size_t klen, int *vlen) {
207
 
  return (char *)tchdbget(data_table, key, klen, vlen);
208
 
}
209
 
 
210
 
/* Fastest way to fetch both key and value from TCHDB since it only
211
 
   involves one allocation. That is, both key and value are living
212
 
   on the same block of memory. The return value is a pointer to the
213
 
   next key. Technically it is a pointer to the region of memory that
214
 
   holds both key and value. */
215
 
char *BlitzData::next_key_and_row(const char *key, const size_t klen,
216
 
                                  int *next_key_len, const char **value,
217
 
                                  int *value_len) {
218
 
  return tchdbgetnext3(data_table, key, klen, next_key_len, value, value_len);
219
 
}
220
 
 
221
 
char *BlitzData::first_row(int *row_len) {
222
 
  return (char *)tchdbgetnext(data_table, NULL, 0, row_len);
223
 
}
224
 
 
225
 
uint64_t BlitzData::next_hidden_row_id(void) {
226
 
  /* current_hidden_row_id is an atomic type */
227
 
  uint64_t rv = current_hidden_row_id.increment();
228
 
  return rv;
229
 
}
230
 
 
231
 
int BlitzData::write_row(const char *key, const size_t klen,
232
 
                         const unsigned char *row, const size_t rlen) {
233
 
  return (tchdbput(data_table, key, klen, row, rlen)) ? 0 : 1;
234
 
}
235
 
 
236
 
int BlitzData::write_unique_row(const char *key, const size_t klen,
237
 
                                const unsigned char *row, const size_t rlen) {
238
 
  int rv = 0;
239
 
 
240
 
  if (!tchdbputkeep(data_table, key, klen, row, rlen)) {
241
 
    if (tchdbecode(data_table) == TCEKEEP) {
242
 
      errno = HA_ERR_FOUND_DUPP_KEY;
243
 
      rv = HA_ERR_FOUND_DUPP_KEY;
244
 
    }
245
 
  }
246
 
  return rv;
247
 
}
248
 
 
249
 
int BlitzData::delete_row(const char *key, const size_t klen) {
250
 
  return (tchdbout(data_table, key, klen)) ? 0 : -1;
251
 
}
252
 
 
253
 
bool BlitzData::delete_all_rows() {
254
 
  char buf[BLITZ_MAX_META_LEN];
255
 
 
256
 
  /* Evacuate the meta data buffer since this will be wiped out. */
257
 
  memcpy(buf, tc_meta_buffer, BLITZ_MAX_META_LEN);
258
 
 
259
 
  /* Now it's safe to wipe everything. */
260
 
  if (!tchdbvanish(data_table))
261
 
    return false;
262
 
 
263
 
  /* Copy the evacuated meta buffer back to the fresh TCHDB file. */
264
 
  tc_meta_buffer = tchdbopaque(data_table);
265
 
  memcpy(tc_meta_buffer, buf, BLITZ_MAX_META_LEN);
266
 
  
267
 
  return true;
268
 
}
269
 
 
270
 
/* Code from here on is for BlitzDB's internal system information management.
271
 
   It is deliberately separated from the data dictionary code because we
272
 
   might move to a simple flat file structure in the future. For now we
273
 
   use a micro Tokyo Cabinet database for this. */
274
 
int BlitzData::create_system_table(const std::string &path) {
275
 
  int rv = 0;
276
 
  int mode = (HDBOWRITER | HDBOCREAT);
277
 
 
278
 
  if ((rv = open_system_table(path.c_str(), mode)) != 0)
279
 
    return rv;
280
 
 
281
 
  return close_system_table();
282
 
}
283
 
 
284
 
int BlitzData::open_system_table(const std::string &path, const int mode) {
285
 
  char buf[FN_REFLEN];
286
 
  const int BUCKETS = 7;
287
 
 
288
 
  if ((system_table = tchdbnew()) == NULL)
289
 
    return HA_ERR_OUT_OF_MEM;
290
 
 
291
 
  if (!tchdbsetmutex(system_table)) {
292
 
    tchdbdel(system_table);
293
 
    return HA_ERR_CRASHED_ON_USAGE;
294
 
  }
295
 
 
296
 
  if (!tchdbtune(system_table, BUCKETS, -1, -1, 0)) {
297
 
    tchdbdel(system_table);
298
 
    return HA_ERR_CRASHED_ON_USAGE;
299
 
  }
300
 
 
301
 
  snprintf(buf, FN_REFLEN, "%s%s", path.c_str(), BLITZ_SYSTEM_EXT);
302
 
 
303
 
  if (!tchdbopen(system_table, buf, mode)) {
304
 
    tchdbdel(system_table);
305
 
    return HA_ERR_CRASHED_ON_USAGE;
306
 
  }
307
 
 
308
 
  return 0;
309
 
}
310
 
 
311
 
int BlitzData::close_system_table(void) {
312
 
  assert(system_table);
313
 
 
314
 
  if (!tchdbclose(system_table)) {
315
 
    tchdbdel(system_table);
316
 
    return HA_ERR_CRASHED_ON_USAGE;
317
 
  }
318
 
  tchdbdel(system_table);
319
 
  return 0;
320
 
}
321
 
 
322
 
bool BlitzData::write_table_definition(drizzled::message::Table &proto) {
323
 
  assert(system_table);
324
 
 
325
 
  std::string serialized_proto;
326
 
  proto.SerializeToString(&serialized_proto);
327
 
 
328
 
  if (!tchdbput(system_table, BLITZ_TABLE_PROTO_KEY.c_str(),
329
 
                BLITZ_TABLE_PROTO_KEY.length(), serialized_proto.c_str(),
330
 
                serialized_proto.length())) {
331
 
    return false;
332
 
  }
333
 
 
334
 
  if (proto.options().has_comment()) {
335
 
    if (!tchdbput(system_table, BLITZ_TABLE_PROTO_COMMENT_KEY.c_str(),
336
 
                  BLITZ_TABLE_PROTO_COMMENT_KEY.length(),
337
 
                  proto.options().comment().c_str(),
338
 
                  proto.options().comment().length())) {
339
 
      return false;
340
 
    }
341
 
  }
342
 
  return true;
343
 
}
344
 
 
345
 
char *BlitzData::get_system_entry(const char *key, const size_t klen,
346
 
                                  int *vlen) {
347
 
  assert(system_table);
348
 
  return (char *)tchdbget(system_table, key, klen, vlen);
349
 
}