Docstoc

PhD Thesis Proposal

Document Sample
PhD Thesis Proposal Powered By Docstoc
					 




    Modular Algorithms for 
    Component Replication 


           Jakša Vučković




    Technical Report UBLCS‐2006‐13 

              March 2006 




    Department of Computer Science 

         University of Bologna 

        Mura Anteo Zamboni 7 
         40127 Bologna (Italy)
The  University  of  Bologna  Department  of  Computer  Science  Research  Technical  Reports  are 
available  in  PDF  and  gzipped  PostScript  formats  via  anonymous  FTP  from  the  area 
ftp.cs.unibo.it:/pub/TR/UBLCS or via WWW at URL http://www.cs.unibo.it/. Plain‐text abstracts 
organized by year are available in the directory ABSTRACTS. 
      
   Recent Titles from the UBLCS Technical Report Series 
    
2005‐8    Loss  Functions  and  Structured  Domains  for  Support  Vector  Machines  (Ph.D.  Thesis), 
          Portera, F., March 2005. 
2005‐9    A  Reasoning  Infrastructure  to  Support  Cooperation  of  Intelligent  Agents  on  the  Semantic 
          Grid, Dragoni, N., Gaspari, M., Guidi, D., April 2005. 
2005‐10  Fault  Tolerant  Knowledge  Level  Communication  in  Open  Asynchronous  Multi‐Agent 
         Systems, Dragoni, N., Gaspari, M., April 2005. 
2005‐11  The  AEDSS  Application  Ontology:  Enhanced  Automatic  Assessment  of  EDSS  in  Multiple 
         Sclerosis, Gaspari, M., Saletti, N., Scandellari, C., Stecchi, S., April 2005. 
2005‐12  How to cheat BitTorrent and why nobody does, Hales, D., Patarin, S., May 2005. 
2005‐13  Choose Your Tribe! ‐ Evolution at the Next Level in a Peer‐to‐Peer network, Hales, D., May 
         2005. 
2005‐14  Knowledge‐Based Jobs and the Boundaries of Firms: Agent‐based simulation of Firms Learning 
         and Workforc Skill Set Dynamics, Mollona, E., Hales, D., June 2005. 
2005‐15  Tag‐Based  Cooperation  in  Peer‐to‐Peer  Networks  with  Newscast,  Marcozzi,  A.,  Hales,  D., 
         Jesi, G., Arteconi, S., Babaoglu, O., June 2005. 
2005‐16  Atomic Commit and Negotiation in Service Oriented Computing, Bocchi, L., Ciancarini, P., 
         Lucchi, R., June 2005. 
2005‐17  Efficient and Robust Fully Distributed Power Method with an Application to Link Analysis, 
         Canright, G., Engo‐Monsen, K., Jelasity, M., September 2005. 
2005‐18  On  Computing  the  Topological  Entropy  of  One‐sided  Cellular  Automata,  Di  Lena,  P., 
         September 2005. 
2005‐19  A  model  for  imperfect  XML  data  based  on  Dempster‐Shafer’s  theory  of  evidence,  Magnani, 
         M., Montesi, D., September 2005. 
2005‐20  Friends for Free: Self‐Organizing Artificial Social Networks for Trust and Cooperation, Hales, 
         D., Arteconi, S., November 2005. 
2005‐21  Greedy Cheating Liars and the Fools Who Believe Them, Arteconi, S., Hales, D., December 
         2005. 
2006‐01  Lambda‐Types  on  the  Lambda‐Calculus  with  Abbreviations:  a  Certified  Specification,  Guidi, 
         F., January 2006. 
2006‐02  On the Quality‐Based Evaluation and Selection of Grid Services (Ph.D. Thesis), Andreozzi, 
         S., March 2006. 
2006‐03  Transactional  Aspects  in  Coordination  and  Composition  of  Web  Services  (Ph.D.  Thesis), 
         Bocchi, L., March 2006. 
2006‐04  Semantic Frameworks for Implicit Computational Complexity (Ph.D. Thesis), Dal Lago, U., 
         March 2006. 
2006‐05  Fault  Tolerant  Knowledge  Level  Inter‐Agent  Communication  in  Open  Multi‐Agent  Systems 
         (Ph.D. Thesis), Dragoni, N., March 2006. 

                                                     ii
2006‐06  Middleware Services for Dynamic Clustering of Application Servers (Ph.D. Thesis), Lodi, G., 
         March 2006. 
 
 
     




                                                 iii
       

Modular Algorithms for Component Replication 
(PhD Thesis) 
       

Jakša Vučković 1
 
Technical Report UBLCS-2006-13
 
March 2006 
 
 
Abstract 
 
    Modern  component  based  middleware  is  based  on  design  solutions  such  as  separation  of  concerns, 
multi  tiered  architecture,  automated  transaction  management.  These  approaches  open  new  research 
directions in replication. Very little work has been done in this area and it was mostly the application of 
older techniques coming from distributed systems or databases. These techniques are not always efficient 
and sometimes they’re not even correct when applied to the component model. 
    In  this  thesis  we  have  studied  the  component  model  from  a  replication  point  of  view.  We  identified 
common  sub  problems  in  replicating  components  and  refactored  replication  in  terms  of  these  sub‐
problems.  These  sub‐problems  include  keeping  track  of  the  members  of  the  cluster,  maintaining  exactly 
once semantics, collecting the changes that should be replicated, propagating these changes reliably. We 
applied our approach to design a framework for fast development of replication algorithms and used this 
framework to implement a series of effective replication algorithms.  
    Among  the  developed  algorithms  we  present  two  of  them  that  combine  different  mechanisms  for 
reaching  fault‐tolerance,  namely  replication  and  transactions.  Both  of  these  algorithms  combine 
transactions and replication in an orthogonal way, meaning that transactions do not influence replication 
nor the replication influences transaction semantics. We achieve this by treating transactions as part of 
the  application  and  by  replicating  the  state  of  transactions.  The  main  difference  between  the  two 
algorithms lies in the fact that the first one replicates flat transactions and the second one uses the Open 
Nested Transaction model. Moreover the first one treats the transaction manager as a black box, while the 
second  one  actually  involved  the  modification  of  the  transaction  manager.  Both  algorithms  have  shown 
satisfactory performance compared to industry solutions.




1
    Department of Computer Science, University of Bologna, Mura A. Zamboni 7, 40127 Bologna, Italy.


                                                               iv
Acknowledgements 
     
    First  of  all  I  would  like  to  thank  my  colleagues  Simon  Patarin  and  Vance  Maverick  for 
providing me guidance during the most difficult times while working on my thesis. 
     
    I would like to thank Marta Patiño‐Martinez, Ricardo  Jimenez‐Peris and Francisco Perez for 
all the things that they taught me during the period I have spent at the Univesidad Politécnica 
de Madrid. 
     
    I would like to thank my supervisor Özalp Babaoğlu for providing me the right environment 
in which to work on my thesis. 
     
    Finally I would like to thank all of my friends and colleagues for moral support, the coffee 
breaks and the parties.
Contents 

Contents ................................................................................................................................................... vi

List of Figures.......................................................................................................................................... ix

Chapter 1 Introduction ............................................................................................................................1

Chapter 2 An Introduction To Replication ..........................................................................................3
    2.1      Replication in Distributed Systems......................................................................................3
       2.1.1   Active and Passive Replication........................................................................................3
       2.1.2   Consistency.........................................................................................................................4
    2.2      Replication in Databases........................................................................................................4
       2.2.1   Consistency.........................................................................................................................5
       2.2.2   Design Choices...................................................................................................................5
       2.2.3   Concurrency Control.........................................................................................................6

Chapter 3 Component Replication ........................................................................................................8
    3.1      CORBA Replication................................................................................................................8
       3.1.1   Service Based Approach .................................................................................................10
       3.1.2   Integration Based Approach ..........................................................................................11
       3.1.3   Interception Based Approach.........................................................................................12
       3.1.4   The FT‐CORBA Standard ...............................................................................................12
       3.1.5   Combining Transactions and Replication ....................................................................14
    3.2      J2EE Replication....................................................................................................................16
       3.2.1    Possible Choices...............................................................................................................19
       3.2.2    What to replicate? ............................................................................................................19
       3.2.3    Horizontal and Vertical Replication..............................................................................20
       3.2.4    When to Replicate? ..........................................................................................................21
       3.2.5    Replication Transport......................................................................................................24
       3.2.6    Other Aspects ...................................................................................................................25
       3.2.7    Existing Work...................................................................................................................25

Chapter 4 The Replication Framework...............................................................................................28
    4.1      The Java 2 Enterprise Edition Platform .............................................................................28
       4.1.1   Enterprise Java Beans ......................................................................................................29
       4.1.2   Transactions......................................................................................................................31
    4.2          JBoss Application Server Internals.....................................................................................33
       4.2.1        JBoss Interceptors.............................................................................................................33
   4.3      Application Server Abstraction Layer ...............................................................................35
      4.3.1   Intercepting Invocations .................................................................................................35
      4.3.2   Handling Components....................................................................................................37
      4.3.3   Requests and Responses .................................................................................................38
      4.3.4   Transaction Interception .................................................................................................39
   4.4      The Building Blocks .............................................................................................................40
      4.4.1   Chain of Interceptors.......................................................................................................40
      4.4.2   Collecting Changes..........................................................................................................41
      4.4.3   Interchangeable Group Communication......................................................................42
      4.4.4   Load Balancing and Failover..........................................................................................44
      4.4.5   Replicator..........................................................................................................................45

Chapter 5 Transaction Replication Algorithm ..................................................................................50
   5.1      The Algorithm.......................................................................................................................51
      5.1.1   The Actors.........................................................................................................................51
      5.1.2   The Data ............................................................................................................................51
      5.1.3   The Algorithm..................................................................................................................52
   5.2      The Implementation.............................................................................................................54
      5.2.1   Collecting Changes..........................................................................................................54
      5.2.2   Receiving and Applying Changes.................................................................................55
      5.2.3   Transaction Association and Failover...........................................................................55
   5.3          Correctness Proof .................................................................................................................56

Chapter 6 ONT Replication Algorithm ..............................................................................................59
   6.1      Open Nested Transactions ..................................................................................................59
      6.1.1   The Activity Service.........................................................................................................59
      6.1.2   Implementing ONTs with the Java Activity Service...................................................59
   6.2      Replicating ONTs .................................................................................................................60
      6.2.1   Actors ................................................................................................................................60
      6.2.2   Data....................................................................................................................................61
      6.2.3   The Algorithm..................................................................................................................62
   6.3          Implementation.....................................................................................................................63
   6.4          Correctness Proof .................................................................................................................65

Chapter 7 Performance Evaluation......................................................................................................68
   7.1      ECPerf Benchmark ...............................................................................................................68
      7.1.1   Automating Benchmarks ................................................................................................69
      7.1.2   Benchmarking of the replication framework ...............................................................70
      7.1.3   Benchmarking of the ONT Replication Algorithm .....................................................71
   7.2      Custom Benchmarks ............................................................................................................74
      7.2.1   Non Replicated JBoss ......................................................................................................76
      7.2.2   Default JBoss Replication................................................................................................76
      7.2.3   Transaction Replication Algorithm ...............................................................................77

                                                                         vii
        7.2.4         ONT Replication Algorithm...........................................................................................83
    7.3          Profiling .................................................................................................................................84

Chapter 8 Conclusions...........................................................................................................................87
    8.1          Contributions ........................................................................................................................87
    8.2          Implementation Effort .........................................................................................................88
    8.3          Research Directions..............................................................................................................89

References................................................................................................................................................91




                                                                            viii
List of Figures 

Figure 2.1 Active versus Passive Replication.........................................................................................4
Figure 2.2 Single  Primary versus Multiple Pimaries ...........................................................................6
Figure 3.1 CORBA Architecture ..............................................................................................................9
Figure 3.2 Service Based CORBA Replication .....................................................................................10
Figure 3.3 Integration Based CORBA Replication ..............................................................................11
Figure 3.4 Interception Based CORBA Replication.............................................................................12
Figure 3.5 FT‐CORBA Architecture ......................................................................................................13
Figure 3.6 Transactions in CORBA........................................................................................................14
Figure 3.7 OTS Architecture...................................................................................................................14
Figure 3.8 Combining Transactions and Replication in Eternal........................................................15
Figure 3.9 Session Beans and Entity Beans ..........................................................................................17
Figure 3.10 Web Clients and HTTP Sessions .......................................................................................17
Figure 3.11 Transactions in J2EE ...........................................................................................................18
Figure 3.12 J2EE Transaction Manager Architecture ..........................................................................19
Figure 3.13 Horizontal Replication .......................................................................................................20
Figure 3.14 Vertical Replication.............................................................................................................21
Figure 3.15 Invocation Triggered Replication .....................................................................................22
Figure 3.16 Remote Invocation Triggered Replication .......................................................................23
Figure 3.17 Transaction Triggered Replication ...................................................................................23
Figure 4.1 Three Tier Architecture ........................................................................................................29
Figure 4.2 J2EE Architecture ..................................................................................................................29
Figure 4.3 The Home and Remote Interfaces.......................................................................................31
Figure 4.4 Client and Server Side Interceptors ....................................................................................35
Figure 4.5 Invocation Tree......................................................................................................................36
Figure 4.6 Multiple Interception Points................................................................................................37
Figure 4.7 Transaction Interception ......................................................................................................39
Figure 4.8 Chain of Interceptors ............................................................................................................40
Figure 4.9 Collecting Changes ...............................................................................................................41
Figure 5.1 Extended Bean Changes Data Structure ............................................................................52
Figure 6.1 The Changes Data Structure ................................................................................................62
Figure 6.2 ONT Replication Architecture.............................................................................................64
Figure 6.3 The Changes Data Structure with Uncommitted Changes .............................................65
Figure 4 Replication Framework Overhead.........................................................................................70
Figure 7.5 ONT Replication Throughput with ECPerf.......................................................................71
Figure 7.6 ONT Replication Latency with ECPerf ..............................................................................72
Figure 7.7 ONT Replication Throughput with Extended ECPerf .....................................................74
Figure 7.8 ONT Replication Latency with Extended ECPerf.............................................................74
Figure 7.9 Non Replicated JBoss Throughput .....................................................................................76
Figure 7.10 Non Replicated JBoss Latency...........................................................................................76
Figure 7.11 Default JBoss Replication Throughput.............................................................................77
Figure 7.12 Default JBoss Replication Latency ....................................................................................77
Figure 7.13 Transaction Replication Throughput ...............................................................................78
Figure 7.14 Transaction Replication Latency .......................................................................................78
Figure 7.15 Transaction Replication Throughput (without blocking)..............................................79
Figure 7.16 Transaction Replication Latency (without blocking) .....................................................79
Figure 7.17 Throughput Improvement Without Blocking.................................................................79
Figure 7.18 Latency Improvement Without Blocking ........................................................................80
Figure 7.19 Transaction Replication Throughput (SFSB only) ..........................................................80
Figure 7.20 Transaction Replication Latency (SFSBs only) ................................................................81
Figure 7.21 Transaction Replication Throughput Comparison.........................................................81
Figure 7.22 Transaction Replication Latency Comparison ................................................................81
Figure 7.23 Transaction Replication Throughput with JBora............................................................82
Figure 7.24 Transaction Replication Latency with JBora ...................................................................82
Figure 7.25 Transaction Replication Throughput with JBora (detail) ..............................................83
Figure 7.26 Transaction Replication Latency with JBora (detail)......................................................83
Figure 7.27 ONT Replication Throughput ...........................................................................................84
Figure 7.28 ONT Replication Latency...................................................................................................84




                                                                   x
Chapter 1 

Introduction 

    The last decade has witnessed a huge growth of on‐line services. The requirement for very 
complex  and  large  applications  for  e‐banking,  e‐commerce,  remote  ticket  booking,  etc.  has 
fostered  the  design  of  solutions  that  would  simplify  development  of  such  applications.  These 
solutions brought two big changes in the trends of system design. 
    The  first  one  was  to  modularize  applications  into  smaller  composable  units  called 
components.  The  advantage  of  components  was  the  possibility  to  reuse  them  in  different 
applications  and  to  compose  applications  from  existing  components.  Component  based 
applications are more easily extended by replacing some of their components with others that 
offered new features or a better implementation. 
    The other important step was to separate non‐functional concerns such as persistence, access 
control, authentication, transaction management, communication from the functional aspects of 
the  application.  This  simplified  the  process  significantly  and  shortened  the  time  required  to 
develop  complex  and  robust  applications.  These  design  trends  led  to  the  birth  of  application 
servers that provided all these aspects in a more or less transparent way. 
    One  of  the  fundamental  aspects  of  the  new  on‐line  services  is  their  high  availability. 
Providing high availability in a transparent way is a very challenging task in the design of an 
application  server.  High  availability  means  having  a  service  that  is  able  to  handle  heavy  load 
and to conceal the presence of faults. Replication is a useful technique that can be used to obtain 
high availability, in terms of both: fault tolerance and scalability. But replication comes at a cost, 
especially  for  application  servers  that  transparently  provide  non  functional  features.  It 
introduces  significant  complexity  in  many  other  aspects  of  an  application  server,  because 
replication  changes  the semantics  behind  the  interfaces  between  parts  of  the server, its  hosted 
application  and  the  clients.  When  replicating  an  application  server  we  need  to  take  into 
consideration  database  access,  transactions,  interaction  between  components,  communication 
and perform replication without breaking any of the semantics of these provided services. 
    Some  application  servers  offer  completely  transparent  replication  of  hosted  components  in 
order to achieve fault tolerance and scalability. Most of the existing solutions are adaptations of 
replication algorithms coming from the distributed systems or database area, but little research 
has  been  done  to  understand  the  component  model  from  a  replication  point  of  view. 
Components  present  a  dual  nature  that  has  features  of  both  processes  and  data.  But  since 
components may interact with each other we have to pay special attention on these interactions 
when we perform replication. 
    The purpose of this thesis is to research how replication of component based systems should 
be  done  in  order  to  provide  fault‐tolerance.  Our  goal  is  to  understand  what  the  specific 
                                                                                              1 Introduction

problems  of  replicating  component  based  systems  are  and  find  adequate  solutions  both  from 
the algorithmic and also architectural point of view. We want to know what implications it has 
to  replicate  components  that  invoke  each  other  and  how  replication  can  be  combined  with 
persistence, concurrency control and transaction management. 
    After analyzing the component model and existing solutions, we divide the replication into 
smaller  sub‐problems  such  as  keeping  the  client  up‐to‐date,  performing  failover,  tracking 
changes  performed  by  a  client  request,  propagating  changes  among  servers,  etc.  For  each  of 
these  sub‐problems  we  present  one  or  more  solutions.  Some  of  the  solutions  we  present  are 
taken from existing component replication systems or from research done in other fields. Some 
other solutions such as transaction replication and advanced transaction replication are a novel 
contribution.  We  have  implemented  a  modular  framework  for  replication  algorithms.  Each 
module  of  the  framework  is  a  building  block  that  implements  a  solution  to  a  sub‐problem  of 
replication.  Replication  algorithms  may  be  composed  out  of  these  building  blocks.  Using  the 
building  blocks,  we  have  implemented  two  new  replication  algorithms  that  replicate 
respectively flat and open nested transactions. 
    The thesis is structured as follows: Chapter 2 and Chapter 3 represent the state of the art. In 
Chapter 2, we give an overview of the replication approaches used in distributed systems and 
databases and then in Chapter 3 we examine the existing solutions for component replication. 
In Chapter 4 we present our framework for building component replication algorithms and the 
basic building blocks that deal with sub‐problems of component replication. In Chapter 5 and 
Chapter 6, we present two replication algorithms for components. More specifically in Chapter 
5,  we  show  how  our  framework  can  be  used  to  replicate  not  only  components  but  also 
transactions that span over multiple components and multiple client invocations. In Chapter 6 
we  extend  this  solution  to  replicate  an  advanced  transaction  model.  Finally  in  Chapter  7  we 
analyze the performance of our framework and the implemented algorithms. 
    The  work  of  this  thesis  has  been  done  in  the  context  of  the  ADAPT  ‐  Middleware 
Technologies  for Adaptive  and  Composable  Distributed  Components  project  [49].  The  overall 
goal  of  the  ADAPT  project  was  to  develop  an  infrastructure  for  inter‐enterprise  business 
processes that are implemented as composite services and to provide middleware support for 
highly  available  basic  services  that  will  be  used  to  build  higher  level  composite  services.  This 
thesis objective was the design and implementation of a middleware platform that would host 
and replicate stateful basic services.  
    The  first  part  of  the  replication  framework  was  developed  by  the  Bologna  ADAPT  team, 
which  was  comprised  of  3  members  including  me.  The  requirements  specification  and  the 
framework  design was  done  jointly  through a  continuous revision  process.  In the  first  part  of 
the  framework  I  have  implemented  transaction  interception,  preprocessing,  passive 
instantiation  and  exception  wrapping.  The  second  part  of  the  framework  which  includes  the 
replication  building  blocks  and all  the  presented  replication  algorithms  were entirely defined, 
designed and developed by me.




UBLCS-2006-13                                                                                               2
Chapter 2 
An Introduction To Replication 

   Replication has been studied through the years in many different areas. Its roots span into 
two  big  areas:  databases  and  distributed  systems.  These  two  computer  science  branches 
historically had different approaches to replication. The first big difference was the basic entity 
that had to be replicated: in the database world it was data, while in the distributed systems it 
was  a  process.  Another  important  difference  was  the  purpose  for  performing  replication. 
Databases  were  replicated  for  scalability  and  load  distribution  while  in  distributed  systems 
replication  was  solely  used  to  achieve  fault  tolerance.  Because  the  two  areas  had  different 
purposes, different requirements were defined for replication algorithms; in particular different 
consistency guarantees have been defined. 

2.1       Replication in Distributed Systems 
   In distributed systems replication is mainly used to provide fault tolerance. The entity being 
replicated is a process. Two replication strategies have been used in distributed systems: Active 
and Passive replication. 

2.1.1     Active and Passive Replication 
   In  active  replication,  also  known  as  the  state  machine  approach  each  client  request  is 
processed by all the servers. This requires that the process hosted by the servers is deterministic. 
Deterministic means that, given the same initial state and a request sequence, all processes will 
produce the same response sequence and end up in the same final state. In order to make all the 
servers receive the same sequence of operations, an atomic broadcast protocol must be used. An 
atomic  broadcast  protocol  guarantees  that  either  all  the  servers receive  a  message  or  none,  plus 
that they all receive messages in the same order. The big disadvantage for active replication is 
that in practice most of the real world servers are non‐deterministic. Still active replication is the 
preferable choice when dealing with real time systems that require quick response even under 
the presence of faults or with systems that must handle byzantine faults. 
   In passive replication there is only one server (called primary) that processes client requests. 
After processing a request, the primary server updates the state on the other (backup) servers 
and sends back the response to the client. If the primary server fails, one of the backup servers 
takes  its  place.  Passive  replication  may  be  used  even  for  non‐deterministic  processes.  The 
disadvantage of passive replication compared to active is that in case of failure the response is 
delayed. 
                                                                                 2 An Introduction To Replication



                  Active Replication                                           Passive Replication

                        Client                                                        Client




        process          process           process                   process           process           process


         state             state             state                     state             state             state

        server            server           server                server         server                    server
                                   Figure 2.1 Active versus Passive Replication
   There are two models for representing distributed systems: the synchronous and asynchronous 
model.  In  the  Synchronous  model  it  is  assumed  that  a  message  is  transmitted  in  a  bounded 
time, while in the Asynchronous there is no such assumption. This distinction led to different 
algorithms  with  different  guarantees.  An  important  result  that  has  been  proven  for 
asynchronous systems is that it is impossible to obtain consensus in a distributed system model 
where no synchrony assumption is made and when at least one process can crash [8]. Since the 
consensus problem stands at the basis of replication, this result had profound implications for 
replication  algorithms  which  needed  to  introduce  some  oracles  such  as  failure  detectors  or 
synchronization primitives in order to circumvent the consensus impossibility problem. 

2.1.2       Consistency 
     Consistency  guarantees  are  expressed  in  distributed  systems  through  sequential  consistency 
[4] and linearizability [5]. In its first form sequential consistency was defined so that ʺ...the results 
of  any  execution  is  the  same  as  if  the  operations  of  all  the  processors  were  executed  in  some  sequential 
order, and the operations of each individual processor appear in this sequence in the order specified by its 
program.ʺ The informal definition of linearizability is “A concurrent computation is linearizable if it 
is  equivalent  …  to  a  legal  sequential  computation”.  Even  if  these  two  widely  adopted  consistency 
criteria may seem equivalent at first sight, Attiya and Welch [6] say that: “Sequential Consistency 
requires  that  all  the  operations  appear  to  have  executed  atomically,  in  some  sequential  order  that  is 
consistent  with  the  order  seen  at  individual  processes.  When  this  order  must  also  preserve  the  global 
(external) ordering of non‐overlapping operations, this consistency guarantee is called Linearizability.” 

2.2         Replication in Databases 
   While  in  distributed  systems  it  was  a  process,  the  basic  unit  of  replication  in  databases  is 
data. Since data can be more easily transferred through the network than a process, in databases 
passive  replication  is  preferred  to  active  replication.  Data  is  modified  by  transactions,  which, 
from our point of view, can be considered as sequences of read and write operations. 
   Transactions  [2]  are  a  concept  introduced  in  databases  to  group  together  a  set  of  read  and 
write  operations.  After  executing  the  operations  successfully  a  transaction  may  commit, 
otherwise it aborts. Transactions have the following, so called ACID, properties: 
         • Atomicity ‐ operations of a transaction are all executed or none  

UBLCS-2006-13                                                                                                           4
                                                                        2 An Introduction To Replication

        • Consistency ‐ data is left in a consistent state after completing a transaction 
        • Isolation – concurrent transactions do not interfere with each other, but appear as they 
          have been executed one by one 
        • Durability – the effects of a completed transactions are persistent 
    A  variant  of  transactions  are  nested  transactions.  In  this  model  a  transaction  may  have  sub‐
transactions yielding to a tree like structure. A sub‐transaction is committed (rolled back) only if 
its parent is committed (rolled back). Changes performed by a sub‐transaction are visible only 
to its ancestors and descendants. From the point of view of replication, nested transactions are 
not  very  different  from  flat  transactions,  but  we  will  see  how  advantage  may  be  taken  from 
them to replicate components. 

2.2.1     Consistency 
    A  DBMS  must  enforce  the  ACID  properties  of  transactions  in  order  to  be  correct.  The 
correctness  of  a  DBMS  is  specified  with  the  serializability  property  [2].  The  serializability 
property  says  that  the  concurrent  execution  of  transactions  must  lead  to  the  same  effects as  if 
the transactions were executed in some serial order. 
    For replicated databases the correctness criteria is expressed through the 1‐copy serializability 
[2] property. This property says that a DBMS must behave as if there was a single copy of the 
database  and  preserve  the  serializability  criteria.  1‐copy  serializability  is  the  consistency 
guarantee  for  replicated  databases,  just  as  sequential  consistency  and  linearizability  were  for 
distributed systems. Ensuring 1‐copy serializability, while maintaining acceptable performance 
at the same time, is a difficult goal to reach. For this reason different weaker consistency models 
were defined and implemented by most commercial database management systems. 

2.2.2     Design Choices 
    Database replication algorithms are categorized into eager and lazy replication [3]. In eager 
replication  updates  are  replicated  before  the  commit  of  a  transaction.  In  lazy  replication, 
changes are not propagated immediately but delayed until a later time. This may be at a certain 
time  interval  or  just  after  the  transaction  commit.  Eager  replication  has  the  advantage  that 
concurrency  control  is  relatively  easy  to  implement,  but  eager  replication  introduces  an 
additional  communication  overhead  with  respect  to  lazy  solutions.  For  lazy  replication 
algorithms, consistency is harder to achieve. Nevertheless there have been many lazy solutions 
based  on  the  primary/backup  approach  which  guarantee  consistency,  but  lose  performance 
improvements since the primary becomes the bottleneck. 
     
    Another important distinction in database replication algorithms is the set of replicas that a 
client  may  use  to  perform  updates.  In  certain  solutions  there  is  only  one  replica  (primary) 
responsible  of  updating  the  data  and  any  changes  are  then  propagated  to  the  other  replicas 
(backups).  We  call  this  the  primary/backup  approach.  In  some  more  advanced  replication 
algorithms  different  replicas  are  allowed  to  update  data.  In  this  case  we  will  talk  about  the 
multi‐primary  approach.  Note  that  this  is  not  active  replication.  In  active  replication  different 
sites process the same requests, while in this case different sites will process different requests 
and later propagate changes to each other. 




UBLCS-2006-13                                                                                              5
                                                                           2 An Introduction To Replication



              Primary/Backup                                                 Multi-primary


         Client             Client                                  Client                   Client




                   DB                DB     DB                     DB              DB           DB
                  primary       backup     backup                primary          primary      primary



                            Figure 2.2 Single Primary versus Multiple Pimaries
   Some typical replication algorithms that follow the multi‐primary approach are: 
        • ROWA [9] (Read One Write All) – In this algorithm when a write is issued, the data is 
          updated  at  each  site.  Reads  can  be  performed  on  any  site.  This  algorithm  keeps  all 
          copies  synchronized,  but  has  the  problem  that  when  one  of  the  sites  fails,  writes 
          cannot be performed. When increasing the number of replicas, the probability that one 
          of them fails is also increased. 
        • ROWAA [12] (Read One Write All Available) – This is a variant of the ROWA algorithm 
          that is fault‐tolerant. Reads can still be performed on any site, but writes now can be 
          issued  only  to  the  sites  that  are  available.  This  algorithm  needs  recovery  of  failed 
          replicas. 
        • QC (Quorum  Consensus) –  The  quorum  based algorithm  minimizes  the  overall load 
          of the cluster for write operations at the cost of read operations. Both read and write 
          operations  are  issued  to  a  quorum  of  the  replicas.  Quorum  properties  give  us  the 
          guarantee  that  any  read  will  be  consistent  and  up‐to‐date.  Some  variants  of  this 
          algorithm  [13]  can  have  different  quorums  for  reads  and  writes  in  order  to  improve 
          performance. 
    While the primary/backup approach is much simpler because it avoids concurrent updates 
