Changeset: bc9655e0a9eb for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/bc9655e0a9eb
Modified Files:
gdk/gdk.h
gdk/gdk_batop.c
gdk/gdk_bbp.c
gdk/gdk_private.h
sql/backends/monet5/sql_statement.c
sql/server/rel_select.c
sql/storage/bat/bat_storage.c
sql/storage/store.c
sql/test/miscellaneous/Tests/simple_selects.test
Branch: properties
Log Message:
Merged with default
diffs (truncated from 5666 to 300 lines):
diff --git a/gdk/gdk.h b/gdk/gdk.h
--- a/gdk/gdk.h
+++ b/gdk/gdk.h
@@ -774,22 +774,34 @@ typedef enum {
BAT_APPEND, /* only reads and appends allowed */
} restrict_t;
+/* batDirtydesc: should be set (true) if any of the following fields
+ * have changed since the bat was last saved: hseqbase, batRestricted,
+ * batTransient, batCount, and the theap properties tkey, tseqbase,
+ * tsorted, trevsorted, twidth, tshift, tnonil, tnil, tnokey, tnosorted,
+ * tnorevsorted, tminpos, tmaxpos, and tunique_est; in addition, the
+ * value should be set if the BBP field BBP_logical(bid) is changed.
+ *
+ * theaplock: this lock should be held when reading or writing any of
+ * the fields mentioned above for batDirtydesc, and also when reading or
+ * writing any of the following fields: batDirtydesc, theap, tvheap,
+ * batInserted, batCapacity. There is no need for the lock if the bat
+ * cannot possibly be modified concurrently, e.g. when it is new and not
+ * yet returned to the interpreter or during system initialization. */
typedef struct BAT {
/* static bat properties */
oid hseqbase; /* head seq base */
MT_Id creator_tid; /* which thread created it */
bat batCacheid; /* index into BBP */
+ role_t batRole; /* role of the bat */
/* dynamic bat properties */
- restrict_t batRestricted; /* access privileges */
- bool batTransient; /* should the BAT persist on disk? */
+ restrict_t batRestricted:2; /* access privileges */
bool
+ batTransient:1, /* should the BAT persist on disk? */
batCopiedtodisk:1, /* once written */
batDirtyflushed:1, /* was dirty before commit started? */
batDirtydesc:1; /* bat descriptor dirty marker */
- uint16_t /* adjacent bit fields are packed together (if they fit) */
- selcnt:10; /* how often used in equi select without hash */
- role_t batRole; /* role of the bat */
+ uint16_t selcnt; /* how often used in equi select without hash */
uint16_t unused; /* value=0 for now (sneakily used by mat.c) */
int batSharecnt; /* incoming view count */
@@ -961,14 +973,18 @@ typedef struct BATiter {
sorted:1,
revsorted:1,
hdirty:1,
- vhdirty:1;
+ vhdirty:1,
+ dirtydesc:1,
+ copiedtodisk:1,
+ transient:1;
+ restrict_t restricted:2;
+#ifndef NDEBUG
+ bool locked:1;
+#endif
union {
oid tvid;
bool tmsk;
};
-#ifndef NDEBUG
- bool locked;
-#endif
} BATiter;
static inline BATiter
@@ -1003,8 +1019,14 @@ bat_iterator_nolock(BAT *b)
.nil = b->tnil,
.sorted = b->tsorted,
.revsorted = b->trevsorted,
- .hdirty = b->theap->dirty,
- .vhdirty = b->tvheap && b->tvheap->dirty,
+ /* only look at heap dirty flag if we own it */
+ .hdirty = b->theap->parentid == b->batCacheid &&
b->theap->dirty,
+ /* also, if there is no vheap, it's not dirty */
+ .vhdirty = b->tvheap && b->tvheap->parentid ==
b->batCacheid && b->tvheap->dirty,
+ .dirtydesc = b->batDirtydesc,
+ .copiedtodisk = b->batCopiedtodisk,
+ .transient = b->batTransient,
+ .restricted = b->batRestricted,
#ifndef NDEBUG
.locked = false,
#endif
@@ -1282,6 +1304,10 @@ gdk_export restrict_t BATgetaccess(BAT *
(b)->batDirtydesc || \
(b)->theap->dirty || \
((b)->tvheap != NULL && (b)->tvheap->dirty))
+#define BATdirtybi(bi) (!(bi).copiedtodisk || \
+ (bi).dirtydesc || \
+ (bi).hdirty || \
+ (bi).vhdirty)
#define BATdirtydata(b) (!(b)->batCopiedtodisk ||
\
(b)->theap->dirty || \
((b)->tvheap != NULL && (b)->tvheap->dirty))
@@ -1396,7 +1422,8 @@ gdk_export void GDKqsort(void *restrict
#define BATtvoid(b) (BATtdense(b) || (b)->ttype==TYPE_void)
#define BATtkey(b) ((b)->tkey || BATtdense(b))
-/* set some properties that are trivial to deduce */
+/* set some properties that are trivial to deduce; called with theaplock
+ * held */
static inline void
BATsettrivprop(BAT *b)
{
diff --git a/gdk/gdk_aggr.c b/gdk/gdk_aggr.c
--- a/gdk/gdk_aggr.c
+++ b/gdk/gdk_aggr.c
@@ -3746,8 +3746,11 @@ BATmin_skipnil(BAT *b, void *aggr, bit s
bi.width, 0, bi.count,
ATOMnilptr(bi.type), 1, 1);
if (r == 0) {
- bi.nonil = true;
+ /* there are no nils, record that */
+ MT_lock_set(&b->theaplock);
+ b->tnonil = true;
b->batDirtydesc = true;
+ MT_lock_unset(&b->theaplock);
}
} else {
r = 0;
diff --git a/gdk/gdk_align.c b/gdk/gdk_align.c
--- a/gdk/gdk_align.c
+++ b/gdk/gdk_align.c
@@ -262,11 +262,11 @@ BATmaterialize(BAT *b)
b->tbaseoff = 0;
b->theap->dirty = true;
b->tunique_est = is_oid_nil(t) ? 1.0 : (double) b->batCount;
- MT_lock_unset(&b->theaplock);
b->ttype = TYPE_oid;
BATsetdims(b, 0);
b->batDirtydesc = true;
BATsetcount(b, b->batCount);
+ MT_lock_unset(&b->theaplock);
HEAPdecref(h, false);
if (vh)
HEAPdecref(vh, true);
diff --git a/gdk/gdk_bat.c b/gdk/gdk_bat.c
--- a/gdk/gdk_bat.c
+++ b/gdk/gdk_bat.c
@@ -804,7 +804,7 @@ COLcopy(BAT *b, int tt, bool writable, r
* atom-types */
if (!writable &&
role == TRANSIENT &&
- b->batRestricted == BAT_READ &&
+ bi.restricted == BAT_READ &&
ATOMstorage(b->ttype) != TYPE_msk && /* no view on TYPE_msk */
(!VIEWtparent(b) ||
BBP_cache(VIEWtparent(b))->batRestricted == BAT_READ)) {
@@ -1033,9 +1033,11 @@ BUNappendmulti(BAT *b, const void *value
}
}
if (dense) {
+ MT_lock_set(&b->theaplock);
if (b->batCount == 0)
b->tseqbase = ovals ? ovals[0] : oid_nil;
BATsetcount(b, BATcount(b) + count);
+ MT_lock_unset(&b->theaplock);
return GDK_SUCCEED;
} else {
/* we need to materialize b; allocate enough capacity */
@@ -1062,11 +1064,10 @@ BUNappendmulti(BAT *b, const void *value
return rc;
}
- if (count > BATcount(b) / gdk_unique_estimate_keep_fraction) {
- MT_lock_set(&b->theaplock);
+ MT_lock_set(&b->theaplock);
+ if (count > BATcount(b) / gdk_unique_estimate_keep_fraction)
b->tunique_est = 0;
- MT_lock_unset(&b->theaplock);
- }
+
const void *t = b->ttype == TYPE_msk ? &(msk){false} :
ATOMnilptr(b->ttype);
if (b->ttype == TYPE_oid) {
/* spend extra effort on oid (possible candidate list) */
@@ -1162,6 +1163,7 @@ BUNappendmulti(BAT *b, const void *value
b->tnonil = false;
b->tsorted = b->trevsorted = b->tkey = false;
}
+ MT_lock_unset(&b->theaplock);
MT_rwlock_wrlock(&b->thashlock);
if (values && b->ttype) {
int (*atomcmp) (const void *, const void *) =
ATOMcompare(b->ttype);
@@ -1273,7 +1275,9 @@ BUNappendmulti(BAT *b, const void *value
}
}
MT_rwlock_wrunlock(&b->thashlock);
+ MT_lock_set(&b->theaplock);
BATsetcount(b, p);
+ MT_lock_unset(&b->theaplock);
IMPSdestroy(b); /* no support for inserts in imprints yet */
OIDXdestroy(b);
@@ -1307,12 +1311,12 @@ BUNdelete(BAT *b, oid o)
return GDK_FAIL;
}
TRC_DEBUG(ALGO, ALGOBATFMT " deleting oid " OIDFMT "\n", ALGOBATPAR(b),
o);
- b->batDirtydesc = true;
val = BUNtail(bi, p);
/* writing the values should be locked, reading could be done
* unlocked (since we're the only thread that should be changing
* anything) */
MT_lock_set(&b->theaplock);
+ b->batDirtydesc = true;
if (b->tmaxpos == p)
b->tmaxpos = BUN_NONE;
if (b->tminpos == p)
@@ -1320,7 +1324,7 @@ BUNdelete(BAT *b, oid o)
MT_lock_unset(&b->theaplock);
if (ATOMunfix(b->ttype, val) != GDK_SUCCEED)
return GDK_FAIL;
- HASHdelete(b, p, val);
+ HASHdelete(&bi, p, val);
ATOMdel(b->ttype, b->tvheap, (var_t *) BUNtloc(bi, p));
if (p != BATcount(b) - 1 &&
(b->ttype != TYPE_void || BATtdense(b))) {
@@ -1337,9 +1341,9 @@ BUNdelete(BAT *b, oid o)
mskClr(b, BATcount(b) - 1);
} else {
val = Tloc(b, BATcount(b) - 1);
- HASHdelete(b, BATcount(b) - 1, val);
+ HASHdelete(&bi, BATcount(b) - 1, val);
memcpy(Tloc(b, p), val, b->twidth);
- HASHinsert(b, p, val);
+ HASHinsert(&bi, p, val);
MT_lock_set(&b->theaplock);
if (b->tminpos == BATcount(b) - 1)
b->tminpos = p;
@@ -1348,18 +1352,19 @@ BUNdelete(BAT *b, oid o)
MT_lock_unset(&b->theaplock);
}
/* no longer sorted */
+ MT_lock_set(&b->theaplock);
b->tsorted = b->trevsorted = false;
b->theap->dirty = true;
+ MT_lock_unset(&b->theaplock);
}
+ MT_lock_set(&b->theaplock);
if (b->tnosorted >= p)
b->tnosorted = 0;
if (b->tnorevsorted >= p)
b->tnorevsorted = 0;
- MT_lock_set(&b->theaplock);
b->batCount--;
if (BATcount(b) < gdk_unique_estimate_keep_fraction)
b->tunique_est = 0;
- MT_lock_unset(&b->theaplock);
if (b->batCount <= 1) {
/* some trivial properties */
b->tkey = true;
@@ -1370,6 +1375,7 @@ BUNdelete(BAT *b, oid o)
b->tnonil = true;
}
}
+ MT_lock_unset(&b->theaplock);
IMPSdestroy(b);
OIDXdestroy(b);
return GDK_SUCCEED;
@@ -1487,7 +1493,7 @@ BUNinplacemulti(BAT *b, const oid *posit
}
}
}
- HASHdelete_locked(b, p, val); /* first delete old
value from hash */
+ HASHdelete_locked(&bi, p, val); /* first delete old
value from hash */
} else {
/* out of range old value, so the properties and
* hash cannot be trusted */
@@ -1606,12 +1612,13 @@ BUNinplacemulti(BAT *b, const oid *posit
}
}
- HASHinsert_locked(b, p, t); /* insert new value into hash */
+ HASHinsert_locked(&bi, p, t); /* insert new value into hash */
tt = b->ttype;
prv = p > 0 ? p - 1 : BUN_NONE;
nxt = p < last ? p + 1 : BUN_NONE;
+ MT_lock_set(&b->theaplock);
if (b->tsorted) {
if (prv != BUN_NONE &&
ATOMcmp(tt, t, BUNtail(bi, prv)) < 0) {
@@ -1653,6 +1660,7 @@ BUNinplacemulti(BAT *b, const oid *posit
b->tnokey[0] = b->tnokey[1] = 0;
if (b->tnonil && ATOMstorage(b->ttype) != TYPE_msk)
b->tnonil = t && ATOMcmp(b->ttype, t,
ATOMnilptr(b->ttype)) != 0;
+ MT_lock_unset(&b->theaplock);
}
MT_rwlock_wrunlock(&b->thashlock);
MT_lock_set(&b->theaplock);
@@ -1864,6 +1872,9 @@ BATsetcapacity(BAT *b, BUN cnt)
assert(b->batCount <= cnt);
}
+/* Set the batCount value for the bat and also set some dependent
+ * properties. This function should be called only when it is save from
+ * concurrent use (e.g. when theaplock is being held). */
void
BATsetcount(BAT *b, BUN cnt)
{
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]