View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.catalog;
19  
20  import java.io.IOException;
21  import java.net.ConnectException;
22  import java.util.ArrayList;
23  import java.util.List;
24  
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  import org.apache.hadoop.hbase.HConstants;
28  import org.apache.hadoop.hbase.HRegionInfo;
29  import org.apache.hadoop.hbase.NotAllMetaRegionsOnlineException;
30  import org.apache.hadoop.hbase.ServerName;
31  import org.apache.hadoop.hbase.client.Delete;
32  import org.apache.hadoop.hbase.client.HTable;
33  import org.apache.hadoop.hbase.client.Put;
34  import org.apache.hadoop.hbase.client.Result;
35  import org.apache.hadoop.hbase.util.Bytes;
36  import org.apache.hadoop.hbase.util.Writables;
37  
38  /**
39   * Writes region and assignment information to <code>.META.</code>.
40   * TODO: Put MetaReader and MetaEditor together; doesn't make sense having
41   * them distinct.
42   */
43  public class MetaEditor {
44    // TODO: Strip CatalogTracker from this class.  Its all over and in the end
45    // its only used to get its Configuration so we can get associated
46    // Connection.
47    private static final Log LOG = LogFactory.getLog(MetaEditor.class);
48  
49    private static Put makePutFromRegionInfo(HRegionInfo regionInfo)
50    throws IOException {
51      Put put = new Put(regionInfo.getRegionName());
52      put.add(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER,
53          Writables.getBytes(regionInfo));
54      return put;
55    }
56  
57    /**
58     * Put the passed <code>p</code> to the <code>.META.</code> table.
59     * @param ct CatalogTracker on whose back we will ride the edit.
60     * @param p Put to add to .META.
61     * @throws IOException
62     */
63    static void putToMetaTable(final CatalogTracker ct, final Put p)
64    throws IOException {
65      put(MetaReader.getMetaHTable(ct), p);
66    }
67  
68    /**
69     * Put the passed <code>p</code> to the <code>.META.</code> table.
70     * @param ct CatalogTracker on whose back we will ride the edit.
71     * @param p Put to add to .META.
72     * @throws IOException
73     */
74    static void putToRootTable(final CatalogTracker ct, final Put p)
75    throws IOException {
76      put(MetaReader.getRootHTable(ct), p);
77    }
78  
79    /**
80     * Put the passed <code>p</code> to a catalog table.
81     * @param ct CatalogTracker on whose back we will ride the edit.
82     * @param p Put to add
83     * @throws IOException
84     */
85    static void putToCatalogTable(final CatalogTracker ct, final Put p)
86    throws IOException {
87      HTable t = MetaReader.getCatalogHTable(ct, p.getRow());
88      put(t, p);
89    }
90  
91    /**
92     * @param t Table to use (will be closed when done).
93     * @param p
94     * @throws IOException
95     */
96    private static void put(final HTable t, final Put p) throws IOException {
97      try {
98        t.put(p);
99      } finally {
100       t.close();
101     }
102   }
103 
104   /**
105    * Put the passed <code>ps</code> to the <code>.META.</code> table.
106    * @param ct CatalogTracker on whose back we will ride the edit.
107    * @param ps Put to add to .META.
108    * @throws IOException
109    */
110   static void putsToMetaTable(final CatalogTracker ct, final List<Put> ps)
111   throws IOException {
112     HTable t = MetaReader.getMetaHTable(ct);
113     try {
114       t.put(ps);
115     } finally {
116       t.close();
117     }
118   }
119 
120   /**
121    * Delete the passed <code>d</code> from the <code>.META.</code> table.
122    * @param ct CatalogTracker on whose back we will ride the edit.
123    * @param d Delete to add to .META.
124    * @throws IOException
125    */
126   static void deleteMetaTable(final CatalogTracker ct, final Delete d)
127   throws IOException {
128     HTable t = MetaReader.getMetaHTable(ct);
129     try {
130       t.delete(d);
131     } finally {
132       t.close();
133     }
134   }
135   
136   /**
137    * Adds a META row for the specified new region.
138    * @param regionInfo region information
139    * @throws IOException if problem connecting or updating meta
140    */
141   public static void addRegionToMeta(CatalogTracker catalogTracker,
142       HRegionInfo regionInfo)
143   throws IOException {
144     putToMetaTable(catalogTracker, makePutFromRegionInfo(regionInfo));
145     LOG.info("Added region " + regionInfo.getRegionNameAsString() + " to META");
146   }
147 
148   /**
149    * Adds a META row for each of the specified new regions.
150    * @param catalogTracker CatalogTracker
151    * @param regionInfos region information list
152    * @throws IOException if problem connecting or updating meta
153    */
154   public static void addRegionsToMeta(CatalogTracker catalogTracker,
155       List<HRegionInfo> regionInfos)
156   throws IOException {
157     List<Put> puts = new ArrayList<Put>();
158     for (HRegionInfo regionInfo : regionInfos) { 
159       puts.add(makePutFromRegionInfo(regionInfo));
160     }
161     putsToMetaTable(catalogTracker, puts);
162     LOG.info("Added " + puts.size() + " regions in META");
163   }
164 
165   /**
166    * Offline parent in meta.
167    * Used when splitting.
168    * @param catalogTracker
169    * @param parent
170    * @param a Split daughter region A
171    * @param b Split daughter region B
172    * @throws NotAllMetaRegionsOnlineException
173    * @throws IOException
174    */
175   public static void offlineParentInMeta(CatalogTracker catalogTracker,
176       HRegionInfo parent, final HRegionInfo a, final HRegionInfo b)
177   throws NotAllMetaRegionsOnlineException, IOException {
178     HRegionInfo copyOfParent = new HRegionInfo(parent);
179     copyOfParent.setOffline(true);
180     copyOfParent.setSplit(true);
181     Put put = new Put(copyOfParent.getRegionName());
182     addRegionInfo(put, copyOfParent);
183     put.add(HConstants.CATALOG_FAMILY, HConstants.SPLITA_QUALIFIER,
184       Writables.getBytes(a));
185     put.add(HConstants.CATALOG_FAMILY, HConstants.SPLITB_QUALIFIER,
186       Writables.getBytes(b));
187     putToMetaTable(catalogTracker, put);
188     LOG.info("Offlined parent region " + parent.getRegionNameAsString() +
189       " in META");
190   }
191 
192   public static void addDaughter(final CatalogTracker catalogTracker,
193       final HRegionInfo regionInfo, final ServerName sn)
194   throws NotAllMetaRegionsOnlineException, IOException {
195     Put put = new Put(regionInfo.getRegionName());
196     addRegionInfo(put, regionInfo);
197     if (sn != null) addLocation(put, sn);
198     putToMetaTable(catalogTracker, put);
199     LOG.info("Added daughter " + regionInfo.getRegionNameAsString() +
200       (sn == null? ", serverName=null": ", serverName=" + sn.toString()));
201   }
202 
203   /**
204    * Updates the location of the specified META region in ROOT to be the
205    * specified server hostname and startcode.
206    * <p>
207    * Uses passed catalog tracker to get a connection to the server hosting
208    * ROOT and makes edits to that region.
209    *
210    * @param catalogTracker catalog tracker
211    * @param regionInfo region to update location of
212    * @param sn Server name
213    * @throws IOException
214    * @throws ConnectException Usually because the regionserver carrying .META.
215    * is down.
216    * @throws NullPointerException Because no -ROOT- server connection
217    */
218   public static void updateMetaLocation(CatalogTracker catalogTracker,
219       HRegionInfo regionInfo, ServerName sn)
220   throws IOException, ConnectException {
221     updateLocation(catalogTracker, regionInfo, sn);
222   }
223 
224   /**
225    * Updates the location of the specified region in META to be the specified
226    * server hostname and startcode.
227    * <p>
228    * Uses passed catalog tracker to get a connection to the server hosting
229    * META and makes edits to that region.
230    *
231    * @param catalogTracker catalog tracker
232    * @param regionInfo region to update location of
233    * @param sn Server name
234    * @throws IOException
235    */
236   public static void updateRegionLocation(CatalogTracker catalogTracker,
237       HRegionInfo regionInfo, ServerName sn)
238   throws IOException {
239     updateLocation(catalogTracker, regionInfo, sn);
240   }
241 
242   /**
243    * Updates the location of the specified region to be the specified server.
244    * <p>
245    * Connects to the specified server which should be hosting the specified
246    * catalog region name to perform the edit.
247    *
248    * @param catalogTracker
249    * @param regionInfo region to update location of
250    * @param sn Server name
251    * @throws IOException In particular could throw {@link java.net.ConnectException}
252    * if the server is down on other end.
253    */
254   private static void updateLocation(final CatalogTracker catalogTracker,
255       HRegionInfo regionInfo, ServerName sn)
256   throws IOException {
257     Put put = new Put(regionInfo.getRegionName());
258     addLocation(put, sn);
259     putToCatalogTable(catalogTracker, put);
260     LOG.info("Updated row " + regionInfo.getRegionNameAsString() +
261       " with server=" + sn);
262   }
263 
264   /**
265    * Deletes the specified region from META.
266    * @param catalogTracker
267    * @param regionInfo region to be deleted from META
268    * @throws IOException
269    */
270   public static void deleteRegion(CatalogTracker catalogTracker,
271       HRegionInfo regionInfo)
272   throws IOException {
273     Delete delete = new Delete(regionInfo.getRegionName());
274     deleteMetaTable(catalogTracker, delete);
275     LOG.info("Deleted region " + regionInfo.getRegionNameAsString() + " from META");
276   }
277 
278   /**
279    * Deletes daughters references in offlined split parent.
280    * @param catalogTracker
281    * @param parent Parent row we're to remove daughter reference from
282    * @throws NotAllMetaRegionsOnlineException
283    * @throws IOException
284    */
285   public static void deleteDaughtersReferencesInParent(CatalogTracker catalogTracker,
286       final HRegionInfo parent)
287   throws NotAllMetaRegionsOnlineException, IOException {
288     Delete delete = new Delete(parent.getRegionName());
289     delete.deleteColumns(HConstants.CATALOG_FAMILY, HConstants.SPLITA_QUALIFIER);
290     delete.deleteColumns(HConstants.CATALOG_FAMILY, HConstants.SPLITB_QUALIFIER);
291     deleteMetaTable(catalogTracker, delete);
292     LOG.info("Deleted daughters references, qualifier=" + Bytes.toStringBinary(HConstants.SPLITA_QUALIFIER) +
293       " and qualifier=" + Bytes.toStringBinary(HConstants.SPLITB_QUALIFIER) +
294       ", from parent " + parent.getRegionNameAsString());
295   }
296 
297   public static HRegionInfo getHRegionInfo(
298       Result data) throws IOException {
299     byte [] bytes =
300       data.getValue(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER);
301     if (bytes == null) return null;
302     HRegionInfo info = Writables.getHRegionInfo(bytes);
303     LOG.info("Current INFO from scan results = " + info);
304     return info;
305   }
306 
307   private static Put addRegionInfo(final Put p, final HRegionInfo hri)
308   throws IOException {
309     p.add(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER,
310         Writables.getBytes(hri));
311     return p;
312   }
313 
314   private static Put addLocation(final Put p, final ServerName sn) {
315     p.add(HConstants.CATALOG_FAMILY, HConstants.SERVER_QUALIFIER,
316       Bytes.toBytes(sn.getHostAndPort()));
317     p.add(HConstants.CATALOG_FAMILY, HConstants.STARTCODE_QUALIFIER,
318       Bytes.toBytes(sn.getStartcode()));
319     return p;
320   }
321 }