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.objectweb.jac.core.*; 022 import org.objectweb.jac.core.rtti.*; 023 import org.objectweb.jac.core.dist.*; 024 025 /** 026 * This class handles any type of consistency protocol on a 027 * replicaction group. 028 * 029 * <p>A replication group is a set of objects of the same class that 030 * are related through a consistency protocol.<p> 031 * 032 * @author <a href="http://cedric.cnam.fr/~pawlak/index-english.html">Renaud Pawlak</a> 033 */ 034 035 public class Consistency { 036 037 /** The knowledge style is defined by the user (the whole knowledge 038 graph has to be defined at construction time). */ 039 public static int KS_USER = 0; 040 /** With this knowledge style, all the replicas know the same 041 unique replica (to be defined at construction time). */ 042 public static int KS_ONE = 1; 043 /** With this knowledge style, all the replicas know all the other 044 replicas (none info is required at construction time). */ 045 public static int KS_ALL = 2; 046 /** With this knowledge style, each replica knows only one replica 047 which is its neighbour in the replicas list (and last knows the 048 first) (none info is required at construction time). */ 049 public static int KS_NEXT = 3; 050 /** With this knowledge style, each replica knows only one replica 051 which is its father in a binary tree (the top of the tree has 052 to be defined at construction time). */ 053 public static int KS_BTREE = 4; 054 055 /** Use to indicate that you need all the methods. */ 056 public static String ALL_METHODS = "ALL"; 057 /** Use to indicate that you need all the modifiers. */ 058 public static String ALL_MODIFIERS = "ALL_MODIFIERS"; 059 /** Use to indicate that you need all the getters. */ 060 public static String ALL_GETTERS = "ALL_GETTERS"; 061 062 /** The wrapper type that implements the consistency protocol. */ 063 Class consistencyWrapperType; 064 /** The knowledge style. */ 065 int knowledgeStyle = 0; 066 /** The knowledge graph. */ 067 int[] knowledgeGraph = null; 068 069 /** 070 * Creates a new consistency. 071 * 072 * <p>The knowledge style can be one the following: 073 * 074 * <ul><li>KS_USER: the knowledge style is defined by the user (the 075 * whole knowledge graph has to be defined in the int[] argument 076 * that defines the edges of the graph)</li> 077 * 078 * <li>KS_ONE: with this knowledge style, all the replicas know the 079 * same unique replica (the knowledge graph argument contains only 080 * one element)</li> 081 * 082 * <li>KS_ALL: with this knowledge style, all the replicas know all 083 * the other replicas (the knowledge graph is empty)</li> 084 * 085 * <li>KS_NEXT: with this knowledge style, each replica knows only 086 * one replica which is its neighbour in the replicas list (and 087 * last knows the first) (the knowledge graph is empty)</li> 088 * 089 * <li>KS_BTREE: with this knowledge style, each replica knows only 090 * one replica which is its father in a binary tree (the knowledge 091 * graph argument contains only one element wich is the top of the 092 * tree).</li></ul> 093 * 094 * @param consistencyWrapperType the wrapper type that actually 095 * implements the consistency protocol 096 * @param knowledgeStyle can be KS_USER, KS_ONE, KS_ALL, KS_NEXT, 097 * or KS_BTREE 098 * @param knowledgeGraph depending on the knowledge style, can be 099 * empty or describing what set of replicas are known by other 100 * replicas */ 101 102 public Consistency ( Class consistencyWrapperType, 103 int knowledgeStyle, int[] knowledgeGraph ) { 104 this.consistencyWrapperType = consistencyWrapperType; 105 this.knowledgeStyle = knowledgeStyle; 106 this.knowledgeGraph = knowledgeGraph; 107 } 108 109 /** 110 * Says if a replica is deployed on the given site. 111 * 112 * @param name the name of the replica 113 * @param container the remote container to check 114 * @return true if a replica of the given name is found on the 115 * given container */ 116 117 public static boolean isReplicatedOn ( String name, RemoteContainer container ) { 118 RemoteRef rr = container.bindTo ( "JAC_name_repository" ); 119 Object distobj = rr.invoke ( 120 "callOrgMethod", new Object[] { "getObject", new Object[] { name } } ); 121 if ( distobj == null ) { 122 return false; 123 } 124 return true; 125 } 126 127 /** 128 * Construct a real methods array with an array that can contain 129 * consistency specific strings (like the one that indicates that 130 * we need all the modifiers). 131 * 132 * @param type the class to expand 133 * @param methods a set of methods to expand (can contain 134 * ALL_METHODS, ALL_MODIFIERS, and ALL_GETTERS keywords) 135 * @return a set of methods where the keywords have been expanded 136 * with the corresponding method of the type */ 137 138 protected String[] expandMethods( Class type, String[] methods ) { 139 if ( methods == null ) return null; 140 Vector newVM = new Vector(); 141 for ( int i = 0; i < methods.length; i++ ) { 142 if ( methods[i].equals(ALL_METHODS) ) { 143 newVM.addAll( Arrays.asList( 144 ClassRepository.getMethodsName(type) ) ); 145 } 146 else if ( methods[i].equals(ALL_MODIFIERS) ) { 147 newVM.addAll( Arrays.asList( 148 ClassRepository.getModifiersNames(type) ) ); 149 } 150 else if ( methods[i].equals(ALL_GETTERS) ) { 151 newVM.addAll( Arrays.asList( 152 ClassRepository.getGettersNames(type) ) ); 153 } 154 else { 155 newVM.add( methods[i] ); 156 } 157 } 158 String[] newMethods = new String[newVM.size()]; 159 for ( int i = 0; i < newMethods.length; i++ ) { 160 newMethods[i] = (String) newVM.get(i); 161 } 162 return newMethods; 163 } 164 165 166 /** 167 * Deploy the consistency on a set of remote objects. 168 * 169 * <p>PRE: the objects must have been previously deployed. 170 * 171 * @param members the references on the replicated members 172 * @param type the class of these members 173 * @param readMethods the names of the methods of the type that 174 * read the objects states 175 * @param writeMethods the names of the methods of the type that 176 * write the objects states 177 * @param callMethods the names of the methods of the type that 178 * neither read or write the objects states 179 * 180 * @see Deployment#deployStruct(Object[]) 181 * @see Deployment#deploy(Object[]) 182 * @see Deployment#replicateStruct(Object) 183 * @see Deployment#replicate(Object) 184 */ 185 186 public void deploy ( RemoteRef[] members, Class type, 187 String[] readMethods, 188 String[] writeMethods, 189 String[] callMethods ) 190 throws WrongConsistencyDefinitionException { 191 192 ConsistencyWrapper curwrapper; 193 RemoteRef referee = null; 194 boolean ok = false; 195 196 readMethods = expandMethods( type, readMethods ); 197 writeMethods = expandMethods( type, writeMethods ); 198 callMethods = expandMethods( type, callMethods ); 199 200 try { 201 202 String kstag = ""; 203 204 if (knowledgeStyle == KS_ONE) { 205 206 referee = members[knowledgeGraph[0]]; 207 for (int i = 0; i < members.length; i++) { 208 wrapMember ( members[i], 209 new String[] {"whenRead", "whenWrite", "whenCall"}, 210 new String[][] {readMethods, writeMethods, callMethods}, 211 new RemoteRef[] { referee }, kstag ); 212 } 213 ok = true; 214 } 215 216 if (knowledgeStyle == KS_ALL) { 217 218 for (int i = 0; i < members.length; i++) { 219 wrapMember ( members[i], 220 new String[] {"whenRead", "whenWrite", "whenCall"}, 221 new String[][] {readMethods, writeMethods, callMethods}, 222 members, kstag ); 223 } 224 ok = true; 225 } 226 227 if (knowledgeStyle == KS_NEXT) { 228 229 for (int i = 0; i < members.length; i++) { 230 if ( i == members.length - 1 ) { 231 referee = members[0]; 232 } else { 233 referee = members[i + 1]; 234 } 235 wrapMember ( members[i], 236 new String[] {"whenRead", "whenWrite", "whenCall"}, 237 new String[][] {readMethods, writeMethods, callMethods}, 238 new RemoteRef[] { referee }, kstag ); 239 } 240 ok = true; 241 } 242 } catch ( Exception e ) { e.printStackTrace(); } 243 244 if (!ok) { 245 throw new WrongConsistencyDefinitionException(); 246 } 247 } 248 249 /** 250 * Internally used to wrap a remote member with a consistency 251 * wrapper. 252 * 253 * @param member the member to wrap 254 * @param wrappingMethods the methods of the consistency wrapper 255 * that will wrap this member 256 * @param wrappedMethods for each wrapping method, the set of 257 * methods of the member that will be actually wrapped 258 * @param knowledge the set of other members known by the newly 259 * wrapped member 260 * @param kstag the knowledge style tag */ 261 262 protected void wrapMember ( RemoteRef member, String[] wrappingMethods, 263 String[][] wrappedMethods, RemoteRef[] knowledge, 264 String kstag ) 265 throws InstantiationException { 266 267 if ( wrappedMethods != null && wrappingMethods != null ) { 268 269 Class wrapper_type = consistencyWrapperType; 270 ConsistencyWrapper wrapper = null; 271 272 try { 273 274 wrapper = (ConsistencyWrapper) wrapper_type.newInstance(); 275 276 if (wrapper == null) { 277 throw new InstantiationException(); 278 } 279 280 //wrapper.setKnownReplicas( knowledge ); 281 //wrapper.knowledgeStyle = knowledgeStyle; 282 //wrapper.kstag = kstag; 283 wrapper.setReadMethods ( wrappedMethods[0] ); 284 wrapper.setWriteMethods ( wrappedMethods[1] ); 285 wrapper.setCallMethods ( wrappedMethods[2] ); 286 287 } catch ( Exception e ) { 288 throw new InstantiationException(); 289 } 290 291 member.invoke( 292 "wrap", 293 new Object[] { 294 wrapper, 295 wrappingMethods, 296 wrappedMethods 297 } 298 ); 299 } 300 } 301 302 /** 303 * This method binds a new object to the group of replicas of this 304 * consistency. 305 * 306 * @param name the name of the replica to bind to 307 * @param tobind the object to be put in consistency with the group 308 */ 309 public static void bindToDistObj(String name, Wrappee tobind) { 310 Topology topology = Topology.get(); 311 if (topology.countContainers() < 1) 312 return; 313 RemoteContainer rc = topology.getContainer(0); 314 RemoteRef rr = rc.bindTo(name); 315 rr.invokeRoleMethod ( 316 "addMember", 317 new Object[] { RemoteRef.create(NameRepository.get().getName(tobind), tobind) } ); 318 } 319 320 } 321 322 class WrongConsistencyDefinitionException extends Exception {} 323 324 325 326 327 328 329 330