Introduction
The InterBase services manager is a new feature added to the latest version
of the product. The services manager allows developers to program
administrative functions, like backup, restore, and user management, directly
into their applications. Prior to the existence of the services manager,
it would be necessary to perform these types of functions by either using
the command line utilities by themselves or having the application execute
the utility. This paper will describe how the services manager works
as well as how to integrate it into your new InterBase 6.0 applications.
The objective of this paper is to outline the basics of using this new
feature in InterBase and to present ideas of how it can be used to enhance
existing or new applications written using InterBase.
How it works
Normally when using the InterBase API, a connection is made to a specific
database. From this connection, information can be retrieved.
The services manager works outside the realm of databases. This allows
an application to make a connection directly to the server without first
making a connection to a database. Because of this, is is possible
to get information on the server itself as well as initiate actions on
databases.
The services manager makes use of two type of services: passive services
and active services. By using these services effectively, applications
can easily administer a server and customize its interface based on the
capabilities and version of a server.
Passive Services
Passive services are used to retrieve information from the server and do
not require the server to start a thread to perform some kind of action,
unlike active services which will be discussed next. Passive services
can be started using the API call isc_service_query and will not
return from the server until the request is processed or a timeout period
has expired. When the server receives a request for a passive services,
it simply locates the service requested, retrieves the required information,
and places the information in the output buffer sent in via the API call.
The information returned by these types of services fall into the following
three categories.
-
Static information
This information does not change based on the state of the server
since it is usually a static element inside the server. Different
types of static information which can be retrieved from the server
include
-
the version and implementation of the server, for example a Windows NT
server would return "WI-V6.0.0" for its version and its implementation
would return "InterBase/x86/Windows NT"
-
the version of the services manager, currently 2
-
the path to and name of the security database (ISC4.GDB) currently in use
-
the path to the directory which contains the interbase.msg file
-
and the location where the server will create its .lck files.
-
Dynamic information
Dynamic information changes based on the state of the InterBase
server. When requesting dynamic information from the server, it is
important to keep in mind that the service query call will return the information
based when the server started processing the request. Any changes
made while the request is being processed may not be reflected in the return
from a particular request. Dynamic information which can be returned
from the server include
-
the number of active user connections on the server
-
the names and number of databases in use by the server
-
the current licenses active on the server (certificate keys and IDs)
-
the number of users licensed to access the server
-
the current settings in the InterBase configuration file
Dynamic information can be used in conjunction with the existing InterBase
API calls to return information such as the users connected to a particular
database, and with the active services to perform administrative tasks
such as adding additional user licenses to the server and retrieving log
file information.
-
Active Service Information
A number of the services which can be started instruct the server
to perform some action. These services are known as active services
and will be discussed next. When requesting information about an
active service, it is important to remember to start the service first
(otherwise, your calls will fail). Information which can be
retrieved from the server when using the two types of services together
include
-
the interbase.log file from a remote server
-
the user information found in the InterBase security database (ISC4.GDB)
-
the information about limbo transactions
-
and the verbose output that results from a database backup or restore
Active Services
Active services are used to request that the server start a worker thread
to perform some kind of action. Active services are started using
the API call isc_service_start and will return control back to the
client from the server once the thread has been started or on an error
condition. When the server receives a request to start an active
serrvice, it locates the service requested, parses the service parameter
buffer, and starts the thread specified by the service action call.
The services manager only allows one active service to be running at
a time per attachment to the services manager. Because of this, active
services are usually started in the following manner
-
call isc_service_attach with the appropriate connection information
-
call isc_service_start with the parameters needed for a particular
service
-
call isc_service_query to retrive information about the service
which was started
-
call isc_service_detach to disconnect from the services manager
The services which can be started using isc_service_start mirror
the functionality of the command-line tools gbak, gstat, gfix, and
gsec. The follwing tasks can be performed using active services:
-
Database backup and restore
-
Database validation and repair
-
Adding, modifying, removing, and retrieving user entries from the security
database
-
Administering software activation certificates
-
Setting database properties
-
Retrieving remote interbase.log files
Security
The security context used by the services manager is determined by the
information passed in when connecting to the services manager. When
connecting to the service manager, the input parameter block will specify
a username and a password. This information is used to determine
if the username and password combine to make a valid InterBase user and
to determine if the user is the SYSDBA user. This base security context
is used for all services, active or passive, which are executed using this
connection.
Some of the services can only be accessed by the SYSDBA user, for example
adding license certificates. Most of the passive services can be
accessed by any valid InterBase user and many of the active services take
an optional role name as a parameter if the service acts on a database,
for example modifying user information in the security database.
Working with services
When working with services, the most important thing to remember is that
everything done by the services is with respect to the server and its environment.
This is particularly important when using the active services. If
you are already familiar with using the InterBase API to work with databases
and transactions, then working with services should seem familiar.
Note:
All length values in the spb must be 2 bytes and all numeric data values
in the spb must be 4 bytes, there are two new macros that have been added
to ibase.h. They are ADD_SPB_LENGTH and ADD_SPB_NUMERIC.
Each of these takes a pointer to the spb and the data to be added.
ADD_SPB_LENGTH adds the length to the spb as 2 bytes and ADD_SPB_DATA adds
the data to the spb as 4 bytes. After each of these macros are called,
the spb is incremented to the next available slot in the buffer.
The macros are defined as follows:
#define ADD_SPB_LENGTH (p, length) {*p++ = length;
*p++ = length >> 8;}
#define ADD_SPB_NUMERIC (p, data) {*p++ = data;
*p++ = data >> 8;
*p++ = data >> 16;
*p++ = data >> 24;}
When parsing a buffer which has information returned from the server via
a call to isc_service_query, discussed later, the same restriction
applies. Use the existing InterBase API call isc_vax_integer
to process the length and numeric data information.
Connecting to the services manager
The first step in working with the services manager is connecting to it.
This is done using the API call isc_service_attach which is defined
as follows:
ISC_STATUS ISC_EXPORT isc_service_attach (ISC_STATUS *status_vector,
ISC_USHORT service_length,
char *service,
isc_svc_handle *svc_handle,
ISC_USHORT spb_length,
char *spb)
returns: value of ISC_STATUS[1] :: 0 if no error
>0 if there is an error
*status_vector: pointer to a 20 element array of ISC_STATUS
service_length: length in characters of the name of the service and host to connect to.
Specify 0 if the service is a null terminated string.
*service: pointer to a character buffer containing the name of the host to connect to.
*svc_handle: pointer to a long value used to store the handle of the service structure
on the server. note: This value MUST be 0L when attaching to a service.
spb_length: length in bytes of the service parameter buffer
*spb: pointer to a buffer containing the service parameter
To specify which server to connect to, set the service parameter
to one of the following connection strings
-
serverhost:service_mgr for a TCP/IP connection
-
serverhostservice_mgr for a NetBEUI connection
-
serverhost@service_mgr for a SPX connection
-
service_mgr for a local connection
The literal string service_mgr is required in all instances.
Replace serverhost with the name of the actual server that
will be used for the connection.
Before intiating a connection to the services manager, a service parameter
block (SPB) must be filled out with the username and password to be used
for the connection. As described earlier, the username and password
used to connect will be used to determine access to other services.
Once the connection is made, use the svc_handle to start or query
services and to disconnect from the services manager.
An example of how to connect to the services manager via TCP/IP
char *user = "SYSDBA",
*pass = "masterkey";
ISC_STATUS status [20];
isc_svc_handle *svc_handle = NULL;
char svc_name[32],
spb_buff[128],
*spb = spb_buff,;
ISC_USHORT spblen;
*spb++ = isc_spb_version;
*spb++ = isc_spb_current_version;
*spb++ = isc_spb_user_name;
*spb++ = strlen (user);
strcpy (spb, user);
spb += strlen (user);
*spb++ = isc_spb_password;
*spb++ = strlen (pass);
strcpy (spb, pass);
spb += strlen (pass);
sprintf (svc_name, "myserver:service_mgr"); /* TCP/IP */
spblen = spb - spb_buff;
if (isc_service_attach (status, 0, svc_name, &svc_handle, spblen, spb_buff))
{
isc_print_status (status);
exit (1);
}
The user parameters accepted in the spb for isc_service_attach are:
| Parameter |
Length |
Data |
Meaning |
| isc_spb_current_version |
1 |
isc_spb_version |
2 bytes which specify the version of the spb. These
must always be the first two bytes in the spb. |
| isc_spb_user_name |
length of username |
the username |
the username to connect to the service manager with.
This username will be used for all services that require a username to
be specified. |
| isc_spb_password |
length of password |
the password |
the password to connect to the service manager with.
This password will be used for all services that require a password to
be specified. |
Starting services
Once a client has attached to the services mananger using isc_service_attach,
the client uses this API call to start an active service on the server.
As mentioned before, active services can perform such operations as database
backup, log file retrieval, or administration of server licenses.
Only one active service can be started at a time per service handle.
An error will result if an attempt is made to start more than one service
on the server using the same service handle. The API
call for starting a service, isc_service_start is defined as follows:
ISC_STATUS ISC_EXPORT isc_service_start(ISC_STATUS *status_vector,
isc_svc_handle *svc_handle,
isc_resv_handle *reserved,
ISC_USHORT spb_length,
char *spb);
returns: value of ISC_STATUS[1] :: 0 if no error
>0 if there is an error
*status_vector: pointer to a 20 element array of ISC_STATUS
*svc_handle: pointer to a long value used to store the handle of the service structure
on the server. This must point to a handle previously allocated in
isc_service_attach.
*reserved: this parameter is being reserved for future use
spb_length: length in characters of the send buffer
*spb: pointer to a buffer containing flags instructing the service manager to process
information
For each service action, there is a list of parameters which define that
action. The paramters consist of three different peices of
information: the parameter name, a length, and a value. The length
and value are specific to the individual parameters.
The services which can be started using isc_service_start are
| Service |
Description |
Restrictions
|
| isc_action_svc_backup |
Starts database backup process on the server |
SYSDBA or database owner |
| isc_action_svc_restore |
Starts database restore process on the server |
SYSDBA or database owner |
| isc_action_svc_repair |
Starts database repair process on the server |
SYSDBA or database owner |
| isc_action_svc_add_user |
Adds a new user to the security database |
none |
| isc_action_svc_delete_user |
Deletes a user record from the security database |
none |
| isc_action_svc_modify_user |
Modifies a user record in the security database |
none |
| isc_action_svc_display_user |
Displays a user record from the security database |
none |
| isc_action_svc_properties |
Sets database properties |
SYSDBA or database owner |
| isc_action_svc_add_license |
Adds a license to the license file |
SYSDBA user only |
| isc_action_svc_remove_license |
Removes a license from the license file |
SYSDBA user only |
| isc_action_svc_db_stats |
Retrieves database statistics |
SYSDBA or database owner |
| isc_action_svc_get_ib_log |
Retrieves the InterBase log file from the server |
none |
When the server receives a request to start a service thread, the following
process occurs
-
The service parameter is validated against the known services. This
determines the thread to start and any security restrictions that may be
in place.
-
Next, a check is made to determine if any services are currently running
using the same service handle. If another service is active and using
the same service handle, the current request to start is denied and an
error is returned to the client.
-
The parameters to the service are parsed and validated based on the information
passed in. The service parameters are validated twice; once by the
server and again by the service thread. Since the service threads
mirror much of the same functionality as some of the command-line tools,
the service thread will always produce an exact error if one is encountered
during the parsing stage.
-
After the service has been identified and the service parameters parsed
and organized into a form by which it can be recognized by the thread,
the service thread is launched. At this point the server waits
until the thread sends an event which signals that all intialization is
complete and the serivice has actually started, or in some cases completed.
-
Once the server receives the event, the isc_service_start call returns
control back to the client.
It is very important to keep in mind that the service is executing based
on the current server environment and not the client environment.
This means that any database or file parameters specified must be done
with respect to the server.
The return value and status from isc_service_start represents
any error that could have occurred either in the process of launching the
service thread or from the service itself, for example, the database to
backup could not be opened. isc_service_start will not return
until the service has completed its initialization and is actually running.
The following is an example of starting the service to retrieve the contents
of the interbase.log file. It assumes that a connection has already
been made using isc_service_attach.
ISC_STATUS status [20];
char thd_buff[256], *thd = thd_buff;
ISC_USHORT thdlen;
/* isc_service_attach happens here */
*thd++ = isc_action_svc_get_ib_log;
thdlen = thd - thd_buff;
if (isc_service_start(status, &svc_handle, NULL, thdlen, thd_buff))
{
isc_print_status (status);
isc_service_detach (status, &svc_handle);
exit(1);
}
Many of the active services return some type of information back to
the client. The way this is accomplished is via a call to isc_service_query,
which will be discussed next. The information from the service thread
is stored in an internal buffer in the server. This buffer is currently
set to hold 1k worth of information. If, while the service is writing
to this internal buffer, the buffer becomes filled, the service thread
will wait until there is more room in the buffer. In order
for the buffer to be emptied, the client must query this information.
However, if, while the service is running the client disconnects, the service
will stop writing to the internal buffer, but will complete its operation.
There is currently no way to cancel a running service.
Querying services
In addition to starting active services on the server using isc_service_start,
a client can start a passive service using the API call isc_service_query
once a successful connection has been made to the services manager via
isc_service_attach. The client uses
this API call to retrieve information about the server, such as the installed
licenses or to return information from a currently running active service.
This is accomplished by specifying the correct parameters in the receive
buffer specified in the API call which is defined below
ISC_STATUS ISC_EXPORT isc_service_query (ISC_STATUS *status_vector,
isc_svc_handle *svc_handle,
isc_resv_handle *reserved,
ISC_USHORT send_spb_length,
char *send_spb,
ISC_USHORT recv_spb_length,
char *recv_spb,
ISC_USHORT response_buffer_length,
char *response_buffer);
returns: value of ISC_STATUS[1] :: 0 if no error
>0 if there is an error
*status_vector: pointer to a 20 element array of ISC_STATUS
*svc_handle: pointer to a long value used to store the handle of the service structure on the server.
This must point to a handle previously allocated in isc_service_attach.
*reserved: this parameter is being reserved for future use
send_spb_length: length in characters of the send buffer
*send_spb: pointer to a buffer containing flags instructing the service manager to process information
recv_spb_length: length in characters of the receive buffer
*recv_spb: pointer to a buffer containing flags instructing the service manager to return information
response_buffer_length: length in characters of the return buffer
*response_buffer: pointer to a buffer containing information received from the services manager
The services which can be used to return information about the server and
its environment are
| Service |
Description |
| isc_info_svc_svr_db_info |
Retrieves the number of active attachments, databases, and database
names |
| isc_info_svc_get_license |
Retrieves all license keys and IDs from the license file |
| isc_info_svc_get_license_mask |
Retrieves a bitmask representing licensed options on the server |
| isc_info_svc_get_config |
Retrieves the parameters and values for IB_CONFIG |
| isc_info_svc_version |
Retrieves the version of the services manager |
| isc_info_svc_server_version |
Retrieves the version of the InterBase server |
| isc_info_svc_implementation |
Retrieves the implementation of the InterBase server |
| isc_info_svc_capabilities |
Retrieves a bitmask representing the server's capabilities |
| isc_info_svc_user_dbpath |
Retrieves the path to the security database in use by the server |
| isc_info_svc_get_env |
Retrieves the setting of $INTERBASE |
| isc_info_svc_get_env_lock |
Retrieves the setting of $INTERBASE_LCK |
| isc_info_svc_get_env_msg |
Retrieves the setting of $INTERBASE_MSG |
| isc_info_svc_get_licensed_users |
Retrieves the number of users licensed for accessing the server |
As mentioned earlier, isc_service_query can also be used to return
information about any active services which are currently running on the
server. The services which retrieve information from active services
are
| Service |
Description |
Active service |
| isc_info_svc_get_users |
Returns the user information from isc_action_svc_display_users |
isc_action_svc_display_user |
| isc_info_svc_limbo_trans |
Retrieve the limbo transactions |
isc_action_svc_repair with the option isc_spb_rpr_list_limbo_trans |
| isc_info_svc_running |
Checks to see if a service is running on an attachment |
can be used with any isc_action_svc call |
| isc_info_svc_line |
Retrieves 1 line of service output per call |
can be used with any isc_action_svc call |
| isc_info_svc_to_eof |
Retrieves as much of the server output as will fit in the supplied
buffer |
can be used with any isc_action_svc call |
Calls to isc_service_query can request more than one item at
a time. This can be useful in reducing the number of calls
to the server, however, as with anything, there are always caveats.
If the call to isc_query_service is going to return more information
than can fit in the response buffer, the buffer will be filled with as
much information as possible and the buffer will be terminated by the flag
isc_info_truncated. Since these services normally return information
about the server's environment, there is no way to reissue the request
and have it restart from where the last call left off. To retrieve
all of the informaion requested, the response buffer will need to be increased
and another call will need to be made.
Now, the information regarding isc_info_truncated only relates
to those services which do not work with active services.
The following example demonstrates how to request and process a query
to return the number of users licensed to access the server and the path
to the interbase.msg which is currently in use.
@@ Insert Example here!!
Detaching services
Just as when working with databases, you should always disconnect from
the services manager when finished. If an application does not disconnect
properly, the server will continue to hold onto the memory used by the
connection until the server detects that the client is no longer attached.
Once the server detects that the client is not connected, all memory held
by that connection is freed. To detach from the services manager,
use the API call isc_service_detach which is defined as
ISC_STATUS ISC_EXPORT isc_service_detach (ISC_STATUS *status_vector,
isc_svc_handle *svc_handle);
returns: value of ISC_STATUS[1] :: 0 if no error
>0 if there is an error
*status_vector: pointer to a 20 element array of ISC_STATUS
*svc_handle: pointer to a long value used to store the handle of the service structure on the
server. This must point to a handle previously allocated in isc_service_attach.
Working with the results
Now that we have discussed the mechanics involved in accessing and working
with the services manager, it is time to explore how to work with the information
returned from the services mananger.
All calls into the services manager return a status vector which contains
any errors which may have occurred during the call. However, in order
to actually work with the information requested, a call to isc_service_query
is required. As mentioned above, the service manager can be queried
to return information about the server's environment or about active services
which are currently running or have just completed. Information is
returned using via the response buffer specified in the call to isc_service_query.
This buffer contains information in one of two formats; formatted or unformatted.
Unformatted buffers
Most active services store their information as unformatted text inside
the server. An example of an active service which stores its
information this way is isc_action_svc_backup which is used to backup
a database. When this service is initiated along with the parameter
isc_spb_verbose, the backup service will store all of the output
produced. This corresponds to the -v flag used with the command-line
tool GBAK. The information stored in the internal buffer is
then returned to the client via isc_service_query using either the
parameter isc_info_svc_line or isc_info_svc_to_eof.
Using the parameter isc_info_svc_line instructs the server to fill
the client's buffer with no more than 1 line of information. Since
a line of information is delimited by a carriage return, the response buffer
for the query call does not have to accomodate 1K of information, however
it may require more calls into the server. An alternative method
for returning the information is to use isc_info_svc_to_eof .
Using this parameter in the query call instructs the server to fill the
client's response buffer with as much information as will fit. In
order to make the most of the call to the server using isc_info_svc_to_eof,
it is important to keep in mind that the server will store up to 1K of
information at a time. In addition, it is even more important to
keep in mind that once the internal buffer is full, the service will not
continue until the client requests some of the information stored in the
buffer. The database backup example will show how to work with and
unformatted buffer returned by isc_info_svc_line.
Formatted buffers
While some of the active services return unformatted information, which
in this case is basically equivalent to a text dump, most of the services
return information in a formatted buffer. The information in a formatted
buffer is returned via a specific buffer sent in with the call to isc_service_query.
The information returned has a is very specific to the parameter sent in,
however, the format of the buffer is fairly generic between the different
services.
The basic format of the buffer is made of clumpets of data, much like
an InterBase status vector or dpb buffer. The format of a service
buffer is
For queries that return a single piece of information (i.e. isc_info_svc_get_env)
<isc_info_svc_get_env>
<2 byte length>
<data>
<isc_info_end>
For queries that return numeric information (i.e isc_info_svc_get_licensed_users)
<isc_info_get_licensed_users>
<4 byte data>
<isc_info_end>
For queries that return a clumpet of information (i.e. isc_info_svc_db_info)
<isc_info_svc_db_info>
<isc_spb_num_att>
<4 byte data>
<isc_info_spb_num_users>
<4 byte data>
<isc_info_spb_dbname>
<2 byte length>
<data>
..... (the clumpet is repeated for each database)
<isc_info_spb_dbname>
<2 byte length>
<data>
<isc_info_flag_end>
<isc_info_end>
Even though each call has a slightly different return buffer, they all
follow the same pattern which is
-
The first bit of the clumpet responds to the information being requested
-
The next bit of the clumpet corresponds to one of three things (based on
the first bit)
-
A 2 byte length which indicates the length of the data to follow
-
A 4 byte numeric value which indicates the data requested
-
A bit which represents the start of a new clumpet of information which
will end with isc_info_flag_end
-
The last bit of the return buffer is one of the following flags
-
isc_info_end which indicates that all of the information requested
was returned successfully
-
isc_info_truncated which indicates that not all of the information
requested could be returned in the buffer given. If the information
returned was truncated, you will need to increase the response buffer and
reissue the query. The information returned when the query is reissued
will start from the first request. It will not continue where
it left off.
Example: Database Backup
To put all of the information presented above into perspective, this example
will center around performing a database backup and will use much of the
information presented above. As with all services, and especially
those which work with databases, it is extremely important to remember
that the service is excuted on the server.
This example is separated into two parts. The first part performs
the setup for connecting to the services manager and starting the service.
In this section there will be examples of the following:
-
setting up the connection SPB and attaching to the services manager
-
setting up the SPB for starting the service
-
basic error handling
The second part of the example focuses on querying the service to provide
the output for the backup. There will be specific examples of
-
setting up the receive spb to issue the query using isc_info_svc_line
-
parsing an unformatted buffer
-
sending the output to the console
-
detaching from the services manager
The setup
char *user = "SYSDBA",
*pass = "masterkey",
*dbname = "employee.gdb",
*bkup_file = "employee.gbk";
ISC_STATUS status [20];
isc_svc_handle svc_handle = NULL;
char svc_name[RESPBUF], spb_buff[RESPBUF], thd_buff[RESPBUF];
char respbuf[RESPBUF], *p = respbuf, *spb = spb_buff, *thd = thd_buff,*x;
short spblen, thdlen;
int i = 0, cnt=0;
boolean finished = FALSE;
/* Set up the spb for connecting to the services manager.
* in this example, we will connect to the server running
* on the local machine.
*/
*spb++ = isc_spb_version;
*spb++ = isc_spb_current_version;
*spb++ = isc_spb_user_name;
*spb++ = strlen (user);
strcpy (spb, user);
spb += strlen(user);
*spb++ = isc_spb_password;
*spb++ = strlen (pass);
strcpy (spb, pass);
spb += strlen (pass);
sprintf (svc_name, "service_mgr");
spblen = spb - spb_buff;
if (isc_service_attach (status, 0, svc_name, &svc_handle, spblen, spb_buff))
{
isc_print_status (status);
exit (1);
}
/* Set up the spb for starting the backup service */
*thd++ = isc_action_svc_backup;
/* Add the database name to the buffer */
*thd++ = isc_spb_dbname;
ADD_SPB_LENGTH (thd, strlen(dbname));
strcpy (thd, dbname);
thd += strlen (dbname);
/* Add the name of the backup file to the buffer */
*thd++ = isc_spb_bkp_file;
ADD_SPB_LENGTH (thd, strlen(bkup_file));
strcpy (thd, bkup_file);
thd += strlen (bkup_file);
/* Specify that that we want verbose output (GBAK -v) */
*thd++ = isc_spb_verbose;
thdlen = thd - thd_buff;
/* Start the service and process any errors that may be returned */
if (isc_service_start(status, &svc_handle, NULL, thdlen, thd_buff))
{
long *vector = status;
printf ("Unable to start service:n");
while (isc_interprete (respbuf, &vector))
printf ("ERROR: %sn", respbuf);
printf ("End of errorsn");
isc_service_detach (status, &svc_handle);
exit(1);
}
Seeing the results
do {
/* Add isc_info_svc_line to the send buffer for the query */
char sendbuf[] = {isc_info_svc_line};
ISC_STATUS loc_status[20], *stat = loc_status;
/* Issue the query */
if (isc_service_query (status, &svc_handle, NULL, 0, NULL,
sizeof (sendbuf), sendbuf, RESPBUF, respbuf))
{
isc_print_status (status);
isc_service_detach (status, &svc_handle);
exit(1);
}
/* If the query is successful, start processing the return buffer */
x = p = respbuf;
if (*p++ == isc_info_svc_line)
{
ISC_USHORT len = 0, chTmp = 0;
/* Get the length of the data being returned */
len = (ISC_USHORT)isc_vax_integer(p, sizeof(ISC_USHORT));
p += sizeof (ISC_USHORT);
/* If there is no length, then we should be done .. let's check */
if (!len)
{
if (*p != isc_info_end)
printf ("Format error ... <%d>n", *p);
else
printf ("Output completedn");
break;
}
/* There is a length for the data, so to be different, let's print
* it out character by character
*/
for (chTmp = 0; chTmp < len; chTmp++)
printf("%c",p[chTmp]);
/* Since we only requested one item this time, we should be at the end of
* the buffer terminated by isc_info_end after moving the pointer past the
* data we just printed out
*/
p += len;
if (*p != isc_info_truncated && *p != isc_info_end)
{
printf ("Format error ... encountered <%d>n", *p);
break;
}
}
}
while (*x == isc_info_svc_line);
isc_service_detach(status, &svc_handle);
}
Summary
This paper outlined the new InterBase services manager which can enable
developers to program administrative functions, like backup, restore, and
user management, directly into new applications. To be successful
with the services API, it is important to keep the following issues in
mind.
-
All services are performed on the server based upon the server's environment
-
Working with the services are much like working with databases, though
not the same
-
The username and password used to connect to the services manager is going
to be used for all subsequent calls using that attachment
-
All numeric information must be passed to the services manager as a 4 byte
value. Use the macro ADD_SPB_DATA to facilitate this
-
All lengths returned from the services manager are 2 bytes and numeric
data is 4 bytes. Use isc_vax_integer to retrieve this
information
-
The basic format of the return buffers is the same, however, it is specific
to the information being requested
-
Keep and open mind. Much of the information can be combined with
other API calls to really take advantage of the InterBase server.
For example, an application can return a list of all the usernames currently
attached to all databases which are active on the server. This can
be accomplished using the service isc_info_svc_db_info and a call
to isc_database_info with the dpb parameter isc_info_user_names.
Presented at the 1999 Borland Develpers Conference
Connect with Us