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 }