~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/blitzdb/blitzdata.cc

Initial import of Project BlitzDB.

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 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 "ha_blitz.h"
 
21
 
 
22
#define BLITZ_TC_EXTRA_MMAP_SIZE (1024 * 1024 * 256)
 
23
#define BLITZ_TC_BUCKET_NUM 1000000
 
24
 
 
25
BlitzData::BlitzData() : current_hidden_id(0) {
 
26
  pthread_mutex_init(&id_lock, NULL);
 
27
}
 
28
 
 
29
BlitzData::~BlitzData() {
 
30
  pthread_mutex_destroy(&id_lock);
 
31
}
 
32
 
 
33
bool BlitzData::startup(const char *table_name) {
 
34
  data_table = open_table(table_name, BLITZ_DATAFILE_EXT, HDBOWRITER);
 
35
 
 
36
  if (data_table == NULL)
 
37
    return false;
 
38
 
 
39
  system_table = open_table(table_name, BLITZ_SYSTEM_EXT, HDBOWRITER);
 
40
 
 
41
  if (system_table == NULL) {
 
42
    close_table(data_table);
 
43
    return false;
 
44
  }
 
45
 
 
46
  tc_meta_buffer = tchdbopaque(data_table);
 
47
  current_hidden_id = (uint64_t)uint8korr(tc_meta_buffer);
 
48
  return true;
 
49
}
 
50
 
 
51
bool BlitzData::shutdown() {
 
52
  /* Copy the latest autogenerated ID back to TC's metadata buffer.
 
53
     This data will be sync'd by TC. */
 
54
  int8store(tc_meta_buffer, current_hidden_id);
 
55
 
 
56
  if (!close_table(data_table))
 
57
    return false;
 
58
 
 
59
  if (!close_table(system_table))
 
60
    return false;
 
61
 
 
62
  return true;
 
63
}
 
64
 
 
65
/* Similar to UNIX touch(1) but generates a TCHDB file. */
 
66
int BlitzData::create_table(const char *table_path, const char *ext) {
 
67
  TCHDB *table;
 
68
  int mode = (HDBOWRITER | HDBOCREAT);
 
69
 
 
70
  if ((table = open_table(table_path, ext, mode)) == NULL)
 
71
    return HA_ERR_CRASHED_ON_USAGE;
 
72
 
 
73
  if (!close_table(table))
 
74
    return HA_ERR_CRASHED_ON_USAGE;
 
75
 
 
76
  return 0;
 
77
}
 
78
 
 
79
TCHDB *BlitzData::open_table(const char *path, const char *ext, int mode) {
 
80
  TCHDB *table;
 
81
  char name_buffer[FN_REFLEN];
 
82
 
 
83
  if ((table = tchdbnew()) == NULL) {
 
84
    return NULL;
 
85
  }
 
86
 
 
87
  if (!tchdbsetmutex(table)) {
 
88
    tchdbdel(table);
 
89
    return NULL;
 
90
  }
 
91
 
 
92
  /* Allow the data table to use more resource than default. */
 
93
  if (strcmp(ext, BLITZ_DATAFILE_EXT) == 0) {
 
94
    if (!tchdbtune(table, BLITZ_TC_BUCKET_NUM, -1, -1, 0)) {
 
95
      tchdbdel(table);
 
96
      return NULL;
 
97
    }
 
98
 
 
99
    if (!tchdbsetxmsiz(table, BLITZ_TC_EXTRA_MMAP_SIZE)) {
 
100
      tchdbdel(table);
 
101
      return NULL;
 
102
    }
 
103
  }
 
104
 
 
105
  snprintf(name_buffer, FN_REFLEN, "%s%s", path, ext);
 
106
 
 
107
  if (!tchdbopen(table, name_buffer, mode)) {
 
108
    tchdbdel(table);
 
109
    return NULL;
 
110
  }
 
111
 
 
112
  return table;
 
113
}
 
114
 
 
115
bool BlitzData::rename_table(const char *from, const char *to) {
 
116
  char from_buf[FN_REFLEN];
 
117
  char to_buf[FN_REFLEN];
 
118
 
 
119
  snprintf(from_buf, FN_REFLEN, "%s%s", from, BLITZ_DATAFILE_EXT);
 
120
  snprintf(to_buf, FN_REFLEN, "%s%s", to, BLITZ_DATAFILE_EXT);
 
121
 
 
122
  if (rename(from_buf, to_buf) != 0)
 
123
    return false;
 
124
 
 
125
  snprintf(from_buf, FN_REFLEN, "%s%s", from, BLITZ_SYSTEM_EXT);
 
126
  snprintf(to_buf, FN_REFLEN, "%s%s", to, BLITZ_SYSTEM_EXT);
 
127
 
 
128
  if (rename(from_buf, to_buf) != 0)
 
129
    return false;
 
130
 
 
131
  return true;
 
132
}
 
