View Javadoc

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