Skip to content

Commit

Permalink
HBASE-29082: Support for custom meta table name suffix
Browse files Browse the repository at this point in the history
  • Loading branch information
kabhishek4 committed Feb 25, 2025
1 parent 28f1b51 commit 1c63e68
Show file tree
Hide file tree
Showing 3 changed files with 164 additions and 3 deletions.
12 changes: 12 additions & 0 deletions hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -1641,6 +1641,18 @@ public enum OperationStatusCode {
*/
public final static boolean REJECT_DECOMMISSIONED_HOSTS_DEFAULT = false;

/**
* Adds a suffix to the meta table name: value=’test’ -> ‘hbase:meta_test’
* Added in HBASE-XXXXX to support having multiple hbase:meta tables (with distinct names )to
* enable storage sharing by more than one clusters.
*/
public final static String HBASE_META_TABLE_SUFFIX = "hbase.meta.table.suffix";

/**
* Default value of {@link #HBASE_META_TABLE_SUFFIX}
*/
public final static String HBASE_META_TABLE_SUFFIX_DEFAULT_VALUE = "";

private HConstants() {
// Can't be instantiated with this ctor.
}
Expand Down
37 changes: 34 additions & 3 deletions hbase-common/src/main/java/org/apache/hadoop/hbase/TableName.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
*/
package org.apache.hadoop.hbase;

import com.google.errorprone.annotations.RestrictedApi;
import java.nio.ByteBuffer;
import java.util.concurrent.ScheduledExecutorService;
import org.apache.hadoop.conf.Configuration;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Set;
Expand All @@ -27,6 +30,9 @@
import org.apache.yetus.audience.InterfaceAudience;

import org.apache.hbase.thirdparty.com.google.common.base.Preconditions;
import org.apache.hbase.thirdparty.com.google.common.base.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Immutable POJO class for representing a table name. Which is of the form: <table
Expand All @@ -44,6 +50,8 @@
*/
@InterfaceAudience.Public
public final class TableName implements Comparable<TableName> {
private static final Logger LOG = LoggerFactory.getLogger(TableName.class);


/** See {@link #createTableNameIfNecessary(ByteBuffer, ByteBuffer)} */
private static final Set<TableName> tableCache = new CopyOnWriteArraySet<>();
Expand All @@ -65,9 +73,32 @@ public final class TableName implements Comparable<TableName> {
public static final String VALID_USER_TABLE_REGEX = "(?:(?:(?:" + VALID_NAMESPACE_REGEX + "\\"
+ NAMESPACE_DELIM + ")?)" + "(?:" + VALID_TABLE_QUALIFIER_REGEX + "))";

/** The hbase:meta table's name. */
public static final TableName META_TABLE_NAME =
valueOf(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR, "meta");
/** The name of hbase meta table could either be hbase:meta_xxx or 'hbase:meta' otherwise.
* Config hbase.meta.table.suffix will govern the decision of adding suffix to the habase:meta */
public static final TableName META_TABLE_NAME;
static {
Configuration conf = HBaseConfiguration.create();
META_TABLE_NAME = initializeHbaseMetaTableName(conf);
LOG.info("Meta table name: {}", META_TABLE_NAME);
}

/* Visible for testing only */
@RestrictedApi(explanation = "Should only be called in tests", link = "",
allowedOnPath = ".*/src/test/.*")
public static TableName getDefaultNameOfMetaForReplica() {
return valueOf(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR, "meta");
}

public static TableName initializeHbaseMetaTableName(Configuration conf) {
String suffix_val = conf.get(HConstants.HBASE_META_TABLE_SUFFIX,
HConstants.HBASE_META_TABLE_SUFFIX_DEFAULT_VALUE);
if (Strings.isNullOrEmpty(suffix_val)) {
return valueOf(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR, "meta");
} else {
return valueOf(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR,
"meta_" + suffix_val);
}
}

/**
* The Namespace table's name.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* 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;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.RegionInfo;
import org.apache.hadoop.hbase.master.HMaster;
import org.apache.hadoop.hbase.testclassification.MediumTests;
import org.apache.hadoop.hbase.testclassification.MiscTests;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.Pair;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.rules.TestName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Test {@link org.apache.hadoop.hbase.TestMetaTableForReplica}.
*/
@Category({ MiscTests.class, MediumTests.class })
@SuppressWarnings("deprecation")
public class TestMetaTableForReplica {
@ClassRule
public static final HBaseClassTestRule CLASS_RULE =
HBaseClassTestRule.forClass(TestMetaTableForReplica.class);

private static final Logger LOG = LoggerFactory.getLogger(TestMetaTableForReplica.class);
private static final HBaseTestingUtil UTIL = new HBaseTestingUtil();
private static Connection connection;

@Rule
public TestName name = new TestName();

@BeforeClass
public static void beforeClass() throws Exception {
Configuration c = new Configuration(UTIL.getConfiguration());
// quicker heartbeat interval for faster DN death notification
c.setInt("dfs.namenode.heartbeat.recheck-interval", 5000);
c.setInt("dfs.heartbeat.interval", 1);
c.setInt("dfs.client.socket-timeout", 5000);
c.setInt("hbase.ipc.client.connect.max.retries", 1);
c.setInt("dfs.client.block.recovery.retries", 1);
c.setInt(HConstants.ZK_SESSION_TIMEOUT, 1000);
//Start cluster having non-default hbase meta table name
c.setStrings(HConstants.HBASE_META_TABLE_SUFFIX, "test");
UTIL.startMiniCluster(3);
connection = ConnectionFactory.createConnection(c);
}

@AfterClass
public static void afterClass() throws Exception {
connection.close();
UTIL.shutdownMiniCluster();
}

@Test
public void testStateOfMetaForReplica() {
HMaster m = UTIL.getMiniHBaseCluster().getMaster();
assertTrue(m.waitForMetaOnline());
}

@Test
public void testNameOfMetaForReplica() {
//Check the correctness of the meta table for replica
String metaTableName = TableName.META_TABLE_NAME.getNameWithNamespaceInclAsString();
assertNotNull(metaTableName);

//Check if name of the meta table for replica is not same as default table
assertEquals(0,
TableName.META_TABLE_NAME.compareTo(TableName.getDefaultNameOfMetaForReplica()));
}

@Test
public void testGetNonExistentRegionFromMetaFromReplica() throws IOException {
final String name = this.name.getMethodName();
LOG.info("Started " + name);
Pair<RegionInfo, ServerName> pair =
MetaTableAccessor.getRegion(connection, Bytes.toBytes("nonexistent-region"));
assertNull(pair);
LOG.info("Finished " + name);
}

@Test
public void testGetExistentRegionFromMetaFromReplica() throws IOException {
final TableName tableName = TableName.valueOf(name.getMethodName());
LOG.info("Started " + tableName);
UTIL.createTable(tableName, HConstants.CATALOG_FAMILY);
assertEquals(1, MetaTableAccessor.getTableRegions(connection, tableName).size());
}
}

0 comments on commit 1c63e68

Please sign in to comment.