133
 
 
134
bool BlitzData::close_table(TCHDB *table) {
 
135
  assert(table);
 
136
 
 
137
  if (!tchdbclose(table)) {
 
138
    tchdbdel(table);
 
139
    return false ;
 
140
  }
 
141
 
 
142
  tchdbdel(table);
 
143
  return true;
 
144
}
 
145
 
 
146
bool BlitzData::write_table_definition(TCHDB *table,
 
147
                                       drizzled::message::Table &proto) {
 
148
  assert(table);
 
149
  string serialized_proto;
 
150
 
 
151
  proto.SerializeToString(&serialized_proto);
 
152
 
 
153
  if (!tchdbput(table, BLITZ_TABLE_PROTO_KEY.c_str(),
 
154
                BLITZ_TABLE_PROTO_KEY.length(), serialized_proto.c_str(),
 
155
                serialized_proto.length())) {
 
156
    return false;
 
157
  }
 
158
 
 
159
  if (proto.options().has_comment()) {
 
160
    if (!tchdbput(table, BLITZ_TABLE_PROTO_COMMENT_KEY.c_str(),
 
161
                  BLITZ_TABLE_PROTO_COMMENT_KEY.length(),
 
162
                  proto.options().comment().c_str(),
 
163
                  proto.options().comment().length())) {
 
164
      return false;
 
165
    }
 
166
  }
 
167
  return true;
 
168
}
 
169
 
 
170
uint64_t BlitzData::nrecords() {
 
171
  return tchdbrnum(data_table);
 
172
}
 
173
 
 
174
char *BlitzData::get_row(const char *key, const size_t klen, int *vlen) {
 
175
  return (char *)tchdbget(data_table, key, klen, vlen);
 
176
}
 
177
 
 
178
/* Fastest way to fetch both key and value from TCHDB since it only
 
179
   involves one allocation. That is, both key and value are living
 
180
   on the same block of memory. The return value is a pointer to the
 
181
   next key. Technically it is a pointer to the region of memory that
 
182
   holds both key and value. */
 
183
char *BlitzData::next_key_and_row(const char *key, const size_t klen,
 
184
                                  int *next_key_len, const char **value,
 
185
                                  int *value_length) {
 
186
  return tchdbgetnext3(data_table, key, klen, next_key_len,
 
187
                       value, value_length);
 
188
}
 
189
 
 
190
/* Set key_ptr to the beginning of the key on memory and return
 
191
   the length of the key */
 
192
uint16_t BlitzData::fetch_position(unsigned char *position_buf,
 
193
                                   unsigned char *key_ptr) {
 
194
  uint16_t key_length;
 
195
  memcpy(&key_length, position_buf, sizeof(uint16_t));
 
196
  key_ptr = position_buf + sizeof(uint16_t);
 
197
  return key_length;
 
198
}
 
199
 
 
200
/* Store the position of the most recently fetched record so
 
201
   that drizzled can directly fetch the row later on for some
 
202
   arbitrary reason. */
 
203
void BlitzData::store_position(unsigned char *ref, char *key,
 
204
                               const size_t klen) {
 
205
  uint16_t key_length = (uint16_t)klen;
 
206
  memcpy(ref, &key_length, sizeof(uint16_t));
 
207
  memcpy(ref + sizeof(uint16_t), key, klen);
 
208
}
 
209
 
 
210
uint64_t BlitzData::next_hidden_row_id(void) {
 
211
  pthread_mutex_lock(&id_lock);
 
212
  uint64_t rv = ++current_hidden_id;
 
213
  pthread_mutex_unlock(&id_lock);
 
214
  return rv;
 
215
}
 
216
 
 
217
size_t BlitzData::generate_table_key(char *key_buffer) {
 
218
  int8store(key_buffer, next_hidden_row_id());
 
219
  return sizeof(uint64_t);
 
220
}
 
221
 
 
222
bool BlitzData::overwrite_row(const char *key, const size_t klen,
 
223
                              const unsigned char *row, const size_t rlen) {
 
224
  return tchdbput(data_table, key, klen, row, rlen);
 
225
}
 
226
 
 
227
bool BlitzData::delete_row(const char *key, const size_t klen) {
 
228
  return tchdbout(data_table, key, klen);
 
229
}
 
230
 
 
231
bool BlitzData::delete_all_rows() {
 
232
  return tchdbvanish(data_table);
 
233
}