Shared memory performance enhancement for all Unix platforms
A shared memory performance enhancement has been enabled for all Unix platforms, starting with the base c-treeACE V11.6 line. The following changes have now been well proven in production use since late fall of 2017.
The Unix/Linux shared memory communication protocol has been changed to improve performance by improving the internal spin operation to be more efficient, especially for relatively short database operations.
Compatibility Note: It is important to recompile the client due to this shared memory change. A server that uses this modified shared memory protocol only supports shared memory connections from clients that also use this new enhanced protocol. If an older client (pre-V11.6) attempts to connect, it will fail with error SHMC_ERR (841) and the server will log the following message to CTSTATUS.FCS:
Fri May 26 12:13:07 2017
- User# 00016 FSHAREMM: The client's shared memory version (3) is not compatible with the server's shared memory version (4)
Performance enhanced by reducing calls to system time() function
Each function call made by a c-tree client required calling the time() system function to get the starting time of the current request. This revision changes that architecture to reduce the number of these calls, thereby improving performance of each FairCom DB function called by a client application.
New add record blocking lock mode avoids network traversals
When a table lock is in effect, a record add call by a connection that is not holding the table lock fails with error DLOK_ERR (42) and sysiocod of DLKT_COD (-1024) if that connection has not enabled the ISAM blocking write lock mode. Calling LKISAM(ctENABLE_BLK) before adding the record avoids the error, but it requires an additional call to the server, plus another call after the record add call to restore the original lock mode.
The c-tree client library and FairCom Server now support a new SetOperationsState() mode that can be used to enable the blocking write lock mode during the record add call and then restore the original lock mode, all in a single call to the server.
To use this feature, call SETOPS(OPS_LOCKON_ADD_BLK, OPS_STATE_ON) before calling the record add function (ADDREC() or ADDVREC()). The SETOPS() call sets a bit on the client side and returns to the caller without making a call to the server. This bit is passed to the server on the next record add call. The server and client library turn off this mode when the record add call completes, so it applies only to the first record add call that is made after turning on this option. For this reason, it's recommended to enable this mode right before the call to add the record to which you want this mode to apply.
The record read functions that check and turn off the OPS_LOCKON_GET and OPS_LOCKON_BLK modes ignore this new mode. The record add functions that check and turn off the OPS_LOCKON_ADD_BLK mode ignore the OPS_LOCKON_GET and OPS_LOCKON_BLK modes.
Note: Both the client library and the server must support this feature to use it. If the client supports the feature but the server does not, a call to SETOPS(OPS_LOCKON_ADD_BLK, OPS_STATE_ON) fails (uerr_cod is set to NSUP_ERR, 454) and there is no effect on the next record add call. For this reason, it is good practice to check for a failed call to SETOPS(). Because the return value from SETOPS() is the present state of the operation status word, not an error code value, the proper way to check for a failed call to SETOPS() is to check the value of uerr_cod after calling SETOPS(). If uerr_cod is 0 (NO_ERROR), the call succeeded. Otherwise, the call failed with the error code whose value is stored in uerr_cod.
Example:
SETOPS(OPS_LOCKON_ADD_BLK,OPS_STATE_ON);
if (uerr_cod)) {
printf("Error: Failed to enable auto blocking lock mode on next record add: %d\n",
uerr_cod);
} else {
printf("Enabled auto blocking lock mode on next record add.\n");
ADDVREC(...);
}
Affected Components: c-tree client library, c-tree Server
Compatibility: Note that new client and server are both required in order to use the new feature. Old clients are compatible with new server. (They are not aware of the new feature.) New client returns a NSUP_ERR error if the new feature is used with an old server.
Performance enhanced by client function to get information for multiple connections in a single call
When retrieving connection information for many connected c-tree clients, FairCom DB Monitor could take a very long time to return. The bulk of this time was spent in client-by-client connection returns. To reduce this expensive network traffic, a new function was added to obtain all connection information in a single API call. This function is available for all client applications.
FairCom Server now supports a function that returns information for multiple connections in a single call. Prior to the availability of this function, a function call from the client to the Server was required for obtaining information about each connection of interest. This new approach greatly reduces network traffic.
ctGetConnectionInfo
Function prototype:
extern ctCONV NINT ctDECL ctGetConnectionInfo(NINT versn,pctCONINF pconninfo,pNINT pnconnections);
Version 1 structure:
/* Output data format for ctGetConnectionInfo() function: */
typedef struct ctconinf {
COUNT utaskid; /* internal task id */
COUNT uactflg; /* active request indicator */
LONG umemsum; /* user memory */
LONG ulogtim; /* logon time */
LONG ucurtim; /* current time */
LONG urqstim; /* time of last request */
LONG utrntim; /* time of last TRANBEG */
LONG unbrfil; /* number of open files */
LONG urqstfn; /* last request function # */
ULONG sipaddr; /* client IP address */
ULONG sip6addr[4]; /* client IPv6 address */
TEXT unodnam[32]; /* node ID information */
TEXT uname[32]; /* user id string */
TEXT ucominfo[32]; /* communication info */
TEXT urqst[32]; /* last request function name */
} ctCONINF, ctMEM *pctCONINF;
Example:
NINT rc,nconnect;
ctCONINF conninfo[32];
nconnect = 32;
if ((rc = ctGetConnectionInfo(ctCONINF_VERS_V01,conninfo,&nconnect))) {
printf("Error: %d\n", rc);
} else {
printf("Current number of connections: %d\n", nconnect);
}
Note: The caller must be a member of the ADMIN group; otherwise the function returns error LADM_ERR (589).
Socket wait interval can be used to check server failover status
The client library now supports setting a time interval in seconds after which a socket receive call checks the server failover status. If a failover has occurred, the c-tree function call returns error SERVER_FAILOVER_ERR (1159). If no failover has occurred, the socket receive call waits again for the specified time interval. To use this feature, call this function:
NINT retval;
retval = ctSetCommProtocolOption(ctCOMMOPT_SOCKET_WAIT_INTERVAL, socketWaitInterval);
where socketWaitInterval is a string that holds the desired time interval in seconds, for example, "5" to indicate 5 seconds.
This function can be called at any time to change the setting. A c-tree instance must have already been initialized before calling this function. It affects the current c-tree instance.
Note: The socket timeout value, which has been supported for a number of years, can now be set using this function instead of having to modify a field of the c-tree global variable structure directly. For example, to set the socket timeout to 10 seconds call:
retval = ctSetCommProtocolOption(ctCOMMOPT_SOCKET_TIMEOUT, "10");
Affected Components: c-tree client library