This work begins from the assumption that it is not possible to build abstractions or services that hide this underlying reality, if only because those constraints are physical. The management of mobile objects under these constraints implies that a set of events must be watched, managed or created; others might disappear and won't need further attention. Best effort is provided to react to and exploit fully the current environment to the benefit of interacting mobile and stationary objects.
The main contributions of this work are the design of an architecture that provides the following functionality:
During execution, the three lower layers combine to form a single entity, called the ``Capsule,'' that provides a support environment for distributed object execution. It encapsulates and insulates objects from the underlying machine and operating system architecture. A capsule defines interfaces to a set of fundamental services available to the objects that live ``within''. Object belonging to a capsule share the same address space (i.e. a capsule is a single process), with each object being allocated at least one thread.
2.1 Language Layer
The Hector kernel is designed to support objects written in different languages. A module that implements the mapping between the Capsule Kernel Layer (written in Python) and objects written in a particular language is called a ``language mapping.'' The set of language mappings loaded into a Capsule forms the Language Layer.
A binding can require that a role be optional and have cardinality constraints. Roles have a relationship such as ``a client role needs a mobile agent role'' between them. This concept is very important when describing mobile behaviour.
2.2 Encapsulation Layer
Encapsulation furnishes different types of services known as transparencies. We will describe only those services related to mobile computing management such as trading, naming, notification, and type management services.
By using a communication layer, a capsule can interact with other capsules. All types of faults occurring at this level are reported to the encapsulation layer using the event notification service. The encapsulation layer can directly access this layer, opening and closing connections via an abstract API.
3.0 How objects interact
In this section, we discuss the language layer abstractions that arise from the desire to have an application-aware adaptability mechanism that can copes with mobile constraints in an heterogeneous environment. 3.1 Binding negotiation
3.1.1 Binding type negotiation
A binding is a context for object interactions. A binding type, stored in a Type Service, describes how interactions between objects must occur. It also offers a domain which allows each interacting object to reach a common understanding of the semantics of all concepts used during interactions such as Integer, Names, QoS....
Mobile components cannot guarantee QoS as stationary networks do. Nevertheless a mobile host can provide information about the environment in which it runs. An object runs in a specific type of environment that we call CoE (Class of Environment)[8]. The environment of a mobile object changes dynamically and corresponds to the quantified schema of configuration of local entities that it needs to process an interaction.
Example: if bandwidth < 9 Kbps do_something.Adaptation rules are mainly specified by the application user using an ECA (Event Condition Action) structure. The Event Notification service is responsible for notifying the occurrence of events that an object has subscribed to.
The types of event/conditions can be: crossing a threshold, changes of configuration such as the migration of objects (instance), availability of memory, network disconnection, any types of fault. The types of actions are known as callbacks and can do nothing but notify the application object (exception), defer communications, keep track of instance of moving object, call appropriate functions, changing dynamically actions locally or remotely.
Event/conditions of an adaptation rule are expressed in a constraint language which provides a set of operators which allow arbitrarily complex expressions involving properties and values[9]. This description can be computationaly complete with respect to the observable properties of the local system if the programmer knows all observable events.
An action is fired when the condition expression is true[9]. The following example contains four adaptation rules:
adaptation_rules = {
Our adaptability rules syntax are generic enough so that we can express complicated policies such as priority of degradation for multimedia applications. For example, it allows us to specify which aspect of the multi-media stream we want to be degraded by priority when a range of events happen such as dropping the sound first then the number of frames per second).
``bandwidth > 20'':increase_traffic_cb,
``exists(tcp_errors)'': use_udp,
``cpu_load > 10'': migrate_object_cb,
``disconnected'': re_negotiate_cb
}
4.0 Mobility Service
We have showed how our architecture copes with mobile constraints through the use of binding, QoS negotiation and adaptability rules. These are language level abstractions concepts. Engineering aspects require the collaboration of different services defined in the encapsulation layer. Coordination is provided by the mobile service
4.1 Object migration
Migration is one type of action (amongst others) that can be specified in an adaptability rule. A migrating object can be either passive or active. A passive object is a class definition or a function (e.g.: a filter). An active object is an instance of the Hector object class. Both types of objects need to be accessed, tracked and instantiated from any capsule.The migration of an object is decided either by the mobility service or by the application object.4.1.1 Moving an active objects
An active object migrates from a capsule to another capsule. Each capsule has a unique ID. The following migration class is inherited by all migratable objects.import elvin # Notification service
class Migration:
``````Initialise an event notification and watch
migrating events''''''
def __init__ (self):
self.lv = elvin.elvin()
self.lv.subscribe(``exists(migrated)'':chain_update)
def move (self, obj, here, there):
``````suspend and copy the object''''''
p_obj= obj.suspend()
send (p_obj, here, there)
def suspend(self):
``````suspend and pickle an object with contexts''''''
T_id = get_reftype(obj)
bind_contex = get_bind_context(obj)
p_obj = pickle (obj, T_id, bind_context)
notify(``migrating'', obj.__name__, there)
def resume(self, p_obj):
``````retrieve instance of object''''''
obj, T_id, bind_contex = unpickle(p_obj)
factory (Tid, obj, bind_context)
notify(``migrated'', obj.__name__, there)
def chain_update (self,d_not):
``````update reference''''''
if in_current_capsule(obj):
-- if there is a chain_in pointer to this
-- object in the capsule
create_chain_out(obj, there)
update (trader, name_service, obj,there)
Upon a decision to migrate an active object, the migration service does:4.1.2 Moving a passive object
The migration of a passive object is far simpler. Passive objects are either a class definition or a function. In Python, class definitions include the implementation of their methods. The type service does most of the work to achieve a class migration. Indeed, our type service is federated and stores a class definition so that a class can be instantiated from anywhere.`````` A class to represent fully `picklable' functions. ``````
# Standard/built-in modules.
import marshal
# Common modules.
import internals
class FlatFunction:
`````` A class to represent fully `picklable' functions. ``````
def __init__(self, fn=None):
`````` Create a picklable representation of a function
We use a default argument here so that the flattened
function can be pickled/unpickled without the need for a
`__getinitargs__' method. We do this so that the
flattened function does not have to store any reference
to the function object that it was created from.''''''
# The only time `None' is a valid argument is when
# the constructor is being called by the `pickle' module
if fn != None:
self._flatten(fn)
return
def unflatten(self, namespace=None):
`````` Create a function object from the flattened
function! ``````
if namespace == None:
namespace = globals()
return self._unflatten(namespace)
###########################################################
# Internal methods.
###########################################################
def _flatten(self, fn):
`````` Create a `picklable' representation of a function.``````
# Get a list of the function's default parameter
# values, its code object, and its documentation.
self.defaults = fn.func_defaults
self.code = marshal.dumps(fn.func_code)
self.doc = fn.__doc__
return
def _unflatten(self, namespace):
`````` Create a function object from the flattened function
# Unmarshal the code object.
code_object = marshal.loads(self.code)
# Create a function object from the code object.
function_object = internals.PyFunction_New \
(code_object, namespace)
# Set the default arguments.
if self.defaults != None:
internals.PyFunction_SetDefaults \
(function_object, self.defaults)
# Set the documentation string.
if self.doc != None:
internals.PyFunction_SetDoc \
(function_object, self.doc)
return function_object
4.1.3 References of mobile objects
The reference of an object is obtained by export and import to the trading or the naming service. There are two choices when handling references to active migrating objects. Either (1) each object currently interacting with the moving object updates their reference on the fly, or (2) they do not, and the capsule of the moving object has to provide an infrastructure to forward its communication to the new location. The first choice is expensive and might penalize all interacting objects involved in a multi party interaction. We take the second approach because the reference is transparently manipulated at the encapsulation language layer even if objects move during the life of a binding.
D. Arnold, A. Bond, M. Chilvers - Hector - Distributed Object in Python - Dr. Dobb's Sourcebook #273 January 1997. http://www.dstc.edu.au/Hector/
A. Campbell, G. Coulson, D. Hutchison - A quality of service Architecture - Journal of Computer Communication Review - Vol 24 Number 2 April 1994.
J. Gray, P. Helland, P. O'Neil, D. Shasha - The Dangers of Replication and a Solution - SIGMOD Record Proc, Quebec - June 1996
ITU/ISO - Reference Model for Open Distributed Processing - Part 1,2,3 IS 10746-(1,2,3). http://www.iso.ch:8000/RM-ODP/
Object Management Group - CORBAservices - Life Cycle Services Specification - 1995
J. Hylton, K. Manheimer, F-L Drake Jnr, B. Warsaw, R. Masse, G. van Rossum - Knowbot programming: System support for mobile agents.In Proceedings of the 5th International Workshop on Object Orientation in Operating Systems (IWOOOS '96), pages 8-13, Oct. 1996
A.Rakotonirainy, A. Bond - Mobile Transparency - Proc ICODP, Toronto, May 1997. http://www.dstc.edu.au/AU/staff/andry/icodp.ps
B. Segall - Elvin: Event notification service. DSTC Internal Report, 1995.