Changeset: 7253f70231be for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=7253f70231be
Modified Files:
        gdk/gdk_heap.c
        gdk/gdk_private.h
        gdk/gdk_storage.c
Branch: Jul2017
Log Message:

Recover varheaps on first loading after startup.
This fixes bug 6465.


diffs (156 lines):

diff --git a/gdk/gdk_heap.c b/gdk/gdk_heap.c
--- a/gdk/gdk_heap.c
+++ b/gdk/gdk_heap.c
@@ -1003,7 +1003,7 @@ HEAP_malloc(Heap *heap, size_t nbytes)
         */
        ttrail = 0;
        trail = 0;
-       for (block = hheader->head; block != 0; block = HEAP_index(heap, block, 
CHUNK)->next) {
+       for (block = hheader->head; block != 0; block = blockp->next) {
                blockp = HEAP_index(heap, block, CHUNK);
 
 #ifdef TRACE
@@ -1171,3 +1171,118 @@ HEAP_free(Heap *heap, var_t mem)
                hheader->head = block;
        }
 }
+
+void
+HEAP_recover(Heap *h, const var_t *offsets, BUN noffsets)
+{
+       HEADER *hheader;
+       CHUNK *blockp;
+       size_t dirty = 0;
+       var_t maxoff = 0;
+       BUN i;
+
+       if (!h->cleanhash)
+               return;
+       hheader = HEAP_index(h, 0, HEADER);
+       assert(h->free >= sizeof(HEADER));
+       assert(hheader->version == HEAPVERSION);
+       assert(h->size >= hheader->firstblock);
+       for (i = 0; i < noffsets; i++)
+               if (offsets[i] > maxoff)
+                       maxoff = offsets[i];
+       assert(maxoff < h->free);
+       if (maxoff == 0) {
+               if (hheader->head != hheader->firstblock) {
+                       hheader->head = hheader->firstblock;
+                       dirty = sizeof(HEADER);
+               }
+               blockp = HEAP_index(h, hheader->firstblock, CHUNK);
+               if (blockp->next != 0 ||
+                   blockp->size != h->size - hheader->head) {
+                       blockp->size = (size_t) (h->size - hheader->head);
+                       blockp->next = 0;
+                       dirty = hheader->firstblock + sizeof(CHUNK);
+               }
+       } else {
+               size_t block = maxoff - hheader->alignment;
+               size_t end = block + *HEAP_index(h, block, size_t);
+               size_t trail;
+
+               assert(end <= h->free);
+               if (end + sizeof(CHUNK) <= h->free) {
+                       blockp = HEAP_index(h, end, CHUNK);
+                       if (hheader->head <= end &&
+                           blockp->next == 0 &&
+                           blockp->size == h->free - end)
+                               return;
+               } else if (hheader->head == 0) {
+                       /* no free space after last allocated block
+                        * and no free list */
+                       return;
+               }
+               block = hheader->head;
+               trail = 0;
+               while (block < maxoff && block != 0) {
+                       blockp = HEAP_index(h, block, CHUNK);
+                       trail = block;
+                       block = blockp->next;
+               }
+               if (trail == 0) {
+                       /* no free list */
+                       if (end + sizeof(CHUNK) > h->free) {
+                               /* no free space after last allocated
+                                * block */
+                               if (hheader->head != 0) {
+                                       hheader->head = 0;
+                                       dirty = sizeof(HEADER);
+                               }
+                       } else {
+                               /* there is free space after last
+                                * allocated block */
+                               if (hheader->head != end) {
+                                       hheader->head = end;
+                                       dirty = sizeof(HEADER);
+                               }
+                               blockp = HEAP_index(h, end, CHUNK);
+                               if (blockp->next != 0 ||
+                                   blockp->size != h->free - end) {
+                                       blockp->next = 0;
+                                       blockp->size = h->free - end;
+                                       dirty = end + sizeof(CHUNK);
+                               }
+                       }
+               } else {
+                       /* there is a free list */
+                       blockp = HEAP_index(h, trail, CHUNK);
+                       if (end + sizeof(CHUNK) > h->free) {
+                               /* no free space after last allocated
+                                * block */
+                               if (blockp->next != 0) {
+                                       blockp->next = 0;
+                                       dirty = trail + sizeof(CHUNK);
+                               }
+                       } else {
+                               /* there is free space after last
+                                * allocated block */
+                               if (blockp->next != end) {
+                                       blockp->next = end;
+                                       dirty = trail + sizeof(CHUNK);
+                               }
+                               blockp = HEAP_index(h, end, CHUNK);
+                               if (blockp->next != 0 ||
+                                   blockp->size != h->free - end) {
+                                       blockp->next = 0;
+                                       blockp->size = h->free - end;
+                                       dirty = end + sizeof(CHUNK);
+                               }
+                       }
+               }
+       }
+       h->cleanhash = 0;
+       if (dirty) {
+               if (h->storage == STORE_MMAP)
+                       (void) MT_msync(h->base, dirty);
+               else
+                       h->dirty = 1;
+       }
+}
diff --git a/gdk/gdk_private.h b/gdk/gdk_private.h
--- a/gdk/gdk_private.h
+++ b/gdk/gdk_private.h
@@ -172,6 +172,8 @@ void BBPdump(void);         /* never called: fo
 __hidden gdk_return HEAPload(Heap *h, const char *nme, const char *ext, int 
trunc)
        __attribute__((__warn_unused_result__))
        __attribute__((__visibility__("hidden")));
+__hidden void HEAP_recover(Heap *, const var_t *, BUN)
+       __attribute__((__visibility__("hidden")));
 __hidden gdk_return HEAPsave(Heap *h, const char *nme, const char *ext)
        __attribute__((__warn_unused_result__))
        __attribute__((__visibility__("hidden")));
diff --git a/gdk/gdk_storage.c b/gdk/gdk_storage.c
--- a/gdk/gdk_storage.c
+++ b/gdk/gdk_storage.c
@@ -824,6 +824,9 @@ BATload_intern(bat bid, int lock)
                }
                if (ATOMstorage(b->ttype) == TYPE_str) {
                        strCleanHash(b->tvheap, FALSE); /* ensure consistency */
+               } else {
+                       HEAP_recover(b->tvheap, (const var_t *) Tloc(b, 0),
+                                    BATcount(b));
                }
        }
 
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to