/* actual implementation */ static char * UDFBATreverse_(BAT **ret, BAT *src) { BATiter li; BAT *bn = NULL; BUN p = 0, q = 0; /* assert calling sanity */ assert(ret != NULL); /* handle NULL pointer */ if (src == NULL) throw(MAL, "batudf.reverse", RUNTIME_OBJECT_MISSING); /* check tail type */ if (src->ttype != TYPE_str) { throw(MAL, "batudf.reverse", "tail-type of input BAT must be TYPE_str"); } /* allocate result BAT */ bn = BATnew(src->htype, TYPE_str, BATcount(src)); if (bn == NULL) { throw(MAL, "batudf.reverse", MAL_MALLOC_FAIL); } BATseqbase(bn, src->hseqbase); /* create BAT iterator */ li = bat_iterator(src); /* the core of the algorithm, expensive due to malloc/frees */ BATloop(src, p, q) { char *tr = NULL, *err = NULL; /* get original head & tail value */ ptr h = BUNhead(li, p); const char *t = (const char *) BUNtail(li, p); /* revert tail value */ err = UDFreverse_(&tr, t); if (err != MAL_SUCCEED) { /* error -> bail out */ BBPreleaseref(bn->batCacheid); return err; } /* assert logical sanity */ assert(tr != NULL); /* insert original head and reversed tail in result BAT */ /* BUNins() takes care of all necessary administration */ BUNins(bn, h, tr, FALSE); /* free memory allocated in UDFreverse_() */ GDKfree(tr); }
BUN copy_inserted(BAT *b, BAT *i ) { BUN nr = 0; BUN r; BATiter ii = bat_iterator(i); for (r = i->batInserted; r < BUNlast(i); r++) { BUNins(b, BUNhead(ii,r), BUNtail(ii,r), TRUE); nr++; } return nr; }
str batnil_2_timestamp(bat *res, const bat *bid) { BAT *b, *dst; BATiter bi; BUN p, q; if ((b = BATdescriptor(*bid)) == NULL) { throw(SQL, "batcalc.nil_2_timestamp", "Cannot access descriptor"); } bi = bat_iterator(b); dst = BATnew(b->htype, TYPE_timestamp, BATcount(b), TRANSIENT); if (dst == NULL) { BBPunfix(b->batCacheid); throw(SQL, "sql.2_timestamp", MAL_MALLOC_FAIL); } BATseqbase(dst, b->hseqbase); BATloop(b, p, q) { timestamp r = *timestamp_nil; BUNins(dst, BUNhead(bi, p), &r, FALSE); }
/* * The prime routine for the BAT layer is to create a new hash index. * Its argument is the element type and the maximum number of BUNs be * stored under the hash function. */ BAT * BAThash(BAT *b, BUN masksize) { BAT *o = NULL; lng t0,t1; (void) t0; (void) t1; if (VIEWhparent(b)) { bat p = VIEWhparent(b); o = b; b = BATdescriptor(p); if (!ALIGNsynced(o, b) || BUNfirst(o) != BUNfirst(b)) { BBPunfix(b->batCacheid); b = o; o = NULL; } } MT_lock_set(&GDKhashLock(ABS(b->batCacheid)), "BAThash"); if (b->H->hash == NULL) { unsigned int tpe = ATOMstorage(b->htype); BUN cnt = BATcount(b); BUN mask; BUN p = BUNfirst(b), q = BUNlast(b), r; Hash *h = NULL; Heap *hp = NULL; str nme = BBP_physical(b->batCacheid); BATiter bi = bat_iterator(b); ALGODEBUG fprintf(stderr, "#BAThash: create hash(" BUNFMT ");\n", BATcount(b)); /* cnt = 0, hopefully there is a proper capacity from * which we can derive enough information */ if (!cnt) cnt = BATcapacity(b); if (b->htype == TYPE_void) { if (b->hseqbase == oid_nil) { MT_lock_unset(&GDKhashLock(ABS(b->batCacheid)), "BAThash"); ALGODEBUG fprintf(stderr, "#BAThash: cannot create hash-table on void-NIL column.\n"); return NULL; } ALGODEBUG fprintf(stderr, "#BAThash: creating hash-table on void column..\n"); tpe = TYPE_void; } /* determine hash mask size p = first; then no dynamic * scheme */ if (masksize > 0) { mask = HASHmask(masksize); } else if (ATOMsize(ATOMstorage(tpe)) == 1) { mask = (1 << 8); } else if (ATOMsize(ATOMstorage(tpe)) == 2) { mask = (1 << 12); } else if (b->hkey) { mask = HASHmask(cnt); } else { /* dynamic hash: we start with * HASHmask(cnt/64); if there are too many * collisions we try HASHmask(cnt/16), then * HASHmask(cnt/4), and finally * HASHmask(cnt). */ mask = HASHmask(cnt >> 6); p += (cnt >> 2); /* try out on first 25% of b */ if (p > q) p = q; } if (mask < 1024) mask = 1024; t0 = GDKusec(); do { BUN nslots = mask >> 3; /* 1/8 full is too full */ r = BUNfirst(b); if (hp) { HEAPfree(hp); GDKfree(hp); } if (h) { ALGODEBUG fprintf(stderr, "#BAThash: retry hash construction\n"); GDKfree(h); } /* create the hash structures */ hp = (Heap *) GDKzalloc(sizeof(Heap)); if (hp && (hp->filename = GDKmalloc(strlen(nme) + 12)) != NULL) sprintf(hp->filename, "%s.%chash", nme, b->batCacheid > 0 ? 'h' : 't'); if (hp == NULL || hp->filename == NULL || (h = HASHnew(hp, ATOMtype(b->htype), BATcapacity(b), mask)) == NULL) { MT_lock_unset(&GDKhashLock(ABS(b->batCacheid)), "BAThash"); if (hp != NULL) { GDKfree(hp->filename); GDKfree(hp); } return NULL; } switch (tpe) { case TYPE_bte: starthash(bte); break; case TYPE_sht: starthash(sht); break; case TYPE_int: case TYPE_flt: starthash(int); break; case TYPE_dbl: case TYPE_lng: starthash(lng); break; default: for (; r < p; r++) { ptr v = BUNhead(bi, r); BUN c = (BUN) heap_hash_any(b->H->vheap, h, v); if ( HASHget(h,c) == HASHnil(h) && nslots-- == 0) break; /* mask too full */ HASHputlink(h,r, HASHget(h,c)); HASHput(h,c, r); } break; } } while (r < p && mask < cnt && (mask <<= 2)); /* finish the hashtable with the current mask */ p = r; switch (tpe) { case TYPE_bte: finishhash(bte); break; case TYPE_sht: finishhash(sht); break; case TYPE_int: case TYPE_flt: finishhash(int); break; case TYPE_dbl: case TYPE_lng: finishhash(lng); break; default: for (; p < q; p++) { ptr v = BUNhead(bi, p); BUN c = (BUN) heap_hash_any(b->H->vheap, h, v); HASHputlink(h,p, HASHget(h,c)); HASHput(h,c,p); } break; } b->H->hash = h; t1 = GDKusec(); ALGODEBUG fprintf(stderr, "#BAThash: hash construction "LLFMT" usec\n", t1-t0); ALGODEBUG HASHcollisions(b,b->H->hash); }
void QOTupdateStatistics(str nme, int actions, lng val) { BATiter bi; BUN p; oid idx; int ival=0, *ip= &ival; lng lval=0, *lp= &lval; QOTstatisticsInit(); MT_lock_set(&qotlock, "QOT statistics"); p = BUNfnd(BATmirror(qotStat[QOTnames]),(ptr)nme); if (p == BUN_NONE) { BUNappend(qotStat[QOTnames], nme, FALSE); BUNappend(qotStat[QOTcalls], &ival, FALSE); BUNappend(qotStat[QOTactions], &ival, FALSE); BUNappend(qotStat[QOTtimings], &lval, FALSE); p = BUNfnd(BATmirror(qotStat[QOTnames]),(ptr)nme); if (p == BUN_NONE){ MT_lock_unset(&qotlock, "QOT statistics"); return; } } bi = bat_iterator(qotStat[QOTnames]); idx = *(oid*) BUNhead(bi,p); p = BUNfnd(qotStat[QOTcalls],&idx); if (p == BUN_NONE) { #ifdef _Q_STATISTICS_DEBUG mnstr_printf(GDKout,"#Could not access 'calls'\n"); #endif MT_lock_unset(&qotlock, "QOT statistics"); return; } bi = bat_iterator(qotStat[QOTcalls]); ip = (int*) BUNtail(bi,p); *ip = *ip+1; bi.b->tsorted = bi.b->trevsorted = 0; bi.b->tkey = 0; p = BUNfnd(qotStat[QOTactions],&idx); if (p == BUN_NONE){ #ifdef _Q_STATISTICS_DEBUG mnstr_printf(GDKout,"#Could not access 'actions'\n"); #endif MT_lock_unset(&qotlock, "QOT statistics"); return; } bi = bat_iterator(qotStat[QOTactions]); ip = (int*) BUNtail(bi,p); *ip = *ip+ actions; bi.b->tsorted = bi.b->trevsorted = 0; bi.b->tkey = 0; p = BUNfnd(qotStat[QOTtimings],&idx); if (p == BUN_NONE){ #ifdef _Q_STATISTICS_DEBUG mnstr_printf(GDKout, "#Could not access 'timings'\n"); #endif MT_lock_unset(&qotlock, "QOT statistics"); return ; } bi = bat_iterator(qotStat[QOTtimings]); lp = (lng*) BUNtail(bi,p); *lp = *lp+ val; bi.b->tsorted = bi.b->trevsorted = 0; bi.b->tkey = 0; MT_lock_unset(&qotlock, "QOT statistics"); }