at  different  sites,  the  primary  server  can  be  the  bottleneck  of  the  system  and  no  performance 
improvement can be gained by adding machines to the system. Since the capacity to handle a 
high number of requests is an important feature of databases, multi‐primary approaches are a 
more desirable alternative. On the other hand, multi‐primary approaches introduce concurrent 
updates at different sites and thus need some form of distributed concurrency control method. 
Distributed  concurrency  control  introduces  a  lot  of complexity  in  the  replication  protocol  and 
usually  represents  a  source  of  overhead  in  terms  of  both,  latency  and  throughput.  However, 
given  the  performance  improvement  introduced  by  having  multiple  servers  processing 
requests, the distributed concurrency control overhead is an affordable price to pay. 

2.2.3      Concurrency Control 
    The purpose of concurrency control methods is to preserve consistency in databases. When 
talking  about  databases,  at  the  basis  of  concurrency  control  is  the  notion  of  conflict  of 
operations.  In  general  we  can  assume  that  operations  can  be  classified  into  read  and  write 
operations.  Two  operations  are  conflicting  if  they  are  from  different  transactions,  access  the 
UBLCS-2006-13                                                                                             6
                                                                          2 An Introduction To Replication

same data and one of the operations is a write. In [10] database conflicts have been categorizes 
into these three types: 
        • write‐write – a transaction tries to write data that has already been written by another 
          concurrent  transaction.  This  conflict  can  lead  to  lost  updates,  i.e.  an  update  that  was 
          overwritten. 
        • read‐write  –  a  transaction  writes  data  that  has  already  been  read  by  a  concurrent 
          transaction.  In  this  case  the  value  read  by  the  first  transaction  is  not  valid  anymore. 
          This case is also known as unrepeatable read. 
        • write‐read ‐ a transaction tries to read data that has been written by another concurrent 
          transaction. In this case the second transaction might read an uncommitted state of the 
          database that is inconsistent, also known as dirty read. 
    Two transactions are conflicting if they contain conflicting operations. Concurrency control 
mechanisms restrict possible interleavings of the operations of conflicting transactions. 
    There are two popular concurrency control strategies in databases. These are the optimistic 
and the pessimistic strategy. In the optimistic strategy [7] concurrent access to the same data from 
two  different  transactions  is  permitted,  and  only  at  commit  time,  conflicting  transactions  are 
resolved based on timestamp ordering [11] and one is chosen to commit while others have to roll 
back. The optimistic strategy has the advantage of not using an expensive mechanism such as 
distributed  locks,  and  performs  much  better  if  there  are  a  lot  of  concurrent  non  conflicting 
operations  (i.e.  reads).  But  the  optimistic  strategy  is  not  suitable  for  a  scenario  with  a  large 
number  of  conflicting  operations,  because  the  chances  of  having  to  roll  back  an  operation 
become high. 
    In  the  pessimistic  strategy  conflicting  transactions  are  blocked.  This  is  usually  achieved  by 
using some form of distributed locking. With distributed locking an item need to be locked at all 
sites before it can be accessed. Distributed locks can be implemented in many ways. One of the 
most  common  implementations  is  using  a  centralized  lock  controller  [14],  [15].  While  the 
centralized  lock  controller  is  quite  simple  to  implement  and  does  not  introduce  too  much 
communication overhead, it may represent a bottleneck and a single point of failure. Consensus 
based distributed locking [16] can represents a more fault‐tolerant solution, but it introduces the 
complexity  and  communication  overhead  of  a  consensus  protocol.  The  consensus  based 
distributed locking can be used in combination with the quorum consensus replication. Another 
pessimistic  approach  is  to  have  a  primary  copy  [17]  of  an  item  which  is  the  only  one  allowed 
updating that data. This is somewhat similar to a primary/backup scheme where each item has 
a  different  primary.  This  approach  becomes  slightly  more  complicated  when  a  transaction 
accesses  multiple  items  that  have  primary  copies  on  different  sites.  A  token  ring  based 
distributed concurrency control protocol has also been proposed in [18], but in order to perform 
an  update  two  roundtrips  were  needed.  The  protocol  was  simple  and  formal  verification  has 
been  used  to  prove  its  correctness,  but  the  low  performance  of  the  protocol  determined  its 
impracticality. 
     
    A lot of research has been done in the database area and very important results have been 
achieved. A large number of these results can be reused in other research areas. However, as we 
will see in the next chapter, the results must be re‐interpreted and adapted to a different system 
model such as components and many new problems may arise when adapting those solutions.




UBLCS-2006-13                                                                                                7
Chapter 3 

Component Replication 

    Today  distributed  components  are  a  widely  adopted  technology.  They  were  developed  in 
order  to  simplify  development  of  complex  systems  and  to  hide  aspects  like  distribution, 
persistence, transaction management, security, etc. from the application developer. Components 
have  features  of  both  processes  and  data.  They  live  in  an Application  Server  and  are  invoked 
from remote clients or from other components. They may have a state which is modified as a 
consequence  of  the  processing  of  client  requests.  A  component  does  not  directly  modify 
anything  else  except  its  own  state.  But  it  may  invoke  other  components.  The  state  of  a 
component may be serialized 2  and transferred to persistent storage or to another server. 
    These  characteristics  make  the  task  of  determining  the  state  to  replicate  easier  than  with 
generic processes. On the other hand, unlike data in a database, components may invoke each 
other. Invocations between components add significant complexity to the replication algorithms 
used.  There are  a  number of  failure  scenarios  that  may arise  in  the  case  of  nested  invocations 
between components.  
    Components have a slightly different notion of transactions from the ones we have seen in 
databases.  While  database  transactions  were  defined  by  the  client,  in  this  case  it  is  the 
component itself that may define transactions. Moreover transaction context is propagated from 
one component to another one through invocations. When a component starts a transaction and 
invokes another component, the other component will participate in the same transaction. Some 
form  of  distributed  transaction  commit  protocol  must  be  used  to  coordinate  components  on 
different sites. In some cases transactions may also be nested. We will see in Section 3.1.5 how 
nested transactions can be used to guarantee consistency when performing passive replication. 

3.1       CORBA Replication 
   The  first  mainstream  component  technology  was  the  Common  Object  Request  Broker 
Architecture (CORBA) [19] defined by the Object Management Group in 1991. CORBA defines a 
component  object  model.  These  component  objects  live  on  top  of  an  Object  Request  Broker 
(ORB).  The  ORB  provides  all  necessary  basic  services  to  the  CORBA  objects  and  means  of 
communication. CORBA objects can invoke each other through the ORB, which translates local 
invocations into remote ones. 
    
   CORBA only defines a component model and the relative architecture, but does not provide 
an implementation. There are various commercial and open source ORB implementations. The 


2        Transformed to a byte array
                                                                                 3 Component Replication

standard  guarantees  interoperability  between  these  implementations.  In  other  words 
components  may  invoke  each  other  even  if  they  reside  on  different  ORB  implementations, 
different  physical  machines,  different  operating  systems  or  are  implemented  in  different 
languages. The only thing that a CORBA component must expose in order to be invoked is its 
interface,  which  is  specified  using  the  CORBA  Interface  Definition  Language  (IDL).  Thus  to  any 
invoking component it is enough to know the interface of the component it wishes to invoke. 
    The  IDL  compiler  generates  a  client‐side  stub  and  a  server‐side  skeleton  from  the  IDL 
definition  of the  interface  of  the  server object.  These  two  generated  objects  reside  respectively 
on the client object’s ORB and on the server object’s ORB. 



                           Client                                         Server
                           Object                                         Object


                    stub                                                        skeleton

                           ORB                                          ORB
                                                   IIOP

                           server                                      server

                                    Figure 3.1 CORBA Architecture
   When  a  client  object  wants  to  invoke  a  server  object,  the  request  goes  through  the  server 
object’s stub on the client, which serializes the parameters and passes the invocation next to the 
ORB.  The  client  object’s  ORB  locates  the  server  object’s  ORB,  connects  to  it  and  sends  the 
invocation using the Internet Inter‐ORB Protocol (IIOP) protocol. The server object’s ORB at this 
point will forward the request to the skeleton which will de‐serialize the parameters. After the 
server object performs the operation and returns a response, the response will travel all the way 
backwards through the same path to the client object. 
    
   Besides providing a mean of intercommunication for components, CORBA also offers some 
basic services called Common Object Services. The services are also exposed through the IDL and 
are implemented by the ORB itself. Some of the Common Object Services are: 
        • Naming Service – this service is needed to assign names to objects and organize them 
          according to different contexts 
        • Event  Service  –  service  that  provides  asynchronous  communication  between  CORBA 
          objects. 
        • Life‐cycle Services – determine the methods for object creation and removal 
        • Persistent  Services  –  enable  a  CORBA  object  to  maintain  its  state  in  a  database  thus 
          making the object persistent 
        • Transaction  Services  –  provide  support  for  transactions  spanning  through  multiple 
          objects 
        • Concurrency  Services  –  provide  locking  for  CORBA  objects  so  that  consistency  is  not 
          compromised when the object is accessed by concurrent threads 
        • Externalization Services – enables the transformation of objects into byte arrays and the 
          reverse, so objects can be transferred over the network 


UBLCS-2006-13                                                                                             9
                                                                                3 Component Replication

        • Relationship  Service  –  allows  explicit  representation  of  relationships  between  CORBA 
          objects 
   There  are  more  COS  services  like  the  Time  Service,  Query  Service,  Licensing  Service,  etc. 
that add significant support in the development of CORBA applications. As these services are 
not very tied to replication, we will not elaborate on them. 
    
   We  can  categorize  CORBA  replication  systems  into  three  categories  according  to  their 
approach: 
        • Service – Replication facilities are explicitly provided as a CORBA service.  
        • Integration  –  This  approach  does  not  require  applications  to  be  designed  with 
          replication in mind, but it involves modification of the underlying ORB.  
        • Interception  –  This  approach  makes  replication  transparent  to  the  application  and  to 
          the  ORB.  IIOP  invocations  have  to  be  intercepted  and  handled  accordingly  to  the 
          replication algorithm.  

3.1.1     Service Based Approach 
    In  the  Service  based  approach  CORBA  applications  need  to  make  explicit  use  of  the 
replication  service  in  order  to  achieve  fault‐tolerance.  This  approach  is  not  very  useful  if  we 
want  to  replicate  an  existing  application.  It  is  only  good  in  the  case  we  are  developing  an 
application  from  scratch.  This  was  the  oldest  approach  to  CORBA  replication  and  it  was 
followed in DOORS [33], OGS [30] and Newtop Object Group Service [31]. 


            client object                                     Object Group
                                                    server                      server
                                                   object 1                    object 2
                                        register                register


                  Rep. Svc.

               ORB                                  ORB                          ORB




                              Figure 3.2 Service Based CORBA Replication
    
   The  Object  Group  Service  (OGS)  [30]  provides  replication  for  CORBA  applications  by 
exposing  a  set  of  CORBA  services.  Replica  consistency  is  guaranteed  through  group 
communication based on a consensus algorithm implemented through CORBA service objects. 
OGS  also  provides  support  for  monitoring  the  liveness  of  objects,  duplicate  request  detection 
and suppression and state transfer. 
    
   The  Distributed  Object‐Oriented  Reliable  Service  (DOORS)  [33]  is  another  service 
oriented  approach  for  providing  fault  tolerance.  CORBA  objects  use  DOORS  to  detect  and 
recover from failures. The framework provides support for resource management based on the 
needs  of  the  CORBA  applications.  It  also  supports  transparent  checkpointing  but  does  not 
support duplicate request detection and suppression. 

UBLCS-2006-13                                                                                             10
                                                                                 3 Component Replication

     
    The  Interoperable  Replication  Logic  (IRL)  [32]  also  provides  fault  tolerance  through  a 
CORBA  service.  IRL  is  specific  because  it  supports  fault  tolerant  distributed  applications 
deployed on different CORBA implementations from different ORB vendors. Although not yet 
fully FT‐CORBA compliant, IRL is moving in that direction. 
     
    Newtop Object Group Service [31] is similar to OGS, but it additionally provides support 
for  network  partitions.  A  network  partition  is  a  communication  malfunction  where  a  set  of 
replicas  is  unable  to  communicate  with  another  set  of  replicas.  In  Newtop,  when  a  network 
partition is detected, the object group is split into two or more groups. Total message ordering 
between  inside  groups  is  still  preserved.  This  provides  a  necessary  basis  for  partitionable 
clustering, but it is not sufficient because Newtop does not handle remerging of the groups and 
so there are no guarantees on the consistency of the state of the application. 

3.1.2      Integration Based Approach 
   An  approach  that  is  based  on  the  integration  of  the  replication  algorithm  in  the  ORB  is  a 
better  alternative  than  the  previous  one,  because  it  does  not  require  the  redesign  and 
reimplementation  of  applications.  On  the  other  hand,  this  approach  involves  also  the 
replacement  of  the  interaction  protocol  between  ORBs  (IIOP)  with  a  customized  one.  As 
consequence the modified ORBs are not interoperable with other ORBs. Customized versions of 
ORBs  include  Electra  [34],  Orbix+Isis  [35]  and  AQuA  [26].  A  special  case  of  this  approach  is 
AQuA, where interoperability can be achieved by using object gateways. 

                                                 server object 1               server object 2
             client object




                                                      ORB                           ORB

                 ORB

                 Custom IIOP

                             Figure 3.3 Integration Based CORBA Replication
    
   The  AQuA  framework  [26]  provides  fault‐tolerant  CORBA  objects. AQuA  adds  Quality  of 
Service  to  object  replication.  QoS  attributes  are  specified  using  the  QuO  framework  [29].  This 
framework  provides  a  way  to  dynamically  control  QoS  requirements  for  distributed  object‐
oriented applications. In AQuA, QuO contracts are used to specify availability requirements to 
the  underlying  fault‐tolerance  infrastructure  called  Proteus.  As  underlying  group 
communication layer Proteus uses Ensemble [28]. 
   Proteus is capable of performing both active and passive replication with different levels of 
consistency  and  availability.  It  is  able  to  deal  with  crashes,  value  and  time  faults.  High  level 
availability  requirements  specified  by  the  QuO  framework  are  translated  into  appropriate 
replication  schemes  by  the  Proteus  Dependability  Manager.  Then  the  Proteus  Replication 
Manager  takes  care  of  performing  replication  according  to  the  replication  scheme.  If  Proteus 

UBLCS-2006-13                                                                                               11
                                                                               3 Component Replication

cannot  guarantee  the  desired  level  of  availability,  fall  back  levels  are  defined  by  the  QuO 
framework which can be used instead.  
    
   Electra  [34]  adds  fault  tolerance  by  implementing  a  specialized  ORB.  This  ORB  provides 
fault  detection  and  dynamic  replication.  However  Electra  is  not  interoperable  with  other 
CORBA implementations since it uses a non standard ORB implementation. 
    
   Orbix+Isis [35] was the first commercial implementation of a fault‐tolerant ORB. It is based 
on the Isis reliable broadcast toolkit. Even if it is an integration based approach, Orbix+Isis does 
not provide complete transparency. In particular replicated server objects need to inherit from a 
base class. This means that existing applications cannot be replicated without modification. 

3.1.3     Interception Based Approach 
   This  approach  avoids  interoperability  problems  by  taking  out  replication  logic  from  the 
ORB.  The  price  to  pay  is  that  an  interceptor  has  to  be  implemented  for  every  pair  <operating 
system, ORB implementation>. This approach was first taken by Eternal [22]. 
    

                                                server object 1              server object 2
             client object




                                                    ORB                           ORB
                ORB

                    IIOP
                 Rep. Svc.

                             Figure 3.4 Interception Based CORBA Replication
    
   Eternal  [22],  [24],  [24]  is  based  on  the  Totem  [25]  reliable  group  communication  system.  It 
supports  active  replication  and  the  two  flavors  of  passive  replication:  warm  and  cold  passive 
replication. 
   Eternal  is  able  to  detect  duplicate  requests  that  may  arise  when  doing  passive  replication. 
Consider a scenario where a server crashes after propagating the changes to the backup replica, 
but before sending a response to the client. The client will fail over to the backup and send the 
same  request  again.  But  the  backup  has  already  received  the  state  change  caused  by  that 
request.  In  the  Eternal  system,  the  primary  will  send  the  request  identifier  and  the  response 
along with the state, so the backup will recognize a request already processed by the primary 
and send back the cached response. 
   In Section  3.1.5  we will examine in more detail how Eternal uses distributed transactions as 
a mean for achieving exactly once execution and what are the limitations of this choice. 

3.1.4     The FT‐CORBA Standard 
  There  have  been  several  research  projects  that  implemented  replication  of  CORBA  objects. 
Some of them offered new services usable by CORBA applications to perform replication, while 

UBLCS-2006-13                                                                                            12
                                                                                   3 Component Replication

others  provided  replication  in  a  transparent  way.  Various  replication  strategies  were 
implemented  and  often  the  replication  systems  supported  more  than  one  replication  strategy. 
Most of the CORBA replication systems were based on group communication software. These 
research efforts have lead to the definition of a CORBA standard for fault tolerance, namely FT‐
CORBA [21]. 
    Eternal  was  the  CORBA  replication  system  on  which  the  definition  of  the  FT‐CORBA 
standard  was  based.  It  was  also  the  first  FT‐CORBA  compliant  CORBA  replication 
implementation. 
    FT‐CORBA  is  not  an  implementation  of  a  replicated  ORB  nor  is  it  a  specification  for  a 
replication strategy. The compliance to the standards guarantees only interoperability with the 
client  applications  and  imposes  architectural  requirements  for  some  basic  fault‐tolerance 
mechanisms.  It  defines  three  replication  strategies:  active,  cold  passive  and  warm  passive 
replication.  The  active  one  is  the  same  we  have  seen  in  distributed  systems.  The  difference 
between the two flavors of passive replication is that in the warm passive replication the state of 
the  backup  replicas  is  updated  periodically  while  in  the  cold  passive  replication  the  state  of  the 
primary is periodically written to a log and a passive replica is only loaded when the primary 
fails.  
    In FT‐CORBA a new abstraction was introduced: the object group. This is the set of CORBA 
objects representing the same entity. An object group is identified with an Interoperable Object 
Group  Reference  (IOGR).  The  IOGR  encapsulates  information  on  the  location  of  the  various 
replicas  of  the  represented  entity.  An  FT‐CORBA  compliant  client  ORB  uses  the  IOGR  to 
perform transparent failover. 




                                                   ORB                        ORB
              Object                                                                     Object
              Replica                                                                    Replica

                  manages

            Replication
             Manager                  Fault Notifier                                       …
                                                               monitors
                                      Fault Detector



                                    Figure 3.5 FT-CORBA Architecture
   The  fundamental  architectural  component  of  FT‐CORBA  is  the  Replication  Manager.  It  is 
responsible  for  creating,  removing  and  most  of  all  replicating  objects.  Fault  Detectors  are 
responsible  for  detecting  faults  and  reporting  them  to  Fault  Notifiers.  A  Fault  Notifier 
propagates  fault  notifications  to  the  Replication  Manager  and  other  subscribed  clients.  Upon 
receiving a fault notification the Replication Manager performs appropriate recovery. 




UBLCS-2006-13                                                                                                 13
                                                                                    3 Component Replication

3.1.5     Combining Transactions and Replication 
   We will look briefly at the transaction service offered by CORBA because it is important to 
understand  the  transaction  model  offered  by  CORBA  when  dealing  with  replication  and 
consistency. 


                                                   Client



               transaction
                                                                                     nested transaction




                                        Figure 3.6 Transactions in CORBA
     CORBA offers support for transactions through the Object Transaction Service (OTS) [27]. The 
transaction model used here is closed nested transactions [20]. Like flat transactions that we have 
seen in databases, nested transactions keep the ACID properties. There is a top level transaction 
that  is  called  the  root  transaction.  The  root  transaction  can  have  nested  transactions  called 
subtransactions. Also  subtransactions may  have  their  own  subtransactions.  While  transactions 
are  organized  in  a  tree  structured  hierarchy,  there  may  be  several  transaction  trees  in  the 
system. The commit of a subtransaction does not take effect unless the root transaction commits. 
If  the  root  transaction  performs  a  rollback,  all  its  subtransactions  will  be  rolled  back.  The 
isolation  properties  are  valid  even  between  transactions  that  are  part  of  the  same  transaction 
tree.  In  other  words,  when  a  subtransaction  commits,  its  effects  are  not  visible  to  other 
transaction  trees  and  to  the  sibling  transactions  until  the  root  transaction  commits.  The 
advantage  of  using  subtransactions  is  that  they  can  abort  independently  without  causing  the 
whole transaction tree to abort. 




                                      master             OTS       slave
                                       TM                           TM
                                                     tx context

                             ORB                                           ORB
                                                         IIOP
                             server                                        server

                                            Figure 3.7 OTS Architecture
    
UBLCS-2006-13                                                                                             14
                                                                                      3 Component Replication

    Transactions  are  propagated  between  components  invoking  each  other  by  passing  the 
transactional  context.    The  transactional  context  is  propagated  even  between  different  ORBs. 
Transactions are coordinated by a Transaction Manager, which coordinates the components by a 
two  phase  commit  protocol.  If  there  are  multiple  ORBs,  each  having  its  own  transaction 
manager,  the  different  transaction  managers  will  coordinate  themselves  through  the  OTS 
protocol in a master/slave fashion. 
     
    The  Eternal  system  is  also  the  only  one  that  combines  replication  with  transactions.  The 
CORBA  nested  transactions  are  used  to  obtain  consistency  in  the  case  of  passive  replication. 
When a server receives a client request it starts a new transaction. In case of nested invocations 
between CORBA components, for each invocation a new sub‐transaction is started. If one of the 
components  fails,  the  transaction  rooted  at  that  component  is  rolled  back  thus  causing  all  its 
sub‐transactions to be rolled back too. This not only cancels the effects of processing the request 
at the given component but also on the components that have been invoked. 
    In order to better understand this technique consider the following example: 

                               Bank                     Account X                    Account Y
                                                          $150                          $50
      Client            B.1              B.2      X.1                X.2      Y.1                 Y.2

                                                                              Tx 1
          B.transfer(X,Y,50)                                         Tx 1.1
                                  X.withdraw(50)
                                                                    100


                                                                    150 rollback
          faillover
                                                                                                               Tx 2

                                                                    Tx 2.1
                                       X.withdraw(50)
                                                                    100

                                                                    Y.deposit(50)                       Tx 2.2
                                                                                                 100
                                                                                                 50 rollback
                                      faillover
                                                                    Y.deposit(50)                       Tx 2.3
                                                                                                 100




                      Figure 3.8 Combining Transactions and Replication in Eternal
   We have a client that wants to transfer $50 from account X to account Y. Initially the account 
X holds $150 and account Y holds $50.  All operations on the accounts are performed through 
the bank. The bank and the accounts are all replicated. The money transfer is performed in two 
steps: a withdrawal from account X and a deposit on account Y. Let us examine a failure case 
where a component that is in the middle of an invocation chain fails. First the client submits the 

UBLCS-2006-13                                                                                                         15
                                                                                       3 Component Replication

request  to  the  bank.  When  it  receives  the  client’s  request,  the  bank’s  ORB  will  start  a  new 
transaction.  The  bank  will  start  processing  the  request  by  issuing  a  withdraw  request  to  the 
account X. This request will start a nested subtransaction. Suppose that the money is withdrawn 
from  the  account  and  the  subtransaction  commits,  but  in  the  meanwhile  the  ORB  hosting  the 
bank object fails. The failure of the bank will trigger the abortion of the root transaction, which 
will cause the abortion of all the subtransactions, even the completed ones. So the withdrawal 
from account X will be rolled back and the system will be restored to a consistent state. Now the 
client can safely perform a failover to another replica of the bank. 
    The  second  failure  case  happens  at  a  component  that  is  not  the  one  starting  the  root 
transaction. Let us continue from the point where our client failed over to the backup replica of 
the bank. The client’s request will create another top level transaction, the bank will invoke the 
withdraw  method  of  account  X,  which  will  start  its  own  subtransaction  and  complete 
successfully.  Now  the  bank  issues  a  deposit  request  on  account  Y,  which  will  start  a  second 
subtransaction. Suppose the account Y object fails while processing the deposit request. It is not 
necessary  to  roll  back  the  whole  transaction  tree.  We  only  need  to  roll  back  the  smallest 
transaction  that  encompasses  the  object  that  failed.  The  bank  will  perform  a  failover  to  the 
backup replica of account Y and complete the transfer operation. 
    We have seen an interesting way of taking advantage of transactions in order to guarantee 
consistency. However, in practice using distributed transactions is extremely expensive from a 
performance point of view and should be avoided as much as possible. Another problem of this 
technique  is  that  sometimes  there  are  specific  application  requirements  on  the  use  of 
transactions which are not compatible with the way they are used for transaction replication. So 
we are actually paying the price of not  being able to freely use transactions at the application 
level and a significant performance overhead introduced by the use of the distributed commit 
protocol  in  order  to  guarantee  consistency.  In  Chapter  5  we  propose  a  different  approach  for 
combining transactions and replication that does not incur in such a high overhead and leaves 
the control of transactions to the application. 

3.2        J2EE Replication 
    Java  2  Enterprise  Edition  (J2EE)  [36]  is  a  platform  for  the  development,  deployment  and 
execution of large enterprise applications. It provides a component based programming model 
and  a  specification  of  a  runtime  environment  needed  to  host  applications.  There  are  several 
implementations of the J2EE specifications provided by different vendors. 
    The  basic  components  in  J2EE  are  Enterprise  Java  Beans  (EJB)  [37].  These  are  reusable 
components  that  are  hosted  by  a  J2EE  compliant  application  server.  There  are  three  types  of 
EJBs: session beans, entity beans and message driven beans. Session beans are temporary objects 
bound  to  a  single  user  session.  They  appear  in  two  flavors:  stateless  and  stateful.  Stateless 
session  beans  represent  a  service;  usually  they  are  a  point  of  access  to  other  types  of  beans. 
Stateless session beans are trivially simple to replicate since they do not have state. On the other 
hand stateful session beans do have a state. They represent session data specific to a user. They 
are not shared by multiple clients and expire after a timeout. Usually session beans do not hold 
critical  data.  This  task  is  left  to  entity  beans.  Entity  beans  are  shared  by  all  the  clients  and  are 
mapped  to  some  persistent  storage,  usually  a  database.  Entity  beans  are  the  most  difficult  to 
replicate  and,  in  fact, all  the  commercial  J2EE implementations  relay  that  task  to  the  database 
tier. At  last  message  beans  are  stateless  beans  that  respond  to  messages  received  from  the  Java 
Messaging  Service  (JMS)  [38].  They  can  be  considered  as  a  component  version  of  event 


UBLCS-2006-13                                                                                                      16
                                                                                   3 Component Replication

handlers. Since they, like stateless session beans, do not have a state, replicating them is a trivial 
task. 




                                                       EB

                                       SFSB
           Client                                                                             DB
                                                                      EB

                                        SFSB                EB




                                Figure 3.9 Session Beans and Entity Beans
    In  order  for  RMI  clients  to  access  EJBs,  they  must  first  obtain  a  reference  to  them.  This  is 
done  using  a  naming  service.  In  J2EE  the  naming  service  is  the  JNDI  service.  It  maps  human 
readable  names  to  object  references.  References  are  organized  in  a  hierarchy  of  contexts.  We 
refer to the data contained in the JNDI service as the JNDI tree. The JNDI tree can also contain 
global variables. 
    The advantage of J2EE is that it is bound to a specific language and remote clients download 
stubs  to  perform  remote  invocations.  These  stubs  are  provided  by  the  server  and  contain  the 
load  balancing  and  failover  logic.  A  Java  client  may  invoke  replicated  objects  in  completely 
transparent way: the stub will take care of selecting the right replica and failing over to another 
if that replica is not available. 
    J2EE Application servers implement also a technology for supporting web applications like 
servlets  or  Java  Server  Pages.  These  make  use  of  data  structure  called  HTTP  Sessions  to  store 
session data relative to a particular web client. Since web clients are not able to access directly 
the  stateful  session  beans,  HTTP  Sessions  become  the  necessary  support  for  implementing  an 
application with a stateful session. Usually HTTP Sessions contain references to stateful session 
beans. 



           RMI                                 SFSB              EB
          Client

                                     Servlet                           EB
                                                                                                DB
          Web
          Client
                                      HTTP
                                                      SFSB
                                     Session


                               Figure 3.10 Web Clients and HTTP Sessions


UBLCS-2006-13                                                                                                 17
                                                                                 3 Component Replication

    Like  CORBA,  J2EE  provides  support  for  transactions.  The  model  adopted  in  the  Java 
Transaction  Service  (JTS)  [39]  is  a  simplified  version  of  the  one  used  in  CORBA.  The  main 
difference  is  that  J2EE  does  not  support  nested  transactions.  Anyway  transactions  may  be 
suspended to start new transactions. Suspended transactions later can be later resumed. 


                                         Client



                  transaction

                                                               suspend transaction

                                                                          other transaction




                                   Figure 3.11 Transactions in J2EE
   EJBs have some useful properties when it comes to performing replication. First of all, EJBs 
are  passive  objects.  This  is  an  advantage  because  when  there  are  no  clients  invoking  a  bean, 
there are no threads in it and the state is static, thus it is easier to serialize the state of the bean. 
Moreover EJBs are single threaded: they cannot start a new thread and cannot be accessed by 
more than one thread at a time. This reduces the non‐determinism of a single bean. There is an 
explicit distinction between beans that are private to one client (session beans) and shared beans 
(entity  beans).  Entity  beans  have  an  explicit  mapping  to  persistent  storage  specified  in  an 
external file. All these features make J2EE an adequate platform for consistent replication. 




                       EJB                                                        EJB
                                                     JTS
                                   TM                              TM

                     J2EE App Server                               J2EE App Server
                                                    RMI
                          server                                        server

                                    JDBC                       JDBC

                                                   DB


UBLCS-2006-13                                                                                           18
                                                                                   3 Component Replication

                          Figure 3.12 J2EE Transaction Manager Architecture
    Although little work in the academic world has been done on replicating EJB components, in 
practice many existing J2EE application servers provide some form of replication. We are going 
to analyze some of them. 

