/* * the @#VIEWcombine@ routine effortlessly produces a view with double * vision on the head column. */ BAT * VIEWcombine(BAT *b) { BAT *bn = VIEWhcreate(b), *bm; if (bn == NULL) return NULL; bm = BATmirror(bn); if (bm == NULL) return NULL; if (bn->htype != TYPE_void) { assert(bn->T->vheap == NULL); bn->T = bn->H; bm->H = bn->H; if (bn->T->heap.parentid) BBPshare(bn->T->heap.parentid); if (bn->T->vheap) { assert(bn->T->vheap->parentid != abs(bn->batCacheid)); assert(bn->T->vheap->parentid > 0); BBPshare(bn->T->vheap->parentid); } ALIGNsetH(bn, b); } else { BATseqbase(bm, bn->hseqbase); } return bn; }
/* * @+ View BATS * The general routine for getting a 'view' BAT upon another BAT is * @emph{VIEWcreate}. On this @emph{#read-only} BAT (there is kernel * support for this), you can then make vertical slices. Use * @emph{VIEWhead} for this. * * It is possible to create a view on a writable BAT. Updates in the * parent are then automatically reflected in the VIEW. Note that the * VIEW bat itself can never be modified. * * Horizontal views should only be given out on a view BAT, but only * if it is dead sure the parent BAT is read-only. This because they * cannot physically share the batBuns heap with the parent, as they * need a modified version. */ static BAT * VIEWhcreate(BAT *h) { BATstore *bs; BAT *bn; bat hp; BATcheck(h, "VIEWhcreate", NULL); bs = BATcreatedesc(h->htype, TYPE_void, FALSE, TRANSIENT); if (bs == NULL) return NULL; bn = &bs->B; BATsetdims(bn); hp = VIEWhparent(h); if (h->htype == TYPE_void) hp = 0; if ((hp == 0 && h->htype != TYPE_void) || h->H->heap.copied) hp = h->batCacheid; if (hp) BBPshare(hp); *bn->H = *h->H; bn->batDeleted = h->batDeleted; bn->batFirst = h->batFirst; bn->batInserted = h->batInserted; bn->batCount = h->batCount; bn->batCapacity = h->batCapacity; if (bn->H->vheap) { assert(h->H->vheap); assert(bn->H->vheap->parentid != 0); bn->H->vheap->farmid = h->H->vheap->farmid; BBPshare(bn->H->vheap->parentid); } /* correct values after copy of head info */ bn->H->props = NULL; bn->H->heap.copied = 0; if (hp) bn->H->heap.parentid = hp; if (hp && isVIEW(h)) bn->H->hash = NULL; BATinit_idents(bn); /* some bits must be copied individually. */ bn->batDirty = BATdirty(h); bn->batRestricted = BAT_READ; BBPcacheit(bs, 1); /* enter in BBP */ return bn; }
BAT * VIEWcreate_(BAT *h, BAT *t, int slice_view) { BATstore *bs; BAT *bn; bat hp = 0, tp = 0, vc = 0; BATcheck(h, "VIEWcreate_", NULL); BATcheck(t, "VIEWcreate_", NULL); if (BATcount(h) != BATcount(t)) slice_view = 1; bs = BATcreatedesc(h->htype, t->ttype, FALSE, TRANSIENT); if (bs == NULL) return NULL; bn = &bs->B; hp = VIEWhparent(h); tp = VIEWtparent(t); if ((hp == 0 && h->htype != TYPE_void) || h->H->heap.copied) hp = h->batCacheid; if ((tp == 0 && t->ttype != TYPE_void) || t->T->heap.copied) tp = -t->batCacheid; assert(h->htype != TYPE_void || !hp); assert(t->ttype != TYPE_void || !tp); /* the H and T column descriptors are fully copied. We need * copies because in case of a mark, we are going to override * a column with a void. Take care to zero the accelerator * data, though. */ *bn->H = *h->H; bn->batDeleted = h->batDeleted; bn->batFirst = h->batFirst; bn->batInserted = h->batInserted; bn->batCount = h->batCount; bn->batCapacity = h->batCapacity; if (bn->batFirst > 0) { bn->H->heap.base += h->batFirst * h->H->width; bn->batFirst = 0; } if (h->H == t->T) { vc = 1; tp = hp; bn->T = bn->H; } else { *bn->T = *t->T; if (bn->batCapacity > t->batCapacity) bn->batCapacity = t->batCapacity; if (t->batFirst > 0) bn->T->heap.base += t->batFirst * t->T->width; if (bn->batCount < t->batCount) { /* we can't be sure anymore there are nils */ bn->T->nil = 0; } } if (hp) BBPshare(hp); if (tp) BBPshare(tp); if (bn->H->vheap) { assert(h->H->vheap); assert(bn->H->vheap->parentid > 0); bn->H->vheap->farmid = h->H->vheap->farmid; BBPshare(bn->H->vheap->parentid); } if (bn->T->vheap) { assert(t->T->vheap); assert(bn->T->vheap->parentid > 0); bn->T->vheap->farmid = t->T->vheap->farmid; BBPshare(bn->T->vheap->parentid); } /* note: H/T->heap's points into bs which was just overwritten * with a copy from the parent(s). Clear the copied flag since * our heap was not copied from our parent(s) even if our * parent's heap was copied from its parent(s). */ bn->H->heap.copied = bn->T->heap.copied = 0; bn->H->props = bn->T->props = NULL; /* correct values after copy of head and tail info */ if (hp) bn->H->heap.parentid = hp; if (tp) bn->T->heap.parentid = tp; BATinit_idents(bn); /* Some bits must be copied individually. */ bn->batDirty = BATdirty(h); bn->batRestricted = BAT_READ; if (slice_view || !hp || isVIEW(h)) /* slices are unequal to their parents; cannot use accs */ bn->H->hash = NULL; else /* equal pointers to parent mean view uses acc of parent */ bn->H->hash = h->H->hash; if (slice_view || !tp || isVIEW(t)) bn->T->hash = NULL; else bn->T->hash = t->T->hash; /* imprints are shared, but the check is dynamic */ bn->H->imprints = NULL; bn->T->imprints = NULL; BBPcacheit(bs, 1); /* enter in BBP */ /* View of VIEW combine, ie we need to fix the head of the mirror */ if (vc) { BAT *bm = BATmirror(bn); bm->H = bn->H; } return bn; }
/* * Mitosis-pieces are usually slices (views) of a base table/BAT. * For variable-size atoms, this means that the vheap's of all pieces are * likely to be identical (full) views of the same original base-BAT vheap. * If so, the result of MATproject can also simply be a view of that very * original base-BAT vheap (rather than a new view with all value (re-)inserted), * i.e., we only need to build the result's tail BUN heap by copying the * pointers (references) into the vheap from the input BATs (pieces). */ static BAT * MATproject_var( BAT *map, BAT **bats, int len ) { BAT *res = NULL; int i = 0, j = -1; bit shared_Tvheaps = FALSE; while (i < len && BATcount(bats[i]) == 0) i++; if (i < len && bats[i]->tvarsized && bats[i]->T->vheap != NULL && bats[i]->T->vheap->parentid > 0) { shared_Tvheaps = TRUE; j = i++; } while (shared_Tvheaps && i < len) { shared_Tvheaps &= (BATcount(bats[i]) == 0 || ( bats[i]->ttype == bats[j]->ttype && bats[i]->batRestricted == BAT_READ && bats[i]->T->vheap == bats[j]->T->vheap && bats[i]->T->width == bats[j]->T->width && bats[i]->T->shift == bats[j]->T->shift )); i++; } if (shared_Tvheaps) { switch (bats[j]->T->width) { case sizeof(bte): res = MATproject_bte(map, bats, len, TYPE_bte); break; case sizeof(sht): res = MATproject_sht(map, bats, len, TYPE_sht); break; case sizeof(int): res = MATproject_int(map, bats, len, TYPE_int); break; case sizeof(lng): res = MATproject_lng(map, bats, len, TYPE_lng); break; #ifdef HAVE_HGE case sizeof(hge): res = MATproject_hge(map, bats, len, TYPE_hge); break; #endif default: /* can (should) not happen */ assert(0); return MATproject_any( map, bats, len ); } if (res != NULL) { res->tvarsized = 1; res->ttype = bats[j]->ttype; res->T->vheap = bats[j]->T->vheap; res->T->width = bats[j]->T->width; res->T->shift = bats[j]->T->shift; BBPshare(bats[j]->T->vheap->parentid); } } else res = MATproject_any( map, bats, len ); return res; }