Changeset: 411348e37eda for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/411348e37eda
Modified Files:
        gdk/gdk.h
        gdk/gdk_bat.c
        gdk/gdk_batop.c
        gdk/gdk_logger.c
        sql/storage/bat/bat_logger.c
Branch: default
Log Message:

New interface bat_iterator_hash to initialize BAT iterator with read lock on 
hash.
The .hash pointer is filled in, and the hash is unlocked in
bat_iterator_end.
If .hash is NULL, there is no loaded hash, and the hashlock is not locked.


diffs (truncated from 325 to 300 lines):

diff --git a/gdk/gdk.h b/gdk/gdk.h
--- a/gdk/gdk.h
+++ b/gdk/gdk.h
@@ -2309,6 +2309,7 @@ typedef struct BATiter {
        Heap *h;
        void *base;
        Heap *vh;
+       Hash *hash;             /* if non-NULL, there's a read lock */
        BUN count;
        BUN baseoff;
        oid hseq;
@@ -2422,7 +2423,7 @@ bat_iterator_incref(BATiter *bi)
 }
 
 static inline BATiter
-bat_iterator(BAT *b)
+bat_iterator_internal(BAT *b, bool hash)
 {
        /* needs matching bat_iterator_end */
        BATiter bi;
@@ -2435,6 +2436,8 @@ bat_iterator(BAT *b)
                 * have a parent for its vheap (which would have to be
                 * our own vheap parent), so lock the vheap after the
                 * tail */
+               if (hash)
+                       MT_rwlock_rdlock(&b->thashlock);
                MT_lock_set(&b->theaplock);
                if (b->theap->parentid != b->batCacheid) {
                        pb = BBP_desc(b->theap->parentid);
@@ -2447,6 +2450,11 @@ bat_iterator(BAT *b)
                        MT_lock_set(&pvb->theaplock);
                }
                bi = bat_iterator_nolock(b);
+               if (hash &&
+                   ((bi.hash = b->thash) == NULL || bi.hash == (Hash *) 1)) {
+                       bi.hash = NULL;
+                       MT_rwlock_rdunlock(&b->thashlock);
+               }
                bat_iterator_incref(&bi);
                if (pvb)
                        MT_lock_unset(&pvb->theaplock);
@@ -2464,6 +2472,18 @@ bat_iterator(BAT *b)
        return bi;
 }
 
+static inline BATiter
+bat_iterator(BAT *b)
+{
+       return bat_iterator_internal(b, false);
+}
+
+static inline BATiter
+bat_iterator_hash(BAT *b)
+{
+       return bat_iterator_internal(b, true);
+}
+
 /* return a copy of a BATiter instance; needs to be released with
  * bat_iterator_end */
 static inline BATiter
@@ -2475,6 +2495,8 @@ bat_iterator_copy(const BATiter *bip)
                HEAPincref(bip->h);
        if (bip->vh)
                HEAPincref(bip->vh);
+       if (bip->hash)
+               MT_rwlock_rdlock(&bip->b->thashlock);
        return *bip;
 }
 
@@ -2484,6 +2506,8 @@ bat_iterator_end(BATiter *bip)
        /* matches bat_iterator */
        assert(bip);
        assert(bip->locked);
+       if (bip->hash)
+               MT_rwlock_rdunlock(&bip->b->thashlock);
        if (bip->h)
                HEAPdecref(bip->h, false);
        if (bip->vh)
diff --git a/gdk/gdk_bat.c b/gdk/gdk_bat.c
--- a/gdk/gdk_bat.c
+++ b/gdk/gdk_bat.c
@@ -1974,78 +1974,71 @@ BUNfnd(BAT *b, const void *v)
                bat_iterator_end(&bi);
                v = &off;
        }
