HBASE-8131 - Create table handler needs to handle failure cases. (Ram)

git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1458922 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
ramkrishna 2013-03-20 16:25:23 +00:00
parent e253150cf3
commit 75105027a1
4 changed files with 137 additions and 2 deletions

View File

@ -343,6 +343,23 @@ public class ZKTable {
ZooKeeperProtos.Table.State.DISABLING);
}
/**
* If the table is found in ENABLING state the inmemory state is removed. This
* helps in cases where CreateTable is to be retried by the client incase of
* failures
*
* @param tableName
*/
public void removeEnablingTable(final String tableName) {
synchronized (this.cache) {
if (isEnablingTable(tableName)) {
this.cache.remove(tableName);
}
}
}
/**
* Gets a list of all the tables of specified states in zookeeper.
* @return Set of tables of specified states, empty Set if none

View File

@ -166,6 +166,15 @@ public class CreateTableHandler extends EventHandler {
* @param exception null if process() is successful or not null if something has failed.
*/
protected void completed(final Throwable exception) {
releaseTableLock();
if (exception != null) {
// Try deleting the enabling node in case of error
// If this does not happen then if the client tries to create the table
// again with the same Active master
// It will block the creation saying TableAlreadyExists.
this.assignmentManager.getZKTable().removeEnablingTable(
this.hTableDescriptor.getNameAsString());
}
}
/**
@ -222,8 +231,6 @@ public class CreateTableHandler extends EventHandler {
} catch (KeeperException e) {
throw new IOException("Unable to ensure that " + tableName + " will be" +
" enabled because of a ZooKeeper issue", e);
} finally {
releaseTableLock();
}
}

View File

@ -126,6 +126,7 @@ public class CloneSnapshotHandler extends CreateTableHandler implements Snapshot
@Override
protected void completed(final Throwable exception) {
this.stopped = true;
super.completed(exception);
}
@Override

View File

@ -0,0 +1,110 @@
/**
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.hbase.master.handler;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.HBaseTestingUtility;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HRegionInfo;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.MediumTests;
import org.apache.hadoop.hbase.MiniHBaseCluster;
import org.apache.hadoop.hbase.Server;
import org.apache.hadoop.hbase.master.HMaster;
import org.apache.hadoop.hbase.master.MasterFileSystem;
import org.apache.hadoop.hbase.master.MasterServices;
import org.apache.hadoop.hbase.master.TestMaster;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.zookeeper.ZKTable;
import org.apache.hadoop.hbase.zookeeper.ZKUtil;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;
@Category(MediumTests.class)
public class TestCreateTableHandler {
private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
private static final Log LOG = LogFactory.getLog(TestCreateTableHandler.class);
private static final byte[] TABLENAME = Bytes.toBytes("TestCreateTableHandler");
private static final byte[] FAMILYNAME = Bytes.toBytes("fam");
public static boolean throwException = false;
@BeforeClass
public static void setUp() throws Exception {
TEST_UTIL.startMiniCluster(1);
}
@AfterClass
public static void tearDown() throws Exception {
TEST_UTIL.shutdownMiniCluster();
}
@Test
public void testCreateTableHandlerIfCalledTwoTimesAndFirstOneIsUnderProgress() throws Exception {
final MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster();
final HMaster m = cluster.getMaster();
final HTableDescriptor desc = new HTableDescriptor(TABLENAME);
desc.addFamily(new HColumnDescriptor(FAMILYNAME));
final HRegionInfo[] hRegionInfos = new HRegionInfo[] { new HRegionInfo(desc.getName(), null,
null) };
CustomCreateTableHandler handler = new CustomCreateTableHandler(m, m.getMasterFileSystem(),
desc, cluster.getConfiguration(), hRegionInfos, m);
handler.prepare();
throwException = true;
handler.process();
throwException = false;
CustomCreateTableHandler handler1 = new CustomCreateTableHandler(m, m.getMasterFileSystem(),
desc, cluster.getConfiguration(), hRegionInfos, m);
handler1.prepare();
handler1.process();
for (int i = 0; i < 100; i++) {
if (!TEST_UTIL.getHBaseAdmin().isTableAvailable(TABLENAME)) {
Thread.sleep(200);
}
}
assertTrue(TEST_UTIL.getHBaseAdmin().isTableEnabled(TABLENAME));
}
private static class CustomCreateTableHandler extends CreateTableHandler {
public CustomCreateTableHandler(Server server, MasterFileSystem fileSystemManager,
HTableDescriptor hTableDescriptor, Configuration conf, HRegionInfo[] newRegions,
MasterServices masterServices) {
super(server, fileSystemManager, hTableDescriptor, conf, newRegions, masterServices);
}
@Override
protected List<HRegionInfo> handleCreateHdfsRegions(Path tableRootDir, String tableName)
throws IOException {
if (throwException) {
throw new IOException("Test throws exceptions.");
}
return super.handleCreateHdfsRegions(tableRootDir, tableName);
}
}
}