3.2.1      Possible Choices 
    There  are  many  J2EE  application  servers  that  support  clustering.  The  majority  of 
implementations use the same techniques with slight variations. We will examine the available 
choices when it comes to replicating a J2EE application. These choices are taken from existing 
J2EE implementations, previous solutions coming from replication research in other areas such 
as distributed systems, databases and CORBA or some new ideas we are proposing. 
    EJBs  are  Java  classes  conforming  to  a  set  of  specifications.  These  specifications  introduce 
several  restrictions  of  the  component  model.  These  restrictions  make  it  easier  to  transfer  the 
bean state over the network, map beans to persistent storage and deal with concurrency control. 
As a consequence passive replication seems the natural approach for replicating EJBs. Moreover 
active replication is not scalable and it is not able to deal with non‐deterministic applications. 

3.2.2      What to replicate? 
    There  are  various  parts  of  a  J2EE  application  server  that  can  be  replicated.  These  include 
HTTP sessions, stateful session beans, entity beans, the JNDI tree, the database cache or other 
specific parts of the system. 
    In  order  to  increase  the  fault‐tolerance  of  a  J2EE  system,  the  first  thing  that  should  be 
replicated  are  entity  beans  because  they  hold  the  most  important  data  that  is  shared  by  all 
clients.  Surprisingly  enough,  none  of  the  current  implementations  of  J2EE  servers  replicates 
entity  beans,  instead  they  are  kept  in  a  database  shared  by  all  the  nodes  of  the  cluster.  It  is 
usually  assumed  that  the  database  is  not  a  single  point  of  failure.  The  responsibility  of 
replicating the persistent state of entity beans is left entirely to the DBMS.  
    Replicating  stateful  session  beans  enables  an  RMI  client  to  fail‐over  to  another  replica 
without losing its session state. Since stateful session beans encapsulate data private to a single 
client and are temporary objects with a limited lifespan, it is not crucial that they have a high 
degree of replication. If the state of a stateful session bean is lost, the user behind the client will 
need  to  repeat  the  operations  of  that  session  (for  example  refill  the  virtual  shopping  cart). 
Anyway  it  is  important  that  in  case  of  faults  the  overall  consistency  of  the  system  is  not 
compromised. 
    If  we  want  to  extend  the  ability  to  failover  without  losing  session  data  also  for  web  based 
clients,  we  must  replicate  the  HTTP  sessions  as  well.  HTTP  sessions  also  hold  data  that  is 
private  to  a  single  client  and  everything  that  we  have  said  for  stateful  session  beans  can  be 
applied here also. 
    The  JNDI  Tree  serves  as  the  directory  service  for  the  objects  present  on  a  J2EE  application 
server. It could be a single point of failure if not replicated. Most of the updates to the JNDI tree 
are  performed  when  an  application  is  deployed,  and  the  EJBs  have  to  be  registered  in  it. 
Sometimes the JNDI tree is used to hold global variables or objects that are not EJBs. This use 
case  must  be  also  considered  when  designing  J2EE  replication,  because  underestimating  the 
consistency requirements of the JNDI tree could lead to incorrect application behavior. 
    J2EE servers usually keep a cache of the data retrieved from the database. In a cluster with 
multiple  machines  accessing  the  same  database,  keeping  separate  caches  can  introduce 
inconsistencies in the data seen by each node. The easiest solution is to disable the cache when 

UBLCS-2006-13                                                                                                 19
                                                                                 3 Component Replication

nodes work in a cluster. Some application servers replicate the cache across the cluster so that 
cache contents are never out‐of‐date. 
   Apart from the J2EE services that we have seen, there are other parts that can be replicated. 
In Chapter 5 we propose an algorithm that replicates the transaction manager. 

3.2.3      Horizontal and Vertical Replication 
    From  an  architectural  point  of  view,  the  different  tiers  of  a  J2EE  system  may  be  replicated 
independently  or  as  a  whole.  We  distinguish  between  horizontal  and  vertical  replication.  In 
horizontal replication the application server is in charge of replicating stateful session beans and 
it keeps the entity beans in a database that is shared by all the nodes of the cluster. The DBMS is 
in  charge  of  replicating  entity  beans.  Most  of  the  existing  replication  solutions  take  the 
horizontal  approach.  In  this  approach  we  not  only  have  to  take  particular  effort  to  keep 
consistency  guarantees  between  the  replicas  of  the  same  tier  but  we  also  need  to  handle 
consistency  between  different  tiers.  This  involves  some  coordination  between  the  application 
tier replication and the data tier replication. Either the application tier must be aware of the way 
that the data tier is replicated or the opposite. Integration between two replicated tiers is never 
completely transparent. 



                                     Client




               App. Serv.         App. Serv.            App. Serv.               application tier
                Replica            Replica               Replica



               DB              DB              DB              DB                data tier
              Replica         Replica         Replica         Replica


                                   Figure 3.13 Horizontal Replication
    In the vertical approach replication is performed entirely in the application tier. Each replica 
consists  of  an  application  server  and  its  own  database.  There  is  no  database  that  is  shared 
among  the  different  application  servers.  It  is  assumed  that  an  application  server  and  its 
database  fail  together.  This  can  be  enforced  by  making  one  of  the  two  shut  down  if  the  other 
crashes. Consistency between the application and the data tier comes for free, and we only need 
to concentrate on keeping the replicas at the application tier consistent among themselves. 




UBLCS-2006-13                                                                                              20
                                                                                     3 Component Replication



                                                     Client




               App. Serv.              App. Serv.              App. Serv.             App. Serv.
                Replica                 Replica                 Replica                Replica



                  DB                      DB                      DB                     DB
                 Replica                 Replica                 Replica                Replica

                                       Figure 3.14 Vertical Replication
    
   Existing  replicated  J2EE  servers  have  all  followed  the  horizontal  approach  to  replication. 
This is because entity beans are shared data and in order to access them from multiple nodes 
some sort of distributed concurrency control must be used. For application server developers it 
was much easier to relay this task to existing database software than to re‐implement it at the 
application tier. In Chapters 7, 8 and 9 we present replication algorithms based on the vertical 
approach and see what the advantages offered by this choice are. 

3.2.4      When to Replicate? 
     We  will  use  the  term  replication  triggering  to  refer  to  what  will  be  the  event  that  will  cause 
data to be replicated to the other nodes. There are various possible choices. 
      
     Invocation  ‐  Replication  is  done  after  each  component  invocation.  This  includes  also 
invocations  between  components  that  are  situated  on  the  same  server.  The  JBoss  application 
server  uses  this  approach  to  replicate  stateful  session  beans.  This  approach  introduces  the 
partial  replication  problem.  The  partial  replication  problem  arises  when  a  remote  invocation 
triggers a number of local invocations between components, and we have a failure after some of 
the local invocations have been performed. This means that the state of the invoked components 
has  been  replicated,  but  the  client’s  request  has  not been  completely  executed.  In  this  case we 
should restart the execution on the replica from the point where it stopped, but Java, like most 
of  the  programming  languages,  do  not  provide  support  for  this.  Instead  the  client  could send 
the  same  request  to  the  replica  which  would  trigger  again  the  execution  of  the  same  local 
invocations. This results in some components being invoked twice instead of once. 




UBLCS-2006-13                                                                                                    21
                                                                                      3 Component Replication




                                                                              Server
                 Client                                                       replica




                                                      replicate
                                         replicate




                                                                  replicate




                                                                              replicate
                                                                                     Server
                                                                                     replica


                             Figure 3.15 Invocation Triggered Replication
    Remote Invocation – As a remedy to the partial replication problem, replication could be done 
    Remote Invocation – As a remedy to the partial replication problem, replication could be done 
only  after  remote  invocations  just  before  sending  the  response  to  the  client.  In  this  case  we 
would  replicate  all  data  that  was  changed  during  the  execution  of  a  single  client  request.  We 
have  a  choice  whether  to  replicate  before  sending  the  response  to  the  client  of  after.  If  we 
replicate after the response, and a crash occurs between these two actions, then the client would 
believe the operation performed while actually we have lost all the changes and the other nodes 
know nothing about them. On the other hand, if we replicate before sending the response to the 
client,  a  crash  might  prevent  us  from  notifying  a  client  that  the  operation  was  successfully 
performed and replicated to the other nodes. In this case the client might perform failover and 
send the same request to another node. We call this a duplicate request.  Detecting and correctly 
send the same request to another node. We call this a duplicate request. Detecting and correctly 
handling  duplicate  requests  can  be  implemented  by  sending  the  request  id  and  the  response 
contents attached to the state of the modified components when performing replication. When a 
client  fails  over  to  another  node,  the  new  node  will  check  if  it  already  received  the  changes 
relative to that request id and, if yes, send the cached response back to the client. Otherwise the 
new replica will process the request. 




UBLCS-2006-13                                                                                             22
                                                                                  3 Component Replication




                                                                                Server
                   Client                                                       replica




                                             replicate
                                                                                  Server
                                                                                  replica


                          Figure 3.16 Remote Invocation Triggered Replication
   Transaction Commit – In order to keep the application tier consistent with the data tier even in 
   Transaction Commit – In order to keep the application tier consistent with the data tier even in 
case  of  failures,  replication  algorithms  based  on  horizontal  approaches  perform  replication  at 
transaction commit. This ensures consistency between the data tier and the application tier, but 
does not respect the exactly‐once execution from the client point of view. Consider a situation 
does not respect the  exactly‐once  execution from the client point of view. Consider a situation 
where  a  client  makes  a  remote  invocation  that  will  start  two  transactions.  If  there  is  a  failure 
during  the  second  transaction  we  will  incur  the  partial  replication  problem.  In  order  to 
guarantee exactly‐once execution to the client, we must enforce a one‐to‐one mapping between 
remote invocations and transactions. But enforcing this, takes us back to the case above. 


                                                TX1                             Server
                  Client                                                  TX2   replica
                                          replicate




                                                              replicate




                                                                                  Server
                                                                                  replica



                             Figure 3.17 Transaction Triggered Replication

UBLCS-2006-13                                                                                                23
                                                                                 3 Component Replication

    Periodic  –  Replicating  objects  after  each  invocation  can  become  costly.  Sometimes  the 
replicated  data  does  not  need  to  be  up‐to‐date.  In  this  case  it  is  more  convenient  to  replicate 
data on a periodic basis. This approach may introduce inconsistencies in the system and should 
be  used  with  particular  attention.  The  JBoss  application  server  can  be  configured  to  use  time 
based replication for HTTP sessions. 
     
    In  conclusion,  the  best  replication  triggering  choice  from  the  consistency  point  of  view  is 
replication at remote invocation since a failure of a server means that either the request of the 
client has been entirely processed or not at all. Assuming we have failover and duplicate request 
detection,  we  can  achieve  exactly‐once‐semantics.  In  section  4.4.5  we  will  see  an  algorithm 
following this approach and the formal proof of exactly‐once‐execution. 

3.2.5      Replication Transport 
   By  replication  transport  we  mean  choosing  the  medium  being  used  for  replicating  data 
between nodes. Our choices are:
        • TCP – plain TCP connections are used to transfer data to the backups. This option is 
          easy  to  implement  and  provides  good  performance.  The  problem  of  this  solution  is 
          that  it  does  not  scale  very  well.  In  a  primary/backup  cluster,  there  must  be  n‐1 
          connections,  but  in  a  multi‐primary  cluster  we  will  have  O(n2)  connections.  TCP 
          connections are the most suitable solution when we replicate data only on one backup. 
        • IP  Multicast  –A  more  scalable  approach  than  TCP  connections  is  to  use  IP  multicast. 
          Anyway  this  solution  is  not  practicable  in  every  situation  due  to  the  network 
          configuration of the cluster. 
        • Group Communication Toolkit – neither TCP nor IP Multicast provide  reliable broadcast 
          semantics.  The  group  communication  semantics  is  important  to  achieve  correct 
          behavior in case of failures. There are numerous toolkits [59][60][63][28][25] providing 
          different  levels  of  reliability  and  message  ordering.  The  drawback  of  this  solution  is 
          the  significant  overhead  introduced  by  the  distributed  protocols.  However  if 
          communication is not the bottleneck of the system the added value is certainly worth 
          the overhead. 
        • Client  based  –  there  have  been  approaches  to  replication  that  used  the  client  to  store 
          session data  [64]. This is conceptually equivalent to cold passive replication. The only 
          problem is that in this way only one client has access to the data and reliability of data 
          is entirely left to the client. While it is not a feasible solution to replicate shared data 
          like entity beans, it is a good option for replicating data that is private to a single client 
          like  stateful  session  beans  and  HTTP  sessions.  Moreover  this  solution  decentralizes 
          replication  to  the  clients  and  makes  the  cluster  much  more  scalable.  This  approach 
          also  restricts  us  to  use  horizontal  replication  since  it  can  perform  only  replication  of 
          one single application layer. 
      • Shared  Database  –  a  similar  approach  to  client  based  replication  is  shared  database 
        replication. It is also a passive cold replication approach, but data is kept on a shared 
        database.  Since the database is a part of the cluster and is always present, this time we 
        can  use  it  to  replicate  also  entity  beans.  Furthermore  since  entity  beans  are  already 
        kept in a database we can take advantage of this. The existing application servers that 
        implement clustering use this approach to replicate entity beans. The shared database 
        can be used also to replicate other data like stateful session beans, HTTP sessions, etc. 
        but  usually  these  components  are  replicated  in  a  different  way  for  performance 
UBLCS-2006-13                                                                                           24
                                                                                                3 Component Replication

             reasons. In fact, a shared database can easily become the bottleneck of the cluster and 
             if not replicated it is a single point of failure. 
   The choice of the replication transport medium has a great influence on the performance of 
the  cluster.  The  replication  transport  should  not  be  the  bottleneck  of  the  system.  It  should 
provide a reasonable compromise between performance and reliability guarantees. 

3.2.6        Other Aspects 
   Besides  the  choices  seen  so  far,  there  are  a  lot  of  other  aspects  that  we  have  to  deal  with 
when replicating an application server. 
   The  replication  domain  defines  which  will  be  the  set  of  nodes  where  certain  data  will  be 
replicated  to.  We  could  replicate  application  code  clusterwide,  but  we  could replicate  a  single 
instance  of  a  component  only  to  a  subset  of  the  nodes  (called  subpartition).  This  approach 
would  provide  nice  scalability.  There  could  be  also  combinations  of  various  replication 
techniques for different domains. For example we could replicate after each remote invocation 
on the current subpartition, but have lazy replication on the whole cluster. 
   Another  very  important  aspect  we  have  to  consider  is  concurrency  control.  This  means  that 
concurrent modification of data by two clients should be handled properly even in the case the 
two clients are connected to different servers. In Section 2.2.3 we have seen number of existing 
techniques from the database area for dealing with this. The same techniques can be adapted to 
deal with components. 
   Alternatively,  concurrency  control  can  be  left  to  the  data  tier.  In  fact  many  application 
servers use a shared database performs concurrency control. The advantage of this solution is 
the  use  of  proven  technology  and  a  stable  implementation.  The  disadvantage  is  being 
constrained to use horizontal replication, and thus inheriting all the disadvantages of it. 3
   Finally  we  must  take  into  consideration  transactions  as  well.  Transactions  are  a  backward 
recovery mechanism, meaning that in case of failure, the system is restored to a previous state. 
On the other hand, replication is a forward recovery mechanism because in case of failure the 
computation  is  relayed  to  another  node.  We  have  seen  an  example  of  a  system  that  takes 
advantage  of  the  combination  of  these  two  recovery  mechanisms  in  Section  3.1.5.  Besides  this 
work,  there  has  been  little  research  in  combining  component  replication  and  transactions.  We 
propose  an  alternative  approach  in  Chapter  5  that  seamlessly  combines  these  two  recovery 
mechanisms. 

3.2.7        Existing Work 
    We  will  now  offer  an  overview  of  the  existing  replicated  J2EE  implementations.  Since 
existing J2EE replication implementations are based on the same choices, we will not categorize 
them according to the solutions we have seen so far. Instead we will describe them one by one. 
     
    BEA’s  WebLogic  Application  Server  [40]  is  an  implementation  of  the  J2EE  Specification. 
WebLogic implements the so called “in memory” replication of stateful session beans [41]. This 
just  means  that  stateful  session  beans  are  not  put  into  persistent  storage  but  are  passively 
replicated  using  network  communication.  Network  communication  is  not  relayed  to  a  group 
communication package, but plain TCP connections are used instead. IP Multicast is used only 
for failure detection and replicating the naming service (JNDI). WebLogic uses two methods to 



3
  These disadvantages have already been discussed in Section 3.2.3 and include redundancy of replication algorithms, tight coupling
between tiers and a possible single point of failure in case one of the tiers is not replicated
UBLCS-2006-13                                                                                                                  25
                                                                                3 Component Replication

detect failures. One is to keep TCP connections between servers and the other is to make each 
server periodically multicast a heartbeat message.  
    In  WebLogic  there  is  only  one  primary  server  that  processes  requests  and  then  sends  the 
modified  state  to  the  secondary  server.  There  may  be  more  than  one  secondary  server.  The 
primary  server  maintains  a  TCP  connection  with  each  secondary  server.  State  changes  of  the 
beans are transferred from the primary to the secondary server only after sending the response 
to  the  client.  This  choice  reduces  latency  but  does  not  guarantee  consistency.  In  fact 
modifications  may  be  lost  if  the  primary  server  crashes  before  sending  the  state  to  the 
secondary. 
    As for entity beans, WebLogic replicas all share a common database. Whether the database is 
replicated or not is not even seen by the application server. In Java there is a common interface 
to access the database called Java Database Connectivity (JDBC). The application server uses a 
JDBC  driver  that  is  provided  by  the  database  vendor  to  access  the  database.  Apparently 
WebLogic does not perform any concurrency control for entity beans. 
     
    The  current  version  of  IBM’s  WebSphere  Application  Server  is  6.0.  WebSphere  provides 
replication  through  its  Data  Replication  Service  (DRS)  and  Workload  Management  (WLM) 
subsystems. It replicates stateful session beans, HTTP sessions and the dynamic cache. 
    Stateful  session  beans  are  replicated  in  a  cold  passive  primary/backup  strategy.  Replication 
takes place at transaction commit. 
    HTTP  sessions  –  WebSphere  replicates  HTTP  sessions  in  order  to  enable  also  web  based 
clients to be redirected to another replica without losing session information. Replicating HTTP 
sessions is not sufficient to enable a client to failover to another replica because the client might 
need its session beans. On the other side, replicating stateful session beans without replicating 
HTTP sessions enables only RMI clients to failover, but not the web based clients. 
    Dynamic cache – also the dynamic cache is replicated across the servers in order to improve 
performance. WebSphere does not replicate entity beans, for this reason all the replicas need to 
share the same database. Replicating the dynamic cache reduces the number of accesses to the 
shared database allowing it to sustain a higher load. 
     
    The  JBoss  Application  Server  [43]  is  an  open‐source  J2EE  implementation.  It  has  a  highly 
modular design which makes it easy to modify its behavior.  
    Stateful  session  beans  are  replicated  passively  using  a  group  communication  software 
package,  namely  JGroups.  This  software  also  provides  failure  detection.    There  is  no  single 
primary server, but every server can act as primary. Like WebLogic it has intelligent stubs that 
encapsulate  load  balancing  and  failover  logic.  Concurrency  control  is  not  needed  for  stateful 
session  beans  because  they  hold  session  data  specific  to  a  single  client  and  by  the  J2EE 
specifications, a client should not perform concurrent invocations. 
    Bean  state  is  transferred  using  JGroups  after  each  bean  invocation  before  returning  the 
response to the client. This does not incur the problem we have seen in WebLogic, but has the 
consequence  of  the  possibility  to  have  the  partial  replication  problem  in  case  there  are  nested 
invocations between beans [44]. 
    Like other J2EE implementations, JBoss leaves the replication of Entity Beans to the database 
tier.  JBoss  can  be  configured  to  perform  concurrency  control  on  the  database.  There  are  two 
possible choices: the optimistic and pessimistic strategy. Both of these strategies come from the 
database world. Pessimistic concurrency control is obtained using row locking at the database 
level. Optimistic concurrency control is based on database updates that have as constraint that 
the data read is not modified. 
UBLCS-2006-13                                                                                             26
                                                                                  3 Component Replication

     
    SIB  [45]  is  not  a  J2EE  application  server.  It  is  a  replication  algorithm  for  stateful  session 
beans that substitutes the default replication implementation of the JBoss application server. It 
was  developed  using  the  replication  framework  implemented  in  the ADAPT  project  [50].  It  is 
based  on  the  JBora/Spread  [59],  [60]  group  communication  toolkit,  which  provides  totally 
ordered  broadcast.  entity  beans  are  not  replicated  but  they  are  kept  in  a  shared  database. 
Replication is coordinated with the transaction commit in order to keep stateful session beans 
consistent  with  the  database.  Exactly‐once  execution  is  maintained  under  the  assumption  that 
each  remote  request  is  mapped  to  one  transaction.  This  means  that  if  there  are  multiple 
transactions  in  one  remote  request,  a  failure  might  lead  to  a  partial  replication  scenario. 
Transactions spanning multiple requests are not supported. 
     
    Although  significant  research  has  been  done  on  replication  and  a  lot  of  results  have  been 
achieved in other areas, it is obvious that replicated J2EE systems are still at an early stage. Most 
of  the  existing  solutions  are  not  based  on  previous  research  done  in  replicating  other 
technologies.  There  are  many  replication  strategies,  techniques  and  primitives  that  can  be 
reused to design the replication of a J2EE server. Moreover we have seen that J2EE imposes a 
stringent  model  for  applications,  which  can  be  exploited  to  perform  some  techniques  that  we 
were not able to do with previous technologies. Of course a different model introduces also new 
problematic  aspects  when  dealing  with  replication  which  we  have  studied  and  provided 
solutions for in this thesis. 




UBLCS-2006-13                                                                                                27
Chapter 4 

The Replication Framework 

    To  design  and  evaluate  a  replication  algorithm  for  J2EE  (or  any  practical  component 
architecture)  requires  a  substantial  investment  in  development.  To  ease  this  process,  a 
framework  for  prototyping  EJB  replication  algorithms  has  been  made.  It  factors  the  task  of 
developing a replication algorithm into two layers: the framework itself, which handles all the 
detailed  interactions  with  the  underlying  server  code,  and  the  specific  replication  algorithm, 
which is plugged into the framework. The framework is implemented once and for all, allowing 
the developers to concentrate on the relevant details of the specific replication algorithm. 
    The  first  part  of  the  framework  was  developed  as  part  of  the ADAPT  project  [49].  Later,  it 
has been extended with additional features. We will describe separately the first and the second 
version of the framework, as the latter is built on top of the primitives defined by the former. 4
    The first version of the framework is an abstraction layer over the J2EE server that simplifies 
the programming model and brings in a unique API everything a replication algorithm needs. 
    This  version  avoids  favoring  any  particular  replication  technique.  Thus,  there  are  some 
important problems in replication for which the framework does not provide a ready solution. 
In particular, it does not specify a model for communication between replicas, or for the notion 
of a cluster. 
    For this reason a second version of the framework has been implemented which extends the 
first  one  with  some  building  blocks  for  replication  algorithms.  Still  it  does  not  define  the 
replication  algorithm  in  any  way;  it  just  provides  useful  building  blocks  to  perform  some 
replication specific operations such as collecting state of modified components, communicating 
with the cluster or performing fail‐over. The design of these extensions is very modular and by 
combining  these  building  blocks  different  replication  algorithms  may  be  implemented.  Each 
building  block  may  be  extended  or  completely  substituted  by  another  so  that  more 
sophisticated replication algorithms can be made. 

4.1       The Java 2 Enterprise Edition Platform 
   As  we  said  earlier  in  3.2,  Java  2  Enterprise  Edition  [36]  is  a  platform  for  development, 
deployment  and  execution  of  enterprise  applications.  The  J2EE  technology  was  based  on  the 
three tier architecture. The three tier architecture is an evolution of the client server architecture 
where different aspects of the application are handled by different parts of the system (tiers).  



   4
                                                                             4 The Replication Framework




                                     presentation             application                 data
             client
                                         tier                    tier                     tier


                                    Figure 4.1 Three Tier Architecture
   The client would access the presentation tier which provided the interface to the application 
logic.  The  application  logic  itself  is  contained  in  the  application  tier.  The  application  usually 
contains  the  most  complex  part  of  the  application  and  because  of  this  it  is  supported  by  an 
application server that provides services as transaction management, object persistence, security 
management,  etc.  Finally  persistent  data  is  stored  in  the  data  tier  which  is  accessed  by  the 
application tier. The data tier is usually a database or a set of databases. 



                                         J2EE Application Server


             web                       Web
            client                   container
                                                               EJB                         DB
                                                             Container
             RMI
            client


                                       Figure 4.2 J2EE Architecture
   In  J2EE  the  web  tier  is  represented  by  the  web  container  and  the  application  tier  is 
represented by the EJB container. The web container hosts objects such as JSP pages or Servlets 
that  generate  the  user  interface.  The  web  tier  provides  the  necessary  services  to  make  these 
components  run,  to  handle  HTTP  requests  and  handle  session  association.  Session  data  is 
temporary  data  private  to  a  single  client  and  it  is  maintained  between  different  client 
invocations.  In  the  web  tier,  session  data  is  held  in  HTTP  Session  objects.  HTTP  Sessions  are 
accessed  by  JSPs  and  Servlets.  It  is  responsibility  of  the  web  container  to  associate  the  correct 
HTTP session to a client’s request. 

4.1.1      Enterprise Java Beans 
   Application  logic  is  handled  by  the  EJBs  hosted  by  the  EJB  container.  The  EJB  container 
provides the persistence, concurrency control, transaction, security services to the EJBs. As we 
said in Section 3.2, there are three kinds of EJBs. 
   Session  Beans  are  usually  used  as  the  access  point  for  the  application  logic.    Often  HTTP 
Sessions hold references to Session Beans. Stateless Session Beans are stateless objects in the sense 
that the state of a Stateless Session Bean is not maintained between multiple invocations. In fact 
there is no guarantee that a client will access the same instance in two consecutive invocations. 
EJB  container  implementations  usually  share  the  same  instance  of  a  Stateless  Session  Bean 
between multiple clients. Stateful Session Beans on the other hand have a state and are not shared 
UBLCS-2006-13                                                                                                29
                                                                           4 The Replication Framework

by different clients. Nevertheless a Stateful Session Beans is still a temporary object. If not used 
it  expires  after  a  timeout  and  it  gets  discarded  by  the  EJB  container.  Stateful  Session  Beans 
encapsulate the logic of more complex interactions with the application. A typical example of a 
Stateful Session Beans is a shopping cart of an on‐line store. 
     Entity Beans are persistent objects shared by the clients. The EJB container must take care of 
concurrency  control  when  an  Entity  Bean  is  accessed  by  different  threads.  The  EJB  container 
must also map the Entity Beans to a persistent storage, usually a database, and handle access to 
the database. The fields of an Entity Bean usually represent columns of a table in the database 
and an Entity Bean instance represents a single row in a database. 
     Loading and storing of Entity Beans from and to the database must be done in a consistent 
way. The J2EE Specifications suggest three strategies to deal with this. They are called commit 
options A, B and C. It is important to understand what are the assumptions, requirements and 
guarantees  of  each  of  these  options  in  order  to  guarantee  correct  behavior  of  the  replication 
algorithm.  Persistence  of  Entity  Beans  may  be  managed  in  two  different  ways.  Container 
Managed Persistence leaves the responsibility of accessing the database to the EJB container. CMP 
2.x Entity Beans must be abstract classes and must only declare the setter and getter methods 
used  to  access  its  own  fields.  It  is  up  to  the  EJB  container  to  implement  these  methods  with 
actual code that accessed the database. CMP 1.x Entity Beans had real fields that were properly 
filled by the EJB container before invoking the bean and later stored back to the database. Bean 
Managed Persistence leaves the responsibility of database access to the bean itself. A BMP Entity 
Bean must implement the ejbLoad() and ejbStore() methods, which respectively load and 
store  the  state  of  the  whole  bean  from  and  to  the  database.  All  database  access  should  be 
performed exclusively from these two methods. It is still the EJB container that controls when 
these methods will be invoked. 
     Finally Message Driven Beans are just like Stateless Session Beans that serve as an entry point 
to  the  application  and  have  no  state.  Message  driven  beans  are  not  triggered  by  invocations; 
instead  they  are  triggered  by  JMS  Events.  The  most  important  difference  between  Stateless 
Session  Beans  and  Message  Driven  Beans  is  that  the  latter  ones  are  invoked  asynchronously. 
This means that the application that generated the event that caused the Message Driven Bean 
to be invoked does not block and can proceed with its execution concurrently to the invocation 
of the Message Driven Beans and does not need to wait for any result. 
     A developer supplies an Enterprise Java Bean in four parts: 
        • Home Interface – provides method for controlling the lifecycle of EJBs. There is a Remote 
          Home Interface and a Local Home Interface. The Remote Home interface can be used by 
          both  local  and  remote  clients.  The  Local  Home  Interface  can  be  used  only  by  clients 
          residing on the same server.  
        • Component  Interface  –  defines  the  business  methods  of  an  EJB  instance.  Like  for  the 
          Home  Interface,  here  we  have  a  Remote  Interface  and  a  Local  Interface  that  have  the 
          same functions. 
        • Bean  Class  –  implements  the  methods  of  the  Home  Interfaces  and  the  Component 
          Interfaces. 
        • Deployment Descriptors – XML files that declare non‐functional aspects of an EJB such 
          as  transaction  demarcation,  persistence  mapping,  access  control,  etc.  These  files  are 
          read and interpreted  by  the  EJB  container  in  order  to  provide  the necessary services 
          for the correct hosting of the bean. 



UBLCS-2006-13                                                                                             30
                                                                                               4 The Replication Framework




                                                                   Home Interface
                           Home Interface
                                              Home                                     EJB      Server
                                              Stub                                    Home


             Client
                           Remote Interface




                                                                   Remote Interface
                                                                                                    Bean
                                              Remote                                   EJB
                                                                                               Implementation
                                               Stub                                   Object




                                              Figure 4.3 The Home and Remote Interfaces
    Creation Methods are defined in the Home Interface. They are used to create new instances of 
