Changeset: 583ffdb030f0 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/583ffdb030f0
Branch: multi-cachelock
Log Message:

Merge with default.


diffs (truncated from 452 to 300 lines):

diff --git a/.hgtags b/.hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -785,3 +785,4 @@ 47675351fec22d5d5dc81eec03dfa08f505afc99
 47675351fec22d5d5dc81eec03dfa08f505afc99 Sep2022_release
 44e45c9a451f6afd933773094ec25723f713d3be Jan2022_23
 44e45c9a451f6afd933773094ec25723f713d3be Jan2022_SP5_release
+43d4a717410d6f6692a16a878640fc7e0f248725 Jan2022_25
diff --git a/clients/examples/C/testcondvar.c b/clients/examples/C/testcondvar.c
--- a/clients/examples/C/testcondvar.c
+++ b/clients/examples/C/testcondvar.c
@@ -16,7 +16,12 @@
 
 volatile int timeout = 100; // set this to 0 during interactive debugging
 
-/* global state protected by a lock: */
+/* global state protected by a lock.
+ *
+ * Every worker thread has a number of permits and a number of ticks.
+ * It sleeps on the condition variable, whenever it wakes it will
+ * try to convert one permit into a tick, that is, permit-- and tick++.
+ */
 
 MT_Lock lock = MT_LOCK_INITIALIZER(lock);
 MT_Cond condvar = MT_COND_INITIALIZER(the_condvar);
@@ -28,7 +33,15 @@ struct state {
        bool terminated;
 } states[NN] = { {0} };
 
-
+/*
+ * The main thread holds the lock so it can manipulate and verify the permits
+ * and ticks.  It uses this function to temporarily release the lock so the
+ * workers get a chance to do their work. We give them a 100ms, which should be
+ * plenty.
+ *
+ * If we cannot retake the lock after that interval we assume a worker thread
+ * has gone astray while holding the lock.
+ */
 static void
 let_run(void)
 {
@@ -36,16 +49,17 @@ let_run(void)
 
        MT_sleep_ms(100);
 
+       // try to retake the lock. Make a few attempts before giving up.
        int attempts = 0;
        while (!MT_lock_try(&lock)) {
                if (timeout > 0 && ++attempts > timeout) {
                        fprintf(stderr, "Can't get hold of the lock after %d 
attempts\n", attempts);
+                       fprintf(stderr, "If this is because you're running this 
program in a debugger,\n");
+                       fprintf(stderr, "try setting the timeout variable to 
0.\n");
                        abort();
                }
                MT_sleep_ms(10);
        }
-
-       fprintf(stderr, "\n");
 }
 
 
@@ -54,9 +68,10 @@ worker(void *arg)
 {
        struct state *st = arg;
        int id = (int)(st - &states[0]);
-       fprintf(stderr, "worker %d starting\n", id);
+       fprintf(stderr, "worker %d started, waiting to acquire lock\n", id);
 
        MT_lock_set(&lock);
+       fprintf(stderr, "worker %d acquired lock\n", id);
        while (1) {
                if (st->terminate) {
                        fprintf(stderr, "worker %d terminating\n", id);
@@ -67,7 +82,7 @@ worker(void *arg)
                        st->ticks++;
                        st->permits--;
                }
-               fprintf(stderr, "worker %d waiting\n", id);
+               fprintf(stderr, "worker %d waiting on condvar\n", id);
                MT_cond_wait(&condvar, &lock);
                fprintf(stderr, "worker %d woke up\n", id);
        }
@@ -76,16 +91,6 @@ worker(void *arg)
 }
 
 
-static void clear(void)
-{
-       for (int i = 0; i < NN; i++) {
-               struct state *st = &states[i];
-               st->permits = 0;
-               st->ticks = 0;
-       }
-}
-
-
 static void
 check_impl(int line, int expected_sum_ticks, int expected_max_ticks, int 
expected_sum_permits)
 {
@@ -101,17 +106,26 @@ check_impl(int line, int expected_sum_ti
                        max_ticks = ticks;
        }
 
+       fprintf(stderr, "On line %d: (sum_ticks, max_ticks, sum_permits) = (%d, 
%d, %d)\n",
+                       line,
+                       sum_ticks, max_ticks, sum_permits);
+
        bool good = true;
        good &= (sum_ticks == expected_sum_ticks);
-       good &= (max_ticks == expected_max_ticks);
+       if (expected_max_ticks >= 0)
+               good &= (max_ticks == expected_max_ticks);
        good &= (sum_permits == expected_sum_permits);
        if (good)
                return;
 
-       fprintf(stderr, "\nOn line %d:\n", line);
-       fprintf(stderr, "Expect sum ticks to be %d, is %d\n", 
expected_sum_ticks, sum_ticks);
-       fprintf(stderr, "Expect max ticks to be %d, is %d\n", 
expected_max_ticks, max_ticks);
-       fprintf(stderr, "Expect sum permits to be %d, is %d\n", 
expected_sum_permits, sum_permits);
+       if (expected_max_ticks >= 0) {
+               fprintf(stderr, "MISMATCH: expected (%d, %d, %d)\n",
+                       expected_sum_ticks, expected_max_ticks, 
expected_sum_permits);
+       } else {
+               fprintf(stderr, "MISMATCH: expected (%d, ?, %d)\n",
+                       expected_sum_ticks, expected_sum_permits);
+       }
+
        for (int i = 0; i < NN; i++) {
                fprintf(stderr, "worker %d: ticks=%d permits=%d\n", i, 
states[i].ticks, states[i].permits);
        }
@@ -125,46 +139,54 @@ main(void)
 {
        MT_thread_init();
 
+       // All code in this function runs while we hold the lock.
+       // From time to time we call let_run() to allow the worker threads to 
obtain it.
        MT_lock_set(&lock);
+
+       fprintf(stderr, "-- Initially, everything is zero\n");
        check(0, 0, 0);
 
+       fprintf(stderr, "\n-- Starting the worker threads\n");
        for (int i = 0; i < NN; i++) {
                struct state *st = &states[i];
                char name[MT_NAME_LEN];
                snprintf(name, sizeof(name), "worker%d", i);
                MT_create_thread(&st->id, worker, st, MT_THR_JOINABLE, name);
        }
-       check(0, 0, 0);
+       MT_sleep_ms(100);
 
+       fprintf(stderr, "\n-- Now allow the workers to take the lock, they 
should enter their main loop\n");
        let_run();
        check(0, 0, 0);
 
-       // give them all a permit and broadcast on the condvar. they should all 
run
+       fprintf(stderr, "\n-- All threads get a permit but nothing happens 
because we haven't touched the condvar\n");
        for (int i = 0; i < NN; i++)
                states[i].permits = 1;
        let_run();
-       // haven't notified them yet:
-       check(0, 0, 3);
+       check(0, 0, NN);
+
+       fprintf(stderr, "\n-- Now we broadcast on the condvar. All should 
wake\n");
        MT_cond_broadcast(&condvar);
        let_run();
-       check(3, 1, 0);
+       check(NN, 1, 0);
+
+       fprintf(stderr, "\n-- Now we give each of them %d permits\n", NN);
+       for (int i = 0; i < NN; i++) {
+               states[i].ticks = 0;
+               states[i].permits = NN;
+       }
+       check(0, 0, NN * NN);
 
-       // when using signal, we need to trigger them three times
-       clear();
-       for (int i = 0; i < NN; i++)
-               states[i].permits = 1;
-       let_run();
-       check(0, 0, 3);
-       MT_cond_signal(&condvar);
-       let_run();
-       check(1, 1, 2);
-       MT_cond_signal(&condvar);
-       let_run();
-       check(2, 1, 1);
-       MT_cond_signal(&condvar);
-       let_run();
-       check(3, 1, 0);
+       // Note: counting from 1 instead of 0
+       for (int i = 1; i <= NN; i++) {
+               fprintf(stderr, "\n-- [%d] Signal one, don't know which one it 
will be\n", i);
+               MT_cond_signal(&condvar);
+               let_run();
+               check(i, -1, NN * NN - i);
+       }
 
+
+       fprintf(stderr, "\n-- Telling them all to quit\n");
        for (int i = 0; i < NN; i++) {
                states[i].terminate = true;
        }
@@ -172,12 +194,11 @@ main(void)
        let_run();
 
        for (int i = 0; i < NN; i++) {
-               fprintf(stderr, "joining worker %d\n", i);
+               fprintf(stderr, "-- Joining worker %d\n", i);
                MT_join_thread(states[i].id);
+               fprintf(stderr, "-- Joined worker %d\n", i);
        }
-       fprintf(stderr, "joined all, exiting\n");
+       fprintf(stderr, "\n-- Joined all, exiting\n");
 
-       (void)worker;
-       (void)let_run;
        return 0;
 }
diff --git a/gdk/gdk_bat.c b/gdk/gdk_bat.c
--- a/gdk/gdk_bat.c
+++ b/gdk/gdk_bat.c
@@ -2198,9 +2198,14 @@ backup_new(Heap *hp, bool lock)
        char *batpath, *bakpath;
        struct stat st;
 
+       char *bak_filename = NULL;
+       if ((bak_filename = strrchr(hp->filename, DIR_SEP)) != NULL)
+               bak_filename++;
+       else
+               bak_filename = hp->filename;
        /* check for an existing X.new in BATDIR, BAKDIR and SUBDIR */
        batpath = GDKfilepath(hp->farmid, BATDIR, hp->filename, "new");
-       bakpath = GDKfilepath(hp->farmid, BAKDIR, hp->filename, "new");
+       bakpath = GDKfilepath(hp->farmid, BAKDIR, bak_filename, "new");
        if (batpath != NULL && bakpath != NULL) {
                /* file actions here interact with the global commits */
                if (lock)
diff --git a/geom/lib/libgeom.c b/geom/lib/libgeom.c
--- a/geom/lib/libgeom.c
+++ b/geom/lib/libgeom.c
@@ -23,7 +23,7 @@ geomerror(_In_z_ _Printf_format_string_ 
        char err[256];
        va_start(va, fmt);
        vsnprintf(err, sizeof(err), fmt, va);
-       GDKtracer_log(__FILE__, __func__, __LINE__, M_CRITICAL,
+       GDKtracer_log(__FILE__, __func__, __LINE__, M_ERROR,
                      GDK, NULL, "%s", err);
        va_end(va);
 }
diff --git a/sql/jdbc/tests/Tests/OnClientTester.SQL.py 
b/sql/jdbc/tests/Tests/OnClientTester.SQL.py
--- a/sql/jdbc/tests/Tests/OnClientTester.SQL.py
+++ b/sql/jdbc/tests/Tests/OnClientTester.SQL.py
@@ -20,11 +20,3 @@ try:
 except CalledProcessError as e:
     raise SystemExit(e.stderr)
 
-
-
-##!/bin/sh
-#
-#URL="jdbc:monetdb://${HOST}:${MAPIPORT}/${TSTDB}?user=monetdb&password=monetdb${JDBC_EXTRA_ARGS}"
-#TST=$1
-#
-#java ${TST} "${URL}"
diff --git a/sql/test/concurrent/Tests/All b/sql/test/concurrent/Tests/All
--- a/sql/test/concurrent/Tests/All
+++ b/sql/test/concurrent/Tests/All
@@ -4,3 +4,4 @@ segments-corruption
 read-segment-after-free
 smart-segment-merge
 many-concurrent-client-connections
+truncate-insert-flood
diff --git a/sql/test/concurrent/Tests/truncate-insert-flood.py 
b/sql/test/concurrent/Tests/truncate-insert-flood.py
new file mode 100644
--- /dev/null
+++ b/sql/test/concurrent/Tests/truncate-insert-flood.py
@@ -0,0 +1,66 @@
+import sys, os, tempfile, pymonetdb
+
+try:
+    from MonetDBtesting import process
+except ImportError:
+    import process
+
+from concurrent.futures import ThreadPoolExecutor
+
+nr_clients = 16
+
+with tempfile.TemporaryDirectory() as dbfarm:
+    os.mkdir(os.path.join(dbfarm, 'db'))
+
+    with open(os.path.join(dbfarm, 'errout'), mode='a+') as errout:
+        with process.server(
+                        dbname='db',
+                        dbfarm=os.path.join(dbfarm, 'db'),
_______________________________________________
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org

Reply via email to