Code Examples.
Code Examples.
The recommended way to use RMD is to generate the code throught IDE (refer IDE User Guide). The code thus generate works irrespective of the architecture as the arguments are marshalled at sender side and unmarshalled on receiver side using the XDR library.
If there is a need to use RMD Library directly we have below various examples to illustrate the usage of RMD. There are various possibilities with the many flags and options available with RMD. We cover the recommended way to use RMD in the examples.
The communication parties have a client-server relationship. The server exposes certain services in conjunction with the Exectuion Object (EO) infrastructure. The client tries to execute these services either locally or remotely.
The two modes - syncrhonous and asynchronous calls can be made with or without reply from the client. The four combinations explained are:
- Synchronous Rmd without reply
- Synchronous Rmd with reply
- Asynchronous Rmd without reply
- Asynchronous Rmd with reply
Server Side:
For the client to make a RMD call the server should expose the services as illustrated below:
A typical service provided by an EO (RMD server here) will look as below:
{
ClUint32T inMsgLength = 0;
ClUint8T *pInData = NULL;
{
goto failure;
}
{
goto failure;
}
{
goto buffer_flatten;
}
buffer_flatten:
failure:
return rc;
}
ClPtrT ClBufferHandleT
The type of the handle for the buffer messages.
Definition: clBufferApi.h:82
ClRcT clBufferLengthGet(ClBufferHandleT messageHandle, ClUint32T *pMessageLength)
Returns the length of the message.
ClRcT clBufferNBytesWrite(ClBufferHandleT messageHandle, ClUint8T *pByteBuffer, ClUint32T numberOfBytesToWrite)
Writes the specified number bytes of data from a message.
ClRcT clBufferFlatten(ClBufferHandleT messageHandle, ClUint8T **ppFlattenBuffer)
Flattens message into a single buffer.
ClUint32T ClRcT
Clovis return code type.
Definition: clCommon.h:168
#define CL_OK
Every thing is OK.
Definition: clCommonErrors.h:68
ClOsalTaskDataT ClEoDataT
The type of the EO data.
Definition: clEoApi.h:199
void clHeapFree(CL_IN ClPtrT pAddress)
Frees a pre-allocated memory.
ClRcT clOsalPrintf(const ClCharT *fmt,...)
Prints to the standard output.
Many such services as above can be installed into the native table of EO (RMD server) as illustrated below. The serviceTable needs to be populated with all the services that need to be exposed and then installed via the call - clEoClientInstall() during the initialize as described further below:
NULL,
clRmdServiceExposedByServer,
};
ClRcT(* ClEoPayloadWithReplyCallbackT)(CL_IN ClEoDataT data, CL_IN ClBufferHandleT inMsgHandle, CL_OUT ClBufferHandleT outMsgHandle)
RMD with PAYLOAD with REPLY function pointer.
Definition: clEoApi.h:392
The native table (or any other client table) is installed as illustrated below. These calls usually reside in the clCompAppInitialize() callback registered in the clEoConfig structure of the EO.
static ClRcT clRmdServerInit(
void)
{
{
goto failure;
}
serverFuncList, 0,
{
goto failure;
}
failure:
return rc;
}
#define CL_SIZEOF_ARRAY(__ArrayName__)
The following macros returns the number of items in the given array.
Definition: clCommon.h:103
ClRcT clEoClientInstall(CL_IN ClEoExecutionObjT *pThis, CL_IN ClUint32T clientId, CL_IN ClEoPayloadWithReplyCallbackT *pFuncs, CL_IN ClEoDataT data, CL_IN ClUint32T nFuncs)
Installs the function table for a client.
ClRcT clEoMyEoObjectGet(CL_OUT ClEoExecutionObjT **pEOObj)
Returns EO Object from task specific area.
@ CL_EO_NATIVE_COMPONENT_TABLE_ID
This is the service provided by Host EO.
Definition: clEoApi.h:211
The Execution Object abstracts the properties of a running OS thread or process.
Definition: clEoApi.h:476
The uninstall of the native table is done as illustrated below. Such calls reside in the clCompAppTerminate() registered with the Component Manager (CPM).
static ClRcT clRmdServerExit(
void)
{
{
return rc;
}
}
#define CL_EO_USER_CLIENT_ID_START
You can specify a new clientId greater than CL_EO_USER_CLIENT_ID_START.
Definition: clEoApi.h:315
ClRcT clEoClientUninstall(CL_IN ClEoExecutionObjT *pThis, CL_IN ClUint32T clientId)
Uninstalls the function table for client.
Client Side:
One of the simpler ways to invoke an RMD is to make a synchronous call with the default flags but we strongly recommend using CL_RMD_CALL_NON_PERSISTENT flag to avoid any unnecessary duplication of buffers (which is the default) unless the inMsgHandle needs to be re-used. Care should be taken in releasing the resources allocated like the outMsgHandle which is not applicable in this case.
static ClRcT clRmdSyncWithoutReply(
void)
{
ClUint32T funcId =
ClUint8T inArguments[] =
"The bytestream of arguments to be passed to dest "
"(marshalled if necessary to make endian neutral)";
{
goto failure;
}
(ClUint8T *) &inArguments,
sizeof(inArguments));
{
goto failure;
}
outMsgHandle, flags, &rmdOptions,
NULL);
{
goto failure;
}
clOsalPrintf(
"*******************************************************\n");
clOsalPrintf(
"***************** Sync RMD Succeeded ******************\n");
clOsalPrintf(
"*******************************************************\n");
failure:
return rc;
}
ClRcT clBufferCreate(ClBufferHandleT *pMessageHandle)
Creates a new message.
#define CL_EO_GET_FULL_FN_NUM(cl, fn)
Defines a mechanism to generate unique RMD function number for the function.
Definition: clEoApi.h:189
ClIocNodeAddressT clIocLocalAddressGet(void)
Returns the local IOC node addrress.
#define CL_RMD_DEFAULT_OPTIONS
Default values for the options.
Definition: clRmdApi.h:135
#define CL_RMD_CALL_NON_PERSISTENT
0x0010 If you want RMD to use and free its input message, you are required to set this bit to 1.
Definition: clRmdApi.h:86
ClRcT clRmdWithMsg(CL_IN ClIocAddressT remoteObjAddr, CL_IN ClUint32T funcId, CL_IN ClBufferHandleT inMsgHdl, CL_OUT ClBufferHandleT outMsgHdl, CL_IN ClUint32T flags, CL_IN ClRmdOptionsT *pOptions, CL_IN ClRmdAsyncOptionsT *pAsyncOptions)
Invokes a Remote Function Call when the parameters are passed as messages.
ClIocPortT portId
The IOC communication end point identification on a node.
Definition: clIocApi.h:393
ClIocNodeAddressT nodeAddress
The IOC Node address.
Definition: clIocApi.h:388
IOC address.
Definition: clIocApi.h:401
ClIocPhysicalAddressT iocPhyAddress
Physical address.
Definition: clIocApi.h:406
This is a structure to pass optional parameters.
Definition: clRmdApi.h:196
If the application is interested in the response from the server then it has to create a buffer - outMsgHandle to hold the data the server wants to send back. This buffer needs to be deleted soon after the call when it is no longer being used.
static ClRcT clRmdSyncWithReply(
void)
{
ClUint32T funcId =
ClUint8T inArguments[] =
"The bytestream of arguments to be passed to dest "
"(marshalled if necessary to make endian neutral)";
ClUint8T *pReturnData = NULL;
{
goto failure;
}
{
goto failure;
}
(ClUint8T *) &inArguments,
sizeof(inArguments));
{
goto failure;
}
outMsgHandle, flags, &rmdOptions,
NULL);
{
goto failure;
}
{
clOsalPrintf(
"clBufferMessageNBytesRead() Failed, rc[%#X]\n", rc);
goto rmd_success;
}
clOsalPrintf(
"*******************************************************\n");
clOsalPrintf(
"***************** Sync RMD Succeeded ******************\n");
clOsalPrintf(
"*******************************************************\n");
clOsalPrintf(
"*******************************************************\n");
rmd_success:
failure:
return rc;
}
ClRcT clBufferDelete(ClBufferHandleT *pMessageHandle)
Deletes the Buffers.
#define CL_RMD_CALL_NEED_REPLY
0x0002 If you do not require to check the reply, set this bit to 0.
Definition: clRmdApi.h:71
When the application just wants to notify the server with some information without waiting for a reply then the following mode can be used.
static ClRcT clRmdAsyncWithoutReply(
void)
{
ClUint32T funcId =
ClUint8T inArguments[] =
"The bytestream of arguments to be passed to dest "
"(marshalled if necessary to make endian neutral)";
{
goto failure;
}
(ClUint8T *) &inArguments,
sizeof(inArguments));
{
goto failure;
}
outMsgHandle, flags, &rmdOptions,
NULL);
{
goto failure;
}
failure:
return rc;
}
#define CL_RMD_CALL_ASYNC
0x0001 If you want to make a synchronous call, set this bit to 0.
Definition: clRmdApi.h:66
The application may want to be notified about the success of an asynchronous rmd call with the response data from the server. In this a callback such as the one below is required when invoking the call:
void clRmdAsyncCallback(
ClRcT rc, ClPtrT pCookie,
{
ClCharT *pCallbackArg = pCookie;
ClUint8T *pReturnData = NULL;
{
goto failure;
}
{
clOsalPrintf(
"clBufferMessageNBytesRead() Failed, rc[%#X]\n", rc);
goto failure;
}
clOsalPrintf(
"*******************************************************\n");
clOsalPrintf(
"***************** Async RMD Succeeded *****************\n");
clOsalPrintf(
"*******************************************************\n");
clOsalPrintf(
"*******************************************************\n");
failure:
return;
}
To make the asyncrhonous call the application needs to specify the callback as illustrated below in the form of asyncRmdOptions. It can also supply some argument which will be supplied in the callback (cookie). In this case care has to be taken to release the outMsgHandle in the callback instead of after the RMD call unless there is an error condition. The return code in the above callback lets the application know if the RMD call was successful.
static ClRcT clRmdAsyncWithReply(
void)
{
ClUint32T funcId =
ClCharT cookie[] = "User Specified Argument for the async callback";
ClPtrT pCallbackArg = NULL;
ClUint8T inArguments[] =
"The bytestream of arguments to be passed to dest "
"(marshalled if necessary to make endian neutral)";
if (NULL == pCallbackArg)
{
goto failure;
}
memcpy(pCallbackArg, cookie, sizeof(cookie));
asyncRmdOptions.
pCookie = pCallbackArg;
{
goto failure;
}
{
goto failure;
}
(ClUint8T *) &inArguments,
sizeof(inArguments));
{
goto failure;
}
outMsgHandle, flags, &rmdOptions,
&asyncRmdOptions);
{
goto failure;
}
failure:
return rc;
}
ClPtrT clHeapAllocate(CL_IN ClUint32T size)
Allocates memory of the requested size.
This structure ClRmdAsyncOptionsT contains additional asynchronous call parameters.
Definition: clRmdApi.h:229
ClPtrT pCookie
User's cookie.
Definition: clRmdApi.h:233
ClRmdAsyncCallbackT fpCallback
User's callback.
Definition: clRmdApi.h:237
The above code only depicts the typical flags used. If you want to ensure that the invoked call is executed no more than once at the server you need to set the CL_RMD_CALL_ATMOST_ONCE flag. This flag is only necessary only for the calls that have a side effect if invoked more than once and are not idempotent in nature. The buffer is held at the server so this flag needs to be used judiciously.
The CL_RMD_CALL_NON_PERSISTENT is recommended as in most cases the application deletes the inMsgHandle as soon the call is invoked. Only if the application intends to re-use the inMsgHandle should it avoid this flag. In such a case the application is required to delete the inMsgHandle as indicated in the comments in the examples above.