Natural Access supports two kinds of service object handles: server-side object handles and client-side object handles.
A server-side object handle provides internal (to the service) access to a service object and resides on the server. Only one server-side object handle is associated with a service object.
A client-side object handle provides external (that is, client) access to a service object. Each client attempting concurrent access to a specific service object has a separate client-side object handle.
This topic presents:
Server-side object handles enable a service implementation to refer to a unique instance of one of its internal service objects. A server-side object handle can be a memory pointer, an index into an array, a hash table value, or any other indicator the service developer chooses. Only the service implementation interprets the handle to access the service object.
The service developer must take care to prevent changes to the actual value of the service handle once it has been allocated for use. For example, assume the handle was implemented as a memory pointer to the service object. Now the service object needs to be reallocated since some internal state needs to grow. Any reference to the service object using the old handle is now invalid since the handle no longer points to the service object. In this situation, it is inappropriate to use a memory pointer as the service object handle implementation. An alternate approach could be to have an array of pointers to service objects and to use an array index as the service object handle. In this case, a memory pointer to the service object can change, yet the handle remains constant.
Because an object handle is particular to a service implementation and is interpreted only by the implementation that created it, there is no need to guarantee that a handle from one service is different than a handle from another service. Though the handle values may be the same, they refer to separate, unique service objects implemented in separate, unique service instances.
Note: Do not use memory pointers as service subject handles.
The server-side context handle is a special type of server-side service object handle. A context is equivalent to a service object for Natural Access itself. A context contains the bookkeeping information required to allow processing to occur under the Natural Access infrastructure. Some of this information includes:
The context name
The queue associated with the context
A list of services opened on the context
Just as a server-side object handle uniquely identifies an instance of a service object, a server-side context handle uniquely identifies an instance of a context within the Natural Access core. The Natural Access Server (ctdaemon) maintains a table of all server context handles. With each of these handles, it associates the list of services opened on the context, and a list of clients using the services within the context (that is, the client-side context handles)
The following illustration shows this information. One can infer that the context entry shown in the table is being shared because two clients (clt1 and clt2) are shown using the VCE service. In this server-side table within the Natural Access core, server-side context handles are mapped to the appropriate client-side context handles.
Server side handles
When a Natural Access client application creates a context using ctaCreateContext, local storage must be allocated within the client's process space to hold addressing information that uniquely identifies the server-side context that the client is trying to create. In effect, this local storage acts as a proxy for the server-side context. The proxy is bound to the server-side context upon successful completion of the ctaCreateContext call. The proxy continues to be maintained by the Natural Access core on the client-side for as long as the context exists. Access to the proxy is with a handle. Since the information in the proxy enables remote access to the server-side context, the handle to the proxy operates as a client-side context handle. This is the CTAHD that is passed back to the caller upon successful creation of the context.
Some of the information maintained in the proxy includes:
The address of the Natural Access server containing the context
The queue associated with the context
The context name (if any)
The server-side context handle
A proxy is required because a server-side context handle contains only enough information to reference a context relative to the server's process space. There is not enough inherent information within a server-side context handle to span between processes.
A proxy is also required for any service object that is to be accessed by a client. The proxy contains addressing information that uniquely identifies a service object within the distributed Natural Access system. Again, access to the proxy is through a handle; therefore the handle acts as a client-side service object handle.
These proxies are implemented within the Natural Access core as records within a mapping table. As depicted in the following illustration, this table contains records that associate client-side handles with addressing information necessary to uniquely identify server-side service objects. Creation, maintenance, and destruction of records within this table are the responsibility of the service developer as described in Mapping server handles to client handles.
Client side handle
Because services operate solely within the boundaries of a Natural Access context, there must be a context handle associated with every service object handle. Rather than passing in multiple handles to individual API functions, a service interface should examine its own service handles to infer the context for which the function call is being made. (That is, the caller should not have to explicitly pass the context handle ctahd if it is passing in a service-specific handle.) For example, when an application calls the function vcePlayMessage, it passes only a VCEHD (a VCE specific objhd) that it received when it first called vceOpenFile. From this handle, the VCE service interface logic determines its associated context handle (ctahd).
Thus, if a service implementation uses service handles, it must maintain a mapping of a service object handle to its associated context handle. In addition, as already noted, service interfaces within the distributed Natural Access environment must also map client-side service handles to server-side service handles. Maintenance of this mapping table requires the use of locks to protect underlying data structures while operating in a threaded process environment. Typically, each client context is running as a separate thread within the application.
The Natural Access core provides a set of functions that eliminates having to create redundant mapping table logic. The following table lists these functions:
|
Function |
Description |
|---|---|
|
Creates a client-side API handle and associates it with a server-side object handle. | |
|
Destroys a client-side API handle and clears its associated server-side object handle. | |
|
Associates a server-side object handle with a client-side API handle. | |
|
Associates a service object name with a client-side API handle. | |
|
Retrieves information associated with a client-side API handle: context handle, server-side service object handle, and service identifier. | |
|
Retrieves all information associated with a client-side API handle: context handle, server-side service object handle, service object name, and service identifier. | |
|
Returns the client-side handle associated with a server-side handle. | |
|
Returns the client-side handle associated with the name of a service object. |
There is a single instance of the mapping table running in an application's process space. This mapping table contains information for all services running on all contexts within the application. Each record within the table contains the following information:
|
Item |
Description |
|---|---|
|
objhd |
The client-side service object handle |
|
sobjhd |
The server-side service object handle |
|
svcid |
The unique Natural Access service identifier |
|
name |
The unique service object name |
|
ctahd |
The client-side context handle |
A record in the mapping table corresponds to a proxy. The objhd is the handle returned from dispCreateHandle. By calling this function from within a service interface, the service is automatically provided a unique client-side service object handle that the service interface can return to the caller of its API. After creating a record in the Natural Access core's handle table, the service interface must fill the sobjhd and the name fields within the record. The sobjhd is the value denoted within the dispatcher function names.
The Natural Access core does not transparently map server-side object handles to client-side object handles on behalf of the services. This is because the Natural Access core has no inherent knowledge of service objects. All knowledge of service objects, and their associated handle(s), is encapsulated within the service itself.
Mapping server handle to client handles
The following code sample illustrates how to create handles and set associated values:
DWORD dtmSpiStartTrunkMonitor ( CTAHD ctahd, unsigned board,
unsigned trunk, DTMHD *dtmhd,
DTM_START_PARMS *parms, WORD source)
{
/* (*dtmhd) returns client side handle if object created
successfully, otherwise, returns 0 */
DWORD ret = SUCCESS;
DISP_COMMAND m = {0};
DTM_START_PARMS_EX px = {0};
char objName[ DTM_OBJ_NAME_LEN] = {0};
px.trunk = trunk;
px.board = board;
m.id = DTMCMD_START_MONITOR;
m.ctahd = ctahd;
m.size1 = sizeof px;
m.dataptr1 = &px;
m.objHd = 0;
m.addr.destination = DTM_SVCID;
m.addr.source = source;
ret = dispSendCommand(&m);
/* if object created successfully, m.objHd contains the returned
server side handle */
if ( ret == SUCCESS )
{
ret = dispCreateHandle(ctahd, DTM_SVCID, m.objHd, dtmhd);
if ( ret == SUCCESS )
{
/* Create a name for this object and save in mapping
table. */
_buildObjName(board, trunk, objName);
ret = dispSetHandleValueEx((*dtmhd), m.objHd, objName);
}
}
return ret;
}