Administration API - Design Specification

High-Level Design

High-Level Algorithm

The Server Administration API will be implemented using the existing InterBase services manager using the existing API calls: isc_service_attach, isc_service_detach, and isc_service_query. A new API call will be introduced, isc_service_start, which instructs the server to start a utility thread. The plan of attack for working with the server via the services manager is:

  1. Attach to the services manager using isc_service_attach
    The service manager will call SVC_attach so that it can allocate an SVC structure which contains all the information needed by additional calls including: username of the user issuing the call, version of the spb being used, handles for stdin / stdout redirection.
  2. Using the handle returned, call either isc_service_query or isc_service_start
    isc_service_query

    Based on the spb version stored in the SVC structure, the server will either connect to SVC_query2 (v2) or SVC_query (v1). Once the server has verified that the info parameter is correct (isc_info_svc_xxx), it returns the requested information, specified in the service parameter buffer (spb), to the client.

    isc_service_start
    starts the thread specified by the isc_action_svc parameter in the spb. This call is new to the services API and is not supported by older clients. Its purpose is to tell the server to do something and then return. To retrieve information about some actions, use isc_service_query with the appropriate isc_info_svc parameter. The server uses the username, stdin/out, and spb version in the SVC structure to determine how a thread should be launched. To determine which thread routine to start, SVC_start uses a table, stored in the serv structure, to find the proper thread routine as well as any command-line parsing routine that needs to be called in order to convert the spb parameters into command-line arguments that can be used by the utility threads.
  3. Detach from the services manager using isc_service_detach
    With this call, the server frees the SVC structure from the services manager. The client is not required to allocate / free service handles for each call. A single service handle can be used many times provided that it is not in use prior to any calls (i.e. calling 4 isc_service_starts before any of them are complete).

Interfaces

Service API Functions

The services to start / return data from are now found in isc_service_query and isc_service_start.

ISC_STATUS ISC_EXPORT isc_service_attach 

(ISC_STATUS *status_vector,

unsigned short service_length,

char *service,

isc_svc_handle *svc_handle,

unsigned short spb_length,

char *spb);
returns: 

value of ISC_STATUS[1] :: 0 if no error

isc_error_code if there is an error
*status_vector: 

