static int error(stream *out, char *str) { char *p; if (!out) out = GDKerr; if (str == NULL) return 0; if (mnstr_errnr(out)) return -1; while ((p = strchr(str, '\n')) != NULL) { p++; /* include newline */ if (*str !='!' && mnstr_write(out, "!", 1, 1) != 1) return -1; if (mnstr_write(out, str, p - str, 1) != 1) return -1; str = p; } if (str &&*str) { if (*str !='!' && mnstr_write(out, "!", 1, 1) != 1) return -1; if (mnstr_write(out, str, strlen(str), 1) != 1 || mnstr_write(out, "\n", 1, 1) != 1) return -1; } return 0; }
int ATOMprint(int t, const void *p, stream *s) { ssize_t (*tostr) (char **, size_t *, const void *, bool); ssize_t res; if (p && t >= 0 && t < GDKatomcnt && (tostr = BATatoms[t].atomToStr)) { size_t sz; if (t != TYPE_bat && t < TYPE_str) { char buf[dblStrlen], *addr = buf; /* use memory from stack */ sz = dblStrlen; res = (*tostr) (&addr, &sz, p, true); if (res > 0) res = mnstr_write(s, buf, (size_t) res, 1); } else { str buf = NULL; sz = 0; res = (*tostr) (&buf, &sz, p, true); if (res > 0) res = mnstr_write(s, buf, (size_t) res, 1); GDKfree(buf); } } else { res = mnstr_write(s, "nil", 1, 3); } if (res < 0) GDKsyserror("ATOMprint: write failure\n"); return (int) res; }
static inline int scanner_read_more(struct scanner *lc, int n) { bstream *b = lc->rs; int more = 0; while (b->len < b->pos + lc->yycur + n) { if (lc->mode == LINE_1 || !lc->started) return EOF; /* query is not finished ask for more */ if (b->eof || !isa_block_stream(b->s)) { if (mnstr_write(lc->ws, PROMPT2, sizeof(PROMPT2) - 1, 1) == 1) mnstr_flush(lc->ws); b->eof = 0; more = 1; } /* we need more query text */ if (bstream_next(b) < 0 || /* we asked for more data but didn't get any */ (more && b->eof && b->len < b->pos + lc->yycur + n)) return EOF; } return 1; }
int THRprintf(stream *s, const char *format, ...) { str bf = THRprintbuf, p = 0; size_t bfsz = BUFSIZ; int n = 0; ptrdiff_t m = 0; char c; va_list ap; if (!s) return -1; MT_lock_set(&MT_system_lock, "THRprintf"); if (*format != '!') { c = '#'; if (*format == '#') format++; } else { c = '!'; format++; } do { p = bf; *p++ = c; if (GDKdebug & THRDMASK) { sprintf(p, "%02d ", THRgettid()); while (*p) p++; } m = p - bf; va_start(ap, format); n = vsnprintf(p, bfsz-m, format, ap); va_end(ap); if (n < 0) goto cleanup; if ((size_t) n < bfsz - m) break; /* normal loop exit, usually 1st iteration */ bfsz = m + n + 1; /* precisely what is needed */ if (bf != THRprintbuf) free(bf); bf = (str) malloc(bfsz); assert(bf != NULL); } while (1); p += n; n = 0; if (mnstr_write(s, bf, p - bf, 1) != 1) n = -1; cleanup: if (bf != THRprintbuf) free(bf); MT_lock_unset(&MT_system_lock, "THRprintf"); return n; }
str mnstr_write_stringwrap(int *ret, Stream *S, str *data) { stream *s = *(stream **)S; (void)ret; if (mnstr_write(s, *data, 1, strlen(*data)) < 0) throw(IO, "streams.writeStr", "failed to write string"); return MAL_SUCCEED; }
int handle_error(mvc *m, stream *out, int pstatus) { int go = 1; char *buf = GDKerrbuf; /* transaction already broken */ if (m->type != Q_TRANS && pstatus < 0) { if (mnstr_write(out, TRANS_ABORTED, sizeof(TRANS_ABORTED) - 1, 1) != 1) { go = !go; } } else { if (error(out, m->errstr) < 0 || (buf && buf[0] && error(out, buf) < 0)) { go = !go; } } /* reset error buffers */ m->errstr[0] = 0; if (buf) buf[0] = 0; return go; }
int sqllex(YYSTYPE * yylval, void *parm) { int token; mvc *c = (mvc *) parm; struct scanner *lc = &c->scanner; int pos; /* store position for when view's query ends */ pos = (int)lc->rs->pos + lc->yycur; token = sql_get_next_token(yylval, parm); if (token == NOT) { int next = sqllex(yylval, parm); if (next == NOT) { return sqllex(yylval, parm); } else if (next == BETWEEN) { token = NOT_BETWEEN; } else if (next == sqlIN) { token = NOT_IN; } else if (next == LIKE) { token = NOT_LIKE; } else if (next == ILIKE) { token = NOT_ILIKE; } else { lc->yynext = next; } } else if (token == UNION) { int next = sqllex(yylval, parm); if (next == JOIN) { token = UNIONJOIN; } else { lc->yynext = next; } } else if (token == NO) { int next = sqllex(yylval, parm); switch (next) { case MAXVALUE: token = NOMAXVALUE; break; case MINVALUE: token = NOMINVALUE; break; case CYCLE: token = NOCYCLE; break; default: lc->yynext = next; break; } } else if (token == SCOLON) { /* ignore semi-colon(s) following a semi-colon */ if (lc->yylast == SCOLON) { int prev = lc->yycur; while ((token = sql_get_next_token(yylval, parm)) == SCOLON) prev = lc->yycur; /* skip the skipped stuff also in the buffer */ lc->rs->pos += prev; lc->yycur -= prev; assert(lc->yycur >= 0); } } if (lc->log) mnstr_write(lc->log, lc->rs->buf+pos, lc->rs->pos + lc->yycur - pos, 1); /* Don't include literals in the calculation of the key */ if (token != STRING && token != sqlINT && token != OIDNUM && token != INTNUM && token != APPROXNUM && token != sqlNULL) lc->key ^= token; lc->started += (token != EOF); return token; }
/* * Input to be processed is collected in a Client specific buffer. It * is filled by reading information from a stream, a terminal, or by * scheduling strings constructed internally. The latter involves * removing any escape character needed to manipulate the string within * the kernel. The buffer space is automatically expanded to * accommodate new information and the read pointers are adjusted. * * The input is read from a (blocked) stream and stored in the client * record input buffer. The storage area grows automatically upon need. * The origin of the input stream depends on the connectivity mode. * * Each operation received from a front-end consists of at least one * line. To simplify misaligned communication with front-ends, we use * different prompts structures. * * The default action is to read information from an ascii-stream one * line at a time. This is the preferred mode for reading from terminal. * * The next statement block is to be read. Send a prompt to warn the * front-end to issue the request. */ int MCreadClient(Client c) { bstream *in = c->fdin; #ifdef MAL_CLIENT_DEBUG printf("# streamClient %d %d\n", c->idx, isa_block_stream(in->s)); #endif while (in->pos < in->len && (isspace((int) (in->buf[in->pos])) || in->buf[in->pos] == ';' || !in->buf[in->pos])) in->pos++; if (in->pos >= in->len || in->mode) { ssize_t rd, sum = 0; if (in->eof || !isa_block_stream(c->fdout)) { if (!isa_block_stream(c->fdout) && c->promptlength > 0) mnstr_write(c->fdout, c->prompt, c->promptlength, 1); mnstr_flush(c->fdout); in->eof = 0; } while ((rd = bstream_next(in)) > 0 && !in->eof) { sum += rd; if (!in->mode) /* read one line at a time in line mode */ break; } if (in->mode) { /* find last new line */ char *p = in->buf + in->len - 1; while (p > in->buf && *p != '\n') { *(p + 1) = *p; p--; } if (p > in->buf) *(p + 1) = 0; if (p != in->buf + in->len - 1) in->len++; } if (sum == 0 && in->eof && isa_block_stream(in->s)) { /* we hadn't seen the EOF before, so just try again (this time with prompt) */ #ifdef MAL_CLIENT_DEBUG printf("# retry stream reading %d %d\n", c->idx, in->eof); #endif return MCreadClient(c); } #ifdef MAL_CLIENT_DEBUG printf("# simple stream received %d sum " SZFMT "\n", c->idx, sum); #endif } if (in->pos >= in->len) { /* end of stream reached */ #ifdef MAL_CLIENT_DEBUG printf("# end of stream received %d %d\n", c->idx, c->bak == 0); #endif if (c->bak) { MCpopClientInput(c); if (c->fdin == NULL) return 0; return MCreadClient(c); } return 0; } if (*CURRENT(c) == '?') { showHelp(c->nspace, CURRENT(c) + 1, c->fdout); in->pos = in->len; return MCreadClient(c); } #ifdef MAL_CLIENT_DEBUG printf("# finished stream read %d %d\n", (int) in->pos, (int) in->len); printf("#%s\n", in->buf); #endif return 1; }
/* #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; }
static void produceDataStream(Sensor se) { char buf[MYBUFSIZ + 1], *tuple, *c, *d; FILE *fd; int i, snr; int multiply=1000, usec = 0; time_t lasttime = 0, tm = 0; struct tm stm; /* read a events of messages from a file or standard input. It is processed multiple times. The header is the delay imposed */ snr = 0; do { if ( datafile == 0){ fd = stdin; } else { fd = fopen(datafile, "r"); if (fd == NULL) { mnstr_printf(SEout, "Could not open file '%s'\n", datafile); close_stream(se->toServer); se->toServer = NULL; return; } } /* read the event requests and sent when the becomes */ while (fgets(buf, MYBUFSIZ, fd) != 0) { int newdelay = delay; tuple = buf; if ( timecolumn >= 0 ) { /* calculate the difference with previous event */ /* use a simplistic csv file format */ c= buf; for ( i = timecolumn; i> 0; i--){ if ( (d=strchr(c,(int)','))){ c= d+1; } } /* convert time to epoch in seconds*/ memset(&stm, 0, sizeof(struct tm)); if ( c ){ c = strptime(c,"%Y-%m-%d %H:%M:%S", &stm); tm = mktime(&stm); if ( *c == '.') { /* microseconds */ usec = atoi(c+1); if ( usec) multiply = 1; } } /* calculate time differential in seconds */ if ( lasttime ) newdelay = (int) difftime(tm,lasttime) * multiply + usec; lasttime = tm; if (trace && newdelay) mnstr_printf(SEout, "delayed %d\n", newdelay); MT_sleep_ms(newdelay); } else if (delay > 0) { /* wait */ MT_sleep_ms(delay); } if (delay < 0) { mnstr_printf(SEout, "%s", tuple); mnstr_printf(SEout, "send it?"); getchar(); } if (trace) mnstr_printf(SEout, "%s", tuple); if ((mnstr_write(se->toServer, tuple, 1, strlen(tuple))) == -1 && (errno == EPIPE)) { mnstr_printf(SEout, "errno:%s\n", strerror(errno)); return; } } fclose(fd); snr++; } while (snr != events); }
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; }
/* * Input to be processed is collected in a Client specific buffer. It * is filled by reading information from a stream, a terminal, or by * scheduling strings constructed internally. The latter involves * removing any escape character needed to manipulate the string within * the kernel. The buffer space is automatically expanded to * accommodate new information and the read pointers are adjusted. * * The input is read from a (blocked) stream and stored in the client * record input buffer. The storage area grows automatically upon need. * The origin of the input stream depends on the connectivity mode. * * Each operation received from a front-end consists of at least one * line. To simplify misaligned communication with front-ends, we use * different prompts structures. * * The default action is to read information from an ascii-stream one * line at a time. This is the preferred mode for reading from terminal. * * The next statement block is to be read. Send a prompt to warn the * front-end to issue the request. */ int MCreadClient(Client c) { bstream *in = c->fdin; #ifdef MAL_CLIENT_DEBUG fprintf(stderr,"# streamClient %d %d\n", c->idx, isa_block_stream(in->s)); #endif while (in->pos < in->len && (isspace((unsigned char) (in->buf[in->pos])) || in->buf[in->pos] == ';' || !in->buf[in->pos])) in->pos++; if (in->pos >= in->len || in->mode) { ssize_t rd, sum = 0; if (in->eof || !isa_block_stream(c->fdout)) { if (!isa_block_stream(c->fdout) && c->promptlength > 0) mnstr_write(c->fdout, c->prompt, c->promptlength, 1); mnstr_flush(c->fdout); in->eof = false; } while ((rd = bstream_next(in)) > 0 && !in->eof) { sum += rd; if (!in->mode) /* read one line at a time in line mode */ break; } if (in->mode) { /* find last new line */ char *p = in->buf + in->len - 1; while (p > in->buf && *p != '\n') { *(p + 1) = *p; p--; } if (p > in->buf) *(p + 1) = 0; if (p != in->buf + in->len - 1) in->len++; } #ifdef MAL_CLIENT_DEBUG fprintf(stderr, "# simple stream received %d sum %zu\n", c->idx, sum); #endif } if (in->pos >= in->len) { /* end of stream reached */ #ifdef MAL_CLIENT_DEBUG fprintf(stderr,"# end of stream received %d %d\n", c->idx, c->bak == 0); #endif if (c->bak) { MCpopClientInput(c); if (c->fdin == NULL) return 0; return MCreadClient(c); } return 0; } #ifdef MAL_CLIENT_DEBUG fprintf(stderr,"# finished stream read %d %d\n", (int) in->pos, (int) in->len); printf("#%s\n", in->buf); #endif return 1; }