diff --git a/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/grpc/BigtableInstanceName.java b/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/grpc/BigtableInstanceName.java index df68c8f57d..ce58eafc43 100644 --- a/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/grpc/BigtableInstanceName.java +++ b/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/grpc/BigtableInstanceName.java @@ -126,6 +126,11 @@ public InstanceName toGcbInstanceName() { return InstanceName.of(projectId, instanceId); } + //TODO(rahulkql): Refactor once google-cloud-java/issues/4091 is resolved. + public com.google.bigtable.admin.v2.InstanceName toAdminInstanceName() { + return com.google.bigtable.admin.v2.InstanceName.of(projectId, instanceId); + } + public BigtableClusterName toClusterName(String clusterId) { return new BigtableClusterName(instanceName + "/clusters/" + clusterId); } diff --git a/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/grpc/TestBigtableInstanceName.java b/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/grpc/TestBigtableInstanceName.java index 75a476db0f..a20a9de08b 100644 --- a/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/grpc/TestBigtableInstanceName.java +++ b/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/grpc/TestBigtableInstanceName.java @@ -15,6 +15,7 @@ */ package com.google.cloud.bigtable.grpc; +import com.google.cloud.bigtable.data.v2.models.InstanceName; import org.junit.Assert; import org.junit.Rule; import org.junit.Test; @@ -97,4 +98,15 @@ public void testNoInstanceName() { expectedException.expect(IllegalArgumentException.class); new BigtableInstanceName("project", ""); } + + @Test + public void testGcbInstanceName(){ + Assert.assertTrue(bigtableInstanceName.toGcbInstanceName() instanceof InstanceName); + } + + @Test + public void testAdminInstanceName(){ + Assert.assertTrue(bigtableInstanceName.toAdminInstanceName() instanceof + com.google.bigtable.admin.v2.InstanceName); + } } diff --git a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/adapters/admin/ColumnDescriptorAdapter.java b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/adapters/admin/ColumnDescriptorAdapter.java index bfc69fc6d4..b857d943e0 100644 --- a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/adapters/admin/ColumnDescriptorAdapter.java +++ b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/adapters/admin/ColumnDescriptorAdapter.java @@ -15,23 +15,22 @@ */ package com.google.cloud.bigtable.hbase.adapters.admin; +import static com.google.cloud.bigtable.admin.v2.models.GCRules.GCRULES; + import com.google.bigtable.admin.v2.ColumnFamily; import com.google.bigtable.admin.v2.GcRule; -import com.google.bigtable.admin.v2.GcRule.Intersection; import com.google.bigtable.admin.v2.GcRule.RuleCase; -import com.google.bigtable.admin.v2.GcRule.Union; -import com.google.common.annotations.VisibleForTesting; +import com.google.cloud.bigtable.admin.v2.models.GCRules.GCRule; import com.google.common.base.Joiner; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; -import com.google.protobuf.Duration; +import org.threeten.bp.Duration; import org.apache.hadoop.hbase.HColumnDescriptor; import org.apache.hadoop.hbase.HConstants; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -164,12 +163,12 @@ public static void throwIfRequestingUnsupportedFeatures(HColumnDescriptor column } /** - * Construct an Bigtable {@link com.google.bigtable.admin.v2.GcRule} from the given column descriptor. + * Construct an Bigtable {@link GCRule} from the given column descriptor. * * @param columnDescriptor a {@link org.apache.hadoop.hbase.HColumnDescriptor} object. - * @return a {@link com.google.bigtable.admin.v2.GcRule} object. + * @return a {@link GCRule} object. */ - public static GcRule buildGarbageCollectionRule(HColumnDescriptor columnDescriptor) { + public static GCRule buildGarbageCollectionRule(HColumnDescriptor columnDescriptor) { int maxVersions = columnDescriptor.getMaxVersions(); int minVersions = columnDescriptor.getMinVersions(); int ttlSeconds = columnDescriptor.getTimeToLive(); @@ -181,12 +180,12 @@ public static GcRule buildGarbageCollectionRule(HColumnDescriptor columnDescript if (maxVersions == Integer.MAX_VALUE) { return null; } else { - return maxVersions(maxVersions); + return GCRULES.maxVersions(maxVersions); } } // minVersions only comes into play with a TTL: - GcRule ageRule = maxAge(ttlSeconds); + GCRule ageRule = GCRULES.maxAge(Duration.ofSeconds(ttlSeconds)); if (minVersions != HColumnDescriptor.DEFAULT_MIN_VERSIONS) { // The logic here is: only delete a cell if: // 1) the age is older than :ttlSeconds AND @@ -196,43 +195,15 @@ public static GcRule buildGarbageCollectionRule(HColumnDescriptor columnDescript // Intersection (AND) // - maxAge = :HBase_ttlSeconds // - maxVersions = :HBase_minVersion - ageRule = intersection(ageRule, maxVersions(minVersions)); + ageRule = GCRULES.intersection().rule(ageRule).rule(GCRULES.maxVersions(minVersions)); } if (maxVersions == Integer.MAX_VALUE) { return ageRule; } else { - return union(ageRule, maxVersions(maxVersions)); + return GCRULES.union().rule(ageRule).rule(GCRULES.maxVersions(maxVersions)); } } - @VisibleForTesting - static GcRule intersection(GcRule... rules) { - return GcRule.newBuilder() - .setIntersection(Intersection.newBuilder().addAllRules(Arrays.asList(rules)).build()) - .build(); - } - - @VisibleForTesting - static GcRule union(GcRule... rules) { - return GcRule.newBuilder() - .setUnion(Union.newBuilder().addAllRules(Arrays.asList(rules)).build()) - .build(); - } - - private static Duration duration(int ttlSeconds) { - return Duration.newBuilder().setSeconds(ttlSeconds).build(); - } - - @VisibleForTesting - static GcRule maxAge(int ttlSeconds) { - return GcRule.newBuilder().setMaxAge(duration(ttlSeconds)).build(); - } - - @VisibleForTesting - static GcRule maxVersions(int maxVersions) { - return GcRule.newBuilder().setMaxNumVersions(maxVersions).build(); - } - /** *

