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

Use a read-write lock for the embedded database. With this approach, queries 
can run in parallel. The implementation of the lock is very basic, i.e a single 
MT_lock is used. However this suffices it's only purpose so far.


diffs (truncated from 321 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
@@ -37,15 +37,15 @@ typedef struct {
        monetdb_column **converted_columns;
 } monetdb_result_internal;
 
-static MT_Lock embedded_lock = MT_LOCK_INITIALIZER("embedded_lock");
+static MT_RWLock embedded_lock = MT_RWLOCK_INITIALIZER("embedded_lock");
 static bool monetdb_embedded_initialized = false;
 
 bool
 monetdb_is_initialized(void)
 {
-       MT_lock_set(&embedded_lock);
+       MT_rwlock_read_set(&embedded_lock);
        bool res = monetdb_embedded_initialized;
-       MT_lock_unset(&embedded_lock);
+       MT_rwlock_read_unset(&embedded_lock);
        return res;
 }
 
@@ -327,9 +327,9 @@ monetdb_connect(monetdb_connection *conn
        char* msg = MAL_SUCCEED;
        if (!conn)
                return createException(MAL, 
"embedded.monetdb_connect_internal", "monetdb_connection parameter is NULL");
-       MT_lock_set(&embedded_lock);
+       MT_rwlock_read_set(&embedded_lock);
        msg = monetdb_connect_internal(conn);
-       MT_lock_unset(&embedded_lock);
+       MT_rwlock_read_unset(&embedded_lock);
        return msg;
 }
 
@@ -337,9 +337,9 @@ char*
 monetdb_disconnect(monetdb_connection conn)
 {
        char* msg = MAL_SUCCEED;
-       MT_lock_set(&embedded_lock);
+       MT_rwlock_read_set(&embedded_lock);
        msg = monetdb_disconnect_internal(conn);
-       MT_lock_unset(&embedded_lock);
+       MT_rwlock_read_unset(&embedded_lock);
        return msg;
 }
 
@@ -362,7 +362,7 @@ monetdb_startup(char* dbdir, bool silent
        int setlen;
        gdk_return gdk_res;
 
-       MT_lock_set(&embedded_lock);
+       MT_rwlock_write_set(&embedded_lock);
        GDKfataljumpenable = 1;
        if(setjmp(GDKfataljump) != 0) {
                msg = GDKfatalmsg;
@@ -427,7 +427,7 @@ cleanup:
        if (msg)
                monetdb_shutdown_internal();
 done:
-       MT_lock_unset(&embedded_lock);
+       MT_rwlock_write_unset(&embedded_lock);
        return msg;
 }
 
@@ -437,9 +437,9 @@ monetdb_clear_prepare(monetdb_connection
        char query[64], *msg;
 
        sprintf(query, "release "LLFMT, id); //no need to validate at this level
-       MT_lock_set(&embedded_lock);
+       MT_rwlock_read_set(&embedded_lock);
        msg = monetdb_query_internal(conn, query, NULL, NULL, NULL, 'X');
-       MT_lock_unset(&embedded_lock);
+       MT_rwlock_read_unset(&embedded_lock);
        return msg;
 }
 
@@ -449,9 +449,9 @@ monetdb_send_close(monetdb_connection co
        char query[64], *msg;
 
        sprintf(query, "close "LLFMT, id); //no need to validate at this level
-       MT_lock_set(&embedded_lock);
+       MT_rwlock_read_set(&embedded_lock);
        msg = monetdb_query_internal(conn, query, NULL, NULL, NULL, 'X');
-       MT_lock_unset(&embedded_lock);
+       MT_rwlock_read_unset(&embedded_lock);
        return msg;
 }
 
@@ -461,9 +461,9 @@ monetdb_set_autocommit(monetdb_connectio
        char query[64], *msg;
 
        sprintf(query, "auto_commit %"PRIi8, value); //no need to validate at 
this level
-       MT_lock_set(&embedded_lock);
+       MT_rwlock_read_set(&embedded_lock);
        msg = monetdb_query_internal(conn, query, NULL, NULL, NULL, 'X');
-       MT_lock_unset(&embedded_lock);
+       MT_rwlock_read_unset(&embedded_lock);
        return msg;
 }
 
@@ -471,9 +471,9 @@ char*
 monetdb_query(monetdb_connection conn, char* query, monetdb_result** result, 
int64_t* affected_rows, int64_t* prepare_id)
 {
        char* msg;
-       MT_lock_set(&embedded_lock);
+       MT_rwlock_read_set(&embedded_lock);
        msg = monetdb_query_internal(conn, query, result, affected_rows, 
prepare_id, 'S');
-       MT_lock_unset(&embedded_lock);
+       MT_rwlock_read_unset(&embedded_lock);
        return msg;
 }
 
@@ -484,9 +484,9 @@ monetdb_append(monetdb_connection conn, 
        mvc *m;
        char* msg = MAL_SUCCEED;
 
-       MT_lock_set(&embedded_lock);
+       MT_rwlock_read_set(&embedded_lock);
        if ((msg = validate_connection(conn, "embedded.monetdb_append")) != 
MAL_SUCCEED) {
-               MT_lock_unset(&embedded_lock);
+               MT_rwlock_read_unset(&embedded_lock);
                return msg; //The connection is invalid, there is no 
transaction going
        }
 
@@ -557,7 +557,7 @@ monetdb_append(monetdb_connection conn, 
        }
 cleanup:
        msg = commit_action(m, msg);
-       MT_lock_unset(&embedded_lock);
+       MT_rwlock_read_unset(&embedded_lock);
        return msg;
 }
 
@@ -565,9 +565,9 @@ char*
 monetdb_cleanup_result(monetdb_connection conn, monetdb_result* result)
 {
        char* msg = MAL_SUCCEED;
-       MT_lock_set(&embedded_lock);
+       MT_rwlock_read_set(&embedded_lock);
        msg = monetdb_cleanup_result_internal(conn, result);
-       MT_lock_unset(&embedded_lock);
+       MT_rwlock_read_unset(&embedded_lock);
        return msg;
 }
 
@@ -583,9 +583,9 @@ monetdb_get_columns(monetdb_connection c
        node *n;
        Client c = (Client) conn;
 
-       MT_lock_set(&embedded_lock);
+       MT_rwlock_read_set(&embedded_lock);
        if ((msg = validate_connection(conn, "embedded.monetdb_get_columns")) 
!= MAL_SUCCEED) {
-               MT_lock_unset(&embedded_lock);
+               MT_rwlock_read_unset(&embedded_lock);
                return msg;
        }
 
@@ -647,7 +647,7 @@ monetdb_get_columns(monetdb_connection c
 
 cleanup:
        msg = commit_action(m, msg);
-       MT_lock_unset(&embedded_lock);
+       MT_rwlock_read_unset(&embedded_lock);
        return msg;
 }
 
@@ -655,12 +655,12 @@ char*
 monetdb_shutdown(void)
 {
        char* msg = MAL_SUCCEED;
-       MT_lock_set(&embedded_lock);
+       MT_rwlock_write_set(&embedded_lock);
        if (monetdb_embedded_initialized)
                monetdb_shutdown_internal();
        else
                msg = createException(MAL, "embedded.monetdb_shutdown", 
"MonetDBLite has not yet started");
-       MT_lock_unset(&embedded_lock);
+       MT_rwlock_write_unset(&embedded_lock);
        return msg;
 }
 
@@ -732,9 +732,9 @@ monetdb_result_fetch(monetdb_connection 
        size_t j = 0;
        Client c = (Client) conn;
 
-       MT_lock_set(&embedded_lock);
+       MT_rwlock_read_set(&embedded_lock);
        if ((msg = validate_connection(conn, "embedded.monetdb_result_fetch")) 
!= MAL_SUCCEED) {
-               MT_lock_unset(&embedded_lock);
+               MT_rwlock_read_unset(&embedded_lock);
                return msg;
        }
 
@@ -753,7 +753,7 @@ monetdb_result_fetch(monetdb_connection 
        // check if we have the column converted already
        if (result->converted_columns[column_index]) {
                *res = result->converted_columns[column_index];
-               MT_lock_unset(&embedded_lock);
+               MT_rwlock_read_unset(&embedded_lock);
                return MAL_SUCCEED;
        }
 
@@ -924,7 +924,7 @@ cleanup:
                *res = result->converted_columns[column_index];
        }
        msg = commit_action(m, msg);
-       MT_lock_unset(&embedded_lock);
+       MT_rwlock_read_unset(&embedded_lock);
        return msg;
 }
 
@@ -936,9 +936,9 @@ monetdb_result_fetch_rawcol(monetdb_conn
        mvc* m;
        Client c = (Client) conn;
 
-       MT_lock_set(&embedded_lock);
+       MT_rwlock_read_set(&embedded_lock);
        if ((msg = validate_connection(conn, 
"embedded.monetdb_result_fetch_rawcol")) != MAL_SUCCEED) {
-               MT_lock_unset(&embedded_lock);
+               MT_rwlock_read_unset(&embedded_lock);
                return msg;
        }
 
@@ -956,7 +956,7 @@ cleanup:
        else
                *res = &(result->monetdb_resultset->cols[column_index]);
        msg = commit_action(m, msg);
-       MT_lock_unset(&embedded_lock);
+       MT_rwlock_read_unset(&embedded_lock);
        return msg;
 }
 
diff --git a/gdk/gdk_system.h b/gdk/gdk_system.h
--- a/gdk/gdk_system.h
+++ b/gdk/gdk_system.h
@@ -482,6 +482,85 @@ gdk_export ATOMIC_TYPE GDKlocksleepcnt;
 #endif
 
 /*
+ * A simple read-write lock implementation.
+ * 
https://stackoverflow.com/questions/12033188/how-would-you-implement-your-own-reader-writer-lock-in-c11
+ * Very simple implementation, but it does what is required for MonetDBLite so 
far. Later we could avoid starvation of
+ * writers, ordering of requests.
+ * This implementation uses a single global MT_Lock, which bottlenecks a lot.
+ */
+
+typedef struct MT_RWLock {
+       MT_Lock lock;
+       bool writer;
+       int readers;
+} MT_RWLock;
+
+#define MT_RWLOCK_INITIALIZER(n) { .lock = MT_LOCK_INITIALIZER(n), .writer = 
false, .readers = 0, }
+
+#define MT_rwlock_read_set(l) \
+       do { \
+               MT_lock_set(&(l)->lock); \
+               if ((l)->writer) { \
+                       MT_thread_setlockwait(&(l)->lock); \
+                       do { \
+                               MT_lock_unset(&(l)->lock); \
+                               MT_sleep_ms(1); \
+                               MT_lock_set(&(l)->lock); \
+                       } while ((l)->writer); \
+                       MT_thread_setlockwait(NULL); \
+               } \
+               (l)->readers++; \
+               MT_lock_unset(&(l)->lock); \
+       } while (0)
+
+#define MT_rwlock_read_unset(l) \
+       do { \
+               MT_lock_set(&(l)->lock); \
+               assert((l)->readers); \
+               assert(!(l)->writer); \
+               (l)->readers--; \
+               MT_lock_unset(&(l)->lock); \
+       } while (0)
+
+#define MT_rwlock_write_set(l) \
+       do { \
+               MT_lock_set(&(l)->lock); \
+               if ((l)->writer || (l)->readers) { \
+                       MT_thread_setlockwait(&(l)->lock); \
+                       do { \
+                               MT_lock_unset(&(l)->lock); \
+                               MT_sleep_ms(1); \
+                               MT_lock_set(&(l)->lock); \
+                       } while ((l)->writer || (l)->readers); \
+                       MT_thread_setlockwait(NULL); \
+               } \
+               assert(!(l)->readers); \
+               (l)->writer = true; \
+               MT_lock_unset(&(l)->lock); \
+       } while (0)
+
+#define MT_rwlock_write_unset(l) \
+       do { \
+               MT_lock_set(&(l)->lock); \
+               assert((l)->writer); \
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to