16 #include "heap_priv.h"
17 #include <drizzled/error.h>
18 #include <drizzled/table.h>
19 #include <drizzled/session.h>
20 #include <drizzled/field/varstring.h>
21 #include <drizzled/plugin/daemon.h>
22 #include <drizzled/plugin/storage_engine.h>
23 #include <drizzled/util/test.h>
24 #include <drizzled/session/table_messages.h>
25 #include <drizzled/statistics_variables.h>
26 #include <drizzled/system_variables.h>
28 #include <boost/thread/mutex.hpp>
35 using namespace drizzled;
38 static const string engine_name(
"MEMORY");
40 boost::mutex THR_LOCK_heap;
42 static const char *ha_heap_exts[] = {
50 plugin::StorageEngine(name_arg,
51 HTON_STATS_RECORDS_IS_EXACT |
56 HTON_SKIP_STORE_LOCK |
63 hp_panic(HA_PANIC_CLOSE);
68 return new ha_heap(*
this, table);
71 const char **bas_ext()
const
76 drizzled::message::Table::Index::IndexType default_index_type()
const
78 return drizzled::message::Table::Index::HASH;
81 int doCreateTable(
Session &session,
91 int heap_create_table(
Session *session,
const char *table_name,
101 int doGetTableDefinition(
Session& session,
105 uint32_t max_supported_keys()
const {
return MAX_KEY; }
106 uint32_t max_supported_key_part_length()
const {
return MAX_KEY_LENGTH; }
108 uint32_t index_flags(
enum ha_key_alg )
const
110 return ( HA_ONLY_WHOLE_INDEX | HA_KEY_SCAN_NOT_ROR);
116 identifier::table::vector &set_of_identifiers);
121 identifier::table::vector&)
127 return session.getMessageCache().doesTableMessageExist(identifier);
130 int HeapEngine::doGetTableDefinition(
Session &session,
134 if (session.getMessageCache().getTableMessage(identifier, table_proto))
145 session.getMessageCache().removeTableMessage(identifier);
147 int error= heap_delete_table(identifier.getPath().c_str());
159 heap_storage_engine=
new HeapEngine(engine_name);
160 context.add(heap_storage_engine);
169 ha_heap::ha_heap(plugin::StorageEngine &engine_arg,
171 :
Cursor(engine_arg, table_arg), file(0), records_changed(0), key_stat_version(0),
186 #define MEMORY_STATS_UPDATE_THRESHOLD 10
190 if ((test_if_locked & HA_OPEN_INTERNAL_TABLE) || (!(file= heap_open(identifier.getPath().c_str(), mode)) && errno == ENOENT))
192 internal_table= test(test_if_locked & HA_OPEN_INTERNAL_TABLE);
197 if (not heap_storage_engine->heap_create_table(getTable()->in_use,
198 identifier.getPath().c_str(),
204 file= internal_table ?
205 heap_open_from_share(internal_share, mode) :
206 heap_open_from_share_and_register(internal_share, mode);
210 THR_LOCK_heap.lock();
211 hp_free(internal_share);
212 THR_LOCK_heap.unlock();
220 set_keys_for_scanning();
229 key_stat_version= file->getShare()->key_stat_version - 1;
234 int ha_heap::close(
void)
236 return internal_table ? hp_close(file) : heap_close(file);
252 Cursor *new_handler= getTable()->getMutableShare()->db_type()->getCursor(*getTable());
254 getTable()->getShare()->getTableName(),
255 getTable()->getShare()->getPath());
257 if (new_handler && !new_handler->
ha_open(identifier, getTable()->db_stat,
258 HA_OPEN_IGNORE_IF_LOCKED))
264 const char *ha_heap::index_type(uint32_t )
286 void ha_heap::set_keys_for_scanning(
void)
291 void ha_heap::update_key_stats()
293 for (uint32_t i= 0; i < getTable()->getShare()->sizeKeys(); i++)
297 if (!key->rec_per_key)
301 if (key->flags & HA_NOSAME)
302 key->rec_per_key[key->key_parts-1]= 1;
305 ha_rows hash_buckets= file->getShare()->keydef[i].hash_buckets;
306 uint32_t no_records= hash_buckets ? (uint) (file->getShare()->records/hash_buckets) : 2;
309 key->rec_per_key[key->key_parts-1]= no_records;
315 key_stat_version= file->getShare()->key_stat_version;
319 int ha_heap::doInsertRecord(
unsigned char * buf)
322 if (getTable()->next_number_field && buf == getTable()->getInsertRecord())
324 if ((res= update_auto_increment()))
327 res= heap_write(file,buf);
328 if (!res && (++records_changed*MEMORY_STATS_UPDATE_THRESHOLD >
329 file->getShare()->records))
335 file->getShare()->key_stat_version++;
340 int ha_heap::doUpdateRecord(
const unsigned char * old_data,
unsigned char * new_data)
344 res= heap_update(file,old_data,new_data);
345 if (!res && ++records_changed*MEMORY_STATS_UPDATE_THRESHOLD >
346 file->getShare()->records)
352 file->getShare()->key_stat_version++;
357 int ha_heap::doDeleteRecord(
const unsigned char * buf)
361 res= heap_delete(file,buf);
362 if (!res && getTable()->getShare()->getType() == message::Table::STANDARD &&
363 ++records_changed*MEMORY_STATS_UPDATE_THRESHOLD > file->getShare()->records)
369 file->getShare()->key_stat_version++;
375 key_part_map keypart_map,
376 enum ha_rkey_function find_flag)
378 assert(inited==INDEX);
379 ha_statistic_increment(&system_status_var::ha_read_key_count);
380 int error = heap_rkey(file,buf,active_index, key, keypart_map, find_flag);
381 getTable()->status = error ? STATUS_NOT_FOUND : 0;
386 key_part_map keypart_map)
388 assert(inited==INDEX);
389 ha_statistic_increment(&system_status_var::ha_read_key_count);
390 int error= heap_rkey(file, buf, active_index, key, keypart_map,
391 HA_READ_PREFIX_LAST);
392 getTable()->status= error ? STATUS_NOT_FOUND : 0;
397 key_part_map keypart_map,
398 enum ha_rkey_function find_flag)
400 ha_statistic_increment(&system_status_var::ha_read_key_count);
401 int error = heap_rkey(file, buf, index, key, keypart_map, find_flag);
402 getTable()->status = error ? STATUS_NOT_FOUND : 0;
406 int ha_heap::index_next(
unsigned char * buf)
408 assert(inited==INDEX);
409 ha_statistic_increment(&system_status_var::ha_read_next_count);
410 int error=heap_rnext(file,buf);
411 getTable()->status=error ? STATUS_NOT_FOUND: 0;
415 int ha_heap::index_prev(
unsigned char * buf)
417 assert(inited==INDEX);
418 ha_statistic_increment(&system_status_var::ha_read_prev_count);
419 int error=heap_rprev(file,buf);
420 getTable()->status=error ? STATUS_NOT_FOUND: 0;
424 int ha_heap::index_first(
unsigned char * buf)
426 assert(inited==INDEX);
427 ha_statistic_increment(&system_status_var::ha_read_first_count);
428 int error=heap_rfirst(file, buf, active_index);
429 getTable()->status=error ? STATUS_NOT_FOUND: 0;
433 int ha_heap::index_last(
unsigned char * buf)
435 assert(inited==INDEX);
436 ha_statistic_increment(&system_status_var::ha_read_last_count);
437 int error=heap_rlast(file, buf, active_index);
438 getTable()->status=error ? STATUS_NOT_FOUND: 0;
444 return scan ? heap_scan_init(file) : 0;
447 int ha_heap::rnd_next(
unsigned char *buf)
449 ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
450 int error=heap_scan(file, buf);
451 getTable()->status=error ? STATUS_NOT_FOUND: 0;
455 int ha_heap::rnd_pos(
unsigned char * buf,
unsigned char *pos)
458 HEAP_PTR heap_position;
459 ha_statistic_increment(&system_status_var::ha_read_rnd_count);
460 memcpy(&heap_position, pos,
sizeof(HEAP_PTR));
461 error=heap_rrnd(file, buf, heap_position);
462 getTable()->status=error ? STATUS_NOT_FOUND: 0;
466 void ha_heap::position(
const unsigned char *)
468 *(HEAP_PTR*) ref= heap_position(file);
471 int ha_heap::info(uint32_t flag)
474 (void) heap_info(file,&hp_info,flag);
476 errkey= hp_info.errkey;
477 stats.records= hp_info.records;
478 stats.deleted= hp_info.deleted;
479 stats.mean_rec_length= hp_info.reclength;
480 stats.data_file_length= hp_info.data_length;
481 stats.index_file_length= hp_info.index_length;
482 stats.max_data_file_length= hp_info.max_records * hp_info.reclength;
483 stats.delete_length= hp_info.deleted * hp_info.reclength;
484 if (flag & HA_STATUS_AUTO)
485 stats.auto_increment_value= hp_info.auto_increment;
491 if (key_stat_version != file->getShare()->key_stat_version)
496 int ha_heap::extra(
enum ha_extra_function operation)
498 return heap_extra(file,operation);
504 return heap_reset(file);
511 if (getTable()->getShare()->getType() == message::Table::STANDARD)
517 file->getShare()->key_stat_version++;
546 int ha_heap::disable_indexes(uint32_t mode)
550 if (mode == HA_KEY_SWITCH_ALL)
552 if (!(error= heap_disable_indexes(file)))
553 set_keys_for_scanning();
558 error= HA_ERR_WRONG_COMMAND;
593 int ha_heap::enable_indexes(uint32_t mode)
597 if (mode == HA_KEY_SWITCH_ALL)
599 if (!(error= heap_enable_indexes(file)))
600 set_keys_for_scanning();
605 error= HA_ERR_WRONG_COMMAND;
624 int ha_heap::indexes_are_disabled()
626 return heap_indexes_are_disabled(file);
629 void ha_heap::drop_table()
631 file->getShare()->delete_on_close= 1;
638 session.getMessageCache().renameTableMessage(from, to);
639 return heap_rename(from.getPath().c_str(), to.getPath().c_str());
643 ha_rows ha_heap::records_in_range(uint32_t inx,
key_range *min_key,
648 if (!min_key || !max_key ||
649 min_key->length != max_key->length ||
650 min_key->length != key->key_length ||
651 min_key->flag != HA_READ_KEY_EXACT ||
652 max_key->flag != HA_READ_AFTER_KEY)
655 if (stats.records <= 1)
656 return stats.records;
659 assert(key_stat_version == file->getShare()->key_stat_version);
660 return key->rec_per_key[key->key_parts-1];
663 int HeapEngine::doCreateTable(
Session &session,
670 const char *table_name= identifier.getPath().c_str();
672 error= heap_create_table(&session, table_name, &table_arg,
679 session.getMessageCache().storeTableMessage(identifier, create_proto);
686 int HeapEngine::heap_create_table(
Session *session,
const char *table_name,
692 uint32_t key, parts, mem_per_row_keys= 0;
693 uint32_t keys= table_arg->getShare()->sizeKeys();
694 uint32_t auto_key= 0, auto_key_type= 0;
695 uint32_t max_key_fieldnr = 0, key_part_size = 0, next_field_pos = 0;
696 uint32_t column_count= table_arg->getShare()->sizeFields();
697 std::vector<HP_KEYDEF> keydef;
699 bool found_real_auto_increment= 0;
707 uint64_t num_rows= table_arg->getShare()->getMaxRows();
708 if (num_rows > UINT32_MAX)
711 for (key= parts= 0; key < keys; key++)
712 parts+= table_arg->
key_info[key].key_parts;
715 std::vector<HA_KEYSEG> seg_buffer;
716 seg_buffer.resize(parts);
719 for (key= 0; key < keys; key++)
723 KeyPartInfo *key_part_end= key_part + pos->key_parts;
725 keydef[key].keysegs= (uint) pos->key_parts;
726 keydef[key].flag= (pos->flags & (HA_NOSAME | HA_NULL_ARE_EQUAL));
727 keydef[key].seg= seg;
729 mem_per_row_keys+=
sizeof(
char*) * 2;
731 for (; key_part != key_part_end; key_part++, seg++)
733 Field *field= key_part->field;
736 if ((seg->type = field->key_type()) != (
int) HA_KEYTYPE_TEXT &&
737 seg->type != HA_KEYTYPE_VARTEXT1 &&
738 seg->type != HA_KEYTYPE_VARTEXT2 &&
739 seg->type != HA_KEYTYPE_VARBINARY1 &&
740 seg->type != HA_KEYTYPE_VARBINARY2)
741 seg->type= HA_KEYTYPE_BINARY;
743 seg->start= (uint) key_part->offset;
744 seg->length= (uint) key_part->length;
745 seg->flag= key_part->key_part_flag;
747 next_field_pos= seg->start + seg->length;
748 if (field->type() == DRIZZLE_TYPE_VARCHAR)
750 next_field_pos+= (uint8_t)(((
Field_varstring*)field)->pack_length_no_ptr());
753 if (next_field_pos > key_part_size) {
754 key_part_size= next_field_pos;
757 if (field->flags & ENUM_FLAG)
758 seg->charset= &my_charset_bin;
760 seg->charset= field->charset();
764 seg->null_pos= (uint) (field->
null_ptr - (
unsigned char*) table_arg->getInsertRecord());
771 if (field->flags & AUTO_INCREMENT_FLAG &&
773 key == table_arg->getShare()->next_number_index)
780 auto_key_type= field->key_type();
782 if ((uint)field->position() + 1 > max_key_fieldnr)
785 max_key_fieldnr= field->position() + 1;
790 if (key_part_size < table_arg->getShare()->null_bytes + ((table_arg->getShare()->last_null_bit_pos+7) >> 3))
793 key_part_size = table_arg->getShare()->null_bytes + ((table_arg->getShare()->last_null_bit_pos+7) >> 3);
800 keydef[table_arg->getShare()->next_number_index].flag|= HA_AUTO_KEY;
801 found_real_auto_increment= table_arg->getShare()->next_number_key_offset == 0;
804 hp_create_info.auto_key= auto_key;
805 hp_create_info.auto_key_type= auto_key_type;
806 hp_create_info.auto_increment= (create_proto.options().has_auto_increment_value() ?
807 create_proto.options().auto_increment_value() - 1 : 0);
808 hp_create_info.max_table_size=session->
variables.max_heap_table_size;
809 hp_create_info.with_auto_increment= found_real_auto_increment;
810 hp_create_info.internal_table= internal_table;
811 hp_create_info.max_chunk_size= table_arg->getShare()->block_size;
813 error= heap_create(table_name,
817 table_arg->getShare()->getRecordLength(), mem_per_row_keys,
818 static_cast<uint32_t
>(num_rows),
820 &hp_create_info, internal_share);
826 void ha_heap::get_auto_increment(uint64_t, uint64_t, uint64_t,
827 uint64_t *first_value,
828 uint64_t *nb_reserved_values)
830 ha_heap::info(HA_STATUS_AUTO);
831 *first_value= stats.auto_increment_value;
833 *nb_reserved_values= UINT64_MAX;
837 int ha_heap::cmp_ref(
const unsigned char *ref1,
const unsigned char *ref2)
839 return memcmp(ref1, ref2,
sizeof(HEAP_PTR));
843 DRIZZLE_DECLARE_PLUGIN
849 N_(
"MEMORY storage engine"),
855 DRIZZLE_DECLARE_PLUGIN_END;