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());
255 if (new_handler && !new_handler->
ha_open(identifier, getTable()->db_stat,
256 HA_OPEN_IGNORE_IF_LOCKED))
262 const char *ha_heap::index_type(uint32_t )
284 void ha_heap::set_keys_for_scanning(
void)
289 void ha_heap::update_key_stats()
291 for (uint32_t i= 0; i < getTable()->getShare()->sizeKeys(); i++)
295 if (!key->rec_per_key)
299 if (key->flags & HA_NOSAME)
300 key->rec_per_key[key->key_parts-1]= 1;
303 ha_rows hash_buckets= file->getShare()->keydef[i].hash_buckets;
304 uint32_t no_records= hash_buckets ? (uint) (file->getShare()->records/hash_buckets) : 2;
307 key->rec_per_key[key->key_parts-1]= no_records;
313 key_stat_version= file->getShare()->key_stat_version;
317 int ha_heap::doInsertRecord(
unsigned char * buf)
320 if (getTable()->next_number_field && buf == getTable()->getInsertRecord())
322 if ((res= update_auto_increment()))
325 res= heap_write(file,buf);
326 if (!res && (++records_changed*MEMORY_STATS_UPDATE_THRESHOLD >
327 file->getShare()->records))
333 file->getShare()->key_stat_version++;
338 int ha_heap::doUpdateRecord(
const unsigned char * old_data,
unsigned char * new_data)
342 res= heap_update(file,old_data,new_data);
343 if (!res && ++records_changed*MEMORY_STATS_UPDATE_THRESHOLD >
344 file->getShare()->records)
350 file->getShare()->key_stat_version++;
355 int ha_heap::doDeleteRecord(
const unsigned char * buf)
359 res= heap_delete(file,buf);
360 if (!res && getTable()->getShare()->getType() == message::Table::STANDARD &&
361 ++records_changed*MEMORY_STATS_UPDATE_THRESHOLD > file->getShare()->records)
367 file->getShare()->key_stat_version++;
373 key_part_map keypart_map,
374 enum ha_rkey_function find_flag)
376 assert(inited==INDEX);
377 ha_statistic_increment(&system_status_var::ha_read_key_count);
378 int error = heap_rkey(file,buf,active_index, key, keypart_map, find_flag);
379 getTable()->status = error ? STATUS_NOT_FOUND : 0;
384 key_part_map keypart_map)
386 assert(inited==INDEX);
387 ha_statistic_increment(&system_status_var::ha_read_key_count);
388 int error= heap_rkey(file, buf, active_index, key, keypart_map,
389 HA_READ_PREFIX_LAST);
390 getTable()->status= error ? STATUS_NOT_FOUND : 0;
395 key_part_map keypart_map,
396 enum ha_rkey_function find_flag)
398 ha_statistic_increment(&system_status_var::ha_read_key_count);
399 int error = heap_rkey(file, buf, index, key, keypart_map, find_flag);
400 getTable()->status = error ? STATUS_NOT_FOUND : 0;
404 int ha_heap::index_next(
unsigned char * buf)
406 assert(inited==INDEX);
407 ha_statistic_increment(&system_status_var::ha_read_next_count);
408 int error=heap_rnext(file,buf);
409 getTable()->status=error ? STATUS_NOT_FOUND: 0;
413 int ha_heap::index_prev(
unsigned char * buf)
415 assert(inited==INDEX);
416 ha_statistic_increment(&system_status_var::ha_read_prev_count);
417 int error=heap_rprev(file,buf);
418 getTable()->status=error ? STATUS_NOT_FOUND: 0;
422 int ha_heap::index_first(
unsigned char * buf)
424 assert(inited==INDEX);
425 ha_statistic_increment(&system_status_var::ha_read_first_count);
426 int error=heap_rfirst(file, buf, active_index);
427 getTable()->status=error ? STATUS_NOT_FOUND: 0;
431 int ha_heap::index_last(
unsigned char * buf)
433 assert(inited==INDEX);
434 ha_statistic_increment(&system_status_var::ha_read_last_count);
435 int error=heap_rlast(file, buf, active_index);
436 getTable()->status=error ? STATUS_NOT_FOUND: 0;
442 return scan ? heap_scan_init(file) : 0;
445 int ha_heap::rnd_next(
unsigned char *buf)
447 ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
448 int error=heap_scan(file, buf);
449 getTable()->status=error ? STATUS_NOT_FOUND: 0;
453 int ha_heap::rnd_pos(
unsigned char * buf,
unsigned char *pos)
456 HEAP_PTR heap_position;
457 ha_statistic_increment(&system_status_var::ha_read_rnd_count);
458 memcpy(&heap_position, pos,
sizeof(HEAP_PTR));
459 error=heap_rrnd(file, buf, heap_position);
460 getTable()->status=error ? STATUS_NOT_FOUND: 0;
464 void ha_heap::position(
const unsigned char *)
466 *(HEAP_PTR*) ref= heap_position(file);
469 int ha_heap::info(uint32_t flag)
472 (void) heap_info(file,&hp_info,flag);
474 errkey= hp_info.errkey;
475 stats.records= hp_info.records;
476 stats.deleted= hp_info.deleted;
477 stats.mean_rec_length= hp_info.reclength;
478 stats.data_file_length= hp_info.data_length;
479 stats.index_file_length= hp_info.index_length;
480 stats.max_data_file_length= hp_info.max_records * hp_info.reclength;
481 stats.delete_length= hp_info.deleted * hp_info.reclength;
482 if (flag & HA_STATUS_AUTO)
483 stats.auto_increment_value= hp_info.auto_increment;
489 if (key_stat_version != file->getShare()->key_stat_version)
494 int ha_heap::extra(
enum ha_extra_function operation)
496 return heap_extra(file,operation);
502 return heap_reset(file);
509 if (getTable()->getShare()->getType() == message::Table::STANDARD)
515 file->getShare()->key_stat_version++;
544 int ha_heap::disable_indexes(uint32_t mode)
548 if (mode == HA_KEY_SWITCH_ALL)
550 if (!(error= heap_disable_indexes(file)))
551 set_keys_for_scanning();
556 error= HA_ERR_WRONG_COMMAND;
591 int ha_heap::enable_indexes(uint32_t mode)
595 if (mode == HA_KEY_SWITCH_ALL)
597 if (!(error= heap_enable_indexes(file)))
598 set_keys_for_scanning();
603 error= HA_ERR_WRONG_COMMAND;
622 int ha_heap::indexes_are_disabled()
624 return heap_indexes_are_disabled(file);
627 void ha_heap::drop_table()
629 file->getShare()->delete_on_close= 1;
636 session.getMessageCache().renameTableMessage(from, to);
637 return heap_rename(from.getPath().c_str(), to.getPath().c_str());
641 ha_rows ha_heap::records_in_range(uint32_t inx,
key_range *min_key,
646 if (!min_key || !max_key ||
647 min_key->length != max_key->length ||
648 min_key->length != key->key_length ||
649 min_key->flag != HA_READ_KEY_EXACT ||
650 max_key->flag != HA_READ_AFTER_KEY)
653 if (stats.records <= 1)
654 return stats.records;
657 assert(key_stat_version == file->getShare()->key_stat_version);
658 return key->rec_per_key[key->key_parts-1];
661 int HeapEngine::doCreateTable(
Session &session,
668 const char *table_name= identifier.getPath().c_str();
670 error= heap_create_table(&session, table_name, &table_arg,
677 session.getMessageCache().storeTableMessage(identifier, create_proto);
684 int HeapEngine::heap_create_table(
Session *session,
const char *table_name,
690 uint32_t key, parts, mem_per_row_keys= 0;
691 uint32_t keys= table_arg->getShare()->sizeKeys();
692 uint32_t auto_key= 0, auto_key_type= 0;
693 uint32_t max_key_fieldnr = 0, key_part_size = 0, next_field_pos = 0;
694 uint32_t column_count= table_arg->getShare()->sizeFields();
695 std::vector<HP_KEYDEF> keydef;
697 bool found_real_auto_increment= 0;
705 uint64_t num_rows= table_arg->getShare()->getMaxRows();
706 if (num_rows > UINT32_MAX)
709 for (key= parts= 0; key < keys; key++)
710 parts+= table_arg->
key_info[key].key_parts;
713 std::vector<HA_KEYSEG> seg_buffer;
714 seg_buffer.resize(parts);
717 for (key= 0; key < keys; key++)
721 KeyPartInfo *key_part_end= key_part + pos->key_parts;
723 keydef[key].keysegs= (uint) pos->key_parts;
724 keydef[key].flag= (pos->flags & (HA_NOSAME | HA_NULL_ARE_EQUAL));
725 keydef[key].seg= seg;
727 mem_per_row_keys+=
sizeof(
char*) * 2;
729 for (; key_part != key_part_end; key_part++, seg++)
731 Field *field= key_part->field;
734 if ((seg->type = field->key_type()) != (
int) HA_KEYTYPE_TEXT &&
735 seg->type != HA_KEYTYPE_VARTEXT1 &&
736 seg->type != HA_KEYTYPE_VARTEXT2 &&
737 seg->type != HA_KEYTYPE_VARBINARY1 &&
738 seg->type != HA_KEYTYPE_VARBINARY2)
739 seg->type= HA_KEYTYPE_BINARY;
741 seg->start= (uint) key_part->offset;
742 seg->length= (uint) key_part->length;
743 seg->flag= key_part->key_part_flag;
745 next_field_pos= seg->start + seg->length;
746 if (field->type() == DRIZZLE_TYPE_VARCHAR)
748 next_field_pos+= (uint8_t)(((
Field_varstring*)field)->pack_length_no_ptr());
751 if (next_field_pos > key_part_size) {
752 key_part_size= next_field_pos;
755 if (field->flags & ENUM_FLAG)
756 seg->charset= &my_charset_bin;
758 seg->charset= field->charset();
762 seg->null_pos= (uint) (field->
null_ptr - (
unsigned char*) table_arg->getInsertRecord());
769 if (field->flags & AUTO_INCREMENT_FLAG &&
771 key == table_arg->getShare()->next_number_index)
778 auto_key_type= field->key_type();
780 if ((uint)field->position() + 1 > max_key_fieldnr)
783 max_key_fieldnr= field->position() + 1;
788 if (key_part_size < table_arg->getShare()->null_bytes + ((table_arg->getShare()->last_null_bit_pos+7) >> 3))
791 key_part_size = table_arg->getShare()->null_bytes + ((table_arg->getShare()->last_null_bit_pos+7) >> 3);
798 keydef[table_arg->getShare()->next_number_index].flag|= HA_AUTO_KEY;
799 found_real_auto_increment= table_arg->getShare()->next_number_key_offset == 0;
802 hp_create_info.auto_key= auto_key;
803 hp_create_info.auto_key_type= auto_key_type;
804 hp_create_info.auto_increment= (create_proto.options().has_auto_increment_value() ?
805 create_proto.options().auto_increment_value() - 1 : 0);
806 hp_create_info.max_table_size=session->
variables.max_heap_table_size;
807 hp_create_info.with_auto_increment= found_real_auto_increment;
808 hp_create_info.internal_table= internal_table;
809 hp_create_info.max_chunk_size= table_arg->getShare()->block_size;
811 error= heap_create(table_name,
815 table_arg->getShare()->getRecordLength(), mem_per_row_keys,
816 static_cast<uint32_t
>(num_rows),
818 &hp_create_info, internal_share);
824 void ha_heap::get_auto_increment(uint64_t, uint64_t, uint64_t,
825 uint64_t *first_value,
826 uint64_t *nb_reserved_values)
828 ha_heap::info(HA_STATUS_AUTO);
829 *first_value= stats.auto_increment_value;
831 *nb_reserved_values= UINT64_MAX;
835 int ha_heap::cmp_ref(
const unsigned char *ref1,
const unsigned char *ref2)
837 return memcmp(ref1, ref2,
sizeof(HEAP_PTR));
841 DRIZZLE_DECLARE_PLUGIN
847 N_(
"MEMORY storage engine"),
853 DRIZZLE_DECLARE_PLUGIN_END;