From a31bf6db6b48bdb9b864cf3ae549afe13378ef94 Mon Sep 17 00:00:00 2001 From: Rahul Kesharawni Date: Wed, 24 Oct 2018 18:56:36 +0530 Subject: [PATCH 1/9] static method for BigtableDataSettings creation only adding fromBigtableOptions static method adding separate methods for each settings Added check for retry & remvoed unneeded setter --- .../hbase/BigtableDataSettingsFactory.java | 276 ++++++++++++++++++ .../TestBigtableDataSettingsFactory.java | 194 ++++++++++++ 2 files changed, 470 insertions(+) create mode 100644 bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BigtableDataSettingsFactory.java create mode 100644 bigtable-client-core-parent/bigtable-hbase/src/test/java/com/google/cloud/bigtable/hbase/TestBigtableDataSettingsFactory.java diff --git a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BigtableDataSettingsFactory.java b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BigtableDataSettingsFactory.java new file mode 100644 index 0000000000..d2224a6421 --- /dev/null +++ b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BigtableDataSettingsFactory.java @@ -0,0 +1,276 @@ +/* + * 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; + +import static com.google.api.client.util.Preconditions.checkState; +import static org.threeten.bp.Duration.ofMillis; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.security.GeneralSecurityException; + +import org.apache.hadoop.conf.Configuration; +import org.threeten.bp.Duration; + +import com.google.api.gax.batching.BatchingSettings; +import com.google.api.gax.batching.FlowControlSettings; +import com.google.api.gax.core.CredentialsProvider; +import com.google.api.gax.core.FixedCredentialsProvider; +import com.google.api.gax.core.NoCredentialsProvider; +import com.google.api.gax.grpc.GrpcTransportChannel; +import com.google.api.gax.retrying.RetrySettings; +import com.google.api.gax.rpc.FixedTransportChannelProvider; +import com.google.cloud.bigtable.config.BigtableOptions; +import com.google.cloud.bigtable.config.BulkOptions; +import com.google.cloud.bigtable.config.CredentialFactory; +import com.google.cloud.bigtable.config.CredentialOptions; +import com.google.cloud.bigtable.config.Logger; +import com.google.cloud.bigtable.config.RetryOptions; +import com.google.cloud.bigtable.data.v2.BigtableDataSettings; +import com.google.cloud.bigtable.data.v2.BigtableDataSettings.Builder; +import com.google.cloud.bigtable.data.v2.models.InstanceName; +import com.google.cloud.bigtable.data.v2.stub.BigtableStubSettings; + +import io.grpc.ManagedChannelBuilder; + +/** + * Static methods to convert an instance of {@link Configuration} or {@link BigtableOptions} to a + * {@link BigtableDataSettings} instance. + */ +public class BigtableDataSettingsFactory { + /** Constant LOG */ + private static final Logger LOG = new Logger(BigtableDataSettingsFactory.class); + + /** + * To create an instance of {@link BigtableDataSettings} from {@link BigtableOptions}. + * + * @param configuration a {@link BigtableOptions} object. + * @return a {@link BigtableDataSettings} object. + * @throws IOException if any. + */ + public static BigtableDataSettings fromBigtableOptions(final BigtableOptions options) + throws IOException, GeneralSecurityException { + checkState(options.getProjectId() != null, "Project ID is required"); + checkState(options.getInstanceId() != null, "Instance ID is required"); + checkState(options.getRetryOptions().enableRetries(), "Disabling retries is not currently supported."); + + BigtableDataSettings.Builder builder = BigtableDataSettings.newBuilder(); + + InstanceName instanceName = InstanceName.newBuilder().setProject(options.getProjectId()) + .setInstance(options.getInstanceId()).build(); + builder.setInstanceName(instanceName); + builder.setAppProfileId(options.getAppProfileId()); + + builder.setEndpoint(options.getDataHost() + ":" + options.getPort()); + + buildCredentialProviderSettings(builder, options.getCredentialOptions()); + + buildBulkMutationsSettings(builder, options); + + buildCheckAndMutateRowSettings(builder, options.getCallOptionsConfig().getShortRpcTimeoutMs()); + + buildReadModifyWriteSettings(builder, options.getCallOptionsConfig().getShortRpcTimeoutMs()); + + buildReadRowsSettings(builder, options); + + buildMutateRowSettings(builder, options); + + buildSampleRowKeysSettings(builder, options); + + // TODO: implementation for channelCount or channelPerCPU + ManagedChannelBuilder channelBuilder = ManagedChannelBuilder + .forAddress(options.getDataHost(), options.getPort()) + .userAgent(options.getUserAgent()); + + if (options.usePlaintextNegotiation()) { + channelBuilder.usePlaintext(); + } + + builder.setTransportChannelProvider( + FixedTransportChannelProvider.create(GrpcTransportChannel.create(channelBuilder.build()))); + + return builder.build(); + } + + /** + * This method is use to build BatchSettings. + * + * @param builder a {@link BigtableDataSettings.Builder} object. + * @param options a {@link BigtableOptions} object. + */ + private static void buildBulkMutationsSettings(Builder builder, BigtableOptions options) { + BulkOptions bulkOptions = options.getBulkOptions(); + BatchingSettings.Builder batchSettingsBuilder = BatchingSettings.newBuilder(); + + long autoFlushMs = bulkOptions.getAutoflushMs(); + long bulkMaxRowKeyCount = bulkOptions.getBulkMaxRowKeyCount(); + long maxInflightRpcs = bulkOptions.getMaxInflightRpcs(); + + if (autoFlushMs > 0) { + batchSettingsBuilder.setDelayThreshold(Duration.ofMillis(autoFlushMs)); + } + FlowControlSettings.Builder flowControlBuilder = FlowControlSettings.newBuilder(); + if (maxInflightRpcs > 0) { + flowControlBuilder + .setMaxOutstandingRequestBytes(bulkOptions.getMaxMemory()) + .setMaxOutstandingElementCount(maxInflightRpcs * bulkMaxRowKeyCount); + } + + batchSettingsBuilder + .setIsEnabled(bulkOptions.useBulkApi()) + .setElementCountThreshold(Long.valueOf(bulkOptions.getBulkMaxRowKeyCount())) + .setRequestByteThreshold(bulkOptions.getBulkMaxRequestSize()) + .setFlowControlSettings(flowControlBuilder.build()); + + // TODO: implement bulkMutationThrottling & bulkMutationRpcTargetMs, once available + builder.bulkMutationsSettings() + .setBatchingSettings(batchSettingsBuilder.build()) + .setSimpleTimeoutNoRetries( + ofMillis(options.getCallOptionsConfig().getShortRpcTimeoutMs())); + } + + /** + * To build sampleRowKey with default Settings based on retries setting. + * + * @param builder a {@link BigtableDataSettings.Builder} object. + * @param bulkMutation a {@link BulkOptions} object. + */ + private static void buildSampleRowKeysSettings(Builder builder, BigtableOptions options) { + builder.sampleRowKeysSettings() + .setRetrySettings(buildIdempotentRetrySettings(options)); + } + + /** + * To build mutateRowSettings with default Settings based on retries setting. + * + * @param builder a {@link BigtableDataSettings.Builder} object. + * @param bulkMutation a {@link BulkOptions} object. + */ + private static void buildMutateRowSettings(Builder builder, BigtableOptions options) { + builder.mutateRowSettings() + .setRetrySettings(buildIdempotentRetrySettings(options)); + } + + /** + * To build readRows with default Settings based on retries setting. + * + * @param builder a {@link BigtableDataSettings.Builder} object. + * @param bulkMutation a {@link BulkOptions} object. + */ + private static void buildReadRowsSettings(Builder builder, BigtableOptions options) { + RetryOptions retryOptions = options.getRetryOptions(); + + RetrySettings.Builder retryBuilder = RetrySettings.newBuilder() + .setInitialRetryDelay(ofMillis(retryOptions.getInitialBackoffMillis())) + .setRetryDelayMultiplier(retryOptions.getBackoffMultiplier()) + .setMaxRetryDelay(ofMillis(retryOptions.getMaxElapsedBackoffMillis())) + .setMaxAttempts(retryOptions.getMaxScanTimeoutRetries()); + + // configurations for RPC timeouts + Duration readPartialRowTimeout = ofMillis(retryOptions.getReadPartialRowTimeoutMillis()); + retryBuilder + .setInitialRpcTimeout(readPartialRowTimeout) + .setMaxRpcTimeout(readPartialRowTimeout) + .setTotalTimeout(ofMillis(options.getCallOptionsConfig().getLongRpcTimeoutMs())); + + builder.readRowsSettings() + .setRetrySettings(retryBuilder.build()); + } + + /** + * This method builds ReadModifyWrite with no retry configurations + * + * @param builder a {@link BigtableDataSettings.Builder} object. + * @param bulkMutation a {@link BulkOptions} object. + */ + private static void buildReadModifyWriteSettings(Builder builder, long rpcTimeoutMs) { + builder.readModifyWriteRowSettings() + .setSimpleTimeoutNoRetries(ofMillis(rpcTimeoutMs)); + } + + /** + * This method builds CheckAndMutateRow with no retry configurations + * + * @param builder a {@link BigtableDataSettings.Builder} object. + * @param bulkMutation a {@link BulkOptions} object. + */ + private static void buildCheckAndMutateRowSettings(Builder builder, long rpcTimeoutMs) { + builder.checkAndMutateRowSettings() + .setSimpleTimeoutNoRetries(ofMillis(rpcTimeoutMs)); + } + + /** + * To create default RetrySettings, for BigtableDataSettings. + * + * @param builder a {@link BigtableDataSettings.Builder} object. + * @param bulkMutation a {@link BulkOptions} object. + */ + private static RetrySettings buildIdempotentRetrySettings(BigtableOptions options) { + RetryOptions retryOptions = options.getRetryOptions(); + + RetrySettings.Builder retryBuilder = RetrySettings.newBuilder() + .setInitialRetryDelay(ofMillis(retryOptions.getInitialBackoffMillis())) + .setRetryDelayMultiplier(retryOptions.getBackoffMultiplier()) + .setMaxRetryDelay(ofMillis(retryOptions.getMaxElapsedBackoffMillis())) + .setMaxAttempts(retryOptions.getMaxScanTimeoutRetries()); + + // configurations for RPC timeouts + Duration shortRpcTimeout = ofMillis(options.getCallOptionsConfig().getShortRpcTimeoutMs()); + retryBuilder + .setInitialRpcTimeout(shortRpcTimeout) + .setMaxRpcTimeout(shortRpcTimeout) + .setTotalTimeout(ofMillis(options.getCallOptionsConfig().getLongRpcTimeoutMs())); + + if (retryOptions.allowRetriesWithoutTimestamp()) { + //TODO: add instruction to create unsafeMutation. + LOG.warn("Retries without Timestamp doesn't support"); + } + return retryBuilder.build(); + } + + /** + * To create CredentialProvider based on CredentialType of BigtableOptions + * + * @param builder + * @param credentialOptions + * @throws FileNotFoundException + * @throws IOException + */ + private static void buildCredentialProviderSettings(Builder builder, CredentialOptions credentialOptions) + throws FileNotFoundException, IOException { + CredentialsProvider credentialsProvider = NoCredentialsProvider.create(); + + switch (credentialOptions.getCredentialType()) { + case DefaultCredentials: + credentialsProvider = BigtableStubSettings.defaultCredentialsProviderBuilder().build(); + break; + case P12: + case SuppliedCredentials: + case SuppliedJson: + credentialsProvider = FixedCredentialsProvider.create(CredentialFactory + .getInputStreamCredential(new FileInputStream(CredentialOptions.getEnvJsonFile()))); + break; + case None: + credentialsProvider = NoCredentialsProvider.create(); + break; + default: + throw new IllegalStateException("Either service account or null credentials must be enabled"); + } + LOG.debug("CredentialsProvider used is: %s", credentialsProvider); + builder.setCredentialsProvider(credentialsProvider); + } +} diff --git a/bigtable-client-core-parent/bigtable-hbase/src/test/java/com/google/cloud/bigtable/hbase/TestBigtableDataSettingsFactory.java b/bigtable-client-core-parent/bigtable-hbase/src/test/java/com/google/cloud/bigtable/hbase/TestBigtableDataSettingsFactory.java new file mode 100644 index 0000000000..6a3c166fd9 --- /dev/null +++ b/bigtable-client-core-parent/bigtable-hbase/src/test/java/com/google/cloud/bigtable/hbase/TestBigtableDataSettingsFactory.java @@ -0,0 +1,194 @@ +/* + * 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; + +import static com.google.cloud.bigtable.config.CallOptionsConfig.LONG_TIMEOUT_MS_DEFAULT; +import static com.google.cloud.bigtable.config.CallOptionsConfig.SHORT_TIMEOUT_MS_DEFAULT; +import static com.google.cloud.bigtable.config.RetryOptions.DEFAULT_BACKOFF_MULTIPLIER; +import static com.google.cloud.bigtable.config.RetryOptions.DEFAULT_INITIAL_BACKOFF_MILLIS; +import static com.google.cloud.bigtable.config.RetryOptions.DEFAULT_MAX_ELAPSED_BACKOFF_MILLIS; +import static com.google.cloud.bigtable.config.RetryOptions.DEFAULT_MAX_SCAN_TIMEOUT_RETRIES; +import static com.google.cloud.bigtable.hbase.TestBigtableOptionsFactory.TEST_INSTANCE_ID; +import static com.google.cloud.bigtable.hbase.TestBigtableOptionsFactory.TEST_PROJECT_ID; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.util.Set; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.threeten.bp.Duration; + +import com.google.api.gax.batching.BatchingSettings; +import com.google.api.gax.core.NoCredentialsProvider; +import com.google.api.gax.retrying.RetrySettings; +import com.google.api.gax.rpc.StatusCode.Code; +import com.google.cloud.bigtable.config.BigtableOptions; +import com.google.cloud.bigtable.config.BulkOptions; +import com.google.cloud.bigtable.config.CredentialOptions; +import com.google.cloud.bigtable.config.RetryOptions; +import com.google.cloud.bigtable.data.v2.BigtableDataSettings; +import com.google.common.collect.ImmutableSet; + +@RunWith(JUnit4.class) +public class TestBigtableDataSettingsFactory { + + private static final String TEST_USER_AGENT = "sampleUserAgent"; + private static final Set DEFAULT_RETRY_CODES = + ImmutableSet.of(Code.DEADLINE_EXCEEDED, Code.UNAVAILABLE, Code.ABORTED); + + @Rule + public ExpectedException expectException = ExpectedException.none(); + + private BigtableOptions bigtableOptions; + + @Before + public void setup() { + bigtableOptions = BigtableOptions.builder() + .setProjectId(TEST_PROJECT_ID).setInstanceId(TEST_INSTANCE_ID) + .build(); + } + + @Test + public void testProjectIdIsRequired() throws IOException, GeneralSecurityException { + BigtableOptions options = BigtableOptions.builder().build(); + + expectException.expect(IllegalStateException.class); + expectException.expectMessage("Project ID is required"); + BigtableDataSettingsFactory.fromBigtableOptions(options); + } + + @Test + public void testInstanceIdIsRequired() throws IOException, GeneralSecurityException { + BigtableOptions options = BigtableOptions.builder().setProjectId(TEST_PROJECT_ID).build(); + + expectException.expect(IllegalStateException.class); + expectException.expectMessage("Instance ID is required"); + BigtableDataSettingsFactory.fromBigtableOptions(options); + } + + @Test + public void testWhenRetriesAreDisabled() throws IOException, GeneralSecurityException { + RetryOptions retryOptions = RetryOptions.builder().setEnableRetries(false).build(); + BigtableOptions options = + BigtableOptions.builder() + .setProjectId(TEST_PROJECT_ID).setInstanceId(TEST_INSTANCE_ID) + .setRetryOptions(retryOptions).build(); + + expectException.expect(IllegalStateException.class); + expectException.expectMessage("Disabling retries is not currently supported."); + BigtableDataSettingsFactory.fromBigtableOptions(options); + } + + @Test + public void testWithNullCredentials() throws IOException, GeneralSecurityException { + BigtableOptions options = + BigtableOptions.builder() + .setProjectId(TEST_PROJECT_ID).setInstanceId(TEST_INSTANCE_ID) + .setCredentialOptions(CredentialOptions.nullCredential()) + .setUserAgent(TEST_USER_AGENT).build(); + BigtableDataSettings settings = BigtableDataSettingsFactory.fromBigtableOptions(options); + Assert.assertTrue(settings.getCredentialsProvider() instanceof NoCredentialsProvider); + } + + @Test + public void testRetrySettings() throws IOException, GeneralSecurityException { + BigtableDataSettings settings = BigtableDataSettingsFactory.fromBigtableOptions(bigtableOptions); + + //Verifying RetrySettings for sampleRowKey, mutateRow & readRowSettings + verifyRetry(settings.sampleRowKeysSettings().getRetrySettings()); + verifyRetry(settings.readRowsSettings().getRetrySettings()); + verifyRetry(settings.mutateRowSettings().getRetrySettings()); + + //Verifying RetrySettings & RetryCodes of non-retryable methods. + verifyDisabledRetry(settings.bulkMutationsSettings().getRetrySettings()); + verifyDisabledRetry(settings.readModifyWriteRowSettings().getRetrySettings()); + verifyDisabledRetry(settings.checkAndMutateRowSettings().getRetrySettings()); + } + + private void verifyRetry(RetrySettings retrySettings) { + assertEquals(DEFAULT_INITIAL_BACKOFF_MILLIS, retrySettings.getInitialRetryDelay().toMillis()); + assertEquals(DEFAULT_BACKOFF_MULTIPLIER,retrySettings.getRetryDelayMultiplier(), 0); + assertEquals(DEFAULT_MAX_ELAPSED_BACKOFF_MILLIS, retrySettings.getMaxRetryDelay().toMillis()); + assertEquals(DEFAULT_MAX_SCAN_TIMEOUT_RETRIES, retrySettings.getMaxAttempts()); + assertEquals(SHORT_TIMEOUT_MS_DEFAULT, retrySettings.getInitialRpcTimeout().toMillis()); + assertEquals(SHORT_TIMEOUT_MS_DEFAULT, retrySettings.getMaxRpcTimeout().toMillis()); + assertEquals(LONG_TIMEOUT_MS_DEFAULT, retrySettings.getTotalTimeout().toMillis()); + } + + private void verifyDisabledRetry(RetrySettings ret) { + assertEquals(Duration.ZERO , ret.getInitialRetryDelay()); + assertEquals(1.0 , ret.getRetryDelayMultiplier(), 0); + assertEquals(Duration.ZERO, ret.getMaxRetryDelay()); + assertEquals(1, ret.getMaxAttempts()); + assertEquals(SHORT_TIMEOUT_MS_DEFAULT, ret.getInitialRpcTimeout().toMillis()); + assertEquals(SHORT_TIMEOUT_MS_DEFAULT, ret.getMaxRpcTimeout().toMillis()); + assertEquals(SHORT_TIMEOUT_MS_DEFAULT, ret.getTotalTimeout().toMillis()); + } + + @Test + public void testRetryCodes() throws IOException, GeneralSecurityException { + BigtableDataSettings settings = BigtableDataSettingsFactory.fromBigtableOptions(bigtableOptions); + + assertEquals(DEFAULT_RETRY_CODES, settings.sampleRowKeysSettings().getRetryableCodes()); + assertEquals(DEFAULT_RETRY_CODES, settings.readRowsSettings().getRetryableCodes()); + + assertEquals(ImmutableSet.of(Code.DEADLINE_EXCEEDED, Code.UNAVAILABLE), + settings.mutateRowSettings().getRetryableCodes()); + + assertTrue(settings.bulkMutationsSettings().getRetryableCodes().isEmpty()); + assertTrue(settings.readModifyWriteRowSettings().getRetryableCodes().isEmpty()); + assertTrue(settings.checkAndMutateRowSettings().getRetryableCodes().isEmpty()); + } + + @Test + public void testWhenBulkOptionIsDisabled() throws IOException, GeneralSecurityException { + BulkOptions bulkOptions = BulkOptions.builder().setUseBulkApi(false).build(); + BigtableOptions options = BigtableOptions.builder().setProjectId(TEST_PROJECT_ID) + .setInstanceId(TEST_INSTANCE_ID).setBulkOptions(bulkOptions) + .build(); + BigtableDataSettings dataSettings = BigtableDataSettingsFactory.fromBigtableOptions(options); + assertFalse(dataSettings.bulkMutationsSettings().getBatchingSettings().getIsEnabled()); + } + + @Test + public void testBulkOption() throws IOException, GeneralSecurityException { + BigtableOptions options = BigtableOptions.builder().setProjectId(TEST_PROJECT_ID) + .setInstanceId(TEST_INSTANCE_ID).build(); + BigtableDataSettings dataSettings = BigtableDataSettingsFactory.fromBigtableOptions(options); + + BulkOptions bulkOptions = options.getBulkOptions(); + BatchingSettings batchingSettings = dataSettings.bulkMutationsSettings().getBatchingSettings(); + long outstandingElementCount = bulkOptions.getMaxInflightRpcs() * bulkOptions.getBulkMaxRowKeyCount(); + assertTrue(batchingSettings.getIsEnabled()); + assertEquals(bulkOptions.getBulkMaxRequestSize(), + batchingSettings.getRequestByteThreshold().longValue()); + assertEquals(bulkOptions.getBulkMaxRowKeyCount(), + batchingSettings.getElementCountThreshold().longValue()); + assertEquals(bulkOptions.getMaxMemory(), + batchingSettings.getFlowControlSettings().getMaxOutstandingRequestBytes().longValue()); + assertEquals(outstandingElementCount, + batchingSettings.getFlowControlSettings().getMaxOutstandingElementCount().longValue()); + } +} From 5e32f954ff855522b80ae8a1ebfb1d404ded53ee Mon Sep 17 00:00:00 2001 From: Rahul Kesharawni Date: Wed, 26 Dec 2018 16:13:41 +0530 Subject: [PATCH 2/9] Adding BigtableDataClient & BigtableAdminClient renamed Factory methods Reverted BulkMutationSettings changes refactored Credentail Provider --- .../BigtableVaneerSettingsFactory.java} | 220 +++++----- .../TestBigtableVaneerSettingsFactory.java | 414 ++++++++++++++++++ .../TestBigtableDataSettingsFactory.java | 194 -------- 3 files changed, 535 insertions(+), 293 deletions(-) rename bigtable-client-core-parent/{bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BigtableDataSettingsFactory.java => bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVaneerSettingsFactory.java} (51%) create mode 100644 bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestBigtableVaneerSettingsFactory.java delete mode 100644 bigtable-client-core-parent/bigtable-hbase/src/test/java/com/google/cloud/bigtable/hbase/TestBigtableDataSettingsFactory.java diff --git a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BigtableDataSettingsFactory.java b/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVaneerSettingsFactory.java similarity index 51% rename from bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BigtableDataSettingsFactory.java rename to bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVaneerSettingsFactory.java index d2224a6421..62ef3ce7ec 100644 --- a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BigtableDataSettingsFactory.java +++ b/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVaneerSettingsFactory.java @@ -13,71 +13,62 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.google.cloud.bigtable.hbase; - -import static com.google.api.client.util.Preconditions.checkState; -import static org.threeten.bp.Duration.ofMillis; - -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.security.GeneralSecurityException; - -import org.apache.hadoop.conf.Configuration; -import org.threeten.bp.Duration; +package com.google.cloud.bigtable.config; import com.google.api.gax.batching.BatchingSettings; import com.google.api.gax.batching.FlowControlSettings; import com.google.api.gax.core.CredentialsProvider; import com.google.api.gax.core.FixedCredentialsProvider; import com.google.api.gax.core.NoCredentialsProvider; -import com.google.api.gax.grpc.GrpcTransportChannel; +import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.rpc.FixedTransportChannelProvider; -import com.google.cloud.bigtable.config.BigtableOptions; -import com.google.cloud.bigtable.config.BulkOptions; -import com.google.cloud.bigtable.config.CredentialFactory; -import com.google.cloud.bigtable.config.CredentialOptions; -import com.google.cloud.bigtable.config.Logger; -import com.google.cloud.bigtable.config.RetryOptions; +import com.google.api.gax.rpc.FixedHeaderProvider; +import com.google.api.gax.rpc.HeaderProvider; +import com.google.auth.Credentials; +import com.google.cloud.bigtable.admin.v2.BigtableTableAdminSettings; import com.google.cloud.bigtable.data.v2.BigtableDataSettings; import com.google.cloud.bigtable.data.v2.BigtableDataSettings.Builder; -import com.google.cloud.bigtable.data.v2.models.InstanceName; -import com.google.cloud.bigtable.data.v2.stub.BigtableStubSettings; +import io.grpc.internal.GrpcUtil; +import java.io.IOException; +import java.security.GeneralSecurityException; +import javax.annotation.Nonnull; +import org.threeten.bp.Duration; -import io.grpc.ManagedChannelBuilder; +import static com.google.api.client.util.Preconditions.checkState; +import static com.google.cloud.bigtable.config.CallOptionsConfig.SHORT_TIMEOUT_MS_DEFAULT; +import static org.threeten.bp.Duration.ofMillis; /** - * Static methods to convert an instance of {@link Configuration} or {@link BigtableOptions} to a - * {@link BigtableDataSettings} instance. + * Static methods to convert an instance of {@link BigtableOptions} to a + * {@link BigtableDataSettings} or {@link BigtableTableAdminSettings} instance . */ -public class BigtableDataSettingsFactory { +public class BigtableVaneerSettingsFactory { + /** Constant LOG */ - private static final Logger LOG = new Logger(BigtableDataSettingsFactory.class); + private static final Logger LOG = new Logger(BigtableVaneerSettingsFactory.class); /** * To create an instance of {@link BigtableDataSettings} from {@link BigtableOptions}. * - * @param configuration a {@link BigtableOptions} object. + * @param options a {@link BigtableOptions} object. * @return a {@link BigtableDataSettings} object. * @throws IOException if any. */ - public static BigtableDataSettings fromBigtableOptions(final BigtableOptions options) - throws IOException, GeneralSecurityException { + public static BigtableDataSettings createBigtableDataSettings(@Nonnull final BigtableOptions options) throws IOException { checkState(options.getProjectId() != null, "Project ID is required"); checkState(options.getInstanceId() != null, "Instance ID is required"); checkState(options.getRetryOptions().enableRetries(), "Disabling retries is not currently supported."); - BigtableDataSettings.Builder builder = BigtableDataSettings.newBuilder(); + final BigtableDataSettings.Builder builder = BigtableDataSettings.newBuilder(); + final String endpoint = options.getDataHost() + ":" + options.getPort(); - InstanceName instanceName = InstanceName.newBuilder().setProject(options.getProjectId()) - .setInstance(options.getInstanceId()).build(); - builder.setInstanceName(instanceName); + builder.setProjectId(options.getProjectId()); + builder.setInstanceId(options.getInstanceId()); builder.setAppProfileId(options.getAppProfileId()); - builder.setEndpoint(options.getDataHost() + ":" + options.getPort()); + builder.setEndpoint(endpoint); - buildCredentialProviderSettings(builder, options.getCredentialOptions()); + builder.setCredentialsProvider(buildCredentialProvider(options.getCredentialOptions())); buildBulkMutationsSettings(builder, options); @@ -91,23 +82,58 @@ public static BigtableDataSettings fromBigtableOptions(final BigtableOptions opt buildSampleRowKeysSettings(builder, options); - // TODO: implementation for channelCount or channelPerCPU - ManagedChannelBuilder channelBuilder = ManagedChannelBuilder - .forAddress(options.getDataHost(), options.getPort()) - .userAgent(options.getUserAgent()); - - if (options.usePlaintextNegotiation()) { - channelBuilder.usePlaintext(); - } + String userAgent = BigtableVersionInfo.CORE_USER_AGENT + "," + options.getUserAgent(); + HeaderProvider headers = FixedHeaderProvider.create(GrpcUtil.USER_AGENT_KEY.name(), userAgent); builder.setTransportChannelProvider( - FixedTransportChannelProvider.create(GrpcTransportChannel.create(channelBuilder.build()))); + InstantiatingGrpcChannelProvider.newBuilder() + .setHeaderProvider(headers) + .setEndpoint(endpoint) + .setPoolSize(options.getChannelCount()) + .build()); return builder.build(); } /** - * This method is use to build BatchSettings. + * To create an instance of {@link BigtableTableAdminSettings} from {@link BigtableOptions}. + * + * @param options a {@link BigtableOptions} object. + * @return a {@link BigtableTableAdminSettings} object. + * @throws IOException if any. + */ + public static BigtableTableAdminSettings createTableAdminSettings(@Nonnull final BigtableOptions options) + throws IOException { + checkState(options.getProjectId() != null, "Project ID is required"); + checkState(options.getInstanceId() != null, "Instance ID is required"); + + final BigtableTableAdminSettings.Builder adminBuilder = BigtableTableAdminSettings.newBuilder(); + + adminBuilder.setProjectId(options.getProjectId()); + adminBuilder.setInstanceId(options.getInstanceId()); + + final String endpoint = options.getAdminHost() + ":" + options.getPort(); + adminBuilder.stubSettings().setEndpoint(endpoint); + + //Overriding default credential with BigtableOptions's credential. + adminBuilder.stubSettings() + .setCredentialsProvider(buildCredentialProvider(options.getCredentialOptions())); + + String userAgent = BigtableVersionInfo.CORE_USER_AGENT + "," + options.getUserAgent(); + HeaderProvider headers = FixedHeaderProvider.create(GrpcUtil.USER_AGENT_KEY.name(), userAgent); + + adminBuilder.stubSettings().setTransportChannelProvider( + InstantiatingGrpcChannelProvider.newBuilder() + .setHeaderProvider(headers) + .setEndpoint(endpoint) + .setPoolSize(options.getChannelCount()) + .build()); + + return adminBuilder.build(); + } + + /** + * This method is use to build {@link BatchingSettings}. * * @param builder a {@link BigtableDataSettings.Builder} object. * @param options a {@link BigtableOptions} object. @@ -119,15 +145,16 @@ private static void buildBulkMutationsSettings(Builder builder, BigtableOptions long autoFlushMs = bulkOptions.getAutoflushMs(); long bulkMaxRowKeyCount = bulkOptions.getBulkMaxRowKeyCount(); long maxInflightRpcs = bulkOptions.getMaxInflightRpcs(); + long shortRpcTimeoutMs = options.getCallOptionsConfig().getShortRpcTimeoutMs(); if (autoFlushMs > 0) { - batchSettingsBuilder.setDelayThreshold(Duration.ofMillis(autoFlushMs)); + batchSettingsBuilder.setDelayThreshold(ofMillis(autoFlushMs)); } FlowControlSettings.Builder flowControlBuilder = FlowControlSettings.newBuilder(); if (maxInflightRpcs > 0) { flowControlBuilder - .setMaxOutstandingRequestBytes(bulkOptions.getMaxMemory()) - .setMaxOutstandingElementCount(maxInflightRpcs * bulkMaxRowKeyCount); + .setMaxOutstandingRequestBytes(bulkOptions.getMaxMemory()) + .setMaxOutstandingElementCount(maxInflightRpcs * bulkMaxRowKeyCount); } batchSettingsBuilder @@ -136,18 +163,18 @@ private static void buildBulkMutationsSettings(Builder builder, BigtableOptions .setRequestByteThreshold(bulkOptions.getBulkMaxRequestSize()) .setFlowControlSettings(flowControlBuilder.build()); - // TODO: implement bulkMutationThrottling & bulkMutationRpcTargetMs, once available + // TODO(rahulkql): implement bulkMutationThrottling & bulkMutationRpcTargetMs, once available builder.bulkMutationsSettings() - .setBatchingSettings(batchSettingsBuilder.build()) - .setSimpleTimeoutNoRetries( - ofMillis(options.getCallOptionsConfig().getShortRpcTimeoutMs())); + .setBatchingSettings(batchSettingsBuilder.build()) + .setSimpleTimeoutNoRetries( + ofMillis(shortRpcTimeoutMs)); } /** - * To build sampleRowKey with default Settings based on retries setting. + * To build BigtableDataSettings#sampleRowKeysSettings with default retries settings. * * @param builder a {@link BigtableDataSettings.Builder} object. - * @param bulkMutation a {@link BulkOptions} object. + * @param options a {@link BigtableOptions} object. */ private static void buildSampleRowKeysSettings(Builder builder, BigtableOptions options) { builder.sampleRowKeysSettings() @@ -155,10 +182,10 @@ private static void buildSampleRowKeysSettings(Builder builder, BigtableOptions } /** - * To build mutateRowSettings with default Settings based on retries setting. + * To build BigtableDataSettings#mutateRowSettings with default retries settings. * * @param builder a {@link BigtableDataSettings.Builder} object. - * @param bulkMutation a {@link BulkOptions} object. + * @param options a {@link BigtableOptions} object. */ private static void buildMutateRowSettings(Builder builder, BigtableOptions options) { builder.mutateRowSettings() @@ -166,10 +193,10 @@ private static void buildMutateRowSettings(Builder builder, BigtableOptions opti } /** - * To build readRows with default Settings based on retries setting. + * To build BigtableDataSettings#readRowsSettings with default retries settings. * * @param builder a {@link BigtableDataSettings.Builder} object. - * @param bulkMutation a {@link BulkOptions} object. + * @param options a {@link BigtableOptions} object. */ private static void buildReadRowsSettings(Builder builder, BigtableOptions options) { RetryOptions retryOptions = options.getRetryOptions(); @@ -192,32 +219,38 @@ private static void buildReadRowsSettings(Builder builder, BigtableOptions optio } /** - * This method builds ReadModifyWrite with no retry configurations + * This method builds BigtableDataSettings#readModifyWriteSettngs when short timeout is other + * than 60_000 ms. * * @param builder a {@link BigtableDataSettings.Builder} object. - * @param bulkMutation a {@link BulkOptions} object. + * @param rpcTimeoutMs a long value for RPC timeout. */ private static void buildReadModifyWriteSettings(Builder builder, long rpcTimeoutMs) { - builder.readModifyWriteRowSettings() - .setSimpleTimeoutNoRetries(ofMillis(rpcTimeoutMs)); + if(rpcTimeoutMs != SHORT_TIMEOUT_MS_DEFAULT) { + builder.readModifyWriteRowSettings() + .setSimpleTimeoutNoRetries(ofMillis(rpcTimeoutMs)); + } } /** - * This method builds CheckAndMutateRow with no retry configurations + * This method builds BigtableDataSettings#checkAndMutateRowSettings when short timeout is other + * than 60_000 ms. * * @param builder a {@link BigtableDataSettings.Builder} object. - * @param bulkMutation a {@link BulkOptions} object. + * @param rpcTimeoutMs a long value for RPC timeout. */ private static void buildCheckAndMutateRowSettings(Builder builder, long rpcTimeoutMs) { - builder.checkAndMutateRowSettings() - .setSimpleTimeoutNoRetries(ofMillis(rpcTimeoutMs)); + if(rpcTimeoutMs != SHORT_TIMEOUT_MS_DEFAULT) { + builder.checkAndMutateRowSettings() + .setSimpleTimeoutNoRetries(ofMillis(rpcTimeoutMs)); + } } /** - * To create default RetrySettings, for BigtableDataSettings. + * To create default {@link RetrySettings} for all idempotent method. * - * @param builder a {@link BigtableDataSettings.Builder} object. - * @param bulkMutation a {@link BulkOptions} object. + * @param options a {@link BigtableOptions} object. + * @return an object of {@link RetrySettings} with idempotent method configuration. */ private static RetrySettings buildIdempotentRetrySettings(BigtableOptions options) { RetryOptions retryOptions = options.getRetryOptions(); @@ -234,43 +267,32 @@ private static RetrySettings buildIdempotentRetrySettings(BigtableOptions option .setInitialRpcTimeout(shortRpcTimeout) .setMaxRpcTimeout(shortRpcTimeout) .setTotalTimeout(ofMillis(options.getCallOptionsConfig().getLongRpcTimeoutMs())); - + if (retryOptions.allowRetriesWithoutTimestamp()) { - //TODO: add instruction to create unsafeMutation. - LOG.warn("Retries without Timestamp doesn't support"); + LOG.warn("Retries without Timestamp does not support yet."); } + return retryBuilder.build(); } /** - * To create CredentialProvider based on CredentialType of BigtableOptions + * To create {@link CredentialsProvider} based on {@link CredentialOptions}. * - * @param builder - * @param credentialOptions - * @throws FileNotFoundException - * @throws IOException + * @param credentialOptions a {@link CredentialOptions} object. + * @throws IOException if any. */ - private static void buildCredentialProviderSettings(Builder builder, CredentialOptions credentialOptions) - throws FileNotFoundException, IOException { - CredentialsProvider credentialsProvider = NoCredentialsProvider.create(); - - switch (credentialOptions.getCredentialType()) { - case DefaultCredentials: - credentialsProvider = BigtableStubSettings.defaultCredentialsProviderBuilder().build(); - break; - case P12: - case SuppliedCredentials: - case SuppliedJson: - credentialsProvider = FixedCredentialsProvider.create(CredentialFactory - .getInputStreamCredential(new FileInputStream(CredentialOptions.getEnvJsonFile()))); - break; - case None: - credentialsProvider = NoCredentialsProvider.create(); - break; - default: - throw new IllegalStateException("Either service account or null credentials must be enabled"); + private static CredentialsProvider buildCredentialProvider( + CredentialOptions credentialOptions) throws IOException { + try { + final Credentials credentials = CredentialFactory.getCredentials(credentialOptions); + if (credentials == null) { + LOG.info("Enabling the use of null credentials. This should not be used in production."); + return NoCredentialsProvider.create(); + } + + return FixedCredentialsProvider.create(credentials); + } catch (GeneralSecurityException exception) { + throw new IOException("Could not initialize credentials.", exception); } - LOG.debug("CredentialsProvider used is: %s", credentialsProvider); - builder.setCredentialsProvider(credentialsProvider); } } diff --git a/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestBigtableVaneerSettingsFactory.java b/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestBigtableVaneerSettingsFactory.java new file mode 100644 index 0000000000..35c665c806 --- /dev/null +++ b/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestBigtableVaneerSettingsFactory.java @@ -0,0 +1,414 @@ +/* + * 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.config; + +import com.google.api.gax.batching.BatchingSettings; +import com.google.api.gax.core.NoCredentialsProvider; +import com.google.api.gax.retrying.RetrySettings; +import com.google.api.gax.rpc.ServerStream; +import com.google.api.gax.rpc.StatusCode.Code; +import com.google.cloud.bigtable.admin.v2.BigtableTableAdminClient; +import com.google.cloud.bigtable.admin.v2.BigtableTableAdminSettings; +import com.google.cloud.bigtable.admin.v2.models.CreateTableRequest; +import com.google.cloud.bigtable.data.v2.BigtableDataClient; +import com.google.cloud.bigtable.data.v2.BigtableDataSettings; +import com.google.cloud.bigtable.data.v2.models.Mutation; +import com.google.cloud.bigtable.data.v2.models.Query; +import com.google.cloud.bigtable.data.v2.models.Row; +import com.google.cloud.bigtable.data.v2.models.RowCell; +import com.google.cloud.bigtable.data.v2.models.RowMutation; +import com.google.common.base.Strings; +import com.google.common.collect.ImmutableSet; +import com.google.protobuf.ByteString; +import java.io.IOException; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.TimeUnit; +import org.junit.After; +import org.junit.Assume; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.threeten.bp.Duration; + +import static com.google.cloud.bigtable.config.CallOptionsConfig.LONG_TIMEOUT_MS_DEFAULT; +import static com.google.cloud.bigtable.config.CallOptionsConfig.SHORT_TIMEOUT_MS_DEFAULT; +import static com.google.cloud.bigtable.config.RetryOptions.DEFAULT_BACKOFF_MULTIPLIER; +import static com.google.cloud.bigtable.config.RetryOptions.DEFAULT_INITIAL_BACKOFF_MILLIS; +import static com.google.cloud.bigtable.config.RetryOptions.DEFAULT_MAX_ELAPSED_BACKOFF_MILLIS; +import static com.google.cloud.bigtable.config.RetryOptions.DEFAULT_MAX_SCAN_TIMEOUT_RETRIES; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +@RunWith(JUnit4.class) +public class TestBigtableVaneerSettingsFactory { + + private static final Logger LOG = new Logger(TestBigtableVaneerSettingsFactory.class); + + private static final String ACTUAL_PROJECT_ID = System.getProperty("test.client.project.id"); + private static final String ACTUAL_INSTANCE_ID = System.getProperty("test.client.instance.id"); + + private static final String TEST_PROJECT_ID = "fakeProjectID"; + private static final String TEST_INSTANCE_ID = "fakeInstanceID"; + private static final String TEST_USER_AGENT = "sampleUserAgent"; + private static final int SHORT_TIMEOUT_MS = 30_000; + + /** + * RetryCodes for idempotent Rpcs. + */ + private static final Set DEFAULT_RETRY_CODES = + ImmutableSet.of(Code.DEADLINE_EXCEEDED, Code.UNAVAILABLE); + + private static final boolean endToEndArgMissing = + Strings.isNullOrEmpty(ACTUAL_PROJECT_ID) && Strings.isNullOrEmpty(ACTUAL_INSTANCE_ID); + + + @Rule + public ExpectedException expectException = ExpectedException.none(); + + private BigtableOptions bigtableOptions = BigtableOptions.builder() + .setProjectId(TEST_PROJECT_ID) + .setInstanceId(TEST_INSTANCE_ID) + .setUserAgent(TEST_USER_AGENT) + .setAdminHost("localhost") + .setDataHost("localhost") + .setCredentialOptions(CredentialOptions.nullCredential()) + .setPort(8080) + .build(); + + private BigtableDataSettings dataSettings; + private BigtableTableAdminSettings adminSettings; + private BigtableDataClient dataClient; + private BigtableTableAdminClient adminClient; + + @After + public void tearDown() throws Exception{ + if (dataClient != null) { + dataClient.close(); + } + + if(adminClient != null){ + adminClient.close(); + } + } + + public void initializeClients() throws IOException{ + BigtableOptions bigtableOptions = BigtableOptions.builder() + .setProjectId(ACTUAL_PROJECT_ID) + .setInstanceId(ACTUAL_INSTANCE_ID) + .setUserAgent("native-bigtable-test-useragent") + .build(); + + dataSettings = BigtableVaneerSettingsFactory.createBigtableDataSettings(bigtableOptions); + dataClient = BigtableDataClient.create(dataSettings); + + adminSettings = BigtableVaneerSettingsFactory.createTableAdminSettings(bigtableOptions); + adminClient = BigtableTableAdminClient.create(adminSettings); + } + + /** + * This test will only run if it found "test.client.project.id" & "test.client.project.id" + * VM arguments. Then it calls to an actual Bigtable Table & performs below checks: + *
+   *   
    + *
  • Check if table with TABLE_ID is existed or not.
  • + *
  • Creates a new table with TABLE_ID.
  • + *
  • Mutates a single row with {@link RowMutation}.
  • + *
  • Retrieves output in {@link ServerStream < Row >}.
  • + *
  • Deletes table created with TABLE_ID.
  • + *
+ *
+ * @throws Exception + */ + @Test + public void testWithActualTables() throws Exception{ + /** + * Checking if both arguments are available or not. + */ + Assume.assumeFalse(endToEndArgMissing); + + if (adminClient == null || dataClient == null) { + initializeClients(); + } + + final String TABLE_ID = "Test-clients-" + UUID.randomUUID().toString(); + final String COLUMN_FAMILY_ID = "CF1"; + final ByteString TEST_QUALIFER = ByteString.copyFromUtf8("qualifier1"); + final ByteString TEST_KEY = ByteString.copyFromUtf8("bigtableDataSettingTest"); + final ByteString TEST_VALUE = ByteString.copyFromUtf8("Test using BigtableDataclient & " + + "BigtableTableAdminClient"); + + //Checking if table already existed in the provided Instance. + if (adminClient.exists(TABLE_ID)) { + adminClient.deleteTable(TABLE_ID); + } + try { + CreateTableRequest createTableRequest = + CreateTableRequest.of(TABLE_ID).addFamily(COLUMN_FAMILY_ID); + adminClient.createTable(createTableRequest); + + //Created table with vaneer TableAdminClient. + boolean tableExist = adminClient.exists(TABLE_ID); + LOG.info("Table successfully created : " + tableExist); + assertTrue(tableExist); + + Mutation mutation = Mutation.create(); + mutation.setCell(COLUMN_FAMILY_ID, TEST_QUALIFER, TEST_VALUE); + RowMutation rowMutation = RowMutation.create(TABLE_ID, TEST_KEY, mutation); + + //Write content to Bigtable using vaneer DataClient. + dataClient.mutateRow(rowMutation); + LOG.info("Successfully Mutated"); + + Query query = Query.create(TABLE_ID); + ServerStream rowStream = dataClient.readRows(query); + for (Row outputRow : rowStream) { + + //Checking if the received output's KEY is same as above. + ByteString key = outputRow.getKey(); + LOG.info("found key: " + key.toStringUtf8()); + assertEquals(TEST_KEY, outputRow.getKey()); + + for (RowCell cell : outputRow.getCells()) { + //Checking if the received output is KEY sent above. + ByteString value = cell.getValue(); + LOG.info("Value found: " + value.toStringUtf8()); + assertEquals(TEST_VALUE, value); + } + } + + //Removing the table. + adminClient.deleteTable(TABLE_ID); + } finally { + //Removing Table in case of some exception occurres. + boolean tableExist = adminClient.exists(TABLE_ID); + if (tableExist) { + adminClient.deleteTable(TABLE_ID); + } + assertFalse(adminClient.exists(TABLE_ID)); + } + } + + @Test + public void testProjectIdIsRequired() throws IOException { + BigtableOptions options = BigtableOptions.builder().build(); + + expectException.expect(IllegalStateException.class); + expectException.expectMessage("Project ID is required"); + dataSettings = BigtableVaneerSettingsFactory.createBigtableDataSettings(options); + } + + @Test + public void testInstanceIdIsRequired() throws IOException { + BigtableOptions options = BigtableOptions.builder().setProjectId(TEST_PROJECT_ID).build(); + + expectException.expect(IllegalStateException.class); + expectException.expectMessage("Instance ID is required"); + dataSettings = BigtableVaneerSettingsFactory.createBigtableDataSettings(options); + } + + @Test + public void testWhenRetriesAreDisabled() throws IOException { + RetryOptions retryOptions = RetryOptions.builder().setEnableRetries(false).build(); + BigtableOptions options = + BigtableOptions.builder() + .setProjectId(TEST_PROJECT_ID).setInstanceId(TEST_INSTANCE_ID) + .setRetryOptions(retryOptions).build(); + + expectException.expect(IllegalStateException.class); + expectException.expectMessage("Disabling retries is not currently supported."); + dataSettings = BigtableVaneerSettingsFactory.createBigtableDataSettings(options); + } + + @Test + public void testWithNullCredentials() throws IOException { + BigtableOptions options = + BigtableOptions.builder() + .setProjectId(TEST_PROJECT_ID).setInstanceId(TEST_INSTANCE_ID) + .setCredentialOptions(CredentialOptions.nullCredential()) + .setUserAgent(TEST_USER_AGENT).build(); + dataSettings = BigtableVaneerSettingsFactory.createBigtableDataSettings(options); + assertTrue(dataSettings.getCredentialsProvider() instanceof NoCredentialsProvider); + } + + @Test + public void testRetriableRpcs() throws IOException { + dataSettings = BigtableVaneerSettingsFactory.createBigtableDataSettings(bigtableOptions); + + //Verifying RetrySettings & RetryCodes of retryables methods. + + //sampleRowKeys + verifyRetry(dataSettings.sampleRowKeysSettings().getRetrySettings()); + assertEquals(DEFAULT_RETRY_CODES, dataSettings.sampleRowKeysSettings().getRetryableCodes()); + + //readRowsSettings + verifyRetry(dataSettings.readRowsSettings().getRetrySettings()); + assertEquals(DEFAULT_RETRY_CODES, dataSettings.readRowsSettings().getRetryableCodes()); + + //mutateRowSettings + verifyRetry(dataSettings.mutateRowSettings().getRetrySettings()); + assertEquals(DEFAULT_RETRY_CODES, dataSettings.mutateRowSettings().getRetryableCodes()); + + } + + private void verifyRetry(RetrySettings retrySettings) { + assertEquals(DEFAULT_INITIAL_BACKOFF_MILLIS, retrySettings.getInitialRetryDelay().toMillis()); + assertEquals(DEFAULT_BACKOFF_MULTIPLIER,retrySettings.getRetryDelayMultiplier(), 0); + assertEquals(DEFAULT_MAX_ELAPSED_BACKOFF_MILLIS, retrySettings.getMaxRetryDelay().toMillis()); + assertEquals(DEFAULT_MAX_SCAN_TIMEOUT_RETRIES, retrySettings.getMaxAttempts()); + assertEquals(SHORT_TIMEOUT_MS_DEFAULT, retrySettings.getInitialRpcTimeout().toMillis()); + assertEquals(SHORT_TIMEOUT_MS_DEFAULT, retrySettings.getMaxRpcTimeout().toMillis()); + assertEquals(LONG_TIMEOUT_MS_DEFAULT, retrySettings.getTotalTimeout().toMillis()); + } + + @Test + public void testNonRetriableRpcs() throws Exception { + CallOptionsConfig callOptions = CallOptionsConfig.builder() + .setShortRpcTimeoutMs(SHORT_TIMEOUT_MS) + .setLongRpcTimeoutMs(LONG_TIMEOUT_MS_DEFAULT) + .build(); + BigtableOptions options = BigtableOptions.builder() + .setProjectId(TEST_PROJECT_ID) + .setInstanceId(TEST_INSTANCE_ID) + .setUserAgent(TEST_USER_AGENT) + .setAdminHost("localhost") + .setDataHost("localhost") + .setPort(8080) + .setCredentialOptions(CredentialOptions.nullCredential()) + .setCallOptionsConfig(callOptions) + .build(); + dataSettings = BigtableVaneerSettingsFactory.createBigtableDataSettings(options); + + //Verifying RetrySettings & RetryCodes of non-retryables methods. + + //bulkMutationsSettings + verifyDisabledRetry(dataSettings.bulkMutationsSettings().getRetrySettings()); + assertTrue(dataSettings.bulkMutationsSettings().getRetryableCodes().isEmpty()); + + //readModifyWriteRowSettings + verifyDisabledRetry(dataSettings.readModifyWriteRowSettings().getRetrySettings()); + assertTrue(dataSettings.readModifyWriteRowSettings().getRetryableCodes().isEmpty()); + + //checkAndMutateRowSettings + verifyDisabledRetry(dataSettings.checkAndMutateRowSettings().getRetrySettings()); + assertTrue(dataSettings.checkAndMutateRowSettings().getRetryableCodes().isEmpty()); + } + + private void verifyDisabledRetry(RetrySettings ret) { + assertEquals(Duration.ZERO , ret.getInitialRetryDelay()); + assertEquals(1.0 , ret.getRetryDelayMultiplier(), 0); + assertEquals(Duration.ZERO, ret.getMaxRetryDelay()); + assertEquals(1, ret.getMaxAttempts()); + assertEquals(SHORT_TIMEOUT_MS, ret.getInitialRpcTimeout().toMillis()); + assertEquals(SHORT_TIMEOUT_MS, ret.getMaxRpcTimeout().toMillis()); + assertEquals(SHORT_TIMEOUT_MS, ret.getTotalTimeout().toMillis()); + } + + @Test + public void testWhenBulkOptionIsDisabled() throws IOException { + BulkOptions bulkOptions = BulkOptions.builder().setUseBulkApi(false).build(); + BigtableOptions options = BigtableOptions.builder() + .setProjectId(TEST_PROJECT_ID) + .setInstanceId(TEST_INSTANCE_ID) + .setCredentialOptions(CredentialOptions.nullCredential()) + .setBulkOptions(bulkOptions) + .build(); + dataSettings = BigtableVaneerSettingsFactory.createBigtableDataSettings(options); + assertFalse(dataSettings.bulkMutationsSettings().getBatchingSettings().getIsEnabled()); + } + + @Test + public void testBulkMutation() throws IOException { + BigtableOptions options = + BigtableOptions.builder() + .setProjectId(TEST_PROJECT_ID) + .setInstanceId(TEST_INSTANCE_ID) + .setCredentialOptions(CredentialOptions.nullCredential()) + .build(); + dataSettings = BigtableVaneerSettingsFactory.createBigtableDataSettings(options); + + BulkOptions bulkOptions = options.getBulkOptions(); + BatchingSettings batchingSettings = dataSettings.bulkMutationsSettings().getBatchingSettings(); + long outstandingElementCount = + bulkOptions.getMaxInflightRpcs() * bulkOptions.getBulkMaxRowKeyCount(); + assertTrue(batchingSettings.getIsEnabled()); + assertEquals(bulkOptions.getBulkMaxRequestSize(), + batchingSettings.getRequestByteThreshold().longValue()); + assertEquals(bulkOptions.getBulkMaxRowKeyCount(), + batchingSettings.getElementCountThreshold().longValue()); + assertEquals(bulkOptions.getMaxMemory(), + batchingSettings.getFlowControlSettings().getMaxOutstandingRequestBytes().longValue()); + assertEquals(outstandingElementCount, + batchingSettings.getFlowControlSettings().getMaxOutstandingElementCount().longValue()); + } + + @Test + public void testReadModifyWrite() throws IOException { + dataSettings = BigtableVaneerSettingsFactory.createBigtableDataSettings(bigtableOptions); + + RetrySettings actualRetry = dataSettings.readModifyWriteRowSettings().getRetrySettings(); + long rpcTimeoutMillis = bigtableOptions.getCallOptionsConfig().getShortRpcTimeoutMs(); + assertEquals(TimeUnit.MILLISECONDS.toSeconds(rpcTimeoutMillis), + actualRetry.getMaxRetryDelay().getSeconds()); + assertEquals(0, actualRetry.getMaxAttempts()); + } + + @Test + public void testCheckAndMutateRow() throws IOException { + dataSettings = BigtableVaneerSettingsFactory.createBigtableDataSettings(bigtableOptions); + RetrySettings actualRetry = dataSettings.checkAndMutateRowSettings().getRetrySettings(); + long rpcTimeoutMillis = bigtableOptions.getCallOptionsConfig().getShortRpcTimeoutMs(); + assertEquals(TimeUnit.MILLISECONDS.toSeconds(rpcTimeoutMillis), + actualRetry.getMaxRetryDelay().getSeconds()); + assertEquals(0, actualRetry.getMaxAttempts()); + } + + @Test + public void testTableAdminProjectIdIsRequired() throws IOException { + BigtableOptions options = BigtableOptions.builder().build(); + + expectException.expect(IllegalStateException.class); + expectException.expectMessage("Project ID is required"); + adminSettings = BigtableVaneerSettingsFactory.createTableAdminSettings(options); + } + + @Test + public void testTableAdminInstanceIdIsRequired() throws IOException { + BigtableOptions options = BigtableOptions.builder().setProjectId(TEST_PROJECT_ID).build(); + + expectException.expect(IllegalStateException.class); + expectException.expectMessage("Instance ID is required"); + adminSettings = BigtableVaneerSettingsFactory.createTableAdminSettings(options); + } + + @Test + public void testTableAdminWithNullCredentials() throws IOException { + BigtableOptions options = + BigtableOptions.builder() + .setProjectId(TEST_PROJECT_ID).setInstanceId(TEST_INSTANCE_ID) + .setCredentialOptions(CredentialOptions.nullCredential()) + .setUserAgent(TEST_USER_AGENT) + .setAdminHost("localhost") + .setPort(8080) + .build(); + adminSettings = BigtableVaneerSettingsFactory.createTableAdminSettings(options); + assertTrue( + adminSettings.getStubSettings().getCredentialsProvider() instanceof NoCredentialsProvider); + } +} diff --git a/bigtable-client-core-parent/bigtable-hbase/src/test/java/com/google/cloud/bigtable/hbase/TestBigtableDataSettingsFactory.java b/bigtable-client-core-parent/bigtable-hbase/src/test/java/com/google/cloud/bigtable/hbase/TestBigtableDataSettingsFactory.java deleted file mode 100644 index 6a3c166fd9..0000000000 --- a/bigtable-client-core-parent/bigtable-hbase/src/test/java/com/google/cloud/bigtable/hbase/TestBigtableDataSettingsFactory.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * 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; - -import static com.google.cloud.bigtable.config.CallOptionsConfig.LONG_TIMEOUT_MS_DEFAULT; -import static com.google.cloud.bigtable.config.CallOptionsConfig.SHORT_TIMEOUT_MS_DEFAULT; -import static com.google.cloud.bigtable.config.RetryOptions.DEFAULT_BACKOFF_MULTIPLIER; -import static com.google.cloud.bigtable.config.RetryOptions.DEFAULT_INITIAL_BACKOFF_MILLIS; -import static com.google.cloud.bigtable.config.RetryOptions.DEFAULT_MAX_ELAPSED_BACKOFF_MILLIS; -import static com.google.cloud.bigtable.config.RetryOptions.DEFAULT_MAX_SCAN_TIMEOUT_RETRIES; -import static com.google.cloud.bigtable.hbase.TestBigtableOptionsFactory.TEST_INSTANCE_ID; -import static com.google.cloud.bigtable.hbase.TestBigtableOptionsFactory.TEST_PROJECT_ID; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.util.Set; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.threeten.bp.Duration; - -import com.google.api.gax.batching.BatchingSettings; -import com.google.api.gax.core.NoCredentialsProvider; -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.cloud.bigtable.config.BigtableOptions; -import com.google.cloud.bigtable.config.BulkOptions; -import com.google.cloud.bigtable.config.CredentialOptions; -import com.google.cloud.bigtable.config.RetryOptions; -import com.google.cloud.bigtable.data.v2.BigtableDataSettings; -import com.google.common.collect.ImmutableSet; - -@RunWith(JUnit4.class) -public class TestBigtableDataSettingsFactory { - - private static final String TEST_USER_AGENT = "sampleUserAgent"; - private static final Set DEFAULT_RETRY_CODES = - ImmutableSet.of(Code.DEADLINE_EXCEEDED, Code.UNAVAILABLE, Code.ABORTED); - - @Rule - public ExpectedException expectException = ExpectedException.none(); - - private BigtableOptions bigtableOptions; - - @Before - public void setup() { - bigtableOptions = BigtableOptions.builder() - .setProjectId(TEST_PROJECT_ID).setInstanceId(TEST_INSTANCE_ID) - .build(); - } - - @Test - public void testProjectIdIsRequired() throws IOException, GeneralSecurityException { - BigtableOptions options = BigtableOptions.builder().build(); - - expectException.expect(IllegalStateException.class); - expectException.expectMessage("Project ID is required"); - BigtableDataSettingsFactory.fromBigtableOptions(options); - } - - @Test - public void testInstanceIdIsRequired() throws IOException, GeneralSecurityException { - BigtableOptions options = BigtableOptions.builder().setProjectId(TEST_PROJECT_ID).build(); - - expectException.expect(IllegalStateException.class); - expectException.expectMessage("Instance ID is required"); - BigtableDataSettingsFactory.fromBigtableOptions(options); - } - - @Test - public void testWhenRetriesAreDisabled() throws IOException, GeneralSecurityException { - RetryOptions retryOptions = RetryOptions.builder().setEnableRetries(false).build(); - BigtableOptions options = - BigtableOptions.builder() - .setProjectId(TEST_PROJECT_ID).setInstanceId(TEST_INSTANCE_ID) - .setRetryOptions(retryOptions).build(); - - expectException.expect(IllegalStateException.class); - expectException.expectMessage("Disabling retries is not currently supported."); - BigtableDataSettingsFactory.fromBigtableOptions(options); - } - - @Test - public void testWithNullCredentials() throws IOException, GeneralSecurityException { - BigtableOptions options = - BigtableOptions.builder() - .setProjectId(TEST_PROJECT_ID).setInstanceId(TEST_INSTANCE_ID) - .setCredentialOptions(CredentialOptions.nullCredential()) - .setUserAgent(TEST_USER_AGENT).build(); - BigtableDataSettings settings = BigtableDataSettingsFactory.fromBigtableOptions(options); - Assert.assertTrue(settings.getCredentialsProvider() instanceof NoCredentialsProvider); - } - - @Test - public void testRetrySettings() throws IOException, GeneralSecurityException { - BigtableDataSettings settings = BigtableDataSettingsFactory.fromBigtableOptions(bigtableOptions); - - //Verifying RetrySettings for sampleRowKey, mutateRow & readRowSettings - verifyRetry(settings.sampleRowKeysSettings().getRetrySettings()); - verifyRetry(settings.readRowsSettings().getRetrySettings()); - verifyRetry(settings.mutateRowSettings().getRetrySettings()); - - //Verifying RetrySettings & RetryCodes of non-retryable methods. - verifyDisabledRetry(settings.bulkMutationsSettings().getRetrySettings()); - verifyDisabledRetry(settings.readModifyWriteRowSettings().getRetrySettings()); - verifyDisabledRetry(settings.checkAndMutateRowSettings().getRetrySettings()); - } - - private void verifyRetry(RetrySettings retrySettings) { - assertEquals(DEFAULT_INITIAL_BACKOFF_MILLIS, retrySettings.getInitialRetryDelay().toMillis()); - assertEquals(DEFAULT_BACKOFF_MULTIPLIER,retrySettings.getRetryDelayMultiplier(), 0); - assertEquals(DEFAULT_MAX_ELAPSED_BACKOFF_MILLIS, retrySettings.getMaxRetryDelay().toMillis()); - assertEquals(DEFAULT_MAX_SCAN_TIMEOUT_RETRIES, retrySettings.getMaxAttempts()); - assertEquals(SHORT_TIMEOUT_MS_DEFAULT, retrySettings.getInitialRpcTimeout().toMillis()); - assertEquals(SHORT_TIMEOUT_MS_DEFAULT, retrySettings.getMaxRpcTimeout().toMillis()); - assertEquals(LONG_TIMEOUT_MS_DEFAULT, retrySettings.getTotalTimeout().toMillis()); - } - - private void verifyDisabledRetry(RetrySettings ret) { - assertEquals(Duration.ZERO , ret.getInitialRetryDelay()); - assertEquals(1.0 , ret.getRetryDelayMultiplier(), 0); - assertEquals(Duration.ZERO, ret.getMaxRetryDelay()); - assertEquals(1, ret.getMaxAttempts()); - assertEquals(SHORT_TIMEOUT_MS_DEFAULT, ret.getInitialRpcTimeout().toMillis()); - assertEquals(SHORT_TIMEOUT_MS_DEFAULT, ret.getMaxRpcTimeout().toMillis()); - assertEquals(SHORT_TIMEOUT_MS_DEFAULT, ret.getTotalTimeout().toMillis()); - } - - @Test - public void testRetryCodes() throws IOException, GeneralSecurityException { - BigtableDataSettings settings = BigtableDataSettingsFactory.fromBigtableOptions(bigtableOptions); - - assertEquals(DEFAULT_RETRY_CODES, settings.sampleRowKeysSettings().getRetryableCodes()); - assertEquals(DEFAULT_RETRY_CODES, settings.readRowsSettings().getRetryableCodes()); - - assertEquals(ImmutableSet.of(Code.DEADLINE_EXCEEDED, Code.UNAVAILABLE), - settings.mutateRowSettings().getRetryableCodes()); - - assertTrue(settings.bulkMutationsSettings().getRetryableCodes().isEmpty()); - assertTrue(settings.readModifyWriteRowSettings().getRetryableCodes().isEmpty()); - assertTrue(settings.checkAndMutateRowSettings().getRetryableCodes().isEmpty()); - } - - @Test - public void testWhenBulkOptionIsDisabled() throws IOException, GeneralSecurityException { - BulkOptions bulkOptions = BulkOptions.builder().setUseBulkApi(false).build(); - BigtableOptions options = BigtableOptions.builder().setProjectId(TEST_PROJECT_ID) - .setInstanceId(TEST_INSTANCE_ID).setBulkOptions(bulkOptions) - .build(); - BigtableDataSettings dataSettings = BigtableDataSettingsFactory.fromBigtableOptions(options); - assertFalse(dataSettings.bulkMutationsSettings().getBatchingSettings().getIsEnabled()); - } - - @Test - public void testBulkOption() throws IOException, GeneralSecurityException { - BigtableOptions options = BigtableOptions.builder().setProjectId(TEST_PROJECT_ID) - .setInstanceId(TEST_INSTANCE_ID).build(); - BigtableDataSettings dataSettings = BigtableDataSettingsFactory.fromBigtableOptions(options); - - BulkOptions bulkOptions = options.getBulkOptions(); - BatchingSettings batchingSettings = dataSettings.bulkMutationsSettings().getBatchingSettings(); - long outstandingElementCount = bulkOptions.getMaxInflightRpcs() * bulkOptions.getBulkMaxRowKeyCount(); - assertTrue(batchingSettings.getIsEnabled()); - assertEquals(bulkOptions.getBulkMaxRequestSize(), - batchingSettings.getRequestByteThreshold().longValue()); - assertEquals(bulkOptions.getBulkMaxRowKeyCount(), - batchingSettings.getElementCountThreshold().longValue()); - assertEquals(bulkOptions.getMaxMemory(), - batchingSettings.getFlowControlSettings().getMaxOutstandingRequestBytes().longValue()); - assertEquals(outstandingElementCount, - batchingSettings.getFlowControlSettings().getMaxOutstandingElementCount().longValue()); - } -} From ffe95f8a0a690ee27ae3b3181d87bfcc065c501a Mon Sep 17 00:00:00 2001 From: Rahul Kesharwani Date: Wed, 23 Jan 2019 15:32:48 +0530 Subject: [PATCH 3/9] Added User-Agent test along with more feedback changes --- ...ava => BigtableVeneerSettingsFactory.java} | 151 +++++------ .../google/cloud/bigtable/config/TEst.java | 31 +++ ...=> TestBigtableVeneerSettingsFactory.java} | 102 +++++--- .../cloud/bigtable/config/TestUserAgent.java | 237 ++++++++++++++++++ .../sslCertificates/client_trust.crt | 27 ++ .../resources/sslCertificates/server_key.pem | 52 ++++ .../sslCertificates/server_trust.crt | 27 ++ 7 files changed, 516 insertions(+), 111 deletions(-) rename bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/{BigtableVaneerSettingsFactory.java => BigtableVeneerSettingsFactory.java} (71%) create mode 100644 bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TEst.java rename bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/{TestBigtableVaneerSettingsFactory.java => TestBigtableVeneerSettingsFactory.java} (84%) create mode 100644 bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestUserAgent.java create mode 100644 bigtable-client-core-parent/bigtable-client-core/src/test/resources/sslCertificates/client_trust.crt create mode 100644 bigtable-client-core-parent/bigtable-client-core/src/test/resources/sslCertificates/server_key.pem create mode 100644 bigtable-client-core-parent/bigtable-client-core/src/test/resources/sslCertificates/server_trust.crt diff --git a/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVaneerSettingsFactory.java b/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVeneerSettingsFactory.java similarity index 71% rename from bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVaneerSettingsFactory.java rename to bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVeneerSettingsFactory.java index 62ef3ce7ec..dd598d90c0 100644 --- a/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVaneerSettingsFactory.java +++ b/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVeneerSettingsFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 Google Inc. All Rights Reserved. + * Copyright 2019 Google LLC. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ */ package com.google.cloud.bigtable.config; +import com.google.api.core.ApiFunction; import com.google.api.gax.batching.BatchingSettings; import com.google.api.gax.batching.FlowControlSettings; import com.google.api.gax.core.CredentialsProvider; @@ -24,11 +25,12 @@ import com.google.api.gax.retrying.RetrySettings; import com.google.api.gax.rpc.FixedHeaderProvider; import com.google.api.gax.rpc.HeaderProvider; +import com.google.api.gax.rpc.TransportChannelProvider; import com.google.auth.Credentials; import com.google.cloud.bigtable.admin.v2.BigtableTableAdminSettings; import com.google.cloud.bigtable.data.v2.BigtableDataSettings; import com.google.cloud.bigtable.data.v2.BigtableDataSettings.Builder; -import io.grpc.internal.GrpcUtil; +import io.grpc.ManagedChannelBuilder; import java.io.IOException; import java.security.GeneralSecurityException; import javax.annotation.Nonnull; @@ -36,17 +38,24 @@ import static com.google.api.client.util.Preconditions.checkState; import static com.google.cloud.bigtable.config.CallOptionsConfig.SHORT_TIMEOUT_MS_DEFAULT; +import static io.grpc.internal.GrpcUtil.USER_AGENT_KEY; import static org.threeten.bp.Duration.ofMillis; /** * Static methods to convert an instance of {@link BigtableOptions} to a * {@link BigtableDataSettings} or {@link BigtableTableAdminSettings} instance . */ -public class BigtableVaneerSettingsFactory { +public class BigtableVeneerSettingsFactory { /** Constant LOG */ - private static final Logger LOG = new Logger(BigtableVaneerSettingsFactory.class); + private static final Logger LOG = new Logger(BigtableVeneerSettingsFactory.class); + //Identifier to distinguish between CBT or GCJ adapter. + private static final String VENEER_ADAPTER = BigtableVersionInfo.CORE_USER_AGENT+"," + + "VENEER_ADAPTER"; + + // 256 MB, server has 256 MB limit. + private final static int MAX_MESSAGE_SIZE = 1 << 28; /** * To create an instance of {@link BigtableDataSettings} from {@link BigtableOptions}. * @@ -60,13 +69,12 @@ public static BigtableDataSettings createBigtableDataSettings(@Nonnull final Big checkState(options.getRetryOptions().enableRetries(), "Disabling retries is not currently supported."); final BigtableDataSettings.Builder builder = BigtableDataSettings.newBuilder(); - final String endpoint = options.getDataHost() + ":" + options.getPort(); builder.setProjectId(options.getProjectId()); builder.setInstanceId(options.getInstanceId()); builder.setAppProfileId(options.getAppProfileId()); - builder.setEndpoint(endpoint); + builder.setEndpoint(options.getDataHost() + ":" + options.getPort()); builder.setCredentialsProvider(buildCredentialProvider(options.getCredentialOptions())); @@ -76,21 +84,15 @@ public static BigtableDataSettings createBigtableDataSettings(@Nonnull final Big buildReadModifyWriteSettings(builder, options.getCallOptionsConfig().getShortRpcTimeoutMs()); + buildReadRowSettings(builder, options); + buildReadRowsSettings(builder, options); buildMutateRowSettings(builder, options); buildSampleRowKeysSettings(builder, options); - String userAgent = BigtableVersionInfo.CORE_USER_AGENT + "," + options.getUserAgent(); - HeaderProvider headers = FixedHeaderProvider.create(GrpcUtil.USER_AGENT_KEY.name(), userAgent); - - builder.setTransportChannelProvider( - InstantiatingGrpcChannelProvider.newBuilder() - .setHeaderProvider(headers) - .setEndpoint(endpoint) - .setPoolSize(options.getChannelCount()) - .build()); + builder.setTransportChannelProvider(createChannelProvider(options.getDataHost(), options)); return builder.build(); } @@ -112,32 +114,18 @@ public static BigtableTableAdminSettings createTableAdminSettings(@Nonnull final adminBuilder.setProjectId(options.getProjectId()); adminBuilder.setInstanceId(options.getInstanceId()); - final String endpoint = options.getAdminHost() + ":" + options.getPort(); - adminBuilder.stubSettings().setEndpoint(endpoint); + adminBuilder.stubSettings().setEndpoint(options.getAdminHost() + ":" + options.getPort()); - //Overriding default credential with BigtableOptions's credential. adminBuilder.stubSettings() .setCredentialsProvider(buildCredentialProvider(options.getCredentialOptions())); - String userAgent = BigtableVersionInfo.CORE_USER_AGENT + "," + options.getUserAgent(); - HeaderProvider headers = FixedHeaderProvider.create(GrpcUtil.USER_AGENT_KEY.name(), userAgent); - - adminBuilder.stubSettings().setTransportChannelProvider( - InstantiatingGrpcChannelProvider.newBuilder() - .setHeaderProvider(headers) - .setEndpoint(endpoint) - .setPoolSize(options.getChannelCount()) - .build()); + adminBuilder.stubSettings() + .setTransportChannelProvider(createChannelProvider(options.getAdminHost(), options)); return adminBuilder.build(); } - /** - * This method is use to build {@link BatchingSettings}. - * - * @param builder a {@link BigtableDataSettings.Builder} object. - * @param options a {@link BigtableOptions} object. - */ + /** Builds {@link BatchingSettings} based on {@link BulkOptions} configuration. */ private static void buildBulkMutationsSettings(Builder builder, BigtableOptions options) { BulkOptions bulkOptions = options.getBulkOptions(); BatchingSettings.Builder batchSettingsBuilder = BatchingSettings.newBuilder(); @@ -170,34 +158,40 @@ private static void buildBulkMutationsSettings(Builder builder, BigtableOptions ofMillis(shortRpcTimeoutMs)); } - /** - * To build BigtableDataSettings#sampleRowKeysSettings with default retries settings. - * - * @param builder a {@link BigtableDataSettings.Builder} object. - * @param options a {@link BigtableOptions} object. - */ + /** To build BigtableDataSettings#sampleRowKeysSettings with default Retry settings. */ private static void buildSampleRowKeysSettings(Builder builder, BigtableOptions options) { builder.sampleRowKeysSettings() .setRetrySettings(buildIdempotentRetrySettings(options)); } - /** - * To build BigtableDataSettings#mutateRowSettings with default retries settings. - * - * @param builder a {@link BigtableDataSettings.Builder} object. - * @param options a {@link BigtableOptions} object. - */ + /** To build BigtableDataSettings#mutateRowSettings with default Retry settings. */ private static void buildMutateRowSettings(Builder builder, BigtableOptions options) { builder.mutateRowSettings() .setRetrySettings(buildIdempotentRetrySettings(options)); } - /** - * To build BigtableDataSettings#readRowsSettings with default retries settings. - * - * @param builder a {@link BigtableDataSettings.Builder} object. - * @param options a {@link BigtableOptions} object. - */ + /** To build default Retry settings for Point Read. */ + private static void buildReadRowSettings(Builder builder, BigtableOptions options) { + RetryOptions retryOptions = options.getRetryOptions(); + + RetrySettings.Builder retryBuilder = RetrySettings.newBuilder() + .setInitialRetryDelay(ofMillis(retryOptions.getInitialBackoffMillis())) + .setRetryDelayMultiplier(retryOptions.getBackoffMultiplier()) + .setMaxRetryDelay(ofMillis(retryOptions.getMaxElapsedBackoffMillis())) + .setMaxAttempts(retryOptions.getMaxScanTimeoutRetries()); + + // configurations for RPC timeouts + Duration readPartialRowTimeout = ofMillis(retryOptions.getReadPartialRowTimeoutMillis()); + retryBuilder + .setInitialRpcTimeout(readPartialRowTimeout) + .setMaxRpcTimeout(readPartialRowTimeout) + .setTotalTimeout(ofMillis(options.getCallOptionsConfig().getLongRpcTimeoutMs())); + + builder.readRowSettings() + .setRetrySettings(retryBuilder.build()); + } + + /** To build BigtableDataSettings#readRowsSettings with default Retry settings. */ private static void buildReadRowsSettings(Builder builder, BigtableOptions options) { RetryOptions retryOptions = options.getRetryOptions(); @@ -219,11 +213,8 @@ private static void buildReadRowsSettings(Builder builder, BigtableOptions optio } /** - * This method builds BigtableDataSettings#readModifyWriteSettngs when short timeout is other + * Builds BigtableDataSettings#readModifyWriteRowSettings when short timeout is other * than 60_000 ms. - * - * @param builder a {@link BigtableDataSettings.Builder} object. - * @param rpcTimeoutMs a long value for RPC timeout. */ private static void buildReadModifyWriteSettings(Builder builder, long rpcTimeoutMs) { if(rpcTimeoutMs != SHORT_TIMEOUT_MS_DEFAULT) { @@ -233,11 +224,8 @@ private static void buildReadModifyWriteSettings(Builder builder, long rpcTimeou } /** - * This method builds BigtableDataSettings#checkAndMutateRowSettings when short timeout is other + * Builds BigtableDataSettings#checkAndMutateRowSettings when short timeout is other * than 60_000 ms. - * - * @param builder a {@link BigtableDataSettings.Builder} object. - * @param rpcTimeoutMs a long value for RPC timeout. */ private static void buildCheckAndMutateRowSettings(Builder builder, long rpcTimeoutMs) { if(rpcTimeoutMs != SHORT_TIMEOUT_MS_DEFAULT) { @@ -246,12 +234,7 @@ private static void buildCheckAndMutateRowSettings(Builder builder, long rpcTime } } - /** - * To create default {@link RetrySettings} for all idempotent method. - * - * @param options a {@link BigtableOptions} object. - * @return an object of {@link RetrySettings} with idempotent method configuration. - */ + /** Creates default {@link RetrySettings} for all idempotent method. */ private static RetrySettings buildIdempotentRetrySettings(BigtableOptions options) { RetryOptions retryOptions = options.getRetryOptions(); @@ -275,12 +258,7 @@ private static RetrySettings buildIdempotentRetrySettings(BigtableOptions option return retryBuilder.build(); } - /** - * To create {@link CredentialsProvider} based on {@link CredentialOptions}. - * - * @param credentialOptions a {@link CredentialOptions} object. - * @throws IOException if any. - */ + /** Creates {@link CredentialsProvider} based on {@link CredentialOptions}. */ private static CredentialsProvider buildCredentialProvider( CredentialOptions credentialOptions) throws IOException { try { @@ -295,4 +273,35 @@ private static CredentialsProvider buildCredentialProvider( throw new IOException("Could not initialize credentials.", exception); } } + + /** Creates {@link TransportChannelProvider} based on Channel Negotiation type. */ + private static TransportChannelProvider createChannelProvider(String hostname, + BigtableOptions options) { + final String endpoint = hostname + ":" + options.getPort(); + String userAgent = VENEER_ADAPTER + options.getUserAgent(); + + //InstantiatingGrpcChannelProvider has special handling for User-Agent header. It set the + //ChannelBuilder with provided value. + HeaderProvider headers = FixedHeaderProvider.create(USER_AGENT_KEY.name(), userAgent); + + InstantiatingGrpcChannelProvider.Builder builder = + InstantiatingGrpcChannelProvider.newBuilder() + .setHeaderProvider(headers) + .setEndpoint(endpoint) + .setPoolSize(options.getChannelCount()) + .setMaxInboundMessageSize(MAX_MESSAGE_SIZE); + + //overriding channel configuration for plaintext negotiation. + if (options.usePlaintextNegotiation()) { + builder.setChannelConfigurator( + new ApiFunction() { + @Override + public ManagedChannelBuilder apply(ManagedChannelBuilder channelBuilder) { + return channelBuilder.usePlaintext(); + } + }); + } + + return builder.build(); + } } diff --git a/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TEst.java b/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TEst.java new file mode 100644 index 0000000000..76f04dbfa2 --- /dev/null +++ b/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TEst.java @@ -0,0 +1,31 @@ +package com.google.cloud.bigtable.config; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; + +public class TEst { + + public static void main(String args[]){ + System.out.println("findnig the credentiatlas"); + String json = CredentialOptions.getEnvJsonFile(); + try { + FileInputStream ins = new FileInputStream(json); + System.out.println(ins); + + System.out.println("second"); + String fileString = new String(Files.readAllBytes(Paths.get(json)), + StandardCharsets.UTF_8); + System.out.println("Contents (Java 7 with character encoding ) : " + fileString); + + + } catch ( IOException e) { + e.printStackTrace(); + } + System.out.println(CredentialOptions.jsonCredentials(json)); + } +} diff --git a/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestBigtableVaneerSettingsFactory.java b/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestBigtableVeneerSettingsFactory.java similarity index 84% rename from bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestBigtableVaneerSettingsFactory.java rename to bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestBigtableVeneerSettingsFactory.java index 35c665c806..b71eab4547 100644 --- a/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestBigtableVaneerSettingsFactory.java +++ b/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestBigtableVeneerSettingsFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 Google Inc. All Rights Reserved. + * Copyright 2019 Google LLC. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,12 +33,15 @@ import com.google.common.base.Strings; import com.google.common.collect.ImmutableSet; import com.google.protobuf.ByteString; +import java.io.FileInputStream; import java.io.IOException; +import java.net.ServerSocket; import java.util.Set; import java.util.UUID; import java.util.concurrent.TimeUnit; import org.junit.After; import org.junit.Assume; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -57,13 +60,12 @@ import static org.junit.Assert.assertTrue; @RunWith(JUnit4.class) -public class TestBigtableVaneerSettingsFactory { +public class TestBigtableVeneerSettingsFactory { - private static final Logger LOG = new Logger(TestBigtableVaneerSettingsFactory.class); + private static final Logger LOG = new Logger(TestBigtableVeneerSettingsFactory.class); private static final String ACTUAL_PROJECT_ID = System.getProperty("test.client.project.id"); private static final String ACTUAL_INSTANCE_ID = System.getProperty("test.client.instance.id"); - private static final String TEST_PROJECT_ID = "fakeProjectID"; private static final String TEST_INSTANCE_ID = "fakeInstanceID"; private static final String TEST_USER_AGENT = "sampleUserAgent"; @@ -82,21 +84,30 @@ public class TestBigtableVaneerSettingsFactory { @Rule public ExpectedException expectException = ExpectedException.none(); - private BigtableOptions bigtableOptions = BigtableOptions.builder() - .setProjectId(TEST_PROJECT_ID) - .setInstanceId(TEST_INSTANCE_ID) - .setUserAgent(TEST_USER_AGENT) - .setAdminHost("localhost") - .setDataHost("localhost") - .setCredentialOptions(CredentialOptions.nullCredential()) - .setPort(8080) - .build(); + private BigtableOptions bigtableOptions; private BigtableDataSettings dataSettings; private BigtableTableAdminSettings adminSettings; private BigtableDataClient dataClient; private BigtableTableAdminClient adminClient; + @Before + public void setUp() throws IOException { + ServerSocket serverSocket = new ServerSocket(0); + final int availablePort = serverSocket.getLocalPort(); + serverSocket.close(); + + bigtableOptions = BigtableOptions.builder() + .setProjectId(TEST_PROJECT_ID) + .setInstanceId(TEST_INSTANCE_ID) + .setUserAgent(TEST_USER_AGENT) + .setAdminHost("localhost") + .setDataHost("localhost") + .setCredentialOptions(CredentialOptions.nullCredential()) + .setPort(availablePort) + .build(); + } + @After public void tearDown() throws Exception{ if (dataClient != null) { @@ -108,26 +119,28 @@ public void tearDown() throws Exception{ } } - public void initializeClients() throws IOException{ - BigtableOptions bigtableOptions = BigtableOptions.builder() + private void initializeClients() throws IOException{ + String josnPath = CredentialOptions.getEnvJsonFile(); + BigtableOptions options = BigtableOptions.builder() .setProjectId(ACTUAL_PROJECT_ID) .setInstanceId(ACTUAL_INSTANCE_ID) - .setUserAgent("native-bigtable-test-useragent") + .setUserAgent("native-bigtable-test") + .setCredentialOptions(CredentialOptions.jsonCredentials(new FileInputStream(josnPath))) .build(); - dataSettings = BigtableVaneerSettingsFactory.createBigtableDataSettings(bigtableOptions); + dataSettings = BigtableVeneerSettingsFactory.createBigtableDataSettings(options); dataClient = BigtableDataClient.create(dataSettings); - adminSettings = BigtableVaneerSettingsFactory.createTableAdminSettings(bigtableOptions); + adminSettings = BigtableVeneerSettingsFactory.createTableAdminSettings(options); adminClient = BigtableTableAdminClient.create(adminSettings); } /** - * This test will only run if it found "test.client.project.id" & "test.client.project.id" - * VM arguments. Then it calls to an actual Bigtable Table & performs below checks: + * This test runs only if it finds "test.client.project.id" & "test.client.project.id" + * VM arguments. Then it calls to an actual Bigtable Table & performs the checks below: *
    *   
    - *
  • Check if table with TABLE_ID is existed or not.
  • + *
  • Checks if table with TABLE_ID exists.
  • *
  • Creates a new table with TABLE_ID.
  • *
  • Mutates a single row with {@link RowMutation}.
  • *
  • Retrieves output in {@link ServerStream < Row >}.
  • @@ -154,7 +167,7 @@ public void testWithActualTables() throws Exception{ final ByteString TEST_VALUE = ByteString.copyFromUtf8("Test using BigtableDataclient & " + "BigtableTableAdminClient"); - //Checking if table already existed in the provided Instance. + //Checking if table already existed in the provided instance. if (adminClient.exists(TABLE_ID)) { adminClient.deleteTable(TABLE_ID); } @@ -196,7 +209,7 @@ public void testWithActualTables() throws Exception{ //Removing the table. adminClient.deleteTable(TABLE_ID); } finally { - //Removing Table in case of some exception occurres. + //Removing Table in case of exceptions. boolean tableExist = adminClient.exists(TABLE_ID); if (tableExist) { adminClient.deleteTable(TABLE_ID); @@ -211,7 +224,7 @@ public void testProjectIdIsRequired() throws IOException { expectException.expect(IllegalStateException.class); expectException.expectMessage("Project ID is required"); - dataSettings = BigtableVaneerSettingsFactory.createBigtableDataSettings(options); + dataSettings = BigtableVeneerSettingsFactory.createBigtableDataSettings(options); } @Test @@ -220,7 +233,7 @@ public void testInstanceIdIsRequired() throws IOException { expectException.expect(IllegalStateException.class); expectException.expectMessage("Instance ID is required"); - dataSettings = BigtableVaneerSettingsFactory.createBigtableDataSettings(options); + dataSettings = BigtableVeneerSettingsFactory.createBigtableDataSettings(options); } @Test @@ -233,7 +246,7 @@ public void testWhenRetriesAreDisabled() throws IOException { expectException.expect(IllegalStateException.class); expectException.expectMessage("Disabling retries is not currently supported."); - dataSettings = BigtableVaneerSettingsFactory.createBigtableDataSettings(options); + dataSettings = BigtableVeneerSettingsFactory.createBigtableDataSettings(options); } @Test @@ -243,15 +256,15 @@ public void testWithNullCredentials() throws IOException { .setProjectId(TEST_PROJECT_ID).setInstanceId(TEST_INSTANCE_ID) .setCredentialOptions(CredentialOptions.nullCredential()) .setUserAgent(TEST_USER_AGENT).build(); - dataSettings = BigtableVaneerSettingsFactory.createBigtableDataSettings(options); + dataSettings = BigtableVeneerSettingsFactory.createBigtableDataSettings(options); assertTrue(dataSettings.getCredentialsProvider() instanceof NoCredentialsProvider); } @Test public void testRetriableRpcs() throws IOException { - dataSettings = BigtableVaneerSettingsFactory.createBigtableDataSettings(bigtableOptions); + dataSettings = BigtableVeneerSettingsFactory.createBigtableDataSettings(bigtableOptions); - //Verifying RetrySettings & RetryCodes of retryables methods. + //Verifying RetrySettings & RetryCodes of retryable methods. //sampleRowKeys verifyRetry(dataSettings.sampleRowKeysSettings().getRetrySettings()); @@ -279,6 +292,10 @@ private void verifyRetry(RetrySettings retrySettings) { @Test public void testNonRetriableRpcs() throws Exception { + ServerSocket serverSocket = new ServerSocket(0); + final int availablePort = serverSocket.getLocalPort(); + serverSocket.close(); + CallOptionsConfig callOptions = CallOptionsConfig.builder() .setShortRpcTimeoutMs(SHORT_TIMEOUT_MS) .setLongRpcTimeoutMs(LONG_TIMEOUT_MS_DEFAULT) @@ -289,13 +306,13 @@ public void testNonRetriableRpcs() throws Exception { .setUserAgent(TEST_USER_AGENT) .setAdminHost("localhost") .setDataHost("localhost") - .setPort(8080) + .setPort(availablePort) .setCredentialOptions(CredentialOptions.nullCredential()) .setCallOptionsConfig(callOptions) .build(); - dataSettings = BigtableVaneerSettingsFactory.createBigtableDataSettings(options); + dataSettings = BigtableVeneerSettingsFactory.createBigtableDataSettings(options); - //Verifying RetrySettings & RetryCodes of non-retryables methods. + //Verifying RetrySettings & RetryCodes of non-retryable methods. //bulkMutationsSettings verifyDisabledRetry(dataSettings.bulkMutationsSettings().getRetrySettings()); @@ -329,7 +346,7 @@ public void testWhenBulkOptionIsDisabled() throws IOException { .setCredentialOptions(CredentialOptions.nullCredential()) .setBulkOptions(bulkOptions) .build(); - dataSettings = BigtableVaneerSettingsFactory.createBigtableDataSettings(options); + dataSettings = BigtableVeneerSettingsFactory.createBigtableDataSettings(options); assertFalse(dataSettings.bulkMutationsSettings().getBatchingSettings().getIsEnabled()); } @@ -341,7 +358,7 @@ public void testBulkMutation() throws IOException { .setInstanceId(TEST_INSTANCE_ID) .setCredentialOptions(CredentialOptions.nullCredential()) .build(); - dataSettings = BigtableVaneerSettingsFactory.createBigtableDataSettings(options); + dataSettings = BigtableVeneerSettingsFactory.createBigtableDataSettings(options); BulkOptions bulkOptions = options.getBulkOptions(); BatchingSettings batchingSettings = dataSettings.bulkMutationsSettings().getBatchingSettings(); @@ -360,7 +377,7 @@ public void testBulkMutation() throws IOException { @Test public void testReadModifyWrite() throws IOException { - dataSettings = BigtableVaneerSettingsFactory.createBigtableDataSettings(bigtableOptions); + dataSettings = BigtableVeneerSettingsFactory.createBigtableDataSettings(bigtableOptions); RetrySettings actualRetry = dataSettings.readModifyWriteRowSettings().getRetrySettings(); long rpcTimeoutMillis = bigtableOptions.getCallOptionsConfig().getShortRpcTimeoutMs(); @@ -371,7 +388,7 @@ public void testReadModifyWrite() throws IOException { @Test public void testCheckAndMutateRow() throws IOException { - dataSettings = BigtableVaneerSettingsFactory.createBigtableDataSettings(bigtableOptions); + dataSettings = BigtableVeneerSettingsFactory.createBigtableDataSettings(bigtableOptions); RetrySettings actualRetry = dataSettings.checkAndMutateRowSettings().getRetrySettings(); long rpcTimeoutMillis = bigtableOptions.getCallOptionsConfig().getShortRpcTimeoutMs(); assertEquals(TimeUnit.MILLISECONDS.toSeconds(rpcTimeoutMillis), @@ -385,7 +402,7 @@ public void testTableAdminProjectIdIsRequired() throws IOException { expectException.expect(IllegalStateException.class); expectException.expectMessage("Project ID is required"); - adminSettings = BigtableVaneerSettingsFactory.createTableAdminSettings(options); + adminSettings = BigtableVeneerSettingsFactory.createTableAdminSettings(options); } @Test @@ -394,21 +411,26 @@ public void testTableAdminInstanceIdIsRequired() throws IOException { expectException.expect(IllegalStateException.class); expectException.expectMessage("Instance ID is required"); - adminSettings = BigtableVaneerSettingsFactory.createTableAdminSettings(options); + adminSettings = BigtableVeneerSettingsFactory.createTableAdminSettings(options); } @Test public void testTableAdminWithNullCredentials() throws IOException { + ServerSocket serverSocket = new ServerSocket(0); + final int availablePort = serverSocket.getLocalPort(); + serverSocket.close(); BigtableOptions options = BigtableOptions.builder() .setProjectId(TEST_PROJECT_ID).setInstanceId(TEST_INSTANCE_ID) .setCredentialOptions(CredentialOptions.nullCredential()) .setUserAgent(TEST_USER_AGENT) .setAdminHost("localhost") - .setPort(8080) + .setPort(availablePort) .build(); - adminSettings = BigtableVaneerSettingsFactory.createTableAdminSettings(options); + adminSettings = BigtableVeneerSettingsFactory.createTableAdminSettings(options); assertTrue( adminSettings.getStubSettings().getCredentialsProvider() instanceof NoCredentialsProvider); } + + } diff --git a/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestUserAgent.java b/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestUserAgent.java new file mode 100644 index 0000000000..2f5377f2c3 --- /dev/null +++ b/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestUserAgent.java @@ -0,0 +1,237 @@ +/* + * Copyright 2019 Google LLC. + * + * 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.config; + +import com.google.api.core.ApiFunction; +import com.google.api.gax.core.NoCredentialsProvider; +import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; +import com.google.api.gax.rpc.FixedHeaderProvider; +import com.google.api.gax.rpc.HeaderProvider; +import com.google.bigtable.v2.BigtableGrpc.BigtableImplBase; +import com.google.bigtable.v2.ReadRowsRequest; +import com.google.bigtable.v2.ReadRowsResponse; +import com.google.cloud.bigtable.data.v2.BigtableDataClient; +import com.google.cloud.bigtable.data.v2.BigtableDataSettings; +import com.google.common.io.Resources; +import io.grpc.ForwardingServerCall; +import io.grpc.ManagedChannelBuilder; +import io.grpc.Metadata; +import io.grpc.Server; +import io.grpc.ServerBuilder; +import io.grpc.ServerCall; +import io.grpc.ServerCallHandler; +import io.grpc.ServerInterceptor; +import io.grpc.ServerInterceptors; +import io.grpc.netty.shaded.io.grpc.netty.GrpcSslContexts; +import io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder; +import io.grpc.netty.shaded.io.netty.handler.ssl.SslContext; +import io.grpc.netty.shaded.io.netty.handler.ssl.SslContextBuilder; +import io.grpc.stub.StreamObserver; +import java.io.File; +import java.net.ServerSocket; +import java.net.URL; +import java.util.regex.Pattern; +import javax.net.ssl.SSLException; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import static io.grpc.internal.GrpcUtil.USER_AGENT_KEY; + +/** + * This class tests UserAgent's on netty server. + */ +@RunWith(JUnit4.class) +public class TestUserAgent { + + private static final Logger logger = new Logger(TestUserAgent.class); + + private static final String TEST_PROJECT_ID = "Project-Id"; + private static final String TEST_INSTANCE_ID = "instance"; + private static final String TEST_USER_AGENT = "VENEER_ADAPTER"; + private static final Pattern EXPECTED_HEADER_PATTERN = + Pattern.compile(".*" + TEST_USER_AGENT + ".*"); + private static final String TABLE_ID = "my-table-id"; + private static final String ROWKEY = "row-key"; + + private BigtableDataSettings dataSettings; + private BigtableDataClient dataClient; + private Server server; + + @After + public void tearDown() throws Exception { + if(dataClient != null){ + dataClient.close(); + } + if (server != null) { + server.shutdown(); + server.awaitTermination(); + } + } + + /** + * To Test UserAgent & PlainText Negotiation type + * when {@link BigtableDataSettings} is created using {@link BigtableOptions}. + */ + @Test + public void testUserAgentUsingPlainTextNegotiation() throws Exception{ + ServerSocket serverSocket = new ServerSocket(0); + final int availablePort = serverSocket.getLocalPort(); + serverSocket.close(); + + //Creates non-ssl server. + createServer(availablePort); + + BigtableOptions bigtableOptions = + BigtableOptions.builder() + .setDataHost("localhost") + .setAdminHost("localhost") + .setProjectId(TEST_PROJECT_ID) + .setInstanceId(TEST_INSTANCE_ID) + .setUserAgent(TEST_USER_AGENT) + .setUsePlaintextNegotiation(true) + .setCredentialOptions(CredentialOptions.nullCredential()) + .setPort(availablePort) + .build(); + + dataSettings = BigtableVeneerSettingsFactory.createBigtableDataSettings(bigtableOptions); + + dataClient = BigtableDataClient.create(dataSettings); + dataClient.readRow(TABLE_ID, ROWKEY); + } + + /** + * Verify userAgent on TLS Negotiation with {@link InstantiatingGrpcChannelProvider} using SSL + * enabled server. + */ + @Test + public void testUserAgentUsingTLSNegotiation() throws Exception { + ServerSocket serverSocket = new ServerSocket(0); + final int availablePort = serverSocket.getLocalPort(); + serverSocket.close(); + + //Creates SSL enabled server. + createSecuredServer(availablePort); + + BigtableDataSettings.Builder builder = + BigtableDataSettings.newBuilder() + .setProjectId(TEST_PROJECT_ID) + .setInstanceId(TEST_INSTANCE_ID) + .setCredentialsProvider(NoCredentialsProvider.create()); + + //Loads secured Certificate + final SslContext sslContext = buildSslContext(); + + final String endpoint = "localhost" + ":" + availablePort; + HeaderProvider headers = FixedHeaderProvider.create(USER_AGENT_KEY.name(), TEST_USER_AGENT); + + builder.setTransportChannelProvider(InstantiatingGrpcChannelProvider.newBuilder() + .setHeaderProvider(headers) + .setEndpoint(endpoint) + .setChannelConfigurator(new ApiFunction() { + @Override + public ManagedChannelBuilder apply(ManagedChannelBuilder input) { + return ((NettyChannelBuilder)input).sslContext(sslContext); + } + }) + .build()); + + dataClient = BigtableDataClient.create(builder.build()); + dataClient.readRow(TABLE_ID, ROWKEY); + } + + /** Creates simple server to intercept plainText Negotiation RPCs. */ + private void createServer(int port) throws Exception{ + server = ServerBuilder.forPort(port).addService( + ServerInterceptors.intercept(new BigtableExtendedImpl(), new HeaderServerInterceptor())) + .build(); + server.start(); + } + + /** Creates secured server to intercept TLS Negotiation RPCs. */ + private void createSecuredServer(int port) throws Exception { + ServerBuilder builder = ServerBuilder.forPort(port).addService( + ServerInterceptors.intercept(new BigtableExtendedImpl(), new HeaderServerInterceptor())); + + try { + URL serverCertChain = Resources.getResource("sslCertificates/server_trust.crt"); + URL privateKey = Resources.getResource("sslCertificates/server_key.pem"); + + builder.useTransportSecurity(new File(serverCertChain.getFile()), + new File(privateKey.getFile())); + } catch (Exception ex) { + throw new AssertionError("No server certificates found"); + } + server = builder.build(); + server.start(); + } + + /** Creates SSLContext from certificate & private key provided in classpath. */ + private static SslContext buildSslContext() throws SSLException { + SslContextBuilder builder = GrpcSslContexts.forClient(); + + try { + URL url = Resources.getResource("sslCertificates/client_trust.crt"); + builder.trustManager(new File(url.getFile())); + } catch (Exception ex) { + throw new AssertionError("No client trust certificate found"); + } + + return builder.build(); + } + + /** + * Overrides {@link BigtableImplBase#readRows(ReadRowsRequest, StreamObserver)} and returns + * dummy response. + * */ + private static class BigtableExtendedImpl extends BigtableImplBase { + @Override + public void readRows(ReadRowsRequest request, + StreamObserver responseObserver) { + responseObserver.onNext(ReadRowsResponse.getDefaultInstance()); + responseObserver.onCompleted(); + } + } + + /** + * Asserts value of UserAgent header with EXPECTED_HEADER_PATTERN passed to the + * {@link InstantiatingGrpcChannelProvider}. + * + * Throws {@link AssertionError} when UserAgent's pattern does not match. + */ + private class HeaderServerInterceptor implements ServerInterceptor { + @Override + public ServerCall.Listener interceptCall(ServerCall call, + final Metadata requestHeaders, ServerCallHandler next) { + + //Logging all available headers. + logger.info("headers received from BigtableDataClient:" + requestHeaders); + + Metadata.Key USER_AGENT_KEY = + Metadata.Key.of("user-agent", Metadata.ASCII_STRING_MARSHALLER); + String headerValue = requestHeaders.get(USER_AGENT_KEY); + + //In case of user-agent not matching, throwing AssertionError. + if (!EXPECTED_HEADER_PATTERN.matcher(headerValue).matches()) { + throw new AssertionError("User-Agent's format did not match"); + } + return next.startCall(new ForwardingServerCall.SimpleForwardingServerCall(call) { + }, requestHeaders); + } + } +} + diff --git a/bigtable-client-core-parent/bigtable-client-core/src/test/resources/sslCertificates/client_trust.crt b/bigtable-client-core-parent/bigtable-client-core/src/test/resources/sslCertificates/client_trust.crt new file mode 100644 index 0000000000..8f20db5051 --- /dev/null +++ b/bigtable-client-core-parent/bigtable-client-core/src/test/resources/sslCertificates/client_trust.crt @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIEpDCCAowCCQDVy3LQHkRQtDANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAls +b2NhbGhvc3QwHhcNMTkwMTE2MDc1NTE3WhcNMjAwMTE2MDc1NTE3WjAUMRIwEAYD +VQQDDAlsb2NhbGhvc3QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDi +6mUxMsBRC6LEi5Cv0qdaEjEcFlF8qx5EGKs1p77+7Nx66VBnlrmmcwwBySwhArpD +JGXXMF3lpXGVHLENYXSwtq101OCTAGgwuZqvIxDcjckQqDu8Q5tLj94+axtq05Hx +50Ot7wtRBX9oS+8AOACgPsO5IQp/T92pN11UKY4K3tIs34HLAsqkoHFHsnzP7waV +0HIh0HdWd9oeWNQCIwALFj33dfZYmzc7592RSHPrEZdspIs3GEpA9WT2E9OrCHem +Hql3CDaNTWcO+SppJqSraRI2pKJSTDDVGWjkkbT+vYcX58gNlpqe98xzDhgt+s9X +X6WqZP5PiHJhVzxSC5oNLHtjsuoOJpy0WLccgjpqNiK747Kf5wm88TJf1KJ885O9 +BoX7ij8EFbdK0FoAfNkMiadFF7niRFUv2AnXd7MMHYRoeDDjfQ08cnLuKfQgRVIv +eY88b2C9Fvonf088mOqCGfdCPt+QB16LfarHmFE15ANmjzkIKgxfqo4ptUuRmsm2 +3i71ZLOq3t7dUvLSFmaY2SioXzB6lrKMvnrgEyCd8ka3LHXGohrwHEHFdhwHCVjw +7ZRBxK4kqihg60uENduPhGWVcwY4QLDNX/77aiMeWI8aXlV4qI/8IkPJTqTh+ZDe +QW93fw4BsrY2R6PfBVcQnxqAdkg+aExu40ESKz6tawIDAQABMA0GCSqGSIb3DQEB +CwUAA4ICAQBE+dvwx5Dry6PUiKBSAbCwmFsqj6Q+P11Q9dUzinfORNRAiMfHiJd+ +ngIqiMR5D/d0wYK6XR1MckjEM9N8i4N25B4qaYpOgI23/iU5cIYRIjVxpfNNmMON +fXcvSMhqS6e14spTnxrg1X5Yj9oE8gE9FArA6EqQpEarELSXDmiRgilJZKQ4RGFk +WOlZcTphwl3gerOD6l37DMWZXWx5DJCfQpRpw/3j2i86qdHN16Le5Ija5CBK+cTU +Vw5RsveumZPjTqsTtyQ8LncoY/fBh/I4QZoelh5s++QqOSvf48Db5WIPNcyGOPKZ +AgXgOabEGX2rEj73zA/80h5YQkVyiywXGxqp3Jy/tPXrXVYJqHNqF3ZCMJAgKtYe +p7JOv/bmhjuSyt+j0gv2Ot/ulWX1gjKHSPrFwd03rT5wXe9ooUWn83VwrmhW5D+l +nn8gi80dqy7GfQWGoQcYmtrd1U3YPQy1kgqO1v807v/QWHyLGWGqXesiO5HqgKp+ +OLXUvnmQYs4HERPCKbrWQ+blgVml0Kiochz50x8sI+aYjErwuinLTXtr0tZmtAO2 +23olBde5MvCBq1XCfJ5hG+2+YHb8LpvkjlbPbpopIftvIFZBSMPCjiZGvpxLS5pA +S2ngXkxoAce7xY/IO+W2FgCvC77Uy6UXiJIZ1PbSdFLN47OzRTMmOg== +-----END CERTIFICATE----- diff --git a/bigtable-client-core-parent/bigtable-client-core/src/test/resources/sslCertificates/server_key.pem b/bigtable-client-core-parent/bigtable-client-core/src/test/resources/sslCertificates/server_key.pem new file mode 100644 index 0000000000..0c75bb8ba3 --- /dev/null +++ b/bigtable-client-core-parent/bigtable-client-core/src/test/resources/sslCertificates/server_key.pem @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQCchlHZDz4QYh5a +k8ryDoaqux6CEXko/ZOcaFFJ19Oz85lKCJbRguW0L9MraL4W4TxuPKinEl0iKj2U +UpAhngGLpLMLwKRAI5gGnbDdbecKwJ7gzjw+owvdY8rq+EfUOQpLG6lwnKGe3ITW +dmcrRZ7afOXDbuGn2RMYNSBRJCbmvqGptTEVK6S5ktXYS2RWJWnKBuatqxzDOgS0 +iRBqOCG3jw8gV6b9I1dMWqCLXCUiL84xrPCy4cn6MRe5Hibz3qDVKsIbkmOUeM44 +hT/lME6IRNkM6PmbLEAEimUV56pwUm4fGECZYxQ3GfWXwFvSDrsB++mP7hx0dlTD +QdA08UaC99VjnJfIKDQGNn1l7TWpuIGPlmLBnj/mwnAk/J4fFS2354x7T5KS3yc6 +SAhf5qStcMyTBp50vjV3CFGwtUrM2ywHIEnsa/NubhSf+rA4+3IrY4AFQEIHrbAM +sWuH47CB6qvrAKeNErTlrMoNSnJ1ifNh8Mtrp7421pX1H3PjTRkSYRDh8TulV2Fd +mLMsxNWZtydaIqUJpETmz7QF8k/KLKmFf3CH6wauQCGZ7WkVuVUYoWQ5EaNZdpZD +3lZblIbVbNyoE04pA7IxS1jTigvNUCIjTBPxbqlaJ8fDQa1j3T3p9vU5CWlEoMlc +M4GunZ/KuQmMkWOTFe9rlwZdVsqXiQIDAQABAoICAB+9GNGjxpj53F/PgiJtEZ+D +C9+h/WhzasAXYwxPKE1gAuBBN5vKKBvOasptlcX77A4KXMRr89ieqhfuWe2HJZcU +UX37lRKwZP5KcXek9ml2v4CkMREebKR6vMXCjIYa/txWApikGh2lZ4Y5QhhDKL/y +/YAQds9bNAT/mMr7QqwdUZig9g/t5pv+i0AtoW3abkYZ+iKTBOUNWbDl7h8rvKKE +7rNHMsQ3q1b/NXisuZbiDLSD9da/8/24gK/3zjw7E2/GGNAQcgLEMETDuD4X+oSl +OUHl598wLNb+3RqA/E2EWXISr96qeYnmyKb5yWShugff9e9KgBiZefyR1s81cW+B +6zBZCK4bG4G/DGHxZUAdY/siBGJ1Vw2kTvt/g4P/5p3s1Hg3FFpAAElBRM4bFMYa +4fEf8EoVgH9KoRQYrWHcdaPmS/F8mwNSanFANEGF/8MXoYgwDFqoezFwEpmEpjpz +UfHcUwlQo+czFlJkvhBX30rVqTBT8gBXaMTO5x9q1OifBmVzCk9rHEVL+bNPBf48 +jeXPhVS+FbVtmxv+etNHSameL48lvlwgWUw6YXZEMs+bxK8P6PwGDc+ygL0V6Y3e +A3AX/ROaU6EpcCgFoW6FRULuAzvllMSosIiPHPsf0+zE1eWGk/6qW+xBb/YDhrNY +gTO0BmAqvnbzAt/9FqylAoIBAQDOgcSmZV4+aaM4aZpiDUSG+SRS5VDYYdKPA8IF +BIYodqKdF2IP3ZRHC4ZPShNCAeNK2QZUa7vxReey0ZQ3iuVVw1FlfT8Bg5AS2PTY +gYJZWnXyqNowXagGzgyx8vCnDSRnWyQHtmxoCyHRvgqdIgEnr2e/4IsYBwACoyji +rCA+TcZUOVowpLA2lOvjftlvk/ONkzCIVaqMouwFRvo25Pd4d6Cte3uyrREwW5YU +tFnImzMeoLVqBQRJxzHxkaLq4onSCelermALam/yRWxJ7so9UIySWdCt48iX6Y6R +wg1L90PGfk4bMyo6r3vr+HOggMFMmiFyQFjj968A/qhtIfPDAoIBAQDCCeRscGwJ +UGPoDlfxvDLTLPtR/GGn69ph6i9Avs49UsdSFBCRx7tp4igG4cu68ixX/5vXBeTc +h0mdbN8trdMG+CmQzpHH0coGSHxKR8zqsX3u+DC265WEcQmCXpyHmXYt/MhQ05Vf +4DpFn/foO/S90Lnjeb1YGBF8fM0hQNmAVIaEkVKr4qz55CZ/CK/dFNrqhmG1/WDq +FXUwPtHe7KXumsnViXOavbZIq9zS3/0d/sTsk1aQwEvohV7cBQNu5LMFxXhOdq70 +oomO1exA6ebMs6YI/tg1SYXSRHlQAy62vl0gGLWjEk5KFG6Jm4q2md3r4Cq8nqX+ +mPuSAd6jrc7DAoIBAQCV7xQ3d/vwNsTCLbJgpJ9vnC6qXULQiF3XZnQVLo61jEVO +525UdJ2244A1y2OmFjbP3jjBTKNdb1Llu1Lw7NDL7w8HL+NyFvKhLJLBK27Xr11Z +vQ0F9soLfskq3mep8lnPDRZg3ytgc0yvu1p7cfgCt1ENuFtlK5fvUkVaJn0Wn2Nz +PVzlWn1yc7e9Khl28KXx0b94DTLR/2x7/GepOZ8QAVNRAgny1cNYJ/cUu0lA5KY+ +A5MUEeZmJtF1QjdWcPp93KJrExI616HF9m/EUjLWR8h4beuchXjcC0BvRcRftnyn +/oZ5KzHrAARqdK6HB1TRaEsGZ//iLLAMedkRu4f/AoIBAFeCyJ9TcJYeyIAe//DJ +FQ8CqXIHZi+qgjpIuPj1VOR5UeWloPduYgrV8YFxEkYE9JTXdfxa7yW6aivyrxDV +5WeuQmjJkRvSdM+yn0OM8FEkrYw6KRZGV498v3Ipo2TQhGknKVyyoBq2cPF3vQHj +EHUPDtcVz5xMdo5zZrxJmA51kJl3RRa6S5MEH4yJaW9G+Zht9OF0HeJUvR5+Jn7o +sclTzBVfQWEXkH9j61q7pFeD0GJ17MOpxlJe3DJUnIDF6it/LMwOYMd6Cpn9xuhb +1TibCRXjgbU+rHjxYtkAJnBKmItiOYELP33Piy7KlJvX9ytrVTruPiT97++goj2l +pKsCggEAYk5INBQad3Ay3roIKSNplnp0/F/AARuVlfd78o0Lt91Sjulq76eHVvuu +8VDXL2nClMmJ7tL8M0yNOarUUS8rYiUq/ntwNvayyJq5IuQffpq+aY82IS2tNRnj +gBiaUtmT3+KjXFTy+AylDDLCVhRi3Sfk1cznTJ2Fjxifmrbs8HiVH5v96mmBoe/P +DFGjtMVF/afI/j+NVqC0dIVCiCxBkkr7CRVjFy2hy87l4IF8Z2kc9rNXZUjGRpkV +0ZqD40jkS/mMZI8NRa5U1adoHopgVDxXoMuG8AI73szPynuzEeGS8ki6iCYUn2Go +vEanFeXQY0SsYfTJlOcVEgVbA8hHBQ== +-----END PRIVATE KEY----- diff --git a/bigtable-client-core-parent/bigtable-client-core/src/test/resources/sslCertificates/server_trust.crt b/bigtable-client-core-parent/bigtable-client-core/src/test/resources/sslCertificates/server_trust.crt new file mode 100644 index 0000000000..b6d72c8312 --- /dev/null +++ b/bigtable-client-core-parent/bigtable-client-core/src/test/resources/sslCertificates/server_trust.crt @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIEnDCCAoQCAQEwDQYJKoZIhvcNAQEFBQAwFDESMBAGA1UEAwwJbG9jYWxob3N0 +MB4XDTE5MDExNjA3NTUzMVoXDTIwMDExNjA3NTUzMVowFDESMBAGA1UEAwwJbG9j +YWxob3N0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnIZR2Q8+EGIe +WpPK8g6GqrseghF5KP2TnGhRSdfTs/OZSgiW0YLltC/TK2i+FuE8bjyopxJdIio9 +lFKQIZ4Bi6SzC8CkQCOYBp2w3W3nCsCe4M48PqML3WPK6vhH1DkKSxupcJyhntyE +1nZnK0We2nzlw27hp9kTGDUgUSQm5r6hqbUxFSukuZLV2EtkViVpygbmrascwzoE +tIkQajght48PIFem/SNXTFqgi1wlIi/OMazwsuHJ+jEXuR4m896g1SrCG5JjlHjO +OIU/5TBOiETZDOj5myxABIplFeeqcFJuHxhAmWMUNxn1l8Bb0g67Afvpj+4cdHZU +w0HQNPFGgvfVY5yXyCg0BjZ9Ze01qbiBj5ZiwZ4/5sJwJPyeHxUtt+eMe0+Skt8n +OkgIX+akrXDMkwaedL41dwhRsLVKzNssByBJ7Gvzbm4Un/qwOPtyK2OABUBCB62w +DLFrh+Owgeqr6wCnjRK05azKDUpydYnzYfDLa6e+NtaV9R9z400ZEmEQ4fE7pVdh +XZizLMTVmbcnWiKlCaRE5s+0BfJPyiyphX9wh+sGrkAhme1pFblVGKFkORGjWXaW +Q95WW5SG1WzcqBNOKQOyMUtY04oLzVAiI0wT8W6pWifHw0GtY9096fb1OQlpRKDJ +XDOBrp2fyrkJjJFjkxXva5cGXVbKl4kCAwEAATANBgkqhkiG9w0BAQUFAAOCAgEA +TSbf7OhFnW05HE4TvKuv1rvh1TBCFzwhjQvKFi8oYUA4g8grcD7n2bJGgRjrniSa +CZBqbmPQc+T4jUuMFEzZ5tz30P/2ma5ZH1F6jpd2E6Igqwmrwa0z+iyQnjR2sMZ6 +lKQ7wGeNBTfgreCiVSmTQE/xck2Z+if7vZXabdgzAtagfA7Q8SpsV5VbYNJSjBLk +PSilineI8cWh4j+FARcICfDPGyqljsSSk1gIHqmwX3Y09MmslVFqSktVGSGV7Svv +GI/LkO0rwPhg8f2W7bkgEa0v46Rk9Ss43Pqpr8umQ7/iFqR/bEUdgXXPBmqw+l42 +kD9WlxCiq8C+rF3ULvkvVA3vj+H5iUqsoO0oc4ooAkDWcSeoPw+MGcet3S1elAKE +xjbbb4i5gF7TJkJai/hC7sGXnjBb6e1j7j685fv/B1st7mz98TMXbKEiTrBeS8q1 +N7AFCrFPztf9/+ItAmL9eqK/XBswNl4MtRZ5td337UhWzNBiBpvXFSQJmXWqs/ol +cFAJNsDRCl6ssHA/n53bW26L7VZtFViKT9huxAWmaWM7UVweRCreUmKw6FR+q4fN +BM8ffiUO92kyk9QZXXNDk0RZNGoKdIT7iaP3rUQAyTHQuF5flQX/afR+1bRx45HR +ERvwHniD31P0ekB+sS23MMjxWa2+b0k9pb2iwb0oWT4= +-----END CERTIFICATE----- From 60c30c534684675d65d75bbd036ebeed5484533e Mon Sep 17 00:00:00 2001 From: Rahul Kesharwani Date: Wed, 23 Jan 2019 19:31:30 +0530 Subject: [PATCH 4/9] added ChannelPerCPU config --- .../config/BigtableVeneerSettingsFactory.java | 1 + .../google/cloud/bigtable/config/TEst.java | 31 ------------------- .../TestBigtableVeneerSettingsFactory.java | 2 -- .../cloud/bigtable/config/TestUserAgent.java | 2 +- 4 files changed, 2 insertions(+), 34 deletions(-) delete mode 100644 bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TEst.java diff --git a/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVeneerSettingsFactory.java b/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVeneerSettingsFactory.java index dd598d90c0..2630ff9106 100644 --- a/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVeneerSettingsFactory.java +++ b/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVeneerSettingsFactory.java @@ -286,6 +286,7 @@ private static TransportChannelProvider createChannelProvider(String hostname, InstantiatingGrpcChannelProvider.Builder builder = InstantiatingGrpcChannelProvider.newBuilder() + .setChannelsPerCpu(2) .setHeaderProvider(headers) .setEndpoint(endpoint) .setPoolSize(options.getChannelCount()) diff --git a/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TEst.java b/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TEst.java deleted file mode 100644 index 76f04dbfa2..0000000000 --- a/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TEst.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.google.cloud.bigtable.config; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Paths; - -public class TEst { - - public static void main(String args[]){ - System.out.println("findnig the credentiatlas"); - String json = CredentialOptions.getEnvJsonFile(); - try { - FileInputStream ins = new FileInputStream(json); - System.out.println(ins); - - System.out.println("second"); - String fileString = new String(Files.readAllBytes(Paths.get(json)), - StandardCharsets.UTF_8); - System.out.println("Contents (Java 7 with character encoding ) : " + fileString); - - - } catch ( IOException e) { - e.printStackTrace(); - } - System.out.println(CredentialOptions.jsonCredentials(json)); - } -} diff --git a/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestBigtableVeneerSettingsFactory.java b/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestBigtableVeneerSettingsFactory.java index b71eab4547..22d7983e82 100644 --- a/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestBigtableVeneerSettingsFactory.java +++ b/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestBigtableVeneerSettingsFactory.java @@ -431,6 +431,4 @@ public void testTableAdminWithNullCredentials() throws IOException { assertTrue( adminSettings.getStubSettings().getCredentialsProvider() instanceof NoCredentialsProvider); } - - } diff --git a/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestUserAgent.java b/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestUserAgent.java index 2f5377f2c3..27bfe8c5c2 100644 --- a/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestUserAgent.java +++ b/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestUserAgent.java @@ -53,7 +53,7 @@ import static io.grpc.internal.GrpcUtil.USER_AGENT_KEY; /** - * This class tests UserAgent's on netty server. + * This class tests value present in User-Agent's on netty server. */ @RunWith(JUnit4.class) public class TestUserAgent { From d5d05946d1a5a3e80b10e374edcf8c6371973a63 Mon Sep 17 00:00:00 2001 From: Rahul Kesharwani Date: Thu, 24 Jan 2019 17:05:02 +0530 Subject: [PATCH 5/9] Adding Refactored BigtableVeneerSettings --- .../config/BigtableVeneerSettingsFactory.java | 147 ++++++++++-------- 1 file changed, 83 insertions(+), 64 deletions(-) diff --git a/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVeneerSettingsFactory.java b/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVeneerSettingsFactory.java index 2630ff9106..2d1ba82618 100644 --- a/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVeneerSettingsFactory.java +++ b/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVeneerSettingsFactory.java @@ -21,18 +21,23 @@ import com.google.api.gax.core.CredentialsProvider; import com.google.api.gax.core.FixedCredentialsProvider; import com.google.api.gax.core.NoCredentialsProvider; +import com.google.api.gax.grpc.GrpcStatusCode; import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; import com.google.api.gax.retrying.RetrySettings; import com.google.api.gax.rpc.FixedHeaderProvider; import com.google.api.gax.rpc.HeaderProvider; +import com.google.api.gax.rpc.StatusCode; import com.google.api.gax.rpc.TransportChannelProvider; import com.google.auth.Credentials; import com.google.cloud.bigtable.admin.v2.BigtableTableAdminSettings; import com.google.cloud.bigtable.data.v2.BigtableDataSettings; import com.google.cloud.bigtable.data.v2.BigtableDataSettings.Builder; +import com.google.common.collect.ImmutableSet; import io.grpc.ManagedChannelBuilder; +import io.grpc.Status; import java.io.IOException; import java.security.GeneralSecurityException; +import java.util.Set; import javax.annotation.Nonnull; import org.threeten.bp.Duration; @@ -56,6 +61,7 @@ public class BigtableVeneerSettingsFactory { // 256 MB, server has 256 MB limit. private final static int MAX_MESSAGE_SIZE = 1 << 28; + /** * To create an instance of {@link BigtableDataSettings} from {@link BigtableOptions}. * @@ -125,18 +131,34 @@ public static BigtableTableAdminSettings createTableAdminSettings(@Nonnull final return adminBuilder.build(); } + /** Creates {@link CredentialsProvider} based on {@link CredentialOptions}. */ + private static CredentialsProvider buildCredentialProvider( + CredentialOptions credentialOptions) throws IOException { + try { + final Credentials credentials = CredentialFactory.getCredentials(credentialOptions); + if (credentials == null) { + LOG.info("Enabling the use of null credentials. This should not be used in production."); + return NoCredentialsProvider.create(); + } + + return FixedCredentialsProvider.create(credentials); + } catch (GeneralSecurityException exception) { + throw new IOException("Could not initialize credentials.", exception); + } + } + /** Builds {@link BatchingSettings} based on {@link BulkOptions} configuration. */ private static void buildBulkMutationsSettings(Builder builder, BigtableOptions options) { BulkOptions bulkOptions = options.getBulkOptions(); - BatchingSettings.Builder batchSettingsBuilder = BatchingSettings.newBuilder(); + BatchingSettings.Builder batchBuilder = + builder.bulkMutationsSettings().getBatchingSettings().toBuilder(); long autoFlushMs = bulkOptions.getAutoflushMs(); long bulkMaxRowKeyCount = bulkOptions.getBulkMaxRowKeyCount(); long maxInflightRpcs = bulkOptions.getMaxInflightRpcs(); - long shortRpcTimeoutMs = options.getCallOptionsConfig().getShortRpcTimeoutMs(); if (autoFlushMs > 0) { - batchSettingsBuilder.setDelayThreshold(ofMillis(autoFlushMs)); + batchBuilder.setDelayThreshold(ofMillis(autoFlushMs)); } FlowControlSettings.Builder flowControlBuilder = FlowControlSettings.newBuilder(); if (maxInflightRpcs > 0) { @@ -145,57 +167,79 @@ private static void buildBulkMutationsSettings(Builder builder, BigtableOptions .setMaxOutstandingElementCount(maxInflightRpcs * bulkMaxRowKeyCount); } - batchSettingsBuilder + batchBuilder .setIsEnabled(bulkOptions.useBulkApi()) .setElementCountThreshold(Long.valueOf(bulkOptions.getBulkMaxRowKeyCount())) .setRequestByteThreshold(bulkOptions.getBulkMaxRequestSize()) .setFlowControlSettings(flowControlBuilder.build()); + RetrySettings retrySettings = + buildIdempotentRetrySettings(builder.bulkMutationsSettings().getRetrySettings(), options); + // TODO(rahulkql): implement bulkMutationThrottling & bulkMutationRpcTargetMs, once available builder.bulkMutationsSettings() - .setBatchingSettings(batchSettingsBuilder.build()) - .setSimpleTimeoutNoRetries( - ofMillis(shortRpcTimeoutMs)); + .setBatchingSettings(batchBuilder.build()) + .setRetrySettings(retrySettings) + .setRetryableCodes(buildRetryCodes(options.getRetryOptions())); + } + + /** + * Builds BigtableDataSettings#checkAndMutateRowSettings when short timeout is other + * than 60_000 ms. + */ + private static void buildCheckAndMutateRowSettings(Builder builder, long rpcTimeoutMs) { + if(rpcTimeoutMs != SHORT_TIMEOUT_MS_DEFAULT) { + builder.checkAndMutateRowSettings() + .setSimpleTimeoutNoRetries(ofMillis(rpcTimeoutMs)); + } + } + + /** + * Builds BigtableDataSettings#readModifyWriteRowSettings when short timeout is other + * than 60_000 ms. + */ + private static void buildReadModifyWriteSettings(Builder builder, long rpcTimeoutMs) { + if(rpcTimeoutMs != SHORT_TIMEOUT_MS_DEFAULT) { + builder.readModifyWriteRowSettings() + .setSimpleTimeoutNoRetries(ofMillis(rpcTimeoutMs)); + } } /** To build BigtableDataSettings#sampleRowKeysSettings with default Retry settings. */ private static void buildSampleRowKeysSettings(Builder builder, BigtableOptions options) { + RetrySettings retrySettings = + buildIdempotentRetrySettings(builder.sampleRowKeysSettings().getRetrySettings(), options); + builder.sampleRowKeysSettings() - .setRetrySettings(buildIdempotentRetrySettings(options)); + .setRetrySettings(retrySettings) + .setRetryableCodes(buildRetryCodes(options.getRetryOptions())); } /** To build BigtableDataSettings#mutateRowSettings with default Retry settings. */ private static void buildMutateRowSettings(Builder builder, BigtableOptions options) { + RetrySettings retrySettings = + buildIdempotentRetrySettings(builder.mutateRowSettings().getRetrySettings(), options); + builder.mutateRowSettings() - .setRetrySettings(buildIdempotentRetrySettings(options)); + .setRetrySettings(retrySettings) + .setRetryableCodes(buildRetryCodes(options.getRetryOptions())); } /** To build default Retry settings for Point Read. */ private static void buildReadRowSettings(Builder builder, BigtableOptions options) { - RetryOptions retryOptions = options.getRetryOptions(); - - RetrySettings.Builder retryBuilder = RetrySettings.newBuilder() - .setInitialRetryDelay(ofMillis(retryOptions.getInitialBackoffMillis())) - .setRetryDelayMultiplier(retryOptions.getBackoffMultiplier()) - .setMaxRetryDelay(ofMillis(retryOptions.getMaxElapsedBackoffMillis())) - .setMaxAttempts(retryOptions.getMaxScanTimeoutRetries()); - - // configurations for RPC timeouts - Duration readPartialRowTimeout = ofMillis(retryOptions.getReadPartialRowTimeoutMillis()); - retryBuilder - .setInitialRpcTimeout(readPartialRowTimeout) - .setMaxRpcTimeout(readPartialRowTimeout) - .setTotalTimeout(ofMillis(options.getCallOptionsConfig().getLongRpcTimeoutMs())); + RetrySettings retrySettings = + buildIdempotentRetrySettings(builder.readRowSettings().getRetrySettings(), options); builder.readRowSettings() - .setRetrySettings(retryBuilder.build()); + .setRetrySettings(retrySettings) + .setRetryableCodes(buildRetryCodes(options.getRetryOptions())); } /** To build BigtableDataSettings#readRowsSettings with default Retry settings. */ private static void buildReadRowsSettings(Builder builder, BigtableOptions options) { RetryOptions retryOptions = options.getRetryOptions(); - RetrySettings.Builder retryBuilder = RetrySettings.newBuilder() + RetrySettings.Builder retryBuilder = builder.readRowsSettings().getRetrySettings().toBuilder() .setInitialRetryDelay(ofMillis(retryOptions.getInitialBackoffMillis())) .setRetryDelayMultiplier(retryOptions.getBackoffMultiplier()) .setMaxRetryDelay(ofMillis(retryOptions.getMaxElapsedBackoffMillis())) @@ -209,36 +253,17 @@ private static void buildReadRowsSettings(Builder builder, BigtableOptions optio .setTotalTimeout(ofMillis(options.getCallOptionsConfig().getLongRpcTimeoutMs())); builder.readRowsSettings() - .setRetrySettings(retryBuilder.build()); - } - - /** - * Builds BigtableDataSettings#readModifyWriteRowSettings when short timeout is other - * than 60_000 ms. - */ - private static void buildReadModifyWriteSettings(Builder builder, long rpcTimeoutMs) { - if(rpcTimeoutMs != SHORT_TIMEOUT_MS_DEFAULT) { - builder.readModifyWriteRowSettings() - .setSimpleTimeoutNoRetries(ofMillis(rpcTimeoutMs)); - } - } - - /** - * Builds BigtableDataSettings#checkAndMutateRowSettings when short timeout is other - * than 60_000 ms. - */ - private static void buildCheckAndMutateRowSettings(Builder builder, long rpcTimeoutMs) { - if(rpcTimeoutMs != SHORT_TIMEOUT_MS_DEFAULT) { - builder.checkAndMutateRowSettings() - .setSimpleTimeoutNoRetries(ofMillis(rpcTimeoutMs)); - } + .setRetrySettings(retryBuilder.build()) + .setRetryableCodes(buildRetryCodes(options.getRetryOptions())); } - /** Creates default {@link RetrySettings} for all idempotent method. */ - private static RetrySettings buildIdempotentRetrySettings(BigtableOptions options) { + /** Creates {@link RetrySettings} for non-streaming idempotent method. */ + private static RetrySettings buildIdempotentRetrySettings(RetrySettings retrySettings, + BigtableOptions options) { RetryOptions retryOptions = options.getRetryOptions(); + RetrySettings.Builder retryBuilder = retrySettings.toBuilder(); - RetrySettings.Builder retryBuilder = RetrySettings.newBuilder() + retryBuilder .setInitialRetryDelay(ofMillis(retryOptions.getInitialBackoffMillis())) .setRetryDelayMultiplier(retryOptions.getBackoffMultiplier()) .setMaxRetryDelay(ofMillis(retryOptions.getMaxElapsedBackoffMillis())) @@ -258,20 +283,14 @@ private static RetrySettings buildIdempotentRetrySettings(BigtableOptions option return retryBuilder.build(); } - /** Creates {@link CredentialsProvider} based on {@link CredentialOptions}. */ - private static CredentialsProvider buildCredentialProvider( - CredentialOptions credentialOptions) throws IOException { - try { - final Credentials credentials = CredentialFactory.getCredentials(credentialOptions); - if (credentials == null) { - LOG.info("Enabling the use of null credentials. This should not be used in production."); - return NoCredentialsProvider.create(); - } - - return FixedCredentialsProvider.create(credentials); - } catch (GeneralSecurityException exception) { - throw new IOException("Could not initialize credentials.", exception); + private static Set buildRetryCodes(RetryOptions retryOptions) { + ImmutableSet.Builder statusCodeBuilder = + ImmutableSet.builderWithExpectedSize(retryOptions.getStatusCodes().size()); + for (Status.Code retryCode : retryOptions.getStatusCodes()) { + statusCodeBuilder.add(GrpcStatusCode.of(retryCode).getCode()); } + + return statusCodeBuilder.build(); } /** Creates {@link TransportChannelProvider} based on Channel Negotiation type. */ From 03f805a7fe424c71cdd32b922a72fb7890d8554e Mon Sep 17 00:00:00 2001 From: Rahul Kesharwani Date: Fri, 25 Jan 2019 08:40:10 +0530 Subject: [PATCH 6/9] Rebase & Refactored retryStatusCodes --- .../config/BigtableVeneerSettingsFactory.java | 16 +++++----- .../TestBigtableVeneerSettingsFactory.java | 29 ++++++++++--------- .../cloud/bigtable/config/TestUserAgent.java | 6 ++-- 3 files changed, 26 insertions(+), 25 deletions(-) diff --git a/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVeneerSettingsFactory.java b/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVeneerSettingsFactory.java index 2d1ba82618..555bf2b74d 100644 --- a/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVeneerSettingsFactory.java +++ b/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVeneerSettingsFactory.java @@ -15,6 +15,11 @@ */ package com.google.cloud.bigtable.config; +import static com.google.api.client.util.Preconditions.checkState; +import static com.google.cloud.bigtable.config.CallOptionsConfig.SHORT_TIMEOUT_MS_DEFAULT; +import static io.grpc.internal.GrpcUtil.USER_AGENT_KEY; +import static org.threeten.bp.Duration.ofMillis; + import com.google.api.core.ApiFunction; import com.google.api.gax.batching.BatchingSettings; import com.google.api.gax.batching.FlowControlSettings; @@ -41,11 +46,6 @@ import javax.annotation.Nonnull; import org.threeten.bp.Duration; -import static com.google.api.client.util.Preconditions.checkState; -import static com.google.cloud.bigtable.config.CallOptionsConfig.SHORT_TIMEOUT_MS_DEFAULT; -import static io.grpc.internal.GrpcUtil.USER_AGENT_KEY; -import static org.threeten.bp.Duration.ofMillis; - /** * Static methods to convert an instance of {@link BigtableOptions} to a * {@link BigtableDataSettings} or {@link BigtableTableAdminSettings} instance . @@ -283,10 +283,10 @@ private static RetrySettings buildIdempotentRetrySettings(RetrySettings retrySet return retryBuilder.build(); } + /** Creates {@link Set} of {@link StatusCode.Code} from {@link Status.Code} */ private static Set buildRetryCodes(RetryOptions retryOptions) { - ImmutableSet.Builder statusCodeBuilder = - ImmutableSet.builderWithExpectedSize(retryOptions.getStatusCodes().size()); - for (Status.Code retryCode : retryOptions.getStatusCodes()) { + ImmutableSet.Builder statusCodeBuilder = ImmutableSet.builder(); + for (Status.Code retryCode : retryOptions.getRetryableStatusCodes()) { statusCodeBuilder.add(GrpcStatusCode.of(retryCode).getCode()); } diff --git a/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestBigtableVeneerSettingsFactory.java b/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestBigtableVeneerSettingsFactory.java index 22d7983e82..de82c6e262 100644 --- a/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestBigtableVeneerSettingsFactory.java +++ b/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestBigtableVeneerSettingsFactory.java @@ -66,6 +66,7 @@ public class TestBigtableVeneerSettingsFactory { private static final String ACTUAL_PROJECT_ID = System.getProperty("test.client.project.id"); private static final String ACTUAL_INSTANCE_ID = System.getProperty("test.client.instance.id"); + private static final String TEST_PROJECT_ID = "fakeProjectID"; private static final String TEST_INSTANCE_ID = "fakeInstanceID"; private static final String TEST_USER_AGENT = "sampleUserAgent"; @@ -75,7 +76,7 @@ public class TestBigtableVeneerSettingsFactory { * RetryCodes for idempotent Rpcs. */ private static final Set DEFAULT_RETRY_CODES = - ImmutableSet.of(Code.DEADLINE_EXCEEDED, Code.UNAVAILABLE); + ImmutableSet.of(Code.DEADLINE_EXCEEDED, Code.UNAVAILABLE, Code.ABORTED, Code.UNAUTHENTICATED); private static final boolean endToEndArgMissing = Strings.isNullOrEmpty(ACTUAL_PROJECT_ID) && Strings.isNullOrEmpty(ACTUAL_INSTANCE_ID); @@ -253,7 +254,8 @@ public void testWhenRetriesAreDisabled() throws IOException { public void testWithNullCredentials() throws IOException { BigtableOptions options = BigtableOptions.builder() - .setProjectId(TEST_PROJECT_ID).setInstanceId(TEST_INSTANCE_ID) + .setProjectId(TEST_PROJECT_ID) + .setInstanceId(TEST_INSTANCE_ID) .setCredentialOptions(CredentialOptions.nullCredential()) .setUserAgent(TEST_USER_AGENT).build(); dataSettings = BigtableVeneerSettingsFactory.createBigtableDataSettings(options); @@ -278,6 +280,9 @@ public void testRetriableRpcs() throws IOException { verifyRetry(dataSettings.mutateRowSettings().getRetrySettings()); assertEquals(DEFAULT_RETRY_CODES, dataSettings.mutateRowSettings().getRetryableCodes()); + //bulkMutationsSettings + verifyRetry(dataSettings.bulkMutationsSettings().getRetrySettings()); + assertEquals(DEFAULT_RETRY_CODES, dataSettings.bulkMutationsSettings().getRetryableCodes()); } private void verifyRetry(RetrySettings retrySettings) { @@ -314,10 +319,6 @@ public void testNonRetriableRpcs() throws Exception { //Verifying RetrySettings & RetryCodes of non-retryable methods. - //bulkMutationsSettings - verifyDisabledRetry(dataSettings.bulkMutationsSettings().getRetrySettings()); - assertTrue(dataSettings.bulkMutationsSettings().getRetryableCodes().isEmpty()); - //readModifyWriteRowSettings verifyDisabledRetry(dataSettings.readModifyWriteRowSettings().getRetrySettings()); assertTrue(dataSettings.readModifyWriteRowSettings().getRetryableCodes().isEmpty()); @@ -327,14 +328,14 @@ public void testNonRetriableRpcs() throws Exception { assertTrue(dataSettings.checkAndMutateRowSettings().getRetryableCodes().isEmpty()); } - private void verifyDisabledRetry(RetrySettings ret) { - assertEquals(Duration.ZERO , ret.getInitialRetryDelay()); - assertEquals(1.0 , ret.getRetryDelayMultiplier(), 0); - assertEquals(Duration.ZERO, ret.getMaxRetryDelay()); - assertEquals(1, ret.getMaxAttempts()); - assertEquals(SHORT_TIMEOUT_MS, ret.getInitialRpcTimeout().toMillis()); - assertEquals(SHORT_TIMEOUT_MS, ret.getMaxRpcTimeout().toMillis()); - assertEquals(SHORT_TIMEOUT_MS, ret.getTotalTimeout().toMillis()); + private void verifyDisabledRetry(RetrySettings retrySettings) { + assertEquals(Duration.ZERO , retrySettings.getInitialRetryDelay()); + assertEquals(1 , retrySettings.getRetryDelayMultiplier(), 0); + assertEquals(Duration.ZERO, retrySettings.getMaxRetryDelay()); + assertEquals(1, retrySettings.getMaxAttempts()); + assertEquals(SHORT_TIMEOUT_MS, retrySettings.getInitialRpcTimeout().toMillis()); + assertEquals(SHORT_TIMEOUT_MS, retrySettings.getMaxRpcTimeout().toMillis()); + assertEquals(SHORT_TIMEOUT_MS, retrySettings.getTotalTimeout().toMillis()); } @Test diff --git a/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestUserAgent.java b/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestUserAgent.java index 27bfe8c5c2..2620f664a8 100644 --- a/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestUserAgent.java +++ b/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestUserAgent.java @@ -60,9 +60,9 @@ public class TestUserAgent { private static final Logger logger = new Logger(TestUserAgent.class); - private static final String TEST_PROJECT_ID = "Project-Id"; - private static final String TEST_INSTANCE_ID = "instance"; - private static final String TEST_USER_AGENT = "VENEER_ADAPTER"; + private static final String TEST_PROJECT_ID = "ProjectId"; + private static final String TEST_INSTANCE_ID = "InstanceId"; + private static final String TEST_USER_AGENT = "test-user-agent"; private static final Pattern EXPECTED_HEADER_PATTERN = Pattern.compile(".*" + TEST_USER_AGENT + ".*"); private static final String TABLE_ID = "my-table-id"; From 14c80af1043f268bbcd55e680bc640844920cbeb Mon Sep 17 00:00:00 2001 From: Rahul Kesharwani Date: Wed, 13 Feb 2019 13:36:04 +0530 Subject: [PATCH 7/9] Addressing Feedback for BigtableVeneerSettings --- .../config/BigtableVeneerSettingsFactory.java | 169 ++++++++---------- .../TestBigtableVeneerSettingsFactory.java | 125 ++----------- 2 files changed, 97 insertions(+), 197 deletions(-) diff --git a/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVeneerSettingsFactory.java b/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVeneerSettingsFactory.java index 555bf2b74d..2527e262af 100644 --- a/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVeneerSettingsFactory.java +++ b/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVeneerSettingsFactory.java @@ -16,7 +16,7 @@ package com.google.cloud.bigtable.config; import static com.google.api.client.util.Preconditions.checkState; -import static com.google.cloud.bigtable.config.CallOptionsConfig.SHORT_TIMEOUT_MS_DEFAULT; +import static com.google.cloud.bigtable.config.BigtableOptions.BIGTABLE_EMULATOR_HOST_ENV_VAR; import static io.grpc.internal.GrpcUtil.USER_AGENT_KEY; import static org.threeten.bp.Duration.ofMillis; @@ -35,6 +35,7 @@ import com.google.api.gax.rpc.TransportChannelProvider; import com.google.auth.Credentials; import com.google.cloud.bigtable.admin.v2.BigtableTableAdminSettings; +import com.google.cloud.bigtable.admin.v2.stub.BigtableTableAdminStubSettings; import com.google.cloud.bigtable.data.v2.BigtableDataSettings; import com.google.cloud.bigtable.data.v2.BigtableDataSettings.Builder; import com.google.common.collect.ImmutableSet; @@ -45,6 +46,7 @@ import java.util.Set; import javax.annotation.Nonnull; import org.threeten.bp.Duration; +import org.threeten.bp.temporal.ChronoUnit; /** * Static methods to convert an instance of {@link BigtableOptions} to a @@ -57,10 +59,12 @@ public class BigtableVeneerSettingsFactory { //Identifier to distinguish between CBT or GCJ adapter. private static final String VENEER_ADAPTER = BigtableVersionInfo.CORE_USER_AGENT+"," - + "VENEER_ADAPTER"; + + "VENEER_ADAPTER,"; // 256 MB, server has 256 MB limit. private final static int MAX_MESSAGE_SIZE = 1 << 28; + private static final int RPC_DEADLINE_MS = 360_000; + private static final int MAX_RETRY_TIMEOUT_MS = 60_000; /** * To create an instance of {@link BigtableDataSettings} from {@link BigtableOptions}. @@ -69,37 +73,44 @@ public class BigtableVeneerSettingsFactory { * @return a {@link BigtableDataSettings} object. * @throws IOException if any. */ - public static BigtableDataSettings createBigtableDataSettings(@Nonnull final BigtableOptions options) throws IOException { - checkState(options.getProjectId() != null, "Project ID is required"); - checkState(options.getInstanceId() != null, "Instance ID is required"); + public static BigtableDataSettings createBigtableDataSettings( + @Nonnull final BigtableOptions options) throws IOException { checkState(options.getRetryOptions().enableRetries(), "Disabling retries is not currently supported."); + checkState(!options.useCachedChannel(), "cachedDataPool is not currently supported."); + + //TODO:add configuration for emulator hosting. + String emulatorHost = System.getenv(BIGTABLE_EMULATOR_HOST_ENV_VAR); + checkState(emulatorHost == null, "Emulator Hosting is not supported yet."); final BigtableDataSettings.Builder builder = BigtableDataSettings.newBuilder(); + Duration shortRpcTimeoutMs = ofMillis(options.getCallOptionsConfig().getShortRpcTimeoutMs()); - builder.setProjectId(options.getProjectId()); - builder.setInstanceId(options.getInstanceId()); - builder.setAppProfileId(options.getAppProfileId()); + builder + .setProjectId(options.getProjectId()) + .setInstanceId(options.getInstanceId()) + .setAppProfileId(options.getAppProfileId()) + .setEndpoint(options.getDataHost() + ":" + options.getPort()) + .setCredentialsProvider(buildCredentialProvider(options.getCredentialOptions())) + .setHeaderProvider(buildHeaderProvider(options.getUserAgent())) + .setTransportChannelProvider(buildChannelProvider(builder.getEndpoint(), options)); - builder.setEndpoint(options.getDataHost() + ":" + options.getPort()); + // Configuration for rpcTimeout & totalTimeout for non-streaming operations. + builder.checkAndMutateRowSettings() + .setSimpleTimeoutNoRetries(shortRpcTimeoutMs); - builder.setCredentialsProvider(buildCredentialProvider(options.getCredentialOptions())); + builder.readModifyWriteRowSettings() + .setSimpleTimeoutNoRetries(shortRpcTimeoutMs); buildBulkMutationsSettings(builder, options); - buildCheckAndMutateRowSettings(builder, options.getCallOptionsConfig().getShortRpcTimeoutMs()); - - buildReadModifyWriteSettings(builder, options.getCallOptionsConfig().getShortRpcTimeoutMs()); + buildReadRowsSettings(builder, options); buildReadRowSettings(builder, options); - buildReadRowsSettings(builder, options); - buildMutateRowSettings(builder, options); buildSampleRowKeysSettings(builder, options); - builder.setTransportChannelProvider(createChannelProvider(options.getDataHost(), options)); - return builder.build(); } @@ -110,23 +121,20 @@ public static BigtableDataSettings createBigtableDataSettings(@Nonnull final Big * @return a {@link BigtableTableAdminSettings} object. * @throws IOException if any. */ - public static BigtableTableAdminSettings createTableAdminSettings(@Nonnull final BigtableOptions options) - throws IOException { - checkState(options.getProjectId() != null, "Project ID is required"); - checkState(options.getInstanceId() != null, "Instance ID is required"); - + public static BigtableTableAdminSettings createTableAdminSettings( + @Nonnull final BigtableOptions options) throws IOException { final BigtableTableAdminSettings.Builder adminBuilder = BigtableTableAdminSettings.newBuilder(); + BigtableTableAdminStubSettings.Builder adminStub = adminBuilder.stubSettings(); - adminBuilder.setProjectId(options.getProjectId()); - adminBuilder.setInstanceId(options.getInstanceId()); - - adminBuilder.stubSettings().setEndpoint(options.getAdminHost() + ":" + options.getPort()); + adminBuilder + .setProjectId(options.getProjectId()) + .setInstanceId(options.getInstanceId()); - adminBuilder.stubSettings() - .setCredentialsProvider(buildCredentialProvider(options.getCredentialOptions())); - - adminBuilder.stubSettings() - .setTransportChannelProvider(createChannelProvider(options.getAdminHost(), options)); + adminStub + .setHeaderProvider(buildHeaderProvider(options.getUserAgent())) + .setEndpoint(options.getAdminHost() + ":" + options.getPort()) + .setCredentialsProvider(buildCredentialProvider(options.getCredentialOptions())) + .setTransportChannelProvider(buildChannelProvider(adminStub.getEndpoint(), options)); return adminBuilder.build(); } @@ -147,6 +155,11 @@ private static CredentialsProvider buildCredentialProvider( } } + /** Creates {@link HeaderProvider} with VENEER_ADAPTER as prefix for user agent */ + private static HeaderProvider buildHeaderProvider(String userAgent){ + return FixedHeaderProvider.create(USER_AGENT_KEY.name(), VENEER_ADAPTER + userAgent); + } + /** Builds {@link BatchingSettings} based on {@link BulkOptions} configuration. */ private static void buildBulkMutationsSettings(Builder builder, BigtableOptions options) { BulkOptions bulkOptions = options.getBulkOptions(); @@ -183,28 +196,6 @@ private static void buildBulkMutationsSettings(Builder builder, BigtableOptions .setRetryableCodes(buildRetryCodes(options.getRetryOptions())); } - /** - * Builds BigtableDataSettings#checkAndMutateRowSettings when short timeout is other - * than 60_000 ms. - */ - private static void buildCheckAndMutateRowSettings(Builder builder, long rpcTimeoutMs) { - if(rpcTimeoutMs != SHORT_TIMEOUT_MS_DEFAULT) { - builder.checkAndMutateRowSettings() - .setSimpleTimeoutNoRetries(ofMillis(rpcTimeoutMs)); - } - } - - /** - * Builds BigtableDataSettings#readModifyWriteRowSettings when short timeout is other - * than 60_000 ms. - */ - private static void buildReadModifyWriteSettings(Builder builder, long rpcTimeoutMs) { - if(rpcTimeoutMs != SHORT_TIMEOUT_MS_DEFAULT) { - builder.readModifyWriteRowSettings() - .setSimpleTimeoutNoRetries(ofMillis(rpcTimeoutMs)); - } - } - /** To build BigtableDataSettings#sampleRowKeysSettings with default Retry settings. */ private static void buildSampleRowKeysSettings(Builder builder, BigtableOptions options) { RetrySettings retrySettings = @@ -238,19 +229,23 @@ private static void buildReadRowSettings(Builder builder, BigtableOptions option /** To build BigtableDataSettings#readRowsSettings with default Retry settings. */ private static void buildReadRowsSettings(Builder builder, BigtableOptions options) { RetryOptions retryOptions = options.getRetryOptions(); + CallOptionsConfig callOptions = options.getCallOptionsConfig(); + RetrySettings.Builder retryBuilder = builder.readRowsSettings().getRetrySettings().toBuilder(); - RetrySettings.Builder retryBuilder = builder.readRowsSettings().getRetrySettings().toBuilder() - .setInitialRetryDelay(ofMillis(retryOptions.getInitialBackoffMillis())) - .setRetryDelayMultiplier(retryOptions.getBackoffMultiplier()) - .setMaxRetryDelay(ofMillis(retryOptions.getMaxElapsedBackoffMillis())) - .setMaxAttempts(retryOptions.getMaxScanTimeoutRetries()); + //Timeout for ReadRows + Duration rpcTimeout = ofMillis(retryOptions.getReadPartialRowTimeoutMillis()); + Duration totalTimeout = ofMillis(callOptions.isUseTimeout() + ? callOptions.getLongRpcTimeoutMs() + : retryOptions.getMaxElapsedBackoffMillis()); - // configurations for RPC timeouts - Duration readPartialRowTimeout = ofMillis(retryOptions.getReadPartialRowTimeoutMillis()); retryBuilder - .setInitialRpcTimeout(readPartialRowTimeout) - .setMaxRpcTimeout(readPartialRowTimeout) - .setTotalTimeout(ofMillis(options.getCallOptionsConfig().getLongRpcTimeoutMs())); + .setInitialRetryDelay(ofMillis(retryOptions.getInitialBackoffMillis())) + .setRetryDelayMultiplier(retryOptions.getBackoffMultiplier()) + .setMaxRetryDelay(Duration.of(1, ChronoUnit.MINUTES)) + .setMaxAttempts(retryOptions.getMaxScanTimeoutRetries()) + .setInitialRpcTimeout(rpcTimeout) + .setMaxRpcTimeout(rpcTimeout) + .setTotalTimeout(totalTimeout); builder.readRowsSettings() .setRetrySettings(retryBuilder.build()) @@ -261,25 +256,26 @@ private static void buildReadRowsSettings(Builder builder, BigtableOptions optio private static RetrySettings buildIdempotentRetrySettings(RetrySettings retrySettings, BigtableOptions options) { RetryOptions retryOptions = options.getRetryOptions(); + CallOptionsConfig callOptions = options.getCallOptionsConfig(); RetrySettings.Builder retryBuilder = retrySettings.toBuilder(); - retryBuilder - .setInitialRetryDelay(ofMillis(retryOptions.getInitialBackoffMillis())) - .setRetryDelayMultiplier(retryOptions.getBackoffMultiplier()) - .setMaxRetryDelay(ofMillis(retryOptions.getMaxElapsedBackoffMillis())) - .setMaxAttempts(retryOptions.getMaxScanTimeoutRetries()); - - // configurations for RPC timeouts - Duration shortRpcTimeout = ofMillis(options.getCallOptionsConfig().getShortRpcTimeoutMs()); - retryBuilder - .setInitialRpcTimeout(shortRpcTimeout) - .setMaxRpcTimeout(shortRpcTimeout) - .setTotalTimeout(ofMillis(options.getCallOptionsConfig().getLongRpcTimeoutMs())); - if (retryOptions.allowRetriesWithoutTimestamp()) { LOG.warn("Retries without Timestamp does not support yet."); } + // if useTimeout is false, then RPC's are defaults to 6 minutes. + Duration rpcTimeout = ofMillis(callOptions.isUseTimeout() + ? callOptions.getShortRpcTimeoutMs() + : RPC_DEADLINE_MS); + + retryBuilder + .setInitialRetryDelay(ofMillis(retryOptions.getInitialBackoffMillis())) + .setRetryDelayMultiplier(retryOptions.getBackoffMultiplier()) + .setMaxRetryDelay(ofMillis(MAX_RETRY_TIMEOUT_MS)) + .setInitialRpcTimeout(rpcTimeout) + .setMaxRpcTimeout(rpcTimeout) + .setTotalTimeout(ofMillis(retryOptions.getMaxElapsedBackoffMillis())); + return retryBuilder.build(); } @@ -294,34 +290,25 @@ private static Set buildRetryCodes(RetryOptions retryOptions) { } /** Creates {@link TransportChannelProvider} based on Channel Negotiation type. */ - private static TransportChannelProvider createChannelProvider(String hostname, + private static TransportChannelProvider buildChannelProvider(String endpoint, BigtableOptions options) { - final String endpoint = hostname + ":" + options.getPort(); - String userAgent = VENEER_ADAPTER + options.getUserAgent(); - - //InstantiatingGrpcChannelProvider has special handling for User-Agent header. It set the - //ChannelBuilder with provided value. - HeaderProvider headers = FixedHeaderProvider.create(USER_AGENT_KEY.name(), userAgent); - - InstantiatingGrpcChannelProvider.Builder builder = + //TODO: refactor Google-cloud-java to expose a static defaultTransportChannelProvider. + InstantiatingGrpcChannelProvider.Builder transportBuilder = InstantiatingGrpcChannelProvider.newBuilder() - .setChannelsPerCpu(2) - .setHeaderProvider(headers) .setEndpoint(endpoint) .setPoolSize(options.getChannelCount()) + .setHeaderProvider(buildHeaderProvider(options.getUserAgent())) .setMaxInboundMessageSize(MAX_MESSAGE_SIZE); //overriding channel configuration for plaintext negotiation. if (options.usePlaintextNegotiation()) { - builder.setChannelConfigurator( - new ApiFunction() { + transportBuilder.setChannelConfigurator(new ApiFunction() { @Override public ManagedChannelBuilder apply(ManagedChannelBuilder channelBuilder) { return channelBuilder.usePlaintext(); } }); } - - return builder.build(); + return transportBuilder.build(); } } diff --git a/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestBigtableVeneerSettingsFactory.java b/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestBigtableVeneerSettingsFactory.java index de82c6e262..51589e7116 100644 --- a/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestBigtableVeneerSettingsFactory.java +++ b/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestBigtableVeneerSettingsFactory.java @@ -38,7 +38,6 @@ import java.net.ServerSocket; import java.util.Set; import java.util.UUID; -import java.util.concurrent.TimeUnit; import org.junit.After; import org.junit.Assume; import org.junit.Before; @@ -49,12 +48,10 @@ import org.junit.runners.JUnit4; import org.threeten.bp.Duration; -import static com.google.cloud.bigtable.config.CallOptionsConfig.LONG_TIMEOUT_MS_DEFAULT; import static com.google.cloud.bigtable.config.CallOptionsConfig.SHORT_TIMEOUT_MS_DEFAULT; import static com.google.cloud.bigtable.config.RetryOptions.DEFAULT_BACKOFF_MULTIPLIER; import static com.google.cloud.bigtable.config.RetryOptions.DEFAULT_INITIAL_BACKOFF_MILLIS; import static com.google.cloud.bigtable.config.RetryOptions.DEFAULT_MAX_ELAPSED_BACKOFF_MILLIS; -import static com.google.cloud.bigtable.config.RetryOptions.DEFAULT_MAX_SCAN_TIMEOUT_RETRIES; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -70,7 +67,6 @@ public class TestBigtableVeneerSettingsFactory { private static final String TEST_PROJECT_ID = "fakeProjectID"; private static final String TEST_INSTANCE_ID = "fakeInstanceID"; private static final String TEST_USER_AGENT = "sampleUserAgent"; - private static final int SHORT_TIMEOUT_MS = 30_000; /** * RetryCodes for idempotent Rpcs. @@ -219,24 +215,6 @@ public void testWithActualTables() throws Exception{ } } - @Test - public void testProjectIdIsRequired() throws IOException { - BigtableOptions options = BigtableOptions.builder().build(); - - expectException.expect(IllegalStateException.class); - expectException.expectMessage("Project ID is required"); - dataSettings = BigtableVeneerSettingsFactory.createBigtableDataSettings(options); - } - - @Test - public void testInstanceIdIsRequired() throws IOException { - BigtableOptions options = BigtableOptions.builder().setProjectId(TEST_PROJECT_ID).build(); - - expectException.expect(IllegalStateException.class); - expectException.expectMessage("Instance ID is required"); - dataSettings = BigtableVeneerSettingsFactory.createBigtableDataSettings(options); - } - @Test public void testWhenRetriesAreDisabled() throws IOException { RetryOptions retryOptions = RetryOptions.builder().setEnableRetries(false).build(); @@ -263,19 +241,14 @@ public void testWithNullCredentials() throws IOException { } @Test - public void testRetriableRpcs() throws IOException { + public void testConfigValues() throws IOException { dataSettings = BigtableVeneerSettingsFactory.createBigtableDataSettings(bigtableOptions); - //Verifying RetrySettings & RetryCodes of retryable methods. - + //Streaming operation's RetrySettings & RetryCodes of retryable methods. //sampleRowKeys verifyRetry(dataSettings.sampleRowKeysSettings().getRetrySettings()); assertEquals(DEFAULT_RETRY_CODES, dataSettings.sampleRowKeysSettings().getRetryableCodes()); - //readRowsSettings - verifyRetry(dataSettings.readRowsSettings().getRetrySettings()); - assertEquals(DEFAULT_RETRY_CODES, dataSettings.readRowsSettings().getRetryableCodes()); - //mutateRowSettings verifyRetry(dataSettings.mutateRowSettings().getRetrySettings()); assertEquals(DEFAULT_RETRY_CODES, dataSettings.mutateRowSettings().getRetryableCodes()); @@ -283,42 +256,8 @@ public void testRetriableRpcs() throws IOException { //bulkMutationsSettings verifyRetry(dataSettings.bulkMutationsSettings().getRetrySettings()); assertEquals(DEFAULT_RETRY_CODES, dataSettings.bulkMutationsSettings().getRetryableCodes()); - } - - private void verifyRetry(RetrySettings retrySettings) { - assertEquals(DEFAULT_INITIAL_BACKOFF_MILLIS, retrySettings.getInitialRetryDelay().toMillis()); - assertEquals(DEFAULT_BACKOFF_MULTIPLIER,retrySettings.getRetryDelayMultiplier(), 0); - assertEquals(DEFAULT_MAX_ELAPSED_BACKOFF_MILLIS, retrySettings.getMaxRetryDelay().toMillis()); - assertEquals(DEFAULT_MAX_SCAN_TIMEOUT_RETRIES, retrySettings.getMaxAttempts()); - assertEquals(SHORT_TIMEOUT_MS_DEFAULT, retrySettings.getInitialRpcTimeout().toMillis()); - assertEquals(SHORT_TIMEOUT_MS_DEFAULT, retrySettings.getMaxRpcTimeout().toMillis()); - assertEquals(LONG_TIMEOUT_MS_DEFAULT, retrySettings.getTotalTimeout().toMillis()); - } - - @Test - public void testNonRetriableRpcs() throws Exception { - ServerSocket serverSocket = new ServerSocket(0); - final int availablePort = serverSocket.getLocalPort(); - serverSocket.close(); - - CallOptionsConfig callOptions = CallOptionsConfig.builder() - .setShortRpcTimeoutMs(SHORT_TIMEOUT_MS) - .setLongRpcTimeoutMs(LONG_TIMEOUT_MS_DEFAULT) - .build(); - BigtableOptions options = BigtableOptions.builder() - .setProjectId(TEST_PROJECT_ID) - .setInstanceId(TEST_INSTANCE_ID) - .setUserAgent(TEST_USER_AGENT) - .setAdminHost("localhost") - .setDataHost("localhost") - .setPort(availablePort) - .setCredentialOptions(CredentialOptions.nullCredential()) - .setCallOptionsConfig(callOptions) - .build(); - dataSettings = BigtableVeneerSettingsFactory.createBigtableDataSettings(options); - - //Verifying RetrySettings & RetryCodes of non-retryable methods. + //Non-streaming operation's verifying RetrySettings & RetryCodes of non-retryable methods. //readModifyWriteRowSettings verifyDisabledRetry(dataSettings.readModifyWriteRowSettings().getRetrySettings()); assertTrue(dataSettings.readModifyWriteRowSettings().getRetryableCodes().isEmpty()); @@ -328,14 +267,25 @@ public void testNonRetriableRpcs() throws Exception { assertTrue(dataSettings.checkAndMutateRowSettings().getRetryableCodes().isEmpty()); } + private void verifyRetry(RetrySettings retrySettings) { + assertEquals(DEFAULT_INITIAL_BACKOFF_MILLIS, retrySettings.getInitialRetryDelay().toMillis()); + assertEquals(DEFAULT_BACKOFF_MULTIPLIER,retrySettings.getRetryDelayMultiplier(), 0); + assertEquals(DEFAULT_MAX_ELAPSED_BACKOFF_MILLIS, retrySettings.getMaxRetryDelay().toMillis()); + assertEquals(0, retrySettings.getMaxAttempts()); + assertEquals(360_000, retrySettings.getInitialRpcTimeout().toMillis()); + assertEquals(360_000, retrySettings.getMaxRpcTimeout().toMillis()); + assertEquals(60_000, retrySettings.getTotalTimeout().toMillis()); + } + private void verifyDisabledRetry(RetrySettings retrySettings) { assertEquals(Duration.ZERO , retrySettings.getInitialRetryDelay()); assertEquals(1 , retrySettings.getRetryDelayMultiplier(), 0); assertEquals(Duration.ZERO, retrySettings.getMaxRetryDelay()); assertEquals(1, retrySettings.getMaxAttempts()); - assertEquals(SHORT_TIMEOUT_MS, retrySettings.getInitialRpcTimeout().toMillis()); - assertEquals(SHORT_TIMEOUT_MS, retrySettings.getMaxRpcTimeout().toMillis()); - assertEquals(SHORT_TIMEOUT_MS, retrySettings.getTotalTimeout().toMillis()); + assertEquals(SHORT_TIMEOUT_MS_DEFAULT, retrySettings.getInitialRpcTimeout().toMillis()); + assertEquals(SHORT_TIMEOUT_MS_DEFAULT, retrySettings.getMaxRpcTimeout().toMillis()); + assertEquals(SHORT_TIMEOUT_MS_DEFAULT, retrySettings.getTotalTimeout().toMillis()); + assertEquals(1, retrySettings.getMaxAttempts()); } @Test @@ -358,6 +308,7 @@ public void testBulkMutation() throws IOException { .setProjectId(TEST_PROJECT_ID) .setInstanceId(TEST_INSTANCE_ID) .setCredentialOptions(CredentialOptions.nullCredential()) + .setUserAgent("Test-user-agent") .build(); dataSettings = BigtableVeneerSettingsFactory.createBigtableDataSettings(options); @@ -365,6 +316,7 @@ public void testBulkMutation() throws IOException { BatchingSettings batchingSettings = dataSettings.bulkMutationsSettings().getBatchingSettings(); long outstandingElementCount = bulkOptions.getMaxInflightRpcs() * bulkOptions.getBulkMaxRowKeyCount(); + assertTrue(batchingSettings.getIsEnabled()); assertEquals(bulkOptions.getBulkMaxRequestSize(), batchingSettings.getRequestByteThreshold().longValue()); @@ -376,45 +328,6 @@ public void testBulkMutation() throws IOException { batchingSettings.getFlowControlSettings().getMaxOutstandingElementCount().longValue()); } - @Test - public void testReadModifyWrite() throws IOException { - dataSettings = BigtableVeneerSettingsFactory.createBigtableDataSettings(bigtableOptions); - - RetrySettings actualRetry = dataSettings.readModifyWriteRowSettings().getRetrySettings(); - long rpcTimeoutMillis = bigtableOptions.getCallOptionsConfig().getShortRpcTimeoutMs(); - assertEquals(TimeUnit.MILLISECONDS.toSeconds(rpcTimeoutMillis), - actualRetry.getMaxRetryDelay().getSeconds()); - assertEquals(0, actualRetry.getMaxAttempts()); - } - - @Test - public void testCheckAndMutateRow() throws IOException { - dataSettings = BigtableVeneerSettingsFactory.createBigtableDataSettings(bigtableOptions); - RetrySettings actualRetry = dataSettings.checkAndMutateRowSettings().getRetrySettings(); - long rpcTimeoutMillis = bigtableOptions.getCallOptionsConfig().getShortRpcTimeoutMs(); - assertEquals(TimeUnit.MILLISECONDS.toSeconds(rpcTimeoutMillis), - actualRetry.getMaxRetryDelay().getSeconds()); - assertEquals(0, actualRetry.getMaxAttempts()); - } - - @Test - public void testTableAdminProjectIdIsRequired() throws IOException { - BigtableOptions options = BigtableOptions.builder().build(); - - expectException.expect(IllegalStateException.class); - expectException.expectMessage("Project ID is required"); - adminSettings = BigtableVeneerSettingsFactory.createTableAdminSettings(options); - } - - @Test - public void testTableAdminInstanceIdIsRequired() throws IOException { - BigtableOptions options = BigtableOptions.builder().setProjectId(TEST_PROJECT_ID).build(); - - expectException.expect(IllegalStateException.class); - expectException.expectMessage("Instance ID is required"); - adminSettings = BigtableVeneerSettingsFactory.createTableAdminSettings(options); - } - @Test public void testTableAdminWithNullCredentials() throws IOException { ServerSocket serverSocket = new ServerSocket(0); From 3b219d75b4938fe4a4ad7e0164a33166133f52f5 Mon Sep 17 00:00:00 2001 From: Rahul Kesharwani Date: Wed, 13 Feb 2019 19:06:26 +0530 Subject: [PATCH 8/9] Update BigtableVeneerSettingsFactory.java Used constant for maxRetryDelay & explicitly set the maxAttempts to zero --- .../cloud/bigtable/config/BigtableVeneerSettingsFactory.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVeneerSettingsFactory.java b/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVeneerSettingsFactory.java index 2527e262af..78851e2b3c 100644 --- a/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVeneerSettingsFactory.java +++ b/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVeneerSettingsFactory.java @@ -46,7 +46,6 @@ import java.util.Set; import javax.annotation.Nonnull; import org.threeten.bp.Duration; -import org.threeten.bp.temporal.ChronoUnit; /** * Static methods to convert an instance of {@link BigtableOptions} to a @@ -241,7 +240,7 @@ private static void buildReadRowsSettings(Builder builder, BigtableOptions optio retryBuilder .setInitialRetryDelay(ofMillis(retryOptions.getInitialBackoffMillis())) .setRetryDelayMultiplier(retryOptions.getBackoffMultiplier()) - .setMaxRetryDelay(Duration.of(1, ChronoUnit.MINUTES)) + .setMaxRetryDelay(ofMillis(MAX_RETRY_TIMEOUT_MS)) .setMaxAttempts(retryOptions.getMaxScanTimeoutRetries()) .setInitialRpcTimeout(rpcTimeout) .setMaxRpcTimeout(rpcTimeout) @@ -274,6 +273,7 @@ private static RetrySettings buildIdempotentRetrySettings(RetrySettings retrySet .setMaxRetryDelay(ofMillis(MAX_RETRY_TIMEOUT_MS)) .setInitialRpcTimeout(rpcTimeout) .setMaxRpcTimeout(rpcTimeout) + .setMaxAttempts(0) .setTotalTimeout(ofMillis(retryOptions.getMaxElapsedBackoffMillis())); return retryBuilder.build(); From d98cd29ca3f4eec6ef761c4031c6cb063734ad33 Mon Sep 17 00:00:00 2001 From: Rahul Kesharwani Date: Mon, 25 Feb 2019 19:17:41 +0530 Subject: [PATCH 9/9] Updated Veneer Settings - Now using EnhancedBigtableDataSettings.defaultGrpcChannelPRovider for channel provider configuration. - Updated existed BigtableDataSetttings.Builder to EnhancedBigtableDataSettings.Builder. - changed user agent for vaneer adapter to lowercase. - throwing exception in case of allowRetriesWithoutTimestamp. --- .../config/BigtableVeneerSettingsFactory.java | 86 +++++++++---------- .../TestBigtableVeneerSettingsFactory.java | 32 ++++--- 2 files changed, 57 insertions(+), 61 deletions(-) diff --git a/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVeneerSettingsFactory.java b/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVeneerSettingsFactory.java index 78851e2b3c..4ff493e924 100644 --- a/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVeneerSettingsFactory.java +++ b/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/config/BigtableVeneerSettingsFactory.java @@ -16,7 +16,7 @@ package com.google.cloud.bigtable.config; import static com.google.api.client.util.Preconditions.checkState; -import static com.google.cloud.bigtable.config.BigtableOptions.BIGTABLE_EMULATOR_HOST_ENV_VAR; +import static com.google.cloud.bigtable.data.v2.stub.EnhancedBigtableStubSettings.defaultGrpcTransportProviderBuilder; import static io.grpc.internal.GrpcUtil.USER_AGENT_KEY; import static org.threeten.bp.Duration.ofMillis; @@ -27,7 +27,6 @@ import com.google.api.gax.core.FixedCredentialsProvider; import com.google.api.gax.core.NoCredentialsProvider; import com.google.api.gax.grpc.GrpcStatusCode; -import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; import com.google.api.gax.retrying.RetrySettings; import com.google.api.gax.rpc.FixedHeaderProvider; import com.google.api.gax.rpc.HeaderProvider; @@ -37,7 +36,7 @@ import com.google.cloud.bigtable.admin.v2.BigtableTableAdminSettings; import com.google.cloud.bigtable.admin.v2.stub.BigtableTableAdminStubSettings; import com.google.cloud.bigtable.data.v2.BigtableDataSettings; -import com.google.cloud.bigtable.data.v2.BigtableDataSettings.Builder; +import com.google.cloud.bigtable.data.v2.stub.EnhancedBigtableStubSettings.Builder; import com.google.common.collect.ImmutableSet; import io.grpc.ManagedChannelBuilder; import io.grpc.Status; @@ -58,10 +57,8 @@ public class BigtableVeneerSettingsFactory { //Identifier to distinguish between CBT or GCJ adapter. private static final String VENEER_ADAPTER = BigtableVersionInfo.CORE_USER_AGENT+"," - + "VENEER_ADAPTER,"; + + "veneer-adapter,"; - // 256 MB, server has 256 MB limit. - private final static int MAX_MESSAGE_SIZE = 1 << 28; private static final int RPC_DEADLINE_MS = 360_000; private static final int MAX_RETRY_TIMEOUT_MS = 60_000; @@ -77,38 +74,41 @@ public static BigtableDataSettings createBigtableDataSettings( checkState(options.getRetryOptions().enableRetries(), "Disabling retries is not currently supported."); checkState(!options.useCachedChannel(), "cachedDataPool is not currently supported."); - //TODO:add configuration for emulator hosting. - String emulatorHost = System.getenv(BIGTABLE_EMULATOR_HOST_ENV_VAR); - checkState(emulatorHost == null, "Emulator Hosting is not supported yet."); - final BigtableDataSettings.Builder builder = BigtableDataSettings.newBuilder(); + final Builder dataSettingStub = builder.stubSettings(); Duration shortRpcTimeoutMs = ofMillis(options.getCallOptionsConfig().getShortRpcTimeoutMs()); builder .setProjectId(options.getProjectId()) .setInstanceId(options.getInstanceId()) - .setAppProfileId(options.getAppProfileId()) + .setAppProfileId(options.getAppProfileId()); + + dataSettingStub .setEndpoint(options.getDataHost() + ":" + options.getPort()) - .setCredentialsProvider(buildCredentialProvider(options.getCredentialOptions())) .setHeaderProvider(buildHeaderProvider(options.getUserAgent())) - .setTransportChannelProvider(buildChannelProvider(builder.getEndpoint(), options)); + .setCredentialsProvider(buildCredentialProvider(options.getCredentialOptions())); + + if(options.usePlaintextNegotiation()){ + dataSettingStub + .setTransportChannelProvider(buildChannelProvider(dataSettingStub.getEndpoint(), options)); + } // Configuration for rpcTimeout & totalTimeout for non-streaming operations. - builder.checkAndMutateRowSettings() + dataSettingStub.checkAndMutateRowSettings() .setSimpleTimeoutNoRetries(shortRpcTimeoutMs); - builder.readModifyWriteRowSettings() + dataSettingStub.readModifyWriteRowSettings() .setSimpleTimeoutNoRetries(shortRpcTimeoutMs); - buildBulkMutationsSettings(builder, options); + buildBulkMutationsSettings(dataSettingStub, options); - buildReadRowsSettings(builder, options); + buildReadRowsSettings(dataSettingStub, options); - buildReadRowSettings(builder, options); + buildReadRowSettings(dataSettingStub, options); - buildMutateRowSettings(builder, options); + buildMutateRowSettings(dataSettingStub, options); - buildSampleRowKeysSettings(builder, options); + buildSampleRowKeysSettings(dataSettingStub, options); return builder.build(); } @@ -132,8 +132,12 @@ public static BigtableTableAdminSettings createTableAdminSettings( adminStub .setHeaderProvider(buildHeaderProvider(options.getUserAgent())) .setEndpoint(options.getAdminHost() + ":" + options.getPort()) - .setCredentialsProvider(buildCredentialProvider(options.getCredentialOptions())) + .setCredentialsProvider(buildCredentialProvider(options.getCredentialOptions())); + + if(options.usePlaintextNegotiation()){ + adminStub .setTransportChannelProvider(buildChannelProvider(adminStub.getEndpoint(), options)); + } return adminBuilder.build(); } @@ -160,10 +164,11 @@ private static HeaderProvider buildHeaderProvider(String userAgent){ } /** Builds {@link BatchingSettings} based on {@link BulkOptions} configuration. */ - private static void buildBulkMutationsSettings(Builder builder, BigtableOptions options) { + private static void buildBulkMutationsSettings(Builder builder, + BigtableOptions options) { BulkOptions bulkOptions = options.getBulkOptions(); BatchingSettings.Builder batchBuilder = - builder.bulkMutationsSettings().getBatchingSettings().toBuilder(); + builder.bulkMutateRowsSettings().getBatchingSettings().toBuilder(); long autoFlushMs = bulkOptions.getAutoflushMs(); long bulkMaxRowKeyCount = bulkOptions.getBulkMaxRowKeyCount(); @@ -186,10 +191,10 @@ private static void buildBulkMutationsSettings(Builder builder, BigtableOptions .setFlowControlSettings(flowControlBuilder.build()); RetrySettings retrySettings = - buildIdempotentRetrySettings(builder.bulkMutationsSettings().getRetrySettings(), options); + buildIdempotentRetrySettings(builder.bulkMutateRowsSettings().getRetrySettings(), options); // TODO(rahulkql): implement bulkMutationThrottling & bulkMutationRpcTargetMs, once available - builder.bulkMutationsSettings() + builder.bulkMutateRowsSettings() .setBatchingSettings(batchBuilder.build()) .setRetrySettings(retrySettings) .setRetryableCodes(buildRetryCodes(options.getRetryOptions())); @@ -259,7 +264,7 @@ private static RetrySettings buildIdempotentRetrySettings(RetrySettings retrySet RetrySettings.Builder retryBuilder = retrySettings.toBuilder(); if (retryOptions.allowRetriesWithoutTimestamp()) { - LOG.warn("Retries without Timestamp does not support yet."); + throw new UnsupportedOperationException("Retries without Timestamp does not support yet."); } // if useTimeout is false, then RPC's are defaults to 6 minutes. @@ -292,23 +297,16 @@ private static Set buildRetryCodes(RetryOptions retryOptions) { /** Creates {@link TransportChannelProvider} based on Channel Negotiation type. */ private static TransportChannelProvider buildChannelProvider(String endpoint, BigtableOptions options) { - //TODO: refactor Google-cloud-java to expose a static defaultTransportChannelProvider. - InstantiatingGrpcChannelProvider.Builder transportBuilder = - InstantiatingGrpcChannelProvider.newBuilder() - .setEndpoint(endpoint) - .setPoolSize(options.getChannelCount()) - .setHeaderProvider(buildHeaderProvider(options.getUserAgent())) - .setMaxInboundMessageSize(MAX_MESSAGE_SIZE); - - //overriding channel configuration for plaintext negotiation. - if (options.usePlaintextNegotiation()) { - transportBuilder.setChannelConfigurator(new ApiFunction() { - @Override - public ManagedChannelBuilder apply(ManagedChannelBuilder channelBuilder) { - return channelBuilder.usePlaintext(); - } - }); - } - return transportBuilder.build(); + + return defaultGrpcTransportProviderBuilder() + .setEndpoint(endpoint) + .setPoolSize(options.getChannelCount()) + .setChannelConfigurator(new ApiFunction() { + @Override + public ManagedChannelBuilder apply(ManagedChannelBuilder channelBuilder) { + return channelBuilder.usePlaintext(); + } + }) + .build(); } } diff --git a/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestBigtableVeneerSettingsFactory.java b/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestBigtableVeneerSettingsFactory.java index 51589e7116..dca1121c06 100644 --- a/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestBigtableVeneerSettingsFactory.java +++ b/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/config/TestBigtableVeneerSettingsFactory.java @@ -144,13 +144,10 @@ private void initializeClients() throws IOException{ *
  • Deletes table created with TABLE_ID.
  • *
*
- * @throws Exception */ @Test public void testWithActualTables() throws Exception{ - /** - * Checking if both arguments are available or not. - */ + // Checking if both arguments are available or not. Assume.assumeFalse(endToEndArgMissing); if (adminClient == null || dataClient == null) { @@ -237,7 +234,7 @@ public void testWithNullCredentials() throws IOException { .setCredentialOptions(CredentialOptions.nullCredential()) .setUserAgent(TEST_USER_AGENT).build(); dataSettings = BigtableVeneerSettingsFactory.createBigtableDataSettings(options); - assertTrue(dataSettings.getCredentialsProvider() instanceof NoCredentialsProvider); + assertTrue(dataSettings.getStubSettings().getCredentialsProvider() instanceof NoCredentialsProvider); } @Test @@ -246,25 +243,26 @@ public void testConfigValues() throws IOException { //Streaming operation's RetrySettings & RetryCodes of retryable methods. //sampleRowKeys - verifyRetry(dataSettings.sampleRowKeysSettings().getRetrySettings()); - assertEquals(DEFAULT_RETRY_CODES, dataSettings.sampleRowKeysSettings().getRetryableCodes()); + verifyRetry(dataSettings.getStubSettings().sampleRowKeysSettings().getRetrySettings()); + assertEquals(DEFAULT_RETRY_CODES, dataSettings.getStubSettings().sampleRowKeysSettings().getRetryableCodes()); //mutateRowSettings - verifyRetry(dataSettings.mutateRowSettings().getRetrySettings()); - assertEquals(DEFAULT_RETRY_CODES, dataSettings.mutateRowSettings().getRetryableCodes()); + verifyRetry(dataSettings.getStubSettings().mutateRowSettings().getRetrySettings()); + assertEquals(DEFAULT_RETRY_CODES, dataSettings.getStubSettings().mutateRowSettings().getRetryableCodes()); //bulkMutationsSettings - verifyRetry(dataSettings.bulkMutationsSettings().getRetrySettings()); - assertEquals(DEFAULT_RETRY_CODES, dataSettings.bulkMutationsSettings().getRetryableCodes()); + verifyRetry(dataSettings.getStubSettings().bulkMutateRowsSettings().getRetrySettings()); + assertEquals(DEFAULT_RETRY_CODES, + dataSettings.getStubSettings().bulkMutateRowsSettings().getRetryableCodes()); //Non-streaming operation's verifying RetrySettings & RetryCodes of non-retryable methods. //readModifyWriteRowSettings - verifyDisabledRetry(dataSettings.readModifyWriteRowSettings().getRetrySettings()); - assertTrue(dataSettings.readModifyWriteRowSettings().getRetryableCodes().isEmpty()); + verifyDisabledRetry(dataSettings.getStubSettings().readModifyWriteRowSettings().getRetrySettings()); + assertTrue(dataSettings.getStubSettings().readModifyWriteRowSettings().getRetryableCodes().isEmpty()); //checkAndMutateRowSettings - verifyDisabledRetry(dataSettings.checkAndMutateRowSettings().getRetrySettings()); - assertTrue(dataSettings.checkAndMutateRowSettings().getRetryableCodes().isEmpty()); + verifyDisabledRetry(dataSettings.getStubSettings().checkAndMutateRowSettings().getRetrySettings()); + assertTrue(dataSettings.getStubSettings().checkAndMutateRowSettings().getRetryableCodes().isEmpty()); } private void verifyRetry(RetrySettings retrySettings) { @@ -298,7 +296,7 @@ public void testWhenBulkOptionIsDisabled() throws IOException { .setBulkOptions(bulkOptions) .build(); dataSettings = BigtableVeneerSettingsFactory.createBigtableDataSettings(options); - assertFalse(dataSettings.bulkMutationsSettings().getBatchingSettings().getIsEnabled()); + assertFalse(dataSettings.getStubSettings().bulkMutateRowsSettings().getBatchingSettings().getIsEnabled()); } @Test @@ -313,7 +311,7 @@ public void testBulkMutation() throws IOException { dataSettings = BigtableVeneerSettingsFactory.createBigtableDataSettings(options); BulkOptions bulkOptions = options.getBulkOptions(); - BatchingSettings batchingSettings = dataSettings.bulkMutationsSettings().getBatchingSettings(); + BatchingSettings batchingSettings = dataSettings.getStubSettings().bulkMutateRowsSettings().getBatchingSettings(); long outstandingElementCount = bulkOptions.getMaxInflightRpcs() * bulkOptions.getBulkMaxRowKeyCount();