-       bi = bat_iterator(b);   /* outside of hashlock */
-       if (BAThash(b) == GDK_SUCCEED) {
-               MT_rwlock_rdlock(&b->thashlock);
-               if (b->thash == NULL) {
-                       MT_rwlock_rdunlock(&b->thashlock);
-                       goto hashfnd_failed;
-               }
+       (void) BAThash(b);
+       bi = bat_iterator_hash(b);
+       if (bi.hash) {
                switch (ATOMbasetype(bi.type)) {
                case TYPE_bte:
-                       HASHloop_bte(&bi, b->thash, r, v)
+                       HASHloop_bte(&bi, bi.hash, r, v)
                                break;
                        break;
                case TYPE_sht:
-                       HASHloop_sht(&bi, b->thash, r, v)
+                       HASHloop_sht(&bi, bi.hash, r, v)
                                break;
                        break;
                case TYPE_int:
-                       HASHloop_int(&bi, b->thash, r, v)
+                       HASHloop_int(&bi, bi.hash, r, v)
                                break;
                        break;
                case TYPE_flt:
-                       HASHloop_flt(&bi, b->thash, r, v)
+                       HASHloop_flt(&bi, bi.hash, r, v)
                                break;
                        break;
                case TYPE_dbl:
-                       HASHloop_dbl(&bi, b->thash, r, v)
+                       HASHloop_dbl(&bi, bi.hash, r, v)
                                break;
                        break;
                case TYPE_lng:
-                       HASHloop_lng(&bi, b->thash, r, v)
+                       HASHloop_lng(&bi, bi.hash, r, v)
                                break;
                        break;
 #ifdef HAVE_HGE
                case TYPE_hge:
-                       HASHloop_hge(&bi, b->thash, r, v)
+                       HASHloop_hge(&bi, bi.hash, r, v)
                                break;
                        break;
 #endif
                case TYPE_uuid:
-                       HASHloop_uuid(&bi, b->thash, r, v)
+                       HASHloop_uuid(&bi, bi.hash, r, v)
                                break;
                        break;
                case TYPE_inet4:
-                       HASHloop_inet4(&bi, b->thash, r, v)
+                       HASHloop_inet4(&bi, bi.hash, r, v)
                                break;
                        break;
                case TYPE_inet6:
-                       HASHloop_inet6(&bi, b->thash, r, v)
+                       HASHloop_inet6(&bi, bi.hash, r, v)
                                break;
                        break;
                case TYPE_str:
                        if (bi.ustr) {
-                               HASHloop_var_t(&bi, b->thash, r, v)
+                               HASHloop_var_t(&bi, bi.hash, r, v)
                                        break;
                        } else {
-                               HASHloop_str(&bi, b->thash, r, v)
+                               HASHloop_str(&bi, bi.hash, r, v)
                                        break;
                        }
                        break;
                default:
-                       HASHloop(&bi, b->thash, r, v)
+                       HASHloop(&bi, bi.hash, r, v)
                                break;
                        break;
                }
-               MT_rwlock_rdunlock(&b->thashlock);
-               bat_iterator_end(&bi);
-               return r;
+       } else {
+               /* can't build hash table, search the slow way */
+               GDKclrerr();
+               r = slowfnd(&bi, v);
        }
-  hashfnd_failed:
-       /* can't build hash table, search the slow way */
-       GDKclrerr();
-       r = slowfnd(&bi, v);
        bat_iterator_end(&bi);
        return r;
 }
diff --git a/gdk/gdk_batop.c b/gdk/gdk_batop.c
--- a/gdk/gdk_batop.c
+++ b/gdk/gdk_batop.c
@@ -3413,21 +3413,20 @@ BATcount_no_nil(BAT *b, BAT *s)
        BATcheck(b, 0);
 
        hseq = b->hseqbase;
-       BATiter bi = bat_iterator(b);
+       (void) BATcheckhash(b);
+       BATiter bi = bat_iterator_hash(b);
        canditer_init_bi(&ci, &bi, s);
        if (bi.nonil) {
                bat_iterator_end(&bi);
                return ci.ncand;
        }
