Loading...
 

CORBA Interface

The Corba interface of the ClassiX® system

Introduction

ClassiX® provides an interface via which external systems can communicate with ClassiX® or several ClassiX® systems can communicate with each other. Communication is limited to sending a message to ClassiX®. Any number of parameters in the form of numbers or character strings can be attached to this message1. These parameters are placed on the stack, as is usual in InstantView®. In this way, ClassiX® can also be used to build service-oriented architectures or to integrate ClassiX® into existing service-oriented environments.

Naming Service

Every ClassiX® instance offering at least one service has to register with the CORBA naming service. In the case of TAO the Naming Service is a programme or a Windows service. It is sufficient if the Naming Service runs on a computer somewhere in the network.

By default, both Naming Service and all ClassiX® instances use IP Multicast to find the Naming Service in the network. Alternatively, the environment variable NameServiceIOR can be used to set the address of the Naming Service:

SET NameServiceIOR=iioploc://hostname:port/NameService

The environment variable must be set on each machine on which the Naming Service and/or a ClassiX® instance is running.

Alternatively, the command line parameter -ORBInitRef NameService=iioploc://hostname:port/NameService used, or according to TAO-Doku -ORBInitRef NameService=corbaloc:iiop:hostname:port/NameService . Enter valid values for hostname and port, corbaloc, iiop and NameService are written in this way. This option is valid for "normal" client and server programs. To start the NamingService itself with a specific address the following command line option can be used: -ORBEndpoint iiop://hostname:port .

Corba Interface

interface CX_REMOTEMSG_RECEIVER_CORBA
{
exception Timeout
{};

typedef sequence MarshaledStack;

void AcceptMsg_CORBA(in string message, in MarshaledStack stack);

// A variant of the the two-parameter AcceptMsg_CORBA method above. This method expects that the sender
// passes an object reference to itself.
void AcceptMsg_CORBA_BiDi(in string message, in MarshaledStack stack, in CX_REMOTEMSG_RECEIVER_CORBA sender);

// A variant of the the two-parameter AcceptMsg_CORBA method above. This call sends a message synchronously
// and returns another stack with the result send in ClassiX as NULL SendMsg(MSG ,REMOTE)
MarshaledStack SendMsg_CORBA(in string message, in MarshaledStack stack) raises (Timeout);

void Ping();
};

This service has a method that records the name of a message and a stack. The stack can also be empty. In addition, there is a method "Ping()" which acts as a kind of dummy, allowing other ClassiX® instances in the network to quickly test whether a given instance responds. The Ping method is implemented in ClassiX® simply empty.

ClassiX® generates such an object and registers it with the CORBA naming service. Each ClassiX® instance offers this service only once.

The service is registered with the Naming Service within a structure. Below the root a folder "ClassiX" is created, below it (optionally) a folder for the current ClassiX project. Below this, under the name "RemoteMsg", a folder for all servers with the service for receiving messages is offered. In it are the current ClassiX® instances. The name consists of computer name, IP address, PID of the ClassiX® instance, User-ID, logon date and the name(s) of the database(s), separated by " | ". Example (In this picture RemoteMsg and name (TH...) are swapped, a project is not specified)

An object running as a service and registered with Corba Namignservice is called a "Servant". In this example 2 ClassiX® instances have registered with the CORBA Naming Service, i.e. 2 ClassiX® instances on the same computer (TH) have called the function 'EnableRemoteMessages' of CX_REMOTE_MANAGER (or CX_CORBA_MANAGER), or have registered in another way.

The instances themselves offer various services. So far only the service "RemoteMsg" is implemented. From a technical point of view, a service is an object that offers one or more methods. This is the interface of such an object. This object makes a service publicly available, namely the service to receive a message.

The terminology of Corba regarding names: The Corba service which offers the binding of names in the network is called Naming Service, but also NamingService, Namingservice, NameService, ... possibly also with a prefix Corba or Corba-. The meaning is always the same. A Corba name (Corbaname) can consist of several components (the name components). As can be seen in the figure above, a hierarchy can be created by choosing name components. At the top is the root, which does not have an explicit name (the "root" here is only for illustration). A name component can either be a naming context, in which case further name components can be bound in the hierarchy under this name, or a name component can designate an "object" under which no further names are possible. The naming contexts must only be registered (bound) by the applications with the naming service. Behind objects, however, there is an implementation, a so-called servant. A servant implements a Corba interface. In Classix, objects that are registered under the naming context RemoteMsg implement the interface CX_REMOTEMSG_RECEIVER_CORBA (see next section). The implementation of an interface does not have to be the same everywhere, e.g. Cxsendmsg implements the same interface as Classix, but in a different way. To distinguish between these objects they can be hung in different projects (see above, the middle part of the name tree) or have unique names.

Not every Corba application has to implement a servant, but Corba can also provide an object reference (not to be confused with a reference in C++), which can be used to call functions without much fuss.

Parameters

When calling the AcceptMsg_CORBA function of the above interface, the argument "message" contains the name of the message in plain text (e.g. SELECT). The same applies to the other methods.

"stack" contains the stack that the recipient of the message should find. The last element of the sequence is at the top of the stack, i.e. the elements are pushed onto the stack from front to back.
An element is always coded as a Corba-String. The following table explains the assignment between string and type:

Type String Example
Integer i i123
String "s"An example
NULL object n n
m1 m1
m2 m2
Persistent object p p
Persistent Collection c c<0|38|0|228|10000>

At the moment only integers and strings and NULL objects can be transmitted. Vectors can be implemented quickly if required.

