|
|
|
|
|
HowTo: the MINOS rotorooter |
$ rotorooter -h
usage: rotorooter -a -p<port#> -b<buffersize> -l<syslog> -e
-a: allow file overwriting
-p: port number rotorooter is listening on
or file name
-b: initial buffer size in long words
-l: syslog facility (eg. 'user')
-e: direct syslog errors to stderr as well
-d: detector override
-s: simflag override
-h: print this message
By default the rotorooter does not allow new output files to overwrite existing files. To override this, for test purposes, one can supply the -a flag and rotorooter will merrily trample over existing files without complaint. Without the flag the rotorooter will create a new filename, e.g. :-
| basename.mdaq.root | first attempt | ||
| basename.1.mdaq.root | first overwrite attempt | ||
| basename.2.mdaq.root | second overwrite attempt |
One can set the port number on which the server listens. Thus multiple copies of rotorooter can be running on a given host machine, each listening to a different port. This could be useful if there were one machine on which output root files were to be written, but one wanted different processes handling DAQ and DCS records. The pre-assigned ports are 9011 for DAQ (default) and 9012 for DCS. Alternatively the "port" can be set to an input file name in which case just that one file is processed e.g.:-
$ rotorooter -a -p run1772.datand rotorooter will terminate as soon as the file finished. To process a zipped file without first uncompressing, pipe the uncompressed output to rotorooter and set the "port" to /dev/stdin e.g.:-
$ gzip -dc run1772.dat.gz | rotorooter -a -p /dev/stdin
The buffer into which data buffers are read is initialized to a default size. Using the -b flag changes the size of the initial buffer. The buffer handling works by floating to a high water mark: if data is sent to the rotorooter that is larger than the buffer it currently holds then it deletes the current buffer and tries to acquire a buffer large enough to satisfy the request. It never tries to resize the buffer downward. If it can't allocate one large enough it works its way downward in 1K chunks until it gets a good buffer; but in such a case the current record might end up corrupted.
As a server that might not be directly connected to a terminal it is necessary to direct warning and error messages somewhere they can be retrieved. Formatted text messages are sent to the syslog facility. Individual messages have different priorities and the syslogd might redirect or ignore messages depending on these options and the configuration in /etc/syslog.config of the host machine. Using the -l flag one can configure the server to use a different syslog "facility" (these include user, local0 through local7). The default value is "local1". If one wants the messages sent to stderr as well then supply the -e flag on the command line.
$ roto_status -s 0will cause the server to do a controlled shutdown.
Sending (e.g. via kill) either the signal SIGTERM (15) or SIGINT (2) to the rotorooter process will force it to terminate any connection to a data source, cleanly close all streams and files and terminate.
Additionally, there is support for converting the straight binary files that the DAQ is capable of writing. In the offline context there is a JobControl module available for taking a RawRecord held by "mom" and sending it to the rotorooter or writing in the binary file format of the pre-rotorooter DAQ.
$ ls $SRT_PUBLIC_CONTEXT/Rotorooter/RotoTalk/rototalk.* rototalk.c rototalk.h
The interface function prototypes are declared in rototalk.h and the code for them is in rototalk.c. The second of these relies on two MINOS specific include files:
Normal usage establishes a connection to the rotorooter once at the beginning of the job and closes it as it exits. Once a connection is established the process then opens a file, sends a series of records and closes the file as necessary. In the case of the DAQ system it might be necessary to have two files open simultaneously during the transition from one subrun to another -- this is supported by the system.
$ daq_bin2roto -h usage: daq_bin2roto -i<hostname> -p<port#> -b<buffersize> -w<whoami> -n<maxrec> <filenames..> -i: hostname where rotorooter is running -b: buffer size to use -w: DCP or DCS -p: port number rotorooter is listening on -v: how verbose to be -n: maximum number of records from each file -h: print this message
#======================================================================= # # A simple job to run roto client # # usage: demojob -bqx roto.jcm # # rhatcher@fnal.gov #======================================================================= echo # get library loaded /Root/LoadLibrary libRotorooter #/Msg/SetLevel Exodus Debug #/Msg/SetLevel Roto Debug # create a path /Path/Create Roto \ Input::Get \ RerootToRawDataModule::Get \ RotoClientModule::Put # uncomment next line to write to binary file #/Roto/RotoClientModule/Set HostPort mybinaryfile.dat -1 /Roto/RotoClientModule/Set BufferWords 6291456 /Roto/RotoClientModule/Set Primary 1 /Roto/Input/Add root_files/gm_far_cosmic_2_hapr01.root /Roto/Run Nin 50
#======================================================================= # # A simple job to read the new RawRecord files # # usage: demojob -bqx read_raw.jcm # # rhatcher@fnal.gov #======================================================================= # load a macro to be run as part of the path # dump_raw.C - takes a "mom" and rummages around in it /Root/LoadMacro dump_raw.C # create a path /Path/Create ReadTest \ Input::Get \ RootCommand::Ana # define when the macro get called and with what arguments # "mom" is the one currently being processed by the path /ReadTest/RootCommand/AddLine/Ana dump_raw(mom,"Ana") # appears SetFormat must happen *before* Add! Don't know why. # eventually code will recognize the standard file extension # and do this automagically /ReadTest/Input/SetFormat raw /ReadTest/Input/Add F00002401_0000.mdaq /ReadTest/Run Nin 20
void rawPrint(RawRecord *rawrec) { if (rawrec == 0) { cout << "No RawRecord found." << endl; return; } bool explicit_iter = true; bool xdump = true; if (explicit_iter) { // Print RawRecord types const RawHeader* rawhead = rawrec->GetRawHeader(); if (rawhead) { cout << " "; rawhead->Print(); } TIter rbi = rawrec->GetRawBlockIter(); RawDataBlock *rb; RawDigitDataBlock *rddb = 0; while ((rb = dynamic_cast (rbi()))) { cout << " " << rb->ClassName() << ":" << rb->GetName() << endl; if (!rddb) { //not under CINT // rddb = dynamic_cast (rb); if (rb->InheritsFrom("RawDigitDataBlock")) { // CINT treats dynamic_cast as a straight C cast // and never returns 0 if it isn't the right type rddb = (RawDigitDataBlock *)(rb); } } if (xdump) rb->Print("x"); } } else rawrec->Print(); } void dump_raw(const MomNavigator* mom, char* byWhom) { if (!mom) { cout << "dump_raw had a null mom ... attempt JobCROOT::GetMom()"; // Attach the current mom ... may fail with an assert() JobCROOT& jc = JobCROOT::Instance(); mom = jc.GetMom(); } bool dumpfrag = true; if (dumpfrag) { TIter fitr = const_cast (mom)->FragmentIter(); cout << "List of Fragments in MomNavigator:" << endl; TObject* tobj; int i = 0; while (tobj = (fitr()) ) { cout << " [" << i << "] " << tobj->ClassName() << ": \"" << tobj->GetName() << "\""<< endl; } } // Find RawRecord fragment in MOM. RawRecord *rawrec = dynamic_cast (mom->GetFragment("RawRecord")); if (rawrec == 0) { cout << "No RawRecord in MOM, " << "mom is " << mom << endl; return; } rawPrint(rawrec); }
| Security, Privacy, Legal |
|