From bf92e392eb4efeae3c68689eb9efbbc28652e24e Mon Sep 17 00:00:00 2001 From: "Mirar (Pontus Hagland)" <pike@sort.mirar.org> Date: Thu, 11 May 2000 08:29:33 +0200 Subject: [PATCH] ... Rev: src/modules/Mird/Makefile.in:1.2 Rev: src/modules/Mird/acconfig.h:1.2 Rev: src/modules/Mird/configure.in:1.2 Rev: src/modules/Mird/mird_glue.c:1.2 Rev: src/modules/Mird/module.pmod.in:1.2 --- src/modules/Mird/Makefile.in | 2 +- src/modules/Mird/acconfig.h | 2 +- src/modules/Mird/configure.in | 2 +- src/modules/Mird/mird_glue.c | 690 ++++++++++++++++++++++++-------- src/modules/Mird/module.pmod.in | 224 ++++++++--- 5 files changed, 694 insertions(+), 226 deletions(-) diff --git a/src/modules/Mird/Makefile.in b/src/modules/Mird/Makefile.in index 56d54fb50b..115a3555b1 100644 --- a/src/modules/Mird/Makefile.in +++ b/src/modules/Mird/Makefile.in @@ -1,4 +1,4 @@ -# $Id: Makefile.in,v 1.1 2000/04/12 11:16:31 mirar Exp $ +# $Id: Makefile.in,v 1.2 2000/05/11 06:29:33 mirar Exp $ @make_variables@ VPATH=@srcdir@:@srcdir@/../..:../.. OBJS=mird_glue.o diff --git a/src/modules/Mird/acconfig.h b/src/modules/Mird/acconfig.h index c539959e25..57d792010c 100644 --- a/src/modules/Mird/acconfig.h +++ b/src/modules/Mird/acconfig.h @@ -1 +1 @@ -/* $Id: acconfig.h,v 1.1 2000/04/12 11:16:31 mirar Exp $ */ +/* $Id: acconfig.h,v 1.2 2000/05/11 06:29:33 mirar Exp $ */ diff --git a/src/modules/Mird/configure.in b/src/modules/Mird/configure.in index 2f68e2e971..2c8bd92809 100644 --- a/src/modules/Mird/configure.in +++ b/src/modules/Mird/configure.in @@ -1,4 +1,4 @@ -# $Id: configure.in,v 1.1 2000/04/12 11:16:31 mirar Exp $ +# $Id: configure.in,v 1.2 2000/05/11 06:29:33 mirar Exp $ AC_INIT(mird_glue.c) AC_CONFIG_HEADER(config.h) diff --git a/src/modules/Mird/mird_glue.c b/src/modules/Mird/mird_glue.c index 35ecdb4f98..f933df9509 100644 --- a/src/modules/Mird/mird_glue.c +++ b/src/modules/Mird/mird_glue.c @@ -7,7 +7,10 @@ #include "stralloc.h" #include "mapping.h" #include "array.h" +#include "builtin_functions.h" +#include "operators.h" #include "object.h" +#include "threads.h" #ifdef HAVE_MIRD_H #ifdef HAVE_LIBMIRD @@ -28,28 +31,48 @@ struct program *mird_scanner_program; #define TRY(X) \ do { MIRD_RES res; if ( (res=(X)) ) pmird_exception(res); } while (0) -#define LOCK(PMIRD) -#define UNLOCK(PMIRD) +#define LOCK(PMIRD) \ + do \ + { \ + struct pmird_storage *me=(PMIRD); \ + ONERROR err; \ + SET_ONERROR(err,pmird_unlock,&(me->mutex)); \ + THREADS_ALLOW(); \ + mt_lock(&(me->mutex)); + +#define UNLOCK(PMIRD) \ + mt_unlock(&(me->mutex)); \ + THREADS_DISALLOW(); \ + UNSET_ONERROR(err); \ + } \ + while (0); /**** utilities ************************************/ +static void pmird_unlock(PIKE_MUTEX_T *mutex) +{ + mt_unlock(mutex); +} + static void pmird_exception(MIRD_RES res) { char *s,*d; mird_describe_error(res,&s); d=alloca(strlen(s)+1); memcpy(d,s,strlen(s)+1); - error("[mird] %s\n",s); + mird_free(s); + mird_free_error(res); + error("[mird] %s\n",d); } -static void pmird_no_database(void) +static void pmird_no_database(char *func) { - error("database is not open\n"); + error("%s: database is not open\n",func); } -static void pmird_tr_no_database(void) +static void pmird_tr_no_database(char *func) { - error("no database connected to the transaction\n"); + error("%s: no database connected to the transaction\n",func); } static void pmird_no_transaction(void) @@ -62,6 +85,7 @@ static void pmird_no_transaction(void) struct pmird_storage { struct mird *db; + PIKE_MUTEX_T mutex; }; #define THIS ((struct pmird_storage*)(fp->current_storage)) @@ -69,6 +93,7 @@ struct pmird_storage static void init_pmird(struct object *o) { THIS->db=NULL; + mt_init(&THIS->mutex); } static void exit_pmird(struct object *o) @@ -78,6 +103,7 @@ static void exit_pmird(struct object *o) mird_free_structure(THIS->db); THIS->db=NULL; } + mt_destroy(&THIS->mutex); } /* @@ -154,9 +180,11 @@ static void exit_pmird(struct object *o) **! **! <pre>flags is a string with any of these characters: **! "r" - readonly +**! "R" - readonly in a live system (one process writes, many reads) **! "n" - don't create if it doesn't exist **! "x" - exclusive (always create) -**! "s" - call sync(2) after fsync +**! "s" - call fsync when finishing transactions +**! "S" - call sync(2) after fsync **! "j" - complain if journal file is gone missing **! </pre> **! @@ -164,24 +192,82 @@ static void exit_pmird(struct object *o) static void pmird_create(INT32 args) { + struct pmird_storage * this=THIS; + if (args<1) SIMPLE_TOO_FEW_ARGS_ERROR("Mird",1); if (sp[-args].type!=T_STRING || sp[-args].u.string->size_shift) SIMPLE_BAD_ARG_ERROR("Mird",1,"8 bit string"); -LOCK(THIS); - if (THIS->db) - mird_free_structure(THIS->db); + if (args>1) + if (sp[1-args].type!=T_MAPPING) + SIMPLE_BAD_ARG_ERROR("Mird",2,"mapping of options"); + + if (this->db) + mird_free_structure(this->db); - TRY(mird_initialize(sp[-args].u.string->str,&(THIS->db))); + TRY(mird_initialize(sp[-args].u.string->str,&(this->db))); + + if (args>1) + { +#define LOOKUP(SVALUE,TEXT) \ + push_svalue(&(SVALUE)); \ + push_text(TEXT); \ + f_index(2); + +#define LOOKUP_INT(SVALUE,TEXT,WHAT) \ + LOOKUP(SVALUE,TEXT); \ + if (!IS_UNDEFINED(sp-1)) \ + { \ + if (sp[-1].type!=T_INT) \ + SIMPLE_BAD_ARG_ERROR("Mird",2,"option \""TEXT"\":int"); \ + this->db->WHAT=sp[-1].u.integer; \ + } \ + pop_stack(); + + LOOKUP_INT(sp[1-args],"block_size",block_size); + LOOKUP_INT(sp[1-args],"frag_bits",frag_bits); + LOOKUP_INT(sp[1-args],"hashtrie_bits",hashtrie_bits); + LOOKUP_INT(sp[1-args],"cache_size",cache_size); + LOOKUP_INT(sp[1-args],"cache_search_length",cache_search_length); + LOOKUP_INT(sp[1-args],"max_free_frag_blocks",max_free_frag_blocks); + LOOKUP_INT(sp[1-args],"file_mode",file_mode); + LOOKUP_INT(sp[1-args],"journal_readback_n",journal_readback_n); + + LOOKUP(sp[1-args],"flags"); + if (!IS_UNDEFINED(sp-1)) + { + int i; + if (sp[-1].type!=T_STRING || + sp[-1].u.string->size_shift) + SIMPLE_BAD_ARG_ERROR("Mird",2,"\"flags\":8-bit string"); + for (i=0; i<sp[-1].u.string->len; i++) + switch (sp[-1].u.string->str[i]) + { + case 'r': this->db->flags|=MIRD_READONLY; break; + case 'R': this->db->flags|=MIRD_READONLY|MIRD_LIVE; break; + case 'n': this->db->flags|=MIRD_NOCREATE; break; + case 'x': this->db->flags|=MIRD_EXCL; break; + case 's': this->db->flags|=MIRD_SYNC_END; break; + case 'S': this->db->flags|=MIRD_CALL_SYNC; break; + case 'j': this->db->flags|=MIRD_JO_COMPLAIN; break; + default: + SIMPLE_BAD_ARG_ERROR("Mird",2,"\"flags\":[rRnxsSj]"); + } + } + pop_stack(); + } -/* THIS->db->hashtrie_bits=4; */ +/* this->db->cache_size=6144; */ +/* this->db->journal_readback_n=10000; */ +/* this->db->hashtrie_bits=4; */ /* options here */ - TRY(mird_open(THIS->db)); -UNLOCK(THIS); +LOCK(this); + TRY(mird_open(this->db)); +UNLOCK(this); pop_n_elems(args); push_int(0); @@ -203,17 +289,19 @@ UNLOCK(THIS); static void pmird_close(INT32 args) { + struct pmird_storage * this=THIS; + MIRD_RES res; pop_n_elems(args); - if (THIS->db) + if (this->db) { -LOCK(THIS); - res=mird_close(THIS->db); - if (res) mird_free_structure(THIS->db); - THIS->db=NULL; +LOCK(this); + res=mird_close(this->db); + if (res) mird_free_structure(this->db); + this->db=NULL; if (res) pmird_exception(res); -UNLOCK(THIS); +UNLOCK(this); } push_int(0); @@ -248,26 +336,30 @@ UNLOCK(THIS); static void pmird_sync(INT32 args) { + struct pmird_storage * this=THIS; + pop_n_elems(args); - if (!THIS->db) pmird_no_database(); + if (!this->db) pmird_no_database("sync"); - LOCK(THIS); - TRY(mird_sync(THIS->db)); - UNLOCK(THIS); + LOCK(this); + TRY(mird_sync(this->db)); + UNLOCK(this); ref_push_object(THISOBJ); } static void pmird_sync_please(INT32 args) { + struct pmird_storage * this=THIS; + pop_n_elems(args); - if (!THIS->db) pmird_no_database(); + if (!this->db) pmird_no_database("sync_please"); - LOCK(THIS); - TRY(mird_sync_please(THIS->db)); - UNLOCK(THIS); + LOCK(this); + TRY(mird_sync_please(this->db)); + UNLOCK(this); ref_push_object(THISOBJ); } @@ -279,6 +371,8 @@ static void pmird_sync_please(INT32 args) static void pmird_fetch(INT32 args) { + struct pmird_storage * this=THIS; + INT_TYPE hashkey,table_id; struct pike_string *stringkey; struct mird *db=THIS->db; @@ -288,28 +382,28 @@ static void pmird_fetch(INT32 args) if (args<2) SIMPLE_TOO_FEW_ARGS_ERROR("store",2); - if (!THIS->db) return pmird_no_transaction(); + if (!this->db) return pmird_no_transaction(); if (sp[1-args].type==T_INT) { get_all_args("fetch",args,"%i%i",&table_id,&hashkey); -LOCK(THIS); +LOCK(this); TRY(mird_key_lookup(db,(mird_key_t)table_id, (mird_key_t)hashkey, &data, &len)); -UNLOCK(THIS); +UNLOCK(this); } else if (sp[1-args].type==T_STRING) { get_all_args("fetch",args,"%i%S",&table_id,&stringkey); -LOCK(THIS); +LOCK(this); TRY(mird_s_key_lookup(db,(mird_key_t)table_id, (unsigned char*)(stringkey->str), (mird_size_t)(stringkey->len), &data, &len)); -UNLOCK(THIS); +UNLOCK(this); } else SIMPLE_BAD_ARG_ERROR("fetch",2,"int|string"); @@ -317,13 +411,64 @@ UNLOCK(THIS); pop_n_elems(args); if (data) + { push_string(make_shared_binary_string(data,len)); + mird_free(data); + } else { push_int(0); sp[-1].subtype=NUMBER_UNDEFINED; } - mird_free(data); +} + +/* +**! method int first_unused_key(int table_id) +**! method int first_unused_key(int table_id,int start_key) +**! method int first_unused_table() +**! method int first_unused_table(int start_table_id) +*/ + +static void pmird_first_unused_key(INT32 args) +{ + struct pmird_storage * this=THIS; + + INT_TYPE table_id=0,start_key=0; + mird_key_t dest_key; + + if (args>1) + get_all_args("first_unused_key",args,"%i%i",&table_id,&start_key); + else + get_all_args("first_unused_key",args,"%i",&table_id); + + if (!this->db) return pmird_no_transaction(); + +LOCK(this); + TRY(mird_find_first_unused(this->db,(mird_key_t)table_id, + (mird_key_t)start_key,&dest_key)); +UNLOCK(this); + pop_n_elems(args); + push_int( (INT_TYPE)dest_key ); +} + +static void pmird_first_unused_table(INT32 args) +{ + struct pmird_storage * this=THIS; + + INT_TYPE table_id=0; + mird_key_t dest_key; + + if (args) + get_all_args("first_unused_table",args,"%i",&table_id); + + if (!this->db) return pmird_no_transaction(); + +LOCK(this); + TRY(mird_find_first_unused_table(this->db,(mird_key_t)table_id, + &dest_key)); +UNLOCK(this); + pop_n_elems(args); + push_int( (INT_TYPE)dest_key ); } /* @@ -335,10 +480,12 @@ UNLOCK(THIS); static void pmird__debug_cut(INT32 args) { - if (THIS->db) + struct pmird_storage * this=THIS; + + if (this->db) { - mird_free_structure(THIS->db); - THIS->db=NULL; + mird_free_structure(this->db); + this->db=NULL; } pop_n_elems(args); @@ -348,7 +495,7 @@ static void pmird__debug_cut(INT32 args) /* **! method void _debug_check_free() **! method void _debug_check_free(int(0..1) silent) -**! This syncs the database and verifies +**! this syncs the database and verifies **! the database free list. It prints stuff **! on stderr. It exists only for debug **! purpose and has no other use. @@ -356,17 +503,43 @@ static void pmird__debug_cut(INT32 args) static void pmird__debug_check_free(INT32 args) { + struct pmird_storage * this=THIS; + int silent=0; if (sp[-args].type==T_INT && sp[-args].u.integer) silent=1; - if (!THIS->db) pmird_no_database(); - TRY(mird_sync(THIS->db)); - mird_debug_check_free(THIS->db,silent); + if (!this->db) pmird_no_database("_debug_check_free"); + TRY(mird_sync(this->db)); + mird_debug_check_free(this->db,silent); pop_n_elems(args); push_int(0); } +/* +**! method int _debug_syscalls() +**! returns the number of syscalls the database has done so far +*/ + +static void pmird__debug_syscalls(INT32 args) +{ + struct pmird_storage * this=THIS; + + if (!this->db) pmird_no_database("_debug_syscalls"); + + pop_n_elems(args); + push_int( (INT_TYPE)(this->db->syscalls_counter[0]) ); + push_int( (INT_TYPE)(this->db->syscalls_counter[1]) ); + push_int( (INT_TYPE)(this->db->syscalls_counter[2]) ); + push_int( (INT_TYPE)(this->db->syscalls_counter[3]) ); + push_int( (INT_TYPE)(this->db->syscalls_counter[4]) ); + push_int( (INT_TYPE)(this->db->syscalls_counter[5]) ); + push_int( (INT_TYPE)(this->db->syscalls_counter[6]) ); + push_int( (INT_TYPE)(this->db->last_used) ); + push_int( (INT_TYPE)(this->db->last_used*this->db->block_size) ); + f_aggregate(9); +} + /**** transaction program ***************************/ struct pmtr_storage @@ -412,6 +585,8 @@ static void exit_pmtr(struct object *o) static void pmtr_create(INT32 args) { + struct pmtr_storage *this=THIS; + struct pmird_storage *pmird; if (args<1) @@ -422,15 +597,15 @@ static void pmtr_create(INT32 args) SIMPLE_BAD_ARG_ERROR("Transaction",1,"Mird object"); add_ref(sp[-args].u.object); - THIS->dbobj=sp[-args].u.object; - THIS->parent=pmird; + this->dbobj=sp[-args].u.object; + this->parent=pmird; - if (!pmird->db) pmird_no_database(); + if (!pmird->db) pmird_no_database("Transaction"); - THIS->mtr=NULL; -LOCK(THIS->parent); - TRY(mird_transaction_new(pmird->db,&(THIS->mtr))); -UNLOCK(THIS->parent); + this->mtr=NULL; +LOCK(this->parent); + TRY(mird_transaction_new(pmird->db,&(this->mtr))); +UNLOCK(this->parent); pop_n_elems(args); push_int(0); @@ -444,18 +619,20 @@ UNLOCK(THIS->parent); static void pmtr_close(INT32 args) { + struct pmtr_storage *this=THIS; + struct mird_transaction *mtr; pop_n_elems(args); - if (!THIS->mtr) return pmird_no_transaction(); - if (!THIS->mtr->db) return pmird_tr_no_database(); + if (!this->mtr) return pmird_no_transaction(); + if (!this->mtr->db) return pmird_tr_no_database("close"); - mtr=THIS->mtr; -LOCK(THIS->parent); + mtr=this->mtr; +LOCK(this->parent); TRY(mird_transaction_close(mtr)); -UNLOCK(THIS->parent); - THIS->mtr=NULL; +UNLOCK(this->parent); + this->mtr=NULL; ref_push_object(THISOBJ); } @@ -468,38 +645,42 @@ UNLOCK(THIS->parent); static void pmtr_cancel(INT32 args) { + struct pmtr_storage *this=THIS; + pop_n_elems(args); - if (!THIS->mtr) return pmird_no_transaction(); - if (!THIS->mtr->db) return pmird_tr_no_database(); + if (!this->mtr) return pmird_no_transaction(); + if (!this->mtr->db) return pmird_tr_no_database("cancel"); -LOCK(THIS->parent); - TRY(mird_transaction_cancel(THIS->mtr)); -UNLOCK(THIS->parent); - THIS->mtr=NULL; +LOCK(this->parent); + TRY(mird_transaction_cancel(this->mtr)); +UNLOCK(this->parent); + this->mtr=NULL; - ref_push_object(THISOBJ); + push_int(0); } static void pmtr_destroy(INT32 args) { + struct pmtr_storage *this=THIS; + pop_n_elems(args); - if (THIS->mtr && - THIS->mtr->db) + if (this->mtr && + this->mtr->db) { -LOCK(THIS->parent); - TRY(mird_transaction_cancel(THIS->mtr)); -UNLOCK(THIS->parent); - THIS->mtr=NULL; +LOCK(this->parent); + TRY(mird_transaction_cancel(this->mtr)); +UNLOCK(this->parent); + this->mtr=NULL; } - else if (THIS->mtr) + else if (this->mtr) { - mird_tr_free(THIS->mtr); - THIS->mtr=NULL; + mird_tr_free(this->mtr); + this->mtr=NULL; } - ref_push_object(THISOBJ); + push_int(0); } /* @@ -512,14 +693,16 @@ UNLOCK(THIS->parent); static void pmtr_resolve(INT32 args) { + struct pmtr_storage *this=THIS; + pop_n_elems(args); - if (!THIS->mtr) return pmird_no_transaction(); - if (!THIS->mtr->db) return pmird_tr_no_database(); + if (!this->mtr) return pmird_no_transaction(); + if (!this->mtr->db) return pmird_tr_no_database("resolve"); -LOCK(THIS->parent); - TRY(mird_tr_resolve(THIS->mtr)); -UNLOCK(THIS->parent); +LOCK(this->parent); + TRY(mird_tr_resolve(this->mtr)); +UNLOCK(this->parent); ref_push_object(THISOBJ); } @@ -530,6 +713,8 @@ UNLOCK(THIS->parent); static void pmtr_store(INT32 args) { + struct pmtr_storage *this=THIS; + INT_TYPE hashkey,table_id; struct pike_string *stringkey; struct pike_string *data; @@ -539,28 +724,28 @@ static void pmtr_store(INT32 args) SIMPLE_TOO_FEW_ARGS_ERROR("store",3); if (!THIS->mtr) return pmird_no_transaction(); - if (!THIS->mtr->db) return pmird_tr_no_database(); + if (!THIS->mtr->db) return pmird_tr_no_database("store"); if (sp[1-args].type==T_INT) { get_all_args("store",args,"%i%i%S",&table_id,&hashkey,&data); -LOCK(THIS->parent); +LOCK(this->parent); TRY(mird_key_store(mtr,(mird_key_t)table_id, (mird_key_t)hashkey, (unsigned char*)(data->str), (mird_size_t)(data->len))); -UNLOCK(THIS->parent); +UNLOCK(this->parent); } else if (sp[1-args].type==T_STRING) { get_all_args("store",args,"%i%S%S",&table_id,&stringkey,&data); -LOCK(THIS->parent); +LOCK(this->parent); TRY(mird_s_key_store(mtr,(mird_key_t)table_id, (unsigned char*)(stringkey->str), (mird_size_t)(stringkey->len), (unsigned char*)(data->str), (mird_size_t)(data->len))); -UNLOCK(THIS->parent); +UNLOCK(this->parent); } else SIMPLE_BAD_ARG_ERROR("store",2,"int|string"); @@ -575,6 +760,8 @@ UNLOCK(THIS->parent); static void pmtr_delete(INT32 args) { + struct pmtr_storage *this=THIS; + INT_TYPE hashkey,table_id; struct pike_string *stringkey; struct mird_transaction *mtr=THIS->mtr; @@ -582,27 +769,27 @@ static void pmtr_delete(INT32 args) if (args<2) SIMPLE_TOO_FEW_ARGS_ERROR("store",2); - if (!THIS->mtr) return pmird_no_transaction(); - if (!THIS->mtr->db) return pmird_tr_no_database(); + if (!this->mtr) return pmird_no_transaction(); + if (!this->mtr->db) return pmird_tr_no_database("delete"); if (sp[1-args].type==T_INT) { get_all_args("delete",args,"%i%i",&table_id,&hashkey); -LOCK(THIS->parent); +LOCK(this->parent); TRY(mird_key_store(mtr,(mird_key_t)table_id, (mird_key_t)hashkey, NULL,0)); -UNLOCK(THIS->parent); +UNLOCK(this->parent); } else if (sp[1-args].type==T_STRING) { get_all_args("delete",args,"%i%S",&table_id,&stringkey); -LOCK(THIS->parent); +LOCK(this->parent); TRY(mird_s_key_store(mtr,(mird_key_t)table_id, (unsigned char*)(stringkey->str), (mird_size_t)(stringkey->len), NULL,0)); -UNLOCK(THIS->parent); +UNLOCK(this->parent); } else SIMPLE_BAD_ARG_ERROR("delete",2,"int|string"); @@ -618,38 +805,40 @@ UNLOCK(THIS->parent); static void pmtr_fetch(INT32 args) { + struct pmtr_storage *this=THIS; + INT_TYPE hashkey,table_id; struct pike_string *stringkey; - struct mird_transaction *mtr=THIS->mtr; + struct mird_transaction *mtr=this->mtr; unsigned char *data; mird_size_t len; if (args<2) SIMPLE_TOO_FEW_ARGS_ERROR("store",2); - if (!THIS->mtr) return pmird_no_transaction(); - if (!THIS->mtr->db) return pmird_tr_no_database(); + if (!this->mtr) return pmird_no_transaction(); + if (!this->mtr->db) return pmird_tr_no_database("fetch"); if (sp[1-args].type==T_INT) { get_all_args("fetch",args,"%i%i",&table_id,&hashkey); -LOCK(THIS->parent); +LOCK(this->parent); TRY(mird_transaction_key_lookup(mtr,(mird_key_t)table_id, (mird_key_t)hashkey, &data, &len)); -UNLOCK(THIS->parent); +UNLOCK(this->parent); } else if (sp[1-args].type==T_STRING) { get_all_args("fetch",args,"%i%S",&table_id,&stringkey); -LOCK(THIS->parent); +LOCK(this->parent); TRY(mird_transaction_s_key_lookup(mtr,(mird_key_t)table_id, (unsigned char*)(stringkey->str), (mird_size_t)(stringkey->len), &data, &len)); -UNLOCK(THIS->parent); +UNLOCK(this->parent); } else SIMPLE_BAD_ARG_ERROR("fetch",2,"int|string"); @@ -657,13 +846,15 @@ UNLOCK(THIS->parent); pop_n_elems(args); if (data) + { push_string(make_shared_binary_string(data,len)); + mird_free(data); + } else { push_int(0); sp[-1].subtype=NUMBER_UNDEFINED; } - mird_free(data); } /* @@ -674,16 +865,18 @@ UNLOCK(THIS->parent); static void pmtr_new_hashkey_table(INT32 args) { + struct pmtr_storage *this=THIS; + INT_TYPE table_id; get_all_args("new_hashkey_table",args,"%i",&table_id); - if (!THIS->mtr) return pmird_no_transaction(); - if (!THIS->mtr->db) return pmird_tr_no_database(); + if (!this->mtr) return pmird_no_transaction(); + if (!this->mtr->db) return pmird_tr_no_database("new_hashkey_table"); -LOCK(THIS->parent); - TRY(mird_key_new_table(THIS->mtr,(mird_key_t)table_id)); -UNLOCK(THIS->parent); +LOCK(this->parent); + TRY(mird_key_new_table(this->mtr,(mird_key_t)table_id)); +UNLOCK(this->parent); pop_n_elems(args); ref_push_object(THISOBJ); @@ -691,16 +884,18 @@ UNLOCK(THIS->parent); static void pmtr_new_stringkey_table(INT32 args) { + struct pmtr_storage *this=THIS; + INT_TYPE table_id; get_all_args("new_hashkey_table",args,"%i",&table_id); - if (!THIS->mtr) return pmird_no_transaction(); - if (!THIS->mtr->db) return pmird_tr_no_database(); + if (!this->mtr) return pmird_no_transaction(); + if (!this->mtr->db) return pmird_tr_no_database("new_stringkey_table"); -LOCK(THIS->parent); - TRY(mird_s_key_new_table(THIS->mtr,(mird_key_t)table_id)); -UNLOCK(THIS->parent); +LOCK(this->parent); + TRY(mird_s_key_new_table(this->mtr,(mird_key_t)table_id)); +UNLOCK(this->parent); pop_n_elems(args); ref_push_object(THISOBJ); @@ -716,16 +911,18 @@ UNLOCK(THIS->parent); static void pmtr_delete_table(INT32 args) { + struct pmtr_storage *this=THIS; + INT_TYPE table_id; get_all_args("delete_table",args,"%i",&table_id); - if (!THIS->mtr) return pmird_no_transaction(); - if (!THIS->mtr->db) return pmird_tr_no_database(); + if (!this->mtr) return pmird_no_transaction(); + if (!this->mtr->db) return pmird_tr_no_database("delete_table"); - LOCK(THIS->parent); - TRY(mird_delete_table(THIS->mtr,(mird_key_t)table_id)); - UNLOCK(THIS->parent); + LOCK(this->parent); + TRY(mird_delete_table(this->mtr,(mird_key_t)table_id)); + UNLOCK(this->parent); } /* @@ -734,16 +931,69 @@ static void pmtr_delete_table(INT32 args) static void pmtr_depend_table(INT32 args) { + struct pmtr_storage *this=THIS; + INT_TYPE table_id; get_all_args("depend_table",args,"%i",&table_id); - if (!THIS->mtr) return pmird_no_transaction(); - if (!THIS->mtr->db) return pmird_tr_no_database(); + if (!this->mtr) return pmird_no_transaction(); + if (!this->mtr->db) return pmird_tr_no_database("depend_table"); - LOCK(THIS->parent); - TRY(mird_depend_table(THIS->mtr,(mird_key_t)table_id)); - UNLOCK(THIS->parent); + LOCK(this->parent); + TRY(mird_depend_table(this->mtr,(mird_key_t)table_id)); + UNLOCK(this->parent); +} + +/* +**! method int first_unused_key(int table_id) +**! method int first_unused_key(int table_id,int start_key) +**! method int first_unused_table() +**! method int first_unused_table(int start_table_id) +*/ + +static void pmtr_first_unused_key(INT32 args) +{ + struct pmtr_storage *this=THIS; + + INT_TYPE table_id=0,start_key=0; + mird_key_t dest_key; + + if (args>1) + get_all_args("first_unused_key",args,"%i%i",&table_id,&start_key); + else + get_all_args("first_unused_key",args,"%i",&table_id); + + if (!this->mtr) return pmird_no_transaction(); + if (!this->mtr->db) return pmird_tr_no_database("first_unused_key"); + +LOCK(this->parent); + TRY(mird_transaction_find_first_unused(this->mtr,(mird_key_t)table_id, + (mird_key_t)start_key,&dest_key)); +UNLOCK(this->parent); + pop_n_elems(args); + push_int( (INT_TYPE)dest_key ); +} + +static void pmtr_first_unused_table(INT32 args) +{ + struct pmtr_storage *this=THIS; + + INT_TYPE table_id=0; + mird_key_t dest_key; + + if (args) + get_all_args("first_unused_table",args,"%i",&table_id); + + if (!this->mtr) return pmird_no_transaction(); + if (!this->mtr->db) return pmird_tr_no_database("first_unused_table"); + +LOCK(this->parent); + TRY(mird_transaction_find_first_unused_table(this->mtr,(mird_key_t)table_id, + &dest_key)); +UNLOCK(this->parent); + pop_n_elems(args); + push_int( (INT_TYPE)dest_key ); } /**** hashkey table scanner ************************/ @@ -753,6 +1003,7 @@ static void pmtr_depend_table(INT32 args) struct pmts_storage { + enum { PMTS_UNKNOWN, PMTS_HASHKEY, PMTS_STRINGKEY } type; struct mird_scan_result *msr; struct mird_s_scan_result *mssr; struct object *obj; @@ -766,6 +1017,7 @@ static void init_pmts(struct object *o) THIS->msr=NULL; THIS->mssr=NULL; THIS->obj=NULL; + THIS->type=PMTS_UNKNOWN; } static void exit_pmts(struct object *o) @@ -793,6 +1045,8 @@ static void pmts_create(INT32 args) { struct pmird_storage *pmird; struct pmtr_storage *pmtr; + struct pmts_storage *this=THIS; + mird_key_t type; if (args<2) SIMPLE_TOO_FEW_ARGS_ERROR("Scanner",2); @@ -811,11 +1065,48 @@ static void pmts_create(INT32 args) SIMPLE_BAD_ARG_ERROR("Scanner",2,"int"); add_ref(sp[-args].u.object); - THIS->obj=sp[-args].u.object; - THIS->pmird=pmird; - THIS->pmtr=pmtr; + this->obj=sp[-args].u.object; + this->pmird=pmird; + this->pmtr=pmtr; - THIS->table_id=(mird_key_t)sp[1-args].u.integer; + this->table_id=(mird_key_t)sp[1-args].u.integer; + + if (!this->pmird) + this->pmird=this->pmtr->parent; + +LOCK(this->pmird); + if (this->pmtr) + TRY(mird_transaction_get_table_type(this->pmtr->mtr, + this->table_id,&type)); + else + TRY(mird_get_table_type(this->pmird->db,this->table_id,&type)); +UNLOCK(this->pmird); + + switch (type) + { + case MIRD_TABLE_HASHKEY: this->type=PMTS_HASHKEY; break; + case MIRD_TABLE_STRINGKEY: this->type=PMTS_STRINGKEY; break; + default: + error("Scanner: Unknown table %08lx\n",(unsigned long)type); + } + + if (args>2) + if (sp[2-args].type!=T_INT) + SIMPLE_BAD_ARG_ERROR("Scanner",3,"int"); + else + { + mird_key_t key=(mird_key_t)sp[2-args].u.integer; + switch (this->type) + { + case PMTS_HASHKEY: + TRY(mird_scan_continued(key,&(this->msr))); + break; + case PMTS_STRINGKEY: + TRY(mird_s_scan_continued(key,&(this->mssr))); + break; + case PMTS_UNKNOWN: error("illegal scanner type\n"); break; + } + } pop_n_elems(args); push_int(0); @@ -836,91 +1127,120 @@ static void pmts_create(INT32 args) static void pmts_read(INT32 args) { + struct pmts_storage *this=THIS; + INT_TYPE n; - MIRD_RES res; + MIRD_RES res=NULL; mird_size_t i; get_all_args("read",args,"%+",&n); - if (THIS->pmird && !THIS->pmird->db) pmird_no_database(); - if (THIS->pmtr && !THIS->pmtr->mtr) pmird_no_transaction(); - if (THIS->pmtr && !THIS->pmtr->parent->db) pmird_tr_no_database(); - - if (THIS->msr) - { - if (THIS->pmird) - res=mird_table_scan(THIS->pmird->db,THIS->table_id,(mird_size_t)n, - THIS->msr,&(THIS->msr)); - else /* pmtr */ - res=mird_transaction_table_scan(THIS->pmtr->mtr, - THIS->table_id,(mird_size_t)n, - THIS->msr,&(THIS->msr)); - } - else if (THIS->mssr) + if (this->pmird && !this->pmird->db) pmird_no_database("read"); + if (this->pmtr && !this->pmtr->mtr) pmird_no_transaction(); + if (this->pmtr && !this->pmtr->parent->db) pmird_tr_no_database("read"); + + +LOCK(this->pmird); + if (this->pmird) { - if (THIS->pmird) - res=mird_s_table_scan(THIS->pmird->db,THIS->table_id,(mird_size_t)n, - THIS->mssr,&(THIS->mssr)); - else /* pmtr */ - res=mird_transaction_s_table_scan(THIS->pmtr->mtr, - THIS->table_id,(mird_size_t)n, - THIS->mssr,&(THIS->mssr)); + switch (this->type) + { + case PMTS_HASHKEY: + res=mird_table_scan(this->pmird->db,this->table_id,(mird_size_t)n, + this->msr,&(this->msr)); + break; + case PMTS_STRINGKEY: + res=mird_s_table_scan(this->pmird->db,this->table_id, + (mird_size_t)n,this->mssr,&(this->mssr)); + break; + case PMTS_UNKNOWN: error("illegal scanner type\n"); break; + } } - else /* chance */ + else /* pmtr */ { - if (THIS->pmird) - res=mird_table_scan(THIS->pmird->db,THIS->table_id,(mird_size_t)n, - NULL,&(THIS->msr)); - else /* pmtr */ - res=mird_transaction_table_scan(THIS->pmtr->mtr, - THIS->table_id,(mird_size_t)n, - NULL,&(THIS->msr)); - if (res && res->error_no==MIRDE_WRONG_TABLE) + switch (this->type) { - mird_free_error(res); - /* it's a string table, then */ - - if (THIS->pmird) - res=mird_s_table_scan(THIS->pmird->db,THIS->table_id, - (mird_size_t)n,THIS->mssr,&(THIS->mssr)); - else /* pmtr */ - res=mird_transaction_s_table_scan(THIS->pmtr->mtr, - THIS->table_id,(mird_size_t)n, - THIS->mssr,&(THIS->mssr)); + case PMTS_HASHKEY: + res=mird_transaction_table_scan(this->pmtr->mtr, + this->table_id,(mird_size_t)n, + this->msr,&(this->msr)); + break; + case PMTS_STRINGKEY: + res=mird_transaction_s_table_scan(this->pmtr->mtr, + this->table_id,(mird_size_t)n, + this->mssr,&(this->mssr)); + break; + case PMTS_UNKNOWN: error("illegal scanner type\n"); break; } } +UNLOCK(this->pmird); if (res) pmird_exception(res); pop_n_elems(args); - if (THIS->msr) + if (this->msr) { - for (i=0; i<THIS->msr->n; i++) + for (i=0; i<this->msr->n; i++) { - push_int((INT_TYPE)(THIS->msr->tupel[i].key)); + push_int((INT_TYPE)(this->msr->tupel[i].key)); push_string(make_shared_binary_string( - THIS->msr->tupel[i].value, - THIS->msr->tupel[i].value_len)); + this->msr->tupel[i].value, + this->msr->tupel[i].value_len)); } - f_aggregate_mapping(THIS->msr->n*2); + f_aggregate_mapping(this->msr->n*2); } - else if (THIS->mssr) + else if (this->mssr) { - for (i=0; i<THIS->mssr->n; i++) + for (i=0; i<this->mssr->n; i++) { push_string(make_shared_binary_string( - THIS->mssr->tupel[i].key, - THIS->mssr->tupel[i].key_len)); + this->mssr->tupel[i].key, + this->mssr->tupel[i].key_len)); push_string(make_shared_binary_string( - THIS->mssr->tupel[i].value, - THIS->mssr->tupel[i].value_len)); + this->mssr->tupel[i].value, + this->mssr->tupel[i].value_len)); } - f_aggregate_mapping(THIS->mssr->n*2); + f_aggregate_mapping(this->mssr->n*2); } else /* eod */ push_int(0); } +/* +**! method int next_key() +**! Gives back a possible argument to the constructor +**! of <ref>Scanner</ref>; allows the possibility +**! to continue to scan even if the Scanner object is lost. +*/ + +static void pmts_next_key(INT32 args) +{ + mird_key_t key; + struct pmts_storage *this=THIS; + switch (this->type) + { + case PMTS_HASHKEY: + TRY(mird_scan_continuation(this->msr,&key)); + break; + case PMTS_STRINGKEY: + TRY(mird_s_scan_continuation(this->mssr,&key)); + break; + case PMTS_UNKNOWN: error("illegal scanner type\n"); break; + } + pop_n_elems(args); + push_int( (INT_TYPE)key ); +} + +/**** *********************************/ + +int mird_check_mem(void); + +static void m_debug_check_mem(INT32 args) +{ + pop_n_elems(args); + push_int(mird_check_mem()); +} + /**** module stuff *********************************/ void pike_module_init(void) @@ -946,9 +1266,16 @@ void pike_module_init(void) ADD_FUNCTION("sync_please",pmird_sync_please,tFunc(tNone,tVoid),0); ADD_FUNCTION("fetch",pmird_fetch,tFunc(tInt tOr(tInt,tStr),tOr(tStr,tInt0)),0); + ADD_FUNCTION("first_unused_key",pmird_first_unused_key, + tFunc(tInt tOr(tVoid,tInt),tInt),0); + ADD_FUNCTION("first_unused_table",pmird_first_unused_table, + tFunc(tOr(tVoid,tInt),tInt),0); + ADD_FUNCTION("_debug_cut",pmird__debug_cut,tFunc(tNone,tVoid),0); ADD_FUNCTION("_debug_check_free",pmird__debug_check_free, tFunc(tNone,tVoid),0); + ADD_FUNCTION("_debug_syscalls",pmird__debug_syscalls, + tFunc(tNone,tArr(tInt)),0); mird_program=end_program(); @@ -973,9 +1300,14 @@ void pike_module_init(void) ADD_FUNCTION("depend_table",pmtr_depend_table,tFunc(tInt,tObj),0); ADD_FUNCTION("new_stringkey_table",pmtr_new_stringkey_table, - tFunc(tNone,tObj),0); + tFunc(tInt,tObj),0); ADD_FUNCTION("new_hashkey_table",pmtr_new_hashkey_table, - tFunc(tNone,tObj),0); + tFunc(tInt,tObj),0); + + ADD_FUNCTION("first_unused_key",pmtr_first_unused_key, + tFunc(tInt tOr(tVoid,tInt),tInt),0); + ADD_FUNCTION("first_unused_table",pmtr_first_unused_table, + tFunc(tOr(tVoid,tInt),tInt),0); mird_transaction_program=end_program(); @@ -988,6 +1320,7 @@ void pike_module_init(void) ADD_FUNCTION("create",pmts_create,tFunc(tObj tInt,tVoid),0); ADD_FUNCTION("read",pmts_read,tFunc(tIntPos,tMap(tOr(tInt,tStr),tStr)),0); + ADD_FUNCTION("next_key",pmts_next_key,tFunc(tNone,tInt),0); mird_scanner_program=end_program(); @@ -1001,6 +1334,9 @@ void pike_module_init(void) add_program_constant("Transaction",mird_transaction_program,0); add_program_constant("Scanner",mird_scanner_program,0); + ADD_FUNCTION("_debug_check_mem",m_debug_check_mem, + tFunc(tNone,tInt),0); + #if 0 p=end_program(); diff --git a/src/modules/Mird/module.pmod.in b/src/modules/Mird/module.pmod.in index 1f1046d749..c182a7ba98 100644 --- a/src/modules/Mird/module.pmod.in +++ b/src/modules/Mird/module.pmod.in @@ -4,7 +4,7 @@ class Mird { constant Glue=@module@; - object mird; + Glue.Mird mird; #define TABLE2ID_TABLE 1 #define ID2TABLE_TABLE 2 @@ -14,13 +14,15 @@ class Mird mapping id2table=([]); int next_table; + function(int,int|string:string) _fetch; + //! class Mird //! //! method void create(string filename,void|mapping options) void create(string filename,void|mapping options) { - mird=Glue.Mird(filename,options); + mird=Glue.Mird(filename,options||([])); mixed err=catch { @@ -29,16 +31,31 @@ class Mird if (err || !next_table) { next_table=max(ID2TABLE_TABLE,TABLE2ID_TABLE)+1; - object mtr=Glue.Transaction(mird); + Glue.Transaction mtr=Glue.Transaction(mird); mtr->new_stringkey_table(TABLE2ID_TABLE); mtr->new_hashkey_table(ID2TABLE_TABLE); mtr->store(TABLE2ID_TABLE,NEXT_TABLE,(string)next_table); mtr->close(); } + _fetch=mird->fetch; + call_out(sync_loop,60,60); } + Glue.Scanner _scanner(int ... args) + { + return Glue.Scanner(mird,@args); + } + + Mird _store(int table_id,int|string key,string data) + { + Transaction tr=transaction(); + tr->_store(table_id,key,data); + tr->close(); + return this_object(); + } + //! method Table table(string name) Table table(string name) @@ -53,6 +70,23 @@ class Mird return Table(this_object(),table2id[name]); } +//! method vTable vtable(string name) +//! A vTable is just like a table, except that the +//! values can be anything, not just strings. The +//! data is encode_value()ed before storage. + + vTable vtable(string name) + { + if (name==NEXT_TABLE) error("illegal name\n"); + if (!table2id[name]) + { + string d=mird->fetch(TABLE2ID_TABLE,name); + if (!d) error("no such table (%O)\n",name); + table2id[name]=(int)d; + } + return vTable(this_object(),table2id[name]); + } + //! method table_name(int id) string table_name(int id) @@ -70,7 +104,7 @@ class Mird Table new_stringkey_table(string name) { - object tr=transaction(); + Transaction tr=transaction(); tr->new_stringkey_table(name); tr->close(); return table(name); @@ -78,7 +112,7 @@ class Mird Table new_hashkey_table(string name) { - object tr=transaction(); + Transaction tr=transaction(); tr->new_hashkey_table(name); tr->close(); return table(name); @@ -114,23 +148,21 @@ class Mird //! shut down the loop. //! Default is 1 minute (60 seconds). - object sync() + Mird sync() { gc(); // kill any leftover transactions mird->sync(); return this_object(); } - object sync_please() + Mird sync_please() { - werror("sync %f\n",gauge { - gc(); // kill any leftover transactions - mird->sync_please(); - }); + gc(); // kill any leftover transactions + mird->sync_please(); return this_object(); } - object sync_loop(int seconds) + Mird sync_loop(int seconds) { remove_call_out(sync_loop); if (seconds<=0) return this_object(); @@ -145,9 +177,8 @@ class Mird void close() { - werror("close\n"); remove_call_out(sync_loop); - mird->close(); + if (mird) mird->close(); } function destroy=close; @@ -159,7 +190,7 @@ class Mird class Table { int table_id; - object parent; + object(Mird)|object(Transaction) parent; //! method void create(object parent,int table_id) void create(object _parent,int _table_id) @@ -168,23 +199,28 @@ class Mird table_id=_table_id; } +//! method Mird.Glue.Scanner scanner() +//! method Mird.Glue.Scanner scanner(int key) +//! Creates a scanner over the called table; +//! if a key is given, continue at that key +//! (as returned from <ref to=Mird.Glue.Scanner.next_key>next_key</ref>). + + Mird.Glue.Scanner scanner(int ... key) + { + return parent->_scanner(table_id,@key); + } + //! method string `[](int|string key) string `[](int|string key) { - return parent->fetch(table_id,key); + string s=parent->_fetch(table_id,key); + return s; } -//! method string `[]=(int|string key) +//! method string `[]=(int|string key,string value) string `[]=(int|string key,string value) { - if (parent->mtr) - return parent->mtr->store(table_id,key,value); - else - { - object tr=parent->transaction(); - tr->mtr->store(table_id,key,value); - tr->close(); - } + parent->_store(table_id,key,value); return value; } @@ -192,7 +228,7 @@ class Mird array(int|string) _indices() { array keys=({}); - object sc=Glue.Scanner(parent->mird,table_id); + Glue.Scanner sc=scanner(); mapping m; while ( (m=sc->read(100)) ) keys+=indices(m); return keys; @@ -201,11 +237,11 @@ class Mird //! method array(int|string) _values() array(int|string) _values() { - array values=({}); - object sc=Glue.Scanner(parent->mird,table_id); + array vals=({}); + Glue.Scanner sc=scanner(); mapping m; - while ( (m=sc->read(100)) ) values+=values(m); - return values; + while ( (m=sc->read(100)) ) vals+=values(m); + return vals; } //! method array|mapping cast("mapping"|"array") @@ -214,7 +250,7 @@ class Mird if (sscanf(to,"array%*s")) { array tupels=({}); - object sc=Glue.Scanner(parent,table_id); + Glue.Scanner sc=scanner(); mapping m; while ( (m=sc->read(100)) ) tupels+=(array)m; return tupels; @@ -222,7 +258,7 @@ class Mird if (sscanf(to,"mapping%*s")) { mapping tupels=([]); - object sc=Glue.Scanner(parent,table_id); + Glue.Scanner sc=scanner(); mapping m; while ( (m=sc->read(100)) ) tupels+=m; return tupels; @@ -231,23 +267,102 @@ class Mird } } +//! +//! subclass vTable +//! inherits Table +//! This is just like a normal table, but all data is encode_value()ed, +//! and unpacked if reading, for convinience. +//! + + class vTable + { + inherit Table; + + mixed `[](int|string key) + { + string s=parent->_fetch(table_id,key); + if (s) return decode_value(s); + return ([])[0]; + } + + string `[]=(int|string key,mixed value) + { + parent->_store(table_id,key,encode_value(value)); + return value; + } + + + array(int|string) _values() + { + array vals=({}); + Glue.Scanner sc=parent->_scanner(table_id); + mapping m; + while ( (m=sc->read(100)) ) vals+=values(m); + return map(vals,decode_value); + } + + array|mapping cast(string to) + { + if (sscanf(to,"array%*s")) + { + array tupels=({}); + Glue.Scanner sc=parent->_scanner(table_id); + mapping m; + while ( (m=sc->read(100)) ) tupels+=(array)m; + return map(tupels,lambda(array(string) v) + { + return ({v[0],decode_value(v[1])}); + }); + } + if (sscanf(to,"mapping%*s")) + { + mapping tupels=([]); + Glue.Scanner sc=parent->_scanner(table_id); + mapping m; + while ( (m=sc->read(100)) ) + tupels+=m; + return (mapping)map((array)tupels, + lambda(array(string) v) + { + return ({v[0],decode_value(v[1])}); + }); + } + error("illegal argument 1 to cast\n"); + } + } + //! //! subclass Transaction //! class Transaction { - object parent; - object mird; - object mtr; + Mird parent; + Glue.Transaction mtr; mapping table2id=([]); int refresh_at_close=0; + function(int,int|string:string) _fetch; + function(int:Glue.Scanner) _scanner; + void create(object _parent) { parent=_parent; - mird=parent->mird; - mtr=Glue.Transaction(mird); + mtr=Glue.Transaction(parent->mird); + _fetch=mtr->fetch; + _scanner=lambda(int ... args) + { + return Glue.Scanner(mtr,@args); + }; + } + + Transaction _store(int table_id,int|string key,string value) + { + if (!value) + mtr->delete(table_id,key); + else + mtr->store(table_id,key,value); + return this_object(); } //! method Table table(string name) @@ -274,6 +389,23 @@ class Mird return Table(this_object(),id); } +//! method vTable vtable(string name) +//! A vTable is just like a table, except that the +//! values can be anything, not just strings. The +//! data is encode_value()ed before storage. + + vTable vtable(string name) + { + if (name==NEXT_TABLE) error("illegal name\n"); + if (!table2id[name]) + { + string d=mird->fetch(TABLE2ID_TABLE,name); + if (!d) error("no such table (%O)\n",name); + table2id[name]=(int)d; + } + return vTable(this_object(),table2id[name]); + } + //! //! method Table new_stringkey_table(string name) //! method Table new_hashkey_table(string name) @@ -284,12 +416,12 @@ class Mird Table new_stringkey_table(string name) { - string d=mird->fetch(TABLE2ID_TABLE,name); + string d=mtr->fetch(TABLE2ID_TABLE,name); if (d) error("table already exist"); int no=parent->next_table++; - mtr->store(TABLE2ID_TABLE,name,(string)next_table); - mtr->store(ID2TABLE_TABLE,next_table,name); - mtr->store(TABLE2ID_TABLE,NEXT_TABLE,(string)next_table); + mtr->store(TABLE2ID_TABLE,name,(string)no); + mtr->store(ID2TABLE_TABLE,no,name); + mtr->store(TABLE2ID_TABLE,NEXT_TABLE,(string)parent->next_table); mtr->new_stringkey_table(no); refresh_at_close=1; return table(name); @@ -297,12 +429,12 @@ class Mird Table new_hashkey_table(string name) { - string d=mird->fetch(TABLE2ID_TABLE,name); + string d=mtr->fetch(TABLE2ID_TABLE,name); if (d) error("table already exist"); int no=parent->next_table++; - mtr->store(TABLE2ID_TABLE,name,(string)next_table); - mtr->store(ID2TABLE_TABLE,next_table,name); - mtr->store(TABLE2ID_TABLE,NEXT_TABLE,(string)next_table); + mtr->store(TABLE2ID_TABLE,name,(string)no); + mtr->store(ID2TABLE_TABLE,no,name); + mtr->store(TABLE2ID_TABLE,NEXT_TABLE,(string)parent->next_table); mtr->new_hashkey_table(no); refresh_at_close=1; return table(name); @@ -344,7 +476,7 @@ class Mird void destroy() { - mtr->destroy(); + if (mtr) destruct(mtr); } } } -- GitLab