private boolean prepareCreate(final MasterProcedureEnv env) throws IOException { final TableName tableName = getTableName(); if (MetaTableAccessor.tableExists(env.getMasterServices().getConnection(), tableName)) { setFailure("master-create-table", new TableExistsException(getTableName())); return false; } // During master initialization, the ZK state could be inconsistent from failed DDL // in the past. If we fail here, it would prevent master to start. We should force // setting the system table state regardless the table state. boolean skipTableStateCheck = !(env.getMasterServices().isInitialized()) && tableName.isSystemTable(); if (!skipTableStateCheck) { TableStateManager tsm = env.getMasterServices().getAssignmentManager().getTableStateManager(); if (tsm.isTableState(tableName, true, ZooKeeperProtos.Table.State.ENABLING, ZooKeeperProtos.Table.State.ENABLED)) { LOG.warn("The table " + tableName + " does not exist in meta but has a znode. " + "run hbck to fix inconsistencies."); setFailure("master-create-table", new TableExistsException(getTableName())); return false; } } return true; }
@Override public TableStateManager getTableStateManager() throws InterruptedException, CoordinatedStateException { try { return new ZKTableStateManager(server.getZooKeeper()); } catch (KeeperException e) { throw new CoordinatedStateException(e); } }
RegionStates(final Server master, final TableStateManager tableStateManager, final ServerManager serverManager, final RegionStateStore regionStateStore) { this.tableStateManager = tableStateManager; this.regionStateStore = regionStateStore; this.serverManager = serverManager; this.server = master; }
/** * Action before any real action of disabling table. Set the exception in the procedure instead * of throwing it. This approach is to deal with backward compatible with 1.0. * @param env MasterProcedureEnv * @throws HBaseException * @throws IOException */ private boolean prepareDisable(final MasterProcedureEnv env) throws HBaseException, IOException { boolean canTableBeDisabled = true; if (tableName.equals(TableName.META_TABLE_NAME)) { setFailure("master-disable-table", new ConstraintException("Cannot disable catalog table")); canTableBeDisabled = false; } else if (!MetaTableAccessor.tableExists(env.getMasterServices().getConnection(), tableName)) { setFailure("master-disable-table", new TableNotFoundException(tableName)); canTableBeDisabled = false; } else if (!skipTableStateCheck) { // There could be multiple client requests trying to disable or enable // the table at the same time. Ensure only the first request is honored // After that, no other requests can be accepted until the table reaches // DISABLED or ENABLED. // // Note: A quick state check should be enough for us to move forward. However, instead of // calling TableStateManager.isTableState() to just check the state, we called // TableStateManager.setTableStateIfInStates() to set the state to DISABLING from ENABLED. // This is because we treat empty state as enabled from 0.92-clusters. See // ZKTableStateManager.setTableStateIfInStates() that has a hack solution to work around // this issue. TableStateManager tsm = env.getMasterServices().getAssignmentManager().getTableStateManager(); if (!tsm.setTableStateIfInStates(tableName, ZooKeeperProtos.Table.State.DISABLING, ZooKeeperProtos.Table.State.DISABLING, ZooKeeperProtos.Table.State.ENABLED)) { LOG.info("Table " + tableName + " isn't enabled; skipping disable"); setFailure("master-disable-table", new TableNotEnabledException(tableName)); canTableBeDisabled = false; } } // We are done the check. Future actions in this procedure could be done asynchronously. ProcedurePrepareLatch.releaseLatch(syncLatch, this); return canTableBeDisabled; }
/** * Action before any real action of enabling table. Set the exception in the procedure instead * of throwing it. This approach is to deal with backward compatible with 1.0. * @param env MasterProcedureEnv * @return whether the table passes the necessary checks * @throws IOException */ private boolean prepareEnable(final MasterProcedureEnv env) throws IOException { boolean canTableBeEnabled = true; // Check whether table exists if (!MetaTableAccessor.tableExists(env.getMasterServices().getConnection(), tableName)) { setFailure("master-enable-table", new TableNotFoundException(tableName)); canTableBeEnabled = false; } else if (!skipTableStateCheck) { // There could be multiple client requests trying to disable or enable // the table at the same time. Ensure only the first request is honored // After that, no other requests can be accepted until the table reaches // DISABLED or ENABLED. // // Note: in 1.0 release, we called TableStateManager.setTableStateIfInStates() to set // the state to ENABLING from DISABLED. The implementation was done before table lock // was implemented. With table lock, there is no need to set the state here (it will // set the state later on). A quick state check should be enough for us to move forward. TableStateManager tsm = env.getMasterServices().getAssignmentManager().getTableStateManager(); if (!tsm.isTableState(tableName, ZooKeeperProtos.Table.State.DISABLED)) { LOG.info("Table " + tableName + " isn't disabled; skipping enable"); setFailure("master-enable-table", new TableNotDisabledException(this.tableName)); canTableBeEnabled = false; } } // We are done the check. Future actions in this procedure could be done asynchronously. ProcedurePrepareLatch.releaseLatch(syncLatch, this); return canTableBeEnabled; }
@Test public void testWeDontReturnDrainingServersForOurBalancePlans() throws Exception { Server server = mock(Server.class); when(server.getServerName()).thenReturn(ServerName.valueOf("master,1,1")); Configuration configuration = mock(Configuration.class); when(server.getConfiguration()).thenReturn(configuration); TableStateManager tsm = mock(TableStateManager.class); ServerManager sm = mock(ServerManager.class); when(sm.isServerOnline(isA(ServerName.class))).thenReturn(true); RegionStateStore rss = mock(RegionStateStore.class); RegionStates regionStates = new RegionStates(server, tsm, sm, rss); ServerName one = mockServer("one", 1); ServerName two = mockServer("two", 1); ServerName three = mockServer("three", 1); when(sm.getDrainingServersList()).thenReturn(Arrays.asList(three)); regionStates.regionOnline(createFakeRegion(), one); regionStates.regionOnline(createFakeRegion(), two); regionStates.regionOnline(createFakeRegion(), three); Map<TableName, Map<ServerName, List<HRegionInfo>>> result = regionStates.getAssignmentsByTable(); for (Map<ServerName, List<HRegionInfo>> map : result.values()) { assertFalse(map.keySet().contains(three)); } }
@Override public abstract TableStateManager getTableStateManager() throws InterruptedException, CoordinatedStateException;
/** * @return Instance of ZKTableStateManager. */ public TableStateManager getTableStateManager() { // These are 'expensive' to make involving trip to zk ensemble so allow // sharing. return this.tableStateManager; }
@Test public void testTableStates() throws CoordinatedStateException, IOException, KeeperException, InterruptedException { final TableName name = TableName.valueOf("testDisabled"); Abortable abortable = new Abortable() { @Override public void abort(String why, Throwable e) { LOG.info(why, e); } @Override public boolean isAborted() { return false; } }; ZooKeeperWatcher zkw = new ZooKeeperWatcher(TEST_UTIL.getConfiguration(), name.getNameAsString(), abortable, true); TableStateManager zkt = new ZKTableStateManager(zkw); assertFalse(zkt.isTableState(name, Table.State.ENABLED)); assertFalse(zkt.isTableState(name, Table.State.DISABLING)); assertFalse(zkt.isTableState(name, Table.State.DISABLED)); assertFalse(zkt.isTableState(name, Table.State.ENABLING)); assertFalse(zkt.isTableState(name, Table.State.DISABLED, Table.State.DISABLING)); assertFalse(zkt.isTableState(name, Table.State.DISABLED, Table.State.ENABLING)); assertFalse(zkt.isTablePresent(name)); zkt.setTableState(name, Table.State.DISABLING); assertTrue(zkt.isTableState(name, Table.State.DISABLING)); assertTrue(zkt.isTableState(name, Table.State.DISABLED, Table.State.DISABLING)); assertFalse(zkt.getTablesInStates(Table.State.DISABLED).contains(name)); assertTrue(zkt.isTablePresent(name)); zkt.setTableState(name, Table.State.DISABLED); assertTrue(zkt.isTableState(name, Table.State.DISABLED)); assertTrue(zkt.isTableState(name, Table.State.DISABLED, Table.State.DISABLING)); assertFalse(zkt.isTableState(name, Table.State.DISABLING)); assertTrue(zkt.getTablesInStates(Table.State.DISABLED).contains(name)); assertTrue(zkt.isTablePresent(name)); zkt.setTableState(name, Table.State.ENABLING); assertTrue(zkt.isTableState(name, Table.State.ENABLING)); assertTrue(zkt.isTableState(name, Table.State.DISABLED, Table.State.ENABLING)); assertFalse(zkt.isTableState(name, Table.State.DISABLED)); assertFalse(zkt.getTablesInStates(Table.State.DISABLED).contains(name)); assertTrue(zkt.isTablePresent(name)); zkt.setTableState(name, Table.State.ENABLED); assertTrue(zkt.isTableState(name, Table.State.ENABLED)); assertFalse(zkt.isTableState(name, Table.State.ENABLING)); assertTrue(zkt.isTablePresent(name)); zkt.setDeletedTable(name); assertFalse(zkt.isTableState(name, Table.State.ENABLED)); assertFalse(zkt.isTableState(name, Table.State.DISABLING)); assertFalse(zkt.isTableState(name, Table.State.DISABLED)); assertFalse(zkt.isTableState(name, Table.State.ENABLING)); assertFalse(zkt.isTableState(name, Table.State.DISABLED, Table.State.DISABLING)); assertFalse(zkt.isTableState(name, Table.State.DISABLED, Table.State.ENABLING)); assertFalse(zkt.isTablePresent(name)); }
public static void validateTableIsEnabled(final HMaster master, final TableName tableName) throws IOException { TableStateManager tsm = master.getAssignmentManager().getTableStateManager(); assertTrue(tsm.isTableState(tableName, ZooKeeperProtos.Table.State.ENABLED)); }
public static void validateTableIsDisabled(final HMaster master, final TableName tableName) throws IOException { TableStateManager tsm = master.getAssignmentManager().getTableStateManager(); assertTrue(tsm.isTableState(tableName, ZooKeeperProtos.Table.State.DISABLED)); }