str BKCinsert_bat_force(bat *r, const bat *bid, const bat *sid, const bit *force) { BAT *b, *s; if ((b = BATdescriptor(*bid)) == NULL) throw(MAL, "bat.insert", RUNTIME_OBJECT_MISSING); if ((b = setaccess(b, BAT_WRITE)) == NULL) throw(MAL, "bat.insert", OPERATION_FAILED); if ((s = BATdescriptor(*sid)) == NULL) { BBPunfix(b->batCacheid); throw(MAL, "bat.insert", RUNTIME_OBJECT_MISSING); } if (BATins(b, s, *force) != GDK_SUCCEED) { BBPunfix(b->batCacheid); BBPunfix(s->batCacheid); throw(MAL, "bat.insert", GDK_EXCEPTION); } BBPunfix(s->batCacheid); BBPkeepref(*r = b->batCacheid); return MAL_SUCCEED; }
/* * Materialize a view into a normal BAT. If it is a slice, we really * want to reduce storage of the new BAT. */ gdk_return VIEWreset(BAT *b) { bat hp, tp, hvp, tvp; Heap head, tail, hh, th; BAT *n = NULL, *v = NULL; if (b == NULL) return GDK_FAIL; hp = VIEWhparent(b); tp = VIEWtparent(b); hvp = VIEWvhparent(b); tvp = VIEWvtparent(b); if (hp || tp) { BAT *m; BATstore *bs; BUN cnt; str nme; size_t nmelen; /* alloc heaps */ memset(&head, 0, sizeof(Heap)); memset(&tail, 0, sizeof(Heap)); memset(&hh, 0, sizeof(Heap)); memset(&th, 0, sizeof(Heap)); n = BATdescriptor(abs(b->batCacheid)); /* normalized */ if (n == NULL) goto bailout; m = BATmirror(n); /* mirror of normalized */ bs = BBP_desc(n->batCacheid); cnt = BATcount(n) + 1; nme = BBP_physical(n->batCacheid); nmelen = nme ? strlen(nme) : 0; assert(n->batCacheid > 0); assert(hp || !b->htype); assert(tp || !b->ttype); head.farmid = BBPselectfarm(n->batRole, n->htype, offheap); tail.farmid = BBPselectfarm(n->batRole, n->ttype, offheap); if (n->htype) { head.filename = (str) GDKmalloc(nmelen + 12); if (head.filename == NULL) goto bailout; snprintf(head.filename, nmelen + 12, "%s.head", nme); if (n->htype && HEAPalloc(&head, cnt, Hsize(n)) != GDK_SUCCEED) goto bailout; } if (n->ttype) { tail.filename = (str) GDKmalloc(nmelen + 12); if (tail.filename == NULL) goto bailout; snprintf(tail.filename, nmelen + 12, "%s.tail", nme); if (n->ttype && HEAPalloc(&tail, cnt, Tsize(n)) != GDK_SUCCEED) goto bailout; } if (n->H->vheap) { hh.farmid = BBPselectfarm(n->batRole, n->htype, varheap); hh.filename = (str) GDKmalloc(nmelen + 12); if (hh.filename == NULL) goto bailout; snprintf(hh.filename, nmelen + 12, "%s.hheap", nme); if (ATOMheap(n->htype, &hh, cnt) != GDK_SUCCEED) goto bailout; } if (n->T->vheap) { th.farmid = BBPselectfarm(n->batRole, n->ttype, varheap); th.filename = (str) GDKmalloc(nmelen + 12); if (th.filename == NULL) goto bailout; snprintf(th.filename, nmelen + 12, "%s.theap", nme); if (ATOMheap(n->ttype, &th, cnt) != GDK_SUCCEED) goto bailout; } v = VIEWcreate(n, n); if (v == NULL) goto bailout; /* cut the link to your parents */ VIEWunlink(n); if (hp) { BBPunshare(hp); BBPunfix(hp); } if (tp) { BBPunshare(tp); BBPunfix(tp); } if (hvp) { BBPunshare(hvp); BBPunfix(hvp); } if (tvp) { BBPunshare(tvp); BBPunfix(tvp); } /* make sure everything points there */ m->S = n->S = &bs->S; m->T = n->H = &bs->H; m->H = n->T = &bs->T; n->H->type = v->H->type; n->H->varsized = v->H->varsized; n->H->shift = v->H->shift; n->H->width = v->H->width; n->H->seq = v->H->seq; n->T->type = v->T->type; n->T->varsized = v->T->varsized; n->T->shift = v->T->shift; n->T->width = v->T->width; n->T->seq = v->T->seq; n->H->heap.parentid = n->T->heap.parentid = 0; n->batRestricted = BAT_WRITE; /* reset BOUND2KEY */ n->H->key = BAThkey(v); n->T->key = BATtkey(v); /* copy the heaps */ n->H->heap = head; n->T->heap = tail; /* unshare from parents heap */ if (hh.base) { assert(n->H->vheap == NULL); n->H->vheap = (Heap *) GDKzalloc(sizeof(Heap)); if (n->H->vheap == NULL) goto bailout; *n->H->vheap = hh; n->H->vheap->parentid = n->batCacheid; } if (th.base) { assert(n->T->vheap == NULL); n->T->vheap = (Heap *) GDKzalloc(sizeof(Heap)); if (n->T->vheap == NULL) goto bailout; *n->T->vheap = th; n->T->vheap->parentid = n->batCacheid; } n->batSharecnt = 0; n->batCopiedtodisk = 0; n->batDirty = 1; /* reset BOUND2KEY */ n->hkey = BAThkey(v); n->tkey = BATtkey(v); /* make the BAT empty and insert all again */ DELTAinit(n); /* reset capacity */ n->batCapacity = cnt; /* swap n and v in case the original input was reversed, because * BATins demands (v)oid-headed input */ if (b->batCacheid < 0) { n = m; m = BATmirror(v); } else { m = v; } /* insert all of v in n, and quit */ BATins(n, m, FALSE); BBPreclaim(v); BBPunfix(n->batCacheid); } return GDK_SUCCEED; bailout: BBPreclaim(v); if (n != NULL) BBPunfix(n->batCacheid); HEAPfree(&head, 0); HEAPfree(&tail, 0); HEAPfree(&hh, 0); HEAPfree(&th, 0); return GDK_FAIL; }
static str MATpackSliceInternal(MalBlkPtr mb, MalStkPtr stk, InstrPtr p) { int i, i1 = p->argc, i2 = -1, *ret = (int*) getArgReference(stk,p,0); BAT *b, *bn; BUN cap = 0, fst, lst, cnt, c; int ht = TYPE_any, tt = TYPE_any; assert(p->argc > 3); switch getArgType(mb,p,1) { case TYPE_wrd: fst = (BUN) *(wrd*) getArgReference(stk,p,1); break; case TYPE_lng: fst = (BUN) *(lng*) getArgReference(stk,p,1); break; case TYPE_int: fst = (BUN) *(int*) getArgReference(stk,p,1); break; default: throw(MAL, "mat.packSlice", "wrong type for lower bound"); } switch getArgType(mb,p,2) { case TYPE_wrd: { wrd l = *(wrd*) getArgReference(stk,p,2); if (l == wrd_nil) lst = BUN_MAX; /* no upper bound */ else lst = (BUN) l; break; } case TYPE_lng: { lng l = *(lng*) getArgReference(stk,p,2); if (l == lng_nil) lst = BUN_MAX; /* no upper bound */ else lst = (BUN) l; break; } case TYPE_int: { int l = *(int*) getArgReference(stk,p,2); if (l == int_nil) lst = BUN_MAX; /* no upper bound */ else lst = (BUN) l; break; } default: throw(MAL, "mat.packSlice", "wrong type for upper bound"); } if (lst < BUN_MAX) lst++; /* inclusive -> exclusive upper bound */ if (lst < fst) lst = fst; cnt = lst - fst; for (i = 3; i < p->argc && cap < lst; i++) { int bid = stk->stk[getArg(p,i)].val.ival; b = BBPquickdesc(abs(bid),FALSE); if (b && bid < 0) b = BATmirror(b); if (b == NULL) throw(MAL, "mat.packSlice", RUNTIME_OBJECT_MISSING); if (ht == TYPE_any){ ht = b->htype; tt = b->ttype; } c = BATcount(b); if (cap <= fst) { /* The optimal case is when the requested slice falls completely in one BAT. * In that case, we can simply return a slice (view) of that BAT. * (A pitty that we have calculated the other slices as well.) */ if (lst <= cap + c) { b = BATdescriptor(bid); if( b){ bn = BATslice(b, fst - cap, lst - cap); BBPunfix(b->batCacheid); BBPkeepref(*ret = bn->batCacheid); } else throw(MAL, "mat.packSlice", RUNTIME_OBJECT_MISSING); return MAL_SUCCEED; } if (fst < cap + c) { /* fst falls in BAT i1 == i */ i1 = i; fst -= cap; lst -= cap; cap = 0; } } cap += c; } /* lst falls in BAT i2 == i-1 */ i2 = i - 1; if (cap <= fst) /* i.e., (i1 > i2) */ cap = 0; else cap -= fst; cnt = MIN(cnt, cap); assert(ht== TYPE_void); bn = BATnew(TYPE_void, tt, cnt, TRANSIENT); if (bn == NULL) throw(MAL, "mat.packSlice", MAL_MALLOC_FAIL); /* must set seqbase or else BATins will not materialize column */ BATseqbase(bn, 0); if (tt == TYPE_void) BATseqbase(BATmirror(bn), 0); for (i = i1; i <= i2; i++) { b = BATdescriptor(stk->stk[getArg(p,i)].val.ival); if (b == NULL){ BBPreleaseref(bn->batCacheid); throw(MAL, "mat.packSlice", RUNTIME_OBJECT_MISSING); } c = BATcount(b); /* use the right oid ranges, don't change the input */ if (i == i1 && fst > 0) { BAT *bb = b; b = BATslice(bb, fst, c); BBPunfix(bb->batCacheid); } else if (i == i2 && lst < c) { BAT *bb = b; b = BATslice(bb, 0, lst); BBPunfix(bb->batCacheid); } BATins(bn,b,FALSE); lst -= c; BBPunfix(b->batCacheid); } BBPkeepref(*ret = bn->batCacheid); return MAL_SUCCEED; }