1 /* 2 * Copyright (c) 1998-2006 The Jgroup Team. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License version 2 as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU Lesser General Public License for more details. 12 * 13 * You should have received a copy of the GNU Lesser General Public License 14 * along with this program; if not, write to the Free Software 15 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 16 * 17 */ 18 19 package jgroup.relacs.gm; 20 21 import java.rmi.RemoteException; 22 import java.util.HashMap; 23 import java.util.Map; 24 25 import jgroup.core.GroupManager; 26 import jgroup.core.InternalGMIService; 27 import jgroup.core.JgroupException; 28 import jgroup.core.MembershipListener; 29 import jgroup.core.MembershipService; 30 import jgroup.core.View; 31 32 import org.apache.log4j.Logger; 33 34 /** 35 * The <code>TimestampLayer</code> creates an agreed timestamp 36 * between all the members in a group.<p> 37 * 38 * The timestamp can be retrieved as a counter (not unique between 39 * groups) or as a timestamp object (unique between groups). 40 * 41 * @author Rohnny Moland 42 */ 43 public class TimestampLayer 44 implements TimestampService, MembershipListener, InternalTimestamp 45 { 46 47 //////////////////////////////////////////////////////////////////////////////////////////// 48 // Logger 49 //////////////////////////////////////////////////////////////////////////////////////////// 50 51 /** Obtain logger for this class */ 52 private static final Logger log = Logger.getLogger(TimestampLayer.class); 53 54 55 //////////////////////////////////////////////////////////////////////////////////////////// 56 // Fields 57 //////////////////////////////////////////////////////////////////////////////////////////// 58 59 /** The GroupManager object */ 60 private GroupManager gm; 61 62 /** The service proxies */ 63 private InternalTimestamp internalTimestamp; 64 65 /** Holds the local timestamp value */ 66 private long timestamp = 0; 67 68 /** The timestamp objects */ 69 private Map<Integer, Timestamp> timestamps = new HashMap<Integer, Timestamp>(); 70 71 /** The view size of the client group */ 72 private int vsize; 73 74 /* 75 * Initialize a timestamp layer. 76 */ 77 private TimestampLayer(GroupManager gm) 78 { 79 this.gm = gm; 80 } 81 82 83 //////////////////////////////////////////////////////////////////////////////////////////// 84 // Static factory 85 //////////////////////////////////////////////////////////////////////////////////////////// 86 87 public static TimestampLayer getLayer(GroupManager gm, MembershipService ms, InternalGMIService igmi) 88 { 89 return new TimestampLayer(gm); 90 } 91 92 93 //////////////////////////////////////////////////////////////////////////////////////////// 94 // Methods from Layer 95 //////////////////////////////////////////////////////////////////////////////////////////// 96 97 /* (non-Javadoc) 98 * @see jgroup.core.Layer#addListener(java.lang.Object) 99 */ 100 public void addListener(Object listener) {} 101 102 103 //////////////////////////////////////////////////////////////////////////////////////////// 104 // Methods from FinalizeLayer 105 //////////////////////////////////////////////////////////////////////////////////////////// 106 107 /* (non-Javadoc) 108 * @see jgroup.core.FinalizeLayer#complete(java.lang.Object) 109 */ 110 public void complete(Object server) 111 throws JgroupException 112 { 113 internalTimestamp = (InternalTimestamp) gm.getService(InternalTimestamp.class); 114 } 115 116 117 //////////////////////////////////////////////////////////////////////////////////////////// 118 // Methods from MembershipListener 119 //////////////////////////////////////////////////////////////////////////////////////////// 120 121 /* (non-Javadoc) 122 * @see jgroup.core.MembershipListener#viewChange(jgroup.core.View) 123 */ 124 public void viewChange(View view) 125 { 126 vsize = view.size(); 127 for (Timestamp tsObj : timestamps.values()) { 128 tsObj.viewChange(view); 129 } 130 //FIXME must also resync the timestamp field. 131 try { 132 Object[] tsMap = (Object[]) internalTimestamp.getInternalTimestamp(); 133 for (int i = 0; i < tsMap.length; i++) { 134 for (Integer id : timestamps.keySet()) { 135 // Get the local timestamp for id 136 Timestamp ts = timestamps.get(id); 137 // Get the remote timestamp for member host i for id 138 Timestamp t = (Timestamp) ((Map) tsMap[i]).get(id); 139 ts = ts.greatest(t); 140 timestamps.put(id, ts); 141 } 142 } 143 } catch (RemoteException e) { 144 log.error("Failed to resync the timestamp object", e); 145 } 146 } 147 148 149 /* (non-Javadoc) 150 * @see jgroup.core.MembershipListener#prepareChange() 151 */ 152 public void prepareChange() {} 153 154 155 /* (non-Javadoc) 156 * @see jgroup.core.MembershipListener#hasLeft() 157 */ 158 public void hasLeft() {} 159 160 161 //////////////////////////////////////////////////////////////////////////////////////////// 162 // Methods from InternalTimestamp 163 //////////////////////////////////////////////////////////////////////////////////////////// 164 165 166 /* (non-Javadoc) 167 * @see jgroup.relacs.gm.InternalTimestamp#getInternalTimestamp() 168 */ 169 public Object getInternalTimestamp() 170 throws RemoteException 171 { 172 return timestamps; 173 } 174 175 176 //////////////////////////////////////////////////////////////////////////////////////////// 177 // Methods from TimestampService 178 //////////////////////////////////////////////////////////////////////////////////////////// 179 180 /* (non-Javadoc) 181 * @see jgroup.relacs.gm.TimestampService#getTimestamp(int) 182 */ 183 public synchronized Timestamp getTimestamp(int id) 184 { 185 Timestamp ts = timestamps.get(id); 186 if (ts == null) { 187 ts = new Timestamp(gm.getGroupId(), id, vsize); 188 timestamps.put(id, ts); 189 } 190 ts.updateTimestamp(); 191 if (log.isDebugEnabled()) 192 log.debug("TimestampLayer.getTimestamp(): " + ts); 193 return ts; 194 } 195 196 197 /* (non-Javadoc) 198 * @see jgroup.relacs.gm.TimestampService#getTimestampCounter() 199 */ 200 public long getTimestampCounter() 201 { 202 if (log.isDebugEnabled()) 203 log.debug("TimestampLayer.getTimestampCounter() ts=" + timestamp); 204 return timestamp++; 205 } 206 207 } // END TimestampLayer