Title: Systems Supporting Distributed Collaboration
1Systems Supporting Distributed Collaboration
Prasun Dewan
Department of Computer Science University of
North Carolina CB 3175 Sitterson Hall Chapel
Hill, NC 27599-3175 dewan_at_cs.unc.edu http/www.c
s.unc.edu/dewan
2Definition
- Oxford Work jointly esp at literary or artistic
production - Malone helps people work together more
effectively - Lynch et al makes users aware they are part of a
group - Wells software and hardware for shared
interactive environment - Ellis supports groups engaged in a common task
and provides an interface to shared environment - Peter Johnson-Lenz computer-mediated culture,
intentional group processes plus supporting
software - Johansen specialized computer aids for
collaborative work groups - Winograd state of mind
3Definition
Collaborative Application
- Same output?
- Symmetric?
- N-User?
I/O
I/O
Coupling
User 2
User 1
Potentially Real-Time
4Traditional Collaborative Applications
File
Mail
Talk
5Benefits Towards Being There
Face-to-Face
Interaction
Computer-Supported
Interaction
Network
6Gesture Cam Remote Surrogate
7Benefits Beyond Being There
Face-to-Face
Hollan Stornetta 92
Interaction
Computer-Supported
Interaction
Network
8Action Workflow
Status By Candidate Workflow Step
Manage Review
Manager
Director
9Combining Both Goals?
- IM
- Feel transported to a common abstract world
- Can specify mood
- Collaborative nanoManipulator
10(No Transcript)
11Collaboration vs. Virtual Environments
VE
12Collaboration vs. Real-Time Distributed Apps.
Collaborative Applications
13Collaboration vs. Mobile Apps.
Mobile Applications
Collaborative Applications
14Relationship with Object-Oriented and User
Interface- Technology
Interactive Applications
O-O Applications
15Traditional System Aspects
Applications
Shared Screen
FC vs. CC
Interoperability
Extensibility/Composability
Applications
Telepointer Jitter
Performance/Resource Management
Functionality/Abstraction
Coupling
System Support
16Views of Collaboration Systems
- Ensure actual needs met.
- Conceptual depth, avoid duplication.
- Build on existing knowledge.
- See integrated sets of features
- Problems
- Issues
- Disciplines
- Systems
- Applications and Infrastructures
17Problems Application Areas
- Business Management
- National Collaboratory
- Software Engineering
- Engineering/Design
- Writing
- Decision making, business processes, monitor
state. - Connected labs.
- Team development, pair programming
- Just in time VR-based
- Distributed co-authoring.
18Problems Application Areas
- Education
-
- Medicine
- Air Traffic Control
- Command and Control
- Games/Casual Interaction
- Any complex task!
- Distance presentation, remote lab., colab
projects - Remote consult, workflow
- Coordinate controllers
- Coordination
- Sharing of information/actions
- Is collaborative
19Generic Tasks
- Social Interaction
- Information Exchange
- Presentation
- Consulting
- Comment/Discuss
- Compose Artifact
20Generic Tasks Product Life Cycle
- Design
- Implementation
- Debugging/Testing
- Inspection/Review
21Specific Experimental Tasks
- Annotate/discuss research article/software
specs/video - Present lecture to remote and local audience
- Rank job candidates
- Choose videos to rent, take on road trip
- Get status report on action items and feedback
from each participant - Choose name for new game
- Search for shopping list online
22Views of Collaboration Systems
- Problems
- Issues
- Disciplines
- Systems Applications and Infrastructures
23Issues Semantics
- Session Management How do distributed users
create, destroy, join, and leave collaborative
sessions? - Single-User Interface What are the application
semantics if there is a single user in the
session? - Coupling what feedback does a user receive in
response to the input of another user? - Access Control How do we ensure that users do
not execute unauthorized commands? - Concurrency Control How do we ensure that
concurrent users do not enter inconsistent
commands?
24Issues Semantics (Contd.)
- Process Control How do we ensure that users
follow prescribed group processes? - Merging How do we merge concurrent commands
entered by different users? - Undo/Redo What are the semantics of undo/redo
in a collaborative session? - Awareness How are users made aware of out of
band'' activities of their collaborator?
25Issues Implementation
- Objects What kind of objects are composed in a
collaborative application? - Collaboration Awareness Which of these objects
are collaboration aware and how are these objects
integrated with existing, collaboration-unaware
objects? - Layers How are these objects arranged in
layers? - Concurrency How is the application decomposed
into concurrent threads? - Distribution How are the application objects
placed in different address spaces and hosts?
26Issues Implementation (Contd.)
- Replication/Migration Which of these objects
are centralized and which are replicated? Which
of the centralized objects can migrate? - Display Consistency How to ensure actions are
executed in the same order on computers that
share them? - Real-Time Support What kind of services are
provided to ensure real-time interaction with
tolerable jitter and latency?
27Views of Collaboration Systems
- Problems
- Issues
- Disciplines
- Systems Applications and Infrastructures
28Computer Science Disciplines
- Operating Systems
- Database Management Systems
- Programming Languages
- User Interface Systems
- Software Engineering
- Distributed file, memory, scheduling, OS-based
IM - Concurrency Control, Recovery
- Shared object constructs
- I/O distribution of window systems, toolkits
- Application area, process control, patterns
29Views of Collaboration Systems
- Problems
- Issues
- Disciplines
- Systems Applications and Infrastructures
30Systems Applications
- RTCALendering
- Cognoter whiteboard
- CES (Transaction-based Collaborative Editing
System) - Grove Outline Editor
- Information Lens Typed Email
- Coordinator Speech-Act Workflow
- Quilt Editor Annotations
- IBIS Discussions
- Video Walls
- Hydra
- GroupDraw optimistic CC
- PREP Diff-based Editor
- MUDs (Multiuser Dungeons)
- DIVE (Distributed Interactive
- Virtual Environment)/ MASSIVE
- MIT (Sarin Greif)
- Xerox (Stefik et al)
- MIT (Liskov)
- MCC (Ellis)
- MIT (Malone )
- Stanford (Winograd 88)
- Bellcore (Leland)
- MCC (Ellis)
- Xerox (Abel)
- U. Toronto (Buxton)
- U. Calgary (Greenberg)
- CMU (Neuwirth)
- Xerox (Curtis)
- Sweden (Fahlen)/ Nottingham (Benford)
31Applications Products
- Groove Apps
- OneNote
- Spreadsheet
- Word Processor
- IM
- Microsoft
- Microsoft
- Google
- Google/Writely
- Everyone
32Systems Infrastructures
- NLS (Engelbart 68)
- Colab (Stefik 85)
- VConf (Lantz 86)
- Rapport (Ahuja 89)
- XTV (Abdel-Wahab, Jeffay Feit 91)
- Rendezvous (Patterson 90)
- Suite (Dewan Choudhary 92)
- TeamWorkstation (Ishii 92)
- Weasel (Graham 95)
- Habanero (Chabert et al 98)
- JCE (Abdel-Wahab 99)
- Disciple (Marsic 01)
- Sync (Munson Dewan 96)
- App-Sharer (Chung, Junuzovic, Dewan 06)
- Post Xerox
- Xerox
- Stanford
- Bell Labs
- UNC/ODU
- Bellcore
- Purdue
- Japan
- Queens
- U. Illinois
- ODU
- Rutgers
- UNC
33Infrastructure Products
- VNC (Li, Stafford-Fraser, Hopper 01)
- NetMeeting (MSFT)
- Groove (MSFT)
- Advanced Reality
- LiveMeeting -Pay by minute service model (MSFT)
- Webex (service model)
- MeetingPlace (Cisco)
- CollaborateNow (IBM)
34Multiple Views
Coupling
Cognoter
WYSIWIS Interaction
Database Transactions
NetMeeting
Software Engineering
Design
35Course Goals
- Study State-of-the-art
- Applications
- Shared Word, Browser
- Infrastructure
- Groove, Shared Objects
- Project
- Survey
- Writing
- Integrate with Survey Paper
- Programming
- Integrate with 243/Program Product
- Presentation
- Research
- Assignments
- Using applications and infrastructures
collaboratively
36Projects
- Infrastructure-based
- Application-/usage- based
- Something usable as this area is
- Practical (probably)
- Unexplored
- Build on top of existing infrastructure
- Sync
- Asynchronous and synchronous
- Application Sharer
- Synchronous existing and new applications
37Application-based
- Make familiar apps collaborative
- Microsoft Office
- Open Office
- Basics implemented
- Make it really work, efficiently
- Eclipse
- Jazz provides some asynchronous support
- Sangam some synchronous support
- Can provide semi-synchronous support
- Loosely coupled pair programming
- Probably remain a prototype
38Application-based
- Custom application for data shared through
Wikis/Google spreadsheet - Shared shopping list
- Recreation activities
- Organizing pot-luck parties (custom Evite)
- Departmental activities
- Organizing study groups
- Scheduling departmental picnics
- Signup sheet for demos in 242
- Creating groups in 790-063
39Application-based
- Teaching and TA Award
- Currently nominations requested and then some
magic happens. - Allow entry of data and voting and linking of
teaching evaluations and other data. - Departmental calendar
- Every week mail sent to coordinator by a certain
time. - Calendar emailed and updated by a central person.
- Make this distributed and allow people to enter
data way in advance. - Same with Systems Tea
40Application-based
- Qual scheduler
- Automatic did not work.
- Semi-automatic, collaborative.
- Students enter courses and time constraints
- Faculty members enter expertise and time
constraints - Schedulers form committees and assign times
based. - System checks qual constraints met.
- TA/RA Matcher
- Students and faculty enter preferences.
- Administrators can see all data.
- Students and faculty can see filtered data.
- E.g. one on one matches.
41Application-based
- Undergrad Advising
- filling a form.
- Looking up requirements
- Scheduling a meeting
- Some initial work done by a 145 team
42Infrastructure-based
- Shared layer
- VNC and NetMeeting share different user-interface
layers - Benefits of different sharing different layers.
- Can we dynamically change shared layer?
- Dynamic policies, performance model
- Work on application sharer
43Infrastructure-based
- Scheduling
- Feedback vs. Feedthrough processing
- Give sufficient time to both using proportional
scheduling. - Energy-aware collaboration
- Energy dissipation a function of amount and rate
of information communication - Can study and adjust the coupling (send summary
information in batches)
44Infrastructure-based
- Locking
- Many locking schemes
- Lock whole spreadsheet vs. individual cell.
- Provide one comprehensive mechanism.
- Partly designed but not implemented.
- Lock-free Consistency management
- Locking ensures displays are consistent no race
conditions. - Consistency without locks operation
transformation - Called optimistic CC misnomer
- For the mathematically inclined
45Infrastructure-based
- Context-specific presence
- Can synchronously monitor idle time.
- Can synchronously monitor every input in shared
apps. - Synchronously summarize application-specific
information - E.g. whose mail are you reading?
- Access control
- Needed because we collaborate
- But it is a pain
- Let us collaborate on setting access control.
- An implementation exists
- User studies
46Example collaborative application
47Example collaborative application
48Example collaborative application
49Example collaborative application
50Example collaborative application
51Implementation Alternatives
- Collaboration-unaware apps
- Screen/window (Application) sharing
- Based on existing UI architectures
- App sharing system is collaboration-aware
- ???
- Based on other, ideally popular architectures
- Maybe based on some other cola-aware
infrastructure - Collaboration-aware apps
- Based on some architecture or collaboration-aware
infrastructure
52Does App Sharing work?
Different Window Sizes, Data
53Implementation Alternatives
- Collaboration-unaware apps
- Screen/window (Application) sharing
- Based on existing UI architectures
- App sharing system is collaboration-aware
- ???
- Based on other, ideally popular architectures
- Maybe based on some other colab-aware
infrastructure - Collaboration-aware apps
- Based on some architecture or collaboration-aware
infrastructure
54Model, View and Controller (MVC)
View
Controller
Model
55Model, View and Controller (MVC)
Controller
View
Model
View
Controller
56Model Code
- public class ConcertExpense
- float unitCost 0
- int numberOfAttendees 0
- PropertyChangeSupport propertyChange
new PropertyChangeSupport(this) - public float getTicketPrice() return
unitCost - public void setTicketPrice(float newVal)
- if (newVal unitCost) return
- float oldVal unitCost int oldTotal
getTotal() - unitCost newVal
- propertyChange.firePropertyChange("ticket
Price", oldVal, newVal) - propertyChange.firePropertyChange("total"
, oldTotal, getTotal()) -
- public int getNumberOfAttendees()
return numberOfAttendees - public void setNumberOfAttendees(int
newVal) - if (numberOfAtendees newVal) return
- int oldVal numberOfAttendees int oldTotal
getTotal() - numberOfAttendees newVal
propertyChange.firePropertyChange("numberOfAttend
ees", oldVal, newVal) - propertyChange.firePropertyChange("total"
, oldTotal, getTotal()) -
57MVC Composition
- package main
- import budget.ConcertExpense
- import bus.uigen.ObjectEditor
- public class MVCBudget
- public static void main(String args)
- ConcertExpense model new ConcertExpense ()
- ObjectEditor.edit(model)
-
58Distributed MVC
Controller
View
Model
View
Controller
59DistributedModel Code
- public class ConcertExpense extends
UnicastRemoteObject implements Remote - float unitCost 0
- int numberOfAttendees 0
- RemotePropertyChangeSupport
propertyChange new RemotePropertyChangeSupport(t
his) - public float getTicketPrice() throws
RemoteException return unitCost - public void setTicketPrice(float newVal)
- unitCost newVal
- propertyChange.firePropertyChange("ticket
Price", null, newVal) - propertyChange.firePropertyChange("total"
, null, getTotal()) -
- public int getNumberOfAttendees() throws
RemoteException return numberOfAttendees - public void setNumberOfAttendees (int
newVal) throws RemoteException - numberOfAttendees newVal
- propertyChange.firePropertyChange("number
OfAttendees", null, newVal) - propertyChange.firePropertyChange("total"
, null, getTotal()) -
- public float getTotal() throws
RemoteException return unitCostnumberOfAttendees
- public void addRemotePropertyChangeListene
r(RemotePropertyChangeListener l) throws
RemoteException - propertyChange.addRemotePropertyChange
Listener(l)
Distribution-Aware
60Notification
- public interface PropertyChangeListener
- public void propertyChange(PropertyChangeEve
nt evt)
Does not extend Remote
61Remote Notification
package util import java.beans.PropertyChangeEven
t import java.rmi.Remote import
java.rmi.RemoteException public interface
RemotePropertyChangeListener extends Remote
public void remotePropertyChange(PropertyChange
Event evt) throws RemoteException
62Registering a Model
- import java.rmi.Naming
- public class AConcertExpenseRegisterer
- public final static String RMI_PORT 1099
// default port for RMI service - public final static MODEL_NAME
myDemoBudget - public static void main (String args)
- try
- String host_name
- java.net.InetAddress.getLocalHost().getCanonica
lHostName() - ConcertExpense model new ConcertExpense()
- String budgetName "//" host_name ""
RMI_PORT "/" MODEL_NAME - Naming.rebind(budget_name, model)
- catch (Exception e)
- e.printStackTrace()
-
63Looking up a Model
- import java.rmi.Naming
- import bus.uigen.ObjectEditor
- public class AConcertExpenseComposer
- final static String REMOTE_HOST
dewan-cs.cs.unc.edu - final static FULL_MODEL_NAME //"
REMOTE_HOST "" AConcerExpenseRegisterer.RM
I_PORT "/" AConcertExpenseRegisterer.MODEL_
NAME - public static void main (String args)
- try
- ConcertExpense model (ConcertExpense)
Naming.lookup(MODEL_NAME) - // connect to generic model and view
- ObjectEditor.edit(model)
- catch (Exception e)
- e.printStackTrace()
-
64Compile Runtime steps
- Compile steps
- rmic budget.ConcertExpense
- Runtime steps
- Start rmi service
- set CLASSPATHltmodel, stubs, skel directorygt
- rmiregistry 1099
- Start registerer
- Start composer at each users workstation
65Screen Sharing vs. MVC Sharing
Data convergence after each user command
WYSIWIS
66Transactions/Disconnection
67Transactions/Disconnection
68Concurrent Transactions
69Concurrent Transactions
70Concurrent Transactions
71Concurrent Transactions
72Concurrent Transactions
73Concurrent Transactions
74Concurrent Transactions
75Conflicting Transactions
76Conflicting Transactions
77Conflicting Transactions
78Conflicting Transactions
79Overriding Transactions
80Overriding Transactions
81Private Data
82Minimum Goals
- Model and not View Sharing
- Logical Disconnection
- Asynchronous Connected Transactions
- Disconnected Transactions
- Conflict resolution
- Awareness of collaborators
- Private Data
83Distributed MVC
Controller
View
Model
View
Controller
84Replicated MVC
Controller
View
Model
Model-View Communication same as Model-Model
Communication?
Model
View
Controller
85Distributed MVC
Controller
View
Model
- Equivalent to Centralized
- Performance difference
- May change dynamically
View
Controller
86Replicated MVC
Controller
View
Model
Both users create replicas?
Model
View
Controller
87Disconnected Interaction
Controller
View
Model
88Need Replicating Infrastructure
Controller
View
Model
Binds to Local (Possibly Different)
View/Controller
Serializes Model
Infrastructure
89Need Replicating Infrastructure
Controller
View
Model
Client Part
Server Part
90Original Model Code
- public class ConcertExpense
- float unitCost 0
- int numberOfAttendees 0
- PropertyChangeSupport propertyChange
new PropertyChangeSupport(this) - public float getTicketPrice() return
unitCost - public void setTicketPrice(float newVal)
- if (newVal unitCost) return
- float oldVal unitCost int oldTotal
getTotal() - unitCost newVal
- propertyChange.firePropertyChange("ticket
Price", oldVal, newVal) - propertyChange.firePropertyChange("total"
, oldTotal, getTotal()) -
- public int getNumberOfAttendees()
return numberOfAttendees - public void setNumberOfAttendees(int
newVal) - if (numberOfAtendees newVal) return
- int oldVal numberOfAttendees int oldTotal
getTotal() - numberOfAttendees newVal
propertyChange.firePropertyChange("numberOfAttend
ees", oldVal, newVal) - propertyChange.firePropertyChange("total"
, oldTotal, getTotal()) -
Requires use of standard notification mechanism
so local infrastructure can listen
91Replicated Model Code
- public class ConcertExpense implements
Serializable - float unitCost 0
- int numberOfAttendees 0
- transient PropertyChangeSupport
propertyChange new PropertyChangeSupport(this)
- public float getTicketPrice() return
unitCost - public void setTicketPrice(float newVal)
- if (newVal unitCost) return
- float oldVal unitCost int oldTotal
getTotal() - unitCost newVal
- propertyChange.firePropertyChange("ticket
Price", null, newVal) - propertyChange.firePropertyChange("total"
, null, getTotal()) -
- public int getNumberOfAttendees()
return numberOfAttendees - public void setNumberOfAttendees(int
newVal) - if (numberOfAtendees newVal) return
- int oldVal numberOfAttendees int oldTotal
getTotal() - numberOfAttendees newVal
- propertyChange.firePropertyChange("number
OfAttendees", null, newVal) - propertyChange.firePropertyChange("total"
, null, getTotal())
Transient variables null in serialized object
No cycles should be created by non-transient
links
92Replicated Model Code
- public class ConcertExpense implements
Serializable - float unitCost 0
- int numberOfAttendees 0
- transient PropertyChangeSupport
propertyChange new PropertyChangeSupport(this)
- public float getTicketPrice() return
unitCost - public void setTicketPrice(float newVal)
- if (newVal unitCost) return
- float oldVal unitCost int oldTotal
getTotal() - unitCost newVal
- propertyChange.firePropertyChange("ticket
Price", null, newVal) - propertyChange.firePropertyChange("total"
, null, getTotal()) -
- public int getNumberOfAttendees()
return numberOfAttendees - public void setNumberOfAttendees(int
newVal) - if (numberOfAtendees newVal) return
- int oldVal numberOfAttendees int oldTotal
getTotal() - numberOfAttendees newVal
- propertyChange.firePropertyChange("number
OfAttendees", null, newVal) - propertyChange.firePropertyChange("total"
, null, getTotal())
Method with well known signature called by
Infrastructure on serialized object
93Fine-Grained Merging
- Objects are encapsulated.
- How to break state into units
- To read incremental state
- Set incremental state
- Serializing copies complete object
- Use Bean Programming Patterns and Property
Notifications
94MVC Composition
- package main
- import budget.ConcertExpense
- import bus.uigen.ObjectEditor
- public class MVCBudget
- public static void main(String args)
- ConcertExpense model new ConcertExpense ()
- ObjectEditor.edit(model)
-
95Registering and composing
- package main
- import budget.ConcertExpense
- import edu.unc.sync.Sync
- public class SyncBudgetCreator
- public static String SERVER_NAME
"dewan-cs.cs.unc.edu/A" - public static String MODEL_NAME "demoBudget"
- public static String CLIENT_ID "alice"
- public static void main(String args)
- ConcertExpense model new ConcertExpense ()
- Sync.replicate (SERVER_NAME,
- MODEL_NAME,
- model,
- CLIENT_ID)
- ObjectEditor.edit(model)
-
96Looking up and composing
Special program needed for creator
- package main
- import budget.ConcertExpense
- import edu.unc.sync.Sync
- import edu.unc.sync.server.SyncClient
- import edu.unc.sync.server.ServerProxy
- public class SyncBudgetUser
- static String CLIENT_ID bob"
- public static void main(String args)
- SyncClient client Sync.open
(SyncBudgetCreator.SERVER_NAME, - SyncBudgetAlice.MODEL_NAME,
- CLIENT_ID)
- ServerProxy server client.getServerProxy(SyncB
udgetCreator.SERVER_NAME) - ConcertExpense model (ConcertExpense)
server.getModel - (SyncBudgetCreator.MODEL_NAME)
- ObjectEditor.edit(model)
-
97Symmetric Programs
- System can create new model only if it does not
exist. - It can be given model class instead of model
instance
98Maybe Registering and composing
- package main
- import budget.ConcertExpense
- import edu.unc.sync.Sync
- import edu.unc.sync.SyncClient
- import edu.unc.sync.SyncProxy
- public class SyncBudget
- public static String SERVER_NAME
"dewan-cs.cs.unc.edu/A" - public static String MODEL_NAME "demoBudget"
- public static Class MODEL_CLASS
ConcertExpense.class - public static void main(String args)
- SyncClient client Sync.replicate
(SERVER_NAME, MODEL_NAME, - MODEL_CLASS, args0)
- ServerProxy server client.getServerProxy(SERVE
R_NAME) - ConcertExpense model (ConcertExpense)
server.getModel (MODEL_NAME) - ObjectEditor.edit(model)
-
99Infrastructure-defined Model-View Interface
- If Infrastructure defines model-view interface
- It can create model and view
- It can compose them
100Automatic Creation of MVC Structure
- package main
- import budget.ConcertExpense
- import edu.unc.sync.SyncObjectEditor
- import edu.unc.sync.Sync
- public class SyncBudget
- public static String SERVER_NAME
"dewan-cs.cs.unc.edu/A" - public static String MODEL_NAME "demoBudget"
- public static Class MODEL_CLASS
ConcertExpense.class - public static Class EDITOR_CLASS
SyncObjectEditor.class - public static void main(String args)
- Sync.replicate (SERVER_NAME, MODEL_NAME,
-
MODEL_CLASS, EDITOR_CLASS, args0) -
-
Can execute this interactively!
101View Interfaces
- package edu.unc.sync.server
- import edu.unc.sync.Replicated
- public interface SyncApplication
- public void init(Object invoker) // invoker
is sync client or server - public void addObject(Replicated object,
String name) // replicated is what model gets
converted to - public void addObject(Object object, String
name) - public void doRefresh() // Sync calls this
whenever it updates model in case app does not
listen to events -
102Automatic Creation of MVC Structure
- package main
- import budget.ConcertExpense
- import edu.unc.sync.SyncObjectEditor
- import edu.unc.sync.Sync
- public class SyncBudget
- public static String SERVER_NAME
"dewan-cs.cs.unc.edu/A" - public static String MODEL_NAME "demoBudget"
- public static Class MODEL_CLASS
ConcertExpense.class - public static Class EDITOR_CLASS
SyncObjectEditor.class - public static void main(String args)
- Sync.replicate (SERVER_NAME, MODEL_NAME,
-
MODEL_CLASS, EDITOR_CLASS, args0) -
-
Constructors with parameters?
103Constructors with Parameters
- Dont have them
- Use init method.
- Application knows what parameters to give.
- Infrastructure knows when and if to create
instance. - Application gives factory.
- For any model or editor class
104Automatic Creation of MVC Structure
- package main
- import budget.ConcertExpense
- import edu.unc.sync.SyncObjectEditor
- import edu.unc.sync.Sync
- public class SyncBudget
- public static String SERVER_NAME
"dewan-cs.cs.unc.edu/A" - public static String MODEL_NAME "demoBudget"
- public static Class MODEL_CLASS
ConcertExpense.class - public static Class EDITOR_CLASS
SyncObjectEditor.class - public static void main(String args)
- Sync.register(ConcertExpense.class, new
ConcertExpenseFactory()) - Sync.replicate (SERVER_NAME, MODEL_NAME,
-
MODEL_CLASS, EDITOR_CLASS, args0) -
-
105Factory Interfaces
package edu.unc.sync public interface
ObjectFactory public Object newInstance(Class
c)
- import budget.ConcertExpense
- import edu.unc.sync.ObjectFactory
- public class ConcertExpenseFactory implements
ObjectFactory - public Object newInstance (Class c)
- return new ConcertExpense()
-
106Multiple Models
- package main
- import budget.ConcertExpense
- import edu.unc.sync.SyncObjectEditor
- import edu.unc.sync.Sync
- import edu.unc.sync.SyncClient
- import edu.unc.sync.SyncProxy
- public class SyncBudget
- public static String SERVER_NAME
"dewan-cs.cs.unc.edu/A" - public static String MODEL_NAME "demoBudget"
- public static String MODEL_NAME_2
"demoBudget2" - public static Class MODEL_CLASS
ConcertExpense.class - public static Class EDITOR_CLASS
SyncObjectEditor.class - public static void main(String args)
- SyncClient client Sync.replicate
(SERVER_NAME, MODEL_NAME, -
MODEL_CLASS, EDITOR_CLASS, args0) - ServerProxy server client.getServerProxy(SERVE
R_NAME) - server.newObject(MODEL_NAME_2,
ConcertExpense.class, EDITOR_CLASS) -
-
107Replicated Model Code
- public class ConcertExpense implements
Serializable - float unitCost 0
- int numberOfAttendees 0
- transient PropertyChangeSupport
propertyChange new PropertyChangeSupport(this)
- public float getTicketPrice() return
unitCost - public void setTicketPrice(float newVal)
- if (newVal unitCost) return
- float oldVal unitCost int oldTotal
getTotal() - unitCost newVal
- propertyChange.firePropertyChange("ticket
Price", null, newVal) - propertyChange.firePropertyChange("total"
, null, getTotal()) -
- public int getNumberOfAttendees()
return numberOfAttendees - public void setNumberOfAttendees(int
newVal) - if (numberOfAtendees newVal) return
- int oldVal numberOfAttendees int oldTotal
getTotal() - numberOfAttendees newVal
- propertyChange.firePropertyChange("number
OfAttendees", null, newVal) - propertyChange.firePropertyChange("total"
, null, getTotal())
No cycles created by non-transient links
108Supporting Private Data?
109Unshared Property
- public class ConcertExpenseWithAttendance extends
ConcertExpense - boolean attend
- public boolean getWillAttend()
- return attend
-
- public void setWillAttend(boolean newVal)
- if (attend newVal) return
- attend newVal
- if (newVal)
- setNumberOfAttendees (getNumberOfAttende
es() 1) - else
- setNumberOfAttendees (getNumberOfAttende
es() - 1) -
-
-
Infrastructure not told about change to
willAttend property
Can use two different notification models. Or use
special API
Neither is View!
110Selective Replication
- package main
- import budget.ConcertExpense
- import edu.unc.sync.SyncObjectEditor
- import edu.unc.sync.Sync
- public class SyncBudget
- public static String SERVER_NAME
"dewan-cs.cs.unc.edu/A" - public static String MODEL_NAME "demoBudget"
- public static Class MODEL_CLASS
ConcertExpenseWithAttendance.class - public static Class EDITOR_CLASS
SyncObjectEditor.class - public static void main(String args)
- // can also choose if replicate in or out
- Sync.setReplicate(ConcertExpenseWithAttendance.c
lass, willAttend", false) - Sync.replicate (SERVER_NAME, MODEL_NAME,
- MODEL_CLASS,
EDITOR_CLASS, args0) -
-
111Awareness Controlling Synchronization
112Awareness Controlling Synchronization
- package main
- import budget.ConcertExpense
- import edu.unc.sync.SyncObjectEditor
- import edu.unc.sync.Sync
- import edu.unc.sync.SyncClient
- public class SyncBudget
- public static String SERVER_NAME
"dewan-cs.cs.unc.edu/A" - public static String MODEL_NAME "demoBudget"
- public static Class MODEL_CLASS
ConcertExpenseWithAttendance.class - public static Class EDITOR_CLASS
SyncObjectEditor.class - public static void main(String args)
- SyncClient client Sync.replicate
(SERVER_NAME, MODEL_NAME, - MODEL_CLASS,
EDITOR_CLASS, args0) - ObjectEditor.edit (new SyncControls(client.getSe
rverProxy(SERVER_NAME)) -
-
113Sync Controls
- package budget
- import java.beans.PropertyChangeListener
- import java.beans.PropertyChangeSupport
- import java.util.Observable
- import java.util.Observer
- import java.util.Vector
- import edu.unc.sync.server.ServerProxy
- public class SyncControls extends Observable
implements Observer - PropertyChangeSupport propertyChange new
PropertyChangeSupport(this) - ServerProxy server
- public SyncControls (ServerProxy theServer)
- server theServer
- server.addObserver(this)
-
- public boolean getRealTimeSynchronize()
- return server.getRealTimeSynchronize()
-
- public void setRealTimeSynchronize (boolean
newVal) - server.setRealTimeSynchronize(newVal)
114Sync Controls (contd.)
-
- public Vector getCurrentCollaborators()
- return server.getOtherClientNames()
-
- public void synchronize()
- server.synchronize()
-
- public void addPropertyChangeListener(PropertyCha
ngeListener l) - propertyChange.addPropertyChangeListener(
l) -
- public void notifyObservers (Object arg)
- setChanged()
- super.notifyObservers(arg)
-
- public void update (Observable observable,
Object event ) - notifyObservers(event)
-
115Does this work?
- public class ConcertExpenseWithAttendance extends
ConcertExpense - boolean attend
- public boolean getWillAttend()
- return attend
-
- public void setWillAttend(boolean newVal)
- if (attend newVal) return
- attend newVal
- if (newVal)
- setNumberOfAttendees (getNumberOfAttende
es() 1) - else
- setNumberOfAttendees (getNumberOfAttende
es() - 1) -
-
-
116Concurrent Transactions
117Concurrent Transactions
118Concurrent Transactions
119Concurrent Transactions
120Concurrent Transactions
121Concurrent Transactions
Race condition!
122Does this work?
- public class ConcertExpenseWithAttendance extends
ConcertExpense - boolean attend
- public boolean getWillAttend()
- return attend
-
- public void setWillAttend(boolean newVal)
- if (attend newVal) return
- attend newVal
- if (newVal)
- setNumberOfAttendees (getNumberOfAttende
es() 1) - else
- setNumberOfAttendees (getNumberOfAttende
es() - 1) -
-
-
Does not keep track of who is attending. Event
vs. state-based
123Bean Properties vs. Records
- Previous solution requires table mapping users to
attendance - Bean properties define replicated records
- No notifications needed if property object does
not change - Though its components may.
- Currently need to define getter and setter for
each shared property - Other important concrete types
- Dynamic Sequences
- Hashtables
- Want arbitrary compositions of records,
sequences, and tables
124Inheritance Based Approach
- Create predefined replicated hashtable and vector
- ReplicatedSequence
- ReplicatedHashtable
- Can subclass to add functionality
- Sequence user
- is-a sequence
- has-a sequence
125Inheritance Based Approach
- public class ReplicatedDirectory extends
ReplicatedDictionary implements FileWrapper -
- public Replicated remove(Object key)
-
- Replicated value super.remove(key)
- if (value instanceof FileWrapper)
- File file ((FileWrapper)
value).getFile() - if (file.exists() !delete(file))
toBeDeleted.addElement(file) -
- return value
-
126Hashtable Pattern
- import bus.uigen.HashtableChangeSupport
- import bus.uigen.HashtableListener
- public class AConcertExpenseTable implements
java.io.Serializable - String name ""
- HashtableltString, ConcertExpensegt table new
Hashtable() - public Enumeration keys ()
- return table.keys()
-
- public Enumeration elements ()
- return table.elements()
-
- public void put (String key, String
ConcertExpense) - table.put(key, value)
- hashtableChangeSupport.keyPut(key, value)
-
- public ConcertExpense remove (String key)
- ConcertExpense retVal table.remove(key)
- hashtableChangeSupport.keyRemoved(key)
- return retVal
Arbitrary type
127Hashtable Events
-
- HashtableChangeSupport hashtableChangeSupport
new HashtableChangeSupport(this) - public void addHashtableListener
(HashtableListener hashtableListener) - hashtableChangeSupport.addHashtableListener(hash
tableListener) -
- public void removeHashtableListener(HashtableList
ener hashtableListener) - hashtableChangeSupport.removeHashtableListener(h
ashtableListener) -
128Hashtable Listener Interface
- // dont really need to worry about this unless
implementing custom UI - package bus.uigen
- public interface HashtableListener
- public void keyPut(Object key, Object value,
int newSize) - public void keyRemoved(Object key, int newSize)
129Vector Pattern
-
- import bus.uigen.VectorChangeSupport
- import bus.uigen.VectorMethodsListener
- import bus.uigen.VectorListener
- public class AnOutline implements
java.io.Serializable - Vector contents new Vector()
- //non pattern method
- public void addString() addElement("")
- //non pattern method for creating recursive
structure - public void addOutline() addElement (new
AnOutline()) - // either this read method
- public Enumeration elements () return
contents.elements() - //or this pair
- public int size() return contents.size()
- public Object elementAt() return
contents.elementAt() -
Programmer-defined
130Vector Pattern
- // optional
- public void addElement(Object element)
- contents.addElement(element)
- vectorChangeSupport.elementAdded(element)
-
- //optional
- public void removeElement(Object element)
- contents.removeElement(element)
- vectorChangeSupport.elementRemoved(element)
-
- //optional
- public void setElementAt(Object element, int
index) - System.out.println("AnOutline" element
"at" index) - contents.setElementAt(element, index)
- vectorChangeSupport.elementChanged(element,
index) -
- //optional
131Vector Events
- VectorChangeSupport vectorChangeSupport new
VectorChangeSupport(this) - // the following two needed for Sync
- public void addVectorMethodsListener(VectorMethod
sListener vectorListener) - vectorChangeSupport.addVectorMethodsListener(vec
torListener) -
- public void removeVectorMethodsListener(VectorMet
hodsListener vectorListener) - vectorChangeSupport.removeVectorMethodsListener(
vectorListener) -
- // the ones below needed for automatic user
interface generation - public void addVectorListener(VectorListener
vectorListener) - vectorChangeSupport.addVectorListener(vectorList
ener) -
- public void removeVectorListener(VectorListener
vectorListener) - vectorChangeSupport.removeVectorListener(vectorL
istener) -
132VectorMethodsListener
- package bus.uigen
- public interface VectorMethodsListener
- public void elementAdded(Object element, int
newSize) - public void elementInserted(Object element, int
pos, int newSize) - public void elementChanged(Object element, int
pos) - public void elementRemoved(int pos, int
newSize) - public void elementRemoved(Object element, int
newSize)
133VectorListener
- package bus.uigen
- public interface VectorListener
- public void updateVector(uiVectorEvent evt)
134VectorEvent
- public class uiVectorEvent implements
java.io.Serializable - public static final int AddComponentEvent 1,
- DeleteComponentEvent
2, - ChangeComponentEvent
3, - InsertComponentEvent 4,
- CompletedComponentsEvent 5,
- UndefEvent 1000
- public int getEventType()
- public Object getNewValue()
- public int getNewSize()
- public Object getOldValue()
- public int getPosition()
-
-
135Three Useful Existing Classes
- bus.uigen.AListenableVector implements
bus.uigen.VectorInterface - implements vector pattern and fires appropriate
events - bus.uigen.AListenableString implements
bus.uigen.VectorInterface - implements the vector pattern with character
instead of object elements. - fires vector events as user inserts, deletes,
characters - SyncObjectEditor displays it as a text field
- updates it incrementally
- Write method of associated property/sequence/hasht
able invoked when user hits Enter - bus.uigen.AListenableHashtable implements
bus.uigen.HashtableInterface - implements hashtable pattern and fires
appropriate events
136Does this work?
- public class ConcertExpenseWithAttendance extends
ConcertExpense - boolean attend
- public boolean getWillAttend()
- return attend
-
- public void setWillAttend(boolean newVal)
- if (attend newVal) return
- attend newVal
- if (newVal)
- setNumberOfAttendees (getNumberOfAttende
es() 1) - else
- setNumberOfAttendees (getNumberOfAttende
es() - 1) -
-
-
Need table of who is attending.
137Overcoming Race Conditions
- package budget
- import java.io.Serializable
- import java.util.Enumeration
- import java.beans.PropertyChangeSupport
- import java.beans.PropertyChangeListener
- import bus.uigen.AListenableHashtable
- import bus.uigen.HashtableInterface
- public class ConcertExpenseWithAttendanceTable
extends ConcertExpense HashtableInterfaceltStri
ng, Booleangt attendance new AListenableHashtable
() - public HashtableInterface getAttendance()
return attendance - public void setAttendance(HashtableInterface
newVal) attendance newVal - public int getNumberOfAttendees()
- Enumeration elements attendance.elements()
- int retVal 0
- while (elements.hasMoreElements())
- if (((Boolean) elements.nextElement()).equals(tr
ue)) retVal - return retVal
-
138Overcoming Race Conditions
-
- transient String userName "Anonymous"
- public void initUserName (String initVal)
- userName initVal attendance.put(userName
, attend) -
- boolean attend
- public boolean getWillAttend() return
attend - public void setWillAttend(boolean newVal)
- if (attend newVal) return
- attend newVal
- attendance.put(userName, attend)
-
-
139Attendance Table
140Attendance Table
141Attendance Table
142Patterns Summary
143Infrastructure Derivation
- Derived from first principles
- Some Java constraints
- Implemented in Sync
- Presentation influenced Sync design
- Just in time implementation
144Interfaces vs. Patterns
- Patterns describe a family of interfaces
- Unification done at runtime, as in type inference
- T elementAt (int i), addElement (T newVal)
- T getP(), void setP(T newVal)
- Certain methods are optional
- insertElement() or addElement() can change a
sequence - Parameterized interfaces require fixed number of
methods and have no runtime unification - Errors in usage caught at compile time.
145Possible Pattern errors
- May forget to define read or write methods
- E.g. missing setter
- Read and write methods may not unify.
- Write methods may not send events
- Missing or unexpected method for registering
observers. - Missing or unexpected initializer of serialized
objects
146Possible Serialization Errors
- Object may not be serializable
- Serializable superclass gt Serializable subclass
- Improper use of transient
- Cycles in non-transient variables
- Assigning serialVersionUID a value of 1L.
- Dont know why Eclipse assigns one
147Summary
- Clients can be started in any order.
- First one run results in object creation.
- Other one gets serialized replica
- View connected by Sync to replica
- SyncObjectEditor is a generic extendible editor
- SyncApplication interface around ObjectEditor
- Can replace it with custom editor implementing
common interface - Can create multiple objects in server
- Each model tree converted to an internal tree of
records, vectors and hashtables in SyncClient
based on patterns in model tree. - Events fired from model tree result in updates to
client tree. - Client tree synchronized with Server tree when
synchronize called. - Synchronize side effect of property handler if in
realTime mode. - Model can be changed by programmer.
- Synchronize can be called by programmer.
148Limits of Replicated
- Records
- Hashtables
- Vectors
- What kinds of apps can be built?
149Sync Drawer (Munson)
- Shape object to capture coordinates.
- Hashtable for shapes
- Existing single-user app transformed
150Weather Report (Calandrino)
- Extends SyncObjectEditor
- Users from different locations enter data
- Aggregated by Object
151Word Processor (Agiwal)
- Hierarchical document
- Text objects have shared properties
152Word Processor (Porwal)
- Hierarchical Outline
- Can move items
153Spreadsheet (Luebke)
- Hashtable
- Used existing single-user tool
154Calendar (McEuen)
- Hashtable
- Used existing single-user tool
155Chat Application (Karl)
156Aware Chat (Wiegand)
157Experimental Data Set (Jordan)
- Scientists collaborating on experimental data
158Starting the Server
159Starting the Server
160Server UI
161Server Script and java.policy
- set synclib D/dewan_backup/java/lib/syncall.jar
- set CLASSPATHsynclib ltother dirs or jarsgt
- java -classpath CLASSPATH -Djava.security.policy
synclib/java.policy - -Djava.util.prefs.syncInterval2000000
edu.unc.sync.server.SyncServer ui trace
server_id A
Default port is 1099
162Java.policy
grant permission java.security.AllPermission
163RMI Registry Script
- set javabinC\"Program Files"\Java\jre1.5.0_04\bi
n - set synclib D/dewan_backup/java/lib/syncall.jar
- set CLASSPATHsynclib ltother dirs or jarsgt
- javabin\rmiregistry 1099
164Steps
- Install sync jar file
- Install java.policy file
- Runtime
- Start rmiregistry
- Make sure it has the jar file in class path.
- Start Sync server
- Make sure it has the jar file in class path and
arguments like reference to java.policy - Start program interacting with SyncClient on
computer of each interacting user. - Make sure it has the jar file in class path
- Can do this all on one machine.
- Need to loosen firewall if server on different
machine - One same machine, must give unique IDs to clients.
165Possible Errors and Symptoms
- SyncServer could not be bound at specified port
access denied (java.net.SocketPermission
127.0.0.11099 connect,resolve - rmiregistry not started, Java.policy file not
installed or not given as server argument - SyncServer could not be bound at specified port
RemoteException occurred in server thread nested
exception is java.rmi.UnmarshalException error
unmarshalling arguments nested exception is
java.lang.ClassNotFoundException
edu.unc.sync.server.SyncServer_Stub - Sync not in class path of rmiregistry
- No user interface created
- -- ui not passed as argument to Sync server
- Could not open dewan-cs.cs.unc.edu/A
- Server not started,
- Client gives wrong id or hostname for server
(case matters!) - The user-interfaces not connected
- Unique client IDs not given
166Possible Errors and Symptoms
- Initial client interfaces same but subsequent
synchronization does not occur - Property events not fired
- Explicitly set replicate to false
- Initial user-interfaces different but subsequent
synchronization of components occurs - Transient or non-serializable components
- Get null pointer exception when firing events
- Not defined initSeralizedObject() method
- InvalidClass Exception
- private static final long serialVersionUID 1L
- Get rid of the variable declaration or dont
assign it a value
167Possible Errors
- Get null server proxy
- May be passing in wrong name
- Or could be an eclipse error
- Call getServerProxy() with no argument
- Returns the first server opened by client
- Get null model from server proxy
- Maybe passing wrong model name
- Call initialModel
- Returns the first model created at proxy
- Get events from AListenableString only sometimes
- Not registering listener of all instances created
168Sync Client User Interface
- SyncClient is also a main program
- Can be used to connect to servers.
- Add objects to a server
169Sync Client User Interface
170Mapping Names to Classes
- objectsReplicated_Directory Text
- Replicated_Directory.classSyncFiles.ReplicatedDir
ectory - SyncFiles.ReplicatedDirectory.editorSyncFiles.Fil
eEditor - Text.class bus.uigen.AListenableString
- bus.uigen.AListenableString.editorSyncObjectEdito
r