(file) Return to drms_module.txt CVS log (file) (dir) Up to [Development] / JSOC / CM / V2.0

File: [Development] / JSOC / CM / V2.0 / drms_module.txt (download)
Revision: (vendor branch), Mon Oct 1 23:12:21 2007 UTC (15 years, 5 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
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 

-------- example -----------
Example: Assume that the file inputs.conf contains the three lines 

# This is a test

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

-------- end example ------

The values of the named parameters are read using the following 

  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"


  setenv blah Hello

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

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:

 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

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 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

     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