Reading and writing ROOT files over the net can be done by creating a TNetFile object instead of a TFile object. Since the TNetFile class inherits from the TFile class it has exactly the same interface and behaviour. The only difference is that it reads and writes via a remote rootd daemon.
TNetFile file names are in standard URL format with protocol "root" or "roots" (for secure authentication). The following are valid TNetFile URL's:
roots://hpsalo/files/aap.root
root://hpbrun.cern.ch/root/hsimple.root
root://pcna49a:5151/~na49/data/run821.root
root://pcna49d.cern.ch:5050//v1/data/run810.root
The only difference with the well known httpd URL's is that the root of the remote file tree is the remote user's home directory. Therefore an absolute pathname requires a // after the host or port specifier (as shown in the last example above). Further the expansion of the standard shell characters, like ~, $, .., etc. is handled as expected. The default port on which the remote rootd listens is 1094 and this default port is assumed by TNetFile (actually by TUrl which is used by TNetFile). Port number 1094 has officially been assigned by IANA for rootd.
The rootd daemon works with the TNetFile class. It allows remote access to ROOT database files in either read or read/write mode. The rootd daemon can be found in the directory $ROOTSYS/bin. It can be started either via inetd or by hand from the command line (no need to be super user). Its performance is comparable with NFS but while NFS requires all kind of system permissions to setup, rootd can be started by any user. The simplest way to start rootd is by running it from the command line while being logged on to the remote machine. Once started rootd goes immediately in the background (no need for the &) and you can log out from the remote node. The only argument required is the port number (> 2048) on which your private rootd will listen. Using TNetFile you can now read and write files on the remote machine. For example:
hpsalo [12] telnet
fsgi02.fnal.gov
login: minuser
Password:
<fsgi02> rootd -p 5151
<fsgi02> exit
hpsalo [13] root
root [0] TFile
*f = TFile::Open("root://fsgi02.fnal.gov:5151/file.root","new")
Name (fsgi02.fnal.gov:rdm): minuser
Password:
root [1] f.ls()
In the above example rootd runs on the remote node under user id minuser and listens to port 5151. When creating a TNetFile object you have to specify this same port number 5151 and use minuser (and corresponding password) as login id. When rootd is started in this way you can only login with the user id under which rootd was started on the remote machine. However, you can make many connections since the original rootd will fork (spawn) a new rootd that will service the requests from the TNetFile. The original rootd keeps listening on the specified port for other connections. Each time a TNetFile makes a connection it gets a new private rootd that will handle its requests. At the end of a root session when all TNetFiles are closed only the original rootd will stay alive ready to service future TNetFiles.
Connecting to a rootd daemon requires a remote user id and password. TNetFile supports three ways for you to provide your login information:
The different methods will be tried in the order given above. On machines with AFS rootd will obtain an AFS token (if it has been compiled with AFS support. To rebuild rootd with AFS support see the install instructions).
#! /usr/bin/perl srand(time()); my $randletter = "(int (rand(26)) + (int (rand(1) + .5) % 2 ? 65 : 97))"; my $salt = sprintf("%c%c", eval $randletter, eval $randletter); my $plaintext = shift; my $crypttext = crypt($plaintext, $salt); print "${crypttext}\n";and store the output in $HOME/.rootdpass.
To build rootd with SRP you have to do the following:
TFile *f1 = new TNetFile("roots://host/file1.root"); TFile *f2 = TFile::Open("roots://remote/file2.root");The system will dynamically load libSRPAuth.so if it exists and SRP will be used for the authentication. Note that other rootd traffic is not encrypted.
To make life simple we provide a general function to open any type of file (except shared memory files of class TMapFile). This functionality is provided by the static TFile::Open() function:
TFile *TFile::Open(const
Text_t *name, Option_t *option="",
const
Text_t *title="",
Depending on the name argument the function returns either a TFile, a TNetFile or a TWebFile object. In case a TNetFile URL specifies a local file a TFile object will be returned (and of course no login information is needed). The arguments of the Open() function are the same as the ones for the TFile constructor.
root [0] TFile
*f1 = TFile::Open("local/file.root", "update")
root [1] TFile
*f2 = TFile::Open("root://pcna49a.cern.ch/data/file.root", "new")
Name (pcna49a:rdm):
Password:
root [2] TFile
*f3 = TFile::Open("roots://pcna49a.cern.ch/data/file2.root", "new")
Name (pcna49a:rdm):
Secure Password:
root [3] TFile
*f4 = TFile::Open("http://root.cern.ch/~rdm/hsimple.root")
root [4] f4.ls()
TWebFile** http://root.cern.ch/~rdm/hsimple.root
TWebFile* http://root.cern.ch/~rdm/hsimple.root
KEY: TH1F hpx;1 This is the px distribution
KEY: TH2F hpxpy;1 py vs px
KEY: TProfile hprof;1 Profile of pz versus px
KEY: TNtuple ntuple;1 Demo ntuple
root [5] hpx.Draw()
If you expect to often connect via TNetFile to a remote machine it is more efficient to install rootd as a service of the inetd super daemon. In this way it is not necessary for each user to run a private rootd. However, this requires a one time modification of two system files (and super user priviliges to do so). Add to /etc/services the line:
rootd 1094/tcp
and to /etc/inetd.conf the line:
rootd stream tcp nowait root /usr/local/root/bin/rootd rootd -i
After these changes force inetd to reread its config file with "kill -HUP <pid inetd>".
Setup in this way it is not necessary to specify a port number in the URL given to TNetFile. TNetFile assumes the default port to be 1094 as specified above in the /etc/services file.
Systems using the new xinetd super daemon, like RedHat 7.0, should create a file /etc/xinetd.d/rootd with the following contents:
# default: on # description: The rootd daemon allows remote access to ROOT files. service rootd { disable = no socket_type = stream wait = no user = root server = /usr/local/root/bin/rootd server_args = -i log_on_success += DURATION USERID log_on_failure += USERID }
Rootd support the following arguments:
-i says
we are started by inetd
-p port# specifies
port number to listen on
-d level level of debug
info written to syslogd
0
= no debug (default)
1
= minimum
2
= medium
3
= maximum
rootd:*:71:72:Anonymous rootd:/var/spool/rootd:/bin/falsewhere you may modify the uid, gid (71, 72) and the home directory to suite your system.
rootd:*:72:rootdwhere the gid must match the gid in /etc/passwd.
mkdir /var/spool/rootd mkdir /var/spool/rootd/tmp chmod 777 /var/spool/rootd/tmpWhere /var/spool/rootd must match the rootd home directory as specified in the rootd /etc/passwd entry.
mkdir /var/spool/rootd/pub chown rootd:rootd /var/spool/rootd/pub
Several remarks: