c99b62d7865a828f8f41c6e82dd36cbd2dd26780 markd Wed Jul 1 21:45:43 2020 -0700 hgBlat mostly works diff --git src/gfServer/gfServer.c src/gfServer/gfServer.c index 032ed0e..d62be7d 100644 --- src/gfServer/gfServer.c +++ src/gfServer/gfServer.c @@ -1008,167 +1008,179 @@ { printf("%s\n", netRecieveString(sd, buf)); } } close(sd); } static void buildIndex(char *gfxFile, int fileCount, char *seqFiles[]) /* build pre-computed index for seqFiles and write to gfxFile */ { struct genoFindIndex *gfIdx = genoFindIndexBuild(fileCount, seqFiles, minMatch, maxGap, tileSize, repMatch, doTrans, NULL, allowOneMismatch, doMask, stepSize, noSimpRepMask); genoFindIndexWrite(gfIdx, gfxFile); } - -static void dynErrorVa(char* msg, va_list args) -/* send back an error response and exit */ +static void dynWarnErrorVa(char* msg, va_list args) +/* warnHandler to log and send back an error response */ { char buf[4096]; int msgLen = vsnprintf(buf, sizeof(buf) - 1, msg, args); buf[msgLen] = '\0'; -logDebug("Error: %s", buf); -printf("Error: %s\n", msg); -exit(1); -} - -static void dynError(char* msg, ...) -/* send back an error response and exit */ -{ -va_list args; -va_start(args, msg); -dynErrorVa(msg, args); -va_end(args); -exit(1); +logError("%s", buf); +printf("Error: %s\n", buf); } static void dynReadBytes(char *buf, int bufSize) /* read pending bytes */ { int readSize = read(STDIN_FILENO, buf, bufSize-1); if (readSize < 0) - dynError("EOF from client"); + errAbort("EOF from client"); buf[readSize] = '\0'; } static void dynReadQuery(char **commandRet, int *qsizeRet, char **genomeNameRet) /* read query request from stdin, same as server expect includes database * Format is: * signature command qsize genome */ { char buf[256]; dynReadBytes(buf, sizeof(buf)); logDebug("query: %s", buf); if (!startsWith(gfSignature(), buf)) - dynError("query does not start with signature, got '%s'", buf); + errAbort("query does not start with signature, got '%s'", buf); static int nwords = 3; char *words[nwords]; int numWords = chopByWhite(buf, words, nwords); if (numWords != nwords) - dynError("expected %d words in request, got %d", nwords, numWords); + errAbort("expected %d words in request, got %d", nwords, numWords); char *command = buf + strlen(gfSignature()); if (!(sameString("query", command) || sameString("protQuery", command) || sameString("transQuery", command))) - dynError("invalid command '%s'", command); + errAbort("invalid command '%s'", command); *commandRet = cloneString(command); *qsizeRet = atoi(words[1]); *genomeNameRet = cloneString(words[2]); } static struct dnaSeq* dynReadQuerySeq(int qSize, boolean isTrans, boolean queryIsProt) /* read the DNA sequence from the query, filtering junk */ { struct dnaSeq *seq; AllocVar(seq); seq->size = qSize; seq->dna = needLargeMem(qSize+1); if (gfReadMulti(STDIN_FILENO, seq->dna, qSize) != qSize) - dynError("read of %d bytes of query sequence failed", qSize); + errAbort("read of %d bytes of query sequence failed", qSize); if (queryIsProt) { seq->size = aaFilteredSize(seq->dna); aaFilter(seq->dna, seq->dna); } else { seq->size = dnaFilteredSize(seq->dna); dnaFilter(seq->dna, seq->dna); } int maxSize = (isTrans ? maxAaSize : maxNtSize); if (seq->size > maxSize) { seq->size = maxSize; seq->dna[maxSize] = 0; } return seq; } static void dynGetDataFiles(char *rootDir, char* genomeName, boolean isTrans, char seqFile[PATH_LEN], char gfIdxFile[PATH_LEN]) /* get paths for sequence files to handle requests and validate they exist */ { safef(seqFile, PATH_LEN, "%s/%s/%s.2bit", rootDir, genomeName, genomeName); if (!fileExists(seqFile)) - dynError("sequence file for %s does not exist: %s", genomeName, seqFile); + errAbort("sequence file for %s does not exist: %s", genomeName, seqFile); safef(gfIdxFile, PATH_LEN, "%s/%s/%s.%s.gfidx", rootDir, genomeName, genomeName, isTrans ? "trans" : "untrans"); if (!fileExists(gfIdxFile)) - dynError("gf index file for %s does not exist: %s", genomeName, gfIdxFile); + errAbort("gf index file for %s does not exist: %s", genomeName, gfIdxFile); } +static void dynWriteTrailer(struct genoFindIndex *gfIdx) +/* write trailer information, which is a subset of what status would return. + * This avoids the need to reconnect and reload index. + */ +{ +char buf[256]; +struct genoFind *gf = gfIdx->isTrans ? gfIdx->transGf[0][0] : gfIdx->untransGf; +sprintf(buf, "version %s", gfVersion); +netSendString(STDOUT_FILENO, buf); +sprintf(buf, "type %s", (gfIdx->isTrans ? "translated" : "nucleotide")); +netSendString(STDOUT_FILENO, buf); +sprintf(buf, "tileSize %d", gf->tileSize); +netSendString(STDOUT_FILENO, buf); +sprintf(buf, "stepSize %d", gf->stepSize); +netSendString(STDOUT_FILENO, buf); +sprintf(buf, "minMatch %d", gf->minMatch); +netSendString(STDOUT_FILENO, buf); +netSendString(STDOUT_FILENO, "trailerEnd"); +} void dynamicServer(char* rootDir) /* dynamic server for inetd. Read query from stdin, open index, query, respond, exit. * only one query at a time */ { +// make sure error is logged, protocol doesn't allow reporting error to user +pushWarnHandler(dynWarnErrorVa); + char *command, *genomeName; int qSize; dynReadQuery(&command, &qSize, &genomeName); boolean isTrans = sameString("protQuery", command) || sameString("transQuery", command); boolean queryIsProt = sameString(command, "protQuery"); char seqFile[PATH_LEN]; char *seqFiles[1] = {seqFile}; // functions expect list of files char gfIdxFile[PATH_LEN]; dynGetDataFiles(rootDir, genomeName, isTrans, seqFiles[0], gfIdxFile); struct genoFindIndex *gfIdx = genoFindIndexLoad(gfIdxFile, isTrans); mustWriteFd(STDOUT_FILENO, "Y", 1); struct dnaSeq* seq = dynReadQuerySeq(qSize, isTrans, queryIsProt); if (isTrans) { if (queryIsProt) transQuery(gfIdx->transGf, seq, STDOUT_FILENO); else transTransQuery(gfIdx->transGf, seq, STDOUT_FILENO); } else { struct hash *perSeqMaxHash = maybePerSeqMax(1, seqFiles); dnaQuery(gfIdx->untransGf, seq, STDOUT_FILENO, perSeqMaxHash); } -logDebug("query done"); netSendString(STDOUT_FILENO, "end"); +dynWriteTrailer(gfIdx); +logDebug("query done"); } + int main(int argc, char *argv[]) /* Process command line. */ { char *command; gfCatchPipes(); dnaUtilOpen(); optionInit(&argc, argv, optionSpecs); command = argv[1]; if (optionExists("trans")) { doTrans = TRUE; tileSize = 4; minMatch = 3; maxGap = 0;