typedef struct _object_ref { /* attributes which name object globally */ attr_list obj_name; /* caches meaning of name in local context */ attr_list name_trans_cache; /* method specific attribute cache */ attr_list method_specific_cache; } object_ref_struct, *object_ref; /* opaque type for completion handle */ typedef struct _handle_struct *otl_handle; /* * perform an invocation. * (sync or async, simple or return) */ extern otl_handle otl_invoke(object_ref obj, attr_list method_attrs, void *pblock, int plen ); otl_is_local_object( object_ref obj ); extern void otl_wait( otl_handle handle ); extern int otl_query_done( otl_handle handle ); extern int otl_release_handle( otl_handle handle );A sample piece of application code to perform an invocation might look like the text below. (Here, by "application code", I mean a chunk of code that calls OTL. This code may be generated by an IDL processor generator or other object-system-specific code generator.)
Incoming values:
{ /* * the otl_is_local_object() call returns quickly if the * object reference has been seen before and thus name * translation results are cached in the object reference * (in obj->name_trans_cache ) */ if (otl_is_local_object(obj)) { /* application specific code to perform local invocation */ } else { /* * application specific code to marshall parameters. * result is values pblock and plen. */ attr_list method_attrs; /* * At this point, method-specific attributes are * cached somehow in the obj attribute list. Construct * a query, get them out and put them in method_attrs. */ otl_handle handle = otl_invoke(obj, method_attrs, pblock, plen); otl_wait(handle); /* * Results are available now and attribute caches are * updated. */ otl_release_handle(handle); } }This code makes use of most of the basic OTL calls. In particular, it uses:
otl_invoke()
will perform local
invocations as well, but it may be valuable to avoid
parameter packing overhead.
otl_invoke()
will perform any invocation, either local or
remote. Its precise behavior is determined by the attributes
associated with the object. Its parameter handling is
limited to transmitting an uninterpreted block of memory and
making it available to the called routine.
otl_invoke()
if the return value is
unnecessary and asynchronous operation is desired.
/* * otl_is_local_object() * This otl utility routine exists to determine object * locality. This determination may require several steps, * including performing name translation if that is * required. Assuming that no name translation is required, * either the obj->object_name or the obj->name_trans_cache * will contain a OTL:HOME_HOST attribute which will be * compared to the current host. If they are equivalent, * the attribute OTL:IS_LOCAL will be added to * obj->name_trans_cache. (This attribute is checked for at * the beginning of the routine as a shortcut to this * process.) If the OTL:HOME_HOST is not present, the * OTL:NAME_SERVER attribute must hold a value that can be * invoked to translate the name and set the OTL:HOME_HOST * attribute. */ otl_is_local_object(obj) object_ref obj; { static atom_t is_local_atom = 0; static atom_t home_host_atom = 0; static atom_t my_host_atom = 0; atom_t home_host; int local_call = 0; if (my_host_atom == 0) { my_host_atom = otl_get_local_host_atom(); } if (is_local_atom == 0) { is_local_atom = atom_from_str("OTL:IS_LOCAL"); } if (obj->name_trans_cache && query_attr(obj->name_trans_cache, is_local_atom, /* type pointer */ NULL, /* value pointer */ NULL)) { return 1; } else { if (home_host_atom == 0) { home_host_atom = atom_from_str("OTL:HOME_HOST"); } if (!query_attr(obj->obj_name, home_host_atom, /* type pointer */ NULL, /* value pointer */ &home_host) && !query_attr(obj->name_trans_cache, home_host_atom, /* type pointer */ NULL, /* value pointer */ &home_host)) { /* * OTL invoke to the value of the OTL:NAME_SERVER * attribute, followed by an otl_wait() and * otl_release_handle(). Upon completion, there * should be a home_host value in * obj->name_trans_cache. */ if (!query_attr(obj->name_trans_cache, home_host_atom, /* type pointer */ NULL, /* value pointer */ &home_host)) { return 0; /* Serious error */ } } return (home_host_atom == my_host_atom); } /*NOTREACHED*/ } extern atom_value otl_get_local_host_atom() { char hostname[256]; char *domainname; gethostname(hostname, 256); strcat(hostname, "."); domainname = rindex(hostname, ".") +1; getdomainname(domainname, 192); return atom_from_str(hostname); }