APPENDIX C

MICO IMPLEMENTATION DETAILS

In this appendix we look at certain implementation details of MICO. This appendix is intended for readers who want to understand the inner workings of MICO. Additionally, it should provide a good starting point for system programmers who want to understand, extend, or modify certain parts of MICO.

We begin with a trace of a method invocation through Mico, since that gives a good overview of the interplay of the various components of Mico. We then discuss how to add new invocation adapters, new object adapters, and new transport protocols to Mico. The appendix will be concluded with a section on the structure of the program code generated by the IDL compiler.

C.1 PATH OF AN OPERATION INVOCATION THROUGH AN ORB

This section follows the path an operation invocation takes from the source (client) to the destination (server), using the “Account” client introduced in Section 3.4 that calls a deposit operation on the server. As already illustrated in Figure 6.4, the method invocation first passes the SII, the ORB, and the GIOP client in the client process. The GIOP client generates a message that is sent to the server. There, it is received by the GIOP server, passes through the ORB and the object adapter, and finally results in a method invocation on the skeleton of the target object. The results of the method invocation return to the client on the reverse route. The following important classes are involved in the execution of the method invocation in the individual components:

• Static Invocation Interface (SII)

— Account_stub: The stub generated by the IDL compiler from the IDL interface Account.

— Object: The base class of all CORBA objects, which is inherited by the stub, in files include/mico/object.h and orb/object.cc.

— StaticRequest: Represents a method invocation in SII, files in-clude/mico/static.h, orb/static.cc.

• ORB

— ORB: Object Request Broker, files include/mico/orb_mico.h, orb/orb.cc.

— ORBInvokeRec: Represents a method invocation in ORB, files in-clude/mico/orb_mico.h, orb/orb.cc.

• GIOP client

— IIOPProxy: GIOP object adapter, files include/mico/iop.h, orb/iop.cc.

— IIOPProxyInvokeRec: Represents a method invocation in the GIOP invocation adapter, files include/mico/iop.h, orb/iop.cc.

— GIOPCodec: Generates and decodes GIOP messages, files include/mico/ iop.h, orb/iop.cc.

— GIOPConn: Represents connection to server, files include/mico/iop.h, orb/iop.cc.

• GIOP server

— IIOPServer: GIOP invocation adapter, files include/mico/iop.h, orb/ iop.cc.

— IIOPServerInvokeRec: Represents a method invocation in the GIOP invocation adapter, files include/mico/iop.h, orb/iop.cc.

— GIOPCodec: Generates and decodes GIOP messages, files include/mico/ iop.h, orb/iop.cc.

— GIOPConn: Represents a connection into the server, files include/mico/ iop.h, orb/iop.cc.

• Object adapter

— POA_impl: Portable Object Adapter, files include/mico/poa_impl.h, orb/poa_impl.cc.

— StaticServerRequest: Represents a method invocation in the POA, files include/mico/static.h, orb/static.cc.

— POA_Account: The skeleton generated by the IDL compiler from the IDL interface Account.

The procedures that take place during an operation invocation based on a remote method invocation are shown separately for the client and server processes below. The indentation represents the call chain. A deeper indentation indicates that the method was called by the previously described method.

C.1.1 Client Side

Account_stub::deposit()

    The initial call made by the client, invoking the deposit operation on the stub object.

StaticRequest::StaticRequest()

    StaticRequest constructor, used in the generated stub to create a Static Request object that represents the method invocation for the object and method name.

StaticRequest::add_*_arg()

    Inserts parameter values into the StaticRequest object. Parameters to these methods are references to StaticAny objects containing the values of the parameters.

StaticRequest::set_result()

    Gives StaticRequest a reference to a StaticAny object which is to hold the return value of the method invocation.

StaticRequest::invoke()

Transfers the method invocation to the ORB, waits for completion of the method invocation, and gets the results from the ORB

ORB::invoke_async()

Creates an ORBInvokeRec object that represents the method invocation in the ORB; identifies the object adapter to be used and sends it to the method invocation.

IIOPProxy::invoke()

Creates an IIOPProxyInvokeRec object that represents the method invocation in the IIOPProxy; generates a message and sends it to the server.

IIOPProxy::make_conn()

Identifies (or creates if it does not yet exist) a GIOPConn object that represents the network connection to the server.

InetAddress::make_transport()

Creates a new TCPTransport object to connect to the server.

TCPTransport::connect()

