A DEEP DIVE INTO OPENCLOVIS INTELLIGENT OBJECT COMMUNICATION


Introduction

The Intelligent-Object-Communication(IOC) is a foundational component of the SAFplus Platform, providing a robust module for object communication in distributed systems. This article delves into the features, architecture, and operational details of IOC.

What is the Intelligent-Object-Communication?

The Intelligent-Object-Communication(IOC) is a compatibility layer that works either on top of UDP or on TIPC. It allows customers to port the SAFplus Platform to other architectures. IOC also abstracts and simplifies some of the legwork required to connect a node to the network.

Features of Intelligent Object Communication

  • Reliable and Unreliable mode of communication: The IOC with the help of TIPC allows the applications to create a reliable or an unreliable communication port. In the case of IOC over UDP only Unreliable communication mode is supported. All the communication ports are connectionless ports. This helps to achieve a high-speed data transfer.
  • Broadcasting of messages: IOC supports the broadcasting of messages, qualified by destination port number. This means that a broadcast message sent from a component will reach all components on all nodes in the cluster that are listening to the communications port specified in the destination-address field of the message.
  • Multicasting of messages: IOC also supports the multicasting of messages. Any component may join the group by registering itself with IOC for a specific multicast address. Thereafter any message sent to that multicast address will reach all the registered components in the cluster.
  • Transparent/Logical Address to a component: Components can communicate using logical addresses instead of physical ones, in this case, an SAFplus Platform component can communicate with another SAFplus Platform component without knowing the second one’s physical address. If the service uses a Location Transparent address, clients do not need to discover what component is currently providing the service; a client simply addresses a message to the Location Transparent Address, and that message is automatically sent to the component that is currently “active”.
  • SAFplus Platform node arrival/departure Notification: IOC can inform a notification to all the interested SAFplus Platform components about the event when a node in the cluster arrives and when one leaves.
  • The arrival/departure notification of a component: The IOC with the help of TIPC will come to know about every SAFplus Platform component’s health in a system and it conveys this to all the interested SAFplus Platform components through a query or callback interface. So that, a component can monitor the health status of other components in the system. Component arrival and departure are actually measured by when the component creates or removes its connection to TIPC, as opposed to when the process is created or deleted. This helps enforce the accuracy of process monitoring.


The architecture of Intelligent Object Communication

The figure below describes IOC architecture:

The architecture of IOC is designed to abstract and simplify the communication process, allowing components to interact efficiently. It is built on top of TIPC, leveraging its capabilities while providing a more user-friendly interface. IOC provides a full set of APIs, therefore all SAFplus Platform components use the IOC APIs rather than TIPC APIs. Also, IOC exposes only the most essential TIPC features to make porting simpler. To enable all the functionalities of IOC, IOC needs a broadcast-enabled environment, and all the nodes should be directly connected.

 

Event service usage example

The following example shows how to create a commport, sending and receiving messages on it. The below source code was developed in clCompAppMain.c.

       1.Create a communication port:

ClRcT retCode = CL_OK;
// It can be any port number within
// the range specified in clIocServices.h.
ClUint32T commPortId = 100;
ClUint32T commMode = CL_IOC_RELIABLE_MESSAGING;
retCode = clIocCommPortCreate(commPortId, commMode, &commPortHandle );
if(CL_OK != retCode) {
// Most of the time the error will occur due to Less memory OR
// If the port is already being used by some other component.
// Cannot do any send and receive with this communication port in
// this application.
clprintf (CL_LOG_SEV_ERROR, "clIocCommPortCreate error [0x%x]\n", retCode);
}

      2.Send a message to a destination:

// Create and fill the sendBuffer here.
ClBufferHandleT sendBuffer = 0;
ClUint32T msgLen=5;
retCode = clBufferCreate(&sendBuffer);
if (retCode != CL_OK)
{
clprintf(CL_LOG_SEV_ERROR, "CLIENT: Message can not be created\n");
}
// Fill the protocol here.
// This is information for the receiver
// to analyze the sendBuffer. This should
// be within the proper range specified in
// clIocProtocol.h file.
ClUint32T protocol= CL_IOC_USER_PROTO_START;

// Fill the receiverAddress here.
ClIocAddressT receiverAddress ;
receiverAddress.iocPhyAddress.nodeAddress = 1;
receiverAddress.iocPhyAddress.portId = 100;

// You can specify the priority of the message.
ClIocSendOptionT sendOption = {0};
sendOption.priority = 1;
sendOption.timeout = CL_IOC_TIMEOUT_FOREVER;

retCode = clIocSend(commPortHandle, sendBuffer, protocol,
&receiverAddress,
&sendOption);

if (retCode != CL_OK)
{
clprintf(CL_LOG_SEV_ERROR, "Error : CLIENT : commPort send : length %d. error = 0x%x.\n",msgLen, retCode);
}
clprintf(CL_LOG_SEV_INFO, "CLIENT: packet sent : length %d.\n", msgLen);

      3.Receive a message from the source:

ClIocRecvOptionT recvOption = { 0 };
ClIocRecvParamT recvParam = { 0 };
ClIocPhysicalAddressT destAddress;
ClUint8T priority;
ClUint8T protoType;
ClUint32T length;

// Create a userMsg for holding the receiver message.
ClBufferHandleT userMsg;
retCode = clBufferCreate(&userMsg);
if (retCode != CL_OK)
{
clprintf(CL_LOG_SEV_ERROR, "APP; Message can not be created ");
}

// Timeout within which
// the IOC should unblock the receiver
// thread with or without a message.
recvOption.recvTimeout =  CL_IOC_TIMEOUT_FOREVER;
retCode = clIocReceive(commPortHandle, &recvOption, userMsg, &recvParam);
if (retCode != CL_OK)
{
clOsalPrintf("error in clIocReceive retCode=0x%x\n",retCode);
}

// - recvParam.priority is the priority of the with which the sender
// sent the message.
priority = recvParam.priority;

// - recvParam.srcAddr is the address of the sender of the message.
srcAddress.nodeAddress = recvParam.srcAddr.iocPhyAddress.nodeAddress;
srcAddress.portId = recvParam.srcAddr.iocPhyAddress.portId;

// - recvParam.protoType is the protocol of the message with which the
// send and the receiver are communicating.
protoType = recvParam.protoType;

// - recvParam.length is the length of the received message.
length = recvParam.length;

clprintf(CL_LOG_SEV_INFO, "SERVER : Received data : length %d,
protocol %d, priority %d, sender 0x%x:0x%x\n",
length, protoType, priority, srcAddress.nodeAddress,
srcAddress.portId);

      4.Result:

  • On the sender side:

Sun Dec 22 18:42:36.105 2024 (Node0I0.2899193 : SAFComponent0_EO.---.---.00013 :   INFO) CLIENT: packet sent : length 5.

  • On the receiver side:

Sun Dec 22 18:42:36.105 2024 (Node0I0.2899193 : SAFComponent0_EO.---.---.00015 :   INFO) SERVER : Received data : length 5, protocol 128, priority 1, sender 0x1:0x64

If you want to see the full source code please refer to: Sender and Receiver.

Conclusion

Intelligent Object Communication (IOC) is a vital component of OpenClovis, providing a high-level, flexible, and reliable communication framework for distributed systems. By abstracting the complexities of underlying protocols like TIPC and leveraging its functions, IOC contributes to providing high availability.