Previous section.
Systems Management: Backup Services API (XBSA)
Copyright © 1998 The Open Group
Overview of Backup Services API
The Open Backup Services API is a
set of procedures which may be called up, available
in a dynamic or static library
provided by a vendor implementing a Backup Service. For the rest
of this Technical Standard, the terms API or XBSA refer to this
Open Backup Services API.
A synchronous interface in the C
language is defined. If an application needs asynchronous
behavior, it can be achieved by using its process or thread
mechanisms.
The following sections in this
chapter give a brief overview of the API calls and their intended
usage. A detailed specification of the procedures comprising the
API is given in the manual-page definitions in
Backup Services API Definitions
.
Type Definitions and Data Structures
defines the data type definitions and data structures
used in the API.
Initialization and Authentication
It is necessary for an XBSA
Application to set up a session with the Backup Service by
invoking the
BSAInit()
call, in order to use these
services. The procedures
BSAQueryApiVersion()
and
BSAQueryServiceProvider()
may be
invoked prior to calling
BSAInit()
to determine the
current version of the API used by the Backup Service
and a string describing the provider of the Backup Service, respectively.
The
BSAInit()
call authenticates the caller, sets up a session with the
Backup Service and sets up an environment for the caller to be
used in subsequent calls. A session set up by a
BSAInit()
call is terminated by a
BSATerminate()
call, which
will release any resources acquired during the setting up of the
session.
Nested sessions, and concurrent sessions in the same address space are not permitted.
BSAInit()
may authenticate the caller using a security token; the exact
definition and use of this security token is implementation
dependent. If a NULL security token is provided, the Backup Service
can use a default, implementation-dependent security mechanism.
In addition to those environmental parameters defined
in this Technical Standard, there may also be additional,
implementation dependent environmental parameters to the
BSAInit()
call.
A potential failure to authenticate the XBSA Client will cause the
BSAInit()
call to return BSA_RC_AUTHENTICATION_FAILURE. The XBSA
Client will have to communicate with the security subsystem that is
being used by the Backup Service to resolve this failure. The XBSA
itself does not provide details about the reason of the
authentication failure, or the means for correcting the
authentication failure.
Transactions
Within each session, an XBSA
Application can make a sequence of calls (for example, to backup
some objects, to query the set of objects it has backed up, or to
restore objects). These calls must be grouped into a transaction
by invoking
BSABeginTxn()
at the beginning of the group
of calls and invoking
BSAEndTxn()
at the end. The
latter either commits the transaction or aborts it.
If a transaction is aborted either
by a
BSAEndTxn()
or
BSATerminate()
call, then the effect of all the calls made
within the transaction is nullified. If a transaction is
committed, then the effect of all the calls within the
transaction is made permanent.
Within a single session,
transactions cannot be nested and cannot overlap. Transactions
are categorized into the following types:
-
Object modification transactions -
in which objects may be created or deleted.
-
Object retrieval transactions - in which objects may only be
queried or retrieved. (This type of transaction provides no functional
benefit for the calling XBSA Application, and is only
included for completeness.)
The type of a transaction is
established by the first create/delete/retrieve operation
performed. Attempts to mix operations in a transaction will
result in a BSA_RC_INVALID_CALL_SEQUENCE error. The permissible call
sequences are defined later in this chapter.
The following example illustrates
the call pattern that may be used by a caller who, in one
transaction, loops through a list of object names to backup each
object.
-
-
if ((rc = BSAInit(bsaHandlePtr, tokenPtr,
userNamePtr, environmentPtr) ) != BSA_RC_SUCCESS) {
<error processing>;
}
if ((rc = BSABeginTxn(bsaHandle) ) != BSA_RC_SUCCESS) {
<error processing>;
}
<loop through all object names> {
if ((rc = BSACreateObject(bsaHandle, objectDescriptorPtr,
dataBlkPtr)) != BSA_RC_SUCCESS) {
<error processing>;
}
<loop through all data for one object> {
if ((rc = BSASendData(bsaHandle,
dataBlkPtr) ) != BSA_RC_SUCCESS) {
<error processing>;
}
} /* loop through all data for one object */
if ((rc = BSAEndData(bsaHandle) ) != BSA_RC_SUCCESS) {
<error processing>;
}
} /* loop through all object names */
if ((rc = BSAEndTxn(bsaHandle,BSA_COMMIT) ) != BSA_RC_SUCCESS) {
<error processing>;
}
if ((rc = BSATerminate(bsaHandle) ) != BSA_RC_SUCCESS) {
<error processing>;
}
In this example, the data for each
of the backup copy objects may be buffered by the API before
sending it to the Backup Service.
Backup and Archive
An XBSA Application can create an
XBSA object (either a backup copy or an archive copy) using the
BSACreateObject()
call, and pass the object's data in buffers using a sequence of
BSASendData()
calls ended by a
BSAEndData()
call.
The ability to pass data in
buffers allows an XBSA Application to use any buffering technique
that is appropriate to ensure consistency or to improve
performance. When data is passed in buffers, all the data for one
object must be passed, in the proper sequence, before any other
operation is started.
A scenario for creating a backup
copy of an object is shown in
Creating a Backup Copy of an Object
.
Figure: Creating a Backup Copy of an Object
Restore and Retrieve
The Restore and Retrieve interface
is similar to the Backup and Archive interface, except that the
data flow is reversed. The
BSAGetData()
call is used
instead of the
BSASendData()
call. Data directed to
standard output may be piped to a filter or command.
The
BSAGetObject()
call
is used to restore (from a backup copy) or retrieve (from an
archive copy) objects. The
BSAGetData()
call is used to
get data for the object in buffers, and the
BSAEndData()
call is to signal the end of getting data for the object. A
scenario for restoring an object is shown in
Restoring an Object
.
Figure: Restoring an Object
It should be noted
that the use of transactions for restore and retrieval operations
does not provide any functional benefit to the calling XBSA
Application.
Query
An XBSA Application may query the Backup Service for XBSA Objects
that have been created. The
BSAQueryObject()
call is used to query
the Backup Service for objects. Since retention of objects is a
function of the Backup Service's implementation there is no
guarantee that the call to
BSAQueryObject()
will return an object descriptor.
The query is based on a subset of the Object Descriptor
attributes, contained in a Query Descriptor.
The result of a query can return Object Descriptors,
but never XBSA Object Data. If the result is multiple Object
Descriptors, the query result is retrieved one Object Descriptor at
a time by using a succession of
BSAGetNextQueryObject()
calls.
The XBSA Application can retrieve the XBSA Object Data by using the
BSAGetObject()
call with the copyId from one of the object
descriptors returned by the query.
For details of the BSA_QueryDescriptor structure, see
BSA_QueryDescriptor
.
API Call Sequences
The permitted API call sequences
are shown in the following diagrams.
Any violation of these sequences will result in a
bad call sequence error.
In the call sequence diagrams, the following conventions are used:
-
States have arbitrary names.
-
Function names have been shortened by dropping the "BSA" prefix.
-
States from which BSAEndTxn(BSA_COMMIT) can be called successfully
are indicated by a double box and named using bold font. Attempts to call BSAEndTxn(BSA_COMMIT)
from any other state will return a BSA_RC_TRANSACTION_ABORTED error.
Figure: Permitted Call Sequences - Overview
Leaving the "Transaction" state with other than a successful
call of BSAEndTxn(BSA_COMMIT)
will cause the transaction to be aborted.
If the transaction was creating or deleting an object,
that object will not be created or deleted.
Apart from this, a transaction does not have any
other side effect. In particular, the state of the
storage media is not restored to the state
just before the start of the aborted transaction.
Figure: Permitted Call Sequences - Transactions
Since getting or querying an object does not alter
the state of the object, leaving the transaction
has no side effects.
Buffers
All buffers that are used by the XBSA are allocated by the XBSA
Application. The Backup Service fills data into the buffers, but
never allocates any memory that is passed back to the XBSA
Application. This simplifies buffer allocation and deletion since
the XBSA Application is solely responsible.
However, to allow the Backup Service to influence how buffers
should be allocated, and to provide the Backup Service with the
ability to reserve private sections in certain buffers, several
conventions are used in the XBSA.
Buffer Size
For function calls that specify the size of the buffer as a
separate parameter, XBSA uses the following convention to
allow the Backup Service to signal that a buffer is not large
enough and provide the XBSA Application with the means to discover
what the correct size should be.
The parameter that specifies the size is a pointer, so that the
Backup Service can alter the parameter. The size is always in
bytes. If the size is adequate and a valid buffer is given, the
Backup Service will copy the requested data into the buffer and set
the actual size in the size parameter.
If the size is inadequate, the Backup Service will not copy the
data into the buffer. It will set the size parameter to the actual size
of the data to be copied and return from the function call with
BSA_RC_BUFFER_TOO_SMALL. This allows the XBSA Application
to allocate a buffer of adequate size and to call the function
again.
The functions that use this convention are
BSAGetEnvironment()
and
BSAQueryServiceProvider().
Private Buffer Space
For function calls that use the BSA_DataBlock32 structure, a convention
has been adopted that allows the Backup Service to reserve certain
portions of the buffer for its own use. There are two areas that
can be reserved by the Backup Service:
-
Header
A contiguous area starting at offset 0 (that is, the start of the buffer)
-
Trailer
A contiguous area that ends at the end of the buffer (that is,
the tail of the buffer)
The area reserved for the XBSA Application is the:
-
Data Segment
A contiguous area that lies in between the Header and Trailer
To make this preference known to the XBSA Application, the Backup
Service sets certain parameters in the BSA_DataBlock32 structure when a
data transfer is initiated. Specifically, when the XBSA Application
issues either the
BSACreateObject()
call or the
BSAGetObject()
call, the BSA_DataBlock32 structure is not used for passing data but
for passing the Backup Service's preference. The parameters that
must be set by the Backup Service, and their meaning, are given in
Parameters in the BSA_DataBlock32 Structure
.
bufferLen == 0
| The Backup Service has no restrictions on the buffer length.
No trailer portion is required.
|
bufferLen != 0
| The Backup Service accepts buffers that are at least
bufferLen bytes in length (minimum length). It also
accepts larger buffers.
For a BSASendData() call, the Backup Service
accepts a trailer that is as least as large as:
trailerBytes >= (bufferLen - numBytes - headerBytes)
For a BSAGetData call, the Backup Service returns
a trailer that is not larger than:
trailerBytes <= (bufferLen - numBytes - headerBytes)
|
numBytes == 0
| The Backup Service has no restrictions on the length of
the data portion of the buffer.
|
numBytes != 0
| The Backup Service accepts (for a BSASendData() call),
or returns (for a BSAGetData() call), a data segment
that does not exceed numBytes bytes.
|
headerBytes == 0
| The Backup Service only accepts or returns buffers with
no header.
|
headerBytes != 0
| The length of the header portion of buffers accepted
or returned by the Backup Service is headerBytes bytes.
|
bufferPtr
| Not used
|
Table: Parameters in the BSA_DataBlock32 Structure
Subsequent calls to
BSAGetData()
or
BSASendData()
must adhere to
the preferences that were specified by the Backup Service.
The relationship between the areas, and their mapping to the
fields of the BSA_DataBlock32 structure is described in
BSA_DataBlock32
.
The Backup Service can write anything into the header and trailer area
of the actual buffer, as specified by the bufferPtr parameter in
the BSA_DataBlock32 structure.
Use of BSA_DataBlock32 in BSASendData()
For
BSASendData(),
all parameters in the BSA_DataBlock32 structure must
be set by the XBSA Application and adhere to the Backup Service
preferences or the function will fail with a BSA_RC_INVALID_DATABLOCK error.
The Backup Service is not allowed to change any of the parameters.
Use of BSA_DataBlock32 in BSAGetData()
For
BSAGetData(),
all parameters in the BSA_DataBlock32 structure must
be set by the XBSA Application and adhere to the Backup Service
preferences or the function will fail with a BSA_RC_INVALID_DATABLOCK error.
The Backup Service must change the following parameter:
-
numBytes
Set the actual number of bytes copied into the data segment.
The Backup Service is not allowed to change any of the other parameters.
Shared Memory
The BSA_DataBlock32 structure contains fields that allow the use of shared memory
blocks for passing data between an XBSA Application and a Backup Service.
The shareId specifies an identifier that can be used by the Backup
Service to map the memory in which the buffer resides into its
address space. A special typedef, BSA_ShareId, is used to define
the shareId
field using a type appropriate for the operating environment.
For UNIX systems, this is based on the shared memory semantics
defined in the Single UNIX Specification, System Interfaces and Headers, Issue 5
(see reference XSH, Issue 5)
and the shareId is the shmid identifier
obtained by calling the
shmget()
function. For NT systems, it is a file handle which will allow the
Backup Service to map the file in memory.
The shareOffset specifies where in shared memory the buffer
starts.
The semantics for the shareId are given in
Parameters in the BSA_DataBlock32 Structure
.
shareId == -1
| This buffer is not available in shared
memory. The shareOffset field is undefined.
The bufferPtr is a true pointer in the
address space of the client.
|
shareId != -1
| The Backup Service may map this buffer into
its memory by using the appropriate operating
system services. The shareOffset becomes an
offset into the shared memory. The bufferPtr
is a true pointer in the address space of the
client.
Note that the Backup Service is not forced to map the buffer into
its address space. It can copy the buffer in the address space of
the XBSA Client.
|
Table: Semantics for shareId
Since the client may be using multiple buffers, it is not
guaranteed that only one shareId is used in the object data
transfers. It is guaranteed, however, that a shareId itself will
not change during a session. In other words, the XBSA Client is
not allowed to re-map a shareId within a session once it has been
made available to the Backup Service. In this way the Backup Service
can keep a simple lookup table to see whether the shareId is currently
mapped in its address space.
The following two sections describe how shared memory buffers are used in
the UNIX and Microsoft Windows NT operating systems.
Shared Memory on UNIX
For UNIX, the scenario for shared memory is as follows:
-
The client performs either a
BSACreateObject()
or
BSAGetObject()
call to
start the transfer and receives the buffer parameters.
-
The client allocates a buffer in shared memory, thereby receiving a
shared memory identifier. The client fills the buffer with data, if necessary.
-
The client calls
BSASendData()
or
BSAGetData()
with the buffer
parameters and the identifier of the shared memory block it previously
allocated.
-
The library implementation forwards the information to a different
process, which will have to map the shared memory into its address
space. This process can use
shmctl()
to retrieve the size of the
shared memory segment, and use
shmat()
to attach the memory to its
address space. Once attached, it uses the shareOffset to locate
the actual buffer, and from there the normal BSA_DataBlock32 rules
apply.
Shared Memory on NT
For NT, the scenario for shared memory is as follows:
-
The client performs either a
BSACreateObject()
or
BSAGetObject()
call to start the transfer and receives the buffer parameters.
-
The client allocates a buffer in shared memory, thereby receiving a
file handle. The shared memory is set up by creating a
file-mapping object using
CreateFileMapping(),
and mapping it the
client's address space with
MapViewOfFile().
The client fills the
buffer with data, if necessary.
-
The client calls
BSASendData()
or
BSAGetData()
with the buffer
parameters and the file handle of the file it used for mapping the
shared memory.
-
The library implementation forwards the information, including the
process ID of the client, to a different process. This process
will have to duplicate the handle using
OpenProcess()
and
DuplicateHandle(),
and map the file in its address space with
MapViewOfFile().
Once mapped, it uses the shareOffset to locate
the actual buffer, and from there the normal BSA_DataBlock32 rules
apply.
For details of the
interfaces, refer to the Microsoft Windows NT documentation.
Why not acquire a nicely bound hard copy?
Click here to return to the publication details or order a copy
of this publication.