View Javadoc

1   package org.apache.helix.controller.stages;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.Collections;
23  import java.util.HashMap;
24  import java.util.HashSet;
25  import java.util.Map;
26  import java.util.Set;
27  
28  import org.apache.helix.HelixDataAccessor;
29  import org.apache.helix.HelixConstants.StateModelToken;
30  import org.apache.helix.PropertyKey.Builder;
31  import org.apache.helix.model.ClusterConstraints;
32  import org.apache.helix.model.CurrentState;
33  import org.apache.helix.model.IdealState;
34  import org.apache.helix.model.InstanceConfig;
35  import org.apache.helix.model.LiveInstance;
36  import org.apache.helix.model.Message;
37  import org.apache.helix.model.StateModelDefinition;
38  import org.apache.helix.model.ClusterConstraints.ConstraintType;
39  import org.apache.log4j.Logger;
40  
41  
42  /**
43   * Reads the data from the cluster using data accessor. This output ClusterData which
44   * provides useful methods to search/lookup properties
45   * 
46   * 
47   */
48  public class ClusterDataCache
49  {
50  
51    Map<String, LiveInstance>                           _liveInstanceMap;
52    Map<String, IdealState>                             _idealStateMap;
53    Map<String, StateModelDefinition>                   _stateModelDefMap;
54    Map<String, InstanceConfig>                         _instanceConfigMap;
55    Map<String, ClusterConstraints>                     _constraintMap;
56    Map<String, Map<String, Map<String, CurrentState>>> _currentStateMap;
57    Map<String, Map<String, Message>>                   _messageMap;
58  
59    // Map<String, Map<String, HealthStat>> _healthStatMap;
60    // private HealthStat _globalStats; // DON'T THINK I WILL USE THIS ANYMORE
61    // private PersistentStats _persistentStats;
62    // private Alerts _alerts;
63    // private AlertStatus _alertStatus;
64  
65    private static final Logger                         LOG =
66                                                                Logger.getLogger(ClusterDataCache.class.getName());
67  
68    /**
69     * This refreshes the cluster data by re-fetching the data from zookeeper in
70     * an efficient way
71     * 
72     * @param accessor
73     * @return
74     */
75    public boolean refresh(HelixDataAccessor accessor)
76    {
77      Builder keyBuilder = accessor.keyBuilder();
78      _idealStateMap = accessor.getChildValuesMap(keyBuilder.idealStates());
79      _liveInstanceMap = accessor.getChildValuesMap(keyBuilder.liveInstances());
80  
81      for (LiveInstance instance : _liveInstanceMap.values())
82      {
83        LOG.trace("live instance: " + instance.getInstanceName() + " "
84            + instance.getSessionId());
85      }
86  
87      _stateModelDefMap = accessor.getChildValuesMap(keyBuilder.stateModelDefs());
88      _instanceConfigMap = accessor.getChildValuesMap(keyBuilder.instanceConfigs());
89      _constraintMap =
90          accessor.getChildValuesMap(keyBuilder.constraints());
91  
92      Map<String, Map<String, Message>> msgMap =
93          new HashMap<String, Map<String, Message>>();
94      for (String instanceName : _liveInstanceMap.keySet())
95      {
96        Map<String, Message> map =
97            accessor.getChildValuesMap(keyBuilder.messages(instanceName));
98        msgMap.put(instanceName, map);
99      }
100     _messageMap = Collections.unmodifiableMap(msgMap);
101 
102     Map<String, Map<String, Map<String, CurrentState>>> allCurStateMap =
103         new HashMap<String, Map<String, Map<String, CurrentState>>>();
104     for (String instanceName : _liveInstanceMap.keySet())
105     {
106       LiveInstance liveInstance = _liveInstanceMap.get(instanceName);
107       String sessionId = liveInstance.getSessionId();
108       if (!allCurStateMap.containsKey(instanceName))
109       {
110         allCurStateMap.put(instanceName, new HashMap<String, Map<String, CurrentState>>());
111       }
112       Map<String, Map<String, CurrentState>> curStateMap =
113           allCurStateMap.get(instanceName);
114       Map<String, CurrentState> map =
115           accessor.getChildValuesMap(keyBuilder.currentStates(instanceName, sessionId));
116       curStateMap.put(sessionId, map);
117     }
118 
119     for (String instance : allCurStateMap.keySet())
120     {
121       allCurStateMap.put(instance,
122                          Collections.unmodifiableMap(allCurStateMap.get(instance)));
123     }
124     _currentStateMap = Collections.unmodifiableMap(allCurStateMap);
125 
126     return true;
127   }
128   /**
129    * Retrieves the idealstates for all resources
130    * @return
131    */
132   public Map<String, IdealState> getIdealStates()
133   {
134     return _idealStateMap;
135   }
136   /**
137    * Returns the LiveInstances for each of the instances that are curretnly up and running
138    * @return
139    */
140   public Map<String, LiveInstance> getLiveInstances()
141   {
142     return _liveInstanceMap;
143   }
144   /**
145    * Provides the current state of the node for a given session id, 
146    * the sessionid can be got from LiveInstance
147    * @param instanceName
148    * @param clientSessionId
149    * @return
150    */
151   public Map<String, CurrentState> getCurrentState(String instanceName,
152                                                    String clientSessionId)
153   {
154     return _currentStateMap.get(instanceName).get(clientSessionId);
155   }
156   /**
157    * Provides a list of current outstanding transitions on a given instance.
158    * @param instanceName
159    * @return
160    */
161   public Map<String, Message> getMessages(String instanceName)
162   {
163     Map<String, Message> map = _messageMap.get(instanceName);
164     if (map != null)
165     {
166       return map;
167     }
168     else
169     {
170       return Collections.emptyMap();
171     }
172   }
173 
174   // public HealthStat getGlobalStats()
175   // {
176   // return _globalStats;
177   // }
178   //
179   // public PersistentStats getPersistentStats()
180   // {
181   // return _persistentStats;
182   // }
183   //
184   // public Alerts getAlerts()
185   // {
186   // return _alerts;
187   // }
188   //
189   // public AlertStatus getAlertStatus()
190   // {
191   // return _alertStatus;
192   // }
193   //
194   // public Map<String, HealthStat> getHealthStats(String instanceName)
195   // {
196   // Map<String, HealthStat> map = _healthStatMap.get(instanceName);
197   // if (map != null)
198   // {
199   // return map;
200   // } else
201   // {
202   // return Collections.emptyMap();
203   // }
204   // }
205  /**
206   * Provides the state model definition for a given state model
207   * @param stateModelDefRef
208   * @return
209   */
210   public StateModelDefinition getStateModelDef(String stateModelDefRef)
211   {
212 
213     return _stateModelDefMap.get(stateModelDefRef);
214   }
215   /**
216    * Provides the idealstate for a given resource
217    * @param resourceName
218    * @return
219    */
220   public IdealState getIdealState(String resourceName)
221   {
222     return _idealStateMap.get(resourceName);
223   }
224   /**
225    * Returns the instance config map
226    * @return
227    */
228   public Map<String, InstanceConfig> getInstanceConfigMap()
229   {
230     return _instanceConfigMap;
231   }
232   
233   /**
234    * Some partitions might be disabled on specific nodes. 
235    * This method allows one to fetch the set of nodes where a given partition is disabled
236    * @param partition
237    * @return
238    */
239   public Set<String> getDisabledInstancesForPartition(String partition)
240   {
241     Set<String> disabledInstancesSet = new HashSet<String>();
242     for (String instance : _instanceConfigMap.keySet())
243     {
244       InstanceConfig config = _instanceConfigMap.get(instance);
245       if (config.getInstanceEnabled() == false
246           || config.getInstanceEnabledForPartition(partition) == false)
247       {
248         disabledInstancesSet.add(instance);
249       }
250     }
251     return disabledInstancesSet;
252   }
253   /**
254    * Returns the number of replicas for a given resource.
255    * @param resourceName
256    * @return
257    */
258   public int getReplicas(String resourceName)
259   {
260     int replicas = -1;
261 
262     if (_idealStateMap.containsKey(resourceName))
263     {
264       String replicasStr = _idealStateMap.get(resourceName).getReplicas();
265 
266       if (replicasStr != null)
267       {
268         if (replicasStr.equals(StateModelToken.ANY_LIVEINSTANCE.toString()))
269         {
270           replicas = _liveInstanceMap.size();
271         }
272         else
273         {
274           try
275           {
276             replicas = Integer.parseInt(replicasStr);
277           }
278           catch (Exception e)
279           {
280             LOG.error("invalid replicas string: " + replicasStr);
281           }
282         }
283       }
284       else
285       {
286         LOG.error("idealState for resource: " + resourceName + " does NOT have replicas");
287       }
288     }
289     return replicas;
290   }
291 
292   /**
293    * Returns the ClusterConstraints for a given constraintType
294    * @param type
295    * @return
296    */
297   public ClusterConstraints getConstraint(ConstraintType type)
298   {
299     if (_constraintMap != null)
300     {
301       return _constraintMap.get(type.toString());
302     }
303     return null;
304   }
305   
306   /**
307    * toString method to print the entire cluster state
308    */
309   @Override
310   public String toString()
311   {
312     StringBuilder sb = new StringBuilder();
313     sb.append("liveInstaceMap:" + _liveInstanceMap).append("\n");
314     sb.append("idealStateMap:" + _idealStateMap).append("\n");
315     sb.append("stateModelDefMap:" + _stateModelDefMap).append("\n");
316     sb.append("instanceConfigMap:" + _instanceConfigMap).append("\n");
317     sb.append("messageMap:" + _messageMap).append("\n");
318 
319     return sb.toString();
320   }
321 }