Changeset: 8e65cdd52c08 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/8e65cdd52c08
Modified Files:
        sql/backends/monet5/mal_backend.c
        sql/backends/monet5/mal_backend.h
        sql/backends/monet5/rel_bin.c
        sql/backends/monet5/sql_gencode.c
        sql/backends/monet5/sql_gencode.h
        sql/backends/monet5/sql_scenario.c
        sql/backends/monet5/sql_statement.c
        sql/common/sql_backend.c
        sql/common/sql_backend.h
        sql/common/sql_types.c
        sql/include/sql_catalog.h
        sql/server/rel_psm.c
        sql/storage/store.c
Branch: Jan2022
Log Message:

Use a single lock for both MAL and SQL instantiation.

The lock per function is now removed, thus saving memory, but possible wasted 
redudant work during function generation is an issue created from this change.
Functions get instantiated only once per server run or when one of their 
dependencies changes, therefore this should happen very rarely.
I also use now a new sql_context lock, to avoid usage of the mal_context lock 
during MAL optimization, which could be dangerous.


diffs (truncated from 855 to 300 lines):

diff --git a/sql/backends/monet5/mal_backend.c 
b/sql/backends/monet5/mal_backend.c
--- a/sql/backends/monet5/mal_backend.c
+++ b/sql/backends/monet5/mal_backend.c
@@ -50,3 +50,14 @@ backend_destroy(backend *b)
                b->subbackend->destroy(b->subbackend);
        _DELETE(b);
 }
+
+/* for recursive functions, if the implementation is not set yet, take it from 
the current compilation */
+str
+backend_function_imp(backend *b, sql_func *f)
+{
+       str res = sql_func_imp(f);
+
+       if (b->mvc->forward && strcmp(res, "") == 0 && b->mvc->forward->base.id 
== f->base.id)
+               res = b->fimp;
+       return res;
+}
diff --git a/sql/backends/monet5/mal_backend.h 
b/sql/backends/monet5/mal_backend.h
--- a/sql/backends/monet5/mal_backend.h
+++ b/sql/backends/monet5/mal_backend.h
@@ -63,10 +63,12 @@ typedef struct backend {
        lng last_id;
        lng rowcnt;
        subbackend *subbackend;
+       str fimp; /* for recurisve functions keep the to be generated MAL 
function name here */
 } backend;
 
 extern backend *backend_reset(backend *b);
 extern backend *backend_create(mvc *m, Client c);
 extern void backend_destroy(backend *b);
+extern str backend_function_imp(backend *b, sql_func *f);
 
 #endif /*MAL_BACKEND_H*/
