--- /dev/null
+/*!
+ \page title AFS-3 Programmer's Reference: Architectural Overview
+
+\author Edward R. Zayas
+Transarc Corporation
+\version 1.0
+\date 2 September 1991 22:53 .cCopyright 1991 Transarc Corporation All Rights
+Reserved FS-00-D160
+
+
+ \page chap1 Chapter 1: Introduction
+
+ \section sec1-1 Section 1.1: Goals and Background
+
+\par
+This paper provides an architectural overview of Transarc's wide-area
+distributed file system, AFS. Specifically, it covers the current level of
+available software, the third-generation AFS-3 system. This document will
+explore the technological climate in which AFS was developed, the nature of
+problem(s) it addresses, and how its design attacks these problems in order to
+realize the inherent benefits in such a file system. It also examines a set of
+additional features for AFS, some of which are actively being considered.
+\par
+This document is a member of a reference suite providing programming
+specifications as to the operation of and interfaces offered by the various AFS
+system components. It is intended to serve as a high-level treatment of
+distributed file systems in general and of AFS in particular. This document
+should ideally be read before any of the others in the suite, as it provides
+the organizational and philosophical framework in which they may best be
+interpreted.
+
+ \section sec1-2 Section 1.2: Document Layout
+
+\par
+Chapter 2 provides a discussion of the technological background and
+developments that created the environment in which AFS and related systems were
+inspired. Chapter 3 examines the specific set of goals that AFS was designed to
+meet, given the possibilities created by personal computing and advances in
+communication technology. Chapter 4 presents the core AFS architecture and how
+it addresses these goals. Finally, Chapter 5 considers how AFS functionality
+may be be improved by certain design changes.
+
+ \section sec1-3 Section 1.3: Related Documents
+
+\par
+The names of the other documents in the collection, along with brief summaries
+of their contents, are listed below.
+\li AFS-3 Programmer?s Reference: File Server/Cache Manager Interface: This
+document describes the File Server and Cache Manager agents, which provide the
+backbone ?le managment services for AFS. The collection of File Servers for a
+cell supplies centralized ?le storage for that site, and allows clients running
+the Cache Manager component to access those ?les in a high-performance, secure
+fashion.
+\li AFS-3 Programmer?s Reference:Volume Server/Volume Location Server
+Interface: This document describes the services through which ?containers? of
+related user data are located and managed.
+\li AFS-3 Programmer?s Reference: Protection Server Interface: This paper
+describes the server responsible for mapping printable user names to and from
+their internal AFS identi?ers. The Protection Server also allows users to
+create, destroy, and manipulate ?groups? of users, which are suitable for
+placement on Access Control Lists (ACLs).
+\li AFS-3 Programmer?s Reference: BOS Server Interface: This paper covers the
+?nanny? service which assists in the administrability of the AFS environment.
+\li AFS-3 Programmer?s Reference: Speci?cation for the Rx Remote Procedure Call
+Facility: This document speci?es the design and operation of the remote
+procedure call and lightweight process packages used by AFS.
+
+ \page chap2 Chapter 2: Technological Background
+
+\par
+Certain changes in technology over the past two decades greatly in?uenced the
+nature of computational resources, and the manner in which they were used.
+These developments created the conditions under which the notion of a
+distributed ?le systems (DFS) was born. This chapter describes these
+technological changes, and explores how a distributed ?le system attempts to
+capitalize on the new computing environment?s strengths and minimize its
+disadvantages.
+
+ \section sec2-1 Section 2.1: Shift in Computational Idioms
+
+\par
+By the beginning of the 1980s, new classes of computing engines and new methods
+by which they may be interconnected were becoming firmly established. At this
+time, a shift was occurring away from the conventional mainframe-based,
+timeshared computing environment to one in which both workstation-class
+machines and the smaller personal computers (PCs) were a strong presence.
+\par
+The new environment offered many benefits to its users when compared with
+timesharing. These smaller, self-sufficient machines moved dedicated computing
+power and cycles directly onto people's desks. Personal machines were powerful
+enough to support a wide variety of applications, and allowed for a richer,
+more intuitive, more graphically-based interface for them. Learning curves were
+greatly reduced, cutting training costs and increasing new-employee
+productivity. In addition, these machines provided a constant level of service
+throughout the day. Since a personal machine was typically only executing
+programs for a single human user, it did not suffer from timesharing's
+load-based response time degradation. Expanding the computing services for an
+organization was often accomplished by simply purchasing more of the relatively
+cheap machines. Even small organizations could now afford their own computing
+resources, over which they exercised full control. This provided more freedom
+to tailor computing services to the specific needs of particular groups.
+\par
+However, many of the benefits offered by the timesharing systems were lost when
+the computing idiom first shifted to include personal-style machines. One of
+the prime casualties of this shift was the loss of the notion of a single name
+space for all files. Instead, workstation-and PC-based environments each had
+independent and completely disconnected file systems. The standardized
+mechanisms through which files could be transferred between machines (e.g.,
+FTP) were largely designed at a time when there were relatively few large
+machines that were connected over slow links. Although the newer multi-megabit
+per second communication pathways allowed for faster transfers, the problem of
+resource location in this environment was still not addressed. There was no
+longer a system-wide file system, or even a file location service, so
+individual users were more isolated from the organization's collective data.
+Overall, disk requirements ballooned, since lack of a shared file system was
+often resolved by replicating all programs and data to each machine that needed
+it. This proliferation of independent copies further complicated the problem of
+version control and management in this distributed world. Since computers were
+often no longer behind locked doors at a computer center, user authentication
+and authorization tasks became more complex. Also, since organizational
+managers were now in direct control of their computing facilities, they had to
+also actively manage the hardware and software upon which they depended.
+\par
+Overall, many of the benefits of the proliferation of independent,
+personal-style machines were partially offset by the communication and
+organizational penalties they imposed. Collaborative work and dissemination of
+information became more difficult now that the previously unified file system
+was fragmented among hundreds of autonomous machines.
+
+ \section sec2-2 Section 2.2: Distributed File Systems
+
+\par
+As a response to the situation outlined above, the notion of a distributed file
+system (DFS) was developed. Basically, a DFS provides a framework in which
+access to files is permitted regardless of their locations. Specifically, a
+distributed file system offers a single, common set of file system operations
+through which those accesses are performed.
+\par
+There are two major variations on the core DFS concept, classified according to
+the way in which file storage is managed. These high-level models are defined
+below.
+\li Peer-to-peer: In this symmetrical model, each participating machine
+provides storage for specific set of files on its own attached disk(s), and
+allows others to access them remotely. Thus, each node in the DFS is capable of
+both importing files (making reference to files resident on foreign machines)
+and exporting files (allowing other machines to reference files located
+locally).
+\li Server-client: In this model, a set of machines designated as servers
+provide the storage for all of the files in the DFS. All other machines, known
+as clients, must direct their file references to these machines. Thus, servers
+are the sole exporters of files in the DFS, and clients are the sole importers.
+
+\par
+The notion of a DFS, whether organized using the peer-to-peer or server-client
+discipline, may be used as a conceptual base upon which the advantages of
+personal computing resources can be combined with the single-system benefits of
+classical timeshared operation.
+\par
+Many distributed file systems have been designed and deployed, operating on the
+fast local area networks available to connect machines within a single site.
+These systems include DOMAIN [9], DS [15], RFS [16], and Sprite [10]. Perhaps
+the most widespread of distributed file systems to date is a product from Sun
+Microsystems, NFS [13] [14], extending the popular unix file system so that it
+operates over local networks.
+
+ \section sec2-3 Section 2.3: Wide-Area Distributed File Systems
+
+\par
+Improvements in long-haul network technology are allowing for faster
+interconnection bandwidths and smaller latencies between distant sites.
+Backbone services have been set up across the country, and T1 (1.5
+megabit/second) links are increasingly available to a larger number of
+locations. Long-distance channels are still at best approximately an order of
+magnitude slower than the typical local area network, and often two orders of
+magnitude slower. The narrowed difference between local-area and wide-area data
+paths opens the window for the notion of a wide-area distributed file system
+(WADFS). In a WADFS, the transparency of file access offered by a local-area
+DFS is extended to cover machines across much larger distances. Wide-area file
+system functionality facilitates collaborative work and dissemination of
+information in this larger theater of operation.
+
+ \page chap3 Chapter 3: AFS-3 Design Goals
+
+ \section sec3-1 Section 3.1: Introduction
+
+\par
+This chapter describes the goals for the AFS-3 system, the first commercial
+WADFS in existence.
+\par
+The original AFS goals have been extended over the history of the project. The
+initial AFS concept was intended to provide a single distributed file system
+facility capable of supporting the computing needs of Carnegie Mellon
+University, a community of roughly 10,000 people. It was expected that most CMU
+users either had their own workstation-class machine on which to work, or had
+access to such machines located in public clusters. After being successfully
+implemented, deployed, and tuned in this capacity, it was recognized that the
+basic design could be augmented to link autonomous AFS installations located
+within the greater CMU campus. As described in Section 2.3, the long-haul
+networking environment developed to a point where it was feasible to further
+extend AFS so that it provided wide-area file service. The underlying AFS
+communication component was adapted to better handle the widely-varying channel
+characteristics encountered by intra-site and inter-site operations.
+\par
+A more detailed history of AFS evolution may be found in [3] and [18].
+
+ \section sec3-2 Section 3.2: System Goals
+
+\par
+At a high level, the AFS designers chose to extend the single-machine unix
+computing environment into a WADFS service. The unix system, in all of its
+numerous incarnations, is an important computing standard, and is in very wide
+use. Since AFS was originally intended to service the heavily unix-oriented CMU
+campus, this decision served an important tactical purpose along with its
+strategic ramifications.
+\par
+In addition, the server-client discipline described in Section 2.2 was chosen
+as the organizational base for AFS. This provides the notion of a central file
+store serving as the primary residence for files within a given organization.
+These centrally-stored files are maintained by server machines and are made
+accessible to computers running the AFS client software.
+\par
+Listed in the following sections are the primary goals for the AFS system.
+Chapter 4 examines how the AFS design decisions, concepts, and implementation
+meet this list of goals.
+
+ \subsection sec3-2-1 Section 3.2.1: Scale
+
+\par
+AFS differs from other existing DFSs in that it has the specific goal of
+supporting a very large user community with a small number of server machines.
+Unlike the rule-of-thumb ratio of approximately 20 client machines for every
+server machine (20:1) used by Sun Microsystem's widespread NFS distributed file
+system, the AFS architecture aims at smoothly supporting client/server ratios
+more along the lines of 200:1 within a single installation. In addition to
+providing a DFS covering a single organization with tens of thousands of users,
+AFS also aims at allowing thousands of independent, autonomous organizations to
+join in the single, shared name space (see Section 3.2.2 below) without a
+centralized control or coordination point. Thus, AFS envisions supporting the
+file system needs of tens of millions of users at interconnected yet autonomous
+sites.
+
+ \subsection sec3-2-2 Section 3.2.2: Name Space
+
+\par
+One of the primary strengths of the timesharing computing environment is the
+fact that it implements a single name space for all files in the system. Users
+can walk up to any terminal connected to a timesharing service and refer to its
+files by the identical name. This greatly encourages collaborative work and
+dissemination of information, as everyone has a common frame of reference. One
+of the major AFS goals is the extension of this concept to a WADFS. Users
+should be able to walk up to any machine acting as an AFS client, anywhere in
+the world, and use the identical file name to refer to a given object.
+\par
+In addition to the common name space, it was also an explicit goal for AFS to
+provide complete access transparency and location transparency for its files.
+Access transparency is defined as the system's ability to use a single
+mechanism to operate on a file, regardless of its location, local or remote.
+Location transparency is defined as the inability to determine a file's
+location from its name. A system offering location transparency may also
+provide transparent file mobility, relocating files between server machines
+without visible effect to the naming system.
+
+ \subsection sec3-2-3 Section 3.2.3: Performance
+
+\par
+Good system performance is a critical AFS goal, especially given the scale,
+client-server ratio, and connectivity specifications described above. The AFS
+architecture aims at providing file access characteristics which, on average,
+are similar to those of local disk performance.
+
+ \subsection sec3-2-4 Section 3.2.4: Security
+
+\par
+A production WADFS, especially one which allows and encourages transparent file
+access between different administrative domains, must be extremely conscious of
+security issues. AFS assumes that server machines are "trusted" within their
+own administrative domain, being kept behind locked doors and only directly
+manipulated by reliable administrative personnel. On the other hand, AFS client
+machines are assumed to exist in inherently insecure environments, such as
+offices and dorm rooms. These client machines are recognized to be
+unsupervisable, and fully accessible to their users. This situation makes AFS
+servers open to attacks mounted by possibly modified client hardware, firmware,
+operating systems, and application software. In addition, while an organization
+may actively enforce the physical security of its own file servers to its
+satisfaction, other organizations may be lax in comparison. It is important to
+partition the system's security mechanism so that a security breach in one
+administrative domain does not allow unauthorized access to the facilities of
+other autonomous domains.
+\par
+The AFS system is targeted to provide confidence in the ability to protect
+system data from unauthorized access in the above environment, where untrusted
+client hardware and software may attempt to perform direct remote file
+operations from anywhere in the world, and where levels of physical security at
+remote sites may not meet the standards of other sites.
+
+ \subsection sec3-2-5 Section 3.2.5: Access Control
+
+\par
+The standard unix access control mechanism associates mode bits with every file
+and directory, applying them based on the user's numerical identifier and the
+user's membership in various groups. This mechanism was considered too
+coarse-grained by the AFS designers. It was seen as insufficient for specifying
+the exact set of individuals and groups which may properly access any given
+file, as well as the operations these principals may perform. The unix group
+mechanism was also considered too coarse and inflexible. AFS was designed to
+provide more flexible and finer-grained control of file access, improving the
+ability to define the set of parties which may operate on files, and what their
+specific access rights are.
+
+ \subsection sec3-2-6 Section 3.2.6: Reliability
+
+\par
+The crash of a server machine in any distributed file system causes the
+information it hosts to become unavailable to the user community. The same
+effect is observed when server and client machines are isolated across a
+network partition. Given the potential size of the AFS user community, a single
+server crash could potentially deny service to a very large number of people.
+The AFS design reflects a desire to minimize the visibility and impact of these
+inevitable server crashes.
+
+ \subsection sec3-2-7 Section 3.2.7: Administrability
+
+\par
+Driven once again by the projected scale of AFS operation, one of the system's
+goals is to offer easy administrability. With the large projected user
+population, the amount of file data expected to be resident in the shared file
+store, and the number of machines in the environment, a WADFS could easily
+become impossible to administer unless its design allowed for easy monitoring
+and manipulation of system resources. It is also imperative to be able to apply
+security and access control mechanisms to the administrative interface.
+
+ \subsection sec3-2-8 Section 3.2.8: Interoperability/Coexistence
+
+\par
+Many organizations currently employ other distributed file systems, most
+notably Sun Microsystem's NFS, which is also an extension of the basic
+single-machine unix system. It is unlikely that AFS will receive significant
+use if it cannot operate concurrently with other DFSs without mutual
+interference. Thus, coexistence with other DFSs is an explicit AFS goal.
+\par
+A related goal is to provide a way for other DFSs to interoperate with AFS to
+various degrees, allowing AFS file operations to be executed from these
+competing systems. This is advantageous, since it may extend the set of
+machines which are capable of interacting with the AFS community. Hardware
+platforms and/or operating systems to which AFS is not ported may thus be able
+to use their native DFS system to perform AFS file references.
+\par
+These two goals serve to extend AFS coverage, and to provide a migration path
+by which potential clients may sample AFS capabilities, and gain experience
+with AFS. This may result in data migration into native AFS systems, or the
+impetus to acquire a native AFS implementation.
+
+ \subsection sec3-2-9 Section 3.2.9: Heterogeneity/Portability
+
+\par
+It is important for AFS to operate on a large number of hardware platforms and
+operating systems, since a large community of unrelated organizations will most
+likely utilize a wide variety of computing environments. The size of the
+potential AFS user community will be unduly restricted if AFS executes on a
+small number of platforms. Not only must AFS support a largely heterogeneous
+computing base, it must also be designed to be easily portable to new hardware
+and software releases in order to maintain this coverage over time.
+
+ \page chap4 Chapter 4: AFS High-Level Design
+
+ \section sec4-1 Section 4.1: Introduction
+
+\par
+This chapter presents an overview of the system architecture for the AFS-3
+WADFS. Different treatments of the AFS system may be found in several
+documents, including [3], [4], [5], and [2]. Certain system features discussed
+here are examined in more detail in the set of accompanying AFS programmer
+specification documents.
+\par
+After the archtectural overview, the system goals enumerated in Chapter 3 are
+revisited, and the contribution of the various AFS design decisions and
+resulting features is noted.
+
+ \section sec4-2 Section 4.2: The AFS System Architecture
+
+ \subsection sec4-2-1 Section 4.2.1: Basic Organization
+
+\par
+As stated in Section 3.2, a server-client organization was chosen for the AFS
+system. A group of trusted server machines provides the primary disk space for
+the central store managed by the organization controlling the servers. File
+system operation requests for specific files and directories arrive at server
+machines from machines running the AFS client software. If the client is
+authorized to perform the operation, then the server proceeds to execute it.
+\par
+In addition to this basic file access functionality, AFS server machines also
+provide related system services. These include authentication service, mapping
+between printable and numerical user identifiers, file location service, time
+service, and such administrative operations as disk management, system
+reconfiguration, and tape backup.
+
+ \subsection sec4-2-2 Section 4.2.2: Volumes
+
+ \subsubsection sec4-2-2-1 Section 4.2.2.1: Definition
+
+\par
+Disk partitions used for AFS storage do not directly host individual user files
+and directories. Rather, connected subtrees of the system's directory structure
+are placed into containers called volumes. Volumes vary in size dynamically as
+the objects it houses are inserted, overwritten, and deleted. Each volume has
+an associated quota, or maximum permissible storage. A single unix disk
+partition may thus host one or more volumes, and in fact may host as many
+volumes as physically fit in the storage space. However, the practical maximum
+is currently 3,500 volumes per disk partition. This limitation is imposed by
+the salvager program, which examines and repairs file system metadata
+structures.
+\par
+There are two ways to identify an AFS volume. The first option is a 32-bit
+numerical value called the volume ID. The second is a human-readable character
+string called the volume name.
+\par
+Internally, a volume is organized as an array of mutable objects, representing
+individual files and directories. The file system object associated with each
+index in this internal array is assigned a uniquifier and a data version
+number. A subset of these values are used to compose an AFS file identifier, or
+FID. FIDs are not normally visible to user applications, but rather are used
+internally by AFS. They consist of ordered triplets, whose components are the
+volume ID, the index within the volume, and the uniquifier for the index.
+\par
+To understand AFS FIDs, let us consider the case where index i in volume v
+refers to a file named example.txt. This file's uniquifier is currently set to
+one (1), and its data version number is currently set to zero (0). The AFS
+client software may then refer to this file with the following FID: (v, i, 1).
+The next time a client overwrites the object identified with the (v, i, 1) FID,
+the data version number for example.txt will be promoted to one (1). Thus, the
+data version number serves to distinguish between different versions of the
+same file. A higher data version number indicates a newer version of the file.
+\par
+Consider the result of deleting file (v, i, 1). This causes the body of
+example.txt to be discarded, and marks index i in volume v as unused. Should
+another program create a file, say a.out, within this volume, index i may be
+reused. If it is, the creation operation will bump the index's uniquifier to
+two (2), and the data version number is reset to zero (0). Any client caching a
+FID for the deleted example.txt file thus cannot affect the completely
+unrelated a.out file, since the uniquifiers differ.
+
+ \subsubsection sec4-2-2-2 Section 4.2.2.2: Attachment
+
+\par
+The connected subtrees contained within individual volumes are attached to
+their proper places in the file space defined by a site, forming a single,
+apparently seamless unix tree. These attachment points are called mount points.
+These mount points are persistent file system objects, implemented as symbolic
+links whose contents obey a stylized format. Thus, AFS mount points differ from
+NFS-style mounts. In the NFS environment, the user dynamically mounts entire
+remote disk partitions using any desired name. These mounts do not survive
+client restarts, and do not insure a uniform namespace between different
+machines.
+\par
+A single volume is chosen as the root of the AFS file space for a given
+organization. By convention, this volume is named root.afs. Each client machine
+belonging to this organization peforms a unix mount() of this root volume (not
+to be confused with an AFS mount point) on its empty /afs directory, thus
+attaching the entire AFS name space at this point.
+
+ \subsubsection sec4-2-2-3 Section 4.2.2.3: Administrative Uses
+
+\par
+Volumes serve as the administrative unit for AFS ?le system data, providing as
+the basis for replication, relocation, and backup operations.
+
+ \subsubsection sec4-2-2-4 Section 4.2.2.4: Replication
+
+Read-only snapshots of AFS volumes may be created by administrative personnel.
+These clones may be deployed on up to eight disk partitions, on the same server
+machine or across di?erent servers. Each clone has the identical volume ID,
+which must di?er from its read-write parent. Thus, at most one clone of any
+given volume v may reside on a given disk partition. File references to this
+read-only clone volume may be serviced by any of the servers which host a copy.
+
+ \subsubsection sec4-2-2-4 Section 4.2.2.5: Backup
+
+\par
+Volumes serve as the unit of tape backup and restore operations. Backups are
+accomplished by first creating an on-line backup volume for each volume to be
+archived. This backup volume is organized as a copy-on-write shadow of the
+original volume, capturing the volume's state at the instant that the backup
+took place. Thus, the backup volume may be envisioned as being composed of a
+set of object pointers back to the original image. The first update operation
+on the file located in index i of the original volume triggers the
+copy-on-write association. This causes the file's contents at the time of the
+snapshot to be physically written to the backup volume before the newer version
+of the file is stored in the parent volume.
+\par
+Thus, AFS on-line backup volumes typically consume little disk space. On
+average, they are composed mostly of links and to a lesser extent the bodies of
+those few files which have been modified since the last backup took place.
+Also, the system does not have to be shut down to insure the integrity of the
+backup images. Dumps are generated from the unchanging backup volumes, and are
+transferred to tape at any convenient time before the next backup snapshot is
+performed.
+
+ \subsubsection sec4-2-2-6 Section 4.2.2.6: Relocation
+
+\par
+Volumes may be moved transparently between disk partitions on a given file
+server, or between different file server machines. The transparency of volume
+motion comes from the fact that neither the user-visible names for the files
+nor the internal AFS FIDs contain server-specific location information.
+\par
+Interruption to file service while a volume move is being executed is typically
+on the order of a few seconds, regardless of the amount of data contained
+within the volume. This derives from the staged algorithm used to move a volume
+to a new server. First, a dump is taken of the volume's contents, and this
+image is installed at the new site. The second stage involves actually locking
+the original volume, taking an incremental dump to capture file updates since
+the first stage. The third stage installs the changes at the new site, and the
+fourth stage deletes the original volume. Further references to this volume
+will resolve to its new location.
+
+ \subsection sec4-2-3 Section 4.2.3: Authentication
+
+\par
+AFS uses the Kerberos [22] [23] authentication system developed at MIT's
+Project Athena to provide reliable identification of the principals attempting
+to operate on the files in its central store. Kerberos provides for mutual
+authentication, not only assuring AFS servers that they are interacting with
+the stated user, but also assuring AFS clients that they are dealing with the
+proper server entities and not imposters. Authentication information is
+mediated through the use of tickets. Clients register passwords with the
+authentication system, and use those passwords during authentication sessions
+to secure these tickets. A ticket is an object which contains an encrypted
+version of the user's name and other information. The file server machines may
+request a caller to present their ticket in the course of a file system
+operation. If the file server can successfully decrypt the ticket, then it
+knows that it was created and delivered by the authentication system, and may
+trust that the caller is the party identified within the ticket.
+\par
+Such subjects as mutual authentication, encryption and decryption, and the use
+of session keys are complex ones. Readers are directed to the above references
+for a complete treatment of Kerberos-based authentication.
+
+ \subsection sec4-2-4 Section 4.2.4: Authorization
+
+ \subsubsection sec4-2-4-1 Section 4.2.4.1: Access Control Lists
+
+\par
+AFS implements per-directory Access Control Lists (ACLs) to improve the ability
+to specify which sets of users have access to the ?les within the directory,
+and which operations they may perform. ACLs are used in addition to the
+standard unix mode bits. ACLs are organized as lists of one or more (principal,
+rights) pairs. A principal may be either the name of an individual user or a
+group of individual users. There are seven expressible rights, as listed below.
+\li Read (r): The ability to read the contents of the files in a directory.
+\li Lookup (l): The ability to look up names in a directory.
+\li Write (w): The ability to create new files and overwrite the contents of
+existing files in a directory.
+\li Insert (i): The ability to insert new files in a directory, but not to
+overwrite existing files.
+\li Delete (d): The ability to delete files in a directory.
+\li Lock (k): The ability to acquire and release advisory locks on a given
+directory.
+\li Administer (a): The ability to change a directory's ACL.
+
+ \subsubsection sec4-2-4-2 Section 4.2.4.2: AFS Groups
+
+\par
+AFS users may create a certain number of groups, differing from the standard
+unix notion of group. These AFS groups are objects that may be placed on ACLs,
+and simply contain a list of AFS user names that are to be treated identically
+for authorization purposes. For example, user erz may create a group called
+erz:friends consisting of the kazar, vasilis, and mason users. Should erz wish
+to grant read, lookup, and insert rights to this group in directory d, he
+should create an entry reading (erz:friends, rli) in d's ACL.
+\par
+AFS offers three special, built-in groups, as described below.
+\par
+1. system:anyuser: Any individual who accesses AFS files is considered by the
+system to be a member of this group, whether or not they hold an authentication
+ticket. This group is unusual in that it doesn't have a stable membership. In
+fact, it doesn't have an explicit list of members. Instead, the system:anyuser
+"membership" grows and shrinks as file accesses occur, with users being
+(conceptually) added and deleted automatically as they interact with the
+system.
+\par
+The system:anyuser group is typically put on the ACL of those directories for
+which some specific level of completely public access is desired, covering any
+user at any AFS site.
+\par
+2. system:authuser: Any individual in possession of a valid Kerberos ticket
+minted by the organization's authentication service is treated as a member of
+this group. Just as with system:anyuser, this special group does not have a
+stable membership. If a user acquires a ticket from the authentication service,
+they are automatically "added" to the group. If the ticket expires or is
+discarded by the user, then the given individual will automatically be
+"removed" from the group.
+\par
+The system:authuser group is usually put on the ACL of those directories for
+which some specific level of intra-site access is desired. Anyone holding a
+valid ticket within the organization will be allowed to perform the set of
+accesses specified by the ACL entry, regardless of their precise individual ID.
+\par
+3. system:administrators: This built-in group de?nes the set of users capable
+of performing certain important administrative operations within the cell.
+Members of this group have explicit 'a' (ACL administration) rights on every
+directory's ACL in the organization. Members of this group are the only ones
+which may legally issue administrative commands to the file server machines
+within the organization. This group is not like the other two described above
+in that it does have a stable membership, where individuals are added and
+deleted from the group explicitly.
+\par
+The system:administrators group is typically put on the ACL of those
+directories which contain sensitive administrative information, or on those
+places where only administrators are allowed to make changes. All members of
+this group have implicit rights to change the ACL on any AFS directory within
+their organization. Thus, they don't have to actually appear on an ACL, or have
+'a' rights enabled in their ACL entry if they do appear, to be able to modify
+the ACL.
+
+ \subsection sec4-2-5 Section 4.2.5: Cells
+
+\par
+A cell is the set of server and client machines managed and operated by an
+administratively independent organization, as fully described in the original
+proposal [17] and specification [18] documents. The cell's administrators make
+decisions concerning such issues as server deployment and configuration, user
+backup schedules, and replication strategies on their own hardware and disk
+storage completely independently from those implemented by other cell
+administrators regarding their own domains. Every client machine belongs to
+exactly one cell, and uses that information to determine where to obtain
+default system resources and services.
+\par
+The cell concept allows autonomous sites to retain full administrative control
+over their facilities while allowing them to collaborate in the establishment
+of a single, common name space composed of the union of their individual name
+spaces. By convention, any file name beginning with /afs is part of this shared
+global name space and can be used at any AFS-capable machine. The original
+mount point concept was modified to contain cell information, allowing volumes
+housed in foreign cells to be mounted in the file space. Again by convention,
+the top-level /afs directory contains a mount point to the root.cell volume for
+each cell in the AFS community, attaching their individual file spaces. Thus,
+the top of the data tree managed by cell xyz is represented by the /afs/xyz
+directory.
+\par
+Creating a new AFS cell is straightforward, with the operation taking three
+basic steps:
+\par
+1. Name selection: A prospective site has to first select a unique name for
+itself. Cell name selection is inspired by the hierarchical Domain naming
+system. Domain-style names are designed to be assignable in a completely
+decentralized fashion. Example cell names are transarc.com, ssc.gov, and
+umich.edu. These names correspond to the AFS installations at Transarc
+Corporation in Pittsburgh, PA, the Superconducting Supercollider Lab in Dallas,
+TX, and the University of Michigan at Ann Arbor, MI. respectively.
+\par
+2. Server installation: Once a cell name has been chosen, the site must bring
+up one or more AFS file server machines, creating a local file space and a
+suite of local services, including authentication (Section 4.2.6.4) and volume
+location (Section 4.2.6.2).
+\par
+3. Advertise services: In order for other cells to discover the presence of the
+new site, it must advertise its name and which of its machines provide basic
+AFS services such as authentication and volume location. An established site
+may then record the machines providing AFS system services for the new cell,
+and then set up its mount point under /afs. By convention, each cell places the
+top of its file tree in a volume named root.cell.
+
+ \subsection sec4-2-6 Section 4.2.6: Implementation of Server
+Functionality
+
+\par
+AFS server functionality is implemented by a set of user-level processes which
+execute on server machines. This section examines the role of each of these
+processes.
+
+ \subsubsection sec4-2-6-1 Section 4.2.6.1: File Server
+
+\par
+This AFS entity is responsible for providing a central disk repository for a
+particular set of files within volumes, and for making these files accessible
+to properly-authorized users running on client machines.
+
+ \subsubsection sec4-2-6-2 Section 4.2.6.2: Volume Location Server
+
+\par
+The Volume Location Server maintains and exports the Volume Location Database
+(VLDB). This database tracks the server or set of servers on which volume
+instances reside. Among the operations it supports are queries returning volume
+location and status information, volume ID management, and creation, deletion,
+and modification of VLDB entries.
+\par
+The VLDB may be replicated to two or more server machines for availability and
+load-sharing reasons. A Volume Location Server process executes on each server
+machine on which a copy of the VLDB resides, managing that copy.
+
+ \subsubsection sec4-2-6-3 Section 4.2.6.3: Volume Server
+
+\par
+The Volume Server allows administrative tasks and probes to be performed on the
+set of AFS volumes residing on the machine on which it is running. These
+operations include volume creation and deletion, renaming volumes, dumping and
+restoring volumes, altering the list of replication sites for a read-only
+volume, creating and propagating a new read-only volume image, creation and
+update of backup volumes, listing all volumes on a partition, and examining
+volume status.
+
+ \subsubsection sec4-2-6-4 Section 4.2.6.4: Authentication Server
+
+\par
+The AFS Authentication Server maintains and exports the Authentication Database
+(ADB). This database tracks the encrypted passwords of the cell's users. The
+Authentication Server interface allows operations that manipulate ADB entries.
+It also implements the Kerberos mutual authentication protocol, supplying the
+appropriate identification tickets to successful callers.
+\par
+The ADB may be replicated to two or more server machines for availability and
+load-sharing reasons. An Authentication Server process executes on each server
+machine on which a copy of the ADB resides, managing that copy.
+
+ \subsubsection sec4-2-6-5 Section 4.2.6.5: Protection Server
+
+\par
+The Protection Server maintains and exports the Protection Database (PDB),
+which maps between printable user and group names and their internal numerical
+AFS identifiers. The Protection Server also allows callers to create, destroy,
+query ownership and membership, and generally manipulate AFS user and group
+records.
+\par
+The PDB may be replicated to two or more server machines for availability and
+load-sharing reasons. A Protection Server process executes on each server
+machine on which a copy of the PDB resides, managing that copy.
+
+ \subsubsection sec4-2-6-6 Section 4.2.6.6: BOS Server
+
+\par
+The BOS Server is an administrative tool which runs on each file server machine
+in a cell. This server is responsible for monitoring the health of the AFS
+agent processess on that machine. The BOS Server brings up the chosen set of
+AFS agents in the proper order after a system reboot, answers requests as to
+their status, and restarts them when they fail. It also accepts commands to
+start, suspend, or resume these processes, and install new server binaries.
+
+ \subsubsection sec4-2-6-7 Section 4.2.6.7: Update Server/Client
+
+\par
+The Update Server and Update Client programs are used to distribute important
+system files and server binaries. For example, consider the case of
+distributing a new File Server binary to the set of Sparcstation server
+machines in a cell. One of the Sparcstation servers is declared to be the
+distribution point for its machine class, and is configured to run an Update
+Server. The new binary is installed in the appropriate local directory on that
+Sparcstation distribution point. Each of the other Sparcstation servers runs an
+Update Client instance, which periodically polls the proper Update Server. The
+new File Server binary will be detected and copied over to the client. Thus,
+new server binaries need only be installed manually once per machine type, and
+the distribution to like server machines will occur automatically.
+
+ \subsection sec4-2-7 Section 4.2.7: Implementation of Client
+Functionality
+
+ \subsubsection sec4-2-7-1 Section 4.2.7.1: Introduction
+
+\par
+The portion of the AFS WADFS which runs on each client machine is called the
+Cache Manager. This code, running within the client's kernel, is a user's
+representative in communicating and interacting with the File Servers. The
+Cache Manager's primary responsibility is to create the illusion that the
+remote AFS file store resides on the client machine's local disk(s).
+\par
+s implied by its name, the Cache Manager supports this illusion by maintaining
+a cache of files referenced from the central AFS store on the machine's local
+disk. All file operations executed by client application programs on files
+within the AFS name space are handled by the Cache Manager and are realized on
+these cached images. Client-side AFS references are directed to the Cache
+Manager via the standard VFS and vnode file system interfaces pioneered and
+advanced by Sun Microsystems [21]. The Cache Manager stores and fetches files
+to and from the shared AFS repository as necessary to satisfy these operations.
+It is responsible for parsing unix pathnames on open() operations and mapping
+each component of the name to the File Server or group of File Servers that
+house the matching directory or file.
+\par
+The Cache Manager has additional responsibilities. It also serves as a reliable
+repository for the user's authentication information, holding on to their
+tickets and wielding them as necessary when challenged during File Server
+interactions. It caches volume location information gathered from probes to the
+VLDB, and keeps the client machine's local clock synchronized with a reliable
+time source.
+
+ \subsubsection sec4-2-7-2 Section 4.2.7.2: Chunked Access
+
+\par
+In previous AFS incarnations, whole-file caching was performed. Whenever an AFS
+file was referenced, the entire contents of the file were stored on the
+client's local disk. This approach had several disadvantages. One problem was
+that no file larger than the amount of disk space allocated to the client's
+local cache could be accessed.
+\par
+AFS-3 supports chunked file access, allowing individual 64 kilobyte pieces to
+be fetched and stored. Chunking allows AFS files of any size to be accessed
+from a client. The chunk size is settable at each client machine, but the
+default chunk size of 64K was chosen so that most unix files would fit within a
+single chunk.
+
+ \subsubsection sec4-2-7-3 Section 4.2.7.3: Cache Management
+
+\par
+The use of a file cache by the AFS client-side code, as described above, raises
+the thorny issue of cache consistency. Each client must effciently determine
+whether its cached file chunks are identical to the corresponding sections of
+the file as stored at the server machine before allowing a user to operate on
+those chunks.
+\par
+AFS employs the notion of a callback as the backbone of its cache consistency
+algorithm. When a server machine delivers one or more chunks of a file to a
+client, it also includes a callback "promise" that the client will be notified
+if any modifications are made to the data in the file at the server. Thus, as
+long as the client machine is in possession of a callback for a file, it knows
+it is correctly synchronized with the centrally-stored version, and allows its
+users to operate on it as desired without any further interaction with the
+server. Before a file server stores a more recent version of a file on its own
+disks, it will first break all outstanding callbacks on this item. A callback
+will eventually time out, even if there are no changes to the file or directory
+it covers.
+
+ \subsection sec4-2-8 Section 4.2.8: Communication Substrate: Rx
+
+\par
+All AFS system agents employ remote procedure call (RPC) interfaces. Thus,
+servers may be queried and operated upon regardless of their location.
+\par
+The Rx RPC package is used by all AFS agents to provide a high-performance,
+multi-threaded, and secure communication mechanism. The Rx protocol is
+adaptive, conforming itself to widely varying network communication media
+encountered by a WADFS. It allows user applications to de?ne and insert their
+own security modules, allowing them to execute the precise end-to-end
+authentication algorithms required to suit their specific needs and goals. Rx
+offers two built-in security modules. The first is the null module, which does
+not perform any encryption or authentication checks. The second built-in
+security module is rxkad, which utilizes Kerberos authentication.
+\par
+Although pervasive throughout the AFS distributed file system, all of its
+agents, and many of its standard application programs, Rx is entirely separable
+from AFS and does not depend on any of its features. In fact, Rx can be used to
+build applications engaging in RPC-style communication under a variety of
+unix-style file systems. There are in-kernel and user-space implementations of
+the Rx facility, with both sharing the same interface.
+
+ \subsection sec4-2-9 Section 4.2.9: Database Replication: ubik
+
+\par
+The three AFS system databases (VLDB, ADB, and PDB) may be replicated to
+multiple server machines to improve their availability and share access loads
+among the replication sites. The ubik replication package is used to implement
+this functionality. A full description of ubik and of the quorum completion
+algorithm it implements may be found in [19] and [20].
+\par
+The basic abstraction provided by ubik is that of a disk file replicated to
+multiple server locations. One machine is considered to be the synchronization
+site, handling all write operations on the database file. Read operations may
+be directed to any of the active members of the quorum, namely a subset of the
+replication sites large enough to insure integrity across such failures as
+individual server crashes and network partitions. All of the quorum members
+participate in regular elections to determine the current synchronization site.
+The ubik algorithms allow server machines to enter and exit the quorum in an
+orderly and consistent fashion.
+\par
+All operations to one of these replicated "abstract files" are performed as
+part of a transaction. If all the related operations performed under a
+transaction are successful, then the transaction is committed, and the changes
+are made permanent. Otherwise, the transaction is aborted, and all of the
+operations for that transaction are undone.
+\par
+Like Rx, the ubik facility may be used by client applications directly. Thus,
+user applicatons may easily implement the notion of a replicated disk file in
+this fashion.
+
+ \subsection sec4-2-10 Section 4.2.10: System Management
+
+\par
+There are several AFS features aimed at facilitating system management. Some of
+these features have already been mentioned, such as volumes, the BOS Server,
+and the pervasive use of secure RPCs throughout the system to perform
+administrative operations from any AFS client machinein the worldwide
+community. This section covers additional AFS features and tools that assist in
+making the system easier to manage.
+
+ \subsubsection sec4-2-10-1 Section 4.2.10.1: Intelligent Access
+Programs
+
+\par
+A set of intelligent user-level applications were written so that the AFS
+system agents could be more easily queried and controlled. These programs
+accept user input, then translate the caller's instructions into the proper
+RPCs to the responsible AFS system agents, in the proper order.
+\par
+An example of this class of AFS application programs is vos, which mediates
+access to the Volume Server and the Volume Location Server agents. Consider the
+vos move operation, which results in a given volume being moved from one site
+to another. The Volume Server does not support a complex operation like a
+volume move directly. In fact, this move operation involves the Volume Servers
+at the current and new machines, as well as the Volume Location Server, which
+tracks volume locations. Volume moves are accomplished by a combination of full
+and incremental volume dump and restore operations, and a VLDB update. The vos
+move command issues the necessary RPCs in the proper order, and attempts to
+recovers from errors at each of the steps.
+\par
+The end result is that the AFS interface presented to system administrators is
+much simpler and more powerful than that offered by the raw RPC interfaces
+themselves. The learning curve for administrative personnel is thus flattened.
+Also, automatic execution of complex system operations are more likely to be
+successful, free from human error.
+
+ \subsubsection sec4-2-10-2 Section 4.2.10.2: Monitoring Interfaces
+
+\par
+The various AFS agent RPC interfaces provide calls which allow for the
+collection of system status and performance data. This data may be displayed by
+such programs as scout, which graphically depicts File Server performance
+numbers and disk utilizations. Such monitoring capabilites allow for quick
+detection of system problems. They also support detailed performance analyses,
+which may indicate the need to reconfigure system resources.
+
+ \subsubsection sec4-2-10-3 Section 4.2.10.3: Backup System
+
+\par
+A special backup system has been designed and implemented for AFS, as described
+in [6]. It is not sufficient to simply dump the contents of all File Server
+partitions onto tape, since volumes are mobile, and need to be tracked
+individually. The AFS backup system allows hierarchical dump schedules to be
+built based on volume names. It generates the appropriate RPCs to create the
+required backup volumes and to dump these snapshots to tape. A database is used
+to track the backup status of system volumes, along with the set of tapes on
+which backups reside.
+
+ \subsection sec4-2-11 Section 4.2.11: Interoperability
+
+\par
+Since the client portion of the AFS software is implemented as a standard
+VFS/vnode file system object, AFS can be installed into client kernels and
+utilized without interference with other VFS-style file systems, such as
+vanilla unix and the NFS distributed file system.
+\par
+Certain machines either cannot or choose not to run the AFS client software
+natively. If these machines run NFS, it is still possible to access AFS files
+through a protocol translator. The NFS-AFS Translator may be run on any machine
+at the given site that runs both NFS and the AFS Cache Manager. All of the NFS
+machines that wish to access the AFS shared store proceed to NFS-mount the
+translator's /afs directory. File references generated at the NFS-based
+machines are received at the translator machine, which is acting in its
+capacity as an NFS server. The file data is actually obtained when the
+translator machine issues the corresponding AFS references in its role as an
+AFS client.
+
+ \section sec4-3 Section 4.3: Meeting AFS Goals
+
+\par
+The AFS WADFS design, as described in this chapter, serves to meet the system
+goals stated in Chapter 3. This section revisits each of these AFS goals, and
+identifies the specific architectural constructs that bear on them.
+
+ \subsection sec4-3-1 Section 4.3.1: Scale
+
+\par
+To date, AFS has been deployed to over 140 sites world-wide, with approximately
+60 of these cells visible on the public Internet. AFS sites are currently
+operating in several European countries, in Japan, and in Australia. While many
+sites are modest in size, certain cells contain more than 30,000 accounts. AFS
+sites have realized client/server ratios in excess of the targeted 200:1.
+
+ \subsection sec4-3-2 Section 4.3.2: Name Space
+
+\par
+A single uniform name space has been constructed across all cells in the
+greater AFS user community. Any pathname beginning with /afs may indeed be used
+at any AFS client. A set of common conventions regarding the organization of
+the top-level /afs directory and several directories below it have been
+established. These conventions also assist in the location of certain per-cell
+resources, such as AFS configuration files.
+\par
+Both access transparency and location transparency are supported by AFS, as
+evidenced by the common access mechanisms and by the ability to transparently
+relocate volumes.
+
+ \subsection sec4-3-3 Section 4.3.3: Performance
+
+\par
+AFS employs caching extensively at all levels to reduce the cost of "remote"
+references. Measured data cache hit ratios are very high, often over 95%. This
+indicates that the file images kept on local disk are very effective in
+satisfying the set of remote file references generated by clients. The
+introduction of file system callbacks has also been demonstrated to be very
+effective in the efficient implementation of cache synchronization. Replicating
+files and system databases across multiple server machines distributes load
+among the given servers. The Rx RPC subsystem has operated successfully at
+network speeds ranging from 19.2 kilobytes/second to experimental
+gigabit/second FDDI networks.
+\par
+Even at the intra-site level, AFS has been shown to deliver good performance,
+especially in high-load situations. One often-quoted study [1] compared the
+performance of an older version of AFS with that of NFS on a large file system
+task named the Andrew Benchmark. While NFS sometimes outperformed AFS at low
+load levels, its performance fell off rapidly at higher loads while AFS
+performance degradation was not significantly affected.
+
+ \subsection sec4-3-4 Section 4.3.4: Security
+
+\par
+The use of Kerberos as the AFS authentication system fits the security goal
+nicely. Access to AFS files from untrusted client machines is predicated on the
+caller's possession of the appropriate Kerberos ticket(s). Setting up per-site,
+Kerveros-based authentication services compartmentalizes any security breach to
+the cell which was compromised. Since the Cache Manager will store multiple
+tickets for its users, they may take on different identities depending on the
+set of file servers being accessed.
+
+ \subsection sec4-3-5 Section 4.3.5: Access Control
+
+\par
+AFS extends the standard unix authorization mechanism with per-directory Access
+Control Lists. These ACLs allow specific AFS principals and groups of these
+principals to be granted a wide variety of rights on the associated files.
+Users may create and manipulate AFS group entities without administrative
+assistance, and place these tailored groups on ACLs.
+
+ \subsection sec4-3-6 Section 4.3.6: Reliability
+
+\par
+A subset of file server crashes are masked by the use of read-only replication
+on volumes containing slowly-changing files. Availability of important,
+frequently-used programs such as editors and compilers may thus been greatly
+improved. Since the level of replication may be chosen per volume, and easily
+changed, each site may decide the proper replication levels for certain
+programs and/or data.
+Similarly, replicated system databases help to maintain service in the face of
+server crashes and network partitions.
+
+ \subsection sec4-3-7 Section 4.3.7: Administrability
+
+\par
+Such features as pervasive, secure RPC interfaces to all AFS system components,
+volumes, overseer processes for monitoring and management of file system
+agents, intelligent user-level access tools, interface routines providing
+performance and statistics information, and an automated backup service
+tailored to a volume-based environment all contribute to the administrability
+of the AFS system.
+
+ \subsection sec4-3-8 Section 4.3.8: Interoperability/Coexistence
+
+\par
+Due to its VFS-style implementation, the AFS client code may be easily
+installed in the machine's kernel, and may service file requests without
+interfering in the operation of any other installed file system. Machines
+either not capable of running AFS natively or choosing not to do so may still
+access AFS files via NFS with the help of a protocol translator agent.
+
+ \subsection sec4-3-9 Section 4.3.9: Heterogeneity/Portability
+
+\par
+As most modern kernels use a VFS-style interface to support their native file
+systems, AFS may usually be ported to a new hardware and/or software
+environment in a relatively straightforward fashion. Such ease of porting
+allows AFS to run on a wide variety of platforms.
+
+ \page chap5 Chapter 5: Future AFS Design Re?nements
+
+ \section sec5-1 Section 5.1: Overview
+
+\par
+The current AFS WADFS design and implementation provides a high-performance,
+scalable, secure, and flexible computing environment. However, there is room
+for improvement on a variety of fronts. This chapter considers a set of topics,
+examining the shortcomings of the current AFS system and considering how
+additional functionality may be fruitfully constructed.
+\par
+Many of these areas are already being addressed in the next-generation AFS
+system which is being built as part of Open Software Foundation?s (OSF)
+Distributed Computing Environment [7] [8].
+
+ \section sec5-2 Section 5.2: unix Semantics
+
+\par
+Any distributed file system which extends the unix file system model to include
+remote file accesses presents its application programs with failure modes which
+do not exist in a single-machine unix implementation. This semantic difference
+is dificult to mask.
+\par
+The current AFS design varies from pure unix semantics in other ways. In a
+single-machine unix environment, modifications made to an open file are
+immediately visible to other processes with open file descriptors to the same
+file. AFS does not reproduce this behavior when programs on different machines
+access the same file. Changes made to one cached copy of the file are not made
+immediately visible to other cached copies. The changes are only made visible
+to other access sites when a modified version of a file is stored back to the
+server providing its primary disk storage. Thus, one client's changes may be
+entirely overwritten by another client's modifications. The situation is
+further complicated by the possibility that dirty file chunks may be flushed
+out to the File Server before the file is closed.
+\par
+The version of AFS created for the OSF offering extends the current, untyped
+callback notion to a set of multiple, independent synchronization guarantees.
+These synchronization tokens allow functionality not offered by AFS-3,
+including byte-range mandatory locking, exclusive file opens, and read and
+write privileges over portions of a file.
+
+ \section sec5-3 Section 5.3: Improved Name Space Management
+
+\par
+Discovery of new AFS cells and their integration into each existing cell's name
+space is a completely manual operation in the current system. As the rate of
+new cell creations increases, the load imposed on system administrators also
+increases. Also, representing each cell's file space entry as a mount point
+object in the /afs directory leads to a potential problem. As the number of
+entries in the /afs directory increase, search time through the directory also
+grows.
+\par
+One improvement to this situation is to implement the top-level /afs directory
+through a Domain-style database. The database would map cell names to the set
+of server machines providing authentication and volume location services for
+that cell. The Cache Manager would query the cell database in the course of
+pathname resolution, and cache its lookup results.
+\par
+In this database-style environment, adding a new cell entry under /afs is
+accomplished by creating the appropriate database entry. The new cell
+information is then immediately accessible to all AFS clients.
+
+ \section sec5-4 Section 5.4: Read/Write Replication
+
+\par
+The AFS-3 servers and databases are currently equipped to handle read/only
+replication exclusively. However, other distributed file systems have
+demonstrated the feasibility of providing full read/write replication of data
+in environments very similar to AFS [11]. Such systems can serve as models for
+the set of required changes.
+
+ \section sec5-5 Section 5.5: Disconnected Operation
+
+\par
+Several facilities are provided by AFS so that server failures and network
+partitions may be completely or partially masked. However, AFS does not provide
+for completely disconnected operation of file system clients. Disconnected
+operation is a mode in which a client continues to access critical data during
+accidental or intentional inability to access the shared file repository. After
+some period of autonomous operation on the set of cached files, the client
+reconnects with the repository and resynchronizes the contents of its cache
+with the shared store.
+\par
+Studies of related systems provide evidence that such disconnected operation is
+feasible [11] [12]. Such a capability may be explored for AFS.
+
+ \section sec5-6 Section 5.6: Multiprocessor Support
+
+\par
+The LWP lightweight thread package used by all AFS system processes assumes
+that individual threads may execute non-preemeptively, and that all other
+threads are quiescent until control is explicitly relinquished from within the
+currently active thread. These assumptions conspire to prevent AFS from
+operating correctly on a multiprocessor platform.
+\par
+A solution to this restriction is to restructure the AFS code organization so
+that the proper locking is performed. Thus, critical sections which were
+previously only implicitly defined are explicitly specified.
+
+ \page biblio Bibliography
+
+\li [1] John H. Howard, Michael L. Kazar, Sherri G. Menees, David A. Nichols,
+M. Satyanarayanan, Robert N. Sidebotham, Michael J. West, Scale and Performance
+in a Distributed File System, ACM Transactions on Computer Systems, Vol. 6, No.
+1, February 1988, pp. 51-81.
+\li [2] Michael L. Kazar, Synchronization and Caching Issues in the Andrew File
+System, USENIX Proceedings, Dallas, TX, Winter 1988.
+\li [3] Alfred Z. Spector, Michael L. Kazar, Uniting File Systems, Unix
+Review, March 1989,
+\li [4] Johna Till Johnson, Distributed File System Brings LAN Technology to
+WANs, Data Communications, November 1990, pp. 66-67.
+\li [5] Michael Padovano, PADCOM Associates, AFS widens your horizons in
+distributed computing, Systems Integration, March 1991.
+\li [6] Steve Lammert, The AFS 3.0 Backup System, LISA IV Conference
+Proceedings, Colorado Springs, Colorado, October 1990.
+\li [7] Michael L. Kazar, Bruce W. Leverett, Owen T. Anderson, Vasilis
+Apostolides, Beth A. Bottos, Sailesh Chutani, Craig F. Everhart, W. Anthony
+Mason, Shu-Tsui Tu, Edward R. Zayas, DEcorum File System Architectural
+Overview, USENIX Conference Proceedings, Anaheim, Texas, Summer 1990.
+\li [8] AFS Drives DCE Selection, Digital Desktop, Vol. 1, No. 6,
+September 1990.
+\li [9] Levine, P.H., The Apollo DOMAIN Distributed File System, in NATO ASI
+Series: Theory and Practice of Distributed Operating Systems, Y. Paker, J-P.
+Banatre, M. Bozyigit, editors, Springer-Verlag, 1987.
+\li [10] M.N. Nelson, B.B. Welch, J.K. Ousterhout, Caching in the Sprite
+Network File System, ACM Transactions on Computer Systems, Vol. 6, No. 1,
+February 1988.
+\li [11] James J. Kistler, M. Satyanarayanan, Disconnected Operaton in the Coda
+File System, CMU School of Computer Science technical report, CMU-CS-91-166, 26
+July 1991.
+\li [12] Puneet Kumar, M. Satyanarayanan, Log-Based Directory Resolution
+in the Coda File System, CMU School of Computer Science internal document, 2
+July 1991.
+\li [13] Sun Microsystems, Inc., NFS: Network File System Protocol
+Specification, RFC 1094, March 1989.
+\li [14] Sun Microsystems, Inc,. Design and Implementation of the Sun Network
+File System, USENIX Summer Conference Proceedings, June 1985.
+\li [15] C.H. Sauer, D.W Johnson, L.K. Loucks, A.A. Shaheen-Gouda, and T.A.
+Smith, RT PC Distributed Services Overview, Operating Systems Review, Vol. 21,
+No. 3, July 1987.
+\li [16] A.P. Rifkin, M.P. Forbes, R.L. Hamilton, M. Sabrio, S. Shah, and
+K. Yueh, RFS Architectural Overview, Usenix Conference Proceedings, Atlanta,
+Summer 1986.
+\li [17] Edward R. Zayas, Administrative Cells: Proposal for Cooperative Andrew
+File Systems, Information Technology Center internal document, Carnegie Mellon
+University, 25 June 1987.
+\li [18] Ed. Zayas, Craig Everhart, Design and Specification of the Cellular
+Andrew Environment, Information Technology Center, Carnegie Mellon University,
+CMU-ITC-070, 2 August 1988.
+\li [19] Kazar, Michael L., Information Technology Center, Carnegie Mellon
+University. Ubik -A Library For Managing Ubiquitous Data, ITCID, Pittsburgh,
+PA, Month, 1988.
+\li [20] Kazar, Michael L., Information Technology Center, Carnegie Mellon
+University. Quorum Completion, ITCID, Pittsburgh, PA, Month, 1988.
+\li [21] S. R. Kleinman. Vnodes: An Architecture for Multiple file
+System Types in Sun UNIX, Conference Proceedings, 1986 Summer Usenix Technical
+Conference, pp. 238-247, El Toro, CA, 1986.
+\li [22] S.P. Miller, B.C. Neuman, J.I. Schiller, J.H. Saltzer. Kerberos
+Authentication and Authorization System, Project Athena Technical Plan, Section
+E.2.1, M.I.T., December 1987.
+\li [23] Bill Bryant. Designing an Authentication System: a Dialogue in Four
+Scenes, Project Athena internal document, M.I.T, draft of 8 February 1988.
+
+
+*/
--- /dev/null
+/*!
+
+ \page title AFS-3 Programmer's Reference: BOS Server Interface
+
+\author Edward R. Zayas
+Transarc Corporation
+\version 1.0
+\date 28 August 1991 11:58 Copyright 1991 Transarc Corporation All Rights
+Reserved FS-00-D161
+
+ \page chap1 Chapter 1: Overview
+
+ \section sec1-1 Section 1.1: Introduction
+
+\par
+One of the important duties of an AFS system administrator is to insure that
+processes on file server machines are properly installed and kept running. The
+BOS Server was written as a tool for assisting administrators in these tasks.
+An instance of the BOS Server runs on each AFS server machine, and has the
+following specific areas of responsibility:
+\li Definition of the set of processes that are to be run on the machine on
+which a given BOS Server executes. This definition may be changed dynamically
+by system administrators. Programs may be marked as continuously or
+periodically runnable.
+\li Automatic startup and restart of these specified processes upon server
+bootup and program failure. The BOS Server also responds to administrator
+requests for stopping and starting one or more of these processes. In addition,
+the BOS Server is capable of restarting itself on command.
+\li Collection of information regarding the current status, command line
+parameters, execution history, and log files generated by the set of server
+programs.
+\li Management of the security information resident on the machine on which the
+BOS Server executes. Such information includes the list of administratively
+privileged people associated with the machine and the set of AFS File Server
+encryption keys used in the course of file service.
+\li Management of the cell configuration information for the server machine in
+question. This includes the name of the cell in which the server resides, along
+with the list and locations of the servers within the cell providing AFS
+database services (e.g., volume location, authentication, protection).
+Installation of server binaries on the given machine. The BOS Server allows
+several "generations" of server software to be kept on its machine.
+Installation of new software for one or more server agents is handled by the
+BOS Server, as is "rolling back" to a previous version should it prove more
+stable than the currently-installed image.
+\par
+Execution of commands on the server machine. An administrator may execute
+arbitrary unix commands on a machine running the BOS Server.
+\par
+Unlike many other AFS server processes, the BOS Server does not maintain a
+cell-wide, replicated database. It does, however, maintain several databases
+used exclusively on every machine on which it runs.
+
+ \section sec1-2 Section 1.2: Scope
+
+\par
+This paper describes the design and structure of the AFS-3 BOS Server. The
+scope of this work is to provide readers with a sufficiently detailed
+description of the BOS Server so that they may construct client applications
+that call the server's RPC interface routines.
+
+ \section sec1-3 Section 1.3: Document Layout
+
+\par
+The second chapter discusses various aspects of the BOS Server's architecture.
+First, one of the basic concepts is examined, namely the bnode. Providing the
+complete description of a program or set of programs to be run on the given
+server machine, a bnode is the generic definitional unit for the BOS Server's
+duties. After bnodes have been explained, the set of standard directories on
+which the BOS Server depends is considered. Also, the set of well-known files
+within these directories is explored. Their uses and internal formats are
+presented. After these sections, a discussion of BOS Server restart times
+follows. The BOS Server has special support for two commonly-used restart
+occasions, as described by this section. Finally, the organization and behavior
+of the bosserver program itself is presented.
+\par
+The third and final chapter provides a detailed examination of the
+programmer-visible BOS Server constants and structures, along with a full
+specification of the API for the RPC-based BOS Server functionality.
+
+ \section sec1-4 Section 1.4: Related Documents
+
+\par
+This document is a member of a documentation suite providing programmer-level
+specifications for the operation of the various AFS servers and agents, and the
+interfaces they export, as well as the underlying RPC system they use to
+communicate. The full suite of related AFS specification documents is listed
+below:
+\li AFS-3 Programmer's Reference: Architectural Overview: This paper provides
+an architectual overview of the AFS distributed file system, describing the
+full set of servers and agents in a coherent way, illustrating their
+relationships to each other and examining their interactions.
+\li AFS-3 Programmer's Reference: File Server/Cache Manager Interface: This
+document describes the File Server and Cache Manager agents, which provide the
+backbone file managment services for AFS. The collection of File Servers for a
+cell supply centralized file storage for that site, and allow clients running
+the Cache Manager component to acces those files in a high-performance, secure
+fashion.
+\li AFS-3 Programmer's Reference:Volume Server/Volume Location Server
+Interface: This document describes the services through which "containers" of
+related user data are located and managed.
+\li AFS-3 Programmer's Reference: Protection Server Interface: This paper
+describes the server responsible for mapping printable user names to and from
+their internal AFS identifiers. The Protection Server also allows users to
+create, destroy, and manipulate "groups" of users, which are suitable for
+placement on ACLs.
+\li AFS-3 Programmer's Reference: Specification for the Rx Remote Procedure
+Call Facility: This document specifies the design and operation of the remote
+procedure call and lightweight process packages used by AFS.
+\par
+In addition to these papers, the AFS 3.1 product is delivered with its own
+user, administrator, installation, and command reference documents.
+
+ \page chap2 Chapter 2: BOS Server Architecture
+
+\par
+This chapter considers some of the architectual features of the AFS-3 BOS
+Server. First, the basic organizational and functional entity employed by the
+BOS Server, the bnode, is discussed. Next, the set of files with which the
+server interacts is examined. The notion of restart times is then explained in
+detail. Finally, the organization and components of the bosserver program
+itself, which implements the BOS Server, are presented.
+
+ \section sec2-1 Section 2.1: Bnodes
+
+ \subsection sec2-1-1 Section 2.1.1: Overview
+
+\par
+The information required to manage each AFS-related program running on a File
+Server machine is encapsulated in a bnode object. These bnodes serve as the
+basic building blocks for BOS Server services. Bnodes have two forms of
+existence:
+\li On-disk: The BosConfig file (see Section 2.3.4 below) defines the set of
+bnodes for which the BOS Server running on that machine will be responsible,
+along with specifying other information such as values for the two restart
+times. This file provides permanent storage (i.e., between bootups) for the
+desired list of programs for that server platform.
+\li In-memory: The contents of the BosConfig file are parsed and internalized
+by the BOS Server when it starts execution. The basic data for a particular
+server program is placed into a struct bnode structure.
+\par
+The initial contents of the BosConfig file are typically set up during system
+installation. The BOS Server can be directed, via its RPC interface, to alter
+existing bnode entries in the BosConfig file, add new ones, and delete old
+ones. Typically, this file is never edited directly.
+
+ \subsection sec2-1-2 Section 2.1.2: Bnode Classes
+
+\par
+The descriptions of the members of the AFS server suite fall into three broad
+classes of programs:
+\li Simple programs: This server class is populated by programs that simply
+need to be kept running, and do not depend on other programs for correctness or
+effectiveness. Examples of AFS servers falling into this category are the
+Volume Location Server, Authentication Server, and Protection Server. Since its
+members exhibit such straightforward behavior, this class of programs is
+referred to as the simple class.
+\li Interrelated programs: The File Server program depends on two other
+programs, and requires that they be executed at the appropriate times and in
+the appropriate sequence, for correct operation. The first of these programs is
+the Volume Server, which must be run concurrently with the File Server. The
+second is the salvager, which repairs the AFS volume metadata on the server
+partitions should the metadata become damaged. The salvager must not be run at
+the same time as the File Server. In honor of the File Server trio that
+inspired it, the class of programs consisting of groups of interrelated
+processes is named the fs class.
+\li Periodic programs: Some AFS servers, such as the BackupServer, only need to
+run every so often, but on a regular and well-defined basis. The name for this
+class is taken from the unix tool that is typically used to define such regular
+executions, namely the cron class.
+\par
+The recognition and definition of these three server classes is exploited by
+the BOS Server. Since all of the programs in a given class share certain common
+characteristics, they may all utilize the same basic data structures to record
+and manage their special requirements. Thus, it is not necessary to reimplement
+all the operations required to satisfy the capabilities promised by the BOS
+Server RPC interface for each and every program the BOS Server manages.
+Implementing one set of operations for each server class is sufficient to
+handle any and all server binaries to be run on the platform.
+
+ \subsection sec2-1-3 Section 2.1.3: Per-Class Bnode Operations
+
+\par
+As mentioned above, only one set of basic routines must be implemented for each
+AFS server class. Much like Sun's VFS/vnode interface [8], providing a common
+set of routines for interacting with a given file system, regardless of its
+underlying implementation and semantics, the BOS Server defines a common vector
+of operations for a class of programs to be run under the BOS Server's
+tutelage. In fact, it was this standardized file system interface that inspired
+the "bnode" name.
+\par
+The BOS Server manipulates the process or processes that are described by each
+bnode by invoking the proper functions in the appropriate order from the
+operation vector for that server class. Thus, the BOS Server itself operates in
+a class-independent fashion. This allows each class to take care of the special
+circumstances associated with it, yet to have the BOS Server itself be totally
+unaware of what special actions (if any) are needed for the class. This
+abstraction also allows more server classes to be implemented without any
+significant change to the BOS Server code itself.
+\par
+There are ten entries in this standardized class function array. The purpose
+and usage of each individual class function is described in detail in Section
+3.3.5. Much like the VFS system, a collection of macros is also provided in
+order to simplify the invocation of these functions. These macros are described
+in Section 3.5. The ten function slots are named here for convenience:
+\li create()
+\li timeout()
+\li getstat()
+\li setstat()
+\li delete()
+\li procexit()
+\li getstring()
+\li getparm()
+\li restartp()
+\li hascore()
+
+ \section sec2-2 Section 2.2: BOS Server Directories
+
+\par
+The BOS Server expects the existence of the following directories on the local
+disk of the platform on which it runs. These directories define where the
+system binaries, log files, ubik databases, and other files lie.
+\li /usr/afs/bin: This directory houses the full set of AFS server binaries.
+Such executables as bosserver, fileserver, vlserver, volserver, kaserver, and
+ptserver reside here.
+\li /usr/afs/db: This directory serves as the well-known location on the
+server's local disk for the ubik database replicas for this machine.
+Specifically, the Authentication Server, Protection Server, and the Volume
+Location Server maintain their local database images here.
+\li /usr/afs/etc: This directory hosts the files containing the security, cell,
+and authorized system administrator list for the given machine. Specifically,
+the CellServDB, KeyFile, License, ThisCell, and UserList files are stored here.
+\li /usr/afs/local: This directory houses the BosConfig file, which supplies
+the BOS Server with the permanent set of bnodes to support. Also contained in
+this directory are files used exclusively by the salvager.
+\li /usr/afs/logs: All of the AFS server programs that maintain log files
+deposit them in this directory.
+
+ \section sec2-3 Section 2.3: BOS Server Files
+
+\par
+Several files, some mentioned above, are maintained on the server's local disk
+and manipulated by the BOS Server. This section examines many of these files,
+and describes their formats.
+
+ \subsection sec2-3-1 Section 2.3.1: /usr/afs/etc/UserList
+
+\par
+This file contains the names of individuals who are allowed to issue
+"restricted" BOS Server commands (e.g., creating & deleting bnodes, setting
+cell information, etc.) on the given hardware platform. The format is
+straightforward, with one administrator name per line. If a cell grants joe and
+schmoe these rights on a machine, that particular UserList will have the
+following two lines:
+\n joe
+\n schmoe
+
+ \subsection sec2-3-2 Section 2.3.2: /usr/afs/etc/CellServDB
+
+\par
+This file identifies the name of the cell to which the given server machine
+belongs, along with the set of machines on which its ubik database servers are
+running. Unlike the CellServDB found in /usr/vice/etc on AFS client machines,
+this file contains only the entry for the home cell. It shares the formatting
+rules with the /usr/vice/etc version of CellServDB. The contents of the
+CellServDB file used by the BOS Server on host grand.central.org are:
+\code
+>grand.central.org #DARPA clearinghouse cell
+192.54.226.100 #grand.central.org
+192.54.226.101 #penn.central.org
+\endcode
+
+ \subsection sec2-3-3 Section 2.3.3: /usr/afs/etc/ThisCell
+
+\par
+The BOS Server obtains its notion of cell membership from the ThisCell file in
+the specified directory. As with the version of ThisCell found in /usr/vice/etc
+on AFS client machines, this file simply contains the character string
+identifying the home cell name. For any server machine in the grand.central.org
+cell, this file contains the following:
+\code
+grand.central.org
+\endcode
+
+ \subsection sec2-3-4 Section 2.3.4: /usr/afs/local/BosConfig
+
+\par
+The BosConfig file is the on-disk representation of the collection of bnodes
+this particular BOS Server manages. The BOS Server reads and writes to this
+file in the normal course of its affairs. The BOS Server itself, in fact,
+should be the only agent that modifies this file. Any changes to BosConfig
+should be carried out by issuing the proper RPCs to the BOS Server running on
+the desired machine.
+\par
+The following is the text of the BosConfig file on grand.central.org. A
+discussion of the contents follows immediately afterwards.
+\code
+restarttime 11 0 4 0 0 checkbintime 3 0 5 0 0
+bnode simple kaserver 1 parm /usr/afs/bin/kaserver
+end bnode simple ptserver 1 parm
+/usr/afs/bin/ptserver end bnode simple vlserver 1
+parm /usr/afs/bin/vlserver end bnode fs fs 1 parm
+/usr/afs/bin/fileserver parm /usr/afs/bin/volserver
+parm /usr/afs/bin/salvager end bnode simple runntp
+1 parm /usr/afs/bin/runntp -localclock transarc.com
+end bnode simple upserver 1 parm
+/usr/afs/bin/upserver end bnode simple
+budb_server 1 parm /usr/afs/bin/budb_server end
+bnode cron backup 1 parm
+/usr/afs/backup/clones/lib/backup.csh daily parm
+05:00 end
+\endcode
+
+\par
+The first two lines of this file set the system and new-binary restart times
+(see Section 2.4, below). They are optional, with the default system restart
+time being every Sunday at 4:00am and the new-binary restart time being 5:00am
+daily. Following the reserved words restarttime and checkbintime are five
+integers, providing the mask, day, hour, minute, and second values (in decimal)
+for the restart time, as diagrammed below:
+\code
+restarttime <mask> <day> <hour> <minute>
+<second> checkbintime <mask> <day> <hour>
+<minute> <second>
+\endcode
+
+\par
+The range of acceptable values for these fields is presented in Section 3.3.1.
+In this example, the restart line specifies a (decimal) mask value of 11,
+selecting the KTIME HOUR, KTIME MIN, and KTIME DAY bits. This indicates that
+the hour, minute, and day values are the ones to be used when matching times.
+Thus, this line requests that system restarts occur on day 0 (Sunday), hour 4
+(4:00am), and minute 0 within that hour.
+\par
+The sets of lines that follow define the individual bnodes for the particular
+machine. The first line of the bnode definition set must begin with the
+reserved word bnode, followed by the type name, the instance name, and the
+initial bnode goal:
+\code
+bnode <type_name> <instance_name> <goal_val>
+\endcode
+
+\par
+The <type name> and <instance name> fields are both character strings, and the
+<goal val> field is an integer. Acceptable values for the <type name> are
+simple, fs, and cron. Acceptable values for <goal val> are defined in Section
+3.2.3, and are normally restricted to the integer values representing BSTAT
+NORMAL and BSTAT SHUTDOWN. Thus, in the bnode line defining the Authentication
+Server, it is declared to be of type simple, have instance name kaserver, and
+have 1 (BSTAT NORMAL) as a goal (e.g., it should be brought up and kept
+running).
+\par
+Following the bnode line in the BosConfig file may be one or more parm lines.
+These entries represent the command line parameters that will be used to invoke
+the proper related program or programs. The entire text of the line after the
+parm reserved word up to the terminating newline is stored as the command line
+string.
+\code
+parm <command_line_text>
+\endcode
+
+\par
+After the parm lines, if any, the reserved word end must appear alone on a
+line, marking the end of an individual bnode definition.
+
+ \subsection sec2-3-5 Section 2.3.5: /usr/afs/local/NoAuth
+
+\par
+The appearance of this file is used to mark whether the BOS Server is to insist
+on properly authenticated connections for its restricted operations or whether
+it will allow any caller to exercise these commands. Not only is the BOS Server
+affected by the presence of this file, but so are all of the bnodes objects the
+BOS Server starts up. If /usr/afs/local/NoAuth is present, the BOS Server will
+start all of its bnodes with the -noauth flag.
+\par
+Completely unauthenticated AFS operation will result if this file is present
+when the BOS Server starts execution. The file itself is typically empty. If
+any data is put into the NoAuth file, it will be ignored by the system.
+
+ \subsection sec2-3-6 Section 2.3.6: /usr/afs/etc/KeyFile
+
+\par
+This file stores the set of AFS encryption keys used for file service
+operations. The file follows the format defined by struct afsconf key and
+struct afsconf keys in include file afs/keys.h. For the reader's convenience,
+these structures are detailed below:
+\code
+#define AFSCONF_MAXKEYS 8
+struct afsconf_key {
+ long kvno;
+ char key[8];
+};
+struct afsconf_keys {
+ long nkeys;
+ struct afsconf_key key[AFSCONF_MAXKEYS];
+};
+\endcode
+\par
+The first longword of the file reveals the number of keys that may be found
+there, with a maximum of AFSCONF MAXKEYS (8). The keys themselves follow, each
+preceded by its key version number.
+\par
+All information in this file is stored in network byte order. Each BOS Server
+converts the data to the appropriate host byte order befor storing and
+manipulating it.
+
+ \section sec2-4 Section 2.4: Restart Times
+
+\par
+It is possible to manually start or restart any server defined within the set
+of BOS Server bnodes from any AFS client machine, simply by making the
+appropriate call to the RPC interface while authenticated as a valid
+administrator (i.e., a principal listed in the UserList file on the given
+machine). However, two restart situations merit the implementation of special
+functionality within the BOS Server. There are two common occasions, occuring
+on a regular basis, where the entire system or individual server programs
+should be brought down and restarted:
+\par
+\b Complete \b system \b restart: To guard against the reliability and
+performance problems caused by any core leaks in long-running programs, the
+entire AFS system should be occasionally shut down and restarted periodically.
+This action 'clears out' the memory system, and may result in smaller memory
+images for these servers, as internal data structures are reinitialized back to
+their starting sizes. It also allows AFS partitions to be regularly examined,
+and salvaged if necessary.
+\par
+Another reason for performing a complete system restart is to commence
+execution of a new release of the BOS Server itself. The new-binary restarts
+described below do not restart the BOS Server if a new version of its software
+has been installed on the machine.
+\par
+\b New-binary \b restarts: New server software may be installed at any time
+with the assistance of the BOS Server. However, it is often not the case that
+such software installations occur as a result of the discovery of an error in
+the program or programs requiring immediate restart. On these occasions,
+restarting the given processes in prime time so that the new binaries may begin
+execution is counterproductive, causing system downtime and interfering with
+user productivity. The system administrator may wish to set an off-peak time
+when the server binaries are automatically compared to the running program
+images, and restarts take place should the on-disk binary be more recent than
+the currently running program. These restarts would thus minimize the resulting
+service disruption.
+\par
+Automatically performing these restart functions could be accomplished by
+creating cron-type bnodes that were defined to execute at the desired times.
+However, rather than force the system administrator to create and supervise
+such bnodes, the BOS Server supports the notion of an internal LWP thread with
+the same effect (see Section 2.5.2). As part of the BosConfig file defined
+above, the administrator may simply specify the values for the complete system
+restart and new-binary restart times, and a dedicated BOS Server thread will
+manage the restarts.
+\par
+Unless otherwise instructed, the BOS Server selects default times for the two
+above restart times. A complete system restart is carried out every Sunday at
+4:00am by default, and a new-binary restart is executed for each updated binary
+at 5:00am every day.
+
+ \section sec2-5 Section 2.5: The bosserver Process
+
+ \subsection sec2-5-1 Section 2.5.1: Introduction
+
+\par
+The user-space bosserver process is in charge of managing the AFS server
+processes and software images, the local security and cell database files, and
+allowing administrators to execute arbitrary programs on the server machine on
+which it runs. It also implements the RPC interface defined in the bosint.xg
+Rxgen definition file.
+
+ \subsection sec2-5-2 Section 2.5.2: Threading
+
+\par
+As with all the other AFS server agents, the BOS Server is a multithreaded
+program. It is configured so that a minimum of two lightweight threads are
+guaranteed to be allocated to handle incoming RPC calls to the BOS Server, and
+a maximum of four threads are commissioned for this task.
+\par
+In addition to these threads assigned to RPC duties, there is one other thread
+employed by the BOS Server, the BozoDaemon(). This thread is responsible for
+keeping track of the two major restart events, namely the system restart and
+the new binary restart (see Section 2.4). Every 60 seconds, this thread is
+awakened, at which time it checks to see if either deadline has occurred. If
+the complete system restart is then due, it invokes internal BOS Server
+routines to shut down the entire suite of AFS agents on that machine and then
+reexecute the BOS Server binary, which results in the restart of all of the
+server processes. If the new-binary time has arrived, the BOS Server shuts down
+the bnodes for which binaries newer than those running are available, and then
+invokes the new software.
+\par
+In general, the following procedure is used when stopping and restarting
+processes. First, the restart() operation defined for each bnode's class is
+invoked via the BOP RESTART() macro. This allows each server to take any
+special steps required before cycling its service. After that function
+completes, the standard mechanisms are used to shut down each bnode's process,
+wait until it has truly stopped its execution, and then start it back up again.
+
+ \subsection sec2-5-3 Section 2.5.3: Initialization Algorithm
+
+\par
+This section describes the procedure followed by the BOS Server from the time
+when it is invoked to the time it has properly initialized the server machine
+upon which it is executing.
+\par
+The first check performed by the BOS Server is whether or not it is running as
+root. It needs to manipulate local unix files and directories in which only
+root has been given access, so it immediately exits with an error message if
+this is not the case. The BOS Server's unix working directory is then set to be
+/usr/afs/logs in order to more easily service incoming RPC requests to fetch
+the contents of the various server log files at this location. Also, changing
+the working directory in this fashion results in any core images dumped by the
+BOS Server's wards will be left in /usr/afs/logs.
+\par
+The command line is then inspected, and the BOS Server determines whether it
+will insist on authenticated RPC connections for secure administrative
+operations by setting up the /usr/afs/local/NoAuth file appropriately (see
+Section 2.3.5). It initializes the underlying bnode package and installs the
+three known bnode types (simple, fs, and cron).
+\par
+After the bnode package is thus set up, the BOS Server ensures that the set of
+local directories on which it will depend are present; refer to Section 2.2 for
+more details on this matter. The license file in /usr/afs/etc/License is then
+read to determine the number of AFS server machines the site is allowed to
+operate, and whether the cell is allowed to run the NFS/AFS Translator
+software. This file is typically obtained in the initial system installation,
+taken from the installation tape. The BOS Server will exit unless this file
+exists and is properly formatted.
+\par
+In order to record its actions, any existing /usr/afs/logs/BosLog file is moved
+to BosLog.old, and a new version is opened in append mode. The BOS Server
+immediately writes a log entry concerning the state of the above set of
+important directories.
+\par
+At this point, the BOS Server reads the BosConfig file, which lists the set of
+bnodes for which it will be responsible. It starts up the processes associated
+with the given bnodes. Once accomplished, it invokes its internal system
+restart LWP thread (covered in Section 2.5.2 above).
+\par
+Rx initialization begins at this point, setting up the RPC infrastructure to
+receive its packets on the AFSCONF NANNYPORT, UDP port 7007. The local cell
+database is then read and internalized, followed by acquisition of the AFS
+encryption keys.
+\par
+After all of these steps have been carried out, the BOS Server has gleaned all
+of the necessary information from its environemnt and has also started up its
+wards. The final initialization action required is to start all of its listener
+LWP threads, which are devoted to executing incoming requests for the BOS
+Server RPC interface.
+
+ \subsection sec2-5-4 Section 2.5.4: Command Line Switches
+
+\par
+The BOS Server recognizes exactly one command line argument: -noauth. By
+default, the BOS Server attempts to use authenticated RPC connections (unless
+the /usr/afs/local/NoAuth file is present; see Section 2.3.5). The appearance
+of the -noauth command line flag signals that this server incarnation is to use
+unauthenticated connections for even those operations that are normally
+restricted to system administrators. This switch is essential during the
+initial AFS system installation, where the procedures followed to bootstrap AFS
+onto a new machine require the BOS Server to run before some system databases
+have been created.
+
+ \page chap3 Chapter 3: BOS Server Interface
+
+ \section sec3-1 Section 3.1: Introduction
+
+\par
+This chapter documents the API for the BOS Server facility, as defined by the
+bosint.xg Rxgen interface file and the bnode.h include file. Descriptions of
+all the constants, structures, macros, and interface functions available to the
+application programmer appear in this chapter.
+
+ \section sec3-2 Section 3.2: Constants
+
+\par
+This section covers the basic constant definitions of interest to the BOS
+Server application programmer. These definitions appear in the bosint.h file,
+automatically generated from the bosint.xg Rxgen interface file. Another file
+is exported to the programmer, namely bnode.h.
+\par
+Each subsection is devoted to describing constants falling into each of the
+following categories:
+\li Status bits
+\li Bnode activity bits
+\li Bnode states
+\li Pruning server binaries
+\li Flag bits for struct bnode proc
+\par
+One constant of general utility is BOZO BSSIZE, which defines the length in
+characters of BOS Server character string buffers, including the trailing null.
+It is defined to be 256 characters.
+
+ \subsection sec3-2-1 Section 3.2.1: Status Bits
+
+\par
+The following bit values are used in the flags field of struct bozo status, as
+defined in Section 3.3.4. They record whether or not the associated bnode
+process currently has a stored core file, whether the bnode execution was
+stopped because of an excessive number of errors, and whether the mode bits on
+server binary directories are incorrect.
+
+\par Name
+BOZO HASCORE
+\par Value
+1
+\par Description
+Does this bnode have a stored core file?
+
+\par Name
+BOZO ERRORSTOP
+\par Value
+2
+\par Description
+Was this bnode execution shut down because of an excessive number of errors
+(more than 10 in a 10 second period)?
+
+\par Name
+BOZO BADDIRACCESS
+\par Value
+3
+\par Description
+Are the mode bits on the /usr/afs directory and its descendants (etc, bin,
+logs, backup, db, local, etc/KeyFile, etc/UserList) correctly set?
+
+ \subsection sec3-2-2 Section 3.2.2: Bnode Activity Bits
+
+\par
+This section describes the legal values for the bit positions within the flags
+field of struct bnode, as defined in Section 3.3.8. They specify conditions
+related to the basic activity of the bnode and of the entities relying on it.
+
+\par Name
+BNODE NEEDTIMEOUT
+\par Value
+0x01
+\par Description
+This bnode is utilizing the timeout mechanism for invoking actions on its
+behalf.
+
+\par Name
+BNODE ACTIVE
+\par Value
+0x02
+\par Description
+The given bnode is in active service.
+
+\par Name
+BNODE WAIT
+\par Value
+0x04
+\par Description
+Someone is waiting for a status change in this bnode.
+
+\par Name
+BNODE DELETE
+\par Value
+0x08
+\par Description
+This bnode should be deleted at the earliest convenience.
+
+\par Name
+BNODE ERRORSTOP
+\par Value
+0x10
+\par Description
+This bnode decommissioned because of an excessive number of errors in its
+associated unix processes.
+
+ \subsection sec3-2-3 Section 3.2.3: Bnode States
+
+\par
+The constants defined in this section are used as values within the goal and
+fileGoal fields within a struct bnode. They specify either the current state of
+the associated bnode, or the anticipated state. In particular, the fileGoal
+field, which is the value stored on disk for the bnode, always represents the
+desired state of the bnode, whether or not it properly reflects the current
+state. For this reason, only BSTAT SHUTDOWN and BSTAT NORMAL may be used within
+the fileGoal field. The goal field may take on any of these values, and
+accurately reflects the current status of the bnode.
+
+\par Name
+BSTAT SHUTDOWN
+\par Value
+0
+\par Description
+The bnode's execution has been (should be) terminated.
+
+\par Name
+BSTAT NORMAL
+\par Value
+1
+\par Description
+The bnode is (should be) executing normally.
+
+\par Name
+BSTAT SHUTTINGDOWN
+\par Value
+2
+\par Description
+The bnode is currently being shutdown; execution has not yet ceased.
+
+\par Name
+BSTAT STARTINGUP
+\par Value
+3
+\par Description
+The bnode execution is currently being commenced; execution has not yet begun.
+
+ \subsection sec3-2-4 Section 3.2.4: Pruning Server Binaries
+
+\par
+The BOZO Prune() interface function, fully defined in Section 3.6.6.4, allows a
+properly-authenticated caller to remove ("prune") old copies of server binaries
+and core files managed by the BOS Server. This section identifies the legal
+values for the flags argument to the above function, specifying exactly what is
+to be pruned.
+
+\par Name
+BOZO PRUNEOLD
+\par Value
+1
+\par Description
+Prune all server binaries with the *.OLD extension.
+
+\par Name
+BOZO PRUNEBAK
+\par Value
+2
+\par Description
+Prune all server binaries with the *.BAK extension.
+
+\par Name
+BOZO PRUNECORE
+\par Value
+3
+\par Description
+Prune core files.
+
+ \subsection sec3-2-5 Section 3.2.5: Flag Bits for struct bnode proc
+
+\par
+This section specifies the acceptable bit values for the flags field in the
+struct bnode proc structure, as defined in Section 3.3.9. Basically, they are
+used to record whether or not the unix binary associated with the bnode has
+ever been run, and if so whether it has ever exited.
+
+\par Name
+BPROC STARTED
+\par Value
+1
+\par Description
+Has the associated unix process ever been started up?
+
+\par Name
+BPROC EXITED
+\par Value
+2
+\par Description
+Has the associated unix process ever exited?
+
+ \section sec3-3 Section 3.3: Structures
+
+\par
+This section describes the major exported BOS Server data structures of
+interest to application programmers.
+
+ \subsection sec3-3-1 Section 3.3.1: struct bozo netKTime
+
+\par
+This structure is used to communicate time values to and from the BOS Server.
+In particular, the BOZO GetRestartTime() and BOZO SetRestartTime() interface
+functions, described in Sections 3.6.2.5 and 3.6.2.6 respectively, use
+parameters declared to be of this type.
+\par
+Four of the fields in this structure specify the hour, minute, second, and day
+of the event in question. The first field in the layout serves as a mask,
+identifying which of the above four fields are to be considered when matching
+the specified time to a given reference time (most often the current time). The
+bit values that may be used for the mask field are defined in the afs/ktime.h
+include file. For convenience, their values are reproduced here, including some
+special cases at the end of the table.
+
+\par Name
+KTIME HOUR
+\par Value
+0x01
+\par Description
+Hour should match.
+
+\par Name
+KTIME MIN
+\par Value
+0x02
+\par Description
+Minute should match.
+
+\par Name
+KTIME SEC
+\par Value
+0x04
+\par Description
+Second should match.
+
+\par Name
+KTIME DAY
+\par Value
+0x08
+\par Description
+Day should match.
+
+\par Name
+KTIME TIME
+\par Value
+0x07
+\par Description
+All times should match.
+
+\par Name
+KTIME NEVER
+\par Value
+0x10
+\par Description
+Special case: never matches.
+
+\par Name
+KTIME NOW
+\par Value
+0x20
+\par Description
+Special case: right now.
+
+\n \b Fields
+\li int mask - A field of bit values used to specify which of the following
+field are to be used in computing matches.
+\li short hour - The hour, ranging in value from 0 to 23.
+\li short min - The minute, ranging in value from 0 to 59.
+\li short sec - The second, ranging in value from 0 to 59.
+\li short day - Zero specifies Sunday, other days follow in order.
+
+ \subsection sec3-3-2 Section 3.3.2: struct bozo key
+
+\par
+This structure defines the format of an AFS encryption key, as stored in the
+key file located at /usr/afs/etc/KeyFile at the host on which the BOS Server
+runs. It is used in the argument list of the BOZO ListKeys() and BOZO AddKeys()
+interface functions, as described in Sections 3.6.4.4 and 3.6.4.5 respectively.
+\n \b Fields
+\li char data[8] - The array of 8 characters representing an encryption key.
+
+ \subsection sec3-3-3 Section 3.3.3: struct bozo keyInfo
+
+\par
+This structure defines the information kept regarding a given AFS encryption
+key, as represented by a variable of type struct bozo key, as described in
+Section 3.3.2 above. A parameter of this type is used by the BOZO ListKeys()
+function (described in Section 3.6.4.4). It contains fields holding the
+associated key's modification time, a checksum on the key, and an unused
+longword field. Note that the mod sec time field listed below is a standard
+unix time value.
+\n \b Fields
+\li long mod sec - The time in seconds when the associated key was last
+modified.
+\li long mod usec - The number of microseconds elapsed since the second
+reported in the mod sec field. This field is never set by the BOS Server, and
+should always contain a zero.
+\li unsigned long keyCheckSum - The 32-bit cryptographic checksum of the
+associated key. A block of zeros is encrypted, and the first four bytes of the
+result are placed into this field.
+\li long spare2 - This longword field is currently unused, and is reserved for
+future use.
+
+ \subsection sec3-3-4 Section 3.3.4: struct bozo status
+
+\par
+This structure defines the layout of the information returned by the status
+parameter for the interface function BOZO GetInstanceInfo(), as defined in
+Section 3.6.2.3. The enclosed fields include such information as the temporary
+and long-term goals for the process instance, an array of bit values recording
+status information, start and exit times, and associated error codes and
+signals.
+\n \b Fields
+\li long goal - The short-term goal for a process instance. Settings for this
+field are BSTAT SHUTDOWN, BSTAT NORMAL, BSTAT SHUTTINGDOWN, and BSTAT
+STARTINGUP. These values are fully defined in Section 3.2.3.
+\li long fileGoal - The long-term goal for a process instance. Accepted
+settings are restricted to a subset of those used by the goal field above, as
+explained in Section 3.2.3.
+\li long procStartTime - The last time the given process instance was started.
+\li long procStarts - The number of process starts executed on the behalf of
+the given bnode.
+\li long lastAnyExit - The last time the process instance exited for any
+reason.
+\li long lastErrorExit - The last time a process exited unexpectedly.
+\li long errorCode - The last exit's return code.
+\li long errorSignal - The last signal terminating the process.
+\li long flags - BOZO HASCORE, BOZO ERRORSTOP, and BOZO BADDIRACCESS. These
+constants are fully defined in Section 3.2.1.
+\li long spare[] - Eight longword spares, currently unassigned and reserved for
+future use.
+
+ \subsection sec3-3-5 Section 3.3.5: struct bnode ops
+
+\par
+This struture defines the base set of operations that each BOS Server bnode
+type (struct bnode type, see Section 3.3.6 below) must implement. They are
+called at the appropriate times within the BOS Server code via the BOP * macros
+(see Section 3.5 and the individual descriptions therein). They allow each
+bnode type to define its own behavior in response to its particular needs.
+\n \b Fields
+\li struct bnode *(*create)() - This function is called whenever a bnode of the
+given type is created. Typically, this function will create bnode structures
+peculiar to its own type and initialize the new records. Each type
+implementation may take a different number of parameters. Note: there is no BOP
+* macro defined for this particular function; it is always called directly.
+\li int (*timeout)() - This function is called whenever a timeout action must
+be taken for this bnode type. It takes a single argument, namely a pointer to a
+type-specific bnode structure. The BOP TIMEOUT macro is defined to simplify the
+construction of a call to this function.
+\li int (*getstat)() - This function is called whenever a caller is attempting
+to get status information concerning a bnode of the given type. It takes two
+parameters, the first being a pointer to a type-specific bnode structure, and
+the second being a pointer to a longword in which the desired status value will
+be placed. The BOP GETSTAT macro is defined to simplify the construction of a
+call to this function.
+\li int (*setstat)() - This function is called whenever a caller is attempting
+to set the status information concerning a bnode of the given type. It takes
+two parameters, the first being a pointer to a type-specific bnode structure,
+and the second being a longword from which the new status value is obtained.
+The BOP SETSTAT macro is defined to simplify the construction of a call to this
+function.
+\li int (*delete)() - This function is called whenever a bnode of this type is
+being deleted. It is expected that the proper deallocation and cleanup steps
+will be performed here. It takes a single argument, a pointer to a
+type-specific bnode structure. The BOP DELETE macro is defined to simplify the
+construction of a call to this function.
+\li int (*procexit)() - This function is called whenever the unix process
+implementing the given bnode exits. It takes two parameters, the first being a
+pointer to a type-specific bnode structure, and the second being a pointer to
+the struct bnode proc (defined in Section 3.3.9), describing that process in
+detail. The BOP PROCEXIT macro is defined to simplify the construction of a
+call to this function.
+\li int (*getstring)() - This function is called whenever the status string for
+the given bnode must be fetched. It takes three parameters. The first is a
+pointer to a type-specific bnode structure, the second is a pointer to a
+character buffer, and the third is a longword specifying the size, in bytes, of
+the above buffer. The BOP GETSTRING macro is defined to simplify the
+construction of a call to this function.
+\li int (*getparm)() - This function is called whenever a particular parameter
+string for the given bnode must be fetched. It takes four parameters. The first
+is a pointer to a type-specific bnode structure, the second is a longword
+identifying the index of the desired parameter string, the third is a pointer
+to a character buffer to receive the parameter string, and the fourth and final
+argument is a longword specifying the size, in bytes, of the above buffer. The
+BOP GETPARM macro is defined to simplify the construction of a call to this
+function.
+\li int (*restartp)() - This function is called whenever the unix process
+implementing the bnode of this type is being restarted. It is expected that the
+stored process command line will be parsed in preparation for the coming
+execution. It takes a single argument, a pointer to a type-specific bnode
+structure from which the command line can be located. The BOP RESTARTP macro is
+defined to simplify the construction of a call to this function.
+\li int (*hascore)() - This function is called whenever it must be determined
+if the attached process currently has a stored core file. It takes a single
+argument, a pointer to a type-specific bnode structure from which the name of
+the core file may be constructed. The BOP HASCORE macro is defined to simplify
+the construction of a call to this function.
+
+ \subsection sec3-3-6 Section 3.3.6: struct bnode type
+
+\par
+This structure encapsulates the defining characteristics for a given bnode
+type. Bnode types are placed on a singly-linked list within the BOS Server, and
+are identified by a null-terminated character string name. They also contain
+the function array defined in Section 3.3.5, that implements the behavior of
+that object type. There are three predefined bnode types known to the BOS
+Server. Their names are simple, fs, and cron. It is not currently possible to
+dynamically define and install new BOS Server types.
+\n \b Fields
+\li struct bnode type *next - Pointer to the next bnode type definition
+structure in the list.
+\li char *name - The null-terminated string name by which this bnode type is
+identified.
+\li bnode ops *ops - The function array that defines the behavior of this given
+bnode type.
+
+ \subsection sec3-3-7 Section 3.3.7: struct bnode token
+
+\par
+This structure is used internally by the BOS Server when parsing the command
+lines with which it will start up process instances. This structure is made
+externally visible should more types of bnode types be implemented.
+\n \b Fields
+\li struct bnode token *next - The next token structure queued to the list.
+\li char *key - A pointer to the token, or parsed character string, associated
+with this entry.
+
+ \subsection sec3-3-8 Section 3.3.8: struct bnode
+
+\par
+This structure defines the essence of a BOS Server process instance. It
+contains such important information as the identifying string name, numbers
+concerning periodic execution on its behalf, the bnode's type, data on start
+and error behavior, a reference count used for garbage collection, and a set of
+flag bits.
+\n \b Fields
+\li char *name - The null-terminated character string providing the instance
+name associated with this bnode.
+\li long nextTimeout - The next time this bnode should be awakened. At the
+specified time, the bnode's flags field will be examined to see if BNODE
+NEEDTIMEOUT is set. If so, its timeout() operation will be invoked via the BOP
+TIMEOUT() macro. This field will then be reset to the current time plus the
+value kept in the period field.
+\li long period - This field specifies the time period between timeout calls.
+It is only used by processes that need to have periodic activity performed.
+\li long rsTime - The time that the BOS Server started counting restarts for
+this process instance.
+\li long rsCount - The count of the number of restarts since the time recorded
+in the rsTime field.
+\li struct bnode type *type - The type object defining this bnode's behavior.
+\li struct bnode ops *ops - This field is a pointer to the function array
+defining this bnode's basic behavior. Note that this is identical to the value
+of type->ops.
+\par
+This pointer is duplicated here for convenience. All of the BOP * macros,
+discussed in Section 3.5, reference the bnode's operation array through this
+pointer.
+\li long procStartTime - The last time this process instance was started
+(executed).
+\li long procStarts - The number of starts (executions) for this process
+instance.
+\li long lastAnyExit - The last time this process instance exited for any
+reason.
+\li long lastErrorExit - The last time this process instance exited
+unexpectedly.
+\li long errorCode - The last exit return code for this process instance.
+\li long errorSignal - The last signal that terminated this process instance.
+\li char *lastErrorName - The name of the last core file generated.
+\li short refCount - A reference count maintained for this bnode.
+\li short flags - This field contains a set of bit fields that identify
+additional status information for the given bnode. The meanings of the legal
+bit values, explained in Section 3.2.2, are: BOZO NEEDTIMEOUT, BOZO ACTIVE,
+BOZO WAIT, BOZO DELETE, and BOZO ERRORSTOP.
+\li char goal - The current goal for the process instance. It may take on any
+of the values defined in Section 3.2.3, namely BSTAT SHUTDOWN, BSTAT NORMAL,
+BSTAT SHUTTINGDOWN, and BSTAT STARTINGUP.
+\par
+This goal may be changed at will by an authorized caller. Such changes affect
+the current status of the process instance. See the description of the BOZO
+SetStatus() and BOZO SetTStatus() interface functions, defined in Sections
+3.6.3.1 and 3.6.3.2 respectively, for more details.
+\li char fileGoal - This field is similar to goal, but represents the goal
+stored in the on-file BOS Server description of this process instance. As with
+the goal field, see functions the description of the BOZO SetStatus() and BOZO
+SetTStatus() interface functions defined in Sections 3.6.3.1 and 3.6.3.2
+respectively for more details.
+
+ \subsection sec3-3-9 Section 3.3.9: struct bnode proc
+
+\par
+This structure defines all of the information known about each unix process the
+BOS Server is currently managing. It contains a reference to the bnode defining
+the process, along with the command line to be used to start the process, the
+optional core file name, the unix pid, and such things as a flag field to keep
+additional state information. The BOS Server keeps these records on a global
+singly-linked list.
+\n \b Fields
+\li struct bnode proc *next - A pointer to the BOS Server's next process
+record.
+\li struct bnode *bnode - A pointer to the bnode creating and defining this
+unix process.
+\li char *comLine - The text of the command line used to start this process.
+\li char *coreName - An optional core file component name for this process.
+\li long pid - The unix pid, if successfully created.
+\li long lastExit - This field keeps the last termination code for this
+process.
+\li long lastSignal - The last signal used to kill this process.
+\li long flags - A set of bits providing additional process state. These bits
+are fully defined in Section 3.2.5, and are: BPROC STARTED and BPROC EXITED.
+
+ \section sec3-4 Section 3.4: Error Codes
+
+\par
+This section covers the set of error codes exported by the BOS Server,
+displaying the printable phrases with which they are associated.
+
+\par Name
+BZNOTACTIVE
+\par Value
+(39424L)
+\par Description
+process not active.
+
+\par Name
+BZNOENT
+\par Value
+(39425L)
+\par Description
+no such entity.
+
+\par Name
+BZBUSY
+\par Value
+(38426L)
+\par Description
+can't do operation now.
+
+\par Name
+BZEXISTS
+\par Value
+(29427L)
+\par Description
+entity already exists.
+
+\par Name
+BZNOCREATE
+\par Value
+(39428)
+\par Description
+failed to create entity.
+
+\par Name
+BZDOM
+\par Value
+(39429L)
+\par Description
+index out of range.
+
+\par Name
+BZACCESS
+\par Value
+(39430L)
+\par Description
+you are not authorized for this operation.
+
+\par Name
+BZSYNTAX
+\par Value
+(39431L)
+\par Description
+syntax error in create parameter.
+
+\par Name
+BZIO
+\par Value
+(39432L)
+\par Description
+I/O error.
+
+\par Name
+BZNET
+\par Value
+(39433L)
+\par Description
+network problem.
+
+\par Name
+BZBADTYPE
+\par Value
+(39434L)
+\par Description
+unrecognized bnode type.
+
+ \section sec3-5 Section 3.5: Macros
+
+\par
+The BOS Server defines a set of macros that are externally visible via the
+bnode.h file. They are used to facilitate the invocation of the members of the
+struct bnode ops function array, which defines the basic operations for a given
+bnode type. Invocations appear throughout the BOS Server code, wherever bnode
+type-specific operations are required. Note that the only member of the struct
+bnode ops function array that does not have a corresponding invocation macro
+defined is create(), which is always called directly.
+
+ \subsection sec3-5-1 Section 3.5.1: BOP TIMEOUT()
+
+\code
+#define BOP_TIMEOUT(bnode) \
+((*(bnode)->ops->timeout)((bnode)))
+\endcode
+\par
+Execute the bnode type-specific actions required when a timeout action must be
+taken. This macro takes a single argument, namely a pointer to a type-specific
+bnode structure.
+
+ \subsection sec3-5-2 Section 3.5.2: BOP GETSTAT()
+
+\code
+#define BOP_GETSTAT(bnode, a) \
+((*(bnode)->ops->getstat)((bnode),(a)))
+\endcode
+\par
+Execute the bnode type-specific actions required when a caller is attempting to
+get status information concerning the bnode. It takes two parameters, the first
+being a pointer to a type-specific bnode structure, and the second being a
+pointer to a longword in which the desired status value will be placed.
+
+ \subsection sec3-5-3 Section 3.5.3: BOP SETSTAT()
+
+\code
+#define BOP_SETSTAT(bnode, a) \
+((*(bnode)->ops->setstat)((bnode),(a)))
+\endcode
+\par
+Execute the bnode type-specific actions required when a caller is attempting to
+set the status information concerning the bnode. It takes two parameters, the
+first being a pointer to a type-specific bnode structure, and the second being
+a longword from which the new status value is obtained.
+
+ \subsection sec3-5-4 Section 3.5.4: BOP DELETE()
+
+\code
+#define BOP_DELETE(bnode) \
+((*(bnode)->ops->delete)((bnode)))
+\endcode
+\par
+Execute the bnode type-specific actions required when a bnode is deleted. This
+macro takes a single argument, namely a pointer to a type-specific bnode
+structure.
+
+ \subsection sec3-5-5 Section 3.5.5: BOP PROCEXIT()
+
+\code
+#define BOP_PROCEXIT(bnode, a) \
+((*(bnode)->ops->procexit)((bnode),(a)))
+\endcode
+\par
+Execute the bnode type-specific actions required whenever the unix process
+implementing the given bnode exits. It takes two parameters, the first being a
+pointer to a type-specific bnode structure, and the second being a pointer to
+the struct bnode proc (defined in Section 3.3.9), describing that process in
+detail.
+
+ \subsection sec3-5-6 Section 3.5.6: BOP GETSTRING()
+
+\code
+#define BOP_GETSTRING(bnode, a, b) \
+((*(bnode)->ops->getstring)((bnode),(a), (b)))
+\endcode
+\par
+Execute the bnode type-specific actions required when the status string for the
+given bnode must be fetched. It takes three parameters. The first is a pointer
+to a type-specific bnode structure, the second is a pointer to a character
+buffer, and the third is a longword specifying the size, in bytes, of the above
+buffer.
+
+ \subsection sec3-5-7 Section 3.5.7: BOP GETPARM()
+
+\code
+#define BOP_GETPARM(bnode, n, b, l) \
+((*(bnode)->ops->getparm)((bnode),(n),(b),(l)))
+\endcode
+\par
+Execute the bnode type-specific actions required when a particular parameter
+string for the given bnode must be fetched. It takes four parameters. The first
+is a pointer to a type-specific bnode structure, the second is a longword
+identifying the index of the desired parameter string, the third is a pointer
+to a character buffer to receive the parameter string, and the fourth and final
+argument is a longword specifying the size, in bytes, of the above buffer.
+
+ \subsection sec3-5-8 Section 3.5.8: BOP RESTARTP()
+
+\code
+#define BOP_RESTARTP(bnode) \
+((*(bnode)->ops->restartp)((bnode)))
+\endcode
+\par
+Execute the bnode type-specific actions required when the unix process
+implementing the bnode of this type is restarted. It is expected that the
+stored process command line will be parsed in preparation for the coming
+execution. It takes a single argument, a pointer to a type-specific bnode
+structure from which the command line can be located.
+
+ \subsection sec3-5-9 Section 3.5.9: BOP HASCORE()
+
+\code
+#define BOP_HASCORE(bnode) ((*(bnode)->ops->hascore)((bnode)))
+\endcode
+\par
+Execute the bnode type-specific actions required when it must be determined
+whether or not the attached process currently has a stored core file. It takes
+a single argument, a pointer to a type-specific bnode structure from which the
+name of the core file may be constructed.
+
+ \section sec3-6 Section 3.6: Functions
+
+\par
+This section covers the BOS Server RPC interface routines. They are generated
+from the bosint.xg Rxgen file. At a high level, these functions may be seen as
+belonging to seven basic classes:
+\li Creating and removing process entries
+\li Examining process information
+\li Starting, stopping, and restarting processes
+\li Security configuration
+\li Cell configuration
+\li Installing/uninstalling server binaries
+\li Executing commands at the server
+\par
+The following is a summary of the interface functions and their purpose,
+divided according to the above classifications:
+
+\par Creating & Removing Process Entries
+
+\par Function Name
+BOZO CreateBnode()
+\par Description
+Create a process instance.
+
+\par Function Name
+BOZO DeleteBnode()
+\par Description
+Delete a process instance.
+
+\par Examining Process Information
+
+\par Function Name
+BOZO GetStatus()
+\par Description
+Get status information for the given process instance.
+
+\par Function Name
+BOZO EnumerateInstance()
+\par Description
+Get instance name from the i'th bnode.
+
+\par Function Name
+BOZO GetInstanceInfo()
+\par Description
+Get information on the given process instance.
+
+\par Function Name
+BOZO GetInstanceParm()
+\par Description
+Get text of command line associated with the given process instance.
+
+\par Function Name
+BOZO GetRestartTime()
+\par Description
+Get one of the BOS Server restart times.
+
+\par Function Name
+BOZO SetRestartTime()
+\par Description
+Set one of the BOS Server restart times.
+
+\par Function Name
+BOZOGetDates()
+\par Description
+Get the modification times for versions of a server binary file.
+
+\par Function Name
+StartBOZO GetLog()
+\par Description
+Pass the IN params when fetching a BOS Server log file.
+
+\par Function Name
+EndBOZO GetLog()
+\par Description
+Get the OUT params when fetching a BOS Server log file.
+
+\par Function Name
+GetInstanceStrings()
+\par Description
+Get strings related to a given process instance.
+
+\par Starting, Stopping & Restarting Processes
+
+\par Function Name
+BOZO SetStatus()
+\par Description
+Set process instance status and goal.
+
+\par Function Name
+BOZO SetTStatus()
+\par Description
+Start all existing process instances.
+
+\par Function Name
+BOZO StartupAll()
+\par Description
+Start all existing process instances.
+
+\par Function Name
+BOZO ShutdownAll()
+\par Description
+Shut down all process instances.
+
+\par Function Name
+BOZO RestartAll()
+\par Description
+Shut down, the restarted all process instances.
+
+\par Function Name
+BOZO ReBozo()
+\par Description
+Shut down, then restart all process instances and the BOS Server itself.
+
+\par Function Name
+BOZO Restart()
+\par Description
+Restart a given isntance.
+
+\par Function Name
+BOZO WaitAll()
+\par Description
+Wait until all process instances have reached their goals.
+
+\par Security Configuration
+
+\par Function Name
+BOZO AddSUser()
+\par Description
+Add a user to the UserList.
+
+\par Function Name
+BOZO DeleteSUser()
+\par Description
+Delete a user from the UserList.
+
+\par Function Name
+BOZO ListSUsers()
+\par Description
+Get the name of the user in a given position in the UserList file.
+
+\par Function Name
+BOZO ListKeys()
+\par Description
+List info about the key at a given index in the key file.
+
+\par Function Name
+BOZO AddKey()
+\par Description
+Add a key to the key file.
+
+\par Function Name
+BOZO DeleteKey()
+\par Description
+Delete the entry for an AFS key.
+
+\par Function Name
+BOZO SetNoAuthFlag()
+\par Description
+Enable or disable authenticated call requirements.
+
+\par Cell Configuration
+
+\par Function Name
+BOZO GetCellName()
+\par Description
+Get the name of the cell to which the BOS Server belongs.
+
+\par Function Name
+BOZO SetCellName()
+\par Description
+Set the name of the cell to which the BOS Server belongs.
+
+\par Function Name
+BOZO GetCellHost()
+\par Description
+Get the name of a database host given its index.
+
+\par Function Name
+BOZO AddCellHost()
+\par Description
+Add an entry to the list of database server hosts.
+
+\par Function Name
+BOZO DeleteCellHost()
+\par Description
+Delete an entry from the list of database server hosts.
+
+\par Installing/Uninstalling Server Binaries
+
+\par Function Name
+StartBOZO Install()
+\par Description
+Pass the IN params when installing a server binary.
+
+\par Function Name
+EndBOZO Install()
+\par Description
+Get the OUT params when installing a server binary.
+
+\par Function Name
+BOZO UnInstall()
+\par Description
+Roll back from a server binary installation.
+
+\par Function Name
+BOZO Prune()
+\par Description
+Throw away old versions of server binaries and core files.
+
+\par Executing Commands at the Server
+
+\par Function Name
+BOZO Exec()
+\par Description
+Execute a shell command at the server.
+
+\par
+All of the string parameters in these functions are expected to point to
+character buffers that are at least BOZO BSSIZE long.
+
+ \subsection sec3-6-1 Section 3.6.1: Creating and Removing Processes
+
+\par
+The two interface routines defined in this section are used for creating and
+deleting bnodes, thus determining which processe instances the BOS Server must
+manage.
+
+ \subsubsection sec3-6-1-1 Section 3.6.1.1: BOZO CreateBnode - Create a
+process instance
+
+\code
+int BOZO CreateBnode(IN struct rx connection *z conn,
+ IN char *type,
+ IN char *instance,
+ IN char *p1,
+ IN char *p2,
+ IN char *p3,
+ IN char *p4,
+ IN char *p5,
+ IN char *p6)
+\endcode
+\par Description
+This interface function allows the caller to create a bnode (process instance)
+on the server machine executing the routine.
+\par
+The instance's type is declared to be the string referenced in the type
+argument. There are three supported instance type names, namely simple, fs, and
+cron (see Section 2.1 for a detailed examination of the types of bnodes
+available).
+\par
+The bnode's name is specified via the instance parameter. Any name may be
+chosen for a BOS Server instance. However, it is advisable to choose a name
+related to the name of the actual binary being instantiated. There are eight
+well-known names already in common use, corresponding to the ASF system agents.
+They are as follows:
+\li kaserver for the Authentication Server.
+\li runntp for the Network Time Protocol Daemon (ntpd).
+\li ptserver for the Protection Server.
+\li upclient for the client portion of the UpdateServer, which brings over
+binary files from /usr/afs/bin directory and configuration files from
+/usr/afs/etc directory on the system control machine.
+\li upclientbin for the client portion of the UpdateServer, which uses the
+/usr/afs/bin directory on the binary distribution machine for this platform's
+CPU/operating system type.
+\li upclientetc for the client portion of the UpdateServer, which
+references the /usr/afs/etc directory on the system control machine.
+\li upserver for the server portion of the UpdateServer.
+\li vlserver for the Volume Location Server.
+\par
+Up to six command-line strings may be communicated in this routine, residing in
+arguments p1 through p6. Different types of bnodes allow for different numbers
+of actual server processes to be started, and the command lines required for
+such instantiation are passed in this manner.
+\par
+The given bnode's setstat() routine from its individual ops array will be
+called in the course of this execution via the BOP SETSTAT() macro.
+\par
+The BOS Server will only allow individuals listed in its locally-maintained
+UserList file to create new instances. If successfully created, the new BOS
+Server instance will be appended to the BosConfig file kept on the machine's
+local disk. The UserList and BosConfig files are examined in detail in Sections
+2.3.1 and 2.3.4 respectively.
+\par Error Codes
+BZACCESS The caller is not authorized to perform this operation.
+\n BZEXISTS The given instance already exists.
+\n BZBADTYPE Illegal value provided in the type parameter.
+\n BZNOCREATE Failed to create desired entry.
+
+ \subsubsection sec3-6-1-2 Section 3.6.1.2: BOZO DeleteBnode - Delete a
+process instance
+
+\code
+int BOZO DeleteBnode(IN struct rx connection *z conn, IN char *instance)
+\endcode
+\par Description
+This routine deletes the BOS Server bnode whose name is specified by the
+instance parameter. If an instance with that name does not exist, this
+operation fails. Similarly, if the process or processes associated with the
+given bnode have not been shut down (see the descriptions for the BOZO
+ShutdownAll() and BOZO ShutdownAll() interface functions), the operation also
+fails.
+\par
+The given bnode's setstat() and delete() routines from its individual ops array
+will be called in the course of this execution via the BOP SETSTAT() and BOP
+DELETE() macros.
+\par
+The BOS Server will only allow individuals listed in its locally-maintained
+UserList file to delete existing instances. If successfully deleted, the old
+BOS Server instance will be removed from the BosConfig file kept on the
+machine's local disk.
+\par Error Codes
+BZACCESS The caller is not authorized to perform this operation.
+\n BZNOENT The given instance name not registered with the BOS Server.
+\n BZBUSY The process(es) associated with the given instance are still active
+(i.e., a shutdown has not yet been performed or has not yet completed).
+
+ \subsection sec3-6-2 Section 3.6.2: Examining Process Information
+
+\par
+This section describes the ten interface functions that collectively allow
+callers to obtain and modify the information stored by the BOS Server to
+describe the set of process that it manages. Among the operations supported by
+the functions examined here are getting and setting status information,
+obtaining the instance parameters, times, and dates, and getting the text of
+log files on the server machine
+
+ \subsubsection sec3-6-2-1 Section 3.6.2.1: BOZO GetStatus - Get status
+information for the given process instance
+
+\code
+int BOZO GetStatus(IN struct rx connection *z conn,
+ IN char *instance,
+ OUT long *intStat,
+ OUT char **statdescr)
+\endcode
+\par Description
+This interface function looks up the bnode for the given process instance and
+places its numerical status indicator into intStat and its status string (if
+any) into a buffer referenced by statdescr.
+\par
+The set of values that may be returned in the intStat argument are defined
+fully in Section 3.2.3. Briefly, they are BSTAT STARTINGUP, BSTAT NORMAL, BSTAT
+SHUTTINGDOWN, and BSTAT SHUTDOWN.
+\par
+A buffer holding BOZO BSSIZE (256) characters is allocated, and statdescr is
+set to point to it. Not all bnodes types implement status strings, which are
+used to provide additional status information for the class. An example of one
+bnode type that does define these strings is fs, which exports the following
+status strings:
+\li "file server running"
+\li "file server up; volser down"
+\li "salvaging file system"
+\li "starting file server"
+\li "file server shutting down"
+\li "salvager shutting down"
+\li "file server shut down"
+\par
+The given bnode's getstat() routine from its individual ops array will be
+called in the course of this execution via the BOP GETSTAT() macro.
+\par Error Codes
+BZNOENT The given process instance is not registered with the BOS Server.
+
+ \subsubsection sec3-6-2-2 Section 3.6.2.2: BOZO EnumerateInstance - Get
+instance name from i'th bnode
+
+\code
+int BOZO EnumerateInstance(IN struct rx connection *z conn,
+ IN long instance,
+ OUT char **iname);
+\endcode
+\par Description
+This routine will find the bnode describing process instance number instance
+and return that instance's name in the buffer to which the iname parameter
+points. This function is meant to be used to enumerate all process instances at
+a BOS Server. The first legal instance number value is zero, which will return
+the instance name from the first registered bnode. Successive values for
+instance will return information from successive bnodes. When all bnodes have
+been thus enumerated, the BOZO EnumerateInstance() function will return BZDOM,
+indicating that the list of bnodes has been exhausted.
+\par Error Codes
+BZDOM The instance number indicated in the instance parameter does not exist.
+
+ \subsubsection sec3-6-2-3 Section 3.6.2.3: BOZO GetInstanceInfo - Get
+information on the given process instance
+
+\code
+int BOZO GetInstanceInfo(IN struct rx connection *z conn,
+ IN char *instance,
+ OUT char **type,
+ OUT struct bozo status *status)
+\endcode
+\par Description
+Given the string name of a BOS Server instance, this interface function returns
+the type of the instance and its associated status descriptor. The set of
+values that may be placed into the type parameter are simple, fs, and cron (see
+Section 2.1 for a detailed examination of the types of bnodes available). The
+status structure filled in by the call includes such information as the goal
+and file goals, the process start time, the number of times the process has
+started, exit information, and whether or not the process has a core file.
+\par Error Codes
+BZNOENT The given process instance is not registered with the BOS Server.
+
+ \subsubsection sec3-6-2-4 Section 3.6.2.4: BOZO GetInstanceParm - Get
+text of command line associated with the given process instance
+
+\code
+int BOZO GetInstanceParm(IN struct rx connection *z conn,
+ IN char *instance,
+ IN long num,
+ OUT char **parm)
+\endcode
+\par Description
+Given the string name of a BOS Server process instance and an index identifying
+the associated command line of interest, this routine returns the text of the
+desired command line. The first associated command line text for the instance
+may be acquired by setting the index parameter, num, to zero. If an index is
+specified for which there is no matching command line stored in the bnode, then
+the function returns BZDOM.
+\par Error Codes
+BZNOENT The given process instance is not registered with the BOS Server.
+\n BZDOM There is no command line text associated with index num for this
+bnode.
+
+ \subsubsection sec3-6-2-5 Section 3.6.2.5: BOZO GetRestartTime - Get
+one of the BOS Server restart times
+
+\code
+int BOZO GetRestartTime(IN struct rx connection *z conn,
+ IN long type,
+ OUT struct bozo netKTime *restartTime)
+\endcode
+\par Description
+The BOS Server maintains two different restart times, for itself and all server
+processes it manages, as described in Section 2.4. Given which one of the two
+types of restart time is desired, this routine fetches the information from the
+BOS Server. The type argument is used to specify the exact restart time to
+fetch. If type is set to one (1), then the general restart time for all agents
+on the machine is fetched. If type is set to two (2), then the new-binary
+restart time is returned. A value other than these two for the type parameter
+results in a return value of BZDOM.
+\par Error Codes
+BZDOM All illegal value was passed in via the type parameter.
+
+ \subsubsection sec3-6-2-6 Section 3.6.2.6: BOZO SetRestartTime - Set
+one of the BOS Server restart times
+
+\code
+int BOZO SetRestartTime(IN struct rx connection *z conn,
+ IN long type,
+ IN struct bozo netKTime *restartTime)
+\endcode
+\par Description
+This function is the inverse of the BOZO GetRestartTime() interface routine
+described in Section 3.6.2.5 above. Given the type of restart time and its new
+value, this routine will set the desired restart time at the BOS Server
+receiving this call. The values for the type parameter are identical to those
+used by BOZO GetRestartTime(), namely one (1) for the general restart time and
+two (2) for the new-binary restart time.
+\par
+The BOS Server will only allow individuals listed in its locally-maintained
+UserList file to set its restart times.
+\par Error Codes
+BZACCESS The caller is not authorized to perform this operation.
+\n BZDOM All illegal value was passed in via the type parameter.
+
+ \subsubsection sec3-6-2-7 Section 3.6.2.7: BOZO GetDates - Get the
+modification times for versions of a server binary file
+
+\code
+int BOZO GetDates(IN struct rx connection *z conn,
+ IN char *path,
+ OUT long *newtime,
+ OUT long *baktime,
+ OUT long *oldtime)
+\endcode
+\par Description
+Given a fully-qualified pathname identifying the particular server binary to
+examine in the path argument, this interface routine returns the modification
+time of that file, along with the modification times for the intermediate
+(.BAK) and old (.OLD) versions. The above-mentioned times are deposited into
+the newtime, baktime and oldtime arguments. Any one or all of the reported
+times may be set to zero, indicating that the associated file does not exist.
+\par Error Codes
+---None.
+
+ \subsubsection sec3-6-2-8 Section 3.6.2.8: StartBOZO GetLog - Pass the
+IN params when fetching a BOS Server log file
+
+\code
+int BOZO StartGetLog(IN struct rx connection *z conn, IN char *name)
+\endcode
+\par Description
+The BOZO GetLog() function defined in the BOS Server Rxgen interface file is
+used to acquire the contents of the given log file from the machine processing
+the call. It is defined to be a streamed function, namely one that can return
+an arbitrary amount of data. For full details on the definition and use of
+streamed functions, please refer to the Streamed Function Calls section in [4].
+\par
+This function is created by Rxgen in response to the BOZO GetLog() interface
+definition in the bosint.xg file. The StartBOZO GetLog() routine handles
+passing the IN parameters of the streamed call to the BOS Server. Specifically,
+the name parameter is used to convey the string name of the desired log file.
+For the purposes of opening the specified files at the machine being contacted,
+the current working directory for the BOS Server is considered to be
+/usr/afs/logs. If the caller is included in the locally-maintained UserList
+file, any pathname may be specified in the name parameter, and the contents of
+the given file will be fetched. All other callers must provide a string that
+does not include the slash character, as it might be used to construct an
+unauthorized request for a file outside the /usr/afs/logs directory.
+\par Error Codes
+RXGEN CC MARSHAL The transmission of the GetLog() IN parameters failed. This
+and all rxgen constant definitions are available from the rxgen consts.h
+include file.
+
+ \subsubsection sec3-6-2-9 Section 3.6.2.9: EndBOZO GetLog - Get the OUT
+params when fetching a BOS Server log file
+
+\code
+int BOZO EndGetLog(IN struct rx connection *z conn)
+\endcode
+\par Description
+This function is created by Rxgen in response to the BOZO GetLog() interface
+definition in the bosint.xg file. The EndBOZO GetLog() routine handles the
+recovery of the OUT parameters for this interface call (of which there are
+none). The utility of such functions is often the value they return. In this
+case, however, EndBOZO GetLog() always returns success. Thus, it is not even
+necessary to invoke this particular function, as it is basically a no-op.
+\par Error Codes
+---Always returns successfully.
+
+ \subsubsection sec3-6-2-10 Section 3.6.2.10: BOZO GetInstanceStrings -
+Get strings related to a given process instance
+
+\code
+int BOZO GetInstanceStrings(IN struct rx connection *z conn,
+IN char *instance,
+OUT char **errorName,
+OUT char **spare1,
+OUT char **spare2,
+OUT char **spare3)
+\endcode
+\par Description
+This interface function takes the string name of a BOS Server instance and
+returns a set of strings associated with it. At the current time, there is only
+one string of interest returned by this routine. Specifically, the errorName
+parameter is set to the error string associated with the bnode, if any. The
+other arguments, spare1 through spare3, are set to the null string. Note that
+memory is allocated for all of the OUT parameters, so the caller should be
+careful to free them once it is done.
+\par Error Codes
+BZNOENT The given process instance is not registered with the BOS Server.
+
+ \subsection sec3-6-3 Section 3.6.3: Starting, Stopping, and Restarting
+Processes
+
+\par
+The eight interface functions described in this section allow BOS Server
+clients to manipulate the execution of the process instances the BOS Server
+controls.
+
+ \subsubsection sec3-6-3-1 Section 3.6.3.1: BOZO SetStatus - Set process
+instance status and goal
+
+\code
+int BOZO SetStatus(IN struct rx connection *z conn,
+ IN char *instance,
+ IN long status)
+\endcode
+\par Description
+This routine sets the actual status field, as well as the "file goal", of the
+given instance to the value supplied in the status parameter. Legal values for
+status are taken from the set described in Section 3.2.3, specifically BSTAT
+NORMAL and BSTAT SHUTDOWN. For more information about these constants (and
+about goals/file goals), please refer to Section 3.2.3.
+\par
+The given bnode's setstat() routine from its individual ops array will be
+called in the course of this execution via the BOP SETSTAT() macro.
+\par
+The BOS Server will only allow individuals listed in its locally-maintained
+UserList file to perform this operation. If successfully modified, the BOS
+Server bnode defining the given instance will be written out to the BosConfig
+file kept on the machine's local disk.
+\par Error Codes
+BZACCESS The caller is not authorized to perform this operation.
+\n BZNOENT The given instance name not registered with the BOS Server.
+
+ \subsubsection sec3-6-3-2 Section 3.6.3.2: BOZO SetTStatus -
+Temporarily set process instance status and goal
+
+\code
+int BOZO SetTStatus(IN struct rx connection *z conn,
+ IN char *instance,
+ IN long status)
+\endcode
+\par Description
+This interface routine is much like the BOZO SetStatus(), defined in Section
+3.6.3.1 above, except that its effect is to set the instance status on a
+temporary basis. Specifically, the status field is set to the given status
+value, but the "file goal" field is not changed. Thus, the instance's stated
+goal has not changed, just its current status.
+\par
+The given bnode's setstat() routine from its individual ops array will be
+called in the course of this execution via the BOP SETSTAT() macro.
+\par
+The BOS Server will only allow individuals listed in its locally-maintained
+UserList file to perform this operation. If successfully modified, the BOS
+Server bnode defining the given instance will be written out to the BosConfig
+file kept on the machine's local disk.
+\par Error Codes
+BZACCESS The caller is not authorized to perform this operation.
+\n BZNOENT The given instance name not registered with the BOS Server.
+
+ \subsubsection sec3-6-3-3 Section 3.6.3.3: BOZO StartupAll - Start all
+existing process instances
+
+\code
+int BOZO StartupAll(IN struct rx connection *z conn)
+\endcode
+\par Description
+This interface function examines all bnodes and attempts to restart all of
+those that have not been explicitly been marked with the BSTAT SHUTDOWN file
+goal. Specifically, BOP SETSTAT() is invoked, causing the setstat() routine
+from each bnode's ops array to be called. The bnode's flags field is left with
+the BNODE ERRORSTOP bit turned off after this call.
+\par
+The given bnode's setstat() routine from its individual ops array will be
+called in the course of this execution via the BOP SETSTAT() macro.
+\par
+The BOS Server will only allow individuals listed in its locally-maintained
+UserList file to start up bnode process instances.
+\par Error Codes
+BZACCESS The caller is not authorized to perform this operation.
+
+ \subsubsection sec3-6-3-4 Section 3.6.3.4: BOZO ShutdownAll - Shut down
+all process instances
+
+\code
+int BOZO ShutdownAll(IN struct rx connection *z conn)
+\endcode
+\par Description
+This interface function iterates through all bnodes and attempts to shut them
+all down. Specifically, the BOP SETSTAT() is invoked, causing the setstat()
+routine from each bnode's ops array to be called, setting that bnode's goal
+field to BSTAT SHUTDOWN.
+\par
+The given bnode's setstat() routine from its individual ops array will be
+called in the course of this execution via the BOP SETSTAT() macro.
+\par
+The BOS Server will only allow individuals listed in its locally-maintained
+UserList file to perform this operation.
+\par Error Codes
+BZACCESS The caller is not authorized to perform this operation.
+
+ \subsubsection sec3-6-3-5 Section 3.6.3.5: BOZO RestartAll - Shut down,
+then restart all process instances
+
+\code
+int BOZO RestartAll(IN struct rx connection *z conn)
+\endcode
+\par Description
+This interface function shuts down every BOS Server process instance, waits
+until the shutdown is complete (i.e., all instances are registered as being in
+state BSTAT SHUTDOWN), and then starts them all up again. While all the
+processes known to the BOS Server are thus restarted, the invocation of the BOS
+Server itself does not share this fate. For simulation of a truly complete
+machine restart, as is necessary when an far-reaching change to a database file
+has been made, use the BOZO ReBozo() interface routine defined in Section
+3.6.3.6 below.
+\par
+The given bnode's getstat() and setstat() routines from its individual ops
+array will be called in the course of this execution via the BOP GETSTAT() and
+BOP SETSTAT() macros.
+\par
+The BOS Server will only allow individuals listed in its locally-maintained
+UserList file to restart bnode process instances.
+\par Error Codes
+BZACCESS The caller is not authorized to perform this operation.
+
+ \subsubsection sec3-6-3-6 Section 3.6.3.6: BOZO ReBozo - Shut down,
+then restart all process instances and the BOS Server itself
+
+\code
+int BOZO ReBozo(IN struct rx connection *z conn)
+\endcode
+\par Description
+This interface routine is identical to the BOZO RestartAll() call, defined in
+Section 3.6.3.5 above, except for the fact that the BOS Server itself is
+restarted in addition to all the known bnodes. All of the BOS Server's open
+file descriptors are closed, and the standard BOS Server binary image is
+started via execve().
+\par
+The given bnode's getstat() and setstat() routines from its individual ops
+array will be called in the course of this execution via the BOP GETSTAT() and
+BOP SETSTAT() macros.
+\par
+The BOS Server will only allow individuals listed in its locally-maintained
+UserList file to restart bnode process instances.
+\par Error Codes
+BZACCESS The caller is not authorized to perform this operation.
+
+ \subsubsection sec3-6-3-7 Section 3.6.3.7: BOZO Restart - Restart a
+given process instance
+
+\code
+int BOZO Restart(IN struct rx connection *z conn, IN char *instance)
+\endcode
+\par Description
+This interface function is used to shut down and then restart the process
+instance identified by the instance string passed as an argument.
+\par
+The given bnode's getstat() and setstat() routines from its individual ops
+array will be called in the course of this execution via the BOP GETSTAT() and
+BOP SETSTAT() macros.
+\par
+The BOS Server will only allow individuals listed in its locally-maintained
+UserList file to restart bnode process instances.
+\par Error Codes
+BZACCESS The caller is not authorized to perform this operation.
+\n BZNOENT The given instance name not registered with the BOS Server.
+
+ \subsubsection sec3-6-3-8 Section 3.6.3.8: BOZO WaitAll - Wait until
+all process instances have reached their goals
+
+\code
+int BOZO WaitAll(IN struct rx connection *z conn)
+\endcode
+\par Description
+This interface function is used to synchronize with the status of the bnodes
+managed by the BOS Server. Specifically, the BOZO WaitAll() call returns when
+each bnode's current status matches the value in its short-term goal field. For
+each bnode it manages, the BOS Server thread handling this call invokes the BOP
+GETSTAT() macro, waiting until the bnode's status and goals line up.
+\par
+Typically, the BOZO WaitAll() routine is used to allow a program to wait until
+all bnodes have terminated their execution (i.e., all goal fields have been set
+to BSTAT SHUTDOWN and all corresponding processes have been killed). Note,
+however, that this routine may also be used to wait until all bnodes start up.
+The true utility of this application of BOZO WaitAll() is more questionable,
+since it will return when all bnodes have simply commenced execution, which
+does not imply that they have completed their initialization phases and are
+thus rendering their normal services.
+\par
+The BOS Server will only allow individuals listed in its locally-maintained
+UserList file to wait on bnodes through this interface function.
+\par
+The given bnode's getstat() routine from its individual ops array will be
+called in the course of this execution via the BOP GETSTAT() macro.
+\par Error Codes
+BZACCESS The caller is not authorized to perform this operation.
+
+ \subsection sec3-6-4 Section 3.6.4: Security Configuration
+
+\par
+This section describes the seven BOS Server interface functions that allow a
+properly-authorized person to examine and modify certain data relating to
+system security. Specifically, it allows for manipulation of the list of
+adminstratively 'privileged' individuals, the set of Kerberos keys used for
+file service, and whether authenticated connections should be required by the
+BOS Server and all other AFS server agents running on the machine.
+
+ \subsubsection sec3-6-4-1 Section 3.6.4.1: BOZO AddSUser - Add a user
+to the UserList
+
+\code
+int BOZO AddSUser(IN struct rx connection *z conn, IN char *name);
+\endcode
+\par Description
+This interface function is used to add the given user name to the UserList file
+of priviledged BOS Server principals. Only individuals already appearing in the
+UserList are permitted to add new entries. If the given user name already
+appears in the file, the function fails. Otherwise, the file is opened in
+append mode and the name is written at the end with a trailing newline.
+\par Error Codes
+BZACCESS The caller is not authorized to perform this operation.
+\n EEXIST The individual specified by name is already on the UserList.
+\n EIO If the UserList file could not be opened or closed.
+
+ \subsubsection sec3-6-4-2 Section 3.6.4.2: BOZO DeleteSUser - Delete a
+user from the UserList
+
+\code
+int BOZO DeleteSUser(IN struct rx connection *z conn, IN char *name)
+\endcode
+\par Description
+This interface function is used to delete the given user name from the UserList
+file of priviledged BOS Server principals. Only individuals already appearing
+in the UserList are permitted to delete existing entries. The file is opened in
+read mode, and a new file named UserList.NXX is created in the same directory
+and opened in write mode. The original UserList is scanned, with each entry
+copied to the new file if it doesn't match the given name. After the scan is
+done, all files are closed, and the UserList.NXX file is renamed to UserList,
+overwriting the original.
+\par Error Codes
+BZACCESS The caller is not authorized to perform this operation.
+\n -1 The UserList file could not be opened.
+\n EIO The UserList.NXX file could not be opened, or an error occured in the
+file close operations.
+\n ENOENT The given name was not found in the original UserList file.
+
+ \subsubsection sec3-6-4-3 Section 3.6.4.3: BOZO ListSUsers - Get the
+name of the user in the given position in the UserList file
+
+\code
+int BOZO ListSUsers(IN struct rx connection *z conn,
+ IN long an,
+ OUT char **name)
+\endcode
+\par Description
+This interface function is used to request the name of priviledged user in the
+an'th slot in the BOS Server's UserList file. The string placed into the name
+parameter may be up to 256 characters long, including the trailing null.
+\par Error Codes
+The UserList file could not be opened, or an invalid value was specified for
+an.
+
+ \subsubsection sec3-6-4-4 Section 3.6.4.4: BOZO ListKeys - List info
+about the key at a given index in the key file
+
+\code
+int BOZO ListKeys(IN struct rx connection *z conn,
+ IN long an,
+ OUT long *kvno,
+ OUT struct bozo key *key,
+ OUT struct bozo keyInfo *keyinfo)
+\endcode
+\par Description
+This interface function allows its callers to specify the index of the desired
+AFS encryption key, and to fetch information regarding that key. If the caller
+is properly authorized, the version number of the specified key is placed into
+the kvno parameter. Similarly, a description of the given key is placed into
+the keyinfo parameter. When the BOS Server is running in noauth mode, the key
+itself will be copied into the key argument, otherwise the key structure will
+be zeroed. The data placed into the keyinfo argument, declared as a struct bozo
+keyInfo as defined in Section 3.3.3, is obtained as follows. The mod sec field
+is taken from the value of st mtime after stat()ing /usr/afs/etc/KeyFile, and
+the mod usec field is zeroed. The keyCheckSum is computed by an Authentication
+Server routine, which calculates a 32-bit cryptographic checksum of the key,
+encrypting a block of zeros and then using the first 4 bytes as the checksum.
+\par
+The BOS Server will only allow individuals listed in its locally-maintained
+UserList file to obtain information regarding the list of AFS keys held by the
+given BOS Server.
+\par Error Codes
+BZACCESS The caller is not authorized to perform this operation.
+\n BZDOM An invalid index was found in the an parameter.
+\n KABADKEY Defined in the exported kautils.h header file corresponding to the
+Authentication Server, this return value indicates a problem with generating
+the checksum field of the keyinfo parameter.
+
+ \subsubsection sec3-6-4-5 Section 3.6.4.5: BOZO AddKey - Add a key to
+the key file
+
+\code
+int BOZO AddKey(IN struct rx connection *z conn,
+ IN long an,
+ IN struct bozo key *key)
+\endcode
+\par Description
+This interface function allows a properly-authorized caller to set the value of
+key version number an to the given AFS key. If a slot is found in the key file
+/usr/afs/etc/KeyFile marked as key version number an, its value is overwritten
+with the key provided. If an entry for the desired key version number does not
+exist, the key file is grown, and the new entry filled with the specified
+information.
+\par
+The BOS Server will only allow individuals listed in its locally-maintained
+UserList file to add new entries into the list of AFS keys held by the BOS
+Server.
+\par Error Codes
+BZACCESS The caller is not authorized to perform this operation.
+\n AFSCONF FULL The system key file already contains the maximum number of keys
+(AFSCONF MAXKEYS, or 8). These two constant defintions are available from the
+cellconfig.h and keys.h AFS include files respectively.
+
+ \subsubsection sec3-6-4-6 Section 3.6.4.6: BOZO DeleteKey - Delete the
+entry for an AFS key
+
+\code
+int BOZO DeleteKey(IN struct rx connection *z conn,
+ IN long an)
+\endcode
+\par Description
+This interface function allows a properly-authorized caller to delete key
+version number an from the key file, /usr/afs/etc/KeyFile. The existing keys
+are scanned, and if one with key version number an is found, it is removed. Any
+keys occurring after the deleted one are shifted to remove the file entry
+entirely.
+\par
+The BOS Server will only allow individuals listed in its locally-maintained
+UserList file to delete entries from the list of AFS keys held by the BOS
+Server.
+\par Error Codes
+BZACCESS The caller is not authorized to perform this operation.
+\n AFSCONF NOTFOUND An entry for key version number an was not found. This
+constant defintion is available from the cellconfig.h AFS include file.
+
+ \subsubsection sec3-6-4-7 Section 3.6.4.7: BOZO SetNoAuthFlag - Enable
+or disable requirement for authenticated calls
+
+\code
+int BOZO SetNoAuthFlag(IN struct rx connection *z conn,
+ IN long flag)
+\endcode
+\par Description
+This interface routine controls the level of authentication imposed on the BOS
+Server and all other AFS server agents on the machine by manipulating the
+NoAuth file in the /usr/afs/local directory on the server. If the flag
+parameter is set to zero (0), the NoAuth file will be removed, instructing the
+BOS Server and AFS agents to authenenticate the RPCs they receive. Otherwise,
+the file is created as an indication to honor all RPC calls to the BOS Server
+and AFS agents, regardless of the credentials carried by callers.
+\par Error Codes
+BZACCESS The caller is not authorized to perform this operation.
+
+ \subsection sec3-6-5 Section 3.6.5: Cell Configuration
+
+\par
+The five interface functions covered in this section all have to do with
+manipulating the configuration information of the machine on which the BOS
+Server runs. In particular, one may get and set the cell name for that server
+machine, enumerate the list of server machines running database servers for the
+cell, and add and delete machines from this list.
+
+ \subsubsection sec3-6-5-1 Section 3.6.5.1: BOZO GetCellName - Get the
+name of the cell to which the BOS Server belongs
+
+\code
+int BOZO GetCellName(IN struct rx connection *z conn, OUT char **name)
+\endcode
+\par Description
+This interface routine returns the name of the cell to which the given BOS
+Server belongs. The BOS Server consults a file on its local disk,
+/usr/afs/etc/ThisCell to obtain this information. If this file does not exist,
+then the BOS Server will return a null string.
+\par Error Codes
+AFSCONF UNKNOWN The BOS Server could not access the cell name file. This
+constant defintion is available from the cellconfig.h AFS include file.
+
+ \subsubsection sec3-6-5-2 Section 3.6.5.2: BOZO SetCellName - Set the
+name of the cell to which the BOS Server belongs
+
+\code
+int BOZO SetCellName(IN struct rx connection *z conn, IN char *name)
+\endcode
+\par Description
+This interface function allows the caller to set the name of the cell to which
+the given BOS Server belongs. The BOS Server writes this information to a file
+on its local disk, /usr/afs/etc/ThisCell. The current contents of this file are
+first obtained, along with other information about the current cell. If this
+operation fails, then BOZO SetCellName() also fails. The string name provided
+as an argument is then stored in ThisCell.
+\par
+The BOS Server will only allow individuals listed in its locally-maintained
+UserList file to set the name of the cell to which the machine executing the
+given BOS Server belongs.
+\par Error Codes
+BZACCESS The caller is not authorized to perform this operation.
+\n AFSCONF NOTFOUND Information about the current cell could not be obtained.
+This constant definition, along with AFSCONF FAILURE appearing below, is
+availabel from the cellconfig.h AFS include file.
+\n AFSCONF FAILURE New cell name could not be written to file.
+
+ \subsubsection sec3-6-5-3 Section 3.6.5.3: BOZO GetCellHost - Get the
+name of a database host given its index
+
+\code
+int BOZO GetCellHost(IN struct rx connection *z conn,
+ IN long awhich,
+ OUT char **name)
+\endcode
+\par Description
+This interface routine allows the caller to get the name of the host appearing
+in position awhich in the list of hosts acting as database servers for the BOS
+Server's cell. The first valid position in the list is index zero. The host's
+name is deposited in the character buffer pointed to by name. If the value of
+the index provided in awhich is out of range, the function fails and a null
+string is placed in name.
+\par Error Codes
+BZDOM The host index in awhich is out of range.
+\n AFSCONF NOTFOUND Information about the current cell could not be obtained.
+This constant defintion may be found in the cellconfig.h AFS include file.
+
+ \subsubsection sec3-6-5-4 Section 3.6.5.4: BOZO AddCellHost - Add an
+entry to the list of database server hosts
+
+\code
+int BOZO AddCellHost(IN struct rx connection *z conn, IN char *name)
+\endcode
+\par Description
+This interface function allows properly-authorized callers to add a name to the
+list of hosts running AFS database server processes for the BOS Server's home
+cell. If the given name does not already appear in the database server list, a
+new entry will be created. Regardless, the mapping from the given name to its
+IP address will be recomputed, and the cell database file,
+/usr/afs/etc/CellServDB will be updated.
+\par
+The BOS Server will only allow individuals listed in its locally-maintained
+UserList file to add an entry to the list of host names providing database
+services for the BOS Server's home cell.
+\par Error Codes
+BZACCESS The caller is not authorized to perform this operation.
+\n AFSCONF NOTFOUND Information about the current cell could not be obtained.
+This constant defintion may be found in the cellconfig.h AFS include file.
+
+ \subsubsection sec3-6-5-5 Section 3.6.5.5: BOZO DeleteCellHost - Delete
+an entry from the list of database server hosts
+
+\code
+int BOZO DeleteCellHost(IN struct rx connection *z conn, IN char *name)
+\endcode
+\par Description
+This interface routine allows properly-authorized callers to remove a given
+name from the list of hosts running AFS database server processes for the BOS
+Server's home cell. If the given name does not appear in the database server
+list, this function will fail. Otherwise, the matching entry will be removed,
+and the cell database file, /usr/afs/etc/CellServDB will be updated.
+\par
+The BOS Server will only allow individuals listed in its locally-maintained
+UserList file to delete an entry from the list of host names providing database
+services for the BOS Server's home cell.
+\par Error Codes
+BZACCESS The caller is not authorized to perform this operation.
+\n AFSCONF NOTFOUND Information about the current cell could not be obtained.
+This constant defintion may be found in the cellconfig.h AFS include file.
+
+ \subsection sec3-6-6 Section 3.6.6: Installing/Uninstalling Server
+Binaries
+
+\par
+There are four BOS Server interface routines that allow administrators to
+install new server binaries and to roll back to older, perhaps more reliable,
+executables. They also allow for stored images of the old binaries (as well as
+core files) to be 'pruned', or selectively deleted.
+
+3.6.6.1 StartBOZO Install - Pass the IN params when installing a server binary
+
+\code
+int StartBOZO Install(IN struct rx connection *z conn,
+ IN char *path,
+ IN long size,
+ IN long flags,
+ IN long date)
+\endcode
+\par Description
+The BOZO Install() function defined in the BOS Server Rxgen interface file is
+used to deliver the executable image of an AFS server process to the given
+server machine and then installing it in the appropriate directory there. It is
+defined to be a streamed function, namely one that can deliver an arbitrary
+amount of data. For full details on the definition and use of streamed
+functions, please refer to the Streamed Function Calls section in [4].
+\par
+This function is created by Rxgen in response to the BOZO Install() interface
+definition in the bosint.xg file. The StartBOZO Install() routine handles
+passing the IN parameters of the streamed call to the BOS Server. Specifically,
+the apath argument specifies the name of the server binary to be installed
+(including the full pathname prefix, if necessary). Also, the length of the
+binary is communicated via the size argument, and the modification time the
+caller wants the given file to carry is placed in date. The flags argument is
+currently ignored by the BOS Server.
+\par
+After the above parameters are delivered with StartBOZO Install(), the BOS
+Server creates a file with the name given in the path parameter followed by a
+.NEW postfix. The size bytes comprising the text of the executable in question
+are then read over the RPC channel and stuffed into this new file. When the
+transfer is complete, the file is closed. The existing versions of the server
+binary are then 'demoted'; the *.BAK version (if it exists) is renamed to
+*.OLD. overwriting the existing *.OLD version if and only if an *.OLD version
+does not exist, or if a *.OLD exists and the .BAK file is at least seven days
+old. The main binary is then renamed to *.BAK. Finally, the *.NEW file is
+renamed to be the new standard binary image to run, and its modification time
+is set to date.
+\par
+The BOS Server will only allow individuals listed in its locally-maintained
+UserList file to install server software onto the machine on which the BOS
+Server runs.
+\par Error Codes
+BZACCESS The caller is not authorized to perform this operation.
+\n 100 An error was encountered when writing the binary image to the local disk
+file. The truncated file was closed and deleted on the BOS Server.
+\n 101 More than size bytes were delivered to the BOS Server in the RPC
+transfer of the executable image.
+\n 102 Fewer than size bytes were delivered to the BOS Server in the RPC
+transfer of the executable image.
+
+ \subsubsection sec3-6-6-2 Section 3.6.6.2: EndBOZO Install - Get the
+OUT params when installing a server binary
+
+\code
+int EndBOZO Install(IN struct rx connection *z conn)
+\endcode
+\par Description
+This function is created by Rxgen in response to the BOZO Install() interface
+definition in the bosint.xg file. The EndBOZO Install() routine handles the
+recovery of the OUT parameters for this interface call, of which there are
+none. The utility of such functions is often the value they return. In this
+case, however, EndBOZO Install() always returns success. Thus, it is not even
+necessary to invoke this particular function, as it is basically a no-op.
+\par Error Codes
+---Always returns successfully.
+
+ \subsubsection sec3-6-6-3 Section 3.6.6.3: BOZO UnInstall - Roll back
+from a server binary installation
+
+\code
+int BOZO UnInstall(IN struct rx connection *z conn, IN char *path)
+\endcode
+\par Description
+This interface function allows a properly-authorized caller to "roll back" from
+the installation of a server binary. If the *.BAK version of the server named
+path exists, it will be renamed to be the main executable file. In this case,
+the *.OLD version, if it exists, will be renamed to *.BAK.If a *.BAK version of
+the binary in question is not found, the *.OLD version is renamed as the new
+standard binary file. If neither a *.BAK or a *.OLD version of the executable
+can be found, the function fails, returning the low-level unix error generated
+at the server.
+\par
+The BOS Server will only allow individuals listed in its locally-maintained
+UserList file to roll back server software on the machine on which the BOS
+Server runs.
+\par Error Codes
+BZACCESS The caller is not authorized to perform this operation.
+
+ \subsubsection sec3-6-6-4 Section 3.6.6.4: BOZO Prune - Throw away old
+versions of server binaries and core files
+
+\code
+int BOZO Prune(IN struct rx connection *z conn, IN long flags)
+\endcode
+\par Description
+This interface routine allows a properly-authorized caller to prune the saved
+versions of server binaries resident on the machine on which the BOS Server
+runs. The /usr/afs/bin directory on the server machine is scanned in directory
+order. If the BOZO PRUNEOLD bit is set in the flags argument, every file with
+the *.OLD extension is deleted. If the BOZO PRUNEBAK bit is set in the flags
+argument, every file with the *.BAK extension is deleted. Next, the
+/usr/afs/logs directory is scanned in directory order. If the BOZO PRUNECORE
+bit is set in the flags argument, every file with a name beginning with the
+prefix core is deleted.
+\par
+The BOS Server will only allow individuals listed in its locally-maintained
+UserList file to prune server software binary versions and core files on the
+machine on which the BOS Server runs.
+\par Error Codes
+BZACCESS The caller is not authorized to perform this operation.
+
+ \subsection sec3-6-7 Section 3.6.7: Executing Commands at the Server
+
+\par
+There is a single interface function defined by the BOS Server that allows
+execution of arbitrary programs or scripts on any server machine on which a BOS
+Server process is active.
+
+3.6.7.1 BOZO Exec - Execute a shell command at the server
+
+\code
+int BOZO Exec(IN struct rx connection *z conn, IN char *cmd)
+\endcode
+\par Description
+This interface routine allows a properly-authorized caller to execute any
+desired shell command on the server on which the given BOS Server runs. There
+is currently no provision made to pipe the output of the given command's
+execution back to the caller through the RPC channel.
+\par
+The BOS Server will only allow individuals listed in its locally-maintained
+UserList file to execute arbitrary shell commands on the server machine on
+which the BOS Server runs via this call.
+\par Error Codes
+BZACCESS The caller is not authorized to perform this operation.
+
+ \page biblio Bibliography
+
+\li [1] CMU Information Technology Center. Synchronization and Caching
+Issues in the Andrew File System, USENIX Proceedings, Dallas, TX, Winter 1988.
+\li [2] Transarc Corporation. AFS 3.0 Command Reference Manual, F-30-0-D103,
+Pittsburgh, PA, April 1990.
+\li [3] Zayas, Edward R., Transarc Corporation. AFS-3 Programmer's
+Reference: Specification for the Rx Remote Procedure Call Facility, FS-00-D164,
+Pittsburgh, PA, April 1991.
+\li [4] Zayas, Edward R., Transarc Corporation. AFS-3 Programmer's Reference:
+File Server/Cache Manager Interface, FS-00-D162, Pittsburgh, PA, April 1991.
+\li [5] Transarc Corporation. AFS 3.0 System Administrator's Guide,
+F-30-0-D102, Pittsburgh, PA, April 1990.
+\li [6] Kazar, Michael L., Information Technology Center, Carnegie Mellon
+University. Ubik -A Library For Managing Ubiquitous Data, ITCID, Pittsburgh,
+PA, Month, 1988.
+\li [7] Kazar, Michael L., Information Technology Center, Carnegie Mellon
+University. Quorum Completion, ITCID, Pittsburgh, PA, Month, 1988.
+\li [8] S. R. Kleinman. Vnodes: An Architecture for Multiple file
+System Types in Sun UNIX, Conference Proceedings, 1986 Summer Usenix Technical
+Conference, pp. 238-247, El Toro, CA, 1986.
+
+*/
+
--- /dev/null
+/*!
+
+ \page title AFS-3 Programmer's Reference: File Server/Cache Manager
+Interface
+
+\author Edward R. Zayas
+Transarc Corporation
+\version 1.1
+\date 20 Aug 1991 9:38 Copyright 1991 Transarc Corporation All Rights Reserved
+FS-00-D162
+
+ \page chap1 Chapter 1: Overview
+
+ \section sec1-1 Section 1.1: Introduction
+
+ \subsection sec1-1-1 Section 1.1.1: The AFS 3.1 Distributed File System
+
+\par
+AFS 3.1 is a distributed file system (DFS) designed to meet the following set
+of requirements:
+\li Server-client model: Permanent file storage for AFS is maintained by a
+collection of file server machines. This centralized storage is accessed by
+individuals running on client machines, which also serve as the computational
+engines for those users. A single machine may act as both an AFS file server
+and client simultaneously. However, file server machines are generally assumed
+to be housed in a secure environment, behind locked doors.
+\li Scale: Unlike other existing DFSs, AFS was designed with the specific goal
+of supporting a very large user community. Unlike the rule-of-thumb ratio of 20
+client machines for every server machine (20:1) used by Sun Microsystem's NFS
+distributed file system [4][5], the AFS architecture aims at smoothly
+supporting client/server ratios more along the lines of 200:1 within a single
+installation.
+\par
+AFS also provides another, higher-level notion of scalability. Not only can
+each independently-administered AFS site, or cell, grow very large (on the
+order of tens of thousands of client machines), but individual cells may easily
+collaborate to form a single, unified file space composed of the union of the
+individual name spaces. Thus, users have the image of a single unix file system
+tree rooted at the /afs directory on their machine. Access to files in this
+tree is performed with the standard unix commands, editors, and tools,
+regardless of a file's location.
+\par
+These cells and the files they export may be geographically dispersed, thus
+requiring client machines to access remote file servers across network pathways
+varying widely in speed, latency, and reliability. The AFS architecture
+encourages this concept of a single, wide-area file system. As of this writing,
+the community AFS filespace includes sites spanning the continental United
+States and Hawaii, and also reaches overseas to various installations in
+Europe, Japan, and Australia.
+\li Performance: This is a critical consideration given the scalability and
+connectivity requirements described above. A high-performance system in the
+face of high client/server ratios and the existence of low-bandwidth,
+high-latency network connections as well as the normal high-speed ones is
+achieved by two major mechanisms:
+\li Caching: Client machines make extensive use of caching techniques wherever
+possible. One important application of this methodology is that each client is
+required to maintain a cache of files it has accessed from AFS file servers,
+performing its operations exclusively on these local copies. This file cache is
+organized in a least-recently-used (LRU) fashion. Thus, each machine will build
+a local working set of objects being referenced by its users. As long as the
+cached images remain 'current' (i.e., compatible with the central version
+stored at the file servers), operations may be performed on these files without
+further communication with the central servers. This results in significant
+reductions in network traffic and server loads, paving the way for the target
+client/server ratios.
+\par
+This file cache is typically located on the client's local hard disk, although
+a strictly in-memory cache is also supported. The disk cache has the advantage
+that its contents will survive crashes and reboots, with the expectation that
+the majority of cached objects will remain current. The local cache parameters,
+including the maximum number of blocks it may occupy on the local disk, may be
+changed on the fly. In order to avoid having the size of the client file cache
+become a limit on the length of an AFS file, caching is actually performed on
+chunks of the file. These chunks are typically 64 Kbytes in length, although
+the chunk size used by the client is settable when the client starts up.
+\li Callbacks: The use of caches by the file system, as described above, raises
+the thorny issue of cache consistency. Each client must efficiently determine
+whether its cached file chunks are identical to the corresponding sections of
+the file as stored at the server machine before allowing a user to operate on
+those chunks. AFS employs the notion of a callback as the backbone of its cache
+consistency algorithm. When a server machine delivers one or more chunks of a
+file to a client, it also includes a callback 'promise' that the client will be
+notified if any modifications are made to the data in the file. Thus, as long
+as the client machine is in possession of a callback for a file, it knows it is
+correctly synchronized with the centrally-stored version, and allows its users
+to operate on it as desired without any further interaction with the server.
+Before a file server stores a more recent version of a file on its own disks,
+it will first break all outstanding callbacks on this item. A callback will
+eventually time out, even if there are no changes to the file or directory it
+covers.
+\li Location transparency: The typical AFS user does not know which server or
+servers houses any of his or her files. In fact, the user's storage may be
+distributed among several servers. This location transparency also allows user
+data to be migrated between servers without users having to take corrective
+actions, or even becoming aware of the shift.
+\li Reliability: The crash of a server machine in any distributed file system
+will cause the information it hosts to become unavailable to the user
+community. The same effect is caused when server and client machines are
+isolated across a network partition. AFS addresses this situation by allowing
+data to be replicated across two or more servers in a read-only fashion. If the
+client machine loses contact with a particular server from which it is
+attempting to fetch data, it hunts among the remaining machines hosting
+replicas, looking for one that is still in operation. This search is performed
+without the user's knowledge or intervention, smoothly masking outages whenever
+possible. Each client machine will automatically perform periodic probes of
+machines on its list of known servers, updating its internal records concerning
+their status. Consequently, server machines may enter and exit the pool without
+administrator intervention.
+\par
+Replication also applies to the various databases employed by the AFS server
+processes. These system databases are read/write replicated with a single
+synchronization site at any instant. If a synchronization site is lost due to
+failure, the remaining database sites elect a new synchronization site
+automatically without operator intervention.
+\li Security: A production file system, especially one which allows and
+encourages transparent access between administrative domains, must be conscious
+of security issues. AFS considers the server machines as 'trusted', being kept
+behind locked doors and only directly manipulated by administrators. On the
+other hand, client machines are, by definition, assumed to exist in inherently
+insecure environments. These client machines are recognized to be fully
+accessible to their users, making AFS servers open to attacks mounted by
+possibly modified hardware, operating systems, and software from its clients.
+\li To provide credible file system security, AFS employs an authentication
+system based on the Kerberos facility developed by Project Athena at MIT
+[6][7]. Users operating from client machines are required to interact with
+Authentication Server agents running on the secure server machines to generate
+secure tokens of identity. These tokens express the user's identity in an
+encrypted fashion, and are stored in the kernel of the client machine. When the
+user attempts to fetch or store files, the server may challenge the user to
+verify his or her identity. This challenge, hidden from the user and handled
+entirely by the RPC layer, will transmit this token to the file server involved
+in the operation. The server machine, upon decoding the token and thus
+discovering the user's true identity, will allow the caller to perform the
+operation if permitted. Access control: The standard unix access control
+mechanism associates mode bits with every file and directory, applying them
+based on the user's numerical identifier and the user's membership in various
+groups. AFS has augmented this traditional access control mechanism with Access
+Control Lists (ACLs). Every AFS directory has an associated ACL which defines
+the principals or parties that may operate on all files contained in the
+directory, and which operations these principals may perform. Rights granted by
+these ACLs include read, write, delete, lookup, insert (create new files, but
+don't overwrite old files), and administer (change the ACL). Principals on
+these ACLs include individual users and groups of users. These groups may be
+defined by AFS users without administrative intervention. AFS ACLs provide for
+much finer-grained access control for its files.
+\li Administrability: Any system with the scaling goals of AFS must pay close
+attention to its ease of administration. The task of running an AFS
+installation is facilitated via the following mechanisms:
+\li Pervasive RPC interfaces: Access to AFS server agents is performed mostly
+via RPC interfaces. Thus, servers may be queried and operated upon regardless
+of their location. In combination with the security system outlined above, even
+administrative functions such as instigating backups, reconfiguring server
+machines, and stopping and restarting servers may be performed by an
+administrator sitting in front of any AFS-capable machine, as long as the
+administrator holds the proper tokens.
+\li Replication: As AFS supports read-only replication for user data and
+read-write replication for system databases, much of the system reconfiguration
+work in light of failures is performed transparently and without human
+intervention. Administrators thus typically have more time to respond to many
+common failure situations.
+\li Data mobility: Improved and balanced utilization of disk resources is
+facilitated by the fact that AFS supports transparent relocation of user data
+between partitions on a single file server machine or between two different
+machines. In a situation where a machine must be brought down for an extended
+period, all its storage may be migrated to other servers so that users may
+continue their work completely unaffected.
+\li Automated 'nanny' services: Each file server machine runs a BOS Server
+process, which assists in the machine's administration. This server is
+responsible for monitoring the health of the AFS agents under its care,
+bringing them up in the proper order after a system reboot, answering requests
+as to their status and restarting them when they fail. It also accepts commands
+to start, suspend, or resume these processes, and install new server binaries.
+Accessible via an RPC interface, this supervisory process relieves
+administrators of some oversight responsibilities and also allows them to
+perform their duties from any machine running AFS, regardless of location or
+geographic distance from the targeted file server machine.
+\li On-line backup: Backups may be performed on the data stored by the AFS file
+server machines without bringing those machines down for the duration.
+Copy-on-write 'snapshots' are taken of the data to be preserved, and tape
+backup is performed from these clones. One added benefit is that these backup
+clones are on-line and accessible by users. Thus, if someone accidentally
+deletes a file that is contained in their last snapshot, they may simply copy
+its contents as of the time the snapshot was taken back into their active
+workspace. This facility also serves to improve the administrability of the
+system, greatly reducing the number of requests to restore data from tape.
+\li On-line help: The set of provided program tools used to interact with the
+active AFS agents are self-documenting in that they will accept command-line
+requests for help, displaying descriptive text in response.
+\li Statistics: Each AFS agent facilitates collection of statistical data on
+its performance, configuration, and status via its RPC interface. Thus, the
+system is easy to monitor. One tool that takes advantage of this facility is
+the scout program. Scout polls file server machines periodically, displaying
+usage statistics, current disk capacities, and whether the server is
+unavailable. Administrators monitoring this information can thus quickly react
+to correct overcrowded disks and machine crashes.
+\li Coexistence: Many organizations currently employ other distributed file
+systems, most notably NFS. AFS was designed to run simultaneously with other
+DFSs without interfering in their operation. In fact, an NFS-AFS translator
+agent exists that allows pure-NFS client machines to transparently access files
+in the AFS community.
+\li Portability: Because AFS is implemented using the standard VFS and vnode
+interfaces pioneered and advanced by Sun Microsystems, AFS is easily portable
+between different platforms from a single vendor or from different vendors.
+
+ \subsection sec1-1-2 Section 1.1.2: Scope of this Document
+
+\par
+This document is a member of a documentation suite providing specifications of
+the operations and interfaces offered by the various AFS servers and agents.
+Specifically, this document will focus on two of these system agents:
+\li File Server: This AFS entity is responsible for providing a central disk
+repository for a particular set of files and for making these files accessible
+to properly-authorized users running on client machines. The File Server is
+implemented as a user-space process
+\li Cache Manager: This code, running within the kernel of an AFS client
+machine, is a user's representative in communicating with the File Servers,
+fetching files back and forth into the local cache as needed. The Cache Manager
+also keeps information as to the composition of its own cell as well as the
+other AFS cells in existence. It resolves file references and operations,
+determining the proper File Server (or group of File Servers) that may satisfy
+the request. In addition, it is also a reliable repository for the user's
+authentication information, holding on to their tokens and wielding them as
+necessary when challenged.
+
+ \subsection sec1-1-3 Section 1.1.3: Related Documents
+
+\par
+The full AFS specification suite of documents is listed below:
+\li AFS-3 Programmer's Reference: Architectural Overview: This paper provides
+an architectual overview of the AFS distributed file system, describing the
+full set of servers and agents in a coherent way, illustrating their
+relationships to each other and examining their interactions.
+\li AFS-3 Programmer's Reference:Volume Server/Volume Location Server
+Interface: This document describes the services through which 'containers' of
+related user data are located and managed.
+\li AFS-3 Programmer's Reference: Protection Server Interface: This paper
+describes the server responsible for providing two-way mappings between
+printable usernames and their internal AFS identifiers. The Protection Server
+also allows users to create, destroy, and manipulate 'groups' of users, which
+are suitable for placement on ACLs. AFS-3 Programmer's Reference: BOS Server
+Interface: This paper explicates the 'nanny' service described above, which
+assists in the administrability of the AFS environment.
+\li AFS-3 Programmer's Reference: Specification for the Rx Remote Procedure
+Call Facility: This document specifies the design and operation of the remote
+procedure call and lightweight process packages used by AFS.
+\par
+In addition to these papers, the AFS 3.1 product is delivered with its own
+user, administrator, installation, and command reference documents.
+
+ \section sec1-2 Section 1.2: Basic Concepts
+
+\par
+To properly understand AFS operation, specifically the tasks and objectives of
+the File Server and Cache Manager, it is necessary to introduce and explain the
+following concepts:
+\li Cell: A cell is the set of server and client machines operated by an
+administratively independent organization. The cell administrators make
+decisions concerning such issues as server deployment and configuration, user
+backup schedules, and replication strategies on their own hardware and disk
+storage completely independently from those implemented by other cell
+administrators regarding their own domains. Every client machine belongs to
+exactly one cell, and uses that information to determine the set of database
+servers it uses to locate system resources and generate authentication
+information.
+\li Volume: AFS disk partitions do not directly host individual user files or
+directories. Rather, connected subtrees of the system's directory structure are
+placed into containers called volumes. Volumes vary in size dynamically as
+objects are inserted, overwritten, and deleted. Each volume has an associated
+quota, or maximum permissible storage. A single unix disk partition may host
+one or more volumes, and in fact may host as many volumes as physically fit in
+the storage space. However, a practical maximum is 3,500 volumes per disk
+partition, since this is the highest number currently handled by the salvager
+program. The salvager is run on occasions where the volume structures on disk
+are inconsistent, repairing the damage. A compile-time constant within the
+salvager imposes the above limit, causing it to refuse to repair any
+inconsistent partition with more than 3,500 volumes. Volumes serve many
+purposes within AFS. First, they reduce the number of objects with which an
+administrator must be concerned, since operations are normally performed on an
+entire volume at once (and thus on all files and directories contained within
+the volume). In addition, volumes are the unit of replication, data mobility
+between servers, and backup. Disk utilization may be balanced by transparently
+moving volumes between partitions.
+\li Mount Point: The connected subtrees contained within individual volumes
+stored at AFS file server machines are 'glued' to their proper places in the
+file space defined by a site, forming a single, apparently seamless unix tree.
+These attachment points are referred to as mount points. Mount points are
+persistent objects, implemented as symbolic links whose contents obey a
+stylized format. Thus, AFS mount points differ from NFS-style mounts. In the
+NFS environment, the user dynamically mounts entire remote disk partitions
+using any desired name. These mounts do not survive client restarts, and do not
+insure a uniform namespace between different machines.
+\par
+As a Cache Manager resolves an AFS pathname as part of a file system operation
+initiated by a user process, it recognizes mount points and takes special
+action to resolve them. The Cache Manager consults the appropriate Volume
+Location Server to discover the File Server (or set of File Servers) hosting
+the indicated volume. This location information is cached, and the Cache
+Manager then proceeds to contact the listed File Server(s) in turn until one is
+found that responds with the contents of the volume's root directory. Once
+mapped to a real file system object, the pathname resolution proceeds to the
+next component.
+\li Database Server: A set of AFS databases is required for the proper
+functioning of the system. Each database may be replicated across two or more
+file server machines. Access to these databases is mediated by a database
+server process running at each replication site. One site is declared to be the
+synchronization site, the sole location accepting requests to modify the
+databases. All other sites are read-only with respect to the set of AFS users.
+When the synchronization site receives an update to its database, it
+immediately distributes it to the other sites. Should a synchronization site go
+down through either a hard failure or a network partition, the remaining sites
+will automatically elect a new synchronization site if they form a quorum, or
+majority. This insures that multiple synchronization sites do not become active
+in the network partition scenario.
+\par
+The classes of AFS database servers are listed below:
+\li Authentication Server: This server maintains the authentication database
+used to generate tokens of identity.
+\li Protection Server: This server maintains mappings between human-readable
+user account names and their internal numerical AFS identifiers. It also
+manages the creation, manipulation, and update of user-defined groups suitable
+for use on ACLs.
+\li Volume Location Server: This server exports information concerning the
+location of the individual volumes housed within the cell.
+
+ \section sec1-3 Section 1.3: Document Layout
+
+\par
+Following this introduction and overview, Chapter 2 describes the architecture
+of the File Server process design. Similarly, Chapter 3 describes the
+architecture of the in-kernel Cache Manager agent. Following these
+architectural examinations, Chapter 4 provides a set of basic coding
+definitions common to both the AFS File Server and Cache Manager, required to
+properly understand the interface specifications which follow. Chapter 5 then
+proceeds to specify the various File Server interfaces. The myriad Cache
+Manager interfaces are presented in Chapter 6, thus completing the document.
+
+ \page chap2 Chapter 2: File Server Architecture
+
+ \section sec2-1 Section 2.1: Overview
+
+\par
+The AFS File Server is a user-level process that presides over the raw disk
+partitions on which it supports one or more volumes. It provides 'half' of the
+fundamental service of the system, namely exporting and regimenting access to
+the user data entrusted to it. The Cache Manager provides the other half,
+acting on behalf of its human users to locate and access the files stored on
+the file server machines.
+\par
+This chapter examines the structure of the File Server process. First, the set
+of AFS agents with which it must interact are discussed. Next, the threading
+structure of the server is examined. Some details of its handling of the race
+conditions created by the callback mechanism are then presented. This is
+followed by a discussion of the read-only volume synchronization mechanism.
+This functionality is used in each RPC interface call and intended to detect
+new releases of read-only volumes. File Servers do not generate callbacks for
+objects residing in read-only volumes, so this synchronization information is
+used to implement a 'whole-volume' callback. Finally, the fact that the File
+Server may drop certain information recorded about the Cache Managers with
+which it has communicated and yet guarantee correctness of operation is
+explored.
+
+ \section sec2-2 Section 2.2: Interactions
+
+\par
+By far the most frequent partner in File Server interactions is the set of
+Cache Managers actively fetching and storing chunks of data files for which the
+File Server provides central storage facilities. The File Server also
+periodically probes the Cache Managers recorded in its tables with which it has
+recently dealt, determining if they are still active or whether their records
+might be garbage-collected.
+\par
+There are two other server entities with which the File Server interacts,
+namely the Protection Server and the BOS Server. Given a fetch or store request
+generated by a Cache Manager, the File Server needs to determine if the caller
+is authorized to perform the given operation. An important step in this process
+is to determine what is referred to as the caller's Current Protection
+Subdomain, or CPS. A user's CPS is a list of principals, beginning with the
+user's internal identifier, followed by the the numerical identifiers for all
+groups to which the user belongs. Once this CPS information is determined, the
+File Server scans the ACL controlling access to the file system object in
+question. If it finds that the ACL contains an entry specifying a principal
+with the appropriate rights which also appears in the user's CPS, then the
+operation is cleared. Otherwise, it is rejected and a protection violation is
+reported to the Cache Manager for ultimate reflection back to the caller.
+\par
+The BOS Server performs administrative operations on the File Server process.
+Thus, their interactions are quite one-sided, and always initiated by the BOS
+Server. The BOS Server does not utilize the File Server's RPC interface, but
+rather generates unix signals to achieve the desired effect.
+
+ \section sec2-3 Section 2.3: Threading
+
+\par
+The File Server is organized as a multi-threaded server. Its threaded behavior
+within a single unix process is achieved by use of the LWP lightweight process
+facility, as described in detail in the companion "AFS-3 Programmer's
+Reference: Specification for the Rx Remote Procedure Call Facility" document.
+The various threads utilized by the File Server are described below:
+\li WorkerLWP: This lightweight process sleeps until a request to execute one
+of the RPC interface functions arrives. It pulls the relevant information out
+of the request, including any incoming data delivered as part of the request,
+and then executes the server stub routine to carry out the operation. The
+thread finishes its current activation by feeding the return code and any
+output data back through the RPC channel back to the calling Cache Manager. The
+File Server initialization sequence specifies that at least three but no more
+than six of these WorkerLWP threads are to exist at any one time. It is
+currently not possible to configure the File Server process with a different
+number of WorkerLWP threads.
+\li FiveMinuteCheckLWP: This thread runs every five minutes, performing such
+housekeeping chores as cleaning up timed-out callbacks, setting disk usage
+statistics, and executing the special handling required by certain AIX
+implementations. Generally, this thread performs activities that do not take
+unbounded time to accomplish and do not block the thread. If reassurance is
+required, FiveMinuteCheckLWP can also be told to print out a banner message to
+the machine's console every so often, stating that the File Server process is
+still running. This is not strictly necessary and an artifact from earlier
+versions, as the File Server's status is now easily accessible at any time
+through the BOS Server running on its machine.
+\li HostCheckLWP: This thread, also activated every five minutes, performs
+periodic checking of the status of Cache Managers that have been previously
+contacted and thus appear in this File Server's internal tables. It generates
+RXAFSCB Probe() calls from the Cache Manager interface, and may find itself
+suspended for an arbitrary amount of time when it enounters unreachable Cache
+Managers.
+
+ \section sec2-4 Section 2.4: Callback Race Conditions
+
+\par
+Callbacks serve to implement the efficient AFS cache consistency mechanism, as
+described in Section 1.1.1. Because of the asynchronous nature of callback
+generation and the multi-threaded operation and organization of both the File
+Server and Cache Manager, race conditions can arise in their use. As an
+example, consider the case of a client machine fetching a chunk of file X. The
+File Server thread activated to carry out the operation ships the contents of
+the chunk and the callback information over to the requesting Cache Manager.
+Before the corresponding Cache Manager thread involved in the exchange can be
+scheduled, another request arrives at the File Server, this time storing a
+modified image of the same chunk from file X. Another worker thread comes to
+life and completes processing of this second request, including execution of an
+RXAFSCB CallBack() to the Cache Manager who still hasn't picked up on the
+results of its fetch operation. If the Cache Manager blindly honors the RXAFSCB
+CallBack() operation first and then proceeds to process the fetch, it will wind
+up believing it has a callback on X when in reality it is out of sync with the
+central copy on the File Server. To resolve the above class of callback race
+condition, the Cache Manager effectively doublechecks the callback information
+received from File Server calls, making sure they haven't already been
+nullified by other file system activity.
+
+ \section sec2-5 Section 2.5: Read-Only Volume Synchronization
+
+\par
+The File Server issues a callback for each file chunk it delivers from a
+read-write volume, thus allowing Cache Managers to efficiently synchronize
+their local caches with the authoritative File Server images. However, no
+callbacks are issued when data from read-only volumes is delivered to clients.
+Thus, it is possible for a new snapshot of the read-only volume to be
+propagated to the set of replication sites without Cache Managers becoming
+aware of the event and marking the appropriate chunks in their caches as stale.
+Although the Cache Manager refreshes its volume version information
+periodically (once an hour), there is still a window where a Cache Manager will
+fail to notice that it has outdated chunks.
+\par
+The volume synchronization mechanism was defined to close this window,
+resulting in what is nearly a 'whole-volume' callback device for read-only
+volumes. Each File Server RPC interface function handling the transfer of file
+data is equipped with a parameter (a volSyncP), which carries this volume
+synchronization information. This parameter is set to a non-zero value by the
+File Server exclusively when the data being fetched is coming from a read-only
+volume. Although the struct AFSVolSync defined in Section 5.1.2.2 passed via a
+volSyncP consists of six longwords, only the first one is set. This leading
+longword carries the creation date of the read-only volume. The Cache Manager
+immediately compares the synchronization value stored in its cached volume
+information against the one just received. If they are identical, then the
+operation is free to complete, secure in the knowledge that all the information
+and files held from that volume are still current. A mismatch, though,
+indicates that every file chunk from this volume is potentially out of date,
+having come from a previous release of the read-only volume. In this case, the
+Cache Manager proceeds to mark every chunk from this volume as suspect. The
+next time the Cache Manager considers accessing any of these chunks, it first
+checks with the File Server it came from which the chunks were obtained to see
+if they are up to date.
+
+ \section sec2-6 Section 2.6: Disposal of Cache Manager Records
+
+\par
+Every File Server, when first starting up, will, by default, allocate enough
+space to record 20,000 callback promises (see Section 5.3 for how to override
+this default). Should the File Server fully populate its callback records, it
+will not allocate more, allowing its memory image to possibly grow in an
+unbounded fashion. Rather, the File Server chooses to break callbacks until it
+acquires a free record. All reachable Cache Managers respond by marking their
+cache entries appropriately, preserving the consistency guarantee. In fact, a
+File Server may arbitrarily and unilaterally purge itself of all records
+associated with a particular Cache Manager. Such actions will reduce its
+performance (forcing these Cache Managers to revalidate items cached from that
+File Server) without sacrificing correctness.
+
+ \page chap3 Chapter 3: Cache Manager Architecture
+
+ \section sec3-1 Section 3.1: Overview
+
+\par
+The AFS Cache Manager is a kernel-resident agent with the following duties and
+responsibilities:
+\li Users are to be given the illusion that files stored in the AFS distributed
+file system are in fact part of the local unix file system of their client
+machine. There are several areas in which this illusion is not fully realized:
+\li Semantics: Full unix semantics are not maintained by the set of agents
+implementing the AFS distributed file system. The largest deviation involves
+the time when changes made to a file are seen by others who also have the file
+open. In AFS, modifications made to a cached copy of a file are not necessarily
+reflected immediately to the central copy (the one hosted by File Server disk
+storage), and thus to other cache sites. Rather, the changes are only
+guaranteed to be visible to others who simultaneously have their own cached
+copies open when the modifying process executes a unix close() operation on the
+file.
+\par
+This differs from the semantics expected from the single-machine, local unix
+environment, where writes performed on one open file descriptor are immediately
+visible to all processes reading the file via their own file descriptors. Thus,
+instead of the standard "last writer wins" behavior, users see "last closer
+wins" behavior on their AFS files. Incidentally, other DFSs, such as NFS, do
+not implement full unix semantics in this case either.
+\li Partial failures: A panic experienced by a local, single-machine unix file
+system will, by definition, cause all local processes to terminate immediately.
+On the other hand, any hard or soft failure experienced by a File Server
+process or the machine upon which it is executing does not cause any of the
+Cache Managers interacting with it to crash. Rather, the Cache Managers will
+now have to reflect their failures in getting responses from the affected File
+Server back up to their callers. Network partitions also induce the same
+behavior. From the user's point of view, part of the file system tree has
+become inaccessible. In addition, certain system calls (e.g., open() and
+read()) may return unexpected failures to their users. Thus, certain coding
+practices that have become common amongst experienced (single-machine) unix
+programmers (e.g., not checking error codes from operations that "can't" fail)
+cause these programs to misbehave in the face of partial failures.
+\par
+To support this transparent access paradigm, the Cache Manager proceeds to:
+\li Intercept all standard unix operations directed towards AFS objects,
+mapping them to references aimed at the corresponding copies in the local
+cache.
+\li Keep a synchronized local cache of AFS files referenced by the client
+machine's users. If the chunks involved in an operation reading data from an
+object are either stale or do not exist in the local cache, then they must be
+fetched from the File Server(s) on which they reside. This may require a query
+to the volume location service in order to locate the place(s) of residence.
+Authentication challenges from File Servers needing to verify the caller's
+identity are handled by the Cache Manager, and the chunk is then incorporated
+into the cache.
+\li Upon receipt of a unix close, all dirty chunks belonging to the object will
+be flushed back to the appropriate File Server.
+\li Callback deliveries and withdrawals from File Servers must be processed,
+keeping the local cache in close synchrony with the state of affairs at the
+central store.
+\li Interfaces are also be provided for those principals who wish to perform
+AFS-specific operations, such as Access Control List (ACL) manipulations or
+changes to the Cache Manager's configuration.
+\par
+This chapter takes a tour of the Cache Manager's architecture, and examines how
+it supports these roles and responsibilities. First, the set of AFS agents with
+which it must interact are discussed. Next, some of the Cache Manager's
+implementation and interface choices are examined. Finally, the server's
+ability to arbitrarily dispose of callback information without affecting the
+correctness of the cache consistency algorithm is explained.
+
+ \section sec3-2 Section 3.2: Interactions
+
+\par
+The main AFS agent interacting with a Cache Manager is the File Server. The
+most common operation performed by the Cache Manager is to act as its users'
+agent in fetching and storing files to and from the centralized repositories.
+Related to this activity, a Cache Manager must be prepared to answer queries
+from a File Server concerning its health. It must also be able to accept
+callback revocation notices generated by File Servers. Since the Cache Manager
+not only engages in data transfer but must also determine where the data is
+located in the first place, it also directs inquiries to Volume Location Server
+agents. There must also be an interface allowing direct interactions with both
+common and administrative users. Certain AFS-specific operations must be made
+available to these parties. In addition, administrative users may desire to
+dynamically reconfigure the Cache Manager. For example, information about a
+newly-created cell may be added without restarting the client's machine.
+
+ \section sec3-3 Section 3.3: Implementation Techniques
+
+\par
+The above roles and behaviors for the Cache Manager influenced the
+implementation choices and methods used to construct it, along with the desire
+to maximize portability. This section begins by showing how the VFS/vnode
+interface, pioneered and standardized by Sun Microsystems, provides not only
+the necessary fine-grain access to user file system operations, but also
+facilitates Cache Manager ports to new hardware and operating system platforms.
+Next, the use of unix system calls is examined. Finally, the threading
+structure employed is described.
+
+ \subsection sec3-3-1 Section 3.3.1: VFS Interface
+
+\par
+As mentioned above, Sun Microsystems has introduced and propagated an important
+concept in the file system world, that of the Virtual File System (VFS)
+interface. This abstraction defines a core collection of file system functions
+which cover all operations required for users to manipulate their data. System
+calls are written in terms of these standardized routines. Also, the associated
+vnode concept generalizes the original unix inode idea and provides hooks for
+differing underlying environments. Thus, to port a system to a new hardware
+platform, the system programmers have only to construct implementations of this
+base array of functions consistent with the new underlying machine.
+\par
+The VFS abstraction also allows multiple file systems (e.g., vanilla unix, DOS,
+NFS, and AFS) to coexist on the same machine without interference. Thus, to
+make a machine AFS-capable, a system designer first extends the base vnode
+structure in well-defined ways in order to store AFS-specific operations with
+each file description. Then, the base function array is coded so that calls
+upon the proper AFS agents are made to accomplish each function's standard
+objectives. In effect, the Cache Manager consists of code that interprets the
+standard set of unix operations imported through this interface and executes
+the AFS protocols to carry them out.
+
+ \subsection sec3-3-2 Section 3.3.2: System Calls
+
+\par
+As mentioned above, many unix system calls are implemented in terms of the base
+function array of vnode-oriented operations. In addition, one existing system
+call has been modified and two new system calls have been added to perform
+AFS-specific operations apart from the Cache Manager's unix 'emulation'
+activities. The standard ioctl() system call has been augmented to handle
+AFS-related operations on objects accessed via open unix file descriptors. One
+of the brand-new system calls is pioctl(), which is much like ioctl() except it
+names targeted objects by pathname instead of file descriptor. Another is afs
+call(), which is used to initialize the Cache Manager threads, as described in
+the section immediately following.
+
+ \subsection sec3-3-3 Section 3.3.3: Threading
+
+\par
+In order to execute its many roles, the Cache Manager is organized as a
+multi-threaded entity. It is implemented with (potentially multiple
+instantiations of) the following three thread classes:
+\li CallBack Listener: This thread implements the Cache Manager callback RPC
+interface, as described in Section 6.5.
+\li Periodic Maintenance: Certain maintenance and checkup activities need to be
+performed at five set intervals. Currently, the frequency of each of these
+operations is hard-wired. It would be a simple matter, though, to make these
+times configurable by adding command-line parameters to the Cache Manager.
+\li Thirty seconds: Flush pending writes for NFS clients coming in through the
+NFS-AFS Translator facility.
+\li One minute: Make sure local cache usage is below the assigned quota, write
+out dirty buffers holding directory data, and keep flock()s alive.
+\li Three minutes: Check for the resuscitation of File Servers previously
+determined to be down, and check the cache of previously computed access
+information in light of any newly expired tickets.
+\li Ten minutes: Check health of all File Servers marked as active, and
+garbage-collect old RPC connections.
+\li One hour: Check the status of the root AFS volume as well as all cached
+information concerning read-only volumes.
+\li Background Operations: The Cache Manager is capable of prefetching file
+system objects, as well as carrying out delayed stores, occurring sometime
+after a close() operation. At least two threads are created at Cache Manager
+initialization time and held in reserve to carry out these objectives. This
+class of background threads implements the following three operations:
+\li Prefetch operation: Fetches particular file system object chunks in the
+expectation that they will soon be needed.
+\li Path-based prefetch operation: The prefetch daemon mentioned above operates
+on objects already at least partly resident in the local cache, referenced by
+their vnode. The path-based prefetch daemon performs the same actions, but on
+objects named solely by their unix pathname.
+\li Delayed store operation: Flush all modified chunks from a file system
+object to the appropriate File Server's disks.
+
+ \section sec3-4 Section 3.4: Disposal of Cache Manager Records
+
+\par
+The Cache Manager is free to throw away any or all of the callbacks it has
+received from the set of File Servers from which it has cached files. This
+housecleaning does not in any way compromise the correctness of the AFS cache
+consistency algorithm. The File Server RPC interface described in this paper
+provides a call to allow a Cache Manager to advise of such unilateral
+jettisoning. However, failure to use this routine still leaves the machine's
+cache consistent. Let us examine the case of a Cache Manager on machine C
+disposing of its callback on file X from File Server F. The next user access on
+file X on machine C will cause the Cache Manager to notice that it does not
+currently hold a callback on it (although the File Server will think it does).
+The Cache Manager on C attempts to revalidate its entry when it is entirely
+possible that the file is still in sync with the central store. In response,
+the File Server will extend the existing callback information it has and
+deliver the new promise to the Cache Manager on C. Now consider the case where
+file X is modified by a party on a machine other than C before such an access
+occurs on C. Under these circumstances, the File Server will break its callback
+on file X before performing the central update. The Cache Manager on C will
+receive one of these "break callback" messages. Since it no longer has a
+callback on file X, the Cache Manager on C will cheerfully acknowledge the File
+Server's notification and move on to other matters. In either case, the
+callback information for both parties will eventually resynchronize. The only
+potential penalty paid is extra inquiries by the Cache Manager and thus
+providing for reduced performance instead of failure of operation.
+
+ \page chap4 Chapter 4: Common Definitions and Data Structures
+
+\par
+This chapter discusses the definitions used in common by the File Server and
+the Cache Manager. They appear in the common.xg file, used by Rxgen to generate
+the C code instantiations of these definitions.
+
+ \section sec4-1 Section 4.1: File-Related Definitions
+
+ \subsection sec4-1-1 Section 4.1.1: struct AFSFid
+
+\par
+This is the type for file system objects within AFS.
+\n \n Fields
+\li unsigned long Volume - This provides the identifier for the volume in which
+the object resides.
+\li unsigned long Vnode - This specifies the index within the given volume
+corresponding to the object.
+\li unsigned long Unique - This is a 'uniquifier' or generation number for the
+slot identified by the Vnode field.
+
+ \section sec4-2 Section 4.2: Callback-related Definitions
+
+ \subsection sec4-2-1 Section 4.2.1: Types of Callbacks
+
+\par
+There are three types of callbacks defined by AFS-3:
+
+\li EXCLUSIVE: This version of callback has not been implemented. Its intent
+was to allow a single Cache Manager to have exclusive rights on the associated
+file data.
+\li SHARED: This callback type indicates that the status information kept by a
+Cache Manager for the associated file is up to date. All cached chunks from
+this file whose version numbers match the status information are thus
+guaranteed to also be up to date. This type of callback is non-exclusive,
+allowing any number of other Cache Managers to have callbacks on this file and
+cache chunks from the file.
+\li DROPPED: This is used to indicate that the given callback promise has been
+cancelled by the issuing File Server. The Cache Manager is forced to mark the
+status of its cache entry as unknown, forcing it to stat the file the next time
+a user attempts to access any chunk from it.
+
+ \subsection sec4-2-2 Section 4.2.2: struct AFSCallBack
+
+\par
+This is the canonical callback structure passed in many File Server RPC
+interface calls.
+\n \b Fields
+\li unsigned long CallBackVersion - Callback version number.
+\li unsigned long ExpirationTime - Time when the callback expires, measured in
+seconds.
+\li unsigned long CallBackType - The type of callback involved, one of
+EXCLUSIVE, SHARED, or DROPPED.
+
+ \subsection sec4-2-3 Section 4.2.3: Callback Arrays
+
+\par
+AFS-3 sometimes does callbacks in bulk. Up to AFSCBMAX (50) callbacks can be
+handled at once. Layouts for the two related structures implementing callback
+arrays, struct AFSCBFids and struct AFSCBs, follow below. Note that the
+callback descriptor in slot i of the array in the AFSCBs structure applies to
+the file identifier contained in slot i in the fid array in the matching
+AFSCBFids structure.
+
+ \subsubsection sec4-2-3-1 Section 4.2.3.1: struct AFSCBFids
+
+\n \b Fields
+\li u int AFSCBFids len - Number of AFS file identifiers stored in the
+structure, up to a maximum of AFSCBMAX.
+\li AFSFid *AFSCBFids val - Pointer to the first element of the array of file
+identifiers.
+
+ \subsubsection sec4-2-3-2 Section 4.2.3.2: struct AFSCBs
+
+\n \b Fields
+\li u int AFSCBs len - Number of AFS callback descriptors stored in the
+structure, up to a maximum of AFSCBMAX.
+\li AFSCallBack *AFSCBs val - Pointer to the actual array of callback
+descriptors
+
+ \section sec4-3 Section 4.3: Locking Definitions
+
+ \subsection sec4-3-1 Section 4.3.1: struct AFSDBLockDesc
+
+\par
+This structure describes the state of an AFS lock.
+\n \b Fields
+\li char waitStates - Types of lockers waiting for the lock.
+\li char exclLocked - Does anyone have a boosted, shared or write lock? (A
+boosted lock allows the holder to have data read-locked and then 'boost' up to
+a write lock on the data without ever relinquishing the lock.)
+\li char readersReading - Number of readers that actually hold a read lock on
+the associated object.
+\li char numWaiting - Total number of parties waiting to acquire this lock in
+some fashion.
+
+ \subsection sec4-3-2 Section 4.3.2: struct AFSDBCacheEntry
+
+\par
+This structure defines the description of a Cache Manager local cache entry, as
+made accessible via the RXAFSCB GetCE() callback RPC call. Note that File
+Servers do not make the above call. Rather, client debugging programs (such as
+cmdebug) are the agents which call RXAFSCB GetCE().
+\n \b Fields
+\li long addr - Memory location in the Cache Manager where this description is
+located.
+\li long cell - Cell part of the fid.
+\li AFSFid netFid - Network (standard) part of the fid
+\li long Length - Number of bytes in the cache entry.
+\li long DataVersion - Data version number for the contents of the cache entry.
+\li struct AFSDBLockDesc lock - Status of the lock object controlling access to
+this cache entry.
+\li long callback - Index in callback records for this object.
+\li long cbExpires - Time when the callback expires.
+\li short refCount - General reference count.
+\li short opens - Number of opens performed on this object.
+\li short writers - Number of writers active on this object.
+\li char mvstat - The file classification, indicating one of normal file, mount
+point, or volume root.
+\li char states - Remembers the state of the given file with a set of
+bits indicating, from lowest-order to highest order: stat info valid, read-only
+file, mount point valid, pending core file, wait-for-store, and mapped file.
+
+ \subsection sec4-3-3 Section 4.3.3: struct AFSDBLock
+
+\par
+This is a fuller description of an AFS lock, including a string name used to
+identify it.
+\n \b Fields
+\li char name[16] - String name of the lock.
+\li struct AFSDBLockDesc lock - Contents of the lock itself.
+
+ \section sec4-4 Section 4.4: Miscellaneous Definitions
+
+ \subsection sec4-4-1 Section 4.4.1: Opaque structures
+
+\par
+A maximum size for opaque structures passed via the File Server interface is
+defined as AFSOPAQUEMAX. Currently, this is set to 1,024 bytes. The AFSOpaque
+typedef is defined for use by those parameters that wish their contents to
+travel completely uninterpreted across the network.
+
+ \subsection sec4-4-2 Section 4.4.2: String Lengths
+
+\par
+Two common definitions used to specify basic AFS string lengths are AFSNAMEMAX
+and AFSPATHMAX. AFSNAMEMAX places an upper limit of 256 characters on such
+things as file and directory names passed as parameters. AFSPATHMAX defines the
+longest pathname expected by the system, composed of slash-separated instances
+of the individual directory and file names mentioned above. The longest
+acceptable pathname is currently set to 1,024 characters.
+
+ \page chap5 Chapter 5: File Server Interfaces
+
+\par
+There are several interfaces offered by the File Server, allowing it to export
+the files stored within the set of AFS volumes resident on its disks to the AFS
+community in a secure fashion and to perform self-administrative tasks. This
+chapter will cover the three File Server interfaces, summarized below. There is
+one File Server interface that will not be discussed in this document, namely
+that used by the Volume Server. It will be fully described in the companion
+AFS-3 Programmer's Reference:Volume Server/Volume Location Server Interface.
+\li RPC: This is the main File Server interface, supporting all of the Cache
+Manager's needs for providing its own clients with appropriate access to file
+system objects stored within AFS. It is closedly tied to the callback interface
+exported by the Cache Manager as described in Section 6.5, which has special
+implications for any application program making direct calls to this interface.
+\li Signals: Certain operations on a File Server must be performed by it
+sending unix signals on the machine on which it is executing. These operations
+include performing clean shutdowns and adjusting debugging output levels.
+Properly-authenticated administrative users do not have to be physically logged
+into a File Server machine to generate these signals. Rather, they may use the
+RPC interface exported by that machine's BOS Server process to generate them
+from any AFS-capable machine.
+\li Command Line: Many of the File Server's operating parameters may be set
+upon startup via its command line interface. Such choices as the number of data
+buffers and callback records to hold in memory may be made here, along with
+various other decisions such as lightweight thread stack size.
+
+ \section sec5-1 Section 5.1: RPC Interface
+
+ \subsection sec5-1-1 Section 5.1.1: Introduction and Caveats
+
+\par
+The documentation for the AFS-3 File Server RPC interface commences with some
+basic definitions and data structures used in conjunction with the function
+calls. This is followed by an examination of the set of non-streamed RPC
+functions, namely those routines whose parameters are all fixed in size. Next,
+the streamed RPC functions, those with parameters that allow an arbitrary
+amount of data to be delivered, are described. A code fragment and accompanying
+description and analysis are offered as an example of how to use the streamed
+RPC calls. Finally, a description of the special requirements on any
+application program making direct calls to this File Server interface appears.
+The File Server assumes that any entity making calls to its RPC functionality
+is a bona fide and full-fledged Cache Manager. Thus, it expects this caller to
+export the Cache Manager's own RPC interface, even if the application simply
+uses File Server calls that don't transfer files and thus generate callbacks.
+\par
+Within those sections describing the RPC functions themselves, the purpose of
+each call is detailed, and the nature and use of its parameters is documented.
+Each of these RPC interface routines returns an integer error code, and a
+subset of the possible values are described. A complete and systematic list of
+potential error returns for each function is difficult to construct and
+unwieldy to examine. This is due to fact that error codes from many different
+packages and from many different levels may arise. Instead of attempting
+completeness, the error return descriptions discuss error codes generated
+within the functions themselves (or a very small number of code levels below
+them) within the File Server code itself, and not from such associated packages
+as the Rx, volume, and protection modules. Many of these error code are defined
+in the companion AFS-3 documents.
+\par
+By convention, a return value of zero reveals that the function call was
+successful and that all of its OUT parameters have been set by the File Server.
+
+ \subsection sec5-1-2 Section 5.1.2: Definitions and Structures
+
+ \subsubsection sec5-1-2-1 Section 5.1.2.1: Constants and Typedefs
+
+\par
+The following constants and typedefs are required to properly use the File
+Server RPC interface, both to provide values and to interpret information
+returned by the calls. The constants appear first, followed by the list of
+typedefs, which sometimes depend on the constants above. Items are alphabetized
+within each group.
+\par
+All of the constants appearing below whose names contain the XSTAT string are
+used in conjuction with the extended data collection facility supported by the
+File Server. The File Server defines some number of data collections, each of
+which consists of an array of longword values computed by the File Server.
+\par
+There are currently two data collections defined for the File Server. The first
+is identified by the AFS XSTATSCOLL CALL INFO constant. This collection of
+longwords relates the number of times each internal function within the File
+Server code has been executed, thus providing profiling information. The second
+File Server data collection is identified by the AFS XSTATSCOLL PERF INFO
+constant. This set of longwords contains information related to the File
+Server's performance.
+
+\par Section 5.1.2.1.1 AFS DISKNAMESIZE [Value = 32]
+Specifies the maximum length for an AFS disk partition, used directly in the
+definition for the DiskName typedef. A DiskName appears as part of a struct
+ViceDisk, a group of which appear inside a struct ViceStatistics, used for
+carrying basic File Server statistics information.
+
+\par Section 5.1.2.1.2 AFS MAX XSTAT LONGS [Value = 1,024]
+Defines the maximum size for a File Server data collection, as exported via the
+RXAFS GetXStats() RPC call. It is used directly in the AFS CollData typedef.
+
+\par Section 5.1.2.1.3 AFS XSTATSCOLL CALL INFO [Value = 0]
+This constant identifies the File Server's data collection containing profiling
+information on the number of times each of its internal procedures has been
+called.
+\par
+Please note that this data collection is not supported by the File Server at
+this time. A request for this data collection will result the return of a
+zero-length array.
+
+\par Section 5.1.2.1.4 AFS XSTATSCOLL PERF INFO [Value = 1]
+This constant identifies the File Server's data collection containing
+performance-related information.
+
+\par Section 5.1.2.1.5 AFS CollData [typedef long AFS CollData<AFS MAX XSTAT
+LONGS>;]
+This typedef is used by Rxgen to create a structure used to pass File Server
+data collections to the caller. It resolves into a C typedef statement defining
+a structure of the same name with the following fields:
+\n \b Fields
+\li u int AFS CollData len - The number of longwords contained within the data
+pointed to by the next field.
+\li long *AFS CollData val - A pointer to a sequence of AFS CollData len
+long-words.
+
+\par Section 5.1.2.1.6 AFSBulkStats [typedef AFSFetchStatus
+AFSBulkStats<AFSCBMAX>;]
+This typedef is used by Rxgen to create a structure used to pass a set of
+statistics structures, as described in the RXAFS BulkStatus documentation in
+Section 5.1.3.21. It resolves into a C typedef statement defining a structure
+of the same name with the following fields:
+\n \b Fields
+\li u int AFSBulkStats len - The number of struct AFSFetchStatus units
+contained within the data to which the next field points.
+\li AFSFetchStatus *AFSBulkStats val - This field houses pointer to a sequence
+of AFSBulkStats len units of type struct AFSFetchStatus.
+
+\par Section 5.1.2.1.7 DiskName [typedef opaque DiskName[AFS DISKNAMESIZE];]
+The name of an AFS disk partition. This object appears as a field within a
+struct ViceDisk,a group of which appear inside a struct ViceStatistics, used
+for carrying basic File Server statistics information. The term opaque
+appearing above inidcates that the object being defined will be treated as an
+undifferentiated string of bytes.
+
+\par Section 5.1.2.1.8 ViceLockType [typedef long ViceLockType;]
+This defines the format of a lock used internally by the Cache Manager. The
+content of these locks is accessible via the RXAFSCB GetLock() RPC function. An
+isomorphic and more refined version of the lock structure used by the Cache
+Manager, mapping directly to this definition, is struct AFSDBLockDesc, defined
+in Section 4.3.1.
+
+ \subsubsection sec5-1-2-2 Section 5.1.2.2: struct AFSVolSync
+
+\par
+This structure conveys volume synchronization information across many of the
+File Server RPC interface calls, allowing something akin to a "whole-volume
+callback" on read-only volumes.
+\n \b Fields
+\li unsigned long spare1 ... spare6 - The first longword, spare1, contains the
+volume's creation date. The rest are currently unused.
+
+ \subsubsection sec5-1-2-3 Section 5.1.2.3: struct AFSFetchStatus
+
+\par
+This structure defines the information returned when a file system object is
+fetched from a File Server.
+\n \b Fields
+\li unsigned long InterfaceVersion - RPC interface version, defined to be 1.
+\li unsigned long FileType - Distinguishes the object as either a file,
+directory, symlink, or invalid.
+\li unsigned long LinkCount - Number of links to this object.
+\li unsigned long Length - Length in bytes.
+\li unsigned long DataVersion - Object's data version number.
+\li unsigned long Author - Identity of the object's author.
+\li unsigned long Owner - Identity of the object's owner.
+\li unsigned long CallerAccess - The set of access rights computed for the
+caller on this object.
+\li unsigned long AnonymousAccess - The set of access rights computed for any
+completely unauthenticated principal.
+\li unsigned long UnixModeBits - Contents of associated unix mode bits.
+\li unsigned long ParentVnode - Vnode for the object's parent directory.
+\li unsigned long ParentUnique - Uniquifier field for the parent object.
+\li unsigned long SegSize - (Not implemented).
+\li unsigned long ClientModTime - Time when the caller last modified the data
+within the object.
+\li unsigned long ServerModTime - Time when the server last modified the data
+within the object.
+\li unsigned long Group - (Not implemented).
+\li unsigned long SyncCounter - (Not implemented).
+\li unsigned long spare1 ... spare4 - Spares.
+
+ \subsubsection sec5-1-2-4 Section 5.1.2.4: struct AFSStoreStatus
+
+\par
+This structure is used to convey which of a file system object's status fields
+should be set, and their new values. Several File Server RPC calls, including
+RXAFS StoreStatus(), RXAFS CreateFile(), RXAFS SymLink(), RXAFS MakeDir(), and
+the streamed call to store file data onto the File Server.
+\n \b Fields
+\li unsigned long Mask - Bit mask, specifying which of the following fields
+should be assigned into the File Server's status block on the object.
+\li unsigned long ClientModTime - The time of day that the object was last
+modified.
+\li unsigned long Owner - The principal identified as the owner of the file
+system object.
+\li unsigned long Group - (Not implemented).
+\li unsigned long UnixModeBits - The set of associated unix mode bits.
+\li unsigned long SegSize - (Not implemented).
+
+ \subsubsection sec5-1-2-5 Section 5.1.2.5: struct ViceDisk
+
+\par
+This structure occurs in struct ViceStatistics, and describes the
+characteristics and status of a disk partition used for AFS storage.
+\n \b Fields
+\li long BlocksAvailable - Number of 1 Kbyte disk blocks still available on the
+partition.
+\li long TotalBlocks - Total number of disk blocks in the partition.
+\li DiskName Name - The human-readable character string name of the disk
+partition (e.g., /vicepa).
+
+ \subsubsection sec5-1-2-6 Section 5.1.2.6: struct ViceStatistics
+
+\par
+This is the File Server statistics structure returned by the RXAFS
+GetStatistics() RPC call.
+\n \b Fields
+\li unsigned long CurrentMsgNumber - Not used.
+\li unsigned long OldestMsgNumber - Not used.
+\li unsigned long CurrentTime - Time of day, as understood by the File Server.
+\li unsigned long BootTime - Kernel's boot time.
+\li unsigned long StartTime - Time when the File Server started up.
+\li long CurrentConnections - Number of connections to Cache Manager instances.
+\li unsigned long TotalViceCalls - Count of all calls made to the RPC
+interface.
+\li unsigned long TotalFetchs - Total number of fetch operations, either status
+or data, performed.
+\li unsigned long FetchDatas - Total number of data fetch operations
+exclusively.
+\li unsigned long FetchedBytes - Total number of bytes fetched from the File
+Server since it started up.
+\li long FetchDataRate - Result of dividing the FetchedBytes field by the
+number of seconds the File Server has been running.
+\li unsigned long TotalStores - Total number of store operations, either status
+or data, performed.
+\li unsigned long StoreDatas - Total number of data store operations
+exclusively.
+\li unsigned long StoredBytes - Total number of bytes stored to the File Server
+since it started up.
+\li long StoreDataRate - The result of dividing the StoredBytes field by the
+number of seconds the File Server has been running.
+\li unsigned long TotalRPCBytesSent - Outdated
+\li unsigned long TotalRPCBytesReceived - Outdated
+\li unsigned long TotalRPCPacketsSent - Outdated
+\li unsigned long TotalRPCPacketsReceived - Outdated
+\li unsigned long TotalRPCPacketsLost - Outdated
+\li unsigned long TotalRPCBogusPackets - Outdated
+\li long SystemCPU - Result of reading from the kernel the usage times
+attributed to system activities.
+\li long UserCPU - Result of reading from the kernel the usage times attributed
+to user-level activities.
+\li long NiceCPU - Result of reading from the kernel the usage times attributed
+to File Server activities that have been nice()d (i.e., run at a lower
+priority).
+\li long IdleCPU - Result of reading from the kernel the usage times attributed
+to idling activities.
+\li long TotalIO - Summary of the number of bytes read/written from the disk.
+\li long ActiveVM - Amount of virtual memory used by the File Server.
+\li long TotalVM - Total space available on disk for virtual memory activities.
+\li long EtherNetTotalErrors - Not used.
+\li long EtherNetTotalWrites - Not used.
+\li long EtherNetTotalInterupts - Not used.
+\li long EtherNetGoodReads - Not used.
+\li long EtherNetTotalBytesWritten - Not used.
+\li long EtherNetTotalBytesRead - Not used.
+\li long ProcessSize - The size of the File Server's data space in 1 Kbyte
+chunks.
+\li long WorkStations - The total number of client Cache Managers
+(workstations) for which information is held by the File Server.
+\li long ActiveWorkStations - The total number of client Cache Managers
+(workstations) that have recently interacted with the File Server. This number
+is strictly less than or equal to the WorkStations field.
+\li long Spare1 ... Spare8 - Not used.
+\li ViceDisk Disk1 ... Disk10 - Statistics concerning up to 10 disk partitions
+used by the File Server. These records keep information on all partitions, not
+just partitions reserved for AFS storage.
+
+ \subsubsection sec5-1-2-7 Section 5.1.2.7: struct afs PerfStats
+
+\par
+This is the structure corresponding to the AFS XSTATSCOLL PERF INFO data
+collection that is defined by the File Server (see Section 5.1.2.1.4). It is
+accessible via the RXAFS GetXStats() interface routine, as defined in Section
+5.1.3.26.
+The fields within this structure fall into the following classifications:
+\li Number of requests for the structure.
+\li Vnode cache information.
+\li Directory package numbers.
+\li Rx information.
+\li Host module fields
+\li Spares.
+
+\par
+Please note that the Rx fields represent the contents of the rx stats structure
+maintained by Rx RPC facility itself. Also, a full description of all the
+structure's fields is not possible here. For example, the reader is referred to
+the companion Rx document for further clarification on the Rx-related fields
+within afs PerfStats.
+\n \b Fields
+\li long numPerfCalls - Number of performance collection calls received.
+\li long vcache L Entries - Number of entries in large (directory) vnode cache.
+\li long vcache L Allocs - Number of allocations for the large vnode cache.
+\li long vcache L Gets - Number of get operations for the large vnode cache.
+\li long vcache L Reads - Number of reads performed on the large vnode cache.
+\li long vcache L Writes - Number of writes executed on the large vnode.cache.
+\li long vcache S Entries - Number of entries in the small (file) vnode cache.
+\li long vcache S Allocs - Number of allocations for the small vnode cache.
+\li long vcache S Gets - Number of get operations for the small vnode cache.
+\li long vcache S Reads - Number of reads performed on the small vnode cache.
+\li long vcache S Writes - Number of writes executed on the small vnode cache.
+\li long vcache H Entries - Number of entries in the header of the vnode cache.
+\li long vcache H Gets - Number of get operations on the header of the vnode
+cache.
+\li long vcache H Replacements - Number of replacement operations on the header
+of the vnode cache.
+\li long dir Buffers - Number of directory package buffers in use.
+\li long dir Calls - Number of read calls made to the directory package.
+\li long dir IOs - Number of directory I/O operations performed.
+\li long rx packetRequests - Number of Rx packet allocation requests.
+\li long rx noPackets RcvClass - Number of failed packet reception requests.
+\li long rx noPackets SendClass - Number of failed packet transmission
+requests.
+\li long rx noPackets SpecialClass - Number of 'special' Rx packet rquests.
+\li long rx socketGreedy - Did setting the Rx socket to SO GREEDY succeed?
+\li long rx bogusPacketOnRead - Number of short packets received.
+\li long rx bogusHost - Latest host address from bogus packets.
+\li long rx noPacketOnRead - Number of attempts to read a packet when one was
+not physically available.
+\li long rx noPacketBuffersOnRead - Number of packets dropped due to buffer
+shortages.
+\li long rx selects - Number of selects performed, waiting for a packet arrival
+or a timeout.
+\li long rx sendSelects - Number of selects forced upon a send.
+\li long rx packetsRead RcvClass - Number of packets read belonging to the
+'Rcv' class.
+\li long rx packetsRead SendClass - Number of packets read that belong to the
+'Send' class.
+\li long rx packetsRead SpecialClass - Number of packets read belonging to the
+'Special' class.
+\li long rx dataPacketsRead - Number of unique data packets read off the wire.
+\li long rx ackPacketsRead - Number of acknowledgement packets read.
+\li long rx dupPacketsRead - Number of duplicate data packets read.
+\li long rx spuriousPacketsRead - Number of inappropriate packets read.
+\li long rx packetsSent RcvClass - Number of packets sent belonging to the
+'Rcv' class.
+\li long rx packetsSent SendClass - Number of packets sent belonging to the
+'Send' class.
+\li long rx packetsSent SpecialClass - Number of packets sent belonging to the
+'Special' class.
+\li long rx ackPacketsSent - Number of acknowledgement packets sent.
+\li long rx pingPacketsSent - Number of ping packets sent.
+\li long rx abortPacketsSent - Number of abort packets sent.
+\li long rx busyPacketsSent - Number of busy packets sent.
+\li long rx dataPacketsSent - Number of unique data packets sent.
+\li long rx dataPacketsReSent - Number of retransmissions sent.
+\li long rx dataPacketsPushed - Number of retransmissions pushed by a NACK.
+\li long rx ignoreAckedPacket - Number of packets whose acked flag was set at
+rxi Start() time.
+\li long rx totalRtt Sec - Total round trip time in seconds.
+\li long rx totalRtt Usec - Microsecond portion of the total round trip time,
+\li long rx minRtt Sec - Minimum round trip time in seconds.
+\li long rx minRtt Usec - Microsecond portion of minimal round trip time.
+\li long rx maxRtt Sec - Maximum round trip time in seconds.
+\li long rx maxRtt Usec - Microsecond portion of maximum round trip time.
+\li long rx nRttSamples - Number of round trip samples.
+\li long rx nServerConns - Total number of server connections.
+\li long rx nClientConns - Total number of client connections.
+\li long rx nPeerStructs - Total number of peer structures.
+\li long rx nCallStructs - Total number of call structures.
+\li long rx nFreeCallStructs - Total number of call structures residing on the
+free list.
+\li long host NumHostEntries - Number of host entries.
+\li long host HostBlocks - Number of blocks in use for host entries.
+\li long host NonDeletedHosts - Number of non-deleted host entries.
+\li long host HostsInSameNetOrSubnet - Number of host entries in the same
+[sub]net as the File Server.
+\li long host HostsInDiffSubnet - Number of host entries in a different subnet
+as the File Server.
+\li long host HostsInDiffNetwork - Number of host entries in a different
+network entirely as the File Server.
+\li long host NumClients - Number of client entries.
+\li long host ClientBlocks - Number of blocks in use for client entries.
+\li long spare[32] - Spare fields, reserved for future use.
+
+ \subsubsection sec5-1-2-8 Section 5.1.2.8: struct AFSFetchVolumeStatus
+
+\par
+The results of asking the File Server for status information concerning a
+particular volume it hosts.
+\n \b Fields
+\li long Vid - Volume ID.
+\li long ParentId - Volume ID in which the given volume is 'primarily' mounted.
+\li This is used to properly resolve pwd operations, as a volume may be mounted
+simultaneously at multiple locations.
+\li char Online - Is the volume currently online and fully available?
+\li char InService - This field records whether the volume is currently in
+service. It is indistinguishable from the Blessed field,
+\li char Blessed - See the description of the InService field immediately
+above.
+\li char NeedsSalvage -Should this volume be salvaged (run through a
+consistency- checking procedure)?
+\li long Type - The classification of this volume, namely a read/write volume
+(RWVOL = 0), read-only volume (ROVOL = 1), or backup volume (BACKVOL = 2).
+\li long MinQuota - Minimum number of 1 Kbyte disk blocks to be set aside for
+this volume. Note: this field is not currently set or accessed by any AFS
+agents.
+\li long MaxQuota - Maximum number of 1 Kbyte disk blocks that may be occupied
+by this volume.
+\li long BlocksInUse - Number of 1 Kbyte disk blocks currently in use by this
+volume.
+\li long PartBlocksAvail - Number of available 1 Kbyte blocks currently unused
+in the volume's partition.
+\li long PartMaxBlocks - Total number of blocks, in use or not, for the
+volume's partition.
+
+ \subsubsection sec5-1-2-9 Section 5.1.2.9: struct AFSStoreVolumeStatus
+
+\par
+This structure is used to convey which of a file system object's status fields
+should be set, and their new values. The RXAFS SetVolumeStatus() RPC call is
+the only user of this structure.
+\n \b Fields
+\li long Mask - Bit mask to determine which of the following two fields should
+be stored in the centralized status for a given volume.
+\li long MinQuota - Minimum number of 1 Kbyte disk blocks to be set aside for
+this volume.
+\li long MaxQuota - Maximum number of 1 Kbyte disk blocks that may be occupied
+by this volume.
+
+ \subsubsection sec5-1-2-10 Section 5.1.2.10: struct AFSVolumeInfo
+
+\par
+This field conveys information regarding a particular volume through certain
+File Server RPC interface calls. For information regarding the different volume
+types that exist, please consult the companion document, AFS-3 Programmer's
+Reference:Volume Server/Volume Location Server Interface.
+\n \b Fields
+\li unsigned long Vid - Volume ID.
+\li long Type - Volume type (see struct AFSFetchVolumeStatus in Section 5.1.2.8
+above).
+\li unsigned long Type0 ... Type4 - The volume IDs for the possible volume
+types in existance for this volume.
+\li unsigned long ServerCount - The number of File Server machines on which an
+instance of this volume is located.
+\li unsigned long Server0 ... Server7 - Up to 8 IP addresses of File Server
+machines hosting an instance on this volume. The first ServerCount of these
+fields hold valid server addresses.
+\li unsigned short Port0 ... Port7 - Up to 8 UDP port numbers on which
+operations on this volume should be directed. The first ServerCount of these
+fields hold valid port identifiers.
+
+ \subsection sec5-1-3 Section 5.1.3: Non-Streamed Function Calls
+
+\par
+The following is a description of the File Server RPC interface routines that
+utilize only parameters with fixed maximum lengths. The majority of the File
+Server calls fall into this suite, with only a handful using streaming
+techniques to pass objects of unbounded size between a File Server and Cache
+Manager.
+\par
+Each function is labeled with an opcode number. This is the low-level numerical
+identifier for the function, and appears in the set of network packets
+constructed for the RPC call.
+
+ \subsubsection sec5-1-3-1 Section 5.1.3.1: RXAFS FetchACL - Fetch the
+ACL associated with the given AFS file identifier
+
+\code
+int RXAFS FetchACL(IN struct rx connection *a rxConnP,
+ IN AFSFid *a dirFidP,
+ OUT AFSOpaque *a ACLP,
+ OUT AFSFetchStatus *a dirNewStatP,
+ OUT AFSVolSync *a volSyncP)
+\endcode
+\par Description
+[Opcode 131] Fetch the ACL for the directory identified by a dirFidP, placing
+it in the space described by the opaque structure to which a ACLP points. Also
+returned is the given directory's status, written to a dirNewStatP. An ACL may
+thus take up at most AFSOPAQUEMAX (1,024) bytes, since this is the maximum size
+of an AFSOpaque.
+\par
+Rx connection information for the related File Server is contained in a
+rxConnP. Volume version information is returned for synchronization purposes in
+a volSyncP.
+\par Error Codes
+EACCES The caller is not permitted to perform this operation. EINVAL An
+internal error in looking up the client record was encountered, or an invalid
+fid was provided. VICETOKENDEAD Caller's authentication token has expired.
+
+ \subsubsection sec5-1-3-2 Section 5.1.3.2: RXAFS FetchStatus - Fetch
+the status information regarding a given file system object
+
+\code
+int RXAFS FetchStatus(IN struct rx connection *a rxConnP,
+ IN AFSFid *a fidToStatP,
+ OUT AFSFetchStatus *a currStatP,
+ OUT AFSCallBack *a callBackP,
+ OUT AFSVolSync *a volSyncP)
+\endcode
+\par Description
+[Opcode 132] Fetch the current status information for the file or directory
+identified by a fidToStatP, placing it into the area to which a currStatP
+points. If the object resides in a read/write volume, then the related callback
+information is returned in a callBackP.
+\par
+Rx connection information for the related File Server is contained in a
+rxConnP. Volume version information is returned for synchronization purposes in
+a volSyncP.
+\par Error Codes
+EACCES The caller is not permitted to perform this operation. EINVAL An
+internal error in looking up the client record was encountered, or an invalid
+fid was provided. VICETOKENDEAD Caller's authentication token has expired.
+
+ \subsubsection sec5-1-3-3 Section 5.1.3.3: RXAFS StoreACL - Associate
+the given ACL with the named directory
+
+\code
+int RXAFS StoreACL(IN struct rx connection *a rxConnP,
+ IN AFSOpaque *a ACLToStoreP,
+ IN AFSFid *a dirFidP,
+ OUT AFSFetchStatus *a dirNewStatP,
+ OUT AFSVolSync *a volSyncP)
+\endcode
+\par Description
+[Opcode 134] Store the ACL information to which a ACLToStoreP points to the
+File Server, associating it with the directory identified by a dirFidP. The
+resulting status information for the a dirFidP directory is returned in a
+dirNewStatP. Note that the ACL supplied via a ACLToStoreP may be at most
+AFSOPAQUEMAX (1,024) bytes long, since this is the maximum size accommodated by
+an AFSOpaque.
+\par
+Rx connection information for the related File Server is contained in a
+rxConnP. Volume version information is returned for synchronization purposes in
+a volSyncP.
+\par Error Codes
+EACCES The caller is not permitted to perform this operation.
+\n E2BIG The given ACL is too large.
+\n EINVAL The given ACL could not translated to its on-disk format.
+
+ \subsubsection sec5-1-3-4 Section 5.1.3.4: RXAFS StoreStatus - Store
+the given status information for the specified file
+
+\code
+int RXAFS StoreStatus(IN struct rx connection *a rxConnP,
+ IN AFSFid *a fidP,
+ IN AFSStoreStatus *a currStatusP,
+ OUT AFSFetchStatus *a srvStatusP,
+ OUT AFSVolSync *a volSyncP)
+\endcode
+\par Description
+[Opcode 135] Store the status information to which a currStatusP points,
+associating it with the file identified by a fidP. All outstanding callbacks on
+this object are broken. The resulting status structure stored at the File
+Server is returned in a srvStatusP.
+\par
+Rx connection information for the related File Server is contained in a
+rxConnP. Volume version information is returned for synchronization purposes in
+a volSyncP.
+\par Error Codes
+EACCES The caller is not permitted to perform this operation.
+\n EINVAL An internal error in looking up the client record was encountered, or
+an invalid fid was provided, or an attempt was made to change the mode of a
+symbolic link.
+\n VICETOKENDEAD Caller's authentication token has expired.
+
+ \subsubsection sec5-1-3-5 Section 5.1.3.5: RXAFS RemoveFile - Delete
+the given file
+
+\code
+int RXAFS RemoveFile(IN struct rx connection *a rxConnP,
+ IN AFSFid *a dirFidP,
+ IN char *a name<AFSNAMEMAX>,
+ OUT AFSFetchStatus *a srvStatusP,
+ OUT AFSVolSync *a volSyncP)
+\endcode
+\par Description
+[Opcode 136] Destroy the file named a name within the directory identified by a
+dirFidP. All outstanding callbacks on this object are broken. The resulting
+status structure stored at the File Server is returned in a srvStatusP.
+\par
+Rx connection information for the related File Server is contained in a
+rxConnP. Volume version information is returned for synchronization purposes in
+a volSyncP.
+\par Error Codes
+EACCES The caller is not permitted to perform this operation.
+\n EINVAL An internal error in looking up the client record was encountered, or
+an invalid fid was provided, or an attempt was made to remove "." or "..".
+\n EISDIR The target of the deletion was supposed to be a file, but it is
+really a directory.
+\n ENOENT The named file was not found.
+\n ENOTDIR The a dirFidP parameter references an object which is not a
+directory, or the deletion target is supposed to be a directory but is not.
+\n ENOTEMPTY The target directory being deleted is not empty.
+\n VICETOKENDEAD Caller's authentication token has expired.
+
+ \subsubsection sec5-1-3-6 Section 5.1.3.6: RXAFS CreateFile - Create
+the given file
+
+\code
+int RXAFS CreateFile(IN struct rx connection *a rxConnP,
+ IN AFSFid *DirFid,
+ IN char *Name,
+ IN AFSStoreStatus *InStatus,
+ OUT AFSFid *OutFid,
+ OUT AFSFetchStatus *OutFidStatus,
+ OUT AFSFetchStatus *OutDirStatus,
+ OUT AFSCallBack *CallBack,
+ OUT AFSVolSync *a volSyncP)
+/* associated with the new file. */
+\endcode
+\par Description
+[Opcode 137] This call is used to create a file, but not for creating a
+directory or a symbolic link. If this call succeeds, it is the Cache Manager's
+responsibility to either create an entry locally in the directory specified by
+DirFid or to invalidate this directory's cache entry.
+\par
+Rx connection information for the related File Server is contained in a
+rxConnP. Volume version information is returned for synchronization purposes in
+a volSyncP.
+\par Error Codes
+EACCES The caller is not permitted to perform this operation.
+\n EINVAL An internal error in looking up the client record was encountered, or
+an invalid fid or name was provided.
+\n ENOTDIR The DirFid parameter references an object which is not a directory.
+\n VICETOKENDEAD Caller's authentication token has expired.
+
+ \subsubsection sec5-1-3-7 Section 5.1.3.7: RXAFS Rename - Rename the
+specified file in the given directory
+
+\code
+int RXAFS Rename(IN struct rx connection *a rxConnP,
+ IN AFSFid *a origDirFidP,
+ IN char *a origNameP,
+ IN AFSFid *a newDirFidP,
+ IN char *a newNameP,
+ OUT AFSFetchStatus *a origDirStatusP,
+ OUT AFSFetchStatus *a newDirStatusP,
+ OUT AFSVolSync *a volSyncP)
+\endcode
+\par Description
+[Opcode 138] Rename file a origNameP in the directory identified by a
+origDirFidP. Its new name is to be a newNameP, and it will reside in the
+directory identified by a newDirFidP. Each of these names must be no more than
+AFSNAMEMAX (256) characters long. The status of the original and new
+directories after the rename operation completes are deposited in a
+origDirStatusP and a newDirStatusP respectively. Existing callbacks are broken
+for all files and directories involved in the operation.
+\par
+Rx connection information for the related File Server is contained in a
+rxConnP. Volume version information is returned for synchronization purposes in
+a volSyncP.
+\par Error Codes
+EACCES New file exists but user doesn't have Delete rights in the directory.
+\n EINVAL Name provided is invalid.
+\n EISDIR Original object is a file and new object is a directory.
+\n ENOENT The object to be renamed doesn't exist in the parent directory.
+\n ENOTDIR Original object is a directory and new object is a file.
+\n EXDEV Rename attempted across a volume boundary, or create a pathname loop,
+or hard links exist to the file.
+
+ \subsubsection sec5-1-3-8 Section 5.1.3.8: RXAFS Symlink - Create a
+symbolic link
+
+\code
+int RXAFS Symlink(IN struct rx connection *a rxConnP,
+ IN AFSFid *a dirFidP,
+ IN char *a nameP,
+ IN char *a linkContentsP,
+ IN AFSStoreStatus *a origDirStatP,
+ OUT AFSFid *a newFidP,
+ OUT AFSFetchStatus *a newFidStatP,
+ OUT AFSFetchStatus *a newDirStatP,
+ OUT AFSVolSync *a volSyncP)
+\endcode
+\par Description
+[Opcode 139] Create a symbolic link named a nameP in the directory identified
+by a dirFidP. The text of the symbolic link is provided in a linkContentsP, and
+the desired status fields for the symbolic link given by a origDirStatP. The
+name offered in a nameP must be less than AFSNAMEMAX (256) characters long, and
+the text of the link to which a linkContentsP points must be less than
+AFSPATHMAX (1,024) characters long. Once the symbolic link has been
+successfully created, its file identifier is returned in a newFidP. Existing
+callbacks to the a dirFidP directory are broken before the symbolic link
+creation completes. The status fields for the symbolic link itself and its
+parent's directory are returned in a newFidStatP and a newDirStatP
+respectively.
+\par
+Rx connection information for the related File Server is contained in a
+rxConnP. Volume version information is returned for synchronization purposes in
+a volSyncP.
+\par Error Codes
+EACCES The caller does not have the necessary access rights.
+\n EINVAL Illegal symbolic link name provided.
+
+ \subsubsection sec5-1-3-9 Section 5.1.3.9: RXAFS Link - Create a hard
+link
+
+\code
+int RXAFS Link(IN struct rx connection *a rxConnP,
+ IN AFSFid *a dirFidP,
+ IN char *a nameP,
+ IN AFSFid *a existingFidP,
+ OUT AFSFetchStatus *a newFidStatP,
+ OUT AFSFetchStatus *a newDirStatP,
+ OUT AFSVolSync *a volSyncP)
+\endcode
+\par Description
+[Opcode 140] Create a hard link named a nameP in the directory identified by a
+dirFidP. The file serving as the basis for the hard link is identified by
+existingFidP. The name offered in a nameP must be less than AFSNAMEMAX (256)
+characters long. Existing callbacks to the a dirFidP directory are broken
+before the hard link creation completes. The status fields for the file itself
+and its parent's directory are returned in a newFidStatP and a newDirStatP
+respectively.
+Rx connection information for the related File Server is contained in a
+rxConnP. Volume version information is returned for synchronization purposes in
+a volSyncP.
+\par Error Codes
+EACCES The caller does not have the necessary access rights.
+\n EISDIR An attempt was made to create a hard link to a directory.
+\n EXDEV Hard link attempted across directories.
+
+ \subsubsection sec5-1-3-10 Section 5.1.3.10: RXAFS MakeDir - Create a
+directory
+
+\code
+int RXAFS MakeDir(IN struct rx connection *a rxConnP,
+ IN AFSFid *a parentDirFid,P
+ IN char *a newDirNameP,
+ IN AFSStoreStatus *a currStatP,
+ OUT AFSFid *a newDirFidP,
+ OUT AFSFetchStatus *a dirFidStatP,
+ OUT AFSFetchStatus *a parentDirStatP,
+ OUT AFSCallBack *a newDirCallBackP,
+ OUT AFSVolSync *a volSyncP)
+\endcode
+\par Description
+[Opcode 141] Create a directory named a newDirNameP within the directory
+identified by a parentDirFidP. The initial status fields for the new directory
+are provided in a currStatP. The new directory's name must be less than
+AFSNAMEMAX (256) characters long. The new directory's ACL is inherited from its
+parent. Existing callbacks on the parent directory are broken before the
+creation completes. Upon successful directory creation, the new directory's
+file identifier is returned in a newDirFidP, and the resulting status
+information for the new and parent directories are stored in a dirFidStatP and
+a parentDirStatP respectively. In addition, a callback for the new directory is
+returned in a newDirCallBackP.
+\par
+Rx connection information for the related File Server is contained in a
+rxConnP. Volume version information is returned for synchronization purposes in
+a volSyncP.
+\par Error Codes
+EACCES The caller does not have the necessary access rights.
+\n EINVAL The directory name provided is unacceptable.
+
+ \subsubsection sec5-1-3-11 Section 5.1.3.11: RXAFS RemoveDir - Remove a
+directory
+
+\code
+int RXAFS RemoveDir(IN struct rx connection *a rxConnP,
+ IN AFSFid *a parentDirFidP,
+ IN char *a dirNameP,
+ OUT AFSFetchStatus *a newParentDirStatP,
+ OUT AFSVolSync *a volSyncP)
+\endcode
+\par Description
+[Opcode 142] Remove the directory named a dirNameP from within its parent
+directory, identified by a parentDirFid. The directory being removed must be
+empty, and its name must be less than AFSNAMEMAX (256) characters long.
+Existing callbacks to the directory being removed and its parent directory are
+broken before the deletion completes. Upon successful deletion, the status
+fields for the parent directory are returned in a newParentDirStatP.
+\par
+Rx connection information for the related File Server is contained in a
+rxConnP. Volume version information is returned for synchronization purposes in
+a volSyncP.
+\par Error Codes
+EACCES The caller does not have the necessary access rights.
+
+ \subsubsection sec5-1-3-12 Section 5.1.3.12: RXAFS GetStatistics - Get
+common File Server statistics
+
+\code
+int RXAFS GetStatistics(IN struct rx connection *a rxConnP,
+ OUT ViceStatistics *a FSInfoP)
+\endcode
+\par Description
+[Opcode 146] Fetch the structure containing a set of common File Server
+statistics. These numbers represent accumulated readings since the time the
+File Server last restarted. For a full description of the individual fields
+contained in this structure, please see Section 5.1.2.6.
+\par
+Rx connection information for the related File Server is contained in a
+rxConnP.
+\par Error Codes
+---No error codes generated.
+
+ \subsubsection sec5-1-3-13 Section 5.1.3.13: RXAFS GiveUpCallBacks -
+Ask the File Server to break the given set of callbacks on the corresponding
+set of file identifiers
+
+\code
+int RXAFS GiveUpCallBacks(IN struct rx connection *a rxConnP,
+ IN AFSCBFids *a fidArrayP,
+ IN AFSCBs *a callBackArrayP)
+\endcode
+\par Description
+[Opcode 147] Given an array of up to AFSCBMAX file identifiers in a fidArrayP
+and a corresponding number of callback structures in a callBackArrayP, ask the
+File Server to remove these callbacks from its register. Note that this routine
+only affects callbacks outstanding on the given set of files for the host
+issuing the RXAFS GiveUpCallBacks call. Callback promises made to other
+machines on any or all of these files are not affected.
+\par
+Rx connection information for the related File Server is contained in a
+rxConnP.
+\par Error Codes
+EINVAL More file identifiers were provided in the a fidArrayP than callbacks in
+the a callBackArray.
+
+ \subsubsection sec5-1-3-14 Section 5.1.3.14: RXAFS GetVolumeInfo - Get
+information about a volume given its name
+
+\code
+int RXAFS GetVolumeInfo(IN struct rx connection *a rxConnP,
+ IN char *a volNameP,
+ OUT VolumeInfo *a volInfoP)
+\endcode
+\par Description
+[Opcode 148] Ask the given File Server for information regarding a volume whose
+name is a volNameP. The volume name must be less than AFSNAMEMAX characters
+long, and the volume itself must reside on the File Server being probed.
+\par
+Rx connection information for the related File Server is contained in a
+rxConnP. Please note that definitions for the error codes with VL prefixes may
+be found in the vlserver.h include file
+\par Error Codes
+Could not contact any of the corresponding Volume Location Servers.
+VL BADNAME An improperly-formatted volume name provided.
+\n VL ENTDELETED An entry was found for the volume, reporting that the volume
+has been deleted.
+\n VL NOENT The given volume was not found.
+
+ \subsubsection sec5-1-3-15 Section 5.1.3.15: RXAFS GetVolumeStatus -
+Get basic status information for the named volume
+
+\code
+int RXAFS GetVolumeStatus(IN struct rx connection *a rxConnP,
+ IN long a volIDP,
+ OUT AFSFetchVolumeStatus *a volFetchStatP,
+ OUT char *a volNameP,
+ OUT char *a offLineMsgP,
+ OUT char *a motdP)
+\endcode
+\par Description
+[Opcode 149] Given the numeric volume identifier contained in a volIDP, fetch
+the basic status information corresponding to that volume. This status
+information is stored into a volFetchStatP. A full description of this status
+structure is found in Section 5.1.2.8. In addition, three other facts about the
+volume are returned. The volume's character string name is placed into a
+volNameP. This name is guaranteed to be less than AFSNAMEMAX characters long.
+The volume's offline message, namely the string recording why the volume is
+off-line (if it is), is stored in a offLineMsgP . Finally, the volume's
+"Message of the Day" is placed in a motdP. Each of the character strings
+deposited into a offLineMsgP and a motdP is guaranteed to be less than
+AFSOPAQUEMAX (1,024) characters long.
+\par
+Rx connection information for the related File Server is contained in a
+rxConnP.
+\par Error Codes
+EACCES The caller does not have the necessary access rights.
+\n EINVAL A volume identifier of zero was specified.
+
+ \subsubsection sec5-1-3-16 Section 5.1.3.16: RXAFS SetVolumeStatus -
+Set the basic status information for the named volume
+
+\code
+int RXAFS SetVolumeStatus(struct rx connection *a rxConnP,
+ long avolIDP,
+ AFSStoreVolumeStatus *a volStoreStatP,
+ char *a volNameP,
+ char *a offLineMsgP,
+ char *a motdP)
+/* for the named volume */
+\endcode
+\par Description
+[Opcode 150] Given the numeric volume identifier contained in a volIDP, set
+that volume's basic status information to the values contained in a
+volStoreStatP. A full description of the fields settable by this call,
+including the necessary masking, is found in Section 5.1.2.9. In addition,
+three other items relating to the volume may be set. Non-null character strings
+found in a volNameP, a offLineMsgP, and a motdP will be stored in the volume's
+printable name, off-line message, and "Message of the Day" fields respectively.
+The volume name provided must be less than AFSNAMEMAX (256) characters long,
+and the other two strings must be less than AFSOPAQUEMAX (1,024) characters
+long each.
+\par
+Rx connection information for the related File Server is contained in a
+rxConnP.
+\par Error Codes
+EACCES The caller does not have the necessary access rights.
+\n EINVAL A volume identifier of zero was specified.
+
+ \subsubsection sec5-1-3-17 Section 5.1.3.17: RXAFS GetRootVolume -
+Return the name of the root volume for the file system
+
+\code
+int RXAFS GetRootVolume(IN struct rx connection *a rxConnP,
+ OUT char *a rootVolNameP)
+\endcode
+\par Description
+[Opcode 151] Fetch the name of the volume which serves as the root of the AFS
+file system and place it into a rootVolNameP. This name will always be less
+than AFSNAMEMAX characters long. Any File Server will respond to this call, not
+just the one hosting the root volume. The queried File Server first tries to
+discover the name of the root volume by reading from the
+/usr/afs/etc/RootVolume file on its local disks. If that file doesn't exist,
+then it will return the default value, namely "root.afs".
+\par
+Rx connection information for the related File Server is contained in a
+rxConnP. Volume version information is returned for synchronization purposes in
+a volSyncP.
+\par Error Codes
+---No error codes generated.
+
+ \subsubsection sec5-1-3-18 5.1.3.18: RXAFS CheckToken - (Obsolete)
+Check that the given user identifier matches the one in the supplied
+authentication token
+
+\code
+int RXAFS CheckToken(IN struct rx connection *a rxConnP,
+ IN long ViceId,
+ IN AFSOpaque *token)
+\endcode
+\par Description
+[Opcode 152] This function only works for the now-obsolete RPC facility used by
+AFS, R. For modern systems using the Rx RPC mechanism, we always get an error
+return from this routine.
+\par
+Rx connection information for the related File Server is contained in a
+rxConnP.
+\par Error Codes
+ECONNREFUSED Always returned on Rx connections.
+
+ \subsubsection sec5-1-3-19 Section 5.1.3.19: RXAFS GetTime - Get the
+File Server's time of day
+
+\code
+int RXAFS GetTime(IN struct rx connection *a rxConnP,
+ OUT unsigned long *a secondsP,
+ OUT unsigned long *a uSecondsP)
+\endcode
+\par Description
+[Opcode 153] Get the current time of day from the File Server specified in the
+Rx connection information contained in a rxConnP. The time is returned in
+elapsed seconds (a secondsP) and microseconds (a uSecondsP) since that standard
+unix "start of the world".
+\par Error Codes
+---No error codes generated.
+
+ \subsubsection sec5-1-3-20 Section 5.1.3.20: RXAFS NGetVolumeInfo - Get
+information about a volume given its name
+
+\code
+int RXAFS NGetVolumeInfo(IN struct rx connection *a rxConnP,
+ IN char *a volNameP,
+ OUT AFSVolumeInfo *a volInfoP)
+\endcode
+\par Description
+[Opcode 154] This function is identical to RXAFS GetVolumeInfo() (see Section
+5.1.3.14), except that it returns a struct AFSVolumeInfo instead of a struct
+VolumeInfo. The basic difference is that struct AFSVolumeInfo also carries an
+accompanying UDP port value for each File Server listed in the record.
+
+ \subsubsection sec5-1-3-21 Section 5.1.3.21: RXAFS BulkStatus - Fetch
+the status information regarding a set of given file system objects
+
+\code
+int RXAFS BulkStatus(IN struct rx connection *a rxConnP,
+ IN AFSCBFids *a fidToStatArrayP,
+ OUT AFSBulkStats *a currStatArrayP,
+ OUT AFSCBs *a callBackArrayP,
+ OUT AFSVolSync *a volSyncP)
+\endcode
+\par Description
+[Opcode 155] This routine is identical to RXAFS FetchStatus() as described in
+Section 5.1.3.2, except for the fact that it allows the caller to ask for the
+current status fields for a set of up to AFSCBMAX (50) file identifiers at
+once.
+\par
+Rx connection information for the related File Server is contained in a
+rxConnP. Volume version information is returned for synchronization purposes in
+a volSyncP.
+\par Error Codes
+EACCES The caller does not have the necessary access rights.
+\n EINVAL The number of file descriptors for which status information was
+requested is illegal.
+
+ \subsubsection sec5-1-3-22 Section 5.1.3.22: RXAFS SetLock - Set an
+advisory lock on the given file identifier
+
+\code
+int RXAFS SetLock(IN struct rx connection *a rxConnP,
+ IN AFSFid *a fidToLockP,
+ IN ViceLockType a lockType,
+ OUT AFSVolSync *a volSyncP)
+\endcode
+\par Description
+[Opcode 156] Set an advisory lock on the file identified by a fidToLockP. There
+are two types of locks that may be specified via a lockType: LockRead and
+LockWrite. An advisory lock times out after AFS LOCKWAIT (5) minutes, and must
+be extended in order to stay in force (see RXAFS ExtendLock(), Section
+5.1.3.23).
+\par
+Rx connection information for the related File Server is contained in a
+rxConnP. Volume version information is returned for synchronization purposes in
+a volSyncP.
+\par Error Codes
+EACCES The caller does not have the necessary access rights.
+\n EINVAL An illegal lock type was specified.
+\n EWOULDBLOCK The lock was already incompatibly granted to another party.
+
+ \subsubsection sec5-1-3-23 Section 5.1.3.23: RXAFS ExtendLock - Extend
+an advisory lock on a file
+
+\code
+int RXAFS ExtendLock(IN struct rx connection *a rxConnP,
+ IN AFSFid *a fidToBeExtendedP,
+ OUT AFSVolSync *a volSyncP)
+\endcode
+\par Description
+[Opcode 157] Extend the advisory lock that has already been granted to the
+caller on the file identified by a fidToBeExtendedP.
+\par
+Rx connection information for the related File Server is contained in a
+rxConnP. Volume version information is returned for synchronization purposes in
+a volSyncP.
+\par Error Codes
+EINVAL The caller does not already have the given file locked.
+
+ \subsubsection sec5-1-3-24 Section 5.1.3.24: RXAFS ReleaseLock -
+Release the advisory lock on a file
+
+\code
+int RXAFS ReleaseLock(IN struct rx connection *a rxConnP,
+ IN AFSFid *a fidToUnlockP,
+ OUT AFSVolSync *a volSyncP)
+\endcode
+\par Description
+[Opcode 158] Release the advisory lock held on the file identified by a
+fidToUnlockP. If this was the last lock on this file, the File Server will
+break all existing callbacks to this file.
+\par
+Rx connection information for the related File Server is contained in a
+rxConnP. Volume version information is returned for synchronization purposes in
+a volSyncP.
+\par Error Codes
+EACCES The caller does not have the necessary access rights.
+
+ \subsubsection sec5-1-3-25 Section 5.1.3.25: RXAFS XStatsVersion - Get
+the version number associated with the File Server's extended statistics
+structure
+
+\code
+int RXAFS XStatsVersion(IN struct rx connection *a rxConnP,
+ OUT long *a versionNumberP)
+\endcode
+\par Description
+[Opcode 159] This call asks the File Server for the current version number of
+the extended statistics structures it exports (see RXAFS GetXStats(), Section
+5.1.3.26). The version number is placed into a versionNumberP.
+\par
+Rx connection information for the related File Server is contained in a
+rxConnP.
+\par Error Codes
+---No error codes generated.
+
+ \subsubsection sec5-1-3-26 Section 5.1.3.26: RXAFS GetXStats - Get the
+current contents of the specified extended statistics structure
+
+\code
+int RXAFS GetXStats(IN struct rx connection *a rxConnP,
+ IN long a clientVersionNumber,
+ IN long a collectionNumber,
+ OUT long *a srvVersionNumberP,
+ OUT long *a timeP,
+ OUT AFS CollData *a dataP)
+\endcode
+\par Description
+[Opcode 160] This function fetches the contents of the specified File Server
+extended statistics structure. The caller provides the version number of the
+data it expects to receive in a clientVersionNumber. Also provided in a
+collectionNumber is the numerical identifier for the desired data collection.
+There are currently two of these data collections defined: AFS XSTATSCOLL CALL
+INFO, which is the list of tallies of the number of invocations of internal
+File Server procedure calls, and AFS XSTATSCOLL PERF INFO, which is a list of
+performance-related numbers. The precise contents of these collections are
+described in Sections 5.1.2.7. The current version number of the File Server
+collections is returned in a srvVersionNumberP, and is always set upon return,
+even if the caller has asked for a difierent version. If the correct version
+number has been specified, and a supported collection number given, then the
+collection data is returned in a dataP. The time of collection is also
+returned, being placed in a timeP.
+\par
+Rx connection information for the related File Server is contained in a
+rxConnP.
+\par Error Codes
+---No error codes are generated.
+
+ \subsection sec5-1-4 Section 5.1.4: Streamed Function Calls
+
+\par
+There are two streamed functions in the File Server RPC interface, used to
+fetch and store arbitrary amounts of data from a file. While some non-streamed
+calls pass such variable-length objects as struct AFSCBFids, these objects have
+a pre-determined maximum size.
+\par
+The two streamed RPC functions are also distinctive in that their single Rxgen
+declarations generate not one but two client-side stub routines. The first is
+used to ship the IN parameters off to the designated File Server, and the
+second to gather the OUT parameters and the error code. If a streamed
+definition declares a routine named X YZ(), the two resulting stubs will be
+named StartX YZ() and EndX YZ(). It is the application programmer's job to
+first invoke StartX YZ(), then manage the unbounded data transfer, then finish
+up by calling EndX YZ(). The first longword in the unbounded data stream being
+fetched from a File Server contains the number of data bytes to follow. The
+application then reads the specified number of bytes from the stream.
+\par
+The following sections describe the four client-side functions resulting from
+the Fetch-Data() and StoreData() declarations in the Rxgen interface definition
+file. These are the actual routines the application programmer will include in
+the client code. For reference, here are the interface definitions that
+generate these functions. Note that the split keyword is what causes Rxgen to
+generate the separate start and end routines. In each case, the number after
+the equal sign specifies the function's identifying opcode number. The opcode
+is passed to the File Server by the StartRXAFS FetchData() and StartRXAFS
+StoreData() stub routines.
+
+\code
+FetchData(IN AFSFid *a_fidToFetchP,
+ IN long a_offset,
+ IN long a_lenInBytes,
+ OUT AFSFetchStatus *a_fidStatP,
+ OUT AFSCallBack *a_callBackP,
+ OUT AFSVolSync *a_volSyncP) split = 130;
+
+StoreData(IN AFSFid *Fid,
+ IN AFSStoreStatus *InStatus,
+ IN long Pos,
+ IN long Length,
+ IN long FileLength,
+ OUT AFSFetchStatus *OutStatus,
+ OUT AFSVolSync *a_volSyncP) split = 133;
+\endcode
+
+ \subsubsection sec5-1-4-1 Section 5.1.4.1: StartRXAFS FetchData - Begin
+a request to fetch file data
+
+\code
+int StartRXAFS FetchData(IN struct rx call *a rxCallP,
+ IN AFSFid *a fidToFetchP,
+ IN long a offset,
+ IN long a lenInBytes)
+\endcode
+
+\par Description
+Begin a request for a lenInBytes bytes of data starting at byte offset a offset
+from the file identified by a fidToFetchP. After successful completion of this
+call, the data stream will make the desired bytes accessible. The first
+longword in the stream contains the number of bytes to actually follow.
+\par
+Rx call information to the related File Server is contained in a rxCallP.
+\par Error Codes
+---No error codes generated.
+
+ \subsubsection sec5-1-4-2 Section 5.1.4.2: EndRXAFS FetchData -
+Conclude a request to fetch file data
+
+\code
+int EndRXAFS FetchData(IN struct rx call *a rxCallP,
+ OUT AFSFetchStatus *a fidStatP,
+ OUT AFSCallBack *a callBackP,
+ OUT AFSVolSync *a volSyncP)
+\endcode
+\par Description
+Conclude a request to fetch file data, as commenced by an StartRXAFS
+FetchData() invocation. By the time this routine has been called, all of the
+desired data has been read off the data stream. The status fields for the file
+from which the data was read are stored in a fidStatP. If the file was from a
+read/write volume, its callback information is placed in a callBackP.
+\par
+Rx call information to the related File Server is contained in a rxCallP.
+Volume version information is returned for synchronization purposes in a
+volSyncP.
+\par Error Codes
+EACCES The caller does not have the necessary access rights. EIO Given file
+could not be opened or statted on the File Server, or there was an error
+reading the given data off the File Server's disk.
+\n -31 An Rx write into the stream ended prematurely.
+
+ \subsubsection sec5-1-4-3 Section 5.1.4.3: StartRXAFS StoreData - Begin
+a request to store file data
+
+\code
+int StartRXAFS StoreData(IN struct rx call *a rxCallP,
+ IN AFSFid *a fidToStoreP,
+ IN reStatus *a fidStatusP,
+ IN AFSStolong a offset,
+ IN long a lenInBytes,
+ IN long a fileLenInBytes)
+\endcode
+\par Description
+Begin a request to write a lenInBytes of data starting at byte offset a offset
+to the file identified by a fidToStoreP, causing that file's length to become a
+fileLenInBytes bytes. After successful completion of this call, the data stream
+will be ready to begin accepting the actual data being written.
+\par
+Rx call information to the related File Server is contained in a rxCallP.
+\par Error Codes
+---No error codes generated.
+
+ \subsubsection sec5-1-4-4 Section 5.1.4.4: EndRXAFS StoreData -
+Conclude a request to store file data
+
+\code
+int EndRXAFS StoreData(IN struct rx call *a rxCallP,
+ OUT AFSFetchStatus *a fidStatP,
+ OUT AFSCallBack *a callBackP,
+ OUT AFSVolSync *a volSyncP)
+\endcode
+\par Description
+Conclude a request to store file data, as commenced by a StartRXAFS StoreData()
+invocation. By the time this routine has been called, all of the file data has
+been inserted into the data stream. The status fields for the file to which the
+data was written are stored in a fidStatP. All existing callbacks to the given
+file are broken before the store concludes.
+\par
+Rx call information to the related File Server is contained in a rxCallP.
+Volume version information is returned for synchronization purposes in a
+volSyncP.
+\par Error Codes
+EACCES The caller does not have the necessary access rights.
+\n EISDIR The file being written to is a symbolic link.
+\n ENOSPEC A write to the File Server's file on local disk failed.
+\n -32 A short read was encountered by the File Server on the data stream.
+
+ \subsection sec5-1-5 Section 5.1.5: Example of Streamed Function Call
+Usage
+
+ \subsubsection sec5-1-5-1 Section 5.1.5.1: Preface
+
+\par
+The following code fragment is offered as an example of how to use the streamed
+File Server RPC calls. In this case, a client fetches some amount of data from
+the given File Server and writes it to a local file it uses to cache the
+information. For simplicity, many issues faced by a true application programmer
+are not addressed here. These issues include locking, managing file chunking,
+data version number mismatches, volume location, Rx connection management,
+defensive programming (e.g., checking parameters before using them),
+client-side cache management algorithms, callback management, and full error
+detection and recovery. Pseudocode is incorporated when appropriate to keep the
+level of detail reasonable. For further descriptions of some of these details
+and issues, the reader is referred to such companion documents as AFS-3
+Programmer's Reference: Specification for the Rx Remote Procedure Call
+Facility, AFS-3 Programmer's Reference:Volume Server/Volume Location Server
+Interface, and AFS-3 Programmer's Reference: Architectural Overview.
+\par
+A discussion of the methods used within the example code fragment follows
+immediately afterwards in Section 5.1.5.3.
+
+ \subsubsection sec5-1-5-2 Section 5.1.5.2: Code Fragment Illustrating
+Fetch Operation
+
+\code
+int code; /*Return code*/
+long bytesRead; /*Num bytes read from Rx*/
+struct myConnInfo *connP; /*Includes Rx conn info*/
+struct rx_call *rxCallP; /*Rx call ptr*/
+struct AFSFid *afsFidP; /*Fid for file to fetch*/
+int lclFid; /*Fid for local cache file*/
+long offsetBytes; /*Starting fetch offset*/
+long bytesToFetch; /*Num bytes to fetch*/
+long bytesFromFS; /*Num bytes FileServer returns*/
+char *fetchBuffP; /*Buffer to hold stream data*/
+int currReadBytes; /*Num bytes for current read*/
+/*
+* Assume that connP, afsFidP, offsetBytes, lclFid,and
+* bytesToFetch have all been given their desired values.
+*/ . . .
+rxCallP = rx_NewCall(connP->rxConnP);
+code = StartRXAFS_FetchData( rxCallP, /*Rx call to use*/
+ afsFidP, /*Fid being fetched from*/
+ offsetBytes, /*Offset in bytes*/
+ bytesToFetch); /*Num bytes wanted*/
+if (code == 0)
+{
+ bytesRead = rx_Read(rxCallP, &bytesFromFS, sizeof(long));
+ if (bytesRead != sizeof(long)) ExitWithError(SHORT_RX_READ);
+ bytesFromFS = ntohl(bytesFromFS);
+ xmitBuffer = malloc(FETCH_BUFF_BYTES);
+ lclFid = open(CacheFileName, O_RDWR, mode);
+ pos = lseek(lclFid, offsetBytes, L_SET);
+ while (bytesToFetch > 0) {
+ currReadBytes = (bytesToFetch > FETCH_BUFF_BYTES) ?
+ FETCH_BUFF_BYTES : bytesToFetch;
+ bytesRead = rx_Read(rxCallP, fetchBuffP, currReadBytes);
+ if (bytesRead != currReadBytes) ExitWithError(SHORT_RX_READ);
+ code = write(lclFid, fetchBuffP, currReadBytes);
+ if (code) ExitWithError(LCL_WRITE_FAILED);
+ bytesToFetch -= bytesRead;
+ } /*Read from the Rx stream*/
+ close(lclFid);
+} else ExitWithError(code);
+code = EndRXAFS_FetchData( rxCallP, /*Rx call to use*/
+ fidStatP, /*Resulting stat fields*/
+ fidCallBackP, /*Resulting callback info*/
+ volSynchP); /*Resulting volume sync info*/
+ code = rx_EndCall(rxCallP, code);
+return(code); . . .
+\endcode
+
+ \subsubsection sec5-1-5-3 Section 5.1.5.3: Discussion and Analysis
+
+\par
+The opening assumption in this discussion is that all the information required
+to do the fetch has already been set up. These mandatory variables are the
+client-side connection information for the File Server hosting the desired
+file, the corresponding AFS file identifier, the byte offset into the file, the
+number of bytes to fetch, and the identifier for the local file serving as a
+cached copy.
+\par
+Given the Rx connection information stored in the client's connP record, rx
+NewCall() is used to create a new Rx call to handle this fetch operation. The
+structure containing this call handle is placed into rxCallP. This call handle
+is used immediately in the invocation of StartRXAFS FetchData(). If this setup
+call fails, the fragment exits. Upon success, though, the File Server will
+commence writing the desired data into the Rx data stream. The File Server
+first writes a single longword onto the stream announcing to the client how
+many bytes of data will actually follow. The fragment reads this number with
+its first rx Read() call. Since all Rx stream data is written in network byte
+order, the fragment translates the byte count to its own host byte order first
+to properly interpret it. Once the number of bytes to appear on the stream is
+known, the client code proceeds to open the appropriate cache file on its own
+local disk and seeks to the appropriate spot within it. A buffer into which the
+stream data will be placed is also created at this time.
+\par
+The example code then falls into a loop where it reads all of the data from the
+File Server and stores it in the corresponding place in the local cache file.
+For each iteration, the code decides whether to read a full buffer's worth or
+the remaining number of bytes, whichever is smaller. After all the data is
+pulled off the Rx stream, the local cache file is closed. At this point, the
+example finishes off the RPC by calling EndRXAFS FetchData(). This gathers in
+the required set of OUT parameters, namely the status fields for the file just
+fetched, callback and volume synchronization information, and the overall error
+code for the streamed routine. The Rx call created to perform the fetch is then
+terminated and cleaned up by invoking rx EndCall().
+
+ \subsection sec5-1-6 Section 5.1.6: Required Caller Functionality
+
+\par
+The AFS File Server RPC interface was originally designed to interact only with
+Cache Manager agents, and thus made some assumptions about its callers. In
+particular, the File Server expected that the agents calling it would
+potentially have stored callback state on file system objects, and would have
+to be periodically pinged in order to garbage-collect its records, removing
+information on dead client machines. Thus, any entity making direct calls to
+this interface must mimic certain Cache Manager actions, and respond to certain
+Cache Manager RPC interface calls.
+\par
+To be safe, any application calling the File Server RPC interface directly
+should export the entire Cache Manager RPC interface. Realistically, though, it
+will only need to provide stubs for the three calls from this interface that
+File Servers know how to make: RXAFSCB InitCallBackState(), RXAFSCB Probe() and
+RXAFSCB CallBack(). The very first File Server call made by this application
+will prompt the given File Server to call RXAFSCB InitCallBackState(). This
+informs the application that the File Server has no record of its existence and
+hence this "Cache Manager" should clear all callback information for that
+server. Once the application responds positively to the inital RXAFSCB
+InitCallBackState(), the File Server will treat it as a bona fide,
+fully-fledged Cache Manager, and probe it every so often with RXAFSCB Probe()
+calls to make sure it is still alive.
+
+ \section sec5-2 Section 5.2: Signal Interface
+
+\par
+While the majority of communication with AFS File Servers occurs over the RPC
+interface, some important operations are invoked by sending unix signals to the
+process. This section describes the set of signals recognized by the File
+Server and the actions they trigger upon receipt, as summarized below:
+\li SIGQUIT: Shut down a File Server.
+\li SIGTSTP: Upgrade debugging output level.
+\li SIGHUP: Reset debugging output level.
+\li SIGTERM: Generate debugging output specifically concerning open files
+within the File Server process.
+
+ \subsection sec5-2-1 Section 5.2.1: SIGQUIT: Server Shutdown
+
+\par
+Upon receipt of this signal, the File Server shuts itself down in an orderly
+fashion. It first writes a message to the console and to its log file
+(/usr/afs/logs/FileLog) stating that a shutdown has commenced. The File Server
+then flushes all modified buffers and prints out a set of internal statistics,
+including cache and disk numbers. Finally, each attached volume is taken
+offline, which means the volume header is written to disk with the appropriate
+bits set.
+\par
+In typical usage, human operators do not send the SIGQUIT signal directly to
+the File Server in order to affect an orderly shutdown. Rather, the BOS Server
+managing the server processes on that machine issues the signal upon receipt of
+a properly-authorized shutdown RPC request.
+
+ \subsection sec5-2-2 Section 5.2.2: SIGTSTP: Upgrade Debugging Level
+
+\par
+Arrival of a SIGTSTP signal results in an increase of the debugging level used
+by the File Server. The routines used for writing to log files are sensitive to
+this debugging level, as recorded in the global LogLevel variable.
+Specifically, these routines will only generate output if the value of LogLevel
+is greater than or equal to the value of its threshold parameter. By default,
+the File Server sets LogLevel to zero upon startup. If a SIGTSTP signal is
+received when the debugging level is zero, it will be bumped to 1. If the
+signal arrives when the debugging level is positive, its value will be
+multiplied by 5. Thus, as more SIGTSTPs are received, the set of debugging
+messages eligible to be delivered to log files grows.
+\par
+Since the SIGTSTP signal is not supported under IBM's AIX 2.2.1 operating
+system, this form of debugging output manipulation is not possible on those
+platforms.
+
+ \subsection sec5-2-3 Section 5.2.3: SIGHUP: Reset Debugging Level
+
+\par
+Receiving a SIGHUP signal causes a File Server to reset its debugging level to
+zero. This effectively reduces the set of debugging messages eligible for
+delivery to log files to a bare minimum. This signal is used in conjunction
+with SIGTSTP to manage the verbosity of log information.
+\par
+Since the SIGHUP signal is not supported under IBM's AIX 2.2.1 operating
+system, this form of debugging output manipulation is not possible on those
+platforms.
+
+ \subsection sec5-2-4 Section 5.2.4: SIGTERM: File Descriptor Check
+
+\par
+Receipt of a SIGTERM signal triggers a routine which sweeps through the given
+File Server's unix file descriptors. For each possible unix fid slot, an
+fstat() is performed on that descriptor, and the particulars of each open file
+are printed out. This action is designed solely for debugging purposes.
+
+ \section sec5-3 Section 5.3: Command Line Interface
+
+\par
+Another interface exported by the File Server is the set of command line
+switches it accepts. Using these switches, many server parameters and actions
+can be set. Under normal conditions, the File Server process is started up by
+the BOS Server on that machine, as described in AFS-3 Programmer's Reference:
+BOS Server Interface. So, in order to utilize any combination of these
+command-line options, the system administrator must define the File Server
+bnode in such a way that these parameters are properly included. Note that the
+switch names must be typed exactly as listed, and that abbreviations are not
+allowed. Thus, specifying -b 300 on the command line is unambiguous, directing
+that 300 buffers are to be allocated. It is not an abbreviation for the -banner
+switch, asking that a message is to be printed to the console periodically.
+\par
+A description of the set of currently-supported command line switches follows.
+\li -b <# buffers> Choose the number of 2,048-byte data buffers to allocate at
+system startup. If this switch is not provided, the File Server will operate
+with 70 such buffers by default.
+\li -banner This switch instructs the File Server to print messages to the
+console every 10 minutes to demonstrate it is still running correctly. The text
+of the printed message is: File Server is running at <time>.
+\li -cb <# callbacks stored> Specify the maximum number of callback records
+stored simultaneously by the File Server. The default pool size is 20,000
+records.
+\li -d <debug level> Set the debugging output level at which File Server runs
+to the value provided. Specifically, the LogLevel global variable is set to the
+given value (See Section 5.2.2). If this switch is not provided, the default
+initial File Server debugging level is set to zero, producing the minimal
+debugging output to the log files.
+\li -k <stack size> Set the stack size to provide server LWPs upon creation,
+measured in 1,024-byte blocks. The default LWP stack size is 24 blocks, or
+24,576 bytes.
+\li -l <large (directory) vnodes> Select the number of "large" vnodes the File
+Server will cache. These vnodes are suitable for recording information about
+AFS directories. The extra space in the vnode allows ACL information to be
+stored along with the directory. The default allocation value is 200 directory
+vnodes.
+\li -pctspare <percent overrun blocks past quota> Similar to the -spare switch,
+except that the number of allowable overrun blocks is expressed as a percentage
+of the given volume's quota. Note: this switch cannot be used in combination
+with the -spare switch.
+\li -rxdbg Instruct the File Server to open a file named rx dbg in the current
+directory, into which the Rx package will write general debugging information.
+If the file is already open (due to the appearance of the -rxdbge switch
+earlier in the command line), this results in a no-op.
+\li -rxdbge Instruct the File Server to open a file named rx dbg in the current
+directory, into which the Rx package will write debugging information related
+to its event-scheduling activities. If the file is already open (due to the
+appearance of the -rxdbg switch earlier in the command line), this results in a
+no-op.
+\li -rxpck <# packets> Set the number of extra Rx packet buffers to hold in
+reserve. These pre-allocated buffers assist in responding to spikes in network
+traffic demands. By default, 100 such packet buffers are maintained.
+\li -s <small (file) vnodes> Select the number of "small" vnodes the File
+Server will cache. These vnodes are suitable for recording information about
+non-directory files. As with directory vnodes, the File Server will allocate
+200 small vnodes by default.
+\li -spare <# overrun blocks to allow> Tell the File Server to allow users
+performing a store operation to overrun the host volume's disk quota by a
+certain number of (1,024-byte) blocks. In other words, the first store
+resulting in a quota overrun will be allowed to succeed if and only if it uses
+no more than these many blocks beyond the quota. Further store operations will
+be rejected until the volume's storage is once again reduced below quota. By
+default, overruns of 1,024 blocks of 1,024 bytes each (1 megabyte total) are
+tolerated. Note: this switch cannot be used in combination with the -pctspare
+switch.
+\li -w <callback wait interval in seconds> This switch determines how often the
+File Server periodic daemon lightweight processes run. Among other things,
+these daemon LWPs check on the validity of callback records, keep disk usage
+statistics up to date, and check the health of the various client machines that
+have previously interacted with the File Server. For a full description of
+these daemon LWPs, consult Section 2.3. The associated argument specifies the
+number of seconds to sleep between daemon invocations. By default, these
+periodic daemons run every 300 seconds (5 minutes).
+
+ \page chap6 Chapter 6: Cache Manager Interfaces
+
+ \section sec6-1 Section 6.1: Overview
+
+\par
+There are several interfaces offered by the Cache Manager, allowing clients to
+access the files stored by the community of AFS File Servers, to configure the
+Cache Manager's behavior and resources, to store and retrieve authentication
+information, to specify the location of community Authentication Server and
+Volume Location Server services, and to observe and debug the Cache Manager's
+state and actions. This chapter will cover the following five interfaces to the
+Cache Manager:
+\li ioctl(): The standard unix ioctl() system call has been extended to
+include more operations, namely waiting until data stores to a File Server
+complete before returning to the caller (VIOCCLOSEWAIT) and getting the name of
+the cell in which an open file resides (VIOCIGETCELL).
+\li pioctl(): An additional system call is provided through which
+applications can access operations specific to AFS, which are often tied to a
+particular pathname. These operations include Access Control List (ACL) and
+mount point management, Kerberos ticket management, cache configuration, cell
+configuration, and status of File Servers.
+\li RPC: Interface by which outside servers and investigators can
+manipulate the Cache Manager. There are two main categories of routines:
+callback management, typically called by the File Server, and
+debugging/statistics, called by programs such as cmdebug and via the xstat
+user-level library for collection of extended statistics.
+\li Files: Much of the Cache Manager's configuration information, as well
+as its view of the AFS services available from the outside world, is obtained
+from parsing various files. One set of these files is typically located in
+/usr/vice/etc, and includes CellServDB, ThisCell, and cacheinfo. Another set is
+usually found in /usr/vice/cache, namely CacheItems, VolumeItems, and AFSLog.
+\li Mariner: This is the interface by which file transfer activity between
+the Cache Manager and File Servers may be monitored. Specifically, it is used
+to monitor the names of the files and directories being fetched and/or stored
+over the network.
+\par
+Another important component not described in this document is the afsd program.
+It is afsd's job to initialize the Cache Manager on a given machine and to
+start up its related daemon threads. It accepts a host of configuration
+decisions via its command-line interface. In addition, it parses some of the
+information kept in the configuration files mentioned above and passes that
+information to the Cache Manager. The reader may find a full description of
+afsd in the AFS 3.0 Command Reference Manual[2].
+
+ \section sec6-2 Section 6.2: Definitions
+
+\par
+This section defines data structures that are used by the pioctl() calls.
+
+ \subsection sec6-2-1 Section 6.2.1: struct VenusFid
+
+\par
+The Cache Manager is the sole active AFS agent aware of the cellular
+architecture of the system. Since AFS file identifiers are not guaranteed to be
+unique across cell boundaries, it must further qualify them for its own
+internal bookkeeping. The struct VenusFid provides just such additional
+qualification, attaching the Cache Manager's internal cell identifier to the
+standard AFS fid.
+\n \b Fields
+\li long Cell - The internal identifier for the cell in which the file resides.
+\li struct ViceFid Fid - The AFS file identifier within the above cell.
+
+ \subsection sec6-2-2 Section 6.2.2: struct ClearToken
+
+\par
+This is the clear-text version of an AFS token of identity. Its fields are
+encrypted into the secret token format, and are made easily available to the
+Cache Manager in this structure.
+\n \b Fields
+\li long AuthHandle - Key version number.
+\li char HandShakeKey[8] - Session key.
+\li long ViceId - Identifier for the AFS principal represented by this token.
+\li long BeginTimestamp - Timestamp of when this token was minted, and hence
+came into effect.
+\li long EndTimestamp - Timestamp of when this token is considered to be
+expired, and thus disregarded.
+
+ \section sec6-3 Section 6.3: ioctl() Interface
+
+\par
+The standard unix ioctl() system call performs operations on file system
+objects referenced with an open file descriptor. AFS has augmented this system
+call with two additional operations, one to perform "safe stores", and one to
+get the name of the cell in which a file resides. A third ioctl() extension is
+now obsolete, namely aborting a store operation currently in progress.
+
+ \subsection sec6-3-1 Section 6.3.1: VIOCCLOSEWAIT
+
+\par
+[Opcode 1] Normally, a client performing a unix close() call on an AFS file
+resumes once the store operation on the given file data to the host File Server
+has commenced but before it has completed. Thus, it is possible that the store
+could actually fail (say, because of network partition or server crashes)
+without the client's knowledge. This new ioctl opcode specifies to the Cache
+Manager that all future close() operations will wait until the associated store
+operation to the File Server has completed fully before returning.
+
+ \subsection sec6-3-2 Section 6.3.2: VIOCABORT
+
+\par
+[Opcode 2] This ioctl() extension is now obsolete. This call results in a noop.
+The original intention of this call was to allow a store operation currently in
+progress to a File Server on the named fid to be aborted.
+
+ \subsection sec6-3-3 Section 6.3.3: VIOIGETCELL
+
+\par
+[Opcode 3] Get the name of the cell in which the given fid resides. If the file
+is not an AFS file, then ENOTTY is returned. The output buffer specified in the
+data area must be large enough to hold the null-terminated string representing
+the file's cell, otherwise EFAULT is returned. However, an out size value of
+zero specifies that the cell name is not to be copied into the output buffer.
+In this case, the caller is simply interested in whether the file is in AFS,
+and not its exact cell of residence.
+
+ \section sec6-4 Section 6.4: pioctl() Interface
+
+ \subsection sec6-4-1 Section 6.4.1: Introduction
+
+\par
+There is a new unix system call, pioctl(), which has been defined especially to
+support the AFS Cache Manager. Its functional definition is as follows:
+\code
+int afs syscall pioctl(IN char *a pathP,
+ IN int a opcode,
+ IN struct ViceIoctl *a paramsP,
+ IN int a followSymLinks)
+\endcode
+\par
+This new call is much like the standard ioctl() call, but differs in that the
+affected file (when applicable) is specified by its path, not by a file
+descriptor. Another difference is the fourth parameter, a followSymLinks,
+determines which file should be used should a pathP be a symbolic link. If a
+followSymLinks be set to 1, then the symbolic link is followed to its target,
+and the pioctl() is applied to that resulting file. If a followSymLinks is set
+to 0, then the pioctl() applies to the symbolic link itself.
+\par
+Not all pioctl() calls affect files. In those cases, the a pathP parameter
+should be set to a null pointer. The second parameter to pioctl(), a opcode,
+specifies which operation is to be performed. The opcode for each of these
+operations is included in the text of the description. Note that not all
+pioctl() opcodes are in use. These unused values correspond to obsolete
+operations.
+\par
+The descriptions that follow identify some of the possible error codes for each
+pioctl() opcode, but do not offer a comprehensive lists. All pioctl() calls
+return 0 upon success.
+\par
+The rest of this section proceeds to describe the individual opcodes available.
+First, though, one asymmetry in this opcode set is pointed out, namely that
+while various operations are defined on AFS mount points, there is no direct
+way to create a mount point.
+\par
+This documentation partitions the pioctl() into several groups:
+\li Volume operations
+\li File Server operations
+\li Cell Operations
+\li Authentication Operations
+\li ACL Operations
+\li Cache operations
+\li Miscellaneous operations
+
+\par
+For all pioctl()s, the fields within the a paramsP parameter will be referred
+to directly. Thus, the values of in, in size, out, and out size are discussed,
+rather than the settings for a paramsP->in, a paramsP->in size, a paramsP->out,
+and a paramsP->out size.
+\par
+For convenience of reference, a list of the actively-supported pioctl()s, their
+opcodes, and brief description appears (in opcode order) below.
+\li [1] VIOCSETAL : Set the ACL on a directory
+\li [2] VIOCGETAL : Get the ACL for a directory
+\li [3] VIOCSETTOK : Set the caller's token for a cell
+\li [4] VIOCGETVOLSTAT : Get volume status
+\li [5] VIOCSETVOLSTAT : Set volume status
+\li [6] VIOCFLUSH : Flush an object from the cache
+\li [8] VIOCGETTOK : Get the caller's token for a cell
+\li [9] VIOCUNLOG : Discard authentication information
+\li [10] VIOCCKSERV : Check the status of one or more File Servers
+\li [11] VIOCCKBACK : Mark cached volume info as stale
+\li [12] VIOCCKCONN : Check caller's tokens/connections
+\li [14] VIOCWHEREIS : Find host(s) for a volume
+\li [20] VIOCACCESS : Check caller's access on object
+\li [21] VIOCUNPAG : See [9] VIOCUNLOG
+\li [22] VIOCGETFID : Get fid for named object
+\li [24] VIOCSETCACHESIZE : Set maximum cache size in blocks
+\li [25] VIOCFLUSHCB : Unilaterally drop a callback
+\li [26] VIOCNEWCELL : Set cell service information
+\li [27] VIOCGETCELL : Get cell configuration entry
+\li [28] VIOCAFS DELETE MT PT : Delete a mount point
+\li [29] VIOC AFS STAT MT PT : Get the contents of a mount point
+\li [30] VIOC FILE CELL NAME : Get cell hosting a given object
+\li [31] VIOC GET WS CELL : Get caller's home cell name
+\li [32] VIOC AFS MARINER HOST : Get/set file transfer monitoring output
+\li [33] VIOC GET PRIMARY CELL : Get the caller's primary cell
+\li [34] VIOC VENUSLOG : Enable/disable Cache Manager logging
+\li [35] VIOC GETCELLSTATUS : Get status info for a cell entry
+\li [36] VIOC SETCELLSTATUS : Set status info for a cell entry
+\li [37] VIOC FLUSHVOLUME : Flush cached data from a volume
+\li [38] VIOC AFS SYSNAME : Get/set the @sys mapping
+\li [39] VIOC EXPORTAFS : Enable/disable NFS/AFS translation
+\li [40] VIOCGETCACHEPARAMS : Get current cache parameter values
+
+ \subsection sec6-4-2 Section 6.4.2: Mount Point Asymmetry
+
+\par
+There is an irregularity which deserves to be mentioned regarding the pioctl()
+interface. There are pioctl() operations for getting information about a mount
+point (VIOC AFS STAT MT PT) and for deleting a mount point (VIOC AFS DELETE MT
+PT), but no operation for creating mount points. To create a mount point, a
+symbolic link obeying a particular format must be created. The first character
+must be either a "%" or a "#", depending on the type of mount point being
+created (see the discussion in Section 6.4.4.4). If the mount point carries the
+name of the cell explicitly, the full cell name will appear next, followed by a
+colon. In all cases, the next portion of the mount point is the volume name. By
+convention, the last character of a mount point must always be a period (".").
+This trailing period is not visible in the output from fs lsmount.
+
+ \subsection sec6-4-3 Section 6.4.3: Volume Operations
+
+\par
+There are several pioctl() opcodes dealing with AFS volumes. It is possible to
+get and set volume information (VIOCGETVOLSTAT, VIOCSETVOLSTAT), discover which
+volume hosts a particular file system object (VIOCWHEREIS), remove all objects
+cached from a given volume (VIOC FLUSHVOLUME), and revalidate cached volume
+information (VIOCCKBACK).
+
+ \subsubsection sec6-4-3-1 Section 6.4.3.1: VIOCGETVOLSTAT: Get volume
+status for pathname
+
+\par
+[Opcode 4] Fetch information concerning the volume that contains the file
+system object named by a pathP. There is no other input for this call, so in
+size should be set to zero. The status information is placed into the buffer
+named by out, if out size is set to a value of sizeof(struct VolumeStatus) or
+larger. Included in the volume information are the volume's ID, quota, and
+number of blocks used in the volume as well as the disk partition on which it
+resides. Internally, the Cache Manager calls the RXAFS GetVolumeInfo() RPC (See
+Section 5.1.3.14) to fetch the volume status.
+\par
+Among the possible error returns, EINVAL indicates that the object named by a
+pathP could not be found.
+
+ \subsubsection sec6-4-3-2 Section 6.4.3.2: VIOCSETVOLSTAT: Set volume
+status for pathname
+
+\par
+[Opcode 5] Set the status fields for the volume hosting the file system object
+named by a pathP. The first object placed into the input buffer in is the new
+status image. Only those fields that may change, namely MinQuota and MaxQuota
+fields, are interpreted upon receipt by the File Server, and are set to the
+desired values. Immediately after the struct VolumeStatus image, the caller
+must place the null-terminated string name of the volume involved in the input
+buffer. New settings for the offline message and MOTD (Message of the Day)
+strings may appear after the volume name. If there are no changes in the
+offline and/or MOTD messages, a null string must appear for that item. The in
+size parameter must be set to the total number of bytes so inserted, including
+the nulls after each string. Internally, the Cache Manager calls the RXAFS
+SetVolumeStatus() RPC (See Section 5.1.3.16) to store the new volume status.
+\par
+Among the possible error returns, EINVAL indicates that the object named by a
+pathP could not be found.
+
+ \subsubsection sec6-4-3-3 Section 6.4.3.3: VIOCWHEREIS: Find the
+server(s) hosting the pathname's volume
+
+\par
+[Opcode 14] Find the set of machines that host the volume in which the file
+system object named by a pathP resides. The input buffer in is not used by this
+call, so in size should be set to zero. The output buffer indicated by out is
+filled with up to 8 IP addresses, one for each File Server hosting the
+indicated volume. Thus, out size should be set to at least (8*sizeof(long)).
+This group of hosts is terminated by the first zeroed IP address that appears
+in the list, but under no circumstances are more than 8 host IP addresses
+returned.
+\par
+Among the possible error returns is EINVAL, indicating that the pathname is not
+in AFS, hence is not contained within a volume. If ENODEV is returned, the
+associated volume information could not be obtained.
+
+ \subsubsection sec6-4-3-4 Section 6.4.3.4: VIOC FLUSHVOLUME: Flush all
+data cached from the pathname's volume
+
+\par
+[Opcode 37] Determine the volume in which the file system object named by a
+pathP resides, and then throw away all currently cached copies of files that
+the Cache Manager has obtained from that volume. This call is typically used
+should a user suspect there is some cache corruption associated with the files
+from a given volume.
+
+ \subsubsection sec6-4-3-5 Section 6.4.3.5: VIOCCKBACK: Check validity
+of all cached volume information
+
+\par
+[Opcode 11] Ask the Cache Manager to check the validity of all cached volume
+information. None of the call's parameters are referenced in this call, so a
+pathP and in should be set to the null pointer, and in size and out size should
+be set to zero.
+\par
+This operation is performed in two steps:
+\li 1 The Cache Manager first refreshes its knowledge of the root volume,
+usually named root.afs. On success, it wakes up any of its own threads waiting
+on the arrival of this information, should it have been previously unreachable.
+This typically happens should the Cache Manager discover in its startup
+sequence that information on the root volume is unavailable. Lacking this
+knowledge at startup time, the Cache Manager settles into a semi-quiescent
+state, checking every so often to see if volume service is available and thus
+may complete its own initialization.
+\li 2 Each cached volume record is flagged as being stale. Any future attempt
+to access information from these volumes will result in the volume record's
+data first being refreshed from the Volume Location Server.
+
+ \subsection sec6-4-4 Section 6.4.4: File Server Operations
+
+\par
+One group of pioctl() opcodes is aimed at performing operations against one or
+more File Servers directly. Specifically, a caller may translate a pathname
+into the corresponding AFS fid (VIOCGETFID), unilaterally discard a set of
+callback promises (VIOCFLUSHCB), get status on mount points (VIOC AFS STAT MT
+PT), delete unwanted mount points (VIOC AFS DELETE MT PT), and check the health
+of a group of File Servers(VIOCCKSERV).
+
+ \subsubsection sec6-4-4-1 Section 6.4.4.1: VIOCGETFID: Get augmented
+fid for named file system object
+
+\par
+[Opcode 22] Return the augmented file identifier for the file system object
+named by a pathP. The desired struct VenusFid is placed in the output buffer
+specified by out. The output buffer size, as indicated by the out size
+parameter, must be set to the value of sizeof(struct VenusFid) or greater. The
+input buffer is not referenced in this call, so in should be set to the null
+pointer and in size set to zero.
+\par
+Among the possible error returns, EINVAL indicates that the object named by a
+pathP was not found.
+
+ \subsubsection sec6-4-4-2 Section 6.4.4.2: VIOCFLUSHCB: Unilaterally
+drop a callback
+
+\par
+[Opcode 25] Remove any callback information kept by the Cache Manager on the
+file system object named by a pathP. Internally, the Cache Manager executes a
+call to the RXAFS GiveUpCallBacks() RPC (See Section 5.1.3.13) to inform the
+appropriate File Server that it is being released from its particular callback
+promise. Note that if the named file resides on a read-only volume, then the
+above call is not made, and success is returned immediately. This optimization
+is possible because AFS File Servers do not grant callbacks on files from
+read-only volumes.
+\par
+Among the possible error returns is EINVAL, which indicates that the object
+named by a pathP was not found.
+
+ \subsubsection sec6-4-4-3 Section 6.4.4.3: VIOC AFS DELETE MT PT:
+Delete a mount point
+
+\par
+[Opcode 28] Remove an AFS mount point. The name of the directory in which the
+mount point exists is specified by a pathP, and the string name of the mount
+point within this directory is provided through the in parameter. The input
+buffer length, in size, is set to the length of the mount point name itself,
+including the trailing null. The output buffer is not accessed by this call, so
+out should be set to the null pointer and out size to zero.
+\par
+One important note is that the a followSymLinks argument must be set to zero
+for correct operation. This is counter-intuitive, since at first glance it
+seems that a symbolic link that resolves to a directory should be a valid
+pathname parameter. However, recall that mount points are implemented as
+symbolic links that do not actually point to another file system object, but
+rather simply contain cell and volume information (see the description in
+Section 6.4.2). This "special" symbolic link must not be resolved by the
+pioctl(), but rather presented as-is to the Cache Manager, which then properly
+interprets it and generates a reference to the given volume's root directory.
+As an unfortunate side-effect, a perfectly valid symbolic link referring to a
+directory will be rejected out of hand by this operation as a value for the a
+pathP parameter.
+\par
+Among the possible error returns, EINVAL reports that the named directory was
+not found, and ENOTDIR indicates that the pathname contained within a pathP is
+not a directory.
+
+ \subsubsection sec6-4-4-4 Section 6.4.4.4: VIOC AFS STAT MT PT: Get the
+contents of a mount point
+
+\par
+[Opcode 29] Return the contents of the given mount point. The directory in
+which the mount point in question resides is provided via the a pathP argument,
+and the in buffer contains the name of the mount point object within this
+directory. As usual, in size is set to the length of the input buffer,
+including the trailing null. If the given object is truly a mount point and the
+out buffer is large enough (its length appears in out size), the mount point's
+contents are stored into out.
+\par
+The mount point string returned obeys a stylized format, as fully described in
+Section 5.6.2 of the AFS 3.0 System Administrator's Guide[1]. Briefly, a
+leading pound sign ("#") indicates a standard mount point, inheriting the
+read-only or read-write preferences of the mount point's containing volume. On
+the other hand, a leading percent sign ("%") advises the Cache Manager to cross
+into the read-write version of the volume, regardless of the existence of
+read-only clones. If a colon (":") separator occurs, the portion up to the
+colon itself denotes the fully-qualified cell name hosting the volume. The rest
+of the string is the volume name itself.
+\par
+Among the possible error codes is EINVAL, indicating that the named object is
+not an AFS mount point. Should the name passed in a pathP be something other
+than a directory, then ENOTDIR is returned.
+
+ \subsubsection sec6-4-4-5 Section 6.4.4.5: VIOCCKSERV: Check the status
+of one or more File Servers
+
+\par
+[Opcode 10] Check the status of the File Servers that have been contacted over
+the lifetime of the Cache Manager. The a pathP parameter is ignored by this
+call, so it should be set to the null pointer. The input parameters as
+specified by in are completely optional. If something is placed in the input
+buffer, namely in size is not zero, then the first item stored there is a
+longword used as a bit array of flags. These flags carry instructions as to the
+domain and the "thoroughness" of this check.
+\par
+Only the settings of the least-significant two bits are recognized. Enabling
+the lowest bit tells the Cache Manager not to ping its list of servers, but
+simply report their status as contained in the internal server records.
+Enabling the next-higher bit limits the search to only those File Servers in a
+given cell. If in size is greater than sizeof(long),a null-terminated cell name
+string follows the initial flag array, specifying the cell to check. If this
+search bit is set but no cell name string follows the longword of flags, then
+the search is restricted to those servers contacted from the same cell as the
+caller.
+\par
+This call returns at least one longword into the output buffer out, specifying
+the number of hosts it discovered to be down. If this number is not zero, then
+the longword IP address for each dead (or unreachable) host follows in the
+output buffer. At most 16 server addresses will be returned, as this is the
+maximum number of servers for which the Cache Manager keeps information.
+\par
+Among the possible error returns is ENOENT, indicating that the optional cell
+name string input value is not known to the Cache Manager.
+
+ \subsection sec6-4-5 Section 6.4.5: Cell Operations
+
+\par
+The Cache Manager is the only active AFS agent that understands the system's
+cellular architecture. Thus, it keeps important information concerning the
+identities of the cells in the community, which cell is in direct
+administrative control of the machine upon which it is running, status and
+configuration of its own cell, and what cell-specific operations may be legally
+executed. The following pioctl()s allow client processes to access and update
+this cellular information. Supported operations include adding or updating
+knowledge of a cell, including the cell overseeing the caller's machine
+(VIOCNEWCELL), fetching the contents of a cell configuration entry
+(VIOCGETCELL), finding out which cell hosts a given file system object (VIOC
+FILE CELL NAME), discovering the cell to which the machine belongs (VIOC GET WS
+CELL), finding out the caller's "primary" cell (VIOC GET PRIMARY CELL), and
+getting/setting certain other per-cell system parameters (VIOC GETCELLSTATUS,
+VIOC SETCELLSTATUS).
+
+ \subsubsection sec6-4-5-1 Section 6.4.5.1: VIOCNEWCELL: Set cell
+service information
+
+\par
+[Opcode 26] Give the Cache Manager all the information it needs to access an
+AFS cell. Exactly eight longwords are placed at the beginning of the in input
+buffer. These specify the IP addresses for the machine providing AFS
+authentication and volume location authentication services. The first such
+longword set to zero will signal the end of the list of server IP addresses.
+After these addresses, the input buffer hosts the null-terminated name of the
+cell to which the above servers belong. The a pathP parameter is not used, and
+so should be set to the null pointer.
+\par
+Among the possible error returns is EACCES, indicating that the caller does not
+have the necessary rights to perform the operation. Only root is allowed to set
+cell server information. If either the IP address array or the server name is
+unacceptable, EINVAL will be returned.
+
+ \subsubsection sec6-4-5-2 Section 6.4.5.2: VIOCGETCELL: Get cell
+configuration entry
+
+\par
+[Opcode 27] Get the i'th cell configuration entry known to the Cache Manager.
+The index of the desired entry is placed into the in input buffer as a
+longword, with the first legal value being zero. If there is a cell associated
+with the given index, the output buffer will be filled with an array of 8
+longwords, followed by a null-terminated string.
+\par
+The longwords correspond to the list of IP addresses of the machines providing
+AFS authentication and volume location services. The string reflects the name
+of the cell for which the given machines are operating. There is no explicit
+count returned of the number of valid IP addresses in the longword array.
+Rather, the list is terminated by the first zero value encountered, or when the
+eighth slot is filled.
+\par
+This routine is intended to be called repeatedly, with the index starting at
+zero and increasing each time. The array of cell information records is kept
+compactly, without holes. A return value of EDOM indicates that the given index
+does not map to a valid entry, and thus may be used as the terminating
+condition for the iteration.
+
+ \subsubsection sec6-4-5-3 Section 6.4.5.3: VIOC FILE CELL NAME: Get
+cell hosting a given object
+
+\par
+[Opcode 30] Ask the Cache Manager to return the name of the cell in which the
+file system object named by a pathP resides. The input arguments are not used,
+so in should be set to the null pointer and in size should be set to zero. The
+null-terminated cell name string is returned in the out output buffer.
+\par
+Among the possible error values, EINVAL indicates that the pathname provided in
+a pathP is illegal. If there is no cell information associated with the given
+object, ESRCH is returned.
+
+ \subsubsection sec6-4-5-4 Section 6.4.5.4: VIOC GET WS CELL: Get
+caller's home cell name
+
+\par
+[Opcode 31] Return the name of the cell to which the caller's machine belongs.
+This cell name is returned as a null-terminated string in the output buffer.
+The input arguments are not used, so in should be set to the null pointer and
+in size should be set to zero.
+\par
+Among the possible error returns is ESRCH, stating that the caller's home cell
+information was not available.
+
+ \subsubsection sec6-4-5-5 Section 6.4.5.5: VIOC GET PRIMARY CELL: Get
+the caller's primary cell
+
+\par
+[Opcode 33] Ask the Cache Manager to return the name of the caller's primary
+cell. Internally, the Cache Manager scans its user records, and the cell
+information referenced by that record is used to extract the cell's string
+name. The input arguments are not used, so in should be set to the null pointer
+and in size should be set to zero. The a pathP pathname argument is not used
+either, and should similarly be set to the null pointer. The null-terminated
+cell name string is placed into the output buffer pointed to by out if it has
+suffcient room.
+\par
+Among the possible error returns is ESRCH, stating that the caller's primary
+cell information was not available.
+
+ \subsubsection sec6-4-5-6 Section 6.4.5.6: VIOC GETCELLSTATUS: Get
+status info for a cell entry
+
+\par
+[Opcode 35] Given a cell name, return a single longword of status flags from
+the Cache Manager's entry for that cell. The null-terminated cell name string
+is expected to be in the in parameter, with in size set to its length plus one
+for the trailing null. The status flags are returned in the out buffer, which
+must have out size set to sizeof(long) or larger.
+\par
+The Cache Manager defines the following output flag values for this operation:
+\li 0x1 This entry is considered the caller's primary cell.
+\li 0x2 The unix setuid() operation is not honored.
+\li 0x4 An obsolete version of the Volume Location Server's database is being
+used. While defined, this flag should no longer be set in modern systems.
+
+\par
+Among the possible error returns is ENOENT, informing the caller that the Cache
+Manager has no knowledge of the given cell name.
+
+ \subsubsection sec6-4-5-7 Section 6.4.5.7: VIOC SETCELLSTATUS: Set
+status info for a cell entry
+
+\par
+[Opcode 36] Given a cell name and an image of the cell status bits that should
+be set, record the association in the Cache Manager. The input buffer in must
+be set up as follows. The first entry is the longword containing the cell
+status bits to be set (see the VIOC GETCELLSTATUS description above for valid
+flag definitions). The next entry is another longword, ignored by the Cache
+Manager. The third and final entry in the input buffer is a null-terminated
+string containing the name of the cell for which the status flags are to be
+applied.
+\par
+Among the possible error returns is ENOENT, reflecting the Cache Manager's
+inability to locate its record for the given cell. Only root is allowed to
+execute this operation, and an EACCES return indicates the caller was not
+effectively root when the call took place.
+
+ \subsection sec6-4-6 Section 6.4.6: Authentication Operations
+
+\par
+The Cache Manager serves as the repository for authentication information for
+AFS clients. Each client process belongs to a single Process Authentication
+Group (PAG). Each process in a given PAG shares authentication information with
+the other members, and thus has the identical rights with respect to AFS Access
+Control Lists (ACLs) as all other processes in the PAG. As the Cache Manager
+interacts with File Servers as a client process' agent, it automatically and
+transparently presents the appropriate authentication information as required
+in order to gain the access to which the caller is entitled. Each PAG can host
+exactly one token per cell. These tokens are objects that unequivocally codify
+the principal's identity, and are encrypted for security. Token operations
+between a Cache Manager and File Server are also encrypted, as are the
+interchanges between clients and the Authentication Servers that generate these
+tokens.
+\par
+There are actually two different flavors of tokens, namely clear and secret.
+The data structure representing clear tokens is described in Section 6.2.2, and
+the secret token appears as an undifferentiated byte stream.
+\par
+This section describes the operations involving these tokens, namely getting
+and setting the caller's token for a particular cell (VIOCGETTOK, VIOCSETTOK),
+checking a caller's access on a specified file system object (VIOCACCESS),
+checking the status of caller's tokens associated with the set of File Server
+connections maintained on its behalf (VIOCCKCONN), and discarding tokens
+entirely (VIOCUNLOG, VIOCUNPAG). These abilities are used by such programs as
+login, klog, unlog, and tokens, which must generate, manipulate, and/or destroy
+AFS tokens.
+
+ \subsubsection sec6-4-6-1 Section 6.4.6.1: VIOCSETTOK: Set the caller's
+token for a cell
+
+\par
+[Opcode 3] Store the caller's secret and clear tokens within the Cache Manager.
+The input buffer is used to hold the following quantities, laid out end to end.
+The first item placed in the buffer is a longword, specifying the length in
+bytes of the secret token, followed by the body of the secret token itself. The
+next field is another longword, this time describing the length in bytes of the
+struct ClearToken, followed by the structure. These are all required fields.
+The caller may optionally include two additional fields, following directly
+after the required ones. The first optional field is a longword which is set to
+a non-zero value if the cell in which these tokens were generated is to be
+marked as the caller's primary cell. The second optional argument is a
+null-terminated string specifying the cell in which these tokens apply. If
+these two optional arguments do not appear, the Cache Manager will default to
+using its home cell and marking the entry as non-primary. The a pathP pathname
+parameter is not used, and thus should be set to the null pointer.
+\par
+If the caller does not have any tokens registered for the cell, the Cache
+Manager will store them. If the caller already has tokens for the cell, the new
+values will overwrite their old values. Because these are stored per PAG, the
+new tokens will thus determine the access rights of all other processes
+belonging to the PAG.
+\par
+Among the possible error returns is ESRCH, indicating the named cell is not
+recognized, and EIO, if information on the local cell is not available.
+
+ \subsubsection sec6-4-6-2 Section 6.4.6.2: VIOCGETTOK: Get the caller's
+token for a cell
+
+\par
+[Opcode 8] Get the specified authentication tokens associated with the caller.
+The a pathP parameter is not used, so it should be set to the null pointer.
+Should the input parameter in be set to a null pointer, then this call will
+place the user's tokens for the machine's home cell in the out output buffer,
+if such tokens exist. In this case, the following objects are placed in the
+output buffer. First, a longword specifying the number of bytes in the body of
+the secret token is delivered, followed immediately by the secret token itself.
+Next is a longword indicating the length in bytes of the clear token, followed
+by the clear token. The input parameter may also consist of a single longword,
+indicating the index of the token desired. Since the Cache Manager is capable
+of storing multiple tokens per principal, this allows the caller to iteratively
+extract the full set of tokens stored for the PAG. The first valid index value
+is zero. The list of tokens is kept compactly, without holes. A return value of
+EDOM indicates that the given index does not map to a valid token entry, and
+thus may be used as the terminating condition for the iteration.
+\par
+Other than EDOM, another possible error return is ENOTCONN, specifying that the
+caller does not have any AFS tokens whatsoever.
+
+ \subsubsection sec6-4-6-3 Section 6.4.6.3: VIOCACCESS: Check caller's
+access on object
+
+\par
+[Opcode 20] This operation is used to determine whether the caller has specific
+access rights on a particular file system object. A single longword is placed
+into the input buffer, in, representing the set of rights in question. The
+acceptable values for these access rights are listen in Section 6.4.5. The
+object to check is named by the a pathP parameter. The output parameters are
+not accessed, so out should be set to the null pointer, and out size set to
+zero.
+If the call returns successfully, the caller has at least the set of rights
+denoted by the bits set in the input buffer. Otherwise, EACCESS is returned.
+
+ \subsubsection sec6-4-6-4 Section 6.4.6.4: VIOCCKCONN: Check status of
+caller's tokens/connections
+
+\par
+[Opcode 12] Check whether the suite of File Server connections maintained on
+behalf of the caller by the Cache Manager has valid authentication tokens. This
+function always returns successfully, communicating the health of said
+connections by writing a single longword value to the specified output buffer
+in out. If zero is returned to the output buffer, then two things are true.
+First, the caller has tokens for at least one cell. Second, all tokens
+encountered upon a review of the caller's connections have been properly minted
+(i.e., have not been generated fraudulently), and, in addition, have not yet
+expired. If these conditions do not currently hold for the caller, then the
+output buffer value will be set to EACCES. Neither the a pathP nor input
+parameters are used by this call.
+
+ \subsubsection sec6-4-6-5 Section 6.4.6.5: VIOCUNLOG: Discard
+authentication information
+
+\par
+[Opcode 9] Discard all authentication information held in trust for the caller.
+The Cache Manager sweeps through its user records, destroying all of the
+caller's associated token information. This results in reducing the rights of
+all processes within the caller's PAG to the level of file system access
+granted to the special system:anyuser group.
+\par
+This operation always returns successfully. None of the parameters are
+referenced, so they should all be set to null pointers and zeroes as
+appropriate.
+
+ \subsubsection sec6-4-6-6 Section 6.4.6.6: VIOCUNPAG: Discard
+authentication information
+
+\par
+[Opcode 21] This call is essentially identical to the VIOCUNLOG operation, and
+is in fact implemented internally by the same code for VIOCUNLOG.
+
+ \subsection sec6-4-7 Section 6.4.7: ACL Operations
+
+\par
+This set of opcodes allows manipulation of AFS Access Control Lists (ACLs).
+Callers are allowed to fetch the ACL on a given directory, or to set the ACL on
+a directory. In AFS-3, ACLs are only maintained on directories, not on
+individual files. Thus, a directory ACL determines the allowable accesses on
+all objects within that directory in conjunction with their normal unix mode
+(owner) bits. Should the a pathP parameter specify a file instead of a
+directory, the ACL operation will be performed on the directory in which the
+given file resides.
+\par
+These pioctl() opcodes deal only in external formats for ACLs, namely the
+actual text stored in an AFS ACL container. This external format is a character
+string, composed of a descriptive header followed by some number of individual
+principal-rights pairs. AFS ACLs actually specify two sublists, namely the
+positive and negative rights lists. The positive list catalogues the set of
+rights that certain principals (individual users or groups of users) have,
+while the negative list contains the set of rights specifically denied to the
+named parties.
+\par
+These external ACL representations differ from the internal format generated by
+the Cache Manager after a parsing pass. The external format may be easily
+generated from the internal format as follows. The header format is expressed
+with the following printf() statement:
+\code
+printf("%d\n%d\n", NumPositiveEntries, NumNegativeEntries);
+\endcode
+\par
+The header first specifies the number of entries on the positive rights list,
+which appear first in the ACL body. The number of entries on the negative list
+is the second item in the header. The negative entries appear after the last
+positive entry.
+\par
+Each entry in the ACL proper obeys the format imposed by the following printf()
+statement:
+\code
+printf("%s\t%d\n", UserOrGroupName, RightsMask);
+\endcode
+\par
+Note that the string name for the user or group is stored in an externalized
+ACL entry. The Protection Server stores the mappings between the numerical
+identifiers for AFS principals and their character string representations.
+There are cases where there is no mapping from the numerical identifier to a
+string name. For example, a user or group may have been deleted sometime after
+they were added to the ACL and before the Cache Manager externalized the ACL
+for storage. In this case, the Cache Manager sets UserOrGroupName to the string
+version of the principal's integer identifier. Should the erz principal be
+deleted from the Protection Server's database in the above scenario, then the
+string '1019' will be stored, since it corresponded to erz's former numerical
+identifier.
+\par
+The RightsMask parameter to the above call represents the set of rights the
+named principal may exercise on the objects covered by the ACL. The following
+flags may be OR'ed together to construct the desired access rights placed in
+RightsMask:
+\code
+#define PRSFS_READ 1 /*Read files*/
+#define PRSFS_WRITE 2 /*Write & write-lock existing files*/
+#define PRSFS_INSERT 4 /*Insert & write-lock new files*/
+#define PRSFS_LOOKUP 8 /*Enumerate files and examine ACL*/
+#define PRSFS_DELETE 16 /*Remove files*/
+#define PRSFS_LOCK 32 /*Read-lock files*/
+#define PRSFS_ADMINISTER 64 /*Set access list of directory*/
+\endcode
+
+ \subsubsection sec6-4-7-1 Section 6.4.7.1: VIOCSETAL: Set the ACL on a
+directory
+
+\par
+[Opcode 1] Set the contents of the ACL associated with the file system object
+named by a pathP. Should this pathname indicate a file and not a directory, the
+Cache Manager will apply this operation to the file's parent directory. The new
+ACL contents, expressed in their externalized form, are made available in in,
+with in size set to its length in characters, including the trailing null.
+There is no output from this call, so out size should be set to zero.
+Internally, the Cache Manager will call the RXAFS StoreACL() RPC (see Section
+5.1.3.3 to store the new ACL on the proper File Server.
+\par
+Possible error codes include EINVAL, indicating that one of three things may be
+true: the named path is not in AFS, there are too many entries in the specified
+ACL, or a non-existent user or group appears on the ACL.
+
+ \subsubsection sec6-4-7-2 Section 6.4.7.2: VIOCGETAL: Get the ACL for a
+directory
+
+\par
+[Opcode 2] Get the contents of the ACL associated with the file system object
+named by a pathP. Should this pathname indicate a file and not a directory, the
+Cache Manager will apply this operation to the file's parent directory. The ACL
+contents, expressed in their externalized form, are delivered into the out
+buffer if out size has been set to a value which indicates that there is enough
+room for the specified ACL. This ACL string will be null-terminated. There is
+no input to this call, so in size should be set to zero. Internally, the Cache
+Manager will call the RXAFS FetchACL() RPC (see Section 5.1.3.1) to fetch the
+ACL from the proper File Server.
+\par
+Possible error codes include EINVAL, indicating that the named path is not in
+AFS.
+
+ \subsection sec6-4-8 Section 6.4.8: Cache Operations
+
+\par
+It is possible to inquire about and affect various aspects of the cache
+maintained locally by the Cache Manager through the group of pioctl()s
+described below. Specifically, one may force certain file system objects to be
+removed from the cache (VIOCFLUSH), set the maximum number of blocks usable by
+the cache (VIOCSETCACHESIZE), and ask for information about the cache's current
+state (VIOCGETCACHEPARAMS).
+
+ \subsubsection sec6-4-8-1 Section 6.4.8.1: VIOCFLUSH: Flush an object
+from the cache
+
+\par
+[Opcode 6] Flush the file system object specified by a pathP out of the local
+cache. The other parameters are not referenced, so they should be set to the
+proper combination of null pointers and zeroes.
+\par
+Among the possible error returns is EINVAL, indicating that the value supplied
+in the a pathP parameter is not acceptable.
+
+ \subsubsection sec6-4-8-2 Section 6.4.8.2: VIOCSETCACHESIZE: Set
+maximum cache size in blocks
+
+\par
+[Opcode 24] Instructs the Cache Manager to set a new maximum size (in 1 Kbyte
+blocks) for its local cache. The input buffer located at in contains the new
+maximum block count. If zero is supplied for this value, the Cache Manager will
+revert its cache limit to its value at startup time. Neither the a pathP nor
+output buffer parameters is referenced by this operation. The Cache Manager
+recomputes its other cache parameters based on this new value, including the
+number of cache files allowed to be dirty at once and the total amount of space
+filled with dirty chunks. Should the new setting be smaller than the number of
+blocks currently being used, the Cache Manager will throw things out of the
+cache until it obeys the new limit.
+\par
+The caller is required to be effectively running as root, or this call will
+fail, returning EACCES. If the Cache Manager is configured to run with a memory
+cache instead of a disk cache, this operation will also fail, returning EROF.
+
+ \subsubsection sec6-4-8-3 Section 6.4.8.3: VIOCGETCACHEPARAMS: Get
+current cache parameter values
+
+\par
+[Opcode 40] Fetch the current values being used for the cache parameters. The
+output buffer is filled with MAXGCSTATS (16) longwords, describing these
+parameters. Only the first two longwords in this array are currently set. The
+first contains the value of afs cacheBlocks, or the maximum number of 1 Kbyte
+blocks which may be used in the cache (see Section 6.4.8.2 for how this value
+may be set). The second longword contains the value of the Cache Manager's
+internal afs blocksUsed variable, or the number of these cache blocks currently
+in use. All other longwords in the array are set to zero. Neither the a pathP
+nor input buffer arguments are referenced by this call.
+\par
+This routine always returns successfully.
+
+ \subsection sec6-4-9 Section 6.4.9: Miscellaneous Operations
+
+\par
+There are several other AFS-specific operations accessible via the pioctl()
+interface that don't fit cleanly into the above categories. They are described
+in this section, and include manipulation of the socket-based Mariner file
+trace interface (VIOC AFS MARINER HOST), enabling and disabling of the
+file-based AFSLog output interface for debugging (VIOC VENUSLOG), getting and
+setting the value of the special @sys pathname component mapping (VIOC AFS
+SYSNAME), and turning the NFS-AFS translator service on and off (VIOC
+EXPORTAFS).
+
+ \subsubsection sec6-4-9-1 Section 6.4.9.1: VIOC AFS MARINER HOST:
+Get/set file transfer monitoring output
+
+\par
+[Opcode 32] This operation is used to get or set the IP address of the host
+destined to receive Mariner output. A detailed description of the Cache Manager
+Mariner interface may be found in Section 6.7.
+\par
+The input buffer located at in is used to pass a single longword containing the
+IP address of the machine to receive output regarding file transfers between
+the Cache Manager and any File Server. If the chosen host IP address is
+0xffffffff, the Cache Manager is prompted to turn off generation of Mariner
+output entirely. If the chosen host IP address is zero, then the Cache Manager
+will not set the Mariner host, but rather return the current Mariner host as a
+single longword written to the out output buffer. Any other value chosen for
+the host IP address enables Mariner output (if it was not already enabled) and
+causes all further traffic to be directed to the given machine.
+\par
+This function always returns successfully.
+
+ \subsubsection sec6-4-9-2 Section 6.4.9.2: VIOC VENUSLOG:
+Enable/disable Cache Manager logging
+
+\par
+[Opcode 34] Tell the Cache Manager whether to generate debugging information,
+and what kind of debugging output to enable. The input buffer located at in is
+used to transmit a single longword to the Cache Manager, expressing the
+caller's wishes. Of the four bytes making up the longword, the highest byte
+indicates the desired value for the internal afsDebug variable, enabling or
+disabling general trace output. The next highest byte indicates the desired
+value for the internal netDebug variable, enabling or disabling network-level
+debugging traces. The third byte is unused, and the low-order byte represents
+an overall on/off value for the functionality. There is a special value for the
+low-order byte, 99, which instructs the Cache Manager to return the current
+debugging setting as a single longword placed into the output buffer pointed to
+by out. The a pathP parameter is not referenced by this routine.
+\par
+Trace output is delivered to the AFSLog file, typically located in the
+/usr/vice/etc directory. When this form of debugging output is enabled, the
+existing AFSLog file is truncated, and its file descriptor is stored for future
+use. When this debugging is disabled, a close() is done on the file, forcing
+all its data to disk. For additional information on the AFSLog file for
+collecting Cache Manager traces, please see the description in Section 6.6.2.1.
+\par
+This call will only succeed if the caller is effectively running as root. If
+this is not the case, an error code of EACCES is returned.
+
+ \subsubsection sec6-4-9-3 Section 6.4.9.3: VIOC AFS SYSNAME: Get/set
+the @sys mapping
+
+\par
+[Opcode 38] Get or set the value of the special @sys pathname component
+understood by the Cache Manager. The input buffer pointed to by in is used to
+house a longword whose value determines whether the @sys value is being set (1)
+or whether the current value is being fetched (0). If it is being set, then a
+null-terminated string is expected to follow in the input buffer, specifying
+the new value of @sys. Otherwise, if we are asking the Cache Manager for the
+current @sys setting, a null-terminated string bearing that value will be
+placed in the out output buffer. The a pathP parameter is not used by this
+call, and thus should be set to a null pointer.
+\par
+There are no special privileges required of the caller to fetch the value of
+the current @sys mapping. However, a native caller must be running effectively
+as root in order to successfully alter the mapping. An unauthorized attempt to
+change the @sys setting will be ignored, and cause this routine to return
+EACCES. This requirement is relaxed for VIOC AFS SYSNAME pioctl() calls
+emanating from foreign file systems such as NFS and accessing AFS files through
+the NFS-AFS translator. Each such remote caller may set its own notion of what
+the @sys mapping is without affecting native AFS clients. Since the uid values
+received in calls from NFS machines are inherently insecure, it is impossible
+to enforce the fact that the caller is truly root on the NFS machine. This,
+while any principal running on an NFS machine may change that foreign machine's
+perception of @sys, it does not impact native AFS users in any way.
+
+ \subsubsection sec6-4-9-4 Section 6.4.9.4: VIOC EXPORTAFS:
+Enable/disable NFS/AFS translation
+
+\par
+[Opcode 39] Enable or disable the ability of an AFS-capable machine to export
+AFS access to NFS clients. Actually, this is a general facility allowing
+exportation of AFS service to any number of other file systems, but the only
+support currently in place is for NFS client machines. A single longword is
+expected in the input buffer in. This input longword is partitioned into
+individual bytes, organized as follows. The high-order byte communicates the
+type of foreign client to receive AFS file services. There are currently two
+legal values for this field, namely 0 for the null foreign file system and 1
+for NFS. The next byte determines whether the Cache Manager is being asked to
+get or set this information. A non-zero value here is interpreted as a command
+to set the export information according to what's in the input longword, and a
+zero-valued byte in this position instructs the Cache Manager to place a
+longword in the output buffer out, which contains the current export settings
+for the foreign system type specified in the high-order byte. The third input
+byte is not used, and the lowest-order input buffer byte determines whether
+export services for the specified system are being enabled or disabled. A
+non-zero value will turn on the services, and a zero value will shut them down.
+The a pathP pathname parameter is not used by this call, and the routine
+generates output only if the export information is being requested instead of
+being set.
+\par
+The caller must be effectively running as root in order for this operation to
+succeed. The call returns EACCES if the caller is not so authorized. If the
+caller specifies an illegal foreign system type in the high-order byte of the
+input longword, then ENODEV is returned. Again, NFS is the only foreign file
+system currently supported.
+\par
+Practically speaking, the machine providing NFS-AFS translation services must
+enable this service with this pioctl() before any NFS client machines may begin
+accessing AFS files. Conversely, if an administrator turns off this export
+facility, the export code on the translator machine will immediately stop
+responding to traffic from its active NFS clients.
+
+ \section sec6-5 Section 6.5: RPC Interface
+
+ \subsection sec6-5-1 Section 6.5.1: Introduction
+
+\par
+This section covers the structure and workings of the Cache Manager's RPC
+interface. Typically, these calls are made by File Server processes. However,
+some of the calls are designed specifically for debugging programs (e.g., the
+cmdebug facility) and for collection of statistical and performance information
+from the Cache Manager. Any client application that makes direct calls on the
+File Server RPC interface must be prepared to export a subset of the Cache
+Manager RPC interface, as discussed in Section 5.1.6.
+\par
+This section will first examine the Cache Manager's use of locks, whose
+settings may be observed via one of the RPC interface calls. Next, it will
+present some definitions and data structures used in the RPC interface, and
+finally document the individual calls available through this interface.
+
+ \subsection sec6-5-2 Section 6.5.2: Locks
+
+\par
+The Cache Manager makes use of locking to insure its internal integrity in the
+face of its multi-threaded design. A total of 11 locks are maintained for this
+purpose, one of which is now obsolete and no longer used (see below). These
+locks are strictly internal, and the Cache Manager itself is the only one able
+to manipulate them. The current settings for these system locks are externally
+accessible for debugging purposes via the AFSRXCB GetLock() RPC interface call,
+as described in Section 6.5.5.4. For each lock, its index in the locking table
+is given in the following text.
+\li afs xvcache [Index 0]: This lock controls access to the status cache
+entries maintained by the Cache Manager. This stat cache keeps stat()-related
+information for AFS files it has dealt with. The stat information is kept
+separate from actual data contents of the related file, since this information
+may change independently (say, as a result of a unix chown() call.
+\li afs xdcache [Index 1]: This lock moderates access to the Cache Manager's
+data cache, namely the contents of the file system objects it has cached
+locally. As stated above, this data cache is separate from the associated
+stat() information.
+\li afs xserver [Index 2]: This lock controls access to the File Server machine
+description table, which keeps tabs on all File Servers contacted in recent
+history. This lock thus indirectly controls access to the set of per-server RPC
+connection descriptors the File Server table makes visible.
+\li afs xvcb [Index 3]: This lock supervises access to the volume callback
+information kept by the Cache Manager. This table is referenced, for example,
+when a client decides to remove one or more callbacks on files from a given
+volume (see the RXAFS GiveUpCallBacks() description on Section 5.1.3.13).
+\li afs xbrs [Index 4]: This lock serializes the actions of the Cache Manager's
+background daemons, which perform prefetching and background file storage
+duties.
+\li afs xcell [Index 5]: This lock controls the addition, deletion, and update
+of items on the linked list housing information on cells known to the Cache
+Manager.
+\li afs xconn [Index 6]: This lock supervises operations concerning the set of
+RPC connection structures kept by the system. This lock is used in combination
+with the
+\li afs xserver lock described above. In some internal Cache Manager code
+paths, the File Server description records are first locked, and then the afs
+xconn lock is used to access the associated Rx connection records. afs xuser
+[Index 7]: This lock serializes access to the per-user structures maintained by
+the Cache Manager.
+\li afs xvolume [Index 8]: This lock is used to control access to the Cache
+Manager's volume information cache, namely the set of entries currently in
+memory, a subset of those stably housed in the VolumeItems disk file (see
+Section 6.6.2.3).
+\li afs puttofileLock [Index 9]: This lock is obsolete, and while still defined
+by the system is no longer used. It formerly serialized writes to a debugging
+output interface buffer, but the internal mechanism has since been updated and
+improved.
+\li afs ftf [Index 10]: This lock is used when flushing cache text pages from
+the machine's virtual memory tables. For each specific machine architecture on
+which the Cache Manager runs, there is a set of virtual memory operations which
+must be invoked to perform this operation. The result of such activities is to
+make sure that the latest contents of new incarnations of binaries are used,
+instead of outdated copies of previous versions still resident in the virtual
+memory system.
+
+ \subsection sec6-5-3 Section 6.5.3: Definitions and Typedefs
+
+\par
+This section documents some macro definitions and typedefs referenced by the
+Cache Manager's RPC interface. Specifically, these definitions and typedefs are
+used in the RXAFSCB GetXStats() and RXAFSCB XStatsVersion calls as described in
+Sections 6.5.5.6 and 6.5.5.7.
+
+\code
+/*
+* Define the version of CacheManager and FileServer extended
+* statistics being implemented.
+*/
+const AFSCB_XSTAT_VERSION = 1;
+
+/*
+* Define the maximum arrays for passing extended statistics
+* info for the CacheManager and FileServer back to our caller.
+*/
+const AFSCB_MAX_XSTAT_LONGS = 2048;
+typedef long AFSCB_CollData<AFSCB_MAX_XSTAT_LONGS>;
+
+/*
+* Define the identifiers for the accessible extended stats data
+* collections.
+*/
+const AFSCB_XSTATSCOLL_CALL_INFO = 0; /*CM call counting & info*/
+const AFSCB_XSTATSCOLL_PERF_INFO = 1; /*CM performance info*/
+\endcode
+
+ \subsection sec6-5-4 Section 6.5.4: Structures
+
+\par
+This section documents some structures used in the Cache Manager RPC interface.
+As with the constants and typedefs in the previous section, these items are
+used in the RXAFSCB GetXStats() and RXAFSCB XStatsVersion calls as described in
+Sections 6.5.5.6 and 6.5.5.7.
+
+ \subsubsection sec6-5-4-1 Section 6.5.4.1: struct afs MeanStats
+
+\par
+This structure may be used to collect a running average figure. It is included
+in some of the statistics structures described below.
+\n \b Fields
+\li long average - The computed average.
+\li long elements - The number of elements sampled for the above aveage.
+
+ \subsubsection sec6-5-4-2 Section 6.5.4.2: struct afs CMCallStats
+
+\par
+This structure maintains profiling information, communicating the number of
+times internal Cache Manager functions are invoked. Each field name has a "C "
+prefix, followed by the name of the function being watched. As this structure
+has entries for over 500 functions, it will not be described further here.
+Those readers who wish to see the full layout of this structure are referred to
+Appendix A.
+\par
+The AFSCB XSTATSCOLL CALL INFO data collection includes the information in this
+structure.
+
+ \subsubsection sec6-5-4-3 Section 6.5.4.3: struct afs CMMeanStats
+
+\par
+This is the other part of the information (along with the struct afs
+CMCallStats construct described above) returned by the AFSCB XSTATSCOLL CALL
+INFO data collection defined by the Cache Manager (see Section 6.5.3). It is
+accessible via the RXAFSCB GetXStats() interface routine, as defined in Section
+6.5.5.7.
+\par
+This structure represents the beginning of work to compute average values for
+some of the extended statistics collected by the Cache Manager.
+\n \b Fields
+\li struct afs MeanStats something - Intended to collect averages for some of
+the Cache Manager extended statistics; not yet implemented.
+
+ \subsubsection sec6-5-4-4 Section 6.5.4.4: struct afs CMStats
+
+\par
+This structure defines the information returned by the AFSCB XSTATSCOLL CALL
+INFO data collection defined by the Cache Manager (see Section 6.5.3). It is
+accessible via the RXAFSCB GetXStats() interface routine, as defined in Section
+6.5.5.7.
+\n \b Fields
+\li struct afs CallStats callInfo - Contains the counts on the number of times
+each internal Cache Manager function has been called.
+\li struct afs MeanStats something - Intended to collect averages for some of
+the Cache Manager extended statistics; not yet implemented.
+
+ \subsubsection sec6-5-4-5 Section 6.5.4.5: struct afs CMPerfStats
+
+\par
+This is the information returned by the AFSCB XSTATSCOLL PERF INFO data
+collection defined by the Cache Manager (see Section 6.5.3). It is accessible
+via the RXAFSCB GetXStats() interface routine, as defined in Section 6.5.5.7.
+\n \b Fields
+\li long numPerfCalls - Number of performance calls received.
+\li long epoch - Cache Manager epoch time.
+\li long numCellsContacted - Number of cells contacted.
+\li long dlocalAccesses - Number of data accesses to files within the local
+cell.
+\li long vlocalAccesses - Number of stat accesses to files within the local
+cell.
+\li long dremoteAccesses - Number of data accesses to files outside of the
+local cell.
+\li long vremoteAccesses - Number of stat accesses to files outside of the
+local cell.
+\li long cacheNumEntries - Number of cache entries.
+\li long cacheBlocksTotal - Number of (1K) blocks configured for the AFS cache.
+\li long cacheBlocksInUse - Number of cache blocks actively in use.
+\li long cacheBlocksOrig - Number of cache blocks configured at bootup.
+\li long cacheMaxDirtyChunks - Maximum number of dirty cache chunks tolerated.
+\li long cacheCurrDirtyChunks - Current count of dirty cache chunks.
+\li long dcacheHits - Number of data file requests satisfied by the local
+cache.
+\li long vcacheHits - Number of stat entry requests satisfied by the local
+cache.
+\li long dcacheMisses - Number of data file requests not satisfied by the local
+cache.
+\li long vcacheMisses - Number of stat entry requests not satisfied by the
+local cache.
+\li long cacheFlushes - Number of files flushed from the cache.
+\li long cacheFilesReused - Number of cache files reused.
+\li long numServerRecords - Number of records used for storing information
+concerning File Servers.
+\li long ProtServerAddr - IP addres of the Protection Server used (not
+implemented).
+\li long spare[32] - A set of longword spares reserved for future use.
+
+ \subsection sec6-5-5 Section 6.5.5: Function Calls
+
+\par
+This section discusses the Cache Manager interface calls. No special
+permissions are required of the caller for any of these operations. A summary
+of the calls making up the interface appears below:
+\li RXAFSCB Probe() "Are-you-alive" call.
+\li RXAFSCB CallBack() Report callbacks dropped by a File Server.
+\li RXAFSCB InitCallBackState() Purge callback state from a File Server.
+\li RXAFSCB GetLock() Get contents of Cache Manager lock table.
+\li RXAFSCB GetCE() Get cache file description.
+\li RXAFSCB XStatsVersion() Get version of extended statistics package.
+\li RXAFSCB GetXStats() Get contents of extended statistics data collection.
+
+ \subsubsection sec6-5-5-1 Section 6.5.5.1: RXAFSCB Probe - Acknowledge
+that the underlying callback service is still operational
+
+\code
+int RXAFSCB Probe(IN struct rx call *a rxCallP)
+\endcode
+\par Description
+[Opcode 206] This call simply implements an "are-you-alive" operation, used to
+determine if the given Cache Manager is still running. Any File Server will
+probe each of the Cache Managers with which it has interacted on a regular
+basis, keeping track of their health. This information serves an important
+purpose for a File Server. In particular, it is used to trigger purging of
+deceased Cache Managers from the File Server's callback records, and also to
+instruct a new or "resurrected" Cache Manager to purge its own callback state
+for the invoking File Server.
+\par
+Rx call information for the related Cache Manager is contained in a rxCallP.
+\par Error Codes
+---No error codes are generated.
+
+ \subsubsection sec6-5-5-2 Section 6.5.5.2: RXAFSCB CallBack - Report
+callbacks dropped by a File Server
+
+\code
+int RXAFSCB CallBack(IN struct rx call *a rxCallP,
+ IN AFSCBFids *a fidArrayP,
+ IN AFSCBs *a callBackArrayP)
+\endcode
+\par Description
+[Opcode 204] Provide information on dropped callbacks to the Cache Manager for
+the calling File Server. The number of fids involved appears in a
+fidArrayP->AFSCBFids len, with the fids themselves located at a
+fidArrayP->AFSCBFids val. Similarly, the number of associated callbacks is
+placed in a callBackArrayP->AFSCBs len, with the callbacks themselves located
+at a callBackArrayP->AFSCBs val.
+\par
+Rx call information for the related Cache Manager is contained in a rxCallP.
+\par Error Codes
+---No error codes are generated.
+
+ \subsubsection sec6-5-5-3 Section 6.5.5.3: RXAFSCB InitCallBackState -
+Purge callback state from a File Server
+
+\code
+int RXAFSCB InitCallBackState(IN struct rx call *a rxCallP)
+\endcode
+\par Description
+[Opcode 205] This routine instructs the Cache Manager to purge its callback
+state for all files and directories that live on the calling host. This
+function is typically called by a File Server when it gets a request from a
+Cache Manager that does not appear in its internal records. This handles
+situations where Cache Managers survive a File Server, or get separated from it
+via a temporary network partition. This also happens upon bootup, or whenever
+the File Server must throw away its record of a Cache Manager because its
+tables have been filled.
+\par
+Rx call information for the related Cache Manager is contained in a rxCallP.
+\par Error Codes
+---No error codes are generated.
+
+ \subsubsection sec6-5-5-4 Section 6.5.5.4: RXAFSCB GetLock - Get
+contents of Cache Manager lock table
+
+\code
+int RXAFSCB GetLock(IN struct rx call *a rxCall,
+ IN long a index,
+ OUT AFSDBLock *a lockP)
+\endcode
+\par Description
+[Opcode 207] Fetch the contents of entry a index in the Cache Manager lock
+table. There are 11 locks in the table, as described in Section 6.5.2. The
+contents of the desired lock, including a string name representing the lock,
+are returned in a lockP.
+\par
+This call is not used by File Servers, but rather by debugging tools such as
+cmdebug.
+\par
+Rx call information for the related Cache Manager is contained in a rxCallP.
+\par Error Codes
+The index value supplied in a index is out of range; it must be between 0 and
+10.
+
+ \subsubsection sec6-5-5-5 Section 6.5.5.5: RXAFSCB GetCE - Get cache
+file description
+
+\code
+int RXAFSCB GetCE(IN struct rx call *a rxCall,
+ IN long a index,
+ OUT AFSDBCacheEntry *a ceP)
+\endcode
+\par Description
+[Opcode 208] Fetch the description for entry a index in the Cache Manager file
+cache, storing it into the buffer to which a ceP points. The structure returned
+into this pointer variable is described in Section 4.3.2.
+\par
+This call is not used by File Servers, but rather by debugging tools such as
+cmdebug.
+\par
+Rx call information for the related Cache Manager is contained in a rxCallP.
+\par Error Codes
+The index value supplied in a index is out of range.
+
+ \subsubsection sec6-5-5-6 Section 6.5.5.6: RXAFSCB XStatsVersion - Get
+version of extended statistics package
+
+\code
+int RXAFSCB XStatsVersion(IN struct rx call *a rxCall,
+ OUT long *a versionNumberP)
+\endcode
+\par Description
+[Opcode 209] This call asks the Cache Manager for the current version number of
+the extended statistics structures it exports (see RXAFSCB GetXStats(), Section
+6.5.5.7). The version number is placed in a versionNumberP.
+\par
+Rx call information for the related Cache Manager is contained in a rxCallP.
+\par Error Codes
+---No error codes are generated.
+
+ \subsubsection sec6-5-5-7 Section 6.5.5.7: RXAFSCB GetXStats - Get
+contents of extended statistics data collection
+
+\code
+int RXAFSCB GetXStats(IN struct rx call *a rxCall,
+ IN long a clientVersionNumber,
+ IN long a collectionNumber,
+ OUT long *a srvVersionNumberP,
+ OUT long *a timeP,
+ OUT AFSCB CollData *a dataP)
+\endcode
+\par Description
+[Opcode 210] This function fetches the contents of the specified Cache Manager
+extended statistics structure. The caller provides the version number of the
+data it expects to receive in a clientVersionNumber. Also provided in a
+collectionNumber is the numerical identifier for the desired data collection.
+There are currently two of these data collections defined: AFSCB XSTATSCOLL
+CALL INFO, which is the list of tallies of the number of invocations of
+internal Cache Manager procedure calls, and AFSCB XSTATSCOLL PERF INFO, which
+is a list of performance-related numbers. The precise contents of these
+collections are described in Section 6.5.4. The current version number of the
+Cache Manager collections is returned in a srvVersionNumberP, and is always set
+upon return, even if the caller has asked for a different version. If the
+correct version number has been specified, and a supported collection number
+given, then the collection data is returned in a dataP. The time of collection
+is also returned, being placed in a timeP.
+\par
+Rx call information for the related Cache Manager is contained in a rxCallP.
+\par Error Codes
+The collection number supplied in a collectionNumber is out of range.
+
+ \section sec6-6 Section 6.6: Files
+
+\par
+The Cache Manager gets some of its start-up configuration information from
+files located on the client machine's hard disk. Each client is required to
+supply a /usr/vice/etc directory in which this configuration data is kept.
+Section 6.6.1 describes the format and purpose of the three files contributing
+this setup information: ThisCell, CellServDB, and cacheinfo.
+
+ \subsection sec6-6-1 Section 6.6.1: Configuration Files
+
+ \subsubsection sec6-6-1-1 Section 6.6.1.1: ThisCell
+
+\par
+The Cache Manager, along with various applications, needs to be able to
+determine the cell to which its client machine belongs. This information is
+provided by the ThisCell file. It contains a single line stating the machine's
+fully-qualified cell name.
+\par
+As with the CellServDB configuration file, the Cache Manager reads the contents
+of ThisCell exactly once, at start-up time. Thus, an incarnation of the Cache
+Manager will maintain precisely one notion of its home cell for its entire
+lifetime. Thus, changes to the text of the ThisCell file will be invisible to
+the running Cache Manager. However, these changes will affect such application
+programs as klog, which allows a user to generate new authentication tickets.
+In this example, klog reads ThisCell every time it is invoked, and then
+interacts with the set of Authentication Servers running in the given home
+cell, unless the caller specifies the desired cell on the command line.
+\par
+The ThisCell file is not expected to be changed on a regular basis. Client
+machines are not imagined to be frequently traded between different
+administrative organizations. The Unix mode bits are set to specify that while
+everyone is allowed to read the file, only root is allowed to modify it.
+
+ \subsubsection sec6-6-1-2 Section 6.6.1.2: CellServDB
+
+\par
+To conduct business with a given AFS cell, a Cache Manager must be informed of
+the cell's name and the set of machines running AFS database servers within
+that cell. Such servers include the Volume Location Server, Authentication
+Server, and Protection Server. This particular cell information is obtained
+upon startup by reading the CellServDB file. Thus, when the Cache Manager
+initialization is complete, it will be able to communicate with the cells
+covered by CellServDB.
+\par
+The following is an excerpt from a valid CellServDB file, demonstrating the
+format used.
+
+\code
+...
+>transarc.com #Transarc Corporation
+192.55.207.7 #henson.transarc.com
+192.55.207.13 #bigbird.transarc.com
+192.55.207.22 #ernie.transarc.com
+>andrew.cmu.edu #Carnegie Mellon University
+128.2.10.2 #vice2.fs.andrew.cmu.edu
+128.2.10.7 #vice7.fs.andrew.cmu.edu
+128.2.10.10 #vice10.fs.andrew.cmu.edu
+...
+\endcode
+\par
+There are four rules describing the legal CellServDB file format:
+\li 1. Each cell has a separate entry. The entries may appear in any order. It
+may be convenient, however, to have the workstation's local cell be the first
+to appear.
+\li 2. No blank lines should appear in the file, even at the end of the last
+entry.
+\li 3. The first line of each cell's entry begins with the '>' character, and
+specifies the cell's human-readable, Internet Domain-style name. Optionally,
+some white space and a comment (preceded by a '#') may follow, briefly
+describing the specified cell.
+\li 4. Each subsequent line in a cell's entry names one of the cell's database
+server machines. The following must appear on the line, in the order given:
+\li The Internet address of the server, in the standard 4-component dot
+notation.
+\li Some amount of whitespace.
+\li A '#', followed by the machine's complete Internet host name. In this
+instance, the '#' sign and the text beyond it specifying the machine name are
+NOT treated as a comment. This is required information.
+\par
+The Cache Manager will use the given host name to determine its current address
+via an Internet Domain lookup. If and only if this lookup fails does the Cache
+Manager fall back to using the dotted Internet address on the first part of the
+line. This dotted address thus appears simply as a hint in case of Domain
+database downtime.
+\par
+The CellServDB file is only parsed once, when the Cache Manager first starts.
+It is possible, however, to amend existing cell information records or add
+completely new ones at any time after Cache Manager initialization completes.
+This is accomplished via the VIOCNEWCELL pioctl() (see Section 6.4.5.1.
+
+ \subsubsection sec6-6-1-3 Section 6.6.1.3: cacheinfo
+
+\par
+This one-line file contains three fields separated by colons:
+\li AFS Root Directory: This is the directory where the Cache Manager mounts
+the AFS root volume. Typically, this is specified to be /afs.
+\li Cache Directory: This field names the directory where the Cache Manager is
+to create its local cache files. This is typically set to /usr/vice/cache.
+\li Cache Blocks: The final field states the upper limit on the number of
+1,024-byte blocks that the Cache Manager is allowed to use in the partition
+hosting the named cache directory.
+\par
+Thus, the following cacheinfo file would instruct the Cache Manager to mount
+the AFS filespace at /afs, and inform it that it may expect to be able to use
+up to 25,000 blocks for the files in its cache directory, /usr/vice/cache.
+\code
+/afs:/usr/vice/cache:25000
+\endcode
+
+ \subsection sec6-6-2 Section 6.6.2: Cache Information Files
+
+ \subsubsection sec6-6-2-1 Section 6.6.2.1: AFSLog
+
+\par
+This is the AFS log file used to hold Cache Manager debugging output. The file
+is set up when the Cache Manager first starts. If it already exists, it is
+truncated. If it doesn't, it is created. Output to this file is enabled and
+disabled via the the VIOC VENUSLOG pioctl() (see Section 6.4.9.2). Normal text
+messages are written to this file by the Cache Manager when output is enabled.
+Each time logging to this file is enabled, the AFSLog file is truncated. Only
+root can read and write this file.
+
+ \subsubsection sec6-6-2-2 Section 6.6.2.2: CacheItems
+
+\par
+The Cache Manager only keeps a subset of its data cache entry descriptors in
+memory at once. The number of these in-memory descriptors is determined by
+afsd. All of the data cache entry descriptors are kept on disk, in the
+CacheItems file. The file begins with a header region, taking up four
+longwords:
+\code
+struct fheader { long magic AFS_FHMAGIC 0x7635fab8 long firstCSize: First chunk
+size long otherCSize: Next chunk sizes long spare }
+\endcode
+\par
+The header is followed by one entry for each cache file. Each is:
+\code
+struct fcache {
+ short hvNextp; /* Next in vnode hash table, or freeDCList */
+ short hcNextp; /* Next index in [fid, chunk] hash table */
+ short chunkNextp; /* File queue of all chunks for a single vnode */
+ struct VenusFid fid; /* Fid for this file */
+ long modTime; /* last time this entry was modified */
+ long versionNo; /* Associated data version number */
+ long chunk; /* Relative chunk number */
+ long inode; /* Unix inode for this chunk */
+ long chunkBytes; /* Num bytes in this chunk */
+ char states; /* Has this chunk been modified? */
+};
+\endcode
+
+ \subsubsection sec6-6-2-3 Section 6.6.2.3: VolumeItems
+
+\par
+The Cache Manager only keeps at most MAXVOLS (50) in-memory volume
+descriptions. However, it records all volume information it has obtained in the
+VolumeItems file in the chosen AFS cache directory. This file is truncated when
+the Cache Manager starts. Each volume record placed into this file has the
+following struct fvolume layout:
+\code
+struct fvolume {
+ long cell; /*Cell for this entry*/
+ long volume; /*Numerical volume ID */
+ long next; /*Hash index*/
+ struct VenusFid dotdot; /*Full fid for .. dir */
+ struct VenusFid mtpoint; /*Full fid for mount point*/
+};
+\endcode
+
+ \section sec6-7 Section 6.7: Mariner Interface
+
+\par
+The Cache Manager Mariner interface allows interested parties to be advised in
+real time as to which files and/or directories are being actively transferred
+between the client machine and one or more File Servers. If enabled, this
+service delivers messages of two different types, as exemplified below:
+\code
+Fetching myDataDirectory
+Fetching myDataFile.c
+Storing myDataObj.o
+\endcode
+\par
+In the first message, the myDataDirectory directory is shown to have just been
+fetched from a File Server. Similarly, the second message indicates that the C
+program myDataFile.c had just been fetched from its File Server of residence.
+Finally, the third message reveals that the myDataObj.o object file has just
+been written out over the network to its respective server.
+\par
+In actuality, the text of the messages carries a string prefix to indicate
+whether a Fetch or Store operation had been performed. So, the full contents of
+the above messages are as follows:
+\code
+fetch$Fetching myDataDirectory
+fetch$Fetching myDataFile.c
+store$Storing myDataObj.o
+\endcode
+The Mariner service may be enabled or disabled for a particular machine by
+using the VIOC AFS MARINER HOST pioctl() (see Section 6.4.9.1). This operation
+allows any host to be specified as the recipient of these messages. A potential
+recipient must have its host be declared the target of such messages, then
+listen to a socket on port 2106.
+\par
+Internally, the Cache Manager maintains a cache of NMAR (10) vnode structure
+pointers and the string name (up to 19 characters) of the associated file or
+directory. This cache is implemented as an array serving as a circular buffer.
+Each time a file is involved in a create or lookup operation on a File Server,
+the current slot in this circular buffer is filled with the relevant vnode and
+string name information, and the current position is advanced. If Mariner
+output is enabled, then an actual network fetch or store operation will trigger
+messages of the kind shown above. Since a fetch or store operation normally
+occurs shortly after the create or lookup, the mapping of vnode to name is
+likely to still be in the Mariner cache when it comes time to generate the
+appropriate message. However, since an unbounded number of other lookups or
+creates could have been performed in the interim, there is no guarantee that
+the mapping entry will not have been overrun. In these instances, the Mariner
+message will be a bit vaguer. Going back to our original example,
+\code
+Fetching myDataDirectory
+Fetching a file
+Storing myDataObj.o
+\endcode
+In this case, the cached association between the vnode containing myDataFile.c
+and its string name was thrown out of the Mariner cache before the network
+fetch operation could be performed. Unable to find the mapping, the generic
+phrase "a file" was used to identify the object involved.
+\par
+Mariner messages only get generated when RPC traffic for fetching or storing a
+file system object occurs between the Cache Manager and a File Server. Thus,
+file accesses that are handled by the Cache Manager's on-board data cache do
+not trigger such announcements.
+
+ \page biblio Bibliography
+
+\li [1] Transarc Corporation. AFS 3.0 System Administrator's Guide,
+F-30-0-D102, Pittsburgh, PA, April 1990.
+\li [2] Transarc Corporation. AFS 3.0 Command Reference Manual, F-30-0-D103,
+Pittsburgh, PA, April 1990.
+\li [3] CMU Information Technology Center. Synchronization and Caching Issues
+in the Andrew File System, USENIX Proceedings, Dallas, TX, Winter 1988.
+\li [4] Sun Microsystems, Inc. NFS: Network File System Protocol Specification,
+RFC 1094, March 1989.
+\li [5] Sun Microsystems, Inc. Design and Implementation of the Sun Network
+File System, USENIX Summer Conference Proceedings, June 1985.
+\li [6] S.P. Miller, B.C. Neuman, J.I. Schiller, J.H. Saltzer. Kerberos
+Authentication and Authorization System, Project Athena Technical Plan, Section
+E.2.1, M.I.T., December 1987.
+\li [7] Bill Bryant. Designing an Authentication System: a Dialogue in Four
+Scenes, Project Athena internal document, M.I.T, draft of 8 February 1988.
+
+*/
--- /dev/null
+/*! \mainpage AFS-3 Programmer's Reference: Specification for the Rx Remote
+ * Procedure Call Facility
+ *
+ * AFS-3 Programmer's Reference:
+ *
+ * Specification for the Rx Remote Procedure Call Facility
+ * \author Edward R. Zayas
+ * Transarc Corporation
+ * \version 1.2
+ * \date 28 August 1991 10:11 .cCopyright 1991 Transarc Corporation All Rights
+ * Reserved FS-00-D164
+ *
+ * \page chap1 Chapter 1 -- Overview of the Rx RPC system
+ *
+ * \section sec1-1 Section 1.1: Introduction to Rx
+ *
+ * \par
+ * The Rx package provides a high-performance, multi-threaded, and secure
+ * mechanism by which
+ * remote procedure calls (RPCs) may be performed between programs executing
+ * anywhere in a
+ * network of computers. The Rx protocol is adaptive, conforming itself to
+ * widely varying
+ * network communication media. It allows user applications to define and
+ * insert their own
+ * security modules, allowing them to execute the precise end-to-end
+ * authentication algorithms
+ * required to suit their needs and goals. Although pervasive throughout the
+ * AFS distributed
+ * file system, all of its agents, and many of its standard application
+ * programs, Rx is entirely
+ * separable from AFS and does not depend on any of its features. In fact, Rx
+ * can be used to build applications engaging in RPC-style communication under
+ * a variety of unix-style file systems. There are in-kernel and user-space
+ * implementations of the Rx facility, with both sharing the same interface.
+ * \par
+ * This document provides a comprehensive and detailed treatment of the Rx RPC
+ * package.
+ *
+ * \section sec1-2 Section 1.2: Basic Concepts
+ *
+ * \par
+ * The Rx design operates on the set of basic concepts described in this
+ * section.
+ *
+ * \subsection sec1-2-1 Section 1.2.1: Security
+ *
+ * \par
+ * The Rx architecture provides for tight integration between the RPC mechanism
+ * and methods for making this communication medium secure. As elaborated in
+ * Section 5.3.1.3 and illustrated by the built-in rxkad security system
+ * described in Chapter 3, Rx defines the format for a generic security module,
+ * and then allows application programmers to define and activate
+ * instantiations of these modules. Rx itself knows nothing about the internal
+ * details of any particular security model, or the module-specific state it
+ * requires. It does, however, know when to call the generic security
+ * operations, and so can easily execute the security algorithm defined. Rx
+ * does maintain basic state per connection on behalf of any given security
+ * class.
+ *
+ * \subsection sec1-2-2 Section 1.2.2: Services
+ *
+ * \par
+ * An Rx-based server exports services, or specific RPC interfaces that
+ * accomplish certain tasks. Services are identified by (host-address,
+ * UDP-port, serviceID) triples. An Rx service is installed and initialized on
+ * a given host through the use of the rx NewService() routine (See Section
+ * 5.6.3). Incoming calls are stamped with the Rx service type, and must match
+ * an installed service to be accepted. Internally, Rx services also carry
+ * string names which identify them, which is useful for remote debugging and
+ * statistics-gathering programs. The use of a service ID allows a single
+ * server process to export multiple, independently-specified Rx RPC services.
+ * \par
+ * Each Rx service contains one or more security classes, as implemented by
+ * individual security objects. These security objects implement end-to-end
+ * security protocols. Individual peer-to-peer connections established on
+ * behalf of an Rx service will select exactly one of the supported security
+ * objects to define the authentication procedures followed by all calls
+ * associated with the connection. Applications are not limited to using only
+ * the core set of built-in security objects offered by Rx. They are free to
+ * define their own security objects in order to execute the specific protocols
+ * they require.
+ * \par
+ * It is possible to specify both the minimum and maximum number of lightweight
+ * processes available to handle simultaneous calls directed to an Rx service.
+ * In addition, certain procedures may be registered with the service and
+ * called at specific times in the course of handling an RPC request.
+ *
+ * \subsection sec1-2-3 Section 1.2.3: Connections
+ *
+ * \par
+ * An Rx connection represents an authenticated communication path, allowing a
+ * sequence of multiple asynchronous conversations (calls). Each connection is
+ * identified by a connection ID. The low-order bits of the connection ID are
+ * reserved so that they may be stamped with the index of a particular call
+ * channel. With up to RX MAXCALLS concurrent calls (set to 4 in this
+ * implementation), the bottom two bits are set aside for this purpose. The
+ * connection ID is not sufficient to uniquely identify an Rx connection by
+ * itself. Should a client crash and restart, it may reuse a connection ID,
+ * causing inconsistent results. Included with the connection ID is the epoch,
+ * or start time for the client side of the connection. After a crash, the next
+ * incarnation of the client will choose a different epoch value. This will
+ * differentiate the new incarnation from the orphaned connection record on the
+ * server side.
+ * \par
+ * Each connection is associated with a parent service, which defines a set of
+ * supported security models. At creation time, an Rx connection selects the
+ * particular security protocol it will implement, referencing the associated
+ * service. The connection structure maintains state for each individual call
+ * simultaneously handled.
+ *
+ * \subsection sec1-2-4 Section 1.2.4: Peers
+ *
+ * \par
+ * For each connection, Rx maintains information describing the entity, or
+ * peer, on the other side of the wire. A peer is identified by a (host,
+ * UDP-port) pair, with an IP address used to identify the host. Included in
+ * the information kept on this remote communication endpoint are such network
+ * parameters as the maximum packet size supported by the host, current
+ * readings on round trip time and retransmission delays, and packet skew (see
+ * Section 1.2.7). There are also congestion control fields, including
+ * retransmission statistics and descriptions of the maximum number of packets
+ * that may be sent to the peer without pausing. Peer structures are shared
+ * between connections whenever possible, and, hence, are reference-counted. A
+ * peer object may be garbage-collected if it is not actively referenced by any
+ * connection structure and a sufficient period of time has lapsed since the
+ * reference count dropped to zero.
+ *
+ * \subsection sec1-2-5 Section 1.2.5: Calls
+ *
+ * \par
+ * An Rx call represents an individual RPC being executed on a given
+ * connection. As described above, each connection may have up to RX MAXCALLS
+ * calls active at any one instant. The information contained in each call
+ * structure is specific to the given call.
+ * \par
+ * "Permanent" call state, such as the call number, is maintained in the
+ * connection structure itself.
+ *
+ * \subsection sec1-2-6 Section 1.2.6: Quotas
+ *
+ * \par
+ * Each attached server thread must be able to make progress to avoid system
+ * deadlock. The Rx facility ensures that it can always handle the arrival of
+ * the next unacknowledged data packet for an attached call with its system of
+ * packet quotas. A certain number of packets are reserved per server thread
+ * for this purpose, allowing the server threads to queue up an entire window
+ * full of data for an active call and still have packet buffers left over to
+ * be able to read its input without blocking.
+ *
+ * \subsection sec1-2-7 Section 1.2.7: Packet Skew
+ *
+ * \par
+ * If a packet is received n packets later than expected (based on packet
+ * serial numbers), then we define it to have a skew of n. The maximum skew
+ * values allow us to decide when a packet hasn't been received yet because it
+ * is out of order, as opposed to when it is likely to have been dropped.
+ *
+ * \subsection sec1-2-8 Section 1.2.8: Multicasting
+ *
+ * \par
+ * The rx multi.c module provides for multicast abilities, sending an RPC to
+ * several targets simultaneously. While true multicasting is not achieved, it
+ * is simulated by a rapid succession of packet transmissions and a collection
+ * algorithm for the replies. A client program, though, may be programmed as if
+ * multicasting were truly taking place. Thus, Rx is poised to take full
+ * advantage of a system supporting true multicasting with minimal disruption
+ * to the existing client code base.
+ *
+ * \section sec1-3 Section 1.3: Scope
+ *
+ * \par
+ * This paper is a member of a documentation suite providing specifications as
+ * to the operation and interfaces offered by the various AFS servers and
+ * agents. Rx is an integral part of the AFS environment, as it provides the
+ * high-performance, secure pathway by which these system components
+ * communicate across the network. Although AFS is dependent on Rx's services,
+ * the reverse is not true. Rx is a fully independent RPC package, standing on
+ * its own and usable in other environments.
+ * \par
+ * The intent of this work is to provide readers with a sufficiently detailed
+ * description of Rx that they may proceed to write their own applications on
+ * top of it. In fact, code for a sample Rx server and client are provided.
+ * \par
+ * One topic related to Rx will not be covered by this document, namely the
+ * Rxgen stub generator. Rather, rxgen is addressed in a separate document.
+ *
+ * \section sec1-4 Section 1.4: Document Layout
+ *
+ * \par
+ * After this introduction, Chapter 2 will introduce and describe various
+ * facilities and tools that support Rx. In particular, the threading and
+ * locking packages used by Rx will be examined, along with a set of timer and
+ * preemption tools. Chapter 3 proceeds to examine the details of one of the
+ * built-in security modules offered by Rx. Based on the Kerberos system
+ * developed by MIT's Project Athena, this rxkad module allows secure, ecrypted
+ * communication between the server and client ends of the RPC. Chapter 5 then
+ * provides the full Rx programming interface, and Chapter 6 illustrates the
+ * use of this programming interface by providing a fully-operational
+ * programming example employing Rx. This rxdemo suite is examined in detail,
+ * ranging all the way from a step-by-step analysis of the human-authored
+ * files, and the Rxgen-generated files upon which they are based, to the
+ * workings of the associated Makefile. Output from the example rxdemo server
+ * and client is also provided.
+ *
+ * \section sec1-5 Section 1.5: Related Documents
+ *
+ * \par
+ * Titles for the full suite of AFS specification documents are listed below.
+ * All of the servers and agents making up the AFS computing environment,
+ * whether running in the unix kernel or in user space, utilize an Rx RPC
+ * interface through which they export their services.
+ * \par
+ * \li AFS-3 Programmer's Reference: Architectural Overview: This paper
+ * provides an architectual overview of the AFS distributed file system,
+ * describing the full set of servers and agents in a coherent way,
+ * illustrating their relationships to each other and examining their
+ * interactions.
+ * \li AFS-3 Programmer's Reference: file Server/Cache Manager Interface: This
+ * document describes the workings and interfaces of the two primary AFS
+ * agents, the file Server and Cache Manager. The file Server provides a
+ * centralized disk repository for sets of files, regulating access to them.
+ * End users sitting on client machines rely on the Cache Manager agent,
+ * running in their kernel, to act as their agent in accessing the data stored
+ * on file Server machines, making those files appear as if they were really
+ * housed locally.
+ * \li AFS-3 Programmer's Reference:Volume Server/Volume Location Server
+ * Interface: This document describes the services through which "containers"
+ * of related user data are located and managed.
+ * \li AFS-3 Programmer's Reference: Protection Server Interface: This paper
+ * describes the server responsible for mapping printable user names to and
+ * from their internal AFS identifiers. The Protection Server also allows users
+ * to create, destroy, and manipulate "groups" of users, which are suitable for
+ * placement on access control lists (ACLs).
+ * \li AFS-3 Programmer's Reference: BOS Server Interface: This paper
+ * explicates the "nanny" service which assists in the administrability of the
+ * AFS environment.
+ * \par
+ * In addition to these papers, the AFS 3.1 product is delivered with its own
+ * user, system administrator, installation, and command reference documents.
+ *
+ * \page chap2 Chapter 2 -- The LWP Lightweight Process Package
+ *
+ * \section sec2-1 Section 2.1: Introduction
+ * \par
+ * This chapter describes a package allowing multiple threads of control to
+ * coexist and cooperate within one unix process. Each such thread of control
+ * is also referred to as a lightweight process, in contrast to the traditional
+ * unix (heavyweight) process. Except for the limitations of a fixed stack size
+ * and non-preemptive scheduling, these lightweight processes possess all the
+ * properties usually associated with full-fledged processes in typical
+ * operating systems. For the purposes of this document, the terms lightweight
+ * process, LWP, and thread are completely interchangeable, and they appear
+ * intermixed in this chapter. Included in this lightweight process facility
+ * are various sub-packages, including services for locking, I/O control,
+ * timers, fast time determination, and preemption.
+ * \par
+ * The Rx facility is not the only client of the LWP package. Other LWP clients
+ * within AFS include the file Server, Protection Server, BOS Server, Volume
+ * Server, Volume Location Server, and the Authentication Server, along with
+ * many of the AFS application programs.
+ *
+ * \section sec2-2 Section 2.2: Description
+ *
+ * \subsection Section 2.2.1: sec2-2-1 LWP Overview
+ *
+ * \par
+ * The LWP package implements primitive functions that provide the basic
+ * facilities required to enable procedures written in C to execute
+ * concurrently and asynchronously. The LWP package is meant to be
+ * general-purpose (note the applications mentioned above), with a heavy
+ * emphasis on simplicity. Interprocess communication facilities can be built
+ * on top of this basic mechanism and in fact, many different IPC mechanisms
+ * could be implemented.
+ * \par
+ * In order to set up the threading support environment, a one-time invocation
+ * of the LWP InitializeProcessSupport() function must precede the use of the
+ * facilities described here. This initialization function carves an initial
+ * process out of the currently executing C procedure and returns its thread
+ * ID. For symmetry, an LWP TerminateProcessSupport() function may be used
+ * explicitly to release any storage allocated by its counterpart. If this
+ * function is used, it must be issued from the thread created by the original
+ * LWP InitializeProcessSupport() invocation.
+ * \par
+ * When any of the lightweight process functions completes, an integer value is
+ * returned to indicate whether an error condition was encountered. By
+ * convention, a return value of zero indicates that the operation succeeded.
+ * \par
+ * Macros, typedefs, and manifest constants for error codes needed by the
+ * threading mechanism are exported by the lwp.h include file. A lightweight
+ * process is identified by an object of type PROCESS, which is defined in the
+ * include file.
+ * \par
+ * The process model supported by the LWP operations is based on a
+ * non-preemptive priority dispatching scheme. A priority is an integer in the
+ * range [0..LWP MAX PRIORITY], where 0 is the lowest priority. Once a given
+ * thread is selected and dispatched, it remains in control until it
+ * voluntarily relinquishes its claim on the CPU. Control may be relinquished
+ * by either explicit means (LWP_DispatchProcess()) or implicit means (through
+ * the use of certain other LWP operations with this side effect). In general,
+ * all LWP operations that may cause a higher-priority process to become ready
+ * for dispatching preempt the process requesting the service. When this
+ * occurs, the dispatcher mechanism takes over and automatically schedules the
+ * highest-priority runnable process. Routines in this category, where the
+ * scheduler is guaranteed to be invoked in the absence of errors, are:
+ * \li LWP_WaitProcess()
+ * \li LWP_MwaitProcess()
+ * \li LWP_SignalProcess()
+ * \li LWP_DispatchProcess()
+ * \li LWP_DestroyProcess()
+ * \par
+ * The following functions are guaranteed not to cause preemption, and so may
+ * be issued with no fear of losing control to another thread:
+ * \li LWP_InitializeProcessSupport()
+ * \li LWP_NoYieldSignal()
+ * \li LWP_CurrentProcess()
+ * \li LWP_ActiveProcess()
+ * \li LWP_StackUsed()
+ * \li LWP_NewRock()
+ * \li LWP_GetRock()
+ * \par
+ * The symbol LWP NORMAL PRIORITY, whose value is (LWP MAX PRIORITY-2),
+ * provides a reasonable default value to use for process priorities.
+ * \par
+ * The lwp debug global variable can be set to activate or deactivate debugging
+ * messages tracing the flow of control within the LWP routines. To activate
+ * debugging messages, set lwp debug to a non-zero value. To deactivate, reset
+ * it to zero. All debugging output from the LWP routines is sent to stdout.
+ * \par
+ * The LWP package checks for stack overflows at each context switch. The
+ * variable that controls the action of the package when an overflow occurs is
+ * lwp overflowAction. If it is set to LWP SOMESSAGE, then a message will be
+ * printed on stderr announcing the overflow. If lwp overflowAction is set to
+ * LWP SOABORT, the abort() LWP routine will be called. finally, if lwp
+ * overflowAction is set to LWP SOQUIET, the LWP facility will ignore the
+ * errors. By default, the LWP SOABORT setting is used.
+ * \par
+ * Here is a sketch of a simple program (using some psuedocode) demonstrating
+ * the high-level use of the LWP facility. The opening #include line brings in
+ * the exported LWP definitions. Following this, a routine is defined to wait
+ * on a "queue" object until something is deposited in it, calling the
+ * scheduler as soon as something arrives. Please note that various LWP
+ * routines are introduced here. Their definitions will appear later, in
+ * Section 2.3.1.
+ *
+ * \code
+ * #include <afs/lwp.h>
+ * static read_process(id)
+ * int *id;
+ * { /* Just relinquish control for now */
+ * LWP_DispatchProcess();
+ * for (;;)
+ * {
+ * /* Wait until there is something in the queue */
+ * while (empty(q)) LWP_WaitProcess(q);
+ * /* Process the newly-arrived queue entry */
+ * LWP_DispatchProcess();
+ * }
+ * }
+ * \endcode
+ *
+ * \par
+ * The next routine, write process(), sits in a loop, putting messages on the
+ * shared queue and signalling the reader, which is waiting for activity on the
+ * queue. Signalling a thread is accomplished via the LWP SignalProcess()
+ * library routine.
+ *
+ * \code
+ * static write_process()
+ * { ...
+ * /* Loop, writing data to the shared queue. */
+ * for (mesg = messages; *mesg != 0; mesg++)
+ * {
+ * insert(q, *mesg);
+ * LWP_SignalProcess(q);
+ * }
+ * }
+ * \endcode
+ *
+ * \par
+ * finally, here is the main routine for this demo pseudocode. It starts by
+ * calling the LWP initialization routine. Next, it creates some number of
+ * reader threads with calls to LWP CreateProcess() in addition to the single
+ * writer thread. When all threads terminate, they will signal the main routine
+ * on the done variable. Once signalled, the main routine will reap all the
+ * threads with the help of the LWP DestroyProcess() function.
+ *
+ * \code
+ * main(argc, argv)
+ * int argc;
+ * char **argv;
+ * {
+ * PROCESS *id; /* Initial thread ID */
+ * /* Set up the LWP package, create the initial thread ID. */
+ * LWP_InitializeProcessSupport(0, &id);
+ * /* Create a set of reader threads. */
+ * for (i = 0; i < nreaders; i++)
+ * LWP_CreateProcess(read_process, STACK_SIZE, 0, i, "Reader",
+ * &readers[i]);
+ *
+ * /* Create a single writer thread. */
+ * LWP_CreateProcess(write_process, STACK_SIZE, 1, 0, "Writer", &writer);
+ * /* Wait for all the above threads to terminate. */
+ * for (i = 0; i <= nreaders; i++)
+ * LWP_WaitProcess(&done);
+ *
+ * /* All threads are done. Destroy them all. */
+ * for (i = nreaders-1; i >= 0; i--)
+ * LWP_DestroyProcess(readers[i]);
+ * }
+ * \endcode
+ *
+ * \subsection sec2-2-2 Section 2.2.2: Locking
+ * \par
+ * The LWP locking facility exports a number of routines and macros that allow
+ * a C programmer using LWP threading to place read and write locks on shared
+ * data structures. This locking facility was also written with simplicity in
+ * mind.
+ * \par
+ * In order to invoke the locking mechanism, an object of type struct Lock must
+ * be associated with the object. After being initialized with a call to
+ * LockInit(), the lock object is used in invocations of various macros,
+ * including ObtainReadLock(), ObtainWriteLock(), ReleaseReadLock(),
+ * ReleaseWriteLock(), ObtainSharedLock(), ReleaseSharedLock(), and
+ * BoostSharedLock().
+ * \par
+ * Lock semantics specify that any number of readers may hold a lock in the
+ * absence of a writer. Only a single writer may acquire a lock at any given
+ * time. The lock package guarantees fairness, legislating that each reader and
+ * writer will eventually obtain a given lock. However, this fairness is only
+ * guaranteed if the priorities of the competing processes are identical. Note
+ * that ordering is not guaranteed by this package.
+ * \par
+ * Shared locks are read locks that can be "boosted" into write locks. These
+ * shared locks have an unusual locking matrix. Unboosted shared locks are
+ * compatible with read locks, yet incompatible with write locks and other
+ * shared locks. In essence, a thread holding a shared lock on an object has
+ * effectively read-locked it, and has the option to promote it to a write lock
+ * without allowing any other writer to enter the critical region during the
+ * boost operation itself.
+ * \par
+ * It is illegal for a process to request a particular lock more than once
+ * without first releasing it. Failure to obey this restriction will cause
+ * deadlock. This restriction is not enforced by the LWP code.
+ * \par
+ * Here is a simple pseudocode fragment serving as an example of the available
+ * locking operations. It defines a struct Vnode object, which contains a lock
+ * object. The get vnode() routine will look up a struct Vnode object by name,
+ * and then either read-lock or write-lock it.
+ * \par
+ * As with the high-level LWP example above, the locking routines introduced
+ * here will be fully defined later, in Section 2.3.2.
+ *
+ * \code
+ * #include <afs/lock.h>
+ *
+ * struct Vnode {
+ * ...
+ * struct Lock lock; Used to lock this vnode
+ * ... };
+ *
+ * #define READ 0
+ * #define WRITE 1
+ *
+ * struct Vnode *get_vnode(name, how) char *name;
+ * int how;
+ * {
+ * struct Vnode *v;
+ * v = lookup(name);
+ * if (how == READ)
+ * ObtainReadLock(&v->lock);
+ * else
+ * ObtainWriteLock(&v->lock);
+ * }
+ * \endcode
+ *
+ *
+ * \subsection sec2-2-3 Section 2.2.3: IOMGR
+ *
+ * \par
+ * The IOMGR facility associated with the LWP service allows threads to wait on
+ * various unix events. The exported IOMGR Select() routine allows a thread to
+ * wait on the same set of events as the unix select() call. The parameters to
+ * these two routines are identical. IOMGR Select() puts the calling LWP to
+ * sleep until no threads are active. At this point, the built-in IOMGR thread,
+ * which runs at the lowest priority, wakes up and coalesces all of the select
+ * requests together. It then performs a single select() and wakes up all
+ * threads affected by the result.
+ * \par
+ * The IOMGR Signal() routine allows an LWP to wait on the delivery of a unix
+ * signal. The IOMGR thread installs a signal handler to catch all deliveries
+ * of the unix signal. This signal handler posts information about the signal
+ * delivery to a global data structure. The next time that the IOMGR thread
+ * runs, it delivers the signal to any waiting LWP.
+ * \par
+ * Here is a pseudocode example of the use of the IOMGR facility, providing the
+ * blueprint for an implemention a thread-level socket listener.
+ *
+ * \code
+ * void rpc_SocketListener()
+ * {
+ * int ReadfdMask, WritefdMask, ExceptfdMask, rc;
+ * struct timeval *tvp;
+ * while(TRUE)
+ * { ...
+ * ExceptfdMask = ReadfdMask = (1 << rpc_RequestSocket);
+ * WritefdMask = 0;
+ *
+ * rc = IOMGR_Select(8*sizeof(int), &ReadfdMask, &WritefdMask,
+ * &ExceptfdMask, tvp);
+ *
+ * switch(rc)
+ * {
+ * case 0: /* Timeout */ continue;
+ * /* Main while loop */
+ *
+ * case -1: /* Error */
+ * SystemError("IOMGR_Select");
+ * exit(-1);
+ *
+ * case 1: /* RPC packet arrived! */ ...
+ * process packet ...
+ * break;
+ *
+ * default: Should never occur
+ * }
+ * }
+ * }
+ * \endcode
+ *
+ * \subsection sec2-2-4 Section 2.2.4: Timer
+ * \par
+ * The timer package exports a number of routines that assist in manipulating
+ * lists of objects of type struct TM Elem. These struct TM Elem timers are
+ * assigned a timeout value by the user and inserted in a package-maintained
+ * list. The time remaining to each timer's timeout is kept up to date by the
+ * package under user control. There are routines to remove a timer from its
+ * list, to return an expired timer from a list, and to return the next timer
+ * to expire.
+ * \par
+ * A timer is commonly used by inserting a field of type struct TM Elem into a
+ * structure. After setting the desired timeout value, the structure is
+ * inserted into a list by means of its timer field.
+ * \par
+ * Here is a simple pseudocode example of how the timer package may be used.
+ * After calling the package initialization function, TM Init(), the pseudocode
+ * spins in a loop. first, it updates all the timers via TM Rescan() calls.
+ * Then, it pulls out the first expired timer object with TM GetExpired() (if
+ * any), and processes it.
+ *
+ * \code
+ * static struct TM_Elem *requests;
+ * ...
+ * TM_Init(&requests); /* Initialize timer list */ ...
+ * for (;;) {
+ * TM_Rescan(requests); /* Update the timers */
+ * expired = TM_GetExpired(requests);
+ * if (expired == 0)
+ * break;
+ * . . . process expired element . . .
+ * }
+ * \endcode
+ *
+ * \subsection sec2-2-5 Section 2.2.5: Fast Time
+ *
+ * \par
+ * The fast time routines allows a caller to determine the current time of day
+ * without incurring the expense of a kernel call. It works by mapping the page
+ * of the kernel that holds the time-of-day variable and examining it directly.
+ * Currently, this package only works on Suns. The routines may be called on
+ * other architectures, but they will run more slowly.
+ * \par
+ * The initialization routine for this package is fairly expensive, since it
+ * does a lookup of a kernel symbol via nlist(). If the client application
+ * program only runs for only a short time, it may wish to call FT Init() with
+ * the notReally parameter set to TRUE in order to prevent the lookup from
+ * taking place. This is useful if you are using another package that uses the
+ * fast time facility.
+ *
+ * \subsection sec2-2-6 Section 2.2.6: Preemption
+ *
+ * \par
+ * The preemption package provides a mechanism by which control can pass
+ * between lightweight processes without the need for explicit calls to LWP
+ * DispatchProcess(). This effect is achieved by periodically interrupting the
+ * normal flow of control to check if other (higher priority) procesess are
+ * ready to run.
+ * \par
+ * The package makes use of the BSD interval timer facilities, and so will
+ * cause programs that make their own use of these facilities to malfunction.
+ * In particular, use of alarm(3) or explicit handling of SIGALRM is
+ * disallowed. Also, calls to sleep(3) may return prematurely.
+ * \par
+ * Care should be taken that routines are re-entrant where necessary. In
+ * particular, note that stdio(3) is not re-entrant in general, and hence
+ * multiple threads performing I/O on the same fiLE structure may function
+ * incorrectly.
+ * \par
+ * An example pseudocode routine illustrating the use of this preemption
+ * facility appears below.
+ *
+ * \code
+ * #include <sys/time.h>
+ * #include "preempt.h"
+ * ... struct timeval tv;
+ * LWP_InitializeProcessSupport( ... );
+ * tv.tv_sec = 10;
+ * tv.tv_usec = 0;
+ * PRE_InitPreempt(&tv);
+ * PRE_PreemptMe(); ...
+ * PRE_BeginCritical(); ...
+ * PRE_EndCritical(); ...
+ * PRE_EndPreempt();
+ * \endcode
+ *
+ * \section sec2-3 Section 2.3: Interface Specifications
+ *
+ * \subsection sec2-3-1 Section 2.3.1: LWP
+ *
+ * \par
+ * This section covers the calling interfaces to the LWP package. Please note
+ * that LWP macros (e.g., ActiveProcess) are also included here, rather than
+ * being relegated to a different section.
+ *
+ * \subsubsection sec2-3-1-1 Section 2.3.1.1: LWP_InitializeProcessSupport
+ * _ Initialize the LWP package
+ *
+ * \par
+ * int LWP_InitializeProcessSupport(IN int priority; OUT PROCESS *pid)
+ * \par Description
+ * This function initializes the LWP package. In addition, it turns the current
+ * thread of control into the initial process with the specified priority. The
+ * process ID of this initial thread is returned in the pid parameter. This
+ * routine must be called before any other routine in the LWP library. The
+ * scheduler will NOT be invoked as a result of calling
+ * LWP_InitializeProcessSupport().
+ * \par Error Codes
+ * LWP EBADPRI The given priority is invalid, either negative or too large.
+ *
+ * \subsubsection sec2-3-1-2 Section 2.3.1.2: LWP_TerminateProcessSupport
+ * _ End process support, perform cleanup
+ *
+ * \par
+ * int LWP_TerminateProcessSupport()
+ * \par Description
+ * This routine terminates the LWP threading support and cleans up after it by
+ * freeing any auxiliary storage used. This routine must be called from within
+ * the process that invoked LWP InitializeProcessSupport(). After LWP
+ * TerminateProcessSupport() has been called, it is acceptable to call LWP
+ * InitializeProcessSupport() again in order to restart LWP process support.
+ * \par Error Codes
+ * ---Always succeeds, or performs an abort().
+ *
+ * \subsubsection sec2-3-1-3 Section 2.3.1.3: LWP_CreateProcess _ Create a
+ * new thread
+ *
+ * \par
+ * int LWP_CreateProcess(IN int (*ep)(); IN int stacksize; IN int priority; IN
+ * char *parm; IN char *name; OUT PROCESS *pid)
+ * \par Description
+ * This function is used to create a new lightweight process with a given
+ * printable name. The ep argument identifies the function to be used as the
+ * body of the thread. The argument to be passed to this function is contained
+ * in parm. The new thread's stack size in bytes is specified in stacksize, and
+ * its execution priority in priority. The pid parameter is used to return the
+ * process ID of the new thread.
+ * \par
+ * If the thread is successfully created, it will be marked as runnable. The
+ * scheduler is called before the LWP CreateProcess() call completes, so the
+ * new thread may indeed begin its execution before the completion. Note that
+ * the new thread is guaranteed NOT to run before the call completes if the
+ * specified priority is lower than the caller's. On the other hand, if the new
+ * thread's priority is higher than the caller's, then it is guaranteed to run
+ * before the creation call completes.
+ * \par Error Codes
+ * LWP EBADPRI The given priority is invalid, either negative or too large.
+ * \n LWP NOMEM Could not allocate memory to satisfy the creation request.
+ *
+ * \subsubsection sec2-3-1-4 Section: 2.3.1.4: LWP_DestroyProcess _ Create
+ * a new thread
+ *
+ * \par
+ * int LWP_DestroyProcess(IN PROCESS pid)
+ * \par Description
+ * This routine destroys the thread identified by pid. It will be terminated
+ * immediately, and its internal storage will be reclaimed. A thread is allowed
+ * to destroy itself. In this case, of course, it will only get to see the
+ * return code if the operation fails. Note that a thread may also destroy
+ * itself by returning from the parent C routine.
+ * \par
+ * The scheduler is called by this operation, which may cause an arbitrary
+ * number of threads to execute before the caller regains the processor.
+ * \par Error Codes
+ * LWP EINIT The LWP package has not been initialized.
+ *
+ * \subsubsection sec2-3-1-5 Section 2.3.1.5: WaitProcess _ Wait on an
+ * event
+ *
+ * \par
+ * int LWP WaitProcess(IN char *event)
+ * \par Description
+ * This routine puts the thread making the call to sleep until another LWP
+ * calls the LWP SignalProcess() or LWP NoYieldSignal() routine with the
+ * specified event. Note that signalled events are not queued. If a signal
+ * occurs and no thread is awakened, the signal is lost. The scheduler is
+ * invoked by the LWP WaitProcess() routine.
+ * \par Error Codes
+ * LWP EINIT The LWP package has not been initialized.
+ * \n LWP EBADEVENT The given event pointer is null.
+ *
+ * \subsubsection sec2-3-1-6 Section 2.3.1.6: MwaitProcess _ Wait on a set
+ * of events
+ *
+ * \par
+ * int LWP MwaitProcess(IN int wcount; IN char *evlist[])
+ * \par Description
+ * This function allows a thread to wait for wcount signals on any of the items
+ * in the given evlist. Any number of signals of a particular event are only
+ * counted once. The evlist is a null-terminated list of events to wait for.
+ * The scheduler will be invoked.
+ * \par Error Codes
+ * LWP EINIT The LWP package has not been initialized.
+ * \n LWP EBADCOUNT An illegal number of events has been supplied.
+ *
+ * \subsubsection sec2-3-1-7 Section 2.3.1.7: SignalProcess _ Signal an
+ * event
+ *
+ * \par
+ * int LWP SignalProcess(IN char *event)
+ * \par Description
+ * This routine causes the given event to be signalled. All threads waiting for
+ * this event (exclusively) will be marked as runnable, and the scheduler will
+ * be invoked. Note that threads waiting on multiple events via LWP
+ * MwaitProcess() may not be marked as runnable. Signals are not queued.
+ * Therefore, if no thread is waiting for the signalled event, the signal will
+ * be lost.
+ * \par Error Codes
+ * LWP EINIT The LWP package has not been initialized. LWP EBADEVENT A null
+ * event pointer has been provided. LWP ENOWAIT No thread was waiting on the
+ * given event.
+ *
+ * \subsubsection sec2-3-1-8 Section 2.3.1.8: NoYieldSignal _ Signal an
+ * event without invoking scheduler
+ *
+ * \par
+ * int LWP NoYieldSignal(IN char *event)
+ * \par Description
+ * This function is identical to LWP SignalProcess() except that the scheduler
+ * will not be invoked. Thus, control will remain with the signalling process.
+ * \par Error Codes
+ * LWP EINIT The LWP package has not been initialized. LWP EBADEVENT A null
+ * event pointer has been provided. LWP ENOWAIT No thread was waiting on the
+ * given event.
+ *
+ * \subsubsection sec2-3-1-9 Section 2.3.1.9: DispatchProcess _ Yield
+ * control to the scheduler
+ *
+ * \par
+ * int LWP DispatchProcess()
+ * \par Description
+ * This routine causes the calling thread to yield voluntarily to the LWP
+ * scheduler. If no other thread of appropriate priority is marked as runnable,
+ * the caller will continue its execution.
+ * \par Error Codes
+ * LWP EINIT The LWP package has not been initialized.
+ *
+ * \subsubsection sec2-3-1-10 Section 2.3.1.10: CurrentProcess _ Get the
+ * current thread's ID
+ *
+ * \par
+ * int LWP CurrentProcess(IN PROCESS *pid)
+ * \par Description
+ * This call places the current lightweight process ID in the pid parameter.
+ * \par Error Codes
+ * LWP EINIT The LWP package has not been initialized.
+ *
+ * \subsubsection sec2-3-1-11 Section 2.3.1.11: ActiveProcess _ Get the
+ * current thread's ID (macro)
+ *
+ * \par
+ * int LWP ActiveProcess()
+ * \par Description
+ * This macro's value is the current lightweight process ID. It generates a
+ * value identical to that acquired by calling the LWP CurrentProcess()
+ * function described above if the LWP package has been initialized. If no such
+ * initialization has been done, it will return a value of zero.
+ *
+ * \subsubsection sec2-3-1-12 Section: 2.3.1.12: StackUsed _ Calculate
+ * stack usage
+ *
+ * \par
+ * int LWP StackUsed(IN PROCESS pid; OUT int *max; OUT int *used)
+ * \par Description
+ * This function returns the amount of stack space allocated to the thread
+ * whose identifier is pid, and the amount actually used so far. This is
+ * possible if the global variable lwp stackUseEnabled was TRUE when the thread
+ * was created (it is set this way by default). If so, the thread's stack area
+ * was initialized with a special pattern. The memory still stamped with this
+ * pattern can be determined, and thus the amount of stack used can be
+ * calculated. The max parameter is always set to the thread's stack allocation
+ * value, and used is set to the computed stack usage if lwp stackUseEnabled
+ * was set when the process was created, or else zero.
+ * \par Error Codes
+ * LWP NO STACK Stack usage was not enabled at thread creation time.
+ *
+ * \subsubsection sec2-3-1-13 Section 2.3.1.13: NewRock _ Establish
+ * thread-specific storage
+ *
+ * \par
+ * int LWP NewRock (IN int tag; IN char **value)
+ * \par Description
+ * This function establishes a "rock", or thread-specific information,
+ * associating it with the calling LWP. The tag is intended to be any unique
+ * integer value, and the value is a pointer to a character array containing
+ * the given data.
+ * \par
+ * Users of the LWP package must coordinate their choice of tag values. Note
+ * that a tag's value cannot be changed. Thus, to obtain a mutable data
+ * structure, another level of indirection is required. Up to MAXROCKS (4)
+ * rocks may be associated with any given thread.
+ * \par Error Codes
+ * ENOROCKS A rock with the given tag field already exists. All of the MAXROCKS
+ * are in use.
+ *
+ *
+ * \subsubsection sec2-3-1-14 Section: 2.3.1.14: GetRock _ Retrieve
+ * thread-specific storage
+ *
+ * \par
+ * int LWP GetRock(IN int tag; OUT **value)
+ * \par Description
+ * This routine recovers the thread-specific information associated with the
+ * calling process and the given tag, if any. Such a rock had to be established
+ * through a LWP NewRock() call. The rock's value is deposited into value.
+ * \par Error Codes
+ * LWP EBADROCK A rock has not been associated with the given tag for this
+ * thread.
+ *
+ * \subsection sec2-3-2 Section 2.3.2: Locking
+ *
+ * \par
+ * This section covers the calling interfaces to the locking package. Many of
+ * the user-callable routines are actually implemented as macros.
+ *
+ * \subsubsection sec2-3-2-1 Section 2.3.2.1: Lock Init _ Initialize lock
+ * structure
+ *
+ * \par
+ * void Lock Init(IN struct Lock *lock)
+ * \par Description
+ * This function must be called on the given lock object before any other
+ * operations can be performed on it.
+ * \par Error Codes
+ * ---No value is returned.
+ *
+ * \subsubsection sec2-3-2-2 Section 2.3.2.2: ObtainReadLock _ Acquire a
+ * read lock
+ *
+ * \par
+ * void ObtainReadLock(IN struct Lock *lock)
+ * \par Description
+ * This macro obtains a read lock on the specified lock object. Since this is a
+ * macro and not a function call, results are not predictable if the value of
+ * the lock parameter is a side-effect producing expression, as it will be
+ * evaluated multiple times in the course of the macro interpretation.
+ * Read locks are incompatible with write, shared, and boosted shared locks.
+ * \par Error Codes
+ * ---No value is returned.
+ *
+ * \subsubsection sec2-3-2-3 Section 2.3.2.3: ObtainWriteLock _ Acquire a
+ * write lock
+ *
+ * \par
+ * void ObtainWriteLock(IN struct Lock *lock)
+ * \par Description
+ * This macro obtains a write lock on the specified lock object. Since this is
+ * a macro and not a function call, results are not predictable if the value of
+ * the lock parameter is a side-effect producing expression, as it will be
+ * evaluated multiple times in the course of the macro interpretation.
+ * \par
+ * Write locks are incompatible with all other locks.
+ * \par Error Codes
+ * ---No value is returned.
+ *
+ * \subsubsection sec2-3-2-4 Section 2.3.2.4: ObtainSharedLock _ Acquire a
+ * shared lock
+ *
+ * \par
+ * void ObtainSharedLock(IN struct Lock *lock)
+ * \par Description
+ * This macro obtains a shared lock on the specified lock object. Since this is
+ * a macro and not a function call, results are not predictable if the value of
+ * the lock parameter is a side-effect producing expression, as it will be
+ * evaluated multiple times in the course of the macro interpretation.
+ * \par
+ * Shared locks are incompatible with write and boosted shared locks, but are
+ * compatible with read locks.
+ * \par Error Codes
+ * ---No value is returned.
+ *
+ * \subsubsection sec2-3-2-5 Section 2.3.2.5: ReleaseReadLock _ Release
+ * read lock
+ *
+ * \par
+ * void ReleaseReadLock(IN struct Lock *lock)
+ * \par Description
+ * This macro releases the specified lock. The lock must have been previously
+ * read-locked. Since this is a macro and not a function call, results are not
+ * predictable if the value of the lock parameter is a side-effect producing
+ * expression, as it will be evaluated multiple times in the course of the
+ * macro interpretation. The results are also unpredictable if the lock was not
+ * previously read-locked by the thread calling ReleaseReadLock().
+ * \par Error Codes
+ * ---No value is returned.
+ *
+ * \subsubsection sec2-3-2-6 Section 2.3.2.6: ReleaseWriteLock _ Release
+ * write lock
+ *
+ * \par
+ * void ReleaseWriteLock(IN struct Lock *lock)
+ * \par Description
+ * This macro releases the specified lock. The lock must have been previously
+ * write-locked. Since this is a macro and not a function call, results are not
+ * predictable if the value of the lock parameter is a side-effect producing
+ * expression, as it will be evaluated multiple times in the course of the
+ * macro interpretation. The results are also unpredictable if the lock was not
+ * previously write-locked by the thread calling ReleaseWriteLock().
+ * \par Error Codes
+ * ---No value is returned.
+ *
+ * \subsubsection sec2-3-2-7 Section 2.3.2.7: ReleaseSharedLock _ Release
+ * shared lock
+ *
+ * \par
+ * void ReleaseSharedLock(IN struct Lock *lock)
+ * \par Description
+ * This macro releases the specified lock. The lock must have been previously
+ * share-locked. Since this is a macro and not a function call, results are not
+ * predictalbe if the value of the lock parameter is a side-effect producing
+ * expression, as it will be evaluated multiple times in the course of the
+ * macro interpretation. The results are also unpredictable if the lock was not
+ * previously share-locked by the thread calling ReleaseSharedLock().
+ * \par Error Codes
+ * ---No value is returned.
+ *
+ * \subsubsection sec2-3-2-8 Section 2.3.2.8: CheckLock _ Determine state
+ * of a lock
+ *
+ * \par
+ * void CheckLock(IN struct Lock *lock)
+ * \par Description
+ * This macro produces an integer that specifies the status of the indicated
+ * lock. The value will be -1 if the lock is write-locked, 0 if unlocked, or
+ * otherwise a positive integer that indicates the number of readers (threads
+ * holding read locks). Since this is a macro and not a function call, results
+ * are not predictable if the value of the lock parameter is a side-effect
+ * producing expression, as it will be evaluated multiple times in the course
+ * of the macro interpretation.
+ * \par Error Codes
+ * ---No value is returned.
+ *
+ * \subsubsection sec2-3-2-9 Section 2.3.2.9: BoostLock _ Boost a shared
+ * lock
+ *
+ * \par
+ * void BoostLock(IN struct Lock *lock)
+ * \par Description
+ * This macro promotes ("boosts") a shared lock into a write lock. Such a boost
+ * operation guarantees that no other writer can get into the critical section
+ * in the process. Since this is a macro and not a function call, results are
+ * not predictable if the value of the lock parameter is a side-effect
+ * producing expression, as it will be evaluated multiple times in the course
+ * of the macro interpretation.
+ * \par Error Codes
+ * ---No value is returned.
+ *
+ * \subsubsection sec2-3-2-10 Section 2.3.2.10: UnboostLock _ Unboost a
+ * shared lock
+ *
+ * \par
+ * void UnboostLock(IN struct Lock *lock)
+ * \par Description
+ * This macro demotes a boosted shared lock back down into a regular shared
+ * lock. Such an unboost operation guarantees that no other writer can get into
+ * the critical section in the process. Since this is a macro and not a
+ * function call, results are not predictable if the value of the lock
+ * parameter is a side-effect producing expression, as it will be evaluated
+ * multiple times in the course of the macro interpretation.
+ * \par Error Codes
+ * ---No value is returned.
+ *
+ * \subsection sec2-3-3 Section 2.3.3: IOMGR
+ *
+ * \par
+ * This section covers the calling interfaces to the I/O management package.
+ *
+ * \subsubsection sec2-3-3-1 Section: 2.3.3.1: IOMGR Initialize _
+ * Initialize the package
+ *
+ * \par
+ * int IOMGR Initialize()
+ * \par Description
+ * This function initializes the IOMGR package. Its main task is to create the
+ * IOMGR thread itself, which runs at the lowest possible priority (0). The
+ * remainder of the lightweight processes must be running at priority 1 or
+ * greater (up to a maximum of LWP MAX PRIORITY (4)) for the IOMGR package to
+ * function correctly.
+ * \par Error Codes
+ * -1 The LWP and/or timer package haven't been initialized.
+ * \n <misc> Any errors that may be returned by the LWP CreateProcess()
+ * routine.
+ *
+ * \subsubsection sec2-3-3-2 Section 2.3.3.2: IOMGR finalize _ Clean up
+ * the IOMGR facility
+ *
+ * \par
+ * int IOMGR finalize()
+ * \par Description
+ * This routine cleans up after the IOMGR package when it is no longer needed.
+ * It releases all storage and destroys the IOMGR thread itself.
+ * \par Error Codes
+ * <misc> Any errors that may be returned by the LWP DestroyProcess() routine.
+ *
+ * \subsubsection sec2-3-3-3 Section 2.3.3.3: IOMGR Select _ Perform a
+ * thread-level select()
+ *
+ * \par
+ * int IOMGR Select (IN int numfds; IN int *rfds; IN int *wfds; IN int *xfds;
+ * IN truct timeval *timeout)
+ * \par Description
+ * This routine performs an LWP version of unix select() operation. The
+ * parameters have the same meanings as with the unix call. However, the return
+ * values will be simplified (see below). If this is a polling select (i.e.,
+ * the value of timeout is null), it is done and the IOMGR Select() function
+ * returns to the user with the results. Otherwise, the calling thread is put
+ * to sleep. If at some point the IOMGR thread is the only runnable process, it
+ * will awaken and collect all select requests. The IOMGR will then perform a
+ * single select and awaken the appropriate processes. This will force a return
+ * from the affected IOMGR Select() calls.
+ * \par Error Codes
+ * -1 An error occurred.
+ * \n 0 A timeout occurred.
+ * \n 1 Some number of file descriptors are ready.
+ *
+ * \subsubsection sec2-3-3-4 Section 2.3.3.4: IOMGR Signal _ Associate
+ * unix and LWP signals
+ *
+ * \par
+ * int IOMGR Signal(IN int signo; IN char *event)
+ * \par Description
+ * This function associates an LWP signal with a unix signal. After this call,
+ * when the given unix signal signo is delivered to the (heavyweight unix)
+ * process, the IOMGR thread will deliver an LWP signal to the event via LWP
+ * NoYieldSignal(). This wakes up any lightweight processes waiting on the
+ * event. Multiple deliveries of the signal may be coalesced into one LWP
+ * wakeup. The call to LWP NoYieldSignal() will happen synchronously. It is
+ * safe for an LWP to check for some condition and then go to sleep waiting for
+ * a unix signal without having to worry about delivery of the signal happening
+ * between the check and the call to LWP WaitProcess().
+ * \par Error Codes
+ * LWP EBADSIG The signo value is out of range.
+ * \n LWP EBADEVENT The event pointer is null.
+ *
+ * \subsubsection sec2-3-3-5 Section 2.3.3.5: IOMGR CancelSignal _ Cancel
+ * unix and LWP signal association
+ *
+ * \par
+ * int IOMGR CancelSignal(IN int signo)
+ * \par Description
+ * This routine cancels the association between a unix signal and an LWP event.
+ * After calling this function, the unix signal signo will be handled however
+ * it was handled before the corresponding call to IOMGR Signal().
+ * \par Error Codes
+ * LWP EBADSIG The signo value is out of range.
+ *
+ * \subsubsection sec2-3-3-6 Section 2.3.3.6: IOMGR Sleep _ Sleep for a
+ * given period
+ *
+ * \par
+ * void IOMGR Sleep(IN unsigned seconds)
+ * \par Description
+ * This function calls IOMGR Select() with zero file descriptors and a timeout
+ * structure set up to cause the thread to sleep for the given number of
+ * seconds.
+ * \par Error Codes
+ * ---No value is returned.
+ *
+ * \subsection sec2-3-4 Section 2.3.4: Timer
+ *
+ * \par
+ * This section covers the calling interface to the timer package associated
+ * with the LWP facility.
+ *
+ * \subsubsection sec2-3-4-1 Section 2.3.4.1: TM Init _ Initialize a timer
+ * list
+ *
+ * \par
+ * int TM Init(IN struct TM Elem **list)
+ * \par Description
+ * This function causes the specified timer list to be initialized. TM Init()
+ * must be called before any other timer operations are applied to the list.
+ * \par Error Codes
+ * -1 A null timer list could not be produced.
+ *
+ * \subsubsection sec2-3-4-2 Section 2.3.4.2: TM final _ Clean up a timer
+ * list
+ *
+ * \par
+ * int TM final(IN struct TM Elem **list)
+ * \par Description
+ * This routine is called when the given empty timer list is no longer needed.
+ * All storage associated with the list is released.
+ * \par Error Codes
+ * -1 The list parameter is invalid.
+ *
+ * \subsubsection sec2-3-4-3 Section 2.3.4.3: TM Insert _ Insert an object
+ * into a timer list
+ *
+ * \par
+ * void TM Insert(IN struct TM Elem **list; IN struct TM Elem *elem)
+ * \par Description
+ * This routine enters an new element, elem, into the list denoted by list.
+ * Before the new element is queued, its TimeLeft field (the amount of time
+ * before the object comes due) is set to the value stored in its TotalTime
+ * field. In order to keep TimeLeft fields current, the TM Rescan() function
+ * may be used.
+ * \par Error Codes
+ * ---No return value is generated.
+ *
+ * \subsubsection sec2-3-4-4 Section 2.3.4.4: TM Rescan _ Update all
+ * timers in the list
+ *
+ * \par
+ * int TM Rescan(IN struct TM Elem *list)
+ * \par Description
+ * This function updates the TimeLeft fields of all timers on the given list.
+ * This is done by checking the time-of-day clock. Note: this is the only
+ * routine other than TM Init() that updates the TimeLeft field in the elements
+ * on the list.
+ * \par
+ * Instead of returning a value indicating success or failure, TM Rescan()
+ * returns the number of entries that were discovered to have timed out.
+ * \par Error Codes
+ * ---Instead of error codes, the number of entries that were discovered to
+ * have timed out is returned.
+ *
+ * \subsubsection sec2-3-4-5 Section 2.3.4.5: TM GetExpired _ Returns an
+ * expired timer
+ *
+ * \par
+ * struct TM Elem *TM GetExpired(IN struct TM Elem *list)
+ * \par Description
+ * This routine searches the specified timer list and returns a pointer to an
+ * expired timer element from that list. An expired timer is one whose TimeLeft
+ * field is less than or equal to zero. If there are no expired timers, a null
+ * element pointer is returned.
+ * \par Error Codes
+ * ---Instead of error codes, an expired timer pointer is returned, or a null
+ * timer pointer if there are no expired timer objects.
+ *
+ * \subsubsection sec2-3-4-6 Section 2.3.4.6: TM GetEarliest _ Returns
+ * earliest unexpired timer
+ *
+ * \par
+ * struct TM Elem *TM GetEarliest(IN struct TM Elem *list)
+ * \par Description
+ * This function returns a pointer to the timer element that will be next to
+ * expire on the given list. This is defined to be the timer element with the
+ * smallest (positive) TimeLeft field. If there are no timers on the list, or
+ * if they are all expired, this function will return a null pointer.
+ * \par Error Codes
+ * ---Instead of error codes, a pointer to the next timer element to expireis
+ * returned, or a null timer object pointer if they are all expired.
+ *
+ * \subsubsection sec2-3-4-7 Section 2.3.4.7: TM eql _ Test for equality
+ * of two timestamps
+ *
+ * \par
+ * bool TM eql(IN struct timemval *t1; IN struct timemval *t2)
+ * \par Description
+ * This function compares the given timestamps, t1 and t2, for equality. Note
+ * that the function return value, bool, has been set via typedef to be
+ * equivalent to unsigned char.
+ * \par Error Codes
+ * 0 If the two timestamps differ.
+ * \n 1 If the two timestamps are identical.
+ *
+ * \subsection sec2-3-5 Section 2.3.5: Fast Time
+ * \par
+ * This section covers the calling interface to the fast time package
+ * associated with the LWP facility.
+ *
+ * \subsubsection sec2-3-5-1 Section 2.3.5.1: FT Init _ Initialize the
+ * fast time package
+ *
+ * \par
+ * int FT Init(IN int printErrors; IN int notReally)
+ * \par Description
+ * This routine initializes the fast time package, mapping in the kernel page
+ * containing the time-of-day variable. The printErrors argument, if non-zero,
+ * will cause any errors in initalization to be printed to stderr. The
+ * notReally parameter specifies whether initialization is really to be done.
+ * Other calls in this package will do auto-initialization, and hence the
+ * option is offered here.
+ * \par Error Codes
+ * -1 Indicates that future calls to FT GetTimeOfDay() will still work, but
+ * will not be able to access the information directly, having to make a
+ * kernel call every time.
+ *
+ * \subsubsection sec2-3-5-2 Section 2.3.5.2: FT GetTimeOfDay _ Initialize
+ * the fast time package
+ *
+ * \par
+ * int FT GetTimeOfDay(IN struct timeval *tv; IN struct timezone *tz)
+ * \par Description
+ * This routine is meant to mimic the parameters and behavior of the unix
+ * gettimeofday() function. However, as implemented, it simply calls
+ * gettimeofday() and then does some bound-checking to make sure the value is
+ * reasonable.
+ * \par Error Codes
+ * <misc> Whatever value was returned by gettimeofday() internally.
+ *
+ * \subsection sec2-3-6 Section 2.3.6: Preemption
+ * \par
+ * This section covers the calling interface to the preemption package
+ * associated with the LWP facility.
+ *
+ * \subsubsection sec2-3-6-1 Section 2.3.6.1: PRE InitPreempt _ Initialize
+ * the preemption package
+ *
+ * \par
+ * int PRE InitPreempt(IN struct timeval *slice)
+ * \par Description
+ * This function must be called to initialize the preemption package. It must
+ * appear sometime after the call to LWP InitializeProcessSupport() and
+ * sometime before the first call to any other preemption routine. The slice
+ * argument specifies the time slice size to use. If the slice pointer is set
+ * to null in the call, then the default time slice, DEFAULTSLICE (10
+ * milliseconds), will be used. This routine uses the unix interval timer and
+ * handling of the unix alarm signal, SIGALRM, to implement this timeslicing.
+ * \par Error Codes
+ * LWP EINIT The LWP package hasn't been initialized.
+ * \n LWP ESYSTEM Operations on the signal vector or the interval timer have
+ * failed.
+ *
+ * \subsubsection sec2-3-6-2 Section 2.3.6.2: PRE EndPreempt _ finalize
+ * the preemption package
+ *
+ * \par
+ * int PRE EndPreempt()
+ * \par Description
+ * This routine finalizes use of the preemption package. No further preemptions
+ * will be made. Note that it is not necessary to make this call before exit.
+ * PRE EndPreempt() is provided only for those applications that wish to
+ * continue after turning off preemption.
+ * \par Error Codes
+ * LWP EINIT The LWP package hasn't been initialized.
+ * \n LWP ESYSTEM Operations on the signal vector or the interval timer have
+ * failed.
+ *
+ * \subsubsection sec2-3-6-3 Section 2.3.6.3: PRE PreemptMe _ Mark thread
+ * as preemptible
+ *
+ * \par
+ * int PRE PreemptMe()
+ * \par Description
+ * This macro is used to signify the current thread as a candidate for
+ * preemption. The LWP InitializeProcessSupport() routine must have been called
+ * before PRE PreemptMe().
+ * \par Error Codes
+ * ---No return code is generated.
+ *
+ * \subsubsection sec2-3-6-4 Section 2.3.6.4: PRE BeginCritical _ Enter
+ * thread critical section
+ *
+ * \par
+ * int PRE BeginCritical()
+ * \par Description
+ * This macro places the current thread in a critical section. Upon return, and
+ * for as long as the thread is in the critical section, involuntary
+ * preemptions of this LWP will no longer occur.
+ * \par Error Codes
+ * ---No return code is generated.
+ *
+ * \subsubsection sec2-3-6-5 Section 2.3.6.5: PRE EndCritical _ Exit
+ * thread critical section
+ *
+ * \par
+ * int PRE EndCritical()
+ * \par Description
+ * This macro causes the executing thread to leave a critical section
+ * previously entered via PRE BeginCritical(). If involuntary preemptions were
+ * possible before the matching PRE BeginCritical(), they are once again
+ * possible.
+ * \par Error Codes
+ * ---No return code is generated.
+ *
+ * \page chap3 Chapter 3 -- Rxkad
+ *
+ *
+ * \section sec3-1 Section 3.1: Introduction
+ *
+ * \par
+ * The rxkad security module is offered as one of the built-in Rx
+ * authentication models. It is based on the Kerberos system developed by MIT's
+ * Project Athena. Readers wishing detailed information regarding Kerberos
+ * design and implementation are directed to [2]. This chapter is devoted to
+ * defining how Kerberos authentication services are made available as Rx
+ * components, and assumes the reader has some familiarity with Kerberos.
+ * Included are descriptions of how client-side and server-side Rx security
+ * objects (struct rx securityClass; see Section 5.3.1.1) implementing this
+ * protocol may be generated by an Rx application. Also, a description appears
+ * of the set of routines available in the associated struct rx securityOps
+ * structures, as covered in Section 5.3.1.2. It is strongly recommended that
+ * the reader become familiar with this section on struct rx securityOps before
+ * reading on.
+ *
+ * \section sec3-2 Section 3.2: Definitions
+ *
+ * \par
+ * An important set of definitions related to the rxkad security package is
+ * provided by the rxkad.h include file. Determined here are various values for
+ * ticket lifetimes, along with structures for encryption keys and Kerberos
+ * principals. Declarations for the two routines required to generate the
+ * different rxkad security objects also appear here. The two functions are
+ * named rxkad NewServerSecurityObject() and rxkad NewClientSecurityObject().
+ * In addition, type field values, encryption levels, security index
+ * operations, and statistics structures may be found in this file.
+ * \section sec3-3 Section 3.3: Exported Objects
+ * \par
+ * To be usable as an Rx security module, the rxkad facility exports routines
+ * to create server-side and client-side security objects. The server
+ * authentication object is incorporated into the server code when calling rx
+ * NewService(). The client authentication object is incorporated into the
+ * client code every time a connection is established via rx NewConnection().
+ * Also, in order to implement these security objects, the rxkad module must
+ * provide definitions for some subset of the generic security operations as
+ * defined in the appropriate struct rx securityOps variable.
+ *
+ * \subsection sec3-3-1 Section 3.3.1: Server-Side Mechanisms
+ *
+ * \subsubsection sec3-3-1-1 Section 3.3.1.1: Security Operations
+ *
+ * \par
+ * The server side of the rxkad module fills in all but two of the possible
+ * routines associated with an Rx security object, as described in Section
+ * 5.3.1.2.
+ *
+ * \code
+ * static struct rx_securityOps rxkad_server_ops = {
+ * rxkad_Close,
+ * rxkad_NewConnection,
+ * rxkad_PreparePacket, /* Once per packet creation */
+ * 0, /* Send packet (once per retrans) */
+ * rxkad_CheckAuthentication,
+ * rxkad_CreateChallenge,
+ * rxkad_GetChallenge,
+ * 0,
+ * rxkad_CheckResponse, /* Check data packet */
+ * rxkad_DestroyConnection,
+ * rxkad_GetStats,
+ * };
+ * \endcode
+ *
+ * \par
+ * The rxkad service does not need to take any special action each time a
+ * packet belonging to a call in an rxkad Rx connection is physically
+ * transmitted. Thus, a routine is not supplied for the op SendPacket()
+ * function slot. Similarly, no preparatory work needs to be done previous to
+ * the reception of a response packet from a security challenge, so the op
+ * GetResponse() function slot is also empty.
+ *
+ * \subsubsection sec3-3-1-2 Section 3.3.1.2: Security Object
+ *
+ * \par
+ * The exported routine used to generate an rxkad-specific server-side security
+ * class object is named rxdad NewServerSecurityObject(). It is declared with
+ * four parameters, as follows:
+ *
+ * \code
+ * struct rx_securityClass *
+ * rxkad_NewServerSecurityObject(a_level, a_getKeyRockP, a_getKeyP, a_userOKP)
+ * rxkad_level a_level; /* Minimum level */
+ * char *a_getKeyRockP; /* Rock for get_key implementor */
+ * int (*a_getKeyP)(); /* Passed kvno & addr(key) to fill */
+ * int (*a_userOKP)(); /* Passed name, inst, cell => bool */
+ * \endcode
+ *
+ * \par
+ * The first argument specifies the desired level of encryption, and may take
+ * on the following values (as defined in rxkad.h):
+ * \li rxkad clear: Specifies that packets are to be sent entirely in the
+ * clear, without any encryption whatsoever.
+ * \li rxkad auth: Specifies that packet sequence numbers are to be encrypted.
+ * \li rxkad crypt: Specifies that the entire data packet is to be encrypted.
+ *
+ * \par
+ * The second and third parameters represent, respectively, a pointer to a
+ * private data area, sometimes called a "rock", and a procedure reference that
+ * is called with the key version number accompanying the Kerberos ticket and
+ * returns a pointer to the server's decryption key. The fourth argument, if
+ * not null, is a pointer to a function that will be called for every new
+ * connection with the client's name, instance, and cell. This routine should
+ * return zero if the user is not acceptable to the server.
+ *
+ * \subsection sec3-3-2 Section 3.3.2: Client-Side Mechanisms
+ *
+ * \subsubsection sec3-3-2-1 Section 3.3.2.1: Security Operations
+ *
+ * \par
+ * The client side of the rxkad module fills in relatively few of the routines
+ * associated with an Rx security object, as demonstrated below. The general Rx
+ * security object, of which this is an instance, is described in detail in
+ * Section 5.3.1.2.
+ *
+ * \code
+ * static struct rx_securityOps rxkad_client_ops = {
+ * rxkad_Close,
+ * rxkad_NewConnection, /* Every new connection */
+ * rxkad_PreparePacket, /* Once per packet creation */
+ * 0, /* Send packet (once per retrans) */
+ * 0,
+ * 0,
+ * 0,
+ * rxkad_GetResponse, /* Respond to challenge packet */
+ * 0,
+ * rxkad_CheckPacket, /* Check data packet */
+ * rxkad_DestroyConnection,
+ * rxkad_GetStats,
+ * 0,
+ * 0,
+ * 0,
+ * };
+ * \endcode
+ *
+ * \par
+ * As expected, routines are defined for use when someone destroys a security
+ * object (rxkad Close()) and when an Rx connection using the rxkad model
+ * creates a new connection (rxkad NewConnection()) or deletes an existing one
+ * (rxkad DestroyConnection()). Security-specific operations must also be
+ * performed in behalf of rxkad when packets are created (rxkad
+ * PreparePacket()) and received (rxkad CheckPacket()). finally, the client
+ * side of an rxkad security object must also be capable of constructing
+ * responses to security challenges from the server (rxkad GetResponse()) and
+ * be willing to reveal statistics on its own operation (rxkad GetStats()).
+ *
+ * \subsubsection sec3-3-2-2 Section 3.3.2.2: Security Object
+ *
+ * \par
+ * The exported routine used to generate an rxkad-specific client-side security
+ * class object is named rxkad NewClientSecurityObject(). It is declared with
+ * five parameters, specified below:
+ *
+ * \code
+ * struct rx_securityClass * rxkad_NewClientSecurityObject(
+ * a_level,
+ * a_sessionKeyP,
+ * a_kvno,
+ * a_ticketLen,
+ * a_ticketP
+ * )
+ * rxkad_level a_level;
+ * struct ktc_encryptionKey *a_sessionKeyP;
+ * long a_kvno;
+ * int a_ticketLen;
+ * char *a_ticketP;
+ * \endcode
+ *
+ * \par
+ * The first parameter, a level, specifies the level of encryption desired for
+ * this security object, with legal choices being identical to those defined
+ * for the server-side security object described in Section 3.3.1.2. The second
+ * parameter, a sessionKeyP, provides the session key to use. The ktc
+ * encryptionKey structure is defined in the rxkad.h include file, and consists
+ * of an array of 8 characters. The third parameter, a kvno, provides the key
+ * version number associated with a sessionKeyP. The fourth argument, a
+ * ticketLen, communicates the length in bytes of the data stored in the fifth
+ * parameter, a ticketP, which points to the Kerberos ticket to use for the
+ * principal for which the security object will operate.
+ *
+ * \page chap4 Chapter 4 -- Rx Support Packages
+ *
+ * \section sec4-1 Section 4.1: Introduction
+ * \par
+ * This chapter documents three packages defined directly in support of the Rx
+ * facility.
+ * \li rx queue: Doubly-linked queue package.
+ * \li rx clock: Clock package, using the 4.3BSD interval timer.
+ * \li rx event: Future events package.
+ * \par
+ * References to constants, structures, and functions defined by these support
+ * packages will appear in the following API chapter.
+ *
+ * \section sec4-2 Section 4.2: The rx queue Package
+ *
+ * \par
+ * This package provides a doubly-linked queue structure, along with a full
+ * suite of related operations. The main concern behind the coding of this
+ * facility was efficiency. All functions are implemented as macros, and it is
+ * suggested that only simple expressions be used for all parameters.
+ * \par
+ * The rx queue facility is defined by the rx queue.h include file. Some macros
+ * visible in this file are intended for rx queue internal use only. An
+ * understanding of these "hidden" macros is important, so they will also be
+ * described by this document.
+ *
+ * \subsection sec4-2-1 Section 4.2.1: struct queue
+ *
+ * \par
+ * The queue structure provides the linkage information required to maintain a
+ * queue of objects. The queue structure is prepended to any user-defined data
+ * type which is to be organized in this fashion.
+ * \n \b fields
+ * \li struct queue *prev - Pointer to the previous queue header.
+ * \li struct queue *next - Pointer to the next queue header.
+ * \par
+ * Note that a null Rx queue consists of a single struct queue object whose
+ * next and previous pointers refer to itself.
+ *
+ * \subsection sec4-2-2 Section 4.2.2: Internal Operations
+ *
+ * \par
+ * This section describes the internal operations defined for Rx queues. They
+ * will be referenced by the external operations documented in Section 4.2.3.
+ *
+ * \subsection sec4-2-2-1 Section 4.2.2.1: Q(): Coerce type to a queue
+ * element
+ *
+ * \par
+ * \#define _Q(x) ((struct queue *)(x))
+ * \par
+ * This operation coerces the user structure named by x to a queue element. Any
+ * user structure using the rx queue package must have a struct queue as its
+ * first field.
+ *
+ * \subsubsection sec4-2-2-2 Section 4.2.2.2: QA(): Add a queue element
+ * before/after another element
+ *
+ * \par
+ * \#define _QA(q,i,a,b) (((i->a=q->a)->b=i)->b=q, q->a=i)
+ * \par
+ * This operation adds the queue element referenced by i either before or after
+ * a queue element represented by q. If the (a, b) argument pair corresponds to
+ * an element's (next, prev) fields, the new element at i will be linked after
+ * q. If the (a, b) argument pair corresponds to an element's (prev, next)
+ * fields, the new element at i will be linked before q.
+ *
+ * \subsubsection sec4-2-2-3 QR(): Remove a queue element
+ *
+ * \par
+ * \#define _QR(i) ((_Q(i)->prev->next=_Q(i)->next)->prev=_Q(i)->prev)
+ * \par
+ * This operation removes the queue element referenced by i from its queue. The
+ * prev and next fields within queue element i itself is not updated to reflect
+ * the fact that it is no longer part of the queue.
+ *
+ * \subsubsection sec4-2-2-4 QS(): Splice two queues together
+ *
+ * \par
+ * \#define _QS(q1,q2,a,b) if (queue_IsEmpty(q2)); else
+ * ((((q2->a->b=q1)->a->b=q2->b)->a=q1->a, q1->a=q2->a), queue_Init(q2))
+ * \par
+ * This operation takes the queues identified by q1 and q2 and splices them
+ * together into a single queue. The order in which the two queues are appended
+ * is determined by the a and b arguments. If the (a, b) argument pair
+ * corresponds to q1's (next, prev) fields, then q2 is appended to q1. If the
+ * (a, b) argument pair corresponds to q1's (prev, next) fields, then q is
+ * prepended to q2.
+ * \par
+ * This internal QS() routine uses two exported queue operations, namely queue
+ * Init() and queue IsEmpty(), defined in Sections 4.2.3.1 and 4.2.3.16
+ * respectively below.
+ *
+ * \subsection sec4-2-3 Section 4.2.3: External Operations
+ *
+ * \subsubsection sec4-2-3-1 Section 4.2.3.1: queue Init(): Initialize a
+ * queue header
+ *
+ * \par
+ * \#define queue_Init(q) (_Q(q))->prev = (_Q(q))->next = (_Q(q))
+ * \par
+ * The queue header referred to by the q argument is initialized so that it
+ * describes a null (empty) queue. A queue head is simply a queue element.
+ *
+ * \subsubsection sec4-2-3-2 Section 4.2.3.2: queue Prepend(): Put element
+ * at the head of a queue
+ *
+ * \par
+ * \#define queue_Prepend(q,i) _QA(_Q(q),_Q(i),next,prev)
+ * \par
+ * Place queue element i at the head of the queue denoted by q. The new queue
+ * element, i, should not currently be on any queue.
+ *
+ * \subsubsection sec4-2-3-3 Section 4.2.3.3: queue Append(): Put an
+ * element a the tail of a queue
+ *
+ * \par
+ * \#define queue_Append(q,i) _QA(_Q(q),_Q(i),prev,next)
+ * \par
+ * Place queue element i at the tail of the queue denoted by q. The new queue
+ * element, i, should not currently be on any queue.
+ *
+ * \subsection sec4-2-3-4 Section 4.2.3.4: queue InsertBefore(): Insert a
+ * queue element before another element
+ *
+ * \par
+ * \#define queue_InsertBefore(i1,i2) _QA(_Q(i1),_Q(i2),prev,next)
+ * \par
+ * Insert queue element i2 before element i1 in i1's queue. The new queue
+ * element, i2, should not currently be on any queue.
+ *
+ * \subsubsection sec4-2-3-5 Section 4.2.3.5: queue InsertAfter(): Insert
+ * a queue element after another element
+ *
+ * \par
+ * \#define queue_InsertAfter(i1,i2) _QA(_Q(i1),_Q(i2),next,prev)
+ * \par
+ * Insert queue element i2 after element i1 in i1's queue. The new queue
+ * element, i2, should not currently be on any queue.
+ *
+ * \subsubsection sec4-2-3-6 Section: 4.2.3.6: queue SplicePrepend():
+ * Splice one queue before another
+ *
+ * \par
+ * \#define queue_SplicePrepend(q1,q2) _QS(_Q(q1),_Q(q2),next,prev)
+ * \par
+ * Splice the members of the queue located at q2 to the beginning of the queue
+ * located at q1, reinitializing queue q2.
+ *
+ * \subsubsection sec4-2-3-7 Section 4.2.3.7: queue SpliceAppend(): Splice
+ * one queue after another
+ *
+ * \par
+ * \#define queue_SpliceAppend(q1,q2) _QS(_Q(q1),_Q(q2),prev,next)
+ * \par
+ * Splice the members of the queue located at q2 to the end of the queue
+ * located at q1, reinitializing queue q2. Note that the implementation of
+ * queue SpliceAppend() is identical to that of queue SplicePrepend() except
+ * for the order of the next and prev arguments to the internal queue splicer,
+ * QS().
+ *
+ * \subsubsection sec4-2-3-8 Section 4.2.3.8: queue Replace(): Replace the
+ * contents of a queue with that of another
+ *
+ * \par
+ * \#define queue_Replace(q1,q2) (*_Q(q1) = *_Q(q2),
+ * \n _Q(q1)->next->prev = _Q(q1)->prev->next = _Q(q1),
+ * \n queue_Init(q2))
+ * \par
+ * Replace the contents of the queue located at q1 with the contents of the
+ * queue located at q2. The prev and next fields from q2 are copied into the
+ * queue object referenced by q1, and the appropriate element pointers are
+ * reassigned. After the replacement has occurred, the queue header at q2 is
+ * reinitialized.
+ *
+ * \subsubsection sec4-2-3-9 Section 4.2.3.9: queue Remove(): Remove an
+ * element from its queue
+ *
+ * \par
+ * \#define queue_Remove(i) (_QR(i), _Q(i)->next = 0)
+ * \par
+ * This function removes the queue element located at i from its queue. The
+ * next field for the removed entry is zeroed. Note that multiple removals of
+ * the same queue item are not supported.
+ *
+ * \subsubsection sec4-2-3-10 Section 4.2.3.10: queue MoveAppend(): Move
+ * an element from its queue to the end of another queue
+ *
+ * \par
+ * \#define queue_MoveAppend(q,i) (_QR(i), queue_Append(q,i))
+ * \par
+ * This macro removes the queue element located at i from its current queue.
+ * Once removed, the element at i is appended to the end of the queue located
+ * at q.
+ *
+ * \subsubsection sec4-2-3-11 Section 4.2.3.11: queue MovePrepend(): Move
+ * an element from its queue to the head of another queue
+ *
+ * \par
+ * \#define queue_MovePrepend(q,i) (_QR(i), queue_Prepend(q,i))
+ * \par
+ * This macro removes the queue element located at i from its current queue.
+ * Once removed, the element at i is inserted at the head fo the queue located
+ * at q.
+ *
+ * \subsubsection sec4-2-3-12 Section 4.2.3.12: queue first(): Return the
+ * first element of a queue, coerced to a particular type
+ *
+ * \par
+ * \#define queue_first(q,s) ((struct s *)_Q(q)->next)
+ * \par
+ * Return a pointer to the first element of the queue located at q. The
+ * returned pointer value is coerced to conform to the given s structure. Note
+ * that a properly coerced pointer to the queue head is returned if q is empty.
+ *
+ * \subsubsection sec4-2-3-13 Section 4.2.3.13: queue Last(): Return the
+ * last element of a queue, coerced to a particular type
+ *
+ * \par
+ * \#define queue_Last(q,s) ((struct s *)_Q(q)->prev)
+ * \par
+ * Return a pointer to the last element of the queue located at q. The returned
+ * pointer value is coerced to conform to the given s structure. Note that a
+ * properly coerced pointer to the queue head is returned if q is empty.
+ *
+ * \subsubsection sec4-2-3-14 Section 4.2.3.14: queue Next(): Return the
+ * next element of a queue, coerced to a particular type
+ *
+ * \par
+ * \#define queue_Next(i,s) ((struct s *)_Q(i)->next)
+ * \par
+ * Return a pointer to the queue element occuring after the element located at
+ * i. The returned pointer value is coerced to conform to the given s
+ * structure. Note that a properly coerced pointer to the queue head is
+ * returned if item i is the last in its queue.
+ *
+ * \subsubsection sec4-2-3-15 Section 4.2.3.15: queue Prev(): Return the
+ * next element of a queue, coerced to a particular type
+ *
+ * \par
+ * \#define queue_Prev(i,s) ((struct s *)_Q(i)->prev)
+ * \par
+ * Return a pointer to the queue element occuring before the element located at
+ * i. The returned pointer value is coerced to conform to the given s
+ * structure. Note that a properly coerced pointer to the queue head is
+ * returned if item i is the first in its queue.
+ *
+ * \subsubsection sec4-2-3-16 Section 4.2.3.16: queue IsEmpty(): Is the
+ * given queue empty?
+ *
+ * \par
+ * \#define queue_IsEmpty(q) (_Q(q)->next == _Q(q))
+ * \par
+ * Return a non-zero value if the queue located at q does not have any elements
+ * in it. In this case, the queue consists solely of the queue header at q
+ * whose next and prev fields reference itself.
+ *
+ * \subsubsection sec4-2-3-17 Section 4.2.3.17: queue IsNotEmpty(): Is the
+ * given queue not empty?
+ *
+ * \par
+ * \#define queue_IsNotEmpty(q) (_Q(q)->next != _Q(q))
+ * \par
+ * Return a non-zero value if the queue located at q has at least one element
+ * in it other than the queue header itself.
+ *
+ * \subsubsection sec4-2-3-18 Section 4.2.3.18: queue IsOnQueue(): Is an
+ * element currently queued?
+ *
+ * \par
+ * \#define queue_IsOnQueue(i) (_Q(i)->next != 0)
+ * \par
+ * This macro returns a non-zero value if the queue item located at i is
+ * currently a member of a queue. This is determined by examining its next
+ * field. If it is non-null, the element is considered to be queued. Note that
+ * any element operated on by queue Remove() (Section 4.2.3.9) will have had
+ * its next field zeroed. Hence, it would cause a non-zero return from this
+ * call.
+ *
+ * \subsubsection sec4-2-3-19 Section 4.2.3.19: queue Isfirst(): Is an
+ * element the first on a queue?
+ *
+ * \par
+ * \#define queue_Isfirst(q,i) (_Q(q)->first == _Q(i))
+ * \par
+ * This macro returns a non-zero value if the queue item located at i is the
+ * first element in the queue denoted by q.
+ *
+ * \subsubsection sec4-2-3-20 Section 4.2.3.20: queue IsLast(): Is an
+ * element the last on a queue?
+ *
+ * \par
+ * \#define queue_IsLast(q,i) (_Q(q)->prev == _Q(i))
+ * \par
+ * This macro returns a non-zero value if the queue item located at i is the
+ * last element in the queue denoted by q.
+ *
+ * \subsubsection sec4-2-3-21 Section 4.2.3.21: queue IsEnd(): Is an
+ * element the end of a queue?
+ *
+ * \par
+ * \#define queue_IsEnd(q,i) (_Q(q) == _Q(i))
+ * \par
+ * This macro returns a non-zero value if the queue item located at i is the
+ * end of the queue located at q. Basically, it determines whether a queue
+ * element in question is also the queue header structure itself, and thus does
+ * not represent an actual queue element. This function is useful for
+ * terminating an iterative sweep through a queue, identifying when the search
+ * has wrapped to the queue header.
+ *
+ * \subsubsection sec4-2-3-22 Section 4.2.3.22: queue Scan(): for loop
+ * test for scanning a queue in a forward direction
+ *
+ * \par
+ * \#define queue_Scan(q, qe, next, s)
+ * \n (qe) = queue_first(q, s), next = queue_Next(qe, s);
+ * \n !queue_IsEnd(q, qe);
+ * \n (qe) = (next), next = queue_Next(qe, s)
+ * \par
+ * This macro may be used as the body of a for loop test intended to scan
+ * through each element in the queue located at q. The qe argument is used as
+ * the for loop variable. The next argument is used to store the next value for
+ * qe in the upcoming loop iteration. The s argument provides the name of the
+ * structure to which each queue element is to be coerced. Thus, the values
+ * provided for the qe and next arguments must be of type (struct s *).
+ * \par
+ * An example of how queue Scan() may be used appears in the code fragment
+ * below. It declares a structure named mystruct, which is suitable for
+ * queueing. This queueable structure is composed of the queue pointers
+ * themselves followed by an integer value. The actual queue header is kept in
+ * demoQueue, and the currItemP and nextItemP variables are used to step
+ * through the demoQueue. The queue Scan() macro is used in the for loop to
+ * generate references in currItemP to each queue element in turn for each
+ * iteration. The loop is used to increment every queued structure's myval
+ * field by one.
+ *
+ * \code
+ * struct mystruct {
+ * struct queue q;
+ * int myval;
+ * };
+ * struct queue demoQueue;
+ * struct mystruct *currItemP, *nextItemP;
+ * ...
+ * for (queue_Scan(&demoQueue, currItemP, nextItemP, mystruct)) {
+ * currItemP->myval++;
+ * }
+ * \endcode
+ *
+ * \par
+ * Note that extra initializers can be added before the body of the queue
+ * Scan() invocation above, and extra expressions can be added afterwards.
+ *
+ * \subsubsection sec4-2-3-23 Section 4.2.3.23: queue ScanBackwards(): for
+ * loop test for scanning a queue in a reverse direction
+ *
+ * \par
+ * #define queue_ScanBackwards(q, qe, prev, s)
+ * \n (qe) = queue_Last(q, s), prev = queue_Prev(qe, s);
+ * \n !queue_IsEnd(q, qe);
+ * \n (qe) = prev, prev = queue_Prev(qe, s)
+ * \par
+ * This macro is identical to the queue Scan() macro described above in Section
+ * 4.2.3.22 except for the fact that the given queue is scanned backwards,
+ * starting at the last item in the queue.
+ *
+ * \section sec4-3 Section 4.3: The rx clock Package
+ *
+ * \par
+ * This package maintains a clock which is independent of the time of day. It
+ * uses the unix 4.3BSD interval timer (e.g., getitimer(), setitimer()) in
+ * TIMER REAL mode. Its definition and interface may be found in the rx clock.h
+ * include file.
+ *
+ * \subsection sec4-3-1 Section 4.3.1: struct clock
+ *
+ * \par
+ * This structure is used to represent a clock value as understood by this
+ * package. It consists of two fields, storing the number of seconds and
+ * microseconds that have elapsed since the associated clock Init() routine has
+ * been called.
+ * \par
+ * \b fields
+ * \n long sec -Seconds since call to clock Init().
+ * \n long usec -Microseconds since call to clock Init().
+ *
+ * \subsection sec4-3-2 Section 4.3.12: clock nUpdates
+ *
+ * \par
+ * The integer-valued clock nUpdates is a variable exported by the rx clock
+ * facility. It records the number of times the clock value is actually
+ * updated. It is bumped each time the clock UpdateTime() routine is called, as
+ * described in Section 4.3.3.2.
+ *
+ * \subsection sec4-3-3 Section 4.3.3: Operations
+ *
+ * \subsubsection sec4-3-3-1 Section 4.3.3.1: clock Init(): Initialize the
+ * clock package
+ *
+ * \par
+ * This routine uses the unix setitimer() call to initialize the unix interval
+ * timer. If the setitimer() call fails, an error message will appear on
+ * stderr, and an exit(1) will be executed.
+ *
+ * \subsubsection sec4-3-3-2 Section 4.3.3.2: clock UpdateTime(): Compute
+ * the current time
+ *
+ * \par
+ * The clock UpdateTime() function calls the unix getitimer() routine in order
+ * to update the current time. The exported clock nUpdates variable is
+ * incremented each time the clock UpdateTime() routine is called.
+ *
+ * \subsubsection sec4-3-3-3 Section 4.3.3.3: clock GetTime(): Return the
+ * current clock time
+ *
+ * \par
+ * This macro updates the current time if necessary, and returns the current
+ * time into the cv argument, which is declared to be of type (struct clock *).
+ * 4.3.3.4 clock Sec(): Get the current clock time, truncated to seconds
+ * This macro returns the long value of the sec field of the current time. The
+ * recorded time is updated if necessary before the above value is returned.
+ *
+ * \subsubsection sec4-3-3-5 Section 4.3.3.5: clock ElapsedTime(): Measure
+ * milliseconds between two given clock values
+ *
+ * \par
+ * This macro returns the elapsed time in milliseconds between the two clock
+ * structure pointers provided as arguments, cv1 and cv2.
+ *
+ * \subsubsection sec4-3-3-6 Section 4.3.3.6: clock Advance(): Advance the
+ * recorded clock time by a specified clock value
+ *
+ * \par
+ * This macro takes a single (struct clock *) pointer argument, cv, and adds
+ * this clock value to the internal clock value maintined by the package.
+ *
+ * \subsubsection sec4-3-3-7 Section 4.3.3.7: clock Gt(): Is a clock value
+ * greater than another?
+ *
+ * \par
+ * This macro takes two parameters of type (struct clock *), a and b. It
+ * returns a nonzero value if the a parameter points to a clock value which is
+ * later than the one pointed to by b.
+ *
+ * \subsubsection sec4-3-3-8 Section 4.3.3.8: clock Ge(): Is a clock value
+ * greater than or equal to another?
+ *
+ * \par
+ * This macro takes two parameters of type (struct clock *), a and b. It
+ * returns a nonzero value if the a parameter points to a clock value which is
+ * greater than or equal to the one pointed to by b.
+ *
+ * \subsubsection sec4-3-3-9 Section 4.3.3.9: clock Gt(): Are two clock
+ * values equal?
+ *
+ * \par
+ * This macro takes two parameters of type (struct clock *), a and b. It
+ * returns a non-zero value if the clock values pointed to by a and b are
+ * equal.
+ *
+ * \subsubsection sec4.3.3.10 Section 4.3.3.10: clock Le(): Is a clock
+ * value less than or equal to another?
+ *
+ * \par
+ * This macro takes two parameters of type (struct clock *), a and b. It
+ * returns a nonzero value if the a parameter points to a clock value which is
+ * less than or equal to the one pointed to by b.
+ *
+ * \subsubsection sec4-3-3-11 Section 4.3.3.11: clock Lt(): Is a clock
+ * value less than another?
+ *
+ * \par
+ * This macro takes two parameters of type (struct clock *), a and b. It
+ * returns a nonzero value if the a parameter points to a clock value which is
+ * less than the one pointed to by b.
+ *
+ * \subsubsection sec4-3-3-12 Section 4.3.3.12: clock IsZero(): Is a clock
+ * value zero?
+ *
+ * \par
+ * This macro takes a single parameter of type (struct clock *), c. It returns
+ * a non-zero value if the c parameter points to a clock value which is equal
+ * to zero.
+ *
+ * \subsubsection sec4-3-3-13 Section 4.3.3.13: clock Zero(): Set a clock
+ * value to zero
+ *
+ * \par
+ * This macro takes a single parameter of type (struct clock *), c. It sets the
+ * given clock value to zero.
+ * \subsubsection sec4-3-3-14 Section 4.3.3.14: clock Add(): Add two clock
+ * values together
+ * \par
+ * This macro takes two parameters of type (struct clock *), c1 and c2. It adds
+ * the value of the time in c2 to c1. Both clock values must be positive.
+ *
+ * \subsubsection sec4-3-3-15 Section 4.3.3.15: clock Sub(): Subtract two
+ * clock values
+ *
+ * \par
+ * This macro takes two parameters of type (struct clock *), c1 and c2. It
+ * subtracts the value of the time in c2 from c1. The time pointed to by c2
+ * should be less than the time pointed to by c1.
+ *
+ * \subsubsection sec4-3-3-16 Section 4.3.3.16: clock Float(): Convert a
+ * clock time into floating point
+ *
+ * \par
+ * This macro takes a single parameter of type (struct clock *), c. It
+ * expresses the given clock value as a floating point number.
+ *
+ * \section sec4-4 Section 4.4: The rx event Package
+ *
+ * \par
+ * This package maintains an event facility. An event is defined to be
+ * something that happens at or after a specified clock time, unless cancelled
+ * prematurely. The clock times used are those provided by the rx clock
+ * facility described in Section 4.3 above. A user routine associated with an
+ * event is called with the appropriate arguments when that event occurs. There
+ * are some restrictions on user routines associated with such events. first,
+ * this user-supplied routine should not cause process preemption. Also, the
+ * event passed to the user routine is still resident on the event queue at the
+ * time of invocation. The user must not remove this event explicitly (via an
+ * event Cancel(), see below). Rather, the user routine may remove or schedule
+ * any other event at this time.
+ * \par
+ * The events recorded by this package are kept queued in order of expiration
+ * time, so that the first entry in the queue corresponds to the event which is
+ * the first to expire. This interface is defined by the rx event.h include
+ * file.
+ *
+ * \subsection sec4-4-1 Section 4.4.1: struct rxevent
+ *
+ * \par
+ * This structure defines the format of an Rx event record.
+ * \par
+ * \b fields
+ * \n struct queue junk -The queue to which this event belongs.
+ * \n struct clock eventTime -The clock time recording when this event comes
+ * due.
+ * \n int (*func)() -The user-supplied function to call upon expiration.
+ * \n char *arg -The first argument to the (*func)() function above.
+ * \n char *arg1 -The second argument to the (*func)() function above.
+ *
+ * \subsection sec4-4-2 Section 4.4.2: Operations
+ *
+ * \par
+ * This section covers the interface routines provided for the Rx event
+ * package.
+ *
+ * \subsubsection sec4-4-2-1 Section 4.4.2.1: rxevent Init(): Initialize
+ * the event package
+ *
+ * \par
+ * The rxevent Init() routine takes two arguments. The first, nEvents, is an
+ * integer-valued parameter which specifies the number of event structures to
+ * allocate at one time. This specifies the appropriate granularity of memory
+ * allocation by the event package. The second parameter, scheduler, is a
+ * pointer to an integer-valued function. This function is to be called when an
+ * event is posted (added to the set of events managed by the package) that is
+ * scheduled to expire before any other existing event.
+ * \par
+ * This routine sets up future event allocation block sizes, initializes the
+ * queues used to manage active and free event structures, and recalls that an
+ * initialization has occurred. Thus, this function may be safely called
+ * multiple times.
+ *
+ * \subsubsection sec4-4-2-2 Section 4.4.2.2: rxevent Post(): Schedule an
+ * event
+ *
+ * \par
+ * This function constructs a new event based on the information included in
+ * its parameters and then schedules it. The rxevent Post() routine takes four
+ * parameters. The first is named when, and is of type (struct clock *). It
+ * specifies the clock time at which the event is to occur. The second
+ * parameter is named func and is a pointer to the integer-valued function to
+ * associate with the event that will be created. When the event comes due,
+ * this function will be executed by the event package. The next two arguments
+ * to rxevent Post() are named arg and arg1, and are both of type (char *).
+ * They serve as the two arguments thath will be supplied to the func routine
+ * when the event comes due.
+ * \par
+ * If the given event is set to take place before any other event currently
+ * posted, the scheduler routine established when the rxevent Init() routine
+ * was called will be executed. This gives the application a chance to react to
+ * this new event in a reasonable way. One might expect that this scheduler
+ * routine will alter sleep times used by the application to make sure that it
+ * executes in time to handle the new event.
+ *
+ * \subsubsection sec4-4-2-3 Section 4.4.2.3: rxevent Cancel 1(): Cancel
+ * an event (internal use)
+ *
+ * \par
+ * This routine removes an event from the set managed by this package. It takes
+ * a single parameter named ev of type (struct rxevent *). The ev argument
+ * identifies the pending event to be cancelled.
+ * \par
+ * The rxevent Cancel 1() routine should never be called directly. Rather, it
+ * should be accessed through the rxevent Cancel() macro, described in Section
+ * 4.4.2.4 below.
+ *
+ * \subsubsection sec4-4-2-4 Section 4.4.2.4: rxevent Cancel(): Cancel an
+ * event (external use)
+ *
+ * \par
+ * This macro is the proper way to call the rxevent Cancel 1() routine
+ * described in Section 4.4.2.3 above. Like rxevent Cancel 1(), it takes a
+ * single argument. This event ptr argument is of type (struct rxevent *), and
+ * identi#es the pending event to be cancelled. This macro #rst checks to see
+ * if event ptr is null. If not, it calls rxevent Cancel 1() to perform the
+ * real work. The event ptr argument is zeroed after the cancellation operation
+ * completes.
+ *
+ * \subsubsection sec4-4-2-5 Section 4.4.2.4: rxevent RaiseEvents():
+ * Initialize the event package
+ *
+ * \par
+ * This function processes all events that have expired relative to the current
+ * clock time maintained by the event package. Each qualifying event is removed
+ * from the queue in order, and its user-supplied routine (func()) is executed
+ * with the associated arguments.
+ * \par
+ * The rxevent RaiseEvents() routine takes a single output parameter named
+ * next, defined to be of type (struct clock *). Upon completion of rxevent
+ * RaiseEvents(), the relative time to the next event due to expire is placed
+ * in next. This knowledge may be used to calculate the amount of sleep time
+ * before more event processing is needed. If there is no recorded event which
+ * is still pending at this point, rxevent RaiseEvents() returns a zeroed clock
+ * value into next.
+ *
+ * \subsubsection sec4-4-2-6 Section 4.4.2.6: rxevent TimeToNextEvent():
+ * Get amount of time until the next event expires
+ *
+ * \par
+ * This function returns the time between the current clock value as maintained
+ * by the event package and the the next event's expiration time. This
+ * information is placed in the single output argument,interval, defined to be
+ * of type (struct clock *). The rxevent TimeToNextEvent() function returns
+ * integer-valued quantities. If there are no scheduled events, a zero is
+ * returned. If there are one or more scheduled events, a 1 is returned. If
+ * zero is returned, the interval argument is not updated.
+ *
+ * \page chap5 Chapter 5 -- Programming Interface
+ *
+ * \section sec5-1 Section 5.1: Introduction
+ *
+ * \par
+ * This chapter documents the API for the Rx facility. Included are
+ * descriptions of all the constants, structures, exported variables, macros,
+ * and interface functions available to the application programmer. This
+ * interface is identical regardless of whether the application lives within
+ * the unix kernel or above it.
+ * \par
+ * This chapter actually provides more information than what may be strictly
+ * considered the Rx API. Many objects that were intended to be opaque and for
+ * Rx internal use only are also described here. The reason driving the
+ * inclusion of this "extra" information is that such exported Rx interface
+ * files as rx.h make these objects visible to application programmers. It is
+ * prefereable to describe these objects here than to ignore them and leave
+ * application programmers wondering as to their meaning.
+ * \par
+ * An example application illustrating the use of this interface, showcasing
+ * code from both server and client sides, appears in the following chapter.
+ *
+ * \section sec5-2 Section 5.2: Constants
+ *
+ * \par
+ * This section covers the basic constant definitions of interest to the Rx
+ * application programmer. Each subsection is devoted to describing the
+ * constants falling into the following categories:
+ * \li Configuration quantities
+ * \li Waiting options
+ * \li Connection ID operations
+ * \li Connection flags
+ * \li Connection types
+ * \li Call states
+ * \li Call flags
+ * \li Call modes
+ * \li Packet header flags
+ * \li Packet sizes
+ * \li Packet types
+ * \li Packet classes
+ * \li Conditions prompting ack packets
+ * \li Ack types
+ * \li Error codes
+ * \li Debugging values
+ * \par
+ * An attempt has been made to relate these constant definitions to the objects
+ * or routines that utilize them.
+ *
+ * \subsection sec5-2-1 Section 5.2.1: Configuration Quantities
+ *
+ * \par
+ * These definitions provide some basic Rx configuration parameters, including
+ * the number of simultaneous calls that may be handled on a single connection,
+ * lightweight thread parameters, and timeouts for various operations.
+ *
+ * \par Name
+ * RX IDLE DEAD TIME
+ * \par Value
+ * 60
+ * \par Description
+ * Default idle dead time for connections, in seconds.
+ *
+ * \par Name
+ * RX MAX SERVICES
+ * \par Value
+ * 20
+ * \par Description
+ * The maximum number of Rx services that may be installed within one
+ * application.
+ *
+ * \par Name
+ * RX PROCESS MAXCALLS
+ * \par Value
+ * 4
+ * \par Description
+ * The maximum number of asynchronous calls active simultaneously on any given
+ * Rx connection. This value must be set to a power of two.
+ *
+ * \par Name
+ * RX DEFAULT STACK SIZE
+ * \par Value
+ * 16,000
+ * \par Description
+ * Default lightweight thread stack size, measured in bytes. This value may be
+ * overridden by calling the rx_SetStackSize() macro.
+ *
+ * \par Name
+ * RX PROCESS PRIORITY
+ * \par Value
+ * LWP NORMAL PRIORITY
+ * \par Description
+ * This is the priority under which an Rx thread should run. There should not
+ * generally be any reason to change this setting.
+ *
+ * \par Name
+ * RX CHALLENGE TIMEOUT
+ * \par Value
+ * 2
+ * \par Description
+ * The number of seconds before another authentication request packet is
+ * generated.
+ *
+ * \par Name
+ * RX MAXACKS
+ * \par Value
+ * 255
+ * \par Description
+ * Maximum number of individual acknowledgements that may be carried in an Rx
+ * acknowledgement packet.
+ *
+ * \subsection sec5-2-2 Section 5.2.2: Waiting Options
+ *
+ * \par
+ * These definitions provide readable values indicating whether an operation
+ * should block when packet buffer resources are not available.
+ *
+ * \par Name
+ * RX DONTWAIT
+ * \par Value
+ * 0
+ * \par Description
+ * Wait until the associated operation completes.
+ *
+ * \par Name
+ * RX WAIT
+ * \par Value
+ * 1
+ * \par Description
+ * Don't wait if the associated operation would block.
+ *
+ * \subsection sec5-2-3 Section 5.2.3: Connection ID Operations
+ *
+ * \par
+ * These values assist in extracting the call channel number from a connection
+ * identifier. A call channel is the index of a particular asynchronous call
+ * structure within a single Rx connection.
+ *
+ * \par Name
+ * RX CIDSHIFT
+ * \par Value
+ * 2
+ * \par Description
+ * Number of bits to right-shift to isolate a connection ID. Must be set to
+ * the log (base two) of RX MAXCALLS.
+ *
+ * \par Name
+ * RX CHANNELMASK
+ * \par Value
+ * (RX MAXCALLS-1)
+ * \par Description
+ * Mask used to isolate a call channel from a connection ID field.
+ *
+ * \par Name
+ * RX CIDMASK
+ * \par Value
+ * (~RX CHANNELMASK)
+ * \par Description
+ * Mask used to isolate the connection ID from its field, masking out the call
+ * channel information.
+ *
+ * \subsection sec5-2-4 Section 5.2.4: Connection Flags
+ *
+ * \par
+ * The values defined here appear in the flags field of Rx connections, as
+ * defined by the rx connection structure described in Section 5.3.2.2.
+ *
+ * \par Name
+ * RX CONN MAKECALL WAITING
+ * \par Value
+ * 1
+ * \par Description
+ * rx MakeCall() is waiting for a channel.
+ *
+ * \par Name
+ * RX CONN DESTROY ME
+ * \par Value
+ * 2
+ * \par Description
+ * Destroy this (client) connection after its last call completes.
+ *
+ * \par Name
+ * RX CONN USING PACKET CKSUM
+ * \par Value
+ * 4
+ * \par Description
+ * This packet is using security-related check-summing (a non-zero header,
+ * spare field has been seen.)
+ *
+ * \subsection sec5-2-5 Section 5.2.5: Connection Types
+ *
+ * \par
+ * Rx stores different information in its connection structures, depending on
+ * whether the given connection represents the server side (the one providing
+ * the service) or the client side (the one requesting the service) of the
+ * protocol. The type field within the connection structure (described in
+ * Section 5.3.2.2) takes on the following values to differentiate the two
+ * types of connections, and identifies the fields that are active within the
+ * connection structure.
+ *
+ * \par Name
+ * RX CLIENT CONNECTION
+ * \par Value
+ * 0
+ * \par Description
+ * This is a client-side connection.
+ *
+ * \par Name
+ * CONNECTION
+ * \par Value
+ * 1
+ * \par Description
+ * This is a server-side connection.
+ *
+ * \subsection sec5-2-6 Section 5.2.6: Call States
+ *
+ * \par
+ * An Rx call on a particular connection may be in one of several states at any
+ * instant in time. The following definitions identify the range of states that
+ * a call may assume.
+ *
+ * \par Name
+ * RX STATE NOTINIT
+ * \par Value
+ * 0
+ * \par Description
+ * The call structure has never been used, and is thus still completely
+ * uninitialized.
+ *
+ * \par Name
+ * RX STATE PRECALL
+ * \par Value
+ * 1
+ * \par Description
+ * A call is not yet in progress, but packets have arrived for it anyway. This
+ * only applies to calls within server-side connections.
+ *
+ * \par Name
+ * RX STATE ACTIVE
+ * \par Value
+ * 2
+ * \par Description
+ * This call is fully active, having an attached lightweight thread operating
+ * on its behalf.
+ *
+ * \par Name
+ * RX STATE DAILY
+ * \par Value
+ * 3
+ * \par Description
+ * The call structure is "dallying" after its lightweight thread has completed
+ * its most recent call. This is a "hot-standby" condition, where the call
+ * structure preserves state from the previous call and thus optimizes the
+ * arrival of further, related calls.
+ *
+ * \subsection sec5-2-7 Section 5.2.7: Call Flags:
+ *
+ * \par
+ * These values are used within the flags field of a variable declared to be of
+ * type struct rx call, as described in Section 5.3.2.4. They provide
+ * additional information as to the state of the given Rx call, such as the
+ * type of event for which it is waiting (if any) and whether or not all
+ * incoming packets have been received in support of the call.
+ *
+ * \par Name
+ * RX CALL READER WAIT
+ * \par Value
+ * 1
+ * \par Description
+ * Reader is waiting for next packet.
+ *
+ * \par Name
+ * RX CALL WAIT WINDOW ALLOC
+ * \par Value
+ * 2
+ * \par Description
+ * Sender is waiting for a window so that it can allocate buffers.
+ *
+ * \par Name
+ * RX CALL WAIT WINDOW SEND
+ * \par Value
+ * 4
+ * \par Description
+ * Sender is waiting for a window so that it can send buffers.
+ *
+ * \par Name
+ * RX CALL WAIT PACKETS
+ * \par Value
+ * 8
+ * \par Description
+ * Sender is waiting for packet buffers.
+ *
+ * \par Name
+ * RX CALL RECEIVE DONE
+ * \par Value
+ * 16
+ * \par Description
+ * The call is waiting for a lightweight thread to be assigned to the operation
+ * it has just received.
+ *
+ * \par Name
+ * RX CALL RECEIVE DONE
+ * \par Value
+ * 32
+ * \par Description
+ * All packets have been received on this call.
+ *
+ * \par Name
+ * RX CALL CLEARED
+ * \par Value
+ * 64
+ * \par Description
+ * The receive queue has been cleared when in precall state.
+ *
+ * \subsection sec5-2-8 Section 5.2.8: Call Modes
+ *
+ * \par
+ * These values define the modes of an Rx call when it is in the RX STATE
+ * ACTIVE state, having a lightweight thread assigned to it.
+ *
+ * \par Name
+ * RX MODE SENDING
+ * \par Value
+ * 1
+ * \par Description
+ * We are sending or ready to send.
+ *
+ * \par Name
+ * RX MODE RECEIVING
+ * \par Value
+ * 2
+ * \par Description
+ * We are receiving or ready to receive.
+ *
+ * \par Name
+ * RX MODE ERROR
+ * \par Value
+ * 3
+ * \par Description
+ * Something went wrong in the current conversation.
+ *
+ * \par Name
+ * RX MODE EOF
+ * \par Value
+ * 4
+ * \par Description
+ * The server side has flushed (or the client side has read) the last reply
+ * packet.
+ *
+ * \subsection sec5-2-9 Section 5.2.9: Packet Header Flags
+ *
+ * \par
+ * Rx packets carry a flag field in their headers, providing additional
+ * information regarding the packet's contents. The Rx packet header's flag
+ * field's bits may take the following values:
+ *
+ * \par Name
+ * RX CLIENT INITIATED
+ * \par Value
+ * 1
+ * \par Description
+ * Signifies that a packet has been sent/received from the client side of the
+ * call.
+ *
+ * \par Name
+ * RX REQUEST ACK
+ * \par Value
+ * 2
+ * \par Description
+ * The Rx calls' peer entity requests an acknowledgement.
+ *
+ * \par Name
+ * RX LAST PACKET
+ * \par Value
+ * 4
+ * \par Description
+ * This is the final packet from this side of the call.
+ *
+ * \par Name
+ * RX MORE PACKETS
+ * \par Value
+ * 8
+ * \par Description
+ * There are more packets following this, i.e., the next sequence number seen
+ * by the receiver should be greater than this one, rather than a
+ * retransmission of an earlier sequence number.
+ *
+ * \par Name
+ * RX PRESET FLAGS
+ * \par Value
+ * (RX CLIENT INITIATED | RX LAST PACKET)
+ * \par Description
+ * This flag is preset once per Rx packet. It doesn't change on retransmission
+ * of the packet.
+ *
+ * \subsection sec5-3-10 Section 5.2.10: Packet Sizes
+ *
+ * \par
+ * These values provide sizing information on the various regions within Rx
+ * packets. These packet sections include the IP/UDP headers and bodies as well
+ * Rx header and bodies. Also covered are such values as different maximum
+ * packet sizes depending on whether they are targeted to peers on the same
+ * local network or a more far-flung network. Note that the MTU term appearing
+ * below is an abbreviation for Maximum Transmission Unit.
+ *
+ * \par Name
+ * RX IPUDP SIZE
+ * \par Value
+ * 28
+ * \par Description
+ * The number of bytes taken up by IP/UDP headers.
+ *
+ * \par Name
+ * RX MAX PACKET SIZE
+ * \par Value
+ * (1500 - RX IPUDP SIZE)
+ * \par Description
+ * This is the Ethernet MTU minus IP and UDP header sizes.
+ *
+ * \par Name
+ * RX HEADER SIZE
+ * \par Value
+ * sizeof (struct rx header)
+ * \par Description
+ * The number of bytes in an Rx packet header.
+ *
+ * \par Name
+ * RX MAX PACKET DATA SIZE
+ * \par Value
+ * (RX MAX PACKET SIZE RX - HEADER SIZE)
+ * \par Description
+ * Maximum size in bytes of the user data in a packet.
+ *
+ * \par Name
+ * RX LOCAL PACKET SIZE
+ * \par Value
+ * RX MAX PACKET SIZE
+ * \par Description
+ * Packet size in bytes to use when being sent to a host on the same net.
+ *
+ * \par Name
+ * RX REMOTE PACKET SIZE
+ * \par Value
+ * (576 - RX IPUDP SIZE)
+ * \par Description
+ * Packet size in bytes to use when being sent to a host on a different net.
+ *
+ * \subsection sec5-2-11 Section 5.2.11: Packet Types
+ *
+ * \par
+ * The following values are used in the packetType field within a struct rx
+ * packet, and define the different roles assumed by Rx packets. These roles
+ * include user data packets, different flavors of acknowledgements, busies,
+ * aborts, authentication challenges and responses, and debugging vehicles.
+ *
+ * \par Name
+ * RX PACKET TYPE DATA
+ * \par Value
+ * 1
+ * \par Description
+ * A user data packet.
+ *
+ * \par Name
+ * RX PACKET TYPE ACK
+ * \par Value
+ * 2
+ * \par Description
+ * Acknowledgement packet.
+ *
+ * \par Name
+ * RX PACKET TYPE BUSY
+ * \par Value
+ * 3
+ * \par Description
+ * Busy packet. The server-side entity cannot accept the call at the moment,
+ * but the requestor is encouraged to try again later.
+ *
+ * \par Name
+ * RX PACKET TYPE ABORT
+ * \par Value
+ * 4
+ * \par Description
+ * Abort packet. No response is needed for this packet type.
+ *
+ * \par Name
+ * RX PACKET TYPE ACKALL
+ * \par Value
+ * 5
+ * \par Description
+ * Acknowledges receipt of all packets on a call.
+ *
+ * \par Name
+ * RX PACKET TYPE CHALLENGE
+ * \par Value
+ * 6
+ * \par Description
+ * Challenge the client's identity, requesting credentials.
+ *
+ * \par Name
+ * RX PACKET TYPE RESPONSE
+ * \par Value
+ * 7
+ * \par Description
+ * Response to a RX PACKET TYPE CHALLENGE authentication challenge packet.
+ *
+ * \par Name
+ * RX PACKET TYPE DEBUG
+ * \par Value
+ * 8
+ * \par Description
+ * Request for debugging information.
+ *
+ * \par Name
+ * RX N PACKET TYPES
+ * \par Value
+ * 9
+ * \par Description
+ * The number of Rx packet types defined above. Note that it also includes
+ * packet type 0 (which is unused) in the count.
+ *
+ * \par
+ * The RX PACKET TYPES definition provides a mapping of the above values to
+ * human-readable string names, and is exported by the rx packetTypes variable
+ * catalogued in Section 5.4.9.
+ *
+ * \code
+ * {
+ * "data",
+ * "ack",
+ * "busy",
+ * "abort",
+ * "ackall",
+ * "challenge",
+ * "response",
+ * "debug"
+ * }
+ * \endcode
+ *
+ * \subsection sec5-2-12 Section 5.2.12: Packet Classes
+ *
+ * \par
+ * These definitions are used internally to manage alloction of Rx packet
+ * buffers according to quota classifications. Each packet belongs to one of
+ * the following classes, and its buffer is derived from the corresponding
+ * pool.
+ *
+ * \par Name
+ * RX PACKET CLASS RECEIVE
+ * \par Value
+ * 0
+ * \par Description
+ * Receive packet for user data.
+ *
+ * \par Name
+ * RX PACKET CLASS SEND
+ * \par Value
+ * 1
+ * \par Description
+ * Send packet for user data.
+ *
+ * \par Name
+ * RX PACKET CLASS SPECIAL
+ * \par Value
+ * 2
+ * \par Description
+ * A special packet that does not hold user data, such as an acknowledgement or
+ * authentication challenge.
+ *
+ * \par Name
+ * RX N PACKET CLASSES
+ * \par Value
+ * 3
+ * \par Description
+ * The number of Rx packet classes defined above.
+ *
+ * \subsection sec5-2-13 Section 5.2.13: Conditions Prompting Ack Packets
+ *
+ * \par
+ * Rx acknowledgement packets are constructed and sent by the protocol
+ * according to the following reasons. These values appear in the Rx packet
+ * header of the ack packet itself.
+ *
+ * \par Name
+ * RX ACK REQUESTED
+ * \par Value
+ * 1
+ * \par Description
+ * The peer has explicitly requested an ack on this packet.
+ *
+ * \par Name
+ * RX ACK DUPLICATE
+ * \par Value
+ * 2
+ * \par Description
+ * A duplicate packet has been received.
+ *
+ * \par Name
+ * RX ACK OUT OF SEQUENCE
+ * \par Value
+ * 3
+ * \par Description
+ * A packet has arrived out of sequence.
+ *
+ * \par Name
+ * RX ACK EXCEEDS WINDOW
+ * \par Value
+ * 4
+ * \par Description
+ * A packet sequence number higher than maximum value allowed by the call's
+ * window has been received.
+ *
+ * \par Name
+ * RX ACK NOSPACE
+ * \par Value
+ * 5
+ * \par Description
+ * No packet buffer space is available.
+ *
+ * \par Name
+ * RX ACK PING
+ * \par Value
+ * 6
+ * \par Description
+ * Acknowledgement for keep-alive purposes.
+ *
+ * \par Name
+ * RX ACK PING RESPONSE
+ * \par Value
+ * 7
+ * \par Description
+ * Response to a RX ACK PING packet.
+ *
+ * \par Name
+ * RX ACK DELAY
+ * \par Value
+ * 8
+ * \par Description
+ * An ack generated due to a period of inactivity after normal packet
+ * receptions.
+ *
+ * \subsection 5-2-14 Section 5.2.14: Acknowledgement Types
+ *
+ * \par
+ * These are the set of values placed into the acks array in an Rx
+ * acknowledgement packet, whose data format is defined by struct rx ackPacket.
+ * These definitions are used to convey positive or negative acknowledgements
+ * for a given range of packets.
+ *
+ * \par Name
+ * RX ACK TYPE NACK
+ * \par Value
+ * 0
+ * \par Description
+ * Receiver doesn't currently have the associated packet; it may never hae been
+ * received, or received and then later dropped before processing.
+ *
+ * \par Name
+ * RX ACK TYPE ACK
+ * \par Value
+ * 1
+ * \par Description
+ * Receiver has the associated packet queued, although it may later decide to
+ * discard it.
+ *
+ * \subsection sec5-2-15 Section 5.2.15: Error Codes
+ *
+ * \par
+ * Rx employs error codes ranging from -1 to -64. The Rxgen stub generator may
+ * use other error codes less than -64. User programs calling on Rx, on the
+ * other hand, are expected to return positive error codes. A return value of
+ * zero is interpreted as an indication that the given operation completed
+ * successfully.
+ *
+ * \par Name
+ * RX CALL DEAD
+ * \par Value
+ * -1
+ * \par Description
+ * A connection has been inactive past Rx's tolerance levels and has been shut
+ * down.
+ *
+ * \par Name
+ * RX INVALID OPERATION
+ * \par Value
+ * -2
+ * \par Description
+ * An invalid operation has been attempted, including such protocol errors as
+ * having a client-side call send data after having received the beginning of a
+ * reply from its server-side peer.
+ *
+ * \par Name
+ * RX CALL TIMEOUT
+ * \par Value
+ * -3
+ * \par Description
+ * The (optional) timeout value placed on this call has been exceeded (see
+ * Sections 5.5.3.4 and 5.6.5).
+ *
+ * \par Name
+ * RX EOF
+ * \par Value
+ * -4
+ * \par Description
+ * Unexpected end of data on a read operation.
+ *
+ * \par Name
+ * RX PROTOCOL ERROR
+ * \par Value
+ * -5
+ * \par Description
+ * An unspecified low-level Rx protocol error has occurred.
+ *
+ * \par Name
+ * RX USER ABORT
+ * \par Value
+ * -6
+ * \par Description
+ * A generic user abort code, used when no more specific error code needs to be
+ * communicated. For example, Rx clients employing the multicast feature (see
+ * Section 1.2.8) take advantage of this error code.
+ *
+ * \subsection sec5-2-16 Section 5.2.16: Debugging Values
+ *
+ * \par
+ * Rx provides a set of data collections that convey information about its
+ * internal status and performance. The following values have been defined in
+ * support of this debugging and statistics-collection feature.
+ *
+ * \subsubsection sec5-3-16-1 Section 5.2.16.1: Version Information
+ *
+ * \par
+ * Various versions of the Rx debugging/statistics interface are in existance,
+ * each defining different data collections and handling certain bugs. Each Rx
+ * facility is stamped with a version number of its debugging/statistics
+ * interface, allowing its clients to tailor their requests to the precise data
+ * collections that are supported by a particular Rx entity, and to properly
+ * interpret the data formats received through this interface. All existing Rx
+ * implementations should be at revision M.
+ *
+ * \par Name
+ * RX DEBUGI VERSION MINIMUM
+ * \par Value
+ * 'L'
+ * \par Description
+ * The earliest version of Rx statistics available.
+ *
+ * \par Name
+ * RX DEBUGI VERSION
+ * \par Value
+ * 'M'
+ * \par Description
+ * The latest version of Rx statistics available.
+ *
+ * \par Name
+ * RX DEBUGI VERSION W SECSTATS
+ * \par Value
+ * 'L'
+ * \par Description
+ * Identifies the earliest version in which statistics concerning Rx security
+ * objects is available.
+ *
+ * \par Name
+ * RX DEBUGI VERSION W GETALLCONN
+ * \par Value
+ * 'M'
+ * \par Description
+ * The first version that supports getting information about all current Rx
+ * connections, as specified y the RX DEBUGI GETALLCONN debugging request
+ * packet opcode described below.
+ *
+ * \par Name
+ * RX DEBUGI VERSION W RXSTATS
+ * \par Value
+ * 'M'
+ * \par Description
+ * The first version that supports getting all the Rx statistics in one
+ * operation, as specified by the RX DEBUGI RXSTATS debugging request packet
+ * opcode described below.
+ *
+ * \par Name
+ * RX DEBUGI VERSION W UNALIGNED CONN
+ * \par Value
+ * 'L'
+ * \par Description
+ * There was an alignment problem discovered when returning Rx connection
+ * information in older versions of this debugging/statistics interface. This
+ * identifies the last version that exhibited this alignment problem.
+ *
+ * \subsubsection sec5-2-16-2 Section 5.2.16.2: Opcodes
+ *
+ * \par
+ * When requesting debugging/statistics information, the caller specifies one
+ * of the following supported data collections:
+ *
+ * \par Name
+ * RX DEBUGI GETSTATS
+ * \par Value
+ * 1
+ * \par Description
+ * Get basic Rx statistics.
+ *
+ * \par Name
+ * RX DEBUGI GETCONN
+ * \par Value
+ * 2
+ * \par Description
+ * Get information on all Rx connections considered "interesting" (as defined
+ * below), and no others.
+ *
+ * \par Name
+ * RX DEBUGI GETALLCONN
+ * \par Value
+ * 3
+ * \par Description
+ * Get information on all existing Rx connection structures, even
+ * "uninteresting" ones.
+ *
+ * \par Name
+ * RX DEBUGI RXSTATS
+ * \par Value
+ * 4
+ * \par Description
+ * Get all available Rx stats.
+ *
+ * \par
+ * An Rx connection is considered "interesting" if it is waiting for a call
+ * channel to free up or if it has been marked for destruction. If neither is
+ * true, a connection is still considered interesting if any of its call
+ * channels is actively handling a call or in its preparatory pre-call state.
+ * Failing all the above conditions, a connection is still tagged as
+ * interesting if any of its call channels is in either of the RX MODE SENDING
+ * or RX MODE RECEIVING modes, which are not allowed when the call is not
+ * active.
+ *
+ * \subsubsection sec5-2-16-3 Section 5.2.16.3: Queuing
+ *
+ * \par
+ * These two queueing-related values indicate whether packets are present on
+ * the incoming and outgoing packet queues for a given Rx call. These values
+ * are only used in support of debugging and statistics-gathering operations.
+ *
+ * \par Name
+ * RX OTHER IN
+ * \par Value
+ * 1
+ * \par Description
+ * Packets available in in queue.
+ *
+ * \par Name
+ * RX OTHER OUT
+ * \par Value
+ * 2
+ * \par Description
+ * Packets available in out queue.
+ *
+ * \section sec5-3 Section 5.3: Structures
+ *
+ * \par
+ * This section describes the major exported Rx data structures of interest to
+ * application programmers. The following categories are utilized for the
+ * purpose of organizing the structure descriptions:
+ * \li Security objects
+ * \li Protocol objects
+ * \li Packet formats
+ * \li Debugging and statistics
+ * \li Miscellaneous
+ * \par
+ * Please note that many fields described in this section are declared to be
+ * VOID. This is defined to be char, and is used to get around some compiler
+ * limitations.
+ * \subsection sec5-3-1 Section 5.3.1: Security Objects
+ *
+ * \par
+ * As explained in Section 1.2.1, Rx provides a modular, extensible security
+ * model. This allows Rx applications to either use one of the built-in
+ * security/authentication protocol packages or write and plug in one of their
+ * own. This section examines the various structural components used by Rx to
+ * support generic security and authentication modules.
+ *
+ * \subsubsection sec5-3-1-1 Section 5.3.1.1: struct rx securityOps
+ *
+ * \par
+ * As previously described, each Rx security object must export a fixed set of
+ * interface functions, providing the full set of operations defined on the
+ * object. The rx securityOps structure defines the array of functions
+ * comprising this interface. The Rx facility calls these routines at the
+ * appropriate times, without knowing the specifics of how any particular
+ * security object implements the operation.
+ * \par
+ * A complete description of these interface functions, including information
+ * regarding their exact purpose, parameters, and calling conventions, may be
+ * found in Section 5.5.7.
+ * \par
+ * \b fields
+ * \li int (*op Close)() - React to the disposal of a security object.
+ * \li int (*op NewConnection)() - Invoked each time a new Rx connection
+ * utilizing the associated security object is created.
+ * \li int (*op PreparePacket)() - Invoked each time an outgoing Rx packet is
+ * created and sent on a connection using the given security object.
+ * \li int (*op SendPacket)() - Called each time a packet belonging to a call
+ * in a connection using the security object is physically transmitted.
+ * \li int (*op CheckAuthentication)() - This function is executed each time it
+ * is necessary to check whether authenticated calls are being perfomed on a
+ * connection using the associated security object.
+ * \li int (*op CreateChallenge)() - Invoked each time a server-side challenge
+ * event is created by Rx, namely when the identity of the principal associated
+ * with the peer process must be determined.
+ * \li int (*op GetChallenge)() - Called each time a client-side packet is
+ * constructed in response to an authentication challenge.
+ * \li int (*op GetResponse)() - Executed each time a response to a challenge
+ * event must be received on the server side of a connection.
+ * \li int (*op CheckResponse)() - Invoked each time a response to an
+ * authentication has been received, validating the response and pulling out
+ * the required authentication information.
+ * \li int (*op CheckPacket) () - Invoked each time an Rx packet has been
+ * received, making sure that the packet is properly formatted and that it
+ * hasn't been altered.
+ * \li int (*op DestroyConnection)() - Called each time an Rx connection
+ * employing the given security object is destroyed.
+ * \li int (*op GetStats)() - Executed each time a request for statistics on
+ * the given security object has been received.
+ * \li int (*op Spare1)()-int (*op Spare3)() - Three spare function slots,
+ * reserved for future use.
+ *
+ * \subsubsection sec5-3-1-2 Section 5.2.1.2: struct rx securityClass
+ *
+ * \par
+ * Variables of type struct rx securityClass are used to represent
+ * instantiations of a particular security model employed by Rx. It consists of
+ * a pointer to the set of interface operations implementing the given security
+ * object, along with a pointer to private storage as necessary to support its
+ * operations. These security objects are also reference-counted, tracking the
+ * number of Rx connections in existance that use the given security object. If
+ * the reference count drops to zero, the security module may garbage-collect
+ * the space taken by the unused security object.
+ * \par
+ * \b fields
+ * \li struct rx securityOps *ops - Pointer to the array of interface functions
+ * for the security object.
+ * \li VOID *privateData - Pointer to a region of storage used by the security
+ * object to support its operations.
+ * \li int refCount - A reference count on the security object, tracking the
+ * number of Rx connections employing this model.
+ *
+ * \subsubsection sec5-3-1-3 Section 5.3.1.3: struct rx
+ * securityObjectStats
+ *
+ * \par
+ * This structure is used to report characteristics for an instantiation of a
+ * security object on a particular Rx connection, as well as performance
+ * figures for that object. It is used by the debugging portions of the Rx
+ * package. Every security object defines and manages fields such as level and
+ * flags differently.
+ * \par
+ * \b fields
+ * \li char type - The type of security object being implemented. Existing
+ * values are:
+ * \li 0: The null security package.
+ * \li 1: An obsolete Kerberos-like security object.
+ * \li 2: The rxkad discipline (see Chapter 3).
+ * \li char level - The level at which encryption is utilized.
+ * \li char sparec[10] - Used solely for alignment purposes.
+ * \li long flags - Status flags regarding aspects of the connection relating
+ * to the security object.
+ * \li u long expires - Absolute time when the authentication information
+ * cached by the given connection expires. A value of zero indicates that the
+ * associated authentication information is valid for all time.
+ * \li u long packetsReceived - Number of packets received on this particular
+ * connection, and thus the number of incoming packets handled by the
+ * associated security object.
+ * \li u long packetsSent - Number of packets sent on this particular
+ * connection, and thus the number of outgoing packets handled by the
+ * associated security object.
+ * \li u long bytesReceived - Overall number of "payload" bytes received (i.e.,
+ * packet bytes not associated with IP headers, UDP headers, and the security
+ * module's own header and trailer regions) on this connection.
+ * \li u long bytesSent - Overall number of "payload" bytes sent (i.e., packet
+ * bytes not associated with IP headers, UDP headers, and the security module's
+ * own header and trailer regions) on this connection.
+ * \li short spares[4] - Several shortword spares, reserved for future use.
+ * \li long sparel[8] - Several longword spares, reserved for future use.
+ *
+ * \subsection sec5-3-2 Section 5.3.2: Protocol Objects
+ *
+ * \par
+ * The structures describing the main abstractions and entities provided by Rx,
+ * namely services, peers, connections and calls are covered in this section.
+ *
+ * \subsubsection sec5-3-2-1 Section 5.3.2.1: struct rx service
+ *
+ * \par
+ * An Rx-based server exports services, or specific RPC interfaces that
+ * accomplish certain tasks. Services are identified by (host-address,
+ * UDP-port, serviceID) triples. An Rx service is installed and initialized on
+ * a given host through the use of the rx NewService() routine (See Section
+ * 5.6.3). Incoming calls are stamped with the Rx service type, and must match
+ * an installed service to be accepted. Internally, Rx services also carry
+ * string names for purposes of identification. These strings are useful to
+ * remote debugging and statistics-gathering programs. The use of a service ID
+ * allows a single server process to export multiple, independently-specified
+ * Rx RPC services.
+ * \par
+ * Each Rx service contains one or more security classes, as implemented by
+ * individual security objects. These security objects implement end-to-end
+ * security protocols. Individual peer-to-peer connections established on
+ * behalf of an Rx service will select exactly one of the supported security
+ * objects to define the authentication procedures followed by all calls
+ * associated with the connection. Applications are not limited to using only
+ * the core set of built-in security objects offered by Rx. They are free to
+ * define their own security objects in order to execute the specific protocols
+ * they require.
+ * \par
+ * It is possible to specify both the minimum and maximum number of lightweight
+ * processes available to handle simultaneous calls directed to an Rx service.
+ * In addition, certain procedures may be registered with the service and
+ * called at set times in the course of handling an RPC request.
+ * \par
+ * \b fields
+ * \li u short serviceId - The associated service number.
+ * \li u short servicePort - The chosen UDP port for this service.
+ * \li char *serviceName - The human-readable service name, expressed as a
+ * character
+ * \li string. osi socket socket - The socket structure or file descriptor used
+ * by this service.
+ * \li u short nSecurityObjects - The number of entries in the array of
+ * supported security objects.
+ * \li struct rx securityClass **securityObjects - The array of pointers to the
+ * ser
+ * vice's security class objects.
+ * \li long (*executeRequestProc)() - A pointer to the routine to call when an
+ * RPC request is received for this service.
+ * \li VOID (*destroyConnProc)() - A pointer to the routine to call when one of
+ * the server-side connections associated with this service is destroyed.
+ * \li VOID (*newConnProc)() - A pointer to the routine to call when a
+ * server-side connection associated with this service is created.
+ * \li VOID (*beforeProc)() - A pointer to the routine to call before an
+ * individual RPC call on one of this service's connections is executed.
+ * \li VOID (*afterProc)() - A pointer to the routine to call after an
+ * individual RPC call on one of this service's connections is executed.
+ * \li short nRequestsRunning - The number of simultaneous RPC calls currently
+ * in progress for this service.
+ * \li short maxProcs - This field has two meanings. first, maxProcs limits the
+ * total number of requests that may execute in parallel for any one service.
+ * It also guarantees that this many requests may be handled in parallel if
+ * there are no active calls for any other service.
+ * \li short minProcs - The minimum number of lightweight threads (hence
+ * requests) guaranteed to be simultaneously executable.
+ * \li short connDeadTime - The number of seconds until a client of this
+ * service will be declared to be dead, if it is not responding to the RPC
+ * protocol.
+ * \li short idleDeadTime - The number of seconds a server-side connection for
+ * this service will wait for packet I/O to resume after a quiescent period
+ * before the connection is marked as dead.
+ *
+ * \subsubsection sec5-3-2-2 Section 5.3.2.2: struct rx connection
+ *
+ * \par
+ * An Rx connection represents an authenticated communication path, allowing
+ * multiple asynchronous conversations (calls). Each connection is identified
+ * by a connection ID. The low-order bits of the connection ID are reserved so
+ * they may be stamped with the index of a particular call channel. With up to
+ * RX MAXCALLS concurrent calls (set to 4 in this implementation), the bottom
+ * two bits are set aside for this purpose. The connection ID is not sufficient
+ * by itself to uniquely identify an Rx connection. Should a client crash and
+ * restart, it may reuse a connection ID, causing inconsistent results. In
+ * addition to the connection ID, the epoch, or start time for the client side
+ * of the connection, is used to identify a connection. Should the above
+ * scenario occur, a different epoch value will be chosen by the client,
+ * differentiating this incarnation from the orphaned connection record on the
+ * server side.
+ * \par
+ * Each connection is associated with a parent service, which defines a set of
+ * supported security models. At creation time, an Rx connection selects the
+ * particular security protocol it will implement, referencing the associated
+ * service. The connection structure maintains state about the individual calls
+ * being simultaneously handled.
+ * \par
+ * \b fields
+ * \li struct rx connection *next - Used for internal queueing.
+ * \li struct rx peer *peer - Pointer to the connection's peer information (see
+ * below).
+ * \li u long epoch - Process start time of the client side of the connection.
+ * \li u long cid - Connection identifier. The call channel (i.e., the index
+ * into the connection's array of call structures) may appear in the bottom
+ * bits.
+ * \li VOID *rock - Pointer to an arbitrary region of memory in support of the
+ * connection's operation. The contents of this area are opaque to the Rx
+ * facility in general, but are understood by any special routines used by this
+ * connection.
+ * \li struct rx call *call[RX MAXCALLS] - Pointer to the call channel
+ * structures, describing up to RX MAXCALLS concurrent calls on this
+ * connection.
+ * \li u long callNumber[RX MAXCALLS] - The set of current call numbers on each
+ * of the call channels.
+ * \li int timeout - Obsolete; no longer used.
+ * \li u char flags - Various states of the connection; see Section 5.2.4 for
+ * individual bit definitions.
+ * \li u char type - Whether the connection is a server-side or client-side
+ * one. See Section 5.2.5 for individual bit definitions.
+ * \li u short serviceId - The service ID that should be stamped on requests.
+ * This field is only used by client-side instances of connection structures.
+ * \li struct rx service *service - A pointer to the service structure
+ * associated with this connection. This field is only used by server-side
+ * instances of connection structures.
+ * \li u long serial - Serial number of the next outgoing packet associated
+ * with this connection.
+ * \li u long lastSerial - Serial number of the last packet received in
+ * association with this connection. This field is used in computing packet
+ * skew.
+ * \li u short secondsUntilDead - Maximum numer of seconds of silence that
+ * should be tolerated from the connection's peer before calls will be
+ * terminated with an RX CALL DEAD error.
+ * \li u char secondsUntilPing - The number of seconds between "pings"
+ * (keep-alive probes) when at least one call is active on this connection.
+ * \li u char securityIndex - The index of the security object being used by
+ * this connection. This number selects a slot in the security class array
+ * maintained by the service associated with the connection.
+ * \li long error - Records the latest error code for calls occurring on this
+ * connection.
+ * \li struct rx securityClass *securityObject - A pointer to the security
+ * object used by this connection. This should coincide with the slot value
+ * chosen by the securityIndex field described above.
+ * \li VOID *securityData - A pointer to a region dedicated to hosting any
+ * storage required by the security object being used by this connection.
+ * \li u short securityHeaderSize - The length in bytes of the portion of the
+ * packet header before the user's data that contains the security module's
+ * information.
+ * \li u short securityMaxTrailerSize - The length in bytes of the packet
+ * trailer, appearing after the user's data, as mandated by the connection's
+ * security module.
+ * \li struct rxevent *challengeEvent -Pointer to an event that is scheduled
+ * when the server side of the connection is challenging the client to
+ * authenticate itself.
+ * \li int lastSendTime - The last time a packet was sent on this connection.
+ * \li long maxSerial - The largest serial number seen on incoming packets.
+ * \li u short hardDeadTime - The maximum number of seconds that any call on
+ * this connection may execute. This serves to throttle runaway calls.
+ *
+ * \subsubsection sec5-3-2-3 Section 5.3.2.3: struct rx peer
+ *
+ * \par
+ * For each connection, Rx maintains information describing the entity, or
+ * peer, on the other side of the wire. A peer is identified by a (host,
+ * UDP-port) pair. Included in the information kept on this remote
+ * communication endpoint are such network parameters as the maximum packet
+ * size supported by the host, current readings on round trip time to
+ * retransmission delays, and packet skew (see Section 1.2.7). There are also
+ * congestion control fields, ranging from descriptions of the maximum number
+ * of packets that may be sent to the peer without pausing and retransmission
+ * statistics. Peer structures are shared between connections whenever
+ * possible, and hence are reference-counted. A peer object may be
+ * garbage-collected if it is not actively referenced by any connection
+ * structure and a sufficient period of time has lapsed since the reference
+ * count dropped to zero.
+ * \par
+ * \b fields
+ * \li struct rx peer *next - Use to access internal lists.
+ * \li u long host - Remote IP address, in network byte order
+ * \li u short port - Remote UDP port, in network byte order
+ * \li short packetSize - Maximum packet size for this host, if known.
+ * \li u long idleWhen - When the refCount reference count field (see below)
+ * went to zero.
+ * \li short refCount - Reference count for this structure
+ * \li u char burstSize - Reinitialization size for the burst field (below).
+ * \li u char burst - Number of packets that can be transmitted immediately
+ * without pausing.
+ * \li struct clock burstWait - Time delay until new burst aimed at this peer
+ * is allowed.
+ * \li struct queue congestionQueue - Queue of RPC call descriptors that are
+ * waiting for a non-zero burst value.
+ * \li int rtt - Round trip time to the peer, measured in milliseconds.
+ * \li struct clock timeout - Current retransmission delay to the peer.
+ * \li int nSent - Total number of distinct data packets sent, not including
+ * retransmissions.
+ * \li int reSends - Total number of retransmissions for this peer since the
+ * peer structure instance was created.
+ * \li u long inPacketSkew - Maximum skew on incoming packets (see Section
+ * 1.2.7)
+ * \li u long outPacketSkew - Peer-reported maximum skew on outgoing packets
+ * (see Section 1.2.7).
+ *
+ * \subsubsection sec5-3-2-4 Section 5.3.2.4: struct rx call
+ *
+ * \par
+ * This structure records the state of an active call proceeding on a given Rx
+ * connection. As described above, each connection may have up to RX MAXCALLS
+ * calls active at any one instant, and thus each connection maintains an array
+ * of RX MAXCALLS rx call structures. The information contained here is
+ * specific to the given call; "permanent" call state, such as the call number,
+ * is maintained in the connection structure itself.
+ * \par
+ * \b fields
+ * \li struct queue queue item header - Queueing information for this
+ * structure.
+ * \li struct queue tq - Queue of outgoing ("transmit") packets.
+ * \li struct queue rq - Queue of incoming ("receive") packets.
+ * \li char *bufPtr - Pointer to the next byte to fill or read in the call's
+ * current packet, depending on whether it is being transmitted or received.
+ * \li u short nLeft - Number of bytes left to read in the first packet in the
+ * reception queue (see field rq).
+ * \li u short nFree - Number of bytes still free in the last packet in the
+ * transmission queue (see field tq).
+ * \li struct rx packet *currentPacket - Pointer to the current packet being
+ * assembled or read.
+ * \li struct rx connection *conn - Pointer to the parent connection for this
+ * call.
+ * \li u long *callNumber - Pointer to call number field within the call's
+ * current packet.
+ * \li u char channel - Index within the parent connection's call array that
+ * describes this call.
+ * \li u char dummy1, dummy2 - These are spare fields, reserved for future use.
+ * \li u char state - Current call state. The associated bit definitions appear
+ * in Section 5.2.7.
+ * \li u char mode - Current mode of a call that is in RX STATE ACTIVE state.
+ * The associated bit definitions appear in Section 5.2.8.
+ * \li u char flags - Flags pertaining to the state of the given call. The
+ * associated bit definitions appear in Section 5.2.7.
+ * \li u char localStatus - Local user status information, sent out of band.
+ * This field is currently not in use, set to zero.
+ * \li u char remoteStatus - Remote user status information, received out of
+ * band. This field is currently not in use, set to zero.
+ * \li long error - Error condition for this call.
+ * \li u long timeout - High level timeout for this call
+ * \li u long rnext - Next packet sequence number expected to be received.
+ * \li u long rprev - Sequence number of the previous packet received. This
+ * number is used to decide the proper sequence number for the next packet to
+ * arrive, and may be used to generate a negative acknowledgement.
+ * \li u long rwind - Width of the packet receive window for this call. The
+ * peer must not send packets with sequence numbers greater than or equal to
+ * rnext + rwind.
+ * \li u long tfirst - Sequence number of the first unacknowledged transmit
+ * packet for this call.
+ * \li u long tnext - Next sequence number to use for an outgoing packet.
+ * \li u long twind - Width of the packet transmit window for this call. Rx
+ * cannot assign a sequence number to an outgoing packet greater than or equal
+ * to tfirst + twind.
+ * \li struct rxevent *resendEvent - Pointer to a pending retransmission event,
+ * if any.
+ * \li struct rxevent *timeoutEvent - Pointer to a pending timeout event, if
+ * any.
+ * \li struct rxevent *keepAliveEvent - Pointer to a pending keep-alive event,
+ * if this is an active call.
+ * \li struct rxevent *delayedAckEvent - Pointer to a pending delayed
+ * acknowledgement packet event, if any. Transmission of a delayed
+ * acknowledgement packet is scheduled after all outgoing packets for a call
+ * have been sent. If neither a reply nor a new call are received by the time
+ * the delayedAckEvent activates, the ack packet will be sent.
+ * \li int lastSendTime - Last time a packet was sent for this call.
+ * \li int lastReceiveTime - Last time a packet was received for this call.
+ * \li VOID (*arrivalProc)() - Pointer to the procedure to call when reply is
+ * received.
+ * \li VOID *arrivalProcHandle - Pointer to the handle to pass to the
+ * arrivalProc as its first argument.
+ * \li VOID *arrivalProcArg - Pointer to an additional argument to pass to the
+ * given arrivalProc.
+ * \li u long lastAcked - Sequence number of the last packet "hard-acked" by
+ * the receiver. A packet is considered to be hard-acked if an acknowledgement
+ * is generated after the reader has processed it. The Rx facility may
+ * sometimes "soft-ack" a windowfull of packets before they have been picked up
+ * by the receiver.
+ * \li u long startTime - The time this call started running.
+ * \li u long startWait - The time that a server began waiting for input data
+ * or send quota.
+ *
+ * \subsection sec5-3-3 Section 5.3.3: Packet Formats
+ *
+ * \par
+ * The following sections cover the different data formats employed by the
+ * suite of Rx packet types, as enumerated in Section 5.2.11. A description of
+ * the most commonly-employed Rx packet header appears first, immediately
+ * followed by a description of the generic packet container and descriptor.
+ * The formats for Rx acknowledgement packets and debugging/statistics packets
+ * are also examined.
+ *
+ * \subsubsection sec5-3-3-1 Section 5.3.3.1: struct rx header
+ *
+ * \par
+ * Every Rx packet has its own header region, physically located after the
+ * leading IP/UDP headers. This header contains connection, call, security, and
+ * sequencing information. Along with a type identifier, these fields allow the
+ * receiver to properly interpret the packet. In addition, every client relates
+ * its "epoch", or Rx incarnation date, in each packet. This assists in
+ * identifying protocol problems arising from reuse of connection identifiers
+ * due to a client restart. Also included in the header is a byte of
+ * user-defined status information, allowing out-of-band channel of
+ * communication for the higher-level application using Rx as a transport
+ * mechanism.
+ * \par
+ * \b fields
+ * \li u long epoch - Birth time of the client Rx facility.
+ * \li u long cid - Connection identifier, as defined by the client. The last
+ * RX CIDSHIFT bits in the cid field identify which of the server-side RX
+ * MAXCALLS call channels is to receive the packet.
+ * \li u long callNumber - The current call number on the chosen call channel.
+ * \li u long seq - Sequence number of this packet. Sequence numbers start with
+ * 0 for each new Rx call.
+ * \li u long serial - This packet's serial number. A new serial number is
+ * stamped on each packet transmitted (or retransmitted).
+ * \li u char type - What type of Rx packet this is; see Section 5.2.11 for the
+ * list of legal definitions.
+ * \li u char flags - Flags describing this packet; see Section 5.2.9 for the
+ * list of legal settings.
+ * \li u char userStatus - User-defined status information, uninterpreted by
+ * the Rx facility itself. This field may be easily set or retrieved from Rx
+ * packets via calls to the rx GetLocalStatus(), rx SetLocalStatus(), rx
+ * GetRemoteStatus(), and rx SetRemoteStatus() macros.
+ * \li u char securityIndex - Index in the associated server-side service class
+ * of the security object used by this call.
+ * \li u short serviceId - The server-provided service ID to which this packet
+ * is directed.
+ * \li u short spare - This field was originally a true spare, but is now used
+ * by the built-in rxkad security module for packet header checksums. See the
+ * descriptions of the related rx IsUsingPktChecksum(), rx GetPacketCksum(),
+ * and rx SetPacketCksum() macros.
+ *
+ * \subsubsection sec5-3-3-2 Section 5.3.3.2: struct rx packet
+ *
+ * \par
+ * This structure is used to describe an Rx packet, and includes the wire
+ * version of the packet contents, where all fields exist in network byte
+ * order. It also includes acknowledgement, length, type, and queueing
+ * information.
+ * \par
+ * \b fields
+ * \li struct queue queueItemHeader - field used for internal queueing.
+ * \li u char acked - If non-zero, this field indicates that this packet has
+ * been tentatively (soft-) acknowledged. Thus, the packet has been accepted by
+ * the rx peer entity on the other side of the connection, but has not yet
+ * necessarily been passed to the true reader. The sender is not free to throw
+ * the packet away, as it might still get dropped by the peer before it is
+ * delivered to its destination process.
+ * \li short length - Length in bytes of the user data section.
+ * \li u char packetType - The type of Rx packet described by this record. The
+ * set of legal choices is available in Section 5.2.11.
+ * \li struct clock retryTime - The time when this packet should be
+ * retransmitted next.
+ * \li struct clock timeSent - The last time this packet was transmitted.
+ * \li struct rx header header - A copy of the internal Rx packet header.
+ * \li wire - The text of the packet as it appears on the wire. This structure
+ * has the following sub-fields:
+ * \li u long head[RX HEADER SIZE/sizeof(long)] The wire-level contents of
+ * IP, UDP, and Rx headers.
+ * \li u long data[RX MAX PACKET DATA SIZE/sizeof(long)] The wire form of
+ * the packet's "payload", namely the user data it carries.
+ *
+ * \subsubsection sec5-3-3-3 Section 5.3.3.3: struct rx ackPacket
+ *
+ * \par
+ * This is the format for the data portion of an Rx acknowledgement packet,
+ * used to inform a peer entity performing packet transmissions that a subset
+ * of its packets has been properly received.
+ * \par
+ * \b fields
+ * \li u short bufferSpace - Number of packet buffers available. Specifically,
+ * the number of packet buffers that the ack packet's sender is willing to
+ * provide for data on this or subsequent calls. This number does not have to
+ * fully accurate; it is acceptable for the sender to provide an estimate.
+ * \li u short maxSkew - The maximum difference seen between the serial number
+ * of the packet being acknowledged and highest packet yet received. This is an
+ * indication of the degree to which packets are arriving out of order at the
+ * receiver.
+ * \li u long firstPacket - The serial number of the first packet in the list
+ * of acknowledged packets, as represented by the acks field below.
+ * \li u long previousPacket - The previous packet serial number received.
+ * \li u long serial - The serial number of the packet prompted the
+ * acknowledgement.
+ * \li u char reason - The reason given for the acknowledgement; legal values
+ * for this field are described in Section 5.2.13.
+ * \li u char nAcks - Number of acknowledgements active in the acks array
+ * immediately following.
+ * \li u char acks[RX MAXACKS] - Up to RX MAXACKS packet acknowledgements. The
+ * legal values for each slot in the acks array are described in Section
+ * 5.2.14. Basically, these fields indicate either positive or negative
+ * acknowledgements.
+ *
+ * \par
+ * All packets with serial numbers prior to firstPacket are implicitly
+ * acknowledged by this packet, indicating that they have been fully processed
+ * by the receiver. Thus, the sender need no longer be concerned about them,
+ * and may release all of the resources that they occupy. Packets with serial
+ * numbers firstPacket + nAcks and higher are not acknowledged by this ack
+ * packet. Packets with serial numbers in the range [firstPacket, firstPacket +
+ * nAcks) are explicitly acknowledged, yet their sender-side resources must not
+ * yet be released, as there is yet no guarantee that the receiver will not
+ * throw them away before they can be processed there.
+ * \par
+ * There are some details of importance to be noted. For one, receiving a
+ * positive acknowlegement via the acks array does not imply that the
+ * associated packet is immune from being dropped before it is read and
+ * processed by the receiving entity. It does, however, imply that the sender
+ * should stop retransmitting the packet until further notice. Also, arrival of
+ * an ack packet should prompt the transmitter to immediately retransmit all
+ * packets it holds that have not been explicitly acknowledged and that were
+ * last transmitted with a serial number less than the highest serial number
+ * acknowledged by the acks array.
+ * Note: The fields in this structure are always kept in wire format, namely in
+ * network byte order.
+ *
+ * \subsection sec5-3-4 Section 5.3.4: Debugging and Statistics
+ *
+ * \par
+ * The following structures are defined in support of the debugging and
+ * statistics-gathering interfaces provided by Rx.
+ *
+ * \subsubsection sec5-3-4-1 Section 5.3.4.1: struct rx stats
+ *
+ * \par
+ * This structure maintains Rx statistics, and is gathered by such tools as the
+ * rxdebug program. It must be possible for all of the fields placed in this
+ * structure to be successfully converted from their on-wire network byte
+ * orderings to the host-specific ordering.
+ * \par
+ * \b fields
+ * \li int packetRequests - Number of packet allocation requests processed.
+ * \li int noPackets[RX N PACKET CLASSES] - Number of failed packet requests,
+ * organized per allocation class.
+ * \li int socketGreedy - Whether the SO GREEDY setting succeeded for the Rx
+ * socket.
+ * \li int bogusPacketOnRead - Number of inappropriately short packets
+ * received.
+ * \li int bogusHost - Contains the host address from the last bogus packet
+ * received.
+ * \li int noPacketOnRead - Number of attempts to read a packet off the wire
+ * when there was actually no packet there.
+ * \li int noPacketBuffersOnRead - Number of dropped data packets due to lack
+ * of packet buffers.
+ * \li int selects - Number of selects waiting for a packet arrival or a
+ * timeout.
+ * \li int sendSelects - Number of selects forced when sending packets.
+ * \li int packetsRead[RX N PACKET TYPES] - Total number of packets read,
+ * classified by type.
+ * \li int dataPacketsRead - Number of unique data packets read off the wire.
+ * \li int ackPacketsRead - Number of ack packets read.
+ * \li int dupPacketsRead - Number of duplicate data packets read.
+ * \li int spuriousPacketsRead - Number of inappropriate data packets.
+ * \li int packetsSent[RX N PACKET TYPES] - Number of packet transmissions,
+ * broken down by packet type.
+ * \li int ackPacketsSent - Number of ack packets sent.
+ * \li int pingPacketsSent - Number of ping packets sent.
+ * \li int abortPacketsSent - Number of abort packets sent.
+ * \li int busyPacketsSent - Number of busy packets sent.
+ * \li int dataPacketsSent - Number of unique data packets sent.
+ * \li int dataPacketsReSent - Number of retransmissions.
+ * \li int dataPacketsPushed - Number of retransmissions pushed early by a
+ * negative acknowledgement.
+ * \li int ignoreAckedPacket - Number of packets not retransmitted because they
+ * have already been acked.
+ * \li int struct clock totalRtt - Total round trip time measured for packets,
+ * used to compute average time figure.
+ * \li struct clock minRtt - Minimum round trip time measured for packets.
+ * struct clock maxRtt - Maximum round trip time measured for packets.
+ * \li int nRttSamples - Number of round trip samples.
+ * \li int nServerConns - Number of server connections.
+ * \li int nClientConns - Number of client connections.
+ * \li int nPeerStructs - Number of peer structures.
+ * \li int nCallStructs - Number of call structures physically allocated (using
+ * the internal storage allocator routine).
+ * \li int nFreeCallStructs - Number of call structures which were pulled from
+ * the free queue, thus avoiding a call to the internal storage allocator
+ * routine.
+ * \li int spares[10] - Ten integer spare fields, reserved for future use.
+ *
+ * \subsubsection sec5-3-4-2 Section 5.3.4.2: struct rx debugIn
+ *
+ * \par
+ * This structure defines the data format for a packet requesting one of the
+ * statistics collections maintained by Rx.
+ * \par
+ * \b fields
+ * \li long type - The specific data collection that the caller desires. Legal
+ * settings for this field are described in Section 5.2.16.2.
+ * \li long index - This field is only used when gathering information on Rx
+ * connections. Choose the index of the server-side connection record of which
+ * we are inquiring. This field may be used as an iterator, stepping through
+ * all the connection records, one per debugging request, until they have all
+ * been examined.
+ *
+ * \subsubsection sec5-3-4-3 Section 5.3.4.3: struct rx debugStats
+ *
+ * \par
+ * This structure describes the data format for a reply to an RX DEBUGI
+ * GETSTATS debugging request packet. These fields are given values indicating
+ * the current state of the Rx facility.
+ * \par
+ * \b fields
+ * \li long nFreePackets - Number of packet buffers currently assigned to the
+ * free pool.
+ * \li long packetReclaims - Currently unused.
+ * \li long callsExecuted - Number of calls executed since the Rx facility was
+ * initialized.
+ * \li char waitingForPackets - Is Rx currently blocked waiting for a packet
+ * buffer to come free?
+ * \li char usedFDs - If the Rx facility is executing in the kernel, return the
+ * number of unix file descriptors in use. This number is not directly related
+ * to the Rx package, but rather describes the state of the machine on which Rx
+ * is running.
+ * \li char version - Version number of the debugging package.
+ * \li char spare1[1] - Byte spare, reserved for future use.
+ * \li long spare2[10] - Set of 10 longword spares, reserved for future use.
+ *
+ * \subsubsection sec5-3-4-4 Section 5.3.4.4: struct rx debugConn
+ *
+ * \par
+ * This structure defines the data format returned when a caller requests
+ * information concerning an Rx connection. Thus, rx debugConn defines the
+ * external packaging of interest to external parties. Most of these fields are
+ * set from the rx connection structure, as defined in Section 5.3.2.2, and
+ * others are obtained by indirecting through such objects as the connection's
+ * peer and call structures.
+ * \par
+ * \b fields
+ * \li long host - Address of the host identified by the connection's peer
+ * structure.
+ * \li long cid - The connection ID.
+ * \li long serial - The serial number of the next outgoing packet associated
+ * with this connection.
+ * \li long callNumber[RX MAXCALLS] - The current call numbers for the
+ * individual call channels on this connection.
+ * \li long error - Records the latest error code for calls occurring on this
+ * connection.
+ * \li short port - UDP port associated with the connection's peer.
+ * \li char flags - State of the connection; see Section 5.2.4 for individual
+ * bit definitions.
+ * \li char type - Whether the connection is a server-side or client-side one.
+ * See Section 5.2.5 for individual bit definitions.
+ * \li char securityIndex - Index in the associated server-side service class
+ * of the security object being used by this call.
+ * \li char sparec[3] - Used to force alignment for later fields.
+ * \li char callState[RX MAXCALLS] - Current call state on each call channel.
+ * The associated bit definitions appear in Section 5.2.7.
+ * \li char callMode[RX MAXCALLS] - Current mode of all call channels that are
+ * in RX STATE ACTIVE state. The associated bit definitions appear in Section
+ * 5.2.8.
+ * \li char callFlags[RX MAXCALLS] - Flags pertaining to the state of each of
+ * the connection's call channels. The associated bit definitions appear in
+ * Section 5.2.7.
+ * \li char callOther[RX MAXCALLS] - Flag field for each call channel, where
+ * the presence of the RX OTHER IN flag indicates that there are packets
+ * present on the given call's reception queue, and the RX OTHER OUT flag
+ * indicates the presence of packets on the transmission queue.
+ * \li struct rx securityObjectStats secStats - The contents of the statistics
+ * related to the security object selected by the securityIndex field, if any.
+ * \li long epoch - The connection's client-side incarnation time.
+ * \li long sparel[10] - A set of 10 longword fields, reserved for future use.
+ *
+ * \subsubsection sec5-3-4-5 Section 5.3.4.5: struct rx debugConn vL
+ *
+ * \par
+ * This structure is identical to rx debugConn defined above, except for the
+ * fact that it is missing the sparec field. This sparec field is used in rx
+ * debugConn to fix an alignment problem that was discovered in version L of
+ * the debugging/statistics interface (hence the trailing "tt vL tag in the
+ * structure name). This alignment problem is fixed in version M, which
+ * utilizes and exports the rx debugConn structure exclusively. Information
+ * regarding the range of version-numbering values for the Rx
+ * debugging/statistics interface may be found in Section 5.2.16.1.
+ * \section sec5-4 Section 5.4: Exported Variables
+ *
+ * \par
+ * This section describes the set of variables that the Rx facility exports to
+ * its applications. Some of these variables have macros defined for the sole
+ * purpose of providing the caller with a convenient way to manipulate them.
+ * Note that some of these exported variables are never meant to be altered by
+ * application code (e.g., rx nPackets).
+ *
+ * \subsection sec5-4-1 Section 5.4.1: rx connDeadTime
+ *
+ * \par
+ * This integer-valued variable determines the maximum number of seconds that a
+ * connection may remain completely inactive, without receiving packets of any
+ * kind, before it is eligible for garbage collection. Its initial value is 12
+ * seconds. The rx SetRxDeadTime macro sets the value of this variable.
+ *
+ * \subsection sec5-4-2 Section 5.4.2: rx idleConnectionTime
+ *
+ * \par
+ * This integer-valued variable determines the maximum number of seconds that a
+ * server connection may "idle" (i.e., not have any active calls and otherwise
+ * not have sent a packet) before becoming eligible for garbage collection. Its
+ * initial value is 60 seconds.
+ *
+ * \subsection sec5-4-3 Section 5.4.3: rx idlePeerTime
+ *
+ * \par
+ * This integer-valued variable determines the maximum number of seconds that
+ * an Rx peer structure is allowed to exist without any connection structures
+ * referencing it before becoming eligible for garbage collection. Its initial
+ * value is 60 seconds.
+ *
+ * \subsection sec5-4-4 Section 5.4.4: rx extraQuota
+ *
+ * \par
+ * This integer-valued variable is part of the Rx packet quota system (see
+ * Section 1.2.6), which is used to avoid system deadlock. This ensures that
+ * each server-side thread has a minimum number of packets at its disposal,
+ * allowing it to continue making progress on active calls. This particular
+ * variable records how many extra data packets a user has requested be
+ * allocated. Its initial value is 0.
+ *
+ * \subsection sec5-4-5 Section 5.4.5: rx extraPackets
+ *
+ * \par
+ * This integer-valued variable records how many additional packet buffers are
+ * to be created for each Rx server thread. The caller, upon setting this
+ * variable, is applying some application-specific knowledge of the level of
+ * network activity expected. The rx extraPackets variable is used to compute
+ * the overall number of packet buffers to reserve per server thread, namely rx
+ * nPackets, described below. The initial value is 32 packets.
+ *
+ * \subsection sec5-4-6 Section 5.4.6: rx nPackets
+ *
+ * \par
+ * This integer-valued variable records the total number of packet buffers to
+ * be allocated per Rx server thread. It takes into account the quota packet
+ * buffers and the extra buffers requested by the caller, if any.
+ * \note This variable should never be set directly; the Rx facility itself
+ * computes its value. Setting it incorrectly may result in the service
+ * becoming deadlocked due to insufficient resources. Callers wishing to
+ * allocate more packet buffers to their server threads should indicate that
+ * desire by setting the rx extraPackets variable described above.
+ *
+ * \subsection sec5-4-7 Section 5.4.7: rx nFreePackets
+ *
+ * \par
+ * This integer-valued variable records the number of Rx packet buffers not
+ * currently used by any call. These unused buffers are collected into a free
+ * pool.
+ *
+ * \subsection sec5-4-8 Section 5.4.8: rx stackSize
+ *
+ * \par
+ * This integer-valued variable records the size in bytes for the lightweight
+ * process stack. The variable is initially set to RX DEFAULT STACK SIZE, and
+ * is typically manipulated via the rx SetStackSize() macro.
+ *
+ * \subsection sec5-4-9 Section 5.4.9: rx packetTypes
+ *
+ * \par
+ * This variable holds an array of string names used to describe the different
+ * roles for Rx packets. Its value is derived from the RX PACKET TYPES
+ * definition found in Section 5.2.11.
+ *
+ * \subsection sec5-4-10 Section 5.4.10: rx stats
+ *
+ * \par
+ * This variable contains the statistics structure that keeps track of Rx
+ * statistics. The struct rx stats structure it provides is defined in Section
+ * 5.3.4.1.
+ *
+ * \section sec5-5 Section 5.5: Macros
+ *
+ * \par
+ * Rx uses many macro definitions in preference to calling C functions
+ * directly. There are two main reasons for doing this:
+ * \li field selection: Many Rx operations are easily realized by returning the
+ * value of a particular structure's field. It is wasteful to invoke a C
+ * routine to simply fetch a structure's field, incurring unnecessary function
+ * call overhead. Yet, a convenient, procedure-oriented operation is still
+ * provided to Rx clients for such operations by the use of macros. For
+ * example, the rx ConnectionOf() macro, described in Section 5.5.1.1, simply
+ * indirects through the Rx call structure pointer parameter to deliver the
+ * conn field.
+ * \li Performance optimization: In some cases, a simple test or operation can
+ * be performed to accomplish a particular task. When this simple,
+ * straightforward operation fails, then a true C routine may be called to
+ * handle to more complex (and rarer) situation. The Rx macro rx Write(),
+ * described in Section 5.5.6.2, is a perfect example of this type of
+ * optimization. Invoking rx Write() first checks to determine whether or not
+ * the outgoing call's internal buffer has enough room to accept the specified
+ * data bytes. If so, it copies them into the call's buffer, updating counts
+ * and pointers as appropriate. Otherwise, rx Write() calls the rx WriteProc()
+ * to do the work, which in this more complicated case involves packet
+ * manipulations, dispatches, and allocations. The result is that the common,
+ * simple cases are often handled in-line, with more complex (and rarer) cases
+ * handled through true function invocations.
+ * \par
+ * The set of Rx macros is described according to the following categories.
+ * \li field selections/assignments
+ * \li Boolean operations
+ * \li Service attributes
+ * \li Security-related operations
+ * \li Sizing operations
+ * \li Complex operation
+ * \li Security operation invocations
+ *
+ * \subsection sec5-5-1 Section 5.5.1: field Selections/Assignments
+ *
+ * \par
+ * These macros facilitate the fetching and setting of fields from the
+ * structures described Chapter 5.3.
+ *
+ * \subsubsection sec5-5-1-1 Section 5.5.1.1: rx ConnectionOf()
+ *
+ * \par
+ * \#define rx_ConnectionOf(call) ((call)->conn)
+ * \par
+ * Generate a reference to the connection field within the given Rx call
+ * structure. The value supplied as the call argument must resolve into an
+ * object of type (struct rx call *). An application of the rx ConnectionOf()
+ * macro itself yields an object of type rx peer.
+ *
+ * \subsubsection sec5-5-1-2 Section 5.5.1.2: rx PeerOf()
+ *
+ * \par
+ * \#define rx_PeerOf(conn) ((conn)->peer)
+ * \par
+ * Generate a reference to the peer field within the given Rx call structure.
+ * The value supplied as the conn argument must resolve into an object of type
+ * (struct rx connection *). An instance of the rx PeerOf() macro itself
+ * resolves into an object of type rx peer.
+ *
+ * \subsubsection sec5-5-1-3 Section 5.5.1.3: rx HostOf()
+ *
+ * \par
+ * \#define rx_HostOf(peer) ((peer)->host)
+ * \par
+ * Generate a reference to the host field within the given Rx peer structure.
+ * The value supplied as the peer argument must resolve into an object of type
+ * (struct rx peer *). An instance of the rx HostOf() macro itself resolves
+ * into an object of type u long.
+ *
+ * \subsubsection sec5-5-1-4 Section 5.5.1.4: rx PortOf()
+ *
+ * \par
+ * \#define rx_PortOf(peer) ((peer)->port)
+ * \par
+ * Generate a reference to the port field within the given Rx peer structure.
+ * The value supplied as the peer argument must resolve into an object of type
+ * (struct rx peer *). An instance of the rx PortOf() macro itself resolves
+ * into an object of type u short.
+ *
+ * \subsubsection sec5-5-1-5 Section 5.5.1.5: rx GetLocalStatus()
+ *
+ * \par
+ * \#define rx_GetLocalStatus(call, status) ((call)->localStatus)
+ * \par
+ * Generate a reference to the localStatus field, which specifies the local
+ * user status sent out of band, within the given Rx call structure. The value
+ * supplied as the call argument must resolve into an object of type (struct rx
+ * call *). The second argument, status, is not used. An instance of the rx
+ * GetLocalStatus() macro itself resolves into an object of type u char.
+ *
+ * \subsubsection sec5-5-1-6 Section 5.5.1.6: rx SetLocalStatus()
+ *
+ * \par
+ * \#define rx_SetLocalStatus(call, status) ((call)->localStatus = (status))
+ * \par
+ * Assign the contents of the localStatus field, which specifies the local user
+ * status sent out of band, within the given Rx call structure. The value
+ * supplied as the call argument must resolve into an object of type (struct rx
+ * call *). The second argument, status, provides the new value of the
+ * localStatus field, and must resolve into an object of type u char. An
+ * instance of the rx GetLocalStatus() macro itself resolves into an object
+ * resulting from the assignment, namely the u char status parameter.
+ *
+ * \subsubsection sec5-5-1-7 Section 5.5.1.7: rx GetRemoteStatus()
+ *
+ * \par
+ * \#define rx_GetRemoteStatus(call) ((call)->remoteStatus)
+ * \par
+ * Generate a reference to the remoteStatus field, which specifies the remote
+ * user status received out of band, within the given Rx call structure. The
+ * value supplied as the call argument must resolve into an object of type
+ * (struct rx call *). An instance of the rx GetRemoteStatus() macro itself
+ * resolves into an object of type u char.
+ *
+ * \subsubsection sec5-5-1-8 Section 5.5.1.8: rx Error()
+ *
+ * \par
+ * \#define rx_Error(call) ((call)->error)
+ * \par
+ * Generate a reference to the error field, which specifies the current error
+ * condition, within the given Rx call structure. The value supplied as the
+ * call argument must resolve into an object of type (struct rx call *). An
+ * instance of the rx Error() macro itself resolves into an object of type
+ * long.
+ *
+ * \subsubsection sec5-5-1-9 Section 5.5.1.9: rx DataOf()
+ *
+ * \par
+ * \#define rx_DataOf(packet) ((char *) (packet)->wire.data)
+ * \par
+ * Generate a reference to the beginning of the data portion within the given
+ * Rx packet as it appears on the wire. Any encryption headers will be resident
+ * at this address. For Rx packets of type RX PACKET TYPE DATA, the actual user
+ * data will appear at the address returned by the rx DataOf macro plus the
+ * connection's security header size. The value supplied as the packet argument
+ * must resolve into an object of type (struct rx packet *). An instance of the
+ * rx DataOf() macro itself resolves into an object of type (u long *).
+ *
+ * \subsubsection sec5-5-1-10 Section 5.5.1.10: rx GetDataSize()
+ *
+ * \par
+ * \#define rx_GetDataSize(packet) ((packet)->length)
+ * \par
+ * Generate a reference to the length field, which specifies the number of
+ * bytes of user data contained within the wire form of the packet, within the
+ * given Rx packet description structure. The value supplied as the packet
+ * argument must resolve into an object of type (struct rx packet *). An
+ * instance of the rx GetDataSize() macro itself resolves into an object of
+ * type short.
+ *
+ * \subsubsection sec5-5-1-11 Section 5.5.1.11: rx SetDataSize()
+ *
+ * \par
+ * \#define rx_SetDataSize(packet, size) ((packet)->length = (size))
+ * \par
+ * Assign the contents of the length field, which specifies the number of bytes
+ * of user data contained within the wire form of the packet, within the given
+ * Rx packet description structure. The value supplied as the packet argument
+ * must resolve into an object of type (struct rx packet *). The second
+ * argument, size, provides the new value of the length field, and must resolve
+ * into an object of type short. An instance of the rx SetDataSize() macro
+ * itself resolves into an object resulting from the assignment, namely the
+ * short length parameter.
+ *
+ * \subsubsection sec5-5-1-12 Section 5.5.1.12: rx GetPacketCksum()
+ *
+ * \par
+ * \#define rx_GetPacketCksum(packet) ((packet)->header.spare)
+ * \par
+ * Generate a reference to the header checksum field, as used by the built-in
+ * rxkad security module (See Chapter 3), within the given Rx packet
+ * description structure. The value supplied as the packet argument must
+ * resolve into an object of type (struct rx packet *). An instance of the rx
+ * GetPacketCksum() macro itself resolves into an object of type u short.
+ *
+ * \subsubsection sec5-5-1-13 Section 5.5.1.13: rx SetPacketCksum()
+ *
+ * \par
+ * \#define rx_SetPacketCksum(packet, cksum) ((packet)->header.spare = (cksum))
+ * \par
+ * Assign the contents of the header checksum field, as used by the built-in
+ * rxkad security module (See Chapter 3), within the given Rx packet
+ * description structure. The value supplied as the packet argument must
+ * resolve into an object of type (struct rx packet *). The second argument,
+ * cksum, provides the new value of the checksum, and must resolve into an
+ * object of type u short. An instance of the rx SetPacketCksum() macro itself
+ * resolves into an object resulting from the assignment, namely the u short
+ * checksum parameter.
+ *
+ * \subsubsection sec5-5-1-14 Section 5.5.1.14: rx GetRock()
+ *
+ * \par
+ * \#define rx_GetRock(obj, type) ((type)(obj)->rock)
+ * \par
+ * Generate a reference to the field named rock within the object identified by
+ * the obj pointer. One common Rx structure to which this macro may be applied
+ * is struct rx connection. The specified rock field is casted to the value of
+ * the type parameter, which is the overall value of the rx GetRock() macro.
+ *
+ * \subsubsection sec5-5-1-15 Section 5.5.1.15: rx SetRock()
+ *
+ * \par
+ * \#define rx_SetRock(obj, newrock) ((obj)->rock = (VOID *)(newrock))
+ * \par
+ * Assign the contents of the newrock parameter into the rock field of the
+ * object pointed to by obj. The given object's rock field must be of type
+ * (VOID *). An instance of the rx SetRock() macro itself resolves into an
+ * object resulting from the assignment and is of type (VOID *).
+ *
+ * \subsubsection sec5-5-1-16 Section 5.5.1.16: rx SecurityClassOf()
+ *
+ * \par
+ * \#define rx_SecurityClassOf(conn) ((conn)->securityIndex)
+ * \par
+ * Generate a reference to the security index field of the given Rx connection
+ * description structure. This identifies the security class used by the
+ * connection. The value supplied as the conn argument must resolve into an
+ * object of type (struct rx connection *). An instance of the rx
+ * SecurityClassOf() macro itself resolves into an object of type u char.
+ *
+ * \subsubsection sec5-5-1-17 Section 5.5.1.17: rx SecurityObjectOf()
+ *
+ * \par
+ * \#define rx_SecurityObjectOf(conn) ((conn)->securityObject)
+ * \par
+ * Generate a reference to the security object in use by the given Rx
+ * connection description structure. The choice of security object determines
+ * the authentication protocol enforced by the connection. The value supplied
+ * as the conn argument must resolve into an object of type (struct rx
+ * connection *). An instance of the rx SecurityObjectOf() macro itself
+ * resolves into an object of type (struct rx securityClass *).
+ *
+ * \subsection sec5-5-2 Section 5.5.2: Boolean Operations
+ *
+ * \par
+ * The macros described in this section all return Boolean values. They are
+ * used to query such things as the whether a connection is a server-side or
+ * client-side one and if extra levels of checksumming are being used in Rx
+ * packet headers.
+ *
+ * \subsubsection sec5-5-2-1 Section 5.5.2.1: rx IsServerConn()
+ *
+ * \par
+ * \#define rx_IsServerConn(conn) ((conn)->type == RX_SERVER_CONNECTION)
+ * \par
+ * Determine whether or not the Rx connection specified by the conn argument is
+ * a server-side connection. The value supplied for conn must resolve to an
+ * object of type struct rx connection. The result is determined by testing
+ * whether or not the connection's type field is set to RX SERVER CONNECTION.
+ * \note Another macro, rx ServerConn(), performs the identical operation.
+ *
+ * \subsubsection sec5-5-2-2 Section 5.5.2.2: rx IsClientConn()
+ *
+ * \par
+ * \#define rx_IsClientConn(conn) ((conn)->type == RX_CLIENT_CONNECTION)
+ * \par
+ * Determine whether or not the Rx connection specified by the conn argument is
+ * a client-side connection. The value supplied for conn must resolve to an
+ * object of type struct rx connection. The result is determined by testing
+ * whether or not the connection's type field is set to RX CLIENT CONNECTION.
+ * \note Another macro, rx ClientConn(), performs the identical operation.
+ *
+ * \subsubsection sec5-5-2-3 Section 5.5.2.2: rx IsUsingPktCksum()
+ *
+ * \par
+ * \#define rx_IsUsingPktCksum(conn) ((conn)->flags &
+ * RX_CONN_USING_PACKET_CKSUM)
+ * \par
+ * Determine whether or not the Rx connection specified by the conn argument is
+ * checksum-ming the headers of all packets on its calls. The value supplied
+ * for conn must resolve to an object of type struct rx connection. The result
+ * is determined by testing whether or not the connection's flags field has the
+ * RX CONN USING PACKET CKSUM bit enabled.
+ *
+ * \subsection sec5-5-3 Section 5.5.3: Service Attributes
+ *
+ * \par
+ * This section describes user-callable macros that manipulate the attributes
+ * of an Rx service. Note that these macros must be called (and hence their
+ * operations performed) before the given service is installed via the
+ * appropriate invocation of the associated rx StartServer() function.
+ *
+ * \subsubsection sec5-5-3-1 Section 5.5.3.1: rx SetStackSize()
+ *
+ * \par
+ * rx_stackSize = (((stackSize) stackSize) > rx_stackSize) ? stackSize :
+ * rx_stackSize)
+ * \par
+ * Inform the Rx facility of the stack size in bytes for a class of threads to
+ * be created in support of Rx services. The exported rx stackSize variable
+ * tracks the high-water mark for all stack size requests before the call to rx
+ * StartServer(). If no calls to rx SetStackSize() are made, then rx stackSize
+ * will retain its default setting of RX DEFAULT STACK SIZE.
+ * \par
+ * In this macro, the first argument is not used. It was originally intended
+ * that thread stack sizes would be settable on a per-service basis. However,
+ * calls to rx SetStackSize() will ignore the service parameter and set the
+ * high-water mark for all Rx threads created after the use of rx
+ * SetStackSize(). The second argument, stackSize, specifies determines the new
+ * stack size, and should resolve to an object of type int. The value placed in
+ * the stackSize parameter will not be recorded in the global rx stackSize
+ * variable unless it is greater than the variable's current setting.
+ * \par
+ * An instance of the rx SetStackSize() macro itself resolves into the result
+ * of the assignment, which is an object of type int.
+ *
+ * \subsubsection sec5-5-3-2 Section 5.5.3.2: rx SetMinProcs()
+ *
+ * \par
+ * \#define rx_SetMinProcs(service, min) ((service)->minProcs = (min))
+ * \par
+ * Choose min as the minimum number of threads guaranteed to be available for
+ * parallel execution of the given Rx service. The service parameter should
+ * resolve to an object of type struct rx service. The min parameter should
+ * resolve to an object of type short. An instance of the rx SetMinProcs()
+ * macro itself resolves into the result of the assignment, which is an object
+ * of type short.
+ *
+ * \subsubsection sec5-5-3-3 Section 5.5.3.3: rx SetMaxProcs()
+ *
+ * \par
+ * \#define rx_SetMaxProcs(service, max) ((service)->maxProcs = (max))
+ * \par
+ * Limit the maximum number of threads that may be made available to the given
+ * Rx service for parallel execution to be max. The service parameter should
+ * resolve to an object of type struct rx service. The max parameter should
+ * resolve to an object of type short. An instance of the rx SetMaxProcs()
+ * macro itself resolves into the result of the assignment, which is an object
+ * of type short.
+ *
+ * \subsubsection sec5-5-3-4 Section 5.5.3.4: rx SetIdleDeadTime()
+ *
+ * \par
+ * \#define rx_SetIdleDeadTime(service, time) ((service)->idleDeadTime =
+ * (time))
+ * \par
+ * Every Rx service has a maximum amount of time it is willing to have its
+ * active calls sit idle (i.e., no new data is read or written for a call
+ * marked as RX STATE ACTIVE) before unilaterally shutting down the call. The
+ * expired call will have its error field set to RX CALL TIMEOUT. The operative
+ * assumption in this situation is that the client code is exhibiting a
+ * protocol error that prevents progress from being made on this call, and thus
+ * the call's resources on the server side should be freed. The default value,
+ * as recorded in the service's idleDeadTime field, is set at service creation
+ * time to be 60 seconds. The rx SetIdleTime() macro allows a caller to
+ * dynamically set this idle call timeout value.
+ * \par
+ * The service parameter should resolve to an object of type struct rx service.
+ * Also, the time parameter should resolve to an object of type short. finally,
+ * an instance of the rx SetIdleDeadTime() macro itself resolves into the
+ * result of the assignment, which is an object of type short.
+ *
+ * \subsubsection sec5-5-3-5 Section 5.5.3.5: rx SetServiceDeadTime()
+ *
+ * \par
+ * \#define rx_SetServiceDeadTime(service, seconds)
+ * ((service)->secondsUntilDead = (seconds))
+ * \note This macro definition is obsolete and should NOT be used. Including it
+ * in application code will generate a compile-time error, since the service
+ * structure no longer has such a field defined.
+ * \par
+ * See the description of the rx SetConnDeadTime() macro below to see how hard
+ * timeouts may be set for situations of complete call inactivity.
+ *
+ * \subsubsection sec5-5-3-6 Section 5.5.3.6: rx SetRxDeadTime()
+ *
+ * \par
+ * \#define rx_SetRxDeadTime(seconds) (rx_connDeadTime = (seconds))
+ * \par
+ * Inform the Rx facility of the maximum number of seconds of complete
+ * inactivity that will be tolerated on an active call. The exported rx
+ * connDeadTime variable tracks this value, and is initialized to a value of 12
+ * seconds. The current value of rx connDeadTime will be copied into new Rx
+ * service and connection records upon their creation.
+ * \par
+ * The seconds argument determines the value of rx connDeadTime, and should
+ * resolve to an object of type int. An instance of the rx SetRxDeadTime()
+ * macro itself resolves into the result of the assignment, which is an object
+ * of type int.
+ *
+ * \subsubsection sec5-5-3-7 Section 5.5.3.7: rx SetConnDeadTime()
+ *
+ * \par
+ * \#define rx_SetConnDeadTime(conn, seconds) (rxi_SetConnDeadTime(conn,
+ * seconds))
+ * \par
+ * Every Rx connection has a maximum amount of time it is willing to have its
+ * active calls on a server connection sit without receiving packets of any
+ * kind from its peer. After such a quiescent time, during which neither data
+ * packets (regardless of whether they are properly sequenced or duplicates)
+ * nor keep-alive packets are received, the call's error field is set to RX
+ * CALL DEAD and the call is terminated. The operative assumption in this
+ * situation is that the client making the call has perished, and thus the
+ * call's resources on the server side should be freed. The default value, as
+ * recorded in the connection's secondsUntilDead field, is set at connection
+ * creation time to be the same as its parent service. The rx SetConnDeadTime()
+ * macro allows a caller to dynamically set this timeout value.
+ * \par
+ * The conn parameter should resolve to an object of type struct rx connection.
+ * Also, the seconds parameter should resolve to an object of type int.
+ * finally, an instance of the rx SetConnDeadTime() macro itself resolves into
+ * the a call to rxi SetConnDeadTime(), whose return value is void.
+ *
+ * \subsubsection sec5-5-3-8 Section 5.5.3.8: rx SetConnHardDeadTime()
+ *
+ * \par
+ * \#define rx_SetConnHardDeadTime(conn, seconds) ((conn)->hardDeadTime =
+ * (seconds))
+ * \par
+ * It is convenient to be able to specify that calls on certain Rx connections
+ * have a hard absolute timeout. This guards against protocol errors not caught
+ * by other checks in which one or both of the client and server are looping.
+ * The rx SetConnHardDeadTime() macro is available for this purpose. It will
+ * limit calls on the connection identified by the conn parameter to execution
+ * times of no more than the given number of seconds. By default, active calls
+ * on an Rx connection may proceed for an unbounded time, as long as they are
+ * not totally quiescent (see Section 5.5.3.7 for a description of the rx
+ * SetConnDeadTime()) or idle (see Section 5.5.3.4 for a description of the rx
+ * SetIdleDeadTime()).
+ * \par
+ * The conn parameter should resolve to an object of type (struct rx connection
+ * *). The seconds parameter should resolve to an object of type u short. An
+ * instance of the rx SetConnHardDeadTime() macro itself resolves into the
+ * result of the assignment, which is an object of type u short.
+ *
+ * \subsubsection sec5-5-3-9 Section 5.5.3.9: rx GetBeforeProc()
+ *
+ * \par
+ * \#define rx_GetBeforeProc(service) ((service)->beforeProc)
+ * \par
+ * Return a pointer of type (VOID *)() to the procedure associated with the
+ * given Rx service that will be called immediately upon activation of a server
+ * thread to handle an incoming call. The service parameter should resolve to
+ * an object of type struct rx service.
+ * \par
+ * When an Rx service is first created (via a call to the rx NewService()
+ * function), its beforeProc field is set to a null pointer. See the
+ * description of the rx SetBeforeProc() below.
+ *
+ * \subsubsection sec5-5-3-10 Section 5.5.3.10: rx SetBeforeProc()
+ *
+ * \par
+ * \#define rx_SetBeforeProc(service, proc) ((service)->beforeProc = (proc))
+ * \par
+ * Instruct the Rx facility to call the procedure identified by the proc
+ * parameter immediately upon activation of a server thread to handle an
+ * incoming call. The specified procedure will be called with a single
+ * parameter, a pointer of type struct rx call, identifying the call this
+ * thread will now be responsible for handling. The value returned by the
+ * procedure, if any, is discarded.
+ * \par
+ * The service parameter should resolve to an object of type struct rx service.
+ * The proc parameter should resolve to an object of type (VOID *)(). An
+ * instance of the rx SetBeforeProc() macro itself resolves into the result of
+ * the assignment, which is an object of type (VOID *)().
+ *
+ * \subsubsection sec5-5-3-11 Section 5.5.3.11: rx GetAfterProc()
+ *
+ * \par
+ * \#define rx_GetAfterProc(service) ((service)->afterProc)
+ * \par
+ * Return a pointer of type (VOID *)() to the procedure associated with the
+ * given Rx service that will be called immediately upon completion of the
+ * particular Rx call for which a server thread was activated. The service
+ * parameter should resolve to an object of type struct rx service.
+ * \par
+ * When an Rx service is first created (via a call to the rx NewService()
+ * function), its afterProc field is set to a null pointer. See the description
+ * of the rx SetAfterProc() below.
+ *
+ * \subsubsection sec5-5-3-12 Section 5.5.3.12: rx SetAfterProc()
+ *
+ * \par
+ * \#define rx_SetAfterProc(service, proc) ((service)->afterProc = (proc))
+ * \par
+ * Instruct the Rx facility to call the procedure identified by the proc
+ * parameter immediately upon completion of the particular Rx call for which a
+ * server thread was activated. The specified procedure will be called with a
+ * single parameter, a pointer of type struct rx call, identifying the call
+ * this thread just handled. The value returned by the procedure, if any, is
+ * discarded.
+ * \par
+ * The service parameter should resolve to an object of type struct rx service.
+ * The proc parameter should resolve to an object of type (VOID *)(). An
+ * instance of the rx SetAfterProc() macro itself resolves into the result of
+ * the assignment, which is an object of type (VOID *)().
+ *
+ * \subsubsection sec5-5-3-13 Section 5.5.3.13: rx SetNewConnProc()
+ *
+ * \par
+ * \#define rx_SetNewConnProc(service, proc) ((service)->newConnProc = (proc))
+ * \par
+ * Instruct the Rx facility to call the procedure identified by the proc
+ * parameter as the last step in the creation of a new Rx server-side
+ * connection for the given service. The specified procedure will be called
+ * with a single parameter, a pointer of type (struct rx connection *),
+ * identifying the connection structure that was just built. The value returned
+ * by the procedure, if any, is discarded.
+ * \par
+ * The service parameter should resolve to an object of type struct rx service.
+ * The proc parameter should resolve to an object of type (VOID *)(). An
+ * instance of the rx SetNewConnProc() macro itself resolves into the result of
+ * the assignment, which is an object of type (VOID *)().
+ * \note There is no access counterpart defined for this macro, namely one that
+ * returns the current setting of a service's newConnProc.
+ *
+ * \subsubsection sec5-5-3-14 Section 5.5.3.14: rx SetDestroyConnProc()
+ *
+ * \par
+ * \#define rx_SetDestroyConnProc(service, proc) ((service)->destroyConnProc =
+ * (proc))
+ * \par
+ * Instruct the Rx facility to call the procedure identified by the proc
+ * parameter just before a server connection associated with the given Rx
+ * service is destroyed. The specified procedure will be called with a single
+ * parameter, a pointer of type (struct rx connection *), identifying the
+ * connection about to be destroyed. The value returned by the procedure, if
+ * any, is discarded.
+ * \par
+ * The service parameter should resolve to an object of type struct rx service.
+ * The proc parameter should resolve to an object of type (VOID *)(). An
+ * instance of the rx SetDestroyConnProc() macro itself resolves into the
+ * result of the assignment, which is an object of type (VOID *)().
+ * \note There is no access counterpart defined for this macro, namely one that
+ * returns the current setting of a service's destroyConnProc.
+ *
+ * \subsection sec5-5-4 Section 5.5.4: Security-Related Operations
+ *
+ * \par
+ * The following macros are callable by Rx security modules, and assist in
+ * getting and setting header and trailer lengths, setting actual packet size,
+ * and finding the beginning of the security header (or data).
+ *
+ * \subsubsection sec5-5-4-1 Section 5.5.4.1: rx GetSecurityHeaderSize()
+ *
+ * \par
+ * \#define rx_GetSecurityHeaderSize(conn) ((conn)->securityHeaderSize)
+ * \par
+ * Generate a reference to the field in an Rx connection structure that records
+ * the length in bytes of the associated security module's packet header data.
+ * \par
+ * The conn parameter should resolve to an object of type struct rx connection.
+ * An instance of the rx GetSecurityHeaderSize() macro itself resolves into an
+ * object of type u short.
+ *
+ * \subsubsection sec5-5-4-2 Section 5.5.4.2: rx SetSecurityHeaderSize()
+ *
+ * \par
+ * \#define rx_SetSecurityHeaderSize(conn, length) ((conn)->securityHeaderSize
+ * = (length))
+ * \par
+ * Set the field in a connection structure that records the length in bytes of
+ * the associated security module's packet header data.
+ * \par
+ * The conn parameter should resolve to an object of type struct rx connection.
+ * The length parameter should resolve to an object of type u short. An
+ * instance of the rx SetSecurityHeaderSize() macro itself resolves into the
+ * result of the assignment, which is an object of type u short.
+ *
+ * \subsubsection sec5-5-4-3 Section 5.5.4.3: rx
+ * GetSecurityMaxTrailerSize()
+ *
+ * \par
+ * \#define rx_GetSecurityMaxTrailerSize(conn) ((conn)->securityMaxTrailerSize)
+ * \par
+ * Generate a reference to the field in an Rx connection structure that records
+ * the maximum length in bytes of the associated security module's packet
+ * trailer data.
+ * \par
+ * The conn parameter should resolve to an object of type struct rx connection.
+ * An instance of the rx GetSecurityMaxTrailerSize() macro itself resolves into
+ * an object of type u short.
+ *
+ * \subsubsection sec5-5-4-4 Section 5.5.4.4: rx
+ * SetSecurityMaxTrailerSize()
+ *
+ * \par
+ * \#define rx_SetSecurityMaxTrailerSize(conn, length)
+ * ((conn)->securityMaxTrailerSize = (length))
+ * \par
+ * Set the field in a connection structure that records the maximum length in
+ * bytes of the associated security module's packet trailer data.
+ * \par
+ * The conn parameter should resolve to an object of type struct rx connection.
+ * The length parameter should resolve to an object of type u short. An
+ * instance of the rx SetSecurityHeaderSize() macro itself resolves into the
+ * result of the assignment, which is an object of type u short.
+ *
+ * \subsection sec5-5-5 Section 5.5.5: Sizing Operations
+ *
+ * \par
+ * The macros described in this section assist the application programmer in
+ * determining the sizes of the various Rx packet regions, as well as their
+ * placement within a packet buffer.
+ *
+ * \subsubsection sec5-5-5-1 Section 5.5.5.1: rx UserDataOf()
+ *
+ * \par
+ * \#define rx_UserDataOf(conn, packet) (((char *) (packet)->wire.data) +
+ * (conn)->securityHeaderSize)
+ * \par
+ * Generate a pointer to the beginning of the actual user data in the given Rx
+ * packet, that is associated with the connection described by the conn
+ * pointer. User data appears immediately after the packet's security header
+ * region, whose length is determined by the security module used by the
+ * connection. The conn parameter should resolve to an object of type struct rx
+ * connection. The packet parameter should resolve to an object of type struct
+ * rx packet. An instance of the rx UserDataOf() macro itself resolves into an
+ * object of type (char *).
+ *
+ * \subsubsection sec5-5-5-2 Section 5.5.5.2: rx MaxUserDataSize()
+ *
+ * \par
+ * \#define rx_MaxUserDataSize(conn)
+ * \n ((conn)->peer->packetSize
+ * \n -RX_HEADER_SIZE
+ * \n -(conn)->securityHeaderSize
+ * \n -(conn)->securityMaxTrailerSize)
+ * \par
+ * Return the maximum number of user data bytes that may be carried by a packet
+ * on the Rx connection described by the conn pointer. The overall packet size
+ * is reduced by the IP, UDP, and Rx headers, as well as the header and trailer
+ * areas required by the connection's security module.
+ * \par
+ * The conn parameter should resolve to an object of type struct rx connection.
+ * An instance of the rx MaxUserDataSize() macro itself resolves into the an
+ * object of type (u short).
+ *
+ * \subsection sec5-5-6 Section 5.5.6: Complex Operations
+ *
+ * \par
+ * Two Rx macros are designed to handle potentially complex operations, namely
+ * reading data from an active incoming call and writing data to an active
+ * outgoing call. Each call structure has an internal buffer that is used to
+ * collect and cache data traveling through the call. This buffer is used in
+ * conjunction with reading or writing to the actual Rx packets traveling on
+ * the wire in support of the call. The rx Read() and rx Write() macros allow
+ * their caller to simply manipulate the internal data buffer associated with
+ * the Rx call structures whenever possible, thus avoiding the overhead
+ * associated with a function call. When buffers are either filled or drained
+ * (depending on the direction of the data flow), these macros will then call
+ * functions to handle the more complex cases of generating or receiving
+ * packets in support of the operation.
+ *
+ * \subsubsection sec5-5-6-1 Section 5.5.6.1: rx Read()
+ *
+ * \par
+ * \#define rx_Read(call, buf, nbytes)
+ * \n ((call)->nLeft > (nbytes) ?
+ * \n bcopy((call)->bufPtr, (buf), (nbytes)),
+ * \n (call)->nLeft -= (nbytes), (call)->bufPtr += (nbytes), (nbytes)
+ * \n : rx_ReadProc((call), (buf), (nbytes)))
+ * \par
+ * Read nbytes of data from the given Rx call into the buffer to which buf
+ * points. If the call's internal buffer has at least nbytes bytes already
+ * filled, then this is done in-line with a copy and some pointer and counter
+ * updates within the call structure. If the call's internal buffer doesn't
+ * have enough data to satisfy the request, then the rx ReadProc() function
+ * will handle this more complex situation.
+ * \par
+ * In either case, the rx Read() macro returns the number of bytes actually
+ * read from the call, resolving to an object of type int. If rx Read() returns
+ * fewer than nbytes bytes, the call status should be checked via the rx
+ * Error() macro.
+ *
+ * \subsubsection sec5-5-6-2 Section 5.5.6.2: rx Write()
+ *
+ * \par
+ * \#define rx_Write(call, buf, nbytes)
+ * \n ((call)->nFree > (nbytes) ?
+ * \n bcopy((buf), (call)->bufPtr, (nbytes)),
+ * \n (call)->nFree -= (nbytes),
+ * \n (call)->bufPtr += (nbytes), (nbytes)
+ * \n : rx_WriteProc((call), (buf), (nbytes)))
+ * \par
+ * Write nbytes of data from the buffer pointed to by buf into the given Rx
+ * call. If the call's internal buffer has at least nbytes bytes free, then
+ * this is done in-line with a copy and some pointer and counter updates within
+ * the call structure. If the call's internal buffer doesn't have room, then
+ * the rx WriteProc() function will handle this more complex situation.
+ * \par
+ * In either case, the rx Write() macro returns the number of bytes actually
+ * written to the call, resolving to an object of type int. If zero is
+ * returned, the call status should be checked via the rx Error() macro.
+ *
+ * \subsection sec5-5-7 Section 5.5.7: Security Operation Invocations
+ *
+ * \par
+ * Every Rx security module is required to implement an identically-named set
+ * of operations, through which the security mechanism it defines is invoked.
+ * This characteristic interface is reminiscent of the vnode interface defined
+ * and popularized for file systems by Sun Microsystems [4]. The structure
+ * defining this function array is described in Section 5.3.1.1.
+ * \par
+ * These security operations are part of the struct rx securityClass, which
+ * keeps not only the ops array itself but also any private data they require
+ * and a reference count. Every Rx service contains an array of these security
+ * class objects, specifying the range of security mechanisms it is capable of
+ * enforcing. Every Rx connection within a service is associated with exactly
+ * one of that service's security objects, and every call issued on the
+ * connection will execute the given security protocol.
+ * \par
+ * The macros described below facilitate the execution of the security module
+ * interface functions. They are covered in the same order they appear in the
+ * struct rx securityOps declaration.
+ *
+ * \subsubsection sec5-5-7-1 Section 5.5.7.1: RXS OP()
+ *
+ * \code
+ * #if defined(__STDC__) && !defined(__HIGHC__)
+ * #define RXS_OP(obj, op, args)
+ * ((obj->ops->op_ ## op) ? (*(obj)->ops->op_ ## op)args : 0)
+ * #else
+ * #define RXS_OP(obj, op, args)
+ * ((obj->ops->op_op) ? (*(obj)->ops->op_op)args : 0)
+ * #endif
+ * \endcode
+ *
+ * \par
+ * The RXS OP macro represents the workhorse macro in this group, used by all
+ * the others. It takes three arguments, the first of which is a pointer to the
+ * security object to be referenced. This obj parameter must resolve to an
+ * object of type (struct rx securityOps *). The second parameter identifies
+ * the specific op to be performed on this security object. The actual text of
+ * this op argument is used to name the desired opcode function. The third and
+ * final argument, args, specifies the text of the argument list to be fed to
+ * the chosen security function. Note that this argument must contain the
+ * bracketing parentheses for the function call's arguments. In fact, note that
+ * each of the security function access macros defined below provides the
+ * enclosing parentheses to this third RXS OP() macro.
+ *
+ * \subsubsection sec5-5-7-2 Section 5.5.7.1: RXS Close()
+ *
+ * \par
+ * \#define RXS_Close(obj) RXS_OP(obj, Close, (obj))
+ * \par
+ * This macro causes the execution of the interface routine occupying the op
+ * Close() slot in the Rx security object identified by the obj pointer. This
+ * interface function is invoked by Rx immediately before a security object is
+ * discarded. Among the responsibilities of such a function might be
+ * decrementing the object's refCount field, and thus perhaps freeing up any
+ * space contained within the security object's private storage region,
+ * referenced by the object's privateData field.
+ * \par
+ * The obj parameter must resolve into an object of type (struct rx securityOps
+ * *). In generating a call to the security object's op Close() routine, the
+ * obj pointer is used as its single parameter. An invocation of the RXS
+ * Close() macro results in a return value identical to that of the op Close()
+ * routine, namely a value of type int.
+ *
+ * \subsubsection sec5-5-7-3 Section 5.5.7.3: RXS NewConnection()
+ *
+ * \par
+ * \#define RXS_NewConnection(obj, conn) RXS_OP(obj, NewConnection, (obj,
+ * conn))
+ * \par
+ * This macro causes the execution of the interface routine in the op
+ * NewConnection() slot in the Rx security object identified by the obj
+ * pointer. This interface function is invoked by Rx immediately after a
+ * connection using the given security object is created. Among the
+ * responsibilities of such a function might be incrementing the object's
+ * refCount field, and setting any per-connection information based on the
+ * associated security object's private storage region, as referenced by the
+ * object's privateData field.
+ * \par
+ * The obj parameter must resolve into an object of type (struct rx securityOps
+ * *). The conn argument contains a pointer to the newly-created connection
+ * structure, and must resolve into an object of type (struct rx connection *).
+ * \par
+ * In generating a call to the routine located at the security object's op
+ * NewConnection() slot, the obj and conn pointers are used as its two
+ * parameters. An invocation of the RXS NewConnection() macro results in a
+ * return value identical to that of the op NewConnection() routine, namely a
+ * value of type int.
+ *
+ * \subsubsection sec5-5-7-4 Section 5.5.7.4: RXS PreparePacket()
+ *
+ * \par
+ * \#define RXS_PreparePacket(obj, call, packet)
+ * \n RXS_OP(obj, PreparePacket, (obj, call, packet))
+ * \par
+ * This macro causes the execution of the interface routine in the op
+ * PreparePacket() slot in the Rx security object identified by the obj
+ * pointer. This interface function is invoked by Rx each time it prepares an
+ * outward-bound packet. Among the responsibilities of such a function might be
+ * computing information to put into the packet's security header and/or
+ * trailer.
+ * \par
+ * The obj parameter must resolve into an object of type (struct rx securityOps
+ * *). The call argument contains a pointer to the Rx call to which the given
+ * packet belongs, and must resolve to an object of type (struct rx call *).
+ * The final argument, packet, contains a pointer to the packet itself. It
+ * should resolve to an object of type (struct rx packet *).
+ * \par
+ * In generating a call to the routine located at the security object's op
+ * PreparePacket() slot, the obj, call, and packet pointers are used as its
+ * three parameters. An invocation of the RXS PreparePacket() macro results in
+ * a return value identical to that of the op PreparePacket() routine, namely a
+ * value of type int.
+ *
+ * \subsubsection sec5-5-7-5 Section 5.5.7.5: RXS SendPacket()
+ *
+ * \par
+ * \#define RXS_SendPacket(obj, call, packet) RXS_OP(obj, SendPacket, (obj,
+ * call, packet))
+ * \par
+ * This macro causes the execution of the interface routine occupying the op
+ * SendPacket() slot in the Rx security object identified by the obj pointer.
+ * This interface function is invoked by Rx each time it physically transmits
+ * an outward-bound packet. Among the responsibilities of such a function might
+ * be recomputing information in the packet's security header and/or trailer.
+ * \par
+ * The obj parameter must resolve into an object of type (struct rx securityOps
+ * *). The call argument contains a pointer to the Rx call to which the given
+ * packet belongs, and must resolve to an object of type (struct rx call *).
+ * The final argument, packet, contains a pointer to the packet itself. It
+ * should resolve to an object of type (struct rx packet *).
+ * \par
+ * In generating a call to the routine located at the security object's op
+ * SendPacket() slot, the obj, call, and packet pointers are used as its three
+ * parameters. An invocation of the RXS SendPacket() macro results in a return
+ * value identical to that of the op SendPacket() routine, namely a value of
+ * type int.
+ *
+ * \subsubsection sec5-5-7-6 Section 5.5.7.6: RXS CheckAuthentication()
+ *
+ * \par
+ * \#define RXS_CheckAuthentication(obj, conn) RXS_OP(obj, CheckAuthentication,
+ * (obj, conn))
+ * \par
+ * This macro causes the execution of the interface routine in the op
+ * CheckAuthentication() slot in the Rx security object identified by the obj
+ * pointer. This interface function is invoked by Rx each time it needs to
+ * check whether the given connection is one on which authenticated calls are
+ * being performed. Specifically, a value of 0 is returned if authenticated
+ * calls are not being executed on this connection, and a value of 1 is
+ * returned if they are.
+ * \par
+ * The obj parameter must resolve into an object of type (struct rx securityOps
+ * *). The conn argument contains a pointer to the Rx connection checked as to
+ * whether authentication is being performed, and must resolve to an object of
+ * type (struct rx connection *).
+ * \par
+ * In generating a call to the routine in the security object's op
+ * CheckAuthentication() slot, the obj and conn pointers are used as its two
+ * parameters. An invocation of the RXS CheckAuthentication() macro results in
+ * a return value identical to that of the op CheckAuthentication() routine,
+ * namely a value of type int.
+ *
+ * \subsubsection sec5-5-7-7 Section 5.5.7.7: RXS CreateChallenge()
+ *
+ * \par
+ * \#define RXS_CreateChallenge(obj, conn) RXS_OP(obj, CreateChallenge, (obj,
+ * conn))
+ * \par
+ * This macro causes the execution of the interface routine in the op
+ * CreateChallenge() slot in the Rx security object identified by the obj
+ * pointer. This interface function is invoked by Rx each time a challenge
+ * event is constructed for a given connection. Among the responsibilities of
+ * such a function might be marking the connection as temporarily
+ * unauthenticated until the given challenge is successfully met.
+ * \par
+ * The obj parameter must resolve into an object of type (struct rx securityOps
+ * *). The conn argument contains a pointer to the Rx connection for which the
+ * authentication challenge is being constructed, and must resolve to an object
+ * of type (struct rx connection *).
+ * \par
+ * In generating a call to the routine located at the security object's op
+ * CreateChallenge() slot, the obj and conn pointers are used as its two
+ * parameters. An invocation of the RXS CreateChallenge() macro results in a
+ * return value identical to that of the op CreateChallenge() routine, namely a
+ * value of type int.
+ *
+ * \subsubsection sec5-5-7-8 Section 5.5.7.8: RXS GetChallenge()
+ *
+ * \par
+ * \#define RXS_GetChallenge(obj, conn, packet) RXS_OP(obj, GetChallenge, (obj,
+ * conn, packet))
+ * \par
+ * This macro causes the execution of the interface routine occupying the op
+ * GetChallenge() slot in the Rx security object identified by the obj pointer.
+ * This interface function is invoked by Rx each time a challenge packet is
+ * constructed for a given connection. Among the responsibilities of such a
+ * function might be constructing the appropriate challenge structures in the
+ * area of packet dedicated to security matters.
+ * \par
+ * The obj parameter must resolve into an object of type (struct rx securityOps
+ * *). The conn argument contains a pointer to the Rx connection to which the
+ * given challenge packet belongs, and must resolve to an object of type
+ * (struct rx connection *). The final argument, packet, contains a pointer to
+ * the challenge packet itself. It should resolve to an object of type (struct
+ * rx packet *).
+ * \par
+ * In generating a call to the routine located at the security object's op
+ * GetChallenge() slot, the obj, conn, and packet pointers are used as its
+ * three parameters. An invocation of the RXS GetChallenge() macro results in a
+ * return value identical to that of the op GetChallenge() routine, namely a
+ * value of type int.
+ *
+ * \subsubsection sec5-5-7-9 Section 5.5.7.9: RXS GetResponse()
+ *
+ * \par
+ * \#define RXS_GetResponse(obj, conn, packet) RXS_OP(obj, GetResponse, (obj,
+ * conn, packet))
+ * \par
+ * This macro causes the execution of the interface routine occupying the op
+ * GetResponse() slot in the Rx security object identified by the obj pointer.
+ * This interface function is invoked by Rx on the server side each time a
+ * response to a challenge packet must be received.
+ * \par
+ * The obj parameter must resolve into an object of type (struct rx securityOps
+ * *). The conn argument contains a pointer to the Rx client connection that
+ * must respond to the authentication challenge, and must resolve to a (struct
+ * rx connection *) object. The final argument, packet, contains a pointer to
+ * the packet to be built in response to the challenge. It should resolve to an
+ * object of type (struct rx packet *).
+ * \par
+ * In generating a call to the routine located at the security object's op
+ * GetResponse() slot, the obj, conn, and packet pointers are used as its three
+ * parameters. An invocation of the RXS GetResponse() macro results in a return
+ * value identical to that of the op GetResponse() routine, namely a value of
+ * type int.
+ *
+ * \subsubsection sec5-5-7-10 Section 5.5.7.10: RXS CheckResponse()
+ *
+ * \par
+ * \#define RXS_CheckResponse(obj, conn, packet) RXS_OP(obj, CheckResponse,
+ * (obj, conn, packet))
+ * \par
+ * This macro causes the execution of the interface routine in the op
+ * CheckResponse() slot in the Rx security object identified by the obj
+ * pointer. This interface function is invoked by Rx on the server side each
+ * time a response to a challenge packet is received for a given connection.
+ * The responsibilities of such a function might include verifying the
+ * integrity of the response, pulling out the necessary security information
+ * and storing that information within the affected connection, and otherwise
+ * updating the state of the connection.
+ * \par
+ * The obj parameter must resolve into an object of type (struct rx securityOps
+ * *). The conn argument contains a pointer to the Rx server connection to
+ * which the given challenge response is directed. This argument must resolve
+ * to an object of type (struct rx connection *). The final argument, packet,
+ * contains a pointer to the packet received in response to the challenge
+ * itself. It should resolve to an object of type (struct rx packet *).
+ * \par
+ * In generating a call to the routine located at the security object's op
+ * CheckResponse() slot, the obj, conn, and packet pointers are ued as its
+ * three parameters. An invocation of the RXS CheckResponse() macro results in
+ * a return value identical to that of the op CheckResponse() routine, namely a
+ * value of type int.
+ *
+ * \subsubsection sec5-5-7-11 Section 5.5.7.11: RXS CheckPacket()
+ *
+ * \par
+ * \#define RXS_CheckPacket(obj, call, packet) RXS_OP(obj, CheckPacket, (obj,
+ * call, packet))
+ * \par
+ * This macro causes the execution of the interface routine occupying the op
+ * CheckPacket() slot in the Rx security object identified by the obj pointer.
+ * This interface function is invoked by Rx each time a packet is received. The
+ * responsibilities of such a function might include verifying the integrity of
+ * given packet, detecting any unauthorized modifications or tampering.
+ * \par
+ * The obj parameter must resolve into an object of type (struct rx securityOps
+ * *). The conn argument contains a pointer to the Rx connection to which the
+ * given challenge response is directed, and must resolve to an object of type
+ * (struct rx connection *). The final argument, packet, contains a pointer to
+ * the packet received in response to the challenge itself. It should resolve
+ * to an object of type (struct rx packet *).
+ * \par
+ * In generating a call to the routine located at the security object's op
+ * CheckPacket() slot, the obj, conn, and packet pointers are used as its three
+ * parameters. An invocation of the RXS CheckPacket() macro results in a return
+ * value identical to that of the op CheckPacket() routine, namely a value of
+ * type int.
+ * \par
+ * Please note that any non-zero return will cause Rx to abort all calls on the
+ * connection. Furthermore, the connection itself will be marked as being in
+ * error in such a case, causing it to reject any further incoming packets.
+ *
+ * \subsubsection sec5-5-7-12 Section 5.5.7.12: RXS DestroyConnection()
+ *
+ * \par
+ * \#define RXS_DestroyConnection(obj, conn) RXS_OP(obj, DestroyConnection,
+ * (obj, conn))
+ * \par
+ * This macro causes the execution of the interface routine in the op
+ * DestroyConnection() slot in the Rx security object identified by the obj
+ * pointer. This interface function is invoked by Rx each time a connection
+ * employing the given security object is being destroyed. The responsibilities
+ * of such a function might include deleting any private data maintained by the
+ * security module for this connection.
+ * \par
+ * The obj parameter must resolve into an object of type (struct rx securityOps
+ * *). The conn argument contains a pointer to the Rx connection being reaped,
+ * and must resolve to a (struct rx connection *) object.
+ * \par
+ * In generating a call to the routine located at the security object's op
+ * DestroyConnection() slot, the obj and conn pointers are used as its two
+ * parameters. An invocation of the RXS DestroyConnection() macro results in a
+ * return value identical to that of the op DestroyConnection() routine, namely
+ * a value of type int.
+ *
+ * \subsubsection sec5-5-7-13 Section 5.5.7.13: RXS GetStats()
+ *
+ * \par
+ * \#define RXS_GetStats(obj, conn, stats) RXS_OP(obj, GetStats, (obj, conn,
+ * stats))
+ * \par
+ * This macro causes the execution of the interface routine in the op
+ * GetStats() slot in the Rx security object identified by the obj pointer.
+ * This interface function is invoked by Rx each time current statistics
+ * concerning the given security object are desired.
+ * \par
+ * The obj parameter must resolve into an object of type (struct rx securityOps
+ * *). The conn argument contains a pointer to the Rx connection using the
+ * security object to be examined, and must resolve to an object of type
+ * (struct rx connection *). The final argument, stats, contains a pointer to a
+ * region to be filled with the desired statistics. It should resolve to an
+ * object of type (struct rx securityObjectStats *).
+ * \par
+ * In generating a call to the routine located at the security object's op
+ * GetStats() slot, the obj, conn, and stats pointers are used as its three
+ * parameters. An invocation of the RXS GetStats() macro results in a return
+ * value identical to that of the op GetStats() routine, namely a value of type
+ * int.
+ *
+ * \section sec5-6 Section 5.6: Functions
+ *
+ * \par
+ * Rx exports a collection of functions that, in conjuction with the macros
+ * explored in Section 5.5, allows its clients to set up and export services,
+ * create and tear down connections to these services, and execute remote
+ * procedure calls along these connections.
+ * \par
+ * This paper employs two basic categorizations of these Rx routines. One set
+ * of functions is meant to be called directly by clients of the facility, and
+ * are referred to as the exported operations. The individual members of the
+ * second set of functions are not meant to be called directly by Rx clients,
+ * but rather are called by the collection of defined macros, so they must
+ * still be lexically visible. These indirectly-executed routines are referred
+ * to here as the semi-exported operations.
+ * \par
+ * All Rx routines return zero upon success. The range of error codes employed
+ * by Rx is defined in Section 5.2.15.
+ *
+ * \subsection sec5-6-1 Section 5.6.1: Exported Operations
+ *
+ * \subsection sec5-6-2 Section 5.6.2: rx Init _ Initialize Rx
+ *
+ * \par
+ * int rx Init(IN int port)
+ * \par Description
+ * Initialize the Rx facility. If a non-zero port number is provided, it
+ * becomes the default port number for any service installed later. If 0 is
+ * provided for the port, a random port will be chosen by the system. The rx
+ * Init() function sets up internal tables and timers, along with starting up
+ * the listener thread.
+ * \par Error Codes
+ * RX ADDRINUSE The port provided has already been taken.
+ *
+ * \subsection sec5-6-3 Section 5.6.3: rx NewService _ Create and install
+ * a new service
+ *
+ * \par
+ * struct rx service *rx NewService(IN u short port; IN u short serviceId; IN
+ * char *serviceName; IN struct rx securityClass **securityObjects; IN int
+ * nSecurityObjects; IN long (*serviceProc)())
+ * \par Description
+ * Create and advertise a new Rx service. A service is uniquely named by a UDP
+ * port number plus a non-zero 16-bit serviceId on the given host. The port
+ * argument may be set to zero if rx Init() was called with a non-zero port
+ * number, in which case that original port will be used. A serviceName must
+ * also be provided, to be used for identification purposes (e.g., the service
+ * name might be used for probing for statistics). A pointer to an array of
+ * nSecurityObjects security objects to be associated with the new service is
+ * given in . securityObjects. The service's executeRequestProc() pointer is
+ * set to serviceProc.
+ * \par
+ * The function returns a pointer to a descriptor for the requested Rx service.
+ * A null return value indicates that the new service could not be created.
+ * Possible reasons include:
+ * \li The serviceId parameter was found to be zero.
+ * \li A port value of zero was specified at Rx initialization time (i.e., when
+ * rx init() was called), requiring a non-zero value for the port parameter
+ * here.
+ * \li Another Rx service is already using serviceId.
+ * \li Rx has already created the maximum RX MAX SERVICES Rx services (see
+ * Section 5.2.1).
+ * \par Error Codes
+ * (struct rx service *) NULL The new Rx service could not be created, due to
+ * one of the errors listed above.
+ *
+ * \subsection sec5-6-4 Section 5.6.4: rx NewConnection _ Create a new
+ * connection to a given service
+ *
+ * \par
+ * struct rx connection *rx NewConnection( IN u long shost, IN u short sport,
+ * IN u short sservice, IN struct rx securityClass *securityObject, IN int
+ * service SecurityIndex)
+ * \par Description
+ * Create a new Rx client connection to service sservice on the host whose IP
+ * address is contained in shost and to that host's sport UDP port. The
+ * corresponding Rx service identifier is expected in sservice. The caller also
+ * provides a pointer to the security object to use for the connection in
+ * securityObject, along with that object's serviceSecurityIndex among the
+ * security objects associated with service sservice via a previous rx
+ * NewService() call (see Section 5.6.3).
+ * \note It is permissible to provide a null value for the securityObject
+ * parameter if the chosen serviceSecurityIndex is zero. This corresponds to
+ * the pre-defined null security object, which does not engage in authorization
+ * checking of any kind.
+ * \par Error Codes
+ * --- A pointer to an initialized Rx connection is always returned, unless osi
+ * Panic() is called due to memory allocation failure.
+ *
+ * \subsection sec5-6-5 Section 5.6.5: rx NewCall _ Start a new call on
+ * the given connection
+ *
+ * \par
+ * struct rx call *rx NewCall( IN struct rx connection *conn)
+ * \par Description
+ * Start a new Rx remote procedure call on the connection specified by the conn
+ * parameter. The existing call structures (up to RX MAXCALLS of them) are
+ * examined in order. The first non-active call encountered (i.e., either
+ * unused or whose call->state is RX STATE DALLY) will be appropriated and
+ * reset if necessary. If all call structures are in active use, the RX CONN
+ * MAKECALL WAITING flag is set in the conn->flags field, and the thread
+ * handling this request will sleep until a call structure comes free. Once a
+ * call structure has been reserved, the keep-alive protocol is enabled for it.
+ * \par
+ * The state of the given connection determines the detailed behavior of the
+ * function. The conn->timeout field specifies the absolute upper limit of the
+ * number of seconds this particular call may be in operation. After this time
+ * interval, calls to such routines as rx SendData() or rx ReadData() will fail
+ * with an RX CALL TIMEOUT indication.
+ * \par Error Codes
+ * --- A pointer to an initialized Rx call is always returned, unless osi
+ * Panic() is called due to memory allocation failure.
+ *
+ * \subsection sec5-6-6 Section 5.6.6: rx EndCall _ Terminate the given
+ * call
+ *
+ * \par
+ * int rx EndCall(
+ * \param IN struct rx call *call,
+ * \param IN long rc
+ * \n )
+ * \par Description
+ * Indicate that the Rx call described by the structure located at call is
+ * finished, possibly prematurely. The value passed in the rc parameter is
+ * returned to the peer, if appropriate. The final error code from processing
+ * the call will be returned as rx EndCall()'s value. The given call's state
+ * will be set to RX STATE DALLY, and threads waiting to establish a new call
+ * on this connection are signalled (see the description of the rx NewCall() in
+ * Section 5.6.5).
+ * \par Error Codes
+ * -1 Unspecified error has occurred.
+ *
+ * \subsection sec5-6-7 Section 5.6.7: rx StartServer _ Activate installed
+ * rx service(s)
+ *
+ * \par
+ * void rx StartServer( IN int donateMe)
+ * \par Description
+ * This function starts server threads in support of the Rx services installed
+ * via calls to rx NewService() (see Section 5.6.3). This routine first
+ * computes the number of server threads it must create, governed by the
+ * minProcs and maxProcs fields in the installed service descriptors. The
+ * minProcs field specifies the minimum number of threads that are guaranteed
+ * to be concurrently available to the given service. The maxProcs field
+ * specifies the maximum number of threads that may ever be concurrently
+ * assigned to the particular service, if idle threads are available. Using
+ * this information, rx StartServer() computes the correct overall number of
+ * threads as follows: For each installed service, minProcs threads will be
+ * created, enforcing the minimality guarantee. Calculate the maximum
+ * difference between the maxProcs and minProcs fields for each service, and
+ * create this many additional server threads, enforcing the maximality
+ * guarantee.
+ * \par
+ * If the value placed in the donateMe argument is zero, then rx StartServer()
+ * will simply return after performing as described above. Otherwise, the
+ * thread making the rx StartServer() call will itself begin executing the
+ * server thread loop. In this case, the rx StartServer() call will never
+ * return.
+ * \par Error Codes
+ * ---None.
+ *
+ * \subsection sec5-6-8 Section 5.6.8: rx PrintStats -- Print basic
+ * statistics to a file
+ *
+ * \par
+ * void rx PrintStats( IN FILE *file)
+ * \par Description
+ * Prints Rx statistics (basically the contents of the struct rx stats holding
+ * the statistics for the Rx facility) to the open file descriptor identified
+ * by file. The output is ASCII text, and is intended for human consumption.
+ * \note This function is available only if the Rx package has been compiled
+ * with the RXDEBUG flag.
+ * \par Error Codes
+ * ---None.
+ *
+ * \subsection sec5-6-9 Section 5.6.9: rx PrintPeerStats _ Print peer
+ * statistics to a file
+ * \par
+ * void rx PrintPeerStats( IN FILE *file, IN struct rx peer *peer)
+ * \par Description
+ * Prints the Rx peer statistics found in peer to the open file descriptor
+ * identified by file. The output is in normal ASCII text, and is intended for
+ * human consumption.
+ * \note This function is available only if the Rx package has been compiled
+ * with the RXDEBUG flag.
+ * \par Error Codes
+ * ---None.
+ *
+ * \subsection sec5-6-10 Section 5.6.10: rx finalize _ Shut down Rx
+ * gracefully
+ *
+ * \par
+ * void rx finalize()
+ * \par Description
+ * This routine may be used to shut down the Rx facility for either server or
+ * client applications. All of the client connections will be gracefully
+ * garbage-collected after their active calls are cleaned up. The result of
+ * calling rx finalize() from a client program is that the server-side entity
+ * will be explicitly advised that the client has terminated. This notification
+ * frees the server-side application from having to probe the client until its
+ * records eventually time out, and also allows it to free resources currently
+ * assigned to that client's support.
+ * \par Error Codes
+ * ---None.
+ *
+ * \subsection sec5-6-11 Section 5.6.11: Semi-Exported Operations
+ *
+ * \par
+ * As described in the introductory text in Section 5.6, entries in this
+ * lexically-visible set of Rx functions are not meant to be called directly by
+ * client applications, but rather are invoked by Rx macros called by users.
+ *
+ * \subsection sec5-6-12 Section 5.6.12: rx WriteProc _ Write data to an
+ * outgoing call
+ *
+ * \par
+ * int rx WriteProc( IN struct rx call *call, IN char *buf, IN int nbytes)
+ * \par Description
+ * Write nbytes of data from buffer buf into the Rx call identified by the call
+ * parameter. The value returned by rx WriteProc() reports the number of bytes
+ * actually written into the call. If zero is returned, then the rx Error()
+ * macro may be used to obtain the call status.
+ * \par
+ * This routine is called by the rx Write() macro, which is why it must be
+ * exported by the Rx facility.
+ * \par Error Codes
+ * Indicates error in the given Rx call; use the rx Error() macro to determine
+ * the call status.
+ *
+ * \subsection sec5-6-13 Section 5.6.13: rx ReadProc _ Read data from an
+ * incoming call
+ *
+ * \par
+ * int rx ReadProc( IN struct rx call *call, IN char *buf, IN int nbytes)
+ * \par Description
+ * Read up to nbytes of data from the Rx call identified by the call parameter
+ * into the buf buffer. The value returned by rx ReadProc() reports the number
+ * of bytes actually read from the call. If zero is returned, then the rx
+ * Error() macro may be used to obtain the call status.
+ * \par
+ * This routine is called by the rx Read() macro, which is why it must be
+ * exported by the Rx facility.
+ * \par Error Codes
+ * Indicates error in the given Rx call; use the rx Error() macro to determine
+ * the call status.
+ *
+ * \subsection sec5-6-1 Section 5.6.1: rx FlushWrite -- Flush buffered
+ * data on outgoing call
+ *
+ * \par
+ * void rx FlushWrite( IN struct rx call *call)
+ * \par Description
+ * Flush any buffered data on the given Rx call to the stream. If the call is
+ * taking place on a server connection, the call->mode is set to RX MODE EOF.
+ * If the call is taking place on a client connection, the call->mode is set to
+ * RX MODE RECEIVING.
+ * \par Error Codes
+ * ---None.
+ *
+ * \subsection sec5-6-15 Section 5.6.15: rx SetArrivalProc _ Set function
+ * to invoke upon call packet arrival
+ *
+ * \par
+ * void rx SetArrivalProc( IN struct rx call *call, IN VOID (*proc)(), IN VOID
+ * *handle, IN VOID *arg)
+ * \par Description
+ * Establish a procedure to be called when a packet arrives for a call. This
+ * routine will be called at most once after each call, and will also be called
+ * if there is an error condition on the call or the call is complete. The rx
+ * SetArrivalProc() function is used by multicast Rx routines to build a
+ * selection function that determines which of several calls is likely to be a
+ * good one to read from. The implementor's comments in the Rx code state that,
+ * due to the current implementation, it is probably only reasonable to use rx
+ * SetArrivalProc() immediately after an rx NewCall(), and to only use it once.
+ * \par Error Codes
+ * ---None.
+ *
+ * \page chap6 Chapter 6 -- Example Server and Client
+ *
+ * \section sec6-1 Section 6.1: Introduction
+ *
+ * \par
+ * This chapter provides a sample program showing the use of Rx. Specifically,
+ * the rxdemo application, with all its support files, is documented and
+ * examined. The goal is to provide the reader with a fully-developed and
+ * operational program illustrating the use of both regular Rx remote procedure
+ * calls and streamed RPCs. The full text of the rxdemo application is
+ * reproduced in the sections below, along with additional commentary.
+ * \par
+ * Readers wishing to directly experiment with this example Rx application are
+ * encouraged to examine the on-line version of rxdemo. Since it is a program
+ * of general interest, it has been installed in the usr/contrib tree in the
+ * grand.central.org cell. This area contains user-contributed software for the
+ * entire AFS community. At the top of this tree is the
+ * /afs/grand.central.org/darpa/usr/contrib directory. Both the server-side and
+ * client-side rxdemo binaries (rxdemo server and rxdemo client, respectively)
+ * may be found in the bin subdirectory. The actual sources reside in the
+ * .site/grand.central.org/rxdemo/src subdirectory.
+ * \par
+ * The rxdemo code is composed of two classes of files, namely those written by
+ * a human programmer and those generated from the human-written code by the
+ * Rxgen tool. Included in the first group of files are:
+ * \li rxdemo.xg This is the RPC interface definition file, providing
+ * high-level definitions of the supported calls.
+ * \li rxdemo client.c: This is the rxdemo client program, calling upon the
+ * associated server to perform operations defined by rxdemo.xg.
+ * \li rxdemo server.c: This is the rxdemo server program, implementing the
+ * operations promised in rxdemo.xg.
+ * \li Makefile: This is the file that directs the compilation and
+ * installation of the rxdemo code.
+ * \par
+ * The class of automatically-generated files includes the following items:
+ * \li rxdemo.h: This header file contains the set of constant definitions
+ * present in rxdemo.xg, along with information on the RPC opcodes defined for
+ * this Rx service.
+ * \li rxdemo.cs.c: This client-side stub file performs all the marshalling and
+ * unmarshalling of the arguments for the RPC routines defined in rxdemo.xg.
+ * \li rxdemo.ss.c: This stub file similarly defines all the marshalling and
+ * unmarshalling of arguments for the server side of the RPCs, invokes the
+ * routines defined within rxdemo server.c to implement the calls, and also
+ * provides the dispatcher function.
+ * \li rxdemo.xdr.c: This module defines the routines required to convert
+ * complex user-defined data structures appearing as arguments to the Rx RPC
+ * calls exported by rxdemo.xg into network byte order, so that correct
+ * communication is guaranteed between clients and server with different memory
+ * organizations.
+ * \par
+ * The chapter concludes with a section containing sample output from running
+ * the rxdemo server and client programs.
+ *
+ * \section sec6-2 Section 6.2: Human-Generated files
+ *
+ * \par
+ * The rxdemo application is based on the four human-authored files described
+ * in this section. They provide the basis for the construction of the full set
+ * of modules needed to implement the specified Rx service.
+ *
+ * \subsection sec6-2-1 Section 6.2.1: Interface file: rxdemo.xg
+ *
+ * \par
+ * This file serves as the RPC interface definition file for this application.
+ * It defines various constants, including the Rx service port to use and the
+ * index of the null security object (no encryption is used by rxdemo). It
+ * defines the RXDEMO MAX and RXDEMO MIN constants, which will be used by the
+ * server as the upper and lower bounds on the number of Rx listener threads to
+ * run. It also defines the set of error codes exported by this facility.
+ * finally, it provides the RPC function declarations, namely Add() and
+ * Getfile(). Note that when building the actual function definitions, Rxgen
+ * will prepend the value of the package line in this file, namely "RXDEMO ",
+ * to the function declarations. Thus, the generated functions become RXDEMO
+ * Add() and RXDEMO Getfile(), respectively. Note the use of the split keyword
+ * in the RXDEMO Getfile() declaration, which specifies that this is a streamed
+ * call, and actually generates two client-side stub routines (see Section
+ * 6.3.1).
+ *
+ * \code
+ * /*=======================================================================
+ * * Interface for an example Rx server/client application, using both * *
+ * standard and streamed calls. * ** * Edward R. Zayas * * Transarc
+ * Corporation * ** ** * The United States Government has rights in this
+ * work pursuant * * to contract no. MDA972-90-C-0036 between the United
+ * States Defense * * Advanced Research Projects Agency and Transarc
+ * Corporation. * ** * (C) Copyright 1991 Transarc Corporation * ** *
+ * Redistribution and use in source and binary forms are permitted *
+ * provided that: (1) source distributions retain this entire copy- * *
+ * right notice and comment, and (2) distributions including binaries * *
+ * display the following acknowledgement: * ** * ''This product includes
+ * software developed by Transarc * * Corporation and its contributors'' *
+ * ** * in the documentation or other materials mentioning features or * *
+ * use of this software. Neither the name of Transarc nor the names * * of
+ * its contributors may be used to endorse or promote products * * derived
+ * from this software without specific prior written * * permission. * **
+ * * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * =======================================================================*/
+ *
+ * package RXDEMO_
+ * %#include <rx/rx.h>
+ * %#include <rx/rx_null.h>
+ * %#define RXDEMO_SERVER_PORT 8000 /* Service port to advertise */
+ * %#define RXDEMO_SERVICE_PORT 0 /* User server's port */
+ * %#define RXDEMO_SERVICE_ID 4 /* Service ID */
+ * %#define RXDEMO_NULL_SECOBJ_IDX 0 /* Index of null security object */
+ *
+ * /* Maximum number of requests that will be handled by this service
+ * * simultaneously. This number will be guaranteed to execute in
+ * * parallel if other service's results are being processed. */
+ *
+ * %#define RXDEMO_MAX 3
+ *
+ * /* Minimum number of requests that are guaranteed to be
+ * * handled simultaneously. */
+ *
+ * %#define RXDEMO_MIN 2
+ *
+ * /* Index of the "null" security class in the sample service. */
+ *
+ * %#define RXDEMO_NULL 0
+ *
+ * /* Maximum number of characters in a file name (for demo purposes). */
+ *
+ * %#define RXDEMO_NAME_MAX_CHARS 64
+ *
+ * /* Define the max number of bytes to transfer at one shot. */
+ *
+ * %#define RXDEMO_BUFF_BYTES 512
+ *
+ * /* Values returned by the RXDEMO_Getfile() call.
+ * * RXDEMO_CODE_SUCCESS : Everything went fine.
+ * * RXDEMO_CODE_CANT_OPEN : Can't open named file.
+ * * RXDEMO_CODE_CANT_STAT : Can't stat open file.
+ * * RXDEMO_CODE_CANT_READ : Error reading the open file.
+ * * RXDEMO_CODE_WRITE_ERROR : Error writing the open file. */
+ *
+ * /* ------------Interface calls defined for this service ----------- */
+ * %#define RXDEMO_CODE_SUCCESS 0
+ * %#define RXDEMO_CODE_CANT_OPEN 1
+ * %#define RXDEMO_CODE_CANT_STAT 2
+ * %#define RXDEMO_CODE_CANT_READ 3
+ * %#define RXDEMO_CODE_WRITE_ERROR 4
+ * /* -------------------------------------------------------------------
+ * * RXDEMO_Add *
+ * *
+ * * Summary:
+ * * Add the two numbers provided and return the result. *
+ * * Parameters:
+ * * int a_first : first operand.
+ * * int a_second : Second operand.
+ * * int *a_result : Sum of the above. *
+ * * Side effects: None.
+ * *-------------------------------------------------------------------- */
+ *
+ * Add(IN int a, int b, OUT int *result) = 1;
+ * /*-------------------------------------------------------------------
+ * * RXDEMO_Getfile *
+ * * Summary:
+ * * Return the contents of the named file in the server's environment.
+ * * Parameters:
+ * * STRING a_nameToRead : Name of the file whose contents are to be
+ * * fetched.
+ * * int *a_result : Set to the result of opening and reading the file
+ * * on the server side. *
+ * * Side effects: None.
+ * *-------------------------------------------------------------------- */
+ *
+ * Getfile(IN string a_nameToRead<RXDEMO_NAME_MAX_CHARS>, OUT int *a_result)
+ * split = 2;
+ * \endcode
+ *
+ * \subsection sec6-2-2 Section 6.2.2: Client Program: rxdemo client.c
+ *
+ * \par
+ * The rxdemo client program, rxdemo client, calls upon the associated server
+ * to perform operations defined by rxdemo.xg. After its header, it defines a
+ * private GetIPAddress() utility routine, which given a character string host
+ * name will return its IP address.
+ *
+ * \code
+ * /*=======================================================================
+ * % Client side of an example Rx application, using both standard and % %
+ * streamed calls. % %% % Edward R. Zayas % % Transarc Corporation % %%
+ * %% % The United States Government has rights in this work pursuant % %
+ * to contract no. MDA972-90-C-0036 between the United States Defense % %
+ * Advanced Research Projects Agency and Transarc Corporation. % %% % (C)
+ * Copyright 1991 Transarc Corporation % %% % Redistribution and use in source
+ * and binary forms are permitted % % provided that: (1) source distributions
+ * retain this entire copy- % % right notice and comment, and (2) distributions
+ * including binaries % % display the following acknowledgement: % %% %
+ * ''This product includes software developed by Transarc % % Corporation and
+ * its contributors'' % %% % in the documentation or other materials mentioning
+ * features or % % use of this software. Neither the name of Transarc nor the
+ * names % % of its contributors may be used to endorse or promote products % %
+ * derived from this software without specific prior written % % permission.
+ * % %% % THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
+ * % % WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF % %
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * % %=======================================================================
+ * */
+ *
+ * #include <sys/types.h>
+ * #include <netdb.h>
+ * #include <stdio.h>
+ * #include "rxdemo.h"
+ * static char pn[] = "rxdemo"; /* Program name */
+ * static u_long GetIpAddress(a_hostName) char *a_hostName;
+ * { /* GetIPAddress */
+ * static char rn[] = "GetIPAddress"; /* Routine name */
+ * struct hostent *hostEntP; /* Ptr to host descriptor */
+ * u_long hostIPAddr; /* Host IP address */
+ * hostEntP = gethostbyname(a_hostName);
+ * if (hostEntP == (struct hostent *)0) {
+ * printf("[%s:%s] Host '%s' not found\n",
+ * pn, rn, a_hostName);
+ * exit(1);
+ * }
+ * if (hostEntP->h_length != sizeof(u_long)) {
+ * printf("[%s:%s] Wrong host address length (%d bytes instead of
+ * %d)",
+ * pn, rn, hostEntP->h_length, sizeof(u_long));
+ * exit(1);
+ * }
+ * bcopy(hostEntP->h_addr, (char *)&hostIPAddr, sizeof(hostIPAddr));
+ * return(hostIPAddr);
+ * } /* GetIpAddress */
+ * \endcode
+ *
+ * \par
+ * The main program section of the client code, after handling its command line
+ * arguments, starts off by initializing the Rx facility.
+ *
+ * \code
+ * main(argc, argv)
+ * int argc;
+ * char **argv;
+ * { /* Main */
+ * struct rx_connection *rxConnP; /* Ptr to server connection */
+ * struct rx_call *rxCallP; /* Ptr to Rx call descriptor */
+ * u_long hostIPAddr; /* IP address of chosen host */
+ * int demoUDPPort; /* UDP port of Rx service */
+ * struct rx_securityClass *nullSecObjP; /* Ptr to null security object */
+ * int operand1, operand2; /* Numbers to add int sum; Their sum */
+ * int code; /* Return code */
+ * char fileName[64]; /* Buffer for desired file's name */
+ * long fileDataBytes; /* Num bytes in file to get */
+ * char buff[RXDEMO_BUFF_BYTES+1]; /* Read buffer */
+ * int currBytesToRead; /* Num bytes to read in one iteration */
+ * int maxBytesToRead; /* Max bytes to read in one iteration */
+ * int bytesReallyRead; /* Num bytes read off Rx stream */
+ * int getResults; /* Results of the file fetch */
+ * printf("\n%s: Example Rx client process\n\n", pn);
+ * if ((argc < 2) || (argc > 3)) {
+ * printf("Usage: rxdemo <HostName> [PortToUse]");
+ * exit(1);
+ * }
+ * hostIPAddr = GetIpAddress(argv[1]);
+ * if (argc > 2)
+ * demoUDPPort = atoi(argv[2]);
+ * else
+ * demoUDPPort = RXDEMO_SERVER_PORT;
+ * /* Initialize the Rx facility. */
+ * code = rx_Init(htons(demoUDPPort));
+ * if (code) {
+ * printf("** Error calling rx_Init(); code is %d\n", code);
+ * exit(1);
+ * }
+ * /* Create a client-side null security object. */
+ * nullSecObjP = rxnull_NewClientSecurityObject();
+ * if (nullSecObjP == (struct rx_securityClass *)0) {
+ * printf("%s: Can't create a null client-side security
+ * object!\n", pn);
+ * exit(1);
+ * }
+ * /* Set up a connection to the desired Rx service, telling it to use
+ * * the null security object we just created. */
+ * printf("Connecting to Rx server on '%s', IP address 0x%x, UDP port
+ * %d\n", argv[1], hostIPAddr, demoUDPPort);
+ * rxConnP = rx_NewConnection(hostIPAddr, RXDEMO_SERVER_PORT,
+ * RXDEMO_SERVICE_ID, nullSecObjP, RXDEMO_NULL_SECOBJ_IDX);
+ * if (rxConnP == (struct rx_connection *)0) {
+ * printf("rxdemo: Can't create connection to server!\n");
+ * exit(1);
+ * } else
+ * printf(" ---> Connected.\n");
+ * \endcode
+ *
+ * \par
+ * The rx Init() invocation initializes the Rx library and defines the desired
+ * service UDP port (in network byte order). The rxnull
+ * NewClientSecurityObject() call creates a client-side Rx security object that
+ * does not perform any authentication on Rx calls. Once a client
+ * authentication object is in hand, the program calls rx NewConnection(),
+ * specifying the host, UDP port, Rx service ID, and security information
+ * needed to establish contact with the rxdemo server entity that will be
+ * providing the service.
+ * \par
+ * With the Rx connection in place, the program may perform RPCs. The first one
+ * to be invoked is RXDEMO Add():
+ *
+ * \code
+ * /* Perform our first, simple remote procedure call. */
+ * operand1 = 1;
+ * operand2 = 2;
+ * printf("Asking server to add %d and %d: ", operand1, operand2);
+ * code = RXDEMO_Add(rxConnP, operand1, operand2, &sum);
+ * if (code) {
+ * printf(" // ** Error in the RXDEMO_Add RPC: code is %d\n", code);
+ * exit(1);
+ * }
+ * printf("Reported sum is %d\n", sum);
+ * \endcode
+ *
+ * \par
+ * The first argument to RXDEMO Add() is a pointer to the Rx connection
+ * established above. The client-side body of the RXDEMO Add() function was
+ * generated from the rxdemo.xg interface file, and resides in the rxdemo.cs.c
+ * file (see Section 6.3.1). It gives the appearance of being a normal C
+ * procedure call.
+ * \par
+ * The second RPC invocation involves the more complex, streamed RXDEMO
+ * Getfile() function. More of the internal Rx workings are exposed in this
+ * type of call. The first additional detail to consider is that we must
+ * manually create a new Rx call on the connection.
+ *
+ * \code
+ * /* Set up for our second, streamed procedure call. */
+ * printf("Name of file to read from server: ");
+ * scanf("%s", fileName);
+ * maxBytesToRead = RXDEMO_BUFF_BYTES;
+ * printf("Setting up an Rx call for RXDEMO_Getfile...");
+ * rxCallP = rx_NewCall(rxConnP);
+ * if (rxCallP == (struct rx_call *)0) {
+ * printf("** Can't create call\n");
+ * exit(1);
+ * }
+ * printf("done\n");
+ * \endcode
+ *
+ * \par
+ * Once the Rx call structure has been created, we may begin executing the call
+ * itself. Having been declared to be split in the interface file, Rxgen
+ * creates two function bodies for rxdemo Getfile() and places them in
+ * rxdemo.cs.c. The first, StartRXDEMO Getfile(), is responsible for
+ * marshalling the outgoing arguments and issuing the RPC. The second,
+ * EndRXDEMO Getfile(), takes care of unmarshalling the non-streamed OUT
+ * function parameters. The following code fragment illustrates how the RPC is
+ * started, using the StartRXDEMO Getfile() routine to pass the call parameters
+ * to the server.
+ *
+ * \code
+ * /* Sending IN parameters for the streamed call. */
+ * code = StartRXDEMO_Getfile(rxCallP, fileName);
+ * if (code) {
+ * printf("** Error calling StartRXDEMO_Getfile(); code is %d\n",
+ * code);
+ * exit(1);
+ * }
+ * \endcode
+ *
+ * \par
+ * Once the call parameters have been shipped, the server will commence
+ * delivering the "stream" data bytes back to the client on the given Rx call
+ * structure. The first longword to come back on the stream specifies the
+ * number of bytes to follow.
+ *
+ * \par
+ * Begin reading the data being shipped from the server in response to * our
+ * setup call. The first longword coming back on the Rx call is
+ * the number of bytes to follow. It appears in network byte order,
+ * so we have to fix it up before referring to it.
+ *
+ * \code
+ * bytesReallyRead = rx_Read(rxCallP, &fileDataBytes, sizeof(long));
+ * if (bytesReallyRead != sizeof(long)) {
+ * printf("** Only %d bytes read for file length; should have been %d\n",
+ * bytesReallyRead, sizeof(long));
+ * exit(1);
+ * }
+ * fileDataBytes = ntohl(fileDataBytes);
+ * \endcode
+ *
+ * \par
+ * Once the client knows how many bytes will be sent, it runs a loop in which
+ * it reads a buffer at a time from the Rx call stream, using rx Read() to
+ * accomplish this. In this application, all that is done with each
+ * newly-acquired buffer of information is printing it out.
+ *
+ * \code
+ * /* Read the file bytes via the Rx call, a buffer at a time. */
+ * printf("[file contents (%d bytes) fetched over the Rx call appear
+ * below]\n\n", fileDataBytes);
+ * while (fileDataBytes > 0)
+ * {
+ * currBytesToRead = (fileDataBytes > maxBytesToRead ? maxBytesToRead :
+ * fileDataBytes);
+ * bytesReallyRead = rx_Read(rxCallP, buff, currBytesToRead);
+ * if (bytesReallyRead != currBytesToRead)
+ * {
+ * printf("\nExpecting %d bytes on this read, got %d instead\n",
+ * currBytesToRead, bytesReallyRead);
+ * exit(1);
+ * }
+ * /* Null-terminate the chunk before printing it. */
+ * buff[currBytesToRead] = 0;
+ * printf("%s", buff);
+ * /* Adjust the number of bytes left to read. */
+ * fileDataBytes -= currBytesToRead;
+ * } /* Read one bufferful of the file */
+ * \endcode
+ *
+ * \par
+ * After this loop terminates, the Rx stream has been drained of all data. The
+ * Rx call is concluded by invoking the second of the two
+ * automatically-generated functions, EndRXDEMO Getfile(), which retrieves the
+ * call's OUT parameter from the server.
+ *
+ * \code
+ * /* finish off the Rx call, getting the OUT parameters. */
+ * printf("\n\n[End of file data]\n");
+ * code = EndRXDEMO_Getfile(rxCallP, &getResults);
+ * if (code)
+ * {
+ * printf("** Error getting file transfer results; code is %d\n",
+ * code);
+ * exit(1);
+ * }
+ * \endcode
+ *
+ * \par
+ * With both normal and streamed Rx calls accomplished, the client demo code
+ * concludes by terminating the Rx call it set up earlier. With that done, the
+ * client exits.
+ *
+ * \code
+ * /* finish off the Rx call. */
+ * code = rx_EndCall(rxCallP, code);
+ * if (code)
+ * printf("Error in calling rx_EndCall(); code is %d\n", code);
+ *
+ * printf("\n\nrxdemo complete.\n");
+ * \endcode
+ *
+ * \subsection sec6-2-3 Server Program: rxdemo server.c
+ *
+ * \par
+ * The rxdemo server program, rxdemo server, implements the operations promised
+ * in the rxdemo.xg interface file.
+ * \par
+ * After the initial header, the external function RXDEMO ExecuteRequest() is
+ * declared. The RXDEMO ExecuteRequest() function is generated automatically by
+ * rxgen from the interface file and deposited in rxdemo.ss.c. The main program
+ * listed below will associate this RXDEMO ExecuteRequest() routine with the Rx
+ * service to be instantiated.
+ *
+ * \code
+ * /*======================================================================
+ * % % Advanced Research Projects Agency and Transarc Corporation. % %% %
+ * (C) Copyright 1991 Transarc Corporation % %% % Redistribution and use in
+ * source and binary forms are permitted % % provided that: (1) source
+ * distributions retain this entire copy- % % right notice and comment, and
+ * (2) distributions including binaries % % display the following
+ * acknowledgement: % %% % ''This product includes software developed by
+ * Transarc % % Corporation and its contributors'' % %% % in the documentation
+ * or other materials mentioning features or % % use of this software. Neither
+ * the name of Transarc nor the names % % of its contributors may be used to
+ * endorse or promote products % % derived from this software without specific
+ * prior written % % permission. % %% % THIS SOFTWARE IS PROVIDED "AS IS" AND
+ * WITHOUT ANY EXPRESS OR IMPLIED % % WARRANTIES, INCLUDING, WITHOUT
+ * LIMITATION,
+ * THE IMPLIED WARRANTIES OF % % MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE. % %
+ * ====================================================================== */
+ *
+ * /* Server portion of the example RXDEMO application, using both %
+ * standard and streamed calls. % % Edward R. Zayas % Transarc Corporation %
+ * % % The United States Government has rights in this work pursuant %
+ * to contract no. MDA972-90-C-0036 between the United States Defense % */
+ *
+ * #include <sys/types.h>
+ * #include <sys/stat.h>
+ * #include <sys/file.h>
+ * #include <netdb.h>
+ * #include <stdio.h>
+ * #include "rxdemo.h"
+ * #define N_SECURITY_OBJECTS 1
+ * extern RXDEMO_ExecuteRequest();
+ * \endcode
+ *
+ * \par
+ * After choosing either the default or user-specified UDP port on which the Rx
+ * service will be established, rx Init() is called to set up the library.
+ *
+ * \code
+ * main(argc, argv)
+ * int argc;
+ * char **argv;
+ * { /* Main */
+ * static char pn[] = "rxdemo_server"; /* Program name */
+ * struct rx_securityClass
+ * (securityObjects[1]); /* Security objs */
+ * struct rx_service *rxServiceP; /* Ptr to Rx service descriptor */
+ * struct rx_call *rxCallP; /* Ptr to Rx call descriptor */
+ * int demoUDPPort; /* UDP port of Rx service */
+ * int fd; /* file descriptor */
+ * int code; /* Return code */
+ * printf("\n%s: Example Rx server process\n\n", pn);
+ * if (argc >2) {
+ * printf("Usage: rxdemo [PortToUse]");
+ * exit(1);
+ * }
+ * if (argc > 1)
+ * demoUDPPort = atoi(argv[1]);
+ * else
+ * demoUDPPort = RXDEMO_SERVER_PORT;
+ *
+ * /* Initialize the Rx facility, telling it the UDP port number this
+ * * server will use for its single service. */
+ *
+ * printf("Listening on UDP port %d\n", demoUDPPort);
+ * code = rx_Init(demoUDPPort);
+ * if (code) {
+ * printf("** Error calling rx_Init(); code is %d\n", code);
+ * exit(1);
+ * }
+ * \endcode
+ *
+ * \par
+ * A security object specific to the server side of an Rx conversation is
+ * created in the next code fragment. As with the client side of the code, a
+ * "null" server security object, namely one that does not perform any
+ * authentication at all, is constructed with the rxnull
+ * NewServerSecurityObject() function.
+ *
+ * \code
+ * /* Create a single server-side security object. In this case, the
+ * * null security object (for unauthenticated connections) will be used
+ * * to control security on connections made to this server. */
+ *
+ * securityObjects[RXDEMO_NULL_SECOBJ_IDX] =
+ * rxnull_NewServerSecurityObject();
+ * if (securityObjects[RXDEMO_NULL_SECOBJ_IDX] == (struct rx_securityClass
+ * *) 0) {
+ * printf("** Can't create server-side security object\n");
+ * exit(1);
+ * }
+ * \endcode
+ *
+ * \par
+ * The rxdemo server program is now in a position to create the desired Rx
+ * service, primed to recognize exactly those interface calls defined in
+ * rxdemo.xg. This is accomplished by calling the rx NewService() library
+ * routine, passing it the security object created above and the generated Rx
+ * dispatcher routine.
+ *
+ * \code
+ * /* Instantiate a single sample service. The rxgen-generated procedure
+ * * called to dispatch requests is passed in (RXDEMO_ExecuteRequest). */
+ *
+ * rxServiceP = rx_NewService( 0,
+ * RXDEMO_SERVICE_ID,
+ * "rxdemo",
+ * securityObjects,
+ * 1,
+ * RXDEMO_ExecuteRequest
+ * );
+ * if (rxServiceP == (struct rx_service *) 0) {
+ * printf("** Can't create Rx service\n");
+ * exit(1);
+ * }
+ * \endcode
+ *
+ * \par
+ * The final step in this main routine is to activate servicing of calls to the
+ * exported Rx interface. Specifically, the proper number of threads are
+ * created to handle incoming interface calls. Since we are passing a non-zero
+ * argument to the rx StartServer() call, the main program will itself begin
+ * executing the server thread loop, never returning from the rx StartServer()
+ * call. The print statement afterwards should never be executed, and its
+ * presence represents some level of paranoia, useful for debugging
+ * malfunctioning thread packages.
+ *
+ * \code
+ * /* Start up Rx services, donating this thread to the server pool. */
+ * rx_StartServer(1);
+ * /* We should never return from the previous call. */
+ * printf("** rx_StartServer() returned!!\n"); exit(1);
+ * } /* Main */
+ * \endcode
+ *
+ * \par
+ * Following the main procedure are the functions called by the
+ * automatically-generated routines in the rxdemo.ss.c module to implement the
+ * specific routines defined in the Rx interface.
+ * \par
+ * The first to be defined is the RXDEMO Add() function. The arguments for this
+ * routine are exactly as they appear in the interface definition, with the
+ * exception of the very first. The a rxCallP parameter is a pointer to the Rx
+ * structure describing the call on which this function was activated. All
+ * user-supplied routines implementing an interface function are required to
+ * have a pointer to this structure as their first parameter. Other than
+ * printing out the fact that it has been called and which operands it
+ * received, all that RXDEMO Add() does is compute the sum and place it in the
+ * output parameter.
+ * \par
+ * Since RXDEMO Add() is a non-streamed function, with all data travelling
+ * through the set of parameters, this is all that needs to be done. To mark a
+ * successful completion, RXDEMO Add() returns zero, which is passed all the
+ * way through to the RPC's client.
+ *
+ * \code
+ * int RXDEMO_Add(a_rxCallP, a_operand1, a_operand2, a_resultP)
+ * struct rx_call *a_rxCallP;
+ * int a_operand1, a_operand2;
+ * int *a_resultP;
+ * { /* RXDEMO_Add */
+ * printf("\t[Handling call to RXDEMO_Add(%d, %d)]\n",
+ * a_operand1, a_operand2);
+ * *a_resultP = a_operand1 + a_operand2;
+ * return(0);
+ * } /* RXDEMO_Add */
+ * \endcode
+ *
+ * \par
+ * The next and final interface routine defined in this file is RXDEMO
+ * Getfile(). Declared as a split function in the interface file, RXDEMO
+ * Getfile() is an example of a streamed Rx call. As with RXDEMO Add(), the
+ * initial parameter is required to be a pointer to the Rx call structure with
+ * which this routine is associated, Similarly, the other parameters appear
+ * exactly as in the interface definition, and are handled identically.
+ * \par
+ * The difference between RXDEMO Add() and RXDEMO Getfile() is in the use of
+ * the rx Write() library routine by RXDEMO Getfile() to feed the desired
+ * file's data directly into the Rx call stream. This is an example of the use
+ * of the a rxCallP argument, providing all the information necessary to
+ * support the rx Write() activity.
+ * \par
+ * The RXDEMO Getfile() function begins by printing out the fact that it's been
+ * called and the name of the requested file. It will then attempt to open the
+ * requested file and stat it to determine its size.
+ *
+ * \code
+ * int RXDEMO_Getfile(a_rxCallP, a_nameToRead, a_resultP)
+ * struct rx_call *a_rxCallP;
+ * char *a_nameToRead;
+ * int *a_resultP;
+ * { /* RXDEMO_Getfile */
+ * struct stat fileStat; /* Stat structure for file */
+ * long fileBytes; /* Size of file in bytes */
+ * long nbofileBytes; /* file bytes in network byte order */
+ * int code; /* Return code */
+ * int bytesReallyWritten; /* Bytes written on Rx channel */
+ * int bytesToSend; /* Num bytes to read & send this time */
+ * int maxBytesToSend; /* Max num bytes to read & send ever */
+ * int bytesRead; /* Num bytes read from file */
+ * char buff[RXDEMO_BUFF_BYTES+1]; /* Read buffer */
+ * int fd; /* file descriptor */
+ * maxBytesToSend = RXDEMO_BUFF_BYTES;
+ * printf("\t[Handling call to RXDEMO_Getfile(%s)]\n", a_nameToRead);
+ * fd = open(a_nameToRead, O_RDONLY, 0444);
+ * if (fd <0) {
+ * printf("\t\t[**Can't open file '%s']\n", a_nameToRead);
+ * *a_resultP = RXDEMO_CODE_CANT_OPEN;
+ * return(1);
+ * } else
+ * printf("\t\t[file opened]\n");
+ * /* Stat the file to find out how big it is. */
+ * code = fstat(fd, &fileStat);
+ * if (code) {
+ * a_resultP = RXDEMO_CODE_CANT_STAT;
+ * printf("\t\t[file closed]\n");
+ * close(fd);
+ * return(1);
+ * }
+ * fileBytes = fileStat.st_size;
+ * printf("\t\t[file has %d bytes]\n", fileBytes);
+ * \endcode
+ *
+ * \par
+ * Only standard unix operations have been used so far. Now that the file is
+ * open, we must first feed the size of the file, in bytes, to the Rx call
+ * stream. With this information, the client code can then determine how many
+ * bytes will follow on the stream. As with all data that flows through an Rx
+ * stream, the longword containing the file size, in bytes, must be converted
+ * to network byte order before being sent. This insures that the recipient may
+ * properly interpret the streamed information, regardless of its memory
+ * architecture.
+ *
+ * \code
+ * nbofileBytes = htonl(fileBytes);
+ * /* Write out the size of the file to the Rx call. */
+ * bytesReallyWritten = rx_Write(a_rxCallP, &nbofileBytes, sizeof(long));
+ * if (bytesReallyWritten != sizeof(long)) {
+ * printf("** %d bytes written instead of %d for file length\n",
+ * bytesReallyWritten, sizeof(long));
+ * *a_resultP = RXDEMO_CODE_WRITE_ERROR;
+ * printf("\t\t[file closed]\n");
+ * close(fd);
+ * return(1);
+ * }
+ * \endcode
+ *
+ * \par
+ * Once the number of file bytes has been placed in the stream, the RXDEMO
+ * Getfile() routine runs a loop, reading a buffer's worth of the file and then
+ * inserting that buffer of file data into the Rx stream at each iteration.
+ * This loop executes until all of the file's bytes have been shipped. Notice
+ * there is no special end-of-file character or marker inserted into the
+ * stream.
+ * \par
+ * The body of the loop checks for both unix read() and rx Write errors. If
+ * there is a problem reading from the unix file into the transfer buffer, it
+ * is reflected back to the client by setting the error return parameter
+ * appropriately. Specifically, an individual unix read() operation could fail
+ * to return the desired number of bytes. Problems with rx Write() are handled
+ * similarly. All errors discovered in the loop result in the file being
+ * closed, and RXDEMO Getfile() exiting with a non-zero return value.
+ *
+ * \code
+ * /* Write out the contents of the file, one buffer at a time. */
+ * while (fileBytes > 0) {
+ * /* figure out the number of bytes to
+ * * read (and send) this time. */
+ * bytesToSend = (fileBytes > maxBytesToSend ?
+ * maxBytesToSend : fileBytes);
+ * bytesRead = read(fd, buff, bytesToSend);
+ * if (bytesRead != bytesToSend) {
+ * printf("Read %d instead of %d bytes from the file\n",
+ * bytesRead, bytesToSend);
+ * *a_resultP = RXDEMO_CODE_WRITE_ERROR;
+ * printf("\t\t[file closed]\n");
+ * close(fd);
+ * return(1);
+ * }
+ * /* Go ahead and send them. */
+ * bytesReallyWritten = rx_Write(a_rxCallP, buff, bytesToSend);
+ * if (bytesReallyWritten != bytesToSend) {
+ * printf("%d file bytes written instead of %d\n",
+ * bytesReallyWritten, bytesToSend);
+ * *a_resultP = RXDEMO_CODE_WRITE_ERROR;
+ * printf("\t\t[file closed]\n");
+ * close(fd);
+ * return(1);
+ * }
+ * /* Update the number of bytes left to go. */
+ * fileBytes -= bytesToSend;
+ * } /* Write out the file to our caller */
+ * \endcode
+ *
+ * \par
+ * Once all of the file's bytes have been shipped to the remote client, all
+ * that remains to be done is to close the file and return successfully.
+ *
+ * \code
+ * /* Close the file, then return happily. */
+ * *a_resultP = RXDEMO_CODE_SUCCESS;
+ * printf("\t\t[file closed]\n");
+ * close(fd);
+ * return(0);
+ * } /* RXDEMO_Getfile */
+ * \endcode
+ *
+ * \subsection sec6-2-4 Section 6.2.4: Makefile
+ *
+ * \par
+ * This file directs the compilation and installation of the rxdemo code. It
+ * specifies the locations of libraries, include files, sources, and such tools
+ * as Rxgen and install, which strips symbol tables from executables and places
+ * them in their target directories. This Makefile demostrates cross-cell
+ * software development, with the rxdemo sources residing in the
+ * grand.central.org cell and the AFS include files and libraries accessed from
+ * their locations in the transarc.com cell.
+ * \par
+ * In order to produce and install the rxdemo server and rxdemo client
+ * binaries, the system target should be specified on the command line when
+ * invoking make:
+ * \code
+ * make system
+ * \endcode
+ * \par
+ * A note of caution is in order concerning generation of the rxdemo binaries.
+ * While tools exist that deposit the results of all compilations to other
+ * (architecture-specific) directories, and thus facilitate multiple
+ * simultaneous builds across a variety of machine architectures (e.g.,
+ * Transarc's washtool), the assumption is made here that compilations will
+ * take place directly in the directory containing all the rxdemo sources.
+ * Thus, a user will have to execute a make clean command to remove all
+ * machine-specific object, library, and executable files before compiling for
+ * a different architecture. Note, though, that the binaries are installed into
+ * a directory specifically reserved for the current machine type.
+ * Specifically, the final pathname component of the ${PROJ DIR}bin
+ * installation target is really a symbolic link to ${PROJ DIR}.bin/@sys.
+ * \par
+ * Two libraries are needed to support the rxdemo code. The first is obvious,
+ * namely the Rx librx.a library. The second is the lightweight thread package
+ * library, liblwp.a, which implements all the threading operations that must
+ * be performed. The include files are taken from the unix /usr/include
+ * directory, along with various AFS-specific directories. Note that for
+ * portability reasons, this Makefile only contains fully-qualified AFS
+ * pathnames and "standard" unix pathnames (such as /usr/include).
+ *
+ * \code
+ * /*#=======================================================================#
+ * # The United States Government has rights in this work pursuant # # to
+ * contract no. MDA972-90-C-0036 between the United States Defense # # Advanced
+ * Research Projects Agency and Transarc Corporation. # # # # (C) Copyright
+ * 1991
+ * Transarc Corporation # # # # Redistribution and use in source and binary
+ * forms
+ * are permitted # # provided that: (1) source distributions retain this entire
+ * copy-# # right notice and comment, and (2) distributions including binaries
+ * #
+ * # display the following acknowledgement: # # # # ''This product includes
+ * software developed by Transarc # # Corporation and its contributors'' # # #
+ * #
+ * in the documentation or other materials mentioning features or # # use of
+ * this
+ * software. Neither the name of Transarc nor the names # # of its contributors
+ * may be used to endorse or promote products # # derived from this software
+ * without specific prior written # # permission. # # # # THIS SOFTWARE IS
+ * PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED # # WARRANTIES,
+ * INCLUDING,
+ * WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF # # MERCHANTABILITY AND
+ * FITNESS
+ * FOR A PARTICULAR PURPOSE. #
+ * #=======================================================================# */
+ *
+ * SHELL = /bin/sh
+ * TOOL_CELL = grand.central.org
+ * AFS_INCLIB_CELL = transarc.com
+ * USR_CONTRIB = /afs/${TOOL_CELL}/darpa/usr/contrib/
+ * PROJ_DIR = ${USR_CONTRIB}.site/grand.central.org/rxdemo/
+ * AFS_INCLIB_DIR = /afs/${AFS_INCLIB_CELL}/afs/dest/
+ * RXGEN = ${AFS_INCLIB_DIR}bin/rxgen
+ * INSTALL = ${AFS_INCLIB_DIR}bin/install
+ * LIBS = ${AFS_INCLIB_DIR}lib/librx.a \ ${AFS_INCLIB_DIR}lib/liblwp.a
+ * CFLAGS = -g \
+ * -I. \
+ * -I${AFS_INCLIB_DIR}include \
+ * -I${AFS_INCLIB_DIR}include/afs \
+ * -I${AFS_INCLIB_DIR} \
+ * -I/usr/include
+ *
+ * system: install
+ *
+ * install: all
+ * ${INSTALL} rxdemo_client
+ * ${PROJ_DIR}bin
+ * ${INSTALL} rxdemo_server
+ * ${PROJ_DIR}bin
+ *
+ * all: rxdemo_client rxdemo_server
+ *
+ * rxdemo_client: rxdemo_client.o ${LIBS} rxdemo.cs.o ${CC} ${CFLAGS}
+ * -o rxdemo_client rxdemo_client.o rxdemo.cs.o ${LIBS}
+ *
+ * rxdemo_server: rxdemo_server.o rxdemo.ss.o ${LIBS} ${CC} ${CFLAGS}
+ * -o rxdemo_server rxdemo_server.o rxdemo.ss.o ${LIBS}
+ *
+ * rxdemo_client.o: rxdemo.h
+ *
+ * rxdemo_server.o: rxdemo.h
+ *
+ * rxdemo.cs.c rxdemo.ss.c rxdemo.er.c rxdemo.h: rxdemo.xg rxgen rxdemo.xg
+ *
+ * clean: rm -f *.o rxdemo.cs.c rxdemo.ss.c rxdemo.xdr.c rxdemo.h \
+ * rxdemo_client rxdemo_server core
+ * \endcode
+ *
+ * \section sec6-3 Section 6.3: Computer-Generated files
+ *
+ * \par
+ * The four human-generated files described above provide all the information
+ * necessary to construct the full set of modules to support the rxdemo example
+ * application. This section describes those routines that are generated from
+ * the base set by Rxgen, filling out the code required to implement an Rx
+ * service.
+ *
+ * \subsection sec6-3-1 Client-Side Routines: rxdemo.cs.c
+ *
+ * \par
+ * The rxdemo client.c program, described in Section 6.2.2, calls the
+ * client-side stub routines contained in this module in order to make rxdemo
+ * RPCs. Basically, these client-side stubs are responsible for creating new Rx
+ * calls on the given connection parameter and then marshalling and
+ * unmarshalling the rest of the interface call parameters. The IN and INOUT
+ * arguments, namely those that are to be delivered to the server-side code
+ * implementing the call, must be packaged in network byte order and shipped
+ * along the given Rx call. The return parameters, namely those objects
+ * declared as INOUT and OUT, must be fetched from the server side of the
+ * associated Rx call, put back in host byte order, and inserted into the
+ * appropriate parameter variables.
+ * \par
+ * The first part of rxdemo.cs.c echoes the definitions appearing in the
+ * rxdemo.xg interface file, and also #includes another Rxgen-generated file,
+ * rxdemo.h.
+ *
+ * \code
+ * /*======================================================================%
+ * * % THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED %
+ * * % WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF %
+ * * % MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. %
+ * * %====================================================================== */
+ * /* Machine generated file --Do NOT edit */
+ *
+ * #include "rxdemo.h"
+ * #define RXDEMO_CODE_WRITE_ERROR 4
+ *
+ * #include <rx/rx.h>
+ * #include <rx/rx_null.h>
+ * #define RXDEMO_SERVER_PORT 8000 /* Service port to advertise */
+ * #define RXDEMO_SERVICE_PORT 0 /* User server's port */
+ * #define RXDEMO_SERVICE_ID 4 /* Service ID */
+ * #define RXDEMO_NULL_SECOBJ_IDX 0 /* Index of null security object */
+ * #define RXDEMO_MAX 3
+ * #define RXDEMO_MIN 2
+ * #define RXDEMO_NULL 0
+ * #define RXDEMO_NAME_MAX_CHARS 64
+ * #define RXDEMO_BUFF_BYTES 512
+ * #define RXDEMO_CODE_SUCCESS 0
+ * #define RXDEMO_CODE_CANT_OPEN 1
+ * #define RXDEMO_CODE_CANT_STAT 2
+ * #define RXDEMO_CODE_CANT_READ 3
+ * #define RXDEMO_CODE_WRITE_ERROR 4
+ * \endcode
+ *
+ * \par
+ * The next code fragment defines the client-side stub for the RXDEMO Add()
+ * routine, called by the rxdemo client program to execute the associated RPC.
+ *
+ * \code
+ * int RXDEMO_Add(z_conn, a, b, result) register struct rx_connection *z_conn;
+ * int a, b;
+ * int * result;
+ * {
+ * struct rx_call *z_call = rx_NewCall(z_conn);
+ * static int z_op = 1;
+ * int z_result;
+ * XDR z_xdrs;
+ * xdrrx_create(&z_xdrs, z_call, XDR_ENCODE);
+ * /* Marshal the arguments */
+ * if ((!xdr_int(&z_xdrs, &z_op))
+ * || (!xdr_int(&z_xdrs, &a))
+ * || (!xdr_int(&z_xdrs, &b))) {
+ * z_result = RXGEN_CC_MARSHAL;
+ * goto fail;
+ * }
+ * /* Un-marshal the reply arguments */
+ * z_xdrs.x_op = XDR_DECODE;
+ * if ((!xdr_int(&z_xdrs, result))) {
+ * z_result = RXGEN_CC_UNMARSHAL;
+ * goto fail;
+ * }
+ * z_result = RXGEN_SUCCESS;
+ * fail: return rx_EndCall(z_call, z_result);
+ * }
+ * \endcode
+ *
+ * \par
+ * The very first operation performed by RXDEMO Add() occurs in the local
+ * variable declarations, where z call is set to point to the structure
+ * describing a newly-created Rx call on the given connection. An XDR
+ * structure, z xdrs, is then created for the given Rx call with xdrrx
+ * create(). This XDR object is used to deliver the proper arguments, in
+ * network byte order, to the matching server stub code. Three calls to xdr
+ * int() follow, which insert the appropriate Rx opcode and the two operands
+ * into the Rx call. With the IN arguments thus transmitted, RXDEMO Add()
+ * prepares to pull the value of the single OUT parameter. The z xdrs XDR
+ * structure, originally set to XDR ENCODE objects, is now reset to XDR DECODE
+ * to convert further items received into host byte order. Once the return
+ * parameter promised by the function is retrieved, RXDEMO Add() returns
+ * successfully.
+ * \par
+ * Should any failure occur in passing the parameters to and from the server
+ * side of the call, the branch to fail will invoke Rx EndCall(), which advises
+ * the server that the call has come to a premature end (see Section 5.6.6 for
+ * full details on rx EndCall() and the meaning of its return value).
+ * \par
+ * The next client-side stub appearing in this generated file handles the
+ * delivery of the IN parameters for StartRXDEMO Getfile(). It operates
+ * identically as the RXDEMO Add() stub routine in this respect, except that it
+ * does not attempt to retrieve the OUT parameter. Since this is a streamed
+ * call, the number of bytes that will be placed on the Rx stream cannot be
+ * determined at compile time, and must be handled explicitly by rxdemo
+ * client.c.
+ *
+ * \code
+ * int StartRXDEMO_Getfile(z_call, a_nameToRead)
+ * register struct rx_call *z_call;
+ * char * a_nameToRead;
+ * {
+ * static int z_op = 2;
+ * int z_result;
+ * XDR z_xdrs;
+ * xdrrx_create(&z_xdrs, z_call, XDR_ENCODE);
+ * /* Marshal the arguments */
+ * if ((!xdr_int(&z_xdrs, &z_op)) || (!xdr_string(&z_xdrs, &a_nameToRead,
+ * RXDEMO_NAME_MAX_CHARS))) {
+ * z_result = RXGEN_CC_MARSHAL;
+ * goto fail;
+ * }
+ * z_result = RXGEN_SUCCESS;
+ * fail: return z_result;
+ * }
+ * \endcode
+ *
+ * \par
+ * The final stub routine appearing in this generated file, EndRXDEMO
+ * Getfile(), handles the case where rxdemo client.c has already successfully
+ * recovered the unbounded streamed data appearing on the call, and then simply
+ * has to fetch the OUT parameter. This routine behaves identially to the
+ * latter portion of RXDEMO Getfile().
+ *
+ * \code
+ * int EndRXDEMO_Getfile(z_call, a_result)
+ * register struct rx_call *z_call;
+ * int * a_result;
+ * {
+ * int z_result;
+ * XDR z_xdrs;
+ * /* Un-marshal the reply arguments */
+ * xdrrx_create(&z_xdrs, z_call, XDR_DECODE);
+ * if ((!xdr_int(&z_xdrs, a_result))) {
+ * z_result = RXGEN_CC_UNMARSHAL;
+ * goto fail;
+ * }
+ * z_result = RXGEN_SUCCESS; fail:
+ * return z_result;
+ * }
+ * \endcode
+ *
+ * \subsection sec6-3-2 Server-Side Routines: rxdemo.ss.c
+ *
+ * \par
+ * This generated file provides the core components required to implement the
+ * server side of the rxdemo RPC service. Included in this file is the
+ * generated dispatcher routine, RXDEMO ExecuteRequest(), which the rx
+ * NewService() invocation in rxdemo server.c uses to construct the body of
+ * each listener thread's loop. Also included are the server-side stubs to
+ * handle marshalling and unmarshalling of parameters for each defined RPC call
+ * (i.e., RXDEMO Add() and RXDEMO Getfile()). These stubs are called by RXDEMO
+ * ExecuteRequest(). The routine to be called by RXDEMO ExecuteRequest()
+ * depends on the opcode received, which appears as the very first longword in
+ * the call data.
+ * \par
+ * As usual, the first fragment is copyright information followed by the body
+ * of the definitions from the interface file.
+ *
+ * \code
+ * /*======================================================================%
+ * % Edward R. Zayas % % Transarc Corporation % % % % % % The United States
+ * Government has rights in this work pursuant % % to contract no.
+ * MDA972-90-C-0036 between the United States Defense % % Advanced Research
+ * Projects Agency and Transarc Corporation. % % % % (C) Copyright 1991
+ * Transarc Corporation % % % % Redistribution and use in source and binary
+ * forms are permitted % % provided that: (1) source distributions retain
+ * this entire copy¬% % right notice and comment, and (2) distributions
+ * including binaries %
+ * %====================================================================== */
+ * /* Machine generated file --Do NOT edit */
+ *
+ * #include "rxdemo.h"
+ * #include <rx/rx.h>
+ * #include <rx/rx_null.h>
+ * #define RXDEMO_SERVER_PORT 8000 /* Service port to advertise */
+ * #define RXDEMO_SERVICE_PORT 0 /* User server's port */
+ * #define RXDEMO_SERVICE_ID 4 /* Service ID */
+ * #define RXDEMO_NULL_SECOBJ_IDX 0 /* Index of null security object */
+ * #define RXDEMO_MAX 3
+ * #define RXDEMO_MIN 2
+ * #define RXDEMO_NULL 0
+ * #define RXDEMO_NAME_MAX_CHARS 64
+ * #define RXDEMO_BUFF_BYTES 512
+ * #define RXDEMO_CODE_SUCCESS 0
+ * #define RXDEMO_CODE_CANT_OPEN 1
+ * #define RXDEMO_CODE_CANT_STAT 2
+ * #define RXDEMO_CODE_CANT_READ 3
+ * #define RXDEMO_CODE_WRITE_ERROR 4
+ * \endcode
+ *
+ * \par
+ * After this preamble, the first server-side stub appears. This RXDEMO Add()
+ * routine is basically the inverse of the RXDEMO Add() client-side stub
+ * defined in rxdemo.cs.c. Its job is to unmarshall the IN parameters for the
+ * call, invoke the "true" server-side RXDEMO Add() routine (defined in rxdemo
+ * server.c), and then package and ship the OUT parameter. Being so similar to
+ * the client-side RXDEMO Add(), no further discussion is offered here.
+ *
+ * \code
+ * long _RXDEMO_Add(z_call, z_xdrs)
+ * struct rx_call *z_call;
+ * XDR *z_xdrs;
+ * {
+ * long z_result;
+ * int a, b;
+ * int result;
+ * if ((!xdr_int(z_xdrs, &a)) || (!xdr_int(z_xdrs, &b)))
+ * {
+ * z_result = RXGEN_SS_UNMARSHAL;
+ * goto fail;
+ * }
+ * z_result = RXDEMO_Add(z_call, a, b, &result);
+ * z_xdrs->x_op = XDR_ENCODE;
+ * if ((!xdr_int(z_xdrs, &result)))
+ * z_result = RXGEN_SS_MARSHAL;
+ * fail: return z_result;
+ * }
+ * \endcode
+ *
+ * \par
+ * The second server-side stub, RXDEMO Getfile(), appears next. It operates
+ * identically to RXDEMO Add(), first unmarshalling the IN arguments, then
+ * invoking the routine that actually performs the server-side work for the
+ * call, then finishing up by returning the OUT parameters.
+ *
+ * \code
+ * long _RXDEMO_Getfile(z_call, z_xdrs)
+ * struct rx_call *z_call;
+ * XDR *z_xdrs;
+ * {
+ * long z_result;
+ * char * a_nameToRead=(char *)0;
+ * int a_result;
+ * if ((!xdr_string(z_xdrs, &a_nameToRead, RXDEMO_NAME_MAX_CHARS))) {
+ * z_result = RXGEN_SS_UNMARSHAL;
+ * goto fail;
+ * }
+ * z_result = RXDEMO_Getfile(z_call, a_nameToRead, &a_result);
+ * z_xdrs->x_op = XDR_ENCODE;
+ * if ((!xdr_int(z_xdrs, &a_result)))
+ * z_result = RXGEN_SS_MARSHAL;
+ * fail: z_xdrs->x_op = XDR_FREE;
+ * if (!xdr_string(z_xdrs, &a_nameToRead, RXDEMO_NAME_MAX_CHARS))
+ * goto fail1;
+ * return z_result;
+ * fail1: return RXGEN_SS_XDRFREE;
+ * }
+ * \endcode
+ *
+ * \par
+ * The next portion of the automatically generated server-side module sets up
+ * the dispatcher routine for incoming Rx calls. The above stub routines are
+ * placed into an array in opcode order.
+ *
+ * \code
+ * long _RXDEMO_Add();
+ * long _RXDEMO_Getfile();
+ * static long (*StubProcsArray0[])() = {_RXDEMO_Add, _RXDEMO_Getfile};
+ * \endcode
+ *
+ * \par
+ * The dispatcher routine itself, RXDEMO ExecuteRequest, appears next. This is
+ * the function provided to the rx NewService() call in rxdemo server.c, and it
+ * is used as the body of each listener thread's service loop. When activated,
+ * it decodes the first longword in the given Rx call, which contains the
+ * opcode. It then dispatches the call based on this opcode, invoking the
+ * appropriate server-side stub as organized in the StubProcsArray.
+ *
+ * \code
+ * RXDEMO_ExecuteRequest(z_call)
+ * register struct rx_call *z_call;
+ * {
+ * int op;
+ * XDR z_xdrs;
+ * long z_result;
+ * xdrrx_create(&z_xdrs, z_call, XDR_DECODE);
+ * if (!xdr_int(&z_xdrs, &op))
+ * z_result = RXGEN_DECODE;
+ * else if (op < RXDEMO_LOWEST_OPCODE || op > RXDEMO_HIGHEST_OPCODE)
+ * z_result = RXGEN_OPCODE;
+ * else
+ * z_result = (*StubProcsArray0[op -RXDEMO_LOWEST_OPCODE])(z_call,
+ * &z_xdrs);
+ * return z_result;
+ * }
+ * \endcode
+ *
+ * \subsection sec6-3-3 External Data Rep file: rxdemo.xdr.c
+ *
+ * \par
+ * This file is created to provide the special routines needed to map any
+ * user-defined structures appearing as Rx arguments into and out of network
+ * byte order. Again, all on-thewire data appears in network byte order,
+ * insuring proper communication between servers and clients with different
+ * memory organizations.
+ * \par
+ * Since the rxdemo example application does not define any special structures
+ * to pass as arguments in its calls, this generated file contains only the set
+ * of definitions appearing in the interface file. In general, though, should
+ * the user define a struct xyz and use it as a parameter to an RPC function,
+ * this file would contain a routine named xdr xyz(), which converted the
+ * structure field-by-field to and from network byte order.
+ *
+ * \code
+ * /*======================================================================%
+ * %% % in the documentation or other materials mentioning features or % %
+ * use of this software. Neither the name of Transarc nor the names % % of
+ * its contributors may be used to endorse or promote products % % derived
+ * from this software without specific prior written % % permission. % % %
+ * % THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED %
+ * % WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF %
+ * % MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. %
+ * % Edward R. Zayas % Transarc Corporation % % % The United States
+ * Government has rights in this work pursuant to contract no.
+ * MDA972-90-C-0036 between the United States Defense % Advanced Research
+ * Projects Agency and Transarc Corporation. % % (C) Copyright 1991 Transarc
+ * Corporation % % Redistribution and use in source and binary forms are
+ * permitted % % provided that: (1) source distributions retain this entire
+ * copy¬ % right notice and comment, and (2) distributions including binaries
+ * % % display the following acknowledgement: % % % % ``This product includes
+ * software developed by Transarc % % Corporation and its contributors'' %
+ * %====================================================================== */
+ * /* Machine generated file --Do NOT edit */
+ *
+ * #include "rxdemo.h"
+ * #include <rx/rx.h>
+ * #include <rx/rx_null.h>
+ * #define RXDEMO_SERVER_PORT 8000 /* Service port to advertise */
+ * #define RXDEMO_SERVICE_PORT 0 /* User server's port */
+ * #define RXDEMO_SERVICE_ID 4 /* Service ID */
+ * #define RXDEMO_NULL_SECOBJ_IDX 0 /* Index of null security object */
+ * #define RXDEMO_MAX 3
+ * #define RXDEMO_MIN 2
+ * #define RXDEMO_NULL 0
+ * #define RXDEMO_NAME_MAX_CHARS 64
+ * #define RXDEMO_BUFF_BYTES 512
+ * #define RXDEMO_CODE_SUCCESS 0
+ * #define RXDEMO_CODE_CANT_OPEN 1
+ * #define RXDEMO_CODE_CANT_STAT 2
+ * #define RXDEMO_CODE_CANT_READ 3
+ * #define RXDEMO_CODE_WRITE_ERROR 4
+ * \endcode
+ *
+ * \section sec6-4 Section 6.4: Sample Output
+ *
+ * \par
+ * This section contains the output generated by running the example rxdemo
+ * server and rxdemo client programs described above. The server end was run on
+ * a machine named Apollo, and the client program was run on a machine named
+ * Bigtime.
+ * \par
+ * The server program on Apollo was started as follows:
+ * \li apollo: rxdemo_server
+ * \li rxdemo_server: Example Rx server process
+ * \li Listening on UDP port 8000
+ * \par
+ * At this point, rxdemo server has initialized its Rx module and started up
+ * its listener LWPs, which are sleeping on the arrival of an RPC from any
+ * rxdemo client.
+ * \par
+ * The client portion was then started on Bigtime:
+ * \n bigtime: rxdemo_client apollo
+ * \n rxdemo: Example Rx client process
+ * \n Connecting to Rx server on 'apollo', IP address 0x1acf37c0, UDP port 8000
+ * \n ---> Connected. Asking server to add 1 and 2: Reported sum is 3
+ * \par
+ * The command line instructs rxdemo client to connect to the rxdemo server on
+ * host apollo and to use the standard port defined for this service. It
+ * reports on the successful Rx connection establishment, and immediately
+ * executes an rxdemo Add(1, 2) RPC. It reports that the sum was successfully
+ * received. When the RPC request arrived at the server and was dispatched by
+ * the rxdemo server code, it printed out the following line:
+ * \n [Handling call to RXDEMO_Add(1, 2)]
+ * \par
+ * Next, rxdemo client prompts for the name of the file to read from the rxdemo
+ * server. It is told to fetch the Makefile for the Rx demo directory. The
+ * server is executing in the same directory in which it was compiled, so an
+ * absolute name for the Makefile is not required. The client echoes the
+ * following:
+ * \n Name of file to read from server: Makefile Setting up an Rx call for
+ * RXDEMO_Getfile...done
+ * \par
+ * As with the rxdemo Add() call, rxdemo server receives this RPC, and prints
+ * out the following information:
+ * \li [Handling call to RXDEMO_Getfile(Makefile)]
+ * \li [file opened]
+ * \li [file has 2450 bytes]
+ * \li [file closed]
+ * \par
+ * It successfully opens the named file, and reports on its size in bytes. The
+ * rxdemo server program then executes the streamed portion of the rxdemo
+ * Getfile call, and when complete, indicates that the file has been closed.
+ * Meanwhile, rxdemo client prints out the reported size of the file, follows
+ * it with the file's contents, then advises that the test run has completed:
+ *
+ * \code
+ * [file contents (2450 bytes) fetched over the Rx call appear below]
+ *
+ * /*#=======================================================================#
+ * # The United States Government has rights in this work pursuant # # to
+ * contract no. MDA972-90-C-0036 between the United States Defense # # Advanced
+ * Research Projects Agency and Transarc Corporation. # # # # (C) Copyright
+ * 1991 Transarc Corporation # # # # Redistribution and use in source and
+ * binary forms are permitted # # provided that: (1) source distributions
+ * retain this entire copy-# # right notice and comment, and (2) distributions
+ * including binaries # # display the following acknowledgement: # # # # ''This
+ * product includes software developed by Transarc # # Corporation and its
+ * contributors'' # # # # in the documentation or other materials mentioning
+ * features or # # use of this software. Neither the name of Transarc nor the
+ * names # # of its contributors may be used to endorse or promote products #
+ * # derived from this software without specific prior written # # permission.
+ * # # # # THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
+ * # # WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF # #
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. #
+ * #=======================================================================# */
+ *
+ * SHELL = /bin/sh
+ * TOOL_CELL = grand.central.org
+ * AFS_INCLIB_CELL = transarc.com
+ * USR_CONTRIB = /afs/${TOOL_CELL}/darpa/usr/contrib/
+ * PROJ_DIR = ${USR_CONTRIB}.site/grand.central.org/rxdemo/
+ * AFS_INCLIB_DIR = /afs/${AFS_INCLIB_CELL}/afs/dest/
+ * RXGEN = ${AFS_INCLIB_DIR}bin/rxgen
+ * INSTALL = ${AFS_INCLIB_DIR}bin/install
+ * LIBS = ${AFS_INCLIB_DIR}lib/librx.a \ ${AFS_INCLIB_DIR}lib/liblwp.a
+ * CFLAGS = -g \
+ * -I. \
+ * -I${AFS_INCLIB_DIR}include \
+ * -I${AFS_INCLIB_DIR}include/afs \
+ * -I${AFS_INCLIB_DIR} \
+ * -I/usr/include
+ *
+ * system: install
+ *
+ * install: all
+ * ${INSTALL} rxdemo_client ${PROJ_DIR}bin
+ * ${INSTALL} rxdemo_server ${PROJ_DIR}bin
+ *
+ * all: rxdemo_client rxdemo_server
+ *
+ * rxdemo_client: rxdemo_client.o ${LIBS} rxdemo.cs.o ${CC} ${CFLAGS}
+ * -o rxdemo_client rxdemo_client.o rxdemo.cs.o ${LIBS}
+ *
+ * rxdemo_server: rxdemo_server.o rxdemo.ss.o ${LIBS} ${CC} ${CFLAGS}
+ * -o rxdemo_server rxdemo_server.o rxdemo.ss.o ${LIBS}
+ *
+ * rxdemo_client.o: rxdemo.h
+ *
+ * rxdemo_server.o: rxdemo.h
+ *
+ * rxdemo.cs.c rxdemo.ss.c rxdemo.er.c rxdemo.h: rxdemo.xg rxgen rxdemo.xg
+ *
+ * clean: rm -f *.o rxdemo.cs.c rxdemo.ss.c rxdemo.xdr.c rxdemo.h \
+ * rxdemo_client rxdemo_server core
+ *
+ * [End of file data]
+ * rxdemo complete.
+ * \endcode
+ *
+ * \par
+ * The rxdemo server program continues to run after handling these calls,
+ * offering its services to any other callers. It can be killed by sending it
+ * an interrupt signal using Control-C (or whatever mapping has been set up for
+ * the shell's interrupt character).
+ *
+ * \section Bibliography Bibliography
+ *
+ * \li [1] Transarc Corporation. AFS 3.0 System Administrator's Guide,
+ * F-30-0-D102, Pittsburgh, PA, April 1990.
+ * \li [2] S.P. Miller, B.C. Neuman, J.I. Schiller, J.H. Saltzer. Kerberos
+ * Authentication and Authorization System, Project Athena Technical Plan,
+ * Section E.2.1, M.I.T., December 1987.
+ * \li [3] Bill Bryant. Designing an Authentication System: a Dialogue
+ * in Four Scenes, Project Athena internal document, M.I.T, draft of 8 February
+ * 1988.
+ * \li [4] S. R. Kleinman. Vnodes: An Architecture for Multiple file
+ * System Types in Sun UNIX, Conference Proceedings, 1986 Summer Usenix
+ * Technical Conference, pp. 238-247, El Toro, CA, 1986.
+ *
+ */
--- /dev/null
+/*!
+
+ \page title AFS-3 Programmer's Reference: Volume Server/Volume Location
+Server Interface
+
+ \author Edward R. Zayas
+Transarc Corporation
+\version 1.0
+\date 29 August 1991 14:48 Copyright 1991 Transarc Corporation All Rights
+Reserved FS-00-D165
+
+
+ \page chap1 Chapter 1: Overview
+
+ \section sec1-1 Section 1.1: Introduction
+
+\par
+This document describes the architecture and interfaces for two of the
+important agents of the AFS distributed file system, the Volume Server and the
+Volume Location Server. The Volume Server allows operations affecting entire
+AFS volumes to be executed, while the Volume Location Server provides a lookup
+service for volumes, identifying the server or set of servers on which volume
+instances reside.
+
+ \section sec1-2 Section 1.2: Volumes
+
+ \subsection sec1-2-1 Section 1.2.1: Definition
+
+\par
+The underlying concept manipulated by the two AFS servers examined by this
+document is the volume. Volumes are the basic mechanism for organizing the data
+stored within the file system. They provide the foundation for addressing,
+storing, and accessing file data, along with serving as the administrative
+units for replication, backup, quotas, and data motion between File Servers.
+\par
+Specifically, a volume is a container for a hierarchy of files, a connected
+file system subtree. In this respect, a volume is much like a traditional unix
+file system partition. Like a partition, a volume can be mounted in the sense
+that the root directory of the volume can be named within another volume at an
+AFS mount point. The entire file system hierarchy is built up in this manner,
+using mount points to glue together the individual subtrees resident within
+each volume. The root of this hierarchy is then mounted by each AFS client
+machine using a conventional unix mount point within the workstation's local
+file system. By convention, this entryway into the AFS domain is mounted on the
+/afs local directory. From a user's point of view, there is only a single mount
+point to the system; the internal mount points are generally transparent.
+
+ \subsection sec1-2-2 Section 1.2.2: Volume Naming
+
+\par
+There are two methods by which volumes may be named. The first is via a
+human-readable string name, and the second is via a 32-bit numerical
+identifier. Volume identifiers, whether string or numerical, must be unique
+within any given cell. AFS mount points may use either representation to
+specify the volume whose root directory is to be accessed at the given
+position. Internally, however, AFS agents use the numerical form of
+identification exclusively, having to translate names to the corresponding
+32-bit value.
+
+ \subsection sec1-2-3 Section 1.2.3: Volume Types
+
+\par
+There are three basic volume types: read-write, read-only, and backup volumes.
+\li Read-write: The data in this volume may be both read and written by those
+clients authorized to do so.
+\li Read-only: It is possible to create one or more read-only snapshots of
+read-write volumes. The read-write volume serving as the source image is
+referred to as the parent volume. Each read-only clone, or child, instance must
+reside on a different unix disk partition than the other clones. Every clone
+instance generated from the same parent read-write volume has the identical
+volume name and numerical volume ID. This is the reason why no two clones may
+appear on the same disk partition, as there would be no way to differentiate
+the two. AFS clients are allowed to read files and directories from read-only
+volumes, but cannot overwrite them individually. However, it is possible to
+make changes to the read-write parent and then release the contents of the
+entire volume to all the read-only replicas. The release operation fails if it
+does not reach the appropriate replication sites.
+\li Backup: A backup volume is a special instance of a read-only volume. While
+it is also a read-only snapshot of a given read-write volume, only one instance
+is allowed to exist at any one time. Also, the backup volume must reside on the
+same partition as the parent read-write volume from which it was created. It is
+from a backup volume that the AFS backup system writes file system data to
+tape. In addition, backup volumes may be mounted into the file tree just like
+the other volume types. In fact, by convention, the backup volume for each
+user's home directory subtree is typically mounted as OldFiles in that
+directory. If a user accidentally deletes a file that resides in the backup
+snapshot, the user may simply copy it out of the backup directly without the
+assistance of a system administrator, or any kind of tape restore operation.
+Backup volume are implemented in a copy-on-write fashion. Thus, backup volumes
+may be envisioned as consisting of a set of pointers to the true data objects
+in the base read-write volume when they are first created. When a file is
+overwritten in the read-write version for the first time after the backup
+volume was created, the original data is physically written to the backup
+volume, breaking the copyon-write link. With this mechanism, backup volumes
+maintain the image of the read-write volume at the time the snapshot was taken
+using the minimum amount of additional disk space.
+
+ \section sec1-3 Section 1.3: Scope
+
+\par
+This paper is a member of a documentation suite providing specifications of the
+operation and interfaces offered by the various AFS servers and agents. The
+scope of this work is to provide readers with a sufficiently detailed
+description of the Volume Location Server and the Volume Server so that they
+may construct client applications which call their RPC interface routines.
+
+ \section sec1-4 Section 1.4: Document Layout
+
+\par
+After this introductory portion of the document, Chapters 2 and 3 examine the
+architecture and RPC interface of the Volume Location Server and its replicated
+database. Similarly, Chapters 4 and 5 describe the architecture and RPC
+interface of the Volume Server.
+
+ \page chap2 Chapter 2: Volume Location Server Architecture
+
+ \section sec2-1 Section 2.1: Introduction
+
+\par
+The Volume Location Server allows AFS agents to query the location and basic
+status of volumes resident within the given cell. Volume Location Server
+functions may be invoked directly from authorized users via the vos utility.
+\par
+This chapter briefly discusses various aspects of the Volume Location Server's
+architecture. First, the need for volume location is examined, and the specific
+parties that call the Volume Location Server interface routines are identified.
+Then, the database maintained to provide volume location service, the Volume
+Location Database (VLDB), is examined. Finally, the vlserver process which
+implements the Volume Location Server is considered.
+\par
+As with all AFS servers, the Volume Location Server uses the Rx remote
+procedure call package for communication with its clients.
+
+ \section sec2-2 Section 2.2: The Need For Volume Location
+
+\par
+The Cache Manager agent is the primary consumer of AFS volume location service,
+on which it is critically dependent for its own operation. The Cache Manager
+needs to map volume names or numerical identifiers to the set of File Servers
+on which its instances reside in order to satisfy the file system requests it
+is processing on behalf of it clients. Each time a Cache Manager encounters a
+mount point for which it does not have location information cached, it must
+acquire this information before the pathname resolution may be successfully
+completed. Once the File Server set is known for a particular volume, the Cache
+Manager may then select the proper site among them (e.g. choosing the single
+home for a read-write volume, or randomly selecting a site from a read-only
+volume's replication set) and begin addressing its file manipulation operations
+to that specific server.
+\par
+While the Cache Manager consults the volume location service, it is not capable
+of changing the location of volumes and hence modifying the information
+contained therein. This capability to perform acts which change volume location
+is concentrated within the Volume Server. The Volume Server process running on
+each server machine manages all volume operations affecting that platform,
+including creations, deletions, and movements between servers. It must update
+the volume location database every time it performs one of these actions.
+\par
+None of the other AFS system agents has a need to access the volume location
+database for its site. Surprisingly, this also applies to the File Server
+process. It is only aware of the specific set of volumes that reside on the set
+of physical disks directly attached to the machine on which they execute. It
+has no knowlege of the universe of volumes resident on other servers, either
+within its own cell or in foreign cells.
+
+ \section sec2-3 Section 2.3: The VLDB
+
+\par
+The Volume Location Database (VLDB) is used to allow AFS application programs
+to discover the location of any volume within its cell, along with select
+information about the nature and state of that volume. It is organized in a
+very straightforward fashion, and uses the ubik [4] [5] facility to to provide
+replication across multiple server sites.
+
+ \subsection sec2-3-1 Section 2.3.1: Layout
+
+\par
+The VLDB itself is a very simple structure, and synchronized copies may be
+maintained at two or more sites. Basically, each copy consists of header
+information, followed by a linear (yet unbounded) array of entries. There are
+several associated hash tables used to perform lookups into the VLDB. The first
+hash table looks up volume location information based on the volume's name.
+There are three other hash tables used for lookup, based on volume ID/type
+pairs, one for each possible volume type.
+\par
+The VLDB for a large site may grow to contain tens of thousands of entries, so
+some attempts were made to make each entry as small as possible. For example,
+server addresses within VLDB entries are represented as single-byte indicies
+into a table containing the full longword IP addresses.
+\par
+A free list is kept for deleted VLDB entries. The VLDB will not grow unless all
+the entries on the free list have been exhausted, keeping it as compact as
+possible.
+
+ \subsection sec2-3-2 Section 2.3.2: Database Replication
+
+\par
+The VLDB, along with other important AFS databases, may be replicated to
+multiple sites to improve its availability. The ubik replication package is
+used to implement this functionality for the VLDB. A full description of ubik
+and of the quorum completion algorithm it implements may be found in [4] and
+[5]. The basic abstraction provided by ubik is that of a disk file replicated
+to multiple server locations. One machine is considered to be the
+synchronization site, handling all write operations on the database file. Read
+operations may be directed to any of the active members of the quorum, namely a
+subset of the replication sites large enough to insure integrity across such
+failures as individual server crashes and network partitions. All of the quorum
+members participate in regular elections to determine the current
+synchronization site. The ubik algorithms allow server machines to enter and
+exit the quorum in an orderly and consistent fashion. All operations to one of
+these replicated "abstract files" are performed as part of a transaction. If
+all the related operations performed under a transaction are successful, then
+the transaction is committed, and the changes are made permanent. Otherwise,
+the transaction is aborted, and all of the operations for that transaction are
+undone.
+
+ \section sec2-4 Section 2.4: The vlserver Process
+
+\par
+The user-space vlserver process is in charge of providing volume location
+service for AFS clients. This program maintains the VLDB replica at its
+particular server, and cooperates with all other vlserver processes running in
+the given cell to propagate updates to the database. It implements the RPC
+interface defined in the vldbint.xg definition file for the rxgen RPC stub
+generator program. As part of its startup sequence, it must discover the VLDB
+version it has on its local disk, move to join the quorum of replication sites
+for the VLDB, and get the latest version if the one it came up with was out of
+date. Eventually, it will synchronize with the other VLDB replication sites,
+and it will begin accepting calls.
+\par
+The vlserver program uses at most three Rx worker threads to listen for
+incoming Volume Location Server calls. It has a single, optional command line
+argument. If the string "-noauth" appears when the program is invoked, then
+vlserver will run in an unauthenticated mode where any individual is considered
+authorized to perform any VLDB operation. This mode is necessary when first
+bootstrapping an AFS installation.
+
+ \page chap3 Chapter 3: Volume Location Server Interface
+
+ \section sec3-1 Section 3.1: Introduction
+
+\par
+This chapter documents the API for the Volume Location Server facility, as
+defined by the vldbint.xg Rxgen interface file and the vldbint.h include file.
+Descriptions of all the constants, structures, macros, and interface functions
+available to the application programmer appear here.
+\par
+It is expected that Volume Location Server client programs run in user space,
+as does the associated vos volume utility. However, the kernel-resident Cache
+Manager agent also needs to call a subset of the Volume Location Server's RPC
+interface routines. Thus, a second Volume Location Server interface is
+available, built exclusively to satisfy the Cache Manager's limited needs. This
+subset interface is defined by the afsvlint.xg Rxgen interface file, and is
+examined in the final section of this chapter.
+
+ \section sec3-2 3.2: Constants
+
+\par
+This section covers the basic constant definitions of interest to the Volume
+Location Server application programmer. These definitions appear in the
+vldbint.h file, automatically generated from the vldbint.xg Rxgen interface
+file, and in vlserver.h.
+\par
+Each subsection is devoted to describing the constants falling into the
+following categories:
+\li Configuration and boundary quantities
+\li Update entry bits
+\li List-by-attribute bits
+\li Volume type indices
+\li States for struct vlentry
+\li States for struct vldbentry
+\li ReleaseType argument values
+\li Miscellaneous items
+
+ \subsection sec3-2-1 Section 3.2.1: Configuration and Boundary
+Quantities
+
+\par
+These constants define some basic system values, including configuration
+information.
+
+\par Name
+MAXNAMELEN
+\par Value
+65
+\par Description
+Maximum size of various character strings, including volume name fields in
+structures and host names.
+
+\par Name
+MAXNSERVERS
+\par Value
+8
+\par Description
+Maximum number of replications sites for a volume.
+
+\par Name
+MAXTYPES
+\par Value
+3
+\par Description
+Maximum number of volume types.
+
+\par Name
+VLDBVERSION
+\par Value
+1
+\par Description
+VLDB database version number
+
+\par Name
+HASHSIZE
+\par Value
+8,191
+\par Description
+Size of internal Volume Location Server volume name and volume ID hash tables.
+This must always be a prime number.
+
+\par Name
+NULLO
+\par Value
+0
+\par Description
+Specifies a null pointer value.
+
+\par Name
+VLDBALLOCCOUNT
+\par Value
+40
+\par Description
+Value used when allocating memory internally for VLDB entry records.
+
+\par Name
+BADSERVERID
+\par Value
+255
+\par Description
+Illegal Volume Location Server host ID.
+
+\par Name
+MAXSERVERID
+\par Value
+30
+\par Description
+Maximum number of servers appearing in the VLDB.
+
+\par Name
+MAXSERVERFLAG
+\par Value
+0x80
+\par Description
+First unused flag value in such fields as serverFlags in struct vldbentry and
+RepsitesNewFlags in struct VldbUpdateEntry.
+
+\par Name
+MAXPARTITIONID
+\par Value
+126
+\par Description
+Maximum number of AFS disk partitions for any one server.
+
+\par Name
+MAXBUMPCOUNT
+\par Value
+0x7fffffff
+\par Description
+Maximum interval that the current high-watermark value for a volume ID can be
+increased in one operation.
+
+\par Name
+MAXLOCKTIME
+\par Value
+0x7fffffff
+\par Description
+Maximum number of seconds that any VLDB entry can remain locked.
+
+\par Name
+SIZE
+\par Value
+1,024
+\par Description
+Maximum size of the name field within a struct.
+
+ \subsection sec3-2-2 Section 3.2.2: Update Entry Bits
+
+\par
+These constants define bit values for the Mask field in the struct
+VldbUpdateEntry. Specifically, setting these bits is equivalent to declaring
+that the corresponding field within an object of type struct VldbUpdateEntry
+has been set. For example, setting the VLUPDATE VOLUMENAME flag in Mask
+indicates that the name field contains a valid value.
+
+\par Name
+VLUPDATE VOLUMENAME
+\par Value
+0x0001
+\par Description
+If set, indicates that the name field is valid.
+
+\par Name
+VLUPDATE VOLUMETYPE
+\par Value
+0x0002
+\par Description
+If set, indicates that the volumeType field is valid.
+
+\par Name
+VLUPDATE FLAGS
+\par Value
+0x0004
+\par Description
+If set, indicates that the flags field is valid.
+
+\par Name
+VLUPDATE READONLYID
+\par Value
+0x0008
+\par Description
+If set, indicates that the ReadOnlyId field is valid.
+
+\par Name
+VLUPDATE BACKUPID
+\par Value
+0x0010
+\par Description
+If set, indicates that the BackupId field is valid.
+
+\par Name
+VLUPDATE REPSITES
+\par Value
+0x0020
+\par Description
+If set, indicates that the nModifiedRepsites field is valid.
+
+\par Name
+VLUPDATE CLONEID
+\par Value
+0x0080
+\par Description
+If set, indicates that the cloneId field is valid.
+
+\par Name
+VLUPDATE REPS DELETE
+\par Value
+0x0100
+\par Description
+Is the replica being deleted?
+
+\par Name
+VLUPDATE REPS ADD
+\par Value
+0x0200
+\par Description
+Is the replica being added?
+
+\par Name
+VLUPDATE REPS MODSERV
+\par Value
+0x0400
+\par Description
+Is the server part of the replica location correct?
+
+\par Name
+VLUPDATE REPS MODPART
+\par Value
+0x0800
+\par Description
+Is the partition part of the replica location correct?
+
+\par Name
+VLUPDATE REPS MODFLAG
+\par Value
+0x1000
+\par Description
+Various modification flag values.
+
+ \subsection sec3-2-3 Section 3.2.3: List-By-Attribute Bits
+
+\par
+These constants define bit values for the Mask field in the struct
+VldbListByAttributes is to be used in a match. Specifically, setting these bits
+is equivalent to declaring that the corresponding field within an object of
+type struct VldbListByAttributes is set. For example, setting the VLLIST SERVER
+flag in Mask indicates that the server field contains a valid value.
+
+\par Name
+VLLIST SERVER
+\par Value
+0x1
+\par Description
+If set, indicates that the server field is valid.
+
+\par Name
+VLLIST PARTITION
+\par Value
+0x2
+\par Description
+If set, indicates that the partition field is valid.
+
+\par Name
+VLLIST VOLUMETYPE
+\par Value
+0x4
+\par Description
+If set, indicates that the volumetype field is valid.
+
+\par Name
+VLLIST VOLUMEID
+\par Value
+0x8
+\par Description
+If set, indicates that the volumeid field is valid.
+
+\par Name
+VLLIST FLAG
+\par Value
+0x10
+\par Description
+If set, indicates that that flag field is valid.
+
+ \subsection sec3-2-4 Section 3.2.4: Volume Type Indices
+
+\par
+These constants specify the order of entries in the volumeid array in an object
+of type struct vldbentry. They also identify the three different types of
+volumes in AFS.
+
+\par Name
+RWVOL
+\par Value
+0
+\par Description
+Read-write volume.
+
+\par Name
+ROVOL
+\par Value
+1
+\par Description
+Read-only volume.
+
+\par Name
+BACKVOL
+\par Value
+2
+\par Description
+Backup volume.
+
+ \subsection sec3-2-5 Section 3.2.5: States for struct vlentry
+
+\par
+The following constants appear in the flags field in objects of type struct
+vlentry. The first three values listed specify the state of the entry, while
+all the rest stamp the entry with the type of an ongoing volume operation, such
+as a move, clone, backup, deletion, and dump. These volume operations are the
+legal values to provide to the voloper parameter of the VL SetLock() interface
+routine.
+\par
+For convenience, the constant VLOP ALLOPERS is defined as the inclusive OR of
+the above values from VLOP MOVE through VLOP DUMP.
+
+\par Name
+VLFREE
+\par Value
+0x1
+\par Description
+Entry is in the free list.
+
+\par Name
+VLDELETED
+\par Value
+0x2
+\par Description
+Entry is soft-deleted.
+
+\par Name
+VLLOCKED
+\par Value
+0x4
+\par Description
+Advisory lock held on the entry.
+
+\par Name
+VLOP MOVE
+\par Value
+0x10
+\par Description
+The associated volume is being moved between servers.
+
+\par Name
+VLOP RELEASE
+\par Value
+0x20
+\par Description
+The associated volume is being cloned to its replication sites.
+
+\par Name
+VLOP BACKUP
+\par Value
+0x40
+\par Description
+A backup volume is being created for the associated volume.
+
+\par Name
+VLOP DELETE
+\par Value
+0x80
+\par Description
+The associated volume is being deleted.
+
+\par Name
+VLOP DUMP
+\par Value
+0x100
+\par Description
+A dump is being taken of the associated volume.
+
+ \subsection sec3-2-6 Section 3.2.6: States for struct vldbentry
+
+\par
+Of the following constants, the first three appear in the flags field within an
+object of type struct vldbentry, advising of the existence of the basic volume
+types for the given volume, and hence the validity of the entries in the
+volumeId array field. The rest of the values provided in this table appear in
+the serverFlags array field, and apply to the instances of the volume appearing
+in the various replication sites.
+\par
+This structure appears in numerous Volume Location Server interface calls,
+namely VL CreateEntry(), VL GetEntryByID(), VL GetEntryByName(), VL
+ReplaceEntry() and VL ListEntry().
+
+\par Name
+VLF RWEXISTS
+\par Value
+0x1000
+\par Description
+The read-write volume ID is valid.
+
+\par Name
+VLF ROEXISTS
+\par Value
+0x2000
+\par Description
+The read-only volume ID is valid.
+
+\par Name
+VLF BACKEXISTS
+\par Value
+0x4000
+\par Description
+The backup volume ID is valid.
+
+\par Name
+VLSF NEWREPSITE
+\par Value
+0x01
+\par Description
+Not used; originally intended to mark an entry as belonging to a
+partially-created volume instance.
+
+\par Name
+VLSF ROVOL
+\par Value
+0x02
+\par Description
+A read-only version of the volume appears at this server.
+
+\par Name
+VLSF RWVOL
+\par Value
+0x02
+\par Description
+A read-write version of the volume appears at this server.
+
+\par Name
+VLSF BACKVOL
+\par Value
+0x08
+\par Description
+A backup version of the volume appears at this server.
+
+ \subsection sec3-2-7 Section 3.2.7: ReleaseType Argument Values
+
+\par
+The following values are used in the ReleaseType argument to various Volume
+Location Server interface routines, namely VL ReplaceEntry(), VL UpdateEntry()
+and VL ReleaseLock().
+
+\par Name
+LOCKREL TIMESTAMP
+\par Value
+1
+\par Description
+Is the LockTimestamp field valid?
+
+\par Name
+LOCKREL OPCODE
+\par Value
+2
+\par Description
+Are any of the bits valid in the flags field?
+
+\par Name
+LOCKREL AFSID
+\par Value
+4
+\par Description
+Is the LockAfsId field valid?
+
+ \subsection sec3-2-8 Section 3.2.8: Miscellaneous
+
+\par
+Miscellaneous values.
+\par Name
+VLREPSITE NEW
+\par Value
+1
+\par Description
+Has a replication site gotten a new release of a volume?
+\par
+A synonym for this constant is VLSF NEWREPSITE.
+
+ \section sec3-3 Section 3.3: Structures and Typedefs
+
+\par
+This section describes the major exported Volume Location Server data
+structures of interest to application programmers, along with the typedefs
+based upon those structures.
+
+ \subsection sec3-3-1 Section 3.3.1: struct vldbentry
+
+\par
+This structure represents an entry in the VLDB as made visible to Volume
+Location Server clients. It appears in numerous Volume Location Server
+interface calls, namely VL CreateEntry(), VL GetEntryByID(), VL
+GetEntryByName(), VL ReplaceEntry() and VL ListEntry().
+\n \b Fields
+\li char name[] - The string name for the volume, with a maximum length of
+MAXNAMELEN (65) characters, including the trailing null.
+\li long volumeType - The volume type, one of RWVOL, ROVOL, or BACKVOL.
+\li long nServers - The number of servers that have an instance of this volume.
+\li long serverNumber[] - An array of indices into the table of servers,
+identifying the sites holding an instance of this volume. There are at most
+MAXNSERVERS (8) of these server sites allowed by the Volume Location Server.
+\li long serverPartition[] - An array of partition identifiers, corresponding
+directly to the serverNumber array, specifying the partition on which each of
+those volume instances is located. As with the serverNumber array,
+serverPartition has up to MAXNSERVERS (8) entries.
+\li long serverFlags[] - This array holds one flag value for each of the
+servers in the previous arrays. Again, there are MAXNSERVERS (8) slots in this
+array.
+\li u long volumeId[] - An array of volume IDs, one for each volume type. There
+are MAXTYPES slots in this array.
+\li long cloneId - This field is used during a cloning operation.
+\li long flags - Flags concerning the status of the fields within this
+structure; see Section 3.2.6 for the bit values that apply.
+
+ \subsection sec3-3-2 Section 3.3.2: struct vlentry
+
+\par
+This structure is used internally by the Volume Location Server to fully
+represent a VLDB entry. The client-visible struct vldbentry represents merely a
+subset of the information contained herein.
+\n \b Fields
+\li u long volumeId[] - An array of volume IDs, one for each of the MAXTYPES of
+volume types.
+\li long flags - Flags concerning the status of the fields within this
+structure; see Section 3.2.6 for the bit values that apply.
+\li long LockAfsId - The individual who locked the entry. This feature has not
+yet been implemented.
+\li long LockTimestamp - Time stamp on the entry lock.
+\li long cloneId - This field is used during a cloning operation.
+\li long AssociatedChain - Pointer to the linked list of associated VLDB
+entries.
+\li long nextIdHash[] - Array of MAXTYPES next pointers for the ID hash table
+pointer, one for each related volume ID.
+\li long nextNameHash - Next pointer for the volume name hash table.
+\li long spares1[] - Two longword spare fields.
+\li char name[] - The volume's string name, with a maximum of MAXNAMELEN (65)
+characters, including the trailing null.
+\li u char volumeType - The volume's type, one of RWVOL, ROVOL, or BACKVOL.
+\li u char serverNumber[] - An array of indices into the table of servers,
+identifying the sites holding an instance of this volume. There are at most
+MAXNSERVERS (8) of these server sites allowed by the Volume Location Server.
+\li u char serverPartition[] - An array of partition identifiers, corresponding
+directly to the serverNumber array, specifying the partition on which each of
+those volume instances is located. As with the serverNumber array,
+serverPartition has up to MAXNSERVERS (8) entries.
+\li u char serverFlags[] - This array holds one flag value for each of the
+servers in the previous arrays. Again, there are MAXNSERVERS (8) slots in this
+array.
+\li u char RefCount - Only valid for read-write volumes, this field serves as a
+reference count, basically the number of dependent children volumes.
+\li char spares2[] - This field is used for 32-bit alignment.
+
+ \subsection sec3-3-3 Section 3.3.3: struct vital vlheader
+
+\par
+This structure defines the leading section of the VLDB header, of type struct
+vlheader. It contains frequently-used global variables and general statistics
+information.
+\n \b Fields
+\li long vldbversion - The VLDB version number. This field must appear first in
+the structure.
+\li long headersize - The total number of bytes in the header.
+\li long freePtr - Pointer to the first free enry in the free list, if any.
+\li long eofPtr - Pointer to the first free byte in the header file.
+\li long allocs - The total number of calls to the internal AllocBlock()
+function directed at this file.
+\li long frees - The total number of calls to the internal FreeBlock() function
+directed at this file.
+\li long MaxVolumeId - The largest volume ID ever granted for this cell.
+\li long totalEntries[] - The total number of VLDB entries by volume type in
+the VLDB. This array has MAXTYPES slots, one for each volume type.
+
+ \subsection sec3-3-4 Section 3.3.4: struct vlheader
+
+\par
+This is the layout of the information stored in the VLDB header. Notice it
+includes an object of type struct vital vlheader described above (see Section
+3.3.3) as the first field.
+\n \b Fields
+\li struct vital vlheader vital header - Holds critical VLDB header
+information.
+\li u long IpMappedAddr[] - Keeps MAXSERVERID+1 mappings of IP addresses to
+relative ones.
+\li long VolnameHash[] - The volume name hash table, with HASHSIZE slots.
+\li long VolidHash[][] - The volume ID hash table. The first dimension in this
+array selects which of the MAXTYPES volume types is desired, and the second
+dimension actually implements the HASHSIZE hash table buckets for the given
+volume type.
+
+ \subsection sec3-3-5 Section 3.3.5: struct VldbUpdateEntry
+
+\par
+This structure is used as an argument to the VL UpdateEntry() routine (see
+Section 3.6.7). Please note that multiple entries can be updated at once by
+setting the appropriate Mask bits. The bit values for this purpose are defined
+in Section 3.2.2.
+\n \b Fields
+\li u long Mask - Bit values determining which fields are to be affected by the
+update operation.
+\li char name[] - The volume name, up to MAXNAMELEN (65) characters including
+the trailing null.
+\li long volumeType - The volume type.
+\li long flags - This field is used in conjuction with Mask (in fact, one of
+the Mask bits determines if this field is valid) to choose the valid fields in
+this record.
+\li u long ReadOnlyId - The read-only ID.
+\li u long BackupId - The backup ID.
+\li long cloneId - The clone ID.
+\li long nModifiedRepsites - Number of replication sites whose entry is to be
+changed as below.
+\li u long RepsitesMask[] - Array of bit masks applying to the up to
+MAXNSERVERS (8) replication sites involved.
+\li long RepsitesTargetServer[] - Array of target servers for the operation, at
+most MAXNSERVERS (8) of them.
+\li long RepsitesTargetPart[] - Array of target server partitions for the
+operation, at most MAXNSERVERS (8) of them.
+\li long RepsitesNewServer[] - Array of new server sites, at most MAXNSERVERS
+(8) of them.
+\li long RepsitesNewPart[] - Array of new server partitions for the operation,
+at most MAXNSERVERS (8) of them.
+\li long RepsitesNewFlags[] - Flags applying to each of the new sites, at most
+MAXNSERVERS (8) of them.
+
+ \subsection sec3-3-6 Section 3.3.6: struct VldbListByAttributes
+
+\par
+This structure is used by the VL ListAttributes() routine (see Section 3.6.11).
+\n \b Fields
+\li u long Mask - Bit mask used to select the following attribute fields on
+which to match.
+\li long server - The server address to match.
+\li long partition - The partition ID to match.
+\li long volumetype - The volume type to match.
+\li long volumeid - The volume ID to match.
+\li long flag - Flags concerning these values.
+
+ \subsection sec3-3-7 Section 3.3.7: struct single vldbentry
+
+\par
+This structure is used to construct the vldblist object (See Section 3.3.12),
+which basically generates a queueable (singly-linked) version of struct
+vldbentry.
+\n \b Fields
+\li vldbentry VldbEntry - The VLDB entry to be queued.
+\li vldblist next vldb - The next pointer in the list.
+
+ \subsection sec3-3-8 Section 3.3.8: struct vldb list
+
+\par
+This structure defines the item returned in linked list form from the VL
+LinkedList() function (see Section 3.6.12). This same object is also returned
+in bulk form in calls to the VL ListAttributes() routine (see Section 3.6.11).
+\n \b Fields
+\li vldblist node - The body of the first object in the linked list.
+
+ \subsection sec3-3-9 Section 3.3.9: struct vldstats
+
+\par
+This structure defines fields to record statistics on opcode hit frequency. The
+MAX NUMBER OPCODES constant has been defined as the maximum number of opcodes
+supported by this structure, and is set to 30.
+\n \b Fields
+\li unsigned long start time - Clock time when opcode statistics were last
+cleared.
+\li long requests[] - Number of requests received for each of the MAX NUMBER
+OPCODES opcode types.
+\li long aborts[] - Number of aborts experienced for each of the MAX NUMBER
+OPCODES opcode types.
+\li long reserved[] - These five longword fields are reserved for future use.
+
+ \subsection sec3-3-10 Section 3.3.10: bulk
+
+\code
+typedef opaque bulk<DEFAULTBULK>;
+\endcode
+\par
+This typedef may be used to transfer an uninterpreted set of bytes across the
+Volume Location Server interface. It may carry up to DEFAULTBULK (10,000)
+bytes.
+\n \b Fields
+\li bulk len - The number of bytes contained within the data pointed to by the
+next field.
+\li bulk val - A pointer to a sequence of bulk len bytes.
+
+ \subsection sec3-3-11 Section 3.3.11: bulkentries
+
+\code
+typedef vldbentry bulkentries<>;
+\endcode
+\par
+This typedef is used to transfer an unbounded number of struct vldbentry
+objects. It appears in the parameter list for the VL ListAttributes() interface
+function.
+\n \b Fields
+\li bulkentries len - The number of vldbentry structures contained within the
+data pointed to by the next field.
+\li bulkentries val - A pointer to a sequence of bulkentries len vldbentry
+structures.
+
+ \subsection sec3-3-12 Section 3.3.12: vldblist
+
+\code
+typedef struct single_vldbentry *vldblist;
+\endcode
+\par
+This typedef defines a queueable struct vldbentry object, referenced by the
+single vldbentry typedef as well as struct vldb list.
+
+ \subsection sec3-3-13 Section 3.3.13: vlheader
+
+\code
+typedef struct vlheader vlheader;
+\endcode
+\par
+This typedef provides a short name for objects of type struct vlheader (see
+Section 3.3.4).
+
+ \subsection sec3-3-14 Section 3.3.14: vlentry
+
+\code
+typedef struct vlentry vlentry;
+\endcode
+\par
+This typedef provides a short name for objects of type struct vlentry (see
+Section 3.3.2).
+
+ \section sec3-4 Section 3.4: Error Codes
+
+\par
+This section covers the set of error codes exported by the Volume Location
+Server, displaying the printable phrases with which they are associated.
+
+\par Name
+VL IDEXIST
+\par Value
+(363520L)
+\par Description
+Volume Id entry exists in vl database.
+
+\par Name
+VL IO
+\par Value
+(363521L)
+\par Description
+I/O related error.
+
+\par Name
+VL NAMEEXIST
+\par Value
+(363522L)
+\par Description
+Volume name entry exists in vl database.
+
+\par Name
+VL CREATEFAIL
+\par Value
+(363523L)
+\par Description
+Internal creation failure.
+
+\par Name
+VL NOENT
+\par Value
+(363524L)
+\par Description
+No such entry.
+
+\par Name
+VL EMPTY
+\par Value
+(363525L)
+\par Description
+Vl database is empty.
+
+\par Name
+VL ENTDELETED
+\par Value
+(363526L)
+\par Description
+Entry is deleted (soft delete).
+
+\par Name
+VL BADNAME
+\par Value
+(363527L)
+\par Description
+Volume name is illegal.
+
+\par Name
+VL BADINDEX
+\par Value
+(363528L)
+\par Description
+Index is out of range.
+
+\par Name
+VL BADVOLTYPE
+\par Value
+(363529L)
+\par Description
+Bad volume range.
+
+\par Name
+VL BADSERVER
+\par Value
+(363530L)
+\par Description
+Illegal server number (out of range).
+
+\par Name
+VL BADPARTITION
+\par Value
+(363531L)
+\par Description
+Bad partition number.
+
+\par Name
+VL REPSFULL
+\par Value
+(363532L)
+\par Description
+Run out of space for Replication sites.
+
+\par Name
+VL NOREPSERVER
+\par Value
+(363533L)
+\par Description
+No such Replication server site exists.
+
+\par Name
+VL DUPREPSERVER
+\par Value
+(363534L)
+\par Description
+Replication site already exists.
+
+\par Name
+RL RWNOTFOUND
+\par Value
+(363535L)
+\par Description
+Parent R/W entry not found.
+
+\par Name
+VL BADREFCOUNT
+\par Value
+(363536L)
+\par Description
+Illegal Reference Count number.
+
+\par Name
+VL SIZEEXCEEDED
+\par Value
+(363537L)
+\par Description
+Vl size for attributes exceeded.
+
+\par Name
+VL BADENTRY
+\par Value
+(363538L)
+\par Description
+Bad incoming vl entry.
+
+\par Name
+VL BADVOLIDBUMP
+\par Value
+(363539L)
+\par Description
+Illegal max volid increment.
+
+\par Name
+VL IDALREADYHASHED
+\par Value
+(363540L)
+\par Description
+RO/BACK id already hashed.
+
+\par Name
+VL ENTRYLOCKED
+\par Value
+(363541L)
+\par Description
+Vl entry is already locked.
+
+\par Name
+VL BADVOLOPER
+\par Value
+(363542L)
+\par Description
+Bad volume operation code.
+
+\par Name
+VL BADRELLOCKTYPE
+\par Value
+(363543L)
+\par Description
+Bad release lock type.
+
+\par Name
+VL RERELEASE
+\par Value
+(363544L)
+\par Description
+Status report: last release was aborted.
+
+\par Name
+VL BADSERVERFLAG
+\par Value
+(363545L)
+\par Description
+Invalid replication site server flag.
+
+\par Name
+VL PERM
+\par Value
+(363546L)
+\par Description
+No permission access.
+
+\par Name
+VL NOMEM
+\par Value
+(363547L)
+\par Description
+malloc(realloc) failed to alloc enough memory.
+
+ \section sec3-5 Section 3.5: Macros
+
+\par
+The Volume Location Server defines a small number of macros, as described in
+this section. They are used to update the internal statistics variables and to
+compute offsets into character strings. All of these macros really refer to
+internal operations, and strictly speaking should not be exposed in this
+interface.
+
+ \subsection sec3-5-1 Section 3.5.1: COUNT REQ()
+
+\code
+#define COUNT_REQ(op)
+static int this_op = op-VL_LOWEST_OPCODE;
+dynamic_statistics.requests[this_op]++
+\endcode
+\par
+Bump the appropriate entry in the variable maintaining opcode usage statistics
+for the Volume Location Server. Note that a static variable is set up to record
+this op, namely the index into the opcode monitoring array. This static
+variable is used by the related COUNT ABO() macro defined below.
+
+ \subsection sec3-5-2 Section 3.5.2: COUNT ABO()
+
+\code
+#define COUNT_ABO dynamic_statistics.aborts[this_op]++
+\endcode
+\par
+Bump the appropriate entry in the variable maintaining opcode abort statistics
+for the Volume Location Server. Note that this macro does not take any
+arguemnts. It expects to find a this op variable in its environment, and thus
+depends on its related macro, COUNT REQ() to define that variable.
+
+ \subsection sec3-5-3 Section 3.5.3: DOFFSET()
+
+\code
+#define DOFFSET(abase, astr, aitem) ((abase)+(((char *)(aitem)) -((char
+*)(astr))))
+\endcode
+\par
+Compute the byte offset of charcter object aitem within the enclosing object
+astr, also expressed as a character-based object, then offset the resulting
+address by abase. This macro is used ot compute locations within the VLDB when
+actually writing out information.
+
+ \section sec3-6 Section 3.6: Functions
+
+\par
+This section covers the Volume Location Server RPC interface routines. The
+majority of them are generated from the vldbint.xg Rxgen file, and are meant to
+be used by user-space agents. There is also a subset interface definition
+provided in the afsvlint.xg Rxgen file. These routines, described in Section
+3.7, are meant to be used by a kernel-space agent when dealing with the Volume
+Location Server; in particular, they are called by the Cache Manager.
+
+ \subsection sec3-6-1 Section 3.6.1: VL CreateEntry - Create a VLDB
+entry
+
+\code
+int VL CreateEntry(IN struct rx connection *z conn,
+ IN vldbentry *newentry)
+\endcode
+\par Description
+This function creates a new entry in the VLDB, as specified in the newentry
+argument. Both the name and numerical ID of the new volume must be unique
+(e.g., it must not already appear in the VLDB). For non-read-write entries, the
+read-write parent volume is accessed so that its reference count can be
+updated, and the new entry is added to the parent's chain of associated
+entries.
+The VLDB is write-locked for the duration of this operation.
+\par Error Codes
+VL PERM The caller is not authorized to execute this function. VL NAMEEXIST The
+volume name already appears in the VLDB. VL CREATEFAIL Space for the new entry
+cannot be allocated within the VLDB. VL BADNAME The volume name is invalid. VL
+BADVOLTYPE The volume type is invalid. VL BADSERVER The indicated server
+information is invalid. VL BADPARTITION The indicated partition information is
+invalid. VL BADSERVERFLAG The server flag field is invalid. VL IO An error
+occurred while writing to the VLDB.
+
+ \subsection sec3-6-2 Section 3.6.2: VL DeleteEntry - Delete a VLDB
+entry
+
+\code
+int VL DeleteEntry(IN struct rx connection *z conn,
+ IN long Volid,
+ IN long voltype)
+\endcode
+\par Description
+Delete the entry matching the given volume identifier and volume type as
+specified in the Volid and voltype arguments. For a read-write entry whose
+reference count is greater than 1, the entry is not actually deleted, since at
+least one child (read-only or backup) volume still depends on it. For cases of
+non-read-write volumes, the parent's reference count and associated chains are
+updated.
+\par
+If the associated VLDB entry is already marked as deleted (i.e., its flags
+field has the VLDELETED bit set), then no further action is taken, and VL
+ENTDELETED is returned. The VLDB is write-locked for the duration of this
+operation.
+\par Error Codes
+VL PERM The caller is not authorized to execute this function. VL BADVOLTYPE An
+illegal volume type has been specified by the voltype argument. VL NOENT This
+volume instance does not appear in the VLDB. VL ENTDELETED The given VLDB entry
+has already been marked as deleted. VL IO An error occurred while writing to
+the VLDB.
+
+ \subsection sec3-6-3 Section 3.6.3: VL GetEntryByID - Get VLDB entry by
+volume ID/type
+
+\code
+int VL GetEntryByID(IN struct rx connection *z conn, IN long Volid, IN long
+voltype, OUT vldbentry *entry)
+\endcode
+\par Description
+Given a volume's numerical identifier (Volid) and type (voltype), return a
+pointer to the entry in the VLDB describing the given volume instance.
+\par
+The VLDB is read-locked for the duration of this operation.
+\par Error Codes
+VL BADVOLTYPE An illegal volume type has been specified by the voltype
+argument.
+\n VL NOENT This volume instance does not appear in the VLDB.
+\n VL ENTDELETED The given VLDB entry has already been marked as deleted.
+
+ \subsection sec3-6-4 Section 3.6.4: VL GetEntryByName - Get VLDB entry
+by volume name
+
+\code
+int VL GetEntryByName(IN struct rx connection *z conn,
+ IN char *volumename,
+ OUT vldbentry *entry)
+\endcode
+\par Description
+Given the volume name in the volumename parameter, return a pointer to the
+entry in the VLDB describing the given volume. The name in volumename may be no
+longer than MAXNAMELEN (65) characters, including the trailing null. Note that
+it is legal to use the volume's numerical identifier (in string form) as the
+volume name.
+\par
+The VLDB is read-locked for the duration of this operation.
+\par
+This function is closely related to the VL GetEntryByID() routine, as might be
+expected. In fact, the by-ID routine is called if the volume name provided in
+volumename is the string version of the volume's numerical identifier.
+\par Error Codes
+VL BADVOLTYPE An illegal volume type has been specified by the voltype
+argument.
+\n VL NOENT This volume instance does not appear in the VLDB.
+\n VL ENTDELETED The given VLDB entry has already been marked as deleted.
+\n VL BADNAME The volume name is invalid.
+
+ \subsection sec3-6-5 Section 3.6.5: VL GetNewVolumeId - Generate a new
+volume ID
+
+\code
+int VL GetNewVolumeId(IN struct rx connection *z conn,
+ IN long bumpcount,
+ OUT long *newvolumid)
+\endcode
+\par Description
+Acquire bumpcount unused, consecutively-numbered volume identifiers from the
+Volume Location Server. The lowest-numbered of the newly-acquired set is placed
+in the newvolumid argument. The largest number of volume IDs that may be
+generated with any one call is bounded by the MAXBUMPCOUNT constant defined in
+Section 3.2.1. Currently, there is (effectively) no restriction on the number
+of volume identifiers that may thus be reserved in a single call.
+\par
+The VLDB is write-locked for the duration of this operation.
+\par Error Codes
+VL PERM The caller is not authorized to execute this function.
+\n VL BADVOLIDBUMP The value of the bumpcount parameter exceeds the system
+limit of MAXBUMPCOUNT.
+\n VL IO An error occurred while writing to the VLDB.
+
+ \subsection sec3-6-6 Section 3.6.6: VL ReplaceEntry - Replace entire
+contents of VLDB entry
+
+\code
+int VL ReplaceEntry(IN struct rx connection *z conn,
+ IN long Volid,
+ IN long voltype,
+ IN vldbentry *newentry,
+ IN long ReleaseType)
+\endcode
+\par Description
+Perform a wholesale replacement of the VLDB entry corresponding to the volume
+instance whose identifier is Volid and type voltype with the information
+contained in the newentry argument. Individual VLDB entry fields cannot be
+selectively changed while the others are preserved; VL UpdateEntry() should be
+used for this objective. The permissible values for the ReleaseType parameter
+are defined in Section 3.2.7.
+\par
+The VLDB is write-locked for the duration of this operation. All of the hash
+tables impacted are brought up to date to incorporate the new information.
+\par Error Codes
+VL PERM The caller is not authorized to execute this function.
+\n VL BADVOLTYPE An illegal volume type has been specified by the voltype
+argument.
+\n VL BADRELLOCKTYPE An illegal release lock has been specified by the
+ReleaseType argument.
+\n VL NOENT This volume instance does not appear in the VLDB.
+\n VL BADENTRY An attempt was made to change a read-write volume ID.
+\n VL IO An error occurred while writing to the VLDB.
+
+ \subsection sec3-6-7 Section 3.6.7: VL UpdateEntry - Update contents of
+VLDB entry
+
+\code
+int VL UpdateEntry(IN struct rx connection *z conn,
+ IN long Volid,
+ IN long voltype,
+ IN VldbUpdateEntry *UpdateEntry,
+ IN long ReleaseType)
+\endcode
+\par Description
+Update the VLDB entry corresponding to the volume instance whose identifier is
+Volid and type voltype with the information contained in the UpdateEntry
+argument. Most of the entry's fields can be modified in a single call to VL
+UpdateEntry(). The Mask field within the UpdateEntry parameter selects the
+fields to update with the values stored within the other UpdateEntry fields.
+Permissible values for the ReleaseType parameter are defined in Section 3.2.7.
+\par
+The VLDB is write-locked for the duration of this operation.
+\par Error Codes
+VL PERM The caller is not authorized to execute this function.
+\n VL BADVOLTYPE An illegal volume type has been specified by the voltype
+argument.
+\n VL BADRELLOCKTYPE An illegal release lock has been specified by the
+ReleaseType argument.
+\n VL NOENT This volume instance does not appear in the VLDB.
+\n VL IO An error occurred while writing to the VLDB.
+
+ \subsection sec3-6-8 Section 3.6.8: VL SetLock - Lock VLDB entry
+
+\code
+int VL SetLock(IN struct rx connection *z conn,
+ IN long Volid,
+ IN long voltype,
+ IN long voloper)
+\endcode
+\par Description
+Lock the VLDB entry matching the given volume ID (Volid) and type (voltype) for
+volume operation voloper (e.g., VLOP MOVE and VLOP RELEASE). If the entry is
+currently unlocked, then its LockTimestamp will be zero. If the lock is
+obtained, the given voloper is stamped into the flags field, and the
+LockTimestamp is set to the time of the call.
+\Note
+When the caller attempts to lock the entry for a release operation, special
+care is taken to abort the operation if the entry has already been locked for
+this operation, and the existing lock has timed out. In this case, VL SetLock()
+returns VL RERELEASE.
+\par
+The VLDB is write-locked for the duration of this operation.
+\par Error Codes
+VL PERM The caller is not authorized to execute this function.
+\n VL BADVOLTYPE An illegal volume type has been specified by the voltype
+argument.
+\n VL BADVOLOPER An illegal volume operation was specified in the voloper
+argument. Legal values are defined in the latter part of the table in Section
+3.2.5.
+\n VL ENTDELETED The given VLDB entry has already been marked as deleted.
+\n VL ENTRYLOCKED The given VLDB entry has already been locked (which has not
+yet timed out).
+\n VL RERELEASE A VLDB entry locked for release has timed out, and the caller
+also wanted to perform a release operation on it.
+\n VL IO An error was experienced while attempting to write to the VLDB.
+
+ \subsection sec3-6-9 Section 3.6.9: VL ReleaseLock - Unlock VLDB entry
+
+\code
+int VL ReleaseLock(IN struct rx connection *z conn,
+ IN long Volid,
+ IN long voltype,
+ IN long ReleaseType)
+\endcode
+\par Description
+Unlock the VLDB entry matching the given volume ID (Volid) and type (voltype).
+The ReleaseType argument determines which VLDB entry fields from flags and
+LockAfsId will be cleared along with the lock timestamp in LockTimestamp.
+Permissible values for the ReleaseType parameter are defined in Section 3.2.7.
+\par
+The VLDB is write-locked for the duration of this operation.
+\par Error Codes
+VL PERM The caller is not authorized to execute this function.
+\n VL BADVOLTYPE An illegal volume type has been specified by the voltype
+argument.
+\n VL BADRELLOCKTYPE An illegal release lock has been specified by the
+ReleaseType argument.
+\n VL NOENT This volume instance does not appear in the VLDB.
+\n VL ENTDELETED The given VLDB entry has already been marked as deleted.
+\n VL IO An error was experienced while attempting to write to the VLDB.
+
+ \subsection sec3-6-10 Section 3.6.10: VL ListEntry - Get contents of
+VLDB via index
+
+\code
+int VL ListEntry(IN struct rx connection *z conn,
+ IN long previous index,
+ OUT long *count,
+ OUT long *next index,
+ OUT vldbentry *entry)
+\endcode
+\par Description
+This function assists in the task of enumerating the contents of the VLDB.
+Given an index into the database, previous index, this call return the single
+VLDB entry at that offset, placing it in the entry argument. The number of VLDB
+entries left to list is placed in count, and the index of the next entry to
+request is returned in next index. If an illegal index is provided, count is
+set to -1.
+\par
+The VLDB is read-locked for the duration of this operation.
+\par Error Codes
+---None.
+
+ \subsection sec3-6-11 Section 3.6.11: VL ListAttributes - List all VLDB
+entry matching given attributes, single return object
+
+\code
+int VL ListAttributes(IN struct rx connection *z conn,
+ IN VldbListByAttributes *attributes,
+ OUT long *nentries,
+ OUT bulkentries *blkentries)
+\endcode
+\par Description
+Retrieve all the VLDB entries that match the attributes listed in the
+attributes parameter, placing them in the blkentries object. The number of
+matching entries is placed in nentries. Matching can be done by server number,
+partition, volume type, flag, or volume ID. The legal values to use in the
+attributes argument are listed in Section 3.2.3. Note that if the VLLIST
+VOLUMEID bit is set in attributes, all other bit values are ignored and the
+volume ID provided is the sole search criterion.
+\par
+The VLDB is read-locked for the duration of this operation.
+\par
+Note that VL ListAttributes() is a potentially expensive function, as
+sequential search through all of the VLDB entries is performed in most cases.
+\par Error Codes
+VL NOMEM Memory for the blkentries object could not be allocated.
+\n VL NOENT This specified volume instance does not appear in the VLDB.
+\n VL SIZEEXCEEDED Ran out of room in the blkentries object.
+\n VL IO Error while reading from the VLDB.
+
+ \subsection sec3-6-12 Section 3.6.12: VL LinkedList - List all VLDB
+entry matching given attributes, linked list return object
+
+\code
+int VL LinkedList(IN struct rx connection *z conn,
+ IN VldbListByAttributes *attributes,
+ OUT long *nentries,
+ OUT vldb list *linkedentries)
+\endcode
+\par Description
+Retrieve all the VLDB entries that match the attributes listed in the
+attributes parameter, creating a linked list of entries based in the
+linkedentries object. The number of matching entries is placed in nentries.
+Matching can be done by server number, partition, volume type, flag, or volume
+ID. The legal values to use in the attributes argument are listed in Section
+3.2.3. Note that if the VLLIST VOLUMEID bit is set in attributes, all other bit
+values are ignored and the volume ID provided is the sole search criterion.
+\par
+The VL LinkedList() function is identical to the VL ListAttributes(), except
+for the method of delivering the VLDB entries to the caller.
+\par
+The VLDB is read-locked for the duration of this operation.
+\par Error Codes
+VL NOMEM Memory for an entry in the list based at linkedentries object could
+not be allocated.
+\n VL NOENT This specified volume instance does not appear in the VLDB.
+\n VL SIZEEXCEEDED Ran out of room in the current list object.
+\n VL IO Error while reading from the VLDB.
+
+ \subsection sec3-6-13 Section 3.6.13: VL GetStats - Get Volume Location
+Server statistics
+
+\code
+int VL GetStats(IN struct rx connection *z conn,
+ OUT vldstats *stats,
+ OUT vital vlheader *vital header)
+\endcode
+\par Description
+Collect the different types of VLDB statistics. Part of the VLDB header is
+returned in vital header, which includes such information as the number of
+allocations and frees performed, and the next volume ID to be allocated. The
+dynamic per-operation stats are returned in the stats argument, reporting the
+number and types of operations and aborts.
+\par
+The VLDB is read-locked for the duration of this operation.
+\par Error Codes
+VL PERM The caller is not authorized to execute this function.
+
+ \subsection sec3-6-14 Section 3.6.14: VL Probe - Verify Volume Location
+Server connectivity/status
+
+\code
+int VL Probe(IN struct rx connection *z conn)
+\endcode
+\par Description
+This routine serves a 'pinging' function to determine whether the Volume
+Location Server is still running. If this call succeeds, then the Volume
+Location Server is shown to be capable of responding to RPCs, thus confirming
+connectivity and basic operation.
+\par
+The VLDB is not locked for this operation.
+\par Error Codes
+---None.
+
+ \section sec3-7 Section 3.7: Kernel Interface Subset
+
+\par
+The interface described by this document so far applies to user-level clients,
+such as the vos utility. However, some volume location operations must be
+performed from within the kernel. Specifically, the Cache Manager must find out
+where volumes reside and otherwise gather information about them in order to
+conduct its business with the File Servers holding them. In order to support
+Volume Location Server interconnection for agents operating within the kernel,
+the afsvlint.xg Rxgen interface was built. It is a minimal subset of the
+user-level vldbint.xg definition. Within afsvlint.xg, there are duplicate
+definitions for such constants as MAXNAMELEN, MAXNSERVERS, MAXTYPES, VLF
+RWEXISTS, VLF ROEXISTS, VLF BACKEXISTS, VLSF NEWREPSITE, VLSF ROVOL, VLSF
+RWVOL, and VLSF BACKVOL. Since the only operations the Cache Manager must
+perform are volume location given a specific volume ID or name, and to find out
+about unresponsive Volume Location Servers, the following interface routines
+are duplicated in afsvlint.xg, along with the struct vldbentry declaration:
+\li VL GetEntryByID()
+\li VL GetEntryByName()
+\li VL Probe()
+
+ \page chap4 Chapter 4: Volume Server Architecture
+
+ \section sec4-1 Section 4.1: Introduction
+
+\par
+The Volume Server allows administrative tasks and probes to be performed on the
+set of AFS volumes residing on the machine on which it is running. As described
+in Chapter 2, a distributed database holding volume location info, the VLDB, is
+used by client applications to locate these volumes. Volume Server functions
+are typically invoked either directly from authorized users via the vos utility
+or by the AFS backup system.
+\par
+This chapter briefly discusses various aspects of the Volume Server's
+architecture. First, the high-level on-disk representation of volumes is
+covered. Then, the transactions used in conjuction with volume operations are
+examined. Then, the program implementing the Volume Server, volserver, is
+considered. The nature and format of the log file kept by the Volume Server
+rounds out the description.
+As with all AFS servers, the Volume Server uses the Rx remote procedure call
+package for communication with its clients.
+
+ \section sec4-2 Section 4.2: Disk Representation
+
+\par
+For each volume on an AFS partition, there exists a file visible in the unix
+name space which describes the contents of that volume. By convention, each of
+these files is named by concatenating a prefix string, "V", the numerical
+volume ID, and the postfix string ".vol". Thus, file V0536870918.vol describes
+the volume whose numerical ID is 0536870918. Internally, each per-volume
+descriptor file has such fields as a version number, the numerical volume ID,
+and the numerical parent ID (useful for read-only or backup volumes). It also
+has a list of related inodes, namely files which are not visible from the unix
+name space (i.e., they do not appear as entries in any unix directory object).
+The set of important related inodes are:
+\li Volume info inode: This field identifies the inode which hosts the on-disk
+representation of the volume's header. It is very similar to the information
+pointed to by the volume field of the struct volser trans defined in Section
+5.4.1, recording important status information for the volume.
+\li Large vnode index inode: This field identifies the inode which holds the
+list of vnode identifiers for all directory objects residing within the volume.
+These are "large" since they must also hold the Access Control List (ACL)
+information for the given AFS directory.
+\li Small vnode index inode: This field identifies the inode which holds the
+list of vnode identifiers for all non-directory objects hosted by the volume.
+\par
+All of the actual files and directories residing within an AFS volume, as
+identified by the contents of the large and small vnode index inodes, are also
+free-floating inodes, not appearing in the conventional unix name space. This
+is the reason the vendor-supplied fsck program should not be run on partitions
+containing AFS volumes. Since the inodes making up AFS files and directories,
+as well as the inodes serving as volume indices for them, are not mapped to any
+directory, the standard fsck program would throw away all of these
+"unreferenced" inodes. Thus, a special version of fsck is provided that
+recognizes partitions containing AFS volumes as well as standard unix
+partitions.
+
+ \section sec4-3 Section 4.3: Transactions
+
+\par
+Each individual volume operation is carried out by the Volume Server as a
+transaction, but not in the atomic sense of the word. Logically, creating a
+Volume Server transaction can be equated with performing an "exclusive open" on
+the given volume before beginning the actual work of the desired volume
+operation. No other Volume Server (or File Server) operation is allowed on the
+opened volume until the transaction is terminated. Thus, transactions in the
+context of the Volume Server serve to provide mutual exclusion without any of
+the normal atomicity guarantees. Volumes maintain enough internal state to
+enable recovery from interrupted or failed operations via use of the salvager
+program. Whenever volume inconsistencies are detected, this salvager program is
+run, which then attempts to correct the problem.
+\par
+Volume transactions have timeouts associated with them. This guarantees that
+the death of the agent performing a given volume operation cannot result in the
+volume being permanently removed from circulation. There are actually two
+timeout periods defined for a volume transaction. The first is the warning
+time, defined to be 5 minutes. If a transaction lasts for more than this time
+period without making progress, the Volume Server prints a warning message to
+its log file (see Section 4.5). The second time value associated with a volume
+transaction is the hard timeout, defined to occur 10 minutes after any progress
+has been made on the given operation. After this period, the transaction will
+be unconditionally deleted, and the volume freed for any other operations.
+Transactions are reference-counted. Progress will be deemed to have occurred
+for a transaction, and its internal timeclock field will be updated, when:
+\li 1 The transaction is first created.
+\li 2 A reference is made to the transaction, causing the Volume Server to look
+it up in its internal tables.
+\li 3 The transaction's reference count is decremented.
+
+ \section sec4-4 Section 4.4: The volserver Process
+
+\par
+The volserver user-level program is run on every AFS server machine, and
+implements the Volume Server agent. It is responsible for providing the Volume
+Server interface as defined by the volint.xg Rxgen file.
+\par
+The volserver process defines and launches five threads to perform the bulk of
+its duties. One thread implements a background daemon whose job it is to
+garbage-collect timed-out transaction structures. The other four threads are
+RPC interface listeners, primed to accept remote procedure calls and thus
+perform the defined set of volume operations.
+\par
+Certain non-standard configuration settings are made for the RPC subsystem by
+the volserver program. For example, it chooses to extend the length of time
+that an Rx connection may remain idle from the default 12 seconds to 120
+seconds. The reasoning here is that certain volume operations may take longer
+than 12 seconds of processing time on the server, and thus the default setting
+for the connection timeout value would incorrectly terminate an RPC when in
+fact it was proceeding normally and correctly.
+\par
+The volserver program takes a single, optional command line argument. If a
+positive integer value is provided on the command line, then it shall be used
+to set the debugging level within the Volume Server. By default, a value of
+zero is used, specifying that no special debugging output will be generated and
+fed to the Volume Server log file described below.
+
+ \section sec4-5 Section 4.5: Log File
+
+\par
+The Volume Server keeps a log file, recording the set of events of special
+interest it has encountered. The file is named VolserLog, and is stored in the
+/usr/afs/logs directory on the local disk of the server machine on which the
+Volume Server runs. This is a human-readable file, with every entry
+time-stamped.
+\par
+Whenever the volserver program restarts, it renames the current VolserLog file
+to VolserLog.old, and starts up a fresh log. A properly-authorized individual
+can easily inspect the log file residing on any given server machine. This is
+made possible by the BOS Server AFS agent running on the machine, which allows
+the contents of this file to be fetched and displayed on the caller's machine
+via the bos getlog command.
+\par
+An excerpt from a Volume Server log file follows below. The numbers appearing
+in square brackets at the beginning of each line have been inserted so that we
+may reference the individual lines of the log excerpt in the following
+paragraph.
+\code
+[1] Wed May 8 06:03:00 1991 AttachVolume: Error attaching volume
+/vicepd/V1969547815.vol; volume needs salvage
+[2] Wed May 8 06:03:01 1991 Volser: ListVolumes: Could not attach volume
+1969547815
+[3] Wed May 8 07:36:13 1991 Volser: Clone: Cloning volume 1969541499 to new
+volume 1969541501
+[4] Wed May 8 11:25:05 1991 AttachVolume: Cannot read volume header
+/vicepd/V1969547415.vol
+[5] Wed May 8 11:25:06 1991 Volser: CreateVolume: volume 1969547415
+(bld.dce.s3.dv.pmax_ul3) created
+\endcode
+\par
+Line [1] indicates that the volume whose numerical ID is 1969547815 could not
+be attached on partition /vicepd. This error is probably the result of an
+aborted transaction which left the volume in an inconsistent state, or by
+actual damage to the volume structure or data. In this case, the Volume Server
+recommends that the salvager program be run on this volume to restore its
+integrity. Line [2] records the operation which revealed this situation, namely
+the invocation of an AFSVolListVolumes() RPC.
+\par
+Line [4] reveals that the volume header file for a specific volume could not be
+read. Line [5], as with line [2] in the above paragraph, indicates why this is
+true. Someone had called the AFSVolCreateVolume() interface function, and as a
+precaution, the Volume Server first checked to see if such a volume was already
+present by attempting to read its header.
+\par
+Thus verifying that the volume did not previously exist, the Volume Server
+allowed the AFSVolCreateVolume() call to continue its processing, creating and
+initializing the proper volume file, V1969547415.vol, and the associated header
+and index inodes.
+
+ \page chap5 Chapter 5: Volume Server Interface
+
+ \section sec5-1 Section 5.1 Introduction
+
+\par
+This chapter documents the API for the Volume Server facility, as defined by
+the volint.xg Rxgen interface file and the volser.h include file. Descriptions
+of all the constants, structures, macros, and interface functions available to
+the application programmer appear here.
+
+ \section sec5-2 Section 5.2: Constants
+
+\par
+This section covers the basic constant definitions of interest to the Volume
+Server application programmer. These definitions appear in the volint.h file,
+automatically generated from the volint.xg Rxgen interface file, and in
+volser.h.
+\par
+Each subsection is devoted to describing the constants falling into the
+following categories:
+\li Configuration and boundary values
+\li Interface routine opcodes
+\li Transaction Flags
+\li Volume Types
+\li LWP State
+\li States for struct vldbentry
+\li Validity Checks
+\li Miscellaneous
+
+ \subsection sec5-2-1 Section 5.2.1: Configuration and Boundary Values
+
+\par
+These constants define some basic system configuration values, along with such
+things as maximum sizes of important arrays.
+
+MyPort 5,003 The Rx UDP port on which the Volume Server service may be
+found.
+\par Name
+NameLen
+\par Value
+80
+\par Description
+Used by the vos utility to define maximum lengths for internal filename
+variables.
+
+\par Name
+VLDB MAXSERVERS
+\par Value
+10
+\par Description
+Maximum number of server agents implementing the AFS Volume Location Database
+(VLDB) for the cell.
+
+\par Name
+VOLSERVICE ID
+\par Value
+4
+\par Description
+The Rx service number on the given UDP port (MyPort) above.
+
+\par Name
+INVALID BID
+\par Value
+0
+\par Description
+Used as an invalid read-only or backup volume ID.
+
+\par Name
+VOLSER MAXVOLNAME
+\par Value
+65
+\par Description
+The number of characters in the longest possible volume name, including the
+trailing null. Note: this is only used by the vos utility; the Volume Server
+uses the "old" value below.
+
+\par Name
+VOLSER OLDMAXVOLNAME
+\par Value
+32
+\par Description
+The "old" maximum number of characters in an AFS volume name, including the
+trailing null. In reality, it is also the current maximum.
+
+\par Name
+VOLSER MAX REPSITES
+\par Value
+7
+\par Description
+The maximum number of replication sites for a volume.
+
+\par Name
+VNAMESIZE
+\par Value
+32
+\par Description
+Size in bytes of the name field in struct volintInfo (see Section 5.4.6).
+
+
+ \subsection sec5-2-2 Section 5.2.2: Interface Routine Opcodes
+
+\par
+These constants, appearing in the volint.xg Rxgen interface file for the Volume
+Server, define the opcodes for the RPC routines. Every Rx call on this
+interface contains this opcode, and the dispatcher uses it to select the proper
+code at the server site to carry out the call.
+
+\par Name
+VOLCREATEVOLUME
+\par Value
+100
+\par Description
+Opcode for AFSVolCreateVolume()
+
+\par Name
+VOLDELETEVOLUME
+\par Value
+101
+\par Description
+Opcode for AFSVolDeleteVolume()
+
+\par Name
+VOLRESTORE
+\par Value
+102
+\par Description
+Opcode for AFSVolRestoreVolume()
+
+\par Name
+VOLFORWARD
+\par Value
+103
+\par Description
+Opcode for AFSVolForward()
+
+\par Name
+VOLENDTRANS
+\par Value
+104
+\par Description
+Opcode for AFSVolEndTrans()
+
+\par Name
+VOLCLONE
+\par Value
+105
+\par Description
+Opcode for AFSVolClone() .
+
+\par Name
+VOLSETFLAGS
+\par Value
+106
+\par Description
+Opcode for AFSVolSetFlags()
+
+\par Name
+VOLGETFLAGS
+\par Value
+107
+\par Description
+Opcode for AFSVolGetFlags()
+
+\par Name
+VOLTRANSCREATE
+\par Value
+108
+\par Description
+Opcode for AFSVolTransCreate()
+
+\par Name
+VOLDUMP
+\par Value
+109
+\par Description
+Opcode for AFSVolDump()
+
+\par Name
+VOLGETNTHVOLUME
+\par Value
+110
+\par Description
+Opcode for AFSVolGetNthVolume()
+
+\par Name
+VOLSETFORWARDING
+\par Value
+111
+\par Description
+Opcode for AFSVolSetForwarding()
+
+\par Name
+VOLGETNAME
+\par Value
+112
+\par Description
+Opcode for AFSVolGetName()
+
+\par Name
+VOLGETSTATUS
+\par Value
+113
+\par Description
+Opcode for AFSVolGetStatus()
+
+\par Name
+VOLSIGRESTORE
+\par Value
+114
+\par Description
+Opcode for AFSVolSignalRestore()
+
+\par Name
+VOLLISTPARTITIONS
+\par Value
+115
+\par Description
+Opcode for AFSVolListPartitions()
+
+\par Name
+VOLLISTVOLS
+\par Value
+116
+\par Description
+Opcode for AFSVolListVolumes()
+
+\par Name
+VOLSETIDSTYPES
+\par Value
+117
+\par Description
+Opcode for AFSVolSetIdsTypes()
+
+\par Name
+VOLMONITOR
+\par Value
+118
+\par Description
+Opcode for AFSVolMonitor()
+
+\par Name
+VOLDISKPART
+\par Value
+119
+\par Description
+Opcode for AFSVolPartitionInfo()
+
+\par Name
+VOLRECLONE
+\par Value
+120
+\par Description
+Opcode for AFSVolReClone()
+
+\par Name
+VOLLISTONEVOL
+\par Value
+121
+\par Description
+Opcode for AFSVolListOneVolume()
+
+\par Name
+VOLNUKE
+\par Value
+122
+\par Description
+Opcode for AFSVolNukeVolume()
+
+\par Name
+VOLSETDATE
+\par Value
+123
+\par Description
+Opcode for AFSVolSetDate()
+
+ \subsection sec5-2-3 Section 5.2.3: Transaction Flags
+
+\par
+These constants define the various flags the Volume Server uses in assocation
+with volume transactions, keeping track of volumes upon which operations are
+currently proceeding. There are three sets of flag values, stored in three
+different fields within a struct volser trans: general volume state, attachment
+modes, and specific transaction states.
+
+ \subsubsection sec5-2-3-1: Section 5.2.3.1 vflags
+
+\par
+These values are used to represent the general state of the associated volume.
+They appear in the vflags field within a struct volser trans.
+
+\par Name
+VTDeleteOnSalvage
+\par Value
+1
+\par Description
+The volume should be deleted on next salvage.
+
+\par Name
+VTOutOfService
+\par Value
+2
+\par Description
+This volume should never be put online.
+
+\par Name
+VTDeleted
+\par Value
+4
+\par Description
+This volume has been deleted (via AFSVolDeleteVol¬ume() ), and thus should not
+be manipulated.
+
+ \subsubsection sec5-2-3-2 Section 5.2.3.2: iflags
+
+\par
+These constants represent the desired attachment mode for a volume at the start
+of a transaction. Once attached, the volume header is marked to reflect this
+mode. Attachment modes are useful in salvaging partitions, as they indicate
+whether the operations being performed on individual volumes at the time the
+crash occured could have introduced inconsistencies in their metadata
+descriptors. If a volume was attached in a read-only fashion, then the salvager
+may decide (taking other factors into consideration) that the volume doesn't
+need attention as a result of the crash.
+\par
+These values appear in the iflags field within a struct volser trans.
+
+\par Name
+ITOffline
+\par Value
+0x1
+\par Description
+Volume offline on server (returns VOFFLINE).
+
+\par Name
+ITBusy
+\par Value
+0x2
+\par Description
+Volume busy on server (returns VBUSY).
+
+\par Name
+ITReadOnly
+\par Value
+0x8
+\par Description
+Volume is read-only on client, read-write on server -DO NOT USE.
+
+\par Name
+ITCreate
+\par Value
+0x10
+\par Description
+Volume does not exist correctly yet.
+
+\par Name
+ITCreateVolID
+\par Value
+0x1000
+\par Description
+Create volid.
+
+ \subsubsection sec5-2-3-3 Section 5.2.3.3: tflags
+
+\par
+This value is used to represent the transaction state of the associated volume,
+and appears in the tflags field within a struct volser trans.
+
+\par Name
+TTDeleted
+\par Value
+1
+\par Description
+Delete transaction not yet freed due to high reference count.
+
+ \subsection sec5-2-4 Section 5.2.4: Volume Types
+
+\par
+The following constants may be supplied as values for the type argument to the
+AFSVol-CreateVolume() interface call. They are just synonyms for the three
+values RWVOL, ROVOL,
+
+\par Name
+volser RW
+\par Value
+0
+\par Description
+Specifies a read-write volume type.
+
+\par Name
+volser RO
+\par Value
+1
+\par Description
+Specifies a read-only volume type.
+
+\par Name
+volser BACK
+\par Value
+2
+\par Description
+Specifies a backup volume type.
+
+ \subsection sec5-2-5 Section 5.2.5: LWP State
+
+\par
+This set of exported definitions refers to objects internal to the Volume
+Server, and strictly speaking should not be visible to other agents.
+Specifically, a busyFlags array keeps a set of flags referenced by the set of
+lightweight threads running within the Volume Server. These flags reflect and
+drive the state of each of these worker LWPs.
+
+\par Name
+VHIdle
+\par Value
+1
+\par Description
+Volume Server LWP is idle, waiting for new work.
+
+\par Name
+VHRequest
+\par Value
+2
+\par Description
+A work item has been queued.
+
+ \subsection sec5-2-6 Section 5.2.6: States for struct vldbentry
+
+\par
+The Volume Server defines a collection of synonyms for certain values defined
+by the Volume Location Server. These particular constants are used within the
+flags field in objects of type struct vldbentry. The equivalent Volume Location
+Server values are described in Section 3.2.6.
+
+\par Name
+RW EXISTS
+\par Value
+0x1000
+\par Description
+Synonym for VLF RWEXISTS.
+
+\par Name
+RO EXISTS
+\par Value
+0x2000
+\par Description
+Synonym for VLF ROEXISTS.
+
+\par Name
+BACK EXISTS
+\par Value
+0x4000
+\par Description
+Synonym for VLF BACKEXISTS.
+
+\par Name
+NEW REPSITE
+\par Value
+0x01
+\par Description
+Synonym for VLSF NEWREPSITE.
+
+\par Name
+ITSROVOL
+\par Value
+0x02
+\par Description
+Synonym for VLFS ROVOL.
+
+\par Name
+ITSRWVOL
+\par Value
+0x04
+\par Description
+Synonym for VLSF RWVOL.
+
+\par Name
+ITSBACKVOL
+\par Value
+0x08
+\par Description
+Synonym for VLSF BACKVOL.
+
+ \subsection sec5-2-7 Section 5.2.7: Validity Checks
+
+\par
+These values are used for performing validity checks. The first one appears
+only within the partFlags field within objects of type partList (see Section
+5.4.3). The rest (except VOK and VBUSY) appear in the volFlags field within an
+object of type struct volDescription. These latter defintions are used within
+the volFlags field to mark whether the rest of the fields within the struct
+volDescription are valid. Note that while several constants are defined, only
+some are actually used internally by the Volume Server code.
+
+\par Name
+PARTVALID
+\par Value
+0x01
+\par Description
+The indicated partition is valid.
+
+\par Name
+CLONEVALID
+\par Value
+0x02
+\par Description
+The indicated clone (field volCloneId) is a valid one.
+
+\par Name
+CLONEZAPPED
+\par Value
+0x04
+\par Description
+The indicated clone volume (field volCloneId) has been deleted.
+
+\par Name
+IDVALID
+\par Value
+0x08
+\par Description
+The indicated volume ID (field volId) is valid.
+
+\par Name
+NAMEVALID
+\par Value
+0x10
+\par Description
+The indicted volume name (field volName) is valid. Not used internally by the
+Volume Server.
+
+\par Name
+SIZEVALID
+\par Value
+0x20
+\par Description
+The indicated volume size (field volSize) is valid. Not used internally by the
+Volume Server.
+
+\par Name
+ENTRYVALID
+\par Value
+0x40
+\par Description
+The struct volDescription refers to a valid volume.
+
+\par Name
+REUSECLONEID
+\par Value
+0x80
+\par Description
+The indicated clone ID (field volCloneId) should be reused.
+
+\par Name
+VOK
+\par Value
+0x02
+\par Description
+Used in the status field of struct volintInfo to show that everything is OK.
+
+\par Name
+VBUSY
+\par Value
+110
+\par Description
+Used in the status field of struct volintInfo to show that the volume is
+currently busy.
+
+ \subsection sec5-2-8 Section 5.2.8: Miscellaneous
+
+\par
+This section covers the set of exported Volume Server definitions that don't
+easily fall into the above categories.
+
+\par Name
+SIZE
+\par Value
+1,024
+\par Description
+Not used internally by the Volume Server; used as a maxi¬mum size for internal
+character arrays.
+
+\par Name
+MAXHELPERS
+\par Value
+10
+\par Description
+Size of an internal Volume Server character array (busyFlags), it marks the
+maximum number of threads within the server.
+
+\par Name
+STDERR
+\par Value
+stderr
+\par Description
+Synonym for the unix standard input file descriptor.
+
+\par Name
+STDOUT
+\par Value
+stdout
+\par Description
+Synonym for the unix standard output file descriptor.
+
+ \section sec5-3 Section 5.3: Exported Variables
+
+\par
+This section describes the single variable that the Volume Server exports to
+its applications.
+\par
+The QI GlobalWriteTrans exported variable represents a pointer to the head of
+the global queue of transaction structures for operations being handled by a
+Volume Server. Each object in this list is of type struct volser trans (see
+Section 5.4.1 below).
+
+ \section sec5-4 Section 5.4: Structures and Typedefs
+
+\par
+This section describes the major exported Volume Server data structures of
+interest to application programmers, along with some of the the typedefs based
+on those structures. Please note that typedefs in shose definitions angle
+brackets appear are those fed through the Rxgen RPC stub generator. Rxgen uses
+these angle brackets to specify an array of indefinite size.
+
+ \subsection sec5-4-1 Section 5.4.1: struct volser trans
+
+\par
+This structure defines the transaction record for all volumes upon which an
+active operation is proceeding.
+\n \b Fields
+\li struct volser trans *next - Pointer to the next transaction structure in
+the queue.
+\li long tid - Transaction ID.
+\li long time - The time this transaction was last active, for timeout
+purposes.
+\li This is the standard unix time format.
+\li long creationTime - The time a which this transaction started.
+\li long returnCode - The overall transaction error code.
+\li struct Volume *volume - Pointer to the low-level object describing the
+associated volume. This is included here for the use of lower-level support
+code.
+\li long volid - The associated volume's numerical ID.
+\li long partition - The partition on which the given volume resides.
+\li long dumpTransId - Not used.
+\li long dumpSeq - Not used.
+\li short refCount - Reference count on this structure.
+\li short iflags - Initial attach mode flags.
+\li char vflags - Current volume status flags.
+\li char tflags - Transaction flags.
+\li char incremental - If non-zero, indicates that an incremental restore
+operation should be performed.
+\li char lastProcName[] - Name of the last internal Volume Server procedure
+that used this transaction. This field may be up to 30 characters long,
+including the trailing null, and is intended for debugging purposes only.
+\li struct rx call *rxCallPtr - Pointer to latest associated rx call. This
+field is intended for debugging purposes only.
+
+ \subsection sec5-4-2 Section 5.4.2: struct volDescription
+
+\par
+This structure is used by the AFS backup system to group certain key fields of
+volume information.
+\n \b Fields
+\li char volName[] -The name of the given volume; maximum length of this string
+is VOLSER MAXVOLNAME characters, including the trailing null.
+\li long volId -The volume's numerical ID.
+\li int volSize -The size of the volume, in bytes.
+\li long volFlags -Keeps validity information on the given volume and its
+clones. This field takes on values from the set defined in Section 5.2.7
+\li long volCloneId -The volume's current clone ID.
+
+ \subsection sec5-4-3 Section 5.4.3: struct partList
+
+\par
+This structure is used by the backup system and the vos tool to keep track of
+the state of the AFS disk partitions on a given server.
+\n \b Fields
+\li long partId[] -Set of 26 partition IDs.
+\li long partFlags[] -Set to PARTVALID if the associated partition slot
+corresponds to a valid partition. There are 26 entries in this array.
+
+ \subsection sec5-4-4 Section 5.4.4: struct volser status
+
+\par
+This structure holds the status of a volume as it is known to the Volume
+Server, and is passed to clients through the AFSVolGetStatus() interface call.
+\par
+Two fields appearing in this structure, accessDate and updateDate, deserve a
+special note. In particular, it is important to observe that these fields are
+not kept in full synchrony with reality. When a File Server provides one of its
+client Cache Managers with a chunk of a file on which to operate, it is
+incapable of determining exactly when the data in that chunk is accessed, or
+exactly when it is updated. This is because the manipulations occur on the
+client machine, without any information on these accesses or updates passed
+back to the server. The only time these fields can be modified is when the
+chunk of a file resident within the given volume is delivered to a client (in
+the case of accessDate), or when a client writes back a dirty chunk to the File
+Server (in the case of updateDate).
+\n \b Fields
+\li long volID - The volume's numerical ID, unique within the cell.
+\li long nextUnique - Next value to use for a vnode uniquifier within this
+volume.
+\li int type - Basic volume class, one of RWVOL, ROVOL, or BACKVOL.
+\li long parentID - Volume ID of the parent, if this volume is of type ROVOL or
+BACKVOL.
+\li long cloneID - ID of the latest read-only clone, valid iff the type field
+is set to RWVOL.
+\li long backupID - Volume ID of the latest backup of this read-write volume.
+\li long restoredFromID - The volume ID contained in the dump from which this
+volume was restored. This field is used to simply make sure that an incremental
+dump is not restored on top of something inappropriate. Note that this field
+itself is not dumped.
+\li long maxQuota - The volume's maximum quota, in 1Kbyte blocks.
+\li long minQuota - The volume's minimum quota, in 1Kbyte blocks.
+\li long owner - The user ID of the person responsible for this volume.
+\li long creationDate - For a volume of type RWVOL, this field marks its
+creation date. For the original copy of a clone, this field represents the
+cloning date.
+\li long accessDate - Last access time by a user for this volume. This value is
+expressed as a standard unix longword date quantity.
+\li long updateDate - Last modification time by a user for this volume. This
+value is expressed as a standard unix longword date quantity.
+\li long expirationDate - Expiration date for this volume. If the volume never
+expires, then this field is set to zero.
+\li long backupDate - The last time a backup clone was created for this volume.
+\li long copyDate - The time that this copy of this volume was created.
+
+ \subsection sec5-4-5 Section 5.4.5: struct destServer
+
+\par
+Used to specify the destination server in an AFSVolForward() invocation (see
+Section 5.7.7).
+\n \b Fields
+\li long destHost - The IP address of the destination server.
+\li long destPort - The UDP port for the Volume Server Rx service there.
+\li long destSSID - Currently, this field is always set to 1.
+
+ \subsection sec5-4-6 Section 5.4.6: struct volintInfo
+
+\par
+This structure is used to communicate volume information to the Volume Server's
+RPC clients. It is used to build the volEntries object, which appears as a
+parameter to the AFSVolListVolumes() call.
+\par
+The comments in Section 5.4.4 concerning the accessDate and updateDate fields
+are equally valid for the analogue fields in this structure.
+\n \b Fields
+\li char name[] - The null-terminated name for the volume, which can be no
+longer than VNAMESIZE (32) characters, including the trailing null.
+\li long volid - The volume's numerical ID.
+\li long type - The volume's basic class, one of RWVOL, ROVOL, or BACKVOL.
+\li long backupID - The latest backup volume's ID.
+\li long parentID - The parent volume's ID.
+\li long cloneID - The latest clone volume's ID.
+\li long status - Status of the volume; may be one of VOK or VBUSY.
+\li long copyDate - The time that this copy of this volume was created.
+\li unsigned char inUse - If non-zero, an indication that this volume is
+online.
+\li unsigned char needsSalvaged - If non-zero, an indication that this volume
+needs to be salvaged.
+\li unsigned char destroyMe - If non-zero, an indication that this volume
+should be destroyed.
+\li long creationDate - Creation date for a read/write volume; cloning date for
+the original copy of a read-only volume.
+\li long accessDate - Last access time by a user for this volume.
+\li long updateDate - Last modification time by a user for this volume.
+\li long backupDate - Last time a backup copy was made of this volume.
+\li int dayUse - Number of times this volume was accessed since midnight of the
+current day.
+\li int filecount - the number of file system objects contained within the
+volume.
+\li int maxquota - The upper limit on the number of 1-Kbyte disk blocks of
+storage that this volume may obtain.
+\li int size - Not known.
+\li long flags - Values used by the backup system are stored here.
+\li long spare1 -spare3 -Spare fields, reserved for future use.
+
+ \subsection sec5-4-7 Section 5.4.7: struct transDebugInfo
+
+\par
+This structure is provided for monitoring and debugging purposes. It is used to
+compose the transDebugEntries variable-sized object, which in turn appears as a
+parameter to the AFSVolMonitor() interface call.
+\n \b Fields
+\li long tid - The transaction ID.
+\li long time - The time when the transaction was last active, for timeout
+purposes.
+\li long creationTime - The time the transaction started.
+\li long returnCode - The overall transaction error code.
+\li long volid - The open volume's ID.
+\li long partition - The open volume's partition.
+\li short iflags - Initial attach mode flags (IT*).
+\li char vflags - Current volume status flags (VT*).
+\li char tflags - Transaction flags (TT*).
+\li char lastProcName[] - The string name of the last procedure which used
+transaction. This field may be up to 30 characters long, including the trailing
+null, and is intended for debugging purposes only.
+\li int callValid - Flag which determines if the following fields are valid.
+\li long readNext - Sequence number of the next Rx packet to be read.
+\li long transmitNext - Sequence number of the next Rx packet to be
+transmitted.
+\li int lastSendTime - The last time anything was sent over the wire for this
+transaction.
+\li int lastReceiveTime - The last time anything was received over the wire for
+this transaction.
+
+ \subsection sec5-4-8 Section 5.4.8: struct pIDs
+
+\par
+Used by the AFSVolListPartitions() interface call, this structure is used to
+store information on all of the partitions on a given Volume Server.
+\n \b Fields
+\li long partIds[] - One per letter of the alphabet (/vicepa through /vicepz).
+Filled with 0 for "/vicepa", 25 for "/vicepz". Invalid partition slots are
+filled in with a -1.
+
+ \subsection sec5-4-9 Section 5.4.9: struct diskPartition
+
+\par
+This structure contains information regarding an individual AFS disk partition.
+It is returned as a parameter to the AFSVolPartitionInfo() call.
+\n \b Fields
+\li char name[] -Mounted partition name, up to 32 characters long including the
+trailing null.
+\li char devName[] -Device name on which the partition lives, up to 32
+characters long including the trailing null.
+\li int lock fd -A lock used for mutual exclusion to the named partition. A
+value of -1 indicates the lock is not currently being held. Otherwise, it has
+the file descriptor resulting from the unix open() call on the file specified
+in the name field used to "acquire" the lock.
+\li int totalUsable - The number of blocks within the partition which are
+available.
+\li int free - The number of free blocks in the partition.
+\li int minFree - The minimum number of blocks that must remain free regardless
+of allocation requests.
+
+ \section sec5-4-10 Section 5.4.10: struct restoreCookie
+
+\par
+Used as a parameter to both AFSVolRestore() and AFSVolForward(),a restoreCookie
+keeps information that must be preserved between various Volume Server
+operations.
+\n \b Fields
+\li char name[] - The volume name, up to 32 characters long including the
+trailing null.
+\li long type - The volume type, one of RWVOL, ROVOL, and BACKVOL.
+\li long clone - The current read-only clone ID for this volume.
+\li long parent - The parent ID for this volume.
+
+ \section sec5-4-11 Section 5.4.11: transDebugEntries
+
+\code
+typedef transDebugInfo transDebugEntries<>;
+\endcode
+\par
+This typedef is used to generate a variable-length object which is passed as a
+parameter to the AFSVolMonitor() interface function. Thus, it may carry any
+number of descriptors for active transactions on the given Volume Server.
+Specifi, it causes a C structure of the same name to be defined with the
+following fields:
+\n \b Fields
+\li u int transDebugEntries len - The number of struct transDebugInfo (see
+Section 5.4.7) objects appearing at the memory location pointed to by the
+transDebugEntries val field.
+\li transDebugInfo *transDebugEntries val - A pointer to a region of memory
+containing an array of transDebugEntries len objects of type struct
+transDebugInfo.
+
+ \subsection sec5-4-12 Section 5.4.12: volEntries
+
+\code
+typedef volintInfo volEntries<>;
+\endcode
+\par
+This typedef is used to generate a variable-length object which is passed as a
+parameter to AFSVolListVolumes(). Thus, it may carry any number of descriptors
+for volumes on the given Volume Server. Specifically, it causes a C structure
+of the same name to be defined with the following fields:
+\n \b Fields
+\li u int volEntries len - The number of struct volintInfo (see Section 5.4.6)
+objects appearing at the memory location pointed to by the volEntries val
+field.
+\li volintInfo *volEntries val -A pointer to a region of memory containing an
+array of volEntries len objects of type struct volintInfo.
+
+ \section sec5-5 Section 5.5: Error Codes
+
+\par
+The Volume Server advertises two groups of error codes. The first set consists
+of the standard error codes defined by the package. The second is a collection
+of lower-level return values which are exported here for convenience.
+
+\par Name
+VOLSERTRELE ERROR
+\par Value
+1492325120L
+\par Description
+internal error releasing transaction.
+
+\par Name
+VOLSERNO OP
+\par Value
+1492325121L
+\par Description
+unknown internal error.
+
+\par Name
+VOLSERREAD DUMPERROR
+\par Value
+1492325122L
+\par Description
+badly formatted dump.
+
+\par Name
+VOLSERDUMPERROR
+\par Value
+1492325123L
+\par Description
+badly formatted dump(2).
+
+\par Name
+VOLSERATTACH ERROR
+\par Value
+1492325124L
+\par Description
+could not attach volume.
+
+\par Name
+VOLSERILLEGAL PARTITION
+\par Value
+1492325125L
+\par Description
+illegal partition.
+
+\par Name
+VOLSERDETACH ERROR
+\par Value
+1492325126L
+\par Description
+could not detach volume.
+
+\par Name
+VOLSERBAD ACCESS
+\par Value
+1492325127L
+\par Description
+insufficient privilege for volume operation.
+
+\par Name
+VOLSERVLDB ERROR
+\par Value
+1492325128L
+\par Description
+error from volume location database.
+
+\par Name
+VOLSERBADNAME
+\par Value
+1492325129L
+\par Description
+bad volume name.
+
+\par Name
+VOLSERVOLMOVED
+\par Value
+1492325130L
+\par Description
+volume moved.
+
+\par Name
+VOLSERBADOP
+\par Value
+1492325131L
+\par Description
+illegal volume operation.
+
+\par Name
+VOLSERBADRELEASE
+\par Value
+1492325132L
+\par Description
+volume release failed.
+
+\par Name
+VOLSERVOLBUSY
+\par Value
+1492325133L
+\par Description
+volume still in use by volserver.
+
+\par Name
+VOLSERNO MEMORY
+\par Value
+1492325134L
+\par Description
+out of virtual memory in volserver.
+
+\par Name
+VOLSERNOVOL
+\par Value
+1492325135L
+\par Description
+no such volume.
+
+\par Name
+VOLSERMULTIRWVOL
+\par Value
+1492325136L
+\par Description
+more than one read/write volume.
+
+\par Name
+VOLSERFAILEDOP
+\par Value
+1492325137L
+\par Description
+failed volume server operation.
+
+ \subsection sec5-5-1 Section 5.5.1: Standard
+
+\par
+The error codes described in this section were defined by the Volume Server to
+describe exceptional conditions arising in the course of RPC call handling.
+
+ \subsection sec5-5-2 Section 5.5.2: Low-Level
+
+\par
+These error codes are duplicates of those defined from a package which is
+internal to the Volume Server. They are re-defined here to make them visible to
+Volume Server clients.
+
+\par Name
+VSALVAGE
+\par Value
+101
+\par Description
+Volume needs to be salvaged.
+
+\par Name
+VNOVNODE
+\par Value
+102
+\par Description
+Bad vnode number encountered.
+
+\par Name
+VNOVOL
+\par Value
+103
+\par Description
+The given volume is either not attached, doesn't exist, or is not online.
+
+\par Name
+VVOLEXISTS
+\par Value
+104
+\par Description
+The given volume already exists.
+
+\par Name
+VNOSERVICE
+\par Value
+105
+\par Description
+The volume is currently not in service.
+
+\par Name
+VOFFLINE
+\par Value
+106
+\par Description
+The specified volume is offline, for the reason given in the offline message
+field (a subfield within the volume field in struct volser trans).
+
+\par Name
+VONLINE
+\par Value
+107
+\par Description
+Volume is already online.
+
+\par Name
+VDISKFULL
+\par Value
+108
+\par Description
+The disk partition is full.
+
+\par Name
+VOVERQUOTA
+\par Value
+109
+\par Description
+The given volume's maximum quota, as expressed in the maxQuota field of the
+struct volintInfo, has been exceeded.
+
+\par Name
+VBUSY
+\par Value
+110
+\par Description
+The named volume is temporarily unavailable, and the client is encouraged to
+retry the operation shortly.
+
+\par Name
+VMOVED
+\par Value
+111
+\par Description
+The given volume has moved to a new server.
+
+\par
+The VICE SPECIAL ERRORS constant is defined to be the lowest of these error
+codes.
+
+ \section sec5-6 Section 5.6: Macros
+
+\par
+The Volume Server defines a small number of macros, as described in this
+section.
+ \subsection sec5-6-1 Section 5.6.1: THOLD()
+
+\code
+#define THOLD(tt) ((tt)->refCount++)
+\endcode
+\par
+This macro is used to increment the reference count field, refCount, in an
+object of type struct volser trans. Thus, the associated transaction is
+effectively "held" insuring it won't be garbage-collected. The counterpart to
+this operation, TRELE(), is implemented by the Volume Server as a function.
+
+ \subsection sec5-6-2 Section 5.6.2: ISNAMEVALID()
+
+\code
+#define ISNAMEVALID(name) (strlen(name) < (VOLSER_OLDMAXVOLNAME -9))
+\endcode
+\par
+This macro checks to see if the given name argument is of legal length. It must
+be no more than the size of the container, which is at most VOLSER
+OLDMAXVOLNAME characters, minus the length of the longest standardized volume
+name postfix known to the system. That postfix is the 9-character .restored
+string, which is tacked on to the name of a volume that has been restored from
+a dump.
+
+ \section sec5-7 Section 5.7: Functions
+
+\par
+This section covers the Volume Server RPC interface routines, defined by and
+generated from the volint.xg Rxgen file. The following is a summary of the
+interface functions and their purpose:
+
+\par Fcn Name
+AFSVolCreateVolume
+\par Description
+Create a volume.
+
+\par Fcn Name
+AFSVolDeleteVolume
+\par Description
+Delete a volume.
+
+\par Fcn Name
+AFSVolNukeVolume
+\par Description
+Obliterate a volume completely.
+
+\par Fcn Name
+AFSVolDump
+\par Description
+Dump (i.e., save) the contents of a volume.
+
+\par Fcn Name
+AFSVolSignalRestore
+\par Description
+Show intention to call AFSVolRestore().
+
+\par Fcn Name
+AFSVolRestore
+\par Description
+Recreate a volume from a dump.
+
+\par Fcn Name
+AFSVolForward
+\par Description
+Dump a volume, then restore to a given server and volume.
+
+\par Fcn Name
+AFSVolClone
+\par Description
+Clone (and optionally purge) a volume.
+
+\par Fcn Name
+AFSVolReClone
+\par Description
+Re-clone a volume.
+
+\par Fcn Name
+AFSVolSetForwarding
+\par Description
+Set forwarding info for a moved volume.
+
+\par Fcn Name
+AFSVolTransCreate
+\par Description
+Create transaction for a [volume, partition].
+
+\par Fcn Name
+AFSVolEndTrans
+\par Description
+End a transaction.
+
+\par Fcn Name
+AFSVolGetFlags
+\par Description
+Get volume flags for a transaction.
+
+\par Fcn Name
+AFSVolSetFlags
+\par Description
+Set volume flags for a transaction.
+
+\par Fcn Name
+AFSVolGetName
+\par Description
+Get the volume name associated with a transaction.
+
+\par Fcn Name
+AFSVolGetStatus
+\par Description
+Get status of a transaction/volume.
+
+\par Fcn Name
+AFSVolSetIdsTypes
+\par Description
+Set header info for a volume.
+
+\par Fcn Name
+AFSVolSetDate
+\par Description
+Set creation date in a volume.
+
+\par Fcn Name
+AFSVolListPartitions
+\par Description
+Return a list of AFS partitions on a server.
+
+\par Fcn Name
+AFSVolPartitionInfo
+\par Description
+Get partition information.
+
+\par Fcn Name
+AFSVolListVolumes
+\par Description
+Return a list of volumes on the server.
+
+\par Fcn Name
+AFSVolListOneVolume
+\par Description
+Return header info for a single volume.
+
+\par Fcn Name
+AFSVolGetNthVolume
+\par Description
+Get volume header given its index.
+
+\par Fcn Name
+AFSVolMonitor
+\par Description
+Collect server transaction state.
+
+
+\par
+There are two general comments that apply to most of the Volume Server
+interface routines:
+\li 1. AFS partitions are identified by integers ranging from 0 to 25,
+corresponding to the letters "a" through "z". By convention, AFS partitions are
+named /vicepx, where x is any lower-case letter.
+\li 2. Legal volume types to pass as parameters are RWVOL, ROVOL, and BACKVOL,
+as defined in Section 3.2.4.
+
+ \subsection sec5-7-1 Section 5.7.1: AFSVolCreateVolume - Create a
+volume
+
+\code
+int AFSVolCreateVolume(IN struct rx connection *z conn,
+ IN long partition,
+ IN char *name,
+ IN long type,
+ IN long parent,
+ INOUT long *volid,
+ OUT long *trans)
+\endcode
+\par Description
+Create a volume named name, with numerical identifier volid, and of type type.
+The new volume is to be placed in the specified partition for the server
+machine as identified by the Rx connection information pointed to by z conn. If
+a value of 0 is provided for the parent argument, it will be set by the Volume
+Server to the value of volid itself. The trans parameter is set to the Volume
+Location Server transaction ID corresponding to the volume created by this
+call, if successful.
+The numerical volume identifier supplied in the volid parameter must be
+generated beforehand by calling VL GetNewVolumeID() (see Section 3.6.5). After
+AFSVolCreateVolume() completes correctly, the new volume is marked as offline.
+It must be explicitly brought online through a call to AFSVolSetFlags() (see
+Section 5.7.14) while passing the trans transaction ID generated by
+AFSVolCreateVolume(). The "hold" on the new volume guaranteed by the trans
+transaction may be "released" by calling AFSVolEnd-Trans(). Until then, no
+other process may operate on the volume.
+Upon creation, a volume's maximum quota (as specified in the maxquota field of
+a struct volintInfo) is set to 5,000 1-Kbyte blocks.
+Note that the AFSVolCreateVolume() routine is the only Volume Server function
+that manufactures its own transaction. All others must have already acquired a
+transaction ID via either a previous call to AFSVolCreateVolume() or
+AFSVolTransCreate().
+\par Error Codes
+VOLSERBADNAME The volume name parameter was longer than 31 characters plus the
+trailing null.
+\n VOLSERBAD ACCESS The caller is not authorized to create a volume.
+\n EINVAL The type parameter was illegal. E2BIG A value of 0 was provided in
+the volid parameter. VOLSERVOLBUSY A transaction could not be created, thus the
+given volume was busy.
+\n EIO The new volume entry could not be created.
+\n VOLSERTRELE ERROR The trans transaction's reference count could not be
+dropped to the proper level.
+\n <misc> If the partition parameter is unintelligible, this routine will
+return a low-level unix error.
+
+ \subsection sec5-7-2 Section 5.7.2: AFSVolDeleteVolume - Delete a
+volume
+
+\code
+int AFSVolDeleteVolume(IN struct rx connection *z conn, IN long trans)
+\endcode
+\par Description
+Delete the volume associated with the open transaction ID specified within
+trans. All of the file system objects contained within the given volume are
+destroyed, and the on-disk volume metadata structures are reclaimed. In
+addition, the in-memory volume descriptor's vflags field is set to VTDeleted,
+indicating that it has been deleted.
+\par
+Under some circumstances, a volume should be deleted by calling
+AFSVolNukeVolume() instead of this routine. See Section 5.7.3 for more details.
+\par Error Codes
+VOLSERBAD ACCESS The caller is not authorized to delete a volume.
+\n ENOENT The trans transaction was not found.
+\n VOLSERTRELE ERROR The trans transaction's reference count could not be
+dropped to the proper level.
+
+ \subsection sec5-7-3 Section 5.7.3: AFSVolNukeVolume - Obliterate a
+volume completely
+
+\code
+int AFSVolNukeVolume(IN struct rx connection *z conn,
+ IN long partID,
+ IN long volID)
+\endcode
+\par Description
+Completely obliterate the volume living on partition partID whose ID is volID.
+This involves scanning all inodes on the given partition and removing those
+marked with the specified volID. If the volume is a read-only clone, only the
+header inodes are removed, since they are the only ones stamped with the
+read-only ID. To reclaim the space taken up by the actual data referenced
+through a read-only clone, this routine should be called on the read-write
+master. Note that calling AFSVolNukeVolume() on a read-write volume effectively
+destroys all the read-only volumes cloned from it, since everything except for
+their indicies to the (now-deleted) data will be gone.
+\par
+Under normal circumstances, it is preferable to use AFSVolDeleteVolume()
+instead of AFSVolNukeVolume() to delete a volume. The former is much more
+efficient, as it only touches those objects in the partition that belong to the
+named volume, walking the on-disk volume metadata structures. However,
+AFSVolNukeVolume() must be used in situations where the volume metadata
+structures are known to be damaged. Since a complete scan of all inodes in the
+partition is performed, all disconnected or unreferenced portions of the given
+volume will be reclaimed.
+\par Error Codes
+VOLSERBAD ACCESS The caller is not authorized to call this routine.
+\n VOLSERNOVOL The partition specified by the partID argument is illegal.
+
+ \subsection sec5-7-4 Section 5.7.4: AFSVolDump - Dump (i.e., save) the
+contents of a volume
+
+\code
+int AFSVolDump(IN struct rx connection *z conn,
+ IN long fromTrans,
+ IN long fromDate)
+\endcode
+\par Description
+Generate a canonical dump of the contents of the volume associated with
+transaction fromTrans as of calendar time fromDate. If the given fromDate is
+zero, then a full dump will be carried out. Otherwise, the resulting dump will
+be an incremental one.
+\par
+This is specified as a split function within the volint.xg Rxgen interface
+file. This specifies that two routines are generated, namely StartAFSVolDump()
+and EndAFSVolDump(). The former is used to marshall the IN arguments, and the
+latter is used to unmarshall the return value of the overall operation. The
+actual dump data appears in the Rx stream for the call (see the section
+entitled Example Server and Client in the companion AFS-3 Programmer's
+Reference: Specification for the Rx Remote Procedure Call Facility document).
+\par Error Codes
+VOLSERBAD ACCESS The caller is not authorized to dump a volume.
+\n ENOENT The fromTrans transaction was not found.
+\n VOLSERTRELE ERROR The trans transaction's reference count could not be
+dropped to the proper level.
+
+ \subsection sec5-7-5 Section 5.7.5: AFSVolSignalRestore - Show
+intention to call AFSVolRestore()
+
+\code
+int AFSVolSignalRestore(IN struct rx connection *z conn,
+ IN char *name,
+ IN int type,
+ IN long pid,
+ IN long cloneid)
+\endcode
+\par Description
+Show an intention to the Volume Server that the client will soon call
+AFSVolRestore(). The parameters, namely the volume name, type, parent ID pid
+and clone ID cloneid are stored in a well-known set of global variables. These
+values are used to set the restored volume's header, overriding those values
+present in the dump from which the volume will be resurrected.
+\par Error Codes
+VOLSERBAD ACCESS The caller is not authorized to call this routine.
+\n VOLSERBADNAME The volume name contained in name was longer than 31
+characters plus the trailing null.
+
+ \subsection sec5-7-6 Section 5.7.6: AFSVolRestore - Recreate a volume
+from a dump
+
+\code
+int AFSVolRestore(IN struct rx connection *z conn,
+ IN long toTrans,
+ IN long flags,
+ IN struct restoreCookie *cookie)
+\endcode
+\par Description
+Interpret a canonical volume dump (generated as the result of calling
+AFSVolDumpVolume()), passing it to the volume specified by the toTrans
+transaction. Only the low bit in the flags argument is inspected. If this low
+bit is turned on, the dump will be restored as incremental; otherwise, a full
+restore will be carried out.
+\par
+All callbacks to the restored volume are broken.
+\par
+This is specified as a split function within the volint.xg Rxgen interface
+file. This specifies that two routines are generated, namely
+StartAFSVolRestore() and EndAFSVolRestore() . The former is used to marshall
+the IN arguments, and the latter is used to unmarshall the return value of the
+overall operation. The actual dump data flows over the Rx stream for the call
+(see the section entitled Example Server and Client in the companion AFS-3
+Programmer's Reference: Specification for the Rx Remote Procedure Call Facility
+document).
+\par
+The AFSVolSignalRestore() routine (see Section 5.7.5) should be called before
+invoking this function in order to signal the intention to restore a particular
+volume.
+\par Error Codes
+VOLSERREAD DUMPERROR Dump data being restored is corrupt.
+\n VOLSERBAD ACCESS The caller is not authorized to restore a volume.
+\n ENOENT The fromTrans transaction was not found.
+\n VOLSERTRELE ERROR The trans transaction's reference count could not be
+dropped to the proper level.
+
+ \subsection sec5-7-7 Section 5.7.7: AFSVolForward - Dump a volume, then
+restore to given server and volume
+
+\code
+int AFSVolForward(IN struct rx connection *z conn,
+ IN long fromTrans,
+ IN long fromDate,
+ IN struct destServer *destination,
+ IN long destTrans,
+ IN struct restoreCookie *cookie)
+\endcode
+\par Description
+Dumps the volume associated with transaction fromTrans from the given fromDate.
+The dump itself is sent to the server described by destination, where it is
+restored as the volume associated with transaction destTrans. In reality, an Rx
+connection is set up to the destServer, StartAFSVolRestore() directs writing to
+the Rx call's stream, and then EndAFSVolRestore() is used to deliver the dump
+for the volume corresponding to fromTrans. If a non-zero fromDate is provided,
+then the dump will be incremental from that date. Otherwise, a full dump will
+be delivered.
+\par
+The Rx connection set up for this task is always destroyed before the function
+returns. The destination volume should exist before carrying out this
+operation, and the invoking process should have started transactions on both
+participating volumes.
+\par Error Codes
+VOLSERBAD ACCESS The caller is not authorized to forward a volume.
+\n ENOENT The fromTrans transaction was not found.
+\n VOLSERTRELE ERROR The trans transaction's reference count could not be
+dropped to the proper level.
+\n ENOTCONN An Rx connection to the destination server could not be
+established.
+
+ \subsection sec5-7-8 Section 5.7.8: AFSVolClone - Clone (and optionally
+purge) a volume
+
+\code
+int AFSVolClone(IN struct rx connection *z conn,
+ IN long trans,
+ IN long purgeVol,
+ IN long newType,
+ IN char *newName,
+ INOUT long *newVol)
+\endcode
+\par Description
+Make a clone of the read-write volume associated with transaction trans, giving
+the cloned volume a name of newName. The newType parameter specifies the type
+for the new clone, and may be either ROVOL or BACKVOL. If purgeVol is set to a
+non-zero value, then that volume will be purged during the clone operation.
+This may be more efficient that separate clone and purge calls when making
+backup volumes. The newVol parameter sets the new clone's ID. It is illegal to
+pass a zero in newVol.
+\par Error Codes
+VOLSERBADNAME The volume name contained in newName was longer than 31
+characters plus the trailing null.
+\n VOLSERBAD ACCESS The caller is not authorized to clone a volume.
+\n ENOENT The fromTrans transaction was not found.
+\n VOLSERTRELE ERROR The trans transaction's reference count could not be
+dropped to the proper level.
+\n VBUSY The given transaction was already in use; indicating that someone else
+is currently manipulating the specified clone.
+\n EROFS The volume associated with the given trans is read-only (either ROVOL
+or BACKVOL).
+\n EXDEV The volume associated with the trans transaction and the one specified
+by purgeVol must be on the same disk device, and they must be cloned from the
+same parent volume.
+\n EINVAL The purgeVol must be read-only, i.e. either type ROVOL or BACKVOL.
+
+ \subsection sec5-7-9 Section 5.7.9: AFSVolReClone - Re-clone a volume
+
+\code
+int AFSVolReClone(IN struct rx connection *z conn,
+ IN long tid,
+ IN long cloneID)
+\endcode
+\par Description
+Recreate an existing clone, with identifier cloneID, from the volume associated
+with transaction tid.
+\par Error Codes
+VOLSERBAD ACCESS The caller is not authorized to clone a volume.
+\n ENOENT The tid transaction was not found.
+\n VOLSERTRELE ERROR The tid transaction's reference count could not be dropped
+to the proper level.
+\n VBUSY The given transaction was already in use; indicating that someone else
+is currently manipulating the specified clone.
+\n EROFS The volume to be cloned must be read-write (of type RWVOL).
+\n EXDEV The volume to be cloned and the named clone itself must be on the same
+device. Also, cloneID must have been cloned from the volume associated with
+transaction tid.
+\n EINVAL The target clone must be a read-only volume (i.e., of type ROVOL or
+BACKVOL).
+
+ \subsection sec5-7-10 Section 5.7.10: AFSVolSetForwarding - Set
+forwarding info for a moved volume
+
+\code
+int AFSVolSetForwarding(IN struct rx connection *z conn,
+ IN long tid,
+ IN long newsite)
+\endcode
+\par Description
+Record the IP address specified within newsite as the location of the host
+which now hosts the volume associated with transaction tid, formerly resident
+on the current host. This is intended to gently guide Cache Managers who have
+stale volume location cached to the volume's new site, ensuring the move is
+transparent to clients using that volume.
+\par Error Codes
+VOLSERBAD ACCESS The caller is not authorized to create a forwarding address.
+\n ENOENT The trans transaction was not found.
+
+ \subsection sec5-7-11 Section 5.7.11: AFSVolTransCreate - Create
+transaction for a [volume, partition]
+
+\code
+int AFSVolTransCreate(IN struct rx connection *z conn,
+ IN long volume,
+ IN long partition,
+ IN long flags,
+ OUT long *trans)
+\endcode
+\par Description
+Create a new Volume Server transaction associated with volume ID volume on
+partition partition. The type of volume transaction is specified by the flags
+parameter. The values in flags specify whether the volume should be treated as
+busy (ITBusy), offline (ITOffline), or in shared read-only mode (ITReadOnly).
+The identifier for the new transaction built by this function is returned in
+trans.
+\par
+Creating a transaction serves as a signal to other agents that may be
+interested in accessing a volume that it is unavailable while the Volume Server
+is manipulating it. This prevents the corruption that could result from
+multiple simultaneous operations on a volume.
+\par Error Codes
+EINVAL Illegal value encountered in flags.
+\n VOLSERVOLBUSY A transaction could not be created, thus the given [volume,
+partition] pair was busy.
+\n VOLSERTRELE ERROR The trans transaction's reference count could not be
+dropped to the proper level after creation.
+
+ \subsection sec5-7-12 Section 5.7.12: AFSVolEndTrans - End a
+transaction
+
+\code
+int AFSVolEndTrans(IN struct rx connection *z conn,
+ IN long trans,
+ OUT long *rcode)
+\endcode
+\par Description
+End the transaction identified by trans, returning its final error code into
+rcode. This makes the associated [volume, partition] pair eligible for further
+Volume Server operations.
+\par Error Codes
+VOLSERBAD ACCESS The caller is not authorized to create a transaction.
+\n ENOENT The trans transaction was not found.
+
+ \subsection sec5-7-13 Section 5.7.13: AFSVolGetFlags - Get volume flags
+for a transaction
+
+\code
+int AFSVolGetFlags(IN struct rx connection *z conn,
+ IN long trans,
+ OUT long *flags)
+\endcode
+\par Description
+Return the value of the vflags field of the struct volser trans object
+describing the transaction identified as trans. The set of values placed in the
+flags parameter is described in Section 5.2.3.1. Briefly, they indicate whether
+the volume has been deleted (VTDeleted), out of service (VTOutOfService), or
+marked delete-on-salvage (VTDeleteOnSalvage).
+\par Error Codes
+ENOENT The trans transaction was not found.
+\n VOLSERTRELE ERROR The trans transaction's reference count could not be
+dropped to the proper level.
+
+ \subsection sec5-7-14 Section 5.7.14: AFSVolSetFlags - Set volume flags
+for a transaction
+
+\code
+int AFSVolSetFlags(IN struct rx connection *z conn,
+ IN long trans,
+ IN long flags)
+\endcode
+\par Description
+Set the value of the vflags field of the struct volser trans object describing
+the transaction identified as trans to the contents of flags. The set of legal
+values for the flags parameter is described in Section 5.2.3.1. Briefly, they
+indicate whether the volume has been deleted (VTDeleted), out of service
+(VTOutOfService), or marked delete-onsalvage (VTDeleteOnSalvage).
+\par Error Codes
+ENOENT The trans transaction was not found.
+\n EROFS Updates to this volume are not allowed.
+\n VOLSERTRELE ERROR The trans transaction's reference count could not be
+dropped to the proper level.
+
+ \subsection sec5-7-15 Section 5.7.15: AFSVolGetName - Get the volume
+name associated with a transaction
+
+\code
+int AFSVolGetName(IN struct rx connection *z conn,
+ IN long tid,
+ OUT char **tname)
+\endcode
+\par Description
+Given a transaction identifier tid, return the name of the volume associated
+with the given transaction. The tname parameter is set to point to the address
+of a string buffer of at most 256 chars containing the desired information,
+which is created for this purpose. Note: the caller is responsible for freeing
+the buffer pointed to by tname when its information is no longer needed.
+\par Error Codes
+ENOENT The tid transaction was not found, or a volume was not associated with
+it (VSrv internal error).
+\n E2BIG The volume name was too big (greater than or equal to SIZE (1,024)
+characters.
+\n VOLSERTRELE ERROR The trans transaction's reference count could not be
+dropped to the proper level.
+
+ \subsection sec5-7-16 Section 5.7.16: AFSVolGetStatus - Get status of a
+transaction/volume
+
+\code
+int AFSVolGetStatus(IN struct rx connection *z conn,
+ IN long tid,
+ OUT struct volser status *status)
+\endcode
+\par Description
+This routine fills the status structure passed as a parameter with status
+information for the volume identified by the transaction identified by tid, if
+it exists. Included in this status information are the volume's ID, its type,
+disk quotas, the IDs of its clones and backup volumes, and several other
+administrative details.
+\par Error Codes
+ENOENT The tid transaction was not found.
+\n VOLSERTRELE ERROR The tid transaction's reference count could not be dropped
+to the proper level.
+
+ \subsection sec5-7-17 Section 5.7.17: AFSVolSetIdsTypes - Set header
+info for a volume
+
+\code
+int AFSVolSetIdsTypes(IN struct rx connection *z conn,
+ IN long tId
+ IN char *name,
+ IN long type,
+ IN long pId,
+ IN long cloneId,
+ IN long backupId)
+\endcode
+\par Description
+The transaction identifed by tId is located, and the values supplied for the
+volume name, volume type, parent ID pId, clone ID cloneId and backup ID
+backupId are recorded into the given transaction.
+\par Error Codes
+ENOENT The tId transaction was not found.
+\n VOLSERBAD ACCESS The caller is not authorized to call this routine.
+\n VOLSERBADNAME The volume name contained in name was longer than 31
+characters plus the trailing null.
+\n VOLSERTRELE ERROR The tId transaction's reference count could not be dropped
+to the proper level.
+
+ \subsection sec5-7-18 Section 5.7.18: AFSVolSetDate - Set creation date
+in a volume
+
+\code
+int AFSVolSetDate(IN struct rx connection *z conn,
+ IN long tid,
+ IN long newDate)
+\endcode
+\par Description
+Set the creationDate of the struct volintInfo describing the volume associated
+with transaction tid to newDate.
+\par Error Codes
+VOLSERBAD ACCESS The caller is not authorized to call this routine.
+\n ENOENT The tId transaction was not found.
+\n VOLSERTRELE ERROR The tid transaction's reference count could not be dropped
+to the proper level.
+
+ \subsection sec5-7-19 Section 5.7.19: AFSVolListPartitions - Return a
+list of AFS partitions on a server
+
+\code
+int AFSVolListPartitions(IN struct rx connection *z conn,
+ OUT struct pIDs *partIDs)
+\endcode
+\par Description
+Return a list of AFS partitions in use by the server processing this call. The
+output parameter is the fixed-length partIDs array, with one slot for each of
+26 possible partitions. By convention, AFS partitions are named /vicepx, where
+x is any letter. The /vicepa partition is represented by a zero in this array,
+/vicepa bya1, andsoon. Unused partitions are represented by slots filled with a
+-1.
+\par Error Codes
+---None.
+
+ \subsection sec5-7-20 Section 5.7.20: AFSVolPartitionInfo - Get
+partition information
+
+\code
+int AFSVolPartitionInfo(IN struct rx connection *z conn,
+ IN char *name,
+ OUT struct diskPartition *partition)
+\endcode
+\par Description
+Collect information regarding the partition with the given character string
+name, and place it into the partition object provided.
+\par Error Codes
+VOLSERBAD ACCESS The caller is not authorized to call this routine.
+\n VOLSERILLEGAL PARTITION An illegal partition was specified by name
+
+ \subsection sec5-7-21 Section 5.7.21: AFSVolListVolumes - Return a list
+of volumes on the server
+
+\code
+int AFSVolListVolumes(IN struct rx connection *z conn,
+ IN long partID,
+ IN long flags,
+ OUT volEntries *resultEntries)
+\endcode
+\par Description
+Sweep through all the volumes on the partition identified by partid, filling in
+consecutive records in the resultEntries object. If the flags parameter is set
+to a non-zero value, then full status information is gathered. Otherwise, just
+the volume ID field is written for each record. The fields for a volEntries
+object like the one pointed to by resultEntries are described in Section 5.4.6,
+which covers the struct volintInfo definition.
+\par Error Codes
+VOLSERILLEGAL PARTITION An illegal partition was specified by partID
+\n VOLSERNO MEMORY Not enough memory was available to hold all the required
+entries within resultEntries.
+
+ \subsection sec5-7-22 Section 5.7.22: AFSVolListOneVolume - Return
+header info for a single volume
+
+\code
+int AFSVolListOneVolume(IN struct rx connection *z conn,
+ IN long partID,
+ IN long volid,
+ OUT volEntries *resultEntries)
+\endcode
+\par Description
+Find the information for the volume living on partition partID whose ID is
+volid, and place a single struct volintInfo entry within the variable-size
+resultEntries object.
+\par
+This is similar to the AFSVolListVolumes() call, which returns information on
+all volumes on the specified partition. The full volume information is always
+written into the returned entry (equivalent to setting the flags argument to
+AFSVolListVolumes() to a non-zero value).
+\par Error Codes
+VOLSERILLEGAL PARTITION An illegal partition was specified by partID
+\n ENODEV The given volume was not found on the given partition.
+
+ \subsection sec5-7.23 Section 5.7.23: AFSVolGetNthVolume - Get volume
+header given its index
+
+\code
+int AFSVolGetNthVolume(IN struct rx connection *z conn,
+ IN long index,
+ OUT long *volume,
+ OUT long *partition)
+\endcode
+\par Description
+Using index as a zero-based index into the set of volumes hosted by the server
+chosen by the z conn argument, return the volume ID and partition of residence
+for the given index.
+\Note This functionality has not yet been implemented.
+\par Error Codes
+VOLSERNO OP Not implemented.
+
+ \subsection sec5-7.24 Section 5.7.24: AFSVolMonitor - Collect server
+transaction state
+
+\code
+int AFSVolMonitor(IN struct rx connection *z conn,
+ OUT transDebugEntries *result)
+\endcode
+\par Description
+This call allows the transaction state of a Volume Server to be monitored for
+debugging purposes. Anyone wishing to supervise this Volume Server state may
+call this routine, causing all active transactions to be recorded in the given
+result object.
+\par Error Codes
+---None.
+
+ \page biblio Bibliography
+
+\li [1] Transarc Corporation. AFS 3.0 System Administrator's Guide,
+F-30-0-D102, Pittsburgh, PA, April 1990.
+\li [2] Transarc Corporation. AFS 3.0 Command Reference Manual, F-30-0-D103,
+Pittsburgh, PA, April 1990.
+\li [3] CMU Information Technology Center. Synchronization and Caching
+Issues in the Andrew File System, USENIX Proceedings, Dallas, TX, Winter 1988.
+\li [4] Information Technology Center, Carnegie Mellon University. Ubik -A
+Library For Managing Ubiquitous Data, ITCID, Pittsburgh, PA, Month, 1988.
+\li [5] Information Technology Center, Carnegie Mellon University. Quorum
+Completion, ITCID, Pittsburgh, PA, Month, 1988.
+
+*/