Changeset: 7bd5ca0ce2f1 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=7bd5ca0ce2f1
Modified Files:
        embedded/monetdb_embedded.c
        embedded/monetdb_embedded.h
Branch: cmake-monetdblite
Log Message:

Made MoneDBLite API thread safe.


diffs (truncated from 962 to 300 lines):

diff --git a/embedded/monetdb_embedded.c b/embedded/monetdb_embedded.c
--- a/embedded/monetdb_embedded.c
+++ b/embedded/monetdb_embedded.c
@@ -30,27 +30,53 @@
 #include "rel_updates.h"
 #include "monet_options.h"
 
-static int monetdb_embedded_initialized = 0;
+static MT_Lock embedded_lock = MT_LOCK_INITIALIZER("embedded_lock");
+static bool monetdb_embedded_initialized = false;
 
-int
+bool
 monetdb_is_initialized(void)
 {
-       return monetdb_embedded_initialized > 0;
+       MT_lock_set(&embedded_lock);
+       bool res = monetdb_embedded_initialized;
+       MT_lock_unset(&embedded_lock);
+       return res;
 }
 
 static char*
-validate_connection(monetdb_connection conn, const char* call)
+validate_connection(monetdb_connection conn, const char* call) // Call this 
function always inside the embedded_lock
 {
-       if (!monetdb_is_initialized())
+       if (!monetdb_embedded_initialized)
                return createException(MAL, call, SQLSTATE(HY001) "Embedded 
MonetDB is not started");
        if (!MCvalid((Client) conn))
                return createException(MAL, call, SQLSTATE(HY001) "Invalid 
connection");
        return MAL_SUCCEED;
 }
 
-static MT_Lock embedded_lock = MT_LOCK_INITIALIZER("embedded_lock");
+static void
+monetdb_destroy_column(monetdb_column* column)
+{
+       size_t j;
+
+       if (!column)
+               return;
 
-static void monetdb_destroy_column(monetdb_column* column);
+       if (column->type == monetdb_str) {
+               // FIXME: clean up individual strings
+               char** data = (char**)column->data;
+               for(j = 0; j < column->count; j++) {
+                       if (data[j])
+                               GDKfree(data[j]);
+               }
+       } else if (column->type == monetdb_blob) {
+               monetdb_data_blob* data = (monetdb_data_blob*)column->data;
+               for(j = 0; j < column->count; j++) {
+                       if (data[j].data)
+                               GDKfree(data[j].data);
+               }
+       }
+       GDKfree(column->data);
+       GDKfree(column);
+}
 
 typedef struct {
        monetdb_result res;
@@ -58,153 +84,26 @@ typedef struct {
        monetdb_column **converted_columns;
 } monetdb_result_internal;
 
-char*
-monetdb_connect(monetdb_connection *conn)
-{
-       mvc *m;
-       char* msg = MAL_SUCCEED;
-       Client mc = NULL;
-
-       if (!monetdb_is_initialized()) {
-               msg = createException(MAL, "embedded.monetdb_connect", 
SQLSTATE(42000) "Embedded MonetDB is not started");
-               goto cleanup;
-       }
-       if (!conn) {
-               msg = createException(MAL, "embedded.monetdb_connect", 
SQLSTATE(42000) "monetdb_connection parameter is NULL");
-               goto cleanup;
-       }
-       mc = MCinitClient((oid) 0, 0, 0);
-       if (!MCvalid(mc)) {
-               msg = createException(MAL, "embedded.monetdb_connect", 
SQLSTATE(HY001) "Failed to initialize client");
-               goto cleanup;
-       }
-       mc->curmodule = mc->usermodule = userModule();
-       if (mc->usermodule == NULL) {
-               msg = createException(MAL, "embedded.monetdb_connect", 
SQLSTATE(HY001) "Failed to initialize client MAL module");
-               goto cleanup;
-       }
-       if ((msg = SQLinitClient(mc)) != MAL_SUCCEED)
-               goto cleanup;
-       if ((msg = getSQLContext(mc, NULL, &m, NULL)) != MAL_SUCCEED)
-               goto cleanup;
-       m->session->auto_commit = 1;
-
-cleanup:
-       if (msg && mc) {
-               char* other = monetdb_disconnect(mc);
-               if (other)
-                       GDKfree(other);
-               *conn = NULL;
-       } else if(conn)
-               *conn = mc;
-       return msg;
-}
-
-char*
-monetdb_disconnect(monetdb_connection conn)
-{
-       char* msg = MAL_SUCCEED;
-
-       if ((msg = validate_connection(conn, "embedded.monetdb_disconnect")) != 
MAL_SUCCEED)
-               return msg;
-       SQLexitClient((Client) conn);
-       MCcloseClient((Client) conn);
-       return MAL_SUCCEED;
-}
-
 static char*
-monetdb_shutdown_internal(void)
-{
-       if (monetdb_embedded_initialized) {
-               malEmbeddedReset();
-               monetdb_embedded_initialized = 0;
-       }
-       return MAL_SUCCEED;
-}
-
-char*
-monetdb_startup(char* dbdir, char silent, char sequential)
+monetdb_cleanup_result_internal(monetdb_connection conn, monetdb_result* 
result)
 {
        char* msg = MAL_SUCCEED;
-       monetdb_result* res = NULL;
-       void* c;
-       opt *set = NULL;
-       int setlen;
-       gdk_return gdk_res;
+       monetdb_result_internal* res = (monetdb_result_internal *) result;
 
-       MT_lock_set(&embedded_lock);
-       GDKfataljumpenable = 1;
-       if(setjmp(GDKfataljump) != 0) {
-               msg = GDKfatalmsg;
-               // we will get here if GDKfatal was called.
-               if (msg == NULL)
-                       msg = createException(MAL, "embedded.monetdb_startup", 
SQLSTATE(HY002) "GDKfatal() with unspecified error");
-               goto cleanup;
-       }
-
-       if (monetdb_embedded_initialized)
-               goto cleanup;
+       if ((msg = validate_connection(conn, 
"embedded.monetdb_cleanup_result_internal")) != MAL_SUCCEED)
+               return msg;
 
-       if (silent)
-               MT_fprintf_silent(true);
+       if (res->monetdb_resultset)
+               res_tables_destroy(res->monetdb_resultset);
 
-       if ((setlen = mo_builtin_settings(&set)) == 0) {
-               msg = createException(MAL, "embedded.monetdb_startup", 
SQLSTATE(HY001) MAL_MALLOC_FAIL);
-               goto cleanup;
-       }
-       if (dbdir && (setlen = mo_add_option(&set, setlen, opt_cmdline, 
"gdk_dbpath", dbdir)) == 0) {
-               mo_free_options(set, setlen);
-               msg = createException(MAL, "embedded.monetdb_startup", 
SQLSTATE(HY001) MAL_MALLOC_FAIL);
-               goto cleanup;
-       }
-       if (sequential)
-               setlen = mo_add_option(&set, setlen, opt_cmdline, 
"sql_optimizer", "sequential_pipe");
-       else
-               setlen = mo_add_option(&set, setlen, opt_cmdline, 
"sql_optimizer", "default_pipe");
-       if (setlen == 0) {
-               mo_free_options(set, setlen);
-               msg = createException(MAL, "embedded.monetdb_startup", 
SQLSTATE(HY001) MAL_MALLOC_FAIL);
-               goto cleanup;
+       if (res->converted_columns) {
+               size_t i;
+               for (i = 0; i < res->res.ncols; i++)
+                       monetdb_destroy_column(res->converted_columns[i]);
+               GDKfree(res->converted_columns);
        }
-       gdk_res = GDKinit(set, setlen);
-       mo_free_options(set, setlen);
-       if (gdk_res == GDK_FAIL) {
-               msg = createException(MAL, "embedded.monetdb_startup", 
SQLSTATE(HY002) "GDKinit() failed");
-               goto cleanup;
-       }
-
-       if ((msg = malEmbeddedBoot()) != MAL_SUCCEED)
-               goto cleanup;
-       if (!SQLisInitialized()) {
-               msg = createException(MAL, "embedded.monetdb_startup", 
SQLSTATE(HY002) "SQL initialization failed");
-               goto cleanup;
-       }
-
-       monetdb_embedded_initialized = true;
-
-       if ((msg = monetdb_connect(&c)) != MAL_SUCCEED)
-               goto cleanup;
-       GDKfataljumpenable = 0;
+       GDKfree(res);
 
-       // we do not want to jump after this point, since we cannot do so 
between threads
-       // sanity check, run a SQL query
-       if ((msg = monetdb_query(c, "SELECT id FROM _tables LIMIT 1;", &res, 
NULL, NULL)) != MAL_SUCCEED) {
-               monetdb_embedded_initialized = false;
-               goto cleanup;
-       }
-       if ((msg = monetdb_cleanup_result(c, res)) != MAL_SUCCEED) {
-               monetdb_embedded_initialized = false;
-               goto cleanup;
-       }
-       if ((msg = monetdb_disconnect(c)) != MAL_SUCCEED) {
-               monetdb_embedded_initialized = false;
-               goto cleanup;
-       }
-
-cleanup:
-       if (msg)
-               monetdb_shutdown_internal();
-       MT_lock_unset(&embedded_lock);
        return msg;
 }
 
@@ -212,16 +111,16 @@ static char*
 monetdb_query_internal(monetdb_connection conn, char* query, monetdb_result** 
result, int64_t* affected_rows,
                                           int64_t* prepare_id, char language)
 {
-       char* msg = MAL_SUCCEED, *commit_msg;
+       char* msg = MAL_SUCCEED, *commit_msg = MAL_SUCCEED;
        Client c = (Client) conn;
-       mvc* m;
+       mvc* m = NULL;
        backend *b;
-       char *nq, *qname = "somequery";
+       char *nq = NULL, *qname = "somequery";
        size_t query_len;
        buffer query_buf;
        stream *query_stream;
        monetdb_result_internal *res_internal = NULL;
-       bstream *old_bstream;
+       bstream *old_bstream = NULL;
 
        if ((msg = validate_connection(conn, 
"embedded.monetdb_query_internal")) != MAL_SUCCEED)
                return msg;
@@ -232,12 +131,15 @@ monetdb_query_internal(monetdb_connectio
 
        if (!query)
                return createException(MAL, "embedded.monetdb_query_internal", 
SQLSTATE(42000) "Query missing");
-       if (!(query_stream = buffer_rastream(&query_buf, qname)))
-               return createException(MAL, "embedded.monetdb_query_internal", 
SQLSTATE(HY001) "WARNING: could not setup query stream.");
+       if (!(query_stream = buffer_rastream(&query_buf, qname))) {
+               msg = createException(MAL, "embedded.monetdb_query_internal", 
SQLSTATE(HY001) "WARNING: could not setup query stream.");
+               goto cleanup;
+       }
        query_len = strlen(query) + 3;
-       nq = GDKmalloc(query_len);
-       if (!nq)
-               return createException(MAL, "embedded.monetdb_query_internal", 
SQLSTATE(HY001) "WARNING: could not setup query stream.");
+       if (!(nq = GDKmalloc(query_len))) {
+               msg = createException(MAL, "embedded.monetdb_query_internal", 
SQLSTATE(HY001) "WARNING: could not setup query stream.");
+               goto cleanup;
+       }
        sprintf(nq, "%s\n;", query);
 
        query_buf.pos = 0;
@@ -272,8 +174,7 @@ monetdb_query_internal(monetdb_connectio
                *affected_rows = m->rowcnt;
 
        if (result) {
-               res_internal = GDKzalloc(sizeof(monetdb_result_internal));
-               if (!res_internal) {
+               if (!(res_internal = 
GDKzalloc(sizeof(monetdb_result_internal)))) {
                        msg = createException(MAL, 
"embedded.monetdb_query_internal", SQLSTATE(HY001) MAL_MALLOC_FAIL);
                        goto cleanup;
                }
@@ -309,15 +210,19 @@ monetdb_query_internal(monetdb_connectio
        }
 
 cleanup:
-       GDKfree(nq);
+       if (nq)
+               GDKfree(nq);
        MSresetInstructions(c->curprg->def, 1);
-       bstream_destroy(c->fdin);
-       c->fdin = old_bstream;
+       if (old_bstream) { //c->fdin was set
+               bstream_destroy(c->fdin);
+               c->fdin = old_bstream;
+       }
 
-       commit_msg = SQLautocommit(m); //need always to commit even if msg is 
set
+       if (m) //the connection is valid and a query was attempted
+               commit_msg = SQLautocommit(m); //need always to commit even if 
msg is set
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to