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.util.*; 021 import org.apache.log4j.Logger; 022 import org.objectweb.jac.core.*; 023 import org.objectweb.jac.core.dist.RemoteRef; 024 import org.objectweb.jac.core.rtti.MethodItem; 025 import org.objectweb.jac.util.Log; 026 027 /** 028 * This wrapper implements a consistency protocol that forwards all 029 * the writing calls to all the replicas that are known by the 030 * wrapper. 031 * 032 * <p>It is called "push" since the wrapper pushes the data to the 033 * other replicas. Despite this strategy is the most curently used, 034 * other strong or weak consistency strategies can be implemented by 035 * other consistency wrappers. 036 * 037 * @author <a href="http://cedric.cnam.fr/~pawlak/index-english.html">Renaud Pawlak</a> 038 * 039 * @see #whenWrite(Interaction) 040 * @see StrongPullConsistencyWrapper 041 * @see WeakConsistencyWrapper */ 042 043 public class StrongPushConsistencyWrapper extends ConsistencyWrapper { 044 static Logger logger = Logger.getLogger("consistency"); 045 046 /** a false that is true during notification. */ 047 boolean inNotification = false; 048 049 /** 050 * A friendly constructor for a push consistency wrapper. 051 * 052 * @param hosts a regular expression that defines the host where 053 * the consistency protocol is installed */ 054 055 public StrongPushConsistencyWrapper(AspectComponent ac, String hosts) { 056 super(ac); 057 knownReplicas = null; 058 this.hosts = hosts; 059 } 060 061 /** An empty constructor for the Consistency class. */ 062 public StrongPushConsistencyWrapper(AspectComponent ac) { 063 super(ac); 064 } 065 066 /** 067 * Forwards the call to all the replicas and then call the 068 * replica.<p> 069 * 070 * The pushing mecanism is stopped by using the collaboration 071 * attribute value defined by <code>visitedReplicas</code>. 072 * 073 * @return the value returned by the wrapped method. 074 * @see ConsistencyWrapper#getVisitedReplicas() */ 075 076 public Object whenWrite(Interaction interaction) { 077 078 Object ret = null; 079 080 if (knownReplicas == null) { 081 calculateKnownReplicas(interaction.wrappee); 082 } 083 084 attrdef("Persistence.disabled", "true"); 085 086 if (knownReplicas != null) { 087 if (inNotification) return proceed(interaction); 088 inNotification = true; 089 Collaboration c = Collaboration.get(); 090 Vector notified_replicas = (Vector)c.getAttribute(visitedReplicas); 091 if (notified_replicas == null) { 092 notified_replicas = (Vector)c.addAttribute( 093 visitedReplicas, new Vector()); 094 } 095 096 try { 097 Vector new_nr = new Vector(); 098 RemoteRef cur_replica = RemoteRef.create( 099 NameRepository.get().getName(interaction.wrappee), 100 interaction.wrappee); 101 102 for (int i = 0; i < knownReplicas.size(); i++) { 103 if ( (! notified_replicas.contains(knownReplicas.get(i)) ) && 104 (! ((RemoteRef)knownReplicas.get(i)).getRemCont().isLocal()) ) { 105 106 Vector kr = new Vector(knownReplicas); 107 kr.remove(knownReplicas.get(i)); 108 new_nr.clear(); 109 new_nr.addAll(notified_replicas); 110 new_nr.addAll(kr); 111 new_nr.add (cur_replica); 112 c.addAttribute(visitedReplicas, new_nr); 113 114 logger.debug("(strong) write event on " + 115 NameRepository.get().getName(interaction.wrappee)+ 116 ":" + interaction.method + ":" + 117 ((RemoteRef)knownReplicas.get(i)).getRemCont().getName()); 118 try { 119 ((RemoteRef)knownReplicas.get(i)).invokeRoleMethod( 120 "acceptRemoteWrite", 121 new Object[] { null, 122 new Object[] { interaction.method, 123 interaction.args } } 124 ); 125 } catch ( Exception e ) { 126 logger.error("strong consistency error: "+ 127 "failed to remotely invoke "+ 128 "acceptRemoteWrite for "+ 129 interaction.wrappee+"."+interaction.method); 130 e.printStackTrace(); 131 break; 132 } 133 } 134 } 135 } finally { 136 c.addAttribute(visitedReplicas,null); 137 } 138 } else { 139 logger.debug("none replicas are known for "+ 140 NameRepository.get().getName(interaction.wrappee)); 141 } 142 ret = proceed(interaction); 143 144 inNotification = false; 145 146 return ret; 147 } 148 149 /** 150 * This method is called by <code>whenWrite</code> to push the 151 * needed data when a state is writen in a remote replica. 152 * 153 * The data is :<p> 154 * <ul><pre> 155 * data[0] = the write method name string 156 * data[1] = an array that contains the arguments of the write method 157 * </pre></ul> 158 * 159 * @param remoteReplica expected to be a reference on the remote 160 * replica that recieved the write event 161 * @param data the data transmittedd by <code>whenWrite</code> 162 * @return null by default 163 * @see #whenWrite(Interaction) */ 164 165 public Object acceptRemoteWrite(Wrappee wrappee, RemoteRef remoteReplica, 166 Object[] data) { 167 logger.debug("(strong) remote write event on " + 168 NameRepository.get().getName(wrappee) + 169 ":" + data[0]); 170 Object ret=null; 171 try { 172 ret = ((MethodItem)data[0]).invoke( 173 wrappee, (Object[])data[1]); 174 } catch (Exception e) { 175 e.printStackTrace(); 176 } 177 return ret; 178 } 179 180 /** 181 * Push the current replica state to the binding new replica. 182 * 183 * @param newReplica the replica that is currently binding 184 */ 185 186 public void whenBindingNewReplica(Wrappee wrappee, RemoteRef newReplica) { 187 logger.debug("(strong) initialized " + 188 newReplica + " with " + 189 NameRepository.get().getName(wrappee)); 190 newReplica.remoteCopy(wrappee); 191 } 192 193 }