at:tutorial:distribution
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionLast revisionBoth sides next revision | ||
at:tutorial:distribution [2007/04/26 20:07] – elisag | at:tutorial:distribution [2009/01/30 16:12] – *minor tvcutsem | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | |||
====== Distributed Programming ====== | ====== Distributed Programming ====== | ||
- | This section | + | Building on the actor-based concurrency model explained in the [[actors|previous chapter]], this chapter |
- | The integration of distribution | + | |
- | ===== Starting the Network.. | + | These requirements correspond to the cornerstones of the Ambient-Oriented Programming paradigm. The seamless integration of language support for dealing with partial failures and performing service discovery, hinge on AmbientTalk' |
+ | |||
+ | Before delving in these topics, we illustrate how to activate the network facilities of AmbientTalk in the next section. | ||
+ | |||
+ | ===== Going Online | ||
AmbientTalk provides an unique native object, named '' | AmbientTalk provides an unique native object, named '' | ||
- | When the virtual machine goes online, | + | When the virtual machine goes online, the built-in |
+ | |||
+ | Taking a virtual machine | ||
< | < | ||
Line 15: | Line 19: | ||
</ | </ | ||
- | ===== Exporting and discovering objects | + | ===== Exporting and Discovering Objects |
AmbientTalk provides language support to make some objects available to other objects residing in remote actors by means of the '' | AmbientTalk provides language support to make some objects available to other objects residing in remote actors by means of the '' | ||
< | < | ||
- | defstripe | + | deftype |
def service := object: { | def service := object: { | ||
- | def print(aDoc) { | + | |
- | system.println(" | + | system.println(" |
- | } | + | } |
}; | }; | ||
export: service as: Printer; | export: service as: Printer; | ||
</ | </ | ||
- | When an object its exported by its actor, it becomes discoverable by other actors by means of the service type. Internally, this means that the object is placed in the export table of its actor. As shown in the example, a service type is represented by a stripe. This means that services types are not associated with a set of methods, but they denote an abstract publication topic that objects exports. As a stripe, a service type can thus be a subtype of one or more other service types. For example, an object could offer a color printing services by exporting the following | + | When an object its exported by its actor, it becomes discoverable by other actors by means of the service type. Internally, this means that the object is placed in the export table of its actor. As shown in the example, a service type is represented by a type tag. This means that services types are not associated with a set of methods, but they denote an abstract publication topic that objects exports. As a type tag, a service type can thus be a subtype of one or more other service types. For example, an object could offer a color printing services by exporting the following |
< | < | ||
- | defstripe | + | deftype |
</ | </ | ||
Line 42: | Line 46: | ||
< | < | ||
when: InstantMessenger discovered: { |messenger| | when: InstantMessenger discovered: { |messenger| | ||
- | when: (messenger< | + | |
- | buddyList.put(name, | + | buddyList.put(name, |
- | system.println(" | + | system.println(" |
- | | + | }; |
}; | }; | ||
</ | </ | ||
- | The code block to execute when the service type becomes available is parameterized with the actual remote reference to the discovered service object. In the example above, '' | + | The code block to execute when the service type becomes available is parameterized with the actual remote reference to the discovered service object. In the example above, '' |
< | < | ||
- | We are using a future to get the return value of the '' | + | We are using a future to get the return value of the '' |
</ | </ | ||
Line 57: | Line 62: | ||
As '' | As '' | ||
- | |||
- | ===== Partial Failure Handling | + | ===== Dealing with Transient Failures |
- | Let us consider again the example instant messenger application described in previous | + | Let us consider again the example instant messenger application described in previous |
- | | + | When an object discovers a service type, the '' |
+ | |||
+ | | ||
- Native data types are always passed by copy. | - Native data types are always passed by copy. | ||
- | When a remote far reference receives a messages, it flushes the message to the remote object providing that it is connected. If the remote far reference is disconnected, | + | When a remote far reference receives a message, it flushes the message to the remote object providing that it is connected. If the remote far reference is disconnected, |
- | Therefore, a remote far reference | + | Therefore, a remote far reference |
< | < | ||
when: InstantMessenger discovered: { |messenger| | when: InstantMessenger discovered: { |messenger| | ||
- | ... | + | |
- | when: messenger disconnected: | + | |
- | system.println(" | + | system.println(" |
- | }; | + | }; |
- | when: messenger reconnected: | + | |
- | system.println(" | + | system.println(" |
- | }; | + | }; |
}; | }; | ||
</ | </ | ||
- | Such observers can be also installed | + | This code illustrates how the instant messenger application gets notified when a buddy goes online or offline. In the above code, '' |
+ | |||
+ | In order to cope with partial failures, AmbientTalk also allows developers to retract all currently unsent messages from the remote | ||
+ | |||
+ | The '' | ||
+ | |||
+ | < | ||
+ | when: Service discovered: { | reference | | ||
+ | when: reference disconnected: | ||
+ | messages := retract: reference; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | The '' | ||
+ | |||
+ | The function '' | ||
+ | |||
+ | ===== Dealing with Permanent Failures ===== | ||
+ | |||
+ | As explained in the previous section, remote far references have been designed to be resilient to intermittent disconnections by default. This behaviour is desirable because it can be expected that many partial failures in mobile ad hoc networks | ||
+ | |||
+ | To deal with permanent failures, AmbientTalk uses the concept of leasing. A lease denotes the right to access a resource for a specific duration that is negotiated | ||
+ | |||
+ | ====Leased Object References==== | ||
+ | |||
+ | A leased object | ||
+ | |||
+ | {{ : | ||
+ | |||
+ | ====Working with leased object references==== | ||
+ | |||
+ | The code snippet below illustrates a leased far reference in the context | ||
+ | |||
+ | < | ||
+ | def openSession() { | ||
+ | def shoppingCart := Cart.new(); // to store purchased items | ||
+ | def session := object: { | ||
+ | def addItemToCart(anItem) { ... } | ||
+ | def checkOutCart() { ... } | ||
+ | }; | ||
+ | def leasedSession := lease: minutes(5) for: session; | ||
+ | leasedSession; | ||
+ | }; | ||
+ | </ | ||
+ | |||
+ | The '' | ||
< | < | ||
- | The complete implementation | + | We assume the use of futures to get the return value of the '' |
</ | </ | ||
+ | |||
+ | At client side, a customer can ask a server to open a shopping session as follows: | ||
+ | |||
+ | < | ||
+ | def mySession := server< | ||
+ | ... | ||
+ | mySession< | ||
+ | </ | ||
+ | |||
+ | The future attached to the '' | ||
+ | |||
+ | < | ||
+ | renew: mySession for: minutes(5); | ||
+ | revoke: mySession; | ||
+ | </ | ||
+ | |||
+ | The '' | ||
+ | |||
+ | When no renewal is performed due to a network partition outlasting the lease time period or in absence of utilization, | ||
+ | |||
+ | < | ||
+ | when: mySession expired: { | ||
+ | ... // free up resources used by this session e.g. the cart | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | The construct takes as parameters a leased reference and a block of code that is asynchronously triggered upon the lease expiration. This allows client and service objects to treat a failure as permanent (i.e. to detect when the reference is permanently broken) and to perform application-level failure handling. At server side, this has important benefits for memory management. Once all leased references to a service object have expired, the object becomes subject to garbage collection once it is no longer locally referenced. | ||
+ | |||
+ | ====Leasing patterns==== | ||
+ | As is the case in other leasing mechanisms, determining the proper lease renewal period is not straightforward and may even depend on system parameters such as the number of clients. In AmbientTalk, | ||
+ | |||
+ | The first variant is a // | ||
+ | by the remote object. In other words, as long as the client uses the remote object, the leased reference is transparently renewed by the interpreter. | ||
+ | |||
+ | < | ||
+ | def openSession() { | ||
+ | def shoppingCart := Cart.new(); // to store purchased items | ||
+ | def session := object: { | ||
+ | def addItemToCart(anItem) { ... } | ||
+ | def checkOutCart() { ... } | ||
+ | }; | ||
+ | def leasedSession := renewOnCallLease: | ||
+ | leasedSession; | ||
+ | }; | ||
+ | </ | ||
+ | |||
+ | Similar to '' | ||
+ | |||
+ | The second variant is a // | ||
+ | |||
+ | < | ||
+ | def myObject: = object:{ | ||
+ | ... | ||
+ | }; | ||
+ | def leasedObject := singleCallLease: | ||
+ | </ | ||
+ | |||
+ | Similar to the other two constructs, '' | ||
+ | |||
+ | ====Integrating leasing with future-type message passing==== | ||
+ | |||
+ | Single-call leases are useful for objects adhering to a single call pattern, such as callback objects. Callback objects are often used in asynchronous message passing schemes in order for remote object to be able to return values. These callback objects are typically remotely accessed only once by remote objects with the computed return value. In AmbientTalk, | ||
+ | |||
+ | We have integrated leasing into futures by parameter-passing a future attached to an asynchronous message via a singe-call lease which either expires due to a timeout or upon the reception of the computed return value. The timeout for the implicit single-call lease on a future can be set by annotating the asynchronous message with a '' | ||
+ | |||
+ | < | ||
+ | def sessionFuture := server< | ||
+ | when: sessionFuture becomes: { |session| | ||
+ | // open session with server | ||
+ | }catch: TimeoutException using: { |e| | ||
+ | // unable to open a session, do some clean-up if necessary | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | If the future is resolved, the session variable stores a leased object reference to the remote session object. | ||
+ | |||
+ | < | ||
+ | Note that specifying a '' | ||
+ | </ | ||
+ | |||
+ | ====Importing leased object references==== | ||
+ | |||
+ | Similar to futures, leased object references have been built reflectively on top of AmbientTalk. | ||
+ | |||
+ | To use the language constructs for leased references, you should import the leasedref module as follows: | ||
+ | < | ||
+ | import / | ||
+ | </ | ||
+ | <note warning> | ||
+ | leasedrefs module exports support primitives to manipulate time intervals (i.e. '' | ||
+ | </ | ||
+ | |||
+ | More information pertaining to the API of the leased references language module can be found in the [[appendix|appendix]]. | ||
+ | |||
+ | ===== Taking Offline Remote Objects ===== | ||
+ | |||
+ | AmbientTalk distributed memory management scheme has been based on [[http:// | ||
+ | |||
+ | As previously explained, in order to deal with volatile connections, | ||
+ | |||
+ | < | ||
+ | takeOffline: | ||
+ | </ | ||
+ | |||
+ | The primitive takes as parameter an object which is removed from the export table of the actor where the code is executed. When the object is removed from the export table, all remote far reference to the object become invalidated and the object no longer belongs to the set of root objects and as such, it can be eventually reclaimed by Java's local garbage collector once it is no longer locally referenced. Although the actual reclamation of an unexported object may be triggered at a later point in time, any attempt to access via a remote far reference results in an ObjectOffline exception notifying the client object that the object was taken offline and thus, its remote far references is invalid. | ||
+ | |||
+ | <note tip> | ||
+ | [[distribution# | ||
+ | </ | ||
+ | |||
+ | ====Working with objects taken offline==== | ||
+ | |||
+ | On the client side, taking offline an object results in a permanent disconnection of the remote far references pointing to it. In other words, despite having network connection, unexporting an object renders remote far references permanently disconnected. This implies that client have to deal explicitly with unexported objects. | ||
+ | |||
+ | Clients can get notified when an object is taken offline by means of '' | ||
+ | |||
+ | Additionally, | ||
+ | |||
+ | < | ||
+ | when: messenger takenOffline: | ||
+ | system.println(" | ||
+ | //clean certain resources associated to the buddy | ||
+ | }; | ||
+ | </ | ||
+ | |||
+ | The construct takes as parameter a far reference and a block of code that is executed when the taken offline event is notified to the virtual machine. '' | ||
+ | |||
+ | < | ||
+ | Disconnection, | ||
+ | </ | ||
+ | |||
+ | ====Distributed unit testing and takeOffline==== | ||
+ | |||
+ | As previously mentioned, the '' | ||
+ | |||
+ | These semantics is useful for unit test purposes. The [[appendix# | ||
+ | |||
+ | By means of the '' |
at/tutorial/distribution.txt · Last modified: 2009/01/30 16:13 by tvcutsem