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