4.4 Distribution of Tuple Space
4.5.5 Tuple Search Algorithm
4.5.5.3 Searching for a Remote Tuple
The search process is initiated when a node’s runtime system receives a request from an application to retrieve a tuple. This can be triggered by the invocation of any of the followingTupleSpaeRuntimemethods:in(),inp(),rd(),rdp(, and
Each node’s runtime system maintains an array, A, which contains references to
N stub objects, where N is the number of all other nodes that are participating in the
system. For example, N=9 for a system that has ten participating nodes, and each runtime system has a stub object associated with each of the other nine nodes.
The ordering of these stubs in A reflects the relative probability of the associated remote node being able to successfully satisfy a request for a tuple, determined by its success factor. Whilst the stub order is initially random, once the execution of the system begins and the success factor of each stub is adjusted, the runtime system alters the ordering to reflect the success or failure of any remote requests that it undertakes. Relatively quickly, the ordering the stubs will reflect the node’s unique group of neighbouring nodes that it frequently communicates with; stubs associated with these nodes will be stored towards the beginning of A, while those that have not successfully fulfilled previous requests, or have not yet been communicated with at all, will be stored towards the end. Node groupings for a small Tupleware system are illustrated in Figure 4.6. This figure shows the nodes in a cluster, with each of their success factor values in relation to Node5. As the diagram shows, this node forms a grouping with the nodes with a high associated success factor, to the exclusion of those nodes with a low success factor.
Node11 Node15 Node14 0.30 0.30 0.30 Node7 0.30 Node3 0.30 Node2 Node6 Node1 0.90 Node4 0.90 Node0 0.70 Node10 0.90 Node9 0.70 Node8 0.70 0.90 0.70 Node5 0.30 Node13 0.30 Node12
Figure 4.6: Grouping of neighbouring nodes based on success factor.
It important to note that the logic behind maintaining these groupings is com- pletely distributed; each individual runtime system dynamically updates its array of stubs based on the success or failure of its own requests, and no overarching system-
wide coordination or creation of these groupings is used at any point. All decisions by the runtime system related to where to dispatch each request are made locally, based on information gained locally. This minimises any overhead that would be introduced from a system-wide logic being maintained, while still providing the means for each node to adapt to its role in the execution of a particular application. The ordering of the stubs in array A is utilised when the runtime system makes a request, with requests being performed sequentially, based on their ordering. There- fore, the first remote node queried will be the one associated with stub stored at A[0], and if that request is not successful, then the node associated with the stub at A[1] will be queried, and so on, until either a matching tuple has successfully been re- trieved, or all nodes have been queried unsuccessfully. At each conclusion of each individual request instance, the success factor of the stub used to execute the re- quest is updated, whether the request was successful or a failure. Assuming that one stub in A executes a successful query, then the successful stub’s success factor will increase, and any stubs used to execute an unsuccessful request will have their success factor decreased.
There will be situations encountered when all remote nodes have been queried and have been unable to successfully fulfil the tuple request, and what actions oc- cur subsequently depends on whether the operation being request is blocking or non-blocking. If it is the latter (eitherinp()orrdp()), then the runtime system’s
invoked method will simply return a null value to the application layer, in keeping with the semantics of these methods. However, if it is the former (in()orrd()),
then the semantics of these operations dictate that we must wait until a matching tuple becomes available before returning it to the application. To do this, rather than continually polling each remote node until we are successful, parallel block- ing requests are dispatched to each node, and the runtime simply waits until one of these node can provide a matching tuple. When this eventually occurs, the other pending requests are aborted, and the stub which executed the successful request has its success factor adjusted accordingly.
At the conclusion of any of the tuple retrieval operations, A is reordered based on the updated success factor values of the stubs which it contains. Thus, when subsequent retrieval operations are invoked, the stubs in A will be ordered correctly so that A[0] will contain the stub most likely to execute a successful request, and