1.5. Putting It All Together

Even though our “Hello World” example is simple, it demonstrates the key features of space-based programming and ties together many of the topics we've covered in this chapter. JavaSpaces technology is simple and expressive: with very little code (and only four lines that contain JavaSpace operations) we've implemented a simple distributed application that provides concurrent access to a shared resource (in this case a shared object). Because spaces provide a high-level coordination mechanism, we didn't need to worry about multithreaded server implementation, low-level synchronization issues, or network communication protocols—usual requirements of distributed application design. Instead, our example concretely illustrates what we said earlier in this chapter—that we build space-based applications by designing distributed data structures along with distributed protocols that operate over them. HelloWorld uses a very simple distributed data structure: a shared object that acts as a counter. It also uses a simple protocol: clients take the Message entry to gain exclusive access to it, increment the counter, and then write the entry back to the space to share it once again. This protocol deserves a closer look.

Note that the protocol is loosely coupled— HelloWorld writes an entry into the space without worrying about the specifics of which clients will access it, how many, from where, or when. Likewise, the HelloWorldClients don't care who generated the entry, where, or when; they simply use associative lookup to find it. They don't even care if the entry exists in the space or not, but are content to wait until it shows up. Because the entry is persistent, clients can even show up at much later times (possibly even after HelloWorld has terminated) to retrieve it.

In our example, processes use entries to exchange not only data (a counter) but also behavior. Processes that create entries also supply proper methods of dealing with them, removing that burden from the processes that look up the entries. When a HelloWorldClient retrieves a Message entry, it simply calls the object's increment method (without needing to know how it works).

Our distributed protocol also relies on synchronization. Without coordinated access to a shared resource—in this case, the counter—there would be no way to ensure that only one process at a time has access to it, and processes could inadvertently corrupt it by overwriting each other's changes. Here, to alter an entry, a process must remove it, modify it, and then return it to the space. While the process holds the entry locally, no other processes can access or update it. Transactional security of spaces also plays a key part in guaranteeing this exclusive access: If a process succeeds at a take operation, the entry is removed and returned atomically, and the process is guaranteed to have the only copy of the entry.

This isn't to say our simple example covers everything. Although we can trust a single space operation to be transactionally secure (either it completes or it doesn't), there is nothing in our current example to prevent the Message entry from being irretrievably lost if a client crashes or gets cut off from the network after taking the message entry from the space (as often happens in the presence of partial failure). In cases like this, to ensure the integrity of our applications, we will need to group multiple space operations into a transaction to ensure that either all operations complete (in our example, the entry gets removed and returned to the space) or none occur (the entry still exists in the space). We'll revisit the topic of transactions in greater detail in Chapter 9.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset