This is an automated email from the ASF dual-hosted git repository. ctubbsii pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/accumulo.git
The following commit(s) were added to refs/heads/main by this push: new 7448970bc2 Remove Connector and Instance legacy client APIs (#3073) 7448970bc2 is described below commit 7448970bc277bf1365bc0304b7d8f74412547617 Author: Christopher Tubbs <ctubb...@apache.org> AuthorDate: Tue Nov 8 23:10:13 2022 -0500 Remove Connector and Instance legacy client APIs (#3073) * Remove Connector and Instance legacy client APIs * Improve javadoc wording comparing AccumuloClient with Connector --- .../accumulo/core/client/AccumuloClient.java | 10 +- .../apache/accumulo/core/client/BatchWriter.java | 2 +- .../org/apache/accumulo/core/client/Connector.java | 309 -------------------- .../org/apache/accumulo/core/client/Instance.java | 153 ---------- .../core/client/MutationsRejectedException.java | 29 -- .../core/client/TableOfflineException.java | 8 - .../accumulo/core/client/ZooKeeperInstance.java | 204 ------------- .../accumulo/core/clientImpl/ClientContext.java | 50 ++-- .../accumulo/core/clientImpl/ConnectorImpl.java | 211 -------------- .../core/fate/zookeeper/ZooCacheFactory.java | 10 +- .../accumulo/core/singletons/SingletonManager.java | 27 +- .../org/apache/accumulo/core/util/CleanUp.java | 87 ------ .../core/client/ZooKeeperInstanceTest.java | 197 ------------- .../core/singletons/SingletonManagerTest.java | 43 +-- .../accumulo/minicluster/MiniAccumuloCluster.java | 16 -- .../accumulo/minicluster/MiniAccumuloInstance.java | 53 ---- .../MiniAccumuloClusterClasspathTest.java | 55 ++-- .../MiniAccumuloClusterExistingZooKeepersTest.java | 31 +- .../MiniAccumuloClusterStartStopTest.java | 9 +- .../minicluster/MiniAccumuloClusterTest.java | 127 +++++---- .../server/security/SystemCredentialsTest.java | 16 -- .../main/java/org/apache/accumulo/shell/Shell.java | 4 +- .../accumulo/shell/commands/ScriptCommand.java | 317 --------------------- .../accumulo/test/functional/AccumuloClientIT.java | 36 --- .../apache/accumulo/test/functional/CleanUpIT.java | 170 ----------- 25 files changed, 162 insertions(+), 2012 deletions(-) diff --git a/core/src/main/java/org/apache/accumulo/core/client/AccumuloClient.java b/core/src/main/java/org/apache/accumulo/core/client/AccumuloClient.java index 70537040dc..5c96ebfe9c 100644 --- a/core/src/main/java/org/apache/accumulo/core/client/AccumuloClient.java +++ b/core/src/main/java/org/apache/accumulo/core/client/AccumuloClient.java @@ -51,11 +51,11 @@ import org.apache.accumulo.core.security.Authorizations; * </pre> * * <p> - * If migrating code from Connector to AccumuloClient an important difference to consider is that - * AccumuloClient is closable and Connector is not. Connector uses static resources and therefore - * creating them is cheap. AccumuloClient attempts to clean up resources on close, so constantly - * creating them could perform worse than Connector. Therefore, it would be better to create an - * AccumuloClient and pass it around. + * An important difference with the legacy Connector to consider is that Connector reused global + * static resources. AccumuloClient, however, attempts to clean up its resources on close. So, + * creating many AccumuloClient objects will perform worse than creating many Connectors did. + * Therefore, it is suggested to reuse AccumuloClient instances where possible, rather than create + * many of them. * * <p> * AccumuloClient objects are intended to be thread-safe, and can be used by multiple threads. diff --git a/core/src/main/java/org/apache/accumulo/core/client/BatchWriter.java b/core/src/main/java/org/apache/accumulo/core/client/BatchWriter.java index e077a8d803..e1d81bf02a 100644 --- a/core/src/main/java/org/apache/accumulo/core/client/BatchWriter.java +++ b/core/src/main/java/org/apache/accumulo/core/client/BatchWriter.java @@ -23,7 +23,7 @@ import org.apache.accumulo.core.data.Mutation; /** * Send Mutations to a single Table in Accumulo. * <p> - * When the user uses a Connector to create a BatchWriter, they specify how much memory and how many + * When the user uses a client to create a BatchWriter, they specify how much memory and how many * threads it should use. As the user adds mutations to the batch writer, it buffers them. Once the * buffered mutations have used half of the user specified buffer, the mutations are dumped into the * background to be written by a thread pool. If the user specified memory completely fills up, then diff --git a/core/src/main/java/org/apache/accumulo/core/client/Connector.java b/core/src/main/java/org/apache/accumulo/core/client/Connector.java deleted file mode 100644 index 7a639cec5c..0000000000 --- a/core/src/main/java/org/apache/accumulo/core/client/Connector.java +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.accumulo.core.client; - -import org.apache.accumulo.core.client.admin.InstanceOperations; -import org.apache.accumulo.core.client.admin.NamespaceOperations; -import org.apache.accumulo.core.client.admin.ReplicationOperations; -import org.apache.accumulo.core.client.admin.SecurityOperations; -import org.apache.accumulo.core.client.admin.TableOperations; -import org.apache.accumulo.core.clientImpl.ClientContext; -import org.apache.accumulo.core.clientImpl.ConnectorImpl; -import org.apache.accumulo.core.security.Authorizations; - -/** - * Connector connects to an Accumulo instance and allows the user to request readers and writers for - * the instance as well as various objects that permit administrative operations. - * - * The Connector enforces security on the client side by forcing all API calls to be accompanied by - * user credentials. - * - * @deprecated since 2.0.0. Use {@link AccumuloClient} for writing new code. Connector is available - * for existing code. Use {@link #from(AccumuloClient)} as a bridge between the two. - */ -@Deprecated(since = "2.0.0") -public abstract class Connector { - - /** - * Factory method to create a BatchScanner connected to Accumulo. - * - * @param tableName - * the name of the table to query - * @param authorizations - * A set of authorization labels that will be checked against the column visibility of - * each key in order to filter data. The authorizations passed in must be a subset of the - * accumulo user's set of authorizations. If the accumulo user has authorizations (A1, - * A2) and authorizations (A2, A3) are passed, then an exception will be thrown. - * @param numQueryThreads - * the number of concurrent threads to spawn for querying - * - * @return BatchScanner object for configuring and querying - * @throws TableNotFoundException - * when the specified table doesn't exist - */ - public abstract BatchScanner createBatchScanner(String tableName, Authorizations authorizations, - int numQueryThreads) throws TableNotFoundException; - - /** - * Factory method to create a BatchDeleter connected to Accumulo. - * - * @param tableName - * the name of the table to query and delete from - * @param authorizations - * A set of authorization labels that will be checked against the column visibility of - * each key in order to filter data. The authorizations passed in must be a subset of the - * accumulo user's set of authorizations. If the accumulo user has authorizations (A1, - * A2) and authorizations (A2, A3) are passed, then an exception will be thrown. - * @param numQueryThreads - * the number of concurrent threads to spawn for querying - * @param maxMemory - * size in bytes of the maximum memory to batch before writing - * @param maxLatency - * size in milliseconds; set to 0 or Long.MAX_VALUE to allow the maximum time to hold a - * batch before writing - * @param maxWriteThreads - * the maximum number of threads to use for writing data to the tablet servers - * - * @return BatchDeleter object for configuring and deleting - * @throws TableNotFoundException - * when the specified table doesn't exist - * @deprecated since 1.5.0; Use - * {@link #createBatchDeleter(String, Authorizations, int, BatchWriterConfig)} - * instead. - */ - @Deprecated(since = "1.5.0") - public abstract BatchDeleter createBatchDeleter(String tableName, Authorizations authorizations, - int numQueryThreads, long maxMemory, long maxLatency, int maxWriteThreads) - throws TableNotFoundException; - - /** - * Factory method to create BatchDeleter - * - * @param tableName - * the name of the table to query and delete from - * @param authorizations - * A set of authorization labels that will be checked against the column visibility of - * each key in order to filter data. The authorizations passed in must be a subset of the - * accumulo user's set of authorizations. If the accumulo user has authorizations (A1, - * A2) and authorizations (A2, A3) are passed, then an exception will be thrown. - * @param numQueryThreads - * the number of concurrent threads to spawn for querying - * @param config - * configuration used to create batch writer. This config takes precedence. Any unset - * values will be merged with config set when the Connector was created. If no config was - * set during Connector creation, BatchWriterConfig defaults will be used. - * @return BatchDeleter object for configuring and deleting - * @since 1.5.0 - */ - public abstract BatchDeleter createBatchDeleter(String tableName, Authorizations authorizations, - int numQueryThreads, BatchWriterConfig config) throws TableNotFoundException; - - /** - * Factory method to create a BatchWriter connected to Accumulo. - * - * @param tableName - * the name of the table to insert data into - * @param maxMemory - * size in bytes of the maximum memory to batch before writing - * @param maxLatency - * time in milliseconds; set to 0 or Long.MAX_VALUE to allow the maximum time to hold a - * batch before writing - * @param maxWriteThreads - * the maximum number of threads to use for writing data to the tablet servers - * - * @return BatchWriter object for configuring and writing data to - * @throws TableNotFoundException - * when the specified table doesn't exist - * @deprecated since 1.5.0; Use {@link #createBatchWriter(String, BatchWriterConfig)} instead. - */ - @Deprecated(since = "1.5.0") - public abstract BatchWriter createBatchWriter(String tableName, long maxMemory, long maxLatency, - int maxWriteThreads) throws TableNotFoundException; - - /** - * Factory method to create a BatchWriter connected to Accumulo. - * - * @param tableName - * the name of the table to insert data into - * @param config - * configuration used to create batch writer. This config will take precedence. Any unset - * values will merged with config set when the Connector was created. If no config was - * set during Connector creation, BatchWriterConfig defaults will be used. - * @return BatchWriter object for configuring and writing data to - * @since 1.5.0 - */ - public abstract BatchWriter createBatchWriter(String tableName, BatchWriterConfig config) - throws TableNotFoundException; - - /** - * Factory method to create a Multi-Table BatchWriter connected to Accumulo. Multi-table batch - * writers can queue data for multiple tables, which is good for ingesting data into multiple - * tables from the same source - * - * @param maxMemory - * size in bytes of the maximum memory to batch before writing - * @param maxLatency - * size in milliseconds; set to 0 or Long.MAX_VALUE to allow the maximum time to hold a - * batch before writing - * @param maxWriteThreads - * the maximum number of threads to use for writing data to the tablet servers - * - * @return MultiTableBatchWriter object for configuring and writing data to - * @deprecated since 1.5.0; Use {@link #createMultiTableBatchWriter(BatchWriterConfig)} instead. - */ - @Deprecated(since = "1.5.0") - public abstract MultiTableBatchWriter createMultiTableBatchWriter(long maxMemory, long maxLatency, - int maxWriteThreads); - - /** - * Factory method to create a Multi-Table BatchWriter connected to Accumulo. Multi-table batch - * writers can queue data for multiple tables. Also data for multiple tables can be sent to a - * server in a single batch. Its an efficient way to ingest data into multiple tables from a - * single process. - * - * @param config - * configuration used to create multi-table batch writer. This config will take - * precedence. Any unset values will merged with config set when the Connector was - * created. If no config was set during Connector creation, BatchWriterConfig defaults - * will be used. - * @return MultiTableBatchWriter object for configuring and writing data to - * @since 1.5.0 - */ - public abstract MultiTableBatchWriter createMultiTableBatchWriter(BatchWriterConfig config); - - /** - * Factory method to create a Scanner connected to Accumulo. - * - * @param tableName - * the name of the table to query data from - * @param authorizations - * A set of authorization labels that will be checked against the column visibility of - * each key in order to filter data. The authorizations passed in must be a subset of the - * accumulo user's set of authorizations. If the accumulo user has authorizations (A1, - * A2) and authorizations (A2, A3) are passed, then an exception will be thrown. - * - * @return Scanner object for configuring and querying data with - * @throws TableNotFoundException - * when the specified table doesn't exist - */ - public abstract Scanner createScanner(String tableName, Authorizations authorizations) - throws TableNotFoundException; - - /** - * Factory method to create a ConditionalWriter connected to Accumulo. - * - * @param tableName - * the name of the table to query data from - * @param config - * configuration used to create conditional writer - * - * @return ConditionalWriter object for writing ConditionalMutations - * @throws TableNotFoundException - * when the specified table doesn't exist - * @since 1.6.0 - */ - public abstract ConditionalWriter createConditionalWriter(String tableName, - ConditionalWriterConfig config) throws TableNotFoundException; - - /** - * Accessor method for internal instance object. - * - * @return the internal instance object - */ - public abstract Instance getInstance(); - - /** - * Get the current user for this connector - * - * @return the user name - */ - public abstract String whoami(); - - /** - * Retrieves a TableOperations object to perform table functions, such as create and delete. - * - * @return an object to manipulate tables - */ - public abstract TableOperations tableOperations(); - - /** - * Retrieves a NamespaceOperations object to perform namespace functions, such as create and - * delete. - * - * @return an object to manipulate namespaces - */ - public abstract NamespaceOperations namespaceOperations(); - - /** - * Retrieves a SecurityOperations object to perform user security operations, such as creating - * users. - * - * @return an object to modify users and permissions - */ - public abstract SecurityOperations securityOperations(); - - /** - * Retrieves an InstanceOperations object to modify instance configuration. - * - * @return an object to modify instance configuration - */ - public abstract InstanceOperations instanceOperations(); - - /** - * Retrieves a ReplicationOperations object to manage replication configuration. - * - * @return an object to modify replication configuration - * @since 1.7.0 - */ - public abstract ReplicationOperations replicationOperations(); - - /** - * Creates a Connector from an AccumuloClient. This Connector will no longer work after the - * AccumuloClient is closed. Also anything derived from the Connector (like a Scanner for example) - * is unlikely to work after the AccumuloClient is closed. - * - * @since 2.0 - */ - public static Connector from(AccumuloClient client) - throws AccumuloSecurityException, AccumuloException { - return new ConnectorImpl((ClientContext) client); - } - - /** - * Creates a new Accumulo Client from a Connector. The returned client should be closed and - * closing it will not affect the Connector from which it was derived. This method is useful for - * cases where code written using Connector must call code written using AccumuloClient. Below is - * an example. - * - * <pre> - * <code> - * Connector conn = getMyConnector(); - * try(AccumuloClient client = Connector.newClient(conn) { - * doSomething(client); - * } - * </code> - * </pre> - * - * @since 2.1.0 - */ - public static AccumuloClient newClient(Connector conn) { - return Accumulo.newClient().from(((ConnectorImpl) conn).getAccumuloClient().getProperties()) - .build(); - } -} diff --git a/core/src/main/java/org/apache/accumulo/core/client/Instance.java b/core/src/main/java/org/apache/accumulo/core/client/Instance.java deleted file mode 100644 index 45e664e8d4..0000000000 --- a/core/src/main/java/org/apache/accumulo/core/client/Instance.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.accumulo.core.client; - -import java.nio.ByteBuffer; -import java.util.List; - -import org.apache.accumulo.core.client.security.tokens.AuthenticationToken; -import org.apache.accumulo.core.client.security.tokens.PasswordToken; - -/** - * This class represents the information a client needs to know to connect to an instance of - * accumulo. - * - * @deprecated since 2.0.0, use {@link Accumulo#newClient()} and {@link java.util.Properties} - * instead - */ -@Deprecated(since = "2.0.0") -public interface Instance { - /** - * Returns the location of the tablet server that is serving the root tablet. - * - * @return location in "hostname:port" form - */ - String getRootTabletLocation(); - - /** - * Returns the location(s) of the accumulo manager and any redundant servers. - * - * @return a list of locations in "hostname:port" form - */ - List<String> getMasterLocations(); - - /** - * Returns a unique string that identifies this instance of accumulo. - * - * @return a UUID - */ - String getInstanceID(); - - /** - * Returns the instance name given at system initialization time. - * - * @return current instance name - */ - String getInstanceName(); - - /** - * Returns a comma-separated list of zookeeper servers the instance is using. - * - * @return the zookeeper servers this instance is using in "hostname:port" form - */ - String getZooKeepers(); - - /** - * Returns the zookeeper connection timeout. - * - * @return the configured timeout to connect to zookeeper - */ - int getZooKeepersSessionTimeOut(); - - /** - * Returns a connection to accumulo. - * - * @param user - * a valid accumulo user - * @param pass - * A UTF-8 encoded password. The password may be cleared after making this call. - * @return the accumulo Connector - * @throws AccumuloException - * when a generic exception occurs - * @throws AccumuloSecurityException - * when a user's credentials are invalid - * @deprecated since 1.5, use {@link #getConnector(String, AuthenticationToken)} with - * {@link PasswordToken} - */ - @Deprecated(since = "1.5.0") - default Connector getConnector(String user, byte[] pass) - throws AccumuloException, AccumuloSecurityException { - return getConnector(user, new PasswordToken(pass)); - } - - /** - * Returns a connection to accumulo. - * - * @param user - * a valid accumulo user - * @param pass - * A UTF-8 encoded password. The password may be cleared after making this call. - * @return the accumulo Connector - * @throws AccumuloException - * when a generic exception occurs - * @throws AccumuloSecurityException - * when a user's credentials are invalid - * @deprecated since 1.5, use {@link #getConnector(String, AuthenticationToken)} with - * {@link PasswordToken} - */ - @Deprecated(since = "1.5.0") - default Connector getConnector(String user, ByteBuffer pass) - throws AccumuloException, AccumuloSecurityException { - return getConnector(user, new PasswordToken(pass)); - } - - /** - * Returns a connection to this instance of accumulo. - * - * @param user - * a valid accumulo user - * @param pass - * If a mutable CharSequence is passed in, it may be cleared after this call. - * @return the accumulo Connector - * @throws AccumuloException - * when a generic exception occurs - * @throws AccumuloSecurityException - * when a user's credentials are invalid - * @deprecated since 1.5, use {@link #getConnector(String, AuthenticationToken)} with - * {@link PasswordToken} - */ - @Deprecated(since = "1.5.0") - default Connector getConnector(String user, CharSequence pass) - throws AccumuloException, AccumuloSecurityException { - return getConnector(user, new PasswordToken(pass)); - } - - /** - * Returns a connection to this instance of accumulo. - * - * @param principal - * a valid accumulo user - * @param token - * Use the token type configured for the Accumulo instance you are connecting to. An - * Accumulo instance with default configurations will use {@link PasswordToken} - * @since 1.5.0 - */ - Connector getConnector(String principal, AuthenticationToken token) - throws AccumuloException, AccumuloSecurityException; -} diff --git a/core/src/main/java/org/apache/accumulo/core/client/MutationsRejectedException.java b/core/src/main/java/org/apache/accumulo/core/client/MutationsRejectedException.java index ffe39b9dc4..47852d3104 100644 --- a/core/src/main/java/org/apache/accumulo/core/client/MutationsRejectedException.java +++ b/core/src/main/java/org/apache/accumulo/core/client/MutationsRejectedException.java @@ -43,35 +43,6 @@ public class MutationsRejectedException extends AccumuloException { private final HashSet<String> es = new HashSet<>(); private final int unknownErrors; - /** - * - * @param cvsList - * list of constraint violations - * @param hashMap - * authorization failures - * @param serverSideErrors - * server side errors - * @param unknownErrors - * number of unknown errors - * - * @since 1.7.0 - * @deprecated since 2.0.0, replaced by - * {@link #MutationsRejectedException(AccumuloClient, List, Map, Collection, int, Throwable)} - */ - @Deprecated(since = "2.0.0") - public MutationsRejectedException(Instance instance, List<ConstraintViolationSummary> cvsList, - Map<TabletId,Set<SecurityErrorCode>> hashMap, Collection<String> serverSideErrors, - int unknownErrors, Throwable cause) { - super( - "# constraint violations : " + cvsList.size() + " security codes: " + hashMap.toString() - + " # server errors " + serverSideErrors.size() + " # exceptions " + unknownErrors, - cause); - this.cvsl.addAll(cvsList); - this.af.putAll(hashMap); - this.es.addAll(serverSideErrors); - this.unknownErrors = unknownErrors; - } - /** * Creates Mutations rejected exception * diff --git a/core/src/main/java/org/apache/accumulo/core/client/TableOfflineException.java b/core/src/main/java/org/apache/accumulo/core/client/TableOfflineException.java index 2dbeb1476d..bd0e2661e6 100644 --- a/core/src/main/java/org/apache/accumulo/core/client/TableOfflineException.java +++ b/core/src/main/java/org/apache/accumulo/core/client/TableOfflineException.java @@ -24,14 +24,6 @@ public class TableOfflineException extends RuntimeException { private static final long serialVersionUID = 1L; - /** - * @deprecated since 2.0.0, replaced by {@link #TableOfflineException(String)} - */ - @Deprecated(since = "2.0.0") - public TableOfflineException(Instance instance, String tableId) { - super("Table with ID (" + tableId + ") is offline"); - } - /** * @since 2.0.0 */ diff --git a/core/src/main/java/org/apache/accumulo/core/client/ZooKeeperInstance.java b/core/src/main/java/org/apache/accumulo/core/client/ZooKeeperInstance.java deleted file mode 100644 index 3954b9f12e..0000000000 --- a/core/src/main/java/org/apache/accumulo/core/client/ZooKeeperInstance.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.accumulo.core.client; - -import static com.google.common.base.Preconditions.checkArgument; -import static java.util.concurrent.TimeUnit.SECONDS; - -import java.util.List; -import java.util.Properties; - -import org.apache.accumulo.core.Constants; -import org.apache.accumulo.core.client.security.tokens.AuthenticationToken; -import org.apache.accumulo.core.clientImpl.ClientConfConverter; -import org.apache.accumulo.core.clientImpl.ClientContext; -import org.apache.accumulo.core.clientImpl.ClientInfo; -import org.apache.accumulo.core.clientImpl.ClientInfoImpl; -import org.apache.accumulo.core.clientImpl.InstanceOperationsImpl; -import org.apache.accumulo.core.conf.AccumuloConfiguration; -import org.apache.accumulo.core.conf.ClientProperty; -import org.apache.accumulo.core.conf.ConfigurationTypeHelper; -import org.apache.accumulo.core.data.InstanceId; -import org.apache.accumulo.core.fate.zookeeper.ZooCache; -import org.apache.accumulo.core.fate.zookeeper.ZooCacheFactory; -import org.apache.accumulo.core.metadata.schema.TabletMetadata.Location; -import org.apache.accumulo.core.metadata.schema.TabletMetadata.LocationType; -import org.apache.accumulo.core.metadata.schema.TabletsMetadata; -import org.apache.accumulo.core.singletons.SingletonManager; -import org.apache.accumulo.core.singletons.SingletonManager.Mode; -import org.apache.accumulo.core.singletons.SingletonReservation; -import org.apache.accumulo.core.util.OpTimer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * An implementation of instance that looks in zookeeper to find information needed to connect to an - * instance of accumulo. - * - * <p> - * The advantage of using zookeeper to obtain information about accumulo is that zookeeper is highly - * available, very responsive, and supports caching. - * - * <p> - * Because it is possible for multiple instances of accumulo to share a single set of zookeeper - * servers, all constructors require an accumulo instance name. - * - * If you do not know the instance names then run accumulo - * org.apache.accumulo.server.util.ListInstances on an accumulo server. - * - * @deprecated since 2.0.0, Use {@link Accumulo#newClient()} instead - */ -@Deprecated(since = "2.0.0") -public class ZooKeeperInstance implements Instance { - - private static final Logger log = LoggerFactory.getLogger(ZooKeeperInstance.class); - - private String instanceId = null; - private String instanceName = null; - - private final ZooCache zooCache; - - private final String zooKeepers; - - private final int zooKeepersSessionTimeOut; - - private ClientConfiguration clientConf; - - /** - * - * @param instanceName - * The name of specific accumulo instance. This is set at initialization time. - * @param zooKeepers - * A comma separated list of zoo keeper server locations. Each location can contain an - * optional port, of the format host:port. - */ - public ZooKeeperInstance(String instanceName, String zooKeepers) { - this(ClientConfiguration.loadDefault().withInstance(instanceName).withZkHosts(zooKeepers)); - } - - ZooKeeperInstance(ClientConfiguration config, ZooCacheFactory zcf) { - checkArgument(config != null, "config is null"); - // Enable singletons before before getting a zoocache - SingletonManager.setMode(Mode.CONNECTOR); - this.clientConf = config; - this.instanceId = clientConf.get(ClientConfiguration.ClientProperty.INSTANCE_ID); - this.instanceName = clientConf.get(ClientConfiguration.ClientProperty.INSTANCE_NAME); - if ((instanceId == null) == (instanceName == null)) - throw new IllegalArgumentException( - "Expected exactly one of instanceName and instanceId to be set; " - + (instanceName == null ? "neither" : "both") + " were set"); - this.zooKeepers = clientConf.get(ClientConfiguration.ClientProperty.INSTANCE_ZK_HOST); - this.zooKeepersSessionTimeOut = (int) ConfigurationTypeHelper - .getTimeInMillis(clientConf.get(ClientConfiguration.ClientProperty.INSTANCE_ZK_TIMEOUT)); - zooCache = zcf.getZooCache(zooKeepers, zooKeepersSessionTimeOut); - if (instanceName != null) { - // Validates that the provided instanceName actually exists - getInstanceID(); - } - } - - /** - * @param config - * Client configuration for specifying connection options. See - * {@link ClientConfiguration} which extends Configuration with convenience methods - * specific to Accumulo. - * @since 1.9.0 - */ - public ZooKeeperInstance(ClientConfiguration config) { - this(config, new ZooCacheFactory()); - } - - @Override - public String getInstanceID() { - if (instanceId == null) { - instanceId = ClientContext.getInstanceID(zooCache, instanceName).canonical(); - } - ClientContext.verifyInstanceId(zooCache, instanceId, instanceName); - return instanceId; - } - - @Override - public List<String> getMasterLocations() { - return ClientContext.getManagerLocations(zooCache, getInstanceID()); - } - - @Override - public String getRootTabletLocation() { - OpTimer timer = null; - - if (log.isTraceEnabled()) { - log.trace("tid={} Looking up root tablet location in zookeeper.", - Thread.currentThread().getId()); - timer = new OpTimer().start(); - } - - Location loc = TabletsMetadata - .getRootMetadata(Constants.ZROOT + "/" + getInstanceID(), zooCache).getLocation(); - - if (timer != null) { - timer.stop(); - log.trace("tid={} Found root tablet at {} in {}", Thread.currentThread().getId(), loc, - String.format("%.3f secs", timer.scale(SECONDS))); - } - - if (loc == null || loc.getType() != LocationType.CURRENT) { - return null; - } - - return loc.getHostPort(); - } - - @Override - public String getInstanceName() { - if (instanceName == null) - instanceName = - InstanceOperationsImpl.lookupInstanceName(zooCache, InstanceId.of(getInstanceID())); - - return instanceName; - } - - @Override - public String getZooKeepers() { - return zooKeepers; - } - - @Override - public int getZooKeepersSessionTimeOut() { - return zooKeepersSessionTimeOut; - } - - @Override - public Connector getConnector(String principal, AuthenticationToken token) - throws AccumuloException, AccumuloSecurityException { - Properties properties = ClientConfConverter.toProperties(clientConf); - properties.setProperty(ClientProperty.AUTH_PRINCIPAL.getKey(), principal); - properties.setProperty(ClientProperty.INSTANCE_NAME.getKey(), getInstanceName()); - ClientInfo info = new ClientInfoImpl(properties, token); - AccumuloConfiguration serverConf = ClientConfConverter.toAccumuloConf(properties); - return new org.apache.accumulo.core.clientImpl.ConnectorImpl( - new ClientContext(SingletonReservation.noop(), info, serverConf, null)); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(64); - sb.append("ZooKeeperInstance: ").append(getInstanceName()).append(" ").append(getZooKeepers()); - return sb.toString(); - } -} diff --git a/core/src/main/java/org/apache/accumulo/core/clientImpl/ClientContext.java b/core/src/main/java/org/apache/accumulo/core/clientImpl/ClientContext.java index 67d24ab448..284ae216f9 100644 --- a/core/src/main/java/org/apache/accumulo/core/clientImpl/ClientContext.java +++ b/core/src/main/java/org/apache/accumulo/core/clientImpl/ClientContext.java @@ -21,7 +21,6 @@ package org.apache.accumulo.core.clientImpl; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Suppliers.memoizeWithExpiration; import static java.nio.charset.StandardCharsets.UTF_8; -import static java.util.Objects.requireNonNull; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.SECONDS; import static org.apache.accumulo.core.metadata.schema.TabletMetadata.ColumnType.LOCATION; @@ -509,13 +508,8 @@ public class ClientContext implements AccumuloClient { */ public List<String> getManagerLocations() { ensureOpen(); - return getManagerLocations(zooCache, getInstanceID().canonical()); - } - - // available only for sharing code with old ZooKeeperInstance - public static List<String> getManagerLocations(ZooCache zooCache, String instanceId) { var zLockManagerPath = - ServiceLock.path(Constants.ZROOT + "/" + instanceId + Constants.ZMANAGER_LOCK); + ServiceLock.path(Constants.ZROOT + "/" + getInstanceID() + Constants.ZMANAGER_LOCK); OpTimer timer = null; @@ -548,37 +542,27 @@ public class ClientContext implements AccumuloClient { public InstanceId getInstanceID() { ensureOpen(); if (instanceId == null) { + // lookup by name final String instanceName = info.getInstanceName(); - instanceId = getInstanceID(zooCache, instanceName); - verifyInstanceId(zooCache, instanceId.canonical(), instanceName); + String instanceNamePath = Constants.ZROOT + Constants.ZINSTANCES + "/" + instanceName; + byte[] data = zooCache.get(instanceNamePath); + if (data == null) { + throw new RuntimeException( + "Instance name " + instanceName + " does not exist in zookeeper. " + + "Run \"accumulo org.apache.accumulo.server.util.ListInstances\" to see a list."); + } + String instanceIdString = new String(data, UTF_8); + // verify that the instanceId found via the instanceName actually exists as an instance + if (zooCache.get(Constants.ZROOT + "/" + instanceIdString) == null) { + throw new RuntimeException("Instance id " + instanceIdString + + (instanceName == null ? "" : " pointed to by the name " + instanceName) + + " does not exist in zookeeper"); + } + instanceId = InstanceId.of(instanceIdString); } return instanceId; } - // available only for sharing code with old ZooKeeperInstance - public static InstanceId getInstanceID(ZooCache zooCache, String instanceName) { - requireNonNull(zooCache, "zooCache cannot be null"); - requireNonNull(instanceName, "instanceName cannot be null"); - String instanceNamePath = Constants.ZROOT + Constants.ZINSTANCES + "/" + instanceName; - byte[] data = zooCache.get(instanceNamePath); - if (data == null) { - throw new RuntimeException("Instance name " + instanceName + " does not exist in zookeeper. " - + "Run \"accumulo org.apache.accumulo.server.util.ListInstances\" to see a list."); - } - return InstanceId.of(new String(data, UTF_8)); - } - - // available only for sharing code with old ZooKeeperInstance - public static void verifyInstanceId(ZooCache zooCache, String instanceId, String instanceName) { - requireNonNull(zooCache, "zooCache cannot be null"); - requireNonNull(instanceId, "instanceId cannot be null"); - if (zooCache.get(Constants.ZROOT + "/" + instanceId) == null) { - throw new RuntimeException("Instance id " + instanceId - + (instanceName == null ? "" : " pointed to by the name " + instanceName) - + " does not exist in zookeeper"); - } - } - public String getZooKeeperRoot() { ensureOpen(); return ZooUtil.getRoot(getInstanceID()); diff --git a/core/src/main/java/org/apache/accumulo/core/clientImpl/ConnectorImpl.java b/core/src/main/java/org/apache/accumulo/core/clientImpl/ConnectorImpl.java deleted file mode 100644 index b5341fe8ca..0000000000 --- a/core/src/main/java/org/apache/accumulo/core/clientImpl/ConnectorImpl.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.accumulo.core.clientImpl; - -import static java.util.concurrent.TimeUnit.MILLISECONDS; - -import java.util.List; - -import org.apache.accumulo.core.client.AccumuloException; -import org.apache.accumulo.core.client.AccumuloSecurityException; -import org.apache.accumulo.core.client.BatchDeleter; -import org.apache.accumulo.core.client.BatchScanner; -import org.apache.accumulo.core.client.BatchWriter; -import org.apache.accumulo.core.client.BatchWriterConfig; -import org.apache.accumulo.core.client.ConditionalWriter; -import org.apache.accumulo.core.client.ConditionalWriterConfig; -import org.apache.accumulo.core.client.MultiTableBatchWriter; -import org.apache.accumulo.core.client.Scanner; -import org.apache.accumulo.core.client.TableNotFoundException; -import org.apache.accumulo.core.client.admin.InstanceOperations; -import org.apache.accumulo.core.client.admin.NamespaceOperations; -import org.apache.accumulo.core.client.admin.ReplicationOperations; -import org.apache.accumulo.core.client.admin.SecurityOperations; -import org.apache.accumulo.core.client.admin.TableOperations; -import org.apache.accumulo.core.client.security.tokens.AuthenticationToken; -import org.apache.accumulo.core.clientImpl.thrift.SecurityErrorCode; -import org.apache.accumulo.core.rpc.clients.ThriftClientTypes; -import org.apache.accumulo.core.security.Authorizations; -import org.apache.accumulo.core.singletons.SingletonManager; -import org.apache.accumulo.core.singletons.SingletonManager.Mode; -import org.apache.accumulo.core.trace.TraceUtil; - -/** - * This class now delegates to {@link ClientContext}, except for the methods which were not copied - * over to that. - */ -@Deprecated(since = "2.0.0") -public class ConnectorImpl extends org.apache.accumulo.core.client.Connector { - - private static final String SYSTEM_TOKEN_NAME = - "org.apache.accumulo.server.security.SystemCredentials$SystemToken"; - private final ClientContext context; - - public ConnectorImpl(ClientContext context) throws AccumuloSecurityException, AccumuloException { - this.context = context; - SingletonManager.setMode(Mode.CONNECTOR); - if (context.getCredentials().getToken().isDestroyed()) - throw new AccumuloSecurityException(context.getCredentials().getPrincipal(), - SecurityErrorCode.TOKEN_EXPIRED); - // Skip fail fast for system services; string literal for class name, to avoid dependency on - // server jar - final String tokenClassName = context.getCredentials().getToken().getClass().getName(); - if (!SYSTEM_TOKEN_NAME.equals(tokenClassName)) { - if (!ThriftClientTypes.CLIENT.execute(context, - client -> client.authenticate(TraceUtil.traceInfo(), context.rpcCreds()))) { - throw new AccumuloSecurityException("Authentication failed, access denied", - SecurityErrorCode.BAD_CREDENTIALS); - } - } - } - - public ClientContext getAccumuloClient() { - return context; - } - - @Override - public org.apache.accumulo.core.client.Instance getInstance() { - return new org.apache.accumulo.core.client.Instance() { - @Override - public String getRootTabletLocation() { - return context.getRootTabletLocation(); - } - - @Override - public List<String> getMasterLocations() { - return context.getManagerLocations(); - } - - @Override - public String getInstanceID() { - return context.getInstanceID().canonical(); - } - - @Override - public String getInstanceName() { - return context.getInstanceName(); - } - - @Override - public String getZooKeepers() { - return context.getZooKeepers(); - } - - @Override - public int getZooKeepersSessionTimeOut() { - return context.getZooKeepersSessionTimeOut(); - } - - @Override - public org.apache.accumulo.core.client.Connector getConnector(String principal, - AuthenticationToken token) throws AccumuloException, AccumuloSecurityException { - return org.apache.accumulo.core.client.Connector.from(context); - } - }; - } - - @Override - public BatchScanner createBatchScanner(String tableName, Authorizations authorizations, - int numQueryThreads) throws TableNotFoundException { - return context.createBatchScanner(tableName, authorizations, numQueryThreads); - } - - @Override - public BatchDeleter createBatchDeleter(String tableName, Authorizations authorizations, - int numQueryThreads, long maxMemory, long maxLatency, int maxWriteThreads) - throws TableNotFoundException { - return context.createBatchDeleter(tableName, authorizations, numQueryThreads, - new BatchWriterConfig().setMaxMemory(maxMemory).setMaxLatency(maxLatency, MILLISECONDS) - .setMaxWriteThreads(maxWriteThreads)); - } - - @Override - public BatchDeleter createBatchDeleter(String tableName, Authorizations authorizations, - int numQueryThreads, BatchWriterConfig config) throws TableNotFoundException { - return context.createBatchDeleter(tableName, authorizations, numQueryThreads, config); - } - - @Override - public BatchWriter createBatchWriter(String tableName, long maxMemory, long maxLatency, - int maxWriteThreads) throws TableNotFoundException { - return context.createBatchWriter(tableName, new BatchWriterConfig().setMaxMemory(maxMemory) - .setMaxLatency(maxLatency, MILLISECONDS).setMaxWriteThreads(maxWriteThreads)); - } - - @Override - public BatchWriter createBatchWriter(String tableName, BatchWriterConfig config) - throws TableNotFoundException { - return context.createBatchWriter(tableName, config); - } - - @Override - public MultiTableBatchWriter createMultiTableBatchWriter(long maxMemory, long maxLatency, - int maxWriteThreads) { - return context.createMultiTableBatchWriter(new BatchWriterConfig().setMaxMemory(maxMemory) - .setMaxLatency(maxLatency, MILLISECONDS).setMaxWriteThreads(maxWriteThreads)); - } - - @Override - public MultiTableBatchWriter createMultiTableBatchWriter(BatchWriterConfig config) { - return context.createMultiTableBatchWriter(config); - } - - @Override - public ConditionalWriter createConditionalWriter(String tableName, ConditionalWriterConfig config) - throws TableNotFoundException { - return context.createConditionalWriter(tableName, config); - } - - @Override - public Scanner createScanner(String tableName, Authorizations authorizations) - throws TableNotFoundException { - return context.createScanner(tableName, authorizations); - } - - @Override - public String whoami() { - return context.whoami(); - } - - @Override - public TableOperations tableOperations() { - return context.tableOperations(); - } - - @Override - public NamespaceOperations namespaceOperations() { - return context.namespaceOperations(); - } - - @Override - public SecurityOperations securityOperations() { - return context.securityOperations(); - } - - @Override - public InstanceOperations instanceOperations() { - return context.instanceOperations(); - } - - @Override - public ReplicationOperations replicationOperations() { - return context.replicationOperations(); - } - -} diff --git a/core/src/main/java/org/apache/accumulo/core/fate/zookeeper/ZooCacheFactory.java b/core/src/main/java/org/apache/accumulo/core/fate/zookeeper/ZooCacheFactory.java index 6587fac7a5..731af0443a 100644 --- a/core/src/main/java/org/apache/accumulo/core/fate/zookeeper/ZooCacheFactory.java +++ b/core/src/main/java/org/apache/accumulo/core/fate/zookeeper/ZooCacheFactory.java @@ -27,10 +27,12 @@ import org.apache.accumulo.core.singletons.SingletonService; /** * A factory for {@link ZooCache} instances. * <p> - * Implementation note: We are using the instances map to track all the instances that have been - * created, so we can explicitly close them when the last legacy client has gone away. This is part - * of the "SingletonManager" code, and it is likely that ZooCacheFactory and ZooKeeperInstance can - * be removed when legacy client code support is no longer required. + * Implementation note: We were using the instances map to track all the instances that have been + * created, so we could explicitly close them when the SingletonManager detected that the last + * legacy client (using Connector/ZooKeeperInstance) has gone away. This class may no longer be + * needed, since the legacy client code has been removed, so long as the ZooCache instances it is + * tracking are managed as resources within ClientContext or ServerContext, and explicitly closed + * when those are closed. */ public class ZooCacheFactory { diff --git a/core/src/main/java/org/apache/accumulo/core/singletons/SingletonManager.java b/core/src/main/java/org/apache/accumulo/core/singletons/SingletonManager.java index 4badba37ee..0a7a1bbb16 100644 --- a/core/src/main/java/org/apache/accumulo/core/singletons/SingletonManager.java +++ b/core/src/main/java/org/apache/accumulo/core/singletons/SingletonManager.java @@ -32,8 +32,7 @@ import com.google.common.base.Preconditions; * Historically, Accumulo client code that used Connector had no control over these singletons. The * new AccumuloClient API that replaces Connector is closeable. When all AccumuloClients are closed * then resources used by the singletons are released. This class coordinates releasing those - * resources. For compatibility purposes this class will not release resources when the user has - * created Connectors. + * resources. * * <p> * This class is intermediate solution to resource management. Ideally there would be no static @@ -62,9 +61,10 @@ public class SingletonManager { */ SERVER, /** - * In this mode singletons are never disabled unless the mode is set back to CLIENT. The user - * can do this by using util.CleanUp (an old API created for users). + * This mode was removed along with Connector in 3.0.0. It no longer does anything, but is kept + * here to preserve enum ordinals. */ + @Deprecated(since = "3.0.0") CONNECTOR, /** * In this mode singletons are permanently disabled and entering this mode prevents @@ -77,7 +77,6 @@ public class SingletonManager { private static long reservations; private static Mode mode; private static boolean enabled; - private static boolean transitionedFromClientToConnector; private static List<SingletonService> services; @VisibleForTesting @@ -85,7 +84,6 @@ public class SingletonManager { reservations = 0; mode = Mode.CLIENT; enabled = true; - transitionedFromClientToConnector = false; services = new ArrayList<>(); } @@ -158,16 +156,8 @@ public class SingletonManager { return; if (SingletonManager.mode == Mode.CLOSED) throw new IllegalStateException("Cannot leave closed mode once entered"); - if (SingletonManager.mode == Mode.CLIENT && mode == Mode.CONNECTOR) { - if (transitionedFromClientToConnector) { - throw new IllegalStateException("Can only transition from " + Mode.CLIENT + " to " - + Mode.CONNECTOR + " once. This error indicates that " - + "org.apache.accumulo.core.util.CleanUp.shutdownNow() was called and then later a " - + "Connector was created. Connectors can not be created after CleanUp.shutdownNow()" - + " is called."); - } - - transitionedFromClientToConnector = true; + if (mode == Mode.CONNECTOR) { + throw new IllegalArgumentException("CONNECTOR mode was removed"); } /* @@ -196,10 +186,9 @@ public class SingletonManager { } } else { // if we're in a disabled state AND - // the mode is CONNECTOR or SERVER or if there are active clients, + // the mode is SERVER or if there are active clients, // then enable everything - if (mode == Mode.CONNECTOR || mode == Mode.SERVER - || (mode == Mode.CLIENT && reservations > 0)) { + if (mode == Mode.SERVER || (mode == Mode.CLIENT && reservations > 0)) { services.forEach(SingletonManager::enable); enabled = true; } diff --git a/core/src/main/java/org/apache/accumulo/core/util/CleanUp.java b/core/src/main/java/org/apache/accumulo/core/util/CleanUp.java deleted file mode 100644 index c9ab72e2ad..0000000000 --- a/core/src/main/java/org/apache/accumulo/core/util/CleanUp.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.accumulo.core.util; - -import java.util.Set; - -import org.apache.accumulo.core.client.AccumuloClient; -import org.apache.accumulo.core.client.Connector; -import org.apache.accumulo.core.clientImpl.ConnectorImpl; -import org.apache.accumulo.core.singletons.SingletonManager; -import org.apache.accumulo.core.singletons.SingletonManager.Mode; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Connector uses static resource that create threads and use memory. The only way to clean up these - * static resource related to Connectors created using ZookeeperInstance is to use this class. - * - * <p> - * This class is not needed when only using {@link AccumuloClient}. The new AccumuloClient API that - * replaces Connector is closable. For code that only uses AccumuloClient, when all AccumuloClients - * are closed resources are cleaned up. Connectors that are derived from an AccumuloClient do not - * necessitate the use of this code. - * - * @deprecated since 2.0.0 Use only {@link AccumuloClient} instead. Also, make sure you close the - * AccumuloClient instances. - */ -@Deprecated(since = "2.0.0") -public class CleanUp { - - private static final Logger log = LoggerFactory.getLogger(CleanUp.class); - - /** - * kills all threads created by internal Accumulo singleton resources. After this method is - * called, no Connector will work in the current classloader. - * - * @param conn - * If available, Connector object to close resources on. Will accept null otherwise. - */ - public static void shutdownNow(Connector conn) { - SingletonManager.setMode(Mode.CLIENT); - waitForZooKeeperClientThreads(); - if (conn != null) { - ConnectorImpl connImpl = (ConnectorImpl) conn; - connImpl.getAccumuloClient().close(); - } - } - - /** - * As documented in https://issues.apache.org/jira/browse/ZOOKEEPER-1816, ZooKeeper.close() is a - * non-blocking call. This method will wait on the ZooKeeper internal threads to exit. - */ - private static void waitForZooKeeperClientThreads() { - Set<Thread> threadSet = Thread.getAllStackTraces().keySet(); - for (Thread thread : threadSet) { - // find ZooKeeper threads that were created in the same ClassLoader as the current thread. - if (thread.getClass().getName().startsWith("org.apache.zookeeper.ClientCnxn") && thread - .getContextClassLoader().equals(Thread.currentThread().getContextClassLoader())) { - - // wait for the thread the die - while (thread.isAlive()) { - try { - Thread.sleep(100); - } catch (InterruptedException e) { - log.error("{}", e.getMessage(), e); - } - } - } - } - } -} diff --git a/core/src/test/java/org/apache/accumulo/core/client/ZooKeeperInstanceTest.java b/core/src/test/java/org/apache/accumulo/core/client/ZooKeeperInstanceTest.java deleted file mode 100644 index 48047c710c..0000000000 --- a/core/src/test/java/org/apache/accumulo/core/client/ZooKeeperInstanceTest.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.accumulo.core.client; - -import static java.nio.charset.StandardCharsets.UTF_8; -import static org.easymock.EasyMock.createMock; -import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.replay; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import java.util.List; -import java.util.UUID; - -import org.apache.accumulo.core.Constants; -import org.apache.accumulo.core.data.InstanceId; -import org.apache.accumulo.core.fate.zookeeper.ZooCache; -import org.apache.accumulo.core.fate.zookeeper.ZooCacheFactory; -import org.easymock.EasyMock; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -@Deprecated(since = "2.0.0") -public class ZooKeeperInstanceTest { - private static final InstanceId IID = InstanceId.of(UUID.randomUUID()); - private static final String IID_STRING = IID.canonical(); - private ZooCacheFactory zcf; - private ZooCache zc; - private ZooKeeperInstance zki; - - private static final ClientConfiguration.ClientProperty INSTANCE_ID = - ClientConfiguration.ClientProperty.INSTANCE_ID; - private static final ClientConfiguration.ClientProperty INSTANCE_NAME = - ClientConfiguration.ClientProperty.INSTANCE_NAME; - private static final ClientConfiguration.ClientProperty INSTANCE_ZK_HOST = - ClientConfiguration.ClientProperty.INSTANCE_ZK_HOST; - private static final ClientConfiguration.ClientProperty INSTANCE_ZK_TIMEOUT = - ClientConfiguration.ClientProperty.INSTANCE_ZK_TIMEOUT; - - private void mockIdConstruction(ClientConfiguration config) { - expect(config.get(INSTANCE_ID)).andReturn(IID_STRING); - expect(config.get(INSTANCE_NAME)).andReturn(null); - expect(config.get(INSTANCE_ZK_HOST)).andReturn("zk1"); - expect(config.get(INSTANCE_ZK_TIMEOUT)).andReturn("30"); - } - - private void mockNameConstruction(ClientConfiguration config) { - expect(config.get(INSTANCE_ID)).andReturn(null); - expect(config.get(INSTANCE_NAME)).andReturn("instance"); - expect(config.get(INSTANCE_ZK_HOST)).andReturn("zk1"); - expect(config.get(INSTANCE_ZK_TIMEOUT)).andReturn("30"); - } - - @BeforeEach - public void setUp() { - ClientConfiguration config = createMock(ClientConfiguration.class); - mockNameConstruction(config); - replay(config); - zcf = createMock(ZooCacheFactory.class); - zc = createMock(ZooCache.class); - expect(zcf.getZooCache("zk1", 30000)).andReturn(zc).anyTimes(); - expect(zc.get(Constants.ZROOT + Constants.ZINSTANCES + "/instance")) - .andReturn(IID_STRING.getBytes(UTF_8)); - expect(zc.get(Constants.ZROOT + "/" + IID_STRING)).andReturn("yup".getBytes()); - replay(zc, zcf); - zki = new ZooKeeperInstance(config, zcf); - EasyMock.resetToDefault(zc); - } - - @Test - public void testInvalidConstruction() { - ClientConfiguration config = createMock(ClientConfiguration.class); - expect(config.get(INSTANCE_ID)).andReturn(IID_STRING); - mockNameConstruction(config); - replay(config); - assertThrows(IllegalArgumentException.class, () -> new ZooKeeperInstance(config)); - } - - @Test - public void testInvalidConstruction2() { - ClientConfiguration config = createMock(ClientConfiguration.class); - expect(config.get(INSTANCE_ID)).andReturn(null); - expect(config.get(INSTANCE_NAME)).andReturn(null); - expect(config.get(INSTANCE_ZK_HOST)).andReturn("zk1"); - expect(config.get(INSTANCE_ZK_TIMEOUT)).andReturn("30"); - replay(config); - assertThrows(IllegalArgumentException.class, () -> new ZooKeeperInstance(config)); - } - - @Test - public void testSimpleGetters() { - assertEquals("instance", zki.getInstanceName()); - assertEquals("zk1", zki.getZooKeepers()); - assertEquals(30000, zki.getZooKeepersSessionTimeOut()); - } - - @Test - public void testGetInstanceID_FromCache() { - expect(zc.get(Constants.ZROOT + Constants.ZINSTANCES + "/instance")) - .andReturn(IID_STRING.getBytes(UTF_8)); - expect(zc.get(Constants.ZROOT + "/" + IID_STRING)).andReturn("yup".getBytes()); - replay(zc); - assertEquals(IID_STRING, zki.getInstanceID()); - } - - @Test - public void testGetInstanceID_Direct() { - ClientConfiguration config = createMock(ClientConfiguration.class); - mockIdConstruction(config); - replay(config); - zki = new ZooKeeperInstance(config, zcf); - expect(zc.get(Constants.ZROOT + "/" + IID_STRING)).andReturn("yup".getBytes()); - replay(zc); - assertEquals(IID_STRING, zki.getInstanceID()); - } - - @Test - public void testGetInstanceID_NoMapping() { - ClientConfiguration config = createMock(ClientConfiguration.class); - expect(zc.get(Constants.ZROOT + Constants.ZINSTANCES + "/instance")).andReturn(null); - replay(zc); - EasyMock.reset(config, zcf); - assertThrows(RuntimeException.class, () -> new ZooKeeperInstance(config, zcf)); - } - - @Test - public void testGetInstanceID_IDMissingForName() { - expect(zc.get(Constants.ZROOT + Constants.ZINSTANCES + "/instance")) - .andReturn(IID_STRING.getBytes(UTF_8)); - expect(zc.get(Constants.ZROOT + "/" + IID_STRING)).andReturn(null); - replay(zc); - assertThrows(RuntimeException.class, () -> zki.getInstanceID()); - } - - @Test - public void testGetInstanceID_IDMissingForID() { - ClientConfiguration config = createMock(ClientConfiguration.class); - mockIdConstruction(config); - replay(config); - zki = new ZooKeeperInstance(config, zcf); - expect(zc.get(Constants.ZROOT + "/" + IID_STRING)).andReturn(null); - replay(zc); - assertThrows(RuntimeException.class, () -> zki.getInstanceID()); - } - - @Test - public void testGetInstanceName() { - ClientConfiguration config = createMock(ClientConfiguration.class); - mockIdConstruction(config); - replay(config); - zki = new ZooKeeperInstance(config, zcf); - expect(zc.get(Constants.ZROOT + "/" + IID_STRING)).andReturn("yup".getBytes()); - List<String> children = new java.util.ArrayList<>(); - children.add("child1"); - children.add("child2"); - expect(zc.getChildren(Constants.ZROOT + Constants.ZINSTANCES)).andReturn(children); - expect(zc.get(Constants.ZROOT + Constants.ZINSTANCES + "/child1")) - .andReturn(UUID.randomUUID().toString().getBytes(UTF_8)); - expect(zc.get(Constants.ZROOT + Constants.ZINSTANCES + "/child2")) - .andReturn(IID_STRING.getBytes(UTF_8)); - replay(zc); - assertEquals("child2", zki.getInstanceName()); - } - - @Test - public void testAllZooKeepersAreUsed() { - final String zookeepers = "zk1,zk2,zk3", instanceName = "accumulo"; - ZooCacheFactory factory = createMock(ZooCacheFactory.class); - EasyMock.reset(zc); - expect(factory.getZooCache(zookeepers, 30000)).andReturn(zc).anyTimes(); - expect(zc.get(Constants.ZROOT + Constants.ZINSTANCES + "/" + instanceName)) - .andReturn(IID_STRING.getBytes(UTF_8)); - expect(zc.get(Constants.ZROOT + "/" + IID_STRING)).andReturn("yup".getBytes()); - replay(zc, factory); - ClientConfiguration cfg = - ClientConfiguration.loadDefault().withInstance(instanceName).withZkHosts(zookeepers); - ZooKeeperInstance zki = new ZooKeeperInstance(cfg, factory); - assertEquals(zookeepers, zki.getZooKeepers()); - assertEquals(instanceName, zki.getInstanceName()); - } -} diff --git a/core/src/test/java/org/apache/accumulo/core/singletons/SingletonManagerTest.java b/core/src/test/java/org/apache/accumulo/core/singletons/SingletonManagerTest.java index 83d087a9d1..33d82a363a 100644 --- a/core/src/test/java/org/apache/accumulo/core/singletons/SingletonManagerTest.java +++ b/core/src/test/java/org/apache/accumulo/core/singletons/SingletonManagerTest.java @@ -94,52 +94,21 @@ public class SingletonManagerTest { } @Test - public void testConnectorPreventsDisable() { - - SingletonManager.setMode(Mode.CONNECTOR); - assertEquals(Mode.CONNECTOR, SingletonManager.getMode()); - + public void testConnectorRemoved() { SingletonReservation resv1 = SingletonManager.getClientReservation(); - - assertEquals(1, SingletonManager.getReservationCount()); - - SingletonReservation resv2 = SingletonManager.getClientReservation(); - - assertEquals(2, SingletonManager.getReservationCount()); - resv1.close(); - resv2.close(); - - assertEquals(0, SingletonManager.getReservationCount()); - - assertEquals(new TestService(true, 0, 0), service1); - assertEquals(new TestService(true, 1, 0), service2); - - SingletonManager.setMode(Mode.CLIENT); - assertEquals(Mode.CLIENT, SingletonManager.getMode()); assertEquals(new TestService(false, 0, 1), service1); assertEquals(new TestService(false, 1, 1), service2); - assertThrows(IllegalStateException.class, () -> SingletonManager.setMode(Mode.CONNECTOR), - "Should only be able to set mode to CONNECTOR once"); - - assertEquals(Mode.CLIENT, SingletonManager.getMode()); - } - - @Test - public void testConnectorEnables() { - SingletonReservation resv1 = SingletonManager.getClientReservation(); - resv1.close(); + // this should do nothing + @SuppressWarnings("deprecation") + var e = assertThrows(IllegalArgumentException.class, + () -> SingletonManager.setMode(Mode.CONNECTOR)); + assertTrue(e.getMessage().contains("CONNECTOR")); assertEquals(new TestService(false, 0, 1), service1); assertEquals(new TestService(false, 1, 1), service2); - - // this should enable services - SingletonManager.setMode(Mode.CONNECTOR); - - assertEquals(new TestService(true, 1, 1), service1); - assertEquals(new TestService(true, 2, 1), service2); } @Test diff --git a/minicluster/src/main/java/org/apache/accumulo/minicluster/MiniAccumuloCluster.java b/minicluster/src/main/java/org/apache/accumulo/minicluster/MiniAccumuloCluster.java index 43e0c29788..37d127d939 100644 --- a/minicluster/src/main/java/org/apache/accumulo/minicluster/MiniAccumuloCluster.java +++ b/minicluster/src/main/java/org/apache/accumulo/minicluster/MiniAccumuloCluster.java @@ -24,10 +24,7 @@ import java.util.Properties; import java.util.Set; import org.apache.accumulo.core.client.AccumuloClient; -import org.apache.accumulo.core.client.AccumuloException; -import org.apache.accumulo.core.client.AccumuloSecurityException; import org.apache.accumulo.core.client.security.tokens.AuthenticationToken; -import org.apache.accumulo.core.client.security.tokens.PasswordToken; import org.apache.accumulo.core.clientImpl.ClientInfoImpl; import org.apache.accumulo.core.util.Pair; import org.apache.accumulo.miniclusterImpl.MiniAccumuloClusterImpl; @@ -129,19 +126,6 @@ public class MiniAccumuloCluster implements AutoCloseable { return new MiniAccumuloConfig(impl.getConfig()); } - /** - * Utility method to get a connector to the MAC. - * - * @since 1.6.0 - * @deprecated since 2.0.0, replaced by {@link #createAccumuloClient(String, AuthenticationToken)} - */ - @Deprecated(since = "2.0.0") - public org.apache.accumulo.core.client.Connector getConnector(String user, String passwd) - throws AccumuloException, AccumuloSecurityException { - return org.apache.accumulo.core.client.Connector - .from(impl.createAccumuloClient(user, new PasswordToken(passwd))); - } - /** * Utility method to create an {@link AccumuloClient} with connection to the MAC. The * AccumuloClient object should be closed by user diff --git a/minicluster/src/main/java/org/apache/accumulo/minicluster/MiniAccumuloInstance.java b/minicluster/src/main/java/org/apache/accumulo/minicluster/MiniAccumuloInstance.java deleted file mode 100644 index c0dafae522..0000000000 --- a/minicluster/src/main/java/org/apache/accumulo/minicluster/MiniAccumuloInstance.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.accumulo.minicluster; - -import java.io.File; -import java.io.FileNotFoundException; - -import org.apache.accumulo.core.conf.Property; -import org.apache.accumulo.core.conf.SiteConfiguration; - -/** - * @since 1.6.0 - * @deprecated since 2.0.0, Use {@link MiniAccumuloCluster#getClientProperties(File)} instead - */ -@Deprecated(since = "2.0.0") -public class MiniAccumuloInstance extends org.apache.accumulo.core.client.ZooKeeperInstance { - - /** - * Construct an {@link org.apache.accumulo.core.client.Instance} entry point to Accumulo using a - * {@link MiniAccumuloCluster} directory - */ - public MiniAccumuloInstance(String instanceName, File directory) throws FileNotFoundException { - super(org.apache.accumulo.core.client.ClientConfiguration - .fromFile(new File(new File(directory, "conf"), "client.conf")).withInstance(instanceName) - .withZkHosts(getZooKeepersFromDir(directory))); - } - - // Keep this private to avoid bringing it into the public API - private static String getZooKeepersFromDir(File directory) { - if (!directory.isDirectory()) { - throw new IllegalArgumentException("Not a directory " + directory.getPath()); - } - File configFile = new File(new File(directory, "conf"), "accumulo.properties"); - var conf = SiteConfiguration.fromFile(configFile).build(); - return conf.get(Property.INSTANCE_ZK_HOST); - } -} diff --git a/minicluster/src/test/java/org/apache/accumulo/minicluster/MiniAccumuloClusterClasspathTest.java b/minicluster/src/test/java/org/apache/accumulo/minicluster/MiniAccumuloClusterClasspathTest.java index c3c1af4a91..a40d13e225 100644 --- a/minicluster/src/test/java/org/apache/accumulo/minicluster/MiniAccumuloClusterClasspathTest.java +++ b/minicluster/src/test/java/org/apache/accumulo/minicluster/MiniAccumuloClusterClasspathTest.java @@ -28,6 +28,8 @@ import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; +import org.apache.accumulo.core.client.Accumulo; +import org.apache.accumulo.core.client.AccumuloClient; import org.apache.accumulo.core.client.BatchWriter; import org.apache.accumulo.core.client.BatchWriterConfig; import org.apache.accumulo.core.client.IteratorSetting; @@ -92,48 +94,49 @@ public class MiniAccumuloClusterClasspathTest extends WithTestNames { accumulo.stop(); } - @SuppressWarnings("deprecation") @Test @Timeout(60) public void testPerTableClasspath() throws Exception { - org.apache.accumulo.core.client.Connector conn = - accumulo.getConnector(ROOT_USER, ROOT_PASSWORD); + try (AccumuloClient client = Accumulo.newClient().from(accumulo.getClientProperties()) + .as(ROOT_USER, ROOT_PASSWORD).build()) { - final String tableName = testName(); + final String tableName = testName(); - var ntc = new NewTableConfiguration(); - ntc.setProperties(Map.of(Property.TABLE_CLASSLOADER_CONTEXT.getKey(), "cx1")); - ntc.attachIterator(new IteratorSetting(100, "foocensor", "org.apache.accumulo.test.FooFilter")); + var ntc = new NewTableConfiguration(); + ntc.setProperties(Map.of(Property.TABLE_CLASSLOADER_CONTEXT.getKey(), "cx1")); + ntc.attachIterator( + new IteratorSetting(100, "foocensor", "org.apache.accumulo.test.FooFilter")); - conn.tableOperations().create(tableName, ntc); + client.tableOperations().create(tableName, ntc); - try (BatchWriter bw = conn.createBatchWriter(tableName, new BatchWriterConfig())) { + try (BatchWriter bw = client.createBatchWriter(tableName, new BatchWriterConfig())) { - Mutation m1 = new Mutation("foo"); - m1.put("cf1", "cq1", "v2"); - m1.put("cf1", "cq2", "v3"); + Mutation m1 = new Mutation("foo"); + m1.put("cf1", "cq1", "v2"); + m1.put("cf1", "cq2", "v3"); - bw.addMutation(m1); + bw.addMutation(m1); - Mutation m2 = new Mutation("bar"); - m2.put("cf1", "cq1", "v6"); - m2.put("cf1", "cq2", "v7"); + Mutation m2 = new Mutation("bar"); + m2.put("cf1", "cq1", "v6"); + m2.put("cf1", "cq2", "v7"); - bw.addMutation(m2); + bw.addMutation(m2); - } + } - int count = 0; - try (Scanner scanner = conn.createScanner(tableName, new Authorizations())) { - for (Entry<Key,Value> entry : scanner) { - assertFalse(entry.getKey().getRowData().toString().toLowerCase().contains("foo")); - count++; + int count = 0; + try (Scanner scanner = client.createScanner(tableName, new Authorizations())) { + for (Entry<Key,Value> entry : scanner) { + assertFalse(entry.getKey().getRowData().toString().toLowerCase().contains("foo")); + count++; + } } - } - assertEquals(2, count); + assertEquals(2, count); - conn.tableOperations().delete(tableName); + client.tableOperations().delete(tableName); + } } } diff --git a/minicluster/src/test/java/org/apache/accumulo/minicluster/MiniAccumuloClusterExistingZooKeepersTest.java b/minicluster/src/test/java/org/apache/accumulo/minicluster/MiniAccumuloClusterExistingZooKeepersTest.java index 8efedb5d5d..fdff86ee3e 100644 --- a/minicluster/src/test/java/org/apache/accumulo/minicluster/MiniAccumuloClusterExistingZooKeepersTest.java +++ b/minicluster/src/test/java/org/apache/accumulo/minicluster/MiniAccumuloClusterExistingZooKeepersTest.java @@ -25,6 +25,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.util.Map; +import org.apache.accumulo.core.client.Accumulo; +import org.apache.accumulo.core.client.AccumuloClient; import org.apache.commons.io.FileUtils; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFrameworkFactory; @@ -56,28 +58,29 @@ public class MiniAccumuloClusterExistingZooKeepersTest extends WithTestNames { config = new MiniAccumuloConfig(testDir, SECRET); } - @SuppressWarnings("deprecation") @Test public void canConnectViaExistingZooKeeper() throws Exception { try (TestingServer zooKeeper = new TestingServer(); MiniAccumuloCluster accumulo = new MiniAccumuloCluster(config.setExistingZooKeepers(zooKeeper.getConnectString()))) { accumulo.start(); + assertEquals(zooKeeper.getConnectString(), accumulo.getZooKeepers()); - org.apache.accumulo.core.client.Connector conn = accumulo.getConnector("root", SECRET); - assertEquals(zooKeeper.getConnectString(), conn.getInstance().getZooKeepers()); + try (AccumuloClient client = + Accumulo.newClient().from(accumulo.getClientProperties()).as("root", SECRET).build()) { - String tableName = "foo"; - conn.tableOperations().create(tableName); - Map<String,String> tableIds = conn.tableOperations().tableIdMap(); - assertTrue(tableIds.containsKey(tableName)); + String tableName = "foo"; + client.tableOperations().create(tableName); + Map<String,String> tableIds = client.tableOperations().tableIdMap(); + assertTrue(tableIds.containsKey(tableName)); - String zkTablePath = String.format("/accumulo/%s/tables/%s/name", - conn.getInstance().getInstanceID(), tableIds.get(tableName)); - try (CuratorFramework client = - CuratorFrameworkFactory.newClient(zooKeeper.getConnectString(), new RetryOneTime(1))) { - client.start(); - assertNotNull(client.checkExists().forPath(zkTablePath)); - assertEquals(tableName, new String(client.getData().forPath(zkTablePath))); + String zkTablePath = String.format("/accumulo/%s/tables/%s/name", + client.instanceOperations().getInstanceId().canonical(), tableIds.get(tableName)); + try (CuratorFramework curatorClient = + CuratorFrameworkFactory.newClient(zooKeeper.getConnectString(), new RetryOneTime(1))) { + curatorClient.start(); + assertNotNull(curatorClient.checkExists().forPath(zkTablePath)); + assertEquals(tableName, new String(curatorClient.getData().forPath(zkTablePath))); + } } } } diff --git a/minicluster/src/test/java/org/apache/accumulo/minicluster/MiniAccumuloClusterStartStopTest.java b/minicluster/src/test/java/org/apache/accumulo/minicluster/MiniAccumuloClusterStartStopTest.java index 549bb50e00..5546547a63 100644 --- a/minicluster/src/test/java/org/apache/accumulo/minicluster/MiniAccumuloClusterStartStopTest.java +++ b/minicluster/src/test/java/org/apache/accumulo/minicluster/MiniAccumuloClusterStartStopTest.java @@ -23,6 +23,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.io.IOException; +import org.apache.accumulo.core.client.Accumulo; +import org.apache.accumulo.core.client.AccumuloClient; import org.apache.commons.io.FileUtils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -71,13 +73,14 @@ public class MiniAccumuloClusterStartStopTest extends WithTestNames { } } - @SuppressWarnings("deprecation") @Test public void multipleStopsIsAllowed() throws Exception { accumulo.start(); - org.apache.accumulo.core.client.Connector conn = accumulo.getConnector("root", "superSecret"); - conn.tableOperations().create("foo"); + try (AccumuloClient client = Accumulo.newClient().from(accumulo.getClientProperties()) + .as("root", "superSecret").build()) { + client.tableOperations().create("foo"); + } accumulo.stop(); accumulo.stop(); diff --git a/minicluster/src/test/java/org/apache/accumulo/minicluster/MiniAccumuloClusterTest.java b/minicluster/src/test/java/org/apache/accumulo/minicluster/MiniAccumuloClusterTest.java index 61921fa238..445ca4ff36 100644 --- a/minicluster/src/test/java/org/apache/accumulo/minicluster/MiniAccumuloClusterTest.java +++ b/minicluster/src/test/java/org/apache/accumulo/minicluster/MiniAccumuloClusterTest.java @@ -32,6 +32,8 @@ import java.util.Map.Entry; import java.util.Set; import java.util.UUID; +import org.apache.accumulo.core.client.Accumulo; +import org.apache.accumulo.core.client.AccumuloClient; import org.apache.accumulo.core.client.BatchWriter; import org.apache.accumulo.core.client.BatchWriterConfig; import org.apache.accumulo.core.client.IteratorSetting; @@ -98,84 +100,87 @@ public class MiniAccumuloClusterTest extends WithTestNames { @Test @Timeout(30) public void test() throws Exception { - org.apache.accumulo.core.client.Connector conn = - accumulo.getConnector(ROOT_USER, ROOT_PASSWORD); + try (AccumuloClient conn = Accumulo.newClient().from(accumulo.getClientProperties()) + .as(ROOT_USER, ROOT_PASSWORD).build()) { - final String tableName = testName(); + final String tableName = testName(); - IteratorSetting is = new IteratorSetting(10, SummingCombiner.class); - SummingCombiner.setEncodingType(is, LongCombiner.Type.STRING); - SummingCombiner.setColumns(is, - Collections.singletonList(new IteratorSetting.Column("META", "COUNT"))); + IteratorSetting is = new IteratorSetting(10, SummingCombiner.class); + SummingCombiner.setEncodingType(is, LongCombiner.Type.STRING); + SummingCombiner.setColumns(is, + Collections.singletonList(new IteratorSetting.Column("META", "COUNT"))); - conn.tableOperations().create(tableName, new NewTableConfiguration().attachIterator(is)); + conn.tableOperations().create(tableName, new NewTableConfiguration().attachIterator(is)); - final String principal = "user1"; - final String password = "pass1"; - conn.securityOperations().createLocalUser(principal, new PasswordToken(password)); - conn.securityOperations().changeUserAuthorizations(principal, new Authorizations("A", "B")); - conn.securityOperations().grantTablePermission(principal, tableName, TablePermission.WRITE); - conn.securityOperations().grantTablePermission(principal, tableName, TablePermission.READ); + final String principal = "user1"; + final String password = "pass1"; + conn.securityOperations().createLocalUser(principal, new PasswordToken(password)); + conn.securityOperations().changeUserAuthorizations(principal, new Authorizations("A", "B")); + conn.securityOperations().grantTablePermission(principal, tableName, TablePermission.WRITE); + conn.securityOperations().grantTablePermission(principal, tableName, TablePermission.READ); - org.apache.accumulo.core.client.Connector uconn = accumulo.getConnector(principal, password); + try (AccumuloClient uconn = Accumulo.newClient().from(accumulo.getClientProperties()) + .as(principal, password).build()) { - try (BatchWriter bw = uconn.createBatchWriter(tableName, new BatchWriterConfig())) { + try (BatchWriter bw = uconn.createBatchWriter(tableName, new BatchWriterConfig())) { - UUID uuid = UUID.randomUUID(); + UUID uuid = UUID.randomUUID(); - ColumnVisibility colVisAorB = new ColumnVisibility("A|B"); - Mutation m = new Mutation(uuid.toString()); - m.put("META", "SIZE", colVisAorB, "8"); - m.put("META", "CRC", colVisAorB, "456"); - m.put("META", "COUNT", colVisAorB, "1"); - m.put("DATA", "IMG", new ColumnVisibility("A&B"), "ABCDEFGH"); + ColumnVisibility colVisAorB = new ColumnVisibility("A|B"); + Mutation m = new Mutation(uuid.toString()); + m.put("META", "SIZE", colVisAorB, "8"); + m.put("META", "CRC", colVisAorB, "456"); + m.put("META", "COUNT", colVisAorB, "1"); + m.put("DATA", "IMG", new ColumnVisibility("A&B"), "ABCDEFGH"); - bw.addMutation(m); - bw.flush(); + bw.addMutation(m); + bw.flush(); - m = new Mutation(uuid.toString()); - m.put("META", "COUNT", colVisAorB, "1"); - m.put("META", "CRC", colVisAorB, "123"); - bw.addMutation(m); + m = new Mutation(uuid.toString()); + m.put("META", "COUNT", colVisAorB, "1"); + m.put("META", "CRC", colVisAorB, "123"); + bw.addMutation(m); - } - - int count = 0; - try (Scanner scanner = uconn.createScanner(tableName, new Authorizations("A"))) { - for (Entry<Key,Value> entry : scanner) { - final String actualValue = entry.getValue().toString(); - switch (entry.getKey().getColumnQualifierData().toString()) { - case "COUNT": - assertEquals("2", actualValue); - break; - case "SIZE": - assertEquals("8", actualValue); - break; - case "CRC": - assertEquals("123", actualValue); - break; - default: - fail(); - break; } - count++; - } - } - assertEquals(3, count); - count = 0; - try (Scanner scanner = uconn.createScanner(tableName, new Authorizations("A", "B"))) { - for (Entry<Key,Value> entry : scanner) { - if (entry.getKey().getColumnQualifierData().toString().equals("IMG")) { - assertEquals("ABCDEFGH", entry.getValue().toString()); + int count = 0; + try (Scanner scanner = uconn.createScanner(tableName, new Authorizations("A"))) { + for (Entry<Key,Value> entry : scanner) { + final String actualValue = entry.getValue().toString(); + switch (entry.getKey().getColumnQualifierData().toString()) { + case "COUNT": + assertEquals("2", actualValue); + break; + case "SIZE": + assertEquals("8", actualValue); + break; + case "CRC": + assertEquals("123", actualValue); + break; + default: + fail(); + break; + } + count++; + } } - count++; + assertEquals(3, count); + + count = 0; + try (Scanner scanner = uconn.createScanner(tableName, new Authorizations("A", "B"))) { + for (Entry<Key,Value> entry : scanner) { + if (entry.getKey().getColumnQualifierData().toString().equals("IMG")) { + assertEquals("ABCDEFGH", entry.getValue().toString()); + } + count++; + } + } + + assertEquals(4, count); } + conn.tableOperations().delete(tableName); } - assertEquals(4, count); - - conn.tableOperations().delete(tableName); } @Test diff --git a/server/base/src/test/java/org/apache/accumulo/server/security/SystemCredentialsTest.java b/server/base/src/test/java/org/apache/accumulo/server/security/SystemCredentialsTest.java index bc75dc7bf7..ecd76424eb 100644 --- a/server/base/src/test/java/org/apache/accumulo/server/security/SystemCredentialsTest.java +++ b/server/base/src/test/java/org/apache/accumulo/server/security/SystemCredentialsTest.java @@ -86,22 +86,6 @@ public class SystemCredentialsTest { assertTrue(hash.startsWith(SystemToken.SALT_PREFIX)); } - /** - * This is a test to ensure the SYSTEM_TOKEN_NAME string literal in - * {@link org.apache.accumulo.core.clientImpl.ConnectorImpl} is kept up-to-date if we move the - * {@link SystemToken}<br> - * - * @deprecated This check will not be needed after Connector is removed - */ - @Deprecated(since = "2.0.0") - @Test - public void testSystemToken() { - assertEquals("org.apache.accumulo.server.security.SystemCredentials$SystemToken", - SystemToken.class.getName()); - assertEquals(SystemCredentials.get(instanceId, siteConfig).getToken().getClass(), - SystemToken.class); - } - @Test public void testSystemCredentials() { Credentials a = SystemCredentials.get(instanceId, siteConfig); diff --git a/shell/src/main/java/org/apache/accumulo/shell/Shell.java b/shell/src/main/java/org/apache/accumulo/shell/Shell.java index fce386fcf8..7b086292f6 100644 --- a/shell/src/main/java/org/apache/accumulo/shell/Shell.java +++ b/shell/src/main/java/org/apache/accumulo/shell/Shell.java @@ -384,9 +384,7 @@ public class Shell extends ShellOptions implements KeywordExecutable { {new ClasspathCommand(), new org.apache.accumulo.shell.commands.DebugCommand(), new ListScansCommand(), new ListCompactionsCommand(), new TraceCommand(), new PingCommand(), new ListBulkCommand(), new ListTabletsCommand()}; - @SuppressWarnings("deprecation") - Command[] execCommands = {new ExecfileCommand(), new HistoryCommand(), new ExtensionCommand(), - new org.apache.accumulo.shell.commands.ScriptCommand()}; + Command[] execCommands = {new ExecfileCommand(), new HistoryCommand(), new ExtensionCommand()}; Command[] exitCommands = {new ByeCommand(), new ExitCommand(), new QuitCommand()}; Command[] helpCommands = {new AboutCommand(), new HelpCommand(), new InfoCommand(), new QuestionCommand()}; diff --git a/shell/src/main/java/org/apache/accumulo/shell/commands/ScriptCommand.java b/shell/src/main/java/org/apache/accumulo/shell/commands/ScriptCommand.java deleted file mode 100644 index b5350d6322..0000000000 --- a/shell/src/main/java/org/apache/accumulo/shell/commands/ScriptCommand.java +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.accumulo.shell.commands; - -import static java.nio.charset.StandardCharsets.UTF_8; - -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.io.Reader; -import java.io.Writer; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.TreeSet; - -import javax.script.Bindings; -import javax.script.Compilable; -import javax.script.CompiledScript; -import javax.script.Invocable; -import javax.script.ScriptContext; -import javax.script.ScriptEngine; -import javax.script.ScriptEngineFactory; -import javax.script.ScriptEngineManager; -import javax.script.ScriptException; -import javax.script.SimpleScriptContext; - -import org.apache.accumulo.core.client.AccumuloClient; -import org.apache.accumulo.core.client.AccumuloException; -import org.apache.accumulo.core.client.AccumuloSecurityException; -import org.apache.accumulo.shell.Shell; -import org.apache.accumulo.shell.Shell.Command; -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.Option; -import org.apache.commons.cli.OptionGroup; -import org.apache.commons.cli.Options; - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; - -/** - * @deprecated since 2.0; this command shouldn't be used; The script command is deprecated; use - * jshell for scripting instead - */ - -@Deprecated(since = "2.1.0") -public class ScriptCommand extends Command { - - // Command to allow user to run scripts, see JSR-223 - // https://www.oracle.com/technetwork/articles/javase/scripting-140262.html - - protected Option list, engine, script, file, args, out, function, object; - private static final String DEFAULT_ENGINE = "rhino"; - - @SuppressFBWarnings(value = "PATH_TRAVERSAL_IN", - justification = "app is run in same security context as user providing the filename") - @Override - public int execute(String fullCommand, CommandLine cl, Shell shellState) throws Exception { - - boolean invoke = false; - - Shell.log.warn("The script command is deprecated; use jshell for scripting instead"); - ScriptEngineManager mgr = new ScriptEngineManager(); - - if (cl.hasOption(list.getOpt())) { - listJSREngineInfo(mgr, shellState); - } else if (cl.hasOption(file.getOpt()) || cl.hasOption(script.getOpt())) { - String engineName = DEFAULT_ENGINE; - if (cl.hasOption(engine.getOpt())) { - engineName = cl.getOptionValue(engine.getOpt()); - } - ScriptEngine engine = mgr.getEngineByName(engineName); - if (engine == null) { - shellState.printException(new Exception(engineName + " not found")); - return 1; - } - - if (cl.hasOption(object.getOpt()) || cl.hasOption(function.getOpt())) { - if (!(engine instanceof Invocable)) { - shellState.printException( - new Exception(engineName + " does not support invoking functions or methods")); - return 1; - } - invoke = true; - } - - ScriptContext ctx = new SimpleScriptContext(); - - // Put the following objects into the context so that they - // are available to the scripts - // TODO: What else should go in here? - Bindings b = engine.getBindings(ScriptContext.ENGINE_SCOPE); - putConnector(b, shellState.getAccumuloClient()); - b.put("client", shellState.getAccumuloClient()); - - List<Object> argValues = new ArrayList<>(); - if (cl.hasOption(args.getOpt())) { - String[] argList = cl.getOptionValue(args.getOpt()).split(","); - for (String arg : argList) { - String[] parts = arg.split("="); - if (parts.length == 0) { - continue; - } else if (parts.length == 1) { - b.put(parts[0], null); - argValues.add(null); - } else if (parts.length == 2) { - b.put(parts[0], parts[1]); - argValues.add(parts[1]); - } - } - } - ctx.setBindings(b, ScriptContext.ENGINE_SCOPE); - Object[] argArray = argValues.toArray(new Object[argValues.size()]); - - Writer writer = null; - if (cl.hasOption(out.getOpt())) { - File f = new File(cl.getOptionValue(out.getOpt())); - writer = new FileWriter(f, UTF_8); - ctx.setWriter(writer); - } - - if (cl.hasOption(file.getOpt())) { - File f = new File(cl.getOptionValue(file.getOpt())); - if (!f.exists()) { - if (writer != null) { - writer.close(); - } - shellState.printException(new Exception(f.getAbsolutePath() + " not found")); - return 1; - } - Reader reader = new FileReader(f, UTF_8); - try (reader) { - engine.eval(reader, ctx); - if (invoke) { - this.invokeFunctionOrMethod(shellState, engine, cl, argArray); - } - } catch (ScriptException ex) { - shellState.printException(ex); - return 1; - } finally { - if (writer != null) { - writer.close(); - } - } - } else if (cl.hasOption(script.getOpt())) { - String inlineScript = cl.getOptionValue(script.getOpt()); - try { - if (engine instanceof Compilable) { - Compilable compiledEng = (Compilable) engine; - CompiledScript script = compiledEng.compile(inlineScript); - script.eval(ctx); - if (invoke) { - this.invokeFunctionOrMethod(shellState, engine, cl, argArray); - } - } else { - engine.eval(inlineScript, ctx); - if (invoke) { - this.invokeFunctionOrMethod(shellState, engine, cl, argArray); - } - } - } catch (ScriptException ex) { - shellState.printException(ex); - return 1; - } finally { - if (writer != null) { - writer.close(); - } - } - } - if (writer != null) { - writer.close(); - } - - } else { - printHelp(shellState); - } - return 0; - } - - private void putConnector(Bindings b, AccumuloClient client) { - try { - b.put("connection", org.apache.accumulo.core.client.Connector.from(client)); - } catch (AccumuloSecurityException | AccumuloException e) { - throw new RuntimeException(e); - } - } - - @Override - public String description() { - return "(deprecated) execute JSR-223 scripts"; - } - - @Override - public int numArgs() { - return 0; - } - - @Override - public Options getOptions() { - final Options o = new Options(); - - engine = new Option("e", "engine", false, "engine name, defaults to JDK default (Rhino)"); - engine.setArgName("engineName"); - engine.setArgs(1); - engine.setRequired(false); - o.addOption(engine); - - OptionGroup inputGroup = new OptionGroup(); - list = new Option("l", "list", false, "list available script engines"); - inputGroup.addOption(list); - - script = new Option("s", "script", true, "use inline script"); - script.setArgName("script text"); - script.setArgs(1); - script.setRequired(false); - inputGroup.addOption(script); - - file = new Option("f", "file", true, "use script file"); - file.setArgName("fileName"); - file.setArgs(1); - file.setRequired(false); - - inputGroup.addOption(file); - inputGroup.setRequired(true); - o.addOptionGroup(inputGroup); - - OptionGroup invokeGroup = new OptionGroup(); - object = new Option("obj", "object", true, "name of object"); - object.setArgs(1); - object.setArgName("objectName:methodName"); - object.setRequired(false); - invokeGroup.addOption(object); - - function = new Option("fx", "function", true, "invoke a script function"); - function.setArgName("functionName"); - function.setArgs(1); - function.setRequired(false); - invokeGroup.addOption(function); - invokeGroup.setRequired(false); - o.addOptionGroup(invokeGroup); - - args = new Option("a", "args", true, "comma separated list of key=value arguments"); - args.setArgName("property1=value1,propert2=value2,..."); - args.setArgs(Option.UNLIMITED_VALUES); - args.setRequired(false); - o.addOption(args); - - out = new Option("o", "output", true, "output file"); - out.setArgName("fileName"); - out.setArgs(1); - out.setRequired(false); - o.addOption(out); - - return o; - } - - private void listJSREngineInfo(ScriptEngineManager mgr, Shell shellState) throws IOException { - List<ScriptEngineFactory> factories = mgr.getEngineFactories(); - Set<String> lines = new TreeSet<>(); - for (ScriptEngineFactory factory : factories) { - lines.add("ScriptEngineFactory Info"); - String engName = factory.getEngineName(); - String engVersion = factory.getEngineVersion(); - String langName = factory.getLanguageName(); - String langVersion = factory.getLanguageVersion(); - lines.add("\tScript Engine: " + engName + " (" + engVersion + ")"); - List<String> engNames = factory.getNames(); - for (String name : engNames) { - lines.add("\tEngine Alias: " + name); - } - lines.add("\tLanguage: " + langName + " (" + langVersion + ")"); - } - shellState.printLines(lines.iterator(), true); - - } - - private void invokeFunctionOrMethod(Shell shellState, ScriptEngine engine, CommandLine cl, - Object[] args) { - try { - Invocable inv = (Invocable) engine; - if (cl.hasOption(function.getOpt())) { - inv.invokeFunction(cl.getOptionValue(function.getOpt()), args); - } else if (cl.hasOption(object.getOpt())) { - String objectMethod = cl.getOptionValue(object.getOpt()); - String[] parts = objectMethod.split(":"); - if (parts.length != 2) { - shellState.printException(new Exception("Object and Method must be supplied")); - return; - } - String objectName = parts[0]; - String methodName = parts[1]; - Object obj = engine.get(objectName); - inv.invokeMethod(obj, methodName, args); - - } - } catch (Exception e) { - shellState.printException(e); - } - } - -} diff --git a/test/src/main/java/org/apache/accumulo/test/functional/AccumuloClientIT.java b/test/src/main/java/org/apache/accumulo/test/functional/AccumuloClientIT.java index d5fb850607..694f4ee755 100644 --- a/test/src/main/java/org/apache/accumulo/test/functional/AccumuloClientIT.java +++ b/test/src/main/java/org/apache/accumulo/test/functional/AccumuloClientIT.java @@ -72,42 +72,6 @@ public class AccumuloClientIT extends AccumuloClusterHarness { assertTrue(e.getMessage().toLowerCase().contains("closed")); } - @SuppressWarnings("deprecation") - @Test - public void testGetConnectorFromAccumuloClient() throws Exception { - AccumuloClient client = Accumulo.newClient().from(getClientProps()).build(); - org.apache.accumulo.core.client.Connector c = - org.apache.accumulo.core.client.Connector.from(client); - assertEquals(client.whoami(), c.whoami()); - - // this should cause the connector to stop functioning - client.close(); - - expectClosed(c::tableOperations); - } - - @SuppressWarnings("deprecation") - @Test - public void testGetAccumuloClientFromConnector() throws Exception { - try (AccumuloClient client1 = Accumulo.newClient().from(getClientProps()).build()) { - org.apache.accumulo.core.client.Connector c = - org.apache.accumulo.core.client.Connector.from(client1); - - String tableName = getUniqueNames(1)[0]; - - c.tableOperations().create(tableName); - - try (AccumuloClient client2 = org.apache.accumulo.core.client.Connector.newClient(c)) { - assertTrue(client2.tableOperations().list().contains(tableName)); - } - - // closing client2 should not have had an impact on the connector or client1 - - assertTrue(client1.tableOperations().list().contains(tableName)); - assertTrue(c.tableOperations().list().contains(tableName)); - } - } - @Test public void testAccumuloClientBuilder() throws Exception { AccumuloClient c = Accumulo.newClient().from(getClientProps()).build(); diff --git a/test/src/main/java/org/apache/accumulo/test/functional/CleanUpIT.java b/test/src/main/java/org/apache/accumulo/test/functional/CleanUpIT.java deleted file mode 100644 index 38b03ea4e7..0000000000 --- a/test/src/main/java/org/apache/accumulo/test/functional/CleanUpIT.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.accumulo.test.functional; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.fail; - -import java.time.Duration; -import java.util.Map.Entry; -import java.util.Set; - -import org.apache.accumulo.core.client.BatchWriter; -import org.apache.accumulo.core.client.BatchWriterConfig; -import org.apache.accumulo.core.client.MutationsRejectedException; -import org.apache.accumulo.core.client.Scanner; -import org.apache.accumulo.core.data.Key; -import org.apache.accumulo.core.data.Mutation; -import org.apache.accumulo.core.data.Value; -import org.apache.accumulo.core.security.Authorizations; -import org.apache.accumulo.core.singletons.SingletonManager; -import org.apache.accumulo.harness.SharedMiniClusterBase; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.collect.Iterables; - -/** - * Ensures that all threads spawned for ZooKeeper and Thrift connectivity are reaped after calling - * CleanUp.shutdown(). - * - * Because this is destructive across the current context classloader, the normal teardown methods - * will fail (because they attempt to create a Connector). Until the ZooKeeperInstance and Connector - * are self-contained WRT resource management, we can't leverage the AccumuloClusterBase. - */ -public class CleanUpIT extends SharedMiniClusterBase { - private static final Logger log = LoggerFactory.getLogger(CleanUpIT.class); - - @Override - protected Duration defaultTimeout() { - return Duration.ofSeconds(30); - } - - @BeforeAll - public static void setup() throws Exception { - SharedMiniClusterBase.startMiniCluster(); - } - - @AfterAll - public static void teardown() { - SharedMiniClusterBase.stopMiniCluster(); - } - - @SuppressWarnings("deprecation") - @Test - public void run() throws Exception { - - // CleanUp for Connectors will not work if there are active AccumuloClients - assertEquals(0, SingletonManager.getReservationCount()); - - // CleanUp was created to clean up after connectors. This test intentionally creates a connector - // instead of an AccumuloClient - org.apache.accumulo.core.client.Connector conn = - new org.apache.accumulo.core.client.ZooKeeperInstance(getCluster().getInstanceName(), - getCluster().getZooKeepers()).getConnector(getPrincipal(), getToken()); - - String tableName = getUniqueNames(1)[0]; - conn.tableOperations().create(tableName); - - BatchWriter bw = conn.createBatchWriter(tableName, new BatchWriterConfig()); - - Mutation m1 = new Mutation("r1"); - m1.put("cf1", "cq1", 1, "5"); - - bw.addMutation(m1); - - bw.flush(); - - try (Scanner scanner = conn.createScanner(tableName, new Authorizations())) { - - int count = 0; - for (Entry<Key,Value> entry : scanner) { - count++; - if (!entry.getValue().toString().equals("5")) { - fail("Unexpected value " + entry.getValue()); - } - } - - assertEquals(1, count, "Unexpected count"); - - int threadCount = countThreads(); - if (threadCount < 2) { - printThreadNames(); - fail("Not seeing expected threads. Saw " + threadCount); - } - - // explicitly close the scanner to verify that the scanner throws after close when iterated - scanner.close(); - assertThrows(IllegalStateException.class, () -> Iterables.size(scanner)); - } - - // close the scanners before closing the client, because the scanners need the client's cleanup - // thread pool to execute their cleanup tasks when they are closed, so they don't block - org.apache.accumulo.core.util.CleanUp.shutdownNow(conn); - - Mutation m2 = new Mutation("r2"); - m2.put("cf1", "cq1", 1, "6"); - - bw.addMutation(m1); - assertThrows(MutationsRejectedException.class, bw::flush); - - // expect this to fail also, want to clean up batch writer threads - assertThrows(MutationsRejectedException.class, bw::close); - - var threadCount = countThreads(); - if (threadCount > 0) { - printThreadNames(); - fail("Threads did not go away. Saw " + threadCount); - } - } - - private void printThreadNames() { - Set<Thread> threads = Thread.getAllStackTraces().keySet(); - Exception e = new Exception(); - for (Thread thread : threads) { - e.setStackTrace(thread.getStackTrace()); - log.info("thread name: " + thread.getName(), e); - } - } - - /** - * count threads that should be cleaned up - * - */ - private int countThreads() { - int count = 0; - Set<Thread> threads = Thread.getAllStackTraces().keySet(); - for (Thread thread : threads) { - - if (thread.getName().toLowerCase().contains("sendthread") - || thread.getName().toLowerCase().contains("eventthread")) - count++; - - if (thread.getName().toLowerCase().contains("thrift") - && thread.getName().toLowerCase().contains("pool")) - count++; - } - - return count; - } -}