pointer to a 20 element array of long values (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.



The service name specifies the protocol and is as follows:

TCP/IP

hostname:service_mgr

SPX

@hostnane:service_mgr

Named Pipes

\\hostname\service_mgr

Local

service_mgr

*svc_handle: 

pointer to a long value used to store the handle of the service structure 

on the server.

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 parameters
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

isc_error_code if there is an error
*status_vector: 

pointer to a 20 element array of long values (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.
ISC_STATUS ISC_EXPORT isc_service_query 

(ISC_STATUS *status_vector,

isc_svc_handle *svc_handle,

isc_resv_handle *reserved,

unsigned short send_spb_length,

char *send_spb,

unsigned short recv_spb_length,

char *spb_items,

unsigned short buffer_length,

char *buffer);
returns: 

value of ISC_STATUS[1] :: 0 if no error

isc_error_code if there is an error
*status_vector: 

pointer to a 20 element array of long values (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
buffer_length: 

length in characters of the return buffer
*buffer: 

pointer to a buffer containing information received from the services 

manager
ISC_STATUS ISC_EXPORT isc_service_start

(ISC_STATUS *status_vector,

isc_svc_handle *svc_handle,

isc_resv_handle *reserved,

unsigned short spb_length,

char *spb);
returns: 

value of ISC_STATUS[1] :: 0 if no error

isc_error_code if there is an error
*status_vector: 

pointer to a 20 element array of long values (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

Service Definitions

/*********************************



 *Service parameter block *



 *********************************/



#define isc_spb_version1 		1

#define isc_spb_version			2

#define isc_spb_current_version		2

#define isc_spb_user_name		100

#define isc_spb_sys_user_name 		101

#define isc_spb_sys_user_name_enc 	102

#define isc_spb_password 		103

#define isc_spb_password_enc 		104

#define isc_spb_command_line 		105

#define isc_spb_dbname 			106

#define isc_spb_verbose 		107

#define isc_spb_options                 108



#define isc_spb_connect_timeout 	isc_dpb_connect_timeout

#define isc_spb_dummy_packet_interval 	isc_dpb_dummy_packet_interval

#define isc_spb_sql_role_name 		isc_dpb_sql_role_name



/*****************************



 *Service action items*



 *****************************/



#define isc_action_svc_backup          1 /* Starts database backup process on the server */ 

#define isc_action_svc_restore         2 /* Starts database restore process on the server */ 

#define isc_action_svc_repair          3 /* Starts database repair process on the server */ 

#define isc_action_svc_add_user        4 /* Adds a new user to the security database */ 

#define isc_action_svc_delete_user     5 /* Deletes a user record from the security database */ 

#define isc_action_svc_modify_user     6 /* Modifies a user record in the security database */ 

#define isc_action_svc_properties      7 /* Sets database properties */ 

#define isc_action_svc_add_license     8 /* Adds a license to the license file */ 

#define isc_action_svc_remove_license  9 /* Removes a license from the license file */ 

#define isc_action_svc_lock_stats     10 /* Retrieves lock manager statistics */

#define isc_action_svc_db_stats	      11 /* Retrieves database statistics */

#define isc_action_svc_set_config     11 /* Sets configuration file values - DO NOT DOCUMENT */ 

#define isc_action_svc_default_config 12 /* Sets the configuration options to their default values - DO NOT DOCUMENT */ 

#define isc_action_svc_set_env        13 /* Sets the value for $INTERBASE - DO NOT DOCUMENT */ 

#define isc_action_svc_set_env_lock   14 /* Sets the value for $INTERBASE_LOCK - DO NOT DOCUMENT */ 

#define isc_action_svc_set_env_msg    15 /* Sets the value for $INTERBASE_MSG - DO NOT DOCUMENT */ 



/*****************************



 * Service information items *



 *****************************/



/* Input */



#define isc_info_svc_svr_db_info      50 /* Retrieves the number of attachments and databases */ 

#define isc_info_svc_get_license      52 /* Retrieves a bitmask representing licensed options on the server */ 

#define isc_info_svc_get_config       53 /* Retrieves the parameters and values for IB_CONFIG */ 

#define isc_info_svc_version          54 /* Retrieves the version of the services manager */ 

#define isc_info_svc_server_version   55 /* Retrieves the version of the InterBase server */ 

#define isc_info_svc_implementation   56 /* Retrieves the implementation of the InterBase server */ 

#define isc_info_svc_capabilities     57 /* Retrieves a bitmask representing the server's capabilities */ 

#define isc_info_svc_user_dbpath      58 /* Retrieves the path to the security database in use by the server */ 

#define isc_info_svc_get_env	      59 /* Retrieves the value of $INTERBASE on the server */

#define isc_info_svc_get_env_lock     60 /* Retrieves the value of $INTERBASE_MSG on the server */

#define isc_info_svc_get_env_msg      61 /* Retrieves the value of $INTERBASE_LOCK on the server */

#define isc_info_svc_get_ib_log       62 /* Retrieves the contents of the interbase log file */



/* Output */



#define isc_info_svc_response         63

#define isc_info_svc_response_more    64

#define isc_info_svc_line             65

#define isc_info_svc_to_eof           66

#define isc_info_svc_timeout          67

#define isc_info_svc_data_not_ready   68



/******************************************************



 * Parameters for isc_action_{add|delete|modify)_user *



 ******************************************************/



#define isc_spb_sec_userid            1

#define isc_spb_sec_groupid           2

#define isc_spb_sec_username          3

#define isc_spb_sec_password          4

#define isc_spb_sec_groupname         5

#define isc_spb_sec_firstname         6

#define isc_spb_sec_middlename        7

#define isc_spb_sec_lastname          8





/*******************************************************



 * Parameters for isc_action_svc_(add|remove)_license,*



 *isc_info_svc_get_license*



 *******************************************************/



#define isc_spb_lic_key               9

#define isc_spb_lic_id                10





/*****************************************



 * Parameters for isc_action_svc_backup  *



 *****************************************/



#define isc_spb_bkp_file                 11

#define isc_spb_bkp_factor               12

#define isc_spb_bkp_length               13

#define isc_spb_bkp_ignore_checksums     0x01

#define isc_spb_bkp_ignore_limbo         0x02

#define isc_spb_bkp_metadata_only        0x04

#define isc_spb_bkp_no_garbage_collect   0x08

#define isc_spb_bkp_old_descriptions     0x10

#define isc_spb_bkp_transportable        0x20

#define isc_spb_bkp_mult_files           0x40

#define isc_spb_bkp_convert              0x80





/*********************************************



 * Parameters for isc_action_svc_lock_stats  *



 *********************************************/



#define isc_spb_lck_stats_sample	14

#define isc_spb_lck_stats_secs		15

#define isc_spb_lck_contents		0x01

#define isc_spb_lck_summary		0x02

#define isc_spb_lck_wait		0x04

#define isc_spb_lck_stats		0x08

#define isc_spb_lck_stats_thds		0x10

#define isc_spb_lck_stats_ops		0x20

#define isc_spb_lck_stats_wait		0x40



/********************************************



 * Parameters for isc_action_svc_properties *



 ********************************************/



#define isc_spb_prp_force_shutdown           16

#define isc_spb_prp_page_buffers             17

#define isc_spb_prp_set_write_mode           18

#define isc_spb_prp_sweep_interval           19

#define isc_spb_prp_activate                 0x01

#define isc_spb_prp_shutdown_db              0x02

#define isc_spb_prp_deny_new_attachments     0x04

#define isc_spb_prp_deny_new_transactions    0x08

#define isc_spb_prp_use_full_space           0x10

#define isc_spb_prp_wm_async		     0x20

#define isc_spb_prp_wm_sync		     0x40

#define isc_spb_prp_wm_readonly              0x80



/*****************************************



 * Parameters for isc_action_svc_repair  *



 *****************************************/



#define isc_spb_rpr_commit_transactions      20

#define isc_spb_rpr_rollback_transactions    21

#define isc_spb_rpr_list_limbo_transactions  22

#define isc_spb_trans_id                     23

#define isc_spb_trans_action                 24

#define isc_spb_rpr_checkdatabase            0x01

#define isc_spb_rpr_ignore_checksum          0x02

#define isc_spb_rpr_kill_shadows             0x04

#define isc_spb_rpr_mend_database            0x08

#define isc_spb_rpr_recover_two_phase        0x10

#define isc_spb_rpr_sweep_database           0x20

#define isc_spb_rpr_validate_database        0x40

#define isc_spb_rpr_full                     0x80

#define isc_spb_rpr_commit		     0x100

#define isc_spb_rpr_rollback		     0x200



/*****************************************



 * Parameters for isc_action_svc_restore *



 *****************************************/



#define isc_spb_res_buffers              25

#define isc_spb_res_page_size            26 

#define isc_spb_res_length               27

#define isc_spb_res_deactivate_indexes   0x01

#define isc_spb_res_no_shadow            0x02

#define isc_spb_res_no_validity          0x04

#define isc_spb_res_one_ata_time         0x08

#define isc_spb_res_restore              0x10

#define isc_spb_res_mult_files           0x20



/********************************************



 * Parameters for isc_action_svc_set_config *



 * isc_info_svc_get_config                  *



/********************************************/



#define isc_spb_ibc_lock_mem_size     28

#define isc_spb_ibc_lock_sem_count    29

#define isc_spb_ibc_lock_signal       30

#define isc_spb_ibc_event_mem_size    31

#define isc_spb_ibc_db_cache_pages    32

#define isc_spb_ibc_priority_class    33

#define isc_spb_ibc_svr_map_size      34

#define isc_spb_ibc_svr_min_work_set  35

#define isc_spb_ibc_svr_max_work_set  36

#define isc_spb_ibc_lock_grant_order  37

#define isc_spb_ibc_lockhash          38

#define isc_spb_ibc_deadlock          39

#define isc_spb_ibc_lockspin          40

#define isc_spb_ibc_conn_timeout      41

#define isc_spb_ibc_dummy_intrvl      42

#define isc_spb_ibc_trace_pools       43

#define isc_spb_ibc_temp_dir_name     44

#define isc_spb_ibc_temp_dir_size     45



/*******************************************



 * Parameters for isc_action_svc_set_env,  *



 * isc_action_svc_set_env_lock,            *



 * isc_action_svc_set_env_msg              *



 *******************************************/



#define isc_spb_env_path              46



/*******************************************



 * Parameters for isc_info_svc_svr_db_info *



 *******************************************/



#define isc_spb_num_att               47 

#define isc_spb_num_db                48



/*****************************************



 * Parameters for isc_info_svc_stats     *



 *****************************************/



#define isc_spb_sts_data_pages           0x01

#define isc_spb_sts_database_log         0x02

#define isc_spb_sts_header_pages         0x04

#define isc_spb_sts_index_pages          0x08

#define isc_spb_sts_system_relations     0x10

Detailed Design

Internal Data Structures

This feature is being implemented with very few changes to the existing services manager and utilities. Changes are in bold. Since this feature is making use of the existing NetWare service manager model, code that was once NetWare specific will be updated and will become generic for all platforms. The following structures have changed to accomodate the new features:

Changes to jrd\svc.h

The svc structure needs to accomodate an internal buffer ala NetWare) to hold the information coming from forking off a thread (i.e. GBAK). This structure also needs to keep track of the spb version so that calls to isc_service_query can be processed correctly. Lastly, the username is being stored so that operations that need to check database permissions can be handled without re-issuing username and password information (this information needs to be specified during the first call to isc_service_attach).

typedef struct svc {

struct blk	svc_header;

#ifndef NETWARE_386

    SLONG	svc_handle;	/* "handle" of process/thread running service */

    void	*svc_input;	/* input to service */

    void	*svc_output;	/* output from service */



#else



    ULONG	svc_handle;

    ULONG	svc_stdout_head;

    ULONG	svc_stdout_tail;

    UCHAR	*svc_stdout;

    TEXT	**svc_argv;

    ULONG	svc_argc;



#endif



    CONST struct serv *svc_service;

    UCHAR	*svc_resp_buf;

    UCHAR	*svc_resp_ptr;

    USHORT	svc_resp_buf_len;

    USHORT	svc_resp_len;

    USHORT	svc_flags;

    USHORT	svc_user_flag;



    USHORT	svc_spb_version;



    BOOLEAN	svc_do_shutdown;

    TEXT	svc_switches [1];



    TEXT	svc_username[33];

    TEXT	reserved[1];



} *SVC;



The spb structure is used to hold options passed into the service manager for the initial attachment. This structure needs to hold the spb_version so that it can be used as part of the service attachment process.

typedef struct spb {

    TEXT	*spb_sys_user_name;

    TEXT	*spb_user_name;

    TEXT	*spb_password;

    TEXT	*spb_password_enc;

    TEXT	*spb_command_line;

    SHORT       spb_version;

} SPB;



The serv structure is used to assure the validity of the service being passed. For version 1 calls (isc_spb_version1), this structure holds the names of the service and any information needed to fork the process during a call to isc_service_attach. In version 2, this structure is used by isc_service_start to locate the name of any command-line parsing function and the main thread to start. The serv_action element is needed since version 2 services are not specified as text.

typedef struct serv {



    USHORT	serv_action;

    CONST TEXT	*serv_name;

    CONST TEXT	*serv_std_switches;



#ifndef NETWARE_386



    CONST TEXT	*serv_executable;



#else



    CONST void	(*serv_thd)();

    CONST void  (*serv_cmdline)();

    BOOLEAN	*in_use;



#endif



} *SERV;
burp\burp.c

In order to continue using the same code for both the command-line GBAK and the new GBAK thread, the spb parameters to the GBAK thread need to be converted to command-line options. The main reason for this is that the GBAK thread and command-line tool must have the same functionality (hence the same code base) and existing utilities call into the services manager passing a command-line to GBAK. By providing a conversion routine in each of the command-line utilities, the services manager can make use of any new options added by simply adding the proper flags to ibase.h and adding an entry into the switch table.

typedef struct in_sw_tab_t {

    int     in_sw;

    int     in_spb_sw;

    TEXT    *in_sw_name;

    USHORT  in_sw_state;

    USHORT  in_sw_msg;

} *IN_SW_TAB;
lock\print.c



utilities\dba.e

These components make use of a simple switch statement to parse arguments. It is proposed that this be changed to adhere to the same method as is implemented in other tools, namely using a structure containing the options. This will allow for the ability for the services manager to convert spb parameters into command-line arguments.

typedef struct in_sw_tab_t {

    int     in_sw;

    int     in_spb_sw;

    TEXT    *in_sw_name;

} *IN_SW_TAB;
alice\alice.c

In order to continue using the same code for both the command-line GFIX and the new GFIX thread, the spb parameters to the GFIX thread need to be converted to command-line options. The main reason for this is that the GFIX thread and command-line tool must have the same functionality (hence the same code base) and existing utilities call into the services manager passing a command-line to GFIX. By providing a conversion routine in each of the command-line utilities, the services manager can make use of any new options added by simply adding the proper flags to ibase.h and adding an entry into the switch table.

typedef struct tbl {

    int		tbl_spb_sw;

    TEXT	*tbl_name;

    ULONG	tbl_value;

    ULONG	tbl_requires;

    ULONG	tbl_incompatibilities;

    TEXT	*tbl_text;

} TBL;



Detailed Algorithm

The following code snippets represent the functional changes that need to be made to the server and client so that the new functionality can be supported. Not included in this list are changes that were / need to be made so that existing tools continue to work as before. An example of this would be the service calls used in ibconfig.c to retrieve the configuration file parameters. Also not included are changes to parameter or function name from xxx_service to service_xxx. With the function name changes, their location in the source file was changed to maintain alphabetical order.

This feature requires a new spb version. To accomodate this, a new paramter definition, isc_spb_option has been added to ibase.h. This parameter, when used in conjunction with the new definition isc_spb_current_version define the new spb version. An example buffer adheres to the following format: isc_spb_version isc_spb_current_version This will allow the addition of spb versions without the need to renumber or add additional flags for buffer versioning.

remote\interface.c::svcstart

This is a new function used to prepare a packet of information that instructs the server to actually start the service via passing the proper information off.

#ifdef _ANSI_PROTOTYPES_

static STATUS svcstart (

    STATUS *user_status,

    RDB    rdb,

    P_OP   operation,

    USHORT object,

    USHORT incarnation, 

    USHORT item_length,

    SCHAR  *items)



#else



static STATUS svcstart (user_status, rdb, operation, object, incarnation, 

item_length, items)

    STATUS *user_status;

    RDB    rdb;

    P_OP   operation;

    USHORT object;

    USHORT incarnation;

    USHORT item_length;

    SCHAR  *items;



#endif



{



/**************************************

 *

 *	s v c s t a r t

 *

 **************************************



 *

 * Functional description

 *	Instruct the server to start a service

 *

 **************************************/



PACKET	*packet;

P_INFO	*information;

P_RESP	*response;

CSTRING	temp;



/* Build the primary packet to get the operation started. */



packet = &rdb->rdb_packet;

packet->p_operation = operation;

information = &packet->p_info;

information->p_info_object = object;

information->p_info_incarnation = incarnation;

information->p_info_items.cstr_length = item_length;

information->p_info_items.cstr_address = (UCHAR *) items;

information->p_info_buffer_length = item_length;



/* Assume the result will be successful */



assert (user_status == rdb->rdb_status_vector);

user_status [0] = gds_arg_gds;

user_status [1] = SUCCESS;

user_status [2] = gds_arg_end;



if (!send_packet (rdb->rdb_port, packet, user_status))

    return user_status [1];



/* Set up for the response packet. */



response = &packet->p_resp;

temp = response->p_resp_data;



if (!receive_response (rdb, packet))

    {

    response->p_resp_data = temp;

    return user_status [1];

    }



response->p_resp_data = temp;

return rdb->rdb_status_vector [1];

}
remote\server.c::service_start

This is a new function that calls into isc_service_start with the proper values for the service information provided by P_INFO.

#ifdef _ANSI_PROTOTYPES_



static STATUS service_start (



    PORT	port,

    P_INFO  	*stuff,

    PACKET	*send)



#else



static STATUS service_start (port, stuff, send)



    PORT	port;

    P_INFO  	*stuff;

    PACKET	*send;



#endif



{



/**************************************

 *

 *	s e r v i c e _ s t a r t

 *

 **************************************

 *

 * Functional description

 *	Start a service on the server.

 *

 **************************************/



RDB	rdb;



STATUS	status_vector [20];



rdb = port->port_context;



THREAD_EXIT;



isc_service_start (status_vector,

                   &rdb->rdb_handle,

                   stuff->p_info_items.cstr_length,

                   stuff->p_info_items.cstr_address);



THREAD_ENTER;



return send_response (port, send, 0, 0, status_vector);



}
ipserver\ipserver.c::service_start

This function is the entrypoint for starting a service on the server via IPC.

#ifdef _ANSI_PROTOTYPES_



static void service_start( 

    ICC         icc)



#else



static void service_start( icc)

    ICC         icc;



#endif



{



/**************************************

 *

 *      s e r v i c e _ s t a r t

 *

 **************************************

 *

 * Functional description

 *      Start a service.

 *

 **************************************/



IDB             idb, *ptr;

STATUS          status_vector[20];

STATUS          result;

ips_object      *ips;

ips_comm_area   *comm;

ps_string      *ips_spb;

TEXT            *comm_ptr;

USHORT          spb_length;

UCHAR           *spb, spb_buf[256];

HANDLE          handle;



/* set up communications area */



    GET_COMM_OBJECT;

    comm->ips_operation = op_service_start;

    ips = &comm->ips_operations.ips_op_object;

    handle = (HANDLE)ips->ips_handle;



/* figure out spb buffer */



    ips_spb = &comm->ips_buffers[IPS_START_SVC_SPB];

    spb_length = (USHORT)ips_spb->ips_cl_size;

    if ( spb_length <= sizeof( spb_buf))

        spb = spb_buf;

    else

        spb = get_buffer( comm, spb_length, IPS_START_SVC_SPB);

    NOT_NULL( spb, spb_length);

    IPS_SERVER( comm, IPS_START_SVC_SPB, spb, spb_length);

        if ( !transfer_buffers( icc, comm))

        return;



    idb = (IDB) handle;

    CHECK_HANDLE ( idb, type_idb, isc_bad_svc_handle);

    result = GDS_SERVICE_START( status_vector,

                &idb->idb_handle,

                spb_length, spb);



    send_response( icc, status_vector);

}
jrd\why.c::GDS_SERVICE_START (isc_service_start)

Y-valve 'router' for isc_service_start. Determines which entrypoint the call is going to use.

#ifdef _ANSI_PROTOTYPES_



STATUS API_ROUTINE GDS_SERVICE_START (

    STATUS	*user_status,

    SVC		*handle,

    USHORT	spb_length,

    SCHAR	*spb)



#else



STATUS API_ROUTINE GDS_SERVICE_QUERY (user_status, handle, spb_length, spb)

    STATUS	*user_status;

    SVC		*handle;

    USHORT	spb_length;

    SCHAR	*spb;



#endif



{



/**************************************

 *

 *	i s c _ s e r v i c e _ s t a r t

 *

 **************************************

 *

 * Functional description

 *	Starts a service thread

 *

 **************************************/



STATUS	local [20], *status;

SVC	service;



GET_STATUS;

service = *handle;

CHECK_HANDLE (service, HANDLE_service, isc_bad_svc_handle);

subsystem_enter();



if (CALL (PROC_SERVICE_START, service->implementation)(

	status, 

	&service->handle,

	spb_length,

	spb))

    return error (status, local);



RETURN_SUCCESS;

}
jrd\jrd.c::GDS_SERVICE_START

This function calls SVC_start in svc.c to actually start the service thread

#ifdef _ANSI_PROTOTYPES_



STATUS DLL_EXPORT GDS_SERVICE_START (



    STATUS	*user_status,

    SVC		*svc_handle,

    USHORT	spb_length,

    SCHAR	*spb)



#else



STATUS DLL_EXPORT GDS_SERVICE_START (user_status, svc_handle, spb_length, spb)



    STATUS	*user_status;

    SVC		*svc_handle;

    USHORT	spb_length;

    SCHAR	*spb;



#endif

{



/**************************************

 *

 *	g d s _ s e r v i c e _ s t a r t

 *

 **************************************

 *

 * Functional description

 *	Start the specified service.

 *

 **************************************/



SVC         service;

JMP_BUF     env;

struct tdbb thd_context, *tdbb = NULL;



API_ENTRY_POINT_INIT;

SET_THREAD_DATA;

service = *svc_handle;

CHECK_HANDLE (service, type_svc, isc_bad_svc_handle);

ERROR_INIT (env);

tdbb->tdbb_database = NULL;

SVC_start (service, spb_length, spb);

RETURN_SUCCESS;

}

GDS_SERVICE_ATTACH determines the version of the services manager being used by the name of the service being connected to, currently service_mgr. The only restriction on adding new service names is that the new names must be different from version 1 names that currently exist. Doing this allows the ability to have only one SVC_attach call that can handle all versions of the services manager.

Also, GDS_SERVICE_QUERY contains logic to determine if the call is from a client using the new services manager (version2) or the older services manager (version1).

GDS_SERVICE_QUERY
if (service->svc_spb_version == isc_spb_version1)

    SVC_query2 (service, send_item_length, send_items, recv_item_length, recv_items, buffer_length, buffer);

else

    SVC_query (service, send_item_length, send_items, recv_item_length, recv_items, buffer_length, buffer);
jrd\svc.c::SVC_start

This function looks for the service thread function in the serv structure. Once the thread function is found, the function then looks to see if there is any function (serv->serv_cmdline) that needs to be called to convert the spb into command-line options. Once any command-line parsing is complete, the thread specified in serv->serv_thd is called passing the the SVC structure.

#ifdef _ANSI_PROTOTYPES_



void SVC_start (

    SVC     service,

    USHORT  spb_length,

    SCHAR   *spb)

#else

void SVC_start (service, spb_length, spb)

    SVC     service;

    USHORT  spb_length;

    SCHAR   *spb;

#endif

{



/**************************************

 *

 *	S V C _ s t a r t

 *

 **************************************

 *

 * Functional description

 *      Start an InterBase service

 *

 **************************************/



TDBB    tdbb;

CONST   struct serv *serv;

USHORT  svc_id;

JMP_BUF env, *old_env;

TEXT    switches_buf [512], misc_buf [512];

TEXT    *switches, *misc;



/* The name of the service is the first element of the buffer */



switches = spb;

svc_id = *switches++;

for (serv = services; serv->serv_action; serv++)

    if (serv->serv_action == svc_id &&

        serv->serv_action < isc_action_max)

    break;



if (!serv->serv_name)

    ERR_post (isc_svcnotdef, isc_arg_string, serv->serv_name, 0);



tdbb = GET_THREAD_DATA;

old_env = (JMP_BUF*) tdbb->tdbb_setjmp;

tdbb->tdbb_setjmp = (UCHAR*) env;



if (SETJMP (env))

    {

    tdbb->tdbb_setjmp = (UCHAR*) old_env;

    if ((misc != NULL) && (misc != misc_buf))

    gds__free ((SLONG*)misc);

    if ((switches != NULL) && (switches != switches_buf))

    gds__free ((SLONG*)switches);

    if (service != NULL)

    gds__free ((SLONG*)service);

    ERR_punt();

    }



/* If there is a command-line parsing utility, call into it */

if (serv->serv_cmdline)

    serv->serv_cmdline(spb, service);



service->svc_stdout = gds__alloc ((SLONG) SVC_STDOUT_BUFFER_SIZE + 1);



/* FREE: at SVC_detach() */



if (!service->svc_stdout)		/* NOMEM: */

    ERR_post (isc_virmemexh, 0);



if (serv->serv_thd)

    {

    THREAD_EXIT;

    gds__thread_start (serv->serv_thd, service, 0, 0, (void*)&service->svc_handle);

    THREAD_ENTER;

    }

else

    ERR_post (isc_svcnotdef, isc_arg_string, serv->serv_name, 0);



tdbb->tdbb_setjmp = (UCHAR*) old_env;

}

In addition to SVC_start, there is an additional new function in SVC, SVC_query2. This function is used so that older client applications can still work with new servers. The older implementation can be found in SVC_query which is pretty similar to the new function except that any version 1 functionality has been removed from SVC_query2.

burp\burp.c::BURP_conv_switches



alice\alice.c::ALICE_conv_switches



lock\print.c::PRINT_conv_switches



utilities\dba.c::DBA_conv_switches

The following is an example from burp.c which outlines how the spb parameters will be converted into command-line parameters before being passed into the service thread.

static struct in_sw_tab_t in_sw_table [] = {

    IN_SW_B,    isc_action_max,                 "BACKUP_DATABASE",  FALSE, 60,

    IN_SW_BU,   isc_spb_res_buffers,            "BUFFERS",  	    FALSE, 257,

    IN_SW_C,    isc_action_max,                 "CREATE_DATABASE",  FALSE, 73, 

    IN_SW_CO,   isc_spb_bkp_convert,            "CONVERT",          FALSE, 254,

    IN_SW_E,    isc_action_max,                 "EXPAND",           FALSE, 97,

    IN_SW_F,    isc_action_max,                 "FILE_NAMES",       FALSE, 0,

    IN_SW_FA,   isc_spb_bkp_factor,             "FACTOR",           FALSE, 181,

    IN_SW_G,    isc_spb_bkp_no_garbage_collect, "GARBAGE_COLLECT",  FALSE, 177,

    IN_SW_I,    isc_spb_res_deactivate_indexes, "INACTIVE",         FALSE, 78, 

    IN_SW_IG,   isc_spb_bkp_ignore_checksums,   "IGNORE",           FALSE, 178,

    IN_SW_K,    isc_spb_res_no_shadow,          "KILL",             FALSE, 172,

    IN_SW_L,    isc_spb_bkp_ignore_limbo,       "LIMBO",            FALSE, 98, 

    IN_SW_M,    isc_spb_bkp_metadata_only,      "METADATA",         FALSE, 0,

    IN_SW_M,    isc_action_max,                 "META_DATA",        FALSE, 63,

    IN_SW_N,    isc_spb_res_no_validity,        "NO_VALIDITY",      FALSE, 187,

    IN_SW_NT,   isc_spb_bkp_transportable,      "NT",               FALSE, 239,

    IN_SW_O,    isc_spb_res_one_ata_time,       "ONE_AT_A_TIME",    FALSE, 99, 

    IN_SW_OL,   isc_spb_bkp_old_descriptions,   "OLD_DESCRIPTIONS", FALSE, 186,

    IN_SW_P,    isc_spb_res_page_size,          "PAGE_SIZE",        FALSE, 101,

    IN_SW_PASS, isc_action_max,                 "PASSWORD",         FALSE, 190,

    IN_SW_R,    isc_spb_res_restore,            "REPLACE_DATABASE", FALSE, 112,

    IN_SW_ROLE, isc_spb_sql_role_name,          "ROLE",             FALSE, 252,

    IN_SW_S,    isc_action_max,                 "SKIP_BAD_DATA",    FALSE, 0,

    IN_SW_T,    isc_spb_bkp_transportable,      "TRANSPORTABLE",    FALSE, 175,

    IN_SW_US,   isc_action_max,                 "USE_ALL_SPACE",    FALSE, 0,

    IN_SW_USER, isc_action_max,                 "USER",             FALSE, 191,

    IN_SW_V,    isc_spb_verbose,                "VERBOSE",          FALSE, 0,

    IN_SW_V,    isc_action_max,                 "VERIFY",           FALSE, 113,

    IN_SW_Y,    isc_action_max,                 "Y",                FALSE, 109,

    IN_SW_Z,    isc_action_max,                 "Z",                FALSE, 104,

    IN_SW_0,    0,                              NULL,               FALSE, 0

};



#ifdef _ANSI_PROTOTYPES_



int BURP_conv_switches (TEXT *spb, TEXT *cmdline)

#else

int BURP_conv_switches (spb, cmdline)

    TEXT *spb;

    TEXT *cmdline;

#endif

{



/**************************************

 *

 *  B U R P _ c o n v _ s w i t c h e s

 *

 **************************************

 *

 * Functional description

 *  Convert spb flags to GBAK switches.  cmdline

 *  must have been allocated prior to this call.

 *

 **************************************/



IN_SW_TAB	in_sw_tab;



for (in_sw_tab = in_sw_table; in_sw_tab->in_sw_name; in_sw_tab++, spb++)

    {

    if (*spb & in_sw_tab->in_spb_sw)



	/* the flag is boolean, so just add the switch 

	 * to the command line */



	sprintf (cmdline, "-%s ", in_sw_tab->in_sw_name);



    if (*spb == in_sw_tab->in_spb_sw)



	/* append the switch to and the value

	 * to the command line */



	{

	USHORT length, x;

	sprintf (cmdline, "-%s ", in_sw_tab->in_sw_name);

	x = length = *spb++;

	do *cmdline++ = *spb++; while (--x);

	*cmdline++ = ' ';

	spb += length;

	}

    }

}

New/Affected modules

Below is a comprehensive listing of files that need to be modified for the feature to be complete.

jrd component

  • dfloat_stub.c
  • jrd.c
  • why.c
  • svc_proto.h
  • ibeng32.bind
  • gds32.bind
  • ibase.h
  • jrd_proto.h
  • svc.c
  • entry.h
  • jrd.bind
  • gds.def

ipserver component

  • ipapi_proto.h
  • ipc.h
  • ipclient.c
  • ipserver.c

utilities component

  • srvrmgr.c
  • run_service.c
  • print_pool.c
  • security.e

remote component

  • protocol.h
  • protocol.c
  • server.c
  • ibconfig.c
  • interface.c

burp component

  • burp.c

lock component

  • print.c

utilities component

  • dba.e

alice component

  • alice.c

Testing Considerations

  • Ensure that older client utilities still functional against the 6.0 services manager. Try:
    • Server manager
    • Attaching to a 6.0 server
    • database backup / restore
    • database statistics
    • server configuration property sheet
  • 16-bit WISQL uses the services manager to determine if a local server is running
  • Ensure that the existing (v5.0) security API functions still work against the 6.0 server
  • Ensure that combining isc_info_svc and isc_action_svc calls in the same buffer, fail
  • Ensure that specifying incompatible spb parameters return errors