CS 635 Advanced Object-Oriented Design & Programming Spring Semester, 2004 Pipes Filters and Broker |
||
---|---|---|
© 2004, All Rights Reserved, SDSU & Roger Whitney San Diego State University -- This page last updated 22-Apr-04 |
Pipes & Filters
Unix Example
ls | grep -i b | wc -l
Context
Processing data streams
Problem
Building a system that processes or transforms a stream of data
Forces
Solution
Divide task into multiple sequential processing steps or filter components
Output of one filter is the input of the next filter
Filters process data incrementally
Structure
A Filter can be triggered by:
Some Implementation issues
Dividing the system into separate tasks
Data format passed between filters
This may require filters to convert from common format to a usable format
Implementing the pipes
Filter could directly push/pull data from another filter
Using a separate pipe mechanism
SharedQueue for Java Pipe
import java.util.ArrayList; public class SharedQueue { ArrayList elements = new ArrayList(); public synchronized void append( Object item ) { elements.add( item); notify(); } public synchronized Object get( ) { try { while ( elements.isEmpty() ) wait(); } catch (InterruptedException threadIsDone ) { return null; } return elements.remove( 0); } public int size() { return elements.size(); } }
Error handling
Difficult to do
What happens if 1/2 data is processed when one filter has a runtime exception?
How does one inform the other filters?
Can one restart the pipeline to process the next batch of data?
Example endOfPipeline := $@.
upperCaseFilter := [:input :output | | nextCharacter | [nextCharacter := input next. nextCharacter ~= endOfPipeline] whileTrue: [output nextPut: nextCharacter asUppercase]]. noBeesFilter := [:input :output | | nextCharacter | [nextCharacter := input next. nextCharacter ~= endOfPipeline] whileTrue: [nextCharacter ~= $B ifTrue: [output nextPut: nextCharacter]]]. display := [:input | | nextCharacter | [nextCharacter := input next. nextCharacter ~= endOfPipeline] whileTrue: [Transcript nextPut: nextCharacter; flush]].
dataStream :='Hi Mom. How is Bob@' readStream. pipeA := SharedQueue new. pipeB := SharedQueue new. [upperCaseFilter value: dataStream value: pipeA] fork. [noBeesFilter value: pipeA value: pipeB] fork. [display value: pipeB ] fork.
The Broker Pattern
A broker
Dynamics
Registering Server
Client Server Interaction
Variants
Direct Communication Broker System
Callback Broker System
Known Uses
CORBA
IBM's SOM/DSOM
Mircosoft OLE 2.x
RMI
Consequences
Benefits
Location Transparency
Clients (servers) do not care where servers (clients)are located
Changeability and extensibility of components
Changes to server implementations are transparent to clients if they don't change interfaces
Benefits - Continued
Interoperability between different Broker System
Different broker systems may interoperate if they have a common protocol for the exchange of messages
Liabilities
Restricted Efficiency
Lower fault tolerance compared to non-distributed software
Benefits and Liabilities
Testing and Debugging
A client application using tested services is easier to test than creating the software from scratch
Some RMI
A First Program - Hello World
Modified from "Getting Started Using RMI"
The Remote Interface
public interface Hello extends java.rmi.Remote { String sayHello() throws java.rmi.RemoteException; }
The Server Implementation
// Required for Remote Implementation import java.rmi.*; import java.rmi.server.UnicastRemoteObject; // Used in method getUnixHostName import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class HelloServer extends UnicastRemoteObject implements Hello { public HelloServer() throws RemoteException { } // The actual remote sayHello public String sayHello() throws RemoteException { return "Hello World from " + getUnixHostName(); }
// Works only on UNIX machines
protected String getUnixHostName() { try { Process hostName; BufferedReader answer; hostName = Runtime.getRuntime().exec( "hostname" ); answer = new BufferedReader( new InputStreamReader( hostName.getInputStream()) ); hostName.waitFor(); return answer.readLine().trim(); } catch (Exception noName) { return "Nameless"; } }
// Main that registers with Server with Registry
public static void main(String args[]) { // Create and install a security manager System.setSecurityManager(new RMISecurityManager()); try { HelloServer serverObject = new HelloServer (); Naming.rebind("//roswell.sdsu.edu/HelloServer", serverObject ); System.out.println("HelloServer bound in registry"); } catch (Exception error) { System.out.println("HelloServer err: "); error.printStackTrace(); } } }
The Client Code
import java.rmi.*; import java.net.MalformedURLException; public class HelloClient { public static void main(String args[]) { try { Hello remote = (Hello) Naming.lookup( "//roswell.sdsu.edu/HelloServer"); String message = remote.sayHello(); System.out.println( message ); } catch ( Exception error) { error.printStackTrace(); } } }Note the multiple catches are to illustrate which exceptions are thrown
Running The Example
Server Side
Step 1 . Compile the source code
Step 3 . Insure that the RMI Registry is running
For the default port number
Client Side
The client can be run on the same machine or a different machine than the server
Step 1 . Compile the source code
Proxies
How do HelloClient and HelloSever communicate?
Client talks to a Stub that relays the request to the server over a network
Server responds via a skeleton that relays the response to the Client
Copyright ©, All rights reserved.
2004 SDSU & Roger Whitney, 5500 Campanile Drive, San Diego, CA 92182-7700 USA.
OpenContent license defines the copyright on this document.
Previous    visitors since 22-Apr-04