Enterprise Java Beans. Creation Methods are implemented by the bean class. Finder Methods are 
used to find specific instances of Entity Beans. Each Entity Bean instance has a unique primary 
key. Finder methods are implemented by the Bean Class for BMP Entity Beans. For CMP Entity 
Beans,  finder  methods  are  declared  in  the  deployment  descriptors  using  the  EJBQL  language, 
which is basically SQL for Enterprise Java Beans. 
     
    An  EJB  container  may  perform  caching  of  the  beans.  Enterprise  Java  Beans  may  be 
passivated by the EJB container in order to free up memory. Passivating a bean involves making 
the  bean  release  all  its  resources  and  storing  the  bean’s  state  to  a  persistent  storage.  In  many 
implementations  the  actual  object  instance  is  held  in  memory  and  disassociated  from  any 
identity so it can be used to host another EJB of the same type. Before a bean gets passivated, 
the ejbPassivate() method is invoked on the bean. The bean implementation must release 
all its resources in this method (for example it could close open sockets or JDBC connections). 
After this the container will serialize the state of the bean and put it in some persistent storage. 5  
When a bean is needed again it will be loaded by the EJB container, which will then invoke the 
bean’s ejbActivate() method. 
    In order to access a bean a client must first obtain a reference to the home interface of that 
bean.  This  is  done  using  the  naming  service.  In  J2EE  the  naming  service  is  the  JNDI  service. 
JNDI  associates  EJB  references  to  human  readable  names.  References  are  organizes  into  a 
hierarchical structure of naming contexts. For this reason we refer to the information contained 
in  the  JNDI  service  as  the  JNDI  Tree.  What  is  actually  obtained  is  a  reference  to  the  home 
interface of an EJB. 

4.1.2      Transactions 
   In J2EE transactions are exposed to the application through the JTA interface. This interface 
enables the application to begin, suspend, resume, commit and abort transactions.  
   There  are  two  ways  to  control  transactions  in  J2EE:  Bean  Managed  Transactions  and 
Container  Managed  Transactions.  In  Bean  Managed  Transactions  (BMT)  transactions  are 
demarcated  in  a  programmatic  way.  In  other  words  it  is  the  application  that  invokes  the 
Transaction  Manager  to  begin,  commit  or  abort  transactions.  In  Container  Managed 

5
  For Entity Beans storage actually happens before invoking the ejbPassivate() method and loading after the
ejbAcivate() method.
UBLCS-2006-13                                                                                                          31
                                                                             4 The Replication Framework

Transactions (CMT) transactions are demarcated in a declarative way through the deployment 
descriptor. The deployment descriptor defines a transaction attribute for each method of a bean. 
Transaction attributes specify to the container whether a transaction should be started and they 
can be: 
        • Required  –  if  the  method  is  invoked  without  a  transaction,  the  container  will  create 
          one, otherwise it will use the existing transaction 
        • RequiresNew – the container creates a new transaction in any case 
        • Mandatory – requires that a method is invoked within a transaction, if there is not any 
          an exception is thrown 
        • NotSupported  –  if  the  method  is  invoked  within  a  transaction,  the  container  will 
          suspend that transaction while invoking the method 
        • Supports – can be invoked with or without a transaction, the container does nothing 
        • Never – requires that the method is invoked without a transaction, if there is one and 
          exception is thrown 
    There  are  a  couple  of  crucial  aspects  of  transaction  demarcation  that  are  important  to 
understand.  The  only  kind  of  transactional  beans  are  Entity  Beans.  Being  transactional  means 
that the state of a bean acts as a resource coordinated in the transaction. If the transaction aborts 
the  state  of  a  transactional  bean  is  reverted  back  to  what  it  was  before  the  beginning  of  the 
transaction.  Session  Beans  are  not  transactional.  If  a  Stateful  Session  Bean  gets  modified  in  a 
transaction, and later that transaction aborts, the state will not be reverted. 
    On  the  other  hand,  Entity  Beans  cannot  control  transactions  in  a  programmatic  way.  Only 
Session Beans are allowed to explicitly control transactions. The only way for an Entity Bean to 
control transactions is through the transaction attributes. To fully understand this design choice 
lets see how entity beans are persisted. Loading and storing the state cannot be done during the 
invocation of a bean method. Commit Options (A, B, C) 
    Before the container invokes a business method of an Entity Bean, it must make sure that the 
state  of  the  bean  is  up‐to‐date.  Bringing  the  state  of  a  bean  up‐to‐date  may  involve  loading  it 
from  the  database.  In  order  to  enable  a  transaction  manager  to  manage  the  state  of  a 
transactional  bean,  we  must  perform  loading  and  storing  of  that  bean  within  a  transactional 
context. So the transaction must be started before the bean is loaded from the database, which 
must be done before the bean is invoked. Thus the transaction must be created before invoking 
the bean. The same applies for storing a bean after the method execution. Storing the state of a 
bean which was modified within a transaction must be done before committing the transaction. 
In other words committing (or aborting) the transaction must be done after storing the state of a 
bean in a database, which in turn must be done after invoking the method. 
    If we want to create transactions from within a bean method, then that beans state must not 
participate in the transaction. For this reason Stateful Session Beans are not transactional. BMT 
Session  Beans  and  transactional  Entity  Beans  complement  each  others  in  terms  of  interaction 
types with the transaction manager: 
                                               Session Beans         Entity Beans 

                               Allow BMT              Yes                 No 

                           Transactional              No                  Yes 

    

UBLCS-2006-13                                                                                               32
                                                                             4 The Replication Framework

     Even if Session Beans are not transactional, there is a way to coordinate a Session Bean with 
a  transaction.  This  can  be  done  through  the  SessionSynchronization  interface. A  Session 
Bean  that  implements  this  interface  is  notified  of  the  event  of  a  transaction.  The  interface  has 
three methods a session bean must implement: 
        • afterBegin() – this method is invoked before invoking the first business method of 
          a bean within a transactional context 
        • beforeCompletion() – if a session bean has been invoked within a transaction, this 
          method gets invoked before committing that transaction 
        • afterCompletion(boolean status)  –  this  method  is  invoked  after  the 
          completion of a transaction on any stateful session bean that was invoked within that 
          transaction. The status indicates whether the transaction committed (true) or aborted 
          (false). 
   Implementing the SessionSynchronization interface enables a Stateful Session Bean to 
imitate a transactional resource. For example the bean might load its state from the database in 
the  afterBegin()  method,  store  the  state  of  mark  the  transaction  to  be  aborted  in  the 
beforeCompletion()  and  finally  revert  any  changes  if  the  status  indicates  false  in  the 
afterCompletion() method. 
   Even  if  stateless  session  beans  have  no  state  to  manage.  A  stateless  session  bean  might 
implement the SessionSynchronization interface, because they may define the scope of a 
transactions.  On  the  other  hand,  BMT  Session  Beans  do  not  require  implementing  it  because 
they are in control of the transaction and are aware of when the transaction is about to commit 
and what will be the outcome of the transaction. 

4.2        JBoss Application Server Internals 
    Replication has to deal with several parts and aspects of an application server that are often 
buried deep inside the implementation. The first requirement of our application server of choice 
was  that  it  had  to  be  open  source,  so  we  could  reach  its  internals.  The  other  aspect  we  have 
considered  important  is  the  modularity  of  the  design,  i.e.  how  difficult  would  be  to  integrate 
new  behavior  into  the  existing  code.  Finally  the  application  server  needed  to  be  a  stable  and 
well  documented  piece  of  software  to  provide  a  solid  basis  from  which  to  start  building  our 
replication algorithms. 
    Our choice fell on the JBoss Application Server because it seemed to be the one most closely 
fulfilling  all  of  our  requirements.  Among  the  open  source  servers  that  we  took  into 
consideration JBoss was the most stable. 

4.2.1      JBoss Interceptors 
    For  each  deployed  EJB  there  is  an  EJB  container.  The  EJB  container  is  responsible  for 
managing the instances of an EJB. 
    The EJB container delegates most of its tasks to the container plug‐ins. These plugins handle 
different  aspects  of  EJB  management  such  as  instance  pooling,  caching,  persistence,  etc.  The 
container itself only connects the various plugins. 
    There are four types of container plugins: 
        • Interceptors  –  Interceptors  intercept  invocations  towards  EJBs.  There  are  several 
          Interceptors for each container configuration. Interceptors are connected to each other 
          forming a chain of interceptors. Each interceptor of the chain is responsible of dealing 


UBLCS-2006-13                                                                                               33
                                                                              4 The Replication Framework

          with one specific aspect such as checking security, associating transactions, accessing 
          the InstanceCache, etc. 
        • InstanceCache – this holds the set of EJB instances that are associated with an identity. 
          The Instance Cache is also responsible of activating and passivating EJBs that are not 
          in  the  cache.  If  an  EJB  is  requested  that  is  not  in  the  cache,  the  cache  will  use  the 
          InstancePool to get a free instance and the PersistenceManager to activate the instance. 
        • InstancePool  –  Instance  pooling  is  a  technique  for  improving  performance  of  EJB 
          management. A set of EJBs that are not associated with any identity is maintained in 
          memory. This avoids the latency of creating and initializing a new bean instance each 
          time it is needed. 
        • PersistenceManager  –  the  persistence  manager  is  responsible  of  creating,  removing, 
          loading,  storing,  activating  and  passivating  beans.  There  are  different  Persistence 
          Managers for CMP Entity Beans, BMP Entity Beans, Stateful Session Beans, etc. 
   Let’s take a look at some of the interceptors of the EJB container for CMP 2.x Entity Beans:  
        • SecurityInterceptor – this interceptor verifies the permissions of the client to invoke the 
          method of the bean. 
        • TxInterceptorCMT  –  this  is  the  interceptor  responsible  for  managing  transactions  for 
          CMT beans. It verifies the transaction attribute of the invoked method and, if required, 
          creates  a  new  transaction  by  invoking  the  Transaction  Manager.  Any  transactional 
          context is propagated through the invocations to the next interceptors. 
        • EntityLockInterceptor  –  acquires  a  lock  on  the  target  bean.  The  interceptor  delegates 
          actual  locking  to  the  pluggable  locking  policy.  There  are  two  locks  that  are  acquired 
          when accessing a bean: the method lock and the transaction lock. The method lock is 
          an  exclusive  lock  that  ensures  that  there  are  no  other  threads  accessing  the  bean 
          concurrently.  The  transaction  lock  resolves  conflicts  between  concurrent  transactions 
          accessing  the  same  bean.  The  transaction  lock  can  implement  different  kinds  of 
          locking  policies.  JBoss  provides  implementations  for  pessimistic  locking  at  the 
          application server level and optimistic locking at the database level. 
        • EntityInstanceInterceptor  –  this  interceptor  retrieves  the  correct  Entity  Bean  instance 
          from the Instance Cache. 
        • EntitySynchronizationInterceptor – this interceptor loads and stores the state of the bean 
          through the Persistence Manager. Even if the bean has already been activated by the 
          Instance Cache in the EntityInstanceInterceptor is responsible of keeping the state of 
          the  bean  up‐to‐date.  In  presence  of  a  transactional  context,  this  interceptor  does  not 
          store the bean state immediately but registers a callback that will store the state of the 
          bean on transaction commit. 
   These  do  not  include  all  the  interceptors  of  an  Entity  Bean  container.  Containers  for  other 
types of beans have different interceptors. 




UBLCS-2006-13                                                                                                 34
                                                                           4 The Replication Framework




                             Figure 4.4 Client and Server Side Interceptors
     
    For  remote  invocations,  JBoss  has  also  client  side  interceptors.  Client  side  interceptors  are 
encapsulated  in  the  dynamic  proxy  object  that  is  automatically  downloaded  by  the  remote 
client when doing JNDI lookup prior to performing RMI invocations. They are executed on the 
client machine and perform all the necessary tasks to prepare a request to be transferred to the 
server. These tasks include packaging of security information and transactional context into the 
request. 
     
    We have made use of JBoss interceptors to integrate our replication logic into the server. 
     

4.3       Application Server Abstraction Layer 
    Section  4.2  gives  a  very  simplified  picture  of  the  internals  of  the  application  server. 
Replication is very difficult to implement on such a complex piece of software. For this reason, 
we have decided to define higher level primitives that would expose all the functionality of the 
server that is relevant to replication algorithms. 
    Another  reason  for  creating  higher  level  primitives  was  to  decouple  the  interface  from  the 
implementation.  This  makes  possible  other  implementations  of  our  framework  based  on 
different application servers. In this way any replication algorithm designed for our framework 
could be used with any application server that implements our framework. 
    The concept of interceptors is used as the basis of our framework. We define a different kind 
of interceptors similar to the ones JBoss already uses. 

4.3.1     Intercepting Invocations 
   In  our  framework,  the  two  objects  corresponding  respectively  to  the  client  side  interceptor 
and the server side interceptor are the Client Component Monitor (CCM) and the Component 
Monitor  (CM).  The  CCM  and  the  CM  are  just  interfaces  and  any  replication  algorithm 
developed  using  the  framework  must  implement  them.  The  interfaces  have  methods  that  get 
invoked before a component is invoked. 
   The Client Component Monitor is able to intercept every invocation of the client towards the 
server. More precisely:  
        • Creations of new component instances 
        • Invocations of finder methods 
        • Invocations of the methods of a component 
        • Removals of component instances 
UBLCS-2006-13                                                                                             35
                                                                        4 The Replication Framework

   For  each  type  of  these  interceptions,  the  Client  Component  Monitor  must  implement  a 
specific method. The parameters of the interception method include a reference to the invoked 
component and the parameters passed by the application. These references are used to pass the 
invocation further down the interceptor chain. 
   On  the  server  side  the  situation  is  a  bit  more  complicated.  We  are  intercepting  every 
invocation to every bean. Beans may invoke each other. The consequence of this is that a single 
remote  request  may  generate  a  whole  tree  of  invocations.  There  is  only  one  instance  of  the 
Component Monitor at the server side and it will intercept every one of the invocations forming 
the tree.   


                                                    invocation tree



                remote invocation                  Server



            Client




                                                 local invocations

                                           Figure 4.5 Invocation Tree
   Furthermore  some  replication  algorithms  need  to  intercept  an  invocation  before  a 
component has been resolved and before a transactional context has been set. 6  Because of this 
we  provide  multiple  interception  points  at  the  server  side.  So  we  need  to  provide  also  a 
mechanism for this “early” interception of invocations, which we call preprocessing. 




6        See below Cookie Replication Protocol
UBLCS-2006-13                                                                                         36
                                                                          4 The Replication Framework




                                Figure 4.6 Multiple Interception Points
   More precisely a Component Monitor is able to intercept: 
        • Creations of new components 
        • Invocations of component instances before the component instance has been resolved 
          and  before  the  transactional  context  has  been  set.  This  enables  the  replication 
          algorithm to preprocess invocations. 
        • Invocations  of  component  instances  after  the  component  instance  has  been  resolved 
          and the transactional context has been set. 
        • Invocations of finder methods 
        • Removals of component instances 
        • Invocations performed towards another server. 
   Like in the Client Component Monitor, when intercepting an invocation on the server we are 
provided  with  a  reference  to  the  invoked  component  and  the  invocation  parameters.  On  the 
server  side,  the  references  to  components  are  not  only  used  to  pass  the  invocations  further 
down  the  interception  chain,  but  can  be  also  used  to  perform  various  operations  on  the 
components. 

4.3.2     Handling Components 
    The invoked components can be EJBs or Axis web services. For the purpose of this thesis we 
will  ignore  the  Axis  web  services  although  the  framework  supports  them.  The  framework 
defines a component handle object which represents an underlying EJB. The component handle is 
a unique interface that represents any kind of Enterprise Java Bean (a stateless session bean, a 
stateful session bean or an entity bean). It provides the replication algorithm developer with a 
simpler  view  of  the  system.  Anyway  the  component  handle  object  exposes  methods  for 
discovering whether the underlying object is an entity bean a stateful session bean or a stateless 
session bean. 
    A component handle uniquely identifies an instance of an EJB. In case of an entity bean the 
identifier  of  the  component  handle  corresponds  to  the  primary  key  of  the  bean.  In  case  of  a 
stateful session bean, it is the session id. 


UBLCS-2006-13                                                                                           37
                                                                              4 The Replication Framework

    A component handle may be serialized and transmitted between servers. But transmitting a 
component handle to another server does not transmit the state of that component. When used 
on another server, it will refer to the local copy of the component instance. As a consequence, it 
is also possible that a component handle doesn’t have an associated component instance if that 
component has not been instantiated on the current server. Anyway, that component handle can 
be used to create a local instance of the component. 
    Component handles also support comparison: two component handles test equal if and only 
if they refer to the same component instance. 
     
    It  is  possible  to  obtain  detailed  information  on  the  type  (class)  of  the  EJB  through  the 
component handle. The number of types depends on the applications deployed on the server. 
There  is  one  for  each  deployed  bean  and  web  service.  Access  to  the  underlying  java  object 
implementing the EJB is not provided. Instead, a serializable representation of the state of the 
EJB is provided. 
    The component handle also provides methods to test whether a component is stateful, and 
to  get  and  set  the  state.  In  the API,  the  state  of  a  component  is  an  opaque  serializable  object, 
which can be sent between replicas. 

4.3.3      Requests and Responses 
   All  methods  of  the  objects  representing  requests  and  responses  get  passed  along  the 
invocation chains. These objects carry information about the invocation such as the identifier of 
the component being invoked, the method being invoked and the parameters. Along with this 
standard  information  request  and  response  objects  carry  a  set  of  headers  which  contain 
additional information specific to the replication algorithm. These headers for example may be 
used to transmit information about the transactional context of the current invocation. 
   Responses may be of four types:  
        • EJB  response  –  is  the  response  returned  by  a  successful  execution  of  an  EJB  method. 
          The component monitor should return this response from the call method. 
        • Create  response  –  is  the  response  returned  by  a  create  method  of  the  home  interface. 
          This response wraps the component handle of the newly created component which 
          may be retrieved. 
        • Component  collection  response  –  response  returned  by  a  finder  method.  Wraps  the 
          collection of all the components found. 
        • Exception response – is the response retuned when there has been an exception in the 
          application. 
   In  case  of  an  exception  response  the  response  object  wraps  an  exception  raised  while 
processing the request. There are three types of exceptions: 
        • Application – This exception is raised by the EJB, in general it should be forwarded to 
          the application as it is. 
        • System –  This  is an exception  caused  by  the  server,  these  kinds  of  exceptions are  the 
          ones we are trying to mask. Most replication algorithms will catch this exception and 
          try another server. 
        • Replication  –  This  is  an  exception  raised  by  the  replication  algorithm.  Whether  and 
          how to handle it is specific to the replication algorithm. 
   Having different types of exceptions, enables us to elegantly deal with system failures and 
transparently pass application level exceptions to the upper layer. 
UBLCS-2006-13                                                                                                 38
                                                                        4 The Replication Framework

4.3.4     Transaction Interception 
   Transactions  are  an  important  aspect  that  needs  to  be  considered  when  designing  a 
replication algorithm. Unwarily combining replication and transaction may lead to unexpected 
behavior that may break consistency of the computation. For this reason a replication algorithm 
needs to have a way of knowing and controlling what is happening at the transaction manager 
level. 


                                                  Bean Managed
                                                   Transactions
                                                                  Container Managed
           Client
                                                                    Transactions




                                                       Transaction Interceptor


                                                      Transaction Manager


                                 Figure 4.7 Transaction Interception
    We  supply  this  information  to  the  replication  algorithm  through  the  use  of  transaction 
interceptors. In the programming model of the framework the replication algorithm may define 
a transaction interceptor factory. For transaction started at the application server, the transaction 
interceptor  factory  will  be  asked  to  create  a  transaction  interceptor  object.  The  transaction 
interceptor will intercept all the invocations to its associated transaction, just like the component 
monitor does for EJBs. The methods that a transaction interceptor must implement are: 
        • commit()  –  invoked  when  the  application  server  or  an  EJB  wants  to  commit  a 
          transaction 
        • abort() ‐ invoked when the application server or an EJB wants to abort a transaction 
        • suspend()  ‐  invoked  when  the  application  server  or  an  EJB  wants  to  suspend  a 
          transaction 
        • resume()  ‐  invoked  when  the  application  server  or  an  EJB  wants  to  resume 
          transaction previously suspended 
     The operations above are quite straightforward to understand. This mechanism enables the 
replication algorithm for example to replicate the changes of a transaction when that transaction 
is  committed.  There  are  more  sophisticated  ways  of  using  these  methods  as  we  will  see  in 
Chapter 5. 
     Sometimes a transaction may cross the boundaries of the application server. For example a 
bean,  when  invoked,  could  start  a  new  transaction  but  not  complete  it  before  returning  the 
result to the client. In this case the transaction context will be propagated to the client and the 
next  invocation  the  client  performs  will  be  executed  in  the  same  transaction.  Transaction 
interceptors also need to intercept transactional contexts that are crossing the boundaries of the 
UBLCS-2006-13                                                                                         39
                                                                             4 The Replication Framework

server. Each time a transactional context leaves the server (by being attached to a response or to 
a  request  to  another  server)  the  associated  transaction  interceptor  will  be  notified.  The  same 
happens  for  transactional  contexts  that  are  entering  the  server,  but  the  one  who  is  notified  in 
this  case  is  the  transaction  interceptor  factory  because  there  might  not  be  a  transaction 
interceptor associated to that transactional context. This can happen in the case the transaction 
was created outside the server (the client or another replica).

4.4        The Building Blocks  
    Several  replication  algorithms  are  just  variations  of  the  same  basic  principles.  Others  are 
based on a different approach but still share a part of the solutions to some common problems 
of  replication.  Based  on  extensive  study  of  replication  algorithms  we  have  extended  our 
framework with some basic tools that implement many aspects of replication. These tools come 
in  the  form  of  building  blocks  that  may  be  combined  to  obtain  fully  featured  replication 
algorithms.  Each  building  block  is  in  charge  of  a  particular  aspect  of  replication.  For  example 
we  have  blocks  that  collect  the  state  of  the  modified  components,  blocks  that  maintain  the 
cluster view up‐to‐date, blocks that carry out fail‐over, blocks that deal with multicast, etc. The 
blocks we supply as part of the framework are sufficient for the implementation of a number of 
replication  algorithms.  New  blocks  can  be  created  from  scratch  or  by  extending  the  existing 
ones.  In  fact  most  of  the  building  blocks  of  the  framework  are  designed  to  be  extended  and 
customized. 

4.4.1      Chain of Interceptors 
    Since  we  have  chosen  invocation  interception  to  be  the  primary  way  of  implementing 
replication algorithms, most of our building blocks are indeed interceptors. More precisely they 
are all subclasses of the component monitor. They are combined by chaining them to each other. 
In  this  way  the  first  one  processes  a  request  and  executes  its  own  task  and  then  forwards  the 
request  the  next  interceptor.  Each  of  the  server  interceptors  of  this  chain  has  a  client  side 
counterpart. These counterparts form another chain on the client. 




                                     Figure 4.8 Chain of Interceptors
    The easiest way to construct the chain of interceptors is to implement an interceptor that will 
be  the  head  of  the  chain  and  that  will  initialize  all  the  other  interceptors.  Every  interceptor’s 
constructor  takes  the  next  interceptor  as  parameter.  In  this  way  the  interceptors  know  where 
they should forward requests to. 



UBLCS-2006-13                                                                                                40
                                                                           4 The Replication Framework

   Client  side  interceptors  are  built  in  a  similar  way.  For  performance  reasons,  a  server  side 
interceptor may forgo providing its client side complement, as a result the client side chain does 
not have to be isomorphic to the server side one. 

4.4.2     Collecting Changes 
   As we said earlier a remote invocation may produce a tree of invocations between beans on 
the  server.  Some  replication  algorithms  broadcast  the  state  of  a  bean  to  the  backups 
immediately  after  the  execution  of  a  method  of  that  bean  [44].  Some  other  replication 
algorithms,  for  performance  and  consistency  reasons,  broadcast  the  state  of  all  the  modified 
beans  after  the  execution  of  the  whole  invocation  tree  or  when  committing  a  transaction. 
Regardless of what is the best approach, we provide means to collect the state of the modified 
beans. 
   The purpose of collecting the changes is to identify all the consequences of the execution of 
the remote request on the state of the server. As we will se in Chapter 5, depending on what we 
consider the state of the application server to be, there may be different changes collectors. We 
provide a basic building block that implements collecting the state of all the modified beans. 
   The ChangesCollectorInterceptor will intercept every invocation to a bean and keep 
track of modified, created and deleted beans. Information about these modifications is kept in 
the bean changes data structure that is associated to the current thread. Since in an application 
server there can be multiple threads processing different remote requests, there will be different 
bean changes data structures. But there will always be exactly one bean changes structure per 
remote request. 




                                                Server




            Client




                                                              BeanChanges



                                     Figure 4.9 Collecting Changes 
    
   The BeanChanges data structure contains information about the following modifications: 



UBLCS-2006-13                                                                                            41
                                                                               4 The Replication Framework

        • Creation  –  for  each  created  bean  there  is  an  entry  which  includes  the  bean  identifier 
          and the state of the created bean. 
        • Modification  –  for  each  modified  bean  there  is  an  entry  which  includes  the  bean 
          identifier and the state of the bean after the modification. 
        • Deletion – for each deleted bean there is an entry which includes only the identifier of 
          a bean. 
    All these modifications are collected in order to apply them on a backup and have the same 
state of the server as it is on the primary. 
     
    Formally  we  define  the  changes  collector  to  be  comprised  of  two  functions:  the  collect 
function  that,  given  an  initial  state  of  the  server  and  a  set  of  invocations,  produces  the  bean 
changes  structure;  and  the  apply  function  that  given  an  initial  state  of  the  server  and  a  bean 
changes  structure,  produces  a  new  state  of  the  server.  In  the  same  way  we  must  define  the 
execute function that given a state of the server, and a set of invocations produces a new state. 
We don’t give a generic definition of the state of the server and the operations, because different 
replication algorithms may have different representations of the server state. 
     
    Definition (Changes Collector Correctness): Let t be the tree of invocations executed on a 
server  in  state  S  and  let  c  be  the  changes  data  structure  produced  by  the  execution  of  t.  A 
changes collector cc=(changes, apply) is correct if: 
                                                             
                           execute(t, S) = S’ ⇒ apply(c, S) = S’, where c = changes(t, S) 
                                                             
    Basically this means that applying the changes on the backup will produce the same effect 
that  the  execution  of  the  invocation  tree  did  on  the  primary.  Notice  that  we  have  used  “⇒” 
instead of “⇔”. This is because we consider the execute function to be non‐deterministic, as it is 
the  case  in  the  real  world.  The  execution  of  a  method  on  a  bean  doesn’t  always  produce  the 
same final state. 
    In  particular  if  we  consider  the  tree  of  invocations  to  be  the  one  generated  by  the  remote 
request  of  the  client  r.  Then  our  property  states  that  applying  the  changes  generated  by  the 
execution of a remote request on the backup produces the same state. 
    Our  basic  implementation  of  the  changes  collector  works  like  this:  each  time  a  bean  is 
modified,  the  changes  collector  adds  the  state  of  the  bean  to  the  changes  data  structure, 
overwriting  any  previous  change;  if  a  bean  is  created  the  relative  entry  is  put  in  the  changes 
data  structure  along  with  the  state  of  the  created  bean;  finally  if  a  bean  is  deleted,  a  relative 
entry for the deletion is put in the changes data structure. 
    By  defining  the  state  of  the  server  to  be  a  set  of  components  each  with  its  own  state  and 
properly  defining  the  operations  that  may  be  performed  on  the  beans,  it is straightforward  to 
prove that our changes collector fulfills the correctness criteria. The proof of correctness of the 
changes  collector  is  rather  long  due  to  the  formalisms  used,  but  intuitively  it  is  very  simple. 
Since the basic changes collector is not used in the algorithms studied in this thesis we will omit 
the correctness proof here. 

4.4.3      Interchangeable Group Communication 
   Most  replication  algorithms  are  based  on  some  form  of  group  communication.  There  are 
several  off‐the‐shelf  group  communication  packages  that  come  with  different  features.  Our 
framework includes support for group communication software by abstracting the primitives of 
UBLCS-2006-13                                                                                                  42
                                                                         4 The Replication Framework

the group communication layer. We define a minimalist API that is supposed to be used by the 
replication algorithm and implemented by the group communication toolkit. 
   This API is made of three classes: 
        • GCL – it is the abstraction over the group communication channel and provides a way 
          to  send  and  receive  messages  to/from  the  group.  Moreover  it  provides  the  way  of 
          getting the current view of the cluster. Different group communication packages may 
          implement this interface providing different features and guarantees. 
        • View – The view is essentially the information that the current host has about the other 
          members  of  the  group.  Depending  on  the  underlying  implementation,  this 
          information may be more or less exact. A view contains the list of the current members 
          of the group plus a view identifier. Each time there is a view changes (i.e. a member 
          joins or leaves the group) a new identifier will be assigned to the new view. The same 
          view should have the same id for each member of the group. 
        • ServerAddress  ‐  this  is  the  information  associated  to  one  member  of  the  group.  It 
          uniquely identifies a member and encapsulates all the information needed to contact 
          this member such as IP address, JNDI port the server is listening to, web port, etc. 
   The  group  communication  layer  may  implement  different  forms  of  broadcast  semantics. 
Each  replication  algorithm  will  require  a  different  form  of  replication  semantics.  In  general 
primary‐backup replication will require at least FIFO ordering while multi‐primary  replication 
will require total ordering. Broadcast semantics may be specified in the following way: 
   Reliable broadcast is defined by  these three properties: 
        • Validity:  if  a  correct  process  broadcasts  a  message  m,  then  all  correct  processes 
          eventually deliver m 
        • Agreement:  if  a  correct  process  delivers  a  message  m,  then  all  correct  processes 
          eventually deliver m 
        • Integrity: for any message m, every correct process delivers m at most once, and only if 
          m was previously broadcast by sender(m). 
   A reliable broadcast may have any of the following ordering properties: 
        • FIFO: if a process broadcasts a message m before it broadcasts a message m’, then no 
          correct process delivers m’ unless it has previously delivered m 
        • Causal: if the broadcast of a message m causally precedes the broadcast of a message 
          m’, then no correct process delivers m’ unless it has previously delivered m 
        • Total: if correct processes p and q both deliver messages m and m’, then p delivers m 
          before m’ if and only if q delivers m before m’ 
     
    Along  with  the API,  we  also  provide  three  different  implementations  of  the  GCL  interface 