-       if (BATcheckhash(b)) {
-               MT_rwlock_rdlock(&b->thashlock);
+       if (bi.hash) {
                BUN p = 0;
                const void *nil = b->ustr ? &(var_t){0} : ATOMnilptr(b->ttype);
                cnt = ci.ncand;
-               HASHloop(&bi, b->thash, p, nil)
+               HASHloop(&bi, bi.hash, p, nil)
                        if (canditer_contains(&ci, p + b->hseqbase))
                                cnt--;
-               MT_rwlock_rdunlock(&b->thashlock);
                bat_iterator_end(&bi);
                return cnt;
        }
diff --git a/gdk/gdk_logger.c b/gdk/gdk_logger.c
--- a/gdk/gdk_logger.c
+++ b/gdk/gdk_logger.c
@@ -128,18 +128,16 @@ log_find(BAT *b, BAT *d, int val)
 
        assert(b->ttype == TYPE_int);
        assert(d->ttype == TYPE_oid);
-       BATiter bi = bat_iterator(b);
-       if (BAThash(b) == GDK_SUCCEED) {
-               MT_rwlock_rdlock(&b->thashlock);
-               HASHloop_int(&bi, b->thash, p, &val) {
+       (void) BAThash(b);
+       BATiter bi = bat_iterator_hash(b);
+       if (bi.hash) {
+               HASHloop_int(&bi, bi.hash, p, &val) {
                        oid pos = p;
                        if (BUNfnd(d, &pos) == BUN_NONE) {
-                               MT_rwlock_rdunlock(&b->thashlock);
                                bat_iterator_end(&bi);
                                return p;
                        }
                }
-               MT_rwlock_rdunlock(&b->thashlock);
        } else {                /* unlikely: BAThash failed */
                int *t = (int *) bi.base;
 
@@ -163,20 +161,18 @@ internal_find_bat(logger *lg, log_id id,
        BUN p;
 
        if (BAThash(lg->catalog_id) == GDK_SUCCEED) {
-               BATiter cni = bat_iterator(lg->catalog_id);
-               MT_rwlock_rdlock(&cni.b->thashlock);
+               BATiter cni = bat_iterator_hash(lg->catalog_id);
                if (tid < 0) {
-                       HASHloop_int(&cni, cni.b->thash, p, &id) {
+                       HASHloop_int(&cni, cni.hash, p, &id) {
                                oid pos = p;
                                if (BUNfnd(lg->dcatalog, &pos) == BUN_NONE) {
-                                       MT_rwlock_rdunlock(&cni.b->thashlock);
                                        bat_iterator_end(&cni);
                                        return *(log_bid *) 
Tloc(lg->catalog_bid, p);
                                }
                        }
                } else {
                        BUN cp = BUN_NONE;
-                       HASHloop_int(&cni, cni.b->thash, p, &id) {
+                       HASHloop_int(&cni, cni.hash, p, &id) {
                                lng lid = *(lng *) Tloc(lg->catalog_lid, p);
                                if (lid != lng_nil && lid <= tid) {
                                        break;
@@ -184,12 +180,10 @@ internal_find_bat(logger *lg, log_id id,
                                cp = p;
                        }
                        if (cp != BUN_NONE) {
-                               MT_rwlock_rdunlock(&cni.b->thashlock);
                                bat_iterator_end(&cni);
                                return *(log_bid *) Tloc(lg->catalog_bid, cp);
                        }
                }
-               MT_rwlock_rdunlock(&cni.b->thashlock);
                bat_iterator_end(&cni);
                return 0;       /* not found */
        }
@@ -1582,13 +1576,12 @@ log_read_transaction(logger *lg, BAT *id
                case LOG_CREATE_USTR:
                case LOG_DESTROY:
                        if (tr != NULL && updated && BAThash(lg->catalog_id) == 
GDK_SUCCEED) {
-                               BATiter cni = bat_iterator(lg->catalog_id);
+                               BATiter cni = bat_iterator_hash(lg->catalog_id);
                                BUN p;
                                BUN posnew = BUN_NONE;
                                BUN posold = BUN_NONE;
                                BUN posustr = BUN_NONE;
-                               MT_rwlock_rdlock(&cni.b->thashlock);
-                               HASHloop_int(&cni, cni.b->thash, p, &l.id) {
+                               HASHloop_int(&cni, cni.hash, p, &l.id) {
                                        lng lid = *(lng *) 
Tloc(lg->catalog_lid, p);
                                        if (lid == lng_nil || lid > tr->tid)
                                                posnew = p;
@@ -1601,7 +1594,6 @@ log_read_transaction(logger *lg, BAT *id
                                                        GDKwarning("should not 
be possible\n");
                                        }
                                }
-                               MT_rwlock_rdunlock(&cni.b->thashlock);
                                bat_iterator_end(&cni);
                                /* Normally at this point, posnew is the
                                 * location of the bat that this
diff --git a/sql/storage/bat/bat_logger.c b/sql/storage/bat/bat_logger.c
--- a/sql/storage/bat/bat_logger.c
+++ b/sql/storage/bat/bat_logger.c
@@ -191,7 +191,8 @@ tabins(logger *lg, ...)
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to