13
13
along with this program; if not, write to the Free Software
14
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
#include "heap_priv.h"
16
#include <drizzled/server_includes.h>
19
#include <storage/heap/ha_heap.h>
20
#include <storage/heap/heapdef.h>
17
21
#include <drizzled/error.h>
18
22
#include <drizzled/table.h>
19
23
#include <drizzled/session.h>
20
24
#include <drizzled/current_session.h>
21
25
#include <drizzled/field/timestamp.h>
22
26
#include <drizzled/field/varstring.h>
23
#include "drizzled/plugin/daemon.h"
31
using namespace drizzled;
34
static const string engine_name("MEMORY");
36
29
pthread_mutex_t THR_LOCK_heap= PTHREAD_MUTEX_INITIALIZER;
38
static const char *ha_heap_exts[] = {
42
class HeapEngine : public plugin::StorageEngine
45
explicit HeapEngine(string name_arg) :
46
plugin::StorageEngine(name_arg,
47
HTON_STATS_RECORDS_IS_EXACT |
52
HTON_SKIP_STORE_LOCK |
55
pthread_mutex_init(&THR_LOCK_heap, MY_MUTEX_INIT_FAST);
60
hp_panic(HA_PANIC_CLOSE);
62
pthread_mutex_destroy(&THR_LOCK_heap);
65
virtual Cursor *create(TableShare &table,
66
memory::Root *mem_root)
68
return new (mem_root) ha_heap(*this, table);
71
const char **bas_ext() const {
75
int doCreateTable(Session &session,
77
drizzled::TableIdentifier &identifier,
78
message::Table &create_proto);
80
/* For whatever reason, internal tables can be created by Cursor::open()
82
Instead of diving down a rat hole, let's just cry ourselves to sleep
83
at night with this odd hackish workaround.
85
int heap_create_table(Session *session, const char *table_name,
88
message::Table &create_proto,
89
HP_SHARE **internal_share);
91
int doRenameTable(Session&, TableIdentifier &from, TableIdentifier &to);
93
int doDropTable(Session&, TableIdentifier &identifier);
95
int doGetTableDefinition(Session& session,
96
TableIdentifier &identifier,
97
message::Table &table_message);
99
/* Temp only engine, so do not return values. */
100
void doGetTableNames(CachedDirectory &, SchemaIdentifier& , set<string>&) { };
102
uint32_t max_supported_keys() const { return MAX_KEY; }
103
uint32_t max_supported_key_part_length() const { return MAX_KEY_LENGTH; }
105
uint32_t index_flags(enum ha_key_alg algorithm) const
107
return ((algorithm == HA_KEY_ALG_BTREE) ?
112
HA_ONLY_WHOLE_INDEX |
113
HA_KEY_SCAN_NOT_ROR);
116
bool doDoesTableExist(Session& session, TableIdentifier &identifier);
117
void doGetTableIdentifiers(drizzled::CachedDirectory &directory,
118
drizzled::SchemaIdentifier &schema_identifier,
119
drizzled::TableIdentifiers &set_of_identifiers);
122
void HeapEngine::doGetTableIdentifiers(drizzled::CachedDirectory&,
123
drizzled::SchemaIdentifier&,
124
drizzled::TableIdentifiers&)
128
bool HeapEngine::doDoesTableExist(Session& session, TableIdentifier &identifier)
130
return session.doesTableMessageExist(identifier);
133
int HeapEngine::doGetTableDefinition(Session &session,
134
TableIdentifier &identifier,
135
message::Table &table_proto)
137
if (session.getTableMessage(identifier, table_proto))
143
We have to ignore ENOENT entries as the MEMORY table is created on open and
144
not when doing a CREATE on the table.
146
int HeapEngine::doDropTable(Session &session, TableIdentifier &identifier)
148
session.removeTableMessage(identifier);
150
int error= heap_delete_table(identifier.getPath().c_str());
158
static HeapEngine *heap_storage_engine= NULL;
160
static int heap_init(plugin::Context &context)
162
heap_storage_engine= new HeapEngine(engine_name);
163
context.add(heap_storage_engine);
31
static handler *heap_create_handler(handlerton *hton,
35
int heap_deinit(void *)
37
pthread_mutex_init(&THR_LOCK_heap,MY_MUTEX_INIT_FAST);
39
return hp_panic(HA_PANIC_CLOSE);
43
int heap_init(void *p)
45
heap_hton= (handlerton *)p;
46
heap_hton->state= SHOW_OPTION_YES;
47
heap_hton->create= heap_create_handler;
48
heap_hton->flags= HTON_CAN_RECREATE;
53
static handler *heap_create_handler(handlerton *hton,
57
return new (mem_root) ha_heap(hton, table);
168
61
/*****************************************************************************
170
63
*****************************************************************************/
172
ha_heap::ha_heap(plugin::StorageEngine &engine_arg,
173
TableShare &table_arg)
174
:Cursor(engine_arg, table_arg), file(0), records_changed(0), key_stat_version(0),
65
ha_heap::ha_heap(handlerton *hton, TABLE_SHARE *table_arg)
66
:handler(hton, table_arg), file(0), records_changed(0), key_stat_version(0),
71
static const char *ha_heap_exts[] = {
75
const char **ha_heap::bas_ext() const
179
81
Hash index statistics is updated (copied from HP_KEYDEF::hash_buckets to
180
rec_per_key) after 1/MEMORY_STATS_UPDATE_THRESHOLD fraction of table records
82
rec_per_key) after 1/HEAP_STATS_UPDATE_THRESHOLD fraction of table records
181
83
have been inserted/updated/deleted. delete_all_rows() and table flush cause
186
88
from 0 to non-zero value and vice versa. Otherwise records_in_range may
187
89
erroneously return 0 and 'range' may miss records.
189
#define MEMORY_STATS_UPDATE_THRESHOLD 10
91
#define HEAP_STATS_UPDATE_THRESHOLD 10
191
93
int ha_heap::open(const char *name, int mode, uint32_t test_if_locked)
193
if ((test_if_locked & HA_OPEN_INTERNAL_TABLE) || (!(file= heap_open(name, mode)) && errno == ENOENT))
95
if ((test_if_locked & HA_OPEN_INTERNAL_TABLE) || (!(file= heap_open(name, mode)) && my_errno == ENOENT))
195
97
HA_CREATE_INFO create_info;
196
98
internal_table= test(test_if_locked & HA_OPEN_INTERNAL_TABLE);
197
99
memset(&create_info, 0, sizeof(create_info));
199
HP_SHARE *internal_share= NULL;
200
message::Table create_proto;
202
if (!heap_storage_engine->heap_create_table(ha_session(), name, table,
101
if (!create(name, table, &create_info))
207
103
file= internal_table ?
208
104
heap_open_from_share(internal_share, mode) :
681
610
return key->rec_per_key[key->key_parts-1];
684
int HeapEngine::doCreateTable(Session &session,
686
drizzled::TableIdentifier &identifier,
687
message::Table& create_proto)
690
HP_SHARE *internal_share;
691
const char *table_name= identifier.getPath().c_str();
693
error= heap_create_table(&session, table_name, &table_arg,
700
session.storeTableMessage(identifier, create_proto);
707
int HeapEngine::heap_create_table(Session *session, const char *table_name,
710
message::Table &create_proto,
711
HP_SHARE **internal_share)
614
int ha_heap::create(const char *name, Table *table_arg,
615
HA_CREATE_INFO *create_info)
713
617
uint32_t key, parts, mem_per_row_keys= 0, keys= table_arg->s->keys;
714
618
uint32_t auto_key= 0, auto_key_type= 0;
877
771
HP_CREATE_INFO hp_create_info;
878
772
hp_create_info.auto_key= auto_key;
879
773
hp_create_info.auto_key_type= auto_key_type;
880
hp_create_info.auto_increment= (create_proto.options().has_auto_increment_value() ?
881
create_proto.options().auto_increment_value() - 1 : 0);
882
hp_create_info.max_table_size=session->variables.max_heap_table_size;
774
hp_create_info.auto_increment= (create_info->auto_increment_value ?
775
create_info->auto_increment_value - 1 : 0);
776
hp_create_info.max_table_size=current_session->variables.max_heap_table_size;
883
777
hp_create_info.with_auto_increment= found_real_auto_increment;
884
778
hp_create_info.internal_table= internal_table;
885
779
hp_create_info.max_chunk_size= share->block_size;
886
780
hp_create_info.is_dynamic= (share->row_type == ROW_TYPE_DYNAMIC);
888
error= heap_create(internal::fn_format(buff,table_name,"","",
889
MY_REPLACE_EXT|MY_UNPACK_FILENAME),
891
column_count, columndef,
892
max_key_fieldnr, key_part_size,
893
share->reclength, mem_per_row_keys,
894
static_cast<uint32_t>(num_rows), /* We check for overflow above, so cast is fine here. */
896
&hp_create_info, internal_share);
781
error= heap_create(fn_format(buff,name,"","",
782
MY_REPLACE_EXT|MY_UNPACK_FILENAME),
784
column_count, columndef,
785
max_key_fieldnr, key_part_size,
786
share->reclength, mem_per_row_keys,
787
(uint32_t) share->max_rows, (uint32_t) share->min_rows,
788
&hp_create_info, &internal_share);
898
790
free((unsigned char*) keydef);
899
791
free((void *) columndef);
797
void ha_heap::update_create_info(HA_CREATE_INFO *create_info)
799
table->file->info(HA_STATUS_AUTO);
800
if (!(create_info->used_fields & HA_CREATE_USED_AUTO))
801
create_info->auto_increment_value= stats.auto_increment_value;
802
if (!(create_info->used_fields & HA_CREATE_USED_BLOCK_SIZE))
804
if (file->s->recordspace.is_variable_size)
805
create_info->block_size= file->s->recordspace.chunk_length;
807
create_info->block_size= 0;
905
811
void ha_heap::get_auto_increment(uint64_t, uint64_t, uint64_t,
906
812
uint64_t *first_value,
907
813
uint64_t *nb_reserved_values)