based on three group communication packages. 
     
    JGroups  is  the  reliable  multicast  toolkit  used  by  the  default  clustering  implementation  of 
JBoss.  It is based on a configurable protocol stack. Each layer of the stack provides a part of the 
quality  of  service  properties  guaranteed  by  the  protocol  stack  as  a  whole.    JGroups  includes 
layers that provide lossless transmission (NAKACK & STABLE), FIFO ordering, total ordering, 
virtual synchrony, etc. 
     


UBLCS-2006-13                                                                                          43
                                                                             4 The Replication Framework

    JBora [59]  is  a  Java  wrapper  for  the  Spread  [60]  communication  toolkit.  Spread  is  a  toolkit 
implemented in C that provides reliable total ordered broadcast. Spread uses a daemon‐client 
architecture. There can be multiple interconnected daemons and each client is connected to one 
of the daemons. Spread integrates two low‐level protocols: one for local area networks between 
clients connected to the same daemon (Ring), and one for the wide area network connecting the 
daemons (Hop). Spread supports the Extended Virtual Synchrony model [61]. 
     
    Wandisco  DCone  [63]  is  a  replication SDK  based  on  an  algorithm  derived  from  Lamport’s 
Part Time Parliament consensus algorithm [62], better known as the Paxos algorithm. Layered 
on top of the algorithm, is a replicated state machine abstraction. No central coordinator is used. 
A  flexible  notion  of  quorum  maximizes  availability  when  the  system  encounters  failures.  The 
distributed recovery protocol, which is integrated into the core algorithms, is provably correct 
under any kind of failure scenario. 
     
    The  correctness  criteria  of  group  communication  is  defined  according  to  the  provided 
semantics.  We  have  used  existing  group  communication  implementations  which  have  been 
proven by their authors to provide the stated semantics. 

4.4.4      Load Balancing and Failover 
    The purpose of most replication algorithms is to provide fault‐tolerance. Passive replication 
based  algorithms  achieve  this  by  making  the  client  perform  failover.  To  failover  means  that  if 
the server that the client has sent the request to does not process the request correctly, the client 
re‐issues that request to another server. 
    The  other  major  reason  why  someone  wants  to  use  replication  is  for  distributing  the  load 
between  the  various  servers.  This  technique  is  called  load‐balancing  and  involves  making  the 
clients send requests to different servers. There are numerous strategies for selecting the server 
which to send the request to and they represent different compromises between simplicity and 
uniform distribution of the load. In most cases load balancing can be combined with fail‐over to 
attain fault‐tolerant distributed processing. 
    Both of these techniques require that the client knows who the members of the cluster are. 
Assuming that the servers know what is the view of the cluster, there is a simple algorithm for 
keeping this information up‐to‐date on the client. The client will have its own copy of the view 
of the cluster. On each request it makes, the client will attach as a header the id of its view. The 
server  will  compare  this  id  with  its  own  view  id  and,  if  they  differ,  it  will  send  the  updated 
view along with the response. 
    So far we know how to keep the view on the client up‐to‐date, but this seems like an egg and 
chicken  problem.  In  other  words,  how  does  the  client  get  the  view  for  the  first  time? At  this 
level  of  abstraction,  there  is  no  way  for  the  client  to  build  a  view  without  any  initial 
information.  Algorithm  designers  usually  call  problems  like  this  implementation  details,  but 
often  these  problems  are  more  difficult  to  solve  than  the  problem  solved  by  the  actual 
algorithm. 
    In our case this task is relayed on the JBoss implementation. Some low level techniques are 
used to obtain the first copy of the view. The view is downloaded the first time from the JNDI 
server along with the client stub and all the client side interceptors. Actually each server of the 
cluster hosts a JNDI service, so again we have to know how to contact a JNDI server and what 
to do if the JNDI server we contacted does not work. There is a configuration file on the client 
that contains the list of the servers. The InitialContext that is used to access the JNDI tree 
will try the servers from this list one by one until it gets a reply. If no server can be contacted or 
UBLCS-2006-13                                                                                                44
                                                                           4 The Replication Framework

the list in the configuration file is empty a message will be broadcast on the LAN to find out if 
there are any JNDI servers. Thus every server will listen to these broadcast messages and reply 
accordingly. 

4.4.5      Replicator 
    Now the servers are able to communicate with each other, the client knows how to fail‐over 
to  another  server  and  we  know  what  changes  to  broadcast.  The  only  thing  remaining  is  to 
broadcast these changes and of course make the other servers receive them.  
    This task is accomplished by the Replicator. This is the most important part of a replication 
algorithm since it is the one that decides when changes will be replicated and how. A replicator 
may decide to replicate on each local invocation, on transaction commit or on remote request. 
The replicator also may decide whether to use the group communication layer, the database or 
some other medium to store the changes. 
    We provide a basic implementation of a replicator that performs replication on each remote 
request  and  uses  the  provided  group  communication  layer.  Our  implementation  is  called 
GCLReplicator. After the execution of each remote request the GCLReplicator broadcasts 
the changes that were collected by the changes collector during the execution. 
    The  GCLReplicator  takes  also  care  of  starting  the  Receiver.  The  receiver  is  a  thread  in 
charge  of  receiving  changes  from  the  other  servers  and  applying  them  locally.  Actually  the 
Receiver  treats  the  changes  as  a  black  box,  that  is  applying  the  changes  is  left  to  the  bean 
changes  data  structure.  In  this  way  the  BeanChanges  class  can  be  extended  and  there  is  no 
need to change the Receiver. In Chapter 5 we’ll see how we took advantage of this design choice 
in order to perform transaction replication. 
     
    In order to ensure correct ordering of broadcasts, each time a bean is accessed a lock is put 
on  it,  and  that  lock  is  released  only  when  the  changes  are  broadcast  to  the  backups.  We  call 
these r‐locks. The r‐lock is associated to the remote request and is orthogonal with other locking 
mechanisms used in the underlying server. This is needed for the correct ordering of changes. 
Assume  there  are  two  concurrent  remote  requests  on  the  server  r1  and  r2.  They  both  access 
component  x.  Say  for  example  r1  accesses  x  and  stores  the  state  in  its  bean  changes,  then  r2 
accesses  x  and  stores  the  newer  state  in  its  bean  changes.  But  suppose  now  that  r2  finishes 
before r1 and broadcasts the changes, then r1 broadcasts the changes as well. The backup will 
receive the changes of r1 after r2, and the state of x in the changes of r1 will overwrite the one 
from the changes of r2. But that is not the most recent state. So in order to maintain the correct 
ordering of changes on the backup we need to lock the component until its changes have been 
broadcast. 
    Notice that we could have performed this ordering even on the backup, but in that case, if 
the primary failed between sending the two messages, it would be much more complicated to 
restore the correct state. Another option would have been to delay sending the changes until all 
causally preceding changes were not sent, but if there was a cycle in the dependence graph, we 
wouldn’t know which changes to send first. 
     
    Each time the replicator broadcasts the bean changes, it attaches also the request id and the 
response to the message. In this way, if the primary crashes before sending the response to the 
client, the backups know that the request has been processed and what is the response expected 
by the client. If a server at any time receives a request that has already been processed by an old 
primary,  it  will  return  the  respective  response  back  to  the  client  without  re‐executing  the 

UBLCS-2006-13                                                                                             45
                                                                                       4 The Replication Framework

request. In theory this could lead to servers having very long lists of responses, but in practice 
cached responses may expire after a reasonably long timeout. 
      
     Before returning the response to the client the server needs to be sure that the results have 
been  received  by  the  other  servers.  If  the  group  communication  package  we  use  provides 
reliable broadcast semantics then by the property of agreement we have that if one correct process 
receives message m, then all correct processes will eventually receive m.” This means that we can wait 
to receive our own message and then we can safely return the result to the client. 
     If the server does not wait to receive its own message then it would have no guarantees of 
the message delivery to the rest of the cluster. In fact the server could fail just right after sending 
the response to the client and by coincidence the message to the servers could have been lost. In 
that case the client would fail over to another server while performing the next request, but the 
state of on server would not be consistent with the state on the client, since the update was lost. 
     As a paradox, most off the shelf replicated servers use this second approach. This is because 
the latency introduced by waiting for the reliable broadcast protocol to complete is so large that 
it  does  not  pay  off  for  the  additional  consistency  guarantees.  Our  GCLReplicator  supports 
both ways of replication. In Chapter 7 we compare some performance results of synchronous vs 
asynchronous broadcast. 
      
     The replicator needs to guarantee two properties: 
         • Exactly Once Execution: every request for which a clients receives a response has been 
           executed exactly once on all the correct servers. 
         • 1‐Copy‐Serializability:  The  histories  of  all  the  backups  are  prefixes  of  a  history 
           equivalent to the history on the primary 
    
   For  exactly  once  execution  we  will  assume  that  the  client  never  crashes.  Otherwise  the 
exactly once execution doesn’t make sense. Moreover when we talk about a correct server, we 
refer to a server that has not crashed. We do not expect the crashed servers to recover. We also 
assume that the client has some form of weak failure detector that eventually detects a crashed 
server. In its initial state, the client has a list of all the correct servers 7 . 
    
   Lemma 1        If there is at least one correct server and the client does not crash, the request 
will eventually be processed at least once. 
    Proof:  First  we  will  prove  that  the  request  is  processed  at  least  once.  We  define  5  states 
associated to a single client request. These states are: 
         • Initial – no correct server has received the request. 
         • Processing – there is a correct server processing the node 
         • Processed – a node has processed the request and all the local invocations that the 
              request generated. 
         • Replicated – the changes relative to the request have been replicated on the cluster. 
         • Completed – the client has received the response 
    We start from the Initial state. The client will send a request to a node which it believes to be 
the primary node of the cluster. If the server that the client sends the request to has crashed or it 
is  not  the  primary  then  the  client  will  eventually  fail‐over  to  another  server  from  its  list  of 


7
  In practice this is achieved through a lookup for the JNDI service based on multicast, or by specifying the initial set in a
configuration file.
UBLCS-2006-13                                                                                                             46
                                                                               4 The Replication Framework

servers. If there is at least one correct server, then a server will eventually become the primary 
and the client will eventually send the request to the. If the primary receives a request from the 
client, than we move from Initial to Processing state. 
    If the node processing the request fails before having processed all the local invocations then 
we go back to the Initial state. Otherwise we will go to the Processed state. 
    When the request has been processed, we know that the changes data structure will contain 
all the changes relative to that remote request. The server will replicate the relative changes on 
the other servers. The agreement property of the underlying reliable broadcast primitive gives 
us the guarantee that the changes will be received either by all the members or by none (if the 
sender  crashes).  If  all  the  servers  have  received  the  changes,  then  it  means  that  we  are  in  the 
Replicated state. Otherwise the server has crashed and we are back in the Initial state. 
    From  the  Replicated  state  we  can  move  to  the  Completed  state  if  the  client  receives  a 
response from the server that has processed the request. Notice that if the server crashes, we do 
not go back to the initial state because the other servers have received the changes relative to the 
request. In that case the client will eventually fail over to another node and receive a response.  
     
   Lemma 2          A request will be processed at most once. 
    Proof: For proving at most once semantics we must assume that receiving changes relative to 
a request is equivalent to processing that request. Moreover we have a globally unique identifier 
for each request. 
    Now  that  we  have  constructed  the  basic  state  diagram  it  is  easy  to  prove  the  at  most  once 
semantics.  Thanks  to  its  failure  detector,  a  client  that  has  sent  a  request  to  a  node,  will  never 
send the same request to another node if the first one didn’t crash. If the node that the client has 
sent the request to has crashed and the client didn’t receive any response, then we are either in 
the Idle state or in the Replicated state. 
    If we are in the Idle state, then it is safe to send the same request to another server because 
there are no servers that have received the changes relative to that request. 
    If we are in the Replicated state, then all the nodes have received the changes relative to that 
request  which  include  also  the  request  identifier  and  the  response.  The  client  will  fail  over  to 
another server which will send back the  response relative to that request. 
     
    From combining Lemma 1 and Lemma 2 we have that: 
   Thorem 1      If there is a correct server and the client does not crash, each request will be 
processed exactly once. 
     
    The original definition of serializability [10] was based on the primitives of read and write 
operations  which  were  grouped  using  transactions.  In  a  component  based  system,  it  makes 
more sense to talk about invocations. So we need to redefine some of the fundamental concepts 
of the serializability theory: 
    Definition: Two invocations are conflicting if they are performed on the same component. 
    Definition:  The  changes  relative  to  a  remote  request  c2  are  causally  dependant  on  c1  if  c2 
contains the changes of an invocation o2 that is conflicting with an operation o1 whose changes 
are contained in c1 and o1 happens before o2. 
     
    To complete the proof of correctness we must prove that the order invocations are executed 
on the backup is serializable and equivalent to the history executed on the primary. 
     
UBLCS-2006-13                                                                                                  47
                                                                            4 The Replication Framework

   Lemma 3          The history of the primary is serializable.  
   Proof: This is achieved by the local concurrency control of the underlying application server. 
The application server uses transaction locks to fulfill the ACID properties of transactions. 
    
   Definition (R‐locks): All components invoked by a remote invocation are r‐locked until the 
changes relative to that remote invocation are propagated. A remote invocation cannot access a 
component that is r‐locked by another remote invocation. 
    
   Lemma 4       If  the  changes  c2  are  causally  dependant  on  changes  c1  in  the  history  of  the 
primary, then no backup will receive c2 before c1. 
   Proof: Assume that a backup received c2 before c1. Since we are using a broadcast with FIFO 
ordering, this means that the primary sent the c2 before c1.  
   Let r1 be the remote invocation relative to c1 and r2 the remote invocation relative to c2. If c2 is 
causally dependant on c1 then there is a component x that was accessed by the r1 before it was 
accessed by r2. This means that x was r‐locked by r1 before it was accessed by r2. But can only 
happen if the r‐lock was released before it was accessed by r2. Which means hat c1 was broadcast 
before  x  was  accessed  by  r2  which  in  turn  happened  before  c2  was  sent.  But  that  is  a 
contradiction  since  we assumed  that  the  primary  sent  c2  before  c1.  By  absurd we  have  proven 
the lemma. 
    
   From this follows: 
   Corollary of Lemma 4: If changes c2 are causally dependant on changes c1 in the history on 
the backup, then c2 is causally dependant on c1 in the history of the primary. 
    
   Thorem 2       The  histories  of  all  the  backups  are  prefixes  of  a  history  equivalent  to  the 
history on the primary 
     Proof: Let H1 be the history on the primary and H2 the history on a backup. We will start by 
proving that H2 does not contain any changes that are not in H1. A backup only receives changes 
through  broadcast  and  does  not  process  requests  directly,  otherwise  it  would  be  the  primary. 
Thus H2 does not contain any changes directly processed by the backup. All the changes in H2 
received  from  the  primary  have  been  previously  processed  by  the  primary,  so  they  are 
contained  in  H1.  If  there  was  another  primary  in  the  past,  all  the  changes  processed  by  the 
previous primary were also received by the current primary because of the agreement property 
of  the  reliable  broadcast.  This  means  that  the  changes  contained  in  H2  are  a  subset  of  the 
changes of H1. Let c2 be the latest change of H2. Since H2 is a subset of H1 then H1 also contains 
c2.  For  every  change  c1,  so  that  c2  is  causally  dependant  on  c1,  we  know  by  Lemma  4  that  H2 
contains c1. In other words all the changes in H1 that are not in H2 are not causally dependant on 
c2. 
     Let H1s be the sub‐history of changes in H1 that are not contained in H2. Since a sub‐history 
preserves the total order of its elements. All the changes in H1s preserve also the partial ordering 
defined by the causal dependence relationship. 
     Let H2e be the concatenation of H2 with H1s. H2 is a prefix of H2e. Now we need to show that 
H2e  is  equivalent  to  H1.  By  definition  of  H2e  we  have  that  H2e  and  H1  contain  the  same 
operations. 
     We must show that for any conflicting invocations o1 and o2, o1 happens before o2 in H2e if 
and only if o1 happens before o2 in H1. 

UBLCS-2006-13                                                                                              48
                                                                           4 The Replication Framework

    Suppose that o1 happens before o2 in the primary. Invocations o1 and o2 can either appear in 
the first part of the H2e history (H2) or in the second part (H1s): 
         • If o1 and o2 belong to H1s then by definition of H1s their order is the same in H1  and 
             H2e. 
         • If o2 belongs to H2 then by Lemma 4 o1 will appear before o2 in H2 and thus in H2e. 
         • If o1 belongs to H2 and o2 belongs to H1s then by definition of H2e in the primary. 
         • By Lemma 4 it is impossible that o2 belongs to H2 and o1 to H1s. 
    Now suppose that o1 happens before o2 in H2e. 
         • If o1 and o2 belong to H1s, then by definition of H1s o1 happens before o2 on H1. 
         • If o1 and o2 belongs to H2 then by the Corollary of Lemma 4 we have that o1 happens 
             before o2 on the primary. 
         • If  o1  belongs  to  H2  and  o2  to  H1s  and  we  know  that  o1  and  o2  are  conflicting,  by 
             lemma 5 it cannot be that o1 is causally dependant on o2. Thus o1 happens before o2 
             in H1. 
    We have proven that o1 happens before o2 in H1 if and only if o1 happens before o2 on H2s. By 
this we have also proven Theorem 2. 
     
    If changes c have been received by a server, then from the agreement propriety of the reliable 
broadcast we have that those changes will eventually received by all correct servers. Intuitively 
we can define our 1SR history to be the history containing the operations whose changes were 
received by at least one server. Since we have only one primary broadcasting the changes and 
we are using FIFO broadcast, we know that all the backups will have a common prefix of their 
history. So we know that in any moment there will be a backup whose history is the 1SR history. 
Having proved that the history of any backup is a prefix of a history that is equivalent to the 
history  of  the  primary.  We  can  deduce  that  also  our  1SR  history  is  a  prefix  of  a  history 
equivalent to the history of the primary. 
    If we assume that clients don’t crash, by the exactly‐once‐semantics, we know that  for any 
changes  present  in  the  1SR  history  the  relative  response  will  eventually  be  delivered  to  the 
issuing client 
     
    Now  that  we  have  provided  the  high  level  primitives  for  representing  the  internals  of  an 
application  server  and  that  we  have  defined  the  building  blocks  of  replication  algorithms,  we 
can  use  these  blocks  to  build  complex  replication  algorithms.  The  most  simple  replication 
algorithm  that  replicates  the  state  of  the  modified  beans  on  each  remote  invocation  may  be 
easily constructed by combining the building blocks presented so far. But we will skip that one 
and go on to some more sophisticated solutions. More precisely, we will explore the possibilities 
of  combining  different  forms  of  transactions  with  replication.  In  the  next  chapter  we  will 
examine the replication of flat transactions and in Chapter 6 we will apply a similar approach to 
a more complex transaction model, namely the Open Nested Transactions.




UBLCS-2006-13                                                                                             49
Chapter 5 

Transaction Replication Algorithm 

    Transactions and replication are both means for obtaining fault tolerance. Transactions are a 
backward  recovery  mechanism,  which  means  that  the  system  is  restored  to  a  previous  state 
after a failure. On the other hand, replication is a forward recovery mechanism that enables the 
system to continue performing its work even in the presence of failures. There has been some 
previous work that combined these two mechanisms  [22], which we have discussed in Section 
3.1.5.  
    But the direction in which recovery is performed is not the only difference between the two 
mechanisms.  It  is  important  to  understand  that  they  tolerate  different  kinds  of  failures. 
Consider  the  operation  of  reserving  a  seat  in  a  flight  that  is  overbooked.  A  transaction  will 
rollback an operation that is impossible to complete leaving the system in a consistent state. On 
the other side, it does not matter how many replicas we execute that operation on, it will be still 
impossible to complete. We say therefore that transactions tolerate application failures. 
    Then  again,  transactions  rely  on  system  recovery  in  case  of  a  crash.  But  sometimes  the 
system cannot recover, for example due to hardware failure. In this case replication is the right 
solution  because  this  is  exactly  the  type  of  problem  that  replication  was  designed  for.  So  we 
may consider replication as a solution to persistent failures. 
    Of  course  there  is  a  set  of  faults  correctly  handled  by  both  recovery  mechanisms.  For 
example  a  temporary  crash  of  a  process  can  be  dealt  with  by  the  recovery  mechanism  of  a 
transaction manager or by failing over to another replica. In this case we prefer the replication 
approach because it provides lower response time. 
    We  have  developed  a  replication  algorithm  that  takes  advantage  of  both  of  these 
mechanisms to deal with different fault situations. 
     
    Most  of  the  existing  J2EE  application  servers  provide  EJB  replication.  Replicating  only  the 
state  of  the  EJBs  limits  the  operations  that  are  fault  tolerant.  Some  operations  have  effects  on 
other parts of the system which are not replicated. Such is the case of the Transaction Manager. 
In fact, the execution of an operation may change the internal state of the Transaction Manager. 
By state of the Transaction Manager we refer to the state of the active transactions in the system 
which include information about the accessed objects, the transaction locks, uncommitted state 
of components etc. 
    The J2EE specifications support multiple invocations from the client that are part of the same 
transaction.  If  the  Transaction  Manager  is  not  replicated  a  client  that  fails  over  to  another 
replica, will not be able to resume the transaction started on the failed server. In order to make 
this possible, also the Transaction Manager has to be replicated. 
                                                                    5 Transaction Replication Algorithm

   The  internals  of  a  transaction  manager  are  very  complicated  and  therefore  replicating  a 
transaction  manager  is  a  very  difficult  task.  Instead  of  taking  the  burden  of  implementing  a 
replicated  transaction  manager,  we  have  found  a  way  to  replicate  transactions  using  existing 
non replicated off‐the‐shelf transaction managers. 

5.1       The Algorithm 
    The idea behind our approach is simple: we treat transactions as part of the state of a server. 
If  we  replicate  correctly  the  state  of  the  server  that  includes  transactions,  then  we  replicate 
correctly  transactions  as  well.  Although  the  approach  may  seem  too  simplistic,  it  gives  us  a 
solid base from where to start the definition of our transaction replication algorithm. 

5.1.1     The Actors 
    Our  replication  algorithm  follows  a  primary/backup  vertical  approach.  We  have  a  set  of 
servers. Each server has its own database. One of these servers is the primary server and the others 
are  the  backups.  We  have  several  clients  making  remote  invocations  to  the  primary  server.  The 
server  hosts  beans  that  process  these  invocations.  Each  bean  has  a  unique  beanID.  Beans  may 
invoke other beans on the same server. A remote invocation coming from a client will start an 
invocation tree between beans. The execution model in the beans is single threaded, but there can 
be  multiple  threads  in  the  server  processing  concurrently  different  remote  invocations.  Any 
bean can start, end, suspend or resume a transaction. 8  Transactions have a unique transactionID. 
The transaction is associated to the current thread and is propagated through invocations. Any 
changes done to the state of a bean inside a transaction are not committed until the transaction 
ends. Thus a bean has one persistent state and a state associated to each current transaction that 
modifies it. Transactions are propagated even through remote invocations, so it is possible for a 
client to perform several remote invocations all taking part of the same transaction. 

5.1.2     The Data 
    The data relevant to our replication algorithm are the state of the beans and the state of the 
transactions.  By  state  of  a  transaction  we  refer  to  the  set  of  beans  modified  inside  that 
transaction that has not yet committed or aborted.  
    Since it is very expensive to transfer the whole state of the primary server to the backups, we 
will  perform  replication  incrementally  by  sending  changes  between  requests. As  we  said,  our 
state is composed of the state of the beans and the state of the transactions. A single change can 
be for example a modification of the state of a bean or an abortion of a transaction. We classify 
the changes in committed changes and transaction changes: 
    Committed changes refer to changes performed to a bean. More specifically: 
        • Creation – indicates that a bean has been created. Includes the bean identifier and the 
          state of the created bean. 
        • Modification – indicates that a bean has been modified. Includes the bean identifier and 
          the state of the bean after the modification. 
        • Deletion – indicates that a bean has been deleted. Includes only the identifier of a bean. 
    Transaction changes refer to changes performed to the state of a transaction: 
        • Creation – includes the globally unique identifier of the created transaction 



8        This is a generalization encompassing both CMT and BMT.
UBLCS-2006-13                                                                                             51
                                                                      5 Transaction Replication Algorithm

         • Modification  –  includes  the  globally  unique  identifier  of  the  transaction  plus  a  set  of 
           transactional  changes  associated  to  this  transaction.  A  transactional  change  (different 
           from  transaction  change)  indicates  any  change  of  a  bean  performed  inside  a 
           transaction. It can be either a creation, modification or deletion of a bean. 
         • Commit – includes the GUID of the committed transaction. Indicates that all previous 
           modifications of the transaction are now to be considered committed. 
         • Abort  ‐  includes  the  GUID  of  the  aborted  transaction.  Indicates  that  all  the  previous 
           modifications of the transaction are now to be considered invalid. 
   From  these  basic  changes  we  construct  more  complex  data  structures  that  specify  a  set  of 
changes  that  have  something  in  common:  more  specifically  we  construct  the  extended  bean 
changes data structure that we associate to each remote invocation. The extended bean changes 
data  structure  contains  all  the  changes  performed  in  that  invocation  (the  committed  changes 
and the transaction changes for every transaction involved in that invocation tree). 
   Since there can be multiple threads inside the application server, we will have different bean 
changes  data  structures  at  the  same  time,  but  each  one  of  them  will  be  associated  to  a  single 
thread, more precisely to a single remote invocation. 


        Committed Changes

                    Bean Creation               Bean Modification                Bean Deletion
                    (id, state)                 (id, state)                      (id)


        Transaction Changes

                 Transaction Creation           Transaction Commit            Transaction Abort
                 (txid)                         (txid)                        (txid)


                 Transaction Modification (txid) +
                    Bean Creation               Bean Modification                Bean Deletion
                    (id, state)                 (id, state)                      (id)



                           Figure 5.1 Extended Bean Changes Data Structure
    Another data structure we use is the table of uncommitted changes (TUC). Each backup server 
keeps  a  singleton  of  this  structure.  This  data  structure  contains  the  state  of  uncommitted 
transactions.  Truly  it  contains  all  the  transaction  changes  of  uncommitted  transactions 
organized by transaction. The transaction changes stored in this table are sufficient to construct 
the  state  of  the  transaction.  The  changes  present  in  this  table  include  information  about 
creations  and  modifications  of  transactions.  There  will  be  only  one  transaction  modification 
change per transaction which will contain all the transactional changes done since the creation 
of that transaction. The table will not contain any commit or abort transaction changes.  

5.1.3      The Algorithm 
   The  algorithm  has  to  take  care  of  two  things.  The  first  one  is  associating  transactions  that 
span over multiple remote invocations with clients. Each time a request has been processed, if 

UBLCS-2006-13                                                                                               52
                                                                               5 Transaction Replication Algorithm

there  is  an  active  transaction  associated  to  the  thread,  the  server  attaches  the  transaction 
identifier  to  the  response.  When  the  client  receives  that  response,  it  stores  the  transaction 
identifier  in  a  variable.  The  next  time  it  performs  an  invocation,  the  client  will  attach  to  the 
request the transaction identifier previously received by the server. Once the server receives a 
client request that has a transaction identifier, it will associate the corresponding transaction to 
the  thread  processing  that  request.  In  this  way  we  allow  transactions  to  span  over  multiple 
remote invocations. 
    The  second  thing  our  algorithm  must  take  care  of  is  the  actual  replication  of  transactions 
from  the  primary server  to  the  backups.  If a  transaction  is replicated  correctly,  then  in  case  of 
failure,  any  client  that  performs  failover  to  a  backup  will  be  able  to  resume  any  active 
transaction it had on the primary. 
    The first thing we must do is collect the changes to be replicated for each remote invocation. 
When  the  primary  receives  a  request  from  the  client,  it  will  create  an  extended  bean  changes 
data  structure  relative  to  that  remote  invocation.  As  beans  invoke  each  other,  the  server  will 
collect  information  about  all  the  changes  performed  in  the  invocation  tree.  This  includes 
changes to beans performed out of a transactional context (committed changes) and creations, 
commits,  aborts  of  transactions  and  relative  modifications  from  within  a  transactional  context 
(transaction changes). 
    Each time a bean (or the server on behalf of the bean) creates a transaction, the server will 
add the relative entry denoting a transaction creation to the transaction changes of the extended 
bean changes data structure.  
    Each  time  after  a  bean  is  invoked,  if  there  is  no  transaction  associated  to  the  thread,  the 
server will add the state of the bean in committed changes of the extended bean changes data 
structure.  Otherwise,  if  there  is  a  transaction  associated  to  the  current  thread,  the  server  will 
add the state of the bean to the transaction changes of the extended bean changes data structure 
in the relative transaction entry 9 . The same applies for creation and deletion of beans: the server 
will add the relative entries in the committed changes or transaction changes depending on the 
presence of a transactional context. 
    Some  optimizations  may  be  performed  while  collecting  bean  changes.  If  the  same  bean  is 
invoked  twice  in  the  same  invocation  tree,  the  first  change  entry  will  be  overwritten  by  the 
second  one.  If  a  bean  is  deleted,  then  any  other  relative  changes  will  be  removed  from  the 
extended bean changes data structure. If a bean is first created and then deleted, the extended 
bean  changes  will  not  contain  any  changes  relative  to  that  bean.  This  is  not  true  for  the  case 
when we delete an existing bean and create another with the same id. In that case the extended 
bean changes data structure will contain both, the deletion and the creation.  
    If a transaction is committed, then the server will move all the bean modifications relative to 
that  transaction  in  the  committed  changes  of  the  extended  bean  changes  data  structure.  If  a 
transaction  is  aborted,  then  the  server  will  remove  the  relative  transaction  entry  from  the 
transaction changes of the extended bean changes data structure. 
    When the invocation tree is completely executed, the extended bean changes data structure 
