Changeset: e2fc8bd027c1 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/e2fc8bd027c1
Modified Files:
        gdk/gdk.h
        gdk/gdk_bat.c
        gdk/gdk_batop.c
        gdk/gdk_bbp.c
        gdk/gdk_group.c
        gdk/gdk_hash.c
        gdk/gdk_select.c
        monetdb5/mal/mal_profiler.c
Branch: default
Log Message:

Merge with Jul2021 branch.


diffs (truncated from 1105 to 300 lines):

diff --git a/gdk/gdk.h b/gdk/gdk.h
--- a/gdk/gdk.h
+++ b/gdk/gdk.h
@@ -871,7 +871,40 @@ gdk_export size_t HEAPmemsize(Heap *h);
 gdk_export void HEAPdecref(Heap *h, bool remove);
 gdk_export void HEAPincref(Heap *h);
 
-/* BAT iterator, also protects use of BAT heaps with reference counts */
+/* BAT iterator, also protects use of BAT heaps with reference counts.
+ *
+ * A BAT iterator has to be used with caution, but it does have to be
+ * used in many place.
+ *
+ * An iterator is initialized by assigning it the result of a call to
+ * either bat_iterator or bat_iterator_nolock.  The former must be
+ * accompanied by a call to bat_iterator_end to release resources.
+ *
+ * bat_iterator should be used for BATs that could possibly be modified
+ * in another thread while we're reading the contents of the BAT.
+ * Alternatively, but only for very quick access, the theaplock can be
+ * taken, the data read, and the lock released.  For longer duration
+ * accesses, it is better to use the iterator, even without the BUNt*
+ * macros, since the theaplock is only held very briefly.
+ *
+ * If BATs are to be modified, higher level code must assure that no
+ * other thread is going to modify the same BAT at the same time.  A
+ * to-be-modified BAT should not use bat_iterator.  It can use
+ * bat_iterator_nolock, but be aware that this creates a copy of the
+ * heap pointer(s) (i.e. theap and tvheap) and if the heaps get
+ * extended, the pointers in the BAT structure may be modified, but that
+ * does not modify the pointers in the iterator.  This means that after
+ * operations that may grow a heap, the iterator should be
+ * reinitialized.
+ *
+ * The BAT iterator provides a number of fields that can (and often
+ * should) be used to access information about the BAT.  For string
+ * BATs, if a parallel threads adds values, the offset heap (theap) may
+ * get replaced by a one that is wider.  This involves changing the
+ * twidth and tshift values in the BAT structure.  These changed values
+ * should not be used to access the data in the iterator.  Instead, use
+ * the width and shift values in the iterator itself.
+ */
 typedef struct BATiter {
        BAT *b;
        Heap *h;
diff --git a/gdk/gdk_bat.c b/gdk/gdk_bat.c
--- a/gdk/gdk_bat.c
+++ b/gdk/gdk_bat.c
@@ -613,14 +613,18 @@ BATclear(BAT *b, bool force)
                if (b->tvheap && b->tvheap->free > 0) {
                        Heap *th = GDKmalloc(sizeof(Heap));
 
-                       if (th == NULL)
+                       if (th == NULL) {
+                               MT_lock_unset(&b->theaplock);
                                return GDK_FAIL;
+                       }
                        *th = (Heap) {
                                .farmid = b->tvheap->farmid,
                        };
                        strcpy_len(th->filename, b->tvheap->filename, 
sizeof(th->filename));
-                       if (ATOMheap(b->ttype, th, 0) != GDK_SUCCEED)
+                       if (ATOMheap(b->ttype, th, 0) != GDK_SUCCEED) {
+                               MT_lock_unset(&b->theaplock);
                                return GDK_FAIL;
+                       }
                        ATOMIC_INIT(&th->refs, 1);
                        th->parentid = b->tvheap->parentid;
                        th->dirty = true;
@@ -1447,9 +1451,9 @@ BUNinplacemulti(BAT *b, const oid *posit
                                        MT_rwlock_wrunlock(&b->thashlock);
                                        return GDK_FAIL;
                                }
-                               /* reinitialize iterator after heap upgrade */
-                               bi = bat_iterator_nolock(b);
                        }
+                       /* reinitialize iterator after possible heap upgrade */
+                       bi = bat_iterator_nolock(b);
                        _ptr = BUNtloc(bi, p);
                        switch (b->twidth) {
                        default:        /* only three or four cases possible */
diff --git a/gdk/gdk_batop.c b/gdk/gdk_batop.c
--- a/gdk/gdk_batop.c
+++ b/gdk/gdk_batop.c
@@ -1298,8 +1298,11 @@ BATappend_or_update(BAT *b, BAT *p, BAT 
                                        bat_iterator_end(&ni);
                                        return GDK_FAIL;
                                }
-                               bi = bat_iterator_nolock(b);
                        }
+                       /* in case ATOMreplaceVAR and/or
+                        * GDKupgradevarheap replaces a heap, we need to
+                        * reinitialize the iterator */
+                       bi = bat_iterator_nolock(b);
                        switch (b->twidth) {
                        case 1:
                                ((uint8_t *) b->theap->base)[updid] = (uint8_t) 
(d - GDK_VAROFFSET);
@@ -3036,7 +3039,7 @@ BATcount_no_nil(BAT *b, BAT *s)
                break;
        case TYPE_str:
                base = bi.vh->base;
-               switch (b->twidth) {
+               switch (bi.width) {
                case 1:
                        for (i = 0; i < n; i++)
                                cnt += base[(var_t) ((const unsigned char *) 
p)[canditer_next(&ci) - hseq] + GDK_VAROFFSET] != '\200';
diff --git a/gdk/gdk_bbp.c b/gdk/gdk_bbp.c
--- a/gdk/gdk_bbp.c
+++ b/gdk/gdk_bbp.c
@@ -1764,7 +1764,7 @@ BBPdir_step(bat bid, BUN size, int n, ch
                        GDKerror("Writing BBP.dir file failed.\n");
                        goto bailout;
                }
-               if (fgets(buf, bufsize, *obbpfp) == NULL) {
+               if (fgets(buf, (int) bufsize, *obbpfp) == NULL) {
                        if (ferror(*obbpfp)) {
                                GDKerror("error reading backup BBP.dir.");
                                goto bailout;
@@ -1803,7 +1803,7 @@ BBPdir_last(int n, char *buf, size_t buf
                goto bailout;
        }
        while (obbpf) {
-               if (fgets(buf, bufsize, obbpf) == NULL) {
+               if (fgets(buf, (int) bufsize, obbpf) == NULL) {
                        if (ferror(obbpf)) {
                                GDKerror("error reading backup BBP.dir.");
                                goto bailout;
@@ -3519,13 +3519,11 @@ BBPsync(int cnt, bat *restrict subcommit
 
                        if (d)
                                MT_lock_set(&d->theaplock);
-//                     else
-//                             MT_lock_set(&GDKswapLock(i));
                        if (BBP_status(i) & BBPPERSISTENT) {
                                BAT *b = dirty_bat(&i, subcommit != NULL);
                                if (i <= 0) {
-//                                     MT_lock_unset(&GDKswapLock(subcommit ? 
subcommit[idx] : idx));
-                                       MT_lock_unset(&BBP_desc(i)->theaplock);
+                                       if (d)
+                                               MT_lock_unset(&d->theaplock);
                                        break;
                                }
                                if (b)
@@ -3536,8 +3534,6 @@ BBPsync(int cnt, bat *restrict subcommit
                        }
                        if (d)
                                MT_lock_unset(&d->theaplock);
-//                     else
-//                             MT_lock_unset(&GDKswapLock(i));
                        if (n == -2)
                                break;
                        /* we once again have a saved heap */
diff --git a/gdk/gdk_group.c b/gdk/gdk_group.c
--- a/gdk/gdk_group.c
+++ b/gdk/gdk_group.c
@@ -796,14 +796,17 @@ BATgroup_internal(BAT **groups, BAT **ex
        if (gn == NULL)
                goto error;
        ngrps = (oid *) Tloc(gn, 0);
+       maxgrps = BUN_NONE;
        MT_rwlock_rdlock(&b->thashlock);
        if (b->thash && b->thash != (Hash *) 1)
                maxgrps = b->thash->nunique;
-       else if ((prop = BATgetprop_nolock(b, GDK_NUNIQUE)) != NULL)
-               maxgrps = prop->val.oval;
-       else
-               maxgrps = cnt / 10;
        MT_rwlock_rdunlock(&b->thashlock);
+       if (maxgrps == BUN_NONE) {
+               if ((prop = BATgetprop(b, GDK_NUNIQUE)) != NULL)
+                       maxgrps = prop->val.oval;
+               else
+                       maxgrps = cnt / 10;
+       }
        if (!is_oid_nil(maxgrp) && maxgrps < maxgrp)
                maxgrps += maxgrp;
        if (e && maxgrps < BATcount(e))
@@ -812,18 +815,20 @@ BATgroup_internal(BAT **groups, BAT **ex
                maxgrps += BATcount(h);
        if (maxgrps < GROUPBATINCR)
                maxgrps = GROUPBATINCR;
-       if (b->twidth <= 2)
-               maxgrps = (BUN) 1 << (8 * b->twidth);
+       bi = bat_iterator(b);
+
+       if (bi.width <= 2)
+               maxgrps = (BUN) 1 << (8 * bi.width);
        if (extents) {
                en = COLnew(0, TYPE_oid, maxgrps, TRANSIENT);
                if (en == NULL)
-                       goto error;
+                       goto error1;
                exts = (oid *) Tloc(en, 0);
        }
        if (histo) {
                hn = COLnew(0, TYPE_lng, maxgrps, TRANSIENT);
                if (hn == NULL)
-                       goto error;
+                       goto error1;
                cnts = (lng *) Tloc(hn, 0);
        }
        ngrp = 0;
@@ -837,8 +842,8 @@ BATgroup_internal(BAT **groups, BAT **ex
        /* for strings we can use the offset instead of the actual
         * string values if we know that the strings in the string
         * heap are unique */
-       if (t == TYPE_str && GDK_ELIMDOUBLES(b->tvheap)) {
-               switch (b->twidth) {
+       if (t == TYPE_str && GDK_ELIMDOUBLES(bi.vh)) {
+               switch (bi.width) {
                case 1:
                        t = TYPE_bte;
                        break;
@@ -858,8 +863,6 @@ BATgroup_internal(BAT **groups, BAT **ex
                }
        }
 
-       bi = bat_iterator(b);
-
        if (subsorted ||
            ((BATordered(b) || BATordered_rev(b)) &&
             (g == NULL || BATordered(g) || BATordered_rev(g)))) {
@@ -925,7 +928,7 @@ BATgroup_internal(BAT **groups, BAT **ex
                /* array to maintain last time we saw each old group */
                pgrp = GDKmalloc(sizeof(BUN) * j);
                if (pgrp == NULL)
-                       goto error;
+                       goto error1;
                /* initialize to impossible position */
                memset(pgrp, ~0, sizeof(BUN) * j);
 
@@ -972,7 +975,7 @@ BATgroup_internal(BAT **groups, BAT **ex
 
                algomsg = "byte-sized groups -- ";
                if (bgrps == NULL)
-                       goto error;
+                       goto error1;
                memset(bgrps, 0xFF, 256);
                if (histo)
                        memset(cnts, 0, maxgrps * sizeof(lng));
@@ -1007,7 +1010,7 @@ BATgroup_internal(BAT **groups, BAT **ex
 
                algomsg = "short-sized groups -- ";
                if (sgrps == NULL)
-                       goto error;
+                       goto error1;
                memset(sgrps, 0xFF, 65536 * sizeof(short));
                if (histo)
                        memset(cnts, 0, maxgrps * sizeof(lng));
@@ -1055,10 +1058,12 @@ BATgroup_internal(BAT **groups, BAT **ex
                         * calculate the bounds [lo, lo+BATcount(b))
                         * in the parent that b uses */
                        BAT *b2 = BBPdescriptor(parent);
+                       MT_rwlock_rdunlock(&b->thashlock);
                        lo = b->tbaseoff - b2->tbaseoff;
                        b = b2;
                        bat_iterator_end(&bi);
                        bi = bat_iterator(b);
+                       MT_rwlock_rdlock(&b->thashlock);
                        algomsg = "existing parent hash -- ";
                        phash = true;
                }
@@ -1121,7 +1126,7 @@ BATgroup_internal(BAT **groups, BAT **ex
                 * BATassertProps for similar code; we also exploit if
                 * g is clustered */
                algomsg = "new partial hash -- ";
-               nme = GDKinmemory(b->theap->farmid) ? ":memory:" : 
BBP_physical(b->batCacheid);
+               nme = GDKinmemory(bi.h->farmid) ? ":memory:" : 
BBP_physical(b->batCacheid);
                if (grps && !gc) {
                        /* we manipulate the hash value after having
                         * calculated it, and when doing that, we
@@ -1159,7 +1164,7 @@ BATgroup_internal(BAT **groups, BAT **ex
                        GDKfree(hs);
                        hs = NULL;
                        GDKerror("cannot allocate hash table\n");
-                       goto error;
+                       goto error1;
                }
                if (snprintf(hs->heaplink.filename, 
sizeof(hs->heaplink.filename), "%s.thshgrpl%x", nme, (unsigned) THRgettid()) >= 
(int) sizeof(hs->heaplink.filename) ||
                    snprintf(hs->heapbckt.filename, 
sizeof(hs->heapbckt.filename), "%s.thshgrpb%x", nme, (unsigned) THRgettid()) >= 
(int) sizeof(hs->heapbckt.filename) ||
@@ -1167,7 +1172,7 @@ BATgroup_internal(BAT **groups, BAT **ex
                        GDKfree(hs);
                        hs = NULL;
                        GDKerror("cannot allocate hash table\n");
-                       goto error;
+                       goto error1;
                }
                gn->tsorted = true; /* be optimistic */
 
@@ -1305,8 +1310,9 @@ BATgroup_internal(BAT **groups, BAT **ex
                  ALGOOPTBATPAR(gn), ALGOOPTBATPAR(en),
                  ALGOOPTBATPAR(hn), algomsg, GDKusec() - t0);
        return GDK_SUCCEED;
+  error1:
+       bat_iterator_end(&bi);
   error:
-       bat_iterator_end(&bi);
        if (hs != NULL && hs != b->thash) {
                HEAPfree(&hs->heaplink, true);
                HEAPfree(&hs->heapbckt, true);
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to