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:
- 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.
- 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.
- 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
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
|
|
ipserver component
|
|
utilities component
|
|
remote component
|
|
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