1   /*
2    * Copyright 2010 The Apache Software Foundation
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, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  package org.apache.hadoop.hbase.client;
21  
22  import java.lang.reflect.Field;
23  import java.util.ArrayList;
24  import java.util.HashSet;
25  import java.util.List;
26  import java.util.Map;
27  import java.util.Random;
28  import java.util.Set;
29  
30  import org.apache.hadoop.conf.Configuration;
31  import org.apache.hadoop.hbase.HBaseConfiguration;
32  import org.apache.hadoop.hbase.HBaseTestingUtility;
33  import org.apache.hadoop.hbase.HRegionLocation;
34  import org.apache.hadoop.hbase.ZooKeeperConnectionException;
35  import org.apache.hadoop.hbase.util.Bytes;
36  import org.junit.AfterClass;
37  import org.junit.Assert;
38  import org.junit.BeforeClass;
39  import org.junit.Test;
40  import org.apache.commons.logging.Log;
41  import org.apache.commons.logging.LogFactory;
42  
43  import static org.junit.Assert.assertNull;
44  import static org.junit.Assert.assertNotNull;
45  
46  /**
47   * This class is for testing HCM features
48   */
49  public class TestHCM {
50    private static final Log LOG = LogFactory.getLog(TestHCM.class);
51    private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
52    private static final byte[] TABLE_NAME = Bytes.toBytes("test");
53    private static final byte[] FAM_NAM = Bytes.toBytes("f");
54    private static final byte[] ROW = Bytes.toBytes("bbb");
55  
56    @BeforeClass
57    public static void setUpBeforeClass() throws Exception {
58      TEST_UTIL.startMiniCluster(1);
59    }
60  
61    @AfterClass public static void tearDownAfterClass() throws Exception {
62      TEST_UTIL.shutdownMiniCluster();
63    }
64  
65    /**
66     * @throws InterruptedException 
67     * @throws IllegalAccessException 
68     * @throws NoSuchFieldException 
69     * @throws ZooKeeperConnectionException 
70     * @throws IllegalArgumentException 
71     * @throws SecurityException 
72     * @see https://issues.apache.org/jira/browse/HBASE-2925
73     */
74    // Disabling.  Of course this test will OOME using new Configuration each time
75    // St.Ack 20110428
76    // @Test
77    public void testManyNewConnectionsDoesnotOOME()
78    throws SecurityException, IllegalArgumentException,
79    ZooKeeperConnectionException, NoSuchFieldException, IllegalAccessException,
80    InterruptedException {
81      createNewConfigurations();
82    }
83  
84    private static Random _randy = new Random();
85  
86    public static void createNewConfigurations() throws SecurityException,
87    IllegalArgumentException, NoSuchFieldException,
88    IllegalAccessException, InterruptedException, ZooKeeperConnectionException {
89      HConnection last = null;
90      for (int i = 0; i <= (HConnectionManager.MAX_CACHED_HBASE_INSTANCES * 2); i++) {
91        // set random key to differentiate the connection from previous ones
92        Configuration configuration = HBaseConfiguration.create();
93        configuration.set("somekey", String.valueOf(_randy.nextInt()));
94        System.out.println("Hash Code: " + configuration.hashCode());
95        HConnection connection = HConnectionManager.getConnection(configuration);
96        if (last != null) {
97          if (last == connection) {
98            System.out.println("!! Got same connection for once !!");
99          }
100       }
101       // change the configuration once, and the cached connection is lost forever:
102       //      the hashtable holding the cache won't be able to find its own keys
103       //      to remove them, so the LRU strategy does not work.
104       configuration.set("someotherkey", String.valueOf(_randy.nextInt()));
105       last = connection;
106       LOG.info("Cache Size: "
107           + getHConnectionManagerCacheSize() + ", Valid Keys: "
108           + getValidKeyCount());
109       Thread.sleep(100);
110     }
111     Assert.assertEquals(HConnectionManager.MAX_CACHED_HBASE_INSTANCES,
112       getHConnectionManagerCacheSize());
113     Assert.assertEquals(HConnectionManager.MAX_CACHED_HBASE_INSTANCES,
114       getValidKeyCount());
115   }
116 
117   private static int getHConnectionManagerCacheSize()
118   throws SecurityException, NoSuchFieldException,
119   IllegalArgumentException, IllegalAccessException {
120     Field cacheField =
121       HConnectionManager.class.getDeclaredField("HBASE_INSTANCES");
122     cacheField.setAccessible(true);
123     Map<?, ?> cache = (Map<?, ?>) cacheField.get(null);
124     return cache.size();
125   }
126 
127   private static int getValidKeyCount() throws SecurityException,
128   NoSuchFieldException, IllegalArgumentException,
129   IllegalAccessException {
130     Field cacheField =
131       HConnectionManager.class.getDeclaredField("HBASE_INSTANCES");
132     cacheField.setAccessible(true);
133     Map<?, ?> cache = (Map<?, ?>) cacheField.get(null);
134     List<Object> keys = new ArrayList<Object>(cache.keySet());
135     Set<Object> values = new HashSet<Object>();
136     for (Object key : keys) {
137       values.add(cache.get(key));
138     }
139     return values.size();
140   }
141 
142   /**
143    * Test that when we delete a location using the first row of a region
144    * that we really delete it.
145    * @throws Exception
146    */
147   @Test
148   public void testRegionCaching() throws Exception{
149     HTable table = TEST_UTIL.createTable(TABLE_NAME, FAM_NAM);
150     TEST_UTIL.createMultiRegions(table, FAM_NAM);
151     Put put = new Put(ROW);
152     put.add(FAM_NAM, ROW, ROW);
153     table.put(put);
154     HConnectionManager.HConnectionImplementation conn =
155         (HConnectionManager.HConnectionImplementation)table.getConnection();
156     assertNotNull(conn.getCachedLocation(TABLE_NAME, ROW));
157     conn.deleteCachedLocation(TABLE_NAME, ROW);
158     HRegionLocation rl = conn.getCachedLocation(TABLE_NAME, ROW);
159     assertNull("What is this location?? " + rl, rl);
160   }
161 }