diff --git a/sql/backends/monet5/rel_bin.c b/sql/backends/monet5/rel_bin.c
--- a/sql/backends/monet5/rel_bin.c
+++ b/sql/backends/monet5/rel_bin.c
@@ -1249,7 +1249,7 @@ exp_bin(backend *be, sql_exp *e, stmt *l
                if (f->func->lang == FUNC_LANG_MAL && 
backend_create_mal_func(be->mvc, f->func) < 0)
                        return NULL;
                mod = sql_func_mod(f->func);
-               fimp = sql_func_imp(f->func);
+               fimp = backend_function_imp(be, f->func);
 
                if (f->func->side_effect && left && left->nrcols > 0 && 
f->func->type != F_LOADER && exps_card(exps) < CARD_MULTI) {
                        rows = bin_find_smallest_column(be, left);
@@ -2130,7 +2130,7 @@ rel2bin_table(backend *be, sql_rel *rel,
                                        if (backend_create_subfunc(be, f, ops) 
< 0)
                                                return NULL;
                                        str mod = sql_func_mod(f->func);
-                                       str fcn = sql_func_imp(f->func);
+                                       str fcn = backend_function_imp(be, 
f->func);
                                        q = pushStr(be->mb, q, mod);
                                        q = pushStr(be->mb, q, fcn);
                                        psub = stmt_direct_func(be, q);
diff --git a/sql/backends/monet5/sql_gencode.c 
b/sql/backends/monet5/sql_gencode.c
--- a/sql/backends/monet5/sql_gencode.c
+++ b/sql/backends/monet5/sql_gencode.c
@@ -943,41 +943,79 @@ monet5_has_module(ptr M, char *module)
        return 0;
 }
 
+static MT_Lock sql_gencodeLock = MT_LOCK_INITIALIZER(sql_gencodeLock);
+
+static str
+monet5_cache_remove(Module m, const char *nme)
+{
+       /* Warning, this function doesn't do any locks, so be careful with 
concurrent symbol insert/deletes */
+       Symbol s = findSymbolInModule(m, nme);
+       if (s == NULL)
+               throw(MAL, "cache.remove", SQLSTATE(42000) "internal error, 
symbol missing\n");
+       deleteSymbol(m, s);
+       return MAL_SUCCEED;
+}
+
+/* if 'mod' not NULL, use it otherwise get the module from the client id */
+void
+monet5_freecode(const char *mod, int clientid, const char *name)
+{
+       Module m = NULL;
+       str msg = MAL_SUCCEED;
+
+       if (mod) {
+               m = getModule(putName(mod));
+       } else {
+               Client c = MCgetClient(clientid);
+               if (c)
+                       m = c->usermodule;
+       }
+       if (m) {
+               if (mod)
+                       MT_lock_set(&sql_gencodeLock);
+               msg = monet5_cache_remove(m, name);
+               if (mod)
+                       MT_lock_unset(&sql_gencodeLock);
+               freeException(msg); /* do something with error? */
+       }
+}
+
+/* the function 'f' may not have the 'imp' field set yet */
 int
-monet5_resolve_function(ptr M, sql_func *f)
+monet5_resolve_function(ptr M, sql_func *f, const char *fimp, bit *side_effect)
 {
        Client c;
        Module m;
        int clientID = *(int*) M;
-       const char *mname = putName(sql_func_mod(f)), *fname = 
putName(sql_func_imp(f));
+       const char *mname = putName(sql_func_mod(f)), *fname = putName(fimp);
 
        if (!mname || !fname)
                return 0;
 
        /* Some SQL functions MAL mapping such as count(*) aggregate, the 
number of arguments don't match */
        if (mname == calcRef && fname == getName("=")) {
-               f->side_effect = 0;
+               *side_effect = 0;
                return 1;
        }
        if (mname == aggrRef && (fname == countRef || fname == 
count_no_nilRef)) {
-               f->side_effect = 0;
+               *side_effect = 0;
                return 1;
        }
        if (f->type == F_ANALYTIC) {
-               f->side_effect = 0;
+               *side_effect = 0;
                return 1;
        }
 
        c = MCgetClient(clientID);
-       MT_lock_set(&mal_contextLock);
+       MT_lock_set(&sql_gencodeLock);
        for (m = findModule(c->usermodule, mname); m; m = m->link) {
                for (Symbol s = findSymbolInModule(m, fname); s; s = s->peer) {
                        InstrPtr sig = getSignature(s);
                        int argc = sig->argc - sig->retc, nfargs = 
list_length(f->ops), nfres = list_length(f->res);
 
                        if ((sig->varargs & VARARGS) == VARARGS || f->vararg || 
f->varres) {
-                               f->side_effect = (bit) s->def->unsafeProp;
-                               MT_lock_unset(&mal_contextLock);
+                               *side_effect = (bit) s->def->unsafeProp;
+                               MT_lock_unset(&sql_gencodeLock);
                                return 1;
                        } else if (nfargs == argc && (nfres == sig->retc || 
(sig->retc == 1 && (IS_FILT(f) || IS_PROC(f))))) {
                                /* I removed this code because, it was 
triggering many errors on te SQL <-> MAL translation */
@@ -1013,18 +1051,18 @@ monet5_resolve_function(ptr M, sql_func 
                                        }
                                }
                                if (all_match)*/
-                               f->side_effect = (bit) s->def->unsafeProp;
-                               MT_lock_unset(&mal_contextLock);
+                               *side_effect = (bit) s->def->unsafeProp;
+                               MT_lock_unset(&sql_gencodeLock);
                                return 1;
                        }
                }
        }
-       MT_lock_unset(&mal_contextLock);
+       MT_lock_unset(&sql_gencodeLock);
        return 0;
 }
 
 /* Parse the SQL query from the function, and extract the MAL function from 
the generated abstract syntax tree */
-static int
+static str
 mal_function_find_implementation_address(mvc *m, sql_func *f)
 {
        buffer *b = NULL;
@@ -1033,28 +1071,24 @@ mal_function_find_implementation_address
        char *n = NULL;
        int len = _strlen(f->query);
        dlist *l, *ext_name;
+       str fimp = NULL;
 
-       if (!(b = (buffer*)malloc(sizeof(buffer)))) {
-               (void) sql_error(m, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
-               return -1;
-       }
+       if (!(b = (buffer*)malloc(sizeof(buffer))))
+               return sql_error(m, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
        if (!(n = malloc(len + 2))) {
                free(b);
-               (void) sql_error(m, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
-               return -1;
+               return sql_error(m, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
        }
        snprintf(n, len + 2, "%s\n", f->query);
        len++;
        buffer_init(b, n, len);
        if (!(buf = buffer_rastream(b, "sqlstatement"))) {
                buffer_destroy(b);
-               (void) sql_error(m, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
-               return -1;
+               return sql_error(m, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
        }
        if (!(bs = bstream_create(buf, b->len))) {
                buffer_destroy(b);
-               (void) sql_error(m, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
-               return -1;
+               return sql_error(m, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
        }
        mvc o = *m;
        scanner_init(&m->scanner, bs, NULL);
@@ -1076,10 +1110,9 @@ mal_function_find_implementation_address
                ext_name = l->h->next->next->next->data.lval;
                const char *imp = qname_schema_object(ext_name);
 
-               assert(!f->imp);
                if (strlen(imp) >= IDLENGTH)
                        (void) sql_error(m, 10, SQLSTATE(42000) "MAL function 
name '%s' too large for the backend", imp);
-               else if (!(f->imp = _STRDUP(imp))) /* found the implementation, 
set it */
+               else if (!(fimp = _STRDUP(imp))) /* found the implementation, 
set it */
                        (void) sql_error(m, 10, SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
        }
 
@@ -1103,210 +1136,205 @@ mal_function_find_implementation_address
                *m = o;
                m->label = label;
        }
-       return m->errstr[0] == '\0' ? 0 : -1; /* m was set back to o */
+       return fimp;
 }
 
 int
 backend_create_mal_func(mvc *m, sql_func *f)
 {
+       char *F = NULL, *fn = NULL;
+       bit old_side_effect = f->side_effect, new_side_effect = 0;
+       int clientid = m->clientid;
+       str fimp = NULL;
+
        if (f->instantiated)
                return 0;
-       MT_lock_set(&f->function_lock);
+       FUNC_TYPE_STR(f->type, F, fn)
+       (void) F;
+       if (strlen(f->mod) >= IDLENGTH) {
+               (void) sql_error(m, 10, SQLSTATE(42000) "MAL module name '%s' 
too large for the backend", f->mod);
+               return -1;
+       }
+       if (!(fimp = mal_function_find_implementation_address(m, f)))
+               return -1;
+       if (!backend_resolve_function(&clientid, f, fimp, &new_side_effect)) {
+               (void) sql_error(m, 10, SQLSTATE(3F000) "MAL external name 
%s.%s not bound (%s.%s)", f->mod, fimp, f->s->base.name, f->base.name);
+               return -1;
+       }
+       if (old_side_effect != new_side_effect) {
+               (void) sql_error(m, 10, SQLSTATE(42000) "Side-effect value from 
the SQL %s %s.%s doesn't match the MAL definition %s.%s\n"
+                                                "Either re-create the %s, or 
fix the MAL definition and restart the database", fn, f->s->base.name, 
f->base.name, f->mod, fimp, fn);
+               return -1;
+       }
+       MT_lock_set(&sql_gencodeLock);
        if (!f->instantiated) {
-               char *F = NULL, *fn = NULL;
-               bit side_effect = f->side_effect;
-               int clientid = m->clientid;
-
-               FUNC_TYPE_STR(f->type, F, fn)
-               (void) F;
-               if (strlen(f->mod) >= IDLENGTH) {
-                       (void) sql_error(m, 10, SQLSTATE(42000) "MAL module 
name '%s' too large for the backend", f->mod);
-                       MT_lock_unset(&f->function_lock);
-                       return -1;
-               }
-               if (mal_function_find_implementation_address(m, f) < 0) {
-                       MT_lock_unset(&f->function_lock);
-                       return -1;
-               }
-               if (!backend_resolve_function(&clientid, f)) {
-                       (void) sql_error(m, 10, SQLSTATE(3F000) "MAL external 
name %s.%s not bound (%s.%s)", f->mod, f->imp, f->s->base.name, f->base.name);
-                       _DELETE(f->imp);
-                       MT_lock_unset(&f->function_lock);
-                       return -1;
-               }
-               if (side_effect != f->side_effect) {
-                       (void) sql_error(m, 10, SQLSTATE(42000) "Side-effect 
value from the SQL %s %s.%s doesn't match the MAL definition %s.%s\n"
-                                                        "Either re-create the 
%s, or fix the MAL definition and restart the database", fn, f->s->base.name, 
f->base.name, f->mod, f->imp, fn);
-                       _DELETE(f->imp);
-                       MT_lock_unset(&f->function_lock);
-                       return -1;
-               }
+               f->imp = fimp;
                f->instantiated = TRUE; /* make sure 'instantiated' gets set 
after 'imp' */
+       } else {
+               _DELETE(fimp);
        }
-       MT_lock_unset(&f->function_lock);
+       MT_lock_unset(&sql_gencodeLock);
        return 0;
 }
 
 static int
 backend_create_sql_func(backend *be, sql_func *f, list *restypes, list *ops)
 {
-       int res = 0;
        mvc *m = be->mvc;
+       MalBlkPtr curBlk = NULL;
+       InstrPtr curInstr = NULL;
+       Client c = be->client;
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to