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    * <p>
10   * http://www.apache.org/licenses/LICENSE-2.0
11   * <p>
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  
19  package org.apache.hadoop.hbase.coprocessor.example;
20  
21  import org.apache.commons.logging.Log;
22  import org.apache.commons.logging.LogFactory;
23  import org.apache.hadoop.conf.Configuration;
24  import org.apache.hadoop.fs.FileSystem;
25  import org.apache.hadoop.fs.Path;
26  import org.apache.hadoop.hbase.HBaseTestingUtility;
27  import org.apache.hadoop.hbase.HColumnDescriptor;
28  import org.apache.hadoop.hbase.HConstants;
29  import org.apache.hadoop.hbase.HRegionInfo;
30  import org.apache.hadoop.hbase.HTableDescriptor;
31  import org.apache.hadoop.hbase.MiniHBaseCluster;
32  import org.apache.hadoop.hbase.TableName;
33  import org.apache.hadoop.hbase.client.Admin;
34  import org.apache.hadoop.hbase.client.HTable;
35  import org.apache.hadoop.hbase.client.RetriesExhaustedException;
36  import org.apache.hadoop.hbase.client.example.RefreshHFilesClient;
37  import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
38  import org.apache.hadoop.hbase.regionserver.HRegion;
39  import org.apache.hadoop.hbase.regionserver.HStore;
40  import org.apache.hadoop.hbase.regionserver.Region;
41  import org.apache.hadoop.hbase.regionserver.RegionServerServices;
42  import org.apache.hadoop.hbase.regionserver.Store;
43  import org.apache.hadoop.hbase.testclassification.MediumTests;
44  import org.apache.hadoop.hbase.util.Bytes;
45  import org.apache.hadoop.hbase.util.HFileTestUtil;
46  import org.apache.hadoop.hbase.wal.WAL;
47  import org.junit.After;
48  import org.junit.Test;
49  import org.junit.experimental.categories.Category;
50  
51  import java.io.IOException;
52  import java.util.ArrayList;
53  import java.util.List;
54  
55  import static org.junit.Assert.assertEquals;
56  import static org.junit.Assert.fail;
57  
58  @Category(MediumTests.class)
59  public class TestRefreshHFilesEndpoint {
60    private static final Log LOG = LogFactory.getLog(TestRefreshHFilesEndpoint.class);
61    private static final HBaseTestingUtility HTU = new HBaseTestingUtility();
62    private static final int NUM_MASTER = 1;
63    private static final int NUM_RS = 2;
64    private static final TableName TABLE_NAME = TableName.valueOf("testRefreshRegionHFilesEP");
65    private static final byte[] FAMILY = Bytes.toBytes("family");
66    private static final byte[] QUALIFIER = Bytes.toBytes("qualifier");
67    private static final byte[][] SPLIT_KEY = new byte[][] { Bytes.toBytes("30") };
68    private static final int NUM_ROWS = 5;
69    private static final String HFILE_NAME = "123abcdef";
70  
71    private static Configuration CONF = HTU.getConfiguration();
72    private static MiniHBaseCluster cluster;
73    private static HTableDescriptor desc;
74    private static Admin hbaseAdmin;
75    private static HTable table;
76  
77    public static void setUp(String regionImpl) {
78      try {
79        CONF.set(HConstants.REGION_IMPL, regionImpl);
80        CONF.setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 2);
81  
82        CONF.setStrings(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY, RefreshHFilesEndpoint.class.getName());
83        cluster = HTU.startMiniCluster(NUM_MASTER, NUM_RS);
84  
85        // Create table
86        desc = new HTableDescriptor(TABLE_NAME);
87        desc.addFamily(new HColumnDescriptor(FAMILY));
88        hbaseAdmin = cluster.getMaster().getConnection().getAdmin();
89        hbaseAdmin.createTable(desc, SPLIT_KEY);
90        table = new HTable(HTU.getConfiguration(), TABLE_NAME);
91  
92        // this will create 2 regions spread across slaves
93        HTU.loadNumericRows(table, FAMILY, 1, 20);
94        HTU.flush(TABLE_NAME);
95      } catch (Exception ex) {
96        LOG.error("Couldn't finish setup", ex);
97      }
98    }
99  
100   @After
101   public void tearDown() throws Exception {
102     HTU.shutdownMiniCluster();
103   }
104 
105   @Test
106   public void testRefreshRegionHFilesEndpoint() throws Exception {
107     setUp(HRegion.class.getName());
108     Path tableDir = desc.getTableDir(HTU.getDefaultRootDirPath(), TABLE_NAME.toBytes());
109     for (Region region : cluster.getRegions(TABLE_NAME)) {
110       Path regionDir = new Path(tableDir, region.getRegionInfo().getEncodedName());
111       Path familyDir = new Path(regionDir, Bytes.toString(FAMILY));
112       HFileTestUtil
113         .createHFile(HTU.getConfiguration(), HTU.getTestFileSystem(), new Path(familyDir, HFILE_NAME), FAMILY,
114                      QUALIFIER, Bytes.toBytes("50"), Bytes.toBytes("60"), NUM_ROWS);
115     }
116     assertEquals(2, HTU.getNumHFiles(TABLE_NAME, FAMILY));
117     callRefreshRegionHFilesEndPoint();
118     assertEquals(4, HTU.getNumHFiles(TABLE_NAME, FAMILY));
119   }
120 
121   @Test(expected = IOException.class)
122   public void testRefreshRegionHFilesEndpointWithException() throws IOException {
123     setUp(HRegionForRefreshHFilesEP.class.getName());
124     callRefreshRegionHFilesEndPoint();
125   }
126 
127   private void callRefreshRegionHFilesEndPoint() throws IOException {
128     try {
129       RefreshHFilesClient refreshHFilesClient = new RefreshHFilesClient(CONF);
130       refreshHFilesClient.refreshHFiles(TABLE_NAME);
131     } catch (RetriesExhaustedException rex) {
132       if (rex.getCause() instanceof IOException)
133         throw new IOException();
134     } catch (Throwable ex) {
135       LOG.error(ex);
136       fail("Couldn't call the RefreshRegionHFilesEndpoint");
137     }
138   }
139 
140   public static class HRegionForRefreshHFilesEP extends HRegion {
141     HStoreWithFaultyRefreshHFilesAPI store;
142 
143     public HRegionForRefreshHFilesEP(final Path tableDir, final WAL wal, final FileSystem fs,
144                                      final Configuration confParam, final HRegionInfo regionInfo,
145                                      final HTableDescriptor htd, final RegionServerServices rsServices) {
146       super(tableDir, wal, fs, confParam, regionInfo, htd, rsServices);
147     }
148 
149     @Override
150     public List<Store> getStores() {
151       List<Store> list = new ArrayList<Store>(stores.size());
152       /**
153        * This is used to trigger the custom definition (faulty)
154        * of refresh HFiles API.
155        */
156       try {
157         if (this.store == null)
158           store = new HStoreWithFaultyRefreshHFilesAPI(this, new HColumnDescriptor(FAMILY), this.conf);
159         list.add(store);
160       } catch (IOException ioe) {
161         LOG.info("Couldn't instantiate custom store implementation", ioe);
162       }
163 
164       list.addAll(stores.values());
165       return list;
166     }
167   }
168 
169   public static class HStoreWithFaultyRefreshHFilesAPI extends HStore {
170     public HStoreWithFaultyRefreshHFilesAPI(final HRegion region, final HColumnDescriptor family,
171                                             final Configuration confParam) throws IOException {
172       super(region, family, confParam);
173     }
174 
175     @Override
176     public void refreshStoreFiles() throws IOException {
177       throw new IOException();
178     }
179   }
180 }