* Parse a Bigtable {@link GcRule} that is in line with @@ -338,9 +309,9 @@ public ColumnFamily adapt(HColumnDescriptor columnDescriptor) { throwIfRequestingUnsupportedFeatures(columnDescriptor); ColumnFamily.Builder resultBuilder = ColumnFamily.newBuilder(); - GcRule gcRule = buildGarbageCollectionRule(columnDescriptor); + GCRule gcRule = buildGarbageCollectionRule(columnDescriptor); if (gcRule != null) { - resultBuilder.setGcRule(gcRule); + resultBuilder.setGcRule(gcRule.toProto()); } return resultBuilder.build(); } diff --git a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/adapters/admin/TableAdapter.java b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/adapters/admin/TableAdapter.java index 26a7d4659d..199c0ee1f1 100644 --- a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/adapters/admin/TableAdapter.java +++ b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/adapters/admin/TableAdapter.java @@ -15,8 +15,11 @@ */ package com.google.cloud.bigtable.hbase.adapters.admin; +import static com.google.cloud.bigtable.hbase.adapters.admin.ColumnDescriptorAdapter.buildGarbageCollectionRule; + +import com.google.api.core.InternalApi; import com.google.bigtable.admin.v2.ColumnFamily; -import com.google.bigtable.admin.v2.CreateTableRequest; +import com.google.cloud.bigtable.admin.v2.models.CreateTableRequest; import com.google.bigtable.admin.v2.Table; import com.google.cloud.bigtable.grpc.BigtableInstanceName; @@ -26,8 +29,6 @@ import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.TableName; -import java.util.HashMap; -import java.util.Map; import java.util.Map.Entry; /** @@ -36,42 +37,40 @@ * @author sduskis * @version $Id: $Id */ +@InternalApi public class TableAdapter { private static final ColumnDescriptorAdapter columnDescriptorAdapter = ColumnDescriptorAdapter.INSTANCE; protected final BigtableInstanceName bigtableInstanceName; - - /** *

adapt.

* - * @param desc a {@link org.apache.hadoop.hbase.HTableDescriptor} object. - * @return a {@link com.google.bigtable.admin.v2.Table} object. + * This method adapts ColumnFamily to CreateTableRequest. + * + * @param desc a {@link HTableDescriptor} object. + * @param request a {@link CreateTableRequest} */ - protected static Table adapt(HTableDescriptor desc) { - Map columnFamilies = new HashMap<>(); - for (HColumnDescriptor column : desc.getColumnFamilies()) { - String columnName = column.getNameAsString(); - ColumnFamily columnFamily = columnDescriptorAdapter.adapt(column); - columnFamilies.put(columnName, columnFamily); + protected static void adapt(HTableDescriptor desc, CreateTableRequest request) { + if(request != null) { + for (HColumnDescriptor column : desc.getColumnFamilies()) { + String columnName = column.getNameAsString(); + request.addFamily(columnName, buildGarbageCollectionRule(column)); + } } - return Table.newBuilder().putAllColumnFamilies(columnFamilies).build(); } - public static CreateTableRequest.Builder adapt(HTableDescriptor desc, byte[][] splitKeys) { - CreateTableRequest.Builder builder = CreateTableRequest.newBuilder(); - builder.setTableId(desc.getTableName().getQualifierAsString()); - builder.setTable(adapt(desc)); - addSplitKeys(builder, splitKeys); - return builder; + public static CreateTableRequest adapt(HTableDescriptor desc, byte[][] splitKeys) { + CreateTableRequest request = CreateTableRequest.of(desc.getTableName().getNameAsString()); + adapt(desc, request); + addSplitKeys(splitKeys, request); + return request; } - public static void addSplitKeys(CreateTableRequest.Builder builder, byte[][] splitKeys) { + public static void addSplitKeys(byte[][] splitKeys, CreateTableRequest request) { if (splitKeys != null) { for (byte[] splitKey : splitKeys) { - builder.addInitialSplits( - CreateTableRequest.Split.newBuilder().setKey(ByteString.copyFrom(splitKey)).build()); + request.addSplit(ByteString.copyFrom(splitKey)); } } } @@ -89,8 +88,8 @@ public TableAdapter(BigtableInstanceName bigtableInstanceName) { /** *

adapt.

* - * @param table a {@link com.google.bigtable.admin.v2.Table} object. - * @return a {@link org.apache.hadoop.hbase.HTableDescriptor} object. + * @param table a {@link Table} object. + * @return a {@link HTableDescriptor} object. */ public HTableDescriptor adapt(Table table) { String tableId = bigtableInstanceName.toTableId(table.getName()); diff --git a/bigtable-client-core-parent/bigtable-hbase/src/main/java/org/apache/hadoop/hbase/client/AbstractBigtableAdmin.java b/bigtable-client-core-parent/bigtable-hbase/src/main/java/org/apache/hadoop/hbase/client/AbstractBigtableAdmin.java index 140436ba84..831f222836 100644 --- a/bigtable-client-core-parent/bigtable-hbase/src/main/java/org/apache/hadoop/hbase/client/AbstractBigtableAdmin.java +++ b/bigtable-client-core-parent/bigtable-hbase/src/main/java/org/apache/hadoop/hbase/client/AbstractBigtableAdmin.java @@ -354,13 +354,14 @@ public static byte[][] createSplitKeys(byte[] startKey, byte[] endKey, int numRe /** {@inheritDoc} */ @Override public void createTable(HTableDescriptor desc, byte[][] splitKeys) throws IOException { - createTable(desc.getTableName(), TableAdapter.adapt(desc, splitKeys)); + createTable(desc.getTableName(), TableAdapter.adapt(desc, splitKeys) + .toProto(bigtableInstanceName.toAdminInstanceName())); } - protected void createTable(TableName tableName, CreateTableRequest.Builder builder) throws IOException { - builder.setParent(bigtableInstanceName.toString()); + //TODO(rahulkql):update methods to adapt to v2.models.CreateTableRequest + protected void createTable(TableName tableName, CreateTableRequest request) throws IOException { try { - bigtableTableAdminClient.createTable(builder.build()); + bigtableTableAdminClient.createTable(request); } catch (Throwable throwable) { throw convertToTableExistsException(tableName, throwable); } @@ -370,14 +371,15 @@ protected void createTable(TableName tableName, CreateTableRequest.Builder build @Override public void createTableAsync(final HTableDescriptor desc, byte[][] splitKeys) throws IOException { LOG.warn("Creating the table synchronously"); - CreateTableRequest.Builder builder = TableAdapter.adapt(desc, splitKeys); - createTableAsync(builder, desc.getTableName()); + CreateTableRequest request = TableAdapter.adapt(desc, splitKeys) + .toProto(bigtableInstanceName.toAdminInstanceName()); + createTableAsync(request, desc.getTableName()); } - protected ListenableFuture createTableAsync(CreateTableRequest.Builder builder, + //TODO(rahulkql):update methods to adapt to v2.models.CreateTableRequest + protected ListenableFuture
createTableAsync(CreateTableRequest request, final TableName tableName) throws IOException { - builder.setParent(bigtableInstanceName.toString()); - ListenableFuture
future = bigtableTableAdminClient.createTableAsync(builder.build()); + ListenableFuture
future = bigtableTableAdminClient.createTableAsync(request); final SettableFuture
settableFuture = SettableFuture.create(); Futures.addCallback(future, new FutureCallback
() { @Override public void onSuccess(@Nullable Table result) { diff --git a/bigtable-client-core-parent/bigtable-hbase/src/test/java/com/google/cloud/bigtable/hbase/adapters/admin/TestColumnDescriptorAdapter.java b/bigtable-client-core-parent/bigtable-hbase/src/test/java/com/google/cloud/bigtable/hbase/adapters/admin/TestColumnDescriptorAdapter.java index 5cb049d503..17f7669a03 100644 --- a/bigtable-client-core-parent/bigtable-hbase/src/test/java/com/google/cloud/bigtable/hbase/adapters/admin/TestColumnDescriptorAdapter.java +++ b/bigtable-client-core-parent/bigtable-hbase/src/test/java/com/google/cloud/bigtable/hbase/adapters/admin/TestColumnDescriptorAdapter.java @@ -15,11 +15,9 @@ */ package com.google.cloud.bigtable.hbase.adapters.admin; -import static com.google.cloud.bigtable.hbase.adapters.admin.ColumnDescriptorAdapter.intersection; -import static com.google.cloud.bigtable.hbase.adapters.admin.ColumnDescriptorAdapter.maxAge; -import static com.google.cloud.bigtable.hbase.adapters.admin.ColumnDescriptorAdapter.maxVersions; -import static com.google.cloud.bigtable.hbase.adapters.admin.ColumnDescriptorAdapter.union; +import static com.google.cloud.bigtable.admin.v2.models.GCRules.GCRULES; +import com.google.cloud.bigtable.admin.v2.models.GCRules; import java.util.Map; import java.util.Set; @@ -36,7 +34,8 @@ import org.junit.runners.JUnit4; import com.google.bigtable.admin.v2.ColumnFamily; -import com.google.bigtable.admin.v2.GcRule; +import com.google.cloud.bigtable.admin.v2.models.GCRules.GCRule; +import org.threeten.bp.Duration; /** * Tests for {@link ColumnDescriptorAdapter}. @@ -44,13 +43,14 @@ @RunWith(JUnit4.class) public class TestColumnDescriptorAdapter { + private static final String FAMILY_NAME = "testFamily"; private ColumnDescriptorAdapter adapter; private HColumnDescriptor descriptor; @Before public void setup() { adapter = new ColumnDescriptorAdapter(); - descriptor = new HColumnDescriptor("testFamily"); + descriptor = new HColumnDescriptor(FAMILY_NAME); } @Rule @@ -114,14 +114,18 @@ public void ttlIsPreservedInGcRule() { int ttl = 86400; descriptor.setTimeToLive(ttl); ColumnFamily result = adapter.adapt(descriptor); - Assert.assertEquals(union(maxAge(ttl), maxVersions(1)), result.getGcRule()); + GCRules.GCRule expected = GCRULES.union().rule(GCRULES.maxAge(Duration.ofSeconds(ttl))) + .rule(GCRULES.maxVersions(1)); + Assert.assertEquals(expected.toProto(), result.getGcRule()); } @Test public void ttlIsPreservedInColumnFamily() { // TTL of 1 day (in microseconds): + GCRules.GCRule expected = GCRULES.union().rule(GCRULES.maxAge(Duration.ofSeconds(86400))) + .rule(GCRULES.maxVersions(1)); HColumnDescriptor descriptor = - adapter.adapt("family", columnFamily(union(maxAge(86400), maxVersions(1)))); + adapter.adapt("family", columnFamily(expected)); Assert.assertEquals(1, descriptor.getMaxVersions()); Assert.assertEquals(86400, descriptor.getTimeToLive()); } @@ -130,12 +134,14 @@ public void ttlIsPreservedInColumnFamily() { public void maxVersionsIsPreservedInGcExpression() { descriptor.setMaxVersions(10); ColumnFamily result = adapter.adapt(descriptor); - Assert.assertEquals(maxVersions(10), result.getGcRule()); + GCRules.GCRule expected = GCRULES.maxVersions(10); + Assert.assertEquals(expected.toProto(), result.getGcRule()); } @Test public void maxVersionsIsPreservedInColumnFamily() { - HColumnDescriptor descriptor = adapter.adapt("family", columnFamily(maxVersions(10))); + GCRules.GCRule expected = GCRULES.maxVersions(10); + HColumnDescriptor descriptor = adapter.adapt("family", columnFamily(expected)); Assert.assertEquals(10, descriptor.getMaxVersions()); } @@ -145,12 +151,13 @@ public void minMaxTtlInDescriptor() { descriptor.setMinVersions(10); descriptor.setTimeToLive(86400); // 1 day in seconds ColumnFamily result = adapter.adapt(descriptor); - Assert.assertEquals(minMaxRule(10, 86400, 20), result.getGcRule()); + Assert.assertEquals(minMaxRule(10, 86400, 20).toProto(), result.getGcRule()); } @Test public void minMaxTtlInColumnFamily() { - HColumnDescriptor descriptor = adapter.adapt("family", columnFamily(minMaxRule(10, 86400, 20))); + HColumnDescriptor descriptor = adapter.adapt("family", + columnFamily(minMaxRule(10, 86400, 20))); Assert.assertEquals(20, descriptor.getMaxVersions()); Assert.assertEquals(10, descriptor.getMinVersions()); Assert.assertEquals(86400, descriptor.getTimeToLive()); @@ -177,16 +184,38 @@ public void testBlankExpression(){ Assert.assertEquals(null, ColumnDescriptorAdapter.buildGarbageCollectionRule(descriptor)); } - private static ColumnFamily columnFamily(GcRule rule) { - return ColumnFamily.newBuilder().setGcRule(rule).build(); + @Test + public void testGCruleMaxVersion(){ + int ttl = 100; + descriptor.setTimeToLive(ttl); + descriptor.setMaxVersions(Integer.MAX_VALUE); + ColumnFamily result = adapter.adapt(descriptor); + GCRule expected = GCRULES.maxAge(Duration.ofSeconds(ttl)); + Assert.assertEquals(expected.toProto(), result.getGcRule()); + } + + @Test + public void testAdaptWithColumnFamilyForMaxAge(){ + int ttl = 86400; + GCRule maxAgeGCRule = GCRULES.maxAge(Duration.ofSeconds(ttl)); + ColumnFamily columnFamily = ColumnFamily.newBuilder().setGcRule(maxAgeGCRule.toProto()).build(); + HColumnDescriptor actual = adapter.adapt(FAMILY_NAME, columnFamily); + Assert.assertEquals(ttl, actual.getTimeToLive()); + } + + private static ColumnFamily columnFamily(GCRule rule) { + return ColumnFamily.newBuilder().setGcRule(rule.toProto()).build(); + } + + private GCRule minMaxRule(int minVersions, int ttl, int maxVersions) { + GCRule intersection = GCRULES.intersection().rule(GCRULES.maxAge(Duration.ofSeconds(ttl))) + .rule(GCRULES.maxVersions(minVersions)); + return GCRULES.union().rule(intersection).rule(GCRULES.maxVersions(maxVersions)); } - private GcRule minMaxRule(int minVersions, int ttl, int maxVersions) { - return union( - intersection( - maxAge(ttl), - maxVersions(minVersions) - ), - maxVersions(maxVersions)); + private GCRule minMaxIntersectionRule(int minVersions, int ttl, int maxVersions) { + GCRule intersection = GCRULES.intersection().rule(GCRULES.maxAge(Duration.ofSeconds(ttl))) + .rule(GCRULES.maxVersions(minVersions)); + return intersection; } } diff --git a/bigtable-client-core-parent/bigtable-hbase/src/test/java/com/google/cloud/bigtable/hbase/adapters/admin/TestTableAdapter.java b/bigtable-client-core-parent/bigtable-hbase/src/test/java/com/google/cloud/bigtable/hbase/adapters/admin/TestTableAdapter.java new file mode 100644 index 0000000000..27dfc5d20e --- /dev/null +++ b/bigtable-client-core-parent/bigtable-hbase/src/test/java/com/google/cloud/bigtable/hbase/adapters/admin/TestTableAdapter.java @@ -0,0 +1,117 @@ +/* + * Copyright 2018 Google Inc. All Rights Reserved. + * + * Licensed 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 com.google.cloud.bigtable.hbase.adapters.admin; + +import static com.google.cloud.bigtable.admin.v2.models.GCRules.GCRULES; +import com.google.bigtable.admin.v2.ColumnFamily; +import com.google.bigtable.admin.v2.InstanceName; +import com.google.bigtable.admin.v2.Table; +import com.google.cloud.bigtable.admin.v2.models.CreateTableRequest; +import com.google.cloud.bigtable.admin.v2.models.GCRules.GCRule; +import com.google.cloud.bigtable.grpc.BigtableInstanceName; +import org.apache.hadoop.hbase.HColumnDescriptor; +import org.apache.hadoop.hbase.HTableDescriptor; +import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.util.Bytes; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class TestTableAdapter { + + private static final String PROJECT_ID = "fakeProject"; + private static final String INSTANCE_ID = "fakeInstance"; + private static final String TABLE_ID = "myTable"; + private static final String INSTANCE_NAME = "projects/" + PROJECT_ID + "/instances/" + INSTANCE_ID; + private static final String TABLE_NAME = INSTANCE_NAME + "/tables/" + TABLE_ID; + private static final String COLUMN_FAMILY = "myColumnFamily"; + + private TableAdapter tableAdapter; + private InstanceName instanceName; + + @Before + public void setUp(){ + BigtableInstanceName bigtableInstanceName = new BigtableInstanceName(PROJECT_ID, INSTANCE_ID); + tableAdapter = new TableAdapter(bigtableInstanceName); + instanceName = InstanceName.of(PROJECT_ID, INSTANCE_ID); + } + + @Test + public void testAdaptWithHTableDescriptor(){ + byte[][] splits = new byte[][] { + Bytes.toBytes("AAA"), + Bytes.toBytes("BBB"), + Bytes.toBytes("CCC"), + }; + CreateTableRequest actualRequest = + TableAdapter.adapt(new HTableDescriptor(TableName.valueOf(TABLE_ID)), splits); + + CreateTableRequest expectedRequest = CreateTableRequest.of(TABLE_ID); + TableAdapter.addSplitKeys(splits, expectedRequest); + Assert.assertEquals( + expectedRequest.toProto(instanceName), + actualRequest.toProto(instanceName)); + } + + + @Test + public void testAdaptWithHTableDescriptorWhenSplitIsEmpty(){ + byte[][] splits = new byte[0][0]; + CreateTableRequest actualRequest = + TableAdapter.adapt(new HTableDescriptor(TableName.valueOf(TABLE_ID)), splits); + + CreateTableRequest expectedRequest = CreateTableRequest.of(TABLE_ID); + Assert.assertEquals( + expectedRequest.toProto(instanceName), + actualRequest.toProto(instanceName)); + } + + @Test + public void testAdaptWithColumnDesc(){ + HColumnDescriptor columnDesc = new HColumnDescriptor(COLUMN_FAMILY); + HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(TABLE_ID)); + CreateTableRequest request = CreateTableRequest.of(TABLE_ID); + desc.addFamily(columnDesc); + + TableAdapter.adapt(desc, request); + + GCRule gcRule = ColumnDescriptorAdapter.buildGarbageCollectionRule(columnDesc); + CreateTableRequest expected = + CreateTableRequest.of(TABLE_ID).addFamily(COLUMN_FAMILY, gcRule); + Assert.assertEquals(request.toProto(instanceName), expected.toProto(instanceName)); + } + + + @Test + public void testAdaptForTable(){ + //If no GcRule passed to ColumnFamily, then ColumnDescriptorAdapter#buildGarbageCollectionRule + //updates maxVersion to Integer.MAX_VALUE + GCRule gcRule = GCRULES.maxVersions(1); + ColumnFamily columnFamily = ColumnFamily.newBuilder() + .setGcRule(gcRule.toProto()).build(); + Table table = Table.newBuilder() + .setName(TABLE_NAME) + .putColumnFamilies(COLUMN_FAMILY, columnFamily).build(); + HTableDescriptor actualTableDesc = tableAdapter.adapt(table); + + HTableDescriptor expected = new HTableDescriptor(TableName.valueOf(TABLE_ID)); + expected.addFamily(new HColumnDescriptor(COLUMN_FAMILY)); + Assert.assertEquals(expected, actualTableDesc); + } +} diff --git a/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/com/google/cloud/bigtable/hbase2_x/BigtableAdmin.java b/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/com/google/cloud/bigtable/hbase2_x/BigtableAdmin.java index 58c065d90c..06288db4cf 100644 --- a/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/com/google/cloud/bigtable/hbase2_x/BigtableAdmin.java +++ b/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/com/google/cloud/bigtable/hbase2_x/BigtableAdmin.java @@ -72,7 +72,6 @@ import com.google.cloud.bigtable.hbase2_x.adapters.admin.TableAdapter2x; import com.google.common.util.concurrent.Futures; - /** * HBase 2.x specific implementation of {@link AbstractBigtableAdmin}. * @author spollapally @@ -100,11 +99,11 @@ public void createTable(TableDescriptor desc, byte[] startKey, byte[] endKey, in createTable(desc, createSplitKeys(startKey, endKey, numRegions)); } - /** {@inheritDoc} */ @Override public void createTable(TableDescriptor desc, byte[][] splitKeys) throws IOException { - createTable(desc.getTableName(), TableAdapter2x.adapt(desc, splitKeys)); + createTable(desc.getTableName(), TableAdapter2x.adapt(desc, splitKeys) + .toProto(bigtableInstanceName.toAdminInstanceName())); } /** {@inheritDoc} */ @@ -358,7 +357,6 @@ public Future modifyTableAsync(TableName tableName, TableDescriptor newDes }); } - /* (non-Javadoc) * @see org.apache.hadoop.hbase.client.Admin#truncateTableAsync(org.apache.hadoop.hbase.TableName, boolean) */ @@ -787,4 +785,4 @@ public Future updateReplicationPeerConfigAsync(String s, ReplicationPeerConfig replicationPeerConfig) { throw new UnsupportedOperationException("updateReplicationPeerConfigAsync"); // TODO } -} \ No newline at end of file +} diff --git a/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/com/google/cloud/bigtable/hbase2_x/BigtableAsyncAdmin.java b/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/com/google/cloud/bigtable/hbase2_x/BigtableAsyncAdmin.java index b65c957765..e120ca5c8a 100644 --- a/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/com/google/cloud/bigtable/hbase2_x/BigtableAsyncAdmin.java +++ b/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/com/google/cloud/bigtable/hbase2_x/BigtableAsyncAdmin.java @@ -15,6 +15,8 @@ */ package com.google.cloud.bigtable.hbase2_x; +import static com.google.cloud.bigtable.hbase2_x.FutureUtils.failedFuture; + import com.google.bigtable.admin.v2.CreateTableFromSnapshotRequest; import com.google.bigtable.admin.v2.CreateTableRequest; import com.google.bigtable.admin.v2.DeleteSnapshotRequest; @@ -83,8 +85,6 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; -import static com.google.cloud.bigtable.hbase2_x.FutureUtils.failedFuture; - /** * Bigtable implementation of {@link AsyncAdmin} * @@ -127,9 +127,9 @@ public CompletableFuture createTable(TableDescriptor desc, byte[][] splitK return failedFuture(new IllegalArgumentException("TableName cannot be null")); } - CreateTableRequest.Builder builder = TableAdapter2x.adapt(desc, splitKeys); - builder.setParent(bigtableInstanceName.toString()); - return bigtableTableAdminClient.createTableAsync(builder.build()) + CreateTableRequest request = TableAdapter2x.adapt(desc, splitKeys) + .toProto(bigtableInstanceName.toAdminInstanceName()); + return bigtableTableAdminClient.createTableAsync(request) .handle((resp, ex) -> { if (ex != null) { throw new CompletionException( @@ -617,7 +617,6 @@ public CompletableFuture> getRegions(TableName tableName) { }); } - private BigtableClusterName getSnapshotClusterName() throws IOException { if (bigtableSnapshotClusterName == null) { try { diff --git a/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/com/google/cloud/bigtable/hbase2_x/adapters/admin/TableAdapter2x.java b/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/com/google/cloud/bigtable/hbase2_x/adapters/admin/TableAdapter2x.java index a676a0a145..6110cdb95b 100644 --- a/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/com/google/cloud/bigtable/hbase2_x/adapters/admin/TableAdapter2x.java +++ b/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/com/google/cloud/bigtable/hbase2_x/adapters/admin/TableAdapter2x.java @@ -15,13 +15,9 @@ */ package com.google.cloud.bigtable.hbase2_x.adapters.admin; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import com.google.api.core.InternalApi; -import com.google.bigtable.admin.v2.CreateTableRequest; +import com.google.cloud.bigtable.admin.v2.models.CreateTableRequest; import com.google.cloud.bigtable.grpc.BigtableInstanceName; import org.apache.hadoop.hbase.HColumnDescriptor; import org.apache.hadoop.hbase.HTableDescriptor; @@ -29,37 +25,28 @@ import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor; import org.apache.hadoop.hbase.client.TableDescriptor; import org.apache.hadoop.hbase.client.TableDescriptorBuilder; -import org.apache.hadoop.hbase.util.Bytes; -import com.google.bigtable.admin.v2.ColumnFamily; import com.google.bigtable.admin.v2.Table; import com.google.cloud.bigtable.config.BigtableOptions; import com.google.cloud.bigtable.hbase.adapters.admin.ColumnDescriptorAdapter; import com.google.cloud.bigtable.hbase.adapters.admin.TableAdapter; /** - * Need this extended class as {@link TableAdapter#adapt(org.apache.hadoop.hbase.HTableDescriptor)} - * is not binary compatible with {@link TableAdapter2x#adapt(TableDescriptor)} + * Need this extended class as {@link TableAdapter#adapt(HTableDescriptor, CreateTableRequest)} + * is not binary compatible with {@link TableAdapter2x#adapt(TableDescriptor, byte[][])} * * Similarly, {@link ColumnDescriptorAdapter#adapt(HColumnDescriptor)} is not binary compatible with * {@link ColumnFamilyDescriptor}. * * @author spollapally */ +@InternalApi public class TableAdapter2x { protected static final ColumnDescriptorAdapter columnDescriptorAdapter = new ColumnDescriptorAdapter(); - public static CreateTableRequest.Builder adapt(TableDescriptor desc, byte[][] splitKeys) { + public static CreateTableRequest adapt(TableDescriptor desc, byte[][] splitKeys) { return TableAdapter.adapt(new HTableDescriptor(desc), splitKeys); } - public static Table adapt(TableDescriptor desc) { - return adapt(new HTableDescriptor(desc), null).getTable(); - } - - public static ColumnFamily toColumnFamily(ColumnFamilyDescriptor column) { - return columnDescriptorAdapter.adapt(toHColumnDescriptor(column)); - } - public static HColumnDescriptor toHColumnDescriptor(ColumnFamilyDescriptor column) { TableDescriptor desc = TableDescriptorBuilder.newBuilder(TableName.valueOf("N_A")).setColumnFamily(column) diff --git a/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/test/java/com/google/cloud/bigtable/hbase/com/google/cloud/bigtable/hbase2_x/adapters/admin/TestTableAdapter2x.java b/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/test/java/com/google/cloud/bigtable/hbase/com/google/cloud/bigtable/hbase2_x/adapters/admin/TestTableAdapter2x.java new file mode 100644 index 0000000000..fafdee6402 --- /dev/null +++ b/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/test/java/com/google/cloud/bigtable/hbase/com/google/cloud/bigtable/hbase2_x/adapters/admin/TestTableAdapter2x.java @@ -0,0 +1,104 @@ +/* + * Copyright 2018 Google Inc. All Rights Reserved. + * + * Licensed 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 com.google.cloud.bigtable.hbase.com.google.cloud.bigtable.hbase2_x.adapters.admin; + +import static com.google.cloud.bigtable.admin.v2.models.GCRules.GCRULES; + +import com.google.bigtable.admin.v2.ColumnFamily; +import com.google.bigtable.admin.v2.InstanceName; +import com.google.bigtable.admin.v2.Table; +import com.google.cloud.bigtable.admin.v2.models.CreateTableRequest; +import com.google.cloud.bigtable.admin.v2.models.GCRules; +import com.google.cloud.bigtable.config.BigtableOptions; +import com.google.cloud.bigtable.hbase.adapters.admin.TableAdapter; +import com.google.cloud.bigtable.hbase2_x.adapters.admin.TableAdapter2x; +import org.apache.hadoop.hbase.HColumnDescriptor; +import org.apache.hadoop.hbase.HTableDescriptor; +import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.client.*; +import org.apache.hadoop.hbase.util.Bytes; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class TestTableAdapter2x { + + private static final String PROJECT_ID = "fakeProject"; + private static final String INSTANCE_ID = "fakeInstance"; + private static final String TABLE_ID = "myTable"; + private static final String INSTANCE_NAME = "projects/" + PROJECT_ID + "/instances/" + INSTANCE_ID; + private static final String TABLE_NAME = INSTANCE_NAME + "/tables/" + TABLE_ID; + private static final String COLUMN_FAMILY = "myColumnFamily"; + + private TableAdapter2x tableAdapter2x; + private InstanceName instanceName; + + @Before + public void setUp(){ + BigtableOptions bigtableOptions = BigtableOptions.builder().setProjectId(PROJECT_ID) + .setInstanceId(INSTANCE_ID).build(); + tableAdapter2x = new TableAdapter2x(bigtableOptions); + instanceName = InstanceName.of(PROJECT_ID, INSTANCE_ID); + } + + @Test + public void testAdaptWithSplitKeys(){ + byte[][] splits = new byte[][] { + Bytes.toBytes("AAA"), + Bytes.toBytes("BBB"), + Bytes.toBytes("CCC"), + }; + TableDescriptor desc = TableDescriptorBuilder.newBuilder(TableName.valueOf(TABLE_ID)).build(); + CreateTableRequest actualRequest = TableAdapter2x.adapt(desc, splits); + + CreateTableRequest expectedRequest = CreateTableRequest.of(TABLE_ID); + TableAdapter.addSplitKeys(splits, expectedRequest); + Assert.assertEquals( + expectedRequest.toProto(instanceName), + actualRequest.toProto(instanceName)); + } + + @Test + public void testAdaptWithTable(){ + //If no GcRule passed to ColumnFamily, then ColumnDescriptorAdapter#buildGarbageCollectionRule + //updates maxVersion to Integer.MAX_VALUE + int maxVersion = 1; + GCRules.GCRule gcRule = GCRULES.maxVersions(maxVersion); + ColumnFamily columnFamily = ColumnFamily.newBuilder() + .setGcRule(gcRule.toProto()).build(); + Table table = Table.newBuilder() + .setName(TABLE_NAME) + .putColumnFamilies(COLUMN_FAMILY, columnFamily).build(); + TableDescriptor actualTableDesc = tableAdapter2x.adapt(table); + + TableDescriptor expected = new HTableDescriptor(TableName.valueOf(TABLE_ID)) + .addFamily(new HColumnDescriptor(COLUMN_FAMILY)); + + Assert.assertEquals(expected, actualTableDesc); + } + + @Test + public void testHColumnDescriptorAdapter(){ + ColumnFamilyDescriptor columnFamilyDesc = ColumnFamilyDescriptorBuilder.of(COLUMN_FAMILY); + HColumnDescriptor actualDesc = TableAdapter2x.toHColumnDescriptor(columnFamilyDesc); + HColumnDescriptor columnDes = new HColumnDescriptor(COLUMN_FAMILY); + + Assert.assertEquals(columnDes, actualDesc); + } +}