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