str OPTorcam(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p){ Symbol t; str msg,mod,fcn; lng clk= GDKusec(); int actions = 0; if( p ==NULL ) return 0; removeInstruction(mb, p); if( p->argc == 3){ mod= getArgDefault(mb,p,1); fcn= getArgDefault(mb,p,2); } else { mod= getArgDefault(mb,p,3); fcn= getArgDefault(mb,p,4); } t= findSymbol(cntxt->nspace, putName(mod, strlen(mod)), fcn); if( t == 0) return 0; msg = MACROvalidate(t->def); if( msg) return msg; if( mb->errors == 0) actions= OPTorcamImplementation(cntxt,mb,stk,p); return optimizerCheck(cntxt,mb, "optimizer.orcam", actions, GDKusec() - clk, OPT_CHECK_ALL); }
str OPTsql_append(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p){ str modnme; str fcnnme; str msg= MAL_SUCCEED; Symbol s= NULL; lng t,clk= GDKusec(); int actions = 0; if( p ) removeInstruction(mb, p); OPTDEBUGsql_append mnstr_printf(cntxt->fdout,"=APPLY OPTIMIZER sql_append\n"); if( p && p->argc > 1 ){ if( getArgType(mb,p,1) != TYPE_str || getArgType(mb,p,2) != TYPE_str || !isVarConstant(mb,getArg(p,1)) || !isVarConstant(mb,getArg(p,2)) ) { throw(MAL, "optimizer.sql_append", ILLARG_CONSTANTS); } if( stk != 0){ modnme= *getArgReference_str(stk,p,1); fcnnme= *getArgReference_str(stk,p,2); } else { modnme= getArgDefault(mb,p,1); fcnnme= getArgDefault(mb,p,2); } s= findSymbol(cntxt->nspace, putName(modnme,strlen(modnme)),putName(fcnnme,strlen(fcnnme))); if( s == NULL) { char buf[1024]; snprintf(buf,1024, "%s.%s",modnme,fcnnme); throw(MAL, "optimizer.sql_append", RUNTIME_OBJECT_UNDEFINED ":%s", buf); } mb = s->def; stk= 0; } if( mb->errors ){ /* when we have errors, we still want to see them */ addtoMalBlkHistory(mb,"sql_append"); return MAL_SUCCEED; } actions= OPTsql_appendImplementation(cntxt, mb,stk,p); msg= optimizerCheck(cntxt, mb, "optimizer.sql_append", actions, t=(GDKusec() - clk)); OPTDEBUGsql_append { mnstr_printf(cntxt->fdout,"=FINISHED sql_append %d\n",actions); printFunction(cntxt->fdout,mb,0,LIST_MAL_ALL ); } DEBUGoptimizers mnstr_printf(cntxt->fdout,"#opt_reduce: " LLFMT " ms\n",t); QOTupdateStatistics("sql_append",actions,t); addtoMalBlkHistory(mb,"sql_append"); return msg; }
static lng estimateOverhead(void) { int i; lng l; lng t0 = GDKusec(); for (i = 0; i < 10000; i++) l = GDKusec(); t0 = (GDKusec() - t0) / 10000; #ifdef SENSOR_DEBUG mnstr_printf(SEout, "#Timing overhead " LLFMT " GDKusec\n", t0); #endif return l; }
int consumeStream(Actuator ac) { char buf[MYBUFSIZ + 1]; /* use equal to Linux internal buffer size */ lng clk; char *endptr; lng l = 0; ssize_t m = 0; #ifdef _DEBUG_ACTUATOR_ mnstr_printf(ACout, "Consume stream\n"); #endif buf[0] = 0; while (tuples != events && (m = mnstr_readline(ac->fromServer, buf, MYBUFSIZ)) > 0) { buf[m] = 0; characters += m; received++; tuples++; if (trace) mnstr_printf(ACout, "%s%s", buf, (buf[m - 1] == '\n' ? "" : "\n")); /*mnstr_printf(ACout, "Received tuple[%d]:%s\n",received,buf);*/ endptr = 0; clk = strtoll(buf + 1, &endptr, 0); if (sendFirst == 0) sendFirst = clk; receivedLast = GDKusec(); if (receivedFirst == 0) receivedFirst = receivedLast; if (timestamp) { l = receivedLast - clk; #ifdef _DEBUG_ACTUATOR_ if (trace) mnstr_printf(ACout, "B#%d: " LLFMT " " LLFMT "\n", received, clk, l); #endif totallatency += l; } m = 0; if (statistics && (received % statistics) == 0) { showStatistics(); } } if (errno == EPIPE || errno == ECONNRESET) { mnstr_printf(ACout, "errno:%s\n", strerror(errno)); close_stream(ac->fromServer); } if (statistics) showStatistics(); #ifdef _DEBUG_ACTUATOR_ mnstr_printf(ACout, "tuples %d events %d \n", tuples, events); #endif if (tuples >= events) terminate(ac); return 0; }
/* * @- * Access control enforcement. Except for the server owner * running a scenario should be explicitly permitted. */ static str runScenarioBody(Client c) { str msg= MAL_SUCCEED; lng start; c->exception_buf_initialized = 1; if (setjmp( c->exception_buf) < 0) c->mode = FINISHCLIENT; while ((c->mode > FINISHCLIENT || msg != MAL_SUCCEED) && !GDKexiting()) { if (msg != MAL_SUCCEED){ /* we should actually show it [postponed] mnstr_printf(c->fdout,"!%s\n",msg); */ if (msg != M5OutOfMemory) GDKfree(msg); msg = MAL_SUCCEED; } if (!c->state[0] && (msg = runPhase(c, MAL_SCENARIO_INITCLIENT)) != MAL_SUCCEED) continue; if (c->mode <= FINISHCLIENT || (msg = runPhase(c, MAL_SCENARIO_READER)) != MAL_SUCCEED) continue; c->lastcmd= time(0); start= GDKusec(); if (c->mode <= FINISHCLIENT || (msg = runPhase(c, MAL_SCENARIO_PARSER)) != MAL_SUCCEED) continue; if (c->mode <= FINISHCLIENT || (msg = runPhase(c, MAL_SCENARIO_OPTIMIZE)) != MAL_SUCCEED) continue; if (c->mode <= FINISHCLIENT || (msg = runPhase(c, MAL_SCENARIO_SCHEDULER)) != MAL_SUCCEED) continue; if (c->mode <= FINISHCLIENT || (msg = runPhase(c, MAL_SCENARIO_ENGINE)) != MAL_SUCCEED) continue; c->actions++; start = GDKusec()-start; c->totaltime += start; } if (c->phase[MAL_SCENARIO_EXITCLIENT]) (*c->phase[MAL_SCENARIO_EXITCLIENT]) (c); c->exception_buf_initialized = 0; return msg; }
str ALARMsleep(int *res, int *secs) { (void) res; /* fool compilers */ if (*secs < 0) throw(MAL, "alarm.sleep", "negative delay"); #ifdef __CYGWIN__ /* CYGWIN cannot handle SIGALRM with sleep */ { lng t = GDKusec() + (*secs)*1000000; while (GDKusec() < t) ; } #else MT_sleep_ms(*secs * 1000); #endif return MAL_SUCCEED; }
Client MCinitClientRecord(Client c, oid user, bstream *fin, stream *fout) { str prompt; c->user = user; c->username = 0; c->scenario = NULL; c->oldscenario = NULL; c->srcFile = NULL; c->blkmode = 0; c->fdin = fin ? fin : bstream_create(GDKin, 0); c->yycur = 0; c->bak = NULL; c->listing = 0; c->fdout = fout ? fout : GDKstdout; c->mdb = 0; c->history = 0; c->curprg = c->backup = 0; c->glb = 0; /* remove garbage from previous connection */ if (c->nspace) { freeModule(c->nspace); c->nspace = 0; } c->father = NULL; c->login = c->lastcmd = time(0); //c->active = 0; c->session = GDKusec(); c->qtimeout = 0; c->stimeout = 0; c->stage = 0; c->itrace = 0; c->debugOptimizer = c->debugScheduler = 0; c->flags = MCdefault; c->errbuf = 0; prompt = !fin ? GDKgetenv("monet_prompt") : PROMPT1; c->prompt = GDKstrdup(prompt); c->promptlength = strlen(prompt); c->actions = 0; c->totaltime = 0; /* create a recycler cache */ c->exception_buf_initialized = 0; c->error_row = c->error_fld = c->error_msg = c->error_input = NULL; (void) AUTHgetUsername(&c->username, c); MT_sema_init(&c->s, 0, "Client->s"); return c; }
str ALARMusec(lng *ret) { *ret = GDKusec(); return MAL_SUCCEED; }
int OPTquerylogImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { int i, limit, slimit; InstrPtr p = 0, *old= mb->stmt, q,r; int argc, io, user,nice,sys,idle,iowait,load, arg, start,finish, name; int xtime=0, rtime = 0, tuples=0; InstrPtr defineQuery = NULL; // query log needed? if ( !QLOGisset() ) return 0; (void) pci; (void) stk; /* to fool compilers */ (void) cntxt; /* gather information */ for (i = 1; i < mb->stop; i++) { p = getInstrPtr(mb,i); if ( getModuleId(p) && idcmp(getModuleId(p), "querylog") == 0 && idcmp(getFunctionId(p),"define")==0){ defineQuery= p; getVarConstant(mb,getArg(p,3)).val.lval = GDKusec()-getVarConstant(mb,getArg(p,3)).val.lval ; } } if ( defineQuery == NULL) /* nothing to do */ return 0; limit= mb->stop; slimit= mb->ssize; if ( newMalBlkStmt(mb, mb->ssize) < 0) return 0; pushInstruction(mb, old[0]); /* run the querylog.define operation */ defineQuery = copyInstruction(defineQuery); setFunctionId(defineQuery, insertRef); getArg(defineQuery,0) = newTmpVariable(mb,TYPE_any); defineQuery->token = ASSIGNsymbol; setModuleId(defineQuery,querylogRef); /* collect the initial statistics */ q = newStmt(mb, "clients", "getUsername"); name= getArg(q,0)= newVariable(mb,GDKstrdup("name"),TYPE_str); defineQuery = pushArgument(mb,defineQuery,name); q = newStmt(mb, "mtime", "current_timestamp"); start= getArg(q,0)= newVariable(mb,GDKstrdup("start"),TYPE_timestamp); defineQuery = pushArgument(mb,defineQuery,start); pushInstruction(mb, defineQuery); q = newStmt1(mb, sqlRef, "argRecord"); for ( argc=1; argc < old[0]->argc; argc++) q = pushArgument(mb, q, getArg(old[0],argc)); arg= getArg(q,0)= newVariable(mb,GDKstrdup("args"),TYPE_str); q = newStmt(mb, "alarm", "usec"); xtime = getArg(q,0)= newVariable(mb,GDKstrdup("xtime"),TYPE_lng); user = newVariable(mb,GDKstrdup("user"),TYPE_lng); nice = newVariable(mb,GDKstrdup("nice"),TYPE_lng); sys = newVariable(mb,GDKstrdup("sys"),TYPE_lng); idle = newVariable(mb,GDKstrdup("idle"),TYPE_lng); iowait = newVariable(mb,GDKstrdup("iowait"),TYPE_lng); q = newStmt(mb, "profiler", "cpustats"); q->retc= q->argc =0; q = pushReturn(mb,q,user); q = pushReturn(mb,q,nice); q = pushReturn(mb,q,sys); q = pushReturn(mb,q,idle); q = pushReturn(mb,q,iowait); q = newAssignment(mb); tuples= getArg(q,0) = newVariable(mb,GDKstrdup("tuples"),TYPE_wrd); (void) pushWrd(mb,q,1); for (i = 1; i < limit; i++) { p = old[i]; if (getModuleId(p)==sqlRef && (idcmp(getFunctionId(p),"exportValue")==0 || idcmp(getFunctionId(p),"exportResult")==0 ) ) { q = newStmt(mb, "alarm", "usec"); r = newStmt1(mb, calcRef, "-"); r = pushArgument(mb, r, getArg(q,0)); r = pushArgument(mb, r, xtime); getArg(r,0)=xtime; q = newStmt(mb, "alarm", "usec"); rtime= getArg(q,0)= newVariable(mb,GDKstrdup("rtime"),TYPE_lng); pushInstruction(mb,p); continue; } if ( getModuleId(p) == sqlRef && idcmp(getFunctionId(p),"resultSet")==0 && isaBatType(getVarType(mb,getArg(p,3)))){ q = newStmt(mb, "aggr", "count"); getArg(q,0) = tuples; (void) pushArgument(mb,q, getArg(p,3)); pushInstruction(mb,p); continue; } if ( p->token== ENDsymbol || p->barrier == RETURNsymbol || p->barrier == YIELDsymbol){ if ( rtime == 0){ q = newStmt(mb, "alarm", "usec"); r = newStmt1(mb, calcRef, "-"); r = pushArgument(mb, r, getArg(q,0)); r = pushArgument(mb, r, xtime); getArg(r,0)=xtime; q = newStmt(mb, "alarm", "usec"); rtime= getArg(q,0)= newVariable(mb,GDKstrdup("rtime"),TYPE_lng); } q = newStmt(mb, "alarm", "usec"); r = newStmt1(mb, calcRef, "-"); r = pushArgument(mb, r, getArg(q,0)); r = pushArgument(mb, r, rtime); getArg(r,0)=rtime; /* * Post execution statistics gathering */ q = newStmt(mb, "mtime", "current_timestamp"); finish= getArg(q,0)= newVariable(mb,GDKstrdup("finish"),TYPE_any); q = newStmt(mb, "profiler", "cpuload"); load = newVariable(mb,GDKstrdup("load"),TYPE_int); getArg(q,0)= load; io = newVariable(mb,GDKstrdup("io"),TYPE_int); q= pushReturn(mb,q,io); q = pushArgument(mb,q,user); q = pushArgument(mb,q,nice); q = pushArgument(mb,q,sys); q = pushArgument(mb,q,idle); q = pushArgument(mb,q,iowait); q = newStmt(mb, querylogRef, "call"); q = pushArgument(mb, q, start); q = pushArgument(mb, q, finish); q = pushArgument(mb, q, arg); q = pushArgument(mb, q, tuples); q = pushArgument(mb, q, xtime); q = pushArgument(mb, q, rtime); q = pushArgument(mb, q, load); q = pushArgument(mb, q, io); pushInstruction(mb,p); continue; } pushInstruction(mb,p); if (p->barrier == YIELDsymbol){ /* the factory yield may return */ q = newStmt(mb, "mtime", "current_timestamp"); start= getArg(q,0)= newVariable(mb,GDKstrdup("start"),TYPE_any); q = newStmt1(mb, sqlRef, "argRecord"); for ( argc=1; argc < old[0]->argc; argc++) q = pushArgument(mb, q, getArg(old[0],argc)); arg= getArg(q,0)= newVariable(mb,GDKstrdup("args"),TYPE_str); q = newAssignment(mb); q = pushLng(mb,q,0); q = newAssignment(mb); q = pushWrd(mb,q,0); tuples= getArg(q,0)= newVariable(mb,GDKstrdup("tuples"),TYPE_wrd); newFcnCall(mb,"profiler","setMemoryFlag"); q->argc--; pushWrd(mb,q,1); q = newStmt(mb, "alarm", "usec"); xtime = getArg(q,0)= newVariable(mb,GDKstrdup("xtime"),TYPE_lng); } } for( ; i<slimit; i++) if(old[i]) freeInstruction(old[i]); GDKfree(old); return 1; }
str OPTevaluateImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { InstrPtr p; int i, k, limit, *alias = 0, barrier; MalStkPtr env = NULL; int profiler; int debugstate = cntxt->itrace, actions = 0, constantblock = 0; int *assigned = 0, use; char buf[256]; lng usec = GDKusec(); str msg = MAL_SUCCEED; (void)stk; (void)pci; if ( mb->inlineProp ) return MAL_SUCCEED; cntxt->itrace = 0; #ifdef DEBUG_OPT_EVALUATE fprintf(stderr, "Constant expression optimizer started\n"); #endif assigned = (int*) GDKzalloc(sizeof(int) * mb->vtop); if (assigned == NULL) throw(MAL,"optimzier.evaluate", SQLSTATE(HY001) MAL_MALLOC_FAIL); alias = (int*)GDKzalloc(mb->vsize * sizeof(int) * 2); /* we introduce more */ if (alias == NULL){ GDKfree(assigned); throw(MAL,"optimzier.evaluate", SQLSTATE(HY001) MAL_MALLOC_FAIL); } // arguments are implicitly assigned by context p = getInstrPtr(mb, 0); for ( k =p->retc; k < p->argc; k++) assigned[getArg(p,k)]++; limit = mb->stop; for (i = 1; i < limit; i++) { p = getInstrPtr(mb, i); // The double count emerging from a barrier exit is ignored. if (! blockExit(p) || (blockExit(p) && p->retc != p->argc)) for ( k =0; k < p->retc; k++) if ( p->retc != p->argc || p->token != ASSIGNsymbol ) assigned[getArg(p,k)]++; } for (i = 1; i < limit && cntxt->mode != FINISHCLIENT; i++) { p = getInstrPtr(mb, i); // to avoid management of duplicate assignments over multiple blocks // we limit ourselves to evaluation of the first assignment only. use = assigned[getArg(p,0)] == 1 && !(p->argc == p->retc && blockExit(p)); for (k = p->retc; k < p->argc; k++) if (alias[getArg(p, k)]) getArg(p, k) = alias[getArg(p, k)]; #ifdef DEBUG_OPT_EVALUATE fprintInstruction(stderr , mb, 0, p, LIST_MAL_ALL); #endif /* be aware that you only assign once to a variable */ if (use && p->retc == 1 && OPTallConstant(cntxt, mb, p) && !isUnsafeFunction(p)) { barrier = p->barrier; p->barrier = 0; profiler = malProfileMode; /* we don't trace it */ malProfileMode = 0; if ( env == NULL) { env = prepareMALstack(mb, 2 * mb->vsize); if (!env) { msg = createException(MAL,"optimizer.evaluate", SQLSTATE(HY001) MAL_MALLOC_FAIL); goto wrapup; } env->keepAlive = TRUE; } msg = reenterMAL(cntxt, mb, i, i + 1, env); malProfileMode= profiler; p->barrier = barrier; #ifdef DEBUG_OPT_EVALUATE fprintf(stderr, "#retc var %s\n", getVarName(mb, getArg(p, 0))); fprintf(stderr, "#result:%s\n", msg == MAL_SUCCEED ? "ok" : msg); #endif if (msg == MAL_SUCCEED) { int nvar; ValRecord cst; actions++; cst.vtype = 0; VALcopy(&cst, &env->stk[getArg(p, 0)]); /* You may not overwrite constants. They may be used by * other instructions */ nvar = getArg(p, 1) = defConstant(mb, getArgType(mb, p, 0), &cst); if (nvar >= env->stktop) { VALcopy(&env->stk[getArg(p, 1)], &getVarConstant(mb, getArg(p, 1))); env->stktop = getArg(p, 1) + 1; } alias[getArg(p, 0)] = getArg(p, 1); p->argc = 2; p->token = ASSIGNsymbol; clrFunction(p); p->barrier = barrier; /* freeze the type */ setVarFixed(mb,getArg(p,1)); setVarUDFtype(mb,getArg(p,1)); #ifdef DEBUG_OPT_EVALUATE {str tpename; fprintf(stderr, "Evaluated new constant=%d -> %d:%s\n", getArg(p, 0), getArg(p, 1), tpename = getTypeName(getArgType(mb, p, 1))); GDKfree(tpename); } #endif } else { /* if there is an error, we should postpone message handling, as the actual error (eg. division by zero ) may not happen) */ #ifdef DEBUG_OPT_EVALUATE fprintf(stderr, "Evaluated %s\n", msg); #endif freeException(msg); msg= MAL_SUCCEED; mb->errors = 0; } } constantblock += blockStart(p) && OPTallConstant(cntxt, mb, p); /* default */ } // produces errors in SQL when enabled if ( constantblock) msg = OPTremoveUnusedBlocks(cntxt, mb); cntxt->itrace = debugstate; /* Defense line against incorrect plans */ /* Plan is unaffected */ chkTypes(cntxt->usermodule, mb, FALSE); chkFlow(mb); chkDeclarations(mb); /* keep all actions taken as a post block comment */ usec = GDKusec()- usec; snprintf(buf,256,"%-20s actions=%2d time=" LLFMT " usec","evaluate",actions,usec); newComment(mb,buf); if( actions >= 0) addtoMalBlkHistory(mb); wrapup: if ( env) freeStack(env); if(assigned) GDKfree(assigned); if(alias) GDKfree(alias); return msg; }
/* * 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. */ gdk_return BAThash(BAT *b, BUN masksize) { BAT *o = NULL; lng t0 = 0, t1 = 0; if (BATcheckhash(b)) { if (o != NULL) { o->T->hash = b->T->hash; BBPunfix(b->batCacheid); } return GDK_SUCCEED; } MT_lock_set(&GDKhashLock(abs(b->batCacheid)), "BAThash"); if (b->T->hash == NULL) { unsigned int tpe = ATOMbasetype(b->ttype); BUN cnt = BATcount(b); BUN mask, maxmask = 0; BUN p = BUNfirst(b), q = BUNlast(b), r; Hash *h = NULL; Heap *hp; const char *nme = BBP_physical(b->batCacheid); const char *ext = b->batCacheid > 0 ? "thash" : "hhash"; BATiter bi = bat_iterator(b); #ifdef PERSISTENTHASH int fd; #endif ALGODEBUG fprintf(stderr, "#BAThash: create hash(" BUNFMT ");\n", BATcount(b)); if ((hp = GDKzalloc(sizeof(*hp))) == NULL || (hp->farmid = BBPselectfarm(b->batRole, b->ttype, hashheap)) < 0 || (hp->filename = GDKmalloc(strlen(nme) + 12)) == NULL) { MT_lock_unset(&GDKhashLock(abs(b->batCacheid)), "BAThash"); GDKfree(hp); return GDK_FAIL; } sprintf(hp->filename, "%s.%s", nme, ext); /* cnt = 0, hopefully there is a proper capacity from * which we can derive enough information */ if (!cnt) cnt = BATcapacity(b); if (b->ttype == TYPE_void) { if (b->tseqbase == oid_nil) { MT_lock_unset(&GDKhashLock(abs(b->batCacheid)), "BAThash"); ALGODEBUG fprintf(stderr, "#BAThash: cannot create hash-table on void-NIL column.\n"); GDKfree(hp->filename); GDKfree(hp); return GDK_FAIL; } 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(tpe) == 1) { mask = (1 << 8); } else if (ATOMsize(tpe) == 2) { mask = (1 << 16); } else if (b->tkey) { 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). */ maxmask = HASHmask(cnt); mask = maxmask >> 6; p += (cnt >> 2); /* try out on first 25% of b */ if (p > q) p = q; } t0 = GDKusec(); do { BUN nslots = mask >> 3; /* 1/8 full is too full */ r = BUNfirst(b); if (h) { char *fnme; bte farmid; ALGODEBUG fprintf(stderr, "#BAThash: retry hash construction\n"); fnme = GDKstrdup(hp->filename); farmid = hp->farmid; HEAPfree(hp, 1); memset(hp, 0, sizeof(*hp)); hp->filename = fnme; hp->farmid = farmid; GDKfree(h); h = NULL; } /* create the hash structures */ if ((h = HASHnew(hp, ATOMtype(b->ttype), BATcapacity(b), mask, BATcount(b))) == NULL) { MT_lock_unset(&GDKhashLock(abs(b->batCacheid)), "BAThash"); GDKfree(hp->filename); GDKfree(hp); return GDK_FAIL; } switch (tpe) { case TYPE_bte: starthash(bte); break; case TYPE_sht: starthash(sht); break; case TYPE_int: case TYPE_flt: #if SIZEOF_OID == SIZEOF_INT case TYPE_oid: #endif #if SIZEOF_WRD == SIZEOF_INT case TYPE_wrd: #endif starthash(int); break; case TYPE_dbl: case TYPE_lng: #if SIZEOF_OID == SIZEOF_LNG case TYPE_oid: #endif #if SIZEOF_WRD == SIZEOF_LNG case TYPE_wrd: #endif starthash(lng); break; #ifdef HAVE_HGE case TYPE_hge: starthash(hge); break; #endif default: for (; r < p; r++) { ptr v = BUNtail(bi, r); BUN c = (BUN) heap_hash_any(b->T->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 < maxmask && (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: #if SIZEOF_OID == SIZEOF_INT case TYPE_oid: #endif #if SIZEOF_WRD == SIZEOF_INT case TYPE_wrd: #endif finishhash(int); break; case TYPE_dbl: case TYPE_lng: #if SIZEOF_OID == SIZEOF_LNG case TYPE_oid: #endif #if SIZEOF_WRD == SIZEOF_LNG case TYPE_wrd: #endif finishhash(lng); break; #ifdef HAVE_HGE case TYPE_hge: finishhash(hge); break; #endif default: for (; p < q; p++) { ptr v = BUNtail(bi, p); BUN c = (BUN) heap_hash_any(b->T->vheap, h, v); HASHputlink(h, p, HASHget(h, c)); HASHput(h, c, p); } break; } #ifdef PERSISTENTHASH if ((BBP_status(b->batCacheid) & BBPEXISTING) && b->batInserted == b->batCount && HEAPsave(hp, nme, ext) == GDK_SUCCEED && (fd = GDKfdlocate(hp->farmid, nme, "rb+", ext)) >= 0) { ALGODEBUG fprintf(stderr, "#BAThash: persisting hash %d\n", b->batCacheid); ((size_t *) hp->base)[0] |= 1 << 24; if (write(fd, hp->base, SIZEOF_SIZE_T) < 0) perror("write hash"); if (!(GDKdebug & FORCEMITOMASK)) { #if defined(NATIVE_WIN32) _commit(fd); #elif defined(HAVE_FDATASYNC) fdatasync(fd); #elif defined(HAVE_FSYNC) fsync(fd); #endif } close(fd); } else ALGODEBUG fprintf(stderr, "#BAThash: NOT persisting hash %d\n", b->batCacheid); #endif b->T->hash = h; t1 = GDKusec(); ALGODEBUG fprintf(stderr, "#BAThash: hash construction " LLFMT " usec\n", t1 - t0); ALGODEBUG HASHcollisions(b, b->T->hash); }
/* return TRUE if we have a hash on the tail, even if we need to read * one from disk */ int BATcheckhash(BAT *b) { int ret; lng t; t = GDKusec(); MT_lock_set(&GDKhashLock(abs(b->batCacheid)), "BATcheckhash"); t = GDKusec() - t; // use or ignore a persistent hash #ifdef PERSISTENTHASH if (b->T->hash == NULL) { Hash *h; Heap *hp; const char *nme = BBP_physical(b->batCacheid); const char *ext = b->batCacheid > 0 ? "thash" : "hhash"; int fd; if ((hp = GDKzalloc(sizeof(*hp))) != NULL && (hp->farmid = BBPselectfarm(b->batRole, b->ttype, hashheap)) >= 0 && (hp->filename = GDKmalloc(strlen(nme) + 12)) != NULL) { sprintf(hp->filename, "%s.%s", nme, ext); /* check whether a persisted hash can be found */ if ((fd = GDKfdlocate(hp->farmid, nme, "rb+", ext)) >= 0) { size_t hdata[HASH_HEADER_SIZE]; struct stat st; if ((h = GDKmalloc(sizeof(*h))) != NULL && read(fd, hdata, sizeof(hdata)) == sizeof(hdata) && hdata[0] == (((size_t) 1 << 24) | HASH_VERSION) && hdata[4] == (size_t) BATcount(b) && fstat(fd, &st) == 0 && st.st_size >= (off_t) (hp->size = hp->free = (hdata[1] + hdata[2]) * hdata[3] + HASH_HEADER_SIZE * SIZEOF_SIZE_T) && HEAPload(hp, nme, ext, 0) == GDK_SUCCEED) { h->lim = (BUN) hdata[1]; h->type = ATOMtype(b->ttype); h->mask = (BUN) (hdata[2] - 1); h->heap = hp; h->width = (int) hdata[3]; switch (h->width) { case BUN2: h->nil = (BUN) BUN2_NONE; break; case BUN4: h->nil = (BUN) BUN4_NONE; break; #ifdef BUN8 case BUN8: h->nil = (BUN) BUN8_NONE; break; #endif default: assert(0); } h->Link = hp->base + HASH_HEADER_SIZE * SIZEOF_SIZE_T; h->Hash = (void *) ((char *) h->Link + h->lim * h->width); close(fd); b->T->hash = h; ALGODEBUG fprintf(stderr, "#BATcheckhash: reusing persisted hash %d\n", b->batCacheid); MT_lock_unset(&GDKhashLock(abs(b->batCacheid)), "BATcheckhash"); return 1; } GDKfree(h); close(fd); /* unlink unusable file */ GDKunlink(hp->farmid, BATDIR, nme, ext); } GDKfree(hp->filename); } GDKfree(hp); } #endif ret = b->T->hash != NULL; MT_lock_unset(&GDKhashLock(abs(b->batCacheid)), "BATcheckhash"); ALGODEBUG if (ret) fprintf(stderr, "#BATcheckhash: already has hash %d, waited " LLFMT " usec\n", b->batCacheid, t); return ret; }
static void SQLgetStatistics(Client cntxt, mvc *m, MalBlkPtr mb) { InstrPtr *old = NULL; int oldtop, i, actions = 0, size = 0; lng clk = GDKusec(); sql_trans *tr = m->session->tr; str msg; old = mb->stmt; oldtop = mb->stop; size = (mb->stop * 1.2 < mb->ssize) ? mb->ssize : (int) (mb->stop * 1.2); mb->stmt = (InstrPtr *) GDKzalloc(size * sizeof(InstrPtr)); mb->ssize = size; mb->stop = 0; for (i = 0; i < oldtop; i++) { InstrPtr p = old[i]; char *f = getFunctionId(p); if (getModuleId(p) == sqlRef && f == tidRef) { char *sname = getVarConstant(mb, getArg(p, 2)).val.sval; char *tname = getVarConstant(mb, getArg(p, 3)).val.sval; sql_schema *s = mvc_bind_schema(m, sname); sql_table *t; if (!s || strcmp(s->base.name, dt_schema) == 0) { pushInstruction(mb, p); continue; } t = mvc_bind_table(m, s, tname); if (t && (!isRemote(t) && !isMergeTable(t)) && t->p) { int mt_member = t->p->base.id; setMitosisPartition(p,mt_member); } } if (getModuleId(p) == sqlRef && (f == bindRef || f == bindidxRef)) { int upd = (p->argc == 7 || p->argc == 9); char *sname = getVarConstant(mb, getArg(p, 2 + upd)).val.sval; char *tname = getVarConstant(mb, getArg(p, 3 + upd)).val.sval; char *cname = NULL; int mt_member = 0; BUN rows = 1; /* default to cope with delta bats */ int mode = 0; int k = getArg(p, 0); sql_schema *s = mvc_bind_schema(m, sname); BAT *b; if (!s || strcmp(s->base.name, dt_schema) == 0) { pushInstruction(mb, p); continue; } cname = getVarConstant(mb, getArg(p, 4 + upd)).val.sval; mode = getVarConstant(mb, getArg(p, 5 + upd)).val.ival; if (s && f == bindidxRef && cname) { size_t cnt; sql_idx *i = mvc_bind_idx(m, s, cname); if (i && (!isRemote(i->t) && !isMergeTable(i->t))) { cnt = store_funcs.count_idx(tr, i, 1); assert(cnt <= (size_t) GDK_oid_max); b = store_funcs.bind_idx(m->session->tr, i, RDONLY); if (b) { cnt = BATcount(b); BBPunfix(b->batCacheid); } rows = (BUN) cnt; if (i->t->p) mt_member = i->t->p->base.id; } } else if (s && f == bindRef && cname) { size_t cnt; sql_table *t = mvc_bind_table(m, s, tname); sql_column *c = mvc_bind_column(m, t, cname); if (c && (!isRemote(c->t) && !isMergeTable(c->t))) { cnt = store_funcs.count_col(tr, c, 1); assert(cnt <= (size_t) GDK_oid_max); b = store_funcs.bind_col(m->session->tr, c, RDONLY); if (b) { cnt = BATcount(b); BBPunfix(b->batCacheid); } rows = (BUN) cnt; if (c->t->p) mt_member = c->t->p->base.id; } } if (rows > 1 && mode != RD_INS) setRowCnt(mb,k,rows); if (mt_member && mode != RD_INS) setMitosisPartition(p,mt_member); pushInstruction(mb, p); } else { pushInstruction(mb, p); } } GDKfree(old); msg = optimizerCheck(cntxt, mb, "optimizer.SQLgetstatistics", actions, GDKusec() - clk); if (msg) /* what to do with an error? */ GDKfree(msg); }
static Client MCinitClientRecord(Client c, oid user, bstream *fin, stream *fout) { const char *prompt; c->user = user; c->username = 0; c->scenario = NULL; c->oldscenario = NULL; c->srcFile = NULL; c->blkmode = 0; c->fdin = fin ? fin : bstream_create(GDKin, 0); if ( c->fdin == NULL){ MT_lock_set(&mal_contextLock); c->mode = FREECLIENT; MT_lock_unset(&mal_contextLock); showException(GDKout, MAL, "initClientRecord", MAL_MALLOC_FAIL); return NULL; } c->yycur = 0; c->bak = NULL; c->listing = 0; c->fdout = fout ? fout : GDKstdout; c->mdb = 0; c->history = 0; c->curprg = c->backup = 0; c->glb = 0; /* remove garbage from previous connection * be aware, a user can introduce several modules * that should be freed to avoid memory leaks */ c->usermodule = c->curmodule = 0; c->father = NULL; c->login = c->lastcmd = time(0); //c->active = 0; c->session = GDKusec(); c->qtimeout = 0; c->stimeout = 0; c->itrace = 0; c->flags = 0; c->errbuf = 0; prompt = !fin ? GDKgetenv("monet_prompt") : PROMPT1; c->prompt = GDKstrdup(prompt); if ( c->prompt == NULL){ if (fin == NULL) { c->fdin->s = NULL; bstream_destroy(c->fdin); MT_lock_set(&mal_contextLock); c->mode = FREECLIENT; MT_lock_unset(&mal_contextLock); } showException(GDKout, MAL, "initClientRecord", MAL_MALLOC_FAIL); return NULL; } c->promptlength = strlen(prompt); c->actions = 0; c->exception_buf_initialized = 0; c->error_row = c->error_fld = c->error_msg = c->error_input = NULL; c->wlc_kind = 0; c->wlc = NULL; #ifndef HAVE_EMBEDDED /* no authentication in embedded mode */ { str msg = AUTHgetUsername(&c->username, c); if (msg) /* shouldn't happen */ freeException(msg); } #endif c->blocksize = BLOCK; c->protocol = PROTOCOL_9; c->filetrans = false; c->query = NULL; char name[16]; snprintf(name, sizeof(name), "Client%d->s", (int) (c - mal_clients)); MT_sema_init(&c->s, 0, name); return c; }
str OPTwrapper (Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p){ str modnme = "(NONE)"; str fcnnme = 0; str msg= MAL_SUCCEED; Symbol s= NULL; lng t,clk= GDKusec(); int i, actions = 0; char optimizer[256]; InstrPtr q; if( p == NULL) throw(MAL, "opt_wrapper", "missing optimizer statement"); snprintf(optimizer,256,"%s", fcnnme = getFunctionId(p)); q= copyInstruction(p); OPTIMIZERDEBUG mnstr_printf(cntxt->fdout,"=APPLY OPTIMIZER %s\n",fcnnme); if( p && p->argc > 1 ){ if( getArgType(mb,p,1) != TYPE_str || getArgType(mb,p,2) != TYPE_str || !isVarConstant(mb,getArg(p,1)) || !isVarConstant(mb,getArg(p,2)) ) { freeInstruction(q); throw(MAL, optimizer, ILLARG_CONSTANTS); } if( stk != 0){ modnme= *getArgReference_str(stk,p,1); fcnnme= *getArgReference_str(stk,p,2); } else { modnme= getArgDefault(mb,p,1); fcnnme= getArgDefault(mb,p,2); } removeInstruction(mb, p); s= findSymbol(cntxt->nspace, putName(modnme,strlen(modnme)),putName(fcnnme,strlen(fcnnme))); if( s == NULL) { freeInstruction(q); throw(MAL, optimizer, RUNTIME_OBJECT_UNDEFINED ":%s.%s", modnme, fcnnme); } mb = s->def; stk= 0; } else if( p ) removeInstruction(mb, p); if( mb->errors ){ /* when we have errors, we still want to see them */ addtoMalBlkHistory(mb,getModuleId(q)); freeInstruction(q); return MAL_SUCCEED; } for ( i=0; codes[i].nme; i++) if ( strcmp(codes[i].nme, optimizer)== 0 ){ actions = (int)(*(codes[i].fcn))(cntxt, mb, stk,0); break; } if ( codes[i].nme == 0){ freeInstruction(q); throw(MAL, optimizer, RUNTIME_OBJECT_UNDEFINED ":%s.%s", modnme, fcnnme); } msg= optimizerCheck(cntxt, mb, optimizer, actions, t=(GDKusec() - clk)); OPTIMIZERDEBUG { mnstr_printf(cntxt->fdout,"=FINISHED %s %d\n",optimizer, actions); printFunction(cntxt->fdout,mb,0,LIST_MAL_DEBUG ); } DEBUGoptimizers mnstr_printf(cntxt->fdout,"#optimizer %-11s %3d actions %5d MAL instructions ("SZFMT" K) " LLFMT" usec\n", optimizer, actions, mb->stop, ((sizeof( MalBlkRecord) +mb->ssize * offsetof(InstrRecord, argv)+ mb->vtop * sizeof(int) /* argv estimate */ +mb->vtop* sizeof(VarRecord) + mb->vsize*sizeof(VarPtr)+1023)/1024), t); QOTupdateStatistics(getModuleId(q),actions,t); addtoMalBlkHistory(mb,getModuleId(q)); freeInstruction(q); return msg; }
static void produceStream(Sensor se) { int b; int slen; char buf[MYBUFSIZ + 1]; /* compose an event message locally first */ char tuple[MYBUFSIZ + 1]; /* scratch area for a single tuple element */ int tlen, maxtuple = MYBUFSIZ; int buflen; int numberOFtuples = 0; #ifdef SENSOR_DEBUG mnstr_printf(SEout, "#Start producing the stream\n"); mnstr_printf(SEout, "#%d events, batchsize is %d, columns are %d\n", events, batchsize, columns); #endif /* create scratch space for a single tuple, this should be enough for integer fields */ buflen = 0; while (numberOFtuples < (events * batchsize) || events == -1) { int i; lng currenttsmp = 0; if (delay > 0) { /* wait */ MT_sleep_ms(delay); } if (delay < 0) { mnstr_printf(SEout, "#send next?"); getchar(); } buf[0] = 0; slen = 0; tlen = 0; if (batchsize > 1) { snprintf(tuple, maxtuple, "#%d\n", batchsize); tlen += (int) strlen(tuple + tlen); strncpy(buf, tuple, tlen); slen += tlen; } /* construct a single event record batch */ for (b = batchsize; b > 0; b--) { /* the first column is used for event identifier tagging */ tlen = 0; if (autoincrement) { snprintf(tuple + tlen, maxtuple - tlen, "%d", autoincrement); tlen += (int) strlen(tuple + tlen); autoincrement++; } /* if timestamp is set then the next colum will contain the wall-clock microstamp. This reduces the number of additional columns to be produced by 1 */ if (timestamp) { currenttsmp = GDKusec(); snprintf(tuple + tlen, maxtuple - tlen, "%s" LLFMT "", (autoincrement ? separator[protocol] : ""), currenttsmp); tlen += (int) strlen(tuple + tlen); if (tlen >= maxtuple) { mnstr_printf(SEout, "Buffer not large enough to handle request.\n"); mnstr_printf(SEout, "recompile with larger constant \n"); return; } } /* we only generate integer based events for now */ for (i = (timestamp ? 1 : 0) + (autoincrement ? 1 : 0); i < columns; i++) { if (i) snprintf(tuple + tlen, maxtuple - tlen, "%s%d", separator[protocol], rand()); else snprintf(tuple + tlen, maxtuple - tlen, "%d", rand()); tlen += (int) strlen(tuple + tlen); } snprintf(tuple + tlen, maxtuple - tlen, "\n"); tlen += (int) strlen(tuple + tlen); /* now add the tuple to the buffer if there is room left*/ if (MYBUFSIZ - buflen <= tlen) { mnstr_printf(SEout, "Buffer not large enough to handle request.\n"); mnstr_printf(SEout, "recompile with larger constant \n"); return; } strncpy(buf + slen, tuple, tlen); slen += tlen; numberOFtuples++; } /* the batch has now been created, it should be shipped */ /* watch out, the buffer is not NULL terminated */ if (mnstr_write(se->toServer, buf, 1, slen) == -1 && ((errno == EPIPE) || (errno == ECONNRESET))) { mnstr_printf(SEout, "errno:%s %d\n", strerror(errno), errno); close_stream(se->toServer); se->toServer = NULL; return; } if (trace) { buf[slen] = 0; mnstr_printf(SEout, "%s", buf); /*mnstr_flush(SEout);*/ } } /* you should not close the stream to quickly because then you may loose part of the input */ if (protocol != DEB) { mnstr_printf(SEout, "Columns: %d\n", columns); mnstr_printf(SEout, "Batch size: %d\n", batchsize); mnstr_printf(SEout, "total Number of batches: %d\n", events); mnstr_printf(SEout, "Delay: %d\n", delay); } mnstr_printf(SEout, "ready to close connection?"); (void) getchar(); close_stream(se->toServer); se->toServer = NULL; }
static void SQLgetStatistics(Client cntxt, mvc *m, MalBlkPtr mb) { InstrPtr *old = NULL; int oldtop, i, actions = 0, size = 0; lng clk = GDKusec(); sql_trans *tr = m->session->tr; str msg; old = mb->stmt; oldtop = mb->stop; size = (mb->stop * 1.2 < mb->ssize) ? mb->ssize : (int) (mb->stop * 1.2); mb->stmt = (InstrPtr *) GDKzalloc(size * sizeof(InstrPtr)); mb->ssize = size; mb->stop = 0; for (i = 0; i < oldtop; i++) { InstrPtr p = old[i]; char *f = getFunctionId(p); ValRecord vr; if (getModuleId(p) == sqlRef && f == tidRef) { char *sname = getVarConstant(mb, getArg(p, 2)).val.sval; char *tname = getVarConstant(mb, getArg(p, 3)).val.sval; sql_schema *s = mvc_bind_schema(m, sname); sql_table *t; if (!s || strcmp(s->base.name, dt_schema) == 0) { pushInstruction(mb, p); continue; } t = mvc_bind_table(m, s, tname); if (t && (!isRemote(t) && !isMergeTable(t)) && t->p) { int k = getArg(p, 0), mt_member = t->p->base.id; varSetProp(mb, k, mtProp, op_eq, VALset(&vr, TYPE_int, &mt_member)); } } if (getModuleId(p) == sqlRef && (f == bindRef || f == bindidxRef)) { int upd = (p->argc == 7 || p->argc == 9); char *sname = getVarConstant(mb, getArg(p, 2 + upd)).val.sval; char *tname = getVarConstant(mb, getArg(p, 3 + upd)).val.sval; char *cname = NULL; int not_null = 0, mt_member = 0; wrd rows = 1; /* default to cope with delta bats */ int mode = 0; int k = getArg(p, 0); sql_schema *s = mvc_bind_schema(m, sname); BAT *b; if (!s || strcmp(s->base.name, dt_schema) == 0) { pushInstruction(mb, p); continue; } cname = getVarConstant(mb, getArg(p, 4 + upd)).val.sval; mode = getVarConstant(mb, getArg(p, 5 + upd)).val.ival; if (s && f == bindidxRef && cname) { size_t cnt; sql_idx *i = mvc_bind_idx(m, s, cname); if (i && (!isRemote(i->t) && !isMergeTable(i->t))) { cnt = store_funcs.count_idx(tr, i, 1); assert(cnt <= (size_t) GDK_oid_max); b = store_funcs.bind_idx(m->session->tr, i, RDONLY); if (b) { str loc; if (b->batPersistence == PERSISTENT && BATlocation(&loc, &b->batCacheid) && loc) varSetProp(mb, k, fileProp, op_eq, VALset(&vr, TYPE_str, loc)); cnt = BATcount(b); BBPunfix(b->batCacheid); } rows = (wrd) cnt; if (i->t->p) mt_member = i->t->p->base.id; } } else if (s && f == bindRef && cname) { size_t cnt; sql_table *t = mvc_bind_table(m, s, tname); sql_column *c = mvc_bind_column(m, t, cname); if (c && (!isRemote(c->t) && !isMergeTable(c->t))) { not_null = !c->null; cnt = store_funcs.count_col(tr, c, 1); assert(cnt <= (size_t) GDK_oid_max); b = store_funcs.bind_col(m->session->tr, c, RDONLY); if (b) { str loc; if (b->batPersistence == PERSISTENT && BATlocation(&loc, &b->batCacheid) && loc) varSetProp(mb, k, fileProp, op_eq, VALset(&vr, TYPE_str, loc)); cnt = BATcount(b); BBPunfix(b->batCacheid); } rows = (wrd) cnt; if (c->t->p) mt_member = c->t->p->base.id; } } if (rows > 1 && mode != RD_INS) varSetProp(mb, k, rowsProp, op_eq, VALset(&vr, TYPE_wrd, &rows)); if (not_null) varSetProp(mb, k, notnilProp, op_eq, NULL); if (mt_member && mode != RD_INS) varSetProp(mb, k, mtProp, op_eq, VALset(&vr, TYPE_int, &mt_member)); { int lowprop = hlbProp, highprop = hubProp; /* rows == cnt has been checked above to be <= GDK_oid_max */ oid low = 0, high = low + (oid) rows; pushInstruction(mb, p); if (mode == RD_INS) { low = high; high += 1024 * 1024; } varSetProp(mb, getArg(p, 0), lowprop, op_gte, VALset(&vr, TYPE_oid, &low)); varSetProp(mb, getArg(p, 0), highprop, op_lt, VALset(&vr, TYPE_oid, &high)); } if (not_null) actions++; } else { pushInstruction(mb, p); } } GDKfree(old); msg = optimizerCheck(cntxt, mb, "optimizer.SQLgetstatistics", actions, GDKusec() - clk); if (msg) /* what to do with an error? */ GDKfree(msg); }
str OPTvolcanoImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { int i, limit; int mvcvar = -1; int count=0; InstrPtr p,q, *old = mb->stmt; char buf[256]; lng usec = GDKusec(); str msg = MAL_SUCCEED; (void) pci; (void) cntxt; (void) stk; /* to fool compilers */ if ( mb->inlineProp ) return MAL_SUCCEED; limit= mb->stop; if ( newMalBlkStmt(mb, mb->ssize + 20) < 0) throw(MAL,"optimizer.volcano", SQLSTATE(HY001) MAL_MALLOC_FAIL); for (i = 0; i < limit; i++) { p = old[i]; pushInstruction(mb,p); if( getModuleId(p) == sqlRef && getFunctionId(p)== mvcRef ){ mvcvar = getArg(p,0); continue; } if( count < MAXdelays && getModuleId(p) == algebraRef ){ if( getFunctionId(p) == selectRef || getFunctionId(p) == thetaselectRef || getFunctionId(p) == likeselectRef || getFunctionId(p) == joinRef ){ q= newInstruction(0,languageRef,blockRef); setDestVar(q, newTmpVariable(mb,TYPE_any)); q = pushArgument(mb,q,mvcvar); q = pushArgument(mb,q,getArg(p,0)); mvcvar= getArg(q,0); pushInstruction(mb,q); count++; } continue; } if( count < MAXdelays && getModuleId(p) == groupRef ){ if( getFunctionId(p) == subgroupdoneRef || getFunctionId(p) == groupdoneRef ){ q= newInstruction(0,languageRef,blockRef); setDestVar(q, newTmpVariable(mb,TYPE_any)); q = pushArgument(mb,q,mvcvar); q = pushArgument(mb,q,getArg(p,0)); mvcvar= getArg(q,0); pushInstruction(mb,q); count++; } } if( getModuleId(p) == sqlRef){ if ( getFunctionId(p) == bindRef || getFunctionId(p) == bindidxRef || getFunctionId(p)== tidRef || getFunctionId(p)== appendRef || getFunctionId(p)== updateRef || getFunctionId(p)== deleteRef ){ setArg(p,p->retc,mvcvar); } } } GDKfree(old); /* Defense line against incorrect plans */ if( count){ chkTypes(cntxt->usermodule, mb, FALSE); chkFlow(mb); chkDeclarations(mb); } /* keep all actions taken as a post block comment */ usec = GDKusec()- usec; snprintf(buf,256,"%-20s actions=%2d time=" LLFMT " usec","volcano",count,usec); newComment(mb,buf); if( count >= 0) addtoMalBlkHistory(mb); return msg; }
str OPTmultiplexImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { InstrPtr *old = 0, p; int i, limit, slimit, actions= 0; str msg= MAL_SUCCEED; char buf[256]; lng usec = GDKusec(); (void) stk; (void) pci; old = mb->stmt; limit = mb->stop; slimit = mb->ssize; if ( newMalBlkStmt(mb, mb->ssize) < 0 ) throw(MAL,"optimizer.mergetable", SQLSTATE(HY001) MAL_MALLOC_FAIL); for (i = 0; i < limit; i++) { p = old[i]; if (msg == MAL_SUCCEED && isMultiplex(p)) { if ( MANIFOLDtypecheck(cntxt,mb,p,0) != NULL){ setFunctionId(p, manifoldRef); p->typechk = TYPE_UNKNOWN; pushInstruction(mb, p); actions++; continue; } msg = OPTexpandMultiplex(cntxt, mb, stk, p); if( msg== MAL_SUCCEED){ freeInstruction(p); old[i]=0; actions++; continue; } pushInstruction(mb, p); actions++; } else if( old[i]) pushInstruction(mb, p); } for(;i<slimit; i++) if( old[i]) freeInstruction(old[i]); GDKfree(old); /* Defense line against incorrect plans */ if( msg == MAL_SUCCEED && actions > 0){ chkTypes(cntxt->usermodule, mb, FALSE); chkFlow(mb); chkDeclarations(mb); } /* keep all actions taken as a post block comment */ usec = GDKusec()- usec; snprintf(buf,256,"%-20s actions=%2d time=" LLFMT " usec","multiplex",actions, usec); newComment(mb,buf); if( actions >= 0) addtoMalBlkHistory(mb); return msg; }
/* * 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); }
/* #define _SQL_READER_DEBUG */ str SQLreader(Client c) { int go = TRUE; int more = TRUE; int commit_done = FALSE; backend *be = (backend *) c->sqlcontext; bstream *in = c->fdin; int language = -1; mvc *m = NULL; int blocked = isa_block_stream(in->s); if (SQLinitialized == FALSE) { c->mode = FINISHCLIENT; return NULL; } if (!be || c->mode <= FINISHCLIENT) { #ifdef _SQL_READER_DEBUG mnstr_printf(GDKout, "#SQL client finished\n"); #endif c->mode = FINISHCLIENT; return NULL; } #ifdef _SQL_READER_DEBUG mnstr_printf(GDKout, "#SQLparser: start reading SQL %s %s\n", (be->console ? " from console" : ""), (blocked ? "Blocked read" : "")); #endif language = be->language; /* 'S' for SQL, 'D' from debugger */ m = be->mvc; m->errstr[0] = 0; /* * Continue processing any left-over input from the previous round. */ #ifdef _SQL_READER_DEBUG mnstr_printf(GDKout, "#pos %d len %d eof %d \n", in->pos, in->len, in->eof); #endif /* * Distinguish between console reading and mclient connections. * The former comes with readline functionality. */ while (more) { more = FALSE; /* Different kinds of supported statements sequences A; -- single line s A \n B; -- multi line S A; B; -- compound single block s A; -- many multi line B \n C; -- statements in one block S */ /* auto_commit on end of statement */ if (m->scanner.mode == LINE_N && !commit_done) { go = SQLautocommit(c, m); commit_done = TRUE; } if (go && in->pos >= in->len) { ssize_t rd; if (c->bak) { #ifdef _SQL_READER_DEBUG mnstr_printf(GDKout, "#Switch to backup stream\n"); #endif in = c->fdin; blocked = isa_block_stream(in->s); m->scanner.rs = c->fdin; c->fdin->pos += c->yycur; c->yycur = 0; } if (in->eof || !blocked) { language = (be->console) ? 'S' : 0; /* The rules of auto_commit require us to finish and start a transaction on the start of a new statement (s A;B; case) */ if (!(m->emod & mod_debug) && !commit_done) { go = SQLautocommit(c, m); commit_done = TRUE; } if (go && ((!blocked && mnstr_write(c->fdout, c->prompt, c->promptlength, 1) != 1) || mnstr_flush(c->fdout))) { go = FALSE; break; } in->eof = 0; } if (in->buf == NULL) { more = FALSE; go = FALSE; } else if (go && (rd = bstream_next(in)) <= 0) { #ifdef _SQL_READER_DEBUG mnstr_printf(GDKout, "#rd %d language %d eof %d\n", rd, language, in->eof); #endif if (be->language == 'D' && in->eof == 0) return 0; if (rd == 0 && language !=0 && in->eof && !be->console) { /* we hadn't seen the EOF before, so just try again (this time with prompt) */ more = TRUE; continue; } go = FALSE; break; } else if (go && !be->console && language == 0) { if (in->buf[in->pos] == 's' && !in->eof) { while ((rd = bstream_next(in)) > 0) ; } be->language = in->buf[in->pos++]; if (be->language == 's') { be->language = 'S'; m->scanner.mode = LINE_1; } else if (be->language == 'S') { m->scanner.mode = LINE_N; } } #ifdef _SQL_READER_DEBUG mnstr_printf(GDKout, "#SQL blk:%s\n", in->buf + in->pos); #endif } } if ( (c->stimeout && (GDKusec() - c->session) > c->stimeout) || !go || (strncmp(CURRENT(c), "\\q", 2) == 0)) { in->pos = in->len; /* skip rest of the input */ c->mode = FINISHCLIENT; return NULL; } return 0; }
str OPTgeneratorImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { InstrPtr p,q, *old, *series; int i, k, limit, slimit, actions=0; str m; str bteRef = getName("bte"); str shtRef = getName("sht"); str intRef = getName("int"); str lngRef = getName("lng"); str fltRef = getName("flt"); str dblRef = getName("dbl"); char buf[256]; lng usec= GDKusec(); (void) cntxt; (void) stk; (void) pci; series = (InstrPtr*) GDKzalloc(sizeof(InstrPtr) * mb->vtop); if(series == NULL) throw(MAL,"optimizer.generator", SQLSTATE(HY001) MAL_MALLOC_FAIL); old = mb->stmt; limit = mb->stop; slimit = mb->ssize; // check applicability first for( i=0; i < limit; i++){ p = old[i]; if ( getModuleId(p) == generatorRef && getFunctionId(p) == seriesRef) break; } if (i == limit) { GDKfree(series); return 0; } if (newMalBlkStmt(mb, mb->ssize) < 0) { GDKfree(series); throw(MAL,"optimizer.generator", SQLSTATE(HY001) MAL_MALLOC_FAIL); } for( i=0; i < limit; i++){ p = old[i]; if (p->token == ENDsymbol){ pushInstruction(mb,p); break; } if ( getModuleId(p) == generatorRef && getFunctionId(p) == seriesRef){ series[getArg(p,0)] = p; setModuleId(p, generatorRef); setFunctionId(p, parametersRef); typeChecker(cntxt->usermodule, mb, p, TRUE); pushInstruction(mb,p); } else if ( getModuleId(p) == algebraRef && getFunctionId(p) == selectRef && series[getArg(p,1)]){ errorCheck(p,algebraRef,getArg(p,1)); } else if ( getModuleId(p) == algebraRef && getFunctionId(p) == thetaselectRef && series[getArg(p,1)]){ errorCheck(p,algebraRef,getArg(p,1)); } else if ( getModuleId(p) == algebraRef && getFunctionId(p) == projectionRef && series[getArg(p,2)]){ errorCheck(p,algebraRef,getArg(p,2)); } else if ( getModuleId(p) == sqlRef && getFunctionId(p) == putName("exportValue") && isaBatType(getArgType(mb,p,0)) ){ // interface expects scalar type only, not expressable in MAL signature mb->errors=createException(MAL, "generate_series", SQLSTATE(42000) "internal error, generate_series is a table producing function"); }else if ( getModuleId(p) == batcalcRef && getFunctionId(p) == bteRef && series[getArg(p,1)] && p->argc == 2 ){ casting(bte); } else if ( getModuleId(p) == batcalcRef && getFunctionId(p) == shtRef && series[getArg(p,1)] && p->argc == 2 ){ casting(sht); } else if ( getModuleId(p) == batcalcRef && getFunctionId(p) == intRef && series[getArg(p,1)] && p->argc == 2 ){ casting(int); } else if ( getModuleId(p) == batcalcRef && getFunctionId(p) == lngRef && series[getArg(p,1)] && p->argc == 2 ){ casting(lng); } else if ( getModuleId(p) == batcalcRef && getFunctionId(p) == fltRef && series[getArg(p,1)] && p->argc == 2 ){ casting(flt); } else if ( getModuleId(p) == batcalcRef && getFunctionId(p) == dblRef && series[getArg(p,1)] && p->argc == 2 ){ casting(dbl); } else if ( getModuleId(p) == languageRef && getFunctionId(p) == passRef ) pushInstruction(mb,p); else { // check for use without conversion for(k = p->retc; k < p->argc; k++) if( series[getArg(p,k)]){ m = getModuleId(p); setModuleId(p, generatorRef); typeChecker(cntxt->usermodule, mb, p, TRUE); if(p->typechk == TYPE_UNKNOWN){ setModuleId(p,m); typeChecker(cntxt->usermodule, mb, p, TRUE); setModuleId(series[getArg(p,k)], generatorRef); setFunctionId(series[getArg(p,k)], seriesRef); typeChecker(cntxt->usermodule, mb, series[getArg(p,k)], TRUE); } } pushInstruction(mb,p); } } for (i++; i < limit; i++) pushInstruction(mb, old[i]); for (; i < slimit; i++) if (old[i]) freeInstruction(old[i]); GDKfree(old); GDKfree(series); #ifdef VLT_DEBUG fprintFunction(stderr,mb,0,LIST_MAL_ALL); #endif /* Defense line against incorrect plans */ /* all new/modified statements are already checked */ //chkTypes(cntxt->usermodule, mb, FALSE); //chkFlow(mb); //chkDeclarations(mb); /* keep all actions taken as a post block comment */ usec = GDKusec()- usec; snprintf(buf,256,"%-20s actions=%2d time=" LLFMT " usec","generator",actions, usec); newComment(mb,buf); if( actions >= 0) addtoMalBlkHistory(mb); return MAL_SUCCEED; }
str OPToltpImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { int i, limit, slimit, updates=0; InstrPtr p, q, lcks; int actions = 0; InstrPtr *old; lng usec = GDKusec(); OLTPlocks wlocks, rlocks; char buf[256]; str msg = MAL_SUCCEED; (void) pci; (void) cntxt; (void) stk; /* to fool compilers */ old= mb->stmt; limit= mb->stop; slimit = mb->ssize; // We use a fake collection of objects to speed up the checking later. OLTPclear(wlocks); OLTPclear(rlocks); for (i = 0; i < limit; i++) { p = old[i]; if( getModuleId(p) == sqlRef && getFunctionId(p) == bindRef) addLock(cntxt,rlocks, mb, p, p->retc + 1, p->retc + 2); else if( getModuleId(p) == sqlRef && getFunctionId(p) == bindidxRef) addLock(cntxt,rlocks, mb, p, p->retc + 1, p->retc + 2); else if( getModuleId(p) == sqlRef && getFunctionId(p) == appendRef ){ addLock(cntxt,wlocks, mb, p, p->retc + 1, p->retc + 2); updates++; } else if( getModuleId(p) == sqlRef && getFunctionId(p) == updateRef ){ addLock(cntxt,wlocks, mb, p, p->retc + 1, p->retc + 2); updates++; } else if( getModuleId(p) == sqlRef && getFunctionId(p) == deleteRef ){ addLock(cntxt,wlocks, mb, p, p->retc + 1, p->retc + 2); updates++; } else if( getModuleId(p) == sqlcatalogRef ){ addLock(cntxt,wlocks, mb, p, 0,0); updates++; } } if( updates == 0) return 0; // Get a free instruction, don't get it from mb lcks= newInstruction(0, oltpRef,lockRef); getArg(lcks,0)= newTmpVariable(mb, TYPE_void); for( i = 0; i< MAXOLTPLOCKS; i++) if( wlocks[i]) lcks = pushInt(mb, lcks, i); else if( rlocks[i]) lcks = pushInt(mb, lcks, -i); if( lcks->argc == 1 ){ freeInstruction(lcks); return MAL_SUCCEED; } // Now optimize the code if ( newMalBlkStmt(mb,mb->ssize + 6) < 0) { freeInstruction(lcks); return 0; } pushInstruction(mb,old[0]); pushInstruction(mb,lcks); for (i = 1; i < limit; i++) { p = old[i]; if( p->token == ENDsymbol){ // unlock all if there is an error q= newCatchStmt(mb,"MALexception"); q= newExitStmt(mb,"MALexception"); q= newCatchStmt(mb,"SQLexception"); q= newExitStmt(mb,"SQLexception"); q= copyInstruction(lcks); if( q == NULL){ for(; i<slimit; i++) if( old[i]) freeInstruction(old[i]); GDKfree(old); throw(MAL,"optimizer.oltp", SQLSTATE(HY001) MAL_MALLOC_FAIL); } setFunctionId(q, releaseRef); pushInstruction(mb,q); } pushInstruction(mb,p); } for(; i<slimit; i++) if( old[i]) freeInstruction(old[i]); GDKfree(old); /* Defense line against incorrect plans */ chkTypes(cntxt->usermodule, mb, FALSE); //chkFlow(mb); //chkDeclarations(mb); /* keep all actions taken as a post block comment */ usec = GDKusec()- usec; snprintf(buf,256,"%-20s actions=%2d time=" LLFMT " usec","oltp",actions, usec); newComment(mb,buf); if( actions >= 0) addtoMalBlkHistory(mb); return msg; }
str OPTjsonImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { int i, j, limit, slimit; int bu = 0, br = 0, bj = 0; str nme; InstrPtr p,q; int actions = 0; InstrPtr *old; char buf[256]; lng usec = GDKusec(); str msg = MAL_SUCCEED; (void) pci; (void) cntxt; (void) stk; /* to fool compilers */ old= mb->stmt; limit= mb->stop; slimit = mb->ssize; if ( newMalBlkStmt(mb,mb->stop) < 0) throw(MAL,"optimizer.json", SQLSTATE(HY001) MAL_MALLOC_FAIL); for (i = 0; i < limit; i++) { p = old[i]; if( getModuleId(p) == sqlRef && getFunctionId(p) == affectedRowsRef) { q = newInstruction(0, jsonRef, resultSetRef); q = pushArgument(mb, q, bu); q = pushArgument(mb, q, br); q = pushArgument(mb, q, bj); j = getArg(q,0); p= getInstrPtr(mb,0); setDestVar(q, newTmpVariable(mb, TYPE_str)); pushInstruction(mb,p); q = newInstruction(0, NULL, NULL); q->barrier = RETURNsymbol; getArg(q,0)= getArg(p,0); pushArgument(mb,q,j); pushInstruction(mb,q); actions++; continue; } if( getModuleId(p) == sqlRef && getFunctionId(p) == rsColumnRef) { nme = getVarConstant(mb,getArg(p,4)).val.sval; if (strcmp(nme,"uuid")==0) bu = getArg(p,7); if (strcmp(nme,"lng")==0) br = getArg(p,7); if (strcmp(nme,"json")==0) bj = getArg(p,7); freeInstruction(p); actions++; continue; } pushInstruction(mb,p); } for(; i<slimit; i++) if (old[i]) freeInstruction(old[i]); GDKfree(old); /* Defense line against incorrect plans */ if( actions > 0){ chkTypes(cntxt->usermodule, mb, FALSE); chkFlow(mb); chkDeclarations(mb); } /* keep all actions taken as a post block comment */ usec = GDKusec()- usec; snprintf(buf,256,"%-20s actions=%2d time=" LLFMT " usec","json",actions, usec); newComment(mb,buf); if( actions >= 0) addtoMalBlkHistory(mb); return msg; }