How to Access ROOT Files Remotely via the rootd server ?
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 URL
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
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. fgfgf
Remote Authentication
Before being allowed to access the remote file, TNetFile needs to authenticate vis-a-vis of the remote rootd server. This can be done in several ways described here.
Shadow Passwords
When your system uses shadow passwords you have to compile rootd with -DR__SHADOWPW (see $ROOTSYS/rootd/Module.mk). Since shadow passwords can only be accessed while being superuser (root) this works only when the server is started via inetd. This is inconvenient when you want to run rootd as private user. To solve this problem you should create a file $HOME/.rootdpass containing your encrypted password. If this file exists its password is used for authentication. This method overrides all other authentication methods. To create an encrypted password use a perl script like:
#! /usr/bin/perland store the output in $HOME/.rootdpass.
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";
Using the General TFile::Open() Function
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.
A Sample Session
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()
Starting rootd via inetd
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 /usr/local/root
log_on_success += DURATION USERID
log_on_failure += USERID
}
Rootd Command Line Arguments
Rootd support the following arguments:
| -i | says we are started by (x)inetd |
| -p port# | specifies a different port to listen on. Use port1-port2 to find first available port in range. Use 0-N for range relative to service port. |
| -b tcpwindowsize | specifies the tcp window size in bytes (e.g. see http://www.psc.edu/networking/perf_tune.html). Default is 65535, only change default for pipes with a high bandwidth*delay product. |
| -d level | level of debug info written to syslog 0 = no debug (default) 1 = minimum 2 = medium 3 = maximum |
| -r | files can only be opened in read-only mode |
| -f | do not run as daemon, run in foreground |
| -P file | use this password file instead of $HOME/.srootdpass SRP password file |
| -R bitmask | bit mask specifies which methods will allow authentication to be re-used |
| -S keytabfile | use this keytab file, instead of the default (option only supported when compiled with Kerberos5 support) |
| -T tmpdir | specifies the directory path to be used to place temporary files, default is /usr/tmp. Useful if not running as root. |
| -G gridmapfile | defines the gridmap file to be used for globus authentication if different from globus default (/etc/grid-security/gridmap); (re)defines the GRIDMAP environment variable. |
| -C hostcertfile | defines a file where to find information for the local host Globus information (see GLOBUS.README for details) |
| -s <sshd_port> | specifies the port number for the sshd daemon (default is 22) |
| rootsys_dir | directory containing the ROOT etc and bin directories. Superseeds ROOTSYS or built-in (as specified to ./configure). |
Similar command line arguments are accepted by proofd.
Anonymous rootd Usage
Rootd can also be configured for anonymous usage (like anonymous ftp). To setup rootd to accept anonymous logins do the following (while being logged in as root):
- Add the following line to /etc/passwd:
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/rootdWhere /var/spool/rootd must match the rootd home directory as specified in the rootd /etc/passwd entry.
mkdir /var/spool/rootd/tmp
chmod 777 /var/spool/rootd/tmp
mkdir /var/spool/rootd/pub
chown rootd:rootd /var/spool/rootd/pub
That's all.
Several remarks:
- you can login to an anonymous server either with the names "anonymous" or "rootd".
- the passwd should be of type user@host.do.main. Only the @ is enforced for the time being.
- in anonymous mode the top of the file tree is set to the rootd home directory, therefore only files below the home directory can be accessed.
- anonymous mode only works when the server is started via inetd.