001    /*
002      Copyright (C) 2001-2002 Renaud Pawlak <renaud@aopsys.com>
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.util.*;
021    import org.apache.log4j.Logger;
022    import org.objectweb.jac.core.*;
023    import org.objectweb.jac.core.dist.*;
024    import org.objectweb.jac.core.rtti.ClassRepository;
025    import org.objectweb.jac.util.*;
026    
027    /**
028     * This wrapper class implements the core protocol for a strong
029     * consistency that is based on a pull strategy.
030     *
031     * <p>On contrary to the <code>StrongPushConsistencyWrapper</code>,
032     * this protocol pulls the data from the other replicas. Indeed, each
033     * time a data is read and is not locally available, it is fetched
034     * from the known replicas.<p>
035     *
036     * @see StrongPushConsistencyWrapper
037     * 
038     * @author <a href="http://cedric.cnam.fr/~pawlak/index-english.html">Renaud Pawlak</a>
039     */
040    
041    public class StrongPullConsistencyWrapper extends ConsistencyWrapper {
042        static Logger logger = Logger.getLogger("consistency");
043    
044        String hosts = null;
045    
046        /**
047        * A friendly constructor for a pull consistency wrapper.
048        *
049        * @param hosts a regular expression that defines the host where
050        * the consistency protocol is installed */
051    
052        public StrongPullConsistencyWrapper(AspectComponent ac, String hosts) {
053            super(ac);
054            this.hosts = hosts;
055            knownReplicas = null;
056        } 
057    
058        /** An empty constructor for the Consistency class. */
059        public StrongPullConsistencyWrapper(AspectComponent ac) {
060            super(ac);
061        } 
062    
063        /**
064        * This wrapping method first try to use the wrappee to get the
065        * result of the read method.<p>
066        * 
067        * If this result is null or if an exception occurs, it considers
068        * that the read information was not locally present and tries to
069        * fetch it from the replicas it knows (recursivelly all the
070        * replicas are finally asked). If none of the replica returns a
071        * value, it returns null or throws an exception.
072        *
073        * @return the value returned by the wrapped read method */
074    
075        public Object whenRead(Interaction interaction) {
076    
077            Object ret = null;
078          
079            ret = proceed(interaction);
080    
081            logger.debug("Pull knownReplicas = "+knownReplicas);
082    
083            if (ret == null) {
084    
085                if (knownReplicas != null) {
086                    Collaboration c = Collaboration.get();
087                    Vector asked_replicas = (Vector)c.getAttribute(visitedReplicas);
088                    if (asked_replicas == null) {
089                        asked_replicas = (Vector)c.addAttribute( 
090                            visitedReplicas, new Vector());
091                    }
092    
093                    //System.out.println ( "########### " + notified_replicas );
094                    try {
095                        Vector new_ar = new Vector();
096                        RemoteRef cur_replica = RemoteRef.create( 
097                            NameRepository.get().getName(interaction.wrappee), 
098                            interaction.wrappee);
099                   
100                        for (int i = 0; i < knownReplicas.size(); i++) {
101                            if ( (! asked_replicas.contains( knownReplicas.get(i) ) ) &&
102                                 (! ((RemoteRef)knownReplicas.get(i)).getRemCont().isLocal()) ) {
103                         
104                                Vector kr = new Vector(knownReplicas);
105                                kr.remove(knownReplicas.get(i));
106                                new_ar.clear();
107                                new_ar.addAll(asked_replicas);
108                                new_ar.addAll(kr);
109                                new_ar.add(cur_replica);
110                                c.addAttribute(visitedReplicas, new_ar);
111                         
112                                logger.debug("(strong pull) read event on " + 
113                                          interaction.wrappee + ":" + 
114                                          interaction.method + ":" + 
115                                          ((RemoteRef)knownReplicas.get(i)).getRemCont().getName());
116                                ret = ((RemoteRef)knownReplicas.get(i)).invokeRoleMethod(
117                                    "acceptRemoteRead",
118                                    new Object[] { null,
119                                                   new Object[] { interaction.method,
120                                                                  interaction.args } } );
121                                if (ret != null) {
122                                    break;
123                                }
124                            }
125                        }
126                    } finally {
127                        c.addAttribute(visitedReplicas, null);
128                    }
129                }
130            }   
131            return ret;
132        }
133          
134        /**
135        * Try to read the method asked by <code>whenRead</code>.<p>
136        *
137        * The data is :<p>
138        * <ul><pre>
139        * data[0] = the read method name string
140        * data[1] = an array that contains the arguments of the read method 
141        * </pre></ul>
142        *
143        * @param remoteReplica the replica that received the read event
144        * @param data the read event data
145        * @return the return value of the <code>data[0]</code> method*/
146    
147        public Object acceptRemoteRead(Wrappee wrappee, RemoteRef remoteReplica,
148                                       Object[] data) {
149            logger.debug("(strong pull) remote read event on " + 
150                         wrappee + ":" + (String)data[0]);
151            return ClassRepository.get().getClass(wrappee).getMethod((String)data[0]).invoke(
152                wrappee , (Object[])data[1] );
153        }
154       
155          
156    }