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