|
|
|
|
The Object Management Group (OMG) defines the Interface
Definition Language (IDL) as part of the CORBA specification.
The OMG has always used IDL to not only define unconstrained (
potentially
remote) interfaces, but also those local to a particular
process (or part of CORBA's API). Originally, this was
done in an informal manner with what was described as
Pseudo IDL (PIDL). For example, in CORBA 2.4
the PortableServer::ServantManager object has its interface
defined with the following IDL:
interface ServantManager{ };
The specification then explicitly states that this interface is locality constrained which alerts the reader that this is not true IDL but PIDL.
The local keyword was added in
the CORBA Component Model (CCM) Specification (orbos/99-07-1) and
later included in the core CORBA 2.4 specification.
This keyword can appear in IDL before the interface
keyword and indicates that the interface can only be implemented
by objects in the current process.
The CORBA 2.5 and 2.6 specifications converted many of the
existing locality constrained interfaces to local interfaces.
This includes interceptors, Codec, RT CORBA interfaces,
POA, POAManager, policies, servant managers, and Current.
For example, the servant manager and servant locator interfaces
are now defined as:
local interface ServantManager{ };
local interface ServantLocator : ServantManager {
native Cookie;
Servant preinvoke(in ObjectId oid,
in POA adapter,
in CORBA::Identifier operation,
out Cookie the_cookie)
raises (ForwardRequest);
void postinvoke(in ObjectId oid,
in POA adapter,
in CORBA::Identifier operation,
in Cookie the_cookie,
in Servant the_servant
);
};
Programs that implement and use local interfaces can often do so without regard for the fact that these interfaces are local, but there are some important differences that you should be aware of. The next section of this paper covers the details of local interfaces and the how they can be used in IDL and your applications. The remaining sections focus on implementing and using a local interface using C++ and some of issues involved in doing so. We also discuss how this affects the way servant managers are defined. All example code in the section was tested using OCI TAO 1.2a, which is available from http://www.theaceorb.com.
Each interface in IDL is defined as either a local interface or an
unconstrained interface based
on whether it includes or does not include the local
keyword.
The CORBA specification defines the following special rules related
to the definition and use of local interfaces in IDL:
Basically, these rules ensure that a local reference can never leave a process. The CORBA specification states that the usage of client side language mappings for local types shall be identical to those of equivalent unconstrained types except for the following restrictions:
MARSHAL exception. This means:
CORBA::Any objects containing local types
cannot be marshaledCurrent object contexts that are distinct
from those of the callerCORBA::ORB::resolve_initial_references
operation or through some other local object obtained from
resolve_initial_references.
ORB implementations are also required to minimize the overhead
associated with invocations on local objects.
Local objects are implemented in a language mapping-specific nature
but always via CORBA::LocalObject, which derives from
CORBA::Object. Many of the normal operations allowed
by the CORBA::Object interface are inappropriate for
local objects and throw the NO_IMPLEMENT exception.
These operations include get_interface,
get_domain_managers,
get_policy,
get_client_policy,
set_policy_overrides,
get_policy_overrides,
validate_connection, and
get_component.
Note: The changes to support local objects have not been integrated and released in the C++ Mapping specification. This section assumes that the basic C++ mapping from the orignal CCM specification (orbos/99-07-01) is incorporated into the next C++ mapping release but also discusses some likely changes that may occur before the mapping is approved. It also discusses OCI TAO 1.2a's local object implementation and where it differs from the existing specifications.
You implement local objects in C++ by deriving from both
CORBA::LocalObject and the C++ class that the
interface maps to (the same class name as the interface name).
The CORBA::LocalObject class implements the same
_add_ref() and _remove_ref() member
functions that the ServantBase class also defines.
The original CCM specification states that the default implementations
of these functions do nothing. TAO implements these as the
specification states, but it is likely that the eventual C++
Mapping will specify that reference counting is done by default.
The original CCM specification neglects to state how local object
references can be obtained given a local object. Because TAO
is implemented so that _ptr types are C++ pointers,
you can avoid this issue by directly assigning a pointer
to the servant to _ptr and _var types.
This should work for any ORB implementation that maps
_ptr types to C++ pointers, but may not work
with all ORB implementations.
See the examples below for details of how the mapping may address
this issue.
The Java language mapping for local objects is included in the latest IDL to Java Language Mapping Specification (formal/01-06-06). Several open issues remain with this mapping, but the basics of the Java mapping are analogous with the C++ mapping and consistent with the Java mapping of unconstrained interfaces.
Implementations of local objects extend a special base interface,
org.omg.CORBA.LocalObject instead of
org.omg.CORBA.Object, as unconstrained objects do.
Holder and helper classes are generated for local interfaces
according to the normal mapping rules.
Because servant managers (locators and activators) are now defined as local interfaces, the implementation and use of these objects are dependent on the local object language mapping. A straightforward interpretation of the local object mapping for servant managers leads to backward compatibility problems in the implementation, activation, and use of these objects. It is possible that the eventual C++ mapping may be defined in such a way as to be backward compatible with existing code. TAO is implemented using the normal local object mapping for servant managers and the rest of this section assumes this mapping.
Traditionally, these objects were implemented by deriving from
POA_PortableServer::ServantLocator or
POA_PortableServer::ServantActivator.
With local objects your implementations should derive from
CORBA::LocalObject and either
PortableServer::ServantLocator or
PortableServer::ServantActivator.
Here is a sample servant locator definition:
class Messenger_Locator_i : public virtual PortableServer::ServantLocator,
public virtual CORBA::LocalObject
{
public:
Messenger_Locator_i();
virtual PortableServer::Servant preinvoke (
const PortableServer::ObjectId &oid,
PortableServer::POA_ptr poa,
const char * operation,
void * & cookie)
throw (CORBA::SystemException, PortableServer::ForwardRequest);
virtual void postinvoke (const PortableServer::ObjectId & oid,
PortableServer::POA_ptr poa,
const char * operation,
void * cookie,
PortableServer::Servant servant)
throw (CORBA::SystemException);
};
The implementations of preinvoke() and
postinvoke() remain the same as before the use of
local objects.
Another difference is the activation of servant managers
as local objects. Previously, the developer needed to
activate the servant manager as if it was an unconstrained
CORBA object (using _this() or another POA-related
operation). Because local objects cannot be activated
via a POA, this code now fails to compile and should be
removed. Lastly, you need to convert the servant type
to an object reference so it can be passed to the POA.
Once again, the normal POA operations for generation of
object references cannot be used with local objects.
In TAO, we can simply use an implicit cast to get from
a pointer to the local object to the corresponding
_var type. Here is some sample code for
initializing a servant locator and setting it on the
POA:
Messenger_Locator_i* locator_object = new Messenger_Locator_i;
Messenger_Locator_var locator = locator_object;
childPOA->set_servant_manager(locator.in());
This works because TAO implements the _ptr type
as a pointer to the interface class.
Unfortunately, this assumption is not true of all ORB implementations
and means that the above code is not portable to all C++ ORBs.
Currently, it is planned that the C++ mapping will introduce
a static member function in each local object that returns
a _ptr. This should make the code look something
like this:
Messenger_Locator_i* locator_object = new Messenger_Locator_i;
Messenger_Locator_var locator =
PortableServer::ServantLocator::_create_reference(*locator_object);
childPOA->set_servant_manager(locator.in());
The Messenger_Locator_i implementation above requires
the developer to explicitly
delete the memory associated with the servant locator, if you
want to reclaim that memory.
TAO developers have three choices if they want to automatically
recover this memory:
_add_ref()
and _remove_ref()._add_ref() and _remove_ref()
using CORBA::Object::_incr_refcnt() and
CORBA::Object::_decr_refcnt().TAO_Local_RefCounted_Object instead of
CORBA::LocalObject.
Number 1 above is the only current portable option as the other two
depend on TAO-specific functions in CORBA::Object and
a TAO-specific class, respectively.
The future C++ mapping should either make reference counting the
default for all local objects or provide a standard, reference-counted,
local object class.
This section walks through a simple local object example from definition of the IDL to use of the interface. The actual application is intended to demonstrate the concepts and not necessarily reflect an actual application's use of local interfaces. Here is our application's IDL:
local interface Messenger
{
boolean send_message (in string user_name,
in string subject,
inout string message);
};
We implement this object using the following class:
class Messenger_i : public virtual Messenger,
public virtual CORBA::LocalObject
{
public:
Messenger_i (void);
virtual ~Messenger_i (void);
virtual CORBA::Boolean send_message (const char * user_name,
const char * subject,
char *& message)
throw(CORBA::SystemException);
};
You may want to add reference counting as discussed in the
previous section on servant managers.
Since the C++ memory mapping for this function's arguments
are essentially symmetric for the client and server sides,
you can implement the send_message member function
using the normal C++ server-side rules:
CORBA::Boolean Messenger_i::send_message (const char * user_name,
const char * subject,
char *& message)
throw(CORBA::SystemException)
{
cout << "Message from: " << user_name << endl;
cout << "Subject: " << subject << endl;
cout << "Message: " << message << endl;
return 1;
}
You can now create a local object. Note that an ORB is not required to use a local object:
int main (int argc, char* argv[]) {
try {
Messenger_i *messenger = new Messenger_i;
Messenger_var messenger_obj (messenger);
CORBA::String_var message = CORBA::string_dup ("Howdy");
messenger_obj->send_message ("the_dude", "Test", message.inout());
} catch (...) {
// Handle exceptions raised by local objects
}
}
This code assumes an ORB implementation that maps
Messenger_ptr to
Messenger* (as discussed in the previous example).
Local objects are an important mechanism in CORBA and are required to utilize many advanced CORBA features such as servant managers, portable interceptors, and policies. Almost all CORBA developers will use local objects and many are going to need to define their own local interfaces and implement them. Although some questions remain as to the exact details of the C++ mapping, enough information is available to write code that should comply to the formal mapping with minimal modifications.
Object Computing, Inc (OCI) has been providing educational services to clients, industries and universities since 1993. We offer one of the most comprehensive distributed Object Oriented training curricula in the country. These curricula focus on the fundamentals of OO technology; with close to 40 workshops in OOAD, Java, XML, C++/CORBA and Unix/Linux.
For further information regarding OCI's Educational Services programs, please visit our Educational Services section on the web or contact us at training.
The OCI CORBA News Brief is intended to promote CORBA and object technology in the development of distributed computing applications. Each issue of the CORBA News Brief will feature news and technical information about OCI's supported open-source ORBs (TAO and JacORB), case studies, and examples using CORBA, as well as information about OCI's educational offerings.
The OCI CORBA News Brief is published on a monthly basis. Send ideas for articles of interest to corba.
To subscribe or unsubscribe from the CNB mailing list, send mail to majordomo with the line "subscribe cnb" or "unsubscribe cnb" in the body of the message.
|
![]() |
|