ACCUMULO-3238 Table.ID Namespace.ID Refactor * Replaced all occurrences of tableId and namespaceId Strings that aren't a part of the user facing API with type safe Table.ID and Namespace.ID objects. * Created new methods in Tables and Namespaces for internal use of these type safe objects.
Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/d6ea49e0 Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/d6ea49e0 Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/d6ea49e0 Branch: refs/heads/master Commit: d6ea49e0344ebe8f840248545821d359853f316a Parents: 87e5780 Author: Mike Miller <mmil...@apache.org> Authored: Tue Jul 18 16:45:36 2017 -0400 Committer: Mike Miller <mmil...@apache.org> Committed: Tue Jul 18 16:45:36 2017 -0400 ---------------------------------------------------------------------- .../core/client/MutationsRejectedException.java | 6 +- .../core/client/TableOfflineException.java | 3 +- .../accumulo/core/client/impl/AbstractId.java | 89 +++++++++ .../core/client/impl/ActiveScanImpl.java | 2 +- .../core/client/impl/BatchWriterImpl.java | 4 +- .../core/client/impl/ConditionalWriterImpl.java | 12 +- .../core/client/impl/ConnectorImpl.java | 6 +- .../client/impl/MultiTableBatchWriterImpl.java | 23 ++- .../accumulo/core/client/impl/Namespace.java | 42 +++++ .../client/impl/NamespaceOperationsImpl.java | 13 +- .../accumulo/core/client/impl/Namespaces.java | 138 +++++++++----- .../core/client/impl/OfflineIterator.java | 4 +- .../core/client/impl/OfflineScanner.java | 4 +- .../client/impl/ReplicationOperationsImpl.java | 6 +- .../accumulo/core/client/impl/ScannerImpl.java | 4 +- .../core/client/impl/ScannerIterator.java | 2 +- .../core/client/impl/SyncingTabletLocator.java | 2 +- .../apache/accumulo/core/client/impl/Table.java | 39 ++++ .../core/client/impl/TableOperationsImpl.java | 81 +++++---- .../accumulo/core/client/impl/Tables.java | 180 +++++++++++-------- .../core/client/impl/TabletLocator.java | 12 +- .../core/client/impl/TabletLocatorImpl.java | 8 +- .../client/impl/TabletServerBatchDeleter.java | 4 +- .../client/impl/TabletServerBatchReader.java | 4 +- .../impl/TabletServerBatchReaderIterator.java | 12 +- .../client/impl/TabletServerBatchWriter.java | 54 +++--- .../core/client/impl/ThriftScanner.java | 10 +- .../core/client/impl/TimeoutTabletLocator.java | 2 +- .../accumulo/core/client/impl/Writer.java | 4 +- .../core/client/mapred/AbstractInputFormat.java | 20 ++- .../client/mapred/impl/BatchInputSplit.java | 3 +- .../client/mapreduce/AbstractInputFormat.java | 20 ++- .../client/mapreduce/impl/BatchInputSplit.java | 5 +- .../mapreduce/lib/impl/InputConfigurator.java | 5 +- .../core/client/mock/MockTableOperations.java | 4 +- .../client/mock/impl/MockTabletLocator.java | 2 +- .../accumulo/core/data/impl/KeyExtent.java | 45 ++--- .../accumulo/core/data/impl/TabletIdImpl.java | 2 +- .../core/metadata/MetadataServicer.java | 7 +- .../accumulo/core/metadata/MetadataTable.java | 3 +- .../accumulo/core/metadata/RootTable.java | 3 +- .../core/metadata/ServicerForRootTable.java | 3 +- .../core/metadata/ServicerForUserTables.java | 3 +- .../core/metadata/TableMetadataServicer.java | 7 +- .../core/metadata/schema/MetadataScanner.java | 11 +- .../core/metadata/schema/MetadataSchema.java | 13 +- .../core/metadata/schema/TabletMetadata.java | 5 +- .../core/replication/ReplicationSchema.java | 13 +- .../core/replication/ReplicationTable.java | 3 +- .../core/replication/ReplicationTarget.java | 13 +- .../apache/accumulo/core/summary/Gatherer.java | 5 +- .../accumulo/core/util/ByteBufferUtil.java | 5 + .../org/apache/accumulo/core/util/Merge.java | 3 +- .../core/client/impl/ScannerImplTest.java | 8 +- .../client/impl/TableOperationsImplTest.java | 2 +- .../core/client/impl/TabletLocatorImplTest.java | 18 +- .../impl/TabletServerBatchReaderTest.java | 4 +- .../mapreduce/impl/BatchInputSplitTest.java | 5 +- .../accumulo/core/data/KeyExtentTest.java | 9 +- .../apache/accumulo/core/data/RangeTest.java | 22 +-- .../core/iterators/IteratorUtilTest.java | 11 +- .../iterators/system/MultiIteratorTest.java | 3 +- .../core/metadata/MetadataServicerTest.java | 11 +- .../ReplicationConfigurationUtilTest.java | 5 +- .../core/replication/ReplicationSchemaTest.java | 9 +- .../core/replication/ReplicationTargetTest.java | 21 +-- .../apache/accumulo/core/util/MergeTest.java | 3 +- .../impl/MiniAccumuloClusterImplTest.java | 4 +- .../accumulo/server/client/BulkImporter.java | 3 +- .../server/client/ClientServiceHandler.java | 42 ++--- .../server/conf/NamespaceConfWatcher.java | 16 +- .../server/conf/NamespaceConfiguration.java | 9 +- .../server/conf/ServerConfiguration.java | 6 +- .../server/conf/ServerConfigurationFactory.java | 22 +-- .../accumulo/server/conf/TableConfWatcher.java | 16 +- .../server/conf/TableConfiguration.java | 9 +- .../server/conf/TableParentConfiguration.java | 8 +- .../server/constraints/MetadataConstraints.java | 2 +- .../server/fs/PerTableVolumeChooser.java | 3 +- .../server/fs/VolumeChooserEnvironment.java | 7 +- .../accumulo/server/fs/VolumeManager.java | 3 +- .../accumulo/server/fs/VolumeManagerImpl.java | 5 +- .../apache/accumulo/server/init/Initialize.java | 6 +- .../accumulo/server/master/LiveTServerSet.java | 5 +- .../master/balancer/ChaoticLoadBalancer.java | 6 +- .../master/balancer/DefaultLoadBalancer.java | 35 ++-- .../server/master/balancer/GroupBalancer.java | 4 +- .../balancer/HostRegexTableLoadBalancer.java | 23 +-- .../master/balancer/RegexGroupBalancer.java | 5 +- .../master/balancer/TableLoadBalancer.java | 45 ++--- .../server/master/balancer/TabletBalancer.java | 5 +- .../server/master/state/CurrentState.java | 3 +- .../master/state/TabletStateChangeIterator.java | 11 +- .../accumulo/server/problems/ProblemReport.java | 19 +- .../problems/ProblemReportingIterator.java | 5 +- .../server/problems/ProblemReports.java | 33 ++-- .../DistributedWorkQueueWorkAssignerHelper.java | 3 +- .../server/replication/ReplicationUtil.java | 5 +- .../security/AuditedSecurityOperation.java | 49 ++--- .../server/security/SecurityOperation.java | 108 +++++------ .../security/handler/InsecurePermHandler.java | 11 +- .../handler/KerberosPermissionHandler.java | 11 +- .../security/handler/PermissionHandler.java | 14 +- .../server/security/handler/ZKAuthorizor.java | 3 +- .../server/security/handler/ZKPermHandler.java | 26 +-- .../accumulo/server/tables/TableManager.java | 36 ++-- .../accumulo/server/tables/TableObserver.java | 5 +- .../tabletserver/LargestFirstMemoryManager.java | 7 +- .../server/util/CheckForMetadataProblems.java | 2 +- .../server/util/FindOfflineTablets.java | 3 +- .../server/util/MasterMetadataUtil.java | 11 +- .../accumulo/server/util/MetadataTableUtil.java | 37 ++-- .../accumulo/server/util/NamespacePropUtil.java | 7 +- .../accumulo/server/util/RandomizeVolumes.java | 8 +- .../util/RemoveEntriesForMissingFiles.java | 9 +- .../server/util/ReplicationTableUtil.java | 2 +- .../accumulo/server/util/TableDiskUsage.java | 3 +- .../accumulo/server/util/TablePropUtil.java | 9 +- .../accumulo/server/util/TabletIterator.java | 5 +- .../server/util/VerifyTabletAssignments.java | 3 +- .../server/client/BulkImporterTest.java | 11 +- .../server/conf/NamespaceConfigurationTest.java | 3 +- .../conf/ServerConfigurationFactoryTest.java | 3 +- .../server/conf/TableConfigurationTest.java | 3 +- .../server/fs/VolumeManagerImplTest.java | 3 +- .../BaseHostRegexTableLoadBalancerTest.java | 31 ++-- .../balancer/ChaoticLoadBalancerTest.java | 11 +- .../balancer/DefaultLoadBalancerTest.java | 13 +- .../master/balancer/GroupBalancerTest.java | 3 +- ...gexTableLoadBalancerReconfigurationTest.java | 5 +- .../HostRegexTableLoadBalancerTest.java | 13 +- .../master/balancer/TableLoadBalancerTest.java | 27 +-- .../server/master/state/MergeInfoTest.java | 25 +-- .../server/problems/ProblemReportTest.java | 13 +- .../problems/ProblemReportingIteratorTest.java | 3 +- .../server/util/ReplicationTableUtilTest.java | 7 +- .../accumulo/gc/GarbageCollectionAlgorithm.java | 9 +- .../gc/GarbageCollectionEnvironment.java | 5 +- .../accumulo/gc/SimpleGarbageCollector.java | 7 +- .../accumulo/gc/GarbageCollectionTest.java | 21 +-- .../accumulo/master/FateServiceHandler.java | 72 ++++---- .../java/org/apache/accumulo/master/Master.java | 40 +++-- .../master/MasterClientServiceHandler.java | 48 ++--- .../accumulo/master/TabletGroupWatcher.java | 13 +- .../master/replication/FinishedWorkUpdater.java | 7 +- .../RemoveCompleteReplicationRecords.java | 11 +- .../replication/SequentialWorkAssigner.java | 14 +- .../master/replication/StatusMaker.java | 9 +- .../accumulo/master/replication/WorkMaker.java | 5 +- .../accumulo/master/state/MergeStats.java | 3 +- .../accumulo/master/state/TableStats.java | 11 +- .../accumulo/master/tableOps/BulkImport.java | 27 +-- .../master/tableOps/CancelCompactions.java | 8 +- .../master/tableOps/ChangeTableState.java | 8 +- .../accumulo/master/tableOps/CleanUp.java | 13 +- .../master/tableOps/CleanUpBulkImport.java | 5 +- .../accumulo/master/tableOps/CloneInfo.java | 11 +- .../accumulo/master/tableOps/CloneTable.java | 7 +- .../accumulo/master/tableOps/CompactRange.java | 16 +- .../master/tableOps/CompactionDriver.java | 17 +- .../master/tableOps/CompleteBulkImport.java | 5 +- .../accumulo/master/tableOps/CopyFailed.java | 5 +- .../master/tableOps/CreateImportDir.java | 2 +- .../master/tableOps/CreateNamespace.java | 3 +- .../accumulo/master/tableOps/CreateTable.java | 6 +- .../master/tableOps/DeleteNamespace.java | 5 +- .../accumulo/master/tableOps/DeleteTable.java | 8 +- .../accumulo/master/tableOps/ExportInfo.java | 7 +- .../accumulo/master/tableOps/ExportTable.java | 4 +- .../master/tableOps/FinishCancelCompaction.java | 8 +- .../master/tableOps/FinishCreateNamespace.java | 2 +- .../master/tableOps/FinishCreateTable.java | 2 +- .../master/tableOps/FinishImportTable.java | 2 +- .../tableOps/ImportPopulateZookeeper.java | 11 +- .../accumulo/master/tableOps/ImportTable.java | 6 +- .../master/tableOps/ImportedTableInfo.java | 7 +- .../accumulo/master/tableOps/LoadFiles.java | 11 +- .../master/tableOps/MapImportFileNames.java | 4 +- .../master/tableOps/MoveExportedFiles.java | 8 +- .../master/tableOps/NamespaceCleanUp.java | 5 +- .../accumulo/master/tableOps/NamespaceInfo.java | 4 +- .../master/tableOps/PopulateMetadataTable.java | 6 +- .../master/tableOps/RenameNamespace.java | 5 +- .../accumulo/master/tableOps/RenameTable.java | 10 +- .../accumulo/master/tableOps/TableInfo.java | 7 +- .../accumulo/master/tableOps/TableRangeOp.java | 11 +- .../master/tableOps/TableRangeOpWait.java | 8 +- .../apache/accumulo/master/tableOps/Utils.java | 41 +++-- .../master/tableOps/WriteExportFiles.java | 24 +-- .../accumulo/master/util/TableValidators.java | 16 +- ...tributedWorkQueueWorkAssignerHelperTest.java | 5 +- .../replication/SequentialWorkAssignerTest.java | 12 +- .../replication/UnorderedWorkAssignerTest.java | 3 +- .../master/state/RootTabletStateStoreTest.java | 3 +- .../master/tableOps/ImportTableTest.java | 3 +- .../org/apache/accumulo/monitor/Monitor.java | 5 +- .../rest/problems/ProblemDetailInformation.java | 6 +- .../problems/ProblemSummaryInformation.java | 6 +- .../monitor/rest/problems/ProblemsResource.java | 17 +- .../rest/replication/ReplicationResource.java | 14 +- .../monitor/rest/tables/TableInformation.java | 7 +- .../monitor/rest/tables/TablesResource.java | 23 +-- .../rest/tservers/CurrentOperations.java | 6 +- .../rest/tservers/TabletServerResource.java | 8 +- .../apache/accumulo/monitor/view/WebViews.java | 5 +- .../apache/accumulo/tserver/TabletServer.java | 72 ++++---- .../accumulo/tserver/logger/LogReader.java | 3 +- .../replication/ReplicationServicerHandler.java | 4 +- .../tserver/session/ConditionalSession.java | 5 +- .../tserver/session/SessionManager.java | 14 +- .../tserver/tablet/DatafileManager.java | 2 +- .../apache/accumulo/tserver/tablet/Tablet.java | 7 +- .../accumulo/tserver/AssignmentWatcherTest.java | 3 +- .../tserver/CheckTabletMetadataTest.java | 7 +- .../tserver/LargestFirstMemoryManagerTest.java | 24 +-- .../tserver/TabletServerSyncCheckTest.java | 3 +- .../DefaultCompactionStrategyTest.java | 3 +- .../SizeLimitCompactionStrategyTest.java | 3 +- .../TwoTierCompactionStrategyTest.java | 7 +- .../ConfigurableCompactionStrategyTest.java | 3 +- .../accumulo/tserver/log/LogEntryTest.java | 3 +- .../tserver/log/SortedLogRecoveryTest.java | 3 +- .../accumulo/tserver/logger/LogFileTest.java | 3 +- .../replication/AccumuloReplicaSystemTest.java | 46 ++--- .../replication/ReplicationProcessorTest.java | 3 +- .../accumulo/shell/commands/DUCommand.java | 3 +- .../shell/commands/DeleteNamespaceCommand.java | 7 +- .../shell/commands/RenameNamespaceCommand.java | 8 +- .../accumulo/shell/commands/TableOperation.java | 6 +- .../java/org/apache/accumulo/test/CloneIT.java | 53 +++--- .../org/apache/accumulo/test/FileArchiveIT.java | 7 +- .../apache/accumulo/test/ImportExportIT.java | 2 +- .../org/apache/accumulo/test/ListTables.java | 3 +- .../org/apache/accumulo/test/LocatorIT.java | 3 +- .../accumulo/test/MetaConstraintRetryIT.java | 3 +- .../MissingWalHeaderCompletesRecoveryIT.java | 5 +- .../org/apache/accumulo/test/NamespacesIT.java | 12 +- .../accumulo/test/QueryMetadataTable.java | 2 +- .../test/RewriteTabletDirectoriesIT.java | 3 +- .../java/org/apache/accumulo/test/SampleIT.java | 3 +- .../apache/accumulo/test/SplitRecoveryIT.java | 3 +- .../test/TableConfigurationUpdateIT.java | 2 +- .../apache/accumulo/test/VolumeChooserIT.java | 19 +- .../java/org/apache/accumulo/test/VolumeIT.java | 5 +- .../apache/accumulo/test/WrongTabletTest.java | 5 +- .../test/functional/FunctionalTestUtils.java | 3 +- .../test/functional/MasterAssignmentIT.java | 3 +- .../accumulo/test/functional/MergeIT.java | 7 +- .../test/functional/RegexGroupBalanceIT.java | 5 +- .../accumulo/test/functional/SplitIT.java | 3 +- .../test/functional/SplitRecoveryIT.java | 7 +- .../test/functional/TableChangeStateIT.java | 5 +- .../accumulo/test/functional/TableIT.java | 3 +- .../functional/TabletStateChangeIteratorIT.java | 13 +- .../accumulo/test/functional/WALSunnyDayIT.java | 2 +- .../CloseWriteAheadLogReferencesIT.java | 3 +- .../accumulo/test/master/MergeStateIT.java | 7 +- .../test/master/SuspendedTabletsIT.java | 2 +- .../metadata/MetadataBatchScanTest.java | 3 +- .../performance/scan/CollectTabletStats.java | 9 +- .../test/performance/thrift/NullTserver.java | 3 +- .../test/replication/FinishedWorkUpdaterIT.java | 21 +-- ...bageCollectorCommunicatesWithTServersIT.java | 3 +- .../RemoveCompleteReplicationRecordsIT.java | 41 +++-- .../test/replication/ReplicationIT.java | 29 +-- .../ReplicationOperationsImplIT.java | 49 ++--- .../replication/SequentialWorkAssignerIT.java | 39 ++-- .../test/replication/StatusCombinerMacIT.java | 5 +- .../test/replication/StatusMakerIT.java | 5 +- .../replication/UnorderedWorkAssignerIT.java | 9 +- ...UnusedWalDoesntCloseReplicationStatusIT.java | 9 +- .../accumulo/test/replication/WorkMakerIT.java | 11 +- 272 files changed, 1993 insertions(+), 1446 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/MutationsRejectedException.java ---------------------------------------------------------------------- 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 8f8720a..2bb348d 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 @@ -24,6 +24,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import org.apache.accumulo.core.client.impl.Table; import org.apache.accumulo.core.client.impl.Tables; import org.apache.accumulo.core.client.security.SecurityErrorCode; import org.apache.accumulo.core.data.ConstraintViolationSummary; @@ -68,13 +69,14 @@ public class MutationsRejectedException extends AccumuloException { Map<String,Set<SecurityErrorCode>> result = new HashMap<>(); for (Entry<TabletId,Set<SecurityErrorCode>> entry : hashMap.entrySet()) { - String tableInfo = Tables.getPrintableTableInfoFromId(instance, entry.getKey().getTableId().toString()); + TabletId tabletId = entry.getKey(); + String tableInfo = Tables.getPrintableTableInfoFromId(instance, new Table.ID(tabletId.getTableId().toString())); if (!result.containsKey(tableInfo)) { result.put(tableInfo, new HashSet<SecurityErrorCode>()); } - result.get(tableInfo).addAll(hashMap.get(entry.getKey())); + result.get(tableInfo).addAll(hashMap.get(tabletId)); } return result.toString(); http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/TableOfflineException.java ---------------------------------------------------------------------- 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 ef63228..2afb69d 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 @@ -16,6 +16,7 @@ */ package org.apache.accumulo.core.client; +import org.apache.accumulo.core.client.impl.Table; import org.apache.accumulo.core.client.impl.Tables; public class TableOfflineException extends RuntimeException { @@ -26,7 +27,7 @@ public class TableOfflineException extends RuntimeException { if (tableId == null) return " <unknown table> "; try { - String tableName = Tables.getTableName(instance, tableId); + String tableName = Tables.getTableName(instance, new Table.ID(tableId)); return tableName + " (" + tableId + ")"; } catch (TableNotFoundException e) { return " <unknown table> (" + tableId + ")"; http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/AbstractId.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/AbstractId.java b/core/src/main/java/org/apache/accumulo/core/client/impl/AbstractId.java new file mode 100644 index 0000000..9bf7341 --- /dev/null +++ b/core/src/main/java/org/apache/accumulo/core/client/impl/AbstractId.java @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.accumulo.core.client.impl; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static java.util.Objects.requireNonNull; + +import java.io.Serializable; +import java.util.Objects; + +/** + * An abstract identifier class for comparing equality of identifiers of the same type. + */ +public abstract class AbstractId implements Comparable<AbstractId>, Serializable { + + private static final long serialVersionUID = -155513612834787244L; + private final String canonical; + private Integer hashCode = null; + + protected AbstractId(final String canonical) { + requireNonNull(canonical, "canonical cannot be null"); + this.canonical = canonical; + } + + /** + * The canonical ID + */ + public final String canonicalID() { + return canonical; + } + + public boolean isEmpty() { + return canonical.isEmpty(); + } + + /** + * AbstractID objects are considered equal if, and only if, they are of the same type and have the same canonical identifier. + */ + @Override + public boolean equals(final Object obj) { + if (this == obj) + return true; + return obj != null && Objects.equals(getClass(), obj.getClass()) && Objects.equals(canonicalID(), ((AbstractId) obj).canonicalID()); + } + + @Override + public int hashCode() { + if (hashCode == null) { + hashCode = Objects.hash(canonicalID()); + } + return hashCode; + } + + /** + * Returns a string of the canonical ID + */ + @Override + public String toString() { + return canonical; + } + + /** + * Return a UTF_8 byte[] of the canonical ID. + */ + public final byte[] getUtf8() { + return canonical.getBytes(UTF_8); + } + + @Override + public int compareTo(AbstractId id) { + requireNonNull(id, "id cannot be null"); + return this.canonicalID().compareTo(id.canonicalID()); + } + +} http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/ActiveScanImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/ActiveScanImpl.java b/core/src/main/java/org/apache/accumulo/core/client/impl/ActiveScanImpl.java index dd96aa3..d962143 100644 --- a/core/src/main/java/org/apache/accumulo/core/client/impl/ActiveScanImpl.java +++ b/core/src/main/java/org/apache/accumulo/core/client/impl/ActiveScanImpl.java @@ -60,7 +60,7 @@ public class ActiveScanImpl extends ActiveScan { this.user = activeScan.user; this.age = activeScan.age; this.idle = activeScan.idleTime; - this.tableName = Tables.getTableName(instance, activeScan.tableId); + this.tableName = Tables.getTableName(instance, new Table.ID(activeScan.tableId)); this.type = ScanType.valueOf(activeScan.getType().name()); this.state = ScanState.valueOf(activeScan.state.name()); this.extent = new KeyExtent(activeScan.extent); http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/BatchWriterImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/BatchWriterImpl.java b/core/src/main/java/org/apache/accumulo/core/client/impl/BatchWriterImpl.java index 7096187..57129c9 100644 --- a/core/src/main/java/org/apache/accumulo/core/client/impl/BatchWriterImpl.java +++ b/core/src/main/java/org/apache/accumulo/core/client/impl/BatchWriterImpl.java @@ -25,10 +25,10 @@ import org.apache.accumulo.core.data.Mutation; public class BatchWriterImpl implements BatchWriter { - private final String tableId; + private final Table.ID tableId; private final TabletServerBatchWriter bw; - public BatchWriterImpl(ClientContext context, String tableId, BatchWriterConfig config) { + public BatchWriterImpl(ClientContext context, Table.ID tableId, BatchWriterConfig config) { checkArgument(context != null, "context is null"); checkArgument(tableId != null, "tableId is null"); if (config == null) http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/ConditionalWriterImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/ConditionalWriterImpl.java b/core/src/main/java/org/apache/accumulo/core/client/impl/ConditionalWriterImpl.java index 98a15ca..8f2e64f 100644 --- a/core/src/main/java/org/apache/accumulo/core/client/impl/ConditionalWriterImpl.java +++ b/core/src/main/java/org/apache/accumulo/core/client/impl/ConditionalWriterImpl.java @@ -113,7 +113,7 @@ class ConditionalWriterImpl implements ConditionalWriter { private Map<Text,Boolean> cache = Collections.synchronizedMap(new LRUMap(1000)); private final ClientContext context; private TabletLocator locator; - private final String tableId; + private final Table.ID tableId; private long timeout; private final Durability durability; private final String classLoaderContext; @@ -298,9 +298,9 @@ class ConditionalWriterImpl implements ConditionalWriter { if (failures.size() == mutations.size()) if (!Tables.exists(context.getInstance(), tableId)) - throw new TableDeletedException(tableId); + throw new TableDeletedException(tableId.canonicalID()); else if (Tables.getTableState(context.getInstance(), tableId) == TableState.OFFLINE) - throw new TableOfflineException(context.getInstance(), tableId); + throw new TableOfflineException(context.getInstance(), tableId.canonicalID()); } catch (Exception e) { for (QCMutation qcm : mutations) @@ -383,7 +383,7 @@ class ConditionalWriterImpl implements ConditionalWriter { } } - ConditionalWriterImpl(ClientContext context, String tableId, ConditionalWriterConfig config) { + ConditionalWriterImpl(ClientContext context, Table.ID tableId, ConditionalWriterConfig config) { this.context = context; this.auths = config.getAuthorizations(); this.ve = new VisibilityEvaluator(config.getAuthorizations()); @@ -510,8 +510,8 @@ class ConditionalWriterImpl implements ConditionalWriter { } } - TConditionalSession tcs = client.startConditionalUpdate(tinfo, context.rpcCreds(), ByteBufferUtil.toByteBuffers(auths.getAuthorizations()), tableId, - DurabilityImpl.toThrift(durability), this.classLoaderContext); + TConditionalSession tcs = client.startConditionalUpdate(tinfo, context.rpcCreds(), ByteBufferUtil.toByteBuffers(auths.getAuthorizations()), + tableId.canonicalID(), DurabilityImpl.toThrift(durability), this.classLoaderContext); synchronized (cachedSessionIDs) { SessionID sid = new SessionID(); http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/ConnectorImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/ConnectorImpl.java b/core/src/main/java/org/apache/accumulo/core/client/impl/ConnectorImpl.java index 7f8c600..f49e4dc 100644 --- a/core/src/main/java/org/apache/accumulo/core/client/impl/ConnectorImpl.java +++ b/core/src/main/java/org/apache/accumulo/core/client/impl/ConnectorImpl.java @@ -79,10 +79,10 @@ public class ConnectorImpl extends Connector { this.namespaceops = new NamespaceOperationsImpl(context, tableops); } - private String getTableId(String tableName) throws TableNotFoundException { - String tableId = Tables.getTableId(context.getInstance(), tableName); + private Table.ID getTableId(String tableName) throws TableNotFoundException { + Table.ID tableId = Tables.getTableId(context.getInstance(), tableName); if (Tables.getTableState(context.getInstance(), tableId) == TableState.OFFLINE) - throw new TableOfflineException(context.getInstance(), tableId); + throw new TableOfflineException(context.getInstance(), tableId.canonicalID()); return tableId; } http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/MultiTableBatchWriterImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/MultiTableBatchWriterImpl.java b/core/src/main/java/org/apache/accumulo/core/client/impl/MultiTableBatchWriterImpl.java index 15d1c34..34a3137 100644 --- a/core/src/main/java/org/apache/accumulo/core/client/impl/MultiTableBatchWriterImpl.java +++ b/core/src/main/java/org/apache/accumulo/core/client/impl/MultiTableBatchWriterImpl.java @@ -53,9 +53,9 @@ public class MultiTableBatchWriterImpl implements MultiTableBatchWriter { private class TableBatchWriter implements BatchWriter { - private String tableId; + private Table.ID tableId; - TableBatchWriter(String tableId) { + TableBatchWriter(Table.ID tableId) { this.tableId = tableId; } @@ -85,18 +85,15 @@ public class MultiTableBatchWriterImpl implements MultiTableBatchWriter { /** * CacheLoader which will look up the internal table ID for a given table name. */ - private class TableNameToIdLoader extends CacheLoader<String,String> { + private class TableNameToIdLoader extends CacheLoader<String,Table.ID> { @Override - public String load(String tableName) throws Exception { + public Table.ID load(String tableName) throws Exception { Instance instance = context.getInstance(); - String tableId = Tables.getNameToIdMap(instance).get(tableName); - - if (tableId == null) - throw new TableNotFoundException(null, tableName, null); + Table.ID tableId = Tables.getTableId(instance, tableName); if (Tables.getTableState(instance, tableId) == TableState.OFFLINE) - throw new TableOfflineException(instance, tableId); + throw new TableOfflineException(instance, tableId.canonicalID()); return tableId; } @@ -104,9 +101,9 @@ public class MultiTableBatchWriterImpl implements MultiTableBatchWriter { } private TabletServerBatchWriter bw; - private ConcurrentHashMap<String,BatchWriter> tableWriters; + private ConcurrentHashMap<Table.ID,BatchWriter> tableWriters; private final ClientContext context; - private final LoadingCache<String,String> nameToIdCache; + private final LoadingCache<String,Table.ID> nameToIdCache; public MultiTableBatchWriterImpl(ClientContext context, BatchWriterConfig config) { this(context, config, DEFAULT_CACHE_TIME, DEFAULT_CACHE_TIME_UNIT); @@ -159,7 +156,7 @@ public class MultiTableBatchWriterImpl implements MultiTableBatchWriter { * The name of the table which to find the ID for * @return The table ID, or null if the table name doesn't exist */ - private String getId(String tableName) throws TableNotFoundException { + private Table.ID getId(String tableName) throws TableNotFoundException { try { return nameToIdCache.get(tableName); } catch (UncheckedExecutionException e) { @@ -217,7 +214,7 @@ public class MultiTableBatchWriterImpl implements MultiTableBatchWriter { break; } - String tableId = getId(tableName); + Table.ID tableId = getId(tableName); BatchWriter tbw = tableWriters.get(tableId); if (tbw == null) { http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/Namespace.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/Namespace.java b/core/src/main/java/org/apache/accumulo/core/client/impl/Namespace.java new file mode 100644 index 0000000..41f8b05 --- /dev/null +++ b/core/src/main/java/org/apache/accumulo/core/client/impl/Namespace.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.accumulo.core.client.impl; + +import org.apache.accumulo.core.client.Instance; + +public class Namespace { + + /** + * Object representing an internal Namespace ID. This class was created to help with type safety. For help obtaining the value of a namespace ID from + * Zookeeper, see {@link Namespaces#getNamespaceId(Instance, String)} + */ + public static class ID extends AbstractId { + private static final long serialVersionUID = 8931104141709170293L; + + public static final ID ACCUMULO = new ID("+accumulo"); + public static final ID DEFAULT = new ID("+default"); + + public ID(String canonical) { + super(canonical); + } + } + + public static final String ACCUMULO = "accumulo"; + public static final String DEFAULT = ""; + public static final String SEPARATOR = "."; + +} http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/NamespaceOperationsImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/NamespaceOperationsImpl.java b/core/src/main/java/org/apache/accumulo/core/client/impl/NamespaceOperationsImpl.java index 0716122..3612865 100644 --- a/core/src/main/java/org/apache/accumulo/core/client/impl/NamespaceOperationsImpl.java +++ b/core/src/main/java/org/apache/accumulo/core/client/impl/NamespaceOperationsImpl.java @@ -28,9 +28,11 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.SortedSet; +import java.util.TreeMap; import java.util.TreeSet; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; import org.apache.accumulo.core.client.AccumuloException; import org.apache.accumulo.core.client.AccumuloSecurityException; import org.apache.accumulo.core.client.IteratorSetting; @@ -98,7 +100,7 @@ public class NamespaceOperationsImpl extends NamespaceOperationsHelper { timer = new OpTimer().start(); } - boolean exists = Namespaces.getNameToIdMap(context.getInstance()).containsKey(namespace); + boolean exists = Namespaces.namespaceNameExists(context.getInstance(), namespace); if (timer != null) { timer.stop(); @@ -124,7 +126,7 @@ public class NamespaceOperationsImpl extends NamespaceOperationsHelper { @Override public void delete(String namespace) throws AccumuloException, AccumuloSecurityException, NamespaceNotFoundException, NamespaceNotEmptyException { checkArgument(namespace != null, "namespace is null"); - String namespaceId = Namespaces.getNamespaceId(context.getInstance(), namespace); + Namespace.ID namespaceId = Namespaces.getNamespaceId(context.getInstance(), namespace); if (namespaceId.equals(Namespaces.ACCUMULO_NAMESPACE_ID) || namespaceId.equals(Namespaces.DEFAULT_NAMESPACE_ID)) { Credentials credentials = context.getCredentials(); @@ -133,7 +135,7 @@ public class NamespaceOperationsImpl extends NamespaceOperationsHelper { } if (Namespaces.getTableIds(context.getInstance(), namespaceId).size() > 0) { - throw new NamespaceNotEmptyException(namespaceId, namespace, null); + throw new NamespaceNotEmptyException(namespaceId.canonicalID(), namespace, null); } List<ByteBuffer> args = Arrays.asList(ByteBuffer.wrap(namespace.getBytes(UTF_8))); @@ -213,7 +215,10 @@ public class NamespaceOperationsImpl extends NamespaceOperationsHelper { @Override public Map<String,String> namespaceIdMap() { - return Namespaces.getNameToIdMap(context.getInstance()); + return Namespaces.getNameToIdMap(context.getInstance()).entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().canonicalID(), (v1, v2) -> { + throw new RuntimeException(String.format("Duplicate key for values %s and %s", v1, v2)); + }, TreeMap::new)); } @Override http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/Namespaces.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/Namespaces.java b/core/src/main/java/org/apache/accumulo/core/client/impl/Namespaces.java index 4eda3db..e4a6730 100644 --- a/core/src/main/java/org/apache/accumulo/core/client/impl/Namespaces.java +++ b/core/src/main/java/org/apache/accumulo/core/client/impl/Namespaces.java @@ -18,12 +18,14 @@ package org.apache.accumulo.core.client.impl; import static java.nio.charset.StandardCharsets.UTF_8; +import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Map.Entry; import java.util.SortedMap; import java.util.TreeMap; +import java.util.function.BiConsumer; import org.apache.accumulo.core.Constants; import org.apache.accumulo.core.client.Instance; import org.apache.accumulo.core.client.NamespaceNotFoundException; @@ -31,8 +33,12 @@ import org.apache.accumulo.core.util.Validator; import org.apache.accumulo.core.zookeeper.ZooUtil; import org.apache.accumulo.fate.zookeeper.ZooCache; import org.apache.accumulo.fate.zookeeper.ZooCacheFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class Namespaces { + private static final Logger log = LoggerFactory.getLogger(Namespaces.class); + public static final String VALID_NAME_REGEX = "^\\w*$"; public static final Validator<String> VALID_NAME = new Validator<String>() { @Override @@ -72,78 +78,118 @@ public class Namespaces { } }; - public static final String DEFAULT_NAMESPACE_ID = "+default"; - public static final String DEFAULT_NAMESPACE = ""; - public static final String ACCUMULO_NAMESPACE_ID = "+accumulo"; - public static final String ACCUMULO_NAMESPACE = "accumulo"; + public static final Namespace.ID DEFAULT_NAMESPACE_ID = Namespace.ID.DEFAULT; + public static final String DEFAULT_NAMESPACE = Namespace.DEFAULT; + public static final Namespace.ID ACCUMULO_NAMESPACE_ID = Namespace.ID.ACCUMULO; + public static final String ACCUMULO_NAMESPACE = Namespace.ACCUMULO; private static ZooCache getZooCache(Instance instance) { return new ZooCacheFactory().getZooCache(instance.getZooKeepers(), instance.getZooKeepersSessionTimeOut()); } - private static SortedMap<String,String> getMap(Instance instance, boolean nameAsKey) { + public static boolean exists(Instance instance, Namespace.ID namespaceId) { ZooCache zc = getZooCache(instance); - List<String> namespaceIds = zc.getChildren(ZooUtil.getRoot(instance) + Constants.ZNAMESPACES); + return namespaceIds.contains(namespaceId.canonicalID()); + } - TreeMap<String,String> namespaceMap = new TreeMap<>(); + public static List<Table.ID> getTableIds(Instance instance, Namespace.ID namespaceId) throws NamespaceNotFoundException { + String namespace = getNamespaceName(instance, namespaceId); + List<Table.ID> tableIds = new LinkedList<>(); + for (Entry<String,Table.ID> nameToId : Tables.getNameToIdMap(instance).entrySet()) + if (namespace.equals(Tables.qualify(nameToId.getKey()).getFirst())) + tableIds.add(nameToId.getValue()); + return tableIds; + } + public static List<String> getTableNames(Instance instance, Namespace.ID namespaceId) throws NamespaceNotFoundException { + String namespace = getNamespaceName(instance, namespaceId); + List<String> names = new LinkedList<>(); + for (String name : Tables.getNameToIdMap(instance).keySet()) + if (namespace.equals(Tables.qualify(name).getFirst())) + names.add(name); + return names; + } + + /** + * Populate map passed in as the BiConsumer. key = ID, value = namespaceName + */ + private static void populateMap(Instance instance, BiConsumer<String,String> biConsumer) { + final ZooCache zc = getZooCache(instance); + List<String> namespaceIds = zc.getChildren(ZooUtil.getRoot(instance) + Constants.ZNAMESPACES); for (String id : namespaceIds) { byte[] path = zc.get(ZooUtil.getRoot(instance) + Constants.ZNAMESPACES + "/" + id + Constants.ZNAMESPACE_NAME); if (path != null) { - if (nameAsKey) - namespaceMap.put(new String(path, UTF_8), id); - else - namespaceMap.put(id, new String(path, UTF_8)); + biConsumer.accept(id, new String(path, UTF_8)); } } - return namespaceMap; } - public static boolean exists(Instance instance, String namespaceId) { - ZooCache zc = getZooCache(instance); - List<String> namespaceIds = zc.getChildren(ZooUtil.getRoot(instance) + Constants.ZNAMESPACES); - return namespaceIds.contains(namespaceId); + /** + * Return sorted map with key = ID, value = namespaceName + */ + public static SortedMap<Namespace.ID,String> getIdToNameMap(Instance instance) { + SortedMap<Namespace.ID,String> idMap = new TreeMap<>(); + populateMap(instance, (id, name) -> idMap.put(new Namespace.ID(id), name)); + return idMap; } - public static String getNamespaceId(Instance instance, String namespace) throws NamespaceNotFoundException { - String id = getNameToIdMap(instance).get(namespace); - if (id == null) - throw new NamespaceNotFoundException(null, namespace, "getNamespaceId() failed to find namespace"); - return id; - } - - public static String getNamespaceName(Instance instance, String namespaceId) throws NamespaceNotFoundException { - String namespaceName = getIdToNameMap(instance).get(namespaceId); - if (namespaceName == null) - throw new NamespaceNotFoundException(namespaceId, null, "getNamespaceName() failed to find namespace"); - return namespaceName; + /** + * Return sorted map with key = namespaceName, value = ID + */ + public static SortedMap<String,Namespace.ID> getNameToIdMap(Instance instance) { + SortedMap<String,Namespace.ID> nameMap = new TreeMap<>(); + populateMap(instance, (id, name) -> nameMap.put(name, new Namespace.ID(id))); + return nameMap; } - public static SortedMap<String,String> getNameToIdMap(Instance instance) { - return getMap(instance, true); + /** + * Look for namespace ID in ZK. Throw NamespaceNotFoundException if not found. + */ + public static Namespace.ID getNamespaceId(Instance instance, String namespaceName) throws NamespaceNotFoundException { + final ArrayList<Namespace.ID> singleId = new ArrayList<>(1); + populateMap(instance, (id, name) -> { + if (name.equals(namespaceName)) + singleId.add(new Namespace.ID(id)); + }); + if (singleId.isEmpty()) + throw new NamespaceNotFoundException(null, namespaceName, "getNamespaceId() failed to find namespace"); + return singleId.get(0); } - public static SortedMap<String,String> getIdToNameMap(Instance instance) { - return getMap(instance, false); + /** + * Look for namespace ID in ZK. Fail quietly by logging and returning null. + */ + public static Namespace.ID lookupNamespaceId(Instance instance, String namespaceName) { + Namespace.ID id = null; + try { + id = getNamespaceId(instance, namespaceName); + } catch (NamespaceNotFoundException e) { + if (log.isDebugEnabled()) + log.debug("Failed to find namespace ID from name: " + namespaceName, e); + } + return id; } - public static List<String> getTableIds(Instance instance, String namespaceId) throws NamespaceNotFoundException { - String namespace = getNamespaceName(instance, namespaceId); - List<String> names = new LinkedList<>(); - for (Entry<String,String> nameToId : Tables.getNameToIdMap(instance).entrySet()) - if (namespace.equals(Tables.qualify(nameToId.getKey()).getFirst())) - names.add(nameToId.getValue()); - return names; + /** + * Return true if namespace name exists + */ + public static boolean namespaceNameExists(Instance instance, String namespaceName) { + return lookupNamespaceId(instance, namespaceName) != null; } - public static List<String> getTableNames(Instance instance, String namespaceId) throws NamespaceNotFoundException { - String namespace = getNamespaceName(instance, namespaceId); - List<String> names = new LinkedList<>(); - for (String name : Tables.getNameToIdMap(instance).keySet()) - if (namespace.equals(Tables.qualify(name).getFirst())) - names.add(name); - return names; + /** + * Look for namespace name in ZK. Throw NamespaceNotFoundException if not found. + */ + public static String getNamespaceName(Instance instance, Namespace.ID namespaceId) throws NamespaceNotFoundException { + String name; + ZooCache zc = getZooCache(instance); + byte[] path = zc.get(ZooUtil.getRoot(instance) + Constants.ZNAMESPACES + "/" + namespaceId.canonicalID() + Constants.ZNAMESPACE_NAME); + if (path != null) + name = new String(path, UTF_8); + else + throw new NamespaceNotFoundException(namespaceId.canonicalID(), null, "getNamespaceName() failed to find namespace"); + return name; } } http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/OfflineIterator.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/OfflineIterator.java b/core/src/main/java/org/apache/accumulo/core/client/impl/OfflineIterator.java index 0546ab9..4d8470b 100644 --- a/core/src/main/java/org/apache/accumulo/core/client/impl/OfflineIterator.java +++ b/core/src/main/java/org/apache/accumulo/core/client/impl/OfflineIterator.java @@ -146,7 +146,7 @@ class OfflineIterator implements Iterator<Entry<Key,Value>> { private Range range; private KeyExtent currentExtent; private Connector conn; - private String tableId; + private Table.ID tableId; private Authorizations authorizations; private Instance instance; private ScannerOptions options; @@ -162,7 +162,7 @@ class OfflineIterator implements Iterator<Entry<Key,Value>> { this.range = range.bound(this.options.fetchedColumns.first(), this.options.fetchedColumns.last()); } - this.tableId = table.toString(); + this.tableId = new Table.ID(table.toString()); this.authorizations = authorizations; this.readers = new ArrayList<>(); http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/OfflineScanner.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/OfflineScanner.java b/core/src/main/java/org/apache/accumulo/core/client/impl/OfflineScanner.java index 427a7cc..8772184 100644 --- a/core/src/main/java/org/apache/accumulo/core/client/impl/OfflineScanner.java +++ b/core/src/main/java/org/apache/accumulo/core/client/impl/OfflineScanner.java @@ -41,14 +41,14 @@ public class OfflineScanner extends ScannerOptions implements Scanner { private Authorizations authorizations; private Text tableId; - public OfflineScanner(Instance instance, Credentials credentials, String tableId, Authorizations authorizations) { + public OfflineScanner(Instance instance, Credentials credentials, Table.ID tableId, Authorizations authorizations) { checkArgument(instance != null, "instance is null"); checkArgument(credentials != null, "credentials is null"); checkArgument(tableId != null, "tableId is null"); checkArgument(authorizations != null, "authorizations is null"); this.instance = instance; this.credentials = credentials; - this.tableId = new Text(tableId); + this.tableId = new Text(tableId.getUtf8()); this.range = new Range((Key) null, (Key) null); this.authorizations = authorizations; http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/ReplicationOperationsImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/ReplicationOperationsImpl.java b/core/src/main/java/org/apache/accumulo/core/client/impl/ReplicationOperationsImpl.java index ab6160e..79a2dad 100644 --- a/core/src/main/java/org/apache/accumulo/core/client/impl/ReplicationOperationsImpl.java +++ b/core/src/main/java/org/apache/accumulo/core/client/impl/ReplicationOperationsImpl.java @@ -117,7 +117,7 @@ public class ReplicationOperationsImpl implements ReplicationOperations { }); } - protected String getTableId(Connector conn, String tableName) throws AccumuloException, AccumuloSecurityException, TableNotFoundException { + protected Table.ID getTableId(Connector conn, String tableName) throws AccumuloException, AccumuloSecurityException, TableNotFoundException { TableOperations tops = conn.tableOperations(); if (!conn.tableOperations().exists(tableName)) { @@ -132,7 +132,7 @@ public class ReplicationOperationsImpl implements ReplicationOperations { } } - return tableId; + return new Table.ID(tableId); } @Override @@ -142,7 +142,7 @@ public class ReplicationOperationsImpl implements ReplicationOperations { log.debug("Collecting referenced files for replication of table {}", tableName); Connector conn = context.getConnector(); - String tableId = getTableId(conn, tableName); + Table.ID tableId = getTableId(conn, tableName); log.debug("Found id of {} for name {}", tableId, tableName); http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/ScannerImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/ScannerImpl.java b/core/src/main/java/org/apache/accumulo/core/client/impl/ScannerImpl.java index 89406f4..6d4f4b7 100644 --- a/core/src/main/java/org/apache/accumulo/core/client/impl/ScannerImpl.java +++ b/core/src/main/java/org/apache/accumulo/core/client/impl/ScannerImpl.java @@ -46,7 +46,7 @@ public class ScannerImpl extends ScannerOptions implements Scanner { private final ClientContext context; private Authorizations authorizations; - private String tableId; + private Table.ID tableId; private int size; @@ -54,7 +54,7 @@ public class ScannerImpl extends ScannerOptions implements Scanner { private boolean isolated = false; private long readaheadThreshold = Constants.SCANNER_DEFAULT_READAHEAD_THRESHOLD; - public ScannerImpl(ClientContext context, String tableId, Authorizations authorizations) { + public ScannerImpl(ClientContext context, Table.ID tableId, Authorizations authorizations) { checkArgument(context != null, "context is null"); checkArgument(tableId != null, "tableId is null"); checkArgument(authorizations != null, "authorizations is null"); http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/ScannerIterator.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/ScannerIterator.java b/core/src/main/java/org/apache/accumulo/core/client/impl/ScannerIterator.java index ae55cc0..c24e50b 100644 --- a/core/src/main/java/org/apache/accumulo/core/client/impl/ScannerIterator.java +++ b/core/src/main/java/org/apache/accumulo/core/client/impl/ScannerIterator.java @@ -104,7 +104,7 @@ public class ScannerIterator implements Iterator<Entry<Key,Value>> { } - ScannerIterator(ClientContext context, String tableId, Authorizations authorizations, Range range, int size, int timeOut, ScannerOptions options, + ScannerIterator(ClientContext context, Table.ID tableId, Authorizations authorizations, Range range, int size, int timeOut, ScannerOptions options, boolean isolated, long readaheadThreshold) { this.timeOut = timeOut; this.readaheadThreshold = readaheadThreshold; http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/SyncingTabletLocator.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/SyncingTabletLocator.java b/core/src/main/java/org/apache/accumulo/core/client/impl/SyncingTabletLocator.java index 6e7e072..4c3862f 100644 --- a/core/src/main/java/org/apache/accumulo/core/client/impl/SyncingTabletLocator.java +++ b/core/src/main/java/org/apache/accumulo/core/client/impl/SyncingTabletLocator.java @@ -51,7 +51,7 @@ public class SyncingTabletLocator extends TabletLocator { } } - public SyncingTabletLocator(final ClientContext context, final String tableId) { + public SyncingTabletLocator(final ClientContext context, final Table.ID tableId) { this(new Callable<TabletLocator>() { @Override public TabletLocator call() throws Exception { http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/Table.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/Table.java b/core/src/main/java/org/apache/accumulo/core/client/impl/Table.java new file mode 100644 index 0000000..e20ef01 --- /dev/null +++ b/core/src/main/java/org/apache/accumulo/core/client/impl/Table.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.accumulo.core.client.impl; + +import org.apache.accumulo.core.client.Instance; + +public class Table { + + /** + * Object representing an internal table ID. This class was created to help with type safety. For help obtaining the value of a table ID from Zookeeper, see + * {@link Tables#getTableId(Instance, String)} + */ + public static class ID extends AbstractId { + private static final long serialVersionUID = 7399913185860577809L; + + public static final ID METADATA = new ID("!0"); + public static final ID REPLICATION = new ID("+rep"); + public static final ID ROOT = new ID("+r"); + + public ID(final String canonical) { + super(canonical); + } + } + +} http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/TableOperationsImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/TableOperationsImpl.java b/core/src/main/java/org/apache/accumulo/core/client/impl/TableOperationsImpl.java index 67c52e2..a5b72c1 100644 --- a/core/src/main/java/org/apache/accumulo/core/client/impl/TableOperationsImpl.java +++ b/core/src/main/java/org/apache/accumulo/core/client/impl/TableOperationsImpl.java @@ -359,7 +359,7 @@ public class TableOperationsImpl extends TableOperationsHelper { case NAMESPACE_NOTFOUND: throw new NamespaceNotFoundException(e); case OFFLINE: - throw new TableOfflineException(context.getInstance(), Tables.getTableId(context.getInstance(), tableOrNamespaceName)); + throw new TableOfflineException(context.getInstance(), Tables.getTableId(context.getInstance(), tableOrNamespaceName).canonicalID()); default: throw new AccumuloException(e.description, e); } @@ -379,12 +379,12 @@ public class TableOperationsImpl extends TableOperationsHelper { private static class SplitEnv { private String tableName; - private String tableId; + private Table.ID tableId; private ExecutorService executor; private CountDownLatch latch; private AtomicReference<Throwable> exception; - SplitEnv(String tableName, String tableId, ExecutorService executor, CountDownLatch latch, AtomicReference<Throwable> exception) { + SplitEnv(String tableName, Table.ID tableId, ExecutorService executor, CountDownLatch latch, AtomicReference<Throwable> exception) { this.tableName = tableName; this.tableId = tableId; this.executor = executor; @@ -435,7 +435,7 @@ public class TableOperationsImpl extends TableOperationsHelper { @Override public void addSplits(String tableName, SortedSet<Text> partitionKeys) throws TableNotFoundException, AccumuloException, AccumuloSecurityException { - String tableId = Tables.getTableId(context.getInstance(), tableName); + Table.ID tableId = Tables.getTableId(context.getInstance(), tableName); List<Text> splits = new ArrayList<>(partitionKeys); // should be sorted because we copied from a sorted set, but that makes assumptions about @@ -457,7 +457,7 @@ public class TableOperationsImpl extends TableOperationsHelper { // user would only have the stack trace for the background thread. if (excep instanceof TableNotFoundException) { TableNotFoundException tnfe = (TableNotFoundException) excep; - throw new TableNotFoundException(tableId, tableName, "Table not found by background thread", tnfe); + throw new TableNotFoundException(tableId.canonicalID(), tableName, "Table not found by background thread", tnfe); } else if (excep instanceof AccumuloSecurityException) { // base == background accumulo security exception AccumuloSecurityException base = (AccumuloSecurityException) excep; @@ -478,7 +478,7 @@ public class TableOperationsImpl extends TableOperationsHelper { } } - private void addSplits(String tableName, SortedSet<Text> partitionKeys, String tableId) throws AccumuloException, AccumuloSecurityException, + private void addSplits(String tableName, SortedSet<Text> partitionKeys, Table.ID tableId) throws AccumuloException, AccumuloSecurityException, TableNotFoundException, AccumuloServerException { TabletLocator tabLocator = TabletLocator.getLocator(context, tableId); @@ -498,9 +498,9 @@ public class TableOperationsImpl extends TableOperationsHelper { if (tl == null) { if (!Tables.exists(context.getInstance(), tableId)) - throw new TableNotFoundException(tableId, tableName, null); + throw new TableNotFoundException(tableId.canonicalID(), tableName, null); else if (Tables.getTableState(context.getInstance(), tableId) == TableState.OFFLINE) - throw new TableOfflineException(context.getInstance(), tableId); + throw new TableOfflineException(context.getInstance(), tableId.canonicalID()); continue; } @@ -539,7 +539,7 @@ public class TableOperationsImpl extends TableOperationsHelper { } catch (ThriftSecurityException e) { Tables.clearCache(context.getInstance()); if (!Tables.exists(context.getInstance(), tableId)) - throw new TableNotFoundException(tableId, tableName, null); + throw new TableNotFoundException(tableId.canonicalID(), tableName, null); throw new AccumuloSecurityException(e.user, e.code, e); } catch (NotServingTabletException e) { // Do not silently spin when we repeatedly fail to get the location for a tablet @@ -597,7 +597,7 @@ public class TableOperationsImpl extends TableOperationsHelper { checkArgument(tableName != null, "tableName is null"); - String tableId = Tables.getTableId(context.getInstance(), tableName); + Table.ID tableId = Tables.getTableId(context.getInstance(), tableName); TreeMap<KeyExtent,String> tabletLocations = new TreeMap<>(); @@ -611,7 +611,7 @@ public class TableOperationsImpl extends TableOperationsHelper { throw ase; } catch (Exception e) { if (!Tables.exists(context.getInstance(), tableId)) { - throw new TableNotFoundException(tableId, tableName, null); + throw new TableNotFoundException(tableId.canonicalID(), tableName, null); } if (e instanceof RuntimeException && e.getCause() instanceof AccumuloSecurityException) { @@ -700,7 +700,7 @@ public class TableOperationsImpl extends TableOperationsHelper { checkArgument(srcTableName != null, "srcTableName is null"); checkArgument(newTableName != null, "newTableName is null"); - String srcTableId = Tables.getTableId(context.getInstance(), srcTableName); + Table.ID srcTableId = Tables.getTableId(context.getInstance(), srcTableName); if (flush) _flush(srcTableId, null, null, true); @@ -711,7 +711,7 @@ public class TableOperationsImpl extends TableOperationsHelper { if (propertiesToSet == null) propertiesToSet = Collections.emptyMap(); - List<ByteBuffer> args = Arrays.asList(ByteBuffer.wrap(srcTableId.getBytes(UTF_8)), ByteBuffer.wrap(newTableName.getBytes(UTF_8))); + List<ByteBuffer> args = Arrays.asList(ByteBuffer.wrap(srcTableId.getUtf8()), ByteBuffer.wrap(newTableName.getBytes(UTF_8))); Map<String,String> opts = new HashMap<>(); for (Entry<String,String> entry : propertiesToSet.entrySet()) { if (entry.getKey().startsWith(CLONE_EXCLUDE_PREFIX)) @@ -749,7 +749,7 @@ public class TableOperationsImpl extends TableOperationsHelper { public void flush(String tableName, Text start, Text end, boolean wait) throws AccumuloException, AccumuloSecurityException, TableNotFoundException { checkArgument(tableName != null, "tableName is null"); - String tableId = Tables.getTableId(context.getInstance(), tableName); + Table.ID tableId = Tables.getTableId(context.getInstance(), tableName); _flush(tableId, start, end, wait); } @@ -787,7 +787,7 @@ public class TableOperationsImpl extends TableOperationsHelper { } } - String tableId = Tables.getTableId(context.getInstance(), tableName); + Table.ID tableId = Tables.getTableId(context.getInstance(), tableName); Text start = config.getStartRow(); Text end = config.getEndRow(); @@ -795,7 +795,7 @@ public class TableOperationsImpl extends TableOperationsHelper { if (config.getFlush()) _flush(tableId, start, end, true); - List<ByteBuffer> args = Arrays.asList(ByteBuffer.wrap(tableId.getBytes(UTF_8)), start == null ? EMPTY : TextUtil.getByteBuffer(start), end == null ? EMPTY + List<ByteBuffer> args = Arrays.asList(ByteBuffer.wrap(tableId.getUtf8()), start == null ? EMPTY : TextUtil.getByteBuffer(start), end == null ? EMPTY : TextUtil.getByteBuffer(end), ByteBuffer.wrap(IteratorUtil.encodeIteratorSettings(config.getIterators())), ByteBuffer .wrap(CompactionStrategyConfigUtil.encode(config.getCompactionStrategy()))); @@ -815,9 +815,9 @@ public class TableOperationsImpl extends TableOperationsHelper { @Override public void cancelCompaction(String tableName) throws AccumuloSecurityException, TableNotFoundException, AccumuloException { - String tableId = Tables.getTableId(context.getInstance(), tableName); + Table.ID tableId = Tables.getTableId(context.getInstance(), tableName); - List<ByteBuffer> args = Arrays.asList(ByteBuffer.wrap(tableId.getBytes(UTF_8))); + List<ByteBuffer> args = Arrays.asList(ByteBuffer.wrap(tableId.getUtf8())); Map<String,String> opts = new HashMap<>(); try { @@ -829,7 +829,7 @@ public class TableOperationsImpl extends TableOperationsHelper { } - private void _flush(String tableId, Text start, Text end, boolean wait) throws AccumuloException, AccumuloSecurityException, TableNotFoundException { + private void _flush(Table.ID tableId, Text start, Text end, boolean wait) throws AccumuloException, AccumuloSecurityException, TableNotFoundException { try { long flushID; @@ -841,7 +841,7 @@ public class TableOperationsImpl extends TableOperationsHelper { MasterClientService.Iface client = null; try { client = MasterClient.getConnectionWithRetry(context); - flushID = client.initiateFlush(Tracer.traceInfo(), context.rpcCreds(), tableId); + flushID = client.initiateFlush(Tracer.traceInfo(), context.rpcCreds(), tableId.canonicalID()); break; } catch (TTransportException tte) { log.debug("Failed to call initiateFlush, retrying ... ", tte); @@ -859,8 +859,8 @@ public class TableOperationsImpl extends TableOperationsHelper { MasterClientService.Iface client = null; try { client = MasterClient.getConnectionWithRetry(context); - client.waitForFlush(Tracer.traceInfo(), context.rpcCreds(), tableId, TextUtil.getByteBuffer(start), TextUtil.getByteBuffer(end), flushID, - wait ? Long.MAX_VALUE : 1); + client.waitForFlush(Tracer.traceInfo(), context.rpcCreds(), tableId.canonicalID(), TextUtil.getByteBuffer(start), TextUtil.getByteBuffer(end), + flushID, wait ? Long.MAX_VALUE : 1); break; } catch (TTransportException tte) { log.debug("Failed to call initiateFlush, retrying ... ", tte); @@ -876,7 +876,7 @@ public class TableOperationsImpl extends TableOperationsHelper { } catch (ThriftSecurityException e) { switch (e.getCode()) { case TABLE_DOESNT_EXIST: - throw new TableNotFoundException(tableId, null, e.getMessage(), e); + throw new TableNotFoundException(tableId.canonicalID(), null, e.getMessage(), e); default: log.debug("flush security exception on table id {}", tableId); throw new AccumuloSecurityException(e.user, e.code, e); @@ -1029,15 +1029,15 @@ public class TableOperationsImpl extends TableOperationsHelper { Random random = new Random(); Map<String,Map<KeyExtent,List<Range>>> binnedRanges = new HashMap<>(); - String tableId = Tables.getTableId(context.getInstance(), tableName); + Table.ID tableId = Tables.getTableId(context.getInstance(), tableName); TabletLocator tl = TabletLocator.getLocator(context, tableId); // its possible that the cache could contain complete, but old information about a tables tablets... so clear it tl.invalidateCache(); while (!tl.binRanges(context, Collections.singletonList(range), binnedRanges).isEmpty()) { if (!Tables.exists(context.getInstance(), tableId)) - throw new TableDeletedException(tableId); + throw new TableDeletedException(tableId.canonicalID()); if (Tables.getTableState(context.getInstance(), tableId) == TableState.OFFLINE) - throw new TableOfflineException(context.getInstance(), tableId); + throw new TableOfflineException(context.getInstance(), tableId.canonicalID()); log.warn("Unable to locate bins for specified range. Retrying."); // sleep randomly between 100 and 200ms @@ -1135,7 +1135,7 @@ public class TableOperationsImpl extends TableOperationsHelper { } } - private void waitForTableStateTransition(String tableId, TableState expectedState) throws AccumuloException, TableNotFoundException, + private void waitForTableStateTransition(Table.ID tableId, TableState expectedState) throws AccumuloException, TableNotFoundException, AccumuloSecurityException { Text startRow = null; @@ -1147,7 +1147,7 @@ public class TableOperationsImpl extends TableOperationsHelper { Tables.clearCache(context.getInstance()); if (Tables.getTableState(context.getInstance(), tableId) != expectedState) { if (!Tables.exists(context.getInstance(), tableId)) - throw new TableDeletedException(tableId); + throw new TableDeletedException(tableId.canonicalID()); throw new AccumuloException("Unexpected table state " + tableId + " " + Tables.getTableState(context.getInstance(), tableId) + " != " + expectedState); } } @@ -1269,8 +1269,8 @@ public class TableOperationsImpl extends TableOperationsHelper { public void offline(String tableName, boolean wait) throws AccumuloSecurityException, AccumuloException, TableNotFoundException { checkArgument(tableName != null, "tableName is null"); - String tableId = Tables.getTableId(context.getInstance(), tableName); - List<ByteBuffer> args = Arrays.asList(ByteBuffer.wrap(tableId.getBytes(UTF_8))); + Table.ID tableId = Tables.getTableId(context.getInstance(), tableName); + List<ByteBuffer> args = Arrays.asList(ByteBuffer.wrap(tableId.getUtf8())); Map<String,String> opts = new HashMap<>(); try { @@ -1293,7 +1293,7 @@ public class TableOperationsImpl extends TableOperationsHelper { public void online(String tableName, boolean wait) throws AccumuloSecurityException, AccumuloException, TableNotFoundException { checkArgument(tableName != null, "tableName is null"); - String tableId = Tables.getTableId(context.getInstance(), tableName); + Table.ID tableId = Tables.getTableId(context.getInstance(), tableName); /** * ACCUMULO-4574 if table is already online return without executing fate operation. @@ -1304,7 +1304,7 @@ public class TableOperationsImpl extends TableOperationsHelper { return; } - List<ByteBuffer> args = Arrays.asList(ByteBuffer.wrap(tableId.getBytes(UTF_8))); + List<ByteBuffer> args = Arrays.asList(ByteBuffer.wrap(tableId.getUtf8())); Map<String,String> opts = new HashMap<>(); try { @@ -1327,7 +1327,10 @@ public class TableOperationsImpl extends TableOperationsHelper { @Override public Map<String,String> tableIdMap() { - return Tables.getNameToIdMap(context.getInstance()); + return Tables.getNameToIdMap(context.getInstance()).entrySet().stream() + .collect(Collectors.toMap(Entry::getKey, e -> e.getValue().canonicalID(), (v1, v2) -> { + throw new RuntimeException(String.format("Duplicate key for values %s and %s", v1, v2)); + }, TreeMap::new)); } @Override @@ -1646,7 +1649,7 @@ public class TableOperationsImpl extends TableOperationsHelper { requireNonNull(tableName, "tableName must be non null"); requireNonNull(ranges, "ranges must be non null"); - String tableId = Tables.getTableId(context.getInstance(), tableName); + Table.ID tableId = Tables.getTableId(context.getInstance(), tableName); TabletLocator locator = TabletLocator.getLocator(context, tableId); List<Range> rangeList = null; @@ -1665,9 +1668,9 @@ public class TableOperationsImpl extends TableOperationsHelper { while (!locator.binRanges(context, rangeList, binnedRanges).isEmpty()) { if (!Tables.exists(context.getInstance(), tableId)) - throw new TableNotFoundException(tableId, tableName, null); + throw new TableNotFoundException(tableId.canonicalID(), tableName, null); if (Tables.getTableState(context.getInstance(), tableId) == TableState.OFFLINE) - throw new TableOfflineException(context.getInstance(), tableId); + throw new TableOfflineException(context.getInstance(), tableId.canonicalID()); binnedRanges.clear(); @@ -1711,12 +1714,12 @@ public class TableOperationsImpl extends TableOperationsHelper { @Override public List<Summary> retrieve() throws AccumuloException, AccumuloSecurityException, TableNotFoundException { - String tableId = Tables.getTableId(context.getInstance(), tableName); + Table.ID tableId = Tables.getTableId(context.getInstance(), tableName); if (Tables.getTableState(context.getInstance(), tableId) == TableState.OFFLINE) - throw new TableOfflineException(context.getInstance(), tableId); + throw new TableOfflineException(context.getInstance(), tableId.canonicalID()); TRowRange range = new TRowRange(TextUtil.getByteBuffer(startRow), TextUtil.getByteBuffer(endRow)); - TSummaryRequest request = new TSummaryRequest(tableId, range, summariesToFetch, summarizerClassRegex); + TSummaryRequest request = new TSummaryRequest(tableId.canonicalID(), range, summariesToFetch, summarizerClassRegex); if (flush) { _flush(tableId, startRow, endRow, true); } http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/Tables.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/Tables.java b/core/src/main/java/org/apache/accumulo/core/client/impl/Tables.java index 5c3c0f6..b1d1cad 100644 --- a/core/src/main/java/org/apache/accumulo/core/client/impl/Tables.java +++ b/core/src/main/java/org/apache/accumulo/core/client/impl/Tables.java @@ -19,6 +19,7 @@ package org.apache.accumulo.core.client.impl; import static com.google.common.base.Preconditions.checkArgument; import static java.nio.charset.StandardCharsets.UTF_8; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -26,6 +27,7 @@ import java.util.SortedMap; import java.util.TreeMap; import java.util.concurrent.atomic.AtomicLong; +import java.util.function.BiConsumer; import org.apache.accumulo.core.Constants; import org.apache.accumulo.core.client.Instance; import org.apache.accumulo.core.client.NamespaceNotFoundException; @@ -50,48 +52,11 @@ public class Tables { return new ZooCacheFactory().getZooCache(instance.getZooKeepers(), instance.getZooKeepersSessionTimeOut()); } - private static SortedMap<String,String> getMap(Instance instance, boolean nameAsKey) { - ZooCache zc = getZooCache(instance); - - List<String> tableIds = zc.getChildren(ZooUtil.getRoot(instance) + Constants.ZTABLES); - TreeMap<String,String> tableMap = new TreeMap<>(); - Map<String,String> namespaceIdToNameMap = new HashMap<>(); - - for (String tableId : tableIds) { - byte[] tableName = zc.get(ZooUtil.getRoot(instance) + Constants.ZTABLES + "/" + tableId + Constants.ZTABLE_NAME); - byte[] nId = zc.get(ZooUtil.getRoot(instance) + Constants.ZTABLES + "/" + tableId + Constants.ZTABLE_NAMESPACE); - String namespaceName = Namespaces.DEFAULT_NAMESPACE; - // create fully qualified table name - if (nId == null) { - namespaceName = null; - } else { - String namespaceId = new String(nId, UTF_8); - if (!namespaceId.equals(Namespaces.DEFAULT_NAMESPACE_ID)) { - try { - namespaceName = namespaceIdToNameMap.get(namespaceId); - if (namespaceName == null) { - namespaceName = Namespaces.getNamespaceName(instance, namespaceId); - namespaceIdToNameMap.put(namespaceId, namespaceName); - } - } catch (NamespaceNotFoundException e) { - log.error("Table (" + tableId + ") contains reference to namespace (" + namespaceId + ") that doesn't exist", e); - continue; - } - } - } - if (tableName != null && namespaceName != null) { - String tableNameStr = qualified(new String(tableName, UTF_8), namespaceName); - if (nameAsKey) - tableMap.put(tableNameStr, tableId); - else - tableMap.put(tableId, tableNameStr); - } - } - - return tableMap; - } - - public static String getTableId(Instance instance, String tableName) throws TableNotFoundException { + /** + * Lookup table ID in ZK. Throw TableNotFoundException if not found. Also wraps NamespaceNotFoundException in TableNotFoundException if namespace is not + * found. + */ + public static Table.ID getTableId(Instance instance, String tableName) throws TableNotFoundException { try { return _getTableId(instance, tableName); } catch (NamespaceNotFoundException e) { @@ -99,12 +64,15 @@ public class Tables { } } - public static String _getTableId(Instance instance, String tableName) throws NamespaceNotFoundException, TableNotFoundException { - String tableId = getNameToIdMap(instance).get(tableName); + /** + * Lookup table ID in ZK. If not found, clears cache and tries again. + */ + public static Table.ID _getTableId(Instance instance, String tableName) throws NamespaceNotFoundException, TableNotFoundException { + Table.ID tableId = lookupTableId(instance, tableName); if (tableId == null) { // maybe the table exist, but the cache was not updated yet... so try to clear the cache and check again clearCache(instance); - tableId = getNameToIdMap(instance).get(tableName); + tableId = lookupTableId(instance, tableName); if (tableId == null) { String namespace = qualify(tableName).getFirst(); if (Namespaces.getNameToIdMap(instance).containsKey(namespace)) @@ -116,25 +84,12 @@ public class Tables { return tableId; } - public static String getTableName(Instance instance, String tableId) throws TableNotFoundException { - String tableName = getIdToNameMap(instance).get(tableId); - if (tableName == null) - throw new TableNotFoundException(tableId, null, null); - return tableName; - } - - public static SortedMap<String,String> getNameToIdMap(Instance instance) { - return getMap(instance, true); - } - - public static SortedMap<String,String> getIdToNameMap(Instance instance) { - return getMap(instance, false); - } - - public static boolean exists(Instance instance, String tableId) { + public static boolean exists(Instance instance, Table.ID tableId) { + if (tableId == null) + return false; ZooCache zc = getZooCache(instance); List<String> tableIds = zc.getChildren(ZooUtil.getRoot(instance) + Constants.ZTABLES); - return tableIds.contains(tableId); + return tableIds.contains(tableId.canonicalID()); } public static void clearCache(Instance instance) { @@ -165,32 +120,27 @@ public class Tables { } - public static String getPrintableTableNameFromId(Map<String,String> tidToNameMap, String tableId) { - String tableName = tidToNameMap.get(tableId); - return tableName == null ? "(ID:" + tableId + ")" : tableName; - } - - public static String getPrintableTableInfoFromId(Instance instance, String tableId) { + public static String getPrintableTableInfoFromId(Instance instance, Table.ID tableId) { String tableName = null; try { tableName = getTableName(instance, tableId); } catch (TableNotFoundException e) { // handled in the string formatting } - return tableName == null ? String.format("?(ID:%s)", tableId) : String.format("%s(ID:%s)", tableName, tableId); + return tableName == null ? String.format("?(ID:%s)", tableId.canonicalID()) : String.format("%s(ID:%s)", tableName, tableId.canonicalID()); } public static String getPrintableTableInfoFromName(Instance instance, String tableName) { - String tableId = null; + Table.ID tableId = null; try { tableId = getTableId(instance, tableName); } catch (TableNotFoundException e) { // handled in the string formatting } - return tableId == null ? String.format("%s(?)", tableName) : String.format("%s(ID:%s)", tableName, tableId); + return tableId == null ? String.format("%s(?)", tableName) : String.format("%s(ID:%s)", tableName, tableId.canonicalID()); } - public static TableState getTableState(Instance instance, String tableId) { + public static TableState getTableState(Instance instance, Table.ID tableId) { return getTableState(instance, tableId, false); } @@ -206,9 +156,9 @@ public class Tables { * if true clear the table state in zookeeper before checking status * @return the table state. */ - public static TableState getTableState(Instance instance, String tableId, boolean clearCachedState) { + public static TableState getTableState(Instance instance, Table.ID tableId, boolean clearCachedState) { - String statePath = ZooUtil.getRoot(instance) + Constants.ZTABLES + "/" + tableId + Constants.ZTABLE_STATE; + String statePath = ZooUtil.getRoot(instance) + Constants.ZTABLES + "/" + tableId.canonicalID() + Constants.ZTABLE_STATE; if (clearCachedState) { Tables.clearCacheByPath(instance, statePath); @@ -266,7 +216,7 @@ public class Tables { * @throws IllegalArgumentException * if the table doesn't exist in ZooKeeper */ - public static String getNamespaceId(Instance instance, String tableId) throws TableNotFoundException { + public static Namespace.ID getNamespaceId(Instance instance, Table.ID tableId) throws TableNotFoundException { checkArgument(instance != null, "instance is null"); checkArgument(tableId != null, "tableId is null"); @@ -275,10 +225,86 @@ public class Tables { // We might get null out of ZooCache if this tableID doesn't exist if (null == n) { - throw new TableNotFoundException(tableId, null, null); + throw new TableNotFoundException(tableId.canonicalID(), null, null); } - return new String(n, UTF_8); + return new Namespace.ID(new String(n, UTF_8)); + } + + /** + * Get all table Ids and table names from ZK. The biConsumer accepts the first arg (t) as the table ID and second arg (u) as the table name. + */ + private static void getAllTables(Instance instance, BiConsumer<String,String> biConsumer) { + ZooCache zc = getZooCache(instance); + List<String> tableIds = zc.getChildren(ZooUtil.getRoot(instance) + Constants.ZTABLES); + Map<Namespace.ID,String> namespaceIdToNameMap = new HashMap<>(); + + for (String tableId : tableIds) { + byte[] tableName = zc.get(ZooUtil.getRoot(instance) + Constants.ZTABLES + "/" + tableId + Constants.ZTABLE_NAME); + byte[] nId = zc.get(ZooUtil.getRoot(instance) + Constants.ZTABLES + "/" + tableId + Constants.ZTABLE_NAMESPACE); + String namespaceName = Namespaces.DEFAULT_NAMESPACE; + // create fully qualified table name + if (nId == null) { + namespaceName = null; + } else { + Namespace.ID namespaceId = new Namespace.ID(new String(nId, UTF_8)); + if (!namespaceId.equals(Namespaces.DEFAULT_NAMESPACE_ID)) { + try { + namespaceName = namespaceIdToNameMap.get(namespaceId); + if (namespaceName == null) { + namespaceName = Namespaces.getNamespaceName(instance, namespaceId); + namespaceIdToNameMap.put(namespaceId, namespaceName); + } + } catch (NamespaceNotFoundException e) { + log.error("Table (" + tableId + ") contains reference to namespace (" + namespaceId + ") that doesn't exist", e); + continue; + } + } + } + if (tableName != null && namespaceName != null) { + String tableNameStr = qualified(new String(tableName, UTF_8), namespaceName); + biConsumer.accept(tableId, tableNameStr); + } + } + } + + public static SortedMap<Table.ID,String> getIdToNameMap(Instance instance) { + SortedMap<Table.ID,String> map = new TreeMap<>(); + getAllTables(instance, (id, name) -> map.put(new Table.ID(id), name)); + return map; + } + + public static SortedMap<String,Table.ID> getNameToIdMap(Instance instance) { + SortedMap<String,Table.ID> map = new TreeMap<>(); + getAllTables(instance, (id, name) -> map.put(name, new Table.ID(id))); + return map; + } + + /** + * Lookup the table name in ZK. Fail quietly, returning null if not found. + */ + public static Table.ID lookupTableId(Instance instance, String tableName) { + ArrayList<Table.ID> singleId = new ArrayList<>(1); + getAllTables(instance, (id, name) -> { + if (name.equals(tableName)) + singleId.add(new Table.ID(id)); + }); + if (singleId.isEmpty()) + return null; + else + return singleId.get(0); + } + + public static String getTableName(Instance instance, Table.ID tableId) throws TableNotFoundException { + ArrayList<String> singleName = new ArrayList<>(1); + getAllTables(instance, (id, name) -> { + if (id.equals(tableId.canonicalID())) + singleName.add(name); + }); + if (singleName.isEmpty()) + throw new TableNotFoundException(tableId.canonicalID(), null, null); + + return singleName.get(0); } } http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/TabletLocator.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/TabletLocator.java b/core/src/main/java/org/apache/accumulo/core/client/impl/TabletLocator.java index 9229643..de7b12b 100644 --- a/core/src/main/java/org/apache/accumulo/core/client/impl/TabletLocator.java +++ b/core/src/main/java/org/apache/accumulo/core/client/impl/TabletLocator.java @@ -74,16 +74,16 @@ public abstract class TabletLocator { private static class LocatorKey { String instanceId; - String tableName; + Table.ID tableId; - LocatorKey(String instanceId, String table) { + LocatorKey(String instanceId, Table.ID table) { this.instanceId = instanceId; - this.tableName = table; + this.tableId = table; } @Override public int hashCode() { - return instanceId.hashCode() + tableName.hashCode(); + return instanceId.hashCode() + tableId.hashCode(); } @Override @@ -94,7 +94,7 @@ public abstract class TabletLocator { } public boolean equals(LocatorKey lk) { - return instanceId.equals(lk.instanceId) && tableName.equals(lk.tableName); + return instanceId.equals(lk.instanceId) && tableId.equals(lk.tableId); } } @@ -108,7 +108,7 @@ public abstract class TabletLocator { locators.clear(); } - public static synchronized TabletLocator getLocator(ClientContext context, String tableId) { + public static synchronized TabletLocator getLocator(ClientContext context, Table.ID tableId) { Instance instance = context.getInstance(); LocatorKey key = new LocatorKey(instance.getInstanceID(), tableId); TabletLocator tl = locators.get(key);