88485cfa7f13affa28ec5765fe9b2db90cce42b6 markd Tue Dec 8 21:02:15 2020 -0800 hgPcr working diff --git src/gfServer/gfServer.c src/gfServer/gfServer.c index 22c2a81..07b84de 100644 --- src/gfServer/gfServer.c +++ src/gfServer/gfServer.c @@ -1110,30 +1110,38 @@ static struct genoFindIndex *loadGfIndex(char *gfIdxFile, boolean isTrans) /* load index and set globals from it */ { struct genoFindIndex *gfIdx = genoFindIndexLoad(gfIdxFile, isTrans); struct genoFind *gf = isTrans ? gfIdx->transGf[0][0] : gfIdx->untransGf; minMatch = gf->minMatch; maxGap = gf->maxGap; tileSize = gf->tileSize; noSimpRepMask = gf->noSimpRepMask; allowOneMismatch = gf->allowOneMismatch; stepSize = gf->stepSize; return gfIdx; } +static void dynWarnHandler(char *format, va_list args) +/* log error warning and error message, along with printing */ +{ +logErrorVa(format, args); +vfprintf(stderr, format, args); +fputc('\n', stderr); +} + static void dynSessionInit(struct dynSession *dynSession, char *rootDir, char *genome, char *genomeDataDir, boolean isTrans) /* Initialize or reinitialize a dynSession object */ { // will free current content if initialized genoFindIndexFree(&dynSession->gfIdx); hashFree(&dynSession->perSeqMaxHash); time_t startTime = clock1000(); dynSession->isTrans = isTrans; safecpy(dynSession->genome, sizeof(dynSession->genome), genome); // construct path to sequence and index files char seqFileDir[PATH_LEN]; if (genomeDataDir[0] == '/') // abs or relative @@ -1152,91 +1160,73 @@ errAbort("gf index file for %s does not exist: %s", genome, gfIdxFile); dynSession->gfIdx = loadGfIndex(gfIdxFile, isTrans); char perSeqMaxFile[PATH_LEN]; safef(perSeqMaxFile, PATH_LEN, "%s/%s.perseqmax", seqFileDir, genome); if (fileExists(perSeqMaxFile)) { /* only the basename of the file is saved in the index */ char *slash = strrchr(seqFile, '/'); char *seqFiles[1] = {(slash != NULL) ? slash + 1 : seqFile}; dynSession->perSeqMaxHash = buildPerSeqMax(1, seqFiles, perSeqMaxFile); } logInfo("dynserver: index loading completed in %4.3f seconds", 0.001 * (clock1000() - startTime)); } -static char *dynReadCommand(char* rootDir, char *buf, int bufSize) +static char *dynReadCommand(char* rootDir) /* read command and log, NULL if no more */ { -int readSize = read(STDIN_FILENO, buf, bufSize-1); +char buf[PATH_LEN]; +int readSize = read(STDIN_FILENO, buf, sizeof(buf)-1); if (readSize < 0) errAbort("EOF from client"); if (readSize == 0) return NULL; buf[readSize] = '\0'; -logDebug("query received: %s", buf); if (!startsWith(gfSignature(), buf)) errAbort("query does not start with signature, got '%s'", buf); -return buf + strlen(gfSignature()); +char *cmd = cloneString(buf + strlen(gfSignature())); +logInfo("dynserver: %s", cmd); +return cmd; } -static boolean dynNextCommand(char* rootDir, struct dynSession *dynSession, char **commandRet, int *qsizeRet) -/* Read query request from stdin and (re)initialize session to match paramters. - * Format for query commands: - * signature+command genome genomeDataDir qsize - * Formats for info command: - * signature+command genome genomeDataDir +static const int DYN_CMD_MAX_ARGS = 8; // more than needed to check for junk + +static int dynNextCommand(char* rootDir, struct dynSession *dynSession, char **args) +/* Read query request from stdin and (re)initialize session to match + * parameters. Return number of arguments or zero on EOF + * + * Commands are in the format: + * signature+command genome genomeDataDir [arg ...] */ { -char buf[PATH_LEN]; -char *cmdStr = dynReadCommand(rootDir, buf, sizeof(buf)); +char *cmdStr = dynReadCommand(rootDir); if (cmdStr == NULL) - return FALSE; + return 0; -char *words[6]; -int numWords = chopByWhite(cmdStr, words, ArraySize(words)); -if (numWords == 0) +int numArgs = chopByWhite(cmdStr, args, DYN_CMD_MAX_ARGS); +if (numArgs == 0) errAbort("empty command"); -char *command = words[0]; -*commandRet = cloneString(command); -boolean isTrans = sameString("protQuery", command) || sameString("transQuery", command) - || sameString("transInfo", command); - -char genome[256], genomeDataDir[PATH_LEN]; -if (sameString("query", command) || sameString("protQuery", command) - || sameString("transQuery", command)) - { - if (numWords != 4) - errAbort("expected 4 words in query command, got %d", numWords); - *qsizeRet = atoi(words[3]); - } -else if (sameString("untransInfo", command) || sameString("transInfo", command)) - { - if (numWords != 3) - errAbort("expected 3 words in info command, got %d", numWords); - *qsizeRet = 0; - } -else - errAbort("invalid command '%s'", command); - -safecpy(genome, sizeof(genome), words[1]); -safecpy(genomeDataDir, sizeof(genomeDataDir), words[2]); +if (numArgs < 3) + errAbort("expected at least 3 arguments for a dynamic server command"); +boolean isTrans = sameString("protQuery", args[0]) || sameString("transQuery", args[0]) + || sameString("transInfo", args[0]); // initialize session if new or changed -if ((dynSession->isTrans != isTrans) || (!sameString(dynSession->genome, genome))) - dynSessionInit(dynSession, rootDir, genome, genomeDataDir, isTrans); -return TRUE; +if ((dynSession->isTrans != isTrans) || (!sameString(dynSession->genome, args[1]))) + dynSessionInit(dynSession, rootDir, args[1], args[2], isTrans); +return numArgs; } 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) errAbort("read of %d bytes of query sequence failed", qSize); seq->dna[qSize] = '\0'; if (queryIsProt) { @@ -1246,91 +1236,134 @@ 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 dynamicServerQuery(char *command, int qSize, struct genoFindIndex *gfIdx, struct hash *perSeqMaxHash) -/* handle search queries */ +static void dynamicServerQuery(struct dynSession *dynSession, int numArgs, char **args) +/* handle search queries + * + * signature+command genome genomeDataDir qsize + */ { -mustWriteFd(STDOUT_FILENO, "Y", 1); +struct genoFindIndex *gfIdx = dynSession->gfIdx; +if (numArgs != 4) + errAbort("expected 4 words in %s command, got %d", args[0], numArgs); +int qSize = atoi(args[3]); -boolean queryIsProt = sameString(command, "protQuery"); +boolean queryIsProt = sameString(args[0], "protQuery"); +mustWriteFd(STDOUT_FILENO, "Y", 1); struct dnaSeq* seq = dynReadQuerySeq(qSize, gfIdx->isTrans, queryIsProt); if (gfIdx->isTrans) { if (queryIsProt) transQuery(gfIdx->transGf, seq, STDOUT_FILENO); else transTransQuery(gfIdx->transGf, seq, STDOUT_FILENO); } else { - dnaQuery(gfIdx->untransGf, seq, STDOUT_FILENO, perSeqMaxHash); + dnaQuery(gfIdx->untransGf, seq, STDOUT_FILENO, dynSession->perSeqMaxHash); } netSendString(STDOUT_FILENO, "end"); } -static void dynamicServerInfo(char *command, struct genoFindIndex *gfIdx) -/* handle one of the info commands */ +static void dynamicServerInfo(struct dynSession *dynSession, int numArgs, char **args) +/* handle one of the info commands + * + * signature+command genome genomeDataDir + */ { +struct genoFindIndex *gfIdx = dynSession->gfIdx; +if (numArgs != 3) + errAbort("expected 3 words in %s command, got %d", args[0], numArgs); + 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, "end"); } +static void dynamicServerPcr(struct dynSession *dynSession, int numArgs, char **args) +/* Execute a PCR query + * + * signature+command genome genomeDataDir forward reverse maxDistance + */ +{ +struct genoFindIndex *gfIdx = dynSession->gfIdx; +if (numArgs != 6) + errAbort("expected 6 words in %s command, got %d", args[0], numArgs); +char *fPrimer = args[3]; +char *rPrimer = args[4]; +int maxDistance = atoi(args[5]); +if (badPcrPrimerSeq(fPrimer) || badPcrPrimerSeq(rPrimer)) + errAbort("Can only handle ACGT in primer sequences."); +pcrQuery(gfIdx->untransGf, fPrimer, rPrimer, maxDistance, STDOUT_FILENO); +} + static bool dynamicServerCommand(char* rootDir, struct dynSession* dynSession) /* Execute one command from stdin, (re)initializing session as needed */ { time_t startTime = clock1000(); -char *command; -int qSize; -if (!dynNextCommand(rootDir, dynSession, &command, &qSize)) +char *args[DYN_CMD_MAX_ARGS]; +int numArgs = dynNextCommand(rootDir, dynSession, args); +if (numArgs == 0) return FALSE; -logInfo("dynserver: %s %s %s [%s] qsize=%d ", command, dynSession->genome, dynSession->gfIdxFile, - (dynSession->isTrans ? "trans" : "untrans"), qSize); -if (endsWith(command, "Info")) - dynamicServerInfo(command, dynSession->gfIdx); +if (sameString("query", args[0]) || sameString("protQuery", args[0]) + || sameString("transQuery", args[0])) + { + dynamicServerQuery(dynSession, numArgs, args); + } +else if (sameString("untransInfo", args[0]) || sameString("transInfo", args[0])) + { + dynamicServerInfo(dynSession, numArgs, args); + } +else if (sameString("pcr", args[0])) + { + dynamicServerPcr(dynSession, numArgs, args); + } else - dynamicServerQuery(command, qSize, dynSession->gfIdx, dynSession->perSeqMaxHash); -logInfo("dynserver: %s completed in %4.3f seconds", command, 0.001 * (clock1000() - startTime)); + errAbort("invalid command '%s'", args[0]); + +logInfo("dynserver: %s completed in %4.3f seconds", args[0], 0.001 * (clock1000() - startTime)); +freeMem(args[0]); return TRUE; } static void dynamicServer(char* rootDir) /* dynamic server for inetd. Read query from stdin, open index, query, respond, exit. * only one query at a time */ { +pushWarnHandler(dynWarnHandler); logDebug("dynamicServer connect"); // make sure errors are logged pushWarnHandler(dynWarnErrorVa); struct dynSession dynSession; ZeroVar(&dynSession); while (dynamicServerCommand(rootDir, &dynSession)) continue; logDebug("dynamicServer disconnect"); } int main(int argc, char *argv[]) /* Process command line. */ {