1   /**
2    * Copyright 2009 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;
21  
22  import org.apache.commons.logging.Log;
23  import org.apache.commons.logging.LogFactory;
24  import org.apache.hadoop.conf.Configuration;
25  import org.apache.hadoop.hbase.client.Get;
26  import org.apache.hadoop.hbase.client.HBaseAdmin;
27  import org.apache.hadoop.hbase.client.HConnection;
28  import org.apache.hadoop.hbase.client.HConnectionManager;
29  import org.apache.hadoop.hbase.client.HTable;
30  import org.apache.hadoop.hbase.client.Put;
31  import org.apache.hadoop.hbase.util.Bytes;
32  import org.apache.hadoop.hbase.zookeeper.ZooKeeperWrapper;
33  import org.apache.zookeeper.KeeperException;
34  import org.apache.zookeeper.ZooKeeper;
35  import org.junit.After;
36  import org.junit.AfterClass;
37  import org.junit.Before;
38  import org.junit.BeforeClass;
39  import org.junit.Test;
40  
41  import java.io.IOException;
42  
43  import static org.junit.Assert.assertFalse;
44  import static org.junit.Assert.assertNotNull;
45  import static org.junit.Assert.assertNull;
46  import static org.junit.Assert.fail;
47  
48  public class TestZooKeeper {
49    private final Log LOG = LogFactory.getLog(this.getClass());
50  
51    private final static HBaseTestingUtility
52        TEST_UTIL = new HBaseTestingUtility();
53  
54    private static Configuration conf;
55  
56    /**
57     * @throws java.lang.Exception
58     */
59    @BeforeClass
60    public static void setUpBeforeClass() throws Exception {
61      // Test we can first start the ZK cluster by itself
62      TEST_UTIL.startMiniZKCluster();
63      TEST_UTIL.getConfiguration().setBoolean("dfs.support.append", true);
64      TEST_UTIL.startMiniCluster(2);
65      conf = TEST_UTIL.getConfiguration();
66    }
67  
68    /**
69     * @throws java.lang.Exception
70     */
71    @AfterClass
72    public static void tearDownAfterClass() throws Exception {
73      TEST_UTIL.shutdownMiniCluster();
74    }
75  
76    /**
77     * @throws java.lang.Exception
78     */
79    @Before
80    public void setUp() throws Exception {
81      TEST_UTIL.ensureSomeRegionServersAvailable(2);
82    }
83  
84    /**
85     * See HBASE-1232 and http://wiki.apache.org/hadoop/ZooKeeper/FAQ#4.
86     * @throws IOException
87     * @throws InterruptedException
88     */
89    @Test
90    public void testClientSessionExpired()
91        throws IOException, InterruptedException {
92      new HTable(conf, HConstants.META_TABLE_NAME);
93  
94      ZooKeeperWrapper zkw =
95          ZooKeeperWrapper.createInstance(conf, TestZooKeeper.class.getName());
96      zkw.registerListener(EmptyWatcher.instance);
97      String quorumServers = zkw.getQuorumServers();
98      int sessionTimeout = 5 * 1000; // 5 seconds
99      HConnection connection = HConnectionManager.getConnection(conf);
100     ZooKeeperWrapper connectionZK = connection.getZooKeeperWrapper();
101     long sessionID = connectionZK.getSessionID();
102     byte[] password = connectionZK.getSessionPassword();
103 
104     ZooKeeper zk = new ZooKeeper(quorumServers, sessionTimeout,
105         EmptyWatcher.instance, sessionID, password);
106     zk.close();
107 
108     Thread.sleep(sessionTimeout * 3L);
109 
110     System.err.println("ZooKeeper should have timed out");
111     connection.relocateRegion(HConstants.ROOT_TABLE_NAME, HConstants.EMPTY_BYTE_ARRAY);
112   }
113   @Test
114   public void testRegionServerSessionExpired() throws Exception{
115     LOG.info("Starting testRegionServerSessionExpired");
116     new HTable(conf, HConstants.META_TABLE_NAME);
117     TEST_UTIL.expireRegionServerSession(0);
118     testSanity();
119   }
120   @Test
121   public void testMasterSessionExpired() throws Exception {
122     LOG.info("Starting testMasterSessionExpired");
123     new HTable(conf, HConstants.META_TABLE_NAME);
124     TEST_UTIL.expireMasterSession();
125     testSanity();
126   }
127 
128   /**
129    * Make sure we can use the cluster
130    * @throws Exception
131    */
132   public void testSanity() throws Exception{
133 
134     HBaseAdmin admin = new HBaseAdmin(conf);
135     String tableName = "test"+System.currentTimeMillis();
136     HTableDescriptor desc =
137         new HTableDescriptor(tableName);
138     HColumnDescriptor family = new HColumnDescriptor("fam");
139     desc.addFamily(family);
140     admin.createTable(desc);
141 
142     HTable table = new HTable(tableName);
143     Put put = new Put(Bytes.toBytes("testrow"));
144     put.add(Bytes.toBytes("fam"),
145         Bytes.toBytes("col"), Bytes.toBytes("testdata"));
146     table.put(put);
147 
148   }
149 
150   @Test
151   public void testMultipleZK() {
152     try {
153       HTable localMeta = new HTable(conf, HConstants.META_TABLE_NAME);
154       Configuration otherConf = HBaseConfiguration.create(conf);
155       otherConf.set(HConstants.ZOOKEEPER_QUORUM, "127.0.0.1");
156       HTable ipMeta = new HTable(otherConf, HConstants.META_TABLE_NAME);
157 
158       // dummy, just to open the connection
159       localMeta.exists(new Get(HConstants.LAST_ROW));
160       ipMeta.exists(new Get(HConstants.LAST_ROW));
161 
162       // make sure they aren't the same
163       assertFalse(HConnectionManager.getClientZooKeeperWatcher(conf)
164           .getZooKeeperWrapper() == HConnectionManager.getClientZooKeeperWatcher(
165           otherConf).getZooKeeperWrapper());
166       assertFalse(HConnectionManager.getConnection(conf)
167           .getZooKeeperWrapper().getQuorumServers().equals(HConnectionManager
168           .getConnection(otherConf).getZooKeeperWrapper().getQuorumServers()));
169     } catch (Exception e) {
170       e.printStackTrace();
171       fail();
172     }
173   }
174 
175   /**
176    * Create a bunch of znodes in a hierarchy, try deleting one that has childs
177    * (it will fail), then delete it recursively, then delete the last znode
178    * @throws Exception
179    */
180   @Test
181   public void testZNodeDeletes() throws Exception {
182     ZooKeeperWrapper zkw =
183         ZooKeeperWrapper.createInstance(conf, TestZooKeeper.class.getName());
184     zkw.registerListener(EmptyWatcher.instance);
185     zkw.ensureExists("/l1/l2/l3/l4");
186     try {
187       zkw.deleteZNode("/l1/l2");
188       fail("We should not be able to delete if znode has childs");
189     } catch (KeeperException ex) {
190       assertNotNull(zkw.getData("/l1/l2/l3", "l4"));
191     }
192     zkw.deleteZNode("/l1/l2", true);
193     assertNull(zkw.getData("/l1/l2/l3", "l4"));
194     zkw.deleteZNode("/l1");
195     assertNull(zkw.getData("/l1", "l2"));
196   }
197 }