The stack can of course also be empty. The exact structure of the stack depends on the message that is sent. The recipient and sender must agree on this.

In ClassiX® the method GetLocation() of CX_DB_UTILITY returns the string describing a persistent object or a persistent collection. Example:

CreatePersObject(CX_PERSON) GetManager(OBJECT) Call(GetDBUtility) Call(GetLocation)
// Nun liegt ein String mit der stringifizierten Adresse des persistenten Objektes auf dem Stack

Return values

AcceptMsg_CORBA returns immediately and returns no result. The triggered InstantView® code is executed asynchronously at a later time.

However, it is still possible to return a result by sending a message containing the result to another application. This application does not necessarily have to be a ClassiX® instance, but can be any application as long as it

  • has an identical CORBA interface and
  • registers with the Naming Service like the ClassiX® service "RemoteMsg".

Example: An application named XYZ creates an object with the above interface and registers it with the Naming Service under the name "ClassiX/RemoteMsg/XYZ". Afterwards XYZ sends the message to the desired ClassiX® instance. In the InstantView® code, the message is now processed, and the result is then displayed with CX_CORBA_MANAGER::SendMsg sent to XYZ.

Alternatively (and easier to implement) the method SendMsg_CORBA can be used. This processes the message synchronously and only returns when either

  • all processing has been completed. An empty stack is then returned.
  • or a return stack is registered using NULL SendMsg(MSG, REMOTE).

Scaling

ClassiX® creates a separate thread for the processing of Corba messages. Thus, messages are accepted at any time, regardless of which InstantView® code is currently being executed.

New messages are placed at the very end of the queue, i.e. the messages are only processed when no other commands are pending for execution. This means that it is not possible to say when a message will be processed. It is only guaranteed that the messages are processed in the order in which they arrive. Please note that Corba itself does not always guarantee that messages sent first will be delivered first.

Several ClassiX-® servers can be started with the same project name. The client (e.g. cxsendmsg) can then search for "ClassiX//RemoteMsg" using the NamingService and use any instance registered there.

Example code in C++

The code below shows the sending of a message to a ClassiX® instance. In addition to this code, the sources generated by the IDL compiler from the above interface are required.

// If ACE/TAO is used as CORBA implementation, the following includes are necessary: #include <tao/corba.h> #include <CosNamingC.h> // Include the sources generated by the IDL compiler #include "cxRemoteMsgC.h" // This example sends the message "HELLO" together with a greeting string to a foreign ClassiX® instance const char *ClassiXInstance = "COMPUTERNAME 123"; // Initialize ACE/TAO CORBA ACE::init(); CORBA::ORB_var orb = CORBA::ORB_init(argc, argv, "ClassiX SendMsg"); // Prepare parameters for AcceptMsg_CORBA const char *message = "HELLO"; CX_REMOTEMSG_RECEIVER_CORBA::MarshaledStack stack; stack.length(1); stack[0] = CORBA::string_dup("s\"Hello World!\""); // Get reference to initial naming context CosNaming::NamingContext_var naming_root; CORBA::Object_var naming_obj = orb->resolve_initial_references("NameService"); naming_root = CosNaming::NamingContext::_narrow(naming_obj.in()); // Look up receiver object, i.e. the service "RemoteMsg" of the desired ClassiX® instance CosNaming::Name name; name.length(4); name[0].id = CORBA::string_dup("ClassiX"); name[1].id = CORBA::string_dup("Project"); name[2].id = CORBA::string_dup("RemoteMsg"); name[3].id = CORBA::string_dup(ClassiXInstance); CORBA::Object_var obj = naming_root->resolve(name); // Call AcceptMsg_CORBA CX_REMOTEMSG_RECEIVER_CORBA_var receiver = CX_REMOTEMSG_RECEIVER_CORBA::_narrow(obj.in()); receiver->AcceptMsg_CORBA(message, stack);

Notes on the application

A ClassiX® instance must create a remote or a Corba manager and call the associated EnableRemoteMsg method of these objects before Corba messages can be processed or messages can be sent via Corba. The SendMsg methods of these objects are used to send messages. Since Corba is only one of several conceivable interfaces for message-based communication, the programming interface of ClassiX® has been split into a part that makes the basic functions of all network interfaces usable (this is the remote manager) and another part that offers the specific functionality of Corba. Thus, in many cases, the InstantView programmer can ignore the specific network interface - the business processes are implemented in the same way.

As an example, we will show how to obtain a list of ClassiX® instances in the network with the help of the Corba manager. The core operation is to call the RemoteClients method of the Corba Manager, which returns a vector of instances registered with the Corba Naming Service. The example shows how this vector is traversed, picking out the instance that identifies the local ClassiX®. The variable 'thisComputer' was set to 'thisComputer'. The variable 'thisComputer' was assigned the computer name (GetComputerName), and 'thisPID' was assigned the process ID (GetPID). Furthermore, it is assumed that the local instance has registered with the naming service according to the above scheme, i.e. the corbaname actually contains the computer name and PID.

Var(CorbaManager)
GetManager(CORBA) -> CorbaManager
CorbaManager Call(RemoteClients) #
iterate {
Dup thisComputer StringFind if {
// found 'thisComputer'-substring
Dup thisPID StringFind if {
// found 'thisPID'-substring
break // found the right string
}
}
Drop // wrong name
}

// store the correct name
-> thisComputer

After executing this code, 'thisComputer' no longer contains the computer name, but the Corbaname of the ClassiX® instance.

_

1 In the<0|38|0|228|10000> future, the transfer of other InstantView types, such as vectors and NULL objects, may be implemented.