Changeset: 486f2ab17d12 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=486f2ab17d12
Modified Files:
gdk/gdk_atoms.c
Branch: Feb2013
Log Message:
Rebuild string heap double elimination hash table upon load.
diffs (118 lines):
diff --git a/gdk/gdk_atoms.c b/gdk/gdk_atoms.c
--- a/gdk/gdk_atoms.c
+++ b/gdk/gdk_atoms.c
@@ -1076,6 +1076,9 @@ strHash(const char *s)
return res;
}
+/* if at least (2*SIZEOF_BUN), also store length (heaps are then
+ * incompatible) */
+#define EXTRALEN ((SIZEOF_BUN + GDK_VARALIGN - 1) & ~(GDK_VARALIGN - 1))
void
strCleanHash(Heap *h, int rebuild)
@@ -1084,6 +1087,40 @@ strCleanHash(Heap *h, int rebuild)
if (!GDK_ELIMDOUBLES(h)) {
/* flush hash table for security */
memset(h->base, 0, GDK_STRHASHSIZE);
+ } else {
+ /* rebuild hash table for double elimination
+ *
+ * If appending strings to the BAT was aborted, if the
+ * heap was memory mapped, the hash in the string heap
+ * may well be incorrect. Therefore we don't trust it
+ * when we read in a string heap and we rebuild the
+ * complete table (it is small, so this won't take any
+ * time at all). */
+ size_t pad, pos;
+ const size_t extralen = h->hashash ? EXTRALEN : 0;
+ stridx_t *bucket;
+ BUN off, strhash;
+ const char *s;
+
+ memset(h->base, 0, GDK_STRHASHSIZE);
+ pos = GDK_STRHASHSIZE;
+ while (pos < h->free) {
+ pad = GDK_VARALIGN - (pos & (GDK_VARALIGN - 1));
+ if (pad < sizeof(stridx_t))
+ pad += GDK_VARALIGN;
+ pos += pad + extralen;
+ s = h->base + pos;
+ if (h->hashash)
+ strhash = ((const BUN *) s)[-1];
+ else
+ GDK_STRHASH(s, strhash);
+ off = strhash & GDK_STRHASHMASK;
+ bucket = ((stridx_t *) h->base) + off;
+ if (*bucket == 0)
+ *bucket = pos - extralen - sizeof(stridx_t);
+ assert(strLocate(h, s) != 0);
+ pos += GDK_STRLEN(s);
+ }
}
}
@@ -1092,15 +1129,11 @@ strCleanHash(Heap *h, int rebuild)
* the location of a string in the heap if it exists. Otherwise it
* returns zero.
*/
-/* if at least (2*SIZEOF_BUN), also store length (heaps are then
- * incompatible) */
-#define EXTRALEN ((SIZEOF_BUN + GDK_VARALIGN - 1) & ~(GDK_VARALIGN - 1))
-
var_t
strLocate(Heap *h, const char *v)
{
stridx_t *ref, *next;
- size_t extralen = h->hashash ? EXTRALEN : 0;
+ const size_t extralen = h->hashash ? EXTRALEN : 0;
/* search hash-table, if double-elimination is still in place */
BUN off;
@@ -1125,7 +1158,7 @@ strPut(Heap *h, var_t *dst, const char *
size_t elimbase = GDK_ELIMBASE(h->free);
size_t pad = GDK_VARALIGN - (h->free & (GDK_VARALIGN - 1));
size_t pos, len = GDK_STRLEN(v);
- size_t extralen = h->hashash ? EXTRALEN : 0;
+ const size_t extralen = h->hashash ? EXTRALEN : 0;
stridx_t *bucket, *ref, *next;
BUN off, strhash;
@@ -1134,24 +1167,30 @@ strPut(Heap *h, var_t *dst, const char *
off &= GDK_STRHASHMASK;
bucket = ((stridx_t *) h->base) + off;
- /* search hash-table, if double-elimination is still in place */
- if (elimbase == 0) { /* small string heap (<64KB) -- fully double
eliminated */
- for (ref = bucket; *ref; ref = next) { /* search the linked
list */
+ /* if double-elimination is still in place, search hash-table */
+ if (elimbase == 0) {
+ /* small string heap (<64KB) -- fully double eliminated */
+ for (ref = bucket; *ref; ref = next) {
+ /* search the linked list */
next = (stridx_t *) (h->base + *ref);
- if (GDK_STRCMP(v, (str) (next + 1) + extralen) == 0) {
/* found */
+ if (GDK_STRCMP(v, (str) (next + 1) + extralen) == 0) {
+ /* found */
pos = sizeof(stridx_t) + *ref + extralen;
return *dst = (var_t) (pos >> GDK_VARSHIFT);
}
}
/* is there room for the next pointer in the padding space? */
- if (pad < sizeof(stridx_t))
- pad += GDK_VARALIGN; /* if not, pad more */
+ if (pad < sizeof(stridx_t)) {
+ /* if not, pad more */
+ pad += GDK_VARALIGN;
+ }
} else if (*bucket) {
/* large string heap (>=64KB) --
* opportunistic/probabilistic double elimination */
pos = elimbase + *bucket + extralen;
if (GDK_STRCMP(v, h->base + pos) == 0) {
- return *dst = (var_t) (pos >> GDK_VARSHIFT); /*
already in heap; do not insert! */
+ /* already in heap; do not insert! */
+ return *dst = (var_t) (pos >> GDK_VARSHIFT);
}
#if SIZEOF_VAR_T >= SIZEOF_VOID_P /* in fact SIZEOF_VAR_T == SIZEOF_VOID_P */
if (extralen == 0)
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list