![]() ![]() |
![]() |
File: [Development] / JSOC / CM / V2.0 / drms_module.txt
(download)
Revision: 1.1.1.1 (vendor branch), Mon Oct 1 23:12:21 2007 UTC (15 years, 8 months ago) by arta Branch: Vtag, MAIN CVS Tags: Ver_LATEST, Ver_9-5, Ver_9-41, Ver_9-4, Ver_9-3, Ver_9-2, Ver_9-1, Ver_9-0, Ver_8-8, Ver_8-7, Ver_8-6, Ver_8-5, Ver_8-4, Ver_8-3, Ver_8-2, Ver_8-12, Ver_8-11, Ver_8-10, Ver_8-1, Ver_8-0, Ver_7-1, Ver_7-0, Ver_6-4, Ver_6-3, Ver_6-2, Ver_6-1, Ver_6-0, Ver_5-9, Ver_5-8, Ver_5-7, Ver_5-6, Ver_5-5, Ver_5-3, Ver_5-2, Ver_5-14, Ver_5-13, Ver_5-12, Ver_5-11, Ver_5-10, Ver_5-1, Ver_5-0, Ver_4-7, Ver_4-6, Ver_4-5, Ver_4-4, Ver_4-3, Ver_4-2, Ver_4-1, Ver_4-0, NewTree01_cp09_JSOC, NewTree01_cp08_JSOC, NewTree01_cp07_JSOC, NewTree01_cp06_JSOC, NewTree01_cp05_JSOC, NewTree01_cp04_JSOC, NewTree01_cp03_JSOC, NewTree01_cp02_JSOC, NewTree01_cp01_JSOC, NetDRMS_Ver_LATEST, NetDRMS_Ver_9-5, NetDRMS_Ver_9-41, NetDRMS_Ver_9-4, NetDRMS_Ver_9-3, NetDRMS_Ver_9-2, NetDRMS_Ver_9-1, NetDRMS_Ver_9-0, NetDRMS_Ver_8-8, NetDRMS_Ver_8-7, NetDRMS_Ver_8-6, NetDRMS_Ver_8-5, NetDRMS_Ver_8-4, NetDRMS_Ver_8-12, NetDRMS_Ver_8-11, NetDRMS_Ver_8-10, HEAD Changes since 1.1: +0 -0 lines First new, reorganized JSOC tree |
1. ============= DRMS Module overview ============== DRMS modules share a common main function found in jsoc/src/base/drms/jsoc_main.c. The module executable is run like a normal Unix command line program (see below) and its main function performs the following steps: 1. Parses the command line options and stores them in a global data structure. 2. Connects to a DRMS session master process. 3. Calls the module's main function "DoIt()". 4. If DoIt() returns a non-zero status code, indicating an error, it sends an abort message to the DRMS session master. If DoIt() returns a zero status code (success) it sends a message to the DRMS session master asking it to commit the data generated or modified by the module when the session ends. 5. Disconnects from the DRMS session master. The top-level file for implementing a module should look something like this: ------------------ module.c ------------------------ #include "drms.h" #include "jsoc_main.h" /* List of default parameter values. */ DefaultParams_t default_params[] = { {"parm_name1", "default value1"}, {"parm_name2", "default value2"}, {"mandatory_parm3", NULL }, /* ... more default named parameter values ... */ {NULL, NULL} /* List must end in {NULL, NULL}. */ }; /* Module main function. */ int DoIt(void) { int status; /* Do work... ... Set status == 0 to indicate success. Set status != 0 to indicate failure. */ return status; } ---------------------------------------------------- 2. =========== DRMS command line parsing ============== The functions associated with command line parsing are found in jsoc/src/util/util/cmdparams.{c,h}. The DRMS main program parses the module command line and stores the information in a global data structure CmdParams_t cmdparams; that can be used to access the parameters from anywhere within the module code, including library subroutines. The command line consists of four types of tokens * named parameters given in one of the forms "variable= value", "variable=value" or "--variable value" * single letter flags "-a -b -c" which can also be written in concatenated form "-abc". Flags are translated into named single letter named parameters with the value "1". * unnamed argument strings of the form "value" * command line files of the form "@filename". Each line such a file is parsed as an additional command line. Command files may contain references to other command files. Blank lines or lines beginning in "#" are treated as comment lines and ignored. Command line files are a convenient mechanism go circumvent the limitation on the number of command line arguments in most operating systems. -------- example ----------- Example: Assume that the file inputs.conf contains the three lines # This is a test input1.txt input2.txt then the command line module.exe -vf test=debug abc.txt --log logfile def.bin @inputs.conf will get parsed to have 3 named parameters v = "1" f = "1" test = "debug" log = "logfile" and 4 unnamed arguments abc.txt def.bin input1.txt input2.txt -------- end example ------ The values of the named parameters are read using the following functions: char *cmdparams_get_str(CmdParams_t *parms, char *name, int *status); int8_t cmdparams_get_int8(CmdParams_t *parms, char *name, int *status); int16_t cmdparams_get_int16(CmdParams_t *parms, char *name, int *status); int32_t cmdparams_get_int32(CmdParams_t *parms, char *name, int *status); int64_t cmdparams_get_int64(CmdParams_t *parms, char *name, int *status); float cmdparams_get_float(CmdParams_t *parms, char *name, int *status); double cmdparams_get_double(CmdParams_t *parms, char *name, int *status); double cmdparams_get_time(CmdParams_t *parms, char *name, int *status); int cmdparams_get_int(CmdParams_t *parms, char *name, int *status); If the named parameter is was not given on the command line the functions above try to obtain their values from the environment using the getenv function. Therefore the commands module.exe blah="Hello" and setenv blah Hello module.exe should have the same outcome. The function int cmdparams_exists(CmdParams_t *parms, char *name); returns 1 if a named parameter matching the string in "name" was given on the command line, and 0 if no such parameters was given. The (string) values of the unnamed arguments are read using the following functions: char *cmdparams_getarg(CmdParams_t *parms, int num); int cmdparams_numargs(CmdParams_t *parms); cmdparams_getarg(cmdparms, 0); returns the name of the running program (argv[0]). Default values for parameters can be given in the global struct default_params that must be present in the module. The struct takes the following form: DefaultParams_t default_params[] = { {"parm_name1", "default value1"}, {"parm_name2", "default value2"}, {"mandatory_parm3", NULL }, /* ... more default named parameter values ... */ {NULL, NULL} /* List must end in {NULL, NULL}. */ }; If the value field in the struct for a given parameter is NULL it means that the parameter is mandatory and must be present on the command line. If not, an error message will be printed out and the module terminated immediately after command line parsing. 3. =========== DRMS data functions ============== The module read and writes data using the functions described in jsoc/CM/*/drms_api.txt. 4. =========== Running a DRMS module =========== Running one or more DRMS modules involves three main steps a) starting a DRMS session, b) runnning the module(s) and c) closing the session. The final step will either commit all the data generated by modules in the session or discard it if an error occured. The script /jsoc/scripts/drms/drms_run automates the three steps detailed below, and allows modules (or scripts containing multiple module commands) to be run with a single command. The command host:~> drms_run <command> [options...] will start a new DRMS server, run <command> and depending on the exit status of <command> will either commit or discard changes to the database and stop the DRMS server. drms_run will use the drms_server executable pointed to by the environment variable DRMS_SERVER_EXE. If DRMS_SERVER_EXE is not set drms_run will assume that an executable "drms_server" is in your path. The output from the DRMS server is piped to the file pointed to by the environment variable DRMS_LOGFILE. If DRMS_SERVER_EXE is not set drms_run will create a log file in /tmp/DRMS.<pid>, where <pid> is the PID of the drms_run script interpreter. The three steps are carried out as follows: a) Before you run modules you must have a DRMS server running to act as a session master. This can be done by running the command host:~> jsoc/bin/<target>/drms_server -f The server will print out what interface it is listening for connections on. For example: akhenaten:~/jsoc> bin/custom.akhenaten/drms_server -f DRMS_HOST = akhenaten.Stanford.EDU DRMS_PORT = 33137 DRMS_PID = 20955 DRMS_SESSIONID = 38 DRMS server started with pid=20955, noshare=0, noroe=0 ... The "-f" flag makes the server run in the foreground. Without "-f" the drms_server command spawn a server in a background process, prints the connection info to stdout (as above) and exits. The server will print log messages to stdout and stderr (TBD: Clean up error handling and logging.), and these should be piped to a file if you intend to keep them. b) Now you can run the module(s). The modules do not need to run on the same host as the server. They can run on any host as long as they are able to open a TCP socket connection to the server process. When running a module, the named parameter DRMSSESSION must be set to indicate the host and port where the DRMS server is listening for connection attempts. It is perhaps most convenient to do this by setting the environment variable DRMSSESSION. In the example above this would mean executing the command: akhenaten:~/jsoc> setenv DRMSSESSION akhenaten:33137 Each module that connects causes the server to spawn a new thread to service the new client. The server can service multiple clients simultaneously, but database operations are serialized within the server and executed sequentially using a shared connection to the DRMS database. 3. When all modules have finished successfully you can either a) tell the DRMS server stop and commit all data generated or modified by the modules to the DRMS database by sending a SIGUSR1 signal to it. In the example above that would mean issuing the command akhenaten:~/jsoc> kill -s USR1 20955 or if an error occurs you can b) tell the DRMS server to abort and discard all data generated by the modules by sending it a SIGTERM, SIGQUIT or SIGINT. In the example above that could be done by pressing CTRL-C in the terminal where the server is running or by issuing the command akhenaten:~/jsoc> kill -s INT 20955 It should be safe to kill the server with SIGKILL (kill -9). It will have the same effect as a regular abort except that it leaves a stale entry in DRMS's active session table.
Karen Tian |
Powered by ViewCVS 0.9.4 |