Creates a socket and connects to the server.

GIOPCodec::put_invoke_request()

Generates a network message that represents the method invocation.

GIOPCodec::put_args()

Processes the input parameters to the operation.

StaticRequest::get_in_args()

Marshals the input parameters.

StaticAny::marshal()

Marshals one input parameter.

GIOPConn::output()

Sends the network message to the server.

ORB::wait()

Waits until the method invocation is completed. During this time, incoming network messages are received and processed.

Dispatcher::run()

Waits for incoming data on network connections.

Dispatcher::handle_fevents()

Detects incoming data on network connections and calls the relevant connection handler.

GIOPConn::callback()

The GIOP connection’s handler for incoming data.

GIOPConn::do_read()

Reads data from network connection.

GIOPConn::input_ready()

Is called when a GIOP message is complete.

GIOPConn::input_ready_callback()

Is called to notify the IIOP proxy of an incoming message.

IIOPProxy::input_callback()

The callback to notify the IIOP proxy of an incoming message.

IIOPProxy::handle_input()

Checks the message for its type (i.e., whether it is a reply) and invokes the appropriate method for evaluation of the message.

IIOPProxy::handle_invoke_reply()

Decodes the network message and forwards the results.

GIOPCodec::get_invoke_reply1()

Decodes the GIOP header.

GIOPCodec::get_invoke_reply2()

Processes the invocation’s result and other output parameters.

StaticRequest::set_out_args()

Marshals the result and output parameters.

StaticAny::unmarshal()

Marshals one output parameter.

IIOPProxy::exec_invoke_reply()

Sends results to the ORB.

ORB::answer_invoke()

Stores the results of a method invocation in the associated ORBInvokeRec and designates the method invocation as completed so that ORB::wait()

returns to its caller.

ORB::get_invoke_reply()

Fetches results of method invocation from ORB.

C.1.2 Server Side

GIOPConn::do_read()

Reads data from network connection.

GIOPConn::input_ready()

Is called when a GIOP message is complete.

GIOPConn::input_ready_callback()

Is called to notify the IIOP server of an incoming message.

IIOPServer::input_callback()

Callback routine of IIOPServer that is invoked when a new message arrives.

IIOPServer::handle_input()

Checks the type of message and invokes the corresponding method to evaluate the message.

IIOPServer::handle_invoke_request()

Decodes the GIOP message header and forwards parameters.

GIOPCodec::get_invoke_request()

Decodes the message, creates a GIOPRequest object (equivalent to Request object on client side), and creates an IIOPServer-InvokeRec object that represents method invocation on server side.

IIOPServer::exec_invoke_request()

Passes the invocation request to the ORB.

ORB::invoke_async()

Creates an ORBInvokeRec object that represents the method invocation in the ORB; establishes the object adapter to be used and passes it the method invocation.

POA_impl::invoke()

Checks the object reference of the target object and looks for the POA that manages the target object, and transfers the method invocation to this POA instance.

POA_impl::local_invoke()

Executes, delays, or ignores the method invocation depending on the state of the POA manager belonging to the target POA.

POA_impl::perform_invoke()

Looks up the servant belonging to the target object, depending on the POA policies. Usually, the servant is found in the active object map. Generates a Static ServerRequest object and passes it to the servant’s method dispatcher.

POA_Account::invoke()

Calls the dispatch() methods of the skeleton and its base classes, eventually finding the skeleton that implements the invocation that is being called.

POA_Account::dispatch()

Determines the method that is to be invoked, extracts the parameters from the StaticServerRequest, calls the method implementation, and stores the results in the StaticServerRequest.

StaticServerRequest::add_*_arg()

Gives StaticServerRequest references to Static Any objects that are to hold the parameter values.

StaticServerRequest::set_result()

Gives StaticServerRequest references to the StaticAny object that is to hold the result value.

StaticServerRequest::read_args()

Decodes the input parameters of the method invocation and fills the StaticAnys previously registered via add_*_arg()

with the decoded values.

GIOPRequest::get_in_args()

Unmarshals the input parameters.

StaticAny::demarshal()

Unmarshals one input parameter.

POA_Account::deposit()

Invocation of the target method implemented by the user.

StaticServerRequest::write_results()

Encodes the result value and other output parameters by converting the values contained in the StaticAny objects that have been previously registered via add_*_arg() and set_result()

into a byte stream.

GIOPRequest::set_out_args()