will  contain  all  the  changes  performed  during  the  processing  of  that  particular  client  request. 
Before  returning  the  response  to  the  client,  the  primary  server  broadcasts  the  changes  to  the 
backups. Upon receiving the changes from the primary, the backup will immediately apply the 
committed changes in its own copy of the beans and apply the transaction changes on the TUC. 
Applying  transaction  changes  involves  merging  new  transaction  changes  with  the  old, 


9
  This actually happens only for Entity Beans, since only Entity Beans are transactional. Stateful Session beans are treaded as
committed changes even if they are modified from within a transaction.
UBLCS-2006-13                                                                                                              53
                                                                      5 Transaction Replication Algorithm

committing  and  aborting  transactions  that  may  already  have  an  entry  in  the  TUC  that  was 
received in some previous message. 
   When a backup receives a transaction modification, which contains bean changes performed 
from  within  a  transactional  context,  it  will  first  merge  it  with  any  existing  entry  in  the  TUC. 
Here  we  can  apply  the  same  optimizations  like  when  collecting  bean  changes.  In  particular 
previous  modifications  are  overwritten  and  deletions  remove  previous  creations  and 
modifications.  A  special  case  is  when  the  transaction  change  contains  both  a  deletion  and  a 
creation. This can happen only in the case a bean was deleted and then another one was created 
with the same id. In this case the backup will first apply the deletion and then the creation. 
   If the primary server fails, the clients will fail over to the backup as described in Section 4.4.4. 
We will consider the database of the primary to have failed as we are using a vertical approach. 
Before  starting  to  process  requests  from  the  clients,  the  backup  has  to  recreate  locally  all  the 
transactions  and  restore  their  state  as  it  was  on  the  primary.  To  accomplish  this,  it  uses  the 
information  stored  in  the  TUC.  For  each  transaction  entry,  the  backup  will  locally  create  a 
transaction with the same identifier 10  and apply all the relative changes contained in the TUC 
using that transactional context. 
    

5.2            The Implementation 
   We have used the building blocks of the replication framework to implement the transaction 
replication algorithm. We had to extend some of the basic building blocks and create some new 
ones.  In  particular  we  had  to  modify  the  way  changes  were  collected.  The  design  of  the 
framework  allows  us  to  easily  extend  the  existing  BeanChanges class.  Moreover  we  used 
Transaction Interceptors to keep track of the transactional changes. Another issue we solved by 
using transaction interception was to bypass the association of transactions to clients.  
   For  many  other  parts  of  the  algorithm  we  have  used  the  building  blocks  provided  by  the 
framework  as  they  are.  These  include  the  view  updating  mechanism,  the  Replicator  and  the 
Receiver, the Group Communication Layer and the Failover. 

5.2.1          Collecting Changes 
    In  order  to  collect  changes  we  had  to extend  the  BeanChanges  class  defined  in  4.4.2  with 
information  about  transaction  changes.  We  have  added  tables  that  contain  created,  modified, 
committed and aborted transactions. 
    Modifications  of  transactions  include  bean  changes  performed  in  the  context  of  that 
transaction.  The  only  difference  between  them  and  the  basic  changes  data  structure  we  have 
used is the transaction GUID. So again we extended the basic Changes data structure to include 
this information. 
    We  have  implemented  TransactionInterceptors  that  intercepted  the  begin(), 
commit()  and  abort()  methods  and  created  the  relative  entries  in  the  ExtendedChanges
data structure associated to the current thread. 
    The  ChangesCollector  described  in  Section  4.4.2  was  replaced  by  a  subclass  named 
TransactionalChangesCollector.  After  each  bean  invocation  of  the  invocation  tree,  the 
TransactionalChangesCollector verified if there was a current transaction associated to 
the  thread.  In  case  there  was  one,  the  bean  change  was  added  as  a  transactional  change 
associated to the current transaction. 



10
     To see how this is performed see Section 5.2.3
UBLCS-2006-13                                                                                               54
                                                                       5 Transaction Replication Algorithm

5.2.2      Receiving and Applying Changes 
    One of the parts of the algorithm that did not require modifications was the Receiver from 
Section 4.4.5. The task of the Receiver is only to receive messages from the GCL and apply the 
changes contained in there. To perform this it only needs to invoke the apply() method of the 
BeanChanges class. The BeanChanges class is expected to be smart enough to know how to 
apply  itself  locally.  So  depending  on  the  actual  subclass  of  the  BeanChanges  class,  different 
actions  will  be  performed.  In  our  case  the  ExtendedChanges  will  immediately  apply  all  the 
committed changes to the beans and then it will update the table of uncommitted changes in the 
following way:  
    For  each  created  transaction  it  will  insert  the  relative  entry  into  the  TUC.  For  each 
transaction modification, it will merge the transactional changes with any previous transaction 
modification  already  present  in  the  TUC.  For  each  transaction  commit,  the  previous  changes 
from  the  TUC  relative  to  that  transaction  will  be  committed.  And  finally  for  each  abort,  all 
previous changes for that transaction contained in the TUC will be discarded. 

5.2.3      Transaction Association and Failover 
    We  needed  to  re‐implement  the  mechanism  for  maintaining  transaction  association  across 
remote  invocations,  because  the  one  provided  by  the  server  did  not  work  properly  in  the 
scenario where we were resuming the same transaction on another server after a failover. Our 
TransactionAssociationInterceptor  attaches  the  GUID  of  the  transaction  to  the 
response if there is a current transaction before returning the response to the client. The client 
side  counterpart,  maintains  a  per  thread  association  to  this  GUID  and  attaches  it  to  the  next 
request. 
    Off‐the‐shelf  transaction  managers  are  not  designed  to  support  replication  so  they  do  not 
provide  any  means  of  re‐creating  a  transaction  given  a  state  nor  a  transaction  with  a  specific 
GUID. Instead they generate a new GUID each time they create a transaction. This is a problem 
for our algorithm, which should have more replicas of the same transaction on different servers, 
all  having  the  same  GUID.  So  instead  of  recreating  the  same  transaction,  we  recreate  a 
transaction  identical  to  the  original  one  but  with  a  different  GUID.  But  we  need  to  have  an 
external  GUID  exposed  to  the  application  and  one  internal  that  is  used  by  the  Transaction 
Manager.  We  have  used  the  TransactionInterceptors  provided  by  the  replication 
framework  to  wrap  transactions  and  map  one  GUID  to  another,  so  the  client  always  sees  one 
same external GUID. 
    The client side of the failover mechanism is left unchanged. When it detects a crashed server 
the client tries another one. This is precisely the behavior of the failover interceptor provided by 
the  replication  framework.  However  this  is  not  enough  to  correctly  perform  failover.  Before 
starting to process a request from the client, the server has to recreate the transaction associated 
with the client and set its state up‐to‐date. 
    When a backup receives a request with a specific transaction associated, it first looks into the 
TUC  to  see  if  there  is  an  entry  there.  If  there  is,  it  extracts  the  entry  and  locally  creates  a 
transaction. This new transaction will have a new GUID generated by the Transaction Manager, 
but the transaction gets wrapped in a transaction interceptor that exposes the external GUID of 
the transaction that we have received in the request. 
    Once  we  have  created  this  new  transaction,  it  will  automatically  become  the  current 
transaction.  Now  we  can  apply  all  the  transactional  changes  that  we  extracted  from  the  TUC. 
These include creations, modifications and deletions of beans. In this way we recreate another 
transaction on the backup that has the same state and externally exposes the same GUID as the 
original transaction. 
UBLCS-2006-13                                                                                                  55
                                                                     5 Transaction Replication Algorithm


5.3        Correctness Proof 
   To  verify  that  our  algorithm  actually  does  what  it  is  supposed  to,  first  we  will  define  the 
correctness criteria in terms of: 
        • Exactly Once Execution: every request for which a clients receives a response has been 
          executed exactly once on all the correct servers. 
        • 1‐Copy‐Serializability:  The  histories  of  all  the  backups  are  prefixes  of  a  history 
          equivalent to the history on the primary 
        • Preservation of ACID Properties: Replicated transactions preserve the A.C.I.D. properties 
          even in case of server failures 
   The  first  two  properties  were  already  proven  in  4.4.5  and  since  we  are  using  the  same 
replicator there is no need to prove them again. 
   We have to prove the 4 basic properties of ACID transactions: 
        • Atomicity ‐ operations of a transaction are all executed or none  
        • Consistency ‐ data is left in a consistent state after completing a transaction 
        • Isolation – concurrent transactions do not interfere with each other, but appear as they 
          have been executed one by one 
        • Durability – the effects of a completed transactions are persistent 
   We will try to give a formalization of these properties for a replicated context: 
        • A1: If the client receives a response from an execution where a transaction t has been 
          committed, all the changes of t are received by all the correct servers. 
        • A2:  If  the  client  receives  a  response  from  an  execution  where  a  transaction  t  was 
          aborted, no changes of t will be present in any correct server. 
        • I: 1‐copy‐serializability for transactions (also multi‐request) 
   We  don’t  give  a  formal  definition  of  Consistency  because  that  is  dependant  on  the 
application semantics and goes beyond the scope of a replication algorithm. Notice also that A1 
captures both Durability and an aspect of Atomicity at the same time. 
    
   We  have  to  impose  some  restrictions  on  the  behavior  of  the  client.  These  restrictions  are 
there only to ensure the liveness of the algorithm and not safety. A malicious client that doesn’t 
respect  these  restrictions  is  not  capable  of  compromising  the  functioning  of  the  system.  We 
assume  that  the  client  is  single  threaded  and  that  it  won’t  send  another  request  until  it  has 
received the response to the previous request (except for the first request). The client will only 
send the same request to another server if it suspects the primary to have crashed. 
    
   Let us starts by proving: 
   Thorem 3     A1:  If  the  client  receives  a  response  from  an  execution  where  a  transaction  t 
has been committed, all the changes of t are received by all the correct servers. 
   Proof: t can be either enclosed in one remote request or span over multiple requests.  
   If t is enclosed in a remote request then it is created, committed and all the changes are made 
during  the  execution  that  remote  request.  For  every  change  performed  under  t,  the  algorithm 
will mark that change as uncommitted associating it to t. When t commits all these changes will 
be  marked  as  committed  and  merged  with  the  committed  changes  of  the  current  remote 
request.  When  the  execution  of  the  remote  request  finishes,  the  server  will  broadcast  the 
changes of that remote request including the changes of all committed transactions. If the server 
UBLCS-2006-13                                                                                              56
                                                                    5 Transaction Replication Algorithm

crashes  before  the  broadcast,  the  client will  perform the  fail‐over and another server  will  take 
over  the  request  and  perform  the  same  steps.  If  the  server  doesn’t  crash,  from  the  agreement 
propriety  of  reliable  broadcast,  every  backup  will  receive  the  changes.  Since  changes  of  all 
committed transactions are marked as committed, the backups will apply them. 
    If  t  is  spanning  over  multiple  requests  we  know  that  for  every  component  x  modified  in  t 
either x was modified on p or x was modified on another server q. We have assumed that the 
client will never send a request before it receives the response for the previous request except 
for the first request. Since t spans over multiple requests, we know that this request is not the 
first one, so the client received a response from q before sending the request to p. Then we know 
that q broadcast the changes relative to component x before sending the response to the client. 
So  this  means  that  p  received  the  change  relative  to  x.  From  the  agreement  property  of  the 
reliable broadcast this means that every correct server received the change relative to x. This is 
true also for the case q = p. In other words, until now, we have proven that the backups have 
received  all  the  uncommitted  changes  of  any  previous  request.  But  if  the  client  received  the 
response  from  the  execution  where  t  was  committed,  then  it  means  that  p  has  marked  all  the 
changes  of  that  transaction  performed  in  that  request  as  committed  and  broadcast  the  bean 
changes  data  structure  to  the  other  servers.  The  bean  data  structure  also  included  the 
information  that  the  transaction  committed.  This  means  that  all  the  backups  have  applied  all 
previous uncommitted changes and the committed ones received by p. 
     
  Thorem 4       A2:  If  the  client  receives  a  response  from  an  execution  where  a  transaction  t 
was aborted, no changes of t will be present in any correct server. 
    Proof: For a transaction that is enclosed in one remote request, if that transaction aborts all 
the  relative  changes  will  be  discarded  from  the  changes  and  there  will  be  no  effect  on  the 
backups. 
   For transactions that span over multiple requests, if the primary doesn’t fail, no changes will 
be applied on the backups. If the primary fails, the backup that becomes the new primary will 
recreate  the  transaction  and  apply  relative  changes  in  the  appropriate  transactional  context. 
From this, we have the property that all the changes applied in under a transaction that has not 
been  committed,  are  kept  in  the  correct  transactional  context  of  the  current  primary.  In  other 
words,  no  change  of  that  transaction  will  be  committed.  When  a  remote  request  triggers  the 
abortion  of  the  transaction,  the  current  primary  will  abort  all  the  changes  performed  in  that 
transactional context, including any changes performed by an old primary. 
    
   Thorem 5        I: 1‐copy‐serializability for transactions (also multi‐request) 
    Proof:  Isolation  for  transactions  spanning  over  one  request  are  ensured  by  the  transaction 
locking mechanism of the underlying server. 
    For  transactions  spanning  over  multiple  requests,  if  there  are  no  failure  of  the  primary, 
isolation is still guaranteed by the transaction locking mechanism. 
    If  there  is  a  failure  of  the  primary,  there  will  be  a  number  of  transactions  whose 
uncommitted  changes  were  received  by  the  backups,  but  no  commit  has  been  received.  The 
changes  of  these  transactions  are  kept  in  the  TUC.  When  the  crashed  primary  is  suspected,  a 
new primary will be elected. The new primary will recreate all the transactions locally. Since the 
transaction locking mechanism on the primary ensures that there are no two transactions that 
are  accessing  the  same  component,  upon  restoring  the  transactions  there  will  be  no  conflicts. 
Clients  will  eventually  fail‐over  to  the  new  primary  and  continue  with  the  execution  of  the 


UBLCS-2006-13                                                                                            57
                                                                   5 Transaction Replication Algorithm

transaction. The underlying transaction locking mechanism on the new primary will maintain 
the serializability of transactions. 
     
    In this chapter we have defined an algorithm for the replication of flat transactions in terms 
of the building blocks presented in Section 4.4. The algorithm performs transaction replication, 
which  enables  clients  to  use  transactions  spanning  over  multiple  requests  and  benefit  of  the 
fault  tolerance  provided  by  replication.  The  transaction  replication  algorithm  respects  exactly 
once execution, 1‐copy‐serializability and preserves the ACID properties of transactions. 
    Having  a  transaction  spanning  over  multiple  invocations  is  a  typical  example  of  long 
running  transactions,  where  user  interaction  is  required  inside  the  transaction.  However,  the 
isolation property of ACID transactions keeps the involved resources blocked and may prevent 
the  execution  of  other  transactions  that  access  the  same  resources. A  more  flexible  transaction 
model is needed if we really want to provide the user with long reliable running transactions. 
Open Nested Transactions provide such a model by relaxing the isolation property. In the next 
chapter we will examine the problem of replicating Open Nested Transactions.




UBLCS-2006-13                                                                                           58
Chapter 6 

ONT Replication Algorithm 

6.1       Open Nested Transactions 
     Traditional transactions may be too restrictive for some applications that need to relax some 
of  the  transaction  properties.  For  this  reason,  several  advanced  transaction  models  have  been 
proposed [51].  
     The  model  we  have  chosen  to  replicate  is  the  Open  Nested  Transaction  model  [55].  In  this 
model  transactions  can  be  nested  in  other  transactions.  The  transactions  are  organized  into  a 
tree. An Open Nested Transaction can commit only after its children have committed. If an ONT 
aborts  then  all  of  its  children  abort,  including  the  ones  that  have  already  committed. 
Transactions  that  have  already  committed  are  rolled  back  using  compensating  actions.  These 
compensating actions are usually implemented by the application. 

6.1.1     The Activity Service 
    The J2EE Activity Service specification (J2EEAS) [52] allows the implementation of advanced 
transaction  models  in  J2EE.  The  J2EEAS  consists  of  two  components:  the  activity  service  itself 
and one or more high level services. The activity service provides an abstract unit of work called 
activity, which may or may not be transactional. An activity may encapsulate a JTA transaction 
[53] or be encapsulated by a JTA transaction. Activities may be nested. 
    High  Level  Services  are  defined  on  top  of  the  activity  service  and  represent  advanced 
transaction models. Applications using a HLS explicitly demarcate activities, which produce an 
outcome.  The  activity  service  communicates  demarcation  points  to  registered  actions  through 
signals,  which  are  produced  by  signalsets.  Actions  are  defined  by  the  application  (e.g., 
compensators  to  undo  an  activity).  The  signalset  is  a  finite  state  machine  that  accepts  the 
outcomes of actions as input. It may use that outcome to determine the next signal to send. The 
next signal will not be produced until the previous one has been sent to all registered actions. 
Developers  must  provide  the  specific  signals  that  may  be  produced  during  the  lifetime  of  an 
activity,  the  outcomes  and  the  state  transitions  (signalset)  in  order  to  implement  a  transaction 
model using the J2EEAS. 
     

6.1.2     Implementing ONTs with the Java Activity Service 
    We have used the J2EEAS implementation of the Open Nested Transaction presented in [56]. 
In  the  ONT  model  each  activity  represents  an  atomic  unit  of  work,  so  we  associate  a  JTA 
transaction to each activity. 
                                                                               6 ONT Replication Algorithm

     Activities  may  be  completed,  aborted  or  compensated.  When  created  an  activity  becomes 
active.  An  active  activity  may  be  either  completed  or  aborted.  An  activity  that  is  completed, 
commits the associated transaction. An activity that is aborted aborts the associated transaction. 
An activity that has been completed or aborted is not active anymore. However, an activity that 
has been completed may still be compensated. 
     Activities  may  contain  any  number  of  nested  activities.  The  transaction  associated  to  the 
parent  activity  is  suspended  during  the  execution  of  a  nested  activity.  The  parent  activity 
transaction will resume, when the nested activity finishes. Each activity has a compensator that 
is used to roll back the effects in case the root activity aborts. When a child activity completes, 
its  compensator  is  registered  with  its  parent  activity.  This  procedure  is  performed  recursively 
until  the  top‐level  ONT  activity  is  reached.  An  activity  cannot  complete  until  all  its  children 
have not completed or aborted. In other words, there may not be active children activities when 
the  parent  activity  completes.  When  the  top  level  activity  completes,  all  compensators  are 
discarded. A parent activity may abort even if it has children activities that are still active. If an 
activity aborts than all its active children are aborted and all the compensators registered with it 
are executed. These are the compensators of its children activities that have already completed. 
The compensators will be executed in reverse order. 
     A  bean  may  start,  complete,  abort,  suspend  and  resume  activities.  When  a  bean  starts  an 
activity,  the  activity  is  associated  to  the  current  thread,  and  becomes  the  current  activity.  If  a 
bean invokes another bean, the current activity will be propagated through the invocation. If an 
activity  is  begun  when  there  is  already  a  current  activity,  that  activity  will  become  the  parent 
activity and the new activity will become the current activity. A bean may abort or complete the 
current activity. When the current activity is completed or aborted, its parent activity becomes 
the current one, except for the top level activity. A bean may also suspend the current activity. 
When it suspends the current activity, the parent activity will become the current and the bean 
will  obtain  a  reference  to  the  suspended  activity.  Later  the  bean  may  use  this  reference  to 
resume  the  suspended  activity.  Suspending,  resuming  and  starting  nested  activities  may 
produce  complex  activity  trees.  Since  activities  are  associated  to  the  current  thread  and  the 
client performs commit/abort operations only on the current thread, the whole activity tree will 
be associated to the same thread. 

6.2        Replicating ONTs 
   The approach we took for the replication algorithm for ONTs is the same as the one for Flat 
Transaction Replication. Basically we treat the state of the transaction as part of the application. 
The entities involved are the same as before (primary server, backup servers, beans, invocations) 
but instead of transactions now we have ONT activities.  

6.2.1      Actors 
    Most  of  the  parts  of  the  system  are  similar  to  the  previous  replication  algorithm  we  have 
seen.  We  are  still  following  the  primary/backup  vertical  approach,  so  we  have  a  set  of  servers 
among  which  one  is  the  primary  and  the  others  are  backups.  There  is  no  shared  database,  but 
every server has its own database. Clients perform remote invocations to the primary server. The 
beans  on  the  server  process  requests  and  make  local  invocations  that  form  invocation  trees.  Each 
bean  has  a  unique  beanID.  There  is  one  thread  associated  to  every  remote  invocation  that 
generates the invocation tree. A bean may begin, complete, abort, suspend or resume an activity 
in the way described in Section 6.1.2. The resulting activity tree will be associated to the current 
thread.  This  association  is  maintained  also  over  remote  invocations,  so  a  client  could  make 

UBLCS-2006-13                                                                                                 60
                                                                                    6 ONT Replication Algorithm

multiple  invocations  all  taking  part  of  the  same  activity  tree. Activities  are  identified  by  their 
unique activityID and activity trees are identified by their activityTreeID. 

6.2.2       Data 
   On  each  invocation  we  replicate  the  state  of  the  modified  beans  plus  the  activity  tree 
associated to the current thread. This is a little different approach than the one seen in Chapter 5 
where  transactions  were  replicated incrementally  by  sending  transaction  changes. This  design 
choice  is  a  consequence  of  the  absence  of  activity  service  interceptors  in  the  replication 
framework.  
   Activities are transactional, so all the modifications performed in an activity are considered 
uncommitted  changes  until  the  activity  completes  or  aborts.  Changes  performed  by  a 
compensator  are  wrapped  in  a  dedicated  activity.  We  treat  compensators  like  normal 
invocations.  As in Chapter 5 we will consider only committed changes to determine the state of 
the beans. Uncommitted changes are part of the state of an activity until that activity completes. 
   Like before, committed changes are: 
         • Creation – indicates that a bean has been created. Includes the bean identifier and the 
           state of the created bean. 
         • Modification – indicates that a bean has been modified. Includes the bean identifier and 
           the state of the bean after the modification. 
         • Deletion – indicates that a bean has been deleted. Includes only the identifier of a bean. 
     The state of an activity consists of: 
         • Status  ‐  can  be  either  active  or  completed. 11   We  do  not  consider  activities  that  have 
           aborted or have not yet started. 
         • Uncommitted Changes – changes to beans performed in this activity. Includes Creation, 
           Modification and Deletion changes. 
         • Compensators  –  the  compensators  registered  with  the  activity.  These  are  the 
           compensators of the completed children activities. 
     Finally the state of the activity tree is made of: 
         • Activities – state of the activities that are in the tree  
         • Structure  of  the  tree  ‐  indicating  which  the  relationships  between  the  activities  of  the 
           tree are. 
         • Current Activity – a pointer to the current activity 
   Since  activity  trees  can  span  over  multiple  remote  requests,  we  also  have  to  take 
consideration  of  remote  requests  during  which  the  activity  tree  begun  in  a  previous  remote 
request  has  completed.  There  is  no  need  to  have  a  complex  structure  that  would  indicate 
creations,  modifications,  completions  and  abortions  of  activity  trees,  because  multiple  activity 
trees  cannot  coexist  in  the  same  thread.  So  we  will  have  at  most  one  activity  tree  at  the 
beginning  of  a  remote  invocation  and  at  most  one  activity  tree  at  the  end.  The  only  bit  of 
information we have to include in order to tell whether a previously replicated activity tree has 
been completed is the initial activity tree id. 
   Finally our changes structure takes this form: 



11
   Actually there are eight statuses (Active, Committed, Committing, Completed, MarkedRollback, Rolledback, RollingBack,
toCompensate, Unknown) but for readability reasons we will consider them as only two.

UBLCS-2006-13                                                                                                       61
                                                                             6 ONT Replication Algorithm


        Committed Changes
                    Bean Creation          Bean Modification          Bean Deletion
                    (id, state)            (id, state)                (id)


         Activity Tree (id)         Activity (id, status, compensators)
                                      Bean Creation
                                      (id, state)     Bean Deletion
                                            Bean Modification
                                                      (id)
                   current


                                            (id, state)




            Activity (id, status, compensators)           Activity (id, status, compensators)
              Bean Creation                                 Bean Creation
              (id, state)     Bean Deletion                 (id, state)     Bean Deletion
                    Bean Modification
                              (id)                                Bean Modification
                                                                            (id)
                    (id, state)                                   (id, state)


        Initial Activity Tree ID (id)
                                Figure 6.1 The Changes Data Structure
   Backups  will  keep  a  Temporary  Tree  Table  (TTT)  where  trees  received  from  the  primary  are 
temporarily stored. This table will contain the information about the existing Activity Trees on 
the primary. If the primary fails the backup that becomes the new primary will use information 
held in this structure to reconstruct the activity trees. 

6.2.3     The Algorithm 
    When a new activity tree is started in a remote invocation, and that invocation finished with 
the activity tree still active, the server will attach the activityTreeID to the response sent to the 
client. The client will keep this identifier until it makes the next request. The identifier will be 
attached  to  the  next  request  made  by  the  client.  When  the  server  receives  a  request  with  an 
activityTreeID, it will associate the correct activity tree to the thread processing that request. 
    If the primary server where the activity tree has been created fails between the two requests, 
it is responsibility of the replication algorithm to restore the activity tree on the backup. In this 
way the activity tree (actually its replica) can be resumed on the new primary. 
     
    At the beginning of a remote invocation the server will first create a new empty changes data 
structure. Then it will check if there is a current activity tree. If yes, after re‐associating it with 
the current thread, the server will add the activity tree identifier in the changes data structure. 
    Like  in  the  previous  algorithm  bean  changes  are  collected  right  after  the  bean  has  been 
invoked. If the same bean gets invoked more that once during  the same remote invocation, only 
the last state will be kept in the changes data structure. 
    When  an  activity  completes,  all  its  changes  are  added  to  the  committed  changes.  If  an 
activity aborts, its changes are discarded. Finally if an activity is compensated, the changes of 
the compensator are added to the committed changes. 


UBLCS-2006-13                                                                                           62
                                                                              6 ONT Replication Algorithm

    After  the  whole  invocation  tree  has  completed,  the  server  will  check  if  there  is  an  activity 
tree associated to the current thread. If yes, the whole tree will be included in the changes data 
structure. Just before returning the response to the client, the primary server will broadcast the 
changes data structure to the backups using the group communication layer. 
     
    Each  time  a  backup  receives  a  message  from  the  primary  containing  the  changes  data 
structure  it  applies  the  changes  contained  in  it.  First  it  applies  the  committed  changes,  which 
include creation, modification and deletion of beans. These are permanent changes, so there is 
no need to keep them in a temporary data structure. 
    On the other side, activities may still be aborted so the Activity Tree gets stored in the TTT 
replacing  any  previous  version.  There  is  no  need  to  merge  the  activity  tree  with  the  previous 
version because the one we received contains all the information we need. 
    If the initial activity tree id is not null and is different from the id of the activity tree attached 
to the changes data structure, it means that the previous tree has been completed or aborted. If 
it  was  completed  then  all  its  changes  have  been  included  by  the  primary  in  the  committed 
changes.  If  the  tree  was  aborted  then  the  changes  of  any  completed  children  activities  will  be 
included  in  the  committed  changes,  but  most  likely  will  be  overwritten  by  the  changes  of  the 
compensators. In any case the state of the beans will be the same as on the primary. 
    If the primary crashes, one of the backups will be elected as the new primary. All the clients 
will perform failover to the new primary. The new primary will process the changes contained 
in the TTT before starting to fulfill the requests of the clients. The activity trees contained in the 
TTT will be recreated 12  as they were on the primary. Only after recreating all the activity trees, 
the backup will start processing requests from the clients. 

6.3        Implementation 
    There  are  a  few  important  differences  between  the  replication  algorithm  described  above 
and the actual implementation. It all has to deal with the fact that the ONT High Level Service 
uses  the  underlying  JTA  Service  of  JBoss  to  impose ACID  properties  on  activities.  Each  ONT 
activity  is  associated  to  a  transaction  that  has  some  internal  representation  in  the  Transaction 
Manager.  As  a  consequence  the  Activity  Service  is  not  able  to  return  the  whole  state  of  the 
activity  tree  as  we  have  described  it  in  the  algorithm.  The  missing  parts  are  the  transactions 
associated  to  the  activities.  Moreover  the  uncommitted  state  of  Entity  Beans  is  held  in  the 
database  and  is  managed  by  the  internal  Transaction  Manager  of  the  DBMS,  which  in  turn  is 
coordinated by the Transaction Manager of JBoss. 




12
  This includes creating them in the Activity Service, creating associated transactions and applying the
uncommitted bean changes inside transactions.
UBLCS-2006-13                                                                                        63
                                                                              6 ONT Replication Algorithm




            JBoss
                     Adapt Framework                     Open Nested Transactions
                                                              High Level Service

                    Replication Algorithm


                                                           J2EE Activity       Transaction
                                                             Service            Manager
                                                                                 TX    TX




                           uncommitted state
                                                                            TM




                                Figure 6.2 ONT Replication Architecture
    The JTA transactions are never directly accessed by the application. Their id is never exposed 
externally. The only thing we need them for are their ACID semantics. In fact it is not necessary 
to  replicate  the  transactions  as  they  are;  instead  it  is  enough  to  recreate  on  the  backup  other 
transactions  that  are  equivalent.  That  means  that  we  need  to  recreate  other  transactions  and 
apply the uncommitted changes using the appropriate transactional context. 
    In  order  to  collect  the  uncommitted  modifications,  the  interception  approach  is  used.  It 
works in the same way as the collection of committed bean changes: after each invocation, we 
add the bean to the changes data structure which can host also uncommitted changes organized 
by  activity.  When  we  read  the  state  of  the  bean,  we  are  still  running  under  the  transactional 
context  of  the  transaction  that  was  used  to  invoke  the  bean  so  what  we  read  will  be  the 
uncommitted changes.  




