Merge lp:~posulliv/drizzle/simple-tc-engine into lp:~drizzle-trunk/drizzle/development
- simple-tc-engine
- Merge into development
Status: | Rejected |
---|---|
Rejected by: | Padraig O'Sullivan |
Proposed branch: | lp:~posulliv/drizzle/simple-tc-engine |
Merge into: | lp:~drizzle-trunk/drizzle/development |
Diff against target: |
1515 lines 14 files modified
plugin/tokyo_cabinet_engine/open_tables.cc (+76/-0) plugin/tokyo_cabinet_engine/open_tables.h (+92/-0) plugin/tokyo_cabinet_engine/plugin.ac (+8/-0) plugin/tokyo_cabinet_engine/plugin.ini (+12/-0) plugin/tokyo_cabinet_engine/tokyo_cabinet_engine.cc (+71/-0) plugin/tokyo_cabinet_engine/tokyo_cabinet_engine.h (+73/-0) plugin/tokyo_cabinet_engine/tokyo_cabinet_handler.cc (+221/-0) plugin/tokyo_cabinet_engine/tokyo_cabinet_handler.h (+140/-0) plugin/tokyo_cabinet_engine/tokyo_cabinet_share.cc (+240/-0) plugin/tokyo_cabinet_engine/tokyo_cabinet_share.h (+219/-0) tests/suite/tc_engine/r/auto_increment.result (+32/-0) tests/suite/tc_engine/r/basic.result (+138/-0) tests/suite/tc_engine/t/auto_increment.test (+13/-0) tests/suite/tc_engine/t/basic.test (+107/-0) |
To merge this branch: | bzr merge lp:~posulliv/drizzle/simple-tc-engine |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Stewart Smith (community) | Needs Information | ||
Review via email: mp+12323@code.launchpad.net |
Commit message
Description of the change
Padraig O'Sullivan (posulliv) wrote : | # |
Brian Aker (brianaker) wrote : | # |
Hi!
Yep, we need a new in-memory engine. I can't really judge whether TC would work well for in-memory or not (we need to study up the analytics around this... aka benchmark).
My personal thought? No harm in doing it, and I suspect it will be no worse then the current engine (might even be an improvement...). Is it the final engine? I have my doubts mainly because of concurrency issues. You can certainly learn the interface this way, and... most likely this would be useful for others.
Cheers,
-Brian
Stewart Smith (stewart) wrote : | # |
On Fri, Sep 25, 2009 at 04:45:48AM -0000, Brian Aker wrote:
> Hi!
>
> Yep, we need a new in-memory engine. I can't really judge whether TC
> would work well for in-memory or not (we need to study up the analytics
> around this... aka benchmark).
>
> My personal thought? No harm in doing it, and I suspect it will be no
> worse then the current engine (might even be an improvement...). Is it
> the final engine? I have my doubts mainly because of concurrency issues.
> You can certainly learn the interface this way, and... most likely this
> would be useful for others.
I also really like the idea of maintaining an engine with a clear
boundary between engine API and storage engine code as all of our
existing engines are a bit muddy there and/or rather complex.
--
Stewart Smith
Stewart Smith (stewart) wrote : | # |
the delete table paths seem to be a bit strange. it looks like you're deleting it on the close of the last tableshare, although the proper way would be to do it when explicitly called to remove the table (and check exists/not exists).
If you wanted to be fancy and demo the data dictionary APIs, you could have a (on disk) tc db of table names with the data being the table proto.
Unmerged revisions
- 1155. By Padraig O'Sullivan
-
Merge from trunk.
- 1154. By Padraig O'Sullivan
-
Added some more doxygen comments.
- 1153. By Padraig O'Sullivan
-
Updated plugin main file to have the authors reflected accurately. Included
Brian and Stewart since I based this engine off the tokyo cabinet engine
they did. - 1152. By Padraig O'Sullivan
-
Converted the engine to an in-memory engine. It would be quite trivial to
create an option which lets the engine operate in memory or on disk. We
could even support having tables of both types at the same time. However, I
don't see why you would need a disk-based storage engine when you have
InnoDB? - 1151. By Padraig O'Sullivan
-
Added some doxygen comments and updated the plugin.ini file to indicate that
a test suite is available for this plugin. Thus, the test suite will get run
when 'make test' issued. - 1150. By Padraig O'Sullivan
-
Tiny modification based on valgrind output.
- 1149. By Padraig O'Sullivan
-
Updating the flags based to the tokyo cabinet based storage engine so that
altering of tables is supported. - 1148. By Padraig O'Sullivan
-
Corrected the way tables are updated. Update statements now work correctly.
- 1147. By Padraig O'Sullivan
-
Added support for deleting a row in the storage engine.
- 1146. By Padraig O'Sullivan
-
Added support for storing rows of non-fixed length to the storage engine.
Updates to rows which store blobs still don't work correctly but we are
making some progress.
Preview Diff
1 | === added directory 'plugin/tokyo_cabinet_engine' |
2 | === added file 'plugin/tokyo_cabinet_engine/open_tables.cc' |
3 | --- plugin/tokyo_cabinet_engine/open_tables.cc 1970-01-01 00:00:00 +0000 |
4 | +++ plugin/tokyo_cabinet_engine/open_tables.cc 2009-09-24 03:50:23 +0000 |
5 | @@ -0,0 +1,76 @@ |
6 | +/* |
7 | + * Copyright (C) 2009 Sun Microsystems |
8 | + * |
9 | + * This program is free software; you can redistribute it and/or modify |
10 | + * it under the terms of the GNU General Public License as published by |
11 | + * the Free Software Foundation; either version 2 of the License, or |
12 | + * (at your option) any later version. |
13 | + * |
14 | + * This program is distributed in the hope that it will be useful, |
15 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | + * GNU General Public License for more details. |
18 | + * |
19 | + * You should have received a copy of the GNU General Public License |
20 | + * along with this program; if not, write to the Free Software |
21 | + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
22 | + */ |
23 | + |
24 | +#include <drizzled/server_includes.h> |
25 | +#include "tokyo_cabinet_handler.h" |
26 | +#include "open_tables.h" |
27 | + |
28 | +#include <string> |
29 | +#include <map> |
30 | + |
31 | +using namespace std; |
32 | +using namespace drizzled; |
33 | + |
34 | +TokyoCabinetShare *OpenTables::getShare(const string &name) |
35 | +{ |
36 | + map<const string, TokyoCabinetShare *>::iterator it; |
37 | + pthread_mutex_lock(&mutex); |
38 | + |
39 | + it= open_tables.find(name); |
40 | + if (it != open_tables.end()) |
41 | + { |
42 | + share= (*it).second; |
43 | + } |
44 | + else |
45 | + { |
46 | + share= NULL; |
47 | + } |
48 | + |
49 | + if (! share) |
50 | + { |
51 | + share= new(std::nothrow) TokyoCabinetShare(name); |
52 | + if (! share) |
53 | + { |
54 | + pthread_mutex_unlock(&mutex); |
55 | + return NULL; |
56 | + } |
57 | + if (! share->openTable()) |
58 | + { |
59 | + delete share; |
60 | + return NULL; |
61 | + } |
62 | + open_tables[name]= share; |
63 | + share->initThreadLock(); |
64 | + } |
65 | + share->incUseCount(); |
66 | + pthread_mutex_unlock(&mutex); |
67 | + |
68 | + return share; |
69 | +} |
70 | + |
71 | +void OpenTables::freeShare() |
72 | +{ |
73 | + pthread_mutex_lock(&mutex); |
74 | + share->decUseCount(); |
75 | + if (share->getUseCount() == 0) |
76 | + { |
77 | + share->freeDatabaseHandler(); |
78 | + open_tables.erase(share->getName()); |
79 | + } |
80 | + pthread_mutex_unlock(&mutex); |
81 | +} |
82 | |
83 | === added file 'plugin/tokyo_cabinet_engine/open_tables.h' |
84 | --- plugin/tokyo_cabinet_engine/open_tables.h 1970-01-01 00:00:00 +0000 |
85 | +++ plugin/tokyo_cabinet_engine/open_tables.h 2009-09-24 03:50:23 +0000 |
86 | @@ -0,0 +1,92 @@ |
87 | +/* |
88 | + * Copyright (C) 2009 Sun Microsystems |
89 | + * |
90 | + * This program is free software; you can redistribute it and/or modify |
91 | + * it under the terms of the GNU General Public License as published by |
92 | + * the Free Software Foundation; version 2 of the License. |
93 | + * |
94 | + * This program is distributed in the hope that it will be useful, |
95 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
96 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
97 | + * GNU General Public License for more details. |
98 | + * |
99 | + * You should have received a copy of the GNU General Public License |
100 | + * along with this program; if not, write to the Free Software |
101 | + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
102 | + */ |
103 | + |
104 | +/** |
105 | + * @file |
106 | + * |
107 | + * Defines a class for how open tables will be tracked for this storage |
108 | + * engine. |
109 | + */ |
110 | + |
111 | +#ifndef DRIZZLE_PLUGIN_TOKYO_ENGINE_OPEN_TABLES_H |
112 | +#define DRIZZLE_PLUGIN_TOKYO_ENGINE_OPEN_TABLES_H |
113 | + |
114 | +#include "tokyo_cabinet_handler.h" |
115 | + |
116 | +#include <string> |
117 | +#include <vector> |
118 | +#include <map> |
119 | + |
120 | +/** |
121 | + * @class OpenTables |
122 | + * |
123 | + * Class which tracks all the open tables for the storage engine. |
124 | + * Encapsulating this functionality in a class will make it easier for us to |
125 | + * change things such as whether a std::map or HASH is used to lookup the |
126 | + * open tables. |
127 | + */ |
128 | +class OpenTables |
129 | +{ |
130 | +public: |
131 | + |
132 | + static OpenTables &singleton() |
133 | + { |
134 | + static OpenTables open_tabs; |
135 | + return open_tabs; |
136 | + } |
137 | + |
138 | + /** |
139 | + * Retrieve a share from the structure used to main the list of open |
140 | + * shares. We do a lookup by name. |
141 | + * |
142 | + * @param[in] name name to lookup |
143 | + * @return pointer to the appropriate table share |
144 | + */ |
145 | + TokyoCabinetShare *getShare(const std::string &name); |
146 | + |
147 | + /** |
148 | + * Erase a share from the structure used to maintain the list of shares. |
149 | + */ |
150 | + void freeShare(); |
151 | + |
152 | +private: |
153 | + |
154 | + pthread_mutex_t mutex; |
155 | + |
156 | + std::map<const std::string, TokyoCabinetShare *> |
157 | + open_tables; |
158 | + |
159 | + TokyoCabinetShare *share; |
160 | + |
161 | + OpenTables() |
162 | + : |
163 | + mutex(), |
164 | + open_tables(), |
165 | + share(NULL) |
166 | + { |
167 | + pthread_mutex_init(&mutex, MY_MUTEX_INIT_FAST); |
168 | + } |
169 | + |
170 | + ~OpenTables() |
171 | + { |
172 | + pthread_mutex_destroy(&mutex); |
173 | + } |
174 | + |
175 | + OpenTables(const OpenTables&); |
176 | +}; |
177 | + |
178 | +#endif /* DRIZZLE_PLUGIN_TOKYO_ENGINE_OPEN_TABLES_H */ |
179 | |
180 | === added file 'plugin/tokyo_cabinet_engine/plugin.ac' |
181 | --- plugin/tokyo_cabinet_engine/plugin.ac 1970-01-01 00:00:00 +0000 |
182 | +++ plugin/tokyo_cabinet_engine/plugin.ac 2009-09-24 03:50:23 +0000 |
183 | @@ -0,0 +1,8 @@ |
184 | +AC_LIB_HAVE_LINKFLAGS(tokyocabinet,, |
185 | + [#include <tchdb.h>], |
186 | + [ |
187 | + TCHDB hdb; |
188 | + ]) |
189 | + AS_IF([test "x$ac_cv_libtokyocabinet" = "xno"], |
190 | + AC_MSG_WARN([tokyocabinet not found: not building TokyoCabinet engine.])) |
191 | +DRIZZLED_PLUGIN_DEP_LIBS="${DRIZZLED_PLUGIN_DEP_LIBS} ${LTLIBTOKYOCABINET}" |
192 | |
193 | === added file 'plugin/tokyo_cabinet_engine/plugin.ini' |
194 | --- plugin/tokyo_cabinet_engine/plugin.ini 1970-01-01 00:00:00 +0000 |
195 | +++ plugin/tokyo_cabinet_engine/plugin.ini 2009-09-24 03:50:23 +0000 |
196 | @@ -0,0 +1,12 @@ |
197 | +[plugin] |
198 | +name=tokyo_cabinet_engine |
199 | +title=Tokyo Cabinet Storage Engine |
200 | +description=A Tokyo Cabinet Based Storage Engine |
201 | +load_by_default= yes |
202 | +sources=tokyo_cabinet_engine.cc tokyo_cabinet_handler.cc open_tables.cc |
203 | + tokyo_cabinet_share.cc |
204 | +headers=tokyo_cabinet_engine.h tokyo_cabinet_handler.h open_tables.h |
205 | + tokyo_cabinet_share.h |
206 | +build_conditional="${ac_cv_libtokyocabinet}" = "yes" |
207 | +ldflags=${LTLIBTOKYOCABINET} |
208 | +testsuite=tc_engine |
209 | |
210 | === added file 'plugin/tokyo_cabinet_engine/tokyo_cabinet_engine.cc' |
211 | --- plugin/tokyo_cabinet_engine/tokyo_cabinet_engine.cc 1970-01-01 00:00:00 +0000 |
212 | +++ plugin/tokyo_cabinet_engine/tokyo_cabinet_engine.cc 2009-09-24 03:50:23 +0000 |
213 | @@ -0,0 +1,71 @@ |
214 | +/* |
215 | + * Copyright (C) 2009 Sun Microsystems |
216 | + * |
217 | + * This program is free software; you can redistribute it and/or modify |
218 | + * it under the terms of the GNU General Public License as published by |
219 | + * the Free Software Foundation; either version 2 of the License, or |
220 | + * (at your option) any later version. |
221 | + * |
222 | + * This program is distributed in the hope that it will be useful, |
223 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
224 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
225 | + * GNU General Public License for more details. |
226 | + * |
227 | + * You should have received a copy of the GNU General Public License |
228 | + * along with this program; if not, write to the Free Software |
229 | + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
230 | + */ |
231 | + |
232 | +#include <drizzled/server_includes.h> |
233 | +#include <drizzled/show.h> |
234 | +#include "tokyo_cabinet_engine.h" |
235 | +#include "tokyo_cabinet_handler.h" |
236 | +#include "open_tables.h" |
237 | + |
238 | +#include <string> |
239 | +#include <map> |
240 | + |
241 | +using namespace std; |
242 | +using namespace drizzled; |
243 | + |
244 | +static const string engine_name("Tokyo"); |
245 | +static StorageEngine *tokyo_cabinet_engine= NULL; |
246 | + |
247 | +static int init(plugin::Registry ®istry) |
248 | +{ |
249 | + tokyo_cabinet_engine= new(std::nothrow) TokyoCabinetEngine(engine_name); |
250 | + if (! tokyo_cabinet_engine) |
251 | + { |
252 | + return true; |
253 | + } |
254 | + |
255 | + /* we are good to go */ |
256 | + registry.add(tokyo_cabinet_engine); |
257 | + |
258 | + return false; |
259 | +} |
260 | + |
261 | +static int deinit(plugin::Registry ®istry) |
262 | +{ |
263 | + if (tokyo_cabinet_engine) |
264 | + { |
265 | + registry.remove(tokyo_cabinet_engine); |
266 | + delete tokyo_cabinet_engine; |
267 | + } |
268 | + return false; |
269 | +} |
270 | + |
271 | +drizzle_declare_plugin(tokyo_cabinet_engine) |
272 | +{ |
273 | + "tokyo_cabinet_engine", |
274 | + "0.1", |
275 | + "Padraig O'Sullivan, Brian Aker, Stewart Smith", |
276 | + "Simple In-Memory Tokyo Cabinet Storage Engine", |
277 | + PLUGIN_LICENSE_GPL, |
278 | + init, /* Plugin Init */ |
279 | + deinit, /* Plugin Deinit */ |
280 | + NULL, /* status variables */ |
281 | + NULL, /* system variables */ |
282 | + NULL /* config options */ |
283 | +} |
284 | +drizzle_declare_plugin_end; |
285 | |
286 | === added file 'plugin/tokyo_cabinet_engine/tokyo_cabinet_engine.h' |
287 | --- plugin/tokyo_cabinet_engine/tokyo_cabinet_engine.h 1970-01-01 00:00:00 +0000 |
288 | +++ plugin/tokyo_cabinet_engine/tokyo_cabinet_engine.h 2009-09-24 03:50:23 +0000 |
289 | @@ -0,0 +1,73 @@ |
290 | +/* |
291 | + * Copyright (C) 2009 Sun Microsystems |
292 | + * |
293 | + * This program is free software; you can redistribute it and/or modify |
294 | + * it under the terms of the GNU General Public License as published by |
295 | + * the Free Software Foundation; either version 2 of the License, or |
296 | + * (at your option) any later version. |
297 | + * |
298 | + * This program is distributed in the hope that it will be useful, |
299 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
300 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
301 | + * GNU General Public License for more details. |
302 | + * |
303 | + * You should have received a copy of the GNU General Public License |
304 | + * along with this program; if not, write to the Free Software |
305 | + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
306 | + */ |
307 | + |
308 | +/** |
309 | + * @file |
310 | + * |
311 | + * Declares the class that will represent this storage engine. |
312 | + */ |
313 | + |
314 | +#ifndef DRIZZLE_PLUGIN_TOKYO_CABINET_ENGINE_H |
315 | +#define DRIZZLE_PLUGIN_TOKYO_CABINET_ENGINE_H |
316 | + |
317 | +#include <drizzled/error.h> |
318 | +#include "tokyo_cabinet_handler.h" |
319 | + |
320 | +#include <string> |
321 | + |
322 | +class TokyoCabinetEngine : public StorageEngine |
323 | +{ |
324 | +public: |
325 | + |
326 | + TokyoCabinetEngine(const std::string &in_name) |
327 | + : |
328 | + StorageEngine(in_name, |
329 | + HTON_CAN_RECREATE) |
330 | + {} |
331 | + |
332 | + ~TokyoCabinetEngine() {} |
333 | + |
334 | + virtual handler *create(TableShare *table, |
335 | + MEM_ROOT *mem_root) |
336 | + { |
337 | + return new(mem_root) TokyoCabinetHandler(this, table); |
338 | + } |
339 | + |
340 | + const char **bas_ext() const |
341 | + { |
342 | + return NULL; |
343 | + } |
344 | + |
345 | + int createTableImplementation(Session *, |
346 | + const char *, |
347 | + Table *, |
348 | + HA_CREATE_INFO *, |
349 | + drizzled::message::Table *) |
350 | + { |
351 | + return 0; |
352 | + } |
353 | + |
354 | + int deleteTableImplementation(Session *, |
355 | + const string) |
356 | + { |
357 | + return 0; |
358 | + } |
359 | + |
360 | +}; |
361 | + |
362 | +#endif /* DRIZZLE_PLUGIN_TOKYO_CABINET_ENGINE_H */ |
363 | |
364 | === added file 'plugin/tokyo_cabinet_engine/tokyo_cabinet_handler.cc' |
365 | --- plugin/tokyo_cabinet_engine/tokyo_cabinet_handler.cc 1970-01-01 00:00:00 +0000 |
366 | +++ plugin/tokyo_cabinet_engine/tokyo_cabinet_handler.cc 2009-09-24 03:50:23 +0000 |
367 | @@ -0,0 +1,221 @@ |
368 | +/* |
369 | + * Copyright (C) 2009 Sun Microsystems |
370 | + * |
371 | + * This program is free software; you can redistribute it and/or modify |
372 | + * it under the terms of the GNU General Public License as published by |
373 | + * the Free Software Foundation; either version 2 of the License, or |
374 | + * (at your option) any later version. |
375 | + * |
376 | + * This program is distributed in the hope that it will be useful, |
377 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
378 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
379 | + * GNU General Public License for more details. |
380 | + * |
381 | + * You should have received a copy of the GNU General Public License |
382 | + * along with this program; if not, write to the Free Software |
383 | + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
384 | + */ |
385 | + |
386 | +#include "drizzled/server_includes.h" |
387 | +#include "drizzled/join_table.h" |
388 | +#include "drizzled/handler.h" |
389 | +#include "drizzled/field/blob.h" |
390 | +#include "drizzled/field/timestamp.h" |
391 | +#include "drizzled/session.h" |
392 | + |
393 | +#include "tokyo_cabinet_handler.h" |
394 | +#include "tokyo_cabinet_share.h" |
395 | +#include "open_tables.h" |
396 | + |
397 | +#include <string> |
398 | +#include <map> |
399 | + |
400 | +using namespace std; |
401 | +using namespace drizzled; |
402 | + |
403 | +int TokyoCabinetHandler::open(const char *name, int, uint32_t) |
404 | +{ |
405 | + OpenTables &open_tables= OpenTables::singleton(); |
406 | + if (! (share= open_tables.getShare(name))) |
407 | + { |
408 | + return HA_ERR_OUT_OF_MEM; |
409 | + } |
410 | + |
411 | + assert(share); |
412 | + |
413 | + thr_lock_data_init(share->getThreadLock(), &data_lock, NULL); |
414 | + |
415 | + bool pack_table= ! (table->s->db_create_options & |
416 | + HA_OPTION_PACK_RECORD); |
417 | + share->setFixedLengthTable(pack_table); |
418 | + share->setRowLength(getMaxRowLength()); |
419 | + share->setTableFields(table->field); |
420 | + share->setNullBytes(table->s->null_bytes); |
421 | + share->setTableRecord(table->record[0]); |
422 | + |
423 | + return 0; |
424 | +} |
425 | + |
426 | +int TokyoCabinetHandler::close() |
427 | +{ |
428 | + OpenTables &open_tables= OpenTables::singleton(); |
429 | + open_tables.freeShare(); |
430 | + return 0; |
431 | +} |
432 | + |
433 | +int TokyoCabinetHandler::info(uint32_t flags) |
434 | +{ |
435 | + /* |
436 | + * If this flag is set, then we know that the time of the last |
437 | + * modification needs to be modified. |
438 | + */ |
439 | + if (flags & HA_STATUS_TIME) |
440 | + { |
441 | + } |
442 | + |
443 | + if (flags & HA_STATUS_VARIABLE) |
444 | + { |
445 | + stats.records= share->getNumOfRecords(); |
446 | + } |
447 | + |
448 | + /* |
449 | + * If this flag is set, then we know that the auto_increment value needs |
450 | + * to be updated. |
451 | + */ |
452 | + if (flags & HA_STATUS_AUTO) |
453 | + { |
454 | + stats.auto_increment_value= 1; |
455 | + } |
456 | + |
457 | + return 0; |
458 | +} |
459 | + |
460 | +int TokyoCabinetHandler::rnd_init(bool) |
461 | +{ |
462 | + share->initIterators(); |
463 | + return 0; |
464 | +} |
465 | + |
466 | +int TokyoCabinetHandler::rnd_next(unsigned char *buf) |
467 | +{ |
468 | + return (share->retrieveRow(buf)); |
469 | +} |
470 | + |
471 | +int TokyoCabinetHandler::rnd_pos(unsigned char *buf, unsigned char *pos) |
472 | +{ |
473 | + Field *field_key= table->key_info[table->s->primary_key].key_part->field; |
474 | + uint16_t len; |
475 | + memcpy(&len, pos, sizeof(uint16_t)); |
476 | + int ret= share->findRow(field_key, buf, pos + 2, len); |
477 | + |
478 | + return ret; |
479 | +} |
480 | + |
481 | +void TokyoCabinetHandler::position(const unsigned char *) |
482 | +{ |
483 | + return; |
484 | +} |
485 | + |
486 | +THR_LOCK_DATA **TokyoCabinetHandler::store_lock(Session *session, |
487 | + THR_LOCK_DATA **to, |
488 | + enum thr_lock_type lock_type) |
489 | +{ |
490 | + /* borrowed from archive and BDB engines. TODO: understand this! */ |
491 | + if (lock_type != TL_IGNORE && data_lock.type == TL_UNLOCK) |
492 | + { |
493 | + if ((lock_type >= TL_WRITE_CONCURRENT_INSERT && lock_type <= TL_WRITE) && |
494 | + ! session_tablespace_op(session)) |
495 | + { |
496 | + lock_type= TL_WRITE_ALLOW_WRITE; |
497 | + } |
498 | + if (lock_type == TL_READ_NO_INSERT) |
499 | + { |
500 | + lock_type= TL_READ; |
501 | + } |
502 | + data_lock.type= lock_type; |
503 | + } |
504 | + *to++= &data_lock; |
505 | + return to; |
506 | +} |
507 | + |
508 | +uint32_t TokyoCabinetHandler::index_flags(uint32_t, |
509 | + uint32_t, |
510 | + bool) const |
511 | +{ |
512 | + return 0; |
513 | +} |
514 | + |
515 | +int TokyoCabinetHandler::index_read(unsigned char *buf, |
516 | + const unsigned char *key, |
517 | + uint32_t key_len, |
518 | + enum ha_rkey_function) |
519 | +{ |
520 | + Field *key_field= table->key_info[active_index].key_part->field; |
521 | + ha_statistic_increment(&SSV::ha_read_key_count); |
522 | + int ret= share->findRow(key_field, buf, key, key_len); |
523 | + return ret; |
524 | +} |
525 | + |
526 | +int TokyoCabinetHandler::index_next(unsigned char *) |
527 | +{ |
528 | + return HA_ERR_END_OF_FILE; |
529 | +} |
530 | + |
531 | +int TokyoCabinetHandler::write_row(unsigned char *buf) |
532 | +{ |
533 | + Field *key_field= table->key_info[table->s->primary_key].key_part->field; |
534 | + |
535 | + ha_statistic_increment(&SSV::ha_write_count); |
536 | + |
537 | + if (table->next_number_field && buf == table->record[0]) |
538 | + { |
539 | + update_auto_increment(); |
540 | + } |
541 | + |
542 | + /* push the data to the key/value store */ |
543 | + return (share->storeRow(key_field, buf)); |
544 | +} |
545 | + |
546 | +int TokyoCabinetHandler::update_row(const unsigned char *, |
547 | + unsigned char *new_data) |
548 | +{ |
549 | + Field *key_field= table->key_info[table->s->primary_key].key_part->field; |
550 | + |
551 | + ha_statistic_increment(&SSV::ha_update_count); |
552 | + |
553 | + if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) |
554 | + { |
555 | + table->timestamp_field->set_time(); |
556 | + } |
557 | + |
558 | + return (share->updateRow(key_field, new_data)); |
559 | +} |
560 | + |
561 | +int TokyoCabinetHandler::delete_row(const unsigned char *) |
562 | +{ |
563 | + Field *key_field= table->key_info[table->s->primary_key].key_part->field; |
564 | + ha_statistic_increment(&SSV::ha_delete_count); |
565 | + return (share->deleteRow(key_field)); |
566 | +} |
567 | + |
568 | +int TokyoCabinetHandler::delete_all_rows() |
569 | +{ |
570 | + share->deleteAllRows(); |
571 | + return 0; |
572 | +} |
573 | + |
574 | +uint32_t TokyoCabinetHandler::getMaxRowLength() |
575 | +{ |
576 | + uint32_t len= table->s->reclength + table->s->fields * 2; |
577 | + uint32_t *pos= table->getBlobField(); |
578 | + uint32_t *end= pos + table->sizeBlobFields(); |
579 | + |
580 | + while (pos != end) |
581 | + { |
582 | + Field_blob *blob_field= static_cast<Field_blob *>(table->field[*pos]); |
583 | + len+= 2 + blob_field->get_length(); |
584 | + pos++; |
585 | + } |
586 | + |
587 | + return len; |
588 | +} |
589 | |
590 | === added file 'plugin/tokyo_cabinet_engine/tokyo_cabinet_handler.h' |
591 | --- plugin/tokyo_cabinet_engine/tokyo_cabinet_handler.h 1970-01-01 00:00:00 +0000 |
592 | +++ plugin/tokyo_cabinet_engine/tokyo_cabinet_handler.h 2009-09-24 03:50:23 +0000 |
593 | @@ -0,0 +1,140 @@ |
594 | +/* |
595 | + * Copyright (C) 2009 Sun Microsystems |
596 | + * |
597 | + * This program is free software; you can redistribute it and/or modify |
598 | + * it under the terms of the GNU General Public License as published by |
599 | + * the Free Software Foundation; either version 2 of the License, or |
600 | + * (at your option) any later version. |
601 | + * |
602 | + * This program is distributed in the hope that it will be useful, |
603 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
604 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
605 | + * GNU General Public License for more details. |
606 | + * |
607 | + * You should have received a copy of the GNU General Public License |
608 | + * along with this program; if not, write to the Free Software |
609 | + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
610 | + */ |
611 | + |
612 | +/** |
613 | + * @file |
614 | + * |
615 | + * Declares the handler for the Tokyo Cabinet storage engine. |
616 | + */ |
617 | + |
618 | +#ifndef DRIZZLE_PLUGIN_TOKYO_CABINET_HANDLER_H |
619 | +#define DRIZZLE_PLUGIN_TOKYO_CABINET_HANDLER_H |
620 | + |
621 | +#include <drizzled/handler.h> |
622 | +#include <drizzled/show.h> |
623 | +#include <mysys/thr_lock.h> |
624 | + |
625 | +#include "tokyo_cabinet_share.h" |
626 | + |
627 | +class TokyoCabinetHandler : public handler |
628 | +{ |
629 | +public: |
630 | + |
631 | + /* determines how many indexes are allowed per table */ |
632 | + static const uint32_t MAX_KEYS= 1; |
633 | + static const uint32_t MAX_KEY_PARTS= 1; |
634 | + static const uint32_t MAX_KEY_LEN= 1024; |
635 | + |
636 | + TokyoCabinetHandler(StorageEngine *engine_arg, TableShare *table_arg) |
637 | + : |
638 | + handler(engine_arg, table_arg) |
639 | + {} |
640 | + |
641 | + ~TokyoCabinetHandler() {} |
642 | + |
643 | + const char *table_type() const |
644 | + { |
645 | + return "TOKYO"; |
646 | + } |
647 | + |
648 | + /* |
649 | + The name of the index type that will be used for display |
650 | + don't implement this method unless you really have indexes |
651 | + */ |
652 | + const char *index_type(uint32_t) |
653 | + { |
654 | + return "HASH"; |
655 | + } |
656 | + |
657 | + uint64_t table_flags() const |
658 | + { |
659 | + return (HA_NO_TRANSACTIONS | |
660 | + HA_REQUIRE_PRIMARY_KEY | |
661 | + HA_PRIMARY_KEY_REQUIRED_FOR_POSITION | |
662 | + HA_PRIMARY_KEY_REQUIRED_FOR_DELETE); |
663 | + } |
664 | + |
665 | + /* open a table */ |
666 | + int open(const char *name, int mode, uint32_t test_if_locked); |
667 | + |
668 | + /* close a table */ |
669 | + int close(void); |
670 | + |
671 | + /* provide info to the optimizer */ |
672 | + int info(uint32_t flag); |
673 | + |
674 | + /* preparation for table scan (is this true?) */ |
675 | + int rnd_init(bool scan); |
676 | + |
677 | + /* get the next row and copy it into buf */ |
678 | + int rnd_next(unsigned char *buf); |
679 | + |
680 | + /* locate row pointed to by pos, copy it into buf */ |
681 | + int rnd_pos(unsigned char *buf, unsigned char *pos); |
682 | + |
683 | + /* record position of a record for reordering */ |
684 | + void position(const unsigned char *record); |
685 | + |
686 | + THR_LOCK_DATA **store_lock(Session *session, |
687 | + THR_LOCK_DATA **to, |
688 | + enum thr_lock_type lock_type); |
689 | + |
690 | + uint32_t index_flags(uint32_t idx, uint32_t part, bool all_parts) const; |
691 | + int index_read(unsigned char *buf, |
692 | + const unsigned char *key, |
693 | + uint32_t key_len, |
694 | + enum ha_rkey_function find_flag); |
695 | + int index_next(unsigned char *buf); |
696 | + |
697 | + int write_row(unsigned char *buf); |
698 | + int update_row(const unsigned char *, |
699 | + unsigned char *); |
700 | + int delete_row(const unsigned char *); |
701 | + int delete_all_rows(); |
702 | + |
703 | + uint32_t max_supported_keys() const |
704 | + { |
705 | + return MAX_KEYS; |
706 | + } |
707 | + |
708 | + uint32_t max_supported_key_parts() const |
709 | + { |
710 | + return MAX_KEY_PARTS; |
711 | + } |
712 | + |
713 | + uint32_t max_supported_key_length() const |
714 | + { |
715 | + return MAX_KEY_LEN; |
716 | + } |
717 | + |
718 | +private: |
719 | + |
720 | + /** |
721 | + * Determine the maximum length of a row in the table we are working with. |
722 | + * This function is "borrowed" from the archive storage engine. |
723 | + * |
724 | + * @return the max row length for a table |
725 | + */ |
726 | + uint32_t getMaxRowLength(); |
727 | + |
728 | + THR_LOCK_DATA data_lock; |
729 | + TokyoCabinetShare *share; |
730 | + |
731 | +}; |
732 | + |
733 | +#endif /* DRIZZLE_PLUGIN_TOKYO_CABINET_HANDLER_H */ |
734 | |
735 | === added file 'plugin/tokyo_cabinet_engine/tokyo_cabinet_share.cc' |
736 | --- plugin/tokyo_cabinet_engine/tokyo_cabinet_share.cc 1970-01-01 00:00:00 +0000 |
737 | +++ plugin/tokyo_cabinet_engine/tokyo_cabinet_share.cc 2009-09-24 03:50:23 +0000 |
738 | @@ -0,0 +1,240 @@ |
739 | +/* |
740 | + * Copyright (C) 2009 Sun Microsystems |
741 | + * |
742 | + * This program is free software; you can redistribute it and/or modify |
743 | + * it under the terms of the GNU General Public License as published by |
744 | + * the Free Software Foundation; either version 2 of the License, or |
745 | + * (at your option) any later version. |
746 | + * |
747 | + * This program is distributed in the hope that it will be useful, |
748 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
749 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
750 | + * GNU General Public License for more details. |
751 | + * |
752 | + * You should have received a copy of the GNU General Public License |
753 | + * along with this program; if not, write to the Free Software |
754 | + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
755 | + */ |
756 | + |
757 | +#include "drizzled/server_includes.h" |
758 | +#include "drizzled/handler.h" |
759 | +#include "drizzled/show.h" |
760 | +#include "mysys/thr_lock.h" |
761 | + |
762 | +#include <tcutil.h> |
763 | +#include <tchdb.h> |
764 | +#include <stdlib.h> |
765 | +#include <stdbool.h> |
766 | +#include <stdint.h> |
767 | + |
768 | +#include "tokyo_cabinet_share.h" |
769 | + |
770 | +using namespace std; |
771 | + |
772 | +bool TokyoCabinetShare::createDatabaseHandler() |
773 | +{ |
774 | + data_handler= tcmdbnew(); |
775 | + if (! data_handler) |
776 | + { |
777 | + return false; |
778 | + } |
779 | + return true; |
780 | +} |
781 | + |
782 | +bool TokyoCabinetShare::openTable() |
783 | +{ |
784 | + return true; |
785 | +} |
786 | + |
787 | +void TokyoCabinetShare::freeDatabaseHandler() |
788 | +{ |
789 | + tcmdbdel(data_handler); |
790 | +} |
791 | + |
792 | +int TokyoCabinetShare::storeRow(Field *key_field, |
793 | + unsigned char *row) |
794 | +{ |
795 | + createKey(key_field); |
796 | + |
797 | + unsigned char *buf= new(std::nothrow) unsigned char[row_len]; |
798 | + if (! buf) |
799 | + { |
800 | + return HA_ERR_OUT_OF_MEM; |
801 | + } |
802 | + |
803 | + size_t len= packRow(buf, row); |
804 | + |
805 | + bool ret= tcmdbputkeep(data_handler, |
806 | + primary_key, |
807 | + primary_key_len, |
808 | + buf, |
809 | + len); |
810 | + if (! ret) |
811 | + { |
812 | + delete buf; |
813 | + return HA_ERR_GENERIC; |
814 | + } |
815 | + |
816 | + delete buf; |
817 | + return 0; |
818 | +} |
819 | + |
820 | +int TokyoCabinetShare::updateRow(Field *key_field, |
821 | + unsigned char *row) |
822 | +{ |
823 | + createKey(key_field); |
824 | + |
825 | + unsigned char *buf= new(std::nothrow) unsigned char[row_len]; |
826 | + if (! buf) |
827 | + { |
828 | + return HA_ERR_OUT_OF_MEM; |
829 | + } |
830 | + |
831 | + size_t len= packRow(buf, row); |
832 | + |
833 | + /* TODO: somehow, check if this operation succeeded */ |
834 | + tcmdbput(data_handler, |
835 | + primary_key, |
836 | + primary_key_len, |
837 | + buf, |
838 | + len); |
839 | + |
840 | + delete buf; |
841 | + return 0; |
842 | +} |
843 | + |
844 | +size_t TokyoCabinetShare::packRow(unsigned char *buf, |
845 | + unsigned char *row) |
846 | +{ |
847 | + size_t len= 0; |
848 | + |
849 | + if (fixed_length_table) |
850 | + { |
851 | + memcpy(buf, row, row_len); |
852 | + len= row_len; |
853 | + } |
854 | + else |
855 | + { |
856 | + /* copy NULL bits */ |
857 | + memcpy(buf, row, null_bytes); |
858 | + unsigned char *pos= buf + null_bytes; |
859 | + |
860 | + for (Field **field= fields; *field; field++) |
861 | + { |
862 | + if (! ((*field)->is_null())) |
863 | + { |
864 | + pos= (*field)->pack(pos, row + (*field)->offset(row)); |
865 | + } |
866 | + } |
867 | + len= (size_t) (pos - buf); |
868 | + } |
869 | + return len; |
870 | +} |
871 | + |
872 | +void TokyoCabinetShare::unpackRow(unsigned char *buf, |
873 | + const char *row) |
874 | +{ |
875 | + if (fixed_length_table) |
876 | + { |
877 | + memcpy(buf, row, row_len); |
878 | + } |
879 | + else |
880 | + { |
881 | + const unsigned char *pos= (const unsigned char *) row; |
882 | + memcpy(buf, pos, null_bytes); |
883 | + pos+= null_bytes; |
884 | + |
885 | + for (Field **field= fields; *field; field++) |
886 | + { |
887 | + if (! (*field)->is_null()) |
888 | + { |
889 | + pos= (*field)->unpack(buf + (*field)->offset(table_record), pos); |
890 | + } |
891 | + } |
892 | + } |
893 | +} |
894 | + |
895 | +void TokyoCabinetShare::createKey(Field *key) |
896 | +{ |
897 | + char *pos= primary_key_buff; |
898 | + char attr_buff[1024]; |
899 | + |
900 | + String attribute(attr_buff, |
901 | + sizeof(attr_buff), |
902 | + &my_charset_bin); |
903 | + |
904 | + key->setReadSet(); |
905 | + key->val_str(&attribute, &attribute); |
906 | + |
907 | + size_t len= strlen(key->field_name); |
908 | + memcpy(pos, key->field_name, len); |
909 | + pos+= len; |
910 | + |
911 | + memcpy(pos, attribute.ptr(), attribute.length()); |
912 | + pos+= attribute.length(); |
913 | + |
914 | + primary_key_len= (size_t) (pos - primary_key_buff); |
915 | + primary_key= primary_key_buff; |
916 | +} |
917 | + |
918 | +void TokyoCabinetShare::initIterators() |
919 | +{ |
920 | + tcmdbiterinit(data_handler); |
921 | +} |
922 | + |
923 | +int TokyoCabinetShare::retrieveRow(unsigned char *buf) |
924 | +{ |
925 | + char *key= NULL; |
926 | + |
927 | + while ((key= tcmdbiternext2(data_handler)) != NULL) |
928 | + { |
929 | + char *value= tcmdbget2(data_handler, key); |
930 | + free(key); |
931 | + if (value) |
932 | + { |
933 | + unpackRow(buf, value); |
934 | + free(value); |
935 | + return 0; |
936 | + } |
937 | + } |
938 | + |
939 | + return HA_ERR_END_OF_FILE; |
940 | +} |
941 | + |
942 | +int TokyoCabinetShare::deleteRow(Field *key_field) |
943 | +{ |
944 | + createKey(key_field); |
945 | + |
946 | + bool ret= tcmdbout(data_handler, |
947 | + primary_key, |
948 | + primary_key_len); |
949 | + if (! ret) |
950 | + { |
951 | + return -1; |
952 | + } |
953 | + return 0; |
954 | +} |
955 | + |
956 | +int TokyoCabinetShare::findRow(Field *key_field, |
957 | + unsigned char *buf, |
958 | + const unsigned char *key, |
959 | + size_t key_len) |
960 | +{ |
961 | + key_field->set_key_image(key, key_len); |
962 | + key_field->set_notnull(); |
963 | + createKey(key_field); |
964 | + |
965 | + int size; |
966 | + char *tc_row= (char *) tcmdbget(data_handler, |
967 | + primary_key, |
968 | + primary_key_len, |
969 | + &size); |
970 | + if (tc_row == NULL) |
971 | + { |
972 | + return HA_ERR_KEY_NOT_FOUND; |
973 | + } |
974 | + |
975 | + unpackRow(buf, tc_row); |
976 | + free(tc_row); |
977 | + return 0; |
978 | +} |
979 | |
980 | === added file 'plugin/tokyo_cabinet_engine/tokyo_cabinet_share.h' |
981 | --- plugin/tokyo_cabinet_engine/tokyo_cabinet_share.h 1970-01-01 00:00:00 +0000 |
982 | +++ plugin/tokyo_cabinet_engine/tokyo_cabinet_share.h 2009-09-24 03:50:23 +0000 |
983 | @@ -0,0 +1,219 @@ |
984 | +/* |
985 | + * Copyright (C) 2009 Sun Microsystems |
986 | + * |
987 | + * This program is free software; you can redistribute it and/or modify |
988 | + * it under the terms of the GNU General Public License as published by |
989 | + * the Free Software Foundation; either version 2 of the License, or |
990 | + * (at your option) any later version. |
991 | + * |
992 | + * This program is distributed in the hope that it will be useful, |
993 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
994 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
995 | + * GNU General Public License for more details. |
996 | + * |
997 | + * You should have received a copy of the GNU General Public License |
998 | + * along with this program; if not, write to the Free Software |
999 | + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
1000 | + */ |
1001 | + |
1002 | +/** |
1003 | + * @file |
1004 | + * |
1005 | + * Contains a declaration of the share class for the Tokyo Cabinet storage |
1006 | + * engine. |
1007 | + * |
1008 | + * @todo |
1009 | + * would it not be better to create a class that encapsulates all the calls |
1010 | + * to the Tokyo Cabinet API that we can just use from within the table |
1011 | + * share? |
1012 | + */ |
1013 | + |
1014 | +#ifndef DRIZZLE_PLUGIN_TOKYO_CABINET_SHARE_H |
1015 | +#define DRIZZLE_PLUGIN_TOKYO_CABINET_SHARE_H |
1016 | + |
1017 | +#include <drizzled/handler.h> |
1018 | +#include <drizzled/show.h> |
1019 | +#include <mysys/thr_lock.h> |
1020 | + |
1021 | +#include <tcutil.h> |
1022 | +#include <tchdb.h> |
1023 | +#include <stdlib.h> |
1024 | +#include <stdbool.h> |
1025 | +#include <stdint.h> |
1026 | + |
1027 | +class TokyoCabinetShare |
1028 | +{ |
1029 | +public: |
1030 | + |
1031 | + static const uint32_t MAX_KEY_LEN= 1024; |
1032 | + |
1033 | + TokyoCabinetShare() |
1034 | + : |
1035 | + use_count(0), |
1036 | + lock(), |
1037 | + name(), |
1038 | + data_handler(NULL), |
1039 | + fixed_length_table(false), |
1040 | + row_len(0), |
1041 | + fields(NULL), |
1042 | + null_bytes(0), |
1043 | + table_record(NULL), |
1044 | + primary_key(NULL), |
1045 | + primary_key_len(0) |
1046 | + { |
1047 | + data_handler= tcmdbnew(); |
1048 | + } |
1049 | + |
1050 | + TokyoCabinetShare(const std::string &in_name) |
1051 | + : |
1052 | + use_count(0), |
1053 | + lock(), |
1054 | + name(in_name), |
1055 | + data_handler(NULL), |
1056 | + fixed_length_table(false), |
1057 | + row_len(0), |
1058 | + fields(NULL), |
1059 | + null_bytes(0), |
1060 | + table_record(NULL), |
1061 | + primary_key(NULL), |
1062 | + primary_key_len(0) |
1063 | + { |
1064 | + data_handler= tcmdbnew(); |
1065 | + } |
1066 | + |
1067 | + ~TokyoCabinetShare() |
1068 | + { |
1069 | + thr_lock_delete(&lock); |
1070 | + tcmdbdel(data_handler); |
1071 | + } |
1072 | + |
1073 | + uint32_t getUseCount() const |
1074 | + { |
1075 | + return use_count; |
1076 | + } |
1077 | + |
1078 | + void incUseCount() |
1079 | + { |
1080 | + use_count++; |
1081 | + } |
1082 | + |
1083 | + void decUseCount() |
1084 | + { |
1085 | + use_count--; |
1086 | + } |
1087 | + |
1088 | + const std::string &getName() const |
1089 | + { |
1090 | + return name; |
1091 | + } |
1092 | + |
1093 | + void initThreadLock() |
1094 | + { |
1095 | + thr_lock_init(&lock); |
1096 | + } |
1097 | + |
1098 | + THR_LOCK *getThreadLock() |
1099 | + { |
1100 | + return &lock; |
1101 | + } |
1102 | + |
1103 | + void setFixedLengthTable(bool input) |
1104 | + { |
1105 | + fixed_length_table= input; |
1106 | + } |
1107 | + |
1108 | + bool isFixedLengthTable() const |
1109 | + { |
1110 | + return fixed_length_table; |
1111 | + } |
1112 | + |
1113 | + void setRowLength(uint32_t in_len) |
1114 | + { |
1115 | + row_len= in_len; |
1116 | + } |
1117 | + |
1118 | + void setTableFields(Field **in_fields) |
1119 | + { |
1120 | + fields= in_fields; |
1121 | + } |
1122 | + |
1123 | + void setNullBytes(size_t in_null_bytes) |
1124 | + { |
1125 | + null_bytes= in_null_bytes; |
1126 | + } |
1127 | + |
1128 | + void setTableRecord(unsigned char *in_record) |
1129 | + { |
1130 | + table_record= in_record; |
1131 | + } |
1132 | + |
1133 | + bool createDatabaseHandler(); |
1134 | + |
1135 | + bool openTable(); |
1136 | + |
1137 | + void freeDatabaseHandler(); |
1138 | + |
1139 | + uint64_t getNumOfRecords() |
1140 | + { |
1141 | + return tcmdbrnum(data_handler); |
1142 | + } |
1143 | + |
1144 | + int storeRow(Field *key_field, |
1145 | + unsigned char *row); |
1146 | + |
1147 | + int updateRow(Field *key_field, |
1148 | + unsigned char *row); |
1149 | + |
1150 | + /** |
1151 | + * Create a key for this row to be stored in the Tokyo Cabinet store. The |
1152 | + * key is created based on the primary key value for the row. |
1153 | + * |
1154 | + * @param[in] the primary key field |
1155 | + */ |
1156 | + void createKey(Field *key); |
1157 | + |
1158 | + int deleteRow(Field *key_field); |
1159 | + |
1160 | + void deleteAllRows() |
1161 | + { |
1162 | + tcmdbvanish(data_handler); |
1163 | + } |
1164 | + |
1165 | + void initIterators(); |
1166 | + |
1167 | + int retrieveRow(unsigned char *buf); |
1168 | + |
1169 | + int findRow(Field *key_field, |
1170 | + unsigned char *buf, |
1171 | + const unsigned char *key, |
1172 | + size_t key_len); |
1173 | + |
1174 | +private: |
1175 | + |
1176 | + /** |
1177 | + * Store a variable sized row in Tokyo Cabinet. |
1178 | + */ |
1179 | + size_t packRow(unsigned char *buf, unsigned char *row); |
1180 | + |
1181 | + /** |
1182 | + * Retrieve a variable sized row from Tokyo Cabinet. |
1183 | + */ |
1184 | + void unpackRow(unsigned char *buf, const char *row); |
1185 | + |
1186 | + uint32_t use_count; |
1187 | + THR_LOCK lock; |
1188 | + std::string name; |
1189 | + TCMDB *data_handler; |
1190 | + bool fixed_length_table; |
1191 | + uint32_t row_len; |
1192 | + Field **fields; |
1193 | + size_t null_bytes; |
1194 | + unsigned char *table_record; |
1195 | + |
1196 | + char primary_key_buff[MAX_KEY_LEN]; |
1197 | + char *primary_key; |
1198 | + size_t primary_key_len; |
1199 | + |
1200 | +}; |
1201 | + |
1202 | +#endif /* DRIZZLE_PLUGIN_TOKYO_CABINET_SHARE_H */ |
1203 | |
1204 | === added directory 'tests/suite/tc_engine' |
1205 | === added directory 'tests/suite/tc_engine/r' |
1206 | === added file 'tests/suite/tc_engine/r/auto_increment.result' |
1207 | --- tests/suite/tc_engine/r/auto_increment.result 1970-01-01 00:00:00 +0000 |
1208 | +++ tests/suite/tc_engine/r/auto_increment.result 2009-09-24 03:50:24 +0000 |
1209 | @@ -0,0 +1,32 @@ |
1210 | +DROP TABLE IF EXISTS t2; |
1211 | +Warnings: |
1212 | +Note 1051 Unknown table 't2' |
1213 | +CREATE TABLE t2 (a int primary key auto_increment, b bigint) ENGINE=TOKYO; |
1214 | +insert into t2 (b) values (42),(74),(108),(256); |
1215 | +SELECT * from t2 ORDER BY a; |
1216 | +a b |
1217 | +1 42 |
1218 | +2 74 |
1219 | +3 108 |
1220 | +4 256 |
1221 | +SELECT COUNT(*) from t2; |
1222 | +COUNT(*) |
1223 | +4 |
1224 | +EXPLAIN SELECT * FROM t2 WHERE a=1; |
1225 | +id select_type table type possible_keys key key_len ref rows Extra |
1226 | +1 SIMPLE t2 const PRIMARY PRIMARY 4 const 1 |
1227 | +SELECT * FROM t2 WHERE a=1; |
1228 | +a b |
1229 | +1 42 |
1230 | +SELECT * FROM t2 WHERE a=2; |
1231 | +a b |
1232 | +2 74 |
1233 | +SELECT * FROM t2 WHERE a=3; |
1234 | +a b |
1235 | +3 108 |
1236 | +SELECT * FROM t2 WHERE a=4; |
1237 | +a b |
1238 | +4 256 |
1239 | +SELECT * FROM t2 WHERE a=5; |
1240 | +a b |
1241 | +DROP TABLE t2; |
1242 | |
1243 | === added file 'tests/suite/tc_engine/r/basic.result' |
1244 | --- tests/suite/tc_engine/r/basic.result 1970-01-01 00:00:00 +0000 |
1245 | +++ tests/suite/tc_engine/r/basic.result 2009-09-24 03:50:24 +0000 |
1246 | @@ -0,0 +1,138 @@ |
1247 | +DROP TABLE IF EXISTS t1; |
1248 | +Warnings: |
1249 | +Note 1051 Unknown table 't1' |
1250 | +CREATE TABLE t1 (a int primary key, b varchar(200)) ENGINE=TOKYO; |
1251 | +INSERT INTO t1 (a,b) VALUES (1, 'FOO'); |
1252 | +INSERT INTO t1 (a,b) VALUES (2, 'BAR'); |
1253 | +INSERT INTO t1 (a,b) VALUES (3, 'LCA ROCKS'); |
1254 | +INSERT INTO t1 (a,b) VALUES (4, 'freeze ray'); |
1255 | +INSERT INTO t1 (a,b) VALUES (5, 'this row appears because of the kind donations of....'); |
1256 | +SELECT COUNT(*) FROM t1; |
1257 | +COUNT(*) |
1258 | +5 |
1259 | +SELECT * from t1; |
1260 | +a b |
1261 | +4 freeze ray |
1262 | +5 this row appears because of the kind donations of.... |
1263 | +1 FOO |
1264 | +2 BAR |
1265 | +3 LCA ROCKS |
1266 | +DROP TABLE t1; |
1267 | +CREATE TABLE t2 (a int primary key,b bigint) ENGINE=TOKYO; |
1268 | +insert into t2 (a,b) values (1,42),(2,74),(3,108),(4,256); |
1269 | +SELECT COUNT(*) FROM t2; |
1270 | +COUNT(*) |
1271 | +4 |
1272 | +SELECT * from t2; |
1273 | +a b |
1274 | +4 256 |
1275 | +1 42 |
1276 | +2 74 |
1277 | +3 108 |
1278 | +SELECT * FROM t2 WHERE a > 2; |
1279 | +a b |
1280 | +4 256 |
1281 | +3 108 |
1282 | +SELECT * FROM t2 WHERE a > 4; |
1283 | +a b |
1284 | +DROP TABLE t2; |
1285 | +CREATE TABLE t3 (a int primary key, b int unique) ENGINE=TOKYO; |
1286 | +ERROR 42000: Too many keys specified; max 1 keys allowed |
1287 | +CREATE TABLE t4 (a int, b int, PRIMARY KEY (a,b)) ENGINE=TOKYO; |
1288 | +ERROR 42000: Too many key parts specified; max 1 parts allowed |
1289 | +CREATE TABLE t5 (a int, index(a)) ENGINE=TOKYO; |
1290 | +ERROR 42000: Table handler doesn't support NULL in given index. Please change column 'a' to be NOT NULL or use another handler |
1291 | +drop table if exists t1,t2; |
1292 | +create table t1 (id int primary key, num int) engine=tokyo; |
1293 | +insert into t1 values (1, 100); |
1294 | +insert into t1 values (2, 101); |
1295 | +insert into t1 values (3, 102); |
1296 | +insert into t1 values (4, 103); |
1297 | +insert into t1 values (5, 104); |
1298 | +select * from t1; |
1299 | +id num |
1300 | +1 100 |
1301 | +2 101 |
1302 | +3 102 |
1303 | +4 103 |
1304 | +5 104 |
1305 | +select count(*) from t1; |
1306 | +count(*) |
1307 | +5 |
1308 | +select * from t1 where id = 1; |
1309 | +id num |
1310 | +1 100 |
1311 | +select * from t1 where id = 2; |
1312 | +id num |
1313 | +2 101 |
1314 | +select * from t1 where id = 3; |
1315 | +id num |
1316 | +3 102 |
1317 | +select * from t1 where id = 4; |
1318 | +id num |
1319 | +4 103 |
1320 | +select * from t1 where id = 5; |
1321 | +id num |
1322 | +5 104 |
1323 | +update t1 set num = 1111 where id = 1; |
1324 | +update t1 set num = 2222 where id = 2; |
1325 | +update t1 set num = 3333 where id = 3; |
1326 | +select * from t1 where id < 4; |
1327 | +id num |
1328 | +1 1111 |
1329 | +2 2222 |
1330 | +3 3333 |
1331 | +delete from t1 where id = 1; |
1332 | +delete from t1 where id = 2; |
1333 | +delete from t1 where id = 3; |
1334 | +delete from t1; |
1335 | +drop table t1; |
1336 | +create table t2 (id int primary key, b blob) engine=tokyo; |
1337 | +insert into t2 values (1, "aaa"); |
1338 | +insert into t2 values (2, "bbb"); |
1339 | +insert into t2 values (3, "aaaaaa"); |
1340 | +insert into t2 values (4, "bbbbbb"); |
1341 | +select * from t2; |
1342 | +id b |
1343 | +1 aaa |
1344 | +2 bbb |
1345 | +3 aaaaaa |
1346 | +4 bbbbbb |
1347 | +update t2 set b = NULL where id = 1; |
1348 | +update t2 set b = "updated" where id = 2; |
1349 | +update t2 set b = NULL where id = 3; |
1350 | +update t2 set b = "updated" where id = 4; |
1351 | +select * from t2; |
1352 | +id b |
1353 | +1 NULL |
1354 | +2 updated |
1355 | +3 NULL |
1356 | +4 updated |
1357 | +drop table t2; |
1358 | +create table t1(id int primary key, num1 int, num2 int) engine=tokyo; |
1359 | +create table t2 like t1; |
1360 | +insert into t2 values (1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5), (6,6,6); |
1361 | +insert into t2 values (7,7,7), (8,8,8), (9,9,9), (10,10,10), (11,11,11); |
1362 | +insert into t1 select * from t2; |
1363 | +select * from t1; |
1364 | +id num1 num2 |
1365 | +8 8 8 |
1366 | +1 1 1 |
1367 | +9 9 9 |
1368 | +10 10 10 |
1369 | +2 2 2 |
1370 | +11 11 11 |
1371 | +3 3 3 |
1372 | +4 4 4 |
1373 | +5 5 5 |
1374 | +6 6 6 |
1375 | +7 7 7 |
1376 | +delete from t1; |
1377 | +insert into t1 select * from t2 where id < 5; |
1378 | +select * from t1; |
1379 | +id num1 num2 |
1380 | +1 1 1 |
1381 | +2 2 2 |
1382 | +3 3 3 |
1383 | +4 4 4 |
1384 | +drop table t1, t2; |
1385 | |
1386 | === added directory 'tests/suite/tc_engine/t' |
1387 | === added file 'tests/suite/tc_engine/t/auto_increment.test' |
1388 | --- tests/suite/tc_engine/t/auto_increment.test 1970-01-01 00:00:00 +0000 |
1389 | +++ tests/suite/tc_engine/t/auto_increment.test 2009-09-24 03:50:24 +0000 |
1390 | @@ -0,0 +1,13 @@ |
1391 | +DROP TABLE IF EXISTS t2; |
1392 | +CREATE TABLE t2 (a int primary key auto_increment, b bigint) ENGINE=TOKYO; |
1393 | +insert into t2 (b) values (42),(74),(108),(256); |
1394 | +SELECT * from t2 ORDER BY a; |
1395 | +SELECT COUNT(*) from t2; |
1396 | +EXPLAIN SELECT * FROM t2 WHERE a=1; |
1397 | +SELECT * FROM t2 WHERE a=1; |
1398 | +SELECT * FROM t2 WHERE a=2; |
1399 | +SELECT * FROM t2 WHERE a=3; |
1400 | +SELECT * FROM t2 WHERE a=4; |
1401 | +SELECT * FROM t2 WHERE a=5; |
1402 | +DROP TABLE t2; |
1403 | + |
1404 | |
1405 | === added file 'tests/suite/tc_engine/t/basic.test' |
1406 | --- tests/suite/tc_engine/t/basic.test 1970-01-01 00:00:00 +0000 |
1407 | +++ tests/suite/tc_engine/t/basic.test 2009-09-24 03:50:24 +0000 |
1408 | @@ -0,0 +1,107 @@ |
1409 | +--disable-warnings |
1410 | +DROP TABLE IF EXISTS t1; |
1411 | +--enable-warnings |
1412 | + |
1413 | +CREATE TABLE t1 (a int primary key, b varchar(200)) ENGINE=TOKYO; |
1414 | + |
1415 | +INSERT INTO t1 (a,b) VALUES (1, 'FOO'); |
1416 | +INSERT INTO t1 (a,b) VALUES (2, 'BAR'); |
1417 | +INSERT INTO t1 (a,b) VALUES (3, 'LCA ROCKS'); |
1418 | +INSERT INTO t1 (a,b) VALUES (4, 'freeze ray'); |
1419 | +INSERT INTO t1 (a,b) VALUES (5, 'this row appears because of the kind donations of....'); |
1420 | +SELECT COUNT(*) FROM t1; |
1421 | +SELECT * from t1; |
1422 | + |
1423 | +DROP TABLE t1; |
1424 | + |
1425 | +CREATE TABLE t2 (a int primary key,b bigint) ENGINE=TOKYO; |
1426 | +insert into t2 (a,b) values (1,42),(2,74),(3,108),(4,256); |
1427 | +SELECT COUNT(*) FROM t2; |
1428 | +SELECT * from t2; |
1429 | +SELECT * FROM t2 WHERE a > 2; |
1430 | +SELECT * FROM t2 WHERE a > 4; |
1431 | +DROP TABLE t2; |
1432 | + |
1433 | +--error ER_TOO_MANY_KEYS |
1434 | +CREATE TABLE t3 (a int primary key, b int unique) ENGINE=TOKYO; |
1435 | + |
1436 | +--error ER_TOO_MANY_KEY_PARTS |
1437 | +CREATE TABLE t4 (a int, b int, PRIMARY KEY (a,b)) ENGINE=TOKYO; |
1438 | + |
1439 | +--error ER_NULL_COLUMN_IN_INDEX |
1440 | +CREATE TABLE t5 (a int, index(a)) ENGINE=TOKYO; |
1441 | + |
1442 | +--disable_warnings |
1443 | +drop table if exists t1,t2; |
1444 | +--enable_warnings |
1445 | + |
1446 | +## Easy warm up test |
1447 | +create table t1 (id int primary key, num int) engine=tokyo; |
1448 | + |
1449 | +insert into t1 values (1, 100); |
1450 | +insert into t1 values (2, 101); |
1451 | +insert into t1 values (3, 102); |
1452 | +insert into t1 values (4, 103); |
1453 | +insert into t1 values (5, 104); |
1454 | + |
1455 | +select * from t1; |
1456 | +select count(*) from t1; |
1457 | + |
1458 | +# Test Primary Key |
1459 | +select * from t1 where id = 1; |
1460 | +select * from t1 where id = 2; |
1461 | +select * from t1 where id = 3; |
1462 | +select * from t1 where id = 4; |
1463 | +select * from t1 where id = 5; |
1464 | + |
1465 | +# Update rows based on Primary Key |
1466 | +update t1 set num = 1111 where id = 1; |
1467 | +update t1 set num = 2222 where id = 2; |
1468 | +update t1 set num = 3333 where id = 3; |
1469 | + |
1470 | +select * from t1 where id < 4; |
1471 | + |
1472 | +# Delete rows based on Primary Key |
1473 | +delete from t1 where id = 1; |
1474 | +delete from t1 where id = 2; |
1475 | +delete from t1 where id = 3; |
1476 | + |
1477 | +# Delete remaining rows |
1478 | +delete from t1; |
1479 | + |
1480 | +drop table t1; |
1481 | + |
1482 | +# Test BLOB type |
1483 | +create table t2 (id int primary key, b blob) engine=tokyo; |
1484 | + |
1485 | +insert into t2 values (1, "aaa"); |
1486 | +insert into t2 values (2, "bbb"); |
1487 | +insert into t2 values (3, "aaaaaa"); |
1488 | +insert into t2 values (4, "bbbbbb"); |
1489 | + |
1490 | +select * from t2; |
1491 | + |
1492 | +update t2 set b = NULL where id = 1; |
1493 | +update t2 set b = "updated" where id = 2; |
1494 | +update t2 set b = NULL where id = 3; |
1495 | +update t2 set b = "updated" where id = 4; |
1496 | + |
1497 | +select * from t2; |
1498 | + |
1499 | +drop table t2; |
1500 | + |
1501 | +# Test INSERT-SELECT statements |
1502 | +create table t1(id int primary key, num1 int, num2 int) engine=tokyo; |
1503 | +create table t2 like t1; |
1504 | + |
1505 | +insert into t2 values (1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5), (6,6,6); |
1506 | +insert into t2 values (7,7,7), (8,8,8), (9,9,9), (10,10,10), (11,11,11); |
1507 | + |
1508 | +insert into t1 select * from t2; |
1509 | +select * from t1; |
1510 | +delete from t1; |
1511 | + |
1512 | +insert into t1 select * from t2 where id < 5; |
1513 | +select * from t1; |
1514 | + |
1515 | +drop table t1, t2; |
This merge proposal consists of a simple in-memory storage engine that uses the Tokyo Cabinet in-memory hash API. It also includes a very lacking test suite with 2 small test files for the storage engine. Since this proposal is a little bit out of nowhere and you are probably wondering why the heck I did this, let me explain why I did it...
I'm taking a distributed systems class this semester for fun which will involve a project. I've managed to get a project involving Drizzle approved. What I plan on doing is investigating how to use cloud storage services (such as S3) as the storage backend for a SQL engine (which will be drizzle) and how to implement various consistency protocols over an eventually consistent data store such as S3. Since S3 is basically a key/value store (as described in the Dynamo paper), I wanted to get some practice creating a storage engine using a key/value store interface. Thus, I found Brian's posting on a Tokyo Cabinet based storage engine from a while back and went with that. I ported it to Drizzle and modified it to use the in-memory API calls from Tokyo Cabinet for the heck of it. This will help me in getting my basic S3 storage engine working in the next few weeks as I now have a good idea of how to create a storage engine using a key/value store interface.
I wasn't sure what to do with this engine, so I figured I'd propose it for merging. I also remember Brian's post about a new memory engine so I thought this might make a good start. I'm open to giving this over to someone. I was also under the impression this doesn't really conflict with BlitzDB. From what I understand about BlitzDB, its aimed at being a more general purpose storage engine but then again, maybe I should give this to Toru and he can do what he likes with it.
Anyway, any comments are more than welcome. If no-one is interested in this, or it doesn't prove very useful, well then this proposal can be ignored :) It was good practice for working with a key/value store for me! Alternatively, if there is interest, I can work on it more in my spare time to make it a better in-memory engine if that is desirable.
-Padraig