Marshals the result and other output parameters.

StaticServerRequest::∼StaticServerRequest()

The StaticServerRequest destructor informs POA that method invocation is completed.

POA_impl::answer_invoke()

The POA informs ORB that the method invocation has completed.

ORB::answer_invoke()

Stores the results of a method invocation in associated ORBInvokeRec.

IIOPServer::notify()

Invokes the correct method for handling a reply message, depending on which kind of request has completed.

IIOPServer::handle_invoke_reply()

Retrieves the status of a method invocation from ORB, generates reply message, and sends it to the client.

ORB::get_invoke_reply()

Gets the invocation’s result from the ORB.

GIOPCodec::put_invoke_reply()

Generates a GIOP reply message.

GIOPConn::output()

Sends the message to the client.

C.2 INTEGRATION OF A NEW INVOCATION ADAPTER

In this section of the appendix we show how to integrate a new invocation adapter into a microkernel ORB. In the following we will describe the methods the ORB supplies for this purpose. The methods are declared in the file include/mico/orb_mico.h and implemented in orb/orb.cc in the MICO source tree.

Operations provided by the ORB

image

This initiates an operation invocation. The parameters given are the target object target, the parameter in the form of request, as well as the principal principal, which contains specific information that can be used to identify the method invoked by the caller. The optional parameters that can be used are the Boolean value reply_expected, which indicates whether an operation invocation is one-way or two-way; the callback object callback, the method ORB Callback::callback() of which the ORB automatically invokes when a method invocation is completed; and the ID id that is to be supplied. The result that is returned is an ID that explicitly identifies the operation invocation and can be used later to wait for the completion of the operation invocation.

image

This waits until either the operation invocation specified by the id is completed or the waiting time (in milliseconds) specified by the timeout has lapsed. The timeout value −1 stands for infinite. In the first case, the result TRUE is returned, and in the second, the result FALSE.

image

This gets the results from the ORB of the completed operation invocation specified by id. The result that is supplied is the value of the type InvokeStatus, which can assume the values InvokeOk (operation completed successfully), InvokeForward (object reference of target object has changed), InvokeSysEx (a system exception has occurred), InvokeUsrEx (a user exception has occurred), or InvokeAddrDisp (a different object addressing is requested). In the case of the InvokeForward value, forwarded_target is set to the new object reference, and the operation invocation has to be repeated. In the case of InvokeAddrDisp, the requested addressing type is indicated by ad, and the operation invocation has to be repeated. request is set to the ORBRequest instance specified with invoke_async.

void cancel (CORBA::ORBMsgId id)

This terminates an operation invocation specified by id.

image

This is a convenient combination of invoke_async(), wait(), and get_invoke_ reply(), which blocks until an operation invocation is completed.

The ORBRequest object, which contains the parameters and results of an operation invocation, plays a central role in the development of an operation invocation. This is an abstract class from which a concrete implementation must be derived. This involves the implementation of the methods explained below. The declaration of the class ORBRequest can be found in the file mico/include/mico/orb_fwd.h in the MICO source tree.

ORBRequest represents operation invocation

const char *op_name()

Supplies the name of the invoked operation.

image

Pads params with the list of parameters and ctx with the optional Context_ object.

image

Pads params with the list of parameters and ctx with the optional Context_ object.

CORBA::Boolean get_in_args (CORBA::DataEncoder *encoder)

Codes the input parameters and the optional Context_ object (in this sequence) using encoder.

image

Pads res with the result of the method invocation and params with the output parameters or ex with the exception in the event that one occurred.

image

Pads res with the result of the method invocation and params with the output parameters or ex with the exception in the event that one occurred.

image

Codes the result and the output parameters of an operation invocation (in this sequence) or an exception that occurred using encoder and sets is_except to TRUE in the event an exception occurred; otherwise it sets it to FALSE.

image

Sets the result and the output parameters from this to the supplied value res or params.

image

Sets the result and the output parameters from this to the supplied value res or params.

void set_out_args (CORBA::Exception *ex)

Stores the exception ex as a result of the operation invocation in this.

image

Sets the result and the output parameters of this to the coded values in decoder. is_except indicates whether an exception occurred.

CORBA::Boolean copy_out_args (CORBA::ORBRequest *req)

Copies the output parameters from req to this.

CORBA::Boolean copy_in_args (CORBA::ORBRequest *req)

Copies the input parameters from req to this.

