/* * BBP Management, IO */ static gdk_return CMDrename(bit *retval, BAT *b, const char *s) { int ret; int c; const char *t = s; for ( ; (c = *t) != 0; t++) { if (c != '_' && !GDKisalnum(c)) { GDKerror("CMDrename: identifier expected: %s\n", s); return GDK_FAIL; } } ret = BATname(b, s); *retval = FALSE; if (ret == 1) { GDKerror("CMDrename: identifier expected: %s\n", s); return GDK_FAIL; } else if (ret == BBPRENAME_ILLEGAL) { GDKerror("CMDrename: illegal temporary name: '%s'\n", s); return GDK_FAIL; } else if (ret == BBPRENAME_LONG) { GDKerror("CMDrename: name too long: '%s'\n", s); return GDK_FAIL; } else if (ret != BBPRENAME_ALREADY) { *retval = TRUE; } return GDK_SUCCEED; }
/* * @+ Atomic Type Interface * The collection of built-in types supported for BATs can be extended * easily. In essence, the user should specify conversion routines * from values stored anywhere in memory to its equivalent in the BAT, * and vice verse. Some routines are required for coercion and to * support the BAT administration. * * A new type is incrementally build using the routine * ATOMallocate(id). The parameter id denotes the type name; an entry * is created if the type is so far unknown. * * The size describes the amount of space to be reserved in the BUN. * * The routine put takes a pointer to a memory resident copy and * prepares a persistent copy in the BAT passed. The inverse * operation is get. A new value can be directly included into the * BAT using new, which should prepare a null-value representation. A * value is removed from the BAT store using del, which can take care * of garbage collection and BAT administration. * * The pair tostr and fromstr should convert a reference to a * persistent value to a memory resident string equivalent. FromStr * takes a string and applies a put to store it within a BAT. They * are used to prepare for readable output/input and to support * coercion. * * The routines cmp and eq are comparison routines used to build * access structures. The null returns a reference to a null value * representation. * * The incremental atom construction uses hardwired properties. This * should be improved later on. */ int ATOMallocate(const char *id) { int t; if (strlen(id) >= IDLENGTH) { GDKerror("ATOMallocate: name too long"); return int_nil; } MT_lock_set(&GDKthreadLock); t = ATOMindex(id); if (t < 0) { t = -t; if (t == GDKatomcnt) { if (GDKatomcnt == MAXATOMS) { MT_lock_unset(&GDKthreadLock); GDKerror("ATOMallocate: too many types"); return int_nil; } GDKatomcnt++; } BATatoms[t] = (atomDesc) { .size = sizeof(int), /* default */ .linear = true, /* default */ .storage = t, /* default */ }; strcpy(BATatoms[t].name, id); } MT_lock_unset(&GDKthreadLock); return t; }
/* * The MonetDB server uses a startup script to boot the system. * This script is an ordinary MAL program, but will mostly * consist of include statements to load modules of general interest. * The startup script is run as user Admin. */ int malBootstrap(void) { Client c; str msg, bootfile = "mal_init", s; c = MCinitClient((oid) 0, 0, 0); assert(c != NULL); c->nspace = newModule(NULL, putName("user", 4)); initLibraries(); if ( (msg = defaultScenario(c)) ) { GDKfree(msg); GDKerror("Failed to initialise default scenario"); return 0; } MSinitClientPrg(c, "user", "main"); (void) MCinitClientThread(c); s = malInclude(c, bootfile, 0); if (s != NULL) { mnstr_printf(GDKout, "!%s\n", s); GDKfree(s); return 0; } pushEndInstruction(c->curprg->def); chkProgram(c->fdout, c->nspace, c->curprg->def); if (c->curprg->def->errors) showErrors(c); s = MALengine(c); if (s) GDKfree(s); return 1; }
/* * The emergency flag can be set to force a fatal error if needed. * Otherwise, the caller is able to deal with the lack of memory. */ void * GDKmallocmax(size_t size, size_t *maxsize, int emergency) { ssize_t *s = NULL; if (size == 0) { #ifdef GDK_MEM_NULLALLOWED return NULL; #else GDKfatal("GDKmallocmax: called with size " SZFMT "", size); #endif } size = (size + 7) & ~7; /* round up to a multiple of eight */ GDKmalloc_prefixsize(s, size); if (s == NULL) { GDKmemfail("GDKmalloc", size); GDKmalloc_prefixsize(s, size); if (s == NULL) { if (emergency == 0) { GDKerror("GDKmallocmax: failed for " SZFMT " bytes", size); return NULL; } GDKfatal("GDKmallocmax: failed for " SZFMT " bytes", size); } else { THRprintf(GDKstdout, "#GDKmallocmax: recovery ok. Continuing..\n"); } } *maxsize = size; heapinc(size + MALLOC_EXTRA_SPACE); return (void *) s; }
/* * Determine the variables being used and clear non-used onces. */ void MSresetVariables(Client cntxt, MalBlkPtr mb, MalStkPtr glb, int start) { int i; bit *used = GDKzalloc(mb->vtop * sizeof(bit)); if( used == NULL){ GDKerror("MSresetVariables" MAL_MALLOC_FAIL); return; } for (i = 0; i < start && start < mb->vtop; i++) used[i] = 1; if (mb->errors == 0) for (i = start; i < mb->vtop; i++) { if (used[i] || !isTmpVar(mb, i)) { assert(!mb->var[i]->value.vtype || isVarConstant(mb, i)); used[i] = 1; } if (glb && !used[i]) { if (isVarConstant(mb, i)) garbageElement(cntxt, &glb->stk[i]); /* clean stack entry */ glb->stk[i].vtype = TYPE_int; glb->stk[i].len = 0; glb->stk[i].val.pval = 0; } } if (mb->errors == 0) trimMalVariables_(mb, used, glb); GDKfree(used); }
sht PropertyIndex(str name) { int i=0; for (i=0; i<nr_properties; i++) { if (strcmp(properties[i], name) == 0) return i; } MT_lock_set(&mal_contextLock, "propertyIndex"); /* small change it's already added */ for (i=0; i<nr_properties; i++) { if (strcmp(properties[i], name) == 0) { MT_lock_unset(&mal_contextLock, "propertyIndex"); return i; } } if (i >= max_properties) { max_properties += 256; properties = GDKrealloc(properties, max_properties * sizeof(str)); if( properties == NULL){ GDKerror("PropertyIndex" MAL_MALLOC_FAIL); MT_lock_unset(&mal_contextLock, "propertyIndex"); return nr_properties; } } properties[nr_properties] = GDKstrdup(name); MT_lock_unset(&mal_contextLock, "propertyIndex"); return nr_properties++; }
/* Remote execution of MAL calls for more type/property information to be exchanged */ str mal2str(MalBlkPtr mb, int first, int last) { str ps = NULL, *txt; int i, *len, totlen = 0; txt = GDKmalloc(sizeof(str) * mb->stop); len = GDKmalloc(sizeof(int) * mb->stop); if( txt == NULL || len == NULL){ GDKerror("mal2str: " MAL_MALLOC_FAIL); if( txt ) GDKfree(txt); if( len ) GDKfree(len); return NULL; } for (i = first; i < last; i++) { if( i == 0) txt[i] = instruction2str(mb, 0, getInstrPtr(mb, i), LIST_MAL_NAME | LIST_MAL_TYPE | LIST_MAL_PROPS); else txt[i] = instruction2str(mb, 0, getInstrPtr(mb, i), LIST_MAL_CALL | LIST_MAL_PROPS | LIST_MAL_REMOTE); #ifdef _DEBUG_LISTING_ mnstr_printf(GDKout,"%s\n",txt[i]); #endif if ( txt[i]) totlen += len[i] = (int)strlen(txt[i]); } ps = GDKmalloc(totlen + mb->stop + 1); if( ps == NULL) GDKerror("mal2str: " MAL_MALLOC_FAIL); totlen = 0; for (i = first; i < last; i++) { if( txt[i]){ if( ps){ strncpy(ps + totlen, txt[i], len[i]); ps[totlen + len[i]] = '\n'; ps[totlen + len[i] + 1] = 0; totlen += len[i] + 1; } GDKfree(txt[i]); } } GDKfree(len); GDKfree(txt); return ps; }
ptr GDKreallocmax(void *blk, size_t size, size_t *maxsize, int emergency) { void *oldblk = blk; ssize_t oldsize = 0; size_t newsize; if (blk == NULL) { return GDKmallocmax(size, maxsize, emergency); } if (size == 0) { #ifdef GDK_MEM_NULLALLOWED GDKfree_(blk); *maxsize = 0; return NULL; #else GDKfatal("GDKreallocmax: called with size 0"); #endif } size = (size + 7) & ~7; /* round up to a multiple of eight */ oldsize = GDK_MEM_BLKSIZE(blk); /* check against duplicate free */ assert((oldsize & 2) == 0); newsize = size + MALLOC_EXTRA_SPACE; blk = realloc(((char *) blk) - MALLOC_EXTRA_SPACE, newsize + GLIBC_BUG); if (blk == NULL) { GDKmemfail("GDKrealloc", newsize); blk = realloc(((char *) oldblk) - MALLOC_EXTRA_SPACE, newsize); if (blk == NULL) { if (emergency == 0) { GDKerror("GDKreallocmax: failed for " SZFMT " bytes", newsize); return NULL; } GDKfatal("GDKreallocmax: failed for " SZFMT " bytes", newsize); } else { THRprintf(GDKstdout, "#GDKremallocmax: " "recovery ok. Continuing..\n"); } } /* place MALLOC_EXTRA_SPACE bytes before it */ assert((((size_t) blk) & 4) == 0); blk = ((char *) blk) + MALLOC_EXTRA_SPACE; ((ssize_t *) blk)[-1] = (ssize_t) newsize; /* adapt statistics */ heapinc(newsize); heapdec(oldsize); *maxsize = size; return blk; }
ssize_t ptrFromStr(const char *src, size_t *len, ptr **dst, bool external) { size_t base = 0; const char *p = src; atommem(sizeof(ptr)); **dst = ptr_nil; if (GDK_STRNIL(src)) return 1; while (GDKisspace(*p)) p++; if (external && strncmp(p, "nil", 3) == 0) { p += 3; } else { if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { p += 2; } if (!num16(*p)) { GDKerror("not a number\n"); return -1; } while (num16(*p)) { if (base >= ((size_t) 1 << (8 * sizeof(size_t) - 4))) { GDKerror("overflow\n"); return -1; } base = mult16(base) + base16(*p); p++; } **dst = (ptr) base; } while (GDKisspace(*p)) p++; return (ssize_t) (p - src); }
int readConsole(Client cntxt) { /* execute from stdin */ struct stat statb; char *buf; if (cntxt->promptlength == 0 || !(fstat(fileno(stdin), &statb) == 0 && S_ISCHR(statb.st_mode)) ) return -1; /* read lines and move string to client buffer. */ #ifdef HAVE_LIBREADLINE if( initReadline ==0){ init_readline(); using_history(); stifle_history(1000); initReadline =1 ; } #endif buf= getConsoleInput(cntxt, cntxt->prompt, 0, 1); if( buf) { size_t len= strlen(buf); if( len >= cntxt->fdin->size) { /* extremly dirty inplace buffer overwriting */ cntxt->fdin->buf= realloc(cntxt->fdin->buf, len+1); if( cntxt->fdin->buf == NULL) { GDKerror("readConsole: " MAL_MALLOC_FAIL); free(buf); goto bailout; } cntxt->fdin->size = len; } strcpy(cntxt->fdin->buf, buf); cntxt->fdin->pos = 0; cntxt->fdin->len = len; free(buf); return 1; } bailout: cntxt->fdin->eof = 1; #ifdef HAVE_LIBREADLINE if( initReadline ){ deinit_readline(); initReadline= 0; } #endif return -1; }
/* * String conversion routines. */ ssize_t OIDfromStr(const char *src, size_t *len, oid **dst, bool external) { #if SIZEOF_OID == SIZEOF_INT int ui = 0, *uip = &ui; #else lng ui = 0, *uip = &ui; #endif size_t l = sizeof(ui); ssize_t pos = 0; const char *p = src; atommem(sizeof(oid)); **dst = oid_nil; if (GDK_STRNIL(src)) return 1; while (GDKisspace(*p)) p++; if (external && strncmp(p, "nil", 3) == 0) return (ssize_t) (p - src) + 3; if (GDKisdigit(*p)) { #if SIZEOF_OID == SIZEOF_INT pos = intFromStr(p, &l, &uip, external); #else pos = lngFromStr(p, &l, &uip, external); #endif if (pos < 0) return pos; if (p[pos] == '@') { pos++; while (GDKisdigit(p[pos])) pos++; } if (ui >= 0) { **dst = ui; } p += pos; } else { GDKerror("not an OID\n"); return -1; } while (GDKisspace(*p)) p++; return (ssize_t) (p - src); }
/* * Really really get the lock. Now!! */ static int GDKgetHome(void) { if (MT_pagesize() == 0 || GDKlockFile) return 0; while ((GDKlockFile = fopen(GDKLOCK, "r+")) == NULL) { GDKerror("GDKgetHome: PANIC on open %s. sleep(1)\n", GDKLOCK); MT_sleep_ms(1000); } if (MT_lockf(GDKLOCK, F_TLOCK, 4, 1) < 0) { IODEBUG THRprintf(GDKstdout, "#GDKgetHome: blocking on lock '%s'.\n", GDKLOCK); MT_lockf(GDKLOCK, F_LOCK, 4, 1); } return 1; }
ssize_t dblFromStr(const char *src, size_t *len, dbl **dst, bool external) { const char *p = src; ssize_t n = 0; double d; /* alloc memory */ atommem(sizeof(dbl)); if (GDK_STRNIL(src)) { **dst = dbl_nil; return 1; } while (GDKisspace(*p)) p++; if (external && strncmp(p, "nil", 3) == 0) { **dst = dbl_nil; p += 3; n = (ssize_t) (p - src); } else { /* on overflow, strtod returns HUGE_VAL and sets * errno to ERANGE; on underflow, it returns a value * whose magnitude is no greater than the smallest * normalized double, and may or may not set errno to * ERANGE. We accept underflow, but not overflow. */ char *pe; errno = 0; d = strtod(p, &pe); if (p == pe) p = src; /* nothing converted */ else p = pe; n = (ssize_t) (p - src); if (n == 0 || (errno == ERANGE && (d < -1 || d > 1)) || !isfinite(d) /* no NaN or Infinte */ ) { GDKerror("overflow or not a number\n"); return -1; } else { while (src[n] && GDKisspace(src[n])) n++; **dst = (dbl) d; } } return n; }
static int dec_tostr(void *extra, char **Buf, int *len, int type, ptr a) { /* support dec map to bte, sht, int and lng */ if (type == TYPE_bte) { DEC_TOSTR(bte); } else if (type == TYPE_sht) { DEC_TOSTR(sht); } else if (type == TYPE_int) { DEC_TOSTR(int); } else if (type == TYPE_lng) { DEC_TOSTR(lng); } else { GDKerror("Decimal cannot be mapped to %s\n", ATOMname(type)); } return 0; }
void printSignature(stream *fd, Symbol s, int flg) { InstrPtr p; str txt; if ( s->def == 0 ){ mnstr_printf(fd, "missing definition of %s\n", s->name); return; } txt = GDKzalloc(MAXLISTING); /* some slack for large blocks */ if( txt){ p = getSignature(s); (void) fcnDefinition(s->def, p, txt, flg, txt, MAXLISTING); mnstr_printf(fd, "%s\n", txt); GDKfree(txt); } else GDKerror("printSignature"MAL_MALLOC_FAIL); }
ValPtr VALinit(ValPtr d, int tpe, const void *s) { if (ATOMextern(tpe) == 0) { d->vtype = tpe; memcpy(&d->val.ival, s, ATOMlen(tpe, s)); } else if (s == 0) { GDKerror("VALinit:unsupported init\n"); d->vtype = TYPE_int; } else if (tpe >= TYPE_str && ATOMstorage(tpe) == TYPE_str) { d->vtype = TYPE_str; d->val.sval = GDKstrdup(s); d->len = strLen(s); } else { d->vtype = tpe; d->len = ATOMlen(tpe, s); d->val.pval = GDKmalloc(d->len); memcpy(d->val.pval, s, d->len); } return d; }
/* * The remainder are utilities to manipulate the BAT view and not to * forget some details in the process. It expects a position range in * the underlying BAT and compensates for outliers. */ void VIEWbounds(BAT *b, BAT *view, BUN l, BUN h) { BUN cnt; BATiter bi = bat_iterator(b); if (b == NULL || view == NULL) { GDKerror("VIEWbounds: bat argument missing"); return; } if (h > BATcount(b)) h = BATcount(b); if (h < l) h = l; l += BUNfirst(b); view->batFirst = view->batDeleted = view->batInserted = 0; cnt = h - l; view->H->heap.base = (view->htype) ? BUNhloc(bi, l) : NULL; view->T->heap.base = (view->ttype) ? BUNtloc(bi, l) : NULL; view->H->heap.size = headsize(view, cnt); view->T->heap.size = tailsize(view, cnt); BATsetcount(view, cnt); BATsetcapacity(view, cnt); }
static ssize_t numFromStr(const char *src, size_t *len, void **dst, int tp, bool external) { const char *p = src; size_t sz = ATOMsize(tp); #ifdef HAVE_HGE hge base = 0; #else lng base = 0; #endif int sign = 1; /* a valid number has the following syntax: * [-+]?[0-9]+([eE][0-9]+)?(LL)? -- PCRE syntax, or in other words * optional sign, one or more digits, optional exponent, optional LL * the exponent has the following syntax: * lower or upper case letter E, one or more digits * embedded spaces are not allowed * the optional LL at the end are only allowed for lng and hge * values */ atommem(sz); if (GDK_STRNIL(src)) { memcpy(*dst, ATOMnilptr(tp), sz); return 1; } while (GDKisspace(*p)) p++; if (!num10(*p)) { switch (*p) { case 'n': if (external) { memcpy(*dst, ATOMnilptr(tp), sz); if (p[1] == 'i' && p[2] == 'l') { p += 3; return (ssize_t) (p - src); } } GDKerror("not a number"); goto bailout; case '-': sign = -1; p++; break; case '+': p++; break; } if (!num10(*p)) { GDKerror("not a number"); goto bailout; } } do { int dig = base10(*p); if (base > maxdiv[1].maxval || (base == maxdiv[1].maxval && dig > maxmod10)) { /* overflow */ goto overflow; } base = 10 * base + dig; p++; } while (num10(*p)); if ((*p == 'e' || *p == 'E') && num10(p[1])) { p++; if (base == 0) { /* if base is 0, any exponent will do, the * result is still 0 */ while (num10(*p)) p++; } else { int exp = 0; do { /* this calculation cannot overflow */ exp = exp * 10 + base10(*p); if (exp >= (int) (sizeof(maxdiv) / sizeof(maxdiv[0]))) { /* overflow */ goto overflow; } p++; } while (num10(*p)); if (base > maxdiv[exp].maxval) { /* overflow */ goto overflow; } base *= maxdiv[exp].scale; } } base *= sign; switch (sz) { case 1: { bte **dstbte = (bte **) dst; if (base < GDK_bte_min || base > GDK_bte_max) { goto overflow; } **dstbte = (bte) base; break; } case 2: { sht **dstsht = (sht **) dst; if (base < GDK_sht_min || base > GDK_sht_max) { goto overflow; } **dstsht = (sht) base; break; } case 4: { int **dstint = (int **) dst; if (base < GDK_int_min || base > GDK_int_max) { goto overflow; } **dstint = (int) base; break; } case 8: { lng **dstlng = (lng **) dst; #ifdef HAVE_HGE if (base < GDK_lng_min || base > GDK_lng_max) { goto overflow; } #endif **dstlng = (lng) base; if (p[0] == 'L' && p[1] == 'L') p += 2; break; } #ifdef HAVE_HGE case 16: { hge **dsthge = (hge **) dst; **dsthge = (hge) base; if (p[0] == 'L' && p[1] == 'L') p += 2; break; } #endif } while (GDKisspace(*p)) p++; return (ssize_t) (p - src); overflow: while (num10(*p)) p++; GDKerror("overflow: \"%.*s\" does not fit in %s\n", (int) (p - src), src, ATOMname(tp)); bailout: memcpy(*dst, ATOMnilptr(tp), sz); return -1; }
static str renderTerm(MalBlkPtr mb, MalStkPtr stk, InstrPtr p, int idx, int flg) { char *buf =0; char *nme =0; int nameused= 0; size_t len = 0, maxlen = BUFSIZ; ValRecord *val = 0; char *cv =0; str tpe; int showtype = 0, closequote=0; int varid = getArg(p,idx); buf = GDKzalloc(maxlen); // show the name when required or is used if ((flg & LIST_MAL_NAME) && !isVarConstant(mb,varid) && !isVarTypedef(mb,varid)) { nme = getVarName(mb,varid); len +=snprintf(buf, maxlen, "%s", nme); nameused =1; } // show the value when required or being a constant if( ((flg & LIST_MAL_VALUE) && stk != 0) || isVarConstant(mb,varid) ){ if (nameused){ strcat(buf + len,"="); len++; } // locate value record if (isVarConstant(mb,varid)) val = &getVarConstant(mb, varid); else if( stk) val = &stk->stk[varid]; VALformat(&cv, val); if (len + strlen(cv) >= maxlen) buf= GDKrealloc(buf, maxlen =len + strlen(cv) + BUFSIZ); if( buf == 0){ GDKerror("renderTerm:Failed to allocate"); return 0; } if( strcmp(cv,"nil") == 0){ strcat(buf+len,cv); len += strlen(buf+len); if( cv) GDKfree(cv); showtype =getColumnType(getVarType(mb,varid)) > TYPE_str || ((isVarUDFtype(mb,varid) || isVarTypedef(mb,varid)) && isVarConstant(mb,varid)) || isaBatType(getVarType(mb,varid)); } else{ if ( !isaBatType(getVarType(mb,varid)) && getColumnType(getVarType(mb,varid)) > TYPE_str ){ closequote = 1; strcat(buf+len,"\""); len++; } strcat(buf+len,cv); len += strlen(buf+len); if( cv) GDKfree(cv); if( closequote ){ strcat(buf+len,"\""); len++; } showtype =closequote > TYPE_str || ((isVarUDFtype(mb,varid) || isVarTypedef(mb,varid) || (flg & LIST_MAL_REMOTE)) && isVarConstant(mb,varid)) || (isaBatType(getVarType(mb,varid)) && idx < p->retc); if (stk && isaBatType(getVarType(mb,varid)) && abs(stk->stk[varid].val.ival) ){ BAT *d= BBPquickdesc(abs(stk->stk[varid].val.ival),TRUE); if( d) len += snprintf(buf+len,maxlen-len,"[" BUNFMT "]", BATcount(d)); } } } // show the type when required or frozen by the user // special care should be taken with constants, they may have been casted if ((flg & LIST_MAL_TYPE) || (isVarUDFtype(mb, varid) && idx < p->retc) || isVarTypedef(mb,varid) || showtype){ strcat(buf + len,":"); len++; tpe = getTypeName(getVarType(mb, varid)); len += snprintf(buf+len,maxlen-len,"%s",tpe); GDKfree(tpe); } if( len >= maxlen) GDKerror("renderTerm:Value representation too large"); return buf; }
char * getConsoleInput(Client c, const char *prompt, int linemode, int exit_on_error) { char *line = NULL; char *buf = NULL; size_t length; (void) exit_on_error; (void) linemode; do { #ifdef HAVE_LIBREADLINE if (prompt) { if (buf) free(buf); buf = readline(prompt); /* add a newline to the end since that makes further processing easier */ if (buf) { add_history(buf); length = strlen(buf); buf = realloc(buf, length + 2); if( buf == NULL){ GDKerror("getConsoleInput: " MAL_MALLOC_FAIL); return NULL; } buf[length++] = '\n'; buf[length] = 0; } line = buf; } else #endif { #ifndef HAVE_LIBREADLINE if (prompt) { fputs(prompt, stdout); fflush(stdout); } #endif if (buf == NULL) { buf= malloc(BUFSIZ); if( buf == NULL){ GDKerror("getConsoleInput: " MAL_MALLOC_FAIL); return NULL; } } line = fgets(buf, BUFSIZ, stdin); } if (line == NULL) { /* end of file */ if (buf) free(buf); return NULL; } else length = strlen(line); if (length > 0 ) { /* test for special commands */ while (length > 0 && (*line & ~0x7F) == 0 && isspace((int) *line)) { line++; length--; } /* in the switch, use continue if the line was processed, use break to send to parser */ switch (*line) { case '\0': /* empty line */ break; case '\\': switch (line[1]) { case 'q': free(buf); return NULL; default: break; } line= NULL; break; case '<': /* read commands from file */ if (line[length - 1] == '\n') line[--length] = 0; if (line[length - 1] == '\r') line[--length] = 0; /* doFile(mid, line + 1, 0);*/ line= NULL; continue; case '>': /* redirect output to file */ line++; length--; if (line[length - 1] == '\n') line[--length] = 0; if (line[length - 1] == '\r') line[--length] = 0; if (c->fdout && c->fdout != GDKout && c->fdout != GDKerr){ close_stream(c->fdout); c->fdout= 0; } if (length == 0 || strcmp(line, "stdout") == 0) c->fdout = GDKout; else if (strcmp(line, "stderr") == 0) c->fdout = GDKerr; else if ((c->fdout = open_wastream(line)) == NULL) { c->fdout = GDKout; mnstr_printf(GDKerr, "Cannot open %s\n", line); } line = NULL; continue; #ifdef HAVE_LIBREADLINE case '!': { char *nl; int i; if(line[1]=='\n') { for(i=0; i< history_length; i++){ nl= history_get(i)? history_get(i)->line:0; if( nl) mnstr_printf(c->fdout, "%d %s\n", i, nl); } line = NULL; } else if( history_expand(line,&nl) ==1 ) { mnstr_printf(c->fdout,"#%s",nl); line= nl; } else line= NULL; } continue; #endif case '?': if( line[1] && line[1]!='\n'){ showHelp( c->nspace,line+1, c->fdout); } else showCommands(); line= NULL; continue; } /* make sure we return a pointer that can (and should) be freed by the caller */ if (line) line = buf; } } while (line == NULL); return line; }
/* BATsample implements sampling for void headed BATs */ BAT * BATsample(BAT *b, BUN n) { BAT *bn; BUN cnt, slen; BUN rescnt; struct oidtreenode *tree = NULL; BATcheck(b, "BATsample", NULL); assert(BAThdense(b)); ERRORcheck(n > BUN_MAX, "BATsample: sample size larger than BUN_MAX\n", NULL); ALGODEBUG fprintf(stderr, "#BATsample: sample " BUNFMT " elements.\n", n); cnt = BATcount(b); /* empty sample size */ if (n == 0) { bn = BATnew(TYPE_void, TYPE_void, 0, TRANSIENT); if (bn == NULL) { GDKerror("BATsample: memory allocation error"); return NULL; } BATsetcount(bn, 0); BATseqbase(bn, 0); BATseqbase(BATmirror(bn), 0); /* sample size is larger than the input BAT, return all oids */ } else if (cnt <= n) { bn = BATnew(TYPE_void, TYPE_void, cnt, TRANSIENT); if (bn == NULL) { GDKerror("BATsample: memory allocation error"); return NULL; } BATsetcount(bn, cnt); BATseqbase(bn, 0); BATseqbase(BATmirror(bn), b->H->seq); } else { oid minoid = b->hseqbase; oid maxoid = b->hseqbase + cnt; /* if someone samples more than half of our tree, we * do the antiset */ bit antiset = n > cnt / 2; slen = n; if (antiset) n = cnt - n; tree = GDKmalloc(n * sizeof(struct oidtreenode)); if (tree == NULL) { GDKerror("#BATsample: memory allocation error"); return NULL; } bn = BATnew(TYPE_void, TYPE_oid, slen, TRANSIENT); if (bn == NULL) { GDKfree(tree); GDKerror("#BATsample: memory allocation error"); return NULL; } /* while we do not have enough sample OIDs yet */ for (rescnt = 0; rescnt < n; rescnt++) { oid candoid; do { /* generate a new random OID */ candoid = (oid) (minoid + DRAND * (maxoid - minoid)); /* if that candidate OID was already * generated, try again */ } while (!OIDTreeMaybeInsert(tree, candoid, rescnt)); } if (!antiset) { OIDTreeToBAT(tree, bn); } else { OIDTreeToBATAntiset(tree, bn, minoid, maxoid); } GDKfree(tree); BATsetcount(bn, slen); bn->trevsorted = bn->batCount <= 1; bn->tsorted = 1; bn->tkey = 1; bn->tdense = bn->batCount <= 1; if (bn->batCount == 1) bn->tseqbase = *(oid *) Tloc(bn, BUNfirst(bn)); bn->hdense = 1; bn->hseqbase = 0; bn->hkey = 1; bn->hrevsorted = bn->batCount <= 1; bn->hsorted = 1; } return bn; }
static BAT * ALGjoinPathBody(Client cntxt, int top, BAT **joins, int flag) { BAT *b = NULL; BUN estimate, e = 0; int i, j, k; int *postpone= (int*) GDKzalloc(sizeof(int) *top); int postponed=0; if(postpone == NULL){ GDKerror("joinPathBody" MAL_MALLOC_FAIL); return NULL; } /* solve the join by pairing the smallest first */ while (top > 1) { j = 0; estimate = ALGjoinCost(cntxt,joins[0],joins[1],flag); ALGODEBUG fprintf(stderr,"#joinPath estimate join(%d,%d) %d cnt="BUNFMT" %s\n", joins[0]->batCacheid, joins[1]->batCacheid,(int)estimate, BATcount(joins[0]), postpone[0]?"postpone":""); for (i = 1; i < top - 1; i++) { e = ALGjoinCost(cntxt,joins[i], joins[i + 1],flag); ALGODEBUG fprintf(stderr,"#joinPath estimate join(%d,%d) %d cnt="BUNFMT" %s\n", joins[i]->batCacheid, joins[i+1]->batCacheid,(int)e,BATcount(joins[i]), postpone[i]?"postpone":""); if (e < estimate && ( !(postpone[i] && postpone[i+1]) || postponed<top)) { estimate = e; j = i; } } /* * BEWARE. you may not use a size estimation, because it * may fire a BATproperty check in a few cases. * In case a join fails, we may try another order first before * abandoning the task. It can handle cases where a Cartesian product emerges. * * A left-join sequence only requires the result to be sorted * against the first operand. For all others operand pairs, the cheapest join suffice. */ switch(flag){ case 0: if ( j == 0) { b = BATleftjoin(joins[j], joins[j + 1], BATcount(joins[j])); ALGODEBUG{ fprintf(stderr,"#joinpath step produces "BUNFMT"\n", BATcount(b)); } break; } case 1: b = BATjoin(joins[j], joins[j + 1], (BATcount(joins[j]) < BATcount(joins[j + 1])? BATcount(joins[j]):BATcount(joins[ j + 1]))); break; case 3: b = BATproject(joins[j], joins[j + 1]); ALGODEBUG{ fprintf(stderr,"#joinpath step produces "BUNFMT"\n", BATcount(b)); } break; } if (b==NULL){ if ( postpone[j] && postpone[j+1]){ for( --top; top>=0; top--) BBPunfix(joins[top]->batCacheid); GDKfree(postpone); return NULL; } postpone[j] = TRUE; postpone[j+1] = TRUE; postponed = 0; for( k=0; k<top; k++) postponed += postpone[k]== TRUE; if ( postponed == top){ for( --top; top>=0; top--) BBPunfix(joins[top]->batCacheid); GDKfree(postpone); return NULL; } /* clear the GDKerrors and retry */ if( cntxt->errbuf ) cntxt->errbuf[0]=0; continue; } else { /* reset the postponed joins */ for( k=0; k<top; k++) postpone[k]=FALSE; if (!(b->batDirty&2)) BATsetaccess(b, BAT_READ); postponed = 0; } ALGODEBUG{ if (b ) { fprintf(stderr, "#joinPath %d:= join(%d,%d)" " arguments %d (cnt= "BUNFMT") against (cnt "BUNFMT") cost "BUNFMT"\n", b->batCacheid, joins[j]->batCacheid, joins[j + 1]->batCacheid, j, BATcount(joins[j]), BATcount(joins[j+1]), e); } } if ( b == 0 ){ for( --top; top>=0; top--) BBPunfix(joins[top]->batCacheid); GDKfree(postpone); return 0; } BBPunfix(joins[j]->batCacheid); BBPunfix(joins[j+1]->batCacheid); joins[j] = b; top--; for (i = j + 1; i < top; i++) joins[i] = joins[i + 1]; }