View Javadoc

1   /*
2    * Copyright (c) 1998-2005 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  package jgroup.util.log;
19  
20  import static jgroup.util.log.ViewEvent.RecoveryState.FULLY_REPLICATED;
21  import static jgroup.util.log.ViewEvent.RecoveryState.NEED_RECOVERY;
22  import static jgroup.util.log.ViewEvent.RecoveryState.NEW_MEMBER;
23  import static jgroup.util.log.ViewEvent.RecoveryState.NORMAL;
24  import static jgroup.util.log.ViewEvent.RecoveryState.TOO_MANY_REPLICAS;
25  import jgroup.core.MemberId;
26  import jgroup.core.View;
27  import jgroup.relacs.config.AppConfig;
28  import jgroup.relacs.types.ViewId;
29  import jgroup.util.Network;
30  
31  /**
32   * A view event to be logged.
33   * 
34   * @author Rune Vestvik
35   * @author Hein Meling
36   */
37  public final class ViewEvent
38    extends Event
39  {
40  
41    ////////////////////////////////////////////////////////////////////////////////////////////
42    // Constants
43    ////////////////////////////////////////////////////////////////////////////////////////////
44  
45    private static final long serialVersionUID = 4049640096401864757L;
46  
47    /**
48     * Supported view change event types.
49     */
50    public enum Type implements EventType { ARM, Merge, Server, Client }
51  
52    enum RecoveryState { NEW_MEMBER, NORMAL, NEED_RECOVERY, FULLY_REPLICATED, TOO_MANY_REPLICAS }
53  
54  
55    ////////////////////////////////////////////////////////////////////////////////////////////
56    // Fields
57    ////////////////////////////////////////////////////////////////////////////////////////////
58  
59    /**
60     * The view event to be logged.
61     */
62    private final View view;
63  
64    private int minimalRedundancy;
65  
66    private int initialRedundancy;
67  
68    private RecoveryState state;
69  
70  
71    ////////////////////////////////////////////////////////////////////////////////////////////
72    // Constructor
73    ////////////////////////////////////////////////////////////////////////////////////////////
74  
75    public ViewEvent(EventType type, View view)
76    {
77      super(type, "ViewChange");
78      this.view = (View) view.clone();
79      AppConfig thisApp = AppConfig.getApplication(this.view.getGid());
80      try {
81        this.minimalRedundancy = thisApp.getMinimalRedundancy();
82        this.initialRedundancy = thisApp.getInitialRedundancy();
83      } catch (IllegalStateException e) {
84        /*
85         * Ignored, since we may be running an application without a specified
86         * redundancy, e.g. helloserver.
87         */
88      }
89      computeState();
90    }
91  
92  
93    ////////////////////////////////////////////////////////////////////////////////////////////
94    // Private Methods
95    ////////////////////////////////////////////////////////////////////////////////////////////
96  
97    private void computeState()
98    {
99      int vsize = view.size();
100     if (vsize == initialRedundancy) {
101       state = FULLY_REPLICATED;
102     } else if (vsize < minimalRedundancy) {
103       if (isFirstView())
104         state = NEW_MEMBER;
105       else
106         state = NEED_RECOVERY;
107     } else if (vsize > initialRedundancy) {
108       state = TOO_MANY_REPLICAS;
109     } else if (vsize >= minimalRedundancy && vsize < initialRedundancy) {
110       state = NORMAL;
111     }
112     assert state != null;
113   }
114 
115 
116   ////////////////////////////////////////////////////////////////////////////////////////////
117   // Access Methods
118   ////////////////////////////////////////////////////////////////////////////////////////////
119 
120   public int getViewSize()
121   {
122     return view.size();
123   }
124 
125   public long getViewId()
126   {
127     return view.getVid();
128   }
129 
130   public View getView()
131   {
132     return view;
133   }
134 
135   public int getGroupId()
136   {
137     return view.getGid();
138   }
139 
140   /**
141    * @return True if this view is the first view installed by the member of this view.
142    *   False is returned otherwise.  Meaning that if there is more than one member or
143    *   if the single member view is not the first that the member has installed, then
144    *   false will be returned.
145    */
146   public boolean isFirstView()
147   {
148     if (view.size() == 1) {
149       MemberId memb = view.getMembers()[0];
150       // Compute the initial vid for this single member
151       long theInitialVid = ViewId.create(memb.getEndPoint(), 0);
152       return theInitialVid == view.getVid();
153     } else {
154       return false;
155     }
156   }
157 
158   public boolean isFullyReplicated()
159   {
160     return state == FULLY_REPLICATED;
161   }
162 
163   public boolean isOK()
164   {
165     return state == NORMAL || state == FULLY_REPLICATED;
166   }
167 
168   public boolean needRecovery()
169   {
170     return state == NEED_RECOVERY;
171   }
172 
173   public boolean hasTooManyReplicas()
174   {
175     return state == TOO_MANY_REPLICAS;
176   }
177 
178 
179   ////////////////////////////////////////////////////////////////////////////////////////////
180   // Methods from Object
181   ////////////////////////////////////////////////////////////////////////////////////////////
182 
183   public String toString()
184   {
185     StringBuilder buf = commonToString(true);
186     commonToString(buf);
187     return buf.toString();
188   }
189 
190   /**
191    *  Print the content of this view event without the host and time.
192    */
193   public String shortToString()
194   {
195     StringBuilder buf = new StringBuilder("ViewEvent");
196     commonToString(buf);
197     return buf.toString();
198   }
199 
200   protected void commonToString(StringBuilder buf)
201   {
202     buf.append(" gid=");
203     buf.append(view.getGid());
204     buf.append(" view.size=");
205     buf.append(view.size());
206     buf.append(" (");
207     buf.append(state);
208     buf.append(") vid=");
209     buf.append(view.getVid());
210     buf.append(" members: ");
211     MemberId[] members = view.getMembers();
212     for (int i = 0; i < members.length; i++) {
213       buf.append(Network.getMachineName(members[i].getCanonicalHostName()));
214       buf.append(" ");
215     }
216   }
217 
218 
219   ////////////////////////////////////////////////////////////////////////////////////////////
220   // Serialization Methods
221   ////////////////////////////////////////////////////////////////////////////////////////////
222 
223   /**
224    * Override readObject to update the recovery state, given a particular 
225    * redundancy configuration.
226    */
227 //  private void readObject(ObjectInputStream in)
228 //    throws IOException, ClassNotFoundException
229 //  {
230 //    in.defaultReadObject();
231 //    computeState();
232 //  }
233 
234 } // END ViewEvent