const char *type ()

Supplies a string that identifies the type of request object.

C.3 INTEGRATION OF A NEW OBJECT ADAPTER

In addition to having an interface for new invocation adapters, the ORB also has one for the integration of new object adapters. This interface is described below. In addition, each object adapter must provide an object of the type CORBA::ObjectAdapter over which the ORB has access to the functionality of the object adapter.

Object adapters inherit from basic class ObjectAdapter

ObjectAdapter is an abstract basic class from which an object-adapter-specific concrete implementation must be derived. It must provide implementations for the methods explained below. The declaration for the class Object Adapter can be found in the file include/mico/orb_mico.h in the MICO source tree.

const char *get_oaid () const

Supplies a string that identifies the type of object adapter.

CORBA::Boolean has_object (CORBA::Object_ptr obj)

Then exactly supplies TRUE if the object adapter is responsible for executing an operation invocation on the object obj.

CORBA::Boolean is_local () const

Then exactly supplies TRUE if the object adapter is local, that is, if the execution of the operation invocation does not require any interprocess communication.

image

Initiates an operation invocation with ID id on the object obj, with parameters req and principal. response_expected indicates whether it is a one-way or a two-way operation invocation. The result returned is TRUE if the method invocation could be initiated successfully. Note that this by no means signifies that the operation invocation was completed successfully. The return message indicating whether an operation invocation was completed and what the results were uses the method ORB::answer_invoke().

image

The ORB invokes this method to determine whether the object adapter is managing an object with repository ID repoid or object ID tag under the address addr. The address is important if the object adapter is not local, such as a GIOP proxy. The invocation returns TRUE if the process was initiated successfully. As with invoke, the result is conveyed to the ORB through an invocation of ORB::answer_bind().

CORBA::Boolean locate (CORBA::ORBMsgId id, CORBA::Object_ptr obj)

The ORB invokes this method to determine whether the object reference obj has changed in the meantime due to a migration process. Then exactly supplies TRUE as the result if the process could be initiated successfully. As with invoke, the result is conveyed to the ORB through the invocation of ORB::answer_locate().

CORBA::Object_ptr skeleton (CORBA::Object_ptr obj)

Invoked by the ORB to query the object adapter for the object reference obj about the possible existence of a collocation stub. Delivers the collocation stub as a result or a NIL if one is not available.

void cancel (CORBA::ORBMsgId id)

Terminates the operation invocation with the ID id.

void shutdown (CORBA::Boolean wait_for_completion)

Initiates the termination. As soon as an object adapter has completed its termination, it invokes ORB::answer_shutdown() to notify the ORB. Ifwait_for_completion TRUE occurs, this invocation cannot take place until all operation invocations currently being executed have been completed.

image

Invoked by a skeleton interface (SSI or DSI) when an operation invocation is completed in order to inform the object adapter of the results of the invocation. status is the status value familiar from Section C.2.

Operations provided by the ORB

The ORB supplies the following methods that are associated with the integration of new object adapters. The methods are declared in the file include/mico/orb_mico.h and implemented in the file orb/orb.cc in the MICO source tree.

void register_oa (CORBA::ObjectAdapter *oa)

Registers the object adapter oa at the ORB.

void unregister_oa (CORBA::ObjectAdapter *oa)

Deregisters the object adapter oa at the ORB.

image

The object adapter invokes this method to notify the ORB of the completion of the method invocation under ID id with status status and result req. If status has the value InvokeForward, then obj contains the new object reference. If status has the value InvokeAddrDisp, then ad contains requested addressing type.

image

The object adapter invokes this method to notify the ORB that the bind process with ID id has been completed. status is an instance of the type LocateStatus that can assume the value LocateUnknown (object being searched does not exist), Locate-Here (the object being searched has been found), or LocateForward (object reference of object being searched has changed). The values LocateUnknown and LocateHere are the only values that can occur in connection with answer_bind. In the above case, obj contains the object reference of the found object.

image

This is invoked by the object adapter to notify the ORB of the completion of the locate process with ID id. If status has the value LocateHere or LocateForward, obj contains the current object reference of the queried object; otherwise it contains NIL. If status has the value LocateAddrDisp, then ad contains requested addressing type.

void answer_shutdown (CORBA::ObjectAdapter *oa)

The object adapter oa invokes this method to notify the ORB of the completion of the termination.

