001    /*
002      Copyright (C) 2001 Renaud Pawlak
003    
004      This program is free software; you can redistribute it and/or modify
005      it under the terms of the GNU Lesser General Public License as
006      published by the Free Software Foundation; either version 2 of the
007      License, or (at your option) any later version.
008    
009      This program is distributed in the hope that it will be useful,
010      but WITHOUT ANY WARRANTY; without even the implied warranty of
011      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012      GNU Lesser General Public License for more details.
013    
014      You should have received a copy of the GNU Lesser General Public License
015      along with this program; if not, write to the Free Software
016      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
017    
018    package org.objectweb.jac.aspects.distribution.consistency;
019    
020    import java.lang.reflect.*;
021    import org.objectweb.jac.core.*;
022    import org.objectweb.jac.core.dist.*;
023    
024    /**
025     * This wrapper class implements a weak consistency protocol for a set
026     * of replicas.
027     *
028     * <p>The semantics of this protocol is that the readed data can be
029     * inconsistent with the other replicas. When a write event occurs,
030     * the currently written replicas asks for the consistent state to the
031     * valid replica (the owner) and becomes itself the valid
032     * replica. This protocol ensures that the set of modifications are
033     * finally done in at least one replica.<p>
034     *
035     * @author <a href="http://cedric.cnam.fr/~pawlak/index-english.html">Renaud Pawlak</a> */
036    
037    public class WeakConsistencyWrapper extends ConsistencyWrapper {
038    
039       /** A reference to the valid copy. */ 
040       RemoteRef owner = null;
041       /** True if we are the owner of the valid copy. */
042       boolean isOwner = false;
043    
044       public WeakConsistencyWrapper(AspectComponent ac) {
045          super(ac);
046       }
047    
048       /**
049        * Update the wrappee state with the owner replica state before
050        * proceeding the writing method.<p>
051        *
052        * The wrappee then becomes the owner.<p>
053        *
054         @return the value returned by the wrapped method */
055    
056       public Object whenWrite(Interaction interaction) {
057          
058          if(!isOwner) {
059             /* Warn the owner and retrieves its state */
060             Object[] ownerState = (Object[]) owner.invokeRoleMethod(
061                "acceptRemoteWrite", new Object[] {}
062             );
063             
064             /* Set the new state */
065             Field[] fields = interaction.wrappee.getClass().getDeclaredFields();
066             for ( int i = 0; i < fields.length; i++ ) {
067                try {
068                   fields[i].set( interaction.wrappee, ownerState[i] );
069                } catch (Exception e) {}
070             }
071    
072             /* Warn the replicas that we are the new owner */
073             for (int i = 0; i < knownReplicas.size(); i++) {
074                ((RemoteRef)knownReplicas.get(i)).invokeRoleMethod(
075                   "setOwner",
076                   new Object[] { interaction.wrappee }
077                );
078             }
079          }
080          
081          /* Call the wrappee... */ 
082          return proceed(interaction);
083       }
084    
085       /**
086        * The current object is not the owner anymore and returns the
087        * object state so that the new owner can be consistent 
088        *
089        * @param remoteReplica the replica that is beeing written
090        * @param data this parameter is not used in this protocol (its
091        * value is null)
092        * @return the state of the object so that the written object can
093        * become a consistent owner */
094    
095        public Object acceptRemoteWrite(Wrappee wrappee, RemoteRef remoteReplica,
096                                        Object[] data) {
097           Field[] fields = wrappee.getClass().getDeclaredFields();
098           Object[] state = new Object[fields.length];
099           for ( int i = 0; i < fields.length; i++ ) {
100              try {
101                 state[i] = fields[i].get(wrappee);
102              } catch (Exception e) {}
103           }
104           isOwner = false;
105           return state;
106       }
107       
108       /**
109        * This role method sets a new owner.
110        * 
111        * @param newOwner a remote reference on the new owner
112        * @return null */
113    
114       public Object setOwner (RemoteRef newOwner) {
115          owner = newOwner;
116          isOwner = false;
117          return null;
118       }
119          
120    }