00001
00002
00003
00004
00005
00163
00164
00165 #include "drms.h"
00166 #include "serverdefs.h"
00167 #include "xmem.h"
00168 #include "cmdparams.h"
00169 #include "tee.h"
00170 #ifdef __linux__
00171 #include "backtrace.h"
00172 #include <sched.h>
00173 #endif
00174
00175 #include <poll.h>
00176
00177 #define kCENVFILE "cenvfile"
00178 #define kSHENVFILE "shenvfile"
00179 #define kNOTSPECIFIED "notspecified"
00180 #define kSELFSTARTFLAG "b"
00181 #define kHELPFLAG "h"
00182 #define kVERBOSEFLAG "V"
00183 #define kNOSHAREFLAG "s"
00184 #define kNAGLEOFFFLAG "n"
00185 #define kDOLOGFLAG "L"
00186 #define kFGFLAG "f"
00187 #define kLoopConnFlag "loopconn"
00188 #define kDBTimeOut "DRMS_DBTIMEOUT"
00189 #define kDBUtf8ClientEncoding "DRMS_DBUTF8CLIENTENCODING"
00190
00191
00192 CmdParams_t cmdparams;
00193
00194 ModuleArgs_t module_args[] = {
00195 {ARG_INT, "DRMS_RETENTION", "-1"},
00196 {ARG_INT, "DRMS_NEWSURETENTION", "-1"},
00197 {ARG_INT, "DRMS_ARCHIVE", "-9999"},
00198 {ARG_INT, "DRMS_QUERY_MEM", "512"},
00199 {ARG_INT, "DRMS_SERVER_WAIT", "1"},
00200 {ARG_INT, kDBTimeOut, "-99"},
00201 {ARG_STRING, kCENVFILE, kNOTSPECIFIED, "If set, write out to a file all C-shell commands that set the essential DRMS_* env variables."},
00202 {ARG_STRING, kSHENVFILE, kNOTSPECIFIED, "If set, write out to a file all bash-shell command that set the essential DRMS_* env variables."},
00203 {ARG_FLAG, kSELFSTARTFLAG, NULL, "Indicates that drms_server was started by a socket module."},
00204 {ARG_FLAG, kHELPFLAG, NULL, "Display a usage message, then exit."},
00205 {ARG_FLAG, kVERBOSEFLAG, NULL, "Display diagostic messages while running."},
00206 {ARG_FLAG, kNOSHAREFLAG, NULL, "?"},
00207 {ARG_FLAG, kNAGLEOFFFLAG, NULL, "?"},
00208 {ARG_FLAG, kDOLOGFLAG, NULL, "Generate a log saved into a SUMS directory."},
00209 {ARG_FLAG, kFGFLAG, NULL, "Do not fork a child drms_server process."},
00210 {ARG_FLAG, kLoopConnFlag, NULL, "Loop trying to connect to SUMS if SUMS isn't there."},
00211 {}
00212 };
00213
00214 ModuleArgs_t *gModArgs = module_args;
00215
00216 int threadcounter = 0;
00217 char *abortmessage=NULL;
00218 DRMS_Env_t *env;
00219 static void atexit_action (void) {
00220 fprintf (stderr, "WARNING: DRMS server called exit.\n");
00221 #ifdef DEBUG
00222 #ifdef __linux__
00223 fprintf (stderr, "Stack frame:\n");
00224 show_stackframe (stderr);
00225 hang (12);
00226 #endif
00227 #endif
00228 drms_server_abort (env, 1);
00229 #ifdef DEBUG
00230 xmem_leakreport ();
00231 #endif
00232 }
00233
00234 #if 0
00235
00236
00237 static void drms_createsigmask(sigset_t *set, void *data)
00238 {
00239 pthread_t threadid = *((pthread_t *)data);
00240 if (set && threadid == pthread_self())
00241 {
00242 sigemptyset(set);
00243 sigaddset(set, SIGUSR2);
00244 }
00245 }
00246 #endif
00247
00248
00249 static DRMS_Shutdown_State_t GetShutdownState()
00250 {
00251 DRMS_Shutdown_State_t st = kSHUTDOWN_UNINITIATED;
00252 sem_t *sdsem = drms_server_getsdsem();
00253
00254 if (sdsem)
00255 {
00256
00257
00258 sem_wait(sdsem);
00259
00260 DRMS_Shutdown_State_t sdstate = drms_server_getsd();
00261
00262 if (sdstate == kSHUTDOWN_UNINITIATED)
00263 {
00264 sem_post(sdsem);
00265 }
00266 else if (sdstate == kSHUTDOWN_COMMIT || sdstate == kSHUTDOWN_ABORT || sdstate == kSHUTDOWN_BYMAIN)
00267 {
00268
00269
00270 st = sdstate;
00271 sem_post(sdsem);
00272 }
00273 else
00274 {
00275
00276 sem_post(sdsem);
00277
00278
00279
00280 while (1)
00281 {
00282 sem_wait(sdsem);
00283 sdstate = drms_server_getsd();
00284
00285 if (sdstate == kSHUTDOWN_ABORT || sdstate == kSHUTDOWN_COMMIT)
00286 {
00287 st = sdstate;
00288 sem_post(sdsem);
00289 break;
00290 }
00291
00292 sem_post(sdsem);
00293 sleep(1);
00294 }
00295 }
00296 }
00297
00298 return st;
00299 }
00300
00301 static int FreeCmdparams(void *data)
00302 {
00303 cmdparams_freeall(&cmdparams);
00304 memset(&cmdparams, 0, sizeof(CmdParams_t));
00305 return 0;
00306 }
00307
00308 int main (int argc, char *argv[]) {
00309 int fg=0, noshare=0, verbose=0, nagleoff=0, dolog=0;
00310 struct sockaddr_in client;
00311 int sockfd, clientsockfd, status;
00312 unsigned int client_size = sizeof(client);
00313 char hostname[1024], *user, unknown[]="unknown";
00314 short port;
00315 pthread_t thread;
00316 DRMS_ThreadInfo_t *tinfo;
00317 DB_Handle_t *db_handle;
00318 pid_t pid=0;
00319 const char *dbhost;
00320 char *dbuser, *dbpasswd, *dbname, *sessionns;
00321 char *dbport = NULL;
00322 char dbHostAndPort[64];
00323 char drms_server[] = "drms_server";
00324 char *cenvfileprefix = NULL;
00325 char *shenvfileprefix = NULL;
00326 char envfile[PATH_MAX];
00327 FILE *fptr = NULL;
00328 int selfstart = 0;
00329 time_t now;
00330 int infd[2];
00331 int16_t retention;
00332 int16_t newsuretention;
00333
00334 DRMS_Shutdown_State_t sdstate;
00335 int ans;
00336
00337
00338 #ifdef DEBUG
00339 xmem_config(1,1,1,1,1000000,1,0,0);
00340 #endif
00341
00342
00343 if (cmdparams_parse(&cmdparams, argc, argv)==-1)
00344 {
00345 fprintf(stderr,"Error: Command line parsing failed. Aborting.\n");
00346 return 1;
00347 }
00348 if (cmdparams_exists(&cmdparams,"h"))
00349 {
00350 goto usage;
00351 }
00352 verbose = cmdparams_exists(&cmdparams,"V");
00353 noshare = cmdparams_exists(&cmdparams,"s");
00354 nagleoff = cmdparams_exists(&cmdparams,"n");
00355 dolog = cmdparams_exists(&cmdparams,"L");
00356 fg = cmdparams_exists(&cmdparams,"f");
00357 cenvfileprefix = cmdparams_get_str(&cmdparams, kCENVFILE, NULL);
00358 shenvfileprefix = cmdparams_get_str(&cmdparams, kSHENVFILE, NULL);
00359 selfstart = cmdparams_isflagset(&cmdparams, kSELFSTARTFLAG);
00360
00361
00362 if (verbose)
00363 cmdparams_printall(&cmdparams);
00364
00365
00366 if (!(user = getenv("USER")))
00367 user = unknown;
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384 if ((dbhost = cmdparams_get_str(&cmdparams, "JSOC_DBHOST", NULL)) == NULL)
00385 {
00386 const char *sep = NULL;
00387
00388 dbhost = SERVER;
00389 dbport = DRMSPGPORT;
00390
00391
00392 if ((sep = strchr(dbhost, ':')) != NULL)
00393 {
00394 if (strcmp(sep + 1, dbport) != 0)
00395 {
00396 char *tmpBuf = strdup(dbhost);
00397
00398 if (tmpBuf)
00399 {
00400 tmpBuf[sep - dbhost] = '\0';
00401 fprintf(stderr, "WARNING: the port number in the SERVER localization parameter (%s) and in DRMSPGPORT (%s) conflict.\nThe DRMSPGPORT value will be used.\n", sep + 1, DRMSPGPORT);
00402
00403 snprintf(dbHostAndPort, sizeof(dbHostAndPort), "%s:%s", tmpBuf, dbport);
00404 free(tmpBuf);
00405 tmpBuf = NULL;
00406 }
00407 else
00408 {
00409 fprintf(stderr, "Out of memory.\n");
00410 return 1;
00411 }
00412 }
00413 else
00414 {
00415 snprintf(dbHostAndPort, sizeof(dbHostAndPort), "%s", dbhost);
00416 }
00417 }
00418 else
00419 {
00420 snprintf(dbHostAndPort, sizeof(dbHostAndPort), "%s:%s", dbhost, dbport);
00421 }
00422 }
00423 else
00424 {
00425 snprintf(dbHostAndPort, sizeof(dbHostAndPort), "%s", dbhost);
00426 }
00427
00428 if ((dbname = cmdparams_get_str(&cmdparams, "JSOC_DBNAME", NULL)) == NULL)
00429 dbname = DBNAME;
00430 if ((dbuser = cmdparams_get_str(&cmdparams, "JSOC_DBUSER", NULL)) == NULL)
00431 dbuser = USER;
00432 if ((dbpasswd = cmdparams_get_str(&cmdparams, "JSOC_DBPASSWD", NULL)) == NULL)
00433 dbpasswd = PASSWD;
00434 sessionns = cmdparams_get_str(&cmdparams, "JSOC_SESSIONNS", NULL);
00435 if (sessionns && !strcmp(sessionns, "public")) {
00436 fprintf(stderr, "Can't run drms_server in public namespace\n");
00437 return 1;
00438 }
00439
00440 printf("DRMS server started with pid=%d, noshare=%d\n", pid,noshare);
00441
00442
00443
00444 if ((env = drms_open(dbHostAndPort, dbuser,dbpasswd,dbname,sessionns)) == NULL)
00445 {
00446 fprintf(stderr,"Failure during server initialization.\n");
00447 return 1;
00448 }
00449
00450 time(&now);
00451 fprintf(stdout, "Connected to dbase at %s", ctime(&now));
00452
00453 db_handle = env->session->db_handle;
00454
00455 printf("env->session->db_direct = %d\n",env->session->db_direct );
00456 printf("DRMS server connected to database '%s' on host '%s' and port '%s' as "
00457 "user '%s'.\n",env->session->db_handle->dbname,
00458 env->session->db_handle->dbhost,
00459 env->session->db_handle->dbport,
00460 env->session->db_handle->dbuser);
00461
00462 env->archive = drms_cmdparams_get_int(&cmdparams, "DRMS_ARCHIVE", NULL);
00463 if (env->archive < -1 ) env->archive = INT_MIN;
00464
00465 retention = INT16_MIN;
00466 char errbuf[128];
00467
00468 if (drms_cmdparams_exists(&cmdparams, "DRMS_RETENTION") && drms_cmdparams_get_int(&cmdparams, "DRMS_RETENTION", NULL) != -1)
00469 {
00470 retention = drms_cmdparams_get_int16(&cmdparams, "DRMS_RETENTION", &status);
00471 if (status != DRMS_SUCCESS)
00472 {
00473 if (status == DRMS_ERROR_INVALIDCMDARGCONV)
00474 {
00475 snprintf(errbuf, sizeof(errbuf), "The value for %s must be a 15-bit positive integer.", "DRMS_RETENTION");
00476 fprintf(stderr, errbuf);
00477 }
00478
00479 snprintf(errbuf, sizeof(errbuf), "Invalid value for %s.", "DRMS_RETENTION");
00480 fprintf(stderr, errbuf);
00481 return 1;
00482 }
00483 else if (retention < 0)
00484 {
00485 snprintf(errbuf, sizeof(errbuf), "The value for %s must be a 15-bit positive integer.", "DRMS_RETENTION");
00486 fprintf(stderr, errbuf);
00487 return 1;
00488 }
00489 else
00490 {
00491 retention = (int16_t)(retention & 0x7FFF);
00492 }
00493 }
00494
00495 env->retention = retention;
00496
00497 newsuretention = INT16_MIN;
00498
00499 if (drms_cmdparams_exists(&cmdparams, "DRMS_NEWSURETENTION") && drms_cmdparams_get_int(&cmdparams, "DRMS_NEWSURETENTION", NULL) != -1)
00500 {
00501 newsuretention = drms_cmdparams_get_int16(&cmdparams, "DRMS_NEWSURETENTION", &status);
00502 if (status != DRMS_SUCCESS)
00503 {
00504 if (status == DRMS_ERROR_INVALIDCMDARGCONV)
00505 {
00506 snprintf(errbuf, sizeof(errbuf), "The value for %s must be a 15-bit positive integer.", "DRMS_NEWSURETENTION");
00507 fprintf(stderr, errbuf);
00508 }
00509
00510 snprintf(errbuf, sizeof(errbuf), "Invalid value for %s.", "DRMS_NEWSURETENTION");
00511 fprintf(stderr, errbuf);
00512 return 1;
00513 }
00514 else if (newsuretention < 0)
00515 {
00516 snprintf(errbuf, sizeof(errbuf), "The value for %s must be a 15-bit positive integer.", "DRMS_NEWSURETENTION");
00517 fprintf(stderr, errbuf);
00518 return 1;
00519 }
00520 else
00521 {
00522 newsuretention = (int16_t)(newsuretention & 0x7FFF);
00523 fprintf(stderr, "New retention is %hu.\n", newsuretention);
00524 }
00525 }
00526
00527 env->newsuretention = newsuretention;
00528
00529 env->dbtimeout = drms_cmdparams_get_int(&cmdparams, kDBTimeOut, NULL);
00530 if (env->dbtimeout < 0)
00531 {
00532 env->dbtimeout = INT_MIN;
00533 }
00534 env->query_mem = cmdparams_get_int(&cmdparams, "DRMS_QUERY_MEM", NULL);
00535 env->server_wait = cmdparams_get_int(&cmdparams, "DRMS_SERVER_WAIT", NULL);
00536 env->verbose = verbose;
00537
00538 env->dbpasswd = dbpasswd;
00539 env->user = user;
00540 env->logfile_prefix = "drms_server";
00541 env->dolog = dolog;
00542 env->quiet = 1;
00543 env->selfstart = selfstart;
00544 env->loopconn = cmdparams_isflagset(&cmdparams, kLoopConnFlag);
00545 env->dbutf8clientencoding = cmdparams_isflagset(&cmdparams, kDBUtf8ClientEncoding);
00546
00547
00548 sockfd = db_tcp_listen(hostname, sizeof(hostname), &port);
00549 printf("DRMS server listening on %s:%hu.\n",hostname,port);
00550 fflush(stdout);
00551
00552
00553
00554 if (fg == 0)
00555 {
00556
00557
00558 char rbuf[128];
00559 int childready = 0;
00560
00561 pipe(infd);
00562
00563 if ((pid = fork()) == -1)
00564 {
00565 fprintf(stderr,"Fork system call failed, aborting\n");
00566 return 1;
00567 }
00568 else if (pid>0)
00569 {
00570
00571
00572
00573 close(infd[1]);
00574
00575
00576 if (read(infd[0], rbuf, sizeof(rbuf)) > 0)
00577 {
00578 sscanf(rbuf, "%d", &childready);
00579
00580 if (childready)
00581 {
00582 return 0;
00583 }
00584 else
00585 {
00586 return 1;
00587 }
00588 }
00589
00590 return 1;
00591 }
00592
00593 close(infd[0]);
00594 }
00595
00596 pid = getpid();
00597
00598
00599
00600
00601
00602
00603
00604
00605 atexit(atexit_action);
00606
00607
00608
00609
00610
00611
00612 #ifndef DEBUG
00613 sigemptyset(&env->signal_mask);
00614 sigaddset(&env->signal_mask, SIGINT);
00615 sigaddset(&env->signal_mask, SIGQUIT);
00616 sigaddset(&env->signal_mask, SIGTERM);
00617 sigaddset(&env->signal_mask, SIGUSR1);
00618 sigaddset(&env->signal_mask, SIGPIPE);
00619 sigaddset(&env->signal_mask, SIGUSR2);
00620
00621 if( (status = pthread_sigmask(SIG_BLOCK, &env->signal_mask, &env->old_signal_mask)))
00622 {
00623 fprintf(stderr,"pthread_sigmask call failed with status = %d\n", status);
00624 Exit(1);
00625 }
00626
00627 env->main_thread = pthread_self();
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644 CleanerData_t cleaner = {(pFn_Cleaner_t)FreeCmdparams, (void *)NULL};
00645
00646 drms_server_registercleaner(env, &cleaner);
00647
00648
00649
00650 if( (status = pthread_create(&env->signal_thread, NULL, &drms_signal_thread,
00651 (void *) env)) )
00652 {
00653 fprintf(stderr,"Thread creation failed: %d\n", status);
00654 Exit(1);
00655 }
00656 #endif
00657
00658
00659
00660
00661 if (!noshare)
00662 {
00663 if (verbose)
00664 printf("Setting isolation level to SERIALIZABLE.\n");
00665
00666 if ( db_isolation_level(db_handle, DB_TRANS_SERIALIZABLE) )
00667 {
00668 fprintf(stderr,"Failed to set database isolation level.\n");
00669 Exit(1);
00670 }
00671 }
00672
00673 strncpy(env->session->hostname, hostname, DRMS_MAXHOSTNAME);
00674 env->session->port = port;
00675
00676
00677
00678 drms_server_begin_transaction(env);
00679
00680
00681 if (dolog)
00682 {
00683
00684 printf("DRMS server started with pid=%d, noshare=%d\n",
00685 pid,noshare);
00686 fflush(stdout);
00687 }
00688
00689
00690
00691
00692 printf ("Listening for incoming connections on port %hu.\n", port);
00693 fflush (stdout);
00694
00695
00696
00697
00698 if (strcmp(cenvfileprefix, kNOTSPECIFIED) != 0)
00699 {
00700 snprintf(envfile, sizeof(envfile), "%s.%llu", cenvfileprefix, (unsigned long long)pid);
00701 fptr = fopen(envfile, "w");
00702 if (fptr)
00703 {
00704 fprintf(fptr,
00705 "setenv DRMS_HOST %s;\n"
00706 "setenv DRMS_PORT %hu;\n"
00707 "setenv DRMS_PID %lu;\n"
00708 "setenv DRMSSESSION %s:%hu;\n",
00709 env->session->hostname,
00710 env->session->port,
00711 (unsigned long)pid,
00712 env->session->hostname,
00713 env->session->port);
00714 fclose(fptr);
00715 time(&now);
00716 fprintf(stdout, "wrote environment file at %s", ctime(&now));
00717 }
00718 }
00719 else if (strcmp(shenvfileprefix, kNOTSPECIFIED) != 0)
00720 {
00721 snprintf(envfile, sizeof(envfile), "%s.%llu", shenvfileprefix, (unsigned long long)pid);
00722 fptr = fopen(envfile, "w");
00723
00724 if (fptr)
00725 {
00726 fprintf(fptr,
00727 "DRMS_HOST=%s; export DRMS_HOST;\n"
00728 "DRMS_PORT=%hu; export DRMS_PORT;\n"
00729 "DRMS_PID=%lu; export DRMS_PID;\n"
00730 "DRMSSESSION=%s:%hu; export DRMSSESSION;\n",
00731 env->session->hostname,
00732 env->session->port,
00733 (unsigned long)pid,
00734 env->session->hostname,
00735 env->session->port);
00736 fclose(fptr);
00737 time(&now);
00738 fprintf(stdout, "wrote environment file at %s", ctime(&now));
00739 }
00740 }
00741
00742
00743
00744 if (fg == 0)
00745 {
00746
00747 write(infd[1], "1", 1);
00748 }
00749
00750 ans = 0;
00751
00752 for (;;) {
00753
00754
00755
00756 sdstate = GetShutdownState();
00757
00758 if (sdstate == kSHUTDOWN_COMMIT || sdstate == kSHUTDOWN_ABORT)
00759 {
00760
00761
00762
00763 drms_lock_server(env);
00764 if (env->clientcounter > 0)
00765 {
00766 fprintf(stderr, "WARNING: One or more client threads are actively using drms_server.\nShutting down now will interrupt client processessing (the clients will not be notified).\nDo you want to wait for clients to complete processing before shutting down (Y/N)?\n");
00767 ans = fgetc(stdin);
00768 }
00769 drms_unlock_server(env);
00770
00771 if ((char)ans == 'Y' || (char)ans == 'y')
00772 {
00773 while (1)
00774 {
00775 drms_lock_server(env);
00776
00777
00778 if (env->clientcounter == 0)
00779 {
00780 drms_unlock_server(env);
00781 break;
00782 }
00783
00784 drms_unlock_server(env);
00785 sleep(1);
00786 }
00787 }
00788
00789
00790 break;
00791 }
00792 else if (sdstate != kSHUTDOWN_UNINITIATED)
00793 {
00794
00795 continue;
00796 }
00797
00798
00799
00800
00801
00802
00803
00804
00805 struct pollfd fdinfo[1] = {{0}};
00806 int res = 0;
00807
00808 fdinfo[0].fd = sockfd;
00809 fdinfo[0].events = POLLIN | POLLPRI;
00810
00811 res = poll(fdinfo, 1, 500);
00812
00813 if (res == -1)
00814 {
00815
00816 if (errno == EINTR)
00817 {
00818 continue;
00819 }
00820 else
00821 {
00822 perror ("poll call failed.");
00823 close (sockfd);
00824 pthread_kill(env->signal_thread, SIGTERM);
00825 }
00826 }
00827 else if (res == 0)
00828 {
00829
00830 continue;
00831 }
00832 else
00833 {
00834
00835 if ((clientsockfd = accept (sockfd, NULL, NULL)) < 0 ) {
00836 if (errno == EINTR) continue;
00837 else {
00838 perror ("accept call failed.");
00839 close (sockfd);
00840
00841 pthread_kill(env->signal_thread, SIGTERM);
00842 }
00843 }
00844
00845
00846 client_size = sizeof (client);
00847 if (getpeername (clientsockfd, (struct sockaddr *)&client, &client_size) == -1 ) {
00848 perror ("getpeername call failed.");
00849 continue;
00850 }
00851
00852 if (drms_server_authenticate (clientsockfd, env, threadcounter) == 0) {
00853 printf ("pid %d: Connection from %s:%d accepted.\n", getpid(),
00854 inet_ntoa (client.sin_addr), ntohs (client.sin_port));
00855 threadcounter++;
00856
00857 drms_lock_server (env);
00858 env->clientcounter++;
00859 drms_unlock_server (env);
00860
00861 tinfo = malloc (sizeof (DRMS_ThreadInfo_t));
00862 XASSERT(tinfo);
00863 tinfo->env = env;
00864 tinfo->threadnum = threadcounter;
00865 tinfo->sockfd = clientsockfd;
00866 tinfo->noshare = noshare;
00867
00868
00869 if (nagleoff) {
00870 nagleoff = 0;
00871 if (setsockopt (clientsockfd, IPPROTO_TCP, TCP_NODELAY,
00872 (char *)&nagleoff, sizeof (int)) < 0) {
00873 close (clientsockfd);
00874 continue;
00875 }
00876 }
00877
00878 if( (status = pthread_create (&thread, NULL, &drms_server_thread,
00879 (void *) tinfo))) {
00880 fprintf (stderr, "Thread creation failed: %d\n", status);
00881 close (clientsockfd);
00882 drms_lock_server (env);
00883 --(env->clientcounter);
00884 drms_unlock_server (env);
00885 }
00886 } else {
00887 fprintf (stderr, "pid %d: Connection from %s:%d denied. "
00888 "Invalid username or password.\n", getpid(),
00889 inet_ntoa (client.sin_addr), ntohs (client.sin_port));
00890 close (clientsockfd);
00891 }
00892 }
00893 }
00894
00895
00896
00897 pthread_join(env->signal_thread, NULL);
00898
00899
00900 return 0;
00901
00902 usage:
00903 fprintf (stderr, "Usage: %s [-h]\n"
00904 " %s [-fLnQsV] [DRMS_ARCHIVE={-1,0,1}] [JSOC_params - see man page]\n"
00905 "Options: -h: Print this help message.\n"
00906 " -f: Run server in the foreground.\n"
00907 " -L: Redirect stdout and stderr to SU log files.\n"
00908 " -n: Turn off Nagle's algorithm on TCP/IP sockets.\n"
00909 " -Q: Run in quiet mode.\n"
00910 " -s: Commit after every module exit and continue after errors.\n"
00911 " -V: Verbose debug output.\n"
00912 , argv[0], argv[0]);
00913 return 1;
00914 }
00915