C.4 INTEGRATION OF A NEW TRANSPORT MECHANISM

New GIOP mapping

In MICO a new transport mechanism can generally be incorporated simply through the implementation of an object adapter and the corresponding invocation adapter on the model of the GIOP client and the GIOP server (see Section 6.3.2). However, this is usually a complicated process. An easier way consists of using the framework described in Chapter 6 to map the GIOP to the transport mechanism being used. This involves implementing the classes listed below for transport mechanism X. These classes are described in the following sections. The paths given below are subdirectories in the MICO source tree.

XAddress:

    Address, files include/mico/address.h, include/mico/address_impl.h, orb/address.cc.

XAddressParser:

    Decodes addresses from a given string, and the same for files.

XProfile:

    IOR profiles, files include/mico/ior.h, include/mico/ior_impl.h, orb/ior.cc.

XProfileDecoder:

    Decodes IOR profiles from a given byte stream, and the same for files.

XTransport:

    Client-side transport class, files include/mico/transport.h, include/mico/ transport_impl.h, orb/transport.cc, orb/transport/*.cc.

XTransportServer:

    Server-side transport class, and the same for files.

Also see Section 6.3.2 for the inheritance relationships between these classes and the GIOP framework.

C.4.1 XAddress

First an address type string (similar to “inet”) that has not yet been used, such as “x”, has to be specified. This string serves as the prefix for addresses in string form. The prefix is followed by arbitrary address information, such as a globally explicit number in “x:42”.

Specifying the address prefix

A class XAddress implementing the following methods is then derived from CORBA::Address.

string stringify () const

Supplies the address in string form, such as “x:42”.

const char *proto () const

Supplies the type of this address, such as “x”.

CORBA::Transport *make_transport () const

Creates a Transport object that matches the type of address.

CORBA::TransportServer *make_transport_server () const

Creates a TransportServer object that matches the type of address.

image

Creates an IORProfile object that matches the type of address. The parameters provided are the object ID key, its length keylength, any components components that might exist, and the GIOP version version (default value 1.0) to be used. The components consist of a standardized representation of arbitrary information that could be stored in a profile, which can include the name and the version of the ORB that generated the profile.

CORBA::Boolean is_local () const

Then exactly supplies TRUE if the address refers to the same address space in which it is used.

CORBA::Address *clone () const

Creates an exact copy of this.

CORBA::Long compare (const CORBA::Address &addr) const

Compares this with addr and supplies −1 if this < addr, 0 if this = addr, or 1 if this > addr.

CORBA::Boolean operator== (const CORBA::Address &addr) const

Exactly supplies TRUE if this = addr.

CORBA::Boolean operator< (const CORBA::Address &addr) const

Exactly supplies TRUE if this < addr.

C.4.2 XAddressParser

The class XAddressParser must be derived from CORBA::AddressParser and implement the following methods:

image

Converts an address string (for example, x:42) into an Address object. proto contains the address type (for example, x), and rest contains the rest (for example, 42) of the string.

CORBA::Boolean has_proto (const char *proto) const

Supplies exactly TRUE if the address parser can parse addresses from the type proto (for example, x).

C.4.3 XProfile

In this case too a profile ID that has not yet been used has to be defined (similar to TAG_INTERNET_IOP), such as

Specifying the profile ID

const CORBA::IORProfile::ProfileId TAG_X_IOP = 31415;

Then a class XProfile is derived from CORBA::IORProfile and implements the following methods:

void encode (CORBA::DataEncoder &encoder) const

Codes this using encoder in a byte stream.

CORBA::Address *addr () const

Supplies the address of this profile.

ProfileId id () const

Supplies the profile ID of this profile.

ProfileId encode_id () const

Normally supplies the same result of id(). encode_id() only supplies the profile ID of a basic transport mechanism in special cases (such as the SSL transport mechanism that represents a wrapper for an existing transport mechanism like IIOP).

void objectkey (Octet *key, Long keylength)

Sets the object ID to the supplied value. key contains the new ID and keylength its length.

image

Requests the object ID. The result is a reference to the object ID; keylength is set to the length of the object ID.

CORBA::Boolean reachable ()

Return TRUE if the address contained in the profile can be reached. For example, the address local can only be reached from a process if it was also created in this process. On the other hand, addresses of the type inet can always be reached.

void print (ostream &outputstream) const

Supplies the address in a string form as outputstream.

CORBA::MultiComponent *components ()

Supplies the components contained in the profile.

CORBA::IORProfile *clone () const

Creates an exact copy of this.

image

Compares this with prof and supplies −1 if this < prof, 0 if this = prof, and 1 if this > prof.

image

Supplies exactly TRUE if this = prof.

image

Supplies exactly TRUE if this < prof.

C.4.4 XProfileDecoder

The class XprofileDecoder must be derived from CORBA::ProfileDecoder and implement the following methods:

image

Uses decoder to convert a byte stream into an IORProfile object. The parameters supplied are the profile ID id and the length of the byte stream length.

CORBA::Boolean has_id (ProfileId id) const

Supplies exactly TRUE if the profile decoder can decode profiles of the type id.

C.4.5 XTransport

The class XTransport must be derived from CORBA::Transport and implement the following methods:

image

This method registers a read callback callback that is invoked as soon as data can be received and read on a connection or the Transport object is destroyed. disp is the scheduler used (described in detail in Section C.4.7). Callback objects inherit from the following basic class and implement the method callback(). The method callback() is invoked with this as the first parameter of the Transport object and TransportCallback::Read (if data can be read) or TransportCallback::Remove (if the Transport object is being destroyed) as the second parameter.

image

This method registers a write callback that is invoked in a similar way as reselect() if data can be written or the Transport object is being destroyed.

CORBA::Boolean bind (const CORBA::Address *addr)

Sets the local address of the transport end point to addr.

CORBA::Boolean connect (const CORBA::Address *addr)

Establishes a connection to a remote address.

void close ()

Terminates the connection.

void block (CORBA::Boolean doblock = TRUE)

If doblock is TRUE, then all subsequent read and write operations block until they have been executed completely. Otherwise read and write operations are only executed to the extent that is possible without blocking and an appropriate result code is returned.

CORBA::Boolean isblocking ()

Exactly supplies TRUE in the event that read and write operations are blocking.

CORBA::Boolean isreadable ()

Exactly supplies True if data is available for reading, thus read would not be blocking.

CORBA::Long read (void *buffer, CORBA::Long bufferlen)

At a maximum reads bufferlen bytes from the area referred to by buffer. The result supplied is the number of read bytes or −1 in the case of failure (including EOF).

image

At a maximum writes bufferlen bytes from the area referred to by buffer. The result supplied is the number of written bytes or −1 in the case of failure.

const CORBA::Address *addr ()

Supplies local address.

const CORBA::Address *peer ()

Supplies the remote address of a connection or NIL if no connection exists.

CORBA::Boolean eof () const

Exactly supplies TRUE if the connection was terminated and all data was read.

CORBA::Boolean bad () const

Exactly supplies TRUE if an error occurred.

string errormsg () const

Supplies a textual description of the last error that occurred.

C.4.6 XTransportServer

The class XTransportServer must be derived from CORBA::TransportServer and implement the following methods:

image

Callback objects

This method registers an accept callback that, similar to Transport::rselect(), is invoked when a connection request arrives or the TransportServer object is destroyed. Callback objects inherit from the following basic class and implement the method callback(). The method callback() is invoked with this as the first parameter of the TransportServer object and TransportServerCallback::Accept (if a connection request exists) or TransportServerCallback::Remove (if the TransportServer object is being destroyed) as the second parameter.

image

CORBA::Boolean bind (const CORBA::Address *addr)

Binds the local address of the transport end point to addr. void close ()

Terminates the transport end point. No further connections can be accepted.

void block (CORBA::Boolean doblock = TRUE)

If doblock is TRUE, then all subsequent accept operations block until a connection setup request exists. Otherwise invocations of accept() deliver a NIL if there is no connection setup request.

CORBA::Boolean isblocking ()

Exactly delivers TRUE in the event accept operations are blocking.

CORBA::Transport *accept ()

As soon as a connection setup request exists (i.e., if a client has invoked connect() with the address of this TransportServer object), accept() delivers a Transport object that represents the connection to this client.

const CORBA::Address *addr ()

Supplies the local address.

CORBA::Boolean bad () const

Exactly supplies TRUE if a failure occurs.

string errormsg () const

Supplies a textual description of the last failure that occurred.

C.4.7 Dispatcher

The Transport and TransportServer classes work closely together with the scheduler described in Section 5.3.4. Thus the scheduler is usually used to implement the methods Transport::rselect(), Transport::wselect(), and TransportServer::aselect().

Scheduler events Callback objects

All scheduler implementations inherit from the abstract basic class CORBA:: Dispatcher. This class provides various methods for the registration of callbacks that can be invoked when certain events occur. The possible events are described by the following enumeration:

image

The individual values of this list signify the following:

Timer:

    A timeout has run out.

Read:

    Data can be read from a channel.

Write:

    Data can be written on a channel.

Except:

    An exception (for instance, an error) has occurred on a channel.

All:

    Concerns all possible events.

Remove:

    A callback was removed.

Moved:

    A callback was removed from this dispatcher and entered into another one.

The declaration for the class dispatcher can be found in the file include/mico/transport.h and various implementations can be found in the files orb/dispatch.cc, auxdir/x11.cc, auxdir/qtmico.cc, auxdir/tclmico.cc, auxdir/gtkmico.cc, and auxdir/fltkmico.cc in the MICO source tree.

Schedulers inherit from Dispatcher

Callback objects inherit from the abstract basic class CORBA::Dispatcher-Callback and implement the method callback(). The method callback () is invoked by the dispatcher when an event occurs with this as the first parameter and the event that occurred as the second parameter:

image

image

All implementations of the abstract basic class CORBA::Dispatcher provide the following methods:

image

Registers a read callback cb that is invoked when data can be read on the file handle fd.

image

Registers a write callback cb that is invoked when data can be written on the file handle fd.

image

Registers an exception callback cb that is invoked when an exception occurs on the file handle fd.

image

Registers a timer callback that is invoked when the time timeout (in milliseconds) has elapsed.

void remove (CORBA::DispatcherCallback *cb, Event event)

Removes a callback cb previously registered for an event.

void run (CORBA::Boolean infinite = TRUE)

Waits for the occurrence of the next event and processes it. If infinite = FALSE, it means that exactly one event is being processed. Otherwise an infinite loop is entered.

void move (CORBA::Dispatcher *disp)

Removes all registered callbacks from this and registers them at dispatcher disp.

CORBA::Boolean idle () const

Supplies exactly TRUE if there are no pending events for any registered callback at the time of invocation.

C.4.8 Initialization

Registration of AddressParserand ProfileDecoder

An instance each of XaddressParser and XprofileDecoder must first be created and registered before a new transport mechanism can be used. The easiest way this can be done is through the implementation of registration or deregistration in the constructor or destructor and the creation of a global instance for both classes. Thus:

image

Registration with GIOP framework

In addition, the GIOP framework in the client and in the server must be notified of the existence of the new transport mechanism:

CORBA::ORB_var orb = …;

image

The new transport mechanism can be used if the server is started with the command line option

-ORBIIOPAddr x:42

If an object reference is being exported by the server, it will contain an Xprofile that triggers the client into using the appropriate transport mechanism when invoking methods on this object.

C.5 THE STRUCTURE OF GENERATED PROGRAM CODE

Proxies are based on MICO-specific static interface adapters

This section describes the structure of the program code generated by MICO’S IDL compiler. The IDL language binding for C++ only stipulates the C++ interface for proxy objects that can be accessed by applications (the basis for portability). However, the CORBA standard does not specify how these interfaces are to be implemented. For example, the MICO-specific Static Invocation Interface (SII) is used for marshaling within Mico. Another possibility would be the Dynamic Invocation Interface (DII) that was actually used with earlier versions of MICO.

The IDL specification used earlier in the account application and reproduced in Section D.2 in Appendix D serves as the basis for our discussion. MICO’S IDL compiler standardly produces two files during the translation process. We assume that the –typecode command line option of the IDL compiler was used during the translation. In our example the IDL specification is contained in the file called account.idl:

idl –typecode account.idl

Two files exist after the translation by the IDL compiler: account.h contains all C++ declarations and account.cc all the corresponding C++ definitions. Some extracts from the contents of these files are discussed in the following.

The IDL compiler produces a class for each IDL type that is responsible for the marshalling of an instance of that type. The name of the class consists of the prefix _Marshaller_ followed by the name of the IDL type. The following code fragment shows the marshaller for the IDL type Account:

Marshaller of an IDL type

image

The marshaller is based on the SII and is derived from the class Static TypeInfo. It defines several methods that can be used for marshalling an Account instance. An instance of the marshaller class that can be used within the stubs and skeleton is produced in line 25. One feature is the representation of a type code that has to be generated for each IDL type (line 21). For the representation of the type information for Account, the CDR representation is produced as a

Representation of a type code

character string of hexadecimal values. Since the type code can also appear as the parameter of an operation, the ORB has to be able to interpret this byte sequence anyway. Table C.1 shows the coding of this byte sequence by bytes.

TABLE C.1

Representation of a type code for AccountType as a CDR byte sequence

Pos . Hex Description
0 01 Little Endian
1 00 00 00 Padding
4 0e 00 00 00 TCKind = tk_objref (14)
8 24 00 00 00 Overall length = 36 octets
12 01 Little Endian
13 00 00 00 Padding
16 10 00 00 00 string length = 16 octets
20 49 44 4c 3a 41 63 63 6f 75 6e 74 3a 31 2e 30 00 “IDL:Account:1.0”
36 08 00 00 00 string length = 8 octets
40 41 63 63 6f 75 6e 74 00 “Account”

For each interface of the IDL specification, the IDL compiler generates a number of classes for implementing the stubs and skeletons. Following are the declarations for the C++ classes generated for the interface Account:

image

image

The CORBA standard specifies various helper types for each interface with the suffixes _ptr, _var, and _out (lines 3–7). MICO defines several C++ template types for their implementation. The class Account (line 9) is derived from CORBA::Object and contains the methods required by the CORBA standard (for example, _narrow for the type-safe downcast in line 13). All operations that were defined in the interface Account are defined as pure virtual methods in the C++ class Account (lines 14–16). The class from which the stub objects are instantiated has the (MICO-specific) name Account_stub and is derived from the class Account (line 20). All pure virtual methods are overloaded here and trigger a remote operation invocation when they are implemented.

C++ templates for tools

The skeleton class based on the POA is called POA_Account (line 30) and is derived through an intermediate class of PortableServer::ServantBase of the basis class of all servants (see Figure C.1). POA_Account is not derived from CORBA::Object because a POA makes a distinction between servants and objects. The C++ class POA_Account also defines all operations occurring in the interface Account as pure virtual methods.

image

FIGURE C.I Inheritance relationship between the classes of the generated code and the ORB library.

In addition, the class POA_Account uses the method invoke to define the entry point of incoming operation invocations (line 35). Each skeleton defines a dispatcher that forwards the operations belonging to this interface to the implementation (line 34). The dispatch method successively invokes all dispatch methods belonging to an interface’s direct parents in the interface hierarchy. Figure C.1 shows the inheritance relationships for the C++ class mentioned.

Skeleton has an operation dispatcher

Table C.2 provides an overview of all C++ classes generated by the IDL compiler through use of the POA. Note that the POA tie template is only generated if the IDL compiler is invoked with the command line option –poa-ties.

TABLE C.2

Generated C++ classes for the IDL interface Account

C++ class Description
Account Basic class with tools
Account_stub Stub for remote objects
Account_stub_clp Stub for collocated objects
POA_Account POA-based skeleton
POA_Account_tie<T> Template for tie objects

We will now take a detailed look at the stub object that triggers a remote operation invocation. First the corresponding code fragment:

image

An instance of the class StaticAny encapsulates the actual parameters (line 5) for the input parameter amount. For its representation as a CDR byte sequence, a StaticAny requires the right marshaller that has to be passed as an argument to the constructor (e.g., CORBA::_stc_long for IDL type long). First a StaticRequest, which represents the remote operation invocation, is instantiated (line 6). After the actual parameters of the operation have been added (line 7), the operation is sent to the remote server (line 9). If the invocation of this method is returned, it means that the remote operation was carried out and the results were returned automatically through the StaticAny instances.

Lastly, we will show the dispatch process in the skeleton on the server side:

StaticRequest instance represents operation invocation

image

image

The method POA_Account::invoke is invoked during an incoming operation invocation (line 24). The operation forwards the invocation directly to the skeleton dispatch method (line 4), which is responsible for invoking all dispatchers of a interface’s direct parents. The StaticServerRequest instance contains all information, such as operation name and actual parameters, related to the operation invocation. Based on the operation name, the dispatcher determines whether this operation invocation belongs to the interface. If the dispatcher is responsible, it takes all actual parameters from the invocation (lines 7–13) and then invokes the pure virtual method of the operation (line 15) that is implemented in a class derived from POA_Account.

dispatch calls up all dispatchers of an interface’s direct parents

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
13.58.228.178