UBLCS-2006-13                                                                                               64
                                                                               6 ONT Replication Algorithm


         Committed Changes
                            Bean Creation        Bean Modification          Bean Deletion
                            (id, state)          (id, state)                (id)


         Activity Tree (id)

                                    Activity (id, status, compensators)
                  current




           Activity (id, status, compensators)             Activity (id, status, compensators)


         Initial Activity Tree ID (id)
         Uncommitted Changes

                                    Bean Creation       Bean Modification       Bean Deletion
            activity id             (id, state)         (id, state)             (id)



                                    Bean Creation       Bean Modification       Bean Deletion
            activity id             (id, state)         (id, state)             (id)
                                                      …




                Figure 6.3 The Changes Data Structure with Uncommitted Changes
   As we said before, when a backup becomes primary it will extract the uncommitted changes 
from the TTT. Activity Trees are extracted one by one. For each Activity Tree, the activities will 
be processed from the top to the bottom and for each activity a new transaction will be created 
and the uncommitted changes applied in the relative transactional context. 
    

6.4       Correctness Proof 
    For  the  ONT  Replication  algorithm  the  correctness  criteria  is  similar  to  the  correctness 
criteria we have defined for the flat transaction replication algorithm. 
       • Exactly Once Execution: every request for which a clients receives a response has been 
         executed exactly once on all the correct servers. 
       • 1‐Copy‐Serializability:  The  histories  of  all  the  backups  are  prefixes  of  a  history 
         equivalent to the history on the primary 
       • Preservation  of  ONT  Properties:  Replicated  ONTs  preserve  all  the  properties  of  non 
         replicated ONTs even in case of server failures. 
    



UBLCS-2006-13                                                                                          65
                                                                            6 ONT Replication Algorithm

   Exactly  once  execution  and  1‐copy‐serializability  have  been  proven  in  Section  4.4.5,  so  we 
have to prove the preservation of ONT properties. Let us examine in more detail what are the 
properties of Open Nested Transactions and then try to define them in a replicated context. 
   An Open Nested Transaction can commit only after its children have committed. If an ONT 
aborts  then  all  of  its  children  abort,  including  the  ones  that  have  already  committed. 
Transactions that have already committed are rolled back using compensating actions. 
    
   We  can  define  the  correctness  of  replicated  Open  Nested  Transactions  with  the  following 
properties: 
        • If a client receives a response from an execution where an ONT t has been successfully 
          committed then every change c ∈ t will be completed on the whole cluster. 
        • If the client receives a response from an execution where an ONT t has been aborted 
          then the changes of that ONT and the changes of all the child ONTs will be aborted on 
          the whole cluster. 
    
  Lemma 5          If  the  primary  commits  an  ONT  t,  for  every  change  c  ∈  t  it  will  mark  c  as 
committed. 
   Proof: Let p be the current primary. If p is the one that previously started t, then p holds all 
the changes belonging to t. If t has not been started on p, then there is a server q where the t was 
started. Since there can be at most one primary, it means that q was the previous primary. We 
have  assumed  that  the  client  performs  a  remote  request  r2  only  after  having  received  the 
response from the previous request r1 except for the case when r2 is the first request. But in this 
case we know that there has been a previous request r1 that started t so r2 not the first request. 
This  means  that  the  client  has  received  a  response  from  server  q.  But  this  means  that  q  has 
broadcast the changes to all the backups including p. In other words for every change c which 
has been performed in a remote request ri whose response has been received by the client, c was 
received by all the backups. So p has received any ci ∈ t. 
    
   Thorem 6     If  a  client  receives  a  response  from  an  execution  where  an  ONT  t  has  been 
successfully committed then every change c ∈ t will be completed on the whole cluster. 
   Proof:  By  Lemma  5  we  know  that  the  primary  will  mark  as  committed  all  the  changes 
belonging to that transaction including also any changes preformed in previous remote requests 
or on other servers. 
    
    Lemma 6      At the time when an ONT t is committed at a server p, for each descendant tk 
of t, the compensator of tk will be registered with t in p. 
   Proof: We will give the proof by induction on structure of the ONT tree.  
   Basic case: If t doesn’t have children then the proof is obvious since that is the behavior of the 
algorithm.  
   Induction step: If t has children and for each ti that is a child of t, and for each child tj of ti the 
compensator of tj has been registered with ti, then when t commits the compensators of ti and tj 
will be registered with t. 
   We know that ti  has been committed previously since an ONT cannot commit until all of its 
children commit. We know that ti has either been committed on p or ti has been committed on 
another server q. If ti has been committed on p then p registers the compensator of ti and all the 
compensators registered with ti including the compensator of tj with t. If ti was committed on 
UBLCS-2006-13                                                                                             66
                                                                                6 ONT Replication Algorithm

another  server  q  then  since  the  client  serializes  the  requests,  this  means  that  the  client  has 
received a response from q, which means that q has associated the compensators of ti and tj with 
t  and  then  sent  the  changes  to  the  backups  including  p.  This  means  that  p  has  previously 
received the ONT tree where the compensators of ti and tj were associated to t. 
    By  induction  we  have  that  for  each  descendant  tk  of  t,  at  the  time  we  are  committing  t  the 
compensator of tk will be registered with t. 
 
    Lemma 7      At the time when an ONT t is aborted at a server p, for each committed child ti 
of t, the compensator of ti and the compensators of all descendants of ti will be registered with t 
in p. 
     Proof: For every committed child ti of t from Lemma 6 we know that all the descendants of ti 
have  been  registered  with  ti  at  the  moment  ti  was  committed  in  some  server  q.  From  the 
behavior  of  the  algorithm  we  also  know  that  the  commit  causes  the  compensators  registered 
with ti to be registered with t on q. If q = p then all the descendants of ti are registered with t on 
p.  If  q  ≠  p  then  q  was  the  primary  in  some  moment  in  the  past.  Since  the  client  serializes  the 
requests  we  know  that  the  client  received  a  response  from  q  before  sending  the  request  to  p. 
This  means  that  q  has  previously  broadcast  the  changes  to  p  which  contained  the  ONT  tree 
structure  where  the  compensators  of  all  the  descendants  of  ti  were  registered  with  t.  So  this 
means that for every committed transaction of for each committed child ti of t, the compensator 
of ti and the compensators of all descendants of ti will be registered with t in p as we wanted to 
prove. 
      
     Now we are ready to prove: 
   Thorem 7       If the client receives a response from an execution where an ONT t has been 
aborted then the changes of that ONT and the changes of all the child ONTs will be aborted on 
the whole cluster. 
    Proof:  When  we  abort  t  on  a  server  p  every  uncommitted  child  of  t  is  aborted  and  all  the 
compensators  registered  with  t  are  executed.  For  every  committed  child  ti  from  Lemma  7  we 
have that all the compensators the descendants of ti will be registered with t. Every committed 
descendant of a committed child will be compensated. Recursively all the active descendants of 
t will be aborted and all committed descendants will be compensated. 
    If  the  client  has  received  the  response  that  means  that  p  has  broadcast  the  changes  to  the 
whole  cluster.  Those  changes  include  the  current  state  of  the  ONT  tree  and  the  results  of  the 
compensating actions as committed changes as we wanted to prove. 
     
    In Chapter 5 we have defined an algorithm for flat transaction replication. In this chapter we 
tried  to  apply  the  same  approach  for  Open  Nested  Transactions.  We  have  proved  that  by 
considering replication and transactions orthogonal mechanisms for fault tolerance we are able 
to  benefit  from  both.  We  have  also  examined  proved  that  the  generalization  of  component 
replication  algorithms  defined  in  Chapter  4  is  suitable  for  the  definition  of  transaction 
replication  algorithms,  regardless  of  the  complexity  of  the  specific  model  of  transactions.  We 
have shown that the building blocks we have defined provide a useful tool both for proving the 
correctness  of  a  replication  algorithm  and  implementing  the  algorithm  on  an  architecturally 
complex application server. 
     



UBLCS-2006-13                                                                                                  67
                                                                            6 ONT Replication Algorithm

    




Chapter 7 

Performance Evaluation 

7.1       ECPerf Benchmark 
    The evaluation of the replication algorithms has been done using the ECPerf benchmark [57]. 
ECPerf  is  a  software  used  to  measure  the  performance  and  scalability  of  J2EE  application 
servers. ECPerf simulates a supply chain and defines four application domains: corporate, order 
entry, supply chain management and manufacturing. ECPerf measures the throughput in BBops 
per minute (benchmark business operations). BBops are the sum of the number of transactions of 
the  order  entry  application  and  the  number  of  work  orders  the  manufacturing  application 
generates. 
    The  main  parameter  in  the  tests  is  the  injection  rate  (IR),  which  defines  the  rate  of  the 
business  transactions  executed.  The  number  of  clients  for  the  experiments  depends  on  the  IR. 
The number of clients is five times the IR in the order entry application, and three times the IR 
in the manufacturing application. We have run ECPerf to quantify the overhead introduced by 
our  replication  algorithms  and  compared  the  results  with  our  baselines:  non‐replicated  JBoss 
and JBoss clustering.   
    The  method  of  using  ECPerf  is  to  execute  multiple  runs  with  increasing  IR  values.  The  IR 
value is increased until it reaches a point where the expected BBops is not achieved. That is the 
point where the server cannot handle the load. For verification another few runs should be done 
with  higher  IR  values.  For  these  overloading  IR  values  the  server  could  degrade  gracefully  or 
crash or block. 
    For  each  run  the  configuration  files  must  be  edited,  the  database  has  to  be  re‐filled  with 
values, all the servers have to be restarted and the client has to be started. This is not a simple 
task,  especially  if  the  size  of  the  cluster  is  8  or  16  machines.  For  this  reason  we  have 
implemented  a  system  that  will  perform  all  these  tasks  automatically.  Moreover,  ECPerf  only 
seeks the point where the servers cluster gets saturated and does not provide any information 
about the load of the machines. We have installed a load monitor, that constantly monitors CPU 
and disk usage on each machine. This data is collected and processed at the end of each run. 
    Another  problem  we  had  to  face  is  that  we  did  not  have  exclusive  access  to  the  machines 
used for the benchmarks. This means that in any moment someone could have logged on to a 
machine  and  interfered  with  the  benchmarks.  In  order  to  minimize  the  probability  of  this 
happening we had to run the experiments overnight. This was another reason for automating 
the benchmarks. 


UBLCS-2006-13                                                                                             68
                                                                              6 ONT Replication Algorithm

   Automated nightly runs introduced the problem of monitoring the correct functioning of the 
servers. Due to many server configurations we used, sometimes we had misconfigured servers. 
Another  problem  that  often  appeared  was  file  access  permissions.  In  these  cases  some  of  the 
machines  were  not  operational  and  could  not  participate  in  the  benchmarks.  Most  of  the 
replication  algorithms  we  tested  dealt  correctly  with  this  situation  by  failing  over  to  other 
machines,  but  having  a  lower  number  of  working  machines  than  expected  influenced  the 
performance of the cluster, thus the benchmark could not be considered valid. It was difficult to 
solve  these  problems in  a fully  automated  way,  but we  managed to  avoid  them,  by  excluding 
the faulty machines from the tests and rerunning the tests with a different set of machines. 
    

7.1.1      Automating Benchmarks 
    During  the  benchmarking  of  our  algorithms  we  had  a  pool  of  32  machines  for  the 
application servers, one of them has to be used for the client and we also had one big server for 
the shared database. We have a list of tests. A test is a server configuration, a number of nodes 
and an injection rate. 
    On  each  machine  there  was  a  process  running  to  collect  the  usage  data  such  as  CPU  load, 
disk load, etc. This data was stored on the local file system of the machine.  
    The main script on the client machine started the execution of the whole process. Before each 
run  it  collected  usage  data  from  each  machine  of  the  pool  in  order  to  predict  which  of  the 
machines  had  least  probability  of  being  used  during  the  benchmarks.  This  data  included  the 
number of users logged on the machine, the time from the last user logged in and the average 
load  of  the  last  hour.  Then  a  list  of  usable  machines  was  selected  which  were  able  to  run  the 
benchmarks. Once we had the set of usable machines, we selected a test whose number of nodes 
was  the  highest  among  the  ones  lower  than  the  number  of  usable  machines.  And  finally  we 
selected the optimal machines among the usable ones to run the test. 
    Now the main script started the database and filled in the initial values and reset the usage 
data  on  each  machine.  Then  it  started  the  application  server  on  each  node  in  the  correct 
configuration using multiple parallel SSH connections. After that it waited for all of the servers 
to start. If there was a problem with one of the servers it aborted the test and excluded the faulty 
machine from the pool. 
    Once the servers have all started, the main script started the client. Each application server 
had  a  local  log  file  where  warnings  or  errors  were  logged.  Once  the  test  was  completed,  the 
main script collected and afterwards reset the usage data from all the machines. It also collected 
the server logs from the nodes and shut down all the servers. Any blocked servers were killed 
and the relative machines were excluded from the pool. 
    Once the load data from each machine was collected it was processed in order to be merged 
in a single file. Then graphical representations of the load were generated. All the results from 
the test were stored in a single output directory. There was one output directory for each run of 
the test. The directory contained the log of the main script, the log of each application server, the 
load data, the graphical representation of the load and the ECPerf output files. 
    If the test was successful it was removed from the list of tests. The main script repeated this 
procedure until all of the tests were executed. 




UBLCS-2006-13                                                                                               69
                                                                           6 ONT Replication Algorithm

7.1.2     Benchmarking of the replication framework 




                              Figure 4 Replication Framework Overhead
    One of the first benchmarks we had to perform was testing the overhead introduced by our 
framework.  In  our  experimental  setup,  the  JBoss  application  server  and  the  PostgreSQL 
database management system run on a single 2.4 GHz Pentium IV Linux machine with 1 GB of 
RAM (which is otherwise idle). Clients are executed on a different machine, located on the same 
local area network. In this environment, we measured the performance of two configurations. 
The  first  was  JBoss,  without  the  replication  framework  (and  without  the  JBoss  replication 
mechanism).  The  second  (ADAPT)  was  JBoss  with  the  replication  framework  modified 
configuration, with a “dummy” replication algorithm that causes it to behave as a normal non‐
replicated server. These are the results we have obtained: 
    The  general  shape  of  both  curves  is  the  same:  the  number  of  operations  increases  linearly 
with  the  target  transaction  rate  until  the  server  becomes  overloaded.  After  this  point,  some 
transactions  begin  being  aborted,  due  to  timeout  or  contention  on  the  database  management 
system. This overload threshold is reached at 21 transactions per second for unmodified JBoss, 
and  at  18  transactions  per  second  for  the ADAPT  configuration.  The  throughput  maxima  are 
2105  and  1800  business  operations  per  minute  respectively.  In  other  words,  the  penalty  for 
adding the framework is a 22% drop in throughput on a single node cluster. One should also 
note  that  beyond  the  overload  threshold,  performance  degrades  more  steeply  in  the  ADAPT 
configuration. 
    Clearly,  adding  the  framework  has  a  real  impact  on  the  server.  However,  at  1800  ECPerf 
business operations per minute, the performance is still quite practical, enabling developers to 
run realistic benchmarks against their prototype replication algorithms. The modifications add 
a  performance  cost  of  about  22%.  We  believe  this  cost  is  quite  acceptable  for  prototyping, 
because the development of replication algorithms is much easier within the framework. If an 
algorithm  performs  well  in  this  prototyping  environment,  developers  may  consider  re‐
implementing  it  by  direct  modification  of  the  server.  However,  this  is  unlikely  to  improve 
performance  by  as  much  as  22%.  First,  some  of  the  implementation  mechanisms  of  the 
framework, such as interception of invocations, will be required in a “direct” implementation as 


UBLCS-2006-13                                                                                           70
                                                                          6 ONT Replication Algorithm

well.  But  more  importantly,  replication  algorithms  add  other  substantial  performance  costs, 
such as inter‐server communication. 



7.1.3     Benchmarking of the ONT Replication Algorithm 
   In  order  to  test  the  performance  of  the  ONT  replication  algorithm  we  had  to  perform  two 
kinds of tests. The first one is to test the behavior of the algorithm in a normal application that 
does not use ONTs. The second one involved modification of the ECPerf application in order to 
extend it for ONTs. 
   For the first testing we have run the ECPerf benchmark in three different scenarios:  
        • non replicated JBoss 
        • replicated JBoss with its own replication algorithm 
        • replicated JBoss with our ONT replication algorithm 
   For  the  first  configuration  we  have  used  three  hosts:  one  for  the  client,  one  for  the 
application server and one for the database. The second configuration uses four hosts: one for 
the  client,  two  for  the  primary  and  backup  of  JBoss,  and  one  for  the  shared  database.  The 
database  is  shared  in  JBoss  clustering.  Finally,  the  third  configuration  of  JBoss  is  the  one 
implementing  our  replication  algorithm  (Our  Rep.  Alg.).  In  this  configuration,  there  are  two 
JBoss instances and two database instances, the four instances running on separate hosts, plus a 
host running the clients. Each JBoss instance is connected to its own database, so databases are 
not shared. 




                        Figure 7.5 ONT Replication Throughput with ECPerf
     All con figurations fulfill the ECPerf target till 20 IR. Our replication algorithm saturates for 
higher IR. JBoss clustering and the non‐replicated JBoss are almost able to accomplish the target 
with a load of 25 IR, although being strict they only accomplish it with a 21 IR. It is also worth to 
notice that the non‐replicated JBoss degrades more gracefully under saturation. This means that 
in  terms  of  throughput  our  replication  algorithm  reduces  the  maximum  throughput  around  a 
20% (5% in the strict terms of ECPerf target). 




UBLCS-2006-13                                                                                          71
                                                                          6 ONT Replication Algorithm




                          Figure 7.6 ONT Replication Latency with ECPerf
    As  expected,  JBoss  std.  offers  the  lowest  response  time,  since  it  does  not  incur  in  any 
overhead due to replication. Till 10 IR the response time of our algorithm is similar to the one of 
JBoss  clustering  and  the  non‐replicated  JBoss.  However,  from  10  to  20  IR  the  overhead  of 
replication has a noticeable impact on the response time of our algorithm becoming higher than 
the one of JBoss primary‐backup. However, the response time is still within the limits admitted 
by  ECPerf  (2  seconds).  This  means  that  for  moderate  loads  the  overhead  of  our  replication 
algorithm  is  negligible  and  only  for  high  loads  it  results  in  an  increased,  although  still 
reasonable, response time. This is due to the fact that JBoss does not replicate Entity Beans. So 
our algorithm provides fault tolerance even for Entity Beans at the cost of a loss of 20% in terms 
of performance. 
     
    As we said earlier, the second test involved the modification of the ECPerf software. ECPerf 
is  written  to  benchmark  the  base  functionalities  of  a  J2EE  server.  These  do  not  include  the 
J2EEAS service. In order to test the overhead of replicating ONTs we have extended ECPerf. We 
have built a customized “benchmark” that consists of a shopping cart application derived from 
the one in the ECPerf order entry application domain. 




UBLCS-2006-13                                                                                          72
                                                                            6 ONT Replication Algorithm




    Clients  add  items  to  a  cart.  The  first  time  a  client  adds  an  item,  an  ONT  transaction 
representing  the  cart  is  created.  Each  time  that  a  client  adds  an  item  to  the  cart,  a  child 
transaction of the top‐level ONT transaction is started. Within this transaction, the application 
updates the client credit and stock of the item accordingly. Each of these two actions is a nested 
ONT  transaction.  When  any  of  these  ONT  transactions  commits,  a  compensating  action  is 
registered  in  the  parent  transaction  (Middle  TX).  If  the  customer  has  credit  enough  and  the 
selected item is available in the stock, the item is added to the cart, and the middle ONT sub‐
transaction  registers  the  compensators  with  the  top‐level  ONT  transaction.  If  the  parent 
transaction aborts, the compensating actions will be executed. The compensating action for the 
item  increases  the  quantity  of  the  item  in  the  stock.  The  one  for  the  customer  increases  the 
customer credit. On the other hand, if one of the checks fails, the middle sub‐transaction rolls 
back  executing  the  registered  compensators.  Finally,  the  client  decides  whether  to  buy  the 
contents  of  the  cart,  and  then  the  top‐level  ONT  transaction  is  committed  or  aborted, 
respectively.  If  the  top‐level  ONT  transaction  is  committed  the  compensators  are  forgotten. 
Otherwise,  the  compensators  are  executed  by  the  top‐level  ONT  transaction  undoing  the 
changes  previously  made  by  its  children  transactions.  The  client  for  the  shopping  cart 
application  is  also  an  adaptation  of  the  ECPerf  entry  order  application  in  order  to  generate 
client requests in the same way as ECPerf does. The injection rate (IR) is the parameter used for 
determining the experiment load. Every client adds between five and fifteen items to the cart. 
    In this experiment, we have run the activity service benchmark we have devised under two 
configurations.  The  baseline  configuration  (JBoss  Non‐Replicated)  consists  of  three  hosts:  JBoss 
with  the  J2EEAS  and  the  ONT  running  as  MBeans  on  one  host,  one  database  running  on 
another host, and the clients running in a third host. The second configuration (Our Rep. Alg.) 
runs our replication algorithm for ONTs on five hosts, one for the clients, two hosts for the two 
JBoss instances with J2EEAS, and two hosts for the two database instances. As in the previous 
experiments the database is not shared, each JBoss is connected with one of the databases. The 
JBoss  clustering  configuration  was  not  used  this  time,  since  JBoss  clustering  does  not  support 
the replication of activities. 


UBLCS-2006-13                                                                                            73
                                                                              6 ONT Replication Algorithm




                    Figure 7.7 ONT Replication Throughput with Extended ECPerf
   The  throughput  of  both  the  non‐replicated  JBoss  and  our  replication  algorithm  are  again 
very close. They are able to reach the benchmark target till an IR of 7. The throughput beyond 7 
IR keeps similar till IR=10. At that point, our replication algorithm degrades very fast, whilst the 
non‐replicated  JBoss  exhibits  a  more  or  less  flat  curve  before  falling.  The  reason  for  the  faster 
degradation  of  our  replication  algorithm  is  the  overhead  incurred  that  although  is  moderate, 
once the server saturates it becomes noticeable. In summary, our replication algorithm shows a 
good  behavior  for  longer  client  interactions.  The  overhead  of  replicating  activities  is  not 
perceptible in terms of throughput and response time. 




                      Figure 7.8 ONT Replication Latency with Extended ECPerf
    It  can  be  observed  that  the  response  time  of  our  replication  algorithm  is  very  close  to  the 
non‐replicated  JBoss  for  all  the  injection  rates.  The  response  time  only  increases  on  average 
around 50 ms. although with high IR rates the gap between the two curves increases. This is due 
to the overhead introduced by the replication algorithm. 

7.2        Custom Benchmarks 
   The  ECPerf  benchmark  is  a  big  piece  of  software  which  requires  a  lot  of  configuration  in 
order  to  make  performance  measurements  of  an  application  server.  One  of  the  biggest 
disadvantages  is  that  the  injection  rate  is  specified  statically  and  to  increase  the  load  of  the 
UBLCS-2006-13                                                                                                74
                                                                         6 ONT Replication Algorithm

system, a whole new test must be run. Even with our mechanism for automating ECPerf testing 
a  single  replication  algorithm  could  take  days.  This  becomes  very  inadequate  during  the 
development phase where new optimizations and bug fixes are introduced every day. Another 
weak point of the ECPerf benchmark is that it uses the 1.1 version of CMP. 
    We  wanted  to  test  how  version  2.x  CMP  beans  are  replicated  in  our  algorithms  and  we 
wanted  to  do  it  efficiently.  We  needed  a  benchmarking  software  that  would  adapt  the  load 
dynamically to automatically test the capacity of the server to handle high load. For this reason 
we decided to develop our own benchmarking software. 
    In  order  to  provide  a  realistic  scenario  and  to  avoid  making  a  benchmark  that  would 
naturally evaluate the replication algorithm, the application was designed taking as an example 
the  Duke’s  Bank  Application  provided  with  the  J2EE  reference  implementation.  The  original 
application is based on the Struts object/relational mapping software. We have maintained the 
interfaces of the beans, but have provided CMP v2.0 implementations. 
    The client of the application starts multiple threads that perform invocations on the beans. 
Unlike the ECPerf client, in our case the threads do not sleep between invocations. Each thread 
will perform an invocation as soon as it receives the response to the previous one. It is enough 
to have a single thread making requests to heavily load the server. Servers usually have thread 
pools processing requests by different clients. This approach can take advantage of dead times 
when  having  multiple  concurrent  requests.  For  example  a  thread  might  check  the  security 
permissions  of  the  client  while  another  thread  is  blocked  waiting  for  the  results  from  the 
underlying database. 
    The  main  client  that  starts  the  threads  will  add  threads  one  by  one.  The  client  two 
parameters:  the  desired  overall  duration  of  the  test  and  the  maximum  number  of  threads 
reached. The overall duration will be divided by the maximum number of threads in order to 
obtain the duration of a single period between starting one thread and the next. For each period, 
the client will measure the total number of requests performed in that period and calculate the 
average throughput and latency for the period. 
    We have tested the following configurations: 
       • Non‐replicated JBoss 
       • JBoss with the default replication implementation 
       • JBoss with the Transaction Replication Algorithm based on JGroups 
       • JBoss  with  the  Transaction  Replication  Algorithm  based  on  JGroups  with 
         asynchronous broadcast 
       • JBoss  with  the  Transaction  Replication  Algorithm  based  on  JGroups  with 
         asynchronous broadcast with Stateful Session Bean Replication Only 
       • JBoss with the Transaction Replication Algorithm based on JBora 
       • JBoss with the Transaction Replication Algorithm based on JBora with asynchronous 
         broadcast (partial) 
       • JBoss with the Advanced Transaction Replication Algorithm based on JGroups 
       • JBoss  with  the Advanced  Transaction  Replication Algorithm  based  on  JGroups  with 
         asynchronous broadcast 
    For  each  of  the  above  configurations,  except  the  non‐replicated  one,  we  have  performed 
different  tests  with  varying  number  of  nodes  to  verify  for  scalability  problems.  During  the 
preliminary tests we have noticed that JBoss had problems handling more than 80 threads. We 
have not established whether this was due to the operating system, the JVM or JBoss. However 
we  have  noticed  that  increasing  the  number  of  threads  does  not  have  any  impact  on  the 
UBLCS-2006-13                                                                                         75
                                                                                                              6 ONT Replication Algorithm

throughput except for less than 10 threads. In regard of these considerations, we have chosen 50 
to be the maximum number of threads. 

7.2.1     Non Replicated JBoss 
  The first scenario we present is the non replicated JBoss. This will represent our baseline for 
making performance comparisons since there is no replication overhead involved. 

                                                                               Throughput

                       600


                       500


                       400
               ops/s




                       300


                       200
                                                                                                                      8 nodes
                       100                                                                                            4 nodes
                                                                                                                      2 nodes
                         0
                                 1       3       5       7       9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49

                                                                                     # threads


                                                 Figure 7.9 Non Replicated JBoss Throughput

                                                                                 Latency

                        120


                        100


                         80
                   ms




                         60


                         40
                                                                                                                    8 nodes
                         20                                                                                         4 nodes
                                                                                                                    2 nodes
                             0
                                     1       3       5       7   9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49
                                                                                     # thre ads



                                                         Figure 7.10 Non Replicated JBoss Latency
   We expect any primary/backup replication protocol to have lower performance than a single 
node  non  replicated  JBoss  server.  We  may  notice  how  the  latency  grows  linearly  with  the 
number of threads. This is because the request queue on the server grows and each client thread 
has to wait longer for a response. 

7.2.2     Default JBoss Replication 
   Next we have measured the performance of the default JBoss replication implementation. 
The default JBoss clustering uses the horizontal replication approach, where the various nodes 
rely  on  a  shared  database  to  enforce  concurrency  control  and  Entity  Beans  sharing.  For  this 
UBLCS-2006-13                                                                                                                         76
                                                                                           6 ONT Replication Algorithm

reason  JBoss  can  easily  act  as  a  multi‐primary  cluster.  Since  all  our  replication  algorithms  are 
primary/backup, we have configured JBoss to act as a primary/backup cluster instead of multi‐
primary.  This  was  done  by  setting  the  load  balance  policy  to  FirstAvalableIdenticalAllProxies. 
We have tried this replication with an 8 node, a 4 node and a 2 node cluster and compared the 
results. 

                                                            Throughput

                        350

                        300

                        250

                        200
                ops/s




                        150

                        100                                                                        8 nodes
                                                                                                   4 nodes
                         50
                                                                                                   2 nodes
                          0
                              1   3   5   7   9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49

                                                                  # threads


                                  Figure 7.11 Default JBoss Replication Throughput

                                                              Latency

                        350

                        300

                        250

                        200
                ms




                        150

                        100
                                                                                                   8 nodes
                         50                                                                        4 nodes
                                                                                                   2 nodes
                          0
                              1   3   5   7   9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49

                                                                  # threads


                                      Figure 7.12 Default JBoss Replication Latency
    We can notice how varying the number of nodes does not have impact on throughput and 
latency.  This  is  because  we  are  using  a  primary/backup  schema  and  there  is  only  one  node 
processing requests. This is also a sign of the scalability of the communication protocol. 

7.2.3      Transaction Replication Algorithm 
   Next  we  have  compared  our  Transaction  Replication  Algorithm  that  uses  a  vertical 
approach.  Each  node  has  its  own  database  and  Entity  Beans  are  replicated  by  the  application 
server. This means that there is more data that has to be replicated, and we may expect higher 
overhead. 


UBLCS-2006-13                                                                                                      77
                                                                                              6 ONT Replication Algorithm


                                                              Throughput


                        180

                        160
                        140
                ops/s   120

                        100

                         80

                         60                                                                        8 nodes
                         40                                                                        4 nodes
                         20                                                                        2 nodes
                          0
                              1   3    5    7   9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49

                                                                    # threads


                                      Figure 7.13 Transaction Replication Throughput


                                                                Latency


                        500
                        450
                        400
                        350
                        300
                ms




                        250
                        200
                        150                                                                      8 nodes
                        100                                                                      4 nodes
                         50                                                                      2 nodes
                          0
                              1   3    5    7   9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49

                                                                    # threads


                                           Figure 7.14 Transaction Replication Latency
    Our replication algorithm blocks after it sends a broadcast to the group until it receives its 
own message. We call this Synchronous Broadcast. Synchronous Broadcast increases the latency 
of  processing  a  single  request  and  consequently  puts  more  threads  in  the  waiting  queue. An 
alternative to Synchronous Broadcast is Asynchronous Broadcast. It is used in most implemented 
replication algorithms, especially in databases. In Asynchronous Broadcast we do not block for 
a message to be received but continue processing a request and leave the group communication 
layer in charge of dealing with this. The drawback of asynchronous broadcast is that when we 
send the request to the client, there is no guarantee that the data has actually been replicated. In 
commercial replication implementations asynchronous broadcast is often adopted at the cost of 
reliability  because  the  probability  that  a  server  crashes  in  the  time  gap  between  sending  a 
response to the client and completing the broadcast algorithm is very low. 
    We have tried to measure the impact of the broadcast protocol latency by disabling blocking 
after replication. The improvement we have obtained is represented in these graphs: 


UBLCS-2006-13                                                                                                         78
                                                                                         6 ONT Replication Algorithm


                                                            Throughput

                    250


                    200


                    150
            ops/s



                    100

                                                                                                 8 nodes
                     50
                                                                                                 4 nodes
                                                                                                 2 nodes
                      0
                          1   3    5    7   9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49

                                                                # threads


                Figure 7.15 Transaction Replication Throughput (without blocking)

                                                             Latency

                    350

                    300

                    250

                    200
            ms




                    150

                    100
                                                                                               8 nodes
                     50                                                                        4 nodes
                                                                                               2 nodes
                      0
                          1   3    5    7   9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49

                                                                # threads


                    Figure 7.16 Transaction Replication Latency (without blocking)
                                                            Throughput



                                  180
                                  160
                                  140
                                  120
                                  100
                                   80
                                   60
                                   40
                                   20
                                    0
                                                 blocking             non blocking


                          Figure 7.17 Throughput Improvement Without Blocking




UBLCS-2006-13                                                                                                    79
                                                                                            6 ONT Replication Algorithm


                                                                 Latency



                                     200


                                     150


                                     100


                                      50


                                       0
                                                    blocking               non blocking


                                 Figure 7.18 Latency Improvement Without Blocking
   Without blocking we have improved throughput by 31.1% and lowered latency by 37.2%. 
    
   From  the  numbers  we  can  see  that  our  algorithm  still  performs  slightly  worse  than  JBoss 
replication. However we must consider that ours is a non‐optimized prototype implementation 
and that we replicate entity beans as well. In order to verify if the overhead really comes from 
replicating  Entity  Beans,  we  have  disabled  Entity  Bean  replication  from  our  algorithm  by 
commenting out the relative code. 

                                                               Throughput

                       300


                       250


                       200
               ops/s




                       150


                       100
                                                                                                   8 nodes
                        50                                                                         4 nodes
                                                                                                   2 nodes
                         0
                             1   3    5    7   9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49

                                                                   # threads


                        Figure 7.19 Transaction Replication Throughput (SFSB only)




UBLCS-2006-13                                                                                                       80
                                                                                                   6 ONT Replication Algorithm


                                                                  Latency

                   350

                   300

                   250

                   200
              ms


                   150

                   100
                                                                                                         8 nodes
                    50                                                                                   4 nodes
                                                                                                         2 nodes
                     0
                         1    3   5    7    9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49

                                                                      # threads


                         Figure 7.20 Transaction Replication Latency (SFSBs only)
   From  the  graphs  we  can  see  that  now  our  algorithm  performance  is  very  close  and 
sometimes better than the JBoss replication. 
                                                        Throughput Com paris on

                                    500
                                    450
                                    400
                                    350
                                    300
                             ops /s 250
                                    200
                                    150
                                    100
                                     50
                                      0
                                            non-replicated       jboss          tx rep    tx rep (SFSB
                                                               replication                     only)

                    Figure 7.21 Transaction Replication Throughput Comparison
                                                             Le te ncy Com paris on


                                      140
                                      120
                                      100
                                       80
                              ms
                                       60
                                       40
                                       20
                                        0
                                            non-replicated      jboss         tx rep     tx rep (SFSB
                                                              replication                     only)

                         Figure 7.22 Transaction Replication Latency Comparison
     
    As another experiment we have tried to change the underlying group communication layer. 
We have performed some of the tests with the JBora toolkit. These are the performance results 
of the synchronous variant: 


UBLCS-2006-13                                                                                                              81
                                                                                           6 ONT Replication Algorithm


                                                           Throughput


                       200
                       180
                       160
                       140
                       120
               ops/s

                       100
                        80
                        60                                                                      8 nodes
                        40                                                                      4 nodes
                        20                                                                      2 nodes
                         0
                             1   3   5   7   9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49

                                                                 # threads


                         Figure 7.23 Transaction Replication Throughput with JBora


                                                             Latency


                       400

                       350

                       300

                       250
               ms




                       200

                       150
                                                                                              8 nodes
                       100
                                                                                              4 nodes
                        50                                                                    2 nodes
                         0
                             1   3   5   7   9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49

                                                                 # threads


                             Figure 7.24 Transaction Replication Latency with JBora
   We  may  notice  how  JBora  introduces  some  latency  when  the  number  of  threads  is  lower 
than 10. 




UBLCS-2006-13                                                                                                      82
                                                                                           6 ONT Replication Algorithm


                                                                 Throughput

                       200
                       180
                       160
                                                                                               8 nodes jbora
                       140
                                                                                               4 nodes jbora
                       120
                                                                                               2 nodes jbora
               ops/s



                       100                                                                     8 nodes jgrops
                        80                                                                     4 nodes jgroups
                        60                                                                     2 nodes jgroups

                        40
                        20
                            0
                                1   2       3       4        5     6   7      8   9   10
                                                         # thre ads


                    Figure 7.25 Transaction Replication Throughput with JBora (detail)

                                                                  Latency

                       80

                       70

                       60                                                                      8 nodes jbora
                                                                                               4 nodes jbora
                       50
                                                                                               2 nodes jbora
               ms




                       40                                                                      8 nodes jgroups
                                                                                               4 nodes jgroups
                       30
                                                                                               2 nodes jgroups
                       20

                       10

                        0
                                1   2   3       4        5        6    7    8     9   10
                                                        # thre ads


                        Figure 7.26 Transaction Replication Latency with JBora (detail)
     
    We  believe  that  this  is  a  consequence  of  the  message  packing  performed  by  JBora,  where 
multiple messages are packed into one in order to improve throughput. In this way, only one 
round of the broadcast protocol may be performed for multiple messages. If there is only one 
message to be transmitted, the group communication layer waits a certain time interval to see if 
other  messages  get  queued  for  transmission.  This  time  interval  gets  perceived  in  the  overall 
latency of replication for a low number of threads. 

7.2.4     ONT Replication Algorithm 
   Since  the  ONT  replication  algorithm  uses  the  same  components  as  the  flat  transaction 
replication algorithm, we expect the performance to be very close. Here are the graphs for the 
asynchronous version of the ONT Replication Algorithms: 




UBLCS-2006-13                                                                                                      83
                                                                                           6 ONT Replication Algorithm


                                                           Throughput
                       300


                       250


               ops/s   200


                       150


                       100                                                                      8 nodes
                                                                                                4 nodes
                        50                                                                      2 nodes


                         0
                             1   3   5   7   9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49

                                                                 # threads

                                         Figure 7.27 ONT Replication Throughput

                                                              Latency
                       300


                       250


                       200
               ms




                       150


                       100
                                                                                               8 nodes
                                                                                               4 nodes
                        50                                                                     2 nodes


                         0
                             1   3   5   7   9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49

                                                                 # threads

                                             Figure 7.28 ONT Replication Latency
   As  expected  performance  is  very  close  to  the  asynchronous  version  of  the  Transaction 
Replication Algorithm. There is no point in repeating all the detailed tests with variants of this 
replication algorithm since the results are very likely to reflect what we have already seen in the 
previous algorithm. 

7.3       Profiling 
   We  have  used  profiling  software  to  find  out  what  parts  of  our  algorithms  introduce  most 
overhead. The profiler intercepts every method invocations in the JVM and measures CPU time 
spent  in  each  method  of  the  profiled  program.  We  have  profiled  the  JBoss  application  server, 
but we have excluded the classes that belong to JBoss from monitoring. We have obtained the 
CPU time spent in each of the methods of our framework and our replication algorithm. 
   The time spent in a method includes also the time spent in all the invoked methods. Since we 
are using a chain of responsibility design pattern, the time spent in each interceptor includes the 
time  spent  in  the  following  interceptors.  We  have  extracted  a  view  of  an  invocation  tree  that 
includes our chain of interceptors. 
UBLCS-2006-13                                                                                                      84
                                                                           6 ONT Replication Algorithm




    We  are  displaying  only  the  first  bean  invocation  of  the  invocation  tree.  Nested  invocations 
are contained in EJBRequest.execute(). The root node is the entry point in the interceptor 
chain for the replication algorithm. We can see how most of the CPU time of each interceptor is 
spent in the invocation of the next interceptor. There was a total of 256 invocations, which took 
50.960ms  of  CPU  time.  The  point  where  we  exit  the  interceptor  chain  is  the execute() 
method of the EJBcomponent handle. 
    The  only  two  cases  where  we  add  some  significant  overhead  are  the 
GCLReplicator.replicate() method (5.5% of total time), which sends the changes to the 
backups, and the addModifiedBean() method of the TransactionalChangesCollector  
(7.4% of total time), which serializes the state of the beans in the Changes Data Structure. 
UBLCS-2006-13                                                                                           85
                                                                         6 ONT Replication Algorithm

   The  replicate()  method  does  not  have  very  significant  impact  on  the  overall 
performance  because  it  gets  executed  only  once  per  invocation  tree.  On  the  other  side,  the 
addModifiedBean()  gets  executed  for  every  local  invocation  in  the  invocation  tree.  If  we 
expand the view we can find it occurring again several times further down the invocation tree. 
The  total  time  spent  in  that  method  during  the  whole  invocation  tree  was  20  seconds,  which 
represents  40%  of  the  total  CPU  time.  Along  with  the  overhead  introduced  by  the 
replicate()  method  and  the  rest  of  the  framework  this  explains  the  performance  gap 
between the non replicated case and our replication algorithm. 
   The interesting result here is that the bottleneck of EJB replication is not the communication 
overhead, but Java serialization. We believe that serialization performance can be significantly 
improved using explicit externalization. However, since this is a prototype algorithm, we have 
not researched deeper in this direction. 
    
   By  analyzing  the  performance  of  the  implemented  algorithms,  we  have  shown  that  the 
building  blocks  provide  a  viable  approach  form  implementing  replication  of  an  application 
server.  Considering  that  the  developed  software  is  at  a  prototype  stage,  when  compared  to 
stable industrial solutions the results are very promising.




UBLCS-2006-13                                                                                         86
Chapter 8 

Conclusions 

8.1       Contributions 
    The work of this thesis comprises several contributions to the area of component replication 
and  replication  in  general.  Modern  component  based  middleware  provide  a  model  that  has 
some  interesting  characteristics  when  it  comes  to  replication.  We  have  seen  how  neither 
algorithms from distributed systems nor databases take advantage of its features nor solve some 
peculiar problematic issues when dealing with components.  Since components have the ability 
to invoke each other, when replicating them we have to pay attention to their interactions.   
    We  have  identified  a  generic  approach  to  replicate  components  that  takes  into  account  the 
invocations between components. This approach encompasses a set of more specific replication 
algorithms.  The  generalization  is  an  identification  of  the  common  tasks  of  component 
replication  algorithms  such  as  collecting  changes,  sending  the  changes,  keeping  track  of  the 
membership, detecting duplicate requests, etc. 
    Our generic approach takes the form of a replication framework based on building blocks. 
Each  block  takes  care  of  a  particular  aspect  of  component  replication.  The  building  blocks 
enable  rapid  composition  of  replication  algorithms.  As  a  proof  of  concept  of  our  replication 
framework  we  have  implemented  several  replication  algorithms.  Some  of  these  algorithms 
present novel contributions to component replication and replication in general.  
    We  have  developed  an  algorithm  for  transaction  replication.  This  algorithm  enables  the 
client to start a transaction on one server and, in case of failure, finish it on another server. This 
ability  is  particularly  important  for  long  running  transactions  where  replaying  the  whole 
transaction from the beginning would be unacceptably expensive. 
    We  have  extended  the  concept  of  replicating  transactions  in  another  algorithm  to  replicate 
Open  Nested  Transactions  implemented  in  the  J2EEAS  service.  Open  Nested  Transactions  are 
more  appropriate  than  flat  transactions  for  long  running  transactions,  thus  the  reliability 
requirement becomes even more important. 
    Finally  we  have  benchmarked  our  replication  algorithms  using  an  industry  standard 
benchmark and compared their performance with industrial replication solutions. Even if these 
comparisons were not fair because our algorithms provided a major degree of fault tolerance, 
we showed that these extra features did not have a significant impact on performance. 
    While  performing  the  benchmarks  we  also  developed  an  automated  system,  to  simplify 
benchmark  execution  in  clustered  environments.  The  machine  selection  method  of  our 
automated  system  proved  to  be  very  useful  in  an  environment  with  shared  machines  where 
other  users  could  interfere  with  the  benchmarks.  Moreover  we  have  extended  the  ECPerf 
                                                                                        8 Conclusions

benchmarking software for Open Nested Transactions making it the first benchmark for Open 
Nested Transactions. 
    

8.2      Implementation Effort 
   The whole work of this thesis took 3 years to complete. The most difficult part of this thesis 
was  the  implementation  and  integration  of  considerably  complex  software.  Several  software 
deliverables were produced: 
       • Replication  Framework  –  this  is  the  largest  and  most  complex  part.  It  includes  the 
         Application Server Abstraction Layer and the Building Blocks.  
       • Transaction Replication Algorithm – includes the additional building blocks to construct 
         the  transaction  replication  algorithm  and  the  actual  Component  Monitor  that 
         combines them. 
       • Open  Nested  Transaction  Algorithm  –  extension  of  an  existing  ONT  manager 
         implementation  and  the  relative  replication  algorithm  based  on  the  replication 
         framework. 
       • Extended  ECPerf  for  Open  Nested  Activities  –  extension  of  the  ECPerf  Benchmarking 
         software  with  an  additional  application  domain  that  uses  Open  Nested  Transactions 
         for benchmarking Open Nested Transaction Replication. 
       • Automated  Benchmarking  System  –  the  script  based  system  used  to  automatically  run 
         ECPerf tests 
       • Benchmarking Software – our customized benchmarking software 
  There have been other software implementations during the research for this thesis, but they 
were mostly for understanding and testing functionality of the underlying software. 




UBLCS-2006-13                                                                                        88
                                                                                             8 Conclusions

   The  following  table  indicatively  summarizes  the  size  of  the  various  software  deliverables 
produced: 
    

                                                        Java Classes Lines of Code 
              Replication Framework (total)                          326               36,717  
                   Actual framework                                  149                21,166  
                   JUnit Tests                                       177                15,551  
              Transaction Replication                                  42               3,766  
              ONT Replication (total)                                191               25,733  
                   Replication Algorithm (estimated)                   20                4,226  
              Extended ECPerf (total)                                253               57,969  
                   ONT Part (estimated)                                32                4,691  
              Automated Benchmarking System                   49 (scripts)              1,295 
              Custom Benchmarking Software                             38               2,420  
     
    The  ADAPT  replication  framework  implementation  can  be  downloaded  from: 
http://sourceforge.net/projects/j2ee‐adapt/  .  The  transaction  replication  algorithm,  the 
automated  benchmarking  scripts  and  the  custom  benchmarking  software  can  be  downloaded 
from  the  CVS  repository  at  :extssh:adapt.cs.unibo.it:/usr/cvsroot.  The  ONT  replication 
algorithm  and  the  extended  ECPerf  can  be  downloaded  from  the  CVS  repository  at 
:extssh:adapt01.fi.ls.upm.es:/usr/cvsroot. 

8.3       Research Directions 
    The progress made during this thesis opened many new research directions. We are already 
working on some of these directions but they were not included in this thesis because of their 
incomplete status. 
    Probably  the  most  interesting  is  the  implementation  of  distributed  concurrency  control  as  a 
building  block.  This  will  enable  development  of  multi‐primary  replication  algorithms  which 
will  increase  the  scalability  of  the  system.  Currently  we  have  a  working  implementation  of 
distributed  locks  that  has  not  yet  been  integrated  with  the  replication  framework  nor 
benchmarked.  An  interesting  research  direction  is  to  analyze  the  implications  of  performing 
different methods distributed concurrency control with transaction replication. 
    Another  branch  derived  from  this  thesis  is  a  client  based  replication  algorithm  for  stateful 
session  beans.  Currently  there  is  a  working  prototype  developed  without  the  use  of  the 
framework.  The  integration  of  the  prototype  with  the  framework  would  allow  not  only 
replication of Stateful Session Beans, but also other data associated with a client like for example 
the state of transactions. 
    Finally we have to consider that the actual framework is just a prototype and still lacks some 
features like duplicate request detection and state transfer for joining nodes. There are already 
proven  solutions  for  these  problems.  For  sake  of  completeness,  the  existing  solutions  can  be 
implemented  as  building  blocks  of  the  framework.  The  modular  design  of  the  framework 
would allow us to seamlessly add these features to all the replication algorithms implemented 
using our framework. 


UBLCS-2006-13                                                                                             89
                                                                                             8 Conclusions

    The  work  of  this  thesis  also  creates  the  foundations  upon  which  to  design  and  build 
completely  new  replication  algorithms  for  the  J2EE  platform.  There  are  many  aspects  of 
replication  that  this  thesis  didn’t  take  into  account.  These  aspects  include  partial  replication, 
dynamic  load  balancing,  optimistic  strategies,  partitionable  clusters,  etc.  There  is  already 
significant research done in many of these areas, but applying this research to a complex system 
such as J2EE is a difficult task. Our replication framework enables fast and easy development of 
replication  algorithms  where  only  additional  features  need  to  be  implemented.  We  hope  that 
this contribution will promote research applied to real middleware implementations and fill a 
bit of the gap between industry and research. 




UBLCS-2006-13                                                                                             90
                                                                                                     References




   References 

 [1]   M. Wiesmann, F.Pedone, A. Schiper, B. Kemme and G. Alonso: Understanding Replication 
       in Databases and Distributed Systems, ICDCS 2000: 464‐474 

 [2]   P. Bernstein, V. Hadzilacos and N. Goodman: Concurrency Control and Recovery in Database 
       Systems, Addison Wesley, 1987 

 [3]   J.  Gray,  P.  Helland,  P.  E.  O’Neil,  and  D.  Shasha:  The  dangers  of  replication  and  a  solution, 
       Proc.  of  the ACM  SIGMOD  Int.  Conf.  on  Management  of  Data,  pp.  173–182,  Montreal, 
       Canada, June 1996. 

 [4]   L.  Lamport:  How  to  Make  a  Multiprocessor  Computer  That  Correctly  Executes  Multiprocess 
       Programs, IEEE Trans. Computers, vol. 28, no. 9, pp. 690‐691, Sept. 1979. 

 [5]   M.  Herlihy,  J  Wing:  Linearizability:  A  Correctness  Condition  for  Concurrent  Objects,  ACM 
       Transactions on Programming Languages and Systems, 12(3): 436‐492, July 1990. 

 [6]   H.  Attiya,  J.  Welch:  Sequential  Consistency  versus  Linearizability,  ACM  Transactions  on 
       Computer Systems, May 1994. 

 [7]   H.  Kung,  J.  Robinson:  On  optimistic  methods  of  concurrency  control, ACM  Transactions  on 
       Database Systems 6: 213–226, 1981. 

 [8]   M.  J.  Fischer,  N.  A.  Lynch,  M.  S.  Paterson:  Impossibility  of  distributed  consensus  with  one 
       faulty process, Journal of the ACM 32(3) (1985) 374–382. 

 [9]   P.  Bernstein,  N.  Goodman:  An  algorithm  for  concurrency  control  and  recovery  in  replicated 
       distributed  databases,  ACM  Transactions  on  Database  Systems  9,  pp.  596‐615,  December 
       1984. 

[10]   P.  Bernstein,  N.  Goodman:  Concurrency  Control  in  Distributed  Database  Systems,  ACM 
       Computing Surveys 13, June 1981 

[11]   M. Shapiro, R. E. Millstein: Rehability and fault recovery in distributed processing, in Oceans 
       ʹ77 Conf Record, vol II, Los Angeles, 1977. 

[12]   A.  Chan,  D.  Skeen:  The  reliability  subsystem  of  a  distributed  database  manager,  Tech.  rep. 
       CCA‐85‐02, Computer Corporation of America, 1986. 

[13]   D. K. Gifford: Weighted voting for replicated data, Proc. of the 7th ACM SIGOPS Symposium 
       on Operating Systems Principles, pp. 150‐159, December 1979. 
                                                                                                      References

[14]      P.  Alsberg,  J.  Day:  A  principle  for  resilient  sharing  of  distributed  resources,  in  Proc.  2nd 
          International Conference on Software Engineering, pp. 562‐570, October 1976. 

[15]      H. Garcia‐Molina: Performance of update algorithms for replicated data in a distributed database,  
          Ph.D.  dissertation,  Computer  Science  Dept.,  Stanford  University  of  Stanford, California, 
          June 1979 

[16]      R.  H.  Thomas:  A  solution  to  the  update  problem  for  multiple  copy  databases  which  uses 
          distributed control, Tech Rep. 3340, Bolt Beranek and Newman, July 1976. 

[17]      M.  Stonebraker:  Concurrency  control  and  consistency  of  multiple  copies  of  data  in  distributed 
          INGRES, IEEE Trans. Softw. Eng. SE‐5, pp. 188‐194, May 1979. 

[18]      C.  A.  Ellis:  Consistency  and  Correctness  of  Duplicate  Database  Systems,  ACM  SIGOPS 
          Operating  Systems  Review,  Vol.  11,  5,  Proc.  6th  Symposium  on  Operating  Systems 
          Principles, November 1977. 

[19]      Object  Management  Group:  The  Common  Object  Request  Broker:  Architecture  and 
          specification, 2.6 edition, OMG Technical Committee Document formal/02‐01‐02, jan 2002. 

[20]      E.  Moss:  Nested  Transactions:  An  Approach  to  Reliable  Distributed  Computing,  PhD  Thesis, 
          Massachusetts Institute of Technology Tech. Rep. MIT/LCS/TR‐260, 1981. 

[21]      Object Management Group: Fault tolerant CORBA, OMG Technical Committee Document 
          formal/2001‐09‐29, September 2001. 

[22]      P.  Narasimhan:  Transparent  Fault  tollerance  for  CORBA,  PhD  Thesis,  Department  of 
          Electrical and Computer Engineering, University of California, Santa Barbara, December 
          1999. 

[23]      P.  Felber,  P.  Narasimhan:  Reconciling  Replication  and  Transactions  for  the  End‐to  End 
          Reliability of CORBA Applications, CoopIS/DOA/ODBASE 2002: 737‐754 

[24]      P. Narasimhan, L. E. Moser, P. M. Melliar‐Smith: Eternal ‐ a component‐based framework for 
          transparent fault‐tolerant CORBA. Softw., Pract. Exper. 32(8): 771‐788 (2002) 

[25]      L.  E.  Moser,  P.  M.  Melliar‐Smith,  D.  A.  Agarwal,  R.  K.  Budhia,  C.  A.  Lingley‐
          Papadopoulos:  Totem:  A  Fault‐Tolerant  Multicast  Group  Communication  System.  Commun. 
          ACM 39(4): 54‐63 (1996) 

[26]      K.  Lakshman,  Raj  Yavatkar: AQuA  ‐  An  adaptive  end‐system  quality  of  service  architecture. 
          High‐Speed Networking for Multimedia Applications 1995: 155‐177  

[27]      Object  Management  Group:  Object  Transaction  Service  Specification,  OMG  Technical 
          Committee Document formal/01‐11‐03, May 2001 

[28]      M. G. Hayden: The Ensemble System, Ph.D Thesis, Cornell University, 1998 

[29]    J.  P.  Loyall,  R.  E.  Schantz,  J. A.  Zinky,  D.  E.  Bakken:  Specifying  and  Measuring  Quality  of 
        Service in Distributed Object Systems. ISORC 1998: 43‐52 
   UBLCS-2006-13                                                                                              92
                                                                                                  References

[30]    P.  Felber,  R.  Guerraoui, A.  Schiper:  The  Implementation  of  a  CORBA  Object  Group  Service, 
        TAPOS 4(2): 93‐105 (1998) 

[31]    G.  Morgan,  S.  Shrivastava,  P.  Ezhilchelvan  and  M.  Little:  Design  and  implementation  of  a 
        CORBA  fault_tolerant  object  group  service,  In  Proceedings  of  the  Second  IFIP  WG  6.1 
        International    Working  Conference  on  Distributed  Applications  and  Interoperable 
        Systems, Helsinki, Finland, June 1999. 

[32]    C.  Marchetti,  M.  Mecella,  A.  Virgillito,  R.  Baldoni:  An  Interoperable  Replication  Logic  for 
        CORBA Systems. DOA 2000: 7‐16 

[33]    B. Natarajan, A. S. Gokhale, S. Yajnik, D. C. Schmidt: DOORS: Towards High‐Performance 
        Fault Tolerant CORBA. DOA 2000: 39‐48 

[34]    S.  Maffeis:  Run  Time  Support  for  Object  Oriented  Distributed  Programming,  Ph.D  thesis, 
        University of Zurich, 1995 

[35]    K.P.  Birman  and  R.  van  Renesse:  Reliable  Distributed  Computing  with  the  Isis  Toolkit,  eds. 
        Los Alamitos, Calif.: IEEE CS Press, 1994. 

[36]    Sun Microsystems, The Java TM 2 Platform Enterprise Edition Specification v1.4, 2003 

[37]    Sun Microsystems, Enterprise JavaBeansTM Specification v2.1, 2002 

[38]    Sun Microsystems, JavaTM Message Service Specification v1.1, 2002 

[39]    Sun Microsystems, JavaTM Transaction Service Specification v1.0, 1999 

[40]    BEA Systems Inc, WebLogic Application ServerTM v8.1, http://www.bea.com 

[41]    BEA Systems Inc, Using WebLogic ServerTM Clusters, 2003 

[42]    IBM  Corporation,  The  IBM  WebSphere                      Application      Server,    http://www‐
        306.ibm.com/software/webserver/appserv.  

[43]    JBoss Group, JBoss v3.2.3, http://www.jboss.org 

[44]    J. Vuckovic: Jboss Clustering Analysis, 2003 

[45]    H.  Wu,  B.  Kemme,  V.  Maverick:  Eager  Replication  for  Stateful  J2EE  Servers. 
        CoopIS/DOA/ODBASE (2) 2004: 1376‐1394 

[46]    A.  I.  Kistijantoro,  G.  Morgan,  S.  K.  Shrivastava,  M.  C.  Little:  Component  Replication  in 
        Distributed Systems: A Case Study Using Enterprise Java Beans. SRDS 2003: 89‐98 

[47]    M.  Pasin,  M.  Riveill,  T.  Silva  Weber:  High‐Available  Enterprise  JavaBeans  Using  Group 
        Communication System Support,  

[48]    Y. Saito, M. Shapiro: Replication – Optimistic Approaches, HP Laboratories Palo Alto, 2002 


   UBLCS-2006-13                                                                                            93
                                                                                              References

[49]    ADAPT:  Middleware  technologies  for  Adaptive  and  Componsable  Distributed  Components,  
        Contract no. IST‐2001‐37126, http://adapt.ls.fi.upm.es/adapt.htm 

[50]    O.  Babaoglu,  A.  Bartoli,  V.  Maverick,  S.  Patarin,  J.  Vučković,  H.  Wu:  A  Framework  for 
        Prototyping J2EE Replication Algorithms, DOA2004: 

[51]    A. K. Elmagarmid, editor: Database Transaction Models. Morgan Kaufmann, 1992. 

[52]    Sun Microsystems. JSR 95: J2EE Activity Service for Extended Transactions , Mar. 2004. 

[53]    Sun Microsystems. Java Transaction API Specification (JTA) 1.01, Apr. 1999. 

[54]    Sun  Microsystems:  Java  Management  eXtension:  Instrumentation  and  Agent  Specification 
        v.1.1, 2002, http://java.sun.com/jmx/. 

[55]    G.Weikum  and  H.  J.  Schek:  Concepts  and  Applications  of  Multilevel  Transactions  and  Open 
        Nested Transactions. In Database Transaction Models, chapter 13. MKP, 1992. 

[56]    Francisco  Perez,  Jaksa  Vuckovic,  Marta  Patiño‐Martinez,  Ricardo    Jimenez‐Peris:  Highly 
        Available  Long  Running  Transactions  and  Activities  for  J2EE  Applications,  submitted  to 
        Middleware 2005 

[57]    Sun Microsystems. ECperf specification v1.1 final release, 2003. 

[58]    B. Ban: The JGroups Reliable Group Communication, http://javagroups.com. 

[59]    A.  Bartoli,  M.  Prica,  E.  Antoniutti  Di  Muro:  Reliable  communication,  ADAPT  project 
        deliverable D2, 2004. 

[60]    Y. Amir, J. Stanton, The Spread Wide Area Group Communication System, TR CNDS‐98‐4, The 
        Center for Networking and Distributed Systems, The Johns Hopkins University, 1998 

[61]    L.  E.  Moser,  Y. Amir,  P.  M.  Melliar‐Smith,  D. A. Agarwal:  Extended  Virtual  Synchrony.  In 
        Proceedings  of  the  IEEE  14th  International  Conference  on  Distributed  Computing 
        Systems (Poznan, Poland, June). IEEE Computer Society Press, Los Alamitos, CA, 56‐65.  

[62]    L. Lamport, The part‐time parliament, ACM Trans. Comput. Syst. 16, 2, 133‐169, May 1998. 

[63]    Wandisco, Dcone (Distributed Coordination Engine),  http://www.wandisco.com/sdk.htm 

[64]    Jaksa  Vuckovic:  Client  Based  Stateful  Session  Replication.  In  Supplemental  Volume  of  the 
        2004  International  Conference  on  Dependable  Systems  and  Networks,  Firenze,  pp.  199‐
        201, 2004. 




   UBLCS-2006-13                                                                                        94

				
DOCUMENT INFO
Shared By:
Categories:
Tags:
Stats:
views:20
posted:12/11/2011
language:
pages:104