Plug-in Writer’s 4.x Migration Guide
20-November-2013
Andrew Hanushevsky
©2004-2013
by the Board of Trustees of the Leland Stanford, Jr., University
All Rights Reserved
Produced under contract DE-AC02-76-SFO0515 with the Department of Energy
This code is open-sourced under a GNU Lesser General Public license.
For LGPL terms and conditions see http://www.gnu.org/licenses/
3 IPV6: Socket and Network Interface Changes
4 Summary of Plug-In Changes For Ideal Migration
5.3 XrdOucErrInfo Enhancements
5.5 XrdSfsInterface Enhancements
This
major release of xrootd/cmsd provides full IPV6 support with IPV4
compatibility. As such, it is no longer ABI compatible in two major respects:
1)
Classes
dealing with sockets and the network interfaces have substantially changed, and
2)
The
security interface has changed so as to provide a consistent connection
context.
Additionally,
several classes used by plug-in writers (e.g. XrdOucErrInfo) as well as
abstract plug-in classes have received new methods to enhance the interface. As
such they are not ABI compatible. However, defaults are provided for virtual
methods so only a recompilation is required. This document outlines the
enhanced interfaces to allow you to further optimize the various plug-ins.
Because
version 4.x no longer is ABI backwards compatible, it is necessary to require
that each plug-in include version information so that the plug-in loader can
detect incompatible interfaces. You must include versioning information whether
or not you make any changes to your code. While a simple recompilation against
the version 4.x source code base is likely to be sufficient; versioning
information allows the plug-in manager verify that you have at least carried
out that step.
Use
the XrdVERSIONINFO
macro defined in XrdVersion.hh to include version information in your
plug-in. The exact method is described in each header file that defines the
plug-in interface. Header files and the corresponding plug-ins are shown below.
Header file |
Corresponding
Plug-in |
Related
Directive |
XrdAccAuthorize.hh |
Authorization |
ofs.authlib |
XrdCks.hh |
Checksum
manager |
ofs.ckslib |
XrdCksCalc.hh |
Checksum
calculator |
ofs.ckslib |
XrdClMonitor.hh |
Client-side
monitoring |
n/a |
XrdCmsClient.hh |
Cluster
Manager |
ofs.cmslib |
XrdOss.hh |
Physical
file system |
ofs.osslib |
XrdOssStatInfo.hh |
Alternate
stat() |
oss.stalib |
XrdOucName2Name.hh |
Name-to-name |
oss.namelib |
XrdProtocol.hh |
Protocol |
xrd.protocol |
Header file |
Corresponding
Plug-in |
Related
Directive |
XrdSecInterface |
Authentication |
sec.protocol |
XrdSfsInterface |
Logical
file system |
xrootd.fslib |
The
XrdNetPeer
class is now deprecated but exists for backward compatibility; but may require
source code changes if it is used in certain ways.
This
class embedded an IPV4 structure, sockaddr, and was changed to use XrdNetSockAddr which defines a
larger structure suitable for IPV6. To prevent programs from unknowingly using
the smaller structure, the member name InetAddr, used for the sockaddr structure, was changed
to trigger a compilation error. You should make sure you are not taking the
size of the smaller structure when copying network addresses. Specifically, the
member InetAddr
referred to the sockaddr
structure. This has been changed so that the member
· Intet.Addr refers to the
union of IPV4 and IPV6 sockaddr
structures,
· Inet.v4 refers to an IPV4 sockaddr structure, and
· Inet.v6 refers to an IPV6 sockaddr structure.
If
you are not sensitive to the size of the sockaddr structure, then you can
simply replace all occurrences of InetAddr to be Inet.Addr.
In
general, calls to methods using the XrdNetPeer class as an argument for TCP sockets should
switch to using equivalent methods based on the XrdNetAddr class, if available. Specifically,
review the usage of
· XrdLink::Alloc()
· XrdNet::Accept() and
· XrdNet::Connect()
The
XrdLink::Alloc
method must now pass an XrdNetAddr
object instead of an XrdNetPeer
object. Code review indicated that this method would not be called by any known
plug-ins. Hence, it was deemed safe to make it incompatible.
The
XrdNet methods
accepting XrdNetPeer
objects are still supported for UDP sockets but deprecated for TCP sockets. For
TCP sockets, you should switch to the equivalent method that accepts an XrdNetAddr object.
The
XrdSysDNS
class is now deprecated and essentially obsolete. It is still provided for
backward compatibly but is no longer supported. This class works only in IPV4
contexts. It has been replaced by four address-format agnostic classes:
· XrdNetAddr (which
inherits XrdNetAddrInfo),
· XrdNetSockAddr, and
· XrdNetUtils.
All
uses of XrdSysDNS
should convert to using one or more of the new classes. Specifically,
XrdSysDNS Method |
Replacement
(Single) |
Replacement
(Multiple) |
getAddrName() |
XrdNetAddr::Set() |
XrdNetUtils::GetAddrs() or XrdNetUtils::Hosts() |
getHostAddr() |
XrdNetAddr::Set() |
XrdNetUtils::GetAddrs() or XrdNetUtils::Hosts() |
getHostID() |
XrdNetAddrInfo::Format() |
|
getHostName() |
XrdNetAddr::Set() |
XrdNetUtils::GetAddrs() or XrdNetUtils::Hosts() |
getHostName() |
XrdNetUtils::MyHostName() for current host |
|
getPort() |
XrdNetUtils::ServPort() |
|
getProtoID() |
XrdNetUtils::ProtoID() |
|
Host2Dest() |
XrdNetAddr::Set() |
|
Host2IP()
|
IPV4
specific no replacement |
|
IP2String() |
XrdNetAddrInfo::Format() |
|
IPAddr() |
IPV4
specific no replacement |
|
IPFormat() |
XrdNetAddrInfo::Format() |
|
isDomain() |
XrdNetUtils::Match() |
|
isLoopback() |
XrdNetAddrInfo::isLoopBack() |
|
isMatch() |
XrdNetUtils::Match() |
|
Peername() |
XrdNetAddr::Set() |
|
setPort() |
XrdNetAddr::Set() |
|
The
XrdNetLink
and XrdNetWork
classes have been deleted from the distribution. These were never officially
made available in the public headers and were never used by the base code.
XrdLink Method |
Nature
of change |
Alloc() |
no
longer accepts XrdNetPeer;
you must pass XrdNetAddr |
Host() |
no
longer returns an optional sockaddr copy; use AddrInfo() or NetAddr() to obtain the address |
Name() |
no
longer returns an optional sockaddr copy; use AddrInfo() or NetAddr() to obtain the address |
The
class XrdProtocol_Config
contained the socket address describing the server’s IP address using the member
myAddr has
been sized for IPV6 using a union. While the variable name has not changed,
programs referring to this variable should use the urAddr variable instead.
Otherwise, programs should be sensitive that the socket address may be IPV4 or
IPV6.
The
XrdSecEntity
object has changed, as follows:
1)
It
now includes a pointer to the XrdNetAddrInfo object that describes the connection details
of the end-point that is associated with the entity description as member addrInfo.
2)
In
order to better accommodate this additions, the layout has slightly changed.
In
order to assist authorization and other host address sensitive plug-ins, each
supported security plug-in now sets the addrInfo member to point to a copy of the XrdNetAddrInfo
object passed when requesting a new instance of the protocol. The default authorization
plug-in has been changed to capitalize on this new information. Similar changes
should be made to all private security plug-ins. Failure to set the addrInfo member
will likely result in a SEGV.
Additionally,
the hostname member of the XrdSecEntity object has been documented to contain either a
hostname or an ASCII IP address. This was always true. With the addition of the
addrInfo
member, one can now obtain the actual hostname (i.e. via the XrdNetAddrInfo
object). However, that use is discouraged unless absolutely necessary. This is
to prevent defeating the “nodnr” network directive option.
The
security interfaces have substantially changed. All interfaces that used to
accept a sockaddr
structure now only accept the XrdNetAddrInfo object (for example, the XrdSecProtocol<p>Object function).
The
changes that you should make to your plug-ins are:
1)
Substitute
XrdNetAddr
for any use of sockaddr.
If that is not possible, at the very least, use XrdNetSockAddr instead.
2)
After
converting remove, if possible, redundant include files “arpa/inet.h”, “netinet/in.h”, “sys/socket.hh” and
similar include files.
3)
Convert
from using XrdSysDNS
to a combination of XrdNetAddr
and XrdNetUtils.
4)
Private
security plug-ins must set the addrInfo member in XrdSecEntity.
5)
If
one of your plug-ins relied on the host member in XrdSecEntity to contain an
actual host name, it should be changed to get the actual host using the addrInfo field.
Please be aware that the host member never consistently pointed to a real host
name as it was sensitive to the presence of the nodnr option on the xrd.network
directive.
6)
All
plug-ins must now contain version information. This has become mandatory. Use
the XrdVERSIONINFO
macro defined in XrdVersion.hh
to include version information in your plug-in.
The
following classes have been enhanced with new methods that provide more
flexibility and opportunities to increase performance.
· XrdOss
· XrdOssDF
· XrdOucErrInfo
· XrdSecEntity
· XrdSfsInterface (XrdSfsDirectory,
XrdSfsFile, and XrdSfsFileSystem)
The
following new methods have been added to XrdOss, the abstract class that
defines the physical storage system interface:
FSctl()
This interface allows you to send
arbitrary request data from the logical file system to the physical storage
system and optionally receive a result. It is intended to be used for custom
implementations of the logical and physical storage system plug-ins to perform
operations that are not captured by any existing method. The default
implementation returns –ENOTSUP.
The
following new methods have been added to XrdOssDF, the abstract class
that defines the physical storage system file and directory interface:
Fctl()
This interface allows you to send
arbitrary request data from the logical file system to the physical storage
system and optionally receive a result relative to a particular file or
directory. It is intended to be used for custom implementations of the logical
and physical storage system plug-ins to perform operations that are not
captured by any existing method. The default implementation returns
–ENOTSUP.
ReadV()
This method allows efficient handling
of a vector read request. It is only meant for files. The logical file system
invokes this method when it is asked to handle a file vector read. The default
implementation unrolls the vector of read requests and calls Read() on each element.
StatRet()
This method allows the caller to set a
pointer to a stat structure; implicitly requesting that for each directory
entry returned by Readdir() that the buffer be filled out with the
results of stat() against that
entry. This is meant to dramatically reduce the latency required to obtain
entry attributes of a directory entry. The default implementation returns
–ENOTSUP which forces the caller to manually obtain such information.
WriteV()
This method allows efficient handling
of a vector write request. It is only meant for files. The logical file system
invokes this method when it is asked to handle a file vector write. The default
implementation unrolls the vector of write requests and calls Write() on each element. Currently, file
vector writes are not supported in the upper layers of the system.
The
following new methods have been added to XrdOucErrInfo, the abstract
class that defines the error/data message return path. It is passed to many of
the XrdSfsFileSystem
methods and is part of the XrdSfsDirectory and XrdSfsFile object. These new methods support the object’s
ability to handle information larger than the previously built-in limit of 2048
bytes. This is particularly advantageous when returning redirect information
(i.e. target host plus CGI information) from the logical file system interface.
extData()
Return true when extended information
will be returned (i.e. from an outboard buffer).
getUCap()
Returns the contents of the newly
added member, ucap, that describes the client’s capabilities. These
capabilities can be used to steer client-appropriate processing. For instance,
if the client only supports IPV4 network data then only IPV4 addresses or host
names should be returned.
Reset()
Sets the object to a pristine state
and recycles any extended information buffer.
setErrInfo()
A new variant of this method has been
added that allows you to associate an external buffer defined by the XrdOucBuffer
class that holds error information or return data. This mechanism must be used
to return more than 2048 bytes of information, the previous limit.
The
following new member has been added to XrdSecEntity, the class that defines the client’s
authentication information. It is passed to many of the XrdSfsFileSystem methods.
addrInfo
Points to the XrdNetAddrInfo object that
describes the client’s internet information (e.g. address, hostname, etc). This
object must be used to obtain the client’s true hostname since the host member
may contain a hostname or an IP address should the xrd.network directive’s nodnr option be
in effect. The latter operation should be used only when necessary in order to
not defeat the nodnr
option.
The
following new methods have been added to the XrdSfsInterface specification
(i.e. XrdSfsDirectory,
XrdSfsFile,
XrdSfsFileSystem).
XrdSfsDirectory:: autoStat()
This method allows the caller to set a
pointer to a stat structure; implicitly requesting that for each directory
entry returned by nextEntry() that the buffer be filled out with the
results of stat() against that
entry. This is meant to dramatically reduce the latency required to obtain
entry attributes of a directory entry. The default implementation returns
ENOTSUP which forces the caller to manually obtain such information. See XrdOss::StatRet() for the corresponding method at the physical layer.
XrdSfsFile:: fctl()
A second variant of fctl() allows a client to pass arbitrary
data to the logical file system for a particular file. This is done using the kXR_Qopaqug
option to the kXR_query
request.
XrdSfsFile::readv()
This method allows efficient handling
of a vector read request. It is only meant for files. The logical file system
invokes this method when it is asked to handle a file vector read. The default
implementation unrolls the vector of read requests and calls read() on each element.
XrdSfsFile::SendData()
This method is called for read
operations when the file object returns SFS_SFIO_FDVAL
in the errinfo.code
member in response to a fctl(SFS_FCTL_GETFD) call. Normally, the upper layer would bypass the
logical file system if it could obtain the actual file descriptor associated
with the file and directly issue sendfile() requests in response to read
requests. This can severely constrain what the logical and physical layers can
do with an open file descriptor. The SendData() method allows the file descriptor to
remain hidden by passing the responsibility to issue the sendfile() call to the logical layer. The default implementation merely
returns SFS_OK which causes the read() to be called to complete the request.
XrdSfsFile::SetXio
This method may be called to enable
exchange buffer I/O for write operations. Exchange buffer I/O lets write() claim ownership over a write buffer
in order to accomplish the operation in the background without further copying
the data. It can provide better performance for special kinds of workloads.
XrdSfsFile::writev()
This method allows efficient handling
of a vector write request. It is only meant for files. The logical file system
invokes this method when it is asked to handle a file vector write. The default
implementation unrolls the vector of write requests and calls write() on each element. Currently, file
vector writes are not supported in the upper layers of the system.