Changeset: 3964ff1b8b99 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/3964ff1b8b99
Modified Files:
        gdk/gdk_aggr.c
        gdk/gdk_align.c
        gdk/gdk_bat.c
        gdk/gdk_batop.c
        gdk/gdk_bbp.c
        gdk/gdk_group.c
        gdk/gdk_hash.c
        gdk/gdk_select.c
        gdk/gdk_unique.c
Branch: Jul2021
Log Message:

Use heap lock to protect extra properties.
Also use index lock instead of heap lock to lock out concurrent scans
in BATordered and BATordered_rev.
And also reduce number of times we acquire a lock by doing multiple
calls to nolock functions inside one critical section.


diffs (truncated from 822 to 300 lines):

diff --git a/gdk/gdk_aggr.c b/gdk/gdk_aggr.c
--- a/gdk/gdk_aggr.c
+++ b/gdk/gdk_aggr.c
@@ -3614,7 +3614,7 @@ void *
 BATmin_skipnil(BAT *b, void *aggr, bit skipnil)
 {
        const ValRecord *prop;
-       const void *res;
+       const void *res = NULL;
        size_t s;
        lng t0 = 0;
 
@@ -3628,9 +3628,18 @@ BATmin_skipnil(BAT *b, void *aggr, bit s
        }
        if (BATcount(b) == 0) {
                res = ATOMnilptr(b->ttype);
-       } else if ((prop = BATgetprop(b, GDK_MIN_VALUE)) != NULL) {
-               res = VALptr(prop);
        } else {
+               MT_lock_set(&b->theaplock);
+               if ((prop = BATgetprop_nolock(b, GDK_MIN_VALUE)) != NULL)
+                       res = VALptr(prop);
+               else if ((prop = BATgetprop_nolock(b, GDK_MIN_POS)) != NULL) {
+                       BATiter bi = bat_iterator_nolock(b);
+                       if ((prop = BATsetprop_nolock(b, GDK_MIN_VALUE, 
b->ttype, BUNtail(bi, prop->val.oval))) != NULL)
+                               res = VALptr(prop);
+               }
+               MT_lock_unset(&b->theaplock);
+       }
+       if (res == NULL) {
                oid pos;
                BAT *pb = NULL;
 
@@ -3691,11 +3700,12 @@ BATmin_skipnil(BAT *b, void *aggr, bit s
                if (is_oid_nil(pos)) {
                        res = ATOMnilptr(b->ttype);
                } else {
-                       BATiter bi = bat_iterator(b);
+                       MT_lock_set(&b->theaplock);
+                       BATiter bi = bat_iterator_nolock(b);
                        res = BUNtail(bi, pos - b->hseqbase);
-                       BATsetprop(b, GDK_MIN_VALUE, b->ttype, res);
-                       BATsetprop(b, GDK_MIN_POS, TYPE_oid, &(oid){pos - 
b->hseqbase});
-                       bat_iterator_end(&bi);
+                       BATsetprop_nolock(b, GDK_MIN_VALUE, b->ttype, res);
+                       BATsetprop_nolock(b, GDK_MIN_POS, TYPE_oid, &(oid){pos 
- b->hseqbase});
+                       MT_lock_unset(&b->theaplock);
                }
        }
        if (aggr == NULL) {
@@ -3729,7 +3739,7 @@ void *
 BATmax_skipnil(BAT *b, void *aggr, bit skipnil)
 {
        const ValRecord *prop;
-       const void *res;
+       const void *res = NULL;
        size_t s;
        BATiter bi;
        lng t0 = 0;
@@ -3742,9 +3752,18 @@ BATmax_skipnil(BAT *b, void *aggr, bit s
        }
        if (BATcount(b) == 0) {
                res = ATOMnilptr(b->ttype);
-       } else if ((prop = BATgetprop(b, GDK_MAX_VALUE)) != NULL) {
-               res = VALptr(prop);
        } else {
+               MT_lock_set(&b->theaplock);
+               if ((prop = BATgetprop_nolock(b, GDK_MAX_VALUE)) != NULL)
+                       res = VALptr(prop);
+               else if ((prop = BATgetprop_nolock(b, GDK_MAX_POS)) != NULL) {
+                       BATiter bi = bat_iterator_nolock(b);
+                       if ((prop = BATsetprop_nolock(b, GDK_MAX_VALUE, 
b->ttype, BUNtail(bi, prop->val.oval))) != NULL)
+                               res = VALptr(prop);
+               }
+               MT_lock_unset(&b->theaplock);
+       }
+       if (res == NULL) {
                oid pos;
                BAT *pb = NULL;
 
@@ -3796,13 +3815,14 @@ BATmax_skipnil(BAT *b, void *aggr, bit s
                if (is_oid_nil(pos)) {
                        res = ATOMnilptr(b->ttype);
                } else {
-                       bi = bat_iterator(b);
+                       MT_lock_set(&b->theaplock);
+                       bi = bat_iterator_nolock(b);
                        res = BUNtail(bi, pos - b->hseqbase);
                        if (b->tnonil) {
-                               BATsetprop(b, GDK_MAX_VALUE, b->ttype, res);
-                               BATsetprop(b, GDK_MAX_POS, TYPE_oid, &(oid){pos 
- b->hseqbase});
+                               BATsetprop_nolock(b, GDK_MAX_VALUE, b->ttype, 
res);
+                               BATsetprop_nolock(b, GDK_MAX_POS, TYPE_oid, 
&(oid){pos - b->hseqbase});
                        }
-                       bat_iterator_end(&bi);
+                       MT_lock_unset(&b->theaplock);
                }
        }
        if (aggr == NULL) {
diff --git a/gdk/gdk_align.c b/gdk/gdk_align.c
--- a/gdk/gdk_align.c
+++ b/gdk/gdk_align.c
@@ -254,12 +254,12 @@ BATmaterialize(BAT *b)
        b->theap = tail;
        b->tbaseoff = 0;
        b->theap->dirty = true;
+       BATsetprop_nolock(b, GDK_NUNIQUE, TYPE_oid, &(oid){is_oid_nil(t) ? 1 : 
b->batCount});
        MT_lock_unset(&b->theaplock);
        b->ttype = TYPE_oid;
        BATsetdims(b);
        b->batDirtydesc = true;
        BATsetcount(b, b->batCount);
-       BATsetprop(b, GDK_NUNIQUE, TYPE_oid, &(oid){is_oid_nil(t) ? 1 : 
b->batCount});
 
        return GDK_SUCCEED;
 }
diff --git a/gdk/gdk_bat.c b/gdk/gdk_bat.c
--- a/gdk/gdk_bat.c
+++ b/gdk/gdk_bat.c
@@ -661,14 +661,21 @@ BATfree(BAT *b)
        if (b->tident && !default_ident(b->tident))
                GDKfree(b->tident);
        b->tident = BATstring_t;
+       MT_rwlock_rdlock(&b->thashlock);
+       BUN nunique = BUN_NONE, nbucket = BUN_NONE;
        if (b->thash && b->thash != (Hash *) 1) {
-               BATsetprop(b, GDK_NUNIQUE, TYPE_oid, &(oid){b->thash->nunique});
-               BATsetprop(b, GDK_HASH_BUCKETS, TYPE_oid, 
&(oid){b->thash->nbucket});
+               nunique = b->thash->nunique;
+               nbucket = b->thash->nbucket;
        }
+       MT_rwlock_rdunlock(&b->thashlock);
        HASHfree(b);
        IMPSfree(b);
        OIDXfree(b);
        MT_lock_set(&b->theaplock);
+       if (nunique != BUN_NONE) {
+               BATsetprop_nolock(b, GDK_NUNIQUE, TYPE_oid, &(oid){nunique});
+               BATsetprop_nolock(b, GDK_HASH_BUCKETS, TYPE_oid, 
&(oid){nbucket});
+       }
        if (b->theap) {
                assert(ATOMIC_GET(&b->theap->refs) == 1);
                assert(b->theap->parentid == b->batCacheid);
@@ -1249,16 +1256,24 @@ BUNdelete(BAT *b, oid o)
        val = BUNtail(bi, p);
        if (ATOMlinear(b->ttype) &&
            ATOMcmp(b->ttype, ATOMnilptr(b->ttype), val) != 0) {
-               if ((prop = BATgetprop(b, GDK_MAX_VALUE)) != NULL
-                   && ATOMcmp(b->ttype, VALptr(prop), val) >= 0) {
-                       BATrmprop(b, GDK_MAX_VALUE);
-                       BATrmprop(b, GDK_MAX_POS);
+               MT_lock_set(&b->theaplock);
+               if ((prop = BATgetprop_nolock(b, GDK_MAX_VALUE)) != NULL) {
+                       if (ATOMcmp(b->ttype, VALptr(prop), val) >= 0) {
+                               BATrmprop_nolock(b, GDK_MAX_VALUE);
+                               BATrmprop_nolock(b, GDK_MAX_POS);
+                       }
+               } else {
+                       BATrmprop_nolock(b, GDK_MAX_POS);
                }
-               if ((prop = BATgetprop(b, GDK_MIN_VALUE)) != NULL
-                   && ATOMcmp(b->ttype, VALptr(prop), val) <= 0) {
-                       BATrmprop(b, GDK_MIN_VALUE);
-                       BATrmprop(b, GDK_MIN_POS);
+               if ((prop = BATgetprop_nolock(b, GDK_MIN_VALUE)) != NULL) {
+                       if (ATOMcmp(b->ttype, VALptr(prop), val) <= 0) {
+                               BATrmprop_nolock(b, GDK_MIN_VALUE);
+                               BATrmprop_nolock(b, GDK_MIN_POS);
+                       }
+               } else {
+                       BATrmprop_nolock(b, GDK_MIN_POS);
                }
+               MT_lock_unset(&b->theaplock);
        }
        if (ATOMunfix(b->ttype, val) != GDK_SUCCEED)
                return GDK_FAIL;
@@ -1294,6 +1309,7 @@ BUNdelete(BAT *b, oid o)
                b->tnorevsorted = 0;
        MT_lock_set(&b->theaplock);
        b->batCount--;
+       BATrmprop_nolock(b, GDK_UNIQUE_ESTIMATE);
        MT_lock_unset(&b->theaplock);
        if (b->batCount <= 1) {
                /* some trivial properties */
@@ -1307,7 +1323,6 @@ BUNdelete(BAT *b, oid o)
        }
        IMPSdestroy(b);
        OIDXdestroy(b);
-       BATrmprop(b, GDK_UNIQUE_ESTIMATE);
        return GDK_SUCCEED;
 }
 
@@ -1358,41 +1373,47 @@ BUNinplacemulti(BAT *b, const oid *posit
                if (b->ttype != TYPE_void && ATOMlinear(b->ttype)) {
                        const ValRecord *prop;
 
-                       if ((prop = BATgetprop(b, GDK_MAX_VALUE)) != NULL) {
+                       MT_lock_set(&b->theaplock);
+                       if ((prop = BATgetprop_nolock(b, GDK_MAX_VALUE)) != 
NULL) {
                                if (ATOMcmp(b->ttype, t, ATOMnilptr(b->ttype)) 
!= 0 &&
                                    ATOMcmp(b->ttype, VALptr(prop), t) < 0) {
                                        /* new value is larger than previous
                                         * largest */
-                                       BATsetprop(b, GDK_MAX_VALUE, b->ttype, 
t);
-                                       BATsetprop(b, GDK_MAX_POS, TYPE_oid, 
&(oid){p});
+                                       BATsetprop_nolock(b, GDK_MAX_VALUE, 
b->ttype, t);
+                                       BATsetprop_nolock(b, GDK_MAX_POS, 
TYPE_oid, &(oid){p});
                                } else if (ATOMcmp(b->ttype, t, val) != 0 &&
                                           ATOMcmp(b->ttype, VALptr(prop), val) 
== 0) {
                                        /* old value is equal to largest and
                                         * new value is smaller (see above),
                                         * so we don't know anymore which is
                                         * the largest */
-                                       BATrmprop(b, GDK_MAX_VALUE);
-                                       BATrmprop(b, GDK_MAX_POS);
+                                       BATrmprop_nolock(b, GDK_MAX_VALUE);
+                                       BATrmprop_nolock(b, GDK_MAX_POS);
                                }
+                       } else {
+                               BATrmprop_nolock(b, GDK_MAX_POS);
                        }
-                       if ((prop = BATgetprop(b, GDK_MIN_VALUE)) != NULL) {
+                       if ((prop = BATgetprop_nolock(b, GDK_MIN_VALUE)) != 
NULL) {
                                if (ATOMcmp(b->ttype, t, ATOMnilptr(b->ttype)) 
!= 0 &&
                                    ATOMcmp(b->ttype, VALptr(prop), t) > 0) {
                                        /* new value is smaller than previous
                                         * smallest */
-                                       BATsetprop(b, GDK_MIN_VALUE, b->ttype, 
t);
-                                       BATsetprop(b, GDK_MIN_POS, TYPE_oid, 
&(oid){p});
+                                       BATsetprop_nolock(b, GDK_MIN_VALUE, 
b->ttype, t);
+                                       BATsetprop_nolock(b, GDK_MIN_POS, 
TYPE_oid, &(oid){p});
                                } else if (ATOMcmp(b->ttype, t, val) != 0 &&
                                           ATOMcmp(b->ttype, VALptr(prop), val) 
<= 0) {
                                        /* old value is equal to smallest and
                                         * new value is larger (see above), so
                                         * we don't know anymore which is the
                                         * smallest */
-                                       BATrmprop(b, GDK_MIN_VALUE);
-                                       BATrmprop(b, GDK_MIN_POS);
+                                       BATrmprop_nolock(b, GDK_MIN_VALUE);
+                                       BATrmprop_nolock(b, GDK_MIN_POS);
                                }
+                       } else {
+                               BATrmprop_nolock(b, GDK_MIN_POS);
                        }
-                       BATrmprop(b, GDK_UNIQUE_ESTIMATE);
+                       BATrmprop_nolock(b, GDK_UNIQUE_ESTIMATE);
+                       MT_lock_unset(&b->theaplock);
                } else {
                        PROPdestroy(b);
                }
@@ -2354,6 +2375,9 @@ BATassertProps(BAT *b)
        int cmp;
        const void *prev = NULL, *valp, *nilp;
 
+       /* do the complete check within a lock */
+       MT_lock_set(&b->theaplock);
+
        /* general BAT sanity */
        assert(b != NULL);
        assert(b->batCacheid > 0);
@@ -2447,14 +2471,11 @@ BATassertProps(BAT *b)
                        assert(b->tkey);
                        assert(b->tnonil);
                }
+               MT_lock_unset(&b->theaplock);
                return;
        }
-       /* do the rest on a view in case some other thread changes b */
-       BAT *v = VIEWcreate(b->hseqbase, b);
-       if (v == NULL)
-               return;
-       b = v;
-       BATiter bi = bat_iterator_nolock(b);
+
+       BATiter bi  = bat_iterator_nolock(b);
 
        if (BATtdense(b)) {
                assert(b->tseqbase + b->batCount <= GDK_oid_max);
@@ -2468,7 +2489,7 @@ BATassertProps(BAT *b)
                        for (p = 1; p < q; p++)
                                assert(o[p - 1] + 1 == o[p]);
                }
-               BBPunfix(b->batCacheid);
+               MT_lock_unset(&b->theaplock);
                return;
        }
        assert(1 << b->tshift == b->twidth);
@@ -2513,7 +2534,7 @@ BATassertProps(BAT *b)
        if (!b->tkey && !b->tsorted && !b->trevsorted &&
            !b->tnonil && !b->tnil) {
                /* nothing more to prove */
-               BBPunfix(b->batCacheid);
+               MT_lock_unset(&b->theaplock);
                return;
        }
 
@@ -2524,11 +2545,11 @@ BATassertProps(BAT *b)
                bool seenmax = false, seenmin = false;
                bool seennil = false;
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to