cec3eb53a47d2c04927c2e2e5303985dc5fefb45 markd Mon Apr 12 23:21:46 2021 -0700 added support to status command for dynamic servers diff --git src/gfServer/gfServer.c src/gfServer/gfServer.c index a245f2e..5e20e0c 100644 --- src/gfServer/gfServer.c +++ src/gfServer/gfServer.c @@ -36,81 +36,88 @@ {"maxGap", OPTION_INT}, {"maxNtSize", OPTION_INT}, {"maxTransHits", OPTION_INT}, {"minMatch", OPTION_INT}, {"repMatch", OPTION_INT}, {"seqLog", OPTION_BOOLEAN}, {"ipLog", OPTION_BOOLEAN}, {"debugLog", OPTION_BOOLEAN}, {"stepSize", OPTION_INT}, {"tileSize", OPTION_INT}, {"trans", OPTION_BOOLEAN}, {"syslog", OPTION_BOOLEAN}, {"perSeqMax", OPTION_STRING}, {"noSimpRepMask", OPTION_BOOLEAN}, {"indexFile", OPTION_STRING}, + {"genome", OPTION_STRING}, + {"genomeDataDir", OPTION_STRING}, {"timeout", OPTION_INT}, {NULL, 0} }; int maxNtSize = 40000; int maxAaSize = 8000; int minMatch = gfMinMatch; /* Can be overridden from command line. */ int tileSize = gfTileSize; /* Can be overridden from command line. */ int stepSize = 0; /* Can be overridden from command line. */ boolean doTrans = FALSE; /* Do translation? */ boolean allowOneMismatch = FALSE; boolean noSimpRepMask = FALSE; int repMatch = 1024; /* Can be overridden from command line. */ int maxDnaHits = 100; /* Can be overridden from command line. */ int maxTransHits = 200; /* Can be overridden from command line. */ int maxGap = gfMaxGap; boolean seqLog = FALSE; boolean ipLog = FALSE; boolean doMask = FALSE; boolean canStop = FALSE; char *indexFile = NULL; +char *genome = NULL; +char *genomeDataDir = NULL; int timeout = 90; // default timeout in seconds void usage() /* Explain usage and exit. */ { errAbort( "gfServer v %s - Make a server to quickly find where DNA occurs in genome\n" " To set up a server:\n" " gfServer start host port file(s)\n" " where the files are .2bit or .nib format files specified relative to the current directory\n" " To remove a server:\n" " gfServer stop host port\n" " To query a server with DNA sequence:\n" " gfServer query host port probe.fa\n" " To query a server with protein sequence:\n" " gfServer protQuery host port probe.fa\n" " To query a server with translated DNA sequence:\n" " gfServer transQuery host port probe.fa\n" " To query server with PCR primers:\n" " gfServer pcr host port fPrimer rPrimer maxDistance\n" " To process one probe fa file against a .2bit format genome (not starting server):\n" " gfServer direct probe.fa file(s).2bit\n" " To test PCR without starting server:\n" " gfServer pcrDirect fPrimer rPrimer file(s).2bit\n" - " To figure out usage level:\n" + " To figure out if server is alive, on static instances get usage statics as well:\n" " gfServer status host port\n" + " For dynamic gfServer instances, specify -genome and optionally the -genomeDataDir\n" + " to get information on an untranslated genome index. Include -trans to get about information\n" + " about a translated genome index\n" " To get input file list:\n" " gfServer files host port\n" " To generate a precomputed index:\n" " gfServer index gfidx file(s)\n" " where the files are .2bit or .nib format files. Separate indexes are\n" " be created for untranslated and translated queries. These can be used\n" " with a persistent server as with 'start -indexFile or a dynamic server.\n" " They must follow the naming convention for for dynamic servers.\n" " To run a dynamic server (usually called by xinetd):\n" " gfServer dynserver rootdir\n" " Data files for genomes are found relative to the root directory.\n" " Queries are made using the prefix of the file path relative to the root\n" " directory. The files $genome.2bit, $genome.untrans.gfidx, and\n" " $genome.trans.gfidx are required. Typically the structure will be in\n" " the form:\n" @@ -776,34 +783,37 @@ if (!startsWith(gfSignature(), buf)) { ++noSigCount; close(connectionHandle); continue; } line = buf + strlen(gfSignature()); command = nextWord(&line); if (sameString("quit", command)) { if (canStop) break; else logError("Ignoring quit message"); } - else if (sameString("status", command)) + else if (sameString("status", command) || sameString("transInfo", command) + || sameString("untransInfo", command)) { sprintf(buf, "version %s", gfVersion); errSendString(connectionHandle, buf); + errSendString(connectionHandle, "serverType static"); + errSendString(connectionHandle, buf); sprintf(buf, "type %s", (doTrans ? "translated" : "nucleotide")); errSendString(connectionHandle, buf); sprintf(buf, "host %s", hostName); errSendString(connectionHandle, buf); sprintf(buf, "port %s", portName); errSendString(connectionHandle, buf); sprintf(buf, "tileSize %d", tileSize); errSendString(connectionHandle, buf); sprintf(buf, "stepSize %d", stepSize); errSendString(connectionHandle, buf); sprintf(buf, "minMatch %d", minMatch); errSendString(connectionHandle, buf); sprintf(buf, "pcr requests %ld", pcrCount); errSendString(connectionHandle, buf); sprintf(buf, "blat requests %ld", blatCount); @@ -965,31 +975,36 @@ sprintf(buf, "%squit", gfSignature()); mustWriteFd(sd, buf, strlen(buf)); close(sd); printf("sent stop message to server\n"); } int statusServer(char *hostName, char *portName) /* Send status message to server arnd report result. */ { char buf[256]; int sd = 0; int ret = 0; /* Put together command. */ sd = netMustConnectTo(hostName, portName); +if (genome == NULL) sprintf(buf, "%sstatus", gfSignature()); +else + sprintf(buf, "%s%s %s %s", gfSignature(), (doTrans ? "transInfo" : "untransInfo"), + genome, genomeDataDir); + mustWriteFd(sd, buf, strlen(buf)); for (;;) { if (netGetString(sd, buf) == NULL) { warn("Error reading status information from %s:%s",hostName,portName); ret = -1; break; } if (sameString(buf, "end")) break; else printf("%s\n", buf); } @@ -1247,39 +1262,43 @@ if (!startsWith(gfSignature(), buf)) errAbort("query does not start with signature, got '%s'", buf); char *cmd = cloneString(buf + strlen(gfSignature())); logInfo("dynserver: %s", cmd); return cmd; } 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 ...] + * signature+status */ { char *cmdStr = dynReadCommand(rootDir); if (cmdStr == NULL) return 0; int numArgs = chopByWhite(cmdStr, args, DYN_CMD_MAX_ARGS); if (numArgs == 0) errAbort("empty command"); +if (sameWord(args[0], "status")) + return numArgs; // special case; does not use an index. + 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, 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; @@ -1327,84 +1346,106 @@ 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, dynSession->perSeqMaxHash); } netSendString(STDOUT_FILENO, "end"); } static void dynamicServerInfo(struct dynSession *dynSession, int numArgs, char **args) -/* handle one of the info commands +/* handle one of the info or status commands commands * - * signature+command genome genomeDataDir + * signature+untransInfo genome genomeDataDir + * signature+transInfo 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); +netSendString(STDOUT_FILENO, "serverType dynamic"); 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 dynamicServerStatus(int numArgs, char **args) +/* return enough information to indicate server is working without opening + * a genome index. + * + * signature+status + */ +{ +if (numArgs != 1) + errAbort("expected 1 word in %s command, got %d", args[0], numArgs); +char buf[256]; +sprintf(buf, "version %s", gfVersion); +netSendString(STDOUT_FILENO, buf); +netSendString(STDOUT_FILENO, "serverType dynamic"); +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 *args[DYN_CMD_MAX_ARGS]; int numArgs = dynNextCommand(rootDir, dynSession, args); if (numArgs == 0) return FALSE; if (sameString("query", args[0]) || sameString("protQuery", args[0]) || sameString("transQuery", args[0])) { dynamicServerQuery(dynSession, numArgs, args); } +else if (sameString("status", args[0])) + { + dynamicServerStatus(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 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; } @@ -1448,30 +1489,36 @@ if (optionExists("repMatch")) repMatch = optionInt("repMatch", 0); else repMatch = gfDefaultRepMatch(tileSize, stepSize, doTrans); minMatch = optionInt("minMatch", minMatch); maxDnaHits = optionInt("maxDnaHits", maxDnaHits); maxTransHits = optionInt("maxTransHits", maxTransHits); maxNtSize = optionInt("maxNtSize", maxNtSize); maxAaSize = optionInt("maxAaSize", maxAaSize); seqLog = optionExists("seqLog"); ipLog = optionExists("ipLog"); doMask = optionExists("mask"); canStop = optionExists("canStop"); noSimpRepMask = optionExists("noSimpRepMask"); indexFile = optionVal("indexFile", NULL); +genome = optionVal("genome", NULL); +genomeDataDir = optionVal("genomeDataDir", NULL); +if ((genomeDataDir != NULL) && (genome == NULL)) + errAbort("-genomeDataDir requires the -genome option"); +if ((genome != NULL) && (genomeDataDir == NULL)) + genomeDataDir = "."; timeout = optionInt("timeout", timeout); if (argc < 2) usage(); if (optionExists("log")) logOpenFile(argv[0], optionVal("log", NULL)); if (optionExists("syslog")) logOpenSyslog(argv[0], optionVal("logFacility", NULL)); if (optionExists("debugLog")) logSetMinPriority("debug"); if (sameWord(command, "direct")) { if (argc < 4) usage(); genoFindDirect(argv[2], argc-3, argv+3);