static char *getNLFromHosts(const char *hl_descr) { static char *nl = NULL; char *host, *work, *tmp_descr; nl = realloc(nl, sizeof(char) * PSC_getNrOfNodes()); if (!nl) { PSC_log(-1, "%s: no memory\n", __func__); return NULL; } memset(nl, 0, PSC_getNrOfNodes()); tmp_descr = strdup(hl_descr); if (!tmp_descr) { fprintf(stderr, "%s: no memory\n", __func__); return NULL; } host = strtok_r(tmp_descr, ", ", &work); while (host) { PSnodes_ID_t node; struct hostent *hp = gethostbyname(host); struct in_addr addr; int err; if (!hp) break; memcpy(&addr, hp->h_addr_list[0], sizeof(addr)); err = PSI_infoNodeID(-1, PSP_INFO_HOST, &addr.s_addr, &node, 1); if (err || node==-1) break; nl[node] = 1; host = strtok_r(NULL, ", ", &work); } if (host) printf("Illegal hostname '%s'\n", host); free(tmp_descr); return host ? nl : NULL; }
static char *getNLFromNodes(const char *nl_descr) { static char *nl = NULL, *ret; if (!strcasecmp(nl_descr, "all")) { ret = nl = realloc(nl, sizeof(char) * PSC_getNrOfNodes()); if (!ret) { fprintf(stderr, "%s: no memory\n", __func__); } else { memset(ret, 1, PSC_getNrOfNodes()); } } else { char *tmp_descr = strdup(nl_descr); if (!tmp_descr) { fprintf(stderr, "%s: no memory\n", __func__); ret = NULL; } else { ret = PSC_parseNodelist(tmp_descr); free(tmp_descr); if (!ret) printf("Illegal nodelist '%s'\n", nl_descr); } } return ret; }
void doServer(void) { int forward_id, numClients; ps_send_info_t sinfo; FILE *input = NULL; PSnodes_ID_t node; PSP_PortH_t porth; char *buf, *buf2; buf = malloc(arg_maxmsize); if (!buf) { perror("malloc(buf)"); exit(1); } buf2 = malloc(arg_maxmsize); if (!buf2) { perror("malloc(buf2)"); exit(1); } input = stdin; if (arg_ifile) { input = fopen(arg_ifile, "r"); if (!input) { fprintf(stderr, "Cant open file '%s' for reading : %s\n", arg_ifile, strerror(errno)); exit(1); } } else if (arg_icmd) { input = popen(arg_icmd, "r"); if (!input) { fprintf(stderr, "Cant start input command '%s' : %s\n", arg_icmd, strerror(errno)); exit(1); } } porth = start_server(); if (arg_manual) { numClients = arg_manual; } else { int clientRank = 1; if (arg_hosts) { nodeList = getNLFromHosts(arg_hosts); } else if (arg_nodes) { nodeList = getNLFromNodes(arg_nodes); } else { nodeList = getNLFromNodes("all"); } if (!nodeList && !arg_manual) { fprintf(stderr, "Unknown clients\n"); exit(1); } /* Start clients */ for (node=0; node<PSC_getNrOfNodes(); node++) { if (node == PSC_getMyID()) continue; if (nodeList[node]) { int ret = PSE_spawnAdmin(node, clientRank, rem_argc, rem_argv, 0); if (!ret) clientRank++; } } numClients = clientRank - 1; if (arg_verbose) fprintf(stderr, "Distribute to %d clients\n", numClients); } forward_id = assign_clients(porth, numClients); PSP_StopListen(porth); ps_send_info_init(&sinfo, porth, forward_id); stat_time_start = getusec(); // read from stdin, forward to forward_id while (1) { int len; char *tmp; len = read(fileno(input), buf, arg_maxmsize); if (len <= 0) break; ps_send(&sinfo, buf, len); // swap buffers (ps_send use PSP_ISend. We can read more // data, while we transmit the old data.) tmp = buf; buf = buf2; buf2 = tmp; if (timer_called) { print_stat(arg_cp ? 1 : 0); timer_called = 0; } } if (arg_ifile) { fclose(input); } else if (arg_icmd) { pclose(input); } // Send eof: ps_send(&sinfo, NULL, 0); ps_send_close(&sinfo); free(buf); free(buf2); }
int main(int argc, const char *argv[]) { poptContext optCon; /* context for parsing command-line options */ int rc, version = 0, debugMask = 0, pipeFD[2] = {-1, -1}, magic = FORKMAGIC; char *logdest = NULL, *configfile = "/etc/parastation.conf"; FILE *logfile = NULL; struct poptOption optionsTable[] = { { "debug", 'd', POPT_ARG_INT, &debugMask, 0, "enable debugging with mask <mask>", "mask"}, { "configfile", 'f', POPT_ARG_STRING, &configfile, 0, "use <file> as config-file (default is /etc/parastation.conf)", "file"}, { "logfile", 'l', POPT_ARG_STRING, &logdest, 0, "use <file> for logging (default is syslog(3))." " <file> may be 'stderr' or 'stdout'", "file"}, { "version", 'v', POPT_ARG_NONE, &version, 0, "output version information and exit", NULL}, POPT_AUTOHELP { NULL, '\0', 0, NULL, 0, NULL, NULL} }; optCon = poptGetContext(NULL, argc, argv, optionsTable, 0); rc = poptGetNextOpt(optCon); /* Store arguments for later modification in forwarders, etc. */ PSID_argc = argc; PSID_argv = argv; if (version) { printVersion(); return 0; } if (logdest) { if (strcasecmp(logdest, "stderr")==0) { logfile = stderr; } else if (strcasecmp(logdest, "stdout")==0) { logfile = stdout; } else { logfile = fopen(logdest, "a+"); if (!logfile) { char *errstr = strerror(errno); fprintf(stderr, "Cannot open logfile '%s': %s\n", logdest, errstr ? errstr : "UNKNOWN"); exit(1); } } } if (!logfile) { openlog("psid", LOG_PID|LOG_CONS, LOG_DAEMON); } PSID_initLogs(logfile); printWelcome(); if (rc < -1) { /* an error occurred during option processing */ poptPrintUsage(optCon, stderr, 0); PSID_log(-1, "%s: %s\n", poptBadOption(optCon, POPT_BADOPTION_NOALIAS), poptStrerror(rc)); if (!logfile) fprintf(stderr, "%s: %s\n", poptBadOption(optCon, POPT_BADOPTION_NOALIAS), poptStrerror(rc)); return 1; } /* Save some space in order to modify the cmdline later on */ PSC_saveTitleSpace(PSID_argc, PSID_argv, 1); if (logfile!=stderr && logfile!=stdout) { /* Daemonize only if neither stdout nor stderr is used for logging */ if (pipe(pipeFD) < 0) { PSID_exit(errno, "unable to create pipe"); } /* Start as daemon */ switch (fork()) { case -1: PSID_exit(errno, "unable to fork server process"); break; case 0: /* I'm the child (and running further) */ close (pipeFD[0]); break; default: /* I'm the parent and exiting */ close (pipeFD[1]); /* Wait for child's magic data */ rc = read(pipeFD[0], &magic, sizeof(magic)); if (rc != sizeof(magic) || magic != (FORKMAGIC)) return -1; return 0; } } #define _PATH_TTY "/dev/tty" /* First disconnect from the old controlling tty. */ { int fd = open(_PATH_TTY, O_RDWR | O_NOCTTY); if (fd >= 0) { if (ioctl(fd, TIOCNOTTY, NULL)) { PSID_warn(-1, errno, "%s: ioctl(TIOCNOTTY)", __func__); } close(fd); } } /* * Disable stdin,stdout,stderr and install dummy replacement * Take care if stdout/stderr is used for logging */ { int dummy_fd; dummy_fd=open("/dev/null", O_WRONLY , 0); dup2(dummy_fd, STDIN_FILENO); if (logfile!=stdout) dup2(dummy_fd, STDOUT_FILENO); if (logfile!=stderr) dup2(dummy_fd, STDERR_FILENO); close(dummy_fd); } /* Forget about inherited window sizes */ unsetenv("LINES"); unsetenv("COLUMNS"); if (debugMask) { PSID_setDebugMask(debugMask); PSC_setDebugMask(debugMask); PSID_log(-1, "Debugging mode (mask 0x%x) enabled\n", debugMask); } /* Init the Selector facility as soon as possible */ if (!Selector_isInitialized()) Selector_init(logfile); PSID_registerLoopAct(Selector_gc); /* Initialize timer facility explicitely to ensure correct logging */ if (!Timer_isInitialized()) Timer_init(logfile); /* * Create the Local Service Port as early as possible. Actual * handling is enabled later. This gives psiadmin the chance to * connect. Additionally, this will guarantee exclusiveness */ PSID_createMasterSock(PSmasterSocketName); PSID_checkMaxPID(); /* read the config file */ PSID_readConfigFile(logfile, configfile); /* Now we can rely on the config structure */ { in_addr_t addr; PSID_log(-1, "My ID is %d\n", PSC_getMyID()); addr = PSIDnodes_getAddr(PSC_getMyID()); PSID_log(-1, "My IP is %s\n", inet_ntoa(*(struct in_addr *) &addr)); } if (!logfile && PSID_config->logDest!=LOG_DAEMON) { PSID_log(-1, "Changing logging dest from LOG_DAEMON to %s\n", PSID_config->logDest==LOG_KERN ? "LOG_KERN": PSID_config->logDest==LOG_LOCAL0 ? "LOG_LOCAL0" : PSID_config->logDest==LOG_LOCAL1 ? "LOG_LOCAL1" : PSID_config->logDest==LOG_LOCAL2 ? "LOG_LOCAL2" : PSID_config->logDest==LOG_LOCAL3 ? "LOG_LOCAL3" : PSID_config->logDest==LOG_LOCAL4 ? "LOG_LOCAL4" : PSID_config->logDest==LOG_LOCAL5 ? "LOG_LOCAL5" : PSID_config->logDest==LOG_LOCAL6 ? "LOG_LOCAL6" : PSID_config->logDest==LOG_LOCAL7 ? "LOG_LOCAL7" : "UNKNOWN"); closelog(); openlog("psid", LOG_PID|LOG_CONS, PSID_config->logDest); printWelcome(); } /* call startupScript, if any */ if (PSID_config->startupScript && *PSID_config->startupScript) { int ret = PSID_execScript(PSID_config->startupScript, NULL, NULL, NULL); if (ret > 1) { PSID_log(-1, "startup script '%s' failed. Exiting...\n", PSID_config->startupScript); PSID_finalizeLogs(); exit(1); } } /* Setup handling of signals */ initSigHandlers(); if (PSID_config->coreDir) { if (chdir(PSID_config->coreDir) < 0) { PSID_warn(-1, errno, "Unable to chdir() to coreDirectory '%s'", PSID_config->coreDir); } } PSIDnodes_setProtoV(PSC_getMyID(), PSProtocolVersion); PSIDnodes_setDmnProtoV(PSC_getMyID(), PSDaemonProtocolVersion); PSIDnodes_setHWStatus(PSC_getMyID(), 0); PSIDnodes_setKillDelay(PSC_getMyID(), PSID_config->killDelay); PSIDnodes_setAcctPollI(PSC_getMyID(), PSID_config->acctPollInterval); /* Bring node up with correct numbers of CPUs */ declareNodeAlive(PSC_getMyID(), PSID_getPhysCPUs(), PSID_getVirtCPUs()); /* Initialize timeouts, etc. */ PSID_initStarttime(); /* initialize various modules */ PSIDcomm_init(); /* This has to be first since it gives msgHandler hash */ PSIDclient_init(); initState(); initOptions(); initStatus(); initSignal(); PSIDspawn_init(); initPartition(); initHW(); initAccount(); initInfo(); initEnvironment(); /* Plugins shall be last since they use most of the ones before */ initPlugins(); /* Now we start all the hardware -- this might include the accounter */ PSID_log(PSID_LOG_HW, "%s: starting up the hardware\n", __func__); PSID_startAllHW(); /* * Prepare hostlist to initialize RDP and MCast */ { in_addr_t *hostlist; int i; hostlist = malloc(PSC_getNrOfNodes() * sizeof(unsigned int)); if (!hostlist) { PSID_exit(errno, "Failed to get memory for hostlist"); } for (i=0; i<PSC_getNrOfNodes(); i++) { hostlist[i] = PSIDnodes_getAddr(i); } if (PSID_config->useMCast) { /* Initialize MCast */ int MCastSock = initMCast(PSC_getNrOfNodes(), PSID_config->MCastGroup, PSID_config->MCastPort, logfile, hostlist, PSC_getMyID(), MCastCallBack); if (MCastSock<0) { PSID_exit(errno, "Error while trying initMCast"); } setDeadLimitMCast(PSID_config->deadInterval); PSID_log(-1, "MCast and "); } else { setStatusTimeout(PSID_config->statusTimeout); setMaxStatBCast(PSID_config->statusBroadcasts); setDeadLimit(PSID_config->deadLimit); setTmOutRDP(PSID_config->RDPTimeout); } /* Initialize RDP */ RDPSocket = RDP_init(PSC_getNrOfNodes(), PSIDnodes_getAddr(PSC_getMyID()), PSID_config->RDPPort, logfile, hostlist, PSIDRDP_handleMsg, RDPCallBack); if (RDPSocket<0) { PSID_exit(errno, "Error while trying initRDP"); } PSID_log(-1, "RDP (%d) initialized.\n", RDPSocket); free(hostlist); } /* Now start to listen for clients */ PSID_enableMasterSock(); /* Once RDP and the master socket are ready parents might be released */ if (pipeFD[1] > -1) { if (write(pipeFD[1], &magic, sizeof(magic)) <= 0) { /* We don't care */ } close(pipeFD[1]); } PSID_log(-1, "SelectTime=%d sec DeadInterval=%d\n", PSID_config->selectTime, PSID_config->deadInterval); /* Trigger status stuff, if necessary */ if (PSID_config->useMCast) { declareMaster(PSC_getMyID()); } else { int id = 0; while (id < PSC_getMyID() && (send_DAEMONCONNECT(id) < 0 && errno == EHOSTUNREACH)) { id++; } if (id == PSC_getMyID()) declareMaster(id); } /* * Main loop */ while (1) { int res = Swait(PSID_config->selectTime * 1000); if (res < 0) PSID_warn(-1, errno, "Error while Swait()"); /* Handle actions registered to main-loop */ PSID_handleLoopActions(); } }
PSnodes_ID_t nodeID = psNL->resolveNID(host); if (nodeID == -1) { PSC_log(-1, "%s: no PS node ID for host %s\n", __func__, host); return false; } psNL->nodes[psNL->nrOfNodes++] = nodeID; return true; } bool convHLtoPSnodes(char *hostlist, ResolveFunc_t resolveNID, PSnodes_ID_t **nodes, uint32_t *nrOfNodes) { PSnodeList_t psNL = { .nrOfNodes = 0, .size = PSC_getNrOfNodes(), .resolveNID = resolveNID }; *nrOfNodes = 0; *nodes = NULL; psNL.nodes = malloc(psNL.size * sizeof(*psNL.nodes)); if (!psNL.nodes) { PSC_log(-1, "%s: no memory for nodelist\n", __func__); return false; } if (!traverseHostList(hostlist, hostToPSnode, &psNL)) { free(psNL.nodes); return false; }