View Javadoc

1   package org.apache.helix.util;
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.Map;
23  import java.util.TreeMap;
24  
25  import org.apache.helix.PropertyPathConfig;
26  import org.apache.helix.PropertyType;
27  import org.apache.helix.store.PropertyJsonSerializer;
28  import org.apache.log4j.Logger;
29  
30  public final class HelixUtil
31  {
32    static private Logger LOG = Logger.getLogger(HelixUtil.class);
33  
34    private HelixUtil()
35    {
36    }
37  
38    public static String getPropertyPath(String clusterName, PropertyType type)
39    {
40      return "/" + clusterName + "/" + type.toString();
41    }
42  
43    public static String getInstancePropertyPath(String clusterName, String instanceName,
44        PropertyType type)
45    {
46      return getPropertyPath(clusterName, PropertyType.INSTANCES) + "/" + instanceName + "/"
47          + type.toString();
48    }
49  
50    public static String getInstancePath(String clusterName, String instanceName)
51    {
52      return getPropertyPath(clusterName, PropertyType.INSTANCES) + "/" + instanceName;
53    }
54  
55    public static String getIdealStatePath(String clusterName, String resourceName)
56    {
57      return getPropertyPath(clusterName, PropertyType.IDEALSTATES) + "/" + resourceName;
58    }
59  
60    public static String getIdealStatePath(String clusterName)
61    {
62      return getPropertyPath(clusterName, PropertyType.IDEALSTATES);
63    }
64  
65    public static String getLiveInstancesPath(String clusterName)
66    {
67      return getPropertyPath(clusterName, PropertyType.LIVEINSTANCES);
68    }
69  
70    public static String getMessagePath(String clusterName, String instanceName)
71    {
72      return getInstancePropertyPath(clusterName, instanceName, PropertyType.MESSAGES);
73    }
74  
75    public static String getCurrentStateBasePath(String clusterName, String instanceName)
76    {
77      return getInstancePropertyPath(clusterName, instanceName, PropertyType.CURRENTSTATES);
78    }
79  
80    /**
81     * Even though this is simple we want to have the mechanism of bucketing the
82     * partitions. If we have P partitions and N nodes with K replication factor
83     * and D databases. Then on each node we will have (P/N)*K*D partitions. And
84     * cluster manager neeeds to maintain watch on each of these nodes for every
85     * node. So over all cluster manager will have P*K*D watches which can be
86     * quite large given that we over partition.
87     * 
88     * The other extreme is having one znode per storage per database. This will
89     * result in N*D watches which is good. But data in every node might become
90     * really big since it has to save partition
91     * 
92     * Ideally we want to balance between the two models
93     * 
94     */
95    public static String getCurrentStatePath(String clusterName, String instanceName,
96        String sessionId, String stateUnitKey)
97    {
98      return getInstancePropertyPath(clusterName, instanceName, PropertyType.CURRENTSTATES) + "/"
99          + sessionId + "/" + stateUnitKey;
100   }
101 
102   public static String getExternalViewPath(String clusterName)
103   {
104     return getPropertyPath(clusterName, PropertyType.EXTERNALVIEW);
105   }
106 
107   public static String getStateModelDefinitionPath(String clusterName)
108   {
109     return getPropertyPath(clusterName, PropertyType.STATEMODELDEFS);
110   }
111 
112   public static String getExternalViewPath(String clusterName, String resourceName)
113   {
114     return getPropertyPath(clusterName, PropertyType.EXTERNALVIEW) + "/" + resourceName;
115   }
116 
117   public static String getLiveInstancePath(String clusterName, String instanceName)
118   {
119     return getPropertyPath(clusterName, PropertyType.LIVEINSTANCES) + "/" + instanceName;
120   }
121 
122   public static String getMemberInstancesPath(String clusterName)
123   {
124     return getPropertyPath(clusterName, PropertyType.INSTANCES);
125   }
126 
127   public static String getErrorsPath(String clusterName, String instanceName)
128   {
129     return getInstancePropertyPath(clusterName, instanceName, PropertyType.ERRORS);
130   }
131 
132   public static String getStatusUpdatesPath(String clusterName, String instanceName)
133   {
134     return getInstancePropertyPath(clusterName, instanceName, PropertyType.STATUSUPDATES);
135   }
136 
137   public static String getHealthPath(String clusterName, String instanceName)
138   {
139     return PropertyPathConfig.getPath(PropertyType.HEALTHREPORT, clusterName, instanceName);
140   }
141 
142   public static String getPersistentStatsPath(String clusterName)
143   {
144     return PropertyPathConfig.getPath(PropertyType.PERSISTENTSTATS, clusterName);
145   }
146 
147   public static String getAlertsPath(String clusterName)
148   {
149     return PropertyPathConfig.getPath(PropertyType.ALERTS, clusterName);
150   }
151 
152   public static String getAlertStatusPath(String clusterName)
153   {
154     return PropertyPathConfig.getPath(PropertyType.ALERT_STATUS, clusterName);
155   }
156 
157   public static String getInstanceNameFromPath(String path)
158   {
159     // path structure
160     // /<cluster_name>/instances/<instance_name>/[currentStates/messages]
161     if (path.contains("/" + PropertyType.INSTANCES + "/"))
162     {
163       String[] split = path.split("\\/");
164       if (split.length > 3)
165       {
166         return split[3];
167       }
168     }
169     return null;
170   }
171 
172   // distributed cluster controller
173   public static String getControllerPath(String clusterName)
174   {
175     return getPropertyPath(clusterName, PropertyType.CONTROLLER);
176   }
177 
178   public static String getControllerPropertyPath(String clusterName, PropertyType type)
179   {
180     return PropertyPathConfig.getPath(type, clusterName);
181   }
182   
183   /**
184    * get the parent-path of given path
185    * return "/" string if path = "/xxx", null if path = "/"
186    * 
187    * @param path
188    * @return
189    */
190   public static String getZkParentPath(String path) {
191       if (path.equals("/")) {
192           return null;
193       }
194       
195       int idx = path.lastIndexOf('/');
196       return idx == 0? "/" : path.substring(0, idx);
197   }
198   
199   /**
200    * get the last part of the zk-path
201    * 
202    * @param path
203    * @return
204    */
205   public static String getZkName(String path) {
206       return path.substring(path.lastIndexOf('/') + 1);
207   }
208   
209   /**
210    * parse a csv-formated key-value pairs
211    * 
212    * @param keyValuePairs : csv-formatted key-value pairs. e.g. k1=v1,k2=v2,...
213    * @return 
214    */
215   public static Map<String, String> parseCsvFormatedKeyValuePairs(String keyValuePairs) {
216     String[] pairs = keyValuePairs.split("[\\s,]");
217     Map<String, String> keyValueMap = new TreeMap<String, String>();
218     for (String pair : pairs)
219     {
220       int idx = pair.indexOf('=');
221       if (idx == -1)
222       {
223         LOG.error("Invalid key-value pair: " + pair + ". Igonore it.");
224         continue;
225       }
226 
227       String key = pair.substring(0, idx);
228       String value = pair.substring(idx + 1);
229       keyValueMap.put(key, value);
230     }
231     return keyValueMap;
232   }
233 
234 }