© 2003 Wolfgang Emmerich 1 Validating Distributed Object & Component Designs Wolfgang Emmerich and Nima Kaveh London Software Systems University College London
© 2003 Wolfgang Emmerich2 Outline Distributed Systems Middleware Advanced Communication in Object and Component Middleware Design Issues for Distributed Objects and Components Design Validation using Model Checking Conclusions
© 2003 Wolfgang Emmerich3 Distributed System Example
© 2003 Wolfgang Emmerich4 Host n-1 Host n Host 2 Host 1 What is a Distributed System? Middleware Network Operating System Hardware Component 1 Component n Component 1 Component n Component 1 Component n Component 1 Component n Network
© 2003 Wolfgang Emmerich5 What is a Distributed System? A distributed system is a collection of autonomous hosts that that are connected through a computer network. Each host executes components and operates a distribution middleware, which enables the components to coordinate their activities in such a way that users perceive the system as a single, integrated computing facility.
© 2003 Wolfgang Emmerich6 Abstraction from network protocols Network protocols do not provide right abstractions for building distributed systems: Packet forwarding vs. procedure call Mapping of request parameters to byte streams Resolution of data heterogeneity Identification of components Implementation of component activation Type safety Synchronization of interaction between distributed components Quality of service guarantees
© 2003 Wolfgang Emmerich7 Outline Distributed Systems Middleware Advanced Communication in Object and Component Middleware Design Issues for Distributed Objects and Components Design Validation using Model Checking Conclusions
© 2003 Wolfgang Emmerich Middleware Layered between Application and OS/Network Makes distribution transparent Resolves heterogeneity of Hardware Operating Systems Networks Programming Languages Provides development and run-time environment for distributed systems.
© 2003 Wolfgang Emmerich9 Physical Application Presentation Session Transport Network Data link ISO/OSI Reference Model Middleware Network Operating System
© 2003 Wolfgang Emmerich10 Forms of Middleware Transaction-Oriented IBM CICS BEA Tuxedo Encina Message-Oriented IBM MQSeries DEC Message Queue NCR TopEnd RPC Systems ANSA Sun ONC OSF/DCE Object-Oriented OMG/CORBA DCOM Java/RMI Distributed-Components J2EE .NET CCM
© 2003 Wolfgang Emmerich11 Remote Procedure Calls Enable procedure calls across host boundaries Call interfaces are defined using an Interface Definition Language (IDL) RPC compiler generates presentation and session layer implementation from IDL
© 2003 Wolfgang Emmerich Local vs. Remote Procedure Call CalledCalled Stub CallerCalledCalledCaller Caller Transport Layer (e.g. TCP or UDP)
© 2003 Wolfgang Emmerich13 IDL Example (Unix RPCs) const NL=64; struct Customer { struct DoB {int day; int month; int year;} struct DoB {int day; int month; int year;} string name ; string name ;}; program TRADERPROG { version TRADERVERSION { version TRADERVERSION { void PRINT(Customer)=0; void PRINT(Customer)=0; int STORE(Customer)=1; int STORE(Customer)=1; Customer LOAD(int)=2; Customer LOAD(int)=2; }= 0; }= 0; } = ;
© 2003 Wolfgang Emmerich14 Presentation Layer Resolve data heterogeneity Common data representation Transmission of data declaration Map complex data structures to network transport Static marshalling/unmarshalling Dynamic marshalling/unmarshalling
© 2003 Wolfgang Emmerich15 Marshalling and Unmarshalling Marshalling: Disassemble data structures into transmittable form Unmarshalling: Reassemble the complex data structure. char * marshal() { char * msg; msg=new char[4*(sizeof(int)+1) + strlen(name)+1]; sprintf(msg,"%d %d %d %d %s", dob.day,dob.month,dob.year, strlen(name),name); return(msg); }; void unmarshal(char * msg) { int name_len; sscanf(msg,"%d %d %d %d ", &dob.day,&dob.month, &dob.year,&name_len); name = new char[name_len+1]; sscanf(msg,"%d %d %d %d %s", &dob.day,&dob.month, &dob.year,&name_len,name); };
© 2003 Wolfgang Emmerich16 Stubs Creating code for marshalling and unmarshalling is tedious and error-prone. Code can be generated fully automatically from interface definition. Code is embedded in stubs for client and server. Client stub represents server for client, Server stub represents client for serve. Stubs achieve type safety. Stubs also perform synchronization.
© 2003 Wolfgang Emmerich17 Type Safety How can we make sure that servers are able to perform operations requested by clients? actual parameters provided by clients match the expected parameters of the server? results provided by the server match the expectations of client? Middleware acts as mediator between client and server to ensure type safety. Achieved by interface definition in an agreed language.
© 2003 Wolfgang Emmerich18 Interface Definition Facilitating Type Safety Server Client Request Reply
© 2003 Wolfgang Emmerich19 Synchronization What should client do while server executes Wait? Not care? Proceed concurrently and re-synchronise later? What should server do if clients request operations concurrently Process them sequentially? Process them concurrently? Each of these reasonable Most supported by middleware primitives
© 2003 Wolfgang Emmerich20 Outline Distributed Systems Middleware Advanced Communication in Object and Component Middleware Design Issues for Distributed Objects and Components Design Validation using Model Checking Related Work Conclusions
© 2003 Wolfgang Emmerich21 Policies & Primitives Mainstream object middleware provides few primitives and policies Threading Policies (Server-side): Single Threaded Multi Threaded Synchronization Primitives (Client-side): Synchronous Requests Deferred Synchronous Requests One-way Requests Asynchronous Requests
© 2003 Wolfgang Emmerich22 Server-side threading policies Multiple client objects can request operations from servers concurrently What to do? Options: Queue requests and process them sequentially Start new concurrent threads for every request Use a thread-pool and assign a thread to each new request To relieve programmer of server object: Server-side threading implemented in object adapters POA in CORBA SCM in COM EJB Container in J2EE
© 2003 Wolfgang Emmerich One standardised interface One interface per object operation ORB-dependent interface One interface per object adapter Dynamic Invocation Client Stubs ORB Interface Implementation Skeletons Client Object Implementation ORB Core POA CORBA Architecture
© 2003 Wolfgang Emmerich24 POA Threading Policies Single-threaded: Use when object implementations are not thread safe Default threading policy in CORBA ORB-controlled: Threads to execute object implementations are started, managed and stopped by the ORB Programmer has to be aware that implementations will be called concurrently and make them thread safe (e.g. for stateful objects) Unspecified how ORB implements thread management.
© 2003 Wolfgang Emmerich25 Client-side Synchronisation Primitives Overview Synchronous (Rendevous): Client-blocked until server finished execution of requested operation Oneway: Client continues after request taken by middleware, no synchronisation happens at all Deferred synchronous: Client continues after request taken by middleware, client polls for result Asynchronous: Client continues after request taken by middleware and server informs about the result
© 2003 Wolfgang Emmerich26 Request Synchronization Synchronous requests might block clients unnecessarily. Examples: User Interface Components Concurrent Requests from different servers OO-Middleware default: synchronous requests. :Server :Client Op()
© 2003 Wolfgang Emmerich27 Oneway Requests Return control to client as soon as request has been taken by middleware Client and server are not synchronized Use if Server does not produce a result Failures of operation can be ignored by client :Server :Client oneway()
© 2003 Wolfgang Emmerich28 Oneway using Java Threads class PrintSquad { static void main(String[] args) { static void main(String[] args) { Team team; Team team; Date date; Date date; // initializations of team and date omitted... // initializations of team and date omitted... OnewayReqPrintSquad a=new OnewayReqPrintSquad(team,date); OnewayReqPrintSquad a=new OnewayReqPrintSquad(team,date); a.start(); a.start(); // continue to do work while request thread is blocked... // continue to do work while request thread is blocked... }} // thread that invokes remote method class OnewayReqPrintSquad extends Thread { Team team; Team team; Date date; Date date; OnewayReqPrintSquad(Team t, Date d) { OnewayReqPrintSquad(Team t, Date d) { team=t; date=d; team=t; date=d; } public void run() { public void run() { team.print(date); // call remote method and then die team.print(date); // call remote method and then die }}
© 2003 Wolfgang Emmerich29 Oneway requests in CORBA Declared statically in the interface definition of the server object IDL compiler validates that operation has a void return type does not have any out or inout parameters does not raise type specific exceptions Example: interface Team { oneway void mail_timetable(in string tt); oneway void mail_timetable(in string tt); }; };
© 2003 Wolfgang Emmerich30 r:Request:Server:Client send() r=create_request() delete() Oneway requests in CORBA If oneway declarations cannot be used: Use dynamic invocation interface Op()
© 2003 Wolfgang Emmerich31 :Server :Client:Request Deferred Synchronous Requests Return control to client as soon as request has been taken by middleware Client initiates synchronization Use if Requests take long time Client should not be blocked Clients can bear overhead of synchronization send() op() get_result()
© 2003 Wolfgang Emmerich32 Deferred Synchronous Requests with Threads class PrintSquad { public void print(Team t, Date d) { public void print(Team t, Date d) { DefSyncReqPrintSquad a=new DefSyncReqPrintSquad(t,d); DefSyncReqPrintSquad a=new DefSyncReqPrintSquad(t,d); // do something else here. // do something else here. a.join(this); // wait for request thread to die. a.join(this); // wait for request thread to die. System.out.println(a.getResult()); //get result and print System.out.println(a.getResult()); //get result and print }} // thread that invokes remote method class DefSyncReqPrintSquad extends Thread { String s; String s; Team team; Team team; Date date; Date date; DefSyncReqPrintSquad(Team t, Date d) {team=t; date=d;} DefSyncReqPrintSquad(Team t, Date d) {team=t; date=d;} public String getResult() {return s;} public String getResult() {return s;} public void run() { public void run() { String s; String s; s=team.asString(date);// call remote method and die s=team.asString(date);// call remote method and die }}
© 2003 Wolfgang Emmerich33 CORBA Deferred Synchronous Requests Determined at run-time with using DII By invoking send() from a Request object And using get_response() to obtain result :Server :Client r:Request op() get_response() r=create_request(“op”) send()
© 2003 Wolfgang Emmerich34 Asynchronous Requests Return control to client as soon as request has been taken by middleware Server initiates synchronization Use if Requests take long time Client should not be blocked Server can bear overhead of synchronization :Server :Client op()
© 2003 Wolfgang Emmerich35 Asynchronous Requests with Threads Client has interface for callback Perform request in a newly created thread Client continues in main thread New thread is blocked Requested operation invokes callback to pass result New thread dies when request is complete
© 2003 Wolfgang Emmerich36 Asynchronous Requests with Threads interface Callback { public void result(String s); public void result(String s);} class PrintSquad implements Callback { public void Print(Team team, Date date){ public void Print(Team team, Date date){ A=new AsyncReqPrintSquad(team,date,this); A=new AsyncReqPrintSquad(team,date,this); A.start(); // and then do something else A.start(); // and then do something else } public void result(String s){ public void result(String s){ System.out.print(s); System.out.print(s); }} class AsyncReqPrintSquad extends Thread { Team team; Date date; Callback call; Team team; Date date; Callback call; AsyncReqPrintSquad(Team t, Date d, Callback c) { AsyncReqPrintSquad(Team t, Date d, Callback c) { team=t;date=d;call=c; team=t;date=d;call=c; } public void run() { public void run() { String s=team.AsString(date); String s=team.AsString(date); call.result(s); call.result(s); }}
© 2003 Wolfgang Emmerich37 Asynchronous Requests using Message Passing Message passing is starting to be provided by object- and component-oriented middleware Microsoft Message Queue CORBA Notification Service Java Messaging Service Request and reply explicitly as messages Asynchronous requests can be achieved using two message queues
© 2003 Wolfgang Emmerich38 Asynchronous Requests using Message Queues ClientServer Request Queue Reply Queue enter remove enter
© 2003 Wolfgang Emmerich39 Difference between Threading and MQs Threads Communication is immediate Do not achieve guaranteed delivery of request Can be achieved using language/OS primitives Message Queues Buffer Request and Reply messages Persistent storage may achieve guaranteed delivery Imply additional licensing costs for Messaging
© 2003 Wolfgang Emmerich40 Outline Distributed Systems Middleware Advanced Communication in Object and Component Middleware Design Problems for Distributed Objects and Components Design Validation using Model Checking Related Work Conclusions
© 2003 Wolfgang Emmerich41 Design Problems Client and server objects execute concurrently (or even in parallel when residing on different machines) This concurrency gives raise to the usual problems: Deadlocks Safety Property violations Liveness
© 2003 Wolfgang Emmerich42 Deadlock Example
© 2003 Wolfgang Emmerich43 Safety Properties Notifications of new price are sent only in response to trade update Only traders that have subscribed for notifications will receive them Equity server cannot accept new trade unless notification of previous trade is complete
© 2003 Wolfgang Emmerich44 Liveness Properties It is always the case that the EquityServer will eventually be able to accept a trade Traders will always be able to eventually enter a new trade
© 2003 Wolfgang Emmerich45 Outline Distributed Systems Middleware Advanced Communication in Object and Component Middleware Design Issues for Distributed Objects and Components Design Validation using Model Checking Related Work Conclusions
© 2003 Wolfgang Emmerich46 Motivations & Challenges Confront complexities by offering developers design aid Complement existing Software Engineering validation and verification techniques Only expose designers to the UML notation they are likely to be familiar with Solution not dependent on any specific semantic notation Build on existing tools and notations
© 2003 Wolfgang Emmerich47 Approach Exploit the fact that object and component middleware provide only few primitives for synchronization of distributed objects Representation of these primitives as stereotypes in UML models Formal specification of stereotype semantics Model checking of UML models against given safety and liveness properties
© 2003 Wolfgang Emmerich48 Approach Overview Stereotype UML Class & Statechart diagrams + props. Process Algebra Generation Model Checking Results – UML Sequence diagrams Design Domain Verification Domain
© 2003 Wolfgang Emmerich49 Policies & Primitives Mainstream object middleware provides few primitives and policies Synchronization Primitives (Client-side): Synchronous Requests Deferred Synchronous Requests One-way Requests Asynchronous Requests Threading Policies (Server-side): Single Threaded Multi Threaded
© 2003 Wolfgang Emmerich50 Stereotype UML Class & Statechart diagrams + props Approach Overview Process Algebra Generation Model Checking Results – UML Sequence diagrams Developer Domain Verification Domain
© 2003 Wolfgang Emmerich51 Trading Class Diagram Trader receiveServerUpdates() > NotificationServer receiveEquityData() addTrader() removeTrader() > EquityServer receiveTraderUpdate() > notifier controller myEquityServer traders myUpdateServer traders
© 2003 Wolfgang Emmerich52 Notification Server Statechart idle sending addTrader removeTrader preparing data receiveEquityData reply traders.receiveServerUpdates() > finishedsendout
© 2003 Wolfgang Emmerich53 Equity Server Statechart idle update updates completed notifier.receiveEquityData() > receiveTraderUpdate reply
© 2003 Wolfgang Emmerich54 Object Diagram equityServer1:EquityServer trader1:Trader trader2:Trader notifier1:NotificationServer trader3:Trader Used to depict run-time configuration of the system
© 2003 Wolfgang Emmerich55 User-defined properties Designers must specify properties that the modelled system must adhere to Enforce restriction on parallel execution of state diagram models Safety Nothing bad happens during execution Deadlock, event ordering Liveness Something good eventually happens Eventual termination
© 2003 Wolfgang Emmerich56 Safety Property 1 2 NotificationServer.receiveEquityData 0 EquityServer.receiveTraderUpdate Specifies action ordering across the three state diagrams Trader.receiveServerUpdates
© 2003 Wolfgang Emmerich57 Safety Property 1 2 EquityServer.receiveTraderUpdate 0 {trader1, trader2}.enterNewTrade {notifier1}. traders.receiveServerUpdates Specify property over instances shown in the object diagram
© 2003 Wolfgang Emmerich58 Liveness Property Trader > receiveServerUpdates() > NotificationServer > receiveEquityData() addTrader() removeTrader() > EquityServer > receiveTraderUpdate() > notifier controller myEquityServer traders myUpdateServer traders Progress evaluates to the temporal logic property of “always eventually”
© 2003 Wolfgang Emmerich59 Process Algebra Generation Stereotype UML Class & Statechart diagrams + props Approach Overview Model Checking Results – UML Sequence diagrams Developer Domain Verification Domain
© 2003 Wolfgang Emmerich60 Process Algebra Generation Use Finite State Process algebra (Magee & Kramer 99) to model object synchronisation Finite number of synchronization primitives and activation policies Define FSP fragments for all primitive/policy combinations Compose FSP fragments along the combination of client/server primitives and the object diagram Define fragments and composition in OCL.
© 2003 Wolfgang Emmerich61 > Process Algebra Generation Equity Server StatechartTrading Class Diagram idle update updates completed notifier.receiveEquityData() > receiveTraderUpdate reply NotificationServer EquityServer > notifier controller Combination of single threaded server and synchronous invocation detected
© 2003 Wolfgang Emmerich62 Application FSP Specification EQUITYSERVER=(startserver->Idle), Idle=(receivetraderupdate->Update), Update=(notifier.receiveequitydata->receiveInvocationReply ->Updatescompleted), Updatescompleted=(reply->Idle). NOTIFICATIONSERVER=(startnotificationserver->Idle), Idle=(receiveequitydata->Preparingdata | addtrader->Idle | removetrader->Idle), Preparingdata=(reply->Sending), Sending=(traders.receiveserverupdates->receiveInvocationReply ->Sending | finishedsendout->Idle). ||TRADING_SYSTEM = (notifier1:NOTIFICATIONSERVER || equityserver1:EQUITYSERVER || notificationserverOA:NOTIFIER_OA ) /{ equityserver1.notifier.receiveequitydata / notificationserverOA.receiveRequest, equityserver1.receiveInvocationReply / notificationserverOA.relayReply, notifier1.receiveequitydata / notificationserverOA.relayRequest, notifier1.reply / notificationserverOA.receiveReply }. NOTIFIER_OA =(receiveRequest->relayRequest->receiveReply->relayReply->NOTIFIER_OA).
© 2003 Wolfgang Emmerich63 User-defined Property FSP Specification Safety: property SFY_1= ({trader1,trader2}.equityServer1.receivetraderupdate->S1), S1= ({equityServer1}.notifier1.receiveequitydata->S2), S2= ( {notifier1}.trader1.receiveserverupdates->SFY_1 | {notifier1}.trader2.receiveserverupdates->SFY_1). Liveness: progress EQUITYSERVER_PRG={ trader1.equityServer1.receivetraderupdate, trader2.equityServer1.receivetraderupdate} progress NOTIFICSERVER_PRG ={equityServer1.notifier1.receiveequitydata } progress TRADER_PRG = {notifier1.trader1.receiveserverupdates, notifier1.trader2.receiveserverupdates }
© 2003 Wolfgang Emmerich64 Process Algebra Generation Stereotype UML Class & Statechart diagrams + props Approach Overview Model Checking Generate UML Sequence diagrams for results Developer Domain Verification Domain
© 2003 Wolfgang Emmerich65 Model Checking Generate a Labelled Transition System from the input process algebra Carry out an exhaustive search in state space of the underlying LTS for action traces leading to property violations In case of violation, produce an action trace Trace is used to construct a UML sequence diagram to show scenario leading to the property violation For liveness violations the sequence diagram depicts the trace to the terminal set
© 2003 Wolfgang Emmerich66 Context aware minimization Model checking suffers from the state explosion problem Optimisation is achieved by: Only modelling the synchronization behaviour of a middleware application Building a state space of transitions in state diagrams that only correspond to remote requests TraderOA Trader
© 2003 Wolfgang Emmerich67 Process Algebra Generation Stereotyped UML Class & Statechart diagrams + props Approach Overview Model Checking Results – UML Sequence diagrams Developer Domain Verification Domain
© 2003 Wolfgang Emmerich68 Relating Results Model Checker produces trace in LTS, e.g.: Trace to DEADLOCK: trader1.equityServer1.receivetraderupdate trader1.equityServer1.receivetraderupdate equityServer1.receivetraderupdate equityServer1.receivetraderupdate equityServer1.notifier1.receiveequitydata equityServer1.notifier1.receiveequitydata notifier1.receiveequitydata notifier1.receiveequitydata notifier1.trader1.receiveserverupdate notifier1.trader1.receiveserverupdate trader1.receiveserverupdate trader1.receiveserverupdate trader1.receiveserverupdates_reply trader1.receiveserverupdates_reply notifier1.receiveequitydata_reply notifier1.receiveequitydata_reply equityServer1.receivetraderupdate_reply equityServer1.receivetraderupdate_reply trader1.equityServer1.receivetraderupdate trader1.equityServer1.receivetraderupdate equityServer1.receivetraderupdate equityServer1.receivetraderupdate notifier1.trader1.receiveserverupdate notifier1.trader1.receiveserverupdate equityServer1.notifier1.receiveequitydata equityServer1.notifier1.receiveequitydata trader2.equityServer1.receivetraderupdate trader2.equityServer1.receivetraderupdate
© 2003 Wolfgang Emmerich69 Relating Results More meaningful in UML notation trader1: Trader equityServer1: EquityServer notifier1 : NotificationServer receiveTraderUpdate receiveEquityData receiveServerUpdates receiveTraderUpdate receiveServerUpdates receiveEquityData
© 2003 Wolfgang Emmerich70 Tool Support: Architecture
© 2003 Wolfgang Emmerich71 Tool Support: Design
© 2003 Wolfgang Emmerich72 equityServer1:EquityServer trader1:Trader trader2:Trader notifier1:NotificationServer tradern:Trader … Evaluation: Experiment How many concurrent objects can we support Vary number of traders in architecture below
© 2003 Wolfgang Emmerich73 Evaluation: State Space
© 2003 Wolfgang Emmerich74 Outline Distributed Systems Middleware Advanced Communication in Object and Component Middleware Design Issues for Distributed Objects and Components Design Validation using Model Checking Related Work Conclusions
© 2003 Wolfgang Emmerich75 Some Related Work Cheung & Kramer, Checking Safety Properties using Compositional Reachability Analysis, TOSEM 8(1) Inverardi et al Automated Checking of Architectural Models using SPIN, ASE McUmber & Cheung, A general Framework for formalizing UML with Formal Languages. ICSE 2001.
© 2003 Wolfgang Emmerich76 Outline Distributed Systems Middleware Advanced Communication in Object and Component Middleware Design Issues for Distributed Objects and Components Design Validation using Model Checking Related Work Conclusions
© 2003 Wolfgang Emmerich77 Conclusions Detect synchronisation problems in oo- middleware systems at design Define semantics for client/server communication primitives Use model checking to detect potential execution traces that leading to property violations Confine designers to a pure UML interaction only Introduce no new notations
© 2003 Wolfgang Emmerich78 Future Work Investigate heuristic approaches such as pattern detection in the UML design diagrams Carry out an industrial case study to analyse the scalability and feasibility of our approach Provide semantic mapping to the Promela (SPIN), to demonstrate the general applicability of our concepts