Changeset 6571
- Timestamp:
- Nov 6, 2016 8:04:26 PM (7 years ago)
- Location:
- nanoscale/trunk
- Files:
-
- 4 added
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
nanoscale/trunk/Makefile.in
r4585 r6571 1 USE_TCL_CONFIG = #yes 1 2 2 3 CC = @CC@ … … 25 26 26 27 SERVER_OBJS = server.o 28 ifdef USE_TCL_CONFIG 29 SERVER_OBJS += tclparser.o 30 else 31 SERVER_OBJS += configparser.o 32 endif 27 33 CLIENT_OBJS = client.o clientlib.o 28 34 … … 33 39 SVN_VERSION = $(shell svnversion $(srcdir) | sed 's/Unversioned directory/unknown/') 34 40 35 DEFINES = -DSERVERSFILE=\"$(libdir)/renderservers.tcl\" \ 41 ifdef USE_TCL_CONFIG 42 CONFIGFILE = renderservers.tcl 43 DEFINES = -DTCL_CONFIG 44 else 45 CONFIGFILE = renderservers.cfg 46 DEFINES = 47 endif 48 DEFINES += -DSERVERSFILE=\"$(libdir)/$(CONFIGFILE)\" \ 36 49 -DSVN_VERSION=\"$(SVN_VERSION)\" \ 37 50 -DLOGDIR=\"$(LOGDIR)\" 38 INCLUDES = -I. $(TCL_INC_SPEC) 39 LIBS = $(TCL_LIB_SPEC) \ 40 -Wl,-rpath,$(LD_RUN_PATH) 51 INCLUDES = -I. 52 ifdef USE_TCL_CONFIG 53 INCLUDES += $(TCL_INC_SPEC) 54 endif 55 ifdef USE_TCL_CONFIG 56 LIBS = $(TCL_LIB_SPEC) -Wl,-rpath,$(LD_RUN_PATH) 57 else 58 LIBS = 59 endif 41 60 42 61 .PHONY: all install clean distclean … … 49 68 $(CC) $(CC_SWITCHES) -o $@ $^ $(LIBS) 50 69 51 install: nanoscale renderservers.tclstart_nanoscale.sh70 install: nanoscale $(CONFIGFILE) start_nanoscale.sh 52 71 $(INSTALL_PROGRAM) -D nanoscale $(bindir)/nanoscale 53 72 $(INSTALL_PROGRAM) start_nanoscale.sh $(bindir)/start_nanoscale.sh 54 $(INSTALL_ SCRIPT) renderservers.tcl$(libdir)73 $(INSTALL_DATA) $(CONFIGFILE) $(libdir) 55 74 56 75 client: $(CLIENT_OBJS) … … 60 79 61 80 clean: 62 $(RM) -r a.out $(SERVER_OBJS)*~ core* $(TARGETS) *.log *.tmp logfile* .deps/*.d81 $(RM) -r a.out *.o *~ core* $(TARGETS) *.log *.tmp logfile* .deps/*.d 63 82 64 83 distclean: clean 65 84 $(RM) -r autom4te.cache 66 $(RM) Makefile config.cache config.log config.status config.h renderservers.tclstart_nanoscale.sh85 $(RM) Makefile config.cache config.log config.status config.h $(CONFIGFILE) start_nanoscale.sh 67 86 87 server.o: server.h 88 configparser.o: server.h 89 tclparser.o: server.h -
nanoscale/trunk/configure
r4584 r6571 7676 7676 7677 7677 7678 ac_config_files="$ac_config_files Makefile renderservers. tcl start_nanoscale.sh"7678 ac_config_files="$ac_config_files Makefile renderservers.cfg renderservers.tcl start_nanoscale.sh" 7679 7679 7680 7680 cat >confcache <<\_ACEOF … … 8372 8372 "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; 8373 8373 "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; 8374 "renderservers.cfg") CONFIG_FILES="$CONFIG_FILES renderservers.cfg" ;; 8374 8375 "renderservers.tcl") CONFIG_FILES="$CONFIG_FILES renderservers.tcl" ;; 8375 8376 "start_nanoscale.sh") CONFIG_FILES="$CONFIG_FILES start_nanoscale.sh" ;; -
nanoscale/trunk/configure.ac
r6200 r6571 118 118 AC_OUTPUT([ 119 119 Makefile \ 120 renderservers.cfg \ 120 121 renderservers.tcl \ 121 122 start_nanoscale.sh]) -
nanoscale/trunk/renderservers.tcl.in
r6504 r6571 134 134 MSMSSERVER ${libdir}/vmd/msms 135 135 STRIDE_BIN ${libdir}/vmd/stride 136 LD_LIBRARY_PATH ""137 136 __GL_SYNC_TO_VBLANK 0 138 137 } -
nanoscale/trunk/server.c
r6506 r6571 1 1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 2 /* ====================================================================== 3 * Copyright (c) 2004-201 4HUBzero Foundation, LLC3 * Copyright (c) 2004-2016 HUBzero Foundation, LLC 4 4 * ---------------------------------------------------------------------- 5 5 * See the file "license.terms" for information on usage and … … 20 20 #include <sys/stat.h> 21 21 #include <sys/file.h> 22 #include <syslog.h>23 22 #include <unistd.h> 24 23 #include <fcntl.h> 25 24 25 #ifdef TCL_CONFIG 26 26 #include <tcl.h> 27 #endif 27 28 28 29 #include "config.h" 29 30 #define TRUE 1 31 #define FALSE 0 32 33 #ifndef SERVERSFILE 34 #define SERVERSFILE "/opt/hubzero/rappture/render/lib/renderservers.tcl" 35 #endif 36 37 #ifndef LOGDIR 38 #define LOGDIR "/tmp" 39 #endif 40 41 #define ERROR(...) SysLog(LOG_ERR, __FILE__, __LINE__, __VA_ARGS__) 42 #define TRACE(...) SysLog(LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__) 43 #define WARN(...) SysLog(LOG_WARNING, __FILE__, __LINE__, __VA_ARGS__) 44 #define INFO(...) SysLog(LOG_INFO, __FILE__, __LINE__, __VA_ARGS__) 30 #include "server.h" 45 31 46 32 static const char *syslogLevels[] = { … … 55 41 }; 56 42 57 /* RenderServer -- 58 * 59 * Contains information to describe/execute a render server. 60 */ 61 typedef struct { 62 const char *name; /* Name of server. */ 63 int port; /* Port to listen to. */ 64 int numCmdArgs; /* # of args in command. */ 65 int numEnvArgs; /* # of args in environment. */ 66 char *const *cmdArgs; /* Command to execute for 67 * server. */ 68 char *const *envArgs; /* Environment strings to set. */ 69 int listenerFd; /* Descriptor of the listener 70 socket. */ 71 int inputFd; /* Descriptor to dup input side of 72 * server socket. */ 73 int outputFd; /* Descriptor to dup output side of 74 * server socket. */ 75 int logStdout; /* Redirect server stdout to a 76 file. */ 77 int logStderr; /* Redirect server stderr to a 78 file. */ 79 int combineLogs; /* Combine server stdout/stderr in 80 * same file. */ 81 } RenderServer; 82 83 static Tcl_HashTable serverTable; /* Table of render servers 84 * representing services available to 85 * clients. A new instance is forked 86 * and executed each time a new 87 * request is accepted. */ 43 static int numServers = 0; 44 /* Table of render servers representing services available to 45 * clients. A new instance is forked and executed each time a 46 * new request is accepted. */ 47 static RenderServer *serverTable[MAX_SERVERS]; 48 88 49 static int debug = FALSE; 89 50 static pid_t serverPid; 90 51 91 52 static void 53 Help(const char *program) 54 { 55 fprintf(stderr, 56 "Syntax: %s [-d] [-f serversFile] [-x numVideoCards]\n", program); 57 exit(1); 58 } 59 60 static void 61 InitLog() 62 { 63 //openlog("nanoscale", LOG_CONS | LOG_PID, LOG_USER); 64 openlog("nanoscale", LOG_PID, LOG_USER); 65 } 66 67 void 92 68 SysLog(int priority, const char *path, int lineNum, const char* fmt, ...) 93 69 { … … 105 81 s++; 106 82 } 107 length = snprintf(message, MSG_LEN, "nanoscale (%d %d) %s: %s:%d ", 108 serverPid, getpid(), syslogLevels[priority], s, lineNum); 83 if (serverPid != getpid()) { 84 length = snprintf(message, MSG_LEN, "(%d) %s: %s:%d ", 85 serverPid, syslogLevels[priority], s, lineNum); 86 } else { 87 length = snprintf(message, MSG_LEN, "%s: %s:%d ", 88 syslogLevels[priority], s, lineNum); 89 } 109 90 length += vsnprintf(message + length, MSG_LEN - length, fmt, lst); 110 91 message[MSG_LEN] = '\0'; … … 116 97 } 117 98 118 static void 119 Help(const char *program) 120 { 121 fprintf(stderr, 122 "Syntax: %s [-d] [-f serversFile] [-x numVideoCards]\n", program); 123 exit(1); 124 } 125 126 static RenderServer * 127 NewServer(Tcl_Interp *interp, const char *name) 99 RenderServer * 100 NewServer(const char *name) 128 101 { 129 102 RenderServer *serverPtr; … … 132 105 memset(serverPtr, 0, sizeof(RenderServer)); 133 106 if (serverPtr == NULL) { 134 Tcl_AppendResult(interp, "can't allocate structure for \"", 135 name, "\": ", Tcl_PosixError(interp), (char *)NULL); 107 ERROR("can't allocate structure: %s", strerror(errno)); 136 108 return NULL; 137 109 } 138 serverPtr->name = strdup(name); 110 if (name != NULL) { 111 serverPtr->name = strdup(name); 112 } 139 113 serverPtr->outputFd = STDOUT_FILENO; 140 114 serverPtr->inputFd = STDIN_FILENO; … … 145 119 } 146 120 147 static int 148 ParseSwitches(Tcl_Interp *interp, RenderServer *serverPtr, int *objcPtr, 149 Tcl_Obj ***objvPtr) 150 { 151 int i, objc; 152 Tcl_Obj **objv; 153 154 objc = *objcPtr; 155 objv = *objvPtr; 156 for (i = 3; i < objc; i += 2) { 157 const char *string; 158 char c; 159 160 string = Tcl_GetString(objv[i]); 161 if (string[0] != '-') { 162 break; 163 } 164 c = string[1]; 165 if ((c == 'i') && (strcmp(string, "-input") == 0)) { 166 int f; 167 168 if (Tcl_GetIntFromObj(interp, objv[i+1], &f) != TCL_OK) { 169 return TCL_ERROR; 170 } 171 serverPtr->inputFd = f; 172 } else if ((c == 'o') && (strcmp(string, "-output") == 0)) { 173 int f; 174 175 if (Tcl_GetIntFromObj(interp, objv[i+1], &f) != TCL_OK) { 176 return TCL_ERROR; 177 } 178 serverPtr->outputFd = f; 179 } else if ((c == 'l') && (strcmp(string, "-logstdout") == 0)) { 180 int state; 181 182 if (Tcl_GetBooleanFromObj(interp, objv[i+1], &state) != TCL_OK) { 183 return TCL_ERROR; 184 } 185 serverPtr->logStdout = state; 186 } else if ((c == 'l') && (strcmp(string, "-logstderr") == 0)) { 187 int state; 188 189 if (Tcl_GetBooleanFromObj(interp, objv[i+1], &state) != TCL_OK) { 190 return TCL_ERROR; 191 } 192 serverPtr->logStderr = state; 193 } else if ((c == 'c') && (strcmp(string, "-combinelogs") == 0)) { 194 int state; 195 196 if (Tcl_GetBooleanFromObj(interp, objv[i+1], &state) != TCL_OK) { 197 return TCL_ERROR; 198 } 199 serverPtr->combineLogs = state; 200 } else { 201 Tcl_AppendResult(interp, "unknown switch \"", string, "\"", 202 (char *)NULL); 203 return TCL_ERROR; 204 } 205 } 206 *objcPtr = objc - (i - 3); 207 *objvPtr = objv + (i - 3); 208 return TCL_OK; 209 } 210 211 /* 212 * RegisterServerCmd -- 213 * 214 * Registers a render server to be run when a client connects 215 * on the designated port. The form of the commands is 216 * 217 * register_server <name> <port> <cmd> <environ> 218 * 219 * where 220 * 221 * name Token for the render server. 222 * port Port to listen to accept connections. 223 * cmd Command to be run to start the render server. 224 * environ Name-value pairs of representing environment 225 * variables. 226 * 227 * Note that "cmd" and "environ" are variable and backslash 228 * substituted. A listener socket automatically is established on 229 * the given port to accept client requests. 230 * 231 * Example: 232 * 233 * register_server myServer 12345 ?switches? { 234 * /path/to/myserver arg arg 235 * } { 236 * LD_LIBRARY_PATH $libdir/myServer 237 * } 238 * 239 */ 240 static int 241 RegisterServerCmd(ClientData clientData, Tcl_Interp *interp, int objc, 242 Tcl_Obj *const *objv) 243 { 244 Tcl_Obj *objPtr; 245 const char *serverName; 246 int bool, isNew; 247 int f; 248 int port; 249 int numCmdArgs, numEnvArgs; 250 char *const *cmdArgs; 251 char *const *envArgs; 252 struct sockaddr_in addr; 253 RenderServer *serverPtr; 254 Tcl_HashEntry *hPtr; 255 256 if (objc < 4) { 257 Tcl_AppendResult(interp, "wrong # args: should be \"", 258 Tcl_GetString(objv[0]), " serverName port ?flags? cmd ?environ?", 259 (char *)NULL); 260 return TCL_ERROR; 261 } 262 serverName = Tcl_GetString(objv[1]); 263 if (Tcl_GetIntFromObj(interp, objv[2], &port) != TCL_OK) { 264 return TCL_ERROR; 265 } 266 hPtr = Tcl_CreateHashEntry(&serverTable, (char *)((long)port), &isNew); 267 if (!isNew) { 268 Tcl_AppendResult(interp, "a server is already listening on port ", 269 Tcl_GetString(objv[2]), (char *)NULL); 270 return TCL_ERROR; 271 } 272 serverPtr = NewServer(interp, serverName); 273 if (serverPtr == NULL) { 274 return TCL_ERROR; 275 } 276 Tcl_SetHashValue(hPtr, serverPtr); 277 if (ParseSwitches(interp, serverPtr, &objc, (Tcl_Obj ***)&objv) != TCL_OK) { 278 goto error; 279 } 280 objPtr = Tcl_SubstObj(interp, objv[3], 281 TCL_SUBST_VARIABLES | TCL_SUBST_BACKSLASHES); 282 if (Tcl_SplitList(interp, Tcl_GetString(objPtr), &numCmdArgs, 283 (const char ***)&cmdArgs) != TCL_OK) { 284 goto error; 285 } 286 serverPtr->cmdArgs = cmdArgs; 287 serverPtr->numCmdArgs = numCmdArgs; 288 289 numEnvArgs = 0; 290 envArgs = NULL; 291 if (objc == 5) { 292 objPtr = Tcl_SubstObj(interp, objv[4], 293 TCL_SUBST_VARIABLES | TCL_SUBST_BACKSLASHES); 294 if (Tcl_SplitList(interp, Tcl_GetString(objPtr), &numEnvArgs, 295 (const char ***)&envArgs) != TCL_OK) { 296 goto error; 297 } 298 if (numEnvArgs & 0x1) { 299 Tcl_AppendResult(interp, "odd # elements in enviroment list", 300 (char *)NULL); 301 goto error; 302 } 303 } 304 serverPtr->envArgs = envArgs; 305 serverPtr->numEnvArgs = numEnvArgs; 306 307 /* Create a socket for listening. */ 308 f = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 309 if (f < 0) { 310 Tcl_AppendResult(interp, "can't create listener socket for \"", 311 serverPtr->name, "\": ", Tcl_PosixError(interp), (char *)NULL); 312 goto error; 313 } 314 315 /* If the render server instance should be killed, drop the socket address 316 * reservation immediately, don't linger. */ 317 bool = TRUE; 318 if (setsockopt(f, SOL_SOCKET, SO_REUSEADDR, &bool, sizeof(bool)) < 0) { 319 Tcl_AppendResult(interp, "can't create set socket option for \"", 320 serverPtr->name, "\": ", Tcl_PosixError(interp), (char *)NULL); 321 goto error; 322 } 323 324 /* Bind this address to the socket. */ 325 addr.sin_family = AF_INET; 326 addr.sin_port = htons(port); 327 addr.sin_addr.s_addr = htonl(INADDR_ANY); 328 if (bind(f, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 329 Tcl_AppendResult(interp, "can't bind to socket for \"", 330 serverPtr->name, "\": ", Tcl_PosixError(interp), (char *)NULL); 331 goto error; 332 } 333 /* Listen on the specified port. */ 334 if (listen(f, 5) < 0) { 335 Tcl_AppendResult(interp, "can't listen to socket for \"", 336 serverPtr->name, "\": ", Tcl_PosixError(interp), (char *)NULL); 337 return TCL_ERROR; 338 } 339 serverPtr->listenerFd = f; 340 341 return TCL_OK; 342 error: 343 free(serverPtr); 344 return TCL_ERROR; 345 } 346 347 static int 348 ParseServersFile(const char *fileName) 349 { 350 Tcl_Interp *interp; 351 352 interp = Tcl_CreateInterp(); 353 Tcl_MakeSafe(interp); 354 Tcl_CreateObjCommand(interp, "register_server", RegisterServerCmd, NULL, 355 NULL); 356 if (Tcl_EvalFile(interp, fileName) != TCL_OK) { 357 ERROR("Can't add server: %s", Tcl_GetString(Tcl_GetObjResult(interp))); 358 return FALSE; 359 } 360 Tcl_DeleteInterp(interp); 361 return TRUE; 121 static void 122 InitServerTable() 123 { 124 memset(serverTable, 0, sizeof(serverTable)); 362 125 } 363 126 … … 365 128 main(int argc, char **argv) 366 129 { 130 int si; 367 131 #ifdef SA_NOCLDWAIT 368 132 struct sigaction action; … … 377 141 * screen. */ 378 142 int screenNum; /* Current X screen number. */ 379 Tcl_HashEntry *hPtr;380 Tcl_HashSearch iter;381 143 const char *fileName; /* Path to servers file. */ 382 144 … … 388 150 389 151 strcpy(display, ":0.0"); 390 Tcl_InitHashTable(&serverTable, TCL_ONE_WORD_KEYS); 152 InitLog(); 153 InitServerTable(); 391 154 392 155 /* Process command line switches. */ … … 437 200 } 438 201 serverPid = getpid(); 439 if (!ParseServersFile(fileName)) { 202 if (!ParseServersFile(fileName, &numServers, serverTable)) { 203 ERROR("Exiting on invalid configuration"); 440 204 exit(1); 441 205 } 442 206 443 if (serverTable.numEntries == 0) { 207 /* Create listening sockets */ 208 for (si = 0; si < numServers; si++) { 209 int fd, bool; 210 struct sockaddr_in addr; 211 RenderServer *serverPtr; 212 213 serverPtr = serverTable[si]; 214 215 /* Create a socket for listening. */ 216 fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 217 if (fd < 0) { 218 ERROR("can't create listener socket for \"%s\": %s", 219 serverPtr->name, strerror(errno)); 220 exit(1); 221 } 222 /* If the render server instance should be killed, drop the socket 223 address reservation immediately, don't linger. */ 224 bool = TRUE; 225 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &bool, sizeof(bool)) < 0) { 226 ERROR("can't create set socket option for \"%s\": %s", 227 serverPtr->name, strerror(errno)); 228 exit(1); 229 } 230 /* Bind this address to the socket. */ 231 addr.sin_family = AF_INET; 232 addr.sin_port = htons(serverPtr->port); 233 addr.sin_addr.s_addr = htonl(INADDR_ANY); 234 if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 235 ERROR("can't bind to socket for \"%s\": %s", 236 serverPtr->name, strerror(errno)); 237 exit(1); 238 } 239 /* Listen on the specified port. */ 240 if (listen(fd, 5) < 0) { 241 ERROR("can't listen to socket for \"%s\": %s", 242 serverPtr->name, strerror(errno)); 243 exit(1); 244 } 245 serverPtr->listenerFd = fd; 246 INFO("%s listening on %d", serverPtr->name, serverPtr->port); 247 } 248 249 if (numServers == 0) { 444 250 ERROR("No servers designated."); 445 251 exit(1); … … 457 263 FD_ZERO(&serverFds); 458 264 maxFd = -1; 459 for (hPtr = Tcl_FirstHashEntry(&serverTable, &iter); hPtr != NULL; 460 hPtr = Tcl_NextHashEntry(&iter)) { 265 for (si = 0; si < numServers; si++) { 461 266 RenderServer *serverPtr; 462 267 463 serverPtr = Tcl_GetHashValue(hPtr); 268 serverPtr = serverTable[si]; 269 464 270 FD_SET(serverPtr->listenerFd, &serverFds); 465 271 if (serverPtr->listenerFd > maxFd) { … … 477 283 break; /* Error on select. */ 478 284 } 479 for (hPtr = Tcl_FirstHashEntry(&serverTable, &iter); hPtr != NULL; 480 hPtr = Tcl_NextHashEntry(&iter)) { 285 for (si = 0; si < numServers; si++) { 481 286 RenderServer *serverPtr; 482 287 pid_t child; … … 485 290 struct sockaddr_in newaddr; 486 291 487 serverPtr = Tcl_GetHashValue(hPtr);292 serverPtr = serverTable[si]; 488 293 if (!FD_ISSET(serverPtr->listenerFd, &readFds)) { 489 294 continue; … … 645 450 /* Set the configured environment */ 646 451 for (i = 0; i < serverPtr->numEnvArgs; i += 2) { 452 INFO("Env: %s=%s", serverPtr->envArgs[i], 453 serverPtr->envArgs[i+1]); 647 454 setenv(serverPtr->envArgs[i], serverPtr->envArgs[i+1], 1); 648 455 } 649 { 456 { 650 457 char *cmd; 651 458 652 cmd = Tcl_Merge(serverPtr->numCmdArgs, 653 (const char *const *)serverPtr->cmdArgs); 459 cmd = MergeArgs(serverPtr->numCmdArgs, serverPtr->cmdArgs); 654 460 INFO("Executing %s: client=%s, \"%s\" in=%d out=%d on DISPLAY=%s", 655 461 serverPtr->name, inet_ntoa(newaddr.sin_addr), 656 462 cmd, serverPtr->inputFd, serverPtr->outputFd, display); 463 FreeArgs(cmd); 464 //closelog(); 657 465 /* Replace the current process with the render server. */ 658 466 execvp(serverPtr->cmdArgs[0], serverPtr->cmdArgs); 659 ERROR("Can't execute \"%s\": %s", cmd, strerror(errno));660 Tcl_Free(cmd);467 ERROR("Can't execute \"%s\": %s", serverPtr->cmdArgs[0], 468 strerror(errno)); 661 469 exit(1); 662 470 } -
nanoscale/trunk/start_nanoscale.sh.in
r6267 r6571 29 29 30 30 # Start a window manager so geovis doesn't crash 31 pgrep -u rappture -x twm > /dev/null || twm -display :0 &31 #pgrep -u rappture -x twm > /dev/null || twm -display :0 & 32 32 33 33 exec ${bindir}/nanoscale -x ${numVideo}
Note: See TracChangeset
for help on using the changeset viewer.