From 2c392da8aa790ea7541745c4d77e0b5ecbc47ac6 Mon Sep 17 00:00:00 2001 From: Sunil G Date: Fri, 5 Oct 2018 16:10:47 +0530 Subject: [PATCH] HADOOP-15791. Remove Ozone related sources from the 3.2 branch. Contributed by Elek, Marton. --- .gitignore | 10 - dev-support/bin/dist-layout-stitching | 3 - .../assemblies/hadoop-src-with-hdds.xml | 56 - .../main/resources/assemblies/hadoop-src.xml | 2 - .../src/main/bin/hadoop-functions.sh | 5 - .../hadoop-common/src/main/conf/hadoop-env.sh | 9 - hadoop-hdds/client/pom.xml | 44 - .../hadoop/hdds/scm/XceiverClientGrpc.java | 215 --- .../hadoop/hdds/scm/XceiverClientManager.java | 224 --- .../hadoop/hdds/scm/XceiverClientMetrics.java | 92 -- .../hadoop/hdds/scm/XceiverClientRatis.java | 215 --- .../scm/client/ContainerOperationClient.java | 476 ------ .../hdds/scm/client/HddsClientUtils.java | 255 --- .../hadoop/hdds/scm/client/package-info.java | 23 - .../apache/hadoop/hdds/scm/package-info.java | 23 - .../hdds/scm/storage/ChunkInputStream.java | 279 ---- .../hdds/scm/storage/ChunkOutputStream.java | 236 --- .../hadoop/hdds/scm/storage/package-info.java | 23 - .../dev-support/findbugsExcludeFile.xml | 28 - hadoop-hdds/common/pom.xml | 250 --- .../common/src/main/conf/log4j.properties | 157 -- .../apache/hadoop/hdds/HddsConfigKeys.java | 97 -- .../org/apache/hadoop/hdds/HddsIdFactory.java | 53 - .../org/apache/hadoop/hdds/HddsUtils.java | 351 ----- .../apache/hadoop/hdds/cli/GenericCli.java | 100 -- .../hadoop/hdds/cli/GenericParentCommand.java | 25 - .../hadoop/hdds/cli/HddsVersionProvider.java | 35 - .../hdds/cli/MissingSubcommandException.java | 35 - .../apache/hadoop/hdds/cli/package-info.java | 22 - .../apache/hadoop/hdds/client/BlockID.java | 90 -- .../apache/hadoop/hdds/client/OzoneQuota.java | 203 --- .../hadoop/hdds/client/ReplicationFactor.java | 63 - .../hadoop/hdds/client/ReplicationType.java | 28 - .../hadoop/hdds/client/package-info.java | 23 - .../hadoop/hdds/conf/HddsConfServlet.java | 185 --- .../hadoop/hdds/conf/OzoneConfiguration.java | 162 -- .../apache/hadoop/hdds/conf/package-info.java | 18 - .../org/apache/hadoop/hdds/package-info.java | 23 - .../hadoop/hdds/protocol/DatanodeDetails.java | 401 ----- .../hadoop/hdds/protocol/package-info.java | 22 - .../apache/hadoop/hdds/scm/ScmConfigKeys.java | 287 ---- .../org/apache/hadoop/hdds/scm/ScmInfo.java | 81 - .../hadoop/hdds/scm/XceiverClientSpi.java | 135 -- .../hadoop/hdds/scm/client/ScmClient.java | 174 --- .../hadoop/hdds/scm/client/package-info.java | 24 - .../hdds/scm/container/ContainerID.java | 107 -- .../common/helpers/AllocatedBlock.java | 79 - .../helpers/BlockNotCommittedException.java | 36 - .../common/helpers/ContainerInfo.java | 482 ------ .../common/helpers/ContainerWithPipeline.java | 132 -- .../common/helpers/DeleteBlockResult.java | 53 - .../container/common/helpers/Pipeline.java | 315 ---- .../container/common/helpers/PipelineID.java | 97 -- .../helpers/StorageContainerException.java | 104 -- .../common/helpers/package-info.java | 22 - .../hdds/scm/container/package-info.java | 18 - .../apache/hadoop/hdds/scm/package-info.java | 24 - .../hdds/scm/protocol/LocatedContainer.java | 127 -- .../protocol/ScmBlockLocationProtocol.java | 60 - .../hdds/scm/protocol/ScmLocatedBlock.java | 100 -- .../StorageContainerLocationProtocol.java | 152 -- .../hdds/scm/protocol/package-info.java | 19 - ...ocationProtocolClientSideTranslatorPB.java | 173 --- .../ScmBlockLocationProtocolPB.java | 35 - ...ocationProtocolClientSideTranslatorPB.java | 371 ----- .../StorageContainerLocationProtocolPB.java | 36 - .../hdds/scm/protocolPB/package-info.java | 24 - .../scm/storage/ContainerProtocolCalls.java | 432 ------ .../hadoop/hdds/scm/storage/package-info.java | 23 - .../org/apache/hadoop/ozone/OzoneAcl.java | 233 --- .../apache/hadoop/ozone/OzoneConfigKeys.java | 308 ---- .../org/apache/hadoop/ozone/OzoneConsts.java | 216 --- .../hadoop/ozone/audit/AuditAction.java | 30 - .../hadoop/ozone/audit/AuditEventStatus.java | 36 - .../hadoop/ozone/audit/AuditLogger.java | 76 - .../hadoop/ozone/audit/AuditLoggerType.java | 37 - .../hadoop/ozone/audit/AuditMarker.java | 38 - .../hadoop/ozone/audit/AuditMessage.java | 131 -- .../apache/hadoop/ozone/audit/Auditable.java | 32 - .../apache/hadoop/ozone/audit/Auditor.java | 33 - .../hadoop/ozone/audit/package-info.java | 138 -- .../hadoop/ozone/common/BlockGroup.java | 97 -- .../ozone/common/DeleteBlockGroupResult.java | 97 -- .../InconsistentStorageStateException.java | 51 - .../apache/hadoop/ozone/common/Storage.java | 249 --- .../hadoop/ozone/common/StorageInfo.java | 183 --- .../hadoop/ozone/common/package-info.java | 18 - .../InvalidStateTransitionException.java | 42 - .../common/statemachine/StateMachine.java | 68 - .../common/statemachine/package-info.java | 21 - .../container/common/helpers/BlockData.java | 255 --- .../container/common/helpers/ChunkInfo.java | 184 --- .../common/helpers/package-info.java | 23 - .../org/apache/hadoop/ozone/lease/Lease.java | 189 --- .../lease/LeaseAlreadyExistException.java | 46 - .../ozone/lease/LeaseCallbackExecutor.java | 65 - .../hadoop/ozone/lease/LeaseException.java | 45 - .../ozone/lease/LeaseExpiredException.java | 45 - .../hadoop/ozone/lease/LeaseManager.java | 251 --- .../LeaseManagerNotRunningException.java | 45 - .../ozone/lease/LeaseNotFoundException.java | 46 - .../hadoop/ozone/lease/package-info.java | 26 - .../apache/hadoop/ozone/lock/ActiveLock.java | 101 -- .../apache/hadoop/ozone/lock/LockManager.java | 101 -- .../hadoop/ozone/lock/PooledLockFactory.java | 43 - .../hadoop/ozone/lock/package-info.java | 21 - .../org/apache/hadoop/ozone/package-info.java | 35 - ...ocationProtocolServerSideTranslatorPB.java | 134 -- ...ocationProtocolServerSideTranslatorPB.java | 253 --- .../hadoop/ozone/protocolPB/package-info.java | 24 - .../hadoop/ozone/web/utils/JsonUtils.java | 71 - .../hadoop/ozone/web/utils/package-info.java | 19 - .../hadoop/utils/BackgroundService.java | 161 -- .../apache/hadoop/utils/BackgroundTask.java | 28 - .../hadoop/utils/BackgroundTaskQueue.java | 64 - .../hadoop/utils/BackgroundTaskResult.java | 44 - .../apache/hadoop/utils/BatchOperation.java | 90 -- .../apache/hadoop/utils/EntryConsumer.java | 38 - .../apache/hadoop/utils/HddsVersionInfo.java | 184 --- .../org/apache/hadoop/utils/LevelDBStore.java | 387 ----- .../hadoop/utils/LevelDBStoreIterator.java | 64 - .../hadoop/utils/MetaStoreIterator.java | 39 - .../hadoop/utils/MetadataKeyFilters.java | 205 --- .../apache/hadoop/utils/MetadataStore.java | 227 --- .../hadoop/utils/MetadataStoreBuilder.java | 152 -- .../org/apache/hadoop/utils/RocksDBStore.java | 388 ----- .../hadoop/utils/RocksDBStoreIterator.java | 66 - .../hadoop/utils/RocksDBStoreMBean.java | 144 -- .../hadoop/utils/db/DBConfigFromFile.java | 146 -- .../org/apache/hadoop/utils/db/DBProfile.java | 120 -- .../org/apache/hadoop/utils/db/DBStore.java | 115 -- .../hadoop/utils/db/DBStoreBuilder.java | 201 --- .../org/apache/hadoop/utils/db/RDBStore.java | 270 ---- .../hadoop/utils/db/RDBStoreIterator.java | 88 -- .../org/apache/hadoop/utils/db/RDBTable.java | 173 --- .../org/apache/hadoop/utils/db/Table.java | 150 -- .../apache/hadoop/utils/db/TableConfig.java | 93 -- .../apache/hadoop/utils/db/TableIterator.java | 50 - .../apache/hadoop/utils/db/package-info.java | 22 - .../org/apache/hadoop/utils/package-info.java | 18 - .../java/org/apache/ratis/RatisHelper.java | 207 --- .../java/org/apache/ratis/package-info.java | 22 - .../proto/DatanodeContainerProtocol.proto | 451 ------ .../main/proto/ScmBlockLocationProtocol.proto | 136 -- .../StorageContainerLocationProtocol.proto | 239 --- hadoop-hdds/common/src/main/proto/hdds.proto | 194 --- .../resources/hdds-version-info.properties | 26 - .../src/main/resources/ozone-default.xml | 1299 ---------------- .../apache/hadoop/hdds/scm/package-info.java | 21 - .../apache/hadoop/ozone/TestOzoneAcls.java | 141 -- .../hadoop/ozone/audit/DummyAction.java | 51 - .../hadoop/ozone/audit/DummyEntity.java | 57 - .../ozone/audit/TestOzoneAuditLogger.java | 166 -- .../hadoop/ozone/audit/package-info.java | 23 - .../hadoop/ozone/common/TestStateMachine.java | 106 -- .../hadoop/ozone/lease/TestLeaseManager.java | 373 ----- .../hadoop/ozone/lease/package-info.java | 21 - .../hadoop/ozone/lock/TestLockManager.java | 64 - .../hadoop/ozone/lock/package-info.java | 21 - .../org/apache/hadoop/ozone/package-info.java | 21 - .../hadoop/utils/TestHddsIdFactory.java | 77 - .../hadoop/utils/TestMetadataStore.java | 590 ------- .../hadoop/utils/TestRocksDBStoreMBean.java | 87 -- .../hadoop/utils/db/TestDBConfigFromFile.java | 116 -- .../hadoop/utils/db/TestDBStoreBuilder.java | 174 --- .../apache/hadoop/utils/db/TestRDBStore.java | 255 --- .../hadoop/utils/db/TestRDBTableStore.java | 198 --- .../apache/hadoop/utils/db/package-info.java | 22 - .../src/test/resources/log4j2.properties | 76 - .../common/src/test/resources/test.db.ini | 145 -- .../dev-support/findbugsExcludeFile.xml | 21 - hadoop-hdds/container-service/pom.xml | 109 -- .../hadoop/hdds/scm/HddsServerUtil.java | 336 ---- .../apache/hadoop/hdds/scm/VersionInfo.java | 81 - .../apache/hadoop/hdds/scm/package-info.java | 19 - .../hadoop/ozone/HddsDatanodeService.java | 256 --- .../common/DataNodeLayoutVersion.java | 80 - .../common/helpers/ContainerMetrics.java | 121 -- .../common/helpers/ContainerReport.java | 205 --- .../common/helpers/ContainerUtils.java | 305 ---- .../common/helpers/DatanodeVersionFile.java | 95 -- .../DeletedContainerBlocksSummary.java | 104 -- .../helpers/KeyValueContainerReport.java | 117 -- .../common/helpers/package-info.java | 22 - .../common/impl/ChunkLayOutVersion.java | 98 -- .../container/common/impl/ContainerData.java | 435 ------ .../common/impl/ContainerDataYaml.java | 326 ---- .../container/common/impl/ContainerSet.java | 220 --- .../container/common/impl/HddsDispatcher.java | 213 --- .../common/impl/OpenContainerBlockMap.java | 151 -- ...RandomContainerDeletionChoosingPolicy.java | 70 - .../common/impl/StorageLocationReport.java | 300 ---- ...rderedContainerDeletionChoosingPolicy.java | 90 -- .../container/common/impl/package-info.java | 22 - .../common/interfaces/BlockIterator.java | 57 - .../common/interfaces/Container.java | 135 -- .../ContainerDeletionChoosingPolicy.java | 58 - .../interfaces/ContainerDispatcher.java | 65 - .../interfaces/ContainerLocationManager.java | 58 - .../ContainerLocationManagerMXBean.java | 34 - .../common/interfaces/ContainerPacker.java | 58 - .../container/common/interfaces/Handler.java | 87 -- .../StorageLocationReportMXBean.java | 40 - .../interfaces/VolumeChoosingPolicy.java | 46 - .../common/interfaces/package-info.java | 20 - .../ozone/container/common/package-info.java | 28 - .../report/CommandStatusReportPublisher.java | 87 -- .../report/ContainerReportPublisher.java | 85 - .../common/report/NodeReportPublisher.java | 66 - .../report/PipelineReportPublisher.java | 73 - .../common/report/ReportManager.java | 148 -- .../common/report/ReportPublisher.java | 115 -- .../common/report/ReportPublisherFactory.java | 79 - .../container/common/report/package-info.java | 80 - .../statemachine/DatanodeStateMachine.java | 434 ------ .../statemachine/EndpointStateMachine.java | 295 ---- .../EndpointStateMachineMBean.java | 34 - .../statemachine/SCMConnectionManager.java | 211 --- .../SCMConnectionManagerMXBean.java | 27 - .../common/statemachine/StateContext.java | 504 ------ .../CloseContainerCommandHandler.java | 159 -- .../commandhandler/CommandDispatcher.java | 182 --- .../commandhandler/CommandHandler.java | 75 - .../DeleteBlocksCommandHandler.java | 266 ---- .../ReplicateContainerCommandHandler.java | 102 -- .../commandhandler/package-info.java | 18 - .../common/statemachine/package-info.java | 28 - .../common/states/DatanodeState.java | 55 - .../states/datanode/InitDatanodeState.java | 182 --- .../states/datanode/RunningDatanodeState.java | 178 --- .../common/states/datanode/package-info.java | 21 - .../endpoint/HeartbeatEndpointTask.java | 385 ----- .../states/endpoint/RegisterEndpointTask.java | 257 ---- .../states/endpoint/VersionEndpointTask.java | 112 -- .../common/states/endpoint/package-info.java | 20 - .../container/common/states/package-info.java | 18 - .../transport/server/GrpcXceiverService.java | 80 - .../transport/server/XceiverServerGrpc.java | 150 -- .../transport/server/XceiverServerSpi.java | 61 - .../common/transport/server/package-info.java | 24 - .../transport/server/ratis/CSMMetrics.java | 115 -- .../server/ratis/ContainerStateMachine.java | 656 -------- .../server/ratis/XceiverServerRatis.java | 429 ------ .../transport/server/ratis/package-info.java | 23 - .../common/utils/ContainerCache.java | 172 --- .../common/utils/HddsVolumeUtil.java | 219 --- .../container/common/utils/package-info.java | 18 - .../container/common/volume/HddsVolume.java | 408 ----- .../RoundRobinVolumeChoosingPolicy.java | 83 - .../common/volume/VolumeIOStats.java | 139 -- .../container/common/volume/VolumeInfo.java | 140 -- .../container/common/volume/VolumeSet.java | 406 ----- .../container/common/volume/VolumeUsage.java | 181 --- .../container/common/volume/package-info.java | 21 - .../keyvalue/KeyValueBlockIterator.java | 148 -- .../container/keyvalue/KeyValueContainer.java | 576 ------- .../keyvalue/KeyValueContainerData.java | 297 ---- .../container/keyvalue/KeyValueHandler.java | 850 ---------- .../keyvalue/TarContainerPacker.java | 249 --- .../keyvalue/helpers/BlockUtils.java | 199 --- .../keyvalue/helpers/ChunkUtils.java | 357 ----- .../KeyValueContainerLocationUtil.java | 109 -- .../helpers/KeyValueContainerUtil.java | 226 --- .../keyvalue/helpers/SmallFileUtils.java | 84 - .../keyvalue/helpers/package-info.java | 21 - .../keyvalue/impl/BlockManagerImpl.java | 229 --- .../keyvalue/impl/ChunkManagerImpl.java | 254 --- .../container/keyvalue/impl/package-info.java | 21 - .../keyvalue/interfaces/BlockManager.java | 84 - .../keyvalue/interfaces/ChunkManager.java | 80 - .../keyvalue/interfaces/package-info.java | 21 - .../container/keyvalue/package-info.java | 21 - .../background/BlockDeletingService.java | 258 ---- .../statemachine/background/package-info.java | 18 - .../container/ozoneimpl/ContainerReader.java | 208 --- .../container/ozoneimpl/OzoneContainer.java | 236 --- .../container/ozoneimpl/package-info.java | 21 - .../replication/ContainerDownloader.java | 40 - .../ContainerReplicationSource.java | 49 - .../replication/ContainerReplicator.java | 27 - .../replication/ContainerStreamingOutput.java | 45 - .../DownloadAndImportReplicator.java | 136 -- .../replication/GrpcReplicationClient.java | 169 -- .../replication/GrpcReplicationService.java | 130 -- .../OnDemandContainerReplicationSource.java | 76 - .../replication/ReplicationSupervisor.java | 142 -- .../replication/ReplicationTask.java | 102 -- .../SimpleContainerDownloader.java | 121 -- .../container/replication/package-info.java | 21 - .../org/apache/hadoop/ozone/package-info.java | 23 - .../StorageContainerDatanodeProtocol.java | 75 - .../StorageContainerNodeProtocol.java | 70 - .../ozone/protocol/VersionResponse.java | 154 -- .../commands/CloseContainerCommand.java | 84 - .../protocol/commands/CommandForDatanode.java | 51 - .../protocol/commands/CommandStatus.java | 164 -- .../commands/DeleteBlockCommandStatus.java | 92 -- .../commands/DeleteBlocksCommand.java | 75 - .../protocol/commands/RegisteredCommand.java | 215 --- .../commands/ReplicateContainerCommand.java | 102 -- .../protocol/commands/ReregisterCommand.java | 67 - .../ozone/protocol/commands/SCMCommand.java | 62 - .../ozone/protocol/commands/package-info.java | 21 - .../hadoop/ozone/protocol/package-info.java | 23 - ...atanodeProtocolClientSideTranslatorPB.java | 167 -- .../StorageContainerDatanodeProtocolPB.java | 34 - ...atanodeProtocolServerSideTranslatorPB.java | 94 -- .../hadoop/ozone/protocolPB/package-info.java | 19 - .../StorageContainerDatanodeProtocol.proto | 386 ----- ...sun.jersey.spi.container.ContainerProvider | 16 - .../container/common/ContainerTestUtils.java | 68 - .../ozone/container/common/SCMTestUtils.java | 129 -- .../ozone/container/common/ScmTestMock.java | 353 ----- .../common/TestChunkLayOutVersion.java | 42 - .../common/TestDatanodeLayOutVersion.java | 38 - .../common/TestDatanodeStateMachine.java | 424 ----- .../common/TestKeyValueContainerData.java | 88 -- .../helpers/TestDatanodeVersionFile.java | 134 -- .../common/impl/TestContainerDataYaml.java | 219 --- .../common/impl/TestContainerSet.java | 182 --- .../common/impl/TestHddsDispatcher.java | 153 -- .../container/common/impl/package-info.java | 22 - .../common/interfaces/TestHandler.java | 80 - .../ozone/container/common/package-info.java | 22 - .../common/report/TestReportManager.java | 52 - .../common/report/TestReportPublisher.java | 200 --- .../report/TestReportPublisherFactory.java | 68 - .../container/common/report/package-info.java | 22 - .../commandhandler/package-info.java | 22 - .../endpoint/TestHeartbeatEndpointTask.java | 295 ---- .../common/states/endpoint/package-info.java | 18 - .../common/volume/TestHddsVolume.java | 145 -- .../TestRoundRobinVolumeChoosingPolicy.java | 126 -- .../common/volume/TestVolumeSet.java | 254 --- .../keyvalue/TestBlockManagerImpl.java | 211 --- .../keyvalue/TestChunkManagerImpl.java | 292 ---- .../keyvalue/TestKeyValueBlockIterator.java | 277 ---- .../keyvalue/TestKeyValueContainer.java | 374 ----- .../keyvalue/TestKeyValueHandler.java | 292 ---- .../keyvalue/TestTarContainerPacker.java | 231 --- .../ozoneimpl/TestOzoneContainer.java | 120 -- .../TestReplicationSupervisor.java | 143 -- .../container/replication/package-info.java | 22 - .../BlockDeletingServiceTestImpl.java | 104 -- .../container/testutils/package-info.java | 18 - .../test/resources/additionalfields.container | 12 - .../resources/incorrect.checksum.container | 11 - .../src/test/resources/incorrect.container | 11 - .../src/test/resources/log4j.properties | 23 - hadoop-hdds/framework/README.md | 24 - hadoop-hdds/framework/pom.xml | 69 - .../hadoop/hdds/server/BaseHttpServer.java | 222 --- .../hadoop/hdds/server/ServerUtils.java | 144 -- .../hdds/server/ServiceRuntimeInfo.java | 64 - .../hdds/server/ServiceRuntimeInfoImpl.java | 55 - .../hadoop/hdds/server/events/Event.java | 42 - .../hdds/server/events/EventExecutor.java | 68 - .../hdds/server/events/EventHandler.java | 33 - .../hdds/server/events/EventPublisher.java | 28 - .../hadoop/hdds/server/events/EventQueue.java | 251 --- .../hdds/server/events/EventWatcher.java | 209 --- .../server/events/EventWatcherMetrics.java | 79 - .../events/IdentifiableEventPayload.java | 28 - .../server/events/SingleThreadExecutor.java | 118 -- .../hadoop/hdds/server/events/TypedEvent.java | 58 - .../hdds/server/events/package-info.java | 23 - .../hadoop/hdds/server/package-info.java | 23 - .../src/main/resources/webapps/datanode/dn.js | 92 -- .../webapps/static/angular-1.6.4.min.js | 332 ---- .../webapps/static/angular-nvd3-1.0.9.min.js | 1 - .../webapps/static/angular-route-1.6.4.min.js | 17 - .../resources/webapps/static/d3-3.5.17.min.js | 5 - .../main/resources/webapps/static/dfs-dust.js | 133 -- .../webapps/static/nvd3-1.8.5.min.css | 2 - .../webapps/static/nvd3-1.8.5.min.css.map | 1 - .../webapps/static/nvd3-1.8.5.min.js | 11 - .../webapps/static/nvd3-1.8.5.min.js.map | 1 - .../main/resources/webapps/static/ozone.css | 60 - .../main/resources/webapps/static/ozone.js | 387 ----- .../webapps/static/templates/config.html | 91 -- .../webapps/static/templates/jvm.html | 26 - .../webapps/static/templates/menu.html | 60 - .../webapps/static/templates/overview.html | 39 - .../webapps/static/templates/rpc-metrics.html | 87 -- .../hdds/server/TestBaseHttpServer.java | 98 -- .../hdds/server/events/EventHandlerStub.java | 38 - .../hdds/server/events/TestEventQueue.java | 83 - .../server/events/TestEventQueueChain.java | 79 - .../hdds/server/events/TestEventWatcher.java | 292 ---- .../src/test/resources/ozone-site.xml | 24 - hadoop-hdds/pom.xml | 203 --- hadoop-hdds/server-scm/pom.xml | 129 -- .../org/apache/hadoop/hdds/scm/ScmUtils.java | 45 - .../hadoop/hdds/scm/block/BlockManager.java | 78 - .../hdds/scm/block/BlockManagerImpl.java | 485 ------ .../hdds/scm/block/BlockmanagerMXBean.java | 30 - .../DatanodeDeletedBlockTransactions.java | 148 -- .../hdds/scm/block/DeletedBlockLog.java | 118 -- .../hdds/scm/block/DeletedBlockLogImpl.java | 428 ------ .../hdds/scm/block/PendingDeleteHandler.java | 38 - .../scm/block/PendingDeleteStatusList.java | 79 - .../scm/block/SCMBlockDeletingService.java | 196 --- .../hadoop/hdds/scm/block/package-info.java | 22 - .../command/CommandStatusReportHandler.java | 131 -- .../hadoop/hdds/scm/command/package-info.java | 26 - .../container/CloseContainerEventHandler.java | 160 -- .../scm/container/CloseContainerWatcher.java | 100 -- .../container/ContainerActionsHandler.java | 60 - .../hdds/scm/container/ContainerMapping.java | 699 --------- .../scm/container/ContainerReportHandler.java | 150 -- .../scm/container/ContainerStateManager.java | 570 ------- .../hadoop/hdds/scm/container/Mapping.java | 141 -- .../scm/container/closer/package-info.java | 23 - .../hdds/scm/container/package-info.java | 22 - .../algorithms/ContainerPlacementPolicy.java | 44 - .../placement/algorithms/SCMCommonPolicy.java | 201 --- .../SCMContainerPlacementCapacity.java | 137 -- .../SCMContainerPlacementRandom.java | 92 -- .../placement/algorithms/package-info.java | 18 - .../placement/metrics/ContainerStat.java | 165 -- .../placement/metrics/DatanodeMetric.java | 91 -- .../placement/metrics/LongMetric.java | 162 -- .../container/placement/metrics/NodeStat.java | 67 - .../placement/metrics/SCMMetrics.java | 154 -- .../placement/metrics/SCMNodeMetric.java | 224 --- .../placement/metrics/SCMNodeStat.java | 139 -- .../placement/metrics/package-info.java | 20 - .../scm/container/placement/package-info.java | 19 - .../ReplicationActivityStatus.java | 117 -- .../ReplicationActivityStatusMXBean.java | 28 - .../ReplicationCommandWatcher.java | 56 - .../replication/ReplicationManager.java | 250 --- .../replication/ReplicationQueue.java | 73 - .../replication/ReplicationRequest.java | 123 -- .../container/replication/package-info.java | 23 - .../container/states/ContainerAttribute.java | 245 --- .../container/states/ContainerQueryKey.java | 110 -- .../scm/container/states/ContainerState.java | 96 -- .../container/states/ContainerStateMap.java | 569 ------- .../scm/container/states/package-info.java | 22 - .../hadoop/hdds/scm/events/SCMEvents.java | 255 --- .../hadoop/hdds/scm/events/package-info.java | 23 - .../hdds/scm/exceptions/SCMException.java | 124 -- .../hdds/scm/exceptions/package-info.java | 18 - .../hadoop/hdds/scm/node/CommandQueue.java | 190 --- .../hadoop/hdds/scm/node/DatanodeInfo.java | 128 -- .../hadoop/hdds/scm/node/DeadNodeHandler.java | 100 -- .../hadoop/hdds/scm/node/NewNodeHandler.java | 49 - .../hadoop/hdds/scm/node/NodeManager.java | 219 --- .../hdds/scm/node/NodeManagerMXBean.java | 57 - .../hdds/scm/node/NodeReportHandler.java | 55 - .../hdds/scm/node/NodeStateManager.java | 725 --------- .../hadoop/hdds/scm/node/SCMNodeManager.java | 599 -------- .../scm/node/SCMNodeStorageStatMXBean.java | 77 - .../hdds/scm/node/SCMNodeStorageStatMap.java | 368 ----- .../hdds/scm/node/StaleNodeHandler.java | 42 - .../hdds/scm/node/StorageReportResult.java | 87 -- .../hadoop/hdds/scm/node/package-info.java | 31 - .../scm/node/states/Node2ContainerMap.java | 90 -- .../hdds/scm/node/states/Node2ObjectsMap.java | 162 -- .../scm/node/states/Node2PipelineMap.java | 75 - .../states/NodeAlreadyExistsException.java | 45 - .../hdds/scm/node/states/NodeException.java | 44 - .../node/states/NodeNotFoundException.java | 47 - .../hdds/scm/node/states/NodeStateMap.java | 337 ---- .../hdds/scm/node/states/ReportResult.java | 110 -- .../hdds/scm/node/states/package-info.java | 22 - .../apache/hadoop/hdds/scm/package-info.java | 22 - .../pipelines/PipelineActionEventHandler.java | 62 - .../scm/pipelines/PipelineCloseHandler.java | 52 - .../hdds/scm/pipelines/PipelineManager.java | 171 --- .../scm/pipelines/PipelineReportHandler.java | 59 - .../hdds/scm/pipelines/PipelineSelector.java | 481 ------ .../scm/pipelines/PipelineStateManager.java | 136 -- .../hdds/scm/pipelines/package-info.java | 38 - .../scm/pipelines/ratis/RatisManagerImpl.java | 129 -- .../scm/pipelines/ratis/package-info.java | 18 - .../standalone/StandaloneManagerImpl.java | 122 -- .../pipelines/standalone/package-info.java | 18 - .../hadoop/hdds/scm/ratis/package-info.java | 22 - .../hdds/scm/server/ChillModePrecheck.java | 56 - .../hadoop/hdds/scm/server/Precheck.java | 29 - .../scm/server/SCMBlockProtocolServer.java | 206 --- .../hdds/scm/server/SCMChillModeManager.java | 247 --- .../scm/server/SCMClientProtocolServer.java | 380 ----- .../SCMDatanodeHeartbeatDispatcher.java | 231 --- .../scm/server/SCMDatanodeProtocolServer.java | 315 ---- .../hadoop/hdds/scm/server/SCMMXBean.java | 50 - .../hadoop/hdds/scm/server/SCMStorage.java | 73 - .../scm/server/StorageContainerManager.java | 942 ------------ .../StorageContainerManagerHttpServer.java | 77 - .../hadoop/hdds/scm/server/package-info.java | 22 - .../RetriableDatanodeEventWatcher.java | 58 - .../ozone/protocol/commands/package-info.java | 18 - .../src/main/resources/webapps/scm/index.html | 76 - .../src/main/resources/webapps/scm/main.html | 20 - .../resources/webapps/scm/scm-overview.html | 60 - .../src/main/resources/webapps/scm/scm.js | 54 - .../hadoop/hdds/scm/HddsServerUtilTest.java | 308 ---- .../apache/hadoop/hdds/scm/HddsTestUtils.java | 85 - ...TestStorageContainerManagerHttpServer.java | 142 -- .../org/apache/hadoop/hdds/scm/TestUtils.java | 433 ------ .../hdds/scm/block/TestBlockManager.java | 175 --- .../hdds/scm/block/TestDeletedBlockLog.java | 403 ----- .../hadoop/hdds/scm/block/package-info.java | 23 - .../TestCommandStatusReportHandler.java | 135 -- .../hadoop/hdds/scm/command/package-info.java | 22 - .../hdds/scm/container/MockNodeManager.java | 592 ------- .../TestCloseContainerEventHandler.java | 177 --- .../TestContainerActionsHandler.java | 68 - .../scm/container/TestContainerMapping.java | 380 ----- .../container/TestContainerReportHandler.java | 239 --- .../container/TestContainerStateManager.java | 98 -- .../scm/container/closer/package-info.java | 22 - .../hdds/scm/container/package-info.java | 22 - .../TestSCMContainerPlacementCapacity.java | 106 -- .../TestSCMContainerPlacementRandom.java | 86 -- .../TestReplicationActivityStatus.java | 63 - .../replication/TestReplicationManager.java | 238 --- .../replication/TestReplicationQueue.java | 134 -- .../container/replication/package-info.java | 23 - .../states/TestContainerAttribute.java | 143 -- .../scm/container/states/package-info.java | 22 - .../hdds/scm/node/TestContainerPlacement.java | 171 --- .../hdds/scm/node/TestDeadNodeHandler.java | 236 --- .../hadoop/hdds/scm/node/TestNodeManager.java | 1144 -------------- .../hdds/scm/node/TestNodeReportHandler.java | 94 -- .../scm/node/TestSCMNodeStorageStatMap.java | 262 ---- .../hadoop/hdds/scm/node/package-info.java | 22 - .../node/states/TestNode2ContainerMap.java | 327 ---- .../hdds/scm/node/states/package-info.java | 23 - .../apache/hadoop/hdds/scm/package-info.java | 21 - .../scm/server/TestSCMChillModeManager.java | 125 -- .../server/TestSCMClientProtocolServer.java | 60 - .../TestSCMDatanodeHeartbeatDispatcher.java | 138 -- .../container/TestCloseContainerWatcher.java | 287 ---- .../ozone/container/common/TestEndPoint.java | 530 ------- .../ozone/container/common/package-info.java | 22 - .../placement/TestContainerPlacement.java | 137 -- .../placement/TestDatanodeMetrics.java | 59 - .../container/placement/package-info.java | 22 - .../container/replication/package-info.java | 18 - .../testutils/ReplicationNodeManagerMock.java | 402 ----- .../container/testutils/package-info.java | 18 - hadoop-hdds/tools/pom.xml | 57 - .../apache/hadoop/hdds/scm/cli/SCMCLI.java | 150 -- .../scm/cli/container/CloseSubcommand.java | 54 - .../scm/cli/container/CreateSubcommand.java | 65 - .../scm/cli/container/DeleteSubcommand.java | 60 - .../scm/cli/container/InfoSubcommand.java | 94 -- .../scm/cli/container/ListSubcommand.java | 83 - .../hdds/scm/cli/container/package-info.java | 22 - .../hadoop/hdds/scm/cli/package-info.java | 23 - .../src/main/webapps/datanode/datanode.html | 48 +- .../src/test/resources/log4j.properties | 23 - hadoop-ozone/client/pom.xml | 37 - .../hadoop/ozone/client/BucketArgs.java | 123 -- .../hadoop/ozone/client/ObjectStore.java | 216 --- .../hadoop/ozone/client/OzoneBucket.java | 382 ----- .../hadoop/ozone/client/OzoneClient.java | 110 -- .../ozone/client/OzoneClientException.java | 54 - .../ozone/client/OzoneClientFactory.java | 306 ---- .../client/OzoneClientInvocationHandler.java | 62 - .../hadoop/ozone/client/OzoneClientUtils.java | 136 -- .../apache/hadoop/ozone/client/OzoneKey.java | 119 -- .../hadoop/ozone/client/OzoneKeyDetails.java | 58 - .../hadoop/ozone/client/OzoneKeyLocation.java | 82 - .../hadoop/ozone/client/OzoneVolume.java | 311 ---- .../hadoop/ozone/client/VolumeArgs.java | 128 -- .../client/io/ChunkGroupInputStream.java | 318 ---- .../client/io/ChunkGroupOutputStream.java | 733 --------- .../ozone/client/io/OzoneInputStream.java | 65 - .../ozone/client/io/OzoneOutputStream.java | 64 - .../hadoop/ozone/client/io/package-info.java | 23 - .../hadoop/ozone/client/package-info.java | 23 - .../ozone/client/protocol/ClientProtocol.java | 329 ---- .../ozone/client/protocol/package-info.java | 23 - .../rest/DefaultRestServerSelector.java | 36 - .../client/rest/OzoneExceptionMapper.java | 45 - .../hadoop/ozone/client/rest/RestClient.java | 912 ----------- .../ozone/client/rest/RestServerSelector.java | 40 - .../client/rest/exceptions/package-info.java | 22 - .../client/rest/headers/package-info.java | 22 - .../ozone/client/rest/package-info.java | 23 - .../hadoop/ozone/client/rpc/RpcClient.java | 576 ------- .../hadoop/ozone/client/rpc/package-info.java | 23 - .../ozone/client/TestHddsClientUtils.java | 105 -- .../hadoop/ozone/client/package-info.java | 23 - .../dev-support/findbugsExcludeFile.xml | 22 - hadoop-ozone/common/pom.xml | 115 -- hadoop-ozone/common/src/main/bin/ozone | 242 --- .../common/src/main/bin/ozone-config.sh | 51 - .../common/src/main/bin/start-ozone.sh | 127 -- .../common/src/main/bin/stop-ozone.sh | 101 -- .../src/main/conf/om-audit-log4j2.properties | 86 -- .../common/src/main/conf/ozone-site.xml | 24 - .../java/org/apache/hadoop/ozone/OmUtils.java | 94 -- .../apache/hadoop/ozone/audit/OMAction.java | 61 - .../hadoop/ozone/audit/package-info.java | 22 - .../ozone/client/io/LengthInputStream.java | 49 - .../hadoop/ozone/client/io/package-info.java | 22 - .../ozone/client/rest/OzoneException.java | 267 ---- .../ozone/client/rest/headers/Header.java | 74 - .../client/rest/headers/package-info.java | 22 - .../ozone/client/rest/package-info.java | 22 - .../client/rest/response/BucketInfo.java | 231 --- .../ozone/client/rest/response/KeyInfo.java | 216 --- .../client/rest/response/KeyInfoDetails.java | 107 -- .../client/rest/response/KeyLocation.java | 89 -- .../client/rest/response/VolumeInfo.java | 215 --- .../client/rest/response/VolumeOwner.java | 61 - .../client/rest/response/package-info.java | 24 - .../hadoop/ozone/freon/OzoneGetConf.java | 269 ---- .../hadoop/ozone/freon/package-info.java | 21 - .../apache/hadoop/ozone/om/OMConfigKeys.java | 81 - .../hadoop/ozone/om/helpers/OmBucketArgs.java | 256 --- .../hadoop/ozone/om/helpers/OmBucketInfo.java | 254 --- .../hadoop/ozone/om/helpers/OmKeyArgs.java | 167 -- .../hadoop/ozone/om/helpers/OmKeyInfo.java | 303 ---- .../ozone/om/helpers/OmKeyLocationInfo.java | 143 -- .../om/helpers/OmKeyLocationInfoGroup.java | 118 -- .../ozone/om/helpers/OmOzoneAclMap.java | 110 -- .../hadoop/ozone/om/helpers/OmVolumeArgs.java | 237 --- .../ozone/om/helpers/OpenKeySession.java | 50 - .../hadoop/ozone/om/helpers/ServiceInfo.java | 237 --- .../hadoop/ozone/om/helpers/VolumeArgs.java | 140 -- .../hadoop/ozone/om/helpers/package-info.java | 18 - .../apache/hadoop/ozone/om/package-info.java | 21 - .../om/protocol/OzoneManagerProtocol.java | 253 --- .../ozone/om/protocol/package-info.java | 19 - ...ManagerProtocolClientSideTranslatorPB.java | 775 ---------- .../om/protocolPB/OzoneManagerProtocolPB.java | 34 - .../ozone/om/protocolPB/package-info.java | 19 - .../org/apache/hadoop/ozone/package-info.java | 22 - .../hadoop/ozone/protocolPB/OMPBHelper.java | 113 -- .../ozone/protocolPB/OzonePBHelper.java | 30 - .../hadoop/ozone/protocolPB/package-info.java | 24 - .../hadoop/ozone/util/OzoneVersionInfo.java | 213 --- .../hadoop/ozone/web/handlers/BucketArgs.java | 214 --- .../hadoop/ozone/web/handlers/KeyArgs.java | 117 -- .../hadoop/ozone/web/handlers/ListArgs.java | 142 -- .../hadoop/ozone/web/handlers/UserArgs.java | 172 --- .../hadoop/ozone/web/handlers/VolumeArgs.java | 142 -- .../ozone/web/handlers/package-info.java | 22 - .../hadoop/ozone/web/request/OzoneQuota.java | 214 --- .../ozone/web/request/package-info.java | 23 - .../hadoop/ozone/web/response/BucketInfo.java | 325 ---- .../hadoop/ozone/web/response/KeyInfo.java | 290 ---- .../ozone/web/response/KeyInfoDetails.java | 80 - .../ozone/web/response/KeyLocation.java | 82 - .../ozone/web/response/ListBuckets.java | 154 -- .../hadoop/ozone/web/response/ListKeys.java | 209 --- .../ozone/web/response/ListVolumes.java | 152 -- .../hadoop/ozone/web/response/VolumeInfo.java | 308 ---- .../ozone/web/response/VolumeOwner.java | 60 - .../ozone/web/response/package-info.java | 23 - .../hadoop/ozone/web/utils/OzoneUtils.java | 227 --- .../hadoop/ozone/web/utils/package-info.java | 18 - .../src/main/proto/OzoneManagerProtocol.proto | 481 ------ .../resources/ozone-version-info.properties | 27 - .../src/main/shellprofile.d/hadoop-ozone.sh | 21 - .../hadoop/ozone/web/TestBucketInfo.java | 81 - .../apache/hadoop/ozone/web/TestQuota.java | 116 -- .../apache/hadoop/ozone/web/TestUtils.java | 101 -- .../hadoop/ozone/web/TestVolumeStructs.java | 73 - .../apache/hadoop/ozone/web/package-info.java | 21 - hadoop-ozone/datanode/pom.xml | 49 - .../dev-support/bin/dist-layout-stitching | 113 -- .../dist/dev-support/bin/dist-tar-stitching | 45 - hadoop-ozone/dist/pom.xml | 195 --- hadoop-ozone/dist/src/main/compose/README.md | 51 - .../dist/src/main/compose/ozone-hdfs/.env | 17 - .../compose/ozone-hdfs/docker-compose.yaml | 60 - .../src/main/compose/ozone-hdfs/docker-config | 76 - hadoop-ozone/dist/src/main/compose/ozone/.env | 17 - .../main/compose/ozone/docker-compose.yaml | 49 - .../dist/src/main/compose/ozone/docker-config | 75 - .../main/compose/ozonefs/docker-compose.yaml | 59 - .../src/main/compose/ozonefs/docker-config | 35 - .../dist/src/main/compose/ozoneperf/.env | 17 - .../dist/src/main/compose/ozoneperf/README.md | 73 - .../src/main/compose/ozoneperf/compose-all.sh | 18 - .../ozoneperf/docker-compose-freon.yaml | 26 - .../compose/ozoneperf/docker-compose.yaml | 64 - .../src/main/compose/ozoneperf/docker-config | 35 - .../dist/src/main/compose/ozoneperf/init.sh | 21 - .../src/main/compose/ozoneperf/prometheus.yml | 24 - .../main/compose/ozones3/docker-compose.yaml | 58 - .../src/main/compose/ozones3/docker-config | 73 - .../compose/ozonescripts/.ssh/authorized_keys | 16 - .../src/main/compose/ozonescripts/.ssh/config | 18 - .../compose/ozonescripts/.ssh/environment | 16 - .../src/main/compose/ozonescripts/.ssh/id_rsa | 42 - .../main/compose/ozonescripts/.ssh/id_rsa.pub | 16 - .../src/main/compose/ozonescripts/Dockerfile | 33 - .../src/main/compose/ozonescripts/README.md | 38 - .../compose/ozonescripts/docker-compose.yaml | 42 - .../main/compose/ozonescripts/docker-config | 38 - .../dist/src/main/compose/ozonescripts/ps.sh | 17 - .../src/main/compose/ozonescripts/start.sh | 24 - .../src/main/compose/ozonescripts/stop.sh | 17 - hadoop-ozone/dist/src/main/ozone/README.txt | 51 - .../dist/src/main/smoketest/README.md | 30 - .../dist/src/main/smoketest/basic/basic.robot | 47 - .../main/smoketest/basic/ozone-shell.robot | 82 - .../dist/src/main/smoketest/commonlib.robot | 24 - .../src/main/smoketest/ozonefs/ozonefs.robot | 35 - .../dist/src/main/smoketest/s3/awscli.robot | 63 - hadoop-ozone/dist/src/main/smoketest/test.sh | 102 -- hadoop-ozone/docs/README.md | 55 - hadoop-ozone/docs/archetypes/default.md | 20 - hadoop-ozone/docs/config.yaml | 41 - hadoop-ozone/docs/content/BucketCommands.md | 122 -- hadoop-ozone/docs/content/BuildingSources.md | 54 - hadoop-ozone/docs/content/CommandShell.md | 109 -- hadoop-ozone/docs/content/Concepts.md | 108 -- hadoop-ozone/docs/content/Dozone.md | 110 -- hadoop-ozone/docs/content/Freon.md | 64 - hadoop-ozone/docs/content/Hdds.md | 65 - hadoop-ozone/docs/content/JavaApi.md | 172 --- hadoop-ozone/docs/content/KeyCommands.md | 127 -- hadoop-ozone/docs/content/OzoneFS.md | 80 - hadoop-ozone/docs/content/OzoneManager.md | 77 - hadoop-ozone/docs/content/RealCluster.md | 74 - hadoop-ozone/docs/content/Rest.md | 544 ------- hadoop-ozone/docs/content/RunningViaDocker.md | 73 - hadoop-ozone/docs/content/RunningWithHDFS.md | 77 - hadoop-ozone/docs/content/SCMCLI.md | 29 - hadoop-ozone/docs/content/Settings.md | 142 -- hadoop-ozone/docs/content/VolumeCommands.md | 116 -- hadoop-ozone/docs/content/_index.md | 39 - .../docs/dev-support/bin/generate-site.sh | 29 - hadoop-ozone/docs/pom.xml | 71 - hadoop-ozone/docs/static/NOTES.md | 20 - hadoop-ozone/docs/static/OzoneOverview.png | Bin 41729 -> 0 bytes hadoop-ozone/docs/static/OzoneOverview.svg | 238 --- hadoop-ozone/docs/static/SCMBlockDiagram.png | Bin 14714 -> 0 bytes hadoop-ozone/docs/static/ozone-logo.png | Bin 40237 -> 0 bytes .../ozonedoc/layouts/_default/single.html | 38 - .../docs/themes/ozonedoc/layouts/index.html | 37 - .../ozonedoc/layouts/partials/footer.html | 22 - .../ozonedoc/layouts/partials/header.html | 34 - .../ozonedoc/layouts/partials/navbar.html | 36 - .../ozonedoc/layouts/partials/sidebar.html | 52 - .../static/css/bootstrap-theme.min.css | 6 - .../static/css/bootstrap-theme.min.css.map | 1 - .../ozonedoc/static/css/bootstrap.min.css | 6 - .../ozonedoc/static/css/bootstrap.min.css.map | 1 - .../themes/ozonedoc/static/css/ozonedoc.css | 138 -- .../fonts/glyphicons-halflings-regular.eot | Bin 20127 -> 0 bytes .../fonts/glyphicons-halflings-regular.svg | 288 ---- .../fonts/glyphicons-halflings-regular.ttf | Bin 45404 -> 0 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 23424 -> 0 bytes .../fonts/glyphicons-halflings-regular.woff2 | Bin 18028 -> 0 bytes .../ozonedoc/static/js/bootstrap.min.js | 7 - .../themes/ozonedoc/static/js/jquery.min.js | 5 - .../themes/ozonedoc/static/js/ozonedoc.js | 23 - hadoop-ozone/docs/themes/ozonedoc/theme.toml | 2 - hadoop-ozone/integration-test/pom.xml | 81 - .../TestContainerStateManagerIntegration.java | 417 ----- .../scm/pipeline/TestNode2PipelineMap.java | 131 -- .../hdds/scm/pipeline/TestNodeFailure.java | 126 -- .../hdds/scm/pipeline/TestPipelineClose.java | 147 -- .../hdds/scm/pipeline/TestSCMRestart.java | 119 -- .../apache/hadoop/ozone/MiniOzoneCluster.java | 362 ----- .../hadoop/ozone/MiniOzoneClusterImpl.java | 519 ------- .../apache/hadoop/ozone/OzoneTestUtils.java | 92 -- .../apache/hadoop/ozone/RatisTestHelper.java | 129 -- .../hadoop/ozone/TestContainerOperations.java | 88 -- .../hadoop/ozone/TestMiniOzoneCluster.java | 215 --- .../ozone/TestOzoneConfigurationFields.java | 42 - .../apache/hadoop/ozone/TestOzoneHelper.java | 413 ----- .../ozone/TestStorageContainerManager.java | 460 ------ .../TestStorageContainerManagerHelper.java | 184 --- .../client/rest/TestOzoneRestClient.java | 495 ------ .../ozone/client/rest/package-info.java | 23 - .../TestCloseContainerHandlingByClient.java | 490 ------ .../ozone/client/rpc/TestOzoneRpcClient.java | 979 ------------ .../hadoop/ozone/client/rpc/package-info.java | 23 - .../ozone/container/ContainerTestHelper.java | 616 -------- .../container/TestContainerReplication.java | 179 --- .../common/TestBlockDeletingService.java | 440 ------ .../common/helpers/TestBlockData.java | 127 -- .../impl/TestCloseContainerHandler.java | 261 ---- .../TestContainerDeletionChoosingPolicy.java | 162 -- .../common/impl/TestContainerPersistence.java | 803 ---------- .../commandhandler/TestBlockDeletion.java | 329 ---- .../TestCloseContainerByPipeline.java | 265 ---- .../TestCloseContainerHandler.java | 114 -- .../server/ratis/TestCSMMetrics.java | 189 --- .../metrics/TestContainerMetrics.java | 151 -- .../ozoneimpl/TestOzoneContainer.java | 574 ------- .../ozoneimpl/TestOzoneContainerRatis.java | 138 -- .../container/ozoneimpl/TestRatisManager.java | 124 -- .../container/server/TestContainerServer.java | 246 --- .../server/TestContainerStateMachine.java | 201 --- .../hadoop/ozone/freon/package-info.java | 21 - .../ozone/om/TestContainerReportWithKeys.java | 130 -- .../om/TestMultipleContainerReadWrite.java | 212 --- .../ozone/om/TestOmBlockVersioning.java | 263 ---- .../apache/hadoop/ozone/om/TestOmMetrics.java | 310 ---- .../hadoop/ozone/om/TestOzoneManager.java | 1368 ----------------- .../om/TestOzoneManagerRestInterface.java | 135 -- .../hadoop/ozone/om/TestScmChillMode.java | 365 ----- .../apache/hadoop/ozone/om/package-info.java | 22 - .../hadoop/ozone/ozShell/TestOzoneShell.java | 1102 ------------- .../ozone/scm/TestAllocateContainer.java | 83 - .../ozone/scm/TestContainerSmallFile.java | 161 -- .../TestGetCommittedBlockLengthAndPutKey.java | 254 --- .../hadoop/ozone/scm/TestSCMMXBean.java | 161 -- .../ozone/scm/TestXceiverClientManager.java | 210 --- .../ozone/scm/TestXceiverClientMetrics.java | 173 --- .../hadoop/ozone/scm/node/TestQueryNode.java | 118 -- .../web/TestOzoneRestWithMiniCluster.java | 218 --- .../hadoop/ozone/web/TestOzoneVolumes.java | 183 --- .../hadoop/ozone/web/TestOzoneWebAccess.java | 118 -- .../hadoop/ozone/web/client/TestBuckets.java | 335 ---- .../ozone/web/client/TestBucketsRatis.java | 107 -- .../hadoop/ozone/web/client/TestKeys.java | 761 --------- .../ozone/web/client/TestKeysRatis.java | 126 -- .../ozone/web/client/TestOzoneClient.java | 304 ---- .../hadoop/ozone/web/client/TestVolume.java | 382 ----- .../ozone/web/client/TestVolumeRatis.java | 154 -- .../src/test/resources/log4j.properties | 21 - .../resources/webapps/ozoneManager/.gitkeep | 15 - .../src/test/resources/webapps/scm/.gitkeep | 15 - hadoop-ozone/objectstore-service/pom.xml | 114 -- .../server/datanode/ObjectStoreHandler.java | 164 -- .../hdfs/server/datanode/package-info.java | 22 - .../apache/hadoop/ozone/OzoneRestUtils.java | 222 --- .../org/apache/hadoop/ozone/package-info.java | 22 - .../ozone/web/ObjectStoreApplication.java | 59 - .../ozone/web/OzoneHddsDatanodeService.java | 87 -- .../ozone/web/exceptions/ErrorTable.java | 225 --- .../ozone/web/exceptions/package-info.java | 22 - .../ozone/web/handlers/BucketHandler.java | 197 --- .../web/handlers/BucketProcessTemplate.java | 323 ---- .../hadoop/ozone/web/handlers/KeyHandler.java | 302 ---- .../web/handlers/KeyProcessTemplate.java | 235 --- .../ozone/web/handlers/ServiceFilter.java | 61 - .../web/handlers/StorageHandlerBuilder.java | 80 - .../web/handlers/UserHandlerBuilder.java | 75 - .../ozone/web/handlers/VolumeHandler.java | 272 ---- .../web/handlers/VolumeProcessTemplate.java | 276 ---- .../ozone/web/handlers/package-info.java | 22 - .../ozone/web/interfaces/Accounting.java | 57 - .../hadoop/ozone/web/interfaces/Bucket.java | 183 --- .../hadoop/ozone/web/interfaces/Keys.java | 177 --- .../ozone/web/interfaces/StorageHandler.java | 316 ---- .../hadoop/ozone/web/interfaces/UserAuth.java | 101 -- .../hadoop/ozone/web/interfaces/Volume.java | 182 --- .../ozone/web/interfaces/package-info.java | 22 - .../ozone/web/localstorage/package-info.java | 18 - .../LengthInputStreamMessageBodyWriter.java | 59 - .../web/messages/StringMessageBodyWriter.java | 62 - .../ozone/web/messages/package-info.java | 18 - .../web/netty/CloseableCleanupListener.java | 46 - .../web/netty/ObjectStoreChannelHandler.java | 78 - .../web/netty/ObjectStoreJerseyContainer.java | 348 ----- .../ObjectStoreJerseyContainerProvider.java | 40 - .../web/netty/ObjectStoreRestHttpServer.java | 215 --- .../web/netty/ObjectStoreURLDispatcher.java | 61 - ...questContentObjectStoreChannelHandler.java | 117 -- ...uestDispatchObjectStoreChannelHandler.java | 103 -- .../hadoop/ozone/web/netty/package-info.java | 26 - .../apache/hadoop/ozone/web/package-info.java | 22 - .../storage/DistributedStorageHandler.java | 576 ------- .../ozone/web/storage/package-info.java | 27 - .../hadoop/ozone/web/userauth/Simple.java | 169 -- .../ozone/web/userauth/package-info.java | 23 - ...sun.jersey.spi.container.ContainerProvider | 16 - .../hadoop/ozone/web/TestErrorCode.java | 53 - hadoop-ozone/ozone-manager/pom.xml | 86 -- .../apache/hadoop/ozone/om/BucketManager.java | 79 - .../hadoop/ozone/om/BucketManagerImpl.java | 303 ---- .../hadoop/ozone/om/KeyDeletingService.java | 172 --- .../apache/hadoop/ozone/om/KeyManager.java | 179 --- .../hadoop/ozone/om/KeyManagerImpl.java | 544 ------- .../org/apache/hadoop/ozone/om/OMMXBean.java | 31 - .../hadoop/ozone/om/OMMetadataManager.java | 239 --- .../org/apache/hadoop/ozone/om/OMMetrics.java | 459 ------ .../org/apache/hadoop/ozone/om/OMStorage.java | 90 -- .../ozone/om/OmMetadataManagerImpl.java | 616 -------- .../ozone/om/OpenKeyCleanupService.java | 117 -- .../apache/hadoop/ozone/om/OzoneManager.java | 1158 -------------- .../ozone/om/OzoneManagerHttpServer.java | 78 - .../hadoop/ozone/om/OzoneManagerLock.java | 181 --- .../ozone/om/ServiceListJSONServlet.java | 103 -- .../apache/hadoop/ozone/om/VolumeManager.java | 100 -- .../hadoop/ozone/om/VolumeManagerImpl.java | 429 ------ .../ozone/om/exceptions/OMException.java | 119 -- .../ozone/om/exceptions/package-info.java | 19 - .../apache/hadoop/ozone/om/package-info.java | 21 - ...ManagerProtocolServerSideTranslatorPB.java | 573 ------- .../hadoop/ozone/protocolPB/package-info.java | 22 - .../hadoop/ozone/web/ozShell/Handler.java | 160 -- .../hadoop/ozone/web/ozShell/Shell.java | 80 - .../web/ozShell/bucket/BucketCommands.java | 60 - .../ozShell/bucket/CreateBucketHandler.java | 83 - .../ozShell/bucket/DeleteBucketHandler.java | 68 - .../web/ozShell/bucket/InfoBucketHandler.java | 81 - .../web/ozShell/bucket/ListBucketHandler.java | 118 -- .../ozShell/bucket/UpdateBucketHandler.java | 101 -- .../web/ozShell/bucket/package-info.java | 23 - .../web/ozShell/keys/DeleteKeyHandler.java | 72 - .../ozone/web/ozShell/keys/GetKeyHandler.java | 114 -- .../web/ozShell/keys/InfoKeyHandler.java | 83 - .../ozone/web/ozShell/keys/KeyCommands.java | 60 - .../web/ozShell/keys/ListKeyHandler.java | 120 -- .../ozone/web/ozShell/keys/PutKeyHandler.java | 121 -- .../ozone/web/ozShell/keys/package-info.java | 23 - .../ozone/web/ozShell/package-info.java | 27 - .../ozShell/volume/CreateVolumeHandler.java | 111 -- .../ozShell/volume/DeleteVolumeHandler.java | 63 - .../web/ozShell/volume/InfoVolumeHandler.java | 74 - .../web/ozShell/volume/ListVolumeHandler.java | 117 -- .../ozShell/volume/UpdateVolumeHandler.java | 82 - .../web/ozShell/volume/VolumeCommands.java | 61 - .../web/ozShell/volume/package-info.java | 23 - .../apache/hadoop/ozone/web/package-info.java | 24 - .../resources/webapps/ozoneManager/index.html | 70 - .../resources/webapps/ozoneManager/main.css | 23 - .../resources/webapps/ozoneManager/main.html | 18 - .../webapps/ozoneManager/om-metrics.html | 44 - .../webapps/ozoneManager/ozoneManager.js | 110 -- .../om/ScmBlockLocationTestIngClient.java | 178 --- .../ozone/om/TestBucketManagerImpl.java | 362 ----- .../hadoop/ozone/om/TestChunkStreams.java | 240 --- .../ozone/om/TestKeyDeletingService.java | 201 --- .../hadoop/ozone/om/TestKeyManagerImpl.java | 165 -- .../ozone/om/TestOzoneManagerHttpServer.java | 141 -- .../hadoop/ozone/om/TestOzoneManagerLock.java | 192 --- .../apache/hadoop/ozone/om/package-info.java | 21 - hadoop-ozone/ozonefs/pom.xml | 211 --- .../org/apache/hadoop/fs/ozone/Constants.java | 42 - .../java/org/apache/hadoop/fs/ozone/OzFs.java | 44 - .../hadoop/fs/ozone/OzoneFSInputStream.java | 79 - .../hadoop/fs/ozone/OzoneFSOutputStream.java | 59 - .../hadoop/fs/ozone/OzoneFileSystem.java | 687 --------- .../apache/hadoop/fs/ozone/package-info.java | 30 - .../fs/ozone/TestOzoneFSInputStream.java | 153 -- .../fs/ozone/TestOzoneFileInterfaces.java | 231 --- .../contract/ITestOzoneContractCreate.java | 48 - .../contract/ITestOzoneContractDelete.java | 48 - .../contract/ITestOzoneContractDistCp.java | 50 - .../ITestOzoneContractGetFileStatus.java | 61 - .../contract/ITestOzoneContractMkdir.java | 48 - .../contract/ITestOzoneContractOpen.java | 47 - .../contract/ITestOzoneContractRename.java | 49 - .../contract/ITestOzoneContractRootDir.java | 51 - .../contract/ITestOzoneContractSeek.java | 47 - .../fs/ozone/contract/OzoneContract.java | 123 -- .../src/test/resources/contract/ozone.xml | 113 -- .../src/test/resources/log4j.properties | 24 - hadoop-ozone/pom.xml | 248 --- hadoop-ozone/s3gateway/pom.xml | 178 --- .../CommonHeadersContainerResponseFilter.java | 39 - .../apache/hadoop/ozone/s3/EndpointBase.java | 87 -- .../org/apache/hadoop/ozone/s3/Gateway.java | 66 - .../hadoop/ozone/s3/GatewayApplication.java | 29 - .../hadoop/ozone/s3/OzoneClientProducer.java | 48 - .../ozone/s3/OzoneConfigurationHolder.java | 43 - .../hadoop/ozone/s3/S3GatewayConfigKeys.java | 55 - .../hadoop/ozone/s3/S3GatewayHttpServer.java | 85 - .../ozone/s3/VirtualHostStyleFilter.java | 143 -- .../hadoop/ozone/s3/bucket/DeleteBucket.java | 44 - .../hadoop/ozone/s3/bucket/PutBucket.java | 44 - .../hadoop/ozone/s3/bucket/package-info.java | 30 - .../ozone/s3/commontypes/CommonPrefix.java | 47 - .../ozone/s3/commontypes/IsoDateAdapter.java | 47 - .../ozone/s3/commontypes/KeyMetadata.java | 87 -- .../ozone/s3/commontypes/package-info.java | 29 - .../ozone/s3/exception/OS3Exception.java | 161 -- .../s3/exception/OS3ExceptionMapper.java | 41 - .../ozone/s3/exception/S3ErrorTable.java | 81 - .../ozone/s3/exception/package-info.java | 21 - .../hadoop/ozone/s3/object/DeleteObject.java | 51 - .../hadoop/ozone/s3/object/HeadObject.java | 58 - .../hadoop/ozone/s3/object/ListObject.java | 119 -- .../ozone/s3/object/ListObjectResponse.java | 147 -- .../hadoop/ozone/s3/object/PutObject.java | 61 - .../hadoop/ozone/s3/object/package-info.java | 29 - .../apache/hadoop/ozone/s3/package-info.java | 22 - .../src/main/resources/META-INF/beans.xml | 20 - .../webapps/s3gateway/WEB-INF/beans.xml | 20 - .../webapps/s3gateway/WEB-INF/web.xml | 36 - .../hadoop/ozone/client/ObjectStoreStub.java | 110 -- .../hadoop/ozone/client/OzoneBucketStub.java | 143 -- .../hadoop/ozone/client/OzoneClientStub.java | 37 - .../hadoop/ozone/client/OzoneVolumeStub.java | 95 -- .../hadoop/ozone/client/package-info.java | 21 - .../ozone/s3/TestVirtualHostStyleFilter.java | 163 -- .../ozone/s3/bucket/TestBucketResponse.java | 40 - .../hadoop/ozone/s3/bucket/TestGetBucket.java | 114 -- .../hadoop/ozone/s3/bucket/package-info.java | 21 - .../ozone/s3/exception/TestOS3Exception.java | 49 - .../ozone/s3/exception/package-info.java | 22 - .../ozone/s3/object/TestDeleteObject.java | 56 - .../hadoop/ozone/s3/object/package-info.java | 21 - .../apache/hadoop/ozone/s3/package-info.java | 21 - .../tools/dev-support/findbugsExcludeFile.xml | 19 - hadoop-ozone/tools/pom.xml | 95 -- .../org/apache/hadoop/ozone/freon/Freon.java | 39 - .../ozone/freon/RandomKeyGenerator.java | 1039 ------------- .../hadoop/ozone/freon/package-info.java | 22 - .../GenerateOzoneRequiredConfigurations.java | 148 -- .../hadoop/ozone/genconf/package-info.java | 24 - .../genesis/BenchMarkContainerStateMap.java | 213 --- .../genesis/BenchMarkDatanodeDispatcher.java | 317 ---- .../genesis/BenchMarkMetadataStoreReads.java | 67 - .../genesis/BenchMarkMetadataStoreWrites.java | 60 - .../ozone/genesis/BenchMarkRocksDbStore.java | 115 -- .../apache/hadoop/ozone/genesis/Genesis.java | 60 - .../ozone/genesis/GenesisMemoryProfiler.java | 61 - .../hadoop/ozone/genesis/GenesisUtil.java | 96 -- .../hadoop/ozone/genesis/package-info.java | 25 - .../apache/hadoop/ozone/scm/cli/SQLCLI.java | 567 ------- .../hadoop/ozone/scm/cli/package-info.java | 22 - .../hadoop/ozone/freon/TestDataValidate.java | 115 -- .../ozone/freon/TestRandomKeyGenerator.java | 106 -- ...stGenerateOzoneRequiredConfigurations.java | 213 --- .../hadoop/ozone/genconf/package-info.java | 22 - .../apache/hadoop/ozone/om/TestOmSQLCli.java | 285 ---- .../hadoop/ozone/scm/TestContainerSQLCli.java | 253 --- .../apache/hadoop/test/OzoneTestDriver.java | 59 - hadoop-project/pom.xml | 114 -- hadoop-project/src/site/site.xml | 9 - pom.xml | 71 - 1028 files changed, 1 insertion(+), 138911 deletions(-) delete mode 100644 hadoop-assemblies/src/main/resources/assemblies/hadoop-src-with-hdds.xml delete mode 100644 hadoop-hdds/client/pom.xml delete mode 100644 hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/XceiverClientGrpc.java delete mode 100644 hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/XceiverClientManager.java delete mode 100644 hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/XceiverClientMetrics.java delete mode 100644 hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/XceiverClientRatis.java delete mode 100644 hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/client/ContainerOperationClient.java delete mode 100644 hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/client/HddsClientUtils.java delete mode 100644 hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/client/package-info.java delete mode 100644 hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/package-info.java delete mode 100644 hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/storage/ChunkInputStream.java delete mode 100644 hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/storage/ChunkOutputStream.java delete mode 100644 hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/storage/package-info.java delete mode 100644 hadoop-hdds/common/dev-support/findbugsExcludeFile.xml delete mode 100644 hadoop-hdds/common/pom.xml delete mode 100644 hadoop-hdds/common/src/main/conf/log4j.properties delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsConfigKeys.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsIdFactory.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsUtils.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/GenericCli.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/GenericParentCommand.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/HddsVersionProvider.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/MissingSubcommandException.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/package-info.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/client/BlockID.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/client/OzoneQuota.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/client/ReplicationFactor.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/client/ReplicationType.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/client/package-info.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/conf/HddsConfServlet.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/conf/OzoneConfiguration.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/conf/package-info.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/package-info.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/protocol/DatanodeDetails.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/protocol/package-info.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/ScmConfigKeys.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/ScmInfo.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/XceiverClientSpi.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/client/ScmClient.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/client/package-info.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerID.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/AllocatedBlock.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/BlockNotCommittedException.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/ContainerInfo.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/ContainerWithPipeline.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/DeleteBlockResult.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/Pipeline.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/PipelineID.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/StorageContainerException.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/package-info.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/package-info.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/package-info.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocol/LocatedContainer.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocol/ScmBlockLocationProtocol.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocol/ScmLocatedBlock.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocol/StorageContainerLocationProtocol.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocol/package-info.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocolPB/ScmBlockLocationProtocolClientSideTranslatorPB.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocolPB/ScmBlockLocationProtocolPB.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocolPB/StorageContainerLocationProtocolClientSideTranslatorPB.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocolPB/StorageContainerLocationProtocolPB.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocolPB/package-info.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/storage/ContainerProtocolCalls.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/storage/package-info.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneAcl.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneConfigKeys.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneConsts.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/AuditAction.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/AuditEventStatus.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/AuditLogger.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/AuditLoggerType.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/AuditMarker.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/AuditMessage.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/Auditable.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/Auditor.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/package-info.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/BlockGroup.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/DeleteBlockGroupResult.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/InconsistentStorageStateException.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/Storage.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/StorageInfo.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/package-info.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/statemachine/InvalidStateTransitionException.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/statemachine/StateMachine.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/statemachine/package-info.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/container/common/helpers/BlockData.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/container/common/helpers/ChunkInfo.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/container/common/helpers/package-info.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/Lease.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/LeaseAlreadyExistException.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/LeaseCallbackExecutor.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/LeaseException.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/LeaseExpiredException.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/LeaseManager.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/LeaseManagerNotRunningException.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/LeaseNotFoundException.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/package-info.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lock/ActiveLock.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lock/LockManager.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lock/PooledLockFactory.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lock/package-info.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/package-info.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/protocolPB/ScmBlockLocationProtocolServerSideTranslatorPB.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/protocolPB/StorageContainerLocationProtocolServerSideTranslatorPB.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/protocolPB/package-info.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/web/utils/JsonUtils.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/web/utils/package-info.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/BackgroundService.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/BackgroundTask.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/BackgroundTaskQueue.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/BackgroundTaskResult.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/BatchOperation.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/EntryConsumer.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/HddsVersionInfo.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/LevelDBStore.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/LevelDBStoreIterator.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/MetaStoreIterator.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/MetadataKeyFilters.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/MetadataStore.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/MetadataStoreBuilder.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/RocksDBStore.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/RocksDBStoreIterator.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/RocksDBStoreMBean.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/DBConfigFromFile.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/DBProfile.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/DBStore.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/DBStoreBuilder.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/RDBStore.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/RDBStoreIterator.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/RDBTable.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/Table.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/TableConfig.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/TableIterator.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/package-info.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/package-info.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/ratis/RatisHelper.java delete mode 100644 hadoop-hdds/common/src/main/java/org/apache/ratis/package-info.java delete mode 100644 hadoop-hdds/common/src/main/proto/DatanodeContainerProtocol.proto delete mode 100644 hadoop-hdds/common/src/main/proto/ScmBlockLocationProtocol.proto delete mode 100644 hadoop-hdds/common/src/main/proto/StorageContainerLocationProtocol.proto delete mode 100644 hadoop-hdds/common/src/main/proto/hdds.proto delete mode 100644 hadoop-hdds/common/src/main/resources/hdds-version-info.properties delete mode 100644 hadoop-hdds/common/src/main/resources/ozone-default.xml delete mode 100644 hadoop-hdds/common/src/test/java/org/apache/hadoop/hdds/scm/package-info.java delete mode 100644 hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/TestOzoneAcls.java delete mode 100644 hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/audit/DummyAction.java delete mode 100644 hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/audit/DummyEntity.java delete mode 100644 hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/audit/TestOzoneAuditLogger.java delete mode 100644 hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/audit/package-info.java delete mode 100644 hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/common/TestStateMachine.java delete mode 100644 hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/lease/TestLeaseManager.java delete mode 100644 hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/lease/package-info.java delete mode 100644 hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/lock/TestLockManager.java delete mode 100644 hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/lock/package-info.java delete mode 100644 hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/package-info.java delete mode 100644 hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/TestHddsIdFactory.java delete mode 100644 hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/TestMetadataStore.java delete mode 100644 hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/TestRocksDBStoreMBean.java delete mode 100644 hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/db/TestDBConfigFromFile.java delete mode 100644 hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/db/TestDBStoreBuilder.java delete mode 100644 hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/db/TestRDBStore.java delete mode 100644 hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/db/TestRDBTableStore.java delete mode 100644 hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/db/package-info.java delete mode 100644 hadoop-hdds/common/src/test/resources/log4j2.properties delete mode 100644 hadoop-hdds/common/src/test/resources/test.db.ini delete mode 100644 hadoop-hdds/container-service/dev-support/findbugsExcludeFile.xml delete mode 100644 hadoop-hdds/container-service/pom.xml delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/hdds/scm/HddsServerUtil.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/hdds/scm/VersionInfo.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/hdds/scm/package-info.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/HddsDatanodeService.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/DataNodeLayoutVersion.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/ContainerMetrics.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/ContainerReport.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/ContainerUtils.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/DatanodeVersionFile.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/DeletedContainerBlocksSummary.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/KeyValueContainerReport.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/package-info.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/ChunkLayOutVersion.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/ContainerData.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/ContainerDataYaml.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/ContainerSet.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/HddsDispatcher.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/OpenContainerBlockMap.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/RandomContainerDeletionChoosingPolicy.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/StorageLocationReport.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/TopNOrderedContainerDeletionChoosingPolicy.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/package-info.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/BlockIterator.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/Container.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/ContainerDeletionChoosingPolicy.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/ContainerDispatcher.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/ContainerLocationManager.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/ContainerLocationManagerMXBean.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/ContainerPacker.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/Handler.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/StorageLocationReportMXBean.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/VolumeChoosingPolicy.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/package-info.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/package-info.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/CommandStatusReportPublisher.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/ContainerReportPublisher.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/NodeReportPublisher.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/PipelineReportPublisher.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/ReportManager.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/ReportPublisher.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/ReportPublisherFactory.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/package-info.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/DatanodeStateMachine.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/EndpointStateMachine.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/EndpointStateMachineMBean.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/SCMConnectionManager.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/SCMConnectionManagerMXBean.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/StateContext.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/CloseContainerCommandHandler.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/CommandDispatcher.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/CommandHandler.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/DeleteBlocksCommandHandler.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/ReplicateContainerCommandHandler.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/package-info.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/package-info.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/DatanodeState.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/datanode/InitDatanodeState.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/datanode/RunningDatanodeState.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/datanode/package-info.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/endpoint/HeartbeatEndpointTask.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/endpoint/RegisterEndpointTask.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/endpoint/VersionEndpointTask.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/endpoint/package-info.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/package-info.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/GrpcXceiverService.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/XceiverServerGrpc.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/XceiverServerSpi.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/package-info.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/ratis/CSMMetrics.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/ratis/ContainerStateMachine.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/ratis/XceiverServerRatis.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/ratis/package-info.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/utils/ContainerCache.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/utils/HddsVolumeUtil.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/utils/package-info.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/HddsVolume.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/RoundRobinVolumeChoosingPolicy.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/VolumeIOStats.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/VolumeInfo.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/VolumeSet.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/VolumeUsage.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/package-info.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueBlockIterator.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueContainer.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueContainerData.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueHandler.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/TarContainerPacker.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/helpers/BlockUtils.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/helpers/ChunkUtils.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/helpers/KeyValueContainerLocationUtil.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/helpers/KeyValueContainerUtil.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/helpers/SmallFileUtils.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/helpers/package-info.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/impl/BlockManagerImpl.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/impl/ChunkManagerImpl.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/impl/package-info.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/interfaces/BlockManager.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/interfaces/ChunkManager.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/interfaces/package-info.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/package-info.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/statemachine/background/BlockDeletingService.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/statemachine/background/package-info.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/ozoneimpl/ContainerReader.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/ozoneimpl/OzoneContainer.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/ozoneimpl/package-info.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/ContainerDownloader.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/ContainerReplicationSource.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/ContainerReplicator.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/ContainerStreamingOutput.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/DownloadAndImportReplicator.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/GrpcReplicationClient.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/GrpcReplicationService.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/OnDemandContainerReplicationSource.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/ReplicationSupervisor.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/ReplicationTask.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/SimpleContainerDownloader.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/package-info.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/package-info.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/StorageContainerDatanodeProtocol.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/StorageContainerNodeProtocol.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/VersionResponse.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/CloseContainerCommand.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/CommandForDatanode.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/CommandStatus.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/DeleteBlockCommandStatus.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/DeleteBlocksCommand.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/RegisteredCommand.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/ReplicateContainerCommand.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/ReregisterCommand.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/SCMCommand.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/package-info.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/package-info.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocolPB/StorageContainerDatanodeProtocolClientSideTranslatorPB.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocolPB/StorageContainerDatanodeProtocolPB.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocolPB/StorageContainerDatanodeProtocolServerSideTranslatorPB.java delete mode 100644 hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocolPB/package-info.java delete mode 100644 hadoop-hdds/container-service/src/main/proto/StorageContainerDatanodeProtocol.proto delete mode 100644 hadoop-hdds/container-service/src/main/resources/META-INF/services/com.sun.jersey.spi.container.ContainerProvider delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/ContainerTestUtils.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/SCMTestUtils.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/ScmTestMock.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/TestChunkLayOutVersion.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/TestDatanodeLayOutVersion.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/TestDatanodeStateMachine.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/TestKeyValueContainerData.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/helpers/TestDatanodeVersionFile.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/impl/TestContainerDataYaml.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/impl/TestContainerSet.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/impl/TestHddsDispatcher.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/impl/package-info.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/interfaces/TestHandler.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/package-info.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/report/TestReportManager.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/report/TestReportPublisher.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/report/TestReportPublisherFactory.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/report/package-info.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/package-info.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/states/endpoint/TestHeartbeatEndpointTask.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/states/endpoint/package-info.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/volume/TestHddsVolume.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/volume/TestRoundRobinVolumeChoosingPolicy.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/volume/TestVolumeSet.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestBlockManagerImpl.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestChunkManagerImpl.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestKeyValueBlockIterator.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestKeyValueContainer.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestKeyValueHandler.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestTarContainerPacker.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/ozoneimpl/TestOzoneContainer.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/replication/TestReplicationSupervisor.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/replication/package-info.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/testutils/BlockDeletingServiceTestImpl.java delete mode 100644 hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/testutils/package-info.java delete mode 100644 hadoop-hdds/container-service/src/test/resources/additionalfields.container delete mode 100644 hadoop-hdds/container-service/src/test/resources/incorrect.checksum.container delete mode 100644 hadoop-hdds/container-service/src/test/resources/incorrect.container delete mode 100644 hadoop-hdds/container-service/src/test/resources/log4j.properties delete mode 100644 hadoop-hdds/framework/README.md delete mode 100644 hadoop-hdds/framework/pom.xml delete mode 100644 hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/BaseHttpServer.java delete mode 100644 hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/ServerUtils.java delete mode 100644 hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/ServiceRuntimeInfo.java delete mode 100644 hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/ServiceRuntimeInfoImpl.java delete mode 100644 hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/Event.java delete mode 100644 hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/EventExecutor.java delete mode 100644 hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/EventHandler.java delete mode 100644 hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/EventPublisher.java delete mode 100644 hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/EventQueue.java delete mode 100644 hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/EventWatcher.java delete mode 100644 hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/EventWatcherMetrics.java delete mode 100644 hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/IdentifiableEventPayload.java delete mode 100644 hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/SingleThreadExecutor.java delete mode 100644 hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/TypedEvent.java delete mode 100644 hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/package-info.java delete mode 100644 hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/package-info.java delete mode 100644 hadoop-hdds/framework/src/main/resources/webapps/datanode/dn.js delete mode 100644 hadoop-hdds/framework/src/main/resources/webapps/static/angular-1.6.4.min.js delete mode 100644 hadoop-hdds/framework/src/main/resources/webapps/static/angular-nvd3-1.0.9.min.js delete mode 100644 hadoop-hdds/framework/src/main/resources/webapps/static/angular-route-1.6.4.min.js delete mode 100644 hadoop-hdds/framework/src/main/resources/webapps/static/d3-3.5.17.min.js delete mode 100644 hadoop-hdds/framework/src/main/resources/webapps/static/dfs-dust.js delete mode 100644 hadoop-hdds/framework/src/main/resources/webapps/static/nvd3-1.8.5.min.css delete mode 100644 hadoop-hdds/framework/src/main/resources/webapps/static/nvd3-1.8.5.min.css.map delete mode 100644 hadoop-hdds/framework/src/main/resources/webapps/static/nvd3-1.8.5.min.js delete mode 100644 hadoop-hdds/framework/src/main/resources/webapps/static/nvd3-1.8.5.min.js.map delete mode 100644 hadoop-hdds/framework/src/main/resources/webapps/static/ozone.css delete mode 100644 hadoop-hdds/framework/src/main/resources/webapps/static/ozone.js delete mode 100644 hadoop-hdds/framework/src/main/resources/webapps/static/templates/config.html delete mode 100644 hadoop-hdds/framework/src/main/resources/webapps/static/templates/jvm.html delete mode 100644 hadoop-hdds/framework/src/main/resources/webapps/static/templates/menu.html delete mode 100644 hadoop-hdds/framework/src/main/resources/webapps/static/templates/overview.html delete mode 100644 hadoop-hdds/framework/src/main/resources/webapps/static/templates/rpc-metrics.html delete mode 100644 hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/TestBaseHttpServer.java delete mode 100644 hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/events/EventHandlerStub.java delete mode 100644 hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/events/TestEventQueue.java delete mode 100644 hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/events/TestEventQueueChain.java delete mode 100644 hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/events/TestEventWatcher.java delete mode 100644 hadoop-hdds/framework/src/test/resources/ozone-site.xml delete mode 100644 hadoop-hdds/pom.xml delete mode 100644 hadoop-hdds/server-scm/pom.xml delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ScmUtils.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/BlockManager.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/BlockManagerImpl.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/BlockmanagerMXBean.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/DatanodeDeletedBlockTransactions.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/DeletedBlockLog.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/DeletedBlockLogImpl.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/PendingDeleteHandler.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/PendingDeleteStatusList.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/SCMBlockDeletingService.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/command/CommandStatusReportHandler.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/command/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/CloseContainerEventHandler.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/CloseContainerWatcher.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerActionsHandler.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerMapping.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerReportHandler.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerStateManager.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/Mapping.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/closer/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/algorithms/ContainerPlacementPolicy.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/algorithms/SCMCommonPolicy.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/algorithms/SCMContainerPlacementCapacity.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/algorithms/SCMContainerPlacementRandom.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/algorithms/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/ContainerStat.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/DatanodeMetric.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/LongMetric.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/NodeStat.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/SCMMetrics.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/SCMNodeMetric.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/SCMNodeStat.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/replication/ReplicationActivityStatus.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/replication/ReplicationActivityStatusMXBean.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/replication/ReplicationCommandWatcher.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/replication/ReplicationManager.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/replication/ReplicationQueue.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/replication/ReplicationRequest.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/replication/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/states/ContainerAttribute.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/states/ContainerQueryKey.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/states/ContainerState.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/states/ContainerStateMap.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/states/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/events/SCMEvents.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/events/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/exceptions/SCMException.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/exceptions/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/CommandQueue.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/DatanodeInfo.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/DeadNodeHandler.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/NewNodeHandler.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/NodeManager.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/NodeManagerMXBean.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/NodeReportHandler.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/NodeStateManager.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/SCMNodeManager.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/SCMNodeStorageStatMXBean.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/SCMNodeStorageStatMap.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/StaleNodeHandler.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/StorageReportResult.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/Node2ContainerMap.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/Node2ObjectsMap.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/Node2PipelineMap.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/NodeAlreadyExistsException.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/NodeException.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/NodeNotFoundException.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/NodeStateMap.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/ReportResult.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/PipelineActionEventHandler.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/PipelineCloseHandler.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/PipelineManager.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/PipelineReportHandler.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/PipelineSelector.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/PipelineStateManager.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/ratis/RatisManagerImpl.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/ratis/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/standalone/StandaloneManagerImpl.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/standalone/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ratis/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/ChillModePrecheck.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/Precheck.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMBlockProtocolServer.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMChillModeManager.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMDatanodeHeartbeatDispatcher.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMDatanodeProtocolServer.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMMXBean.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMStorage.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/StorageContainerManager.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/StorageContainerManagerHttpServer.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/ozone/protocol/commands/RetriableDatanodeEventWatcher.java delete mode 100644 hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/ozone/protocol/commands/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/main/resources/webapps/scm/index.html delete mode 100644 hadoop-hdds/server-scm/src/main/resources/webapps/scm/main.html delete mode 100644 hadoop-hdds/server-scm/src/main/resources/webapps/scm/scm-overview.html delete mode 100644 hadoop-hdds/server-scm/src/main/resources/webapps/scm/scm.js delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/HddsServerUtilTest.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/HddsTestUtils.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/TestStorageContainerManagerHttpServer.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/TestUtils.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/block/TestBlockManager.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/block/TestDeletedBlockLog.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/block/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/command/TestCommandStatusReportHandler.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/command/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/MockNodeManager.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/TestCloseContainerEventHandler.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/TestContainerActionsHandler.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/TestContainerMapping.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/TestContainerReportHandler.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/TestContainerStateManager.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/closer/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/placement/algorithms/TestSCMContainerPlacementCapacity.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/placement/algorithms/TestSCMContainerPlacementRandom.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/replication/TestReplicationActivityStatus.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/replication/TestReplicationManager.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/replication/TestReplicationQueue.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/replication/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/states/TestContainerAttribute.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/states/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestContainerPlacement.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestDeadNodeHandler.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestNodeManager.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestNodeReportHandler.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestSCMNodeStorageStatMap.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/states/TestNode2ContainerMap.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/states/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMChillModeManager.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMClientProtocolServer.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMDatanodeHeartbeatDispatcher.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/TestCloseContainerWatcher.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/common/TestEndPoint.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/common/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/placement/TestContainerPlacement.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/placement/TestDatanodeMetrics.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/placement/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/replication/package-info.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/testutils/ReplicationNodeManagerMock.java delete mode 100644 hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/testutils/package-info.java delete mode 100644 hadoop-hdds/tools/pom.xml delete mode 100644 hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/SCMCLI.java delete mode 100644 hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/container/CloseSubcommand.java delete mode 100644 hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/container/CreateSubcommand.java delete mode 100644 hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/container/DeleteSubcommand.java delete mode 100644 hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/container/InfoSubcommand.java delete mode 100644 hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/container/ListSubcommand.java delete mode 100644 hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/container/package-info.java delete mode 100644 hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/package-info.java delete mode 100644 hadoop-ozone/client/pom.xml delete mode 100644 hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/BucketArgs.java delete mode 100644 hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/ObjectStore.java delete mode 100644 hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneBucket.java delete mode 100644 hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneClient.java delete mode 100644 hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneClientException.java delete mode 100644 hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneClientFactory.java delete mode 100644 hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneClientInvocationHandler.java delete mode 100644 hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneClientUtils.java delete mode 100644 hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneKey.java delete mode 100644 hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneKeyDetails.java delete mode 100644 hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneKeyLocation.java delete mode 100644 hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneVolume.java delete mode 100644 hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/VolumeArgs.java delete mode 100644 hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/ChunkGroupInputStream.java delete mode 100644 hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/ChunkGroupOutputStream.java delete mode 100644 hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/OzoneInputStream.java delete mode 100644 hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/OzoneOutputStream.java delete mode 100644 hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/package-info.java delete mode 100644 hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/package-info.java delete mode 100644 hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/protocol/ClientProtocol.java delete mode 100644 hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/protocol/package-info.java delete mode 100644 hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/DefaultRestServerSelector.java delete mode 100644 hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/OzoneExceptionMapper.java delete mode 100644 hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/RestClient.java delete mode 100644 hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/RestServerSelector.java delete mode 100644 hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/exceptions/package-info.java delete mode 100644 hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/headers/package-info.java delete mode 100644 hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/package-info.java delete mode 100644 hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java delete mode 100644 hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/package-info.java delete mode 100644 hadoop-ozone/client/src/test/java/org/apache/hadoop/ozone/client/TestHddsClientUtils.java delete mode 100644 hadoop-ozone/client/src/test/java/org/apache/hadoop/ozone/client/package-info.java delete mode 100644 hadoop-ozone/common/dev-support/findbugsExcludeFile.xml delete mode 100644 hadoop-ozone/common/pom.xml delete mode 100755 hadoop-ozone/common/src/main/bin/ozone delete mode 100755 hadoop-ozone/common/src/main/bin/ozone-config.sh delete mode 100755 hadoop-ozone/common/src/main/bin/start-ozone.sh delete mode 100755 hadoop-ozone/common/src/main/bin/stop-ozone.sh delete mode 100644 hadoop-ozone/common/src/main/conf/om-audit-log4j2.properties delete mode 100644 hadoop-ozone/common/src/main/conf/ozone-site.xml delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/audit/OMAction.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/audit/package-info.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/io/LengthInputStream.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/io/package-info.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/OzoneException.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/headers/Header.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/headers/package-info.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/package-info.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/response/BucketInfo.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/response/KeyInfo.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/response/KeyInfoDetails.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/response/KeyLocation.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/response/VolumeInfo.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/response/VolumeOwner.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/response/package-info.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/freon/OzoneGetConf.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/freon/package-info.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/OMConfigKeys.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmBucketArgs.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmBucketInfo.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmKeyArgs.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmKeyInfo.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmKeyLocationInfo.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmKeyLocationInfoGroup.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmOzoneAclMap.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmVolumeArgs.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OpenKeySession.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/ServiceInfo.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/VolumeArgs.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/package-info.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/package-info.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/package-info.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolPB.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/package-info.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/package-info.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/protocolPB/OMPBHelper.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/protocolPB/OzonePBHelper.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/protocolPB/package-info.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/util/OzoneVersionInfo.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/handlers/BucketArgs.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/handlers/KeyArgs.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/handlers/ListArgs.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/handlers/UserArgs.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/handlers/VolumeArgs.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/handlers/package-info.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/request/OzoneQuota.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/request/package-info.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/BucketInfo.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/KeyInfo.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/KeyInfoDetails.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/KeyLocation.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/ListBuckets.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/ListKeys.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/ListVolumes.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/VolumeInfo.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/VolumeOwner.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/package-info.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/utils/OzoneUtils.java delete mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/utils/package-info.java delete mode 100644 hadoop-ozone/common/src/main/proto/OzoneManagerProtocol.proto delete mode 100644 hadoop-ozone/common/src/main/resources/ozone-version-info.properties delete mode 100644 hadoop-ozone/common/src/main/shellprofile.d/hadoop-ozone.sh delete mode 100644 hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/web/TestBucketInfo.java delete mode 100644 hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/web/TestQuota.java delete mode 100644 hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/web/TestUtils.java delete mode 100644 hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/web/TestVolumeStructs.java delete mode 100644 hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/web/package-info.java delete mode 100644 hadoop-ozone/datanode/pom.xml delete mode 100755 hadoop-ozone/dist/dev-support/bin/dist-layout-stitching delete mode 100755 hadoop-ozone/dist/dev-support/bin/dist-tar-stitching delete mode 100644 hadoop-ozone/dist/pom.xml delete mode 100644 hadoop-ozone/dist/src/main/compose/README.md delete mode 100644 hadoop-ozone/dist/src/main/compose/ozone-hdfs/.env delete mode 100644 hadoop-ozone/dist/src/main/compose/ozone-hdfs/docker-compose.yaml delete mode 100644 hadoop-ozone/dist/src/main/compose/ozone-hdfs/docker-config delete mode 100644 hadoop-ozone/dist/src/main/compose/ozone/.env delete mode 100644 hadoop-ozone/dist/src/main/compose/ozone/docker-compose.yaml delete mode 100644 hadoop-ozone/dist/src/main/compose/ozone/docker-config delete mode 100644 hadoop-ozone/dist/src/main/compose/ozonefs/docker-compose.yaml delete mode 100644 hadoop-ozone/dist/src/main/compose/ozonefs/docker-config delete mode 100644 hadoop-ozone/dist/src/main/compose/ozoneperf/.env delete mode 100644 hadoop-ozone/dist/src/main/compose/ozoneperf/README.md delete mode 100755 hadoop-ozone/dist/src/main/compose/ozoneperf/compose-all.sh delete mode 100644 hadoop-ozone/dist/src/main/compose/ozoneperf/docker-compose-freon.yaml delete mode 100644 hadoop-ozone/dist/src/main/compose/ozoneperf/docker-compose.yaml delete mode 100644 hadoop-ozone/dist/src/main/compose/ozoneperf/docker-config delete mode 100755 hadoop-ozone/dist/src/main/compose/ozoneperf/init.sh delete mode 100644 hadoop-ozone/dist/src/main/compose/ozoneperf/prometheus.yml delete mode 100644 hadoop-ozone/dist/src/main/compose/ozones3/docker-compose.yaml delete mode 100644 hadoop-ozone/dist/src/main/compose/ozones3/docker-config delete mode 100644 hadoop-ozone/dist/src/main/compose/ozonescripts/.ssh/authorized_keys delete mode 100644 hadoop-ozone/dist/src/main/compose/ozonescripts/.ssh/config delete mode 100644 hadoop-ozone/dist/src/main/compose/ozonescripts/.ssh/environment delete mode 100644 hadoop-ozone/dist/src/main/compose/ozonescripts/.ssh/id_rsa delete mode 100644 hadoop-ozone/dist/src/main/compose/ozonescripts/.ssh/id_rsa.pub delete mode 100644 hadoop-ozone/dist/src/main/compose/ozonescripts/Dockerfile delete mode 100644 hadoop-ozone/dist/src/main/compose/ozonescripts/README.md delete mode 100644 hadoop-ozone/dist/src/main/compose/ozonescripts/docker-compose.yaml delete mode 100644 hadoop-ozone/dist/src/main/compose/ozonescripts/docker-config delete mode 100755 hadoop-ozone/dist/src/main/compose/ozonescripts/ps.sh delete mode 100755 hadoop-ozone/dist/src/main/compose/ozonescripts/start.sh delete mode 100755 hadoop-ozone/dist/src/main/compose/ozonescripts/stop.sh delete mode 100644 hadoop-ozone/dist/src/main/ozone/README.txt delete mode 100644 hadoop-ozone/dist/src/main/smoketest/README.md delete mode 100644 hadoop-ozone/dist/src/main/smoketest/basic/basic.robot delete mode 100644 hadoop-ozone/dist/src/main/smoketest/basic/ozone-shell.robot delete mode 100644 hadoop-ozone/dist/src/main/smoketest/commonlib.robot delete mode 100644 hadoop-ozone/dist/src/main/smoketest/ozonefs/ozonefs.robot delete mode 100644 hadoop-ozone/dist/src/main/smoketest/s3/awscli.robot delete mode 100755 hadoop-ozone/dist/src/main/smoketest/test.sh delete mode 100644 hadoop-ozone/docs/README.md delete mode 100644 hadoop-ozone/docs/archetypes/default.md delete mode 100644 hadoop-ozone/docs/config.yaml delete mode 100644 hadoop-ozone/docs/content/BucketCommands.md delete mode 100644 hadoop-ozone/docs/content/BuildingSources.md delete mode 100644 hadoop-ozone/docs/content/CommandShell.md delete mode 100644 hadoop-ozone/docs/content/Concepts.md delete mode 100644 hadoop-ozone/docs/content/Dozone.md delete mode 100644 hadoop-ozone/docs/content/Freon.md delete mode 100644 hadoop-ozone/docs/content/Hdds.md delete mode 100644 hadoop-ozone/docs/content/JavaApi.md delete mode 100644 hadoop-ozone/docs/content/KeyCommands.md delete mode 100644 hadoop-ozone/docs/content/OzoneFS.md delete mode 100644 hadoop-ozone/docs/content/OzoneManager.md delete mode 100644 hadoop-ozone/docs/content/RealCluster.md delete mode 100644 hadoop-ozone/docs/content/Rest.md delete mode 100644 hadoop-ozone/docs/content/RunningViaDocker.md delete mode 100644 hadoop-ozone/docs/content/RunningWithHDFS.md delete mode 100644 hadoop-ozone/docs/content/SCMCLI.md delete mode 100644 hadoop-ozone/docs/content/Settings.md delete mode 100644 hadoop-ozone/docs/content/VolumeCommands.md delete mode 100644 hadoop-ozone/docs/content/_index.md delete mode 100755 hadoop-ozone/docs/dev-support/bin/generate-site.sh delete mode 100644 hadoop-ozone/docs/pom.xml delete mode 100644 hadoop-ozone/docs/static/NOTES.md delete mode 100644 hadoop-ozone/docs/static/OzoneOverview.png delete mode 100644 hadoop-ozone/docs/static/OzoneOverview.svg delete mode 100644 hadoop-ozone/docs/static/SCMBlockDiagram.png delete mode 100644 hadoop-ozone/docs/static/ozone-logo.png delete mode 100644 hadoop-ozone/docs/themes/ozonedoc/layouts/_default/single.html delete mode 100644 hadoop-ozone/docs/themes/ozonedoc/layouts/index.html delete mode 100644 hadoop-ozone/docs/themes/ozonedoc/layouts/partials/footer.html delete mode 100644 hadoop-ozone/docs/themes/ozonedoc/layouts/partials/header.html delete mode 100644 hadoop-ozone/docs/themes/ozonedoc/layouts/partials/navbar.html delete mode 100644 hadoop-ozone/docs/themes/ozonedoc/layouts/partials/sidebar.html delete mode 100644 hadoop-ozone/docs/themes/ozonedoc/static/css/bootstrap-theme.min.css delete mode 100644 hadoop-ozone/docs/themes/ozonedoc/static/css/bootstrap-theme.min.css.map delete mode 100644 hadoop-ozone/docs/themes/ozonedoc/static/css/bootstrap.min.css delete mode 100644 hadoop-ozone/docs/themes/ozonedoc/static/css/bootstrap.min.css.map delete mode 100644 hadoop-ozone/docs/themes/ozonedoc/static/css/ozonedoc.css delete mode 100644 hadoop-ozone/docs/themes/ozonedoc/static/fonts/glyphicons-halflings-regular.eot delete mode 100644 hadoop-ozone/docs/themes/ozonedoc/static/fonts/glyphicons-halflings-regular.svg delete mode 100644 hadoop-ozone/docs/themes/ozonedoc/static/fonts/glyphicons-halflings-regular.ttf delete mode 100644 hadoop-ozone/docs/themes/ozonedoc/static/fonts/glyphicons-halflings-regular.woff delete mode 100644 hadoop-ozone/docs/themes/ozonedoc/static/fonts/glyphicons-halflings-regular.woff2 delete mode 100644 hadoop-ozone/docs/themes/ozonedoc/static/js/bootstrap.min.js delete mode 100644 hadoop-ozone/docs/themes/ozonedoc/static/js/jquery.min.js delete mode 100644 hadoop-ozone/docs/themes/ozonedoc/static/js/ozonedoc.js delete mode 100644 hadoop-ozone/docs/themes/ozonedoc/theme.toml delete mode 100644 hadoop-ozone/integration-test/pom.xml delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/hdds/scm/container/TestContainerStateManagerIntegration.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/hdds/scm/pipeline/TestNode2PipelineMap.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/hdds/scm/pipeline/TestNodeFailure.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/hdds/scm/pipeline/TestPipelineClose.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/hdds/scm/pipeline/TestSCMRestart.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/MiniOzoneCluster.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/MiniOzoneClusterImpl.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/OzoneTestUtils.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/RatisTestHelper.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestContainerOperations.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestMiniOzoneCluster.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestOzoneConfigurationFields.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestOzoneHelper.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestStorageContainerManager.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestStorageContainerManagerHelper.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rest/TestOzoneRestClient.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rest/package-info.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestCloseContainerHandlingByClient.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestOzoneRpcClient.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/package-info.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/ContainerTestHelper.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/TestContainerReplication.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/common/TestBlockDeletingService.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/common/helpers/TestBlockData.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/common/impl/TestCloseContainerHandler.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/common/impl/TestContainerDeletionChoosingPolicy.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/common/impl/TestContainerPersistence.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/TestBlockDeletion.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/TestCloseContainerByPipeline.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/TestCloseContainerHandler.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/common/transport/server/ratis/TestCSMMetrics.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/metrics/TestContainerMetrics.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/ozoneimpl/TestOzoneContainer.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/ozoneimpl/TestOzoneContainerRatis.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/ozoneimpl/TestRatisManager.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/server/TestContainerServer.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/server/TestContainerStateMachine.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/freon/package-info.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestContainerReportWithKeys.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestMultipleContainerReadWrite.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOmBlockVersioning.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOmMetrics.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOzoneManager.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOzoneManagerRestInterface.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestScmChillMode.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/package-info.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/ozShell/TestOzoneShell.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/scm/TestAllocateContainer.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/scm/TestContainerSmallFile.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/scm/TestGetCommittedBlockLengthAndPutKey.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/scm/TestSCMMXBean.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/scm/TestXceiverClientManager.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/scm/TestXceiverClientMetrics.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/scm/node/TestQueryNode.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/web/TestOzoneRestWithMiniCluster.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/web/TestOzoneVolumes.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/web/TestOzoneWebAccess.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/web/client/TestBuckets.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/web/client/TestBucketsRatis.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/web/client/TestKeys.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/web/client/TestKeysRatis.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/web/client/TestOzoneClient.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/web/client/TestVolume.java delete mode 100644 hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/web/client/TestVolumeRatis.java delete mode 100644 hadoop-ozone/integration-test/src/test/resources/log4j.properties delete mode 100644 hadoop-ozone/integration-test/src/test/resources/webapps/ozoneManager/.gitkeep delete mode 100644 hadoop-ozone/integration-test/src/test/resources/webapps/scm/.gitkeep delete mode 100644 hadoop-ozone/objectstore-service/pom.xml delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/hdfs/server/datanode/ObjectStoreHandler.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/hdfs/server/datanode/package-info.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/OzoneRestUtils.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/package-info.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/ObjectStoreApplication.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/OzoneHddsDatanodeService.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/exceptions/ErrorTable.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/exceptions/package-info.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/handlers/BucketHandler.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/handlers/BucketProcessTemplate.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/handlers/KeyHandler.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/handlers/KeyProcessTemplate.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/handlers/ServiceFilter.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/handlers/StorageHandlerBuilder.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/handlers/UserHandlerBuilder.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/handlers/VolumeHandler.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/handlers/VolumeProcessTemplate.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/handlers/package-info.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/interfaces/Accounting.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/interfaces/Bucket.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/interfaces/Keys.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/interfaces/StorageHandler.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/interfaces/UserAuth.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/interfaces/Volume.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/interfaces/package-info.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/localstorage/package-info.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/messages/LengthInputStreamMessageBodyWriter.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/messages/StringMessageBodyWriter.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/messages/package-info.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/netty/CloseableCleanupListener.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/netty/ObjectStoreChannelHandler.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/netty/ObjectStoreJerseyContainer.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/netty/ObjectStoreJerseyContainerProvider.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/netty/ObjectStoreRestHttpServer.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/netty/ObjectStoreURLDispatcher.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/netty/RequestContentObjectStoreChannelHandler.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/netty/RequestDispatchObjectStoreChannelHandler.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/netty/package-info.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/package-info.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/storage/DistributedStorageHandler.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/storage/package-info.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/userauth/Simple.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/java/org/apache/hadoop/ozone/web/userauth/package-info.java delete mode 100644 hadoop-ozone/objectstore-service/src/main/resources/META-INF/services/com.sun.jersey.spi.container.ContainerProvider delete mode 100644 hadoop-ozone/objectstore-service/src/test/java/org/apache/hadoop/ozone/web/TestErrorCode.java delete mode 100644 hadoop-ozone/ozone-manager/pom.xml delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/BucketManager.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/BucketManagerImpl.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/KeyDeletingService.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/KeyManager.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/KeyManagerImpl.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMMXBean.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMMetadataManager.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMMetrics.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMStorage.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OmMetadataManagerImpl.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OpenKeyCleanupService.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManagerHttpServer.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManagerLock.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/ServiceListJSONServlet.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/VolumeManager.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/VolumeManagerImpl.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/exceptions/OMException.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/exceptions/package-info.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/package-info.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerProtocolServerSideTranslatorPB.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/package-info.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/Handler.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/Shell.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/bucket/BucketCommands.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/bucket/CreateBucketHandler.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/bucket/DeleteBucketHandler.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/bucket/InfoBucketHandler.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/bucket/ListBucketHandler.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/bucket/UpdateBucketHandler.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/bucket/package-info.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/keys/DeleteKeyHandler.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/keys/GetKeyHandler.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/keys/InfoKeyHandler.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/keys/KeyCommands.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/keys/ListKeyHandler.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/keys/PutKeyHandler.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/keys/package-info.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/package-info.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/volume/CreateVolumeHandler.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/volume/DeleteVolumeHandler.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/volume/InfoVolumeHandler.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/volume/ListVolumeHandler.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/volume/UpdateVolumeHandler.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/volume/VolumeCommands.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/volume/package-info.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/package-info.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/resources/webapps/ozoneManager/index.html delete mode 100644 hadoop-ozone/ozone-manager/src/main/resources/webapps/ozoneManager/main.css delete mode 100644 hadoop-ozone/ozone-manager/src/main/resources/webapps/ozoneManager/main.html delete mode 100644 hadoop-ozone/ozone-manager/src/main/resources/webapps/ozoneManager/om-metrics.html delete mode 100644 hadoop-ozone/ozone-manager/src/main/resources/webapps/ozoneManager/ozoneManager.js delete mode 100644 hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/ScmBlockLocationTestIngClient.java delete mode 100644 hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestBucketManagerImpl.java delete mode 100644 hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestChunkStreams.java delete mode 100644 hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestKeyDeletingService.java delete mode 100644 hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestKeyManagerImpl.java delete mode 100644 hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestOzoneManagerHttpServer.java delete mode 100644 hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestOzoneManagerLock.java delete mode 100644 hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/package-info.java delete mode 100644 hadoop-ozone/ozonefs/pom.xml delete mode 100644 hadoop-ozone/ozonefs/src/main/java/org/apache/hadoop/fs/ozone/Constants.java delete mode 100644 hadoop-ozone/ozonefs/src/main/java/org/apache/hadoop/fs/ozone/OzFs.java delete mode 100644 hadoop-ozone/ozonefs/src/main/java/org/apache/hadoop/fs/ozone/OzoneFSInputStream.java delete mode 100644 hadoop-ozone/ozonefs/src/main/java/org/apache/hadoop/fs/ozone/OzoneFSOutputStream.java delete mode 100644 hadoop-ozone/ozonefs/src/main/java/org/apache/hadoop/fs/ozone/OzoneFileSystem.java delete mode 100644 hadoop-ozone/ozonefs/src/main/java/org/apache/hadoop/fs/ozone/package-info.java delete mode 100644 hadoop-ozone/ozonefs/src/test/java/org/apache/hadoop/fs/ozone/TestOzoneFSInputStream.java delete mode 100644 hadoop-ozone/ozonefs/src/test/java/org/apache/hadoop/fs/ozone/TestOzoneFileInterfaces.java delete mode 100644 hadoop-ozone/ozonefs/src/test/java/org/apache/hadoop/fs/ozone/contract/ITestOzoneContractCreate.java delete mode 100644 hadoop-ozone/ozonefs/src/test/java/org/apache/hadoop/fs/ozone/contract/ITestOzoneContractDelete.java delete mode 100644 hadoop-ozone/ozonefs/src/test/java/org/apache/hadoop/fs/ozone/contract/ITestOzoneContractDistCp.java delete mode 100644 hadoop-ozone/ozonefs/src/test/java/org/apache/hadoop/fs/ozone/contract/ITestOzoneContractGetFileStatus.java delete mode 100644 hadoop-ozone/ozonefs/src/test/java/org/apache/hadoop/fs/ozone/contract/ITestOzoneContractMkdir.java delete mode 100644 hadoop-ozone/ozonefs/src/test/java/org/apache/hadoop/fs/ozone/contract/ITestOzoneContractOpen.java delete mode 100644 hadoop-ozone/ozonefs/src/test/java/org/apache/hadoop/fs/ozone/contract/ITestOzoneContractRename.java delete mode 100644 hadoop-ozone/ozonefs/src/test/java/org/apache/hadoop/fs/ozone/contract/ITestOzoneContractRootDir.java delete mode 100644 hadoop-ozone/ozonefs/src/test/java/org/apache/hadoop/fs/ozone/contract/ITestOzoneContractSeek.java delete mode 100644 hadoop-ozone/ozonefs/src/test/java/org/apache/hadoop/fs/ozone/contract/OzoneContract.java delete mode 100644 hadoop-ozone/ozonefs/src/test/resources/contract/ozone.xml delete mode 100644 hadoop-ozone/ozonefs/src/test/resources/log4j.properties delete mode 100644 hadoop-ozone/pom.xml delete mode 100644 hadoop-ozone/s3gateway/pom.xml delete mode 100644 hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/CommonHeadersContainerResponseFilter.java delete mode 100644 hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/EndpointBase.java delete mode 100644 hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/Gateway.java delete mode 100644 hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/GatewayApplication.java delete mode 100644 hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/OzoneClientProducer.java delete mode 100644 hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/OzoneConfigurationHolder.java delete mode 100644 hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/S3GatewayConfigKeys.java delete mode 100644 hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/S3GatewayHttpServer.java delete mode 100644 hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/VirtualHostStyleFilter.java delete mode 100644 hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/bucket/DeleteBucket.java delete mode 100644 hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/bucket/PutBucket.java delete mode 100644 hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/bucket/package-info.java delete mode 100644 hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/commontypes/CommonPrefix.java delete mode 100644 hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/commontypes/IsoDateAdapter.java delete mode 100644 hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/commontypes/KeyMetadata.java delete mode 100644 hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/commontypes/package-info.java delete mode 100644 hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/exception/OS3Exception.java delete mode 100644 hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/exception/OS3ExceptionMapper.java delete mode 100644 hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/exception/S3ErrorTable.java delete mode 100644 hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/exception/package-info.java delete mode 100644 hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/object/DeleteObject.java delete mode 100644 hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/object/HeadObject.java delete mode 100644 hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/object/ListObject.java delete mode 100644 hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/object/ListObjectResponse.java delete mode 100644 hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/object/PutObject.java delete mode 100644 hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/object/package-info.java delete mode 100644 hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/package-info.java delete mode 100644 hadoop-ozone/s3gateway/src/main/resources/META-INF/beans.xml delete mode 100644 hadoop-ozone/s3gateway/src/main/resources/webapps/s3gateway/WEB-INF/beans.xml delete mode 100644 hadoop-ozone/s3gateway/src/main/resources/webapps/s3gateway/WEB-INF/web.xml delete mode 100644 hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/ObjectStoreStub.java delete mode 100644 hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/OzoneBucketStub.java delete mode 100644 hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/OzoneClientStub.java delete mode 100644 hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/OzoneVolumeStub.java delete mode 100644 hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/package-info.java delete mode 100644 hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/TestVirtualHostStyleFilter.java delete mode 100644 hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/bucket/TestBucketResponse.java delete mode 100644 hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/bucket/TestGetBucket.java delete mode 100644 hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/bucket/package-info.java delete mode 100644 hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/exception/TestOS3Exception.java delete mode 100644 hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/exception/package-info.java delete mode 100644 hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/object/TestDeleteObject.java delete mode 100644 hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/object/package-info.java delete mode 100644 hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/package-info.java delete mode 100644 hadoop-ozone/tools/dev-support/findbugsExcludeFile.xml delete mode 100644 hadoop-ozone/tools/pom.xml delete mode 100644 hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/freon/Freon.java delete mode 100644 hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/freon/RandomKeyGenerator.java delete mode 100644 hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/freon/package-info.java delete mode 100644 hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/genconf/GenerateOzoneRequiredConfigurations.java delete mode 100644 hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/genconf/package-info.java delete mode 100644 hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/genesis/BenchMarkContainerStateMap.java delete mode 100644 hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/genesis/BenchMarkDatanodeDispatcher.java delete mode 100644 hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/genesis/BenchMarkMetadataStoreReads.java delete mode 100644 hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/genesis/BenchMarkMetadataStoreWrites.java delete mode 100644 hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/genesis/BenchMarkRocksDbStore.java delete mode 100644 hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/genesis/Genesis.java delete mode 100644 hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/genesis/GenesisMemoryProfiler.java delete mode 100644 hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/genesis/GenesisUtil.java delete mode 100644 hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/genesis/package-info.java delete mode 100644 hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/scm/cli/SQLCLI.java delete mode 100644 hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/scm/cli/package-info.java delete mode 100644 hadoop-ozone/tools/src/test/java/org/apache/hadoop/ozone/freon/TestDataValidate.java delete mode 100644 hadoop-ozone/tools/src/test/java/org/apache/hadoop/ozone/freon/TestRandomKeyGenerator.java delete mode 100644 hadoop-ozone/tools/src/test/java/org/apache/hadoop/ozone/genconf/TestGenerateOzoneRequiredConfigurations.java delete mode 100644 hadoop-ozone/tools/src/test/java/org/apache/hadoop/ozone/genconf/package-info.java delete mode 100644 hadoop-ozone/tools/src/test/java/org/apache/hadoop/ozone/om/TestOmSQLCli.java delete mode 100644 hadoop-ozone/tools/src/test/java/org/apache/hadoop/ozone/scm/TestContainerSQLCli.java delete mode 100644 hadoop-ozone/tools/src/test/java/org/apache/hadoop/test/OzoneTestDriver.java diff --git a/.gitignore b/.gitignore index ac245c7575c..fc742c1420b 100644 --- a/.gitignore +++ b/.gitignore @@ -51,13 +51,3 @@ patchprocess/ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/package-lock.json hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/yarn-error.log -# Ignore files generated by HDDS acceptance tests. -hadoop-ozone/acceptance-test/docker-compose.log -hadoop-ozone/acceptance-test/junit-results.xml - -#robotframework outputs -log.html -output.xml -report.html - -hadoop-ozone/docs/public diff --git a/dev-support/bin/dist-layout-stitching b/dev-support/bin/dist-layout-stitching index 584821adbd7..97d544b87ce 100755 --- a/dev-support/bin/dist-layout-stitching +++ b/dev-support/bin/dist-layout-stitching @@ -21,9 +21,6 @@ VERSION=$1 # project.build.directory BASEDIR=$2 -#hdds.version -HDDS_VERSION=$3 - function run() { declare res diff --git a/hadoop-assemblies/src/main/resources/assemblies/hadoop-src-with-hdds.xml b/hadoop-assemblies/src/main/resources/assemblies/hadoop-src-with-hdds.xml deleted file mode 100644 index b1e039fd501..00000000000 --- a/hadoop-assemblies/src/main/resources/assemblies/hadoop-src-with-hdds.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - hadoop-src - - tar.gz - - true - - - . - - LICENCE.txt - README.txt - NOTICE.txt - - - - . - true - - .git/** - **/.gitignore - **/.svn - **/*.iws - **/*.ipr - **/*.iml - **/.classpath - **/.project - **/.settings - **/target/** - - **/*.log - **/build/** - **/file:/** - **/SecurityAuth.audit* - - - - diff --git a/hadoop-assemblies/src/main/resources/assemblies/hadoop-src.xml b/hadoop-assemblies/src/main/resources/assemblies/hadoop-src.xml index f0a8d44376c..b1e039fd501 100644 --- a/hadoop-assemblies/src/main/resources/assemblies/hadoop-src.xml +++ b/hadoop-assemblies/src/main/resources/assemblies/hadoop-src.xml @@ -50,8 +50,6 @@ **/build/** **/file:/** **/SecurityAuth.audit* - hadoop-ozone/** - hadoop-hdds/** diff --git a/hadoop-common-project/hadoop-common/src/main/bin/hadoop-functions.sh b/hadoop-common-project/hadoop-common/src/main/bin/hadoop-functions.sh index 71ba7fffc10..f0daafd47ea 100755 --- a/hadoop-common-project/hadoop-common/src/main/bin/hadoop-functions.sh +++ b/hadoop-common-project/hadoop-common/src/main/bin/hadoop-functions.sh @@ -596,11 +596,6 @@ function hadoop_bootstrap YARN_LIB_JARS_DIR=${YARN_LIB_JARS_DIR:-"share/hadoop/yarn/lib"} MAPRED_DIR=${MAPRED_DIR:-"share/hadoop/mapreduce"} MAPRED_LIB_JARS_DIR=${MAPRED_LIB_JARS_DIR:-"share/hadoop/mapreduce/lib"} - HDDS_DIR=${HDDS_DIR:-"share/hadoop/hdds"} - HDDS_LIB_JARS_DIR=${HDDS_LIB_JARS_DIR:-"share/hadoop/hdds/lib"} - OZONE_DIR=${OZONE_DIR:-"share/hadoop/ozone"} - OZONE_LIB_JARS_DIR=${OZONE_LIB_JARS_DIR:-"share/hadoop/ozone/lib"} - OZONEFS_DIR=${OZONEFS_DIR:-"share/hadoop/ozonefs"} HADOOP_TOOLS_HOME=${HADOOP_TOOLS_HOME:-${HADOOP_HOME}} HADOOP_TOOLS_DIR=${HADOOP_TOOLS_DIR:-"share/hadoop/tools"} diff --git a/hadoop-common-project/hadoop-common/src/main/conf/hadoop-env.sh b/hadoop-common-project/hadoop-common/src/main/conf/hadoop-env.sh index 6db085a3261..029fc40d3c7 100644 --- a/hadoop-common-project/hadoop-common/src/main/conf/hadoop-env.sh +++ b/hadoop-common-project/hadoop-common/src/main/conf/hadoop-env.sh @@ -403,15 +403,6 @@ esac # # export HDFS_DFSROUTER_OPTS="" -### -# Ozone Manager specific parameters -### -# Specify the JVM options to be used when starting the Ozone Manager. -# These options will be appended to the options specified as HADOOP_OPTS -# and therefore may override any similar flags set in HADOOP_OPTS -# -# export HDFS_OM_OPTS="" - ### # HDFS StorageContainerManager specific parameters ### diff --git a/hadoop-hdds/client/pom.xml b/hadoop-hdds/client/pom.xml deleted file mode 100644 index 53d72bb7e44..00000000000 --- a/hadoop-hdds/client/pom.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - 4.0.0 - - org.apache.hadoop - hadoop-hdds - 0.3.0-SNAPSHOT - - - hadoop-hdds-client - 0.3.0-SNAPSHOT - Apache Hadoop Distributed Data Store Client Library - Apache Hadoop HDDS Client - jar - - - - org.apache.hadoop - hadoop-hdds-common - - - - io.netty - netty-all - - - - \ No newline at end of file diff --git a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/XceiverClientGrpc.java b/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/XceiverClientGrpc.java deleted file mode 100644 index d353e7af423..00000000000 --- a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/XceiverClientGrpc.java +++ /dev/null @@ -1,215 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ContainerCommandRequestProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ContainerCommandResponseProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.XceiverClientProtocolServiceGrpc; -import org.apache.hadoop.hdds.protocol.datanode.proto.XceiverClientProtocolServiceGrpc.XceiverClientProtocolServiceStub; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.scm.client.HddsClientUtils; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.ozone.OzoneConfigKeys; -import org.apache.hadoop.util.Time; -import org.apache.ratis.shaded.io.grpc.ManagedChannel; -import org.apache.ratis.shaded.io.grpc.netty.NettyChannelBuilder; -import org.apache.ratis.shaded.io.grpc.stub.StreamObserver; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Semaphore; -import java.util.concurrent.TimeUnit; - -/** - * A Client for the storageContainer protocol. - */ -public class XceiverClientGrpc extends XceiverClientSpi { - static final Logger LOG = LoggerFactory.getLogger(XceiverClientGrpc.class); - private final Pipeline pipeline; - private final Configuration config; - private XceiverClientProtocolServiceStub asyncStub; - private XceiverClientMetrics metrics; - private ManagedChannel channel; - private final Semaphore semaphore; - private boolean closed = false; - - /** - * Constructs a client that can communicate with the Container framework on - * data nodes. - * - * @param pipeline - Pipeline that defines the machines. - * @param config -- Ozone Config - */ - public XceiverClientGrpc(Pipeline pipeline, Configuration config) { - super(); - Preconditions.checkNotNull(pipeline); - Preconditions.checkNotNull(config); - this.pipeline = pipeline; - this.config = config; - this.semaphore = - new Semaphore(HddsClientUtils.getMaxOutstandingRequests(config)); - this.metrics = XceiverClientManager.getXceiverClientMetrics(); - } - - @Override - public void connect() throws Exception { - DatanodeDetails leader = this.pipeline.getLeader(); - - // read port from the data node, on failure use default configured - // port. - int port = leader.getPort(DatanodeDetails.Port.Name.STANDALONE).getValue(); - if (port == 0) { - port = config.getInt(OzoneConfigKeys.DFS_CONTAINER_IPC_PORT, - OzoneConfigKeys.DFS_CONTAINER_IPC_PORT_DEFAULT); - } - LOG.debug("Connecting to server Port : " + leader.getIpAddress()); - channel = NettyChannelBuilder.forAddress(leader.getIpAddress(), port) - .usePlaintext() - .maxInboundMessageSize(OzoneConfigKeys.DFS_CONTAINER_CHUNK_MAX_SIZE) - .build(); - asyncStub = XceiverClientProtocolServiceGrpc.newStub(channel); - } - - /** - * Returns if the xceiver client connects to a server. - * - * @return True if the connection is alive, false otherwise. - */ - @VisibleForTesting - public boolean isConnected() { - return !channel.isTerminated() && !channel.isShutdown(); - } - - @Override - public void close() { - closed = true; - channel.shutdownNow(); - try { - channel.awaitTermination(60, TimeUnit.MINUTES); - } catch (Exception e) { - LOG.error("Unexpected exception while waiting for channel termination", - e); - } - } - - @Override - public Pipeline getPipeline() { - return pipeline; - } - - /** - * Sends a given command to server gets a waitable future back. - * - * @param request Request - * @return Response to the command - * @throws IOException - */ - @Override - public CompletableFuture - sendCommandAsync(ContainerCommandRequestProto request) - throws IOException, ExecutionException, InterruptedException { - if(closed){ - throw new IOException("This channel is not connected."); - } - - if(channel == null || !isConnected()) { - reconnect(); - } - - final CompletableFuture replyFuture = - new CompletableFuture<>(); - semaphore.acquire(); - long requestTime = Time.monotonicNowNanos(); - metrics.incrPendingContainerOpsMetrics(request.getCmdType()); - // create a new grpc stream for each non-async call. - final StreamObserver requestObserver = - asyncStub.send(new StreamObserver() { - @Override - public void onNext(ContainerCommandResponseProto value) { - replyFuture.complete(value); - metrics.decrPendingContainerOpsMetrics(request.getCmdType()); - metrics.addContainerOpsLatency(request.getCmdType(), - Time.monotonicNowNanos() - requestTime); - semaphore.release(); - } - @Override - public void onError(Throwable t) { - replyFuture.completeExceptionally(t); - metrics.decrPendingContainerOpsMetrics(request.getCmdType()); - metrics.addContainerOpsLatency(request.getCmdType(), - Time.monotonicNowNanos() - requestTime); - semaphore.release(); - } - - @Override - public void onCompleted() { - if (!replyFuture.isDone()) { - replyFuture.completeExceptionally( - new IOException("Stream completed but no reply for request " - + request)); - } - } - }); - requestObserver.onNext(request); - requestObserver.onCompleted(); - return replyFuture; - } - - private void reconnect() throws IOException { - try { - connect(); - } catch (Exception e) { - LOG.error("Error while connecting: ", e); - throw new IOException(e); - } - - if (channel == null || !isConnected()) { - throw new IOException("This channel is not connected."); - } - } - - /** - * Create a pipeline. - */ - @Override - public void createPipeline() { - // For stand alone pipeline, there is no notion called setup pipeline. - } - - public void destroyPipeline() { - // For stand alone pipeline, there is no notion called destroy pipeline. - } - - /** - * Returns pipeline Type. - * - * @return - Stand Alone as the type. - */ - @Override - public HddsProtos.ReplicationType getPipelineType() { - return HddsProtos.ReplicationType.STAND_ALONE; - } -} diff --git a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/XceiverClientManager.java b/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/XceiverClientManager.java deleted file mode 100644 index 97624061c31..00000000000 --- a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/XceiverClientManager.java +++ /dev/null @@ -1,224 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.RemovalListener; -import com.google.common.cache.RemovalNotification; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; - -import java.io.Closeable; -import java.io.IOException; -import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; - -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .SCM_CONTAINER_CLIENT_MAX_SIZE_DEFAULT; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .SCM_CONTAINER_CLIENT_MAX_SIZE_KEY; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .SCM_CONTAINER_CLIENT_STALE_THRESHOLD_DEFAULT; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .SCM_CONTAINER_CLIENT_STALE_THRESHOLD_KEY; - -/** - * XceiverClientManager is responsible for the lifecycle of XceiverClient - * instances. Callers use this class to acquire an XceiverClient instance - * connected to the desired container pipeline. When done, the caller also uses - * this class to release the previously acquired XceiverClient instance. - * - * - * This class caches connection to container for reuse purpose, such that - * accessing same container frequently will be through the same connection - * without reestablishing connection. But the connection will be closed if - * not being used for a period of time. - */ -public class XceiverClientManager implements Closeable { - - //TODO : change this to SCM configuration class - private final Configuration conf; - private final Cache clientCache; - private final boolean useRatis; - - private static XceiverClientMetrics metrics; - /** - * Creates a new XceiverClientManager. - * - * @param conf configuration - */ - public XceiverClientManager(Configuration conf) { - Preconditions.checkNotNull(conf); - int maxSize = conf.getInt(SCM_CONTAINER_CLIENT_MAX_SIZE_KEY, - SCM_CONTAINER_CLIENT_MAX_SIZE_DEFAULT); - long staleThresholdMs = conf.getTimeDuration( - SCM_CONTAINER_CLIENT_STALE_THRESHOLD_KEY, - SCM_CONTAINER_CLIENT_STALE_THRESHOLD_DEFAULT, TimeUnit.MILLISECONDS); - this.useRatis = conf.getBoolean( - ScmConfigKeys.DFS_CONTAINER_RATIS_ENABLED_KEY, - ScmConfigKeys.DFS_CONTAINER_RATIS_ENABLED_DEFAULT); - this.conf = conf; - this.clientCache = CacheBuilder.newBuilder() - .expireAfterAccess(staleThresholdMs, TimeUnit.MILLISECONDS) - .maximumSize(maxSize) - .removalListener( - new RemovalListener() { - @Override - public void onRemoval( - RemovalNotification - removalNotification) { - synchronized (clientCache) { - // Mark the entry as evicted - XceiverClientSpi info = removalNotification.getValue(); - info.setEvicted(); - } - } - }).build(); - } - - @VisibleForTesting - public Cache getClientCache() { - return clientCache; - } - - /** - * Acquires a XceiverClientSpi connected to a container capable of - * storing the specified key. - * - * If there is already a cached XceiverClientSpi, simply return - * the cached otherwise create a new one. - * - * @param pipeline the container pipeline for the client connection - * @return XceiverClientSpi connected to a container - * @throws IOException if a XceiverClientSpi cannot be acquired - */ - public XceiverClientSpi acquireClient(Pipeline pipeline, long containerID) - throws IOException { - Preconditions.checkNotNull(pipeline); - Preconditions.checkArgument(pipeline.getMachines() != null); - Preconditions.checkArgument(!pipeline.getMachines().isEmpty()); - - synchronized (clientCache) { - XceiverClientSpi info = getClient(pipeline, containerID); - info.incrementReference(); - return info; - } - } - - /** - * Releases a XceiverClientSpi after use. - * - * @param client client to release - */ - public void releaseClient(XceiverClientSpi client) { - Preconditions.checkNotNull(client); - synchronized (clientCache) { - client.decrementReference(); - } - } - - private XceiverClientSpi getClient(Pipeline pipeline, long containerID) - throws IOException { - try { - return clientCache.get(containerID, - new Callable() { - @Override - public XceiverClientSpi call() throws Exception { - XceiverClientSpi client = null; - switch (pipeline.getType()) { - case RATIS: - client = XceiverClientRatis.newXceiverClientRatis(pipeline, conf); - break; - case STAND_ALONE: - client = new XceiverClientGrpc(pipeline, conf); - break; - case CHAINED: - default: - throw new IOException("not implemented" + pipeline.getType()); - } - client.connect(); - return client; - } - }); - } catch (Exception e) { - throw new IOException( - "Exception getting XceiverClient: " + e.toString(), e); - } - } - - /** - * Close and remove all the cached clients. - */ - public void close() { - //closing is done through RemovalListener - clientCache.invalidateAll(); - clientCache.cleanUp(); - - if (metrics != null) { - metrics.unRegister(); - } - } - - /** - * Tells us if Ratis is enabled for this cluster. - * @return True if Ratis is enabled. - */ - public boolean isUseRatis() { - return useRatis; - } - - /** - * Returns hard coded 3 as replication factor. - * @return 3 - */ - public HddsProtos.ReplicationFactor getFactor() { - if(isUseRatis()) { - return HddsProtos.ReplicationFactor.THREE; - } - return HddsProtos.ReplicationFactor.ONE; - } - - /** - * Returns the default replication type. - * @return Ratis or Standalone - */ - public HddsProtos.ReplicationType getType() { - // TODO : Fix me and make Ratis default before release. - // TODO: Remove this as replication factor and type are pipeline properties - if(isUseRatis()) { - return HddsProtos.ReplicationType.RATIS; - } - return HddsProtos.ReplicationType.STAND_ALONE; - } - - /** - * Get xceiver client metric. - */ - public synchronized static XceiverClientMetrics getXceiverClientMetrics() { - if (metrics == null) { - metrics = XceiverClientMetrics.create(); - } - - return metrics; - } -} diff --git a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/XceiverClientMetrics.java b/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/XceiverClientMetrics.java deleted file mode 100644 index a4304009add..00000000000 --- a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/XceiverClientMetrics.java +++ /dev/null @@ -1,92 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.metrics2.MetricsSystem; -import org.apache.hadoop.metrics2.annotation.Metric; -import org.apache.hadoop.metrics2.annotation.Metrics; -import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem; -import org.apache.hadoop.metrics2.lib.MetricsRegistry; -import org.apache.hadoop.metrics2.lib.MutableCounterLong; -import org.apache.hadoop.metrics2.lib.MutableRate; - -/** - * The client metrics for the Storage Container protocol. - */ -@InterfaceAudience.Private -@Metrics(about = "Storage Container Client Metrics", context = "dfs") -public class XceiverClientMetrics { - public static final String SOURCE_NAME = XceiverClientMetrics.class - .getSimpleName(); - - private @Metric MutableCounterLong pendingOps; - private MutableCounterLong[] pendingOpsArray; - private MutableRate[] containerOpsLatency; - private MetricsRegistry registry; - - public XceiverClientMetrics() { - int numEnumEntries = ContainerProtos.Type.values().length; - this.registry = new MetricsRegistry(SOURCE_NAME); - - this.pendingOpsArray = new MutableCounterLong[numEnumEntries]; - this.containerOpsLatency = new MutableRate[numEnumEntries]; - for (int i = 0; i < numEnumEntries; i++) { - pendingOpsArray[i] = registry.newCounter( - "numPending" + ContainerProtos.Type.forNumber(i + 1), - "number of pending" + ContainerProtos.Type.forNumber(i + 1) + " ops", - (long) 0); - - containerOpsLatency[i] = registry.newRate( - ContainerProtos.Type.forNumber(i + 1) + "Latency", - "latency of " + ContainerProtos.Type.forNumber(i + 1) - + " ops"); - } - } - - public static XceiverClientMetrics create() { - MetricsSystem ms = DefaultMetricsSystem.instance(); - return ms.register(SOURCE_NAME, "Storage Container Client Metrics", - new XceiverClientMetrics()); - } - - public void incrPendingContainerOpsMetrics(ContainerProtos.Type type) { - pendingOps.incr(); - pendingOpsArray[type.ordinal()].incr(); - } - - public void decrPendingContainerOpsMetrics(ContainerProtos.Type type) { - pendingOps.incr(-1); - pendingOpsArray[type.ordinal()].incr(-1); - } - - public void addContainerOpsLatency(ContainerProtos.Type type, - long latencyNanos) { - containerOpsLatency[type.ordinal()].add(latencyNanos); - } - - public long getContainerOpsMetrics(ContainerProtos.Type type) { - return pendingOpsArray[type.ordinal()].value(); - } - - public void unRegister() { - MetricsSystem ms = DefaultMetricsSystem.instance(); - ms.unregisterSource(SOURCE_NAME); - } -} diff --git a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/XceiverClientRatis.java b/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/XceiverClientRatis.java deleted file mode 100644 index 0d301d98516..00000000000 --- a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/XceiverClientRatis.java +++ /dev/null @@ -1,215 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm; - -import org.apache.hadoop.hdds.HddsUtils; -import org.apache.hadoop.io.MultipleIOException; -import org.apache.ratis.retry.RetryPolicy; -import org.apache.ratis.shaded.com.google.protobuf - .InvalidProtocolBufferException; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.scm.client.HddsClientUtils; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandRequestProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandResponseProto; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.ratis.RatisHelper; -import org.apache.ratis.client.RaftClient; -import org.apache.ratis.protocol.RaftClientReply; -import org.apache.ratis.protocol.RaftGroup; -import org.apache.ratis.protocol.RaftPeer; -import org.apache.ratis.rpc.RpcType; -import org.apache.ratis.rpc.SupportedRpcType; -import org.apache.ratis.shaded.com.google.protobuf.ByteString; -import org.apache.ratis.util.CheckedBiConsumer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; -import java.util.concurrent.atomic.AtomicReference; - -/** - * An abstract implementation of {@link XceiverClientSpi} using Ratis. - * The underlying RPC mechanism can be chosen via the constructor. - */ -public final class XceiverClientRatis extends XceiverClientSpi { - static final Logger LOG = LoggerFactory.getLogger(XceiverClientRatis.class); - - public static XceiverClientRatis newXceiverClientRatis( - Pipeline pipeline, Configuration ozoneConf) { - final String rpcType = ozoneConf.get( - ScmConfigKeys.DFS_CONTAINER_RATIS_RPC_TYPE_KEY, - ScmConfigKeys.DFS_CONTAINER_RATIS_RPC_TYPE_DEFAULT); - final int maxOutstandingRequests = - HddsClientUtils.getMaxOutstandingRequests(ozoneConf); - final RetryPolicy retryPolicy = RatisHelper.createRetryPolicy(ozoneConf); - return new XceiverClientRatis(pipeline, - SupportedRpcType.valueOfIgnoreCase(rpcType), maxOutstandingRequests, - retryPolicy); - } - - private final Pipeline pipeline; - private final RpcType rpcType; - private final AtomicReference client = new AtomicReference<>(); - private final int maxOutstandingRequests; - private final RetryPolicy retryPolicy; - - /** - * Constructs a client. - */ - private XceiverClientRatis(Pipeline pipeline, RpcType rpcType, - int maxOutStandingChunks, RetryPolicy retryPolicy) { - super(); - this.pipeline = pipeline; - this.rpcType = rpcType; - this.maxOutstandingRequests = maxOutStandingChunks; - this.retryPolicy = retryPolicy; - } - - /** - * {@inheritDoc} - */ - public void createPipeline() throws IOException { - final RaftGroup group = RatisHelper.newRaftGroup(pipeline); - LOG.debug("creating pipeline:{} with {}", pipeline.getId(), group); - callRatisRpc(pipeline.getMachines(), - (raftClient, peer) -> raftClient.groupAdd(group, peer.getId())); - } - - /** - * {@inheritDoc} - */ - public void destroyPipeline() throws IOException { - final RaftGroup group = RatisHelper.newRaftGroup(pipeline); - LOG.debug("destroying pipeline:{} with {}", pipeline.getId(), group); - callRatisRpc(pipeline.getMachines(), (raftClient, peer) -> raftClient - .groupRemove(group.getGroupId(), true, peer.getId())); - } - - /** - * Returns Ratis as pipeline Type. - * - * @return - Ratis - */ - @Override - public HddsProtos.ReplicationType getPipelineType() { - return HddsProtos.ReplicationType.RATIS; - } - - private void callRatisRpc(List datanodes, - CheckedBiConsumer rpc) - throws IOException { - if (datanodes.isEmpty()) { - return; - } - - final List exceptions = - Collections.synchronizedList(new ArrayList<>()); - datanodes.parallelStream().forEach(d -> { - final RaftPeer p = RatisHelper.toRaftPeer(d); - try (RaftClient client = RatisHelper - .newRaftClient(rpcType, p, retryPolicy)) { - rpc.accept(client, p); - } catch (IOException ioe) { - exceptions.add( - new IOException("Failed invoke Ratis rpc " + rpc + " for " + d, - ioe)); - } - }); - if (!exceptions.isEmpty()) { - throw MultipleIOException.createIOException(exceptions); - } - } - - @Override - public Pipeline getPipeline() { - return pipeline; - } - - @Override - public void connect() throws Exception { - LOG.debug("Connecting to pipeline:{} leader:{}", - getPipeline().getId(), - RatisHelper.toRaftPeerId(pipeline.getLeader())); - // TODO : XceiverClient ratis should pass the config value of - // maxOutstandingRequests so as to set the upper bound on max no of async - // requests to be handled by raft client - if (!client.compareAndSet(null, - RatisHelper.newRaftClient(rpcType, getPipeline(), retryPolicy))) { - throw new IllegalStateException("Client is already connected."); - } - } - - @Override - public void close() { - final RaftClient c = client.getAndSet(null); - if (c != null) { - try { - c.close(); - } catch (IOException e) { - throw new IllegalStateException(e); - } - } - } - - private RaftClient getClient() { - return Objects.requireNonNull(client.get(), "client is null"); - } - - private CompletableFuture sendRequestAsync( - ContainerCommandRequestProto request) { - boolean isReadOnlyRequest = HddsUtils.isReadOnly(request); - ByteString byteString = request.toByteString(); - LOG.debug("sendCommandAsync {} {}", isReadOnlyRequest, request); - return isReadOnlyRequest ? getClient().sendReadOnlyAsync(() -> byteString) : - getClient().sendAsync(() -> byteString); - } - - /** - * Sends a given command to server gets a waitable future back. - * - * @param request Request - * @return Response to the command - * @throws IOException - */ - @Override - public CompletableFuture sendCommandAsync( - ContainerCommandRequestProto request) { - return sendRequestAsync(request).whenComplete((reply, e) -> - LOG.debug("received reply {} for request: {} exception: {}", request, - reply, e)) - .thenApply(reply -> { - try { - return ContainerCommandResponseProto.parseFrom( - reply.getMessage().getContent()); - } catch (InvalidProtocolBufferException e) { - throw new CompletionException(e); - } - }); - } -} diff --git a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/client/ContainerOperationClient.java b/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/client/ContainerOperationClient.java deleted file mode 100644 index fed589c81de..00000000000 --- a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/client/ContainerOperationClient.java +++ /dev/null @@ -1,476 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.client; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdds.scm.XceiverClientManager; -import org.apache.hadoop.hdds.scm.XceiverClientSpi; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerWithPipeline; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.scm.protocolPB - .StorageContainerLocationProtocolClientSideTranslatorPB; -import org.apache.hadoop.hdds.scm.storage.ContainerProtocolCalls; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerData; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ReadContainerResponseProto; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos.ObjectStageChangeRequestProto; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.List; -import java.util.UUID; - -import static org.apache.hadoop.hdds.protocol.proto.HddsProtos.LifeCycleState - .ALLOCATED; -import static org.apache.hadoop.hdds.protocol.proto.HddsProtos.LifeCycleState - .OPEN; - -/** - * This class provides the client-facing APIs of container operations. - */ -public class ContainerOperationClient implements ScmClient { - - private static final Logger LOG = - LoggerFactory.getLogger(ContainerOperationClient.class); - private static long containerSizeB = -1; - private final StorageContainerLocationProtocolClientSideTranslatorPB - storageContainerLocationClient; - private final XceiverClientManager xceiverClientManager; - - public ContainerOperationClient( - StorageContainerLocationProtocolClientSideTranslatorPB - storageContainerLocationClient, - XceiverClientManager xceiverClientManager) { - this.storageContainerLocationClient = storageContainerLocationClient; - this.xceiverClientManager = xceiverClientManager; - } - - /** - * Return the capacity of containers. The current assumption is that all - * containers have the same capacity. Therefore one static is sufficient for - * any container. - * @return The capacity of one container in number of bytes. - */ - public static long getContainerSizeB() { - return containerSizeB; - } - - /** - * Set the capacity of container. Should be exactly once on system start. - * @param size Capacity of one container in number of bytes. - */ - public static void setContainerSizeB(long size) { - containerSizeB = size; - } - - /** - * @inheritDoc - */ - @Override - public ContainerWithPipeline createContainer(String owner) - throws IOException { - XceiverClientSpi client = null; - try { - ContainerWithPipeline containerWithPipeline = - storageContainerLocationClient.allocateContainer( - xceiverClientManager.getType(), - xceiverClientManager.getFactor(), owner); - Pipeline pipeline = containerWithPipeline.getPipeline(); - client = xceiverClientManager.acquireClient(pipeline, - containerWithPipeline.getContainerInfo().getContainerID()); - - // Allocated State means that SCM has allocated this pipeline in its - // namespace. The client needs to create the pipeline on the machines - // which was choosen by the SCM. - Preconditions.checkState(pipeline.getLifeCycleState() == ALLOCATED || - pipeline.getLifeCycleState() == OPEN, "Unexpected pipeline state"); - if (pipeline.getLifeCycleState() == ALLOCATED) { - createPipeline(client, pipeline); - } - createContainer(client, - containerWithPipeline.getContainerInfo().getContainerID()); - return containerWithPipeline; - } finally { - if (client != null) { - xceiverClientManager.releaseClient(client); - } - } - } - - /** - * Create a container over pipeline specified by the SCM. - * - * @param client - Client to communicate with Datanodes. - * @param containerId - Container ID. - * @throws IOException - */ - public void createContainer(XceiverClientSpi client, - long containerId) throws IOException { - String traceID = UUID.randomUUID().toString(); - storageContainerLocationClient.notifyObjectStageChange( - ObjectStageChangeRequestProto.Type.container, - containerId, - ObjectStageChangeRequestProto.Op.create, - ObjectStageChangeRequestProto.Stage.begin); - ContainerProtocolCalls.createContainer(client, containerId, traceID); - storageContainerLocationClient.notifyObjectStageChange( - ObjectStageChangeRequestProto.Type.container, - containerId, - ObjectStageChangeRequestProto.Op.create, - ObjectStageChangeRequestProto.Stage.complete); - - // Let us log this info after we let SCM know that we have completed the - // creation state. - if (LOG.isDebugEnabled()) { - LOG.debug("Created container " + containerId - + " leader:" + client.getPipeline().getLeader() - + " machines:" + client.getPipeline().getMachines()); - } - } - - /** - * Creates a pipeline over the machines choosen by the SCM. - * - * @param client - Client - * @param pipeline - pipeline to be createdon Datanodes. - * @throws IOException - */ - private void createPipeline(XceiverClientSpi client, Pipeline pipeline) - throws IOException { - - Preconditions.checkNotNull(pipeline.getId(), "Pipeline " + - "name cannot be null when client create flag is set."); - - // Pipeline creation is a three step process. - // - // 1. Notify SCM that this client is doing a create pipeline on - // datanodes. - // - // 2. Talk to Datanodes to create the pipeline. - // - // 3. update SCM that pipeline creation was successful. - - // TODO: this has not been fully implemented on server side - // SCMClientProtocolServer#notifyObjectStageChange - // TODO: when implement the pipeline state machine, change - // the pipeline name (string) to pipeline id (long) - //storageContainerLocationClient.notifyObjectStageChange( - // ObjectStageChangeRequestProto.Type.pipeline, - // pipeline.getPipelineName(), - // ObjectStageChangeRequestProto.Op.create, - // ObjectStageChangeRequestProto.Stage.begin); - - client.createPipeline(); - - //storageContainerLocationClient.notifyObjectStageChange( - // ObjectStageChangeRequestProto.Type.pipeline, - // pipeline.getPipelineName(), - // ObjectStageChangeRequestProto.Op.create, - // ObjectStageChangeRequestProto.Stage.complete); - - // TODO : Should we change the state on the client side ?? - // That makes sense, but it is not needed for the client to work. - LOG.debug("Pipeline creation successful. Pipeline: {}", - pipeline.toString()); - } - - /** - * @inheritDoc - */ - @Override - public ContainerWithPipeline createContainer(HddsProtos.ReplicationType type, - HddsProtos.ReplicationFactor factor, String owner) throws IOException { - XceiverClientSpi client = null; - try { - // allocate container on SCM. - ContainerWithPipeline containerWithPipeline = - storageContainerLocationClient.allocateContainer(type, factor, - owner); - Pipeline pipeline = containerWithPipeline.getPipeline(); - client = xceiverClientManager.acquireClient(pipeline, - containerWithPipeline.getContainerInfo().getContainerID()); - - // Allocated State means that SCM has allocated this pipeline in its - // namespace. The client needs to create the pipeline on the machines - // which was choosen by the SCM. - if (pipeline.getLifeCycleState() == ALLOCATED) { - createPipeline(client, pipeline); - } - // connect to pipeline leader and allocate container on leader datanode. - client = xceiverClientManager.acquireClient(pipeline, - containerWithPipeline.getContainerInfo().getContainerID()); - createContainer(client, - containerWithPipeline.getContainerInfo().getContainerID()); - return containerWithPipeline; - } finally { - if (client != null) { - xceiverClientManager.releaseClient(client); - } - } - } - - /** - * Returns a set of Nodes that meet a query criteria. - * - * @param nodeStatuses - Criteria that we want the node to have. - * @param queryScope - Query scope - Cluster or pool. - * @param poolName - if it is pool, a pool name is required. - * @return A set of nodes that meet the requested criteria. - * @throws IOException - */ - @Override - public List queryNode(HddsProtos.NodeState - nodeStatuses, HddsProtos.QueryScope queryScope, String poolName) - throws IOException { - return storageContainerLocationClient.queryNode(nodeStatuses, queryScope, - poolName); - } - - /** - * Creates a specified replication pipeline. - */ - @Override - public Pipeline createReplicationPipeline(HddsProtos.ReplicationType type, - HddsProtos.ReplicationFactor factor, HddsProtos.NodePool nodePool) - throws IOException { - return storageContainerLocationClient.createReplicationPipeline(type, - factor, nodePool); - } - - @Override - public void close() { - try { - xceiverClientManager.close(); - } catch (Exception ex) { - LOG.error("Can't close " + this.getClass().getSimpleName(), ex); - } - } - - /** - * Deletes an existing container. - * - * @param containerId - ID of the container. - * @param pipeline - Pipeline that represents the container. - * @param force - true to forcibly delete the container. - * @throws IOException - */ - @Override - public void deleteContainer(long containerId, Pipeline pipeline, - boolean force) throws IOException { - XceiverClientSpi client = null; - try { - client = xceiverClientManager.acquireClient(pipeline, containerId); - String traceID = UUID.randomUUID().toString(); - ContainerProtocolCalls - .deleteContainer(client, containerId, force, traceID); - storageContainerLocationClient - .deleteContainer(containerId); - if (LOG.isDebugEnabled()) { - LOG.debug("Deleted container {}, leader: {}, machines: {} ", - containerId, - pipeline.getLeader(), - pipeline.getMachines()); - } - } finally { - if (client != null) { - xceiverClientManager.releaseClient(client); - } - } - } - - /** - * Delete the container, this will release any resource it uses. - * @param containerID - containerID. - * @param force - True to forcibly delete the container. - * @throws IOException - */ - @Override - public void deleteContainer(long containerID, boolean force) - throws IOException { - ContainerWithPipeline info = getContainerWithPipeline(containerID); - deleteContainer(containerID, info.getPipeline(), force); - } - - /** - * {@inheritDoc} - */ - @Override - public List listContainer(long startContainerID, - int count) throws IOException { - return storageContainerLocationClient.listContainer( - startContainerID, count); - } - - /** - * Get meta data from an existing container. - * - * @param containerID - ID of the container. - * @param pipeline - Pipeline where the container is located. - * @return ContainerInfo - * @throws IOException - */ - @Override - public ContainerData readContainer(long containerID, - Pipeline pipeline) throws IOException { - XceiverClientSpi client = null; - try { - client = xceiverClientManager.acquireClient(pipeline, containerID); - String traceID = UUID.randomUUID().toString(); - ReadContainerResponseProto response = - ContainerProtocolCalls.readContainer(client, containerID, traceID); - if (LOG.isDebugEnabled()) { - LOG.debug("Read container {}, leader: {}, machines: {} ", - containerID, - pipeline.getLeader(), - pipeline.getMachines()); - } - return response.getContainerData(); - } finally { - if (client != null) { - xceiverClientManager.releaseClient(client); - } - } - } - - /** - * Get meta data from an existing container. - * @param containerID - ID of the container. - * @return ContainerInfo - a message of protobuf which has basic info - * of a container. - * @throws IOException - */ - @Override - public ContainerData readContainer(long containerID) throws IOException { - ContainerWithPipeline info = getContainerWithPipeline(containerID); - return readContainer(containerID, info.getPipeline()); - } - - /** - * Given an id, return the pipeline associated with the container. - * @param containerId - String Container ID - * @return Pipeline of the existing container, corresponding to the given id. - * @throws IOException - */ - @Override - public ContainerInfo getContainer(long containerId) throws - IOException { - return storageContainerLocationClient.getContainer(containerId); - } - - /** - * Gets a container by Name -- Throws if the container does not exist. - * - * @param containerId - Container ID - * @return ContainerWithPipeline - * @throws IOException - */ - @Override - public ContainerWithPipeline getContainerWithPipeline(long containerId) - throws IOException { - return storageContainerLocationClient.getContainerWithPipeline(containerId); - } - - /** - * Close a container. - * - * @param pipeline the container to be closed. - * @throws IOException - */ - @Override - public void closeContainer(long containerId, Pipeline pipeline) - throws IOException { - XceiverClientSpi client = null; - try { - LOG.debug("Close container {}", pipeline); - /* - TODO: two orders here, revisit this later: - 1. close on SCM first, then on data node - 2. close on data node first, then on SCM - - with 1: if client failed after closing on SCM, then there is a - container SCM thinks as closed, but is actually open. Then SCM will no - longer allocate block to it, which is fine. But SCM may later try to - replicate this "closed" container, which I'm not sure is safe. - - with 2: if client failed after close on datanode, then there is a - container SCM thinks as open, but is actually closed. Then SCM will still - try to allocate block to it. Which will fail when actually doing the - write. No more data can be written, but at least the correctness and - consistency of existing data will maintain. - - For now, take the #2 way. - */ - // Actually close the container on Datanode - client = xceiverClientManager.acquireClient(pipeline, containerId); - String traceID = UUID.randomUUID().toString(); - - storageContainerLocationClient.notifyObjectStageChange( - ObjectStageChangeRequestProto.Type.container, - containerId, - ObjectStageChangeRequestProto.Op.close, - ObjectStageChangeRequestProto.Stage.begin); - - ContainerProtocolCalls.closeContainer(client, containerId, traceID); - // Notify SCM to close the container - storageContainerLocationClient.notifyObjectStageChange( - ObjectStageChangeRequestProto.Type.container, - containerId, - ObjectStageChangeRequestProto.Op.close, - ObjectStageChangeRequestProto.Stage.complete); - } finally { - if (client != null) { - xceiverClientManager.releaseClient(client); - } - } - } - - /** - * Close a container. - * - * @throws IOException - */ - @Override - public void closeContainer(long containerId) - throws IOException { - ContainerWithPipeline info = getContainerWithPipeline(containerId); - Pipeline pipeline = info.getPipeline(); - closeContainer(containerId, pipeline); - } - - /** - * Get the the current usage information. - * @param containerID - ID of the container. - * @return the size of the given container. - * @throws IOException - */ - @Override - public long getContainerSize(long containerID) throws IOException { - // TODO : Fix this, it currently returns the capacity - // but not the current usage. - long size = getContainerSizeB(); - if (size == -1) { - throw new IOException("Container size unknown!"); - } - return size; - } -} diff --git a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/client/HddsClientUtils.java b/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/client/HddsClientUtils.java deleted file mode 100644 index 9c590385a4e..00000000000 --- a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/client/HddsClientUtils.java +++ /dev/null @@ -1,255 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.client; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.classification.InterfaceStability; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.scm.ScmConfigKeys; -import org.apache.hadoop.ozone.OzoneConfigKeys; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.text.ParseException; -import java.time.Instant; -import java.time.ZoneId; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.util.concurrent.TimeUnit; - -/** - * Utility methods for Ozone and Container Clients. - * - * The methods to retrieve SCM service endpoints assume there is a single - * SCM service instance. This will change when we switch to replicated service - * instances for redundancy. - */ -@InterfaceAudience.Public -@InterfaceStability.Unstable -public final class HddsClientUtils { - - private static final Logger LOG = LoggerFactory.getLogger( - HddsClientUtils.class); - - private static final int NO_PORT = -1; - - private HddsClientUtils() { - } - - /** - * Date format that used in ozone. Here the format is thread safe to use. - */ - private static final ThreadLocal DATE_FORMAT = - ThreadLocal.withInitial(() -> { - DateTimeFormatter format = - DateTimeFormatter.ofPattern(OzoneConsts.OZONE_DATE_FORMAT); - return format.withZone(ZoneId.of(OzoneConsts.OZONE_TIME_ZONE)); - }); - - - /** - * Convert time in millisecond to a human readable format required in ozone. - * @return a human readable string for the input time - */ - public static String formatDateTime(long millis) { - ZonedDateTime dateTime = ZonedDateTime.ofInstant( - Instant.ofEpochMilli(millis), DATE_FORMAT.get().getZone()); - return DATE_FORMAT.get().format(dateTime); - } - - /** - * Convert time in ozone date format to millisecond. - * @return time in milliseconds - */ - public static long formatDateTime(String date) throws ParseException { - Preconditions.checkNotNull(date, "Date string should not be null."); - return ZonedDateTime.parse(date, DATE_FORMAT.get()) - .toInstant().toEpochMilli(); - } - - - - /** - * verifies that bucket name / volume name is a valid DNS name. - * - * @param resName Bucket or volume Name to be validated - * - * @throws IllegalArgumentException - */ - public static void verifyResourceName(String resName) - throws IllegalArgumentException { - - if (resName == null) { - throw new IllegalArgumentException("Bucket or Volume name is null"); - } - - if ((resName.length() < OzoneConsts.OZONE_MIN_BUCKET_NAME_LENGTH) || - (resName.length() > OzoneConsts.OZONE_MAX_BUCKET_NAME_LENGTH)) { - throw new IllegalArgumentException( - "Bucket or Volume length is illegal, " + - "valid length is 3-63 characters"); - } - - if ((resName.charAt(0) == '.') || (resName.charAt(0) == '-')) { - throw new IllegalArgumentException( - "Bucket or Volume name cannot start with a period or dash"); - } - - if ((resName.charAt(resName.length() - 1) == '.') || - (resName.charAt(resName.length() - 1) == '-')) { - throw new IllegalArgumentException( - "Bucket or Volume name cannot end with a period or dash"); - } - - boolean isIPv4 = true; - char prev = (char) 0; - - for (int index = 0; index < resName.length(); index++) { - char currChar = resName.charAt(index); - - if (currChar != '.') { - isIPv4 = ((currChar >= '0') && (currChar <= '9')) && isIPv4; - } - - if (currChar > 'A' && currChar < 'Z') { - throw new IllegalArgumentException( - "Bucket or Volume name does not support uppercase characters"); - } - - if ((currChar != '.') && (currChar != '-')) { - if ((currChar < '0') || (currChar > '9' && currChar < 'a') || - (currChar > 'z')) { - throw new IllegalArgumentException("Bucket or Volume name has an " + - "unsupported character : " + - currChar); - } - } - - if ((prev == '.') && (currChar == '.')) { - throw new IllegalArgumentException("Bucket or Volume name should not " + - "have two contiguous periods"); - } - - if ((prev == '-') && (currChar == '.')) { - throw new IllegalArgumentException( - "Bucket or Volume name should not have period after dash"); - } - - if ((prev == '.') && (currChar == '-')) { - throw new IllegalArgumentException( - "Bucket or Volume name should not have dash after period"); - } - prev = currChar; - } - - if (isIPv4) { - throw new IllegalArgumentException( - "Bucket or Volume name cannot be an IPv4 address or all numeric"); - } - } - - /** - * verifies that bucket / volume name is a valid DNS name. - * - * @param resourceNames Array of bucket / volume names to be verified. - */ - public static void verifyResourceName(String... resourceNames) { - for (String resourceName : resourceNames) { - HddsClientUtils.verifyResourceName(resourceName); - } - } - - /** - * Checks that object parameters passed as reference is not null. - * - * @param references Array of object references to be checked. - * @param - */ - public static void checkNotNull(T... references) { - for (T ref: references) { - Preconditions.checkNotNull(ref); - } - } - - /** - * Returns the cache value to be used for list calls. - * @param conf Configuration object - * @return list cache size - */ - public static int getListCacheSize(Configuration conf) { - return conf.getInt(OzoneConfigKeys.OZONE_CLIENT_LIST_CACHE_SIZE, - OzoneConfigKeys.OZONE_CLIENT_LIST_CACHE_SIZE_DEFAULT); - } - - /** - * @return a default instance of {@link CloseableHttpClient}. - */ - public static CloseableHttpClient newHttpClient() { - return HddsClientUtils.newHttpClient(new Configuration()); - } - - /** - * Returns a {@link CloseableHttpClient} configured by given configuration. - * If conf is null, returns a default instance. - * - * @param conf configuration - * @return a {@link CloseableHttpClient} instance. - */ - public static CloseableHttpClient newHttpClient(Configuration conf) { - long socketTimeout = OzoneConfigKeys - .OZONE_CLIENT_SOCKET_TIMEOUT_DEFAULT; - long connectionTimeout = OzoneConfigKeys - .OZONE_CLIENT_CONNECTION_TIMEOUT_DEFAULT; - if (conf != null) { - socketTimeout = conf.getTimeDuration( - OzoneConfigKeys.OZONE_CLIENT_SOCKET_TIMEOUT, - OzoneConfigKeys.OZONE_CLIENT_SOCKET_TIMEOUT_DEFAULT, - TimeUnit.MILLISECONDS); - connectionTimeout = conf.getTimeDuration( - OzoneConfigKeys.OZONE_CLIENT_CONNECTION_TIMEOUT, - OzoneConfigKeys.OZONE_CLIENT_CONNECTION_TIMEOUT_DEFAULT, - TimeUnit.MILLISECONDS); - } - - CloseableHttpClient client = HttpClients.custom() - .setDefaultRequestConfig( - RequestConfig.custom() - .setSocketTimeout(Math.toIntExact(socketTimeout)) - .setConnectTimeout(Math.toIntExact(connectionTimeout)) - .build()) - .build(); - return client; - } - - /** - * Returns the maximum no of outstanding async requests to be handled by - * Standalone and Ratis client. - */ - public static int getMaxOutstandingRequests(Configuration config) { - return config - .getInt(ScmConfigKeys.SCM_CONTAINER_CLIENT_MAX_OUTSTANDING_REQUESTS, - ScmConfigKeys - .SCM_CONTAINER_CLIENT_MAX_OUTSTANDING_REQUESTS_DEFAULT); - } -} \ No newline at end of file diff --git a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/client/package-info.java b/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/client/package-info.java deleted file mode 100644 index 73ad78cd787..00000000000 --- a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/client/package-info.java +++ /dev/null @@ -1,23 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.client; - -/** - * Client facing classes for the container operations. - */ \ No newline at end of file diff --git a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/package-info.java b/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/package-info.java deleted file mode 100644 index 9390bc10203..00000000000 --- a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/package-info.java +++ /dev/null @@ -1,23 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm; - -/** - * Classes for different type of container service client. - */ \ No newline at end of file diff --git a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/storage/ChunkInputStream.java b/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/storage/ChunkInputStream.java deleted file mode 100644 index a483197b0ea..00000000000 --- a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/storage/ChunkInputStream.java +++ /dev/null @@ -1,279 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.storage; - -import org.apache.ratis.shaded.com.google.protobuf.ByteString; -import org.apache.hadoop.fs.Seekable; -import org.apache.hadoop.hdds.scm.XceiverClientManager; -import org.apache.hadoop.hdds.scm.XceiverClientSpi; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ChunkInfo; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ReadChunkResponseProto; -import org.apache.hadoop.hdds.client.BlockID; - -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.List; - -/** - * An {@link InputStream} used by the REST service in combination with the - * SCMClient to read the value of a key from a sequence - * of container chunks. All bytes of the key value are stored in container - * chunks. Each chunk may contain multiple underlying {@link ByteBuffer} - * instances. This class encapsulates all state management for iterating - * through the sequence of chunks and the sequence of buffers within each chunk. - */ -public class ChunkInputStream extends InputStream implements Seekable { - - private static final int EOF = -1; - - private final BlockID blockID; - private final String traceID; - private XceiverClientManager xceiverClientManager; - private XceiverClientSpi xceiverClient; - private List chunks; - private int chunkIndex; - private long[] chunkOffset; - private List buffers; - private int bufferIndex; - - /** - * Creates a new ChunkInputStream. - * - * @param blockID block ID of the chunk - * @param xceiverClientManager client manager that controls client - * @param xceiverClient client to perform container calls - * @param chunks list of chunks to read - * @param traceID container protocol call traceID - */ - public ChunkInputStream( - BlockID blockID, XceiverClientManager xceiverClientManager, - XceiverClientSpi xceiverClient, List chunks, String traceID) { - this.blockID = blockID; - this.traceID = traceID; - this.xceiverClientManager = xceiverClientManager; - this.xceiverClient = xceiverClient; - this.chunks = chunks; - this.chunkIndex = -1; - // chunkOffset[i] stores offset at which chunk i stores data in - // ChunkInputStream - this.chunkOffset = new long[this.chunks.size()]; - initializeChunkOffset(); - this.buffers = null; - this.bufferIndex = 0; - } - - private void initializeChunkOffset() { - int tempOffset = 0; - for (int i = 0; i < chunks.size(); i++) { - chunkOffset[i] = tempOffset; - tempOffset += chunks.get(i).getLen(); - } - } - - @Override - public synchronized int read() - throws IOException { - checkOpen(); - int available = prepareRead(1); - return available == EOF ? EOF : - Byte.toUnsignedInt(buffers.get(bufferIndex).get()); - } - - @Override - public synchronized int read(byte[] b, int off, int len) throws IOException { - // According to the JavaDocs for InputStream, it is recommended that - // subclasses provide an override of bulk read if possible for performance - // reasons. In addition to performance, we need to do it for correctness - // reasons. The Ozone REST service uses PipedInputStream and - // PipedOutputStream to relay HTTP response data between a Jersey thread and - // a Netty thread. It turns out that PipedInputStream/PipedOutputStream - // have a subtle dependency (bug?) on the wrapped stream providing separate - // implementations of single-byte read and bulk read. Without this, get key - // responses might close the connection before writing all of the bytes - // advertised in the Content-Length. - if (b == null) { - throw new NullPointerException(); - } - if (off < 0 || len < 0 || len > b.length - off) { - throw new IndexOutOfBoundsException(); - } - if (len == 0) { - return 0; - } - checkOpen(); - int total = 0; - while (len > 0) { - int available = prepareRead(len); - if (available == EOF) { - return total != 0 ? total : EOF; - } - buffers.get(bufferIndex).get(b, off + total, available); - len -= available; - total += available; - } - return total; - } - - @Override - public synchronized void close() { - if (xceiverClientManager != null && xceiverClient != null) { - xceiverClientManager.releaseClient(xceiverClient); - xceiverClientManager = null; - xceiverClient = null; - } - } - - /** - * Checks if the stream is open. If not, throws an exception. - * - * @throws IOException if stream is closed - */ - private synchronized void checkOpen() throws IOException { - if (xceiverClient == null) { - throw new IOException("ChunkInputStream has been closed."); - } - } - - /** - * Prepares to read by advancing through chunks and buffers as needed until it - * finds data to return or encounters EOF. - * - * @param len desired length of data to read - * @return length of data available to read, possibly less than desired length - */ - private synchronized int prepareRead(int len) throws IOException { - for (;;) { - if (chunks == null || chunks.isEmpty()) { - // This must be an empty key. - return EOF; - } else if (buffers == null) { - // The first read triggers fetching the first chunk. - readChunkFromContainer(); - } else if (!buffers.isEmpty() && - buffers.get(bufferIndex).hasRemaining()) { - // Data is available from the current buffer. - ByteBuffer bb = buffers.get(bufferIndex); - return len > bb.remaining() ? bb.remaining() : len; - } else if (!buffers.isEmpty() && - !buffers.get(bufferIndex).hasRemaining() && - bufferIndex < buffers.size() - 1) { - // There are additional buffers available. - ++bufferIndex; - } else if (chunkIndex < chunks.size() - 1) { - // There are additional chunks available. - readChunkFromContainer(); - } else { - // All available input has been consumed. - return EOF; - } - } - } - - /** - * Attempts to read the chunk at the specified offset in the chunk list. If - * successful, then the data of the read chunk is saved so that its bytes can - * be returned from subsequent read calls. - * - * @throws IOException if there is an I/O error while performing the call - */ - private synchronized void readChunkFromContainer() throws IOException { - // On every chunk read chunkIndex should be increased so as to read the - // next chunk - chunkIndex += 1; - final ReadChunkResponseProto readChunkResponse; - final ChunkInfo chunkInfo = chunks.get(chunkIndex); - try { - readChunkResponse = ContainerProtocolCalls - .readChunk(xceiverClient, chunkInfo, blockID, traceID); - } catch (IOException e) { - throw new IOException("Unexpected OzoneException: " + e.toString(), e); - } - ByteString byteString = readChunkResponse.getData(); - if (byteString.size() != chunkInfo.getLen()) { - // Bytes read from chunk should be equal to chunk size. - throw new IOException(String - .format("Inconsistent read for chunk=%s len=%d bytesRead=%d", - chunkInfo.getChunkName(), chunkInfo.getLen(), byteString.size())); - } - buffers = byteString.asReadOnlyByteBufferList(); - bufferIndex = 0; - } - - @Override - public synchronized void seek(long pos) throws IOException { - if (pos < 0 || (chunks.size() == 0 && pos > 0) - || pos >= chunkOffset[chunks.size() - 1] + chunks.get(chunks.size() - 1) - .getLen()) { - throw new EOFException("EOF encountered pos: " + pos + " container key: " - + blockID.getLocalID()); - } - if (chunkIndex == -1) { - chunkIndex = Arrays.binarySearch(chunkOffset, pos); - } else if (pos < chunkOffset[chunkIndex]) { - chunkIndex = Arrays.binarySearch(chunkOffset, 0, chunkIndex, pos); - } else if (pos >= chunkOffset[chunkIndex] + chunks.get(chunkIndex) - .getLen()) { - chunkIndex = - Arrays.binarySearch(chunkOffset, chunkIndex + 1, chunks.size(), pos); - } - if (chunkIndex < 0) { - // Binary search returns -insertionPoint - 1 if element is not present - // in the array. insertionPoint is the point at which element would be - // inserted in the sorted array. We need to adjust the chunkIndex - // accordingly so that chunkIndex = insertionPoint - 1 - chunkIndex = -chunkIndex -2; - } - // adjust chunkIndex so that readChunkFromContainer reads the correct chunk - chunkIndex -= 1; - readChunkFromContainer(); - adjustBufferIndex(pos); - } - - private void adjustBufferIndex(long pos) { - long tempOffest = chunkOffset[chunkIndex]; - for (int i = 0; i < buffers.size(); i++) { - if (pos - tempOffest >= buffers.get(i).capacity()) { - tempOffest += buffers.get(i).capacity(); - } else { - bufferIndex = i; - break; - } - } - buffers.get(bufferIndex).position((int) (pos - tempOffest)); - } - - @Override - public synchronized long getPos() throws IOException { - return chunkIndex == -1 ? 0 : - chunkOffset[chunkIndex] + buffers.get(bufferIndex).position(); - } - - @Override - public boolean seekToNewSource(long targetPos) throws IOException { - return false; - } - - public BlockID getBlockID() { - return blockID; - } -} diff --git a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/storage/ChunkOutputStream.java b/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/storage/ChunkOutputStream.java deleted file mode 100644 index 10b3bb56700..00000000000 --- a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/storage/ChunkOutputStream.java +++ /dev/null @@ -1,236 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.storage; - -import org.apache.ratis.shaded.com.google.protobuf.ByteString; -import org.apache.commons.codec.digest.DigestUtils; -import org.apache.hadoop.hdds.scm.XceiverClientManager; -import org.apache.hadoop.hdds.scm.XceiverClientSpi; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ChunkInfo; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.BlockData; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.KeyValue; -import org.apache.hadoop.hdds.client.BlockID; - -import java.io.IOException; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.util.UUID; - -import static org.apache.hadoop.hdds.scm.storage.ContainerProtocolCalls - .putBlock; -import static org.apache.hadoop.hdds.scm.storage.ContainerProtocolCalls - .writeChunk; - -/** - * An {@link OutputStream} used by the REST service in combination with the - * SCMClient to write the value of a key to a sequence - * of container chunks. Writes are buffered locally and periodically written to - * the container as a new chunk. In order to preserve the semantics that - * replacement of a pre-existing key is atomic, each instance of the stream has - * an internal unique identifier. This unique identifier and a monotonically - * increasing chunk index form a composite key that is used as the chunk name. - * After all data is written, a putKey call creates or updates the corresponding - * container key, and this call includes the full list of chunks that make up - * the key data. The list of chunks is updated all at once. Therefore, a - * concurrent reader never can see an intermediate state in which different - * chunks of data from different versions of the key data are interleaved. - * This class encapsulates all state management for buffering and writing - * through to the container. - */ -public class ChunkOutputStream extends OutputStream { - - private final BlockID blockID; - private final String key; - private final String traceID; - private final BlockData.Builder containerBlockData; - private XceiverClientManager xceiverClientManager; - private XceiverClientSpi xceiverClient; - private ByteBuffer buffer; - private final String streamId; - private int chunkIndex; - private int chunkSize; - - /** - * Creates a new ChunkOutputStream. - * - * @param blockID block ID - * @param key chunk key - * @param xceiverClientManager client manager that controls client - * @param xceiverClient client to perform container calls - * @param traceID container protocol call args - * @param chunkSize chunk size - */ - public ChunkOutputStream(BlockID blockID, String key, - XceiverClientManager xceiverClientManager, - XceiverClientSpi xceiverClient, String traceID, int chunkSize) { - this.blockID = blockID; - this.key = key; - this.traceID = traceID; - this.chunkSize = chunkSize; - KeyValue keyValue = KeyValue.newBuilder() - .setKey("TYPE").setValue("KEY").build(); - this.containerBlockData = BlockData.newBuilder() - .setBlockID(blockID.getDatanodeBlockIDProtobuf()) - .addMetadata(keyValue); - this.xceiverClientManager = xceiverClientManager; - this.xceiverClient = xceiverClient; - this.buffer = ByteBuffer.allocate(chunkSize); - this.streamId = UUID.randomUUID().toString(); - this.chunkIndex = 0; - } - - public ByteBuffer getBuffer() { - return buffer; - } - - @Override - public void write(int b) throws IOException { - checkOpen(); - int rollbackPosition = buffer.position(); - int rollbackLimit = buffer.limit(); - buffer.put((byte)b); - if (buffer.position() == chunkSize) { - flushBufferToChunk(rollbackPosition, rollbackLimit); - } - } - - @Override - public void write(byte[] b, int off, int len) - throws IOException { - if (b == null) { - throw new NullPointerException(); - } - if ((off < 0) || (off > b.length) || (len < 0) || - ((off + len) > b.length) || ((off + len) < 0)) { - throw new IndexOutOfBoundsException(); - } - if (len == 0) { - return; - } - checkOpen(); - while (len > 0) { - int writeLen = Math.min(chunkSize - buffer.position(), len); - int rollbackPosition = buffer.position(); - int rollbackLimit = buffer.limit(); - buffer.put(b, off, writeLen); - if (buffer.position() == chunkSize) { - flushBufferToChunk(rollbackPosition, rollbackLimit); - } - off += writeLen; - len -= writeLen; - } - } - - @Override - public void flush() throws IOException { - checkOpen(); - if (buffer.position() > 0) { - int rollbackPosition = buffer.position(); - int rollbackLimit = buffer.limit(); - flushBufferToChunk(rollbackPosition, rollbackLimit); - } - } - - @Override - public void close() throws IOException { - if (xceiverClientManager != null && xceiverClient != null - && buffer != null) { - if (buffer.position() > 0) { - writeChunkToContainer(); - } - try { - putBlock(xceiverClient, containerBlockData.build(), traceID); - } catch (IOException e) { - throw new IOException( - "Unexpected Storage Container Exception: " + e.toString(), e); - } finally { - cleanup(); - } - } - } - - public void cleanup() { - xceiverClientManager.releaseClient(xceiverClient); - xceiverClientManager = null; - xceiverClient = null; - buffer = null; - } - - /** - * Checks if the stream is open. If not, throws an exception. - * - * @throws IOException if stream is closed - */ - private void checkOpen() throws IOException { - if (xceiverClient == null) { - throw new IOException("ChunkOutputStream has been closed."); - } - } - - /** - * Attempts to flush buffered writes by writing a new chunk to the container. - * If successful, then clears the buffer to prepare to receive writes for a - * new chunk. - * - * @param rollbackPosition position to restore in buffer if write fails - * @param rollbackLimit limit to restore in buffer if write fails - * @throws IOException if there is an I/O error while performing the call - */ - private void flushBufferToChunk(int rollbackPosition, - int rollbackLimit) throws IOException { - boolean success = false; - try { - writeChunkToContainer(); - success = true; - } finally { - if (success) { - buffer.clear(); - } else { - buffer.position(rollbackPosition); - buffer.limit(rollbackLimit); - } - } - } - - /** - * Writes buffered data as a new chunk to the container and saves chunk - * information to be used later in putKey call. - * - * @throws IOException if there is an I/O error while performing the call - */ - private void writeChunkToContainer() throws IOException { - buffer.flip(); - ByteString data = ByteString.copyFrom(buffer); - ChunkInfo chunk = ChunkInfo - .newBuilder() - .setChunkName( - DigestUtils.md5Hex(key) + "_stream_" - + streamId + "_chunk_" + ++chunkIndex) - .setOffset(0) - .setLen(data.size()) - .build(); - try { - writeChunk(xceiverClient, chunk, blockID, data, traceID); - } catch (IOException e) { - throw new IOException( - "Unexpected Storage Container Exception: " + e.toString(), e); - } - containerBlockData.addChunks(chunk); - } -} diff --git a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/storage/package-info.java b/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/storage/package-info.java deleted file mode 100644 index 6e7ce948784..00000000000 --- a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/storage/package-info.java +++ /dev/null @@ -1,23 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.storage; - -/** - * Low level IO streams to upload/download chunks from container service. - */ \ No newline at end of file diff --git a/hadoop-hdds/common/dev-support/findbugsExcludeFile.xml b/hadoop-hdds/common/dev-support/findbugsExcludeFile.xml deleted file mode 100644 index c7db6794cc0..00000000000 --- a/hadoop-hdds/common/dev-support/findbugsExcludeFile.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - diff --git a/hadoop-hdds/common/pom.xml b/hadoop-hdds/common/pom.xml deleted file mode 100644 index 64ebe9bd91d..00000000000 --- a/hadoop-hdds/common/pom.xml +++ /dev/null @@ -1,250 +0,0 @@ - - - - 4.0.0 - - org.apache.hadoop - hadoop-hdds - 0.3.0-SNAPSHOT - - hadoop-hdds-common - 0.3.0-SNAPSHOT - Apache Hadoop Distributed Data Store Common - Apache Hadoop HDDS Common - jar - - - 0.3.0-SNAPSHOT - 2.11.0 - 3.4.2 - ${hdds.version} - - - - - org.fusesource.leveldbjni - leveldbjni-all - - - - ratis-server - org.apache.ratis - - - org.slf4j - slf4j-log4j12 - - - io.dropwizard.metrics - metrics-core - - - - - ratis-netty - org.apache.ratis - - - ratis-grpc - org.apache.ratis - - - com.google.errorprone - error_prone_annotations - 2.2.0 - true - - - - org.rocksdb - rocksdbjni - 5.14.2 - - - - org.apache.hadoop - hadoop-common - test - test-jar - - - - org.apache.logging.log4j - log4j-api - ${log4j2.version} - - - org.apache.logging.log4j - log4j-core - ${log4j2.version} - - - com.lmax - disruptor - ${disruptor.version} - - - org.apache.commons - commons-pool2 - 2.6.0 - - - - - - - - ${basedir}/src/main/resources - - hdds-version-info.properties - - false - - - ${basedir}/src/main/resources - - hdds-version-info.properties - - true - - - - - kr.motd.maven - os-maven-plugin - ${os-maven-plugin.version} - - - - - org.xolstice.maven.plugins - protobuf-maven-plugin - ${protobuf-maven-plugin.version} - true - - - com.google.protobuf:protoc:${protobuf-compile.version}:exe:${os.detected.classifier} - - ${basedir}/src/main/proto/ - - DatanodeContainerProtocol.proto - - target/generated-sources/java - false - - - - compile-protoc - - compile - test-compile - compile-custom - test-compile-custom - - - grpc-java - - io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier} - - - - - - - maven-antrun-plugin - - - generate-sources - - - - - - - - - - run - - - - - - org.apache.hadoop - hadoop-maven-plugins - - - version-info - generate-resources - - version-info - - - - ${basedir}/../ - - */src/main/java/**/*.java - */src/main/proto/*.proto - - - - - - compile-protoc - - protoc - - - ${protobuf.version} - ${protoc.path} - - - ${basedir}/../../hadoop-common-project/hadoop-common/src/main/proto - - - ${basedir}/../../hadoop-hdfs-project/hadoop-hdfs-client/src/main/proto/ - - - ${basedir}/../../hadoop-hdfs-project/hadoop-hdfs/src/main/proto/ - - ${basedir}/src/main/proto - - - ${basedir}/src/main/proto - - StorageContainerLocationProtocol.proto - hdds.proto - ScmBlockLocationProtocol.proto - - - - - - - - org.codehaus.mojo - findbugs-maven-plugin - - ${basedir}/dev-support/findbugsExcludeFile.xml - - - - - diff --git a/hadoop-hdds/common/src/main/conf/log4j.properties b/hadoop-hdds/common/src/main/conf/log4j.properties deleted file mode 100644 index 663e2548ce5..00000000000 --- a/hadoop-hdds/common/src/main/conf/log4j.properties +++ /dev/null @@ -1,157 +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 -# -# 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. - -# Define some default values that can be overridden by system properties -hadoop.root.logger=INFO,console -hadoop.log.dir=. -hadoop.log.file=hadoop.log - -# Define the root logger to the system property "hadoop.root.logger". -log4j.rootLogger=${hadoop.root.logger}, EventCounter - -# Logging Threshold -log4j.threshold=ALL - -# Null Appender -log4j.appender.NullAppender=org.apache.log4j.varia.NullAppender - -# -# Rolling File Appender - cap space usage at 5gb. -# -hadoop.log.maxfilesize=256MB -hadoop.log.maxbackupindex=20 -log4j.appender.RFA=org.apache.log4j.RollingFileAppender -log4j.appender.RFA.File=${hadoop.log.dir}/${hadoop.log.file} - -log4j.appender.RFA.MaxFileSize=${hadoop.log.maxfilesize} -log4j.appender.RFA.MaxBackupIndex=${hadoop.log.maxbackupindex} - -log4j.appender.RFA.layout=org.apache.log4j.PatternLayout - -# Pattern format: Date LogLevel LoggerName LogMessage -log4j.appender.RFA.layout.ConversionPattern=%d{ISO8601} %p %c: %m%n -# Debugging Pattern format -#log4j.appender.RFA.layout.ConversionPattern=%d{ISO8601} %-5p %c{2} (%F:%M(%L)) - %m%n - - -# -# Daily Rolling File Appender -# - -log4j.appender.DRFA=org.apache.log4j.DailyRollingFileAppender -log4j.appender.DRFA.File=${hadoop.log.dir}/${hadoop.log.file} - -# Rollover at midnight -log4j.appender.DRFA.DatePattern=.yyyy-MM-dd - -log4j.appender.DRFA.layout=org.apache.log4j.PatternLayout - -# Pattern format: Date LogLevel LoggerName LogMessage -log4j.appender.DRFA.layout.ConversionPattern=%d{ISO8601} %p %c: %m%n -# Debugging Pattern format -#log4j.appender.DRFA.layout.ConversionPattern=%d{ISO8601} %-5p %c{2} (%F:%M(%L)) - %m%n - - -# -# console -# Add "console" to rootlogger above if you want to use this -# - -log4j.appender.console=org.apache.log4j.ConsoleAppender -log4j.appender.console.target=System.err -log4j.appender.console.layout=org.apache.log4j.PatternLayout -log4j.appender.console.layout.ConversionPattern=%d{ISO8601} %p %c{2}: %m%n - -# -# TaskLog Appender -# -log4j.appender.TLA=org.apache.hadoop.mapred.TaskLogAppender - -log4j.appender.TLA.layout=org.apache.log4j.PatternLayout -log4j.appender.TLA.layout.ConversionPattern=%d{ISO8601} %p %c: %m%n - -# -# HDFS block state change log from block manager -# -# Uncomment the following to log normal block state change -# messages from BlockManager in NameNode. -#log4j.logger.BlockStateChange=DEBUG - -# -#Security appender -# -hadoop.security.logger=INFO,NullAppender -hadoop.security.log.maxfilesize=256MB -hadoop.security.log.maxbackupindex=20 -log4j.category.SecurityLogger=${hadoop.security.logger} -hadoop.security.log.file=SecurityAuth-${user.name}.audit -log4j.appender.RFAS=org.apache.log4j.RollingFileAppender -log4j.appender.RFAS.File=${hadoop.log.dir}/${hadoop.security.log.file} -log4j.appender.RFAS.layout=org.apache.log4j.PatternLayout -log4j.appender.RFAS.layout.ConversionPattern=%d{ISO8601} %p %c: %m%n -log4j.appender.RFAS.MaxFileSize=${hadoop.security.log.maxfilesize} -log4j.appender.RFAS.MaxBackupIndex=${hadoop.security.log.maxbackupindex} - -# -# Daily Rolling Security appender -# -log4j.appender.DRFAS=org.apache.log4j.DailyRollingFileAppender -log4j.appender.DRFAS.File=${hadoop.log.dir}/${hadoop.security.log.file} -log4j.appender.DRFAS.layout=org.apache.log4j.PatternLayout -log4j.appender.DRFAS.layout.ConversionPattern=%d{ISO8601} %p %c: %m%n -log4j.appender.DRFAS.DatePattern=.yyyy-MM-dd - - -# Custom Logging levels -# AWS SDK & S3A FileSystem -#log4j.logger.com.amazonaws=ERROR -log4j.logger.com.amazonaws.http.AmazonHttpClient=ERROR -#log4j.logger.org.apache.hadoop.fs.s3a.S3AFileSystem=WARN - -# -# Event Counter Appender -# Sends counts of logging messages at different severity levels to Hadoop Metrics. -# -log4j.appender.EventCounter=org.apache.hadoop.log.metrics.EventCounter - - -log4j.logger.org.apache.hadoop.ozone=DEBUG,OZONE,FILE - -# Do not log into datanode logs. Remove this line to have single log. -log4j.additivity.org.apache.hadoop.ozone=false - -# For development purposes, log both to console and log file. -log4j.appender.OZONE=org.apache.log4j.ConsoleAppender -log4j.appender.OZONE.Threshold=info -log4j.appender.OZONE.layout=org.apache.log4j.PatternLayout -log4j.appender.OZONE.layout.ConversionPattern=%d{ISO8601} [%t] %-5p \ - %X{component} %X{function} %X{resource} %X{user} %X{request} - %m%n - -# Real ozone logger that writes to ozone.log -log4j.appender.FILE=org.apache.log4j.DailyRollingFileAppender -log4j.appender.FILE.File=${hadoop.log.dir}/ozone.log -log4j.appender.FILE.Threshold=debug -log4j.appender.FILE.layout=org.apache.log4j.PatternLayout -log4j.appender.FILE.layout.ConversionPattern=%d{ISO8601} [%t] %-5p \ -(%F:%L) %X{function} %X{resource} %X{user} %X{request} - \ -%m%n - -# Log levels of third-party libraries -log4j.logger.org.apache.commons.beanutils=WARN - -log4j.logger.org.apache.hadoop.util.NativeCodeLoader=ERROR -log4j.logger.org.apache.ratis.conf.ConfUtils=WARN -log4j.logger.org.apache.hadoop.security.ShellBasedUnixGroupsMapping=ERROR diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsConfigKeys.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsConfigKeys.java deleted file mode 100644 index 856d1136fac..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsConfigKeys.java +++ /dev/null @@ -1,97 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds; - -import org.apache.hadoop.utils.db.DBProfile; - -/** - * This class contains constants for configuration keys and default values - * used in hdds. - */ -public final class HddsConfigKeys { - - /** - * Do not instantiate. - */ - private HddsConfigKeys() { - } - - public static final String HDDS_HEARTBEAT_INTERVAL = - "hdds.heartbeat.interval"; - public static final String HDDS_HEARTBEAT_INTERVAL_DEFAULT = - "30s"; - - public static final String HDDS_NODE_REPORT_INTERVAL = - "hdds.node.report.interval"; - public static final String HDDS_NODE_REPORT_INTERVAL_DEFAULT = - "60s"; - - public static final String HDDS_CONTAINER_REPORT_INTERVAL = - "hdds.container.report.interval"; - public static final String HDDS_CONTAINER_REPORT_INTERVAL_DEFAULT = - "60s"; - - public static final String HDDS_PIPELINE_REPORT_INTERVAL = - "hdds.pipeline.report.interval"; - public static final String HDDS_PIPELINE_REPORT_INTERVAL_DEFAULT = - "60s"; - - public static final String HDDS_COMMAND_STATUS_REPORT_INTERVAL = - "hdds.command.status.report.interval"; - public static final String HDDS_COMMAND_STATUS_REPORT_INTERVAL_DEFAULT = - "60s"; - - public static final String HDDS_CONTAINER_ACTION_MAX_LIMIT = - "hdds.container.action.max.limit"; - public static final int HDDS_CONTAINER_ACTION_MAX_LIMIT_DEFAULT = - 20; - - public static final String HDDS_PIPELINE_ACTION_MAX_LIMIT = - "hdds.pipeline.action.max.limit"; - public static final int HDDS_PIPELINE_ACTION_MAX_LIMIT_DEFAULT = - 20; - - // Configuration to allow volume choosing policy. - public static final String HDDS_DATANODE_VOLUME_CHOOSING_POLICY = - "hdds.datanode.volume.choosing.policy"; - - // DB Profiles used by ROCKDB instances. - public static final String HDDS_DB_PROFILE = "hdds.db.profile"; - public static final DBProfile HDDS_DEFAULT_DB_PROFILE = DBProfile.SSD; - - // Once a container usage crosses this threshold, it is eligible for - // closing. - public static final String HDDS_CONTAINER_CLOSE_THRESHOLD = - "hdds.container.close.threshold"; - public static final float HDDS_CONTAINER_CLOSE_THRESHOLD_DEFAULT = 0.9f; - - public static final String HDDS_SCM_CHILLMODE_ENABLED = - "hdds.scm.chillmode.enabled"; - public static final boolean HDDS_SCM_CHILLMODE_ENABLED_DEFAULT = true; - - // % of containers which should have at least one reported replica - // before SCM comes out of chill mode. - public static final String HDDS_SCM_CHILLMODE_THRESHOLD_PCT = - "hdds.scm.chillmode.threshold.pct"; - public static final double HDDS_SCM_CHILLMODE_THRESHOLD_PCT_DEFAULT = 0.99; - - public static final String HDDS_LOCK_MAX_CONCURRENCY = - "hdds.lock.max.concurrency"; - public static final int HDDS_LOCK_MAX_CONCURRENCY_DEFAULT = 100; - -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsIdFactory.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsIdFactory.java deleted file mode 100644 index b244b8cf75d..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsIdFactory.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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds; - -import java.util.UUID; -import java.util.concurrent.atomic.AtomicLong; - -/** - * HDDS Id generator. - */ -public final class HddsIdFactory { - private HddsIdFactory() { - } - - private static final AtomicLong LONG_COUNTER = new AtomicLong( - System.currentTimeMillis()); - - /** - * Returns an incrementing long. This class doesn't - * persist initial value for long Id's, so incremental id's after restart - * may collide with previously generated Id's. - * - * @return long - */ - public static long getLongId() { - return LONG_COUNTER.incrementAndGet(); - } - - /** - * Returns a uuid. - * - * @return UUID. - */ - public static UUID getUUId() { - return UUID.randomUUID(); - } - -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsUtils.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsUtils.java deleted file mode 100644 index db9d374203c..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsUtils.java +++ /dev/null @@ -1,351 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds; - -import com.google.common.base.Optional; -import com.google.common.base.Strings; -import com.google.common.net.HostAndPort; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.CommonConfigurationKeys; -import org.apache.hadoop.fs.CommonConfigurationKeysPublic; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdds.scm.ScmConfigKeys; -import org.apache.hadoop.net.DNS; -import org.apache.hadoop.net.NetUtils; -import org.apache.hadoop.ozone.OzoneConfigKeys; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.net.InetSocketAddress; -import java.net.UnknownHostException; -import java.nio.file.Paths; -import java.util.Collection; -import java.util.HashSet; - -import static org.apache.hadoop.hdfs.DFSConfigKeys - .DFS_DATANODE_DNS_INTERFACE_KEY; -import static org.apache.hadoop.hdfs.DFSConfigKeys - .DFS_DATANODE_DNS_NAMESERVER_KEY; -import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_DATANODE_HOST_NAME_KEY; -import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ENABLED; -import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ENABLED_DEFAULT; - -/** - * HDDS specific stateless utility functions. - */ -public final class HddsUtils { - - - private static final Logger LOG = LoggerFactory.getLogger(HddsUtils.class); - - /** - * The service ID of the solitary Ozone SCM service. - */ - public static final String OZONE_SCM_SERVICE_ID = "OzoneScmService"; - public static final String OZONE_SCM_SERVICE_INSTANCE_ID = - "OzoneScmServiceInstance"; - - private static final int NO_PORT = -1; - - private HddsUtils() { - } - - /** - * Retrieve the socket address that should be used by clients to connect - * to the SCM. - * - * @param conf - * @return Target InetSocketAddress for the SCM client endpoint. - */ - public static InetSocketAddress getScmAddressForClients(Configuration conf) { - final Optional host = getHostNameFromConfigKeys(conf, - ScmConfigKeys.OZONE_SCM_CLIENT_ADDRESS_KEY); - - if (!host.isPresent()) { - throw new IllegalArgumentException( - ScmConfigKeys.OZONE_SCM_CLIENT_ADDRESS_KEY + " must be defined. See" - + " https://wiki.apache.org/hadoop/Ozone#Configuration for " - + "details" - + " on configuring Ozone."); - } - - final Optional port = getPortNumberFromConfigKeys(conf, - ScmConfigKeys.OZONE_SCM_CLIENT_ADDRESS_KEY); - - return NetUtils.createSocketAddr(host.get() + ":" + port - .or(ScmConfigKeys.OZONE_SCM_CLIENT_PORT_DEFAULT)); - } - - /** - * Retrieve the socket address that should be used by clients to connect - * to the SCM for block service. If - * {@link ScmConfigKeys#OZONE_SCM_BLOCK_CLIENT_ADDRESS_KEY} is not defined - * then {@link ScmConfigKeys#OZONE_SCM_CLIENT_ADDRESS_KEY} is used. - * - * @param conf - * @return Target InetSocketAddress for the SCM block client endpoint. - * @throws IllegalArgumentException if configuration is not defined. - */ - public static InetSocketAddress getScmAddressForBlockClients( - Configuration conf) { - Optional host = getHostNameFromConfigKeys(conf, - ScmConfigKeys.OZONE_SCM_BLOCK_CLIENT_ADDRESS_KEY); - - if (!host.isPresent()) { - host = getHostNameFromConfigKeys(conf, - ScmConfigKeys.OZONE_SCM_CLIENT_ADDRESS_KEY); - if (!host.isPresent()) { - throw new IllegalArgumentException( - ScmConfigKeys.OZONE_SCM_BLOCK_CLIENT_ADDRESS_KEY - + " must be defined. See" - + " https://wiki.apache.org/hadoop/Ozone#Configuration" - + " for details on configuring Ozone."); - } - } - - final Optional port = getPortNumberFromConfigKeys(conf, - ScmConfigKeys.OZONE_SCM_BLOCK_CLIENT_ADDRESS_KEY); - - return NetUtils.createSocketAddr(host.get() + ":" + port - .or(ScmConfigKeys.OZONE_SCM_BLOCK_CLIENT_PORT_DEFAULT)); - } - - /** - * Retrieve the hostname, trying the supplied config keys in order. - * Each config value may be absent, or if present in the format - * host:port (the :port part is optional). - * - * @param conf - Conf - * @param keys a list of configuration key names. - * - * @return first hostname component found from the given keys, or absent. - * @throws IllegalArgumentException if any values are not in the 'host' - * or host:port format. - */ - public static Optional getHostNameFromConfigKeys(Configuration conf, - String... keys) { - for (final String key : keys) { - final String value = conf.getTrimmed(key); - final Optional hostName = getHostName(value); - if (hostName.isPresent()) { - return hostName; - } - } - return Optional.absent(); - } - - /** - * Gets the hostname or Indicates that it is absent. - * @param value host or host:port - * @return hostname - */ - public static Optional getHostName(String value) { - if ((value == null) || value.isEmpty()) { - return Optional.absent(); - } - return Optional.of(HostAndPort.fromString(value).getHostText()); - } - - /** - * Gets the port if there is one, throws otherwise. - * @param value String in host:port format. - * @return Port - */ - public static Optional getHostPort(String value) { - if ((value == null) || value.isEmpty()) { - return Optional.absent(); - } - int port = HostAndPort.fromString(value).getPortOrDefault(NO_PORT); - if (port == NO_PORT) { - return Optional.absent(); - } else { - return Optional.of(port); - } - } - - /** - * Retrieve the port number, trying the supplied config keys in order. - * Each config value may be absent, or if present in the format - * host:port (the :port part is optional). - * - * @param conf Conf - * @param keys a list of configuration key names. - * - * @return first port number component found from the given keys, or absent. - * @throws IllegalArgumentException if any values are not in the 'host' - * or host:port format. - */ - public static Optional getPortNumberFromConfigKeys( - Configuration conf, String... keys) { - for (final String key : keys) { - final String value = conf.getTrimmed(key); - final Optional hostPort = getHostPort(value); - if (hostPort.isPresent()) { - return hostPort; - } - } - return Optional.absent(); - } - - /** - * Retrieve the socket addresses of all storage container managers. - * - * @param conf - * @return A collection of SCM addresses - * @throws IllegalArgumentException If the configuration is invalid - */ - public static Collection getSCMAddresses( - Configuration conf) throws IllegalArgumentException { - Collection addresses = - new HashSet(); - Collection names = - conf.getTrimmedStringCollection(ScmConfigKeys.OZONE_SCM_NAMES); - if (names == null || names.isEmpty()) { - throw new IllegalArgumentException(ScmConfigKeys.OZONE_SCM_NAMES - + " need to be a set of valid DNS names or IP addresses." - + " Null or empty address list found."); - } - - final com.google.common.base.Optional - defaultPort = com.google.common.base.Optional.of(ScmConfigKeys - .OZONE_SCM_DEFAULT_PORT); - for (String address : names) { - com.google.common.base.Optional hostname = - getHostName(address); - if (!hostname.isPresent()) { - throw new IllegalArgumentException("Invalid hostname for SCM: " - + hostname); - } - com.google.common.base.Optional port = - getHostPort(address); - InetSocketAddress addr = NetUtils.createSocketAddr(hostname.get(), - port.or(defaultPort.get())); - addresses.add(addr); - } - return addresses; - } - - public static boolean isHddsEnabled(Configuration conf) { - String securityEnabled = - conf.get(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION, - "simple"); - boolean securityAuthorizationEnabled = conf.getBoolean( - CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHORIZATION, false); - - if (securityEnabled.equals("kerberos") || securityAuthorizationEnabled) { - LOG.error("Ozone is not supported in a security enabled cluster. "); - return false; - } else { - return conf.getBoolean(OZONE_ENABLED, OZONE_ENABLED_DEFAULT); - } - } - - - /** - * Get the path for datanode id file. - * - * @param conf - Configuration - * @return the path of datanode id as string - */ - public static String getDatanodeIdFilePath(Configuration conf) { - String dataNodeIDPath = conf.get(ScmConfigKeys.OZONE_SCM_DATANODE_ID); - if (dataNodeIDPath == null) { - String metaPath = conf.get(OzoneConfigKeys.OZONE_METADATA_DIRS); - if (Strings.isNullOrEmpty(metaPath)) { - // this means meta data is not found, in theory should not happen at - // this point because should've failed earlier. - throw new IllegalArgumentException("Unable to locate meta data" + - "directory when getting datanode id path"); - } - dataNodeIDPath = Paths.get(metaPath, - ScmConfigKeys.OZONE_SCM_DATANODE_ID_PATH_DEFAULT).toString(); - } - return dataNodeIDPath; - } - - /** - * Returns the hostname for this datanode. If the hostname is not - * explicitly configured in the given config, then it is determined - * via the DNS class. - * - * @param conf Configuration - * - * @return the hostname (NB: may not be a FQDN) - * @throws UnknownHostException if the dfs.datanode.dns.interface - * option is used and the hostname can not be determined - */ - public static String getHostName(Configuration conf) - throws UnknownHostException { - String name = conf.get(DFS_DATANODE_HOST_NAME_KEY); - if (name == null) { - String dnsInterface = conf.get( - CommonConfigurationKeys.HADOOP_SECURITY_DNS_INTERFACE_KEY); - String nameServer = conf.get( - CommonConfigurationKeys.HADOOP_SECURITY_DNS_NAMESERVER_KEY); - boolean fallbackToHosts = false; - - if (dnsInterface == null) { - // Try the legacy configuration keys. - dnsInterface = conf.get(DFS_DATANODE_DNS_INTERFACE_KEY); - nameServer = conf.get(DFS_DATANODE_DNS_NAMESERVER_KEY); - } else { - // If HADOOP_SECURITY_DNS_* is set then also attempt hosts file - // resolution if DNS fails. We will not use hosts file resolution - // by default to avoid breaking existing clusters. - fallbackToHosts = true; - } - - name = DNS.getDefaultHost(dnsInterface, nameServer, fallbackToHosts); - } - return name; - } - - /** - * Checks if the container command is read only or not. - * @param proto ContainerCommand Request proto - * @return True if its readOnly , false otherwise. - */ - public static boolean isReadOnly( - ContainerProtos.ContainerCommandRequestProto proto) { - switch (proto.getCmdType()) { - case ReadContainer: - case ReadChunk: - case ListBlock: - case GetBlock: - case GetSmallFile: - case ListContainer: - case ListChunk: - case GetCommittedBlockLength: - return true; - case CloseContainer: - case WriteChunk: - case UpdateContainer: - case CompactChunk: - case CreateContainer: - case DeleteChunk: - case DeleteContainer: - case DeleteBlock: - case PutBlock: - case PutSmallFile: - default: - return false; - } - } - -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/GenericCli.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/GenericCli.java deleted file mode 100644 index e0c8150f447..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/GenericCli.java +++ /dev/null @@ -1,100 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.cli; - -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.Callable; - -import org.apache.hadoop.hdds.conf.OzoneConfiguration; - -import com.google.common.annotations.VisibleForTesting; -import picocli.CommandLine; -import picocli.CommandLine.ExecutionException; -import picocli.CommandLine.Option; -import picocli.CommandLine.RunLast; - -/** - * This is a generic parent class for all the ozone related cli tools. - */ -public class GenericCli implements Callable, GenericParentCommand { - - @Option(names = {"--verbose"}, - description = "More verbose output. Show the stack trace of the errors.") - private boolean verbose; - - @Option(names = {"-D", "--set"}) - private Map configurationOverrides = new HashMap<>(); - - private final CommandLine cmd; - - public GenericCli() { - cmd = new CommandLine(this); - } - - public void run(String[] argv) { - try { - execute(argv); - } catch (ExecutionException ex) { - printError(ex.getCause()); - System.exit(-1); - } - } - - @VisibleForTesting - public void execute(String[] argv) { - cmd.parseWithHandler(new RunLast(), argv); - } - - private void printError(Throwable error) { - if (verbose) { - error.printStackTrace(System.err); - } else { - System.err.println(error.getMessage().split("\n")[0]); - } - if(error instanceof MissingSubcommandException){ - System.err.println(((MissingSubcommandException) error).getUsage()); - } - } - - @Override - public Void call() throws Exception { - throw new MissingSubcommandException(cmd.getUsageMessage()); - } - - public OzoneConfiguration createOzoneConfiguration() { - OzoneConfiguration ozoneConf = new OzoneConfiguration(); - if (configurationOverrides != null) { - for (Entry entry : configurationOverrides.entrySet()) { - ozoneConf - .set(entry.getKey(), entry.getValue()); - } - } - return ozoneConf; - } - - @VisibleForTesting - public picocli.CommandLine getCmd() { - return cmd; - } - - @Override - public boolean isVerbose() { - return verbose; - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/GenericParentCommand.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/GenericParentCommand.java deleted file mode 100644 index a1d21715e77..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/GenericParentCommand.java +++ /dev/null @@ -1,25 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.cli; - -/** - * Interface to access the higher level parameters. - */ -public interface GenericParentCommand { - - boolean isVerbose(); -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/HddsVersionProvider.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/HddsVersionProvider.java deleted file mode 100644 index 7110839546f..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/HddsVersionProvider.java +++ /dev/null @@ -1,35 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.cli; - -import org.apache.hadoop.utils.HddsVersionInfo; - -import picocli.CommandLine.IVersionProvider; - -/** - * Version provider for the CLI interface. - */ -public class HddsVersionProvider implements IVersionProvider { - @Override - public String[] getVersion() throws Exception { - String[] result = new String[] { - HddsVersionInfo.getBuildVersion() - }; - return result; - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/MissingSubcommandException.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/MissingSubcommandException.java deleted file mode 100644 index 9f0c4943246..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/MissingSubcommandException.java +++ /dev/null @@ -1,35 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.cli; - -/** - * Exception to throw if subcommand is not selected but required. - */ -public class MissingSubcommandException extends RuntimeException { - - private String usage; - - public MissingSubcommandException(String usage) { - super("Incomplete command"); - this.usage = usage; - } - - public String getUsage() { - return usage; - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/package-info.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/package-info.java deleted file mode 100644 index 8dcc1d1a3c9..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/package-info.java +++ /dev/null @@ -1,22 +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 - * - * 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. - */ - -/** - * Generic helper class to make instantiate picocli based cli tools. - */ -package org.apache.hadoop.hdds.cli; \ No newline at end of file diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/client/BlockID.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/client/BlockID.java deleted file mode 100644 index 81497406d6b..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/client/BlockID.java +++ /dev/null @@ -1,90 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.client; - -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; - -import java.util.Objects; - -/** - * BlockID of ozone (containerID localID). - */ -public class BlockID { - private long containerID; - private long localID; - - public BlockID(long containerID, long localID) { - this.containerID = containerID; - this.localID = localID; - } - - public long getContainerID() { - return containerID; - } - - public long getLocalID() { - return localID; - } - - @Override - public String toString() { - return new ToStringBuilder(this). - append("containerID", containerID). - append("localID", localID). - toString(); - } - - public HddsProtos.BlockID getProtobuf() { - return HddsProtos.BlockID.newBuilder(). - setContainerID(containerID).setLocalID(localID).build(); - } - - public static BlockID getFromProtobuf(HddsProtos.BlockID blockID) { - return new BlockID(blockID.getContainerID(), - blockID.getLocalID()); - } - - public ContainerProtos.DatanodeBlockID getDatanodeBlockIDProtobuf() { - return ContainerProtos.DatanodeBlockID.newBuilder(). - setContainerID(containerID).setLocalID(localID).build(); - } - - public static BlockID getFromProtobuf( - ContainerProtos.DatanodeBlockID blockID) { - return new BlockID(blockID.getContainerID(), - blockID.getLocalID()); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - BlockID blockID = (BlockID) o; - return containerID == blockID.containerID && localID == blockID.localID; - } - - @Override - public int hashCode() { - return Objects.hash(containerID, localID); - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/client/OzoneQuota.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/client/OzoneQuota.java deleted file mode 100644 index 59708a956b9..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/client/OzoneQuota.java +++ /dev/null @@ -1,203 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.client; - -import org.apache.hadoop.ozone.OzoneConsts; - - -/** - * represents an OzoneQuota Object that can be applied to - * a storage volume. - */ -public class OzoneQuota { - - public static final String OZONE_QUOTA_BYTES = "BYTES"; - public static final String OZONE_QUOTA_MB = "MB"; - public static final String OZONE_QUOTA_GB = "GB"; - public static final String OZONE_QUOTA_TB = "TB"; - - private Units unit; - private long size; - - /** Quota Units.*/ - public enum Units {UNDEFINED, BYTES, KB, MB, GB, TB} - - /** - * Returns size. - * - * @return long - */ - public long getSize() { - return size; - } - - /** - * Returns Units. - * - * @return Unit in MB, GB or TB - */ - public Units getUnit() { - return unit; - } - - /** - * Constructs a default Quota object. - */ - public OzoneQuota() { - this.size = 0; - this.unit = Units.UNDEFINED; - } - - /** - * Constructor for Ozone Quota. - * - * @param size Long Size - * @param unit MB, GB or TB - */ - public OzoneQuota(long size, Units unit) { - this.size = size; - this.unit = unit; - } - - /** - * Formats a quota as a string. - * - * @param quota the quota to format - * @return string representation of quota - */ - public static String formatQuota(OzoneQuota quota) { - return String.valueOf(quota.size) + quota.unit; - } - - /** - * Parses a user provided string and returns the - * Quota Object. - * - * @param quotaString Quota String - * - * @return OzoneQuota object - * - * @throws IllegalArgumentException - */ - public static OzoneQuota parseQuota(String quotaString) - throws IllegalArgumentException { - - if ((quotaString == null) || (quotaString.isEmpty())) { - throw new IllegalArgumentException( - "Quota string cannot be null or empty."); - } - - String uppercase = quotaString.toUpperCase().replaceAll("\\s+", ""); - String size = ""; - int nSize; - Units currUnit = Units.MB; - Boolean found = false; - if (uppercase.endsWith(OZONE_QUOTA_MB)) { - size = uppercase - .substring(0, uppercase.length() - OZONE_QUOTA_MB.length()); - currUnit = Units.MB; - found = true; - } - - if (uppercase.endsWith(OZONE_QUOTA_GB)) { - size = uppercase - .substring(0, uppercase.length() - OZONE_QUOTA_GB.length()); - currUnit = Units.GB; - found = true; - } - - if (uppercase.endsWith(OZONE_QUOTA_TB)) { - size = uppercase - .substring(0, uppercase.length() - OZONE_QUOTA_TB.length()); - currUnit = Units.TB; - found = true; - } - - if (uppercase.endsWith(OZONE_QUOTA_BYTES)) { - size = uppercase - .substring(0, uppercase.length() - OZONE_QUOTA_BYTES.length()); - currUnit = Units.BYTES; - found = true; - } - - if (!found) { - throw new IllegalArgumentException( - "Quota unit not recognized. Supported values are BYTES, MB, GB and " + - "TB."); - } - - nSize = Integer.parseInt(size); - if (nSize < 0) { - throw new IllegalArgumentException("Quota cannot be negative."); - } - - return new OzoneQuota(nSize, currUnit); - } - - - /** - * Returns size in Bytes or -1 if there is no Quota. - */ - public long sizeInBytes() { - switch (this.unit) { - case BYTES: - return this.getSize(); - case MB: - return this.getSize() * OzoneConsts.MB; - case GB: - return this.getSize() * OzoneConsts.GB; - case TB: - return this.getSize() * OzoneConsts.TB; - case UNDEFINED: - default: - return -1; - } - } - - /** - * Returns OzoneQuota corresponding to size in bytes. - * - * @param sizeInBytes size in bytes to be converted - * - * @return OzoneQuota object - */ - public static OzoneQuota getOzoneQuota(long sizeInBytes) { - long size; - Units unit; - if (sizeInBytes % OzoneConsts.TB == 0) { - size = sizeInBytes / OzoneConsts.TB; - unit = Units.TB; - } else if (sizeInBytes % OzoneConsts.GB == 0) { - size = sizeInBytes / OzoneConsts.GB; - unit = Units.GB; - } else if (sizeInBytes % OzoneConsts.MB == 0) { - size = sizeInBytes / OzoneConsts.MB; - unit = Units.MB; - } else { - size = sizeInBytes; - unit = Units.BYTES; - } - return new OzoneQuota((int)size, unit); - } - - @Override - public String toString() { - return size + " " + unit; - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/client/ReplicationFactor.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/client/ReplicationFactor.java deleted file mode 100644 index 0215964ab8e..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/client/ReplicationFactor.java +++ /dev/null @@ -1,63 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.client; - -/** - * The replication factor to be used while writing key into ozone. - */ -public enum ReplicationFactor { - ONE(1), - THREE(3); - - /** - * Integer representation of replication. - */ - private int value; - - /** - * Initializes ReplicationFactor with value. - * @param value replication value - */ - ReplicationFactor(int value) { - this.value = value; - } - - /** - * Returns enum value corresponding to the int value. - * @param value replication value - * @return ReplicationFactor - */ - public static ReplicationFactor valueOf(int value) { - if(value == 1) { - return ONE; - } - if (value == 3) { - return THREE; - } - throw new IllegalArgumentException("Unsupported value: " + value); - } - - /** - * Returns integer representation of ReplicationFactor. - * @return replication value - */ - public int getValue() { - return value; - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/client/ReplicationType.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/client/ReplicationType.java deleted file mode 100644 index 259a1a29317..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/client/ReplicationType.java +++ /dev/null @@ -1,28 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.client; - -/** - * The replication type to be used while writing key into ozone. - */ -public enum ReplicationType { - RATIS, - STAND_ALONE, - CHAINED -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/client/package-info.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/client/package-info.java deleted file mode 100644 index e81f134b259..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/client/package-info.java +++ /dev/null @@ -1,23 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.client; - -/** - * Base property types for HDDS containers and replications. - */ \ No newline at end of file diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/conf/HddsConfServlet.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/conf/HddsConfServlet.java deleted file mode 100644 index 677b752bd9c..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/conf/HddsConfServlet.java +++ /dev/null @@ -1,185 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.conf; - -import com.google.gson.Gson; -import java.io.IOException; -import java.io.Writer; - -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.ws.rs.core.HttpHeaders; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.classification.InterfaceStability; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.http.HttpServer2; - -import com.google.common.annotations.VisibleForTesting; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_TAGS_SYSTEM_KEY; - -/** - * A servlet to print out the running configuration data. - */ -@InterfaceAudience.LimitedPrivate({"HDFS", "MapReduce"}) -@InterfaceStability.Unstable -public class HddsConfServlet extends HttpServlet { - - private static final long serialVersionUID = 1L; - - protected static final String FORMAT_JSON = "json"; - protected static final String FORMAT_XML = "xml"; - private static final String COMMAND = "cmd"; - private static final OzoneConfiguration OZONE_CONFIG = - new OzoneConfiguration(); - private static final transient Logger LOG = - LoggerFactory.getLogger(HddsConfServlet.class); - - - /** - * Return the Configuration of the daemon hosting this servlet. - * This is populated when the HttpServer starts. - */ - private Configuration getConfFromContext() { - Configuration conf = (Configuration) getServletContext().getAttribute( - HttpServer2.CONF_CONTEXT_ATTRIBUTE); - assert conf != null; - return conf; - } - - @Override - public void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - - if (!HttpServer2.isInstrumentationAccessAllowed(getServletContext(), - request, response)) { - return; - } - - String format = parseAcceptHeader(request); - if (FORMAT_XML.equals(format)) { - response.setContentType("text/xml; charset=utf-8"); - } else if (FORMAT_JSON.equals(format)) { - response.setContentType("application/json; charset=utf-8"); - } - - String name = request.getParameter("name"); - Writer out = response.getWriter(); - String cmd = request.getParameter(COMMAND); - - processCommand(cmd, format, request, response, out, name); - out.close(); - } - - private void processCommand(String cmd, String format, - HttpServletRequest request, HttpServletResponse response, Writer out, - String name) - throws IOException { - try { - if (cmd == null) { - if (FORMAT_XML.equals(format)) { - response.setContentType("text/xml; charset=utf-8"); - } else if (FORMAT_JSON.equals(format)) { - response.setContentType("application/json; charset=utf-8"); - } - - writeResponse(getConfFromContext(), out, format, name); - } else { - processConfigTagRequest(request, out); - } - } catch (BadFormatException bfe) { - response.sendError(HttpServletResponse.SC_BAD_REQUEST, bfe.getMessage()); - } catch (IllegalArgumentException iae) { - response.sendError(HttpServletResponse.SC_NOT_FOUND, iae.getMessage()); - } - } - - @VisibleForTesting - static String parseAcceptHeader(HttpServletRequest request) { - String format = request.getHeader(HttpHeaders.ACCEPT); - return format != null && format.contains(FORMAT_JSON) ? - FORMAT_JSON : FORMAT_XML; - } - - /** - * Guts of the servlet - extracted for easy testing. - */ - static void writeResponse(Configuration conf, - Writer out, String format, String propertyName) - throws IOException, IllegalArgumentException, BadFormatException { - if (FORMAT_JSON.equals(format)) { - Configuration.dumpConfiguration(conf, propertyName, out); - } else if (FORMAT_XML.equals(format)) { - conf.writeXml(propertyName, out); - } else { - throw new BadFormatException("Bad format: " + format); - } - } - - public static class BadFormatException extends Exception { - - private static final long serialVersionUID = 1L; - - public BadFormatException(String msg) { - super(msg); - } - } - - private void processConfigTagRequest(HttpServletRequest request, - Writer out) throws IOException { - String cmd = request.getParameter(COMMAND); - Gson gson = new Gson(); - Configuration config = getOzoneConfig(); - - switch (cmd) { - case "getOzoneTags": - out.write(gson.toJson(config.get(OZONE_TAGS_SYSTEM_KEY) - .split(","))); - break; - case "getPropertyByTag": - String tags = request.getParameter("tags"); - Map propMap = new HashMap<>(); - - for (String tag : tags.split(",")) { - if (config.isPropertyTag(tag)) { - Properties properties = config.getAllPropertiesByTag(tag); - propMap.put(tag, properties); - } else { - LOG.debug("Not a valid tag" + tag); - } - } - out.write(gson.toJsonTree(propMap).toString()); - break; - default: - throw new IllegalArgumentException(cmd + " is not a valid command."); - } - - } - - private static Configuration getOzoneConfig() { - return OZONE_CONFIG; - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/conf/OzoneConfiguration.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/conf/OzoneConfiguration.java deleted file mode 100644 index 36d953c960a..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/conf/OzoneConfiguration.java +++ /dev/null @@ -1,162 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.conf; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.conf.Configuration; - -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Unmarshaller; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; - -/** - * Configuration for ozone. - */ -@InterfaceAudience.Private -public class OzoneConfiguration extends Configuration { - static { - activate(); - } - - public OzoneConfiguration() { - OzoneConfiguration.activate(); - } - - public OzoneConfiguration(Configuration conf) { - super(conf); - } - - public List readPropertyFromXml(URL url) throws JAXBException { - JAXBContext context = JAXBContext.newInstance(XMLConfiguration.class); - Unmarshaller um = context.createUnmarshaller(); - - XMLConfiguration config = (XMLConfiguration) um.unmarshal(url); - return config.getProperties(); - } - - /** - * Class to marshall/un-marshall configuration from xml files. - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlRootElement(name = "configuration") - public static class XMLConfiguration { - - @XmlElement(name = "property", type = Property.class) - private List properties = new ArrayList<>(); - - public XMLConfiguration() { - } - - public XMLConfiguration(List properties) { - this.properties = properties; - } - - public List getProperties() { - return properties; - } - - public void setProperties(List properties) { - this.properties = properties; - } - } - - /** - * Class to marshall/un-marshall configuration properties from xml files. - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlRootElement(name = "property") - public static class Property implements Comparable { - - private String name; - private String value; - private String tag; - private String description; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - public String getTag() { - return tag; - } - - public void setTag(String tag) { - this.tag = tag; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - @Override - public int compareTo(Property o) { - if (this == o) { - return 0; - } - return this.getName().compareTo(o.getName()); - } - - @Override - public String toString() { - return this.getName() + " " + this.getValue() + " " + this.getTag(); - } - - @Override - public int hashCode(){ - return this.getName().hashCode(); - } - - @Override - public boolean equals(Object obj) { - return (obj instanceof Property) && (((Property) obj).getName()) - .equals(this.getName()); - } - } - - public static void activate() { - // adds the default resources - Configuration.addDefaultResource("hdfs-default.xml"); - Configuration.addDefaultResource("hdfs-site.xml"); - Configuration.addDefaultResource("ozone-default.xml"); - Configuration.addDefaultResource("ozone-site.xml"); - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/conf/package-info.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/conf/package-info.java deleted file mode 100644 index 948057ebba7..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/conf/package-info.java +++ /dev/null @@ -1,18 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.conf; \ No newline at end of file diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/package-info.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/package-info.java deleted file mode 100644 index f8894e6a7e8..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/package-info.java +++ /dev/null @@ -1,23 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds; - -/** - * Generic HDDS specific configurator and helper classes. - */ \ No newline at end of file diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/protocol/DatanodeDetails.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/protocol/DatanodeDetails.java deleted file mode 100644 index bae22a22cae..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/protocol/DatanodeDetails.java +++ /dev/null @@ -1,401 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.protocol; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.classification.InterfaceStability; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -/** - * DatanodeDetails class contains details about DataNode like: - * - UUID of the DataNode. - * - IP and Hostname details. - * - Port details to which the DataNode will be listening. - */ -@InterfaceAudience.Private -@InterfaceStability.Evolving -public class DatanodeDetails implements Comparable { - - /** - * DataNode's unique identifier in the cluster. - */ - private final UUID uuid; - - private String ipAddress; - private String hostName; - private List ports; - - - /** - * Constructs DatanodeDetails instance. DatanodeDetails.Builder is used - * for instantiating DatanodeDetails. - * @param uuid DataNode's UUID - * @param ipAddress IP Address of this DataNode - * @param hostName DataNode's hostname - * @param ports Ports used by the DataNode - */ - private DatanodeDetails(String uuid, String ipAddress, String hostName, - List ports) { - this.uuid = UUID.fromString(uuid); - this.ipAddress = ipAddress; - this.hostName = hostName; - this.ports = ports; - } - - protected DatanodeDetails(DatanodeDetails datanodeDetails) { - this.uuid = datanodeDetails.uuid; - this.ipAddress = datanodeDetails.ipAddress; - this.hostName = datanodeDetails.hostName; - this.ports = datanodeDetails.ports; - } - - /** - * Returns the DataNode UUID. - * - * @return UUID of DataNode - */ - public UUID getUuid() { - return uuid; - } - - /** - * Returns the string representation of DataNode UUID. - * - * @return UUID of DataNode - */ - public String getUuidString() { - return uuid.toString(); - } - - /** - * Sets the IP address of Datanode. - * - * @param ip IP Address - */ - public void setIpAddress(String ip) { - this.ipAddress = ip; - } - - /** - * Returns IP address of DataNode. - * - * @return IP address - */ - public String getIpAddress() { - return ipAddress; - } - - /** - * Sets the Datanode hostname. - * - * @param host hostname - */ - public void setHostName(String host) { - this.hostName = host; - } - - /** - * Returns Hostname of DataNode. - * - * @return Hostname - */ - public String getHostName() { - return hostName; - } - - /** - * Sets a DataNode Port. - * - * @param port DataNode port - */ - public void setPort(Port port) { - // If the port is already in the list remove it first and add the - // new/updated port value. - ports.remove(port); - ports.add(port); - } - - /** - * Returns all the Ports used by DataNode. - * - * @return DataNode Ports - */ - public List getPorts() { - return ports; - } - - /** - * Given the name returns port number, null if the asked port is not found. - * - * @param name Name of the port - * - * @return Port - */ - public Port getPort(Port.Name name) { - for (Port port : ports) { - if (port.getName().equals(name)) { - return port; - } - } - return null; - } - - /** - * Returns a DatanodeDetails from the protocol buffers. - * - * @param datanodeDetailsProto - protoBuf Message - * @return DatanodeDetails - */ - public static DatanodeDetails getFromProtoBuf( - HddsProtos.DatanodeDetailsProto datanodeDetailsProto) { - DatanodeDetails.Builder builder = newBuilder(); - builder.setUuid(datanodeDetailsProto.getUuid()); - if (datanodeDetailsProto.hasIpAddress()) { - builder.setIpAddress(datanodeDetailsProto.getIpAddress()); - } - if (datanodeDetailsProto.hasHostName()) { - builder.setHostName(datanodeDetailsProto.getHostName()); - } - for (HddsProtos.Port port : datanodeDetailsProto.getPortsList()) { - builder.addPort(newPort( - Port.Name.valueOf(port.getName().toUpperCase()), port.getValue())); - } - return builder.build(); - } - - /** - * Returns a DatanodeDetails protobuf message from a datanode ID. - * @return HddsProtos.DatanodeDetailsProto - */ - public HddsProtos.DatanodeDetailsProto getProtoBufMessage() { - HddsProtos.DatanodeDetailsProto.Builder builder = - HddsProtos.DatanodeDetailsProto.newBuilder() - .setUuid(getUuidString()); - if (ipAddress != null) { - builder.setIpAddress(ipAddress); - } - if (hostName != null) { - builder.setHostName(hostName); - } - for (Port port : ports) { - builder.addPorts(HddsProtos.Port.newBuilder() - .setName(port.getName().toString()) - .setValue(port.getValue()) - .build()); - } - return builder.build(); - } - - @Override - public String toString() { - return uuid.toString() + "{" + - "ip: " + - ipAddress + - ", host: " + - hostName + - "}"; - } - - @Override - public int compareTo(DatanodeDetails that) { - return this.getUuid().compareTo(that.getUuid()); - } - - @Override - public boolean equals(Object obj) { - return obj instanceof DatanodeDetails && - uuid.equals(((DatanodeDetails) obj).uuid); - } - - @Override - public int hashCode() { - return uuid.hashCode(); - } - - /** - * Returns DatanodeDetails.Builder instance. - * - * @return DatanodeDetails.Builder - */ - public static Builder newBuilder() { - return new Builder(); - } - - /** - * Builder class for building DatanodeDetails. - */ - public static final class Builder { - private String id; - private String ipAddress; - private String hostName; - private List ports; - - /** - * Default private constructor. To create Builder instance use - * DatanodeDetails#newBuilder. - */ - private Builder() { - ports = new ArrayList<>(); - } - - /** - * Sets the DatanodeUuid. - * - * @param uuid DatanodeUuid - * @return DatanodeDetails.Builder - */ - public Builder setUuid(String uuid) { - this.id = uuid; - return this; - } - - /** - * Sets the IP address of DataNode. - * - * @param ip address - * @return DatanodeDetails.Builder - */ - public Builder setIpAddress(String ip) { - this.ipAddress = ip; - return this; - } - - /** - * Sets the hostname of DataNode. - * - * @param host hostname - * @return DatanodeDetails.Builder - */ - public Builder setHostName(String host) { - this.hostName = host; - return this; - } - - /** - * Adds a DataNode Port. - * - * @param port DataNode port - * - * @return DatanodeDetails.Builder - */ - public Builder addPort(Port port) { - this.ports.add(port); - return this; - } - - /** - * Builds and returns DatanodeDetails instance. - * - * @return DatanodeDetails - */ - public DatanodeDetails build() { - Preconditions.checkNotNull(id); - return new DatanodeDetails(id, ipAddress, hostName, ports); - } - - } - - /** - * Constructs a new Port with name and value. - * - * @param name Name of the port - * @param value Port number - * - * @return {@code Port} instance - */ - public static Port newPort(Port.Name name, Integer value) { - return new Port(name, value); - } - - /** - * Container to hold DataNode Port details. - */ - public static final class Port { - - /** - * Ports that are supported in DataNode. - */ - public enum Name { - STANDALONE, RATIS, REST - } - - private Name name; - private Integer value; - - /** - * Private constructor for constructing Port object. Use - * DatanodeDetails#newPort to create a new Port object. - * - * @param name - * @param value - */ - private Port(Name name, Integer value) { - this.name = name; - this.value = value; - } - - /** - * Returns the name of the port. - * - * @return Port name - */ - public Name getName() { - return name; - } - - /** - * Returns the port number. - * - * @return Port number - */ - public Integer getValue() { - return value; - } - - @Override - public int hashCode() { - return name.hashCode(); - } - - /** - * Ports are considered equal if they have the same name. - * - * @param anObject - * The object to compare this {@code Port} against - * @return {@code true} if the given object represents a {@code Port} - and has the same name, {@code false} otherwise - */ - @Override - public boolean equals(Object anObject) { - if (this == anObject) { - return true; - } - if (anObject instanceof Port) { - return name.equals(((Port) anObject).name); - } - return false; - } - } - -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/protocol/package-info.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/protocol/package-info.java deleted file mode 100644 index 7dae0fce02c..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/protocol/package-info.java +++ /dev/null @@ -1,22 +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 - * - * 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. - */ - -/** - * This package contains HDDS protocol related classes. - */ -package org.apache.hadoop.hdds.protocol; \ No newline at end of file diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/ScmConfigKeys.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/ScmConfigKeys.java deleted file mode 100644 index 63f59168288..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/ScmConfigKeys.java +++ /dev/null @@ -1,287 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.classification.InterfaceStability; -import org.apache.ratis.shaded.proto.RaftProtos.ReplicationLevel; -import org.apache.ratis.util.TimeDuration; - -import java.util.concurrent.TimeUnit; - -/** - * This class contains constants for configuration keys used in SCM. - */ -@InterfaceAudience.Public -@InterfaceStability.Unstable -public final class ScmConfigKeys { - - public static final String SCM_CONTAINER_CLIENT_STALE_THRESHOLD_KEY = - "scm.container.client.idle.threshold"; - public static final String SCM_CONTAINER_CLIENT_STALE_THRESHOLD_DEFAULT = - "10s"; - - public static final String SCM_CONTAINER_CLIENT_MAX_SIZE_KEY = - "scm.container.client.max.size"; - public static final int SCM_CONTAINER_CLIENT_MAX_SIZE_DEFAULT = - 256; - - public static final String SCM_CONTAINER_CLIENT_MAX_OUTSTANDING_REQUESTS = - "scm.container.client.max.outstanding.requests"; - public static final int SCM_CONTAINER_CLIENT_MAX_OUTSTANDING_REQUESTS_DEFAULT - = 100; - - public static final String DFS_CONTAINER_RATIS_ENABLED_KEY - = "dfs.container.ratis.enabled"; - public static final boolean DFS_CONTAINER_RATIS_ENABLED_DEFAULT - = false; - public static final String DFS_CONTAINER_RATIS_RPC_TYPE_KEY - = "dfs.container.ratis.rpc.type"; - public static final String DFS_CONTAINER_RATIS_RPC_TYPE_DEFAULT - = "GRPC"; - public static final String DFS_CONTAINER_RATIS_NUM_WRITE_CHUNK_THREADS_KEY - = "dfs.container.ratis.num.write.chunk.threads"; - public static final int DFS_CONTAINER_RATIS_NUM_WRITE_CHUNK_THREADS_DEFAULT - = 60; - public static final String DFS_CONTAINER_RATIS_REPLICATION_LEVEL_KEY - = "dfs.container.ratis.replication.level"; - public static final ReplicationLevel - DFS_CONTAINER_RATIS_REPLICATION_LEVEL_DEFAULT = ReplicationLevel.MAJORITY; - public static final String DFS_CONTAINER_RATIS_SEGMENT_SIZE_KEY = - "dfs.container.ratis.segment.size"; - public static final int DFS_CONTAINER_RATIS_SEGMENT_SIZE_DEFAULT = - 1 * 1024 * 1024 * 1024; - public static final String DFS_CONTAINER_RATIS_SEGMENT_PREALLOCATED_SIZE_KEY = - "dfs.container.ratis.segment.preallocated.size"; - public static final int - DFS_CONTAINER_RATIS_SEGMENT_PREALLOCATED_SIZE_DEFAULT = 128 * 1024 * 1024; - public static final String DFS_RATIS_CLIENT_REQUEST_TIMEOUT_DURATION_KEY = - "dfs.ratis.client.request.timeout.duration"; - public static final TimeDuration - DFS_RATIS_CLIENT_REQUEST_TIMEOUT_DURATION_DEFAULT = - TimeDuration.valueOf(3000, TimeUnit.MILLISECONDS); - public static final String DFS_RATIS_CLIENT_REQUEST_MAX_RETRIES_KEY = - "dfs.ratis.client.request.max.retries"; - public static final int DFS_RATIS_CLIENT_REQUEST_MAX_RETRIES_DEFAULT = 180; - public static final String DFS_RATIS_CLIENT_REQUEST_RETRY_INTERVAL_KEY = - "dfs.ratis.client.request.retry.interval"; - public static final TimeDuration - DFS_RATIS_CLIENT_REQUEST_RETRY_INTERVAL_DEFAULT = - TimeDuration.valueOf(100, TimeUnit.MILLISECONDS); - public static final String DFS_RATIS_SERVER_RETRY_CACHE_TIMEOUT_DURATION_KEY = - "dfs.ratis.server.retry-cache.timeout.duration"; - public static final TimeDuration - DFS_RATIS_SERVER_RETRY_CACHE_TIMEOUT_DURATION_DEFAULT = - TimeDuration.valueOf(600000, TimeUnit.MILLISECONDS); - public static final String DFS_RATIS_SERVER_REQUEST_TIMEOUT_DURATION_KEY = - "dfs.ratis.server.request.timeout.duration"; - public static final TimeDuration - DFS_RATIS_SERVER_REQUEST_TIMEOUT_DURATION_DEFAULT = - TimeDuration.valueOf(3000, TimeUnit.MILLISECONDS); - public static final String - DFS_RATIS_LEADER_ELECTION_MINIMUM_TIMEOUT_DURATION_KEY = - "dfs.ratis.leader.election.minimum.timeout.duration"; - public static final TimeDuration - DFS_RATIS_LEADER_ELECTION_MINIMUM_TIMEOUT_DURATION_DEFAULT = - TimeDuration.valueOf(1, TimeUnit.SECONDS); - - public static final String DFS_RATIS_SERVER_FAILURE_DURATION_KEY = - "dfs.ratis.server.failure.duration"; - public static final TimeDuration - DFS_RATIS_SERVER_FAILURE_DURATION_DEFAULT = - TimeDuration.valueOf(120, TimeUnit.SECONDS); - - // TODO : this is copied from OzoneConsts, may need to move to a better place - public static final String OZONE_SCM_CHUNK_SIZE_KEY = "ozone.scm.chunk.size"; - // 16 MB by default - public static final int OZONE_SCM_CHUNK_SIZE_DEFAULT = 16 * 1024 * 1024; - public static final int OZONE_SCM_CHUNK_MAX_SIZE = 32 * 1024 * 1024; - - public static final String OZONE_SCM_CLIENT_PORT_KEY = - "ozone.scm.client.port"; - public static final int OZONE_SCM_CLIENT_PORT_DEFAULT = 9860; - - public static final String OZONE_SCM_DATANODE_PORT_KEY = - "ozone.scm.datanode.port"; - public static final int OZONE_SCM_DATANODE_PORT_DEFAULT = 9861; - - // OZONE_OM_PORT_DEFAULT = 9862 - public static final String OZONE_SCM_BLOCK_CLIENT_PORT_KEY = - "ozone.scm.block.client.port"; - public static final int OZONE_SCM_BLOCK_CLIENT_PORT_DEFAULT = 9863; - - // Container service client - public static final String OZONE_SCM_CLIENT_ADDRESS_KEY = - "ozone.scm.client.address"; - public static final String OZONE_SCM_CLIENT_BIND_HOST_KEY = - "ozone.scm.client.bind.host"; - public static final String OZONE_SCM_CLIENT_BIND_HOST_DEFAULT = - "0.0.0.0"; - - // Block service client - public static final String OZONE_SCM_BLOCK_CLIENT_ADDRESS_KEY = - "ozone.scm.block.client.address"; - public static final String OZONE_SCM_BLOCK_CLIENT_BIND_HOST_KEY = - "ozone.scm.block.client.bind.host"; - public static final String OZONE_SCM_BLOCK_CLIENT_BIND_HOST_DEFAULT = - "0.0.0.0"; - - public static final String OZONE_SCM_DATANODE_ADDRESS_KEY = - "ozone.scm.datanode.address"; - public static final String OZONE_SCM_DATANODE_BIND_HOST_KEY = - "ozone.scm.datanode.bind.host"; - public static final String OZONE_SCM_DATANODE_BIND_HOST_DEFAULT = - "0.0.0.0"; - - public static final String OZONE_SCM_HTTP_ENABLED_KEY = - "ozone.scm.http.enabled"; - public static final String OZONE_SCM_HTTP_BIND_HOST_KEY = - "ozone.scm.http-bind-host"; - public static final String OZONE_SCM_HTTPS_BIND_HOST_KEY = - "ozone.scm.https-bind-host"; - public static final String OZONE_SCM_HTTP_ADDRESS_KEY = - "ozone.scm.http-address"; - public static final String OZONE_SCM_HTTPS_ADDRESS_KEY = - "ozone.scm.https-address"; - public static final String OZONE_SCM_KEYTAB_FILE = - "ozone.scm.keytab.file"; - public static final String OZONE_SCM_HTTP_BIND_HOST_DEFAULT = "0.0.0.0"; - public static final int OZONE_SCM_HTTP_BIND_PORT_DEFAULT = 9876; - public static final int OZONE_SCM_HTTPS_BIND_PORT_DEFAULT = 9877; - - public static final String HDDS_REST_HTTP_ADDRESS_KEY = - "hdds.rest.http-address"; - public static final String HDDS_REST_HTTP_ADDRESS_DEFAULT = "0.0.0.0:9880"; - public static final String HDDS_DATANODE_DIR_KEY = "hdds.datanode.dir"; - public static final String HDDS_REST_CSRF_ENABLED_KEY = - "hdds.rest.rest-csrf.enabled"; - public static final boolean HDDS_REST_CSRF_ENABLED_DEFAULT = false; - public static final String HDDS_REST_NETTY_HIGH_WATERMARK = - "hdds.rest.netty.high.watermark"; - public static final int HDDS_REST_NETTY_HIGH_WATERMARK_DEFAULT = 65536; - public static final int HDDS_REST_NETTY_LOW_WATERMARK_DEFAULT = 32768; - public static final String HDDS_REST_NETTY_LOW_WATERMARK = - "hdds.rest.netty.low.watermark"; - - public static final String OZONE_SCM_HANDLER_COUNT_KEY = - "ozone.scm.handler.count.key"; - public static final int OZONE_SCM_HANDLER_COUNT_DEFAULT = 10; - - public static final String OZONE_SCM_DEADNODE_INTERVAL = - "ozone.scm.dead.node.interval"; - public static final String OZONE_SCM_DEADNODE_INTERVAL_DEFAULT = - "10m"; - - public static final String OZONE_SCM_HEARTBEAT_PROCESS_INTERVAL = - "ozone.scm.heartbeat.thread.interval"; - public static final String OZONE_SCM_HEARTBEAT_PROCESS_INTERVAL_DEFAULT = - "3s"; - - public static final String OZONE_SCM_STALENODE_INTERVAL = - "ozone.scm.stale.node.interval"; - public static final String OZONE_SCM_STALENODE_INTERVAL_DEFAULT = - "90s"; - - public static final String OZONE_SCM_HEARTBEAT_RPC_TIMEOUT = - "ozone.scm.heartbeat.rpc-timeout"; - public static final long OZONE_SCM_HEARTBEAT_RPC_TIMEOUT_DEFAULT = - 1000; - - /** - * Defines how frequently we will log the missing of heartbeat to a specific - * SCM. In the default case we will write a warning message for each 10 - * sequential heart beats that we miss to a specific SCM. This is to avoid - * overrunning the log with lots of HB missed Log statements. - */ - public static final String OZONE_SCM_HEARTBEAT_LOG_WARN_INTERVAL_COUNT = - "ozone.scm.heartbeat.log.warn.interval.count"; - public static final int OZONE_SCM_HEARTBEAT_LOG_WARN_DEFAULT = - 10; - - // ozone.scm.names key is a set of DNS | DNS:PORT | IP Address | IP:PORT. - // Written as a comma separated string. e.g. scm1, scm2:8020, 7.7.7.7:7777 - // - // If this key is not specified datanodes will not be able to find - // SCM. The SCM membership can be dynamic, so this key should contain - // all possible SCM names. Once the SCM leader is discovered datanodes will - // get the right list of SCMs to heartbeat to from the leader. - // While it is good for the datanodes to know the names of all SCM nodes, - // it is sufficient to actually know the name of on working SCM. That SCM - // will be able to return the information about other SCMs that are part of - // the SCM replicated Log. - // - //In case of a membership change, any one of the SCM machines will be - // able to send back a new list to the datanodes. - public static final String OZONE_SCM_NAMES = "ozone.scm.names"; - - public static final int OZONE_SCM_DEFAULT_PORT = - OZONE_SCM_DATANODE_PORT_DEFAULT; - // File Name and path where datanode ID is to written to. - // if this value is not set then container startup will fail. - public static final String OZONE_SCM_DATANODE_ID = "ozone.scm.datanode.id"; - - public static final String OZONE_SCM_DATANODE_ID_PATH_DEFAULT = "datanode.id"; - - public static final String OZONE_SCM_DB_CACHE_SIZE_MB = - "ozone.scm.db.cache.size.mb"; - public static final int OZONE_SCM_DB_CACHE_SIZE_DEFAULT = 128; - - public static final String OZONE_SCM_CONTAINER_SIZE = - "ozone.scm.container.size"; - public static final String OZONE_SCM_CONTAINER_SIZE_DEFAULT = "5GB"; - - public static final String OZONE_SCM_CONTAINER_PLACEMENT_IMPL_KEY = - "ozone.scm.container.placement.impl"; - - public static final String OZONE_SCM_CONTAINER_PROVISION_BATCH_SIZE = - "ozone.scm.container.provision_batch_size"; - public static final int OZONE_SCM_CONTAINER_PROVISION_BATCH_SIZE_DEFAULT = 20; - - public static final String - OZONE_SCM_KEY_VALUE_CONTAINER_DELETION_CHOOSING_POLICY = - "ozone.scm.keyvalue.container.deletion-choosing.policy"; - - public static final String OZONE_SCM_CONTAINER_CREATION_LEASE_TIMEOUT = - "ozone.scm.container.creation.lease.timeout"; - - public static final String - OZONE_SCM_CONTAINER_CREATION_LEASE_TIMEOUT_DEFAULT = "60s"; - - public static final String OZONE_SCM_PIPELINE_CREATION_LEASE_TIMEOUT = - "ozone.scm.pipeline.creation.lease.timeout"; - - public static final String - OZONE_SCM_PIPELINE_CREATION_LEASE_TIMEOUT_DEFAULT = "60s"; - - public static final String OZONE_SCM_BLOCK_DELETION_MAX_RETRY = - "ozone.scm.block.deletion.max.retry"; - public static final int OZONE_SCM_BLOCK_DELETION_MAX_RETRY_DEFAULT = 4096; - - public static final String HDDS_SCM_WATCHER_TIMEOUT = - "hdds.scm.watcher.timeout"; - - public static final String HDDS_SCM_WATCHER_TIMEOUT_DEFAULT = - "10m"; - - /** - * Never constructed. - */ - private ScmConfigKeys() { - - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/ScmInfo.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/ScmInfo.java deleted file mode 100644 index 6236febb7b1..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/ScmInfo.java +++ /dev/null @@ -1,81 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm; - -/** - * ScmInfo wraps the result returned from SCM#getScmInfo which - * contains clusterId and the SCM Id. - */ -public final class ScmInfo { - private String clusterId; - private String scmId; - - /** - * Builder for ScmInfo. - */ - public static class Builder { - private String clusterId; - private String scmId; - - /** - * sets the cluster id. - * @param cid clusterId to be set - * @return Builder for ScmInfo - */ - public Builder setClusterId(String cid) { - this.clusterId = cid; - return this; - } - - /** - * sets the scmId. - * @param id scmId - * @return Builder for scmInfo - */ - public Builder setScmId(String id) { - this.scmId = id; - return this; - } - - public ScmInfo build() { - return new ScmInfo(clusterId, scmId); - } - } - - private ScmInfo(String clusterId, String scmId) { - this.clusterId = clusterId; - this.scmId = scmId; - } - - /** - * Gets the clusterId from the Version file. - * @return ClusterId - */ - public String getClusterId() { - return clusterId; - } - - /** - * Gets the SCM Id from the Version file. - * @return SCM Id - */ - public String getScmId() { - return scmId; - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/XceiverClientSpi.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/XceiverClientSpi.java deleted file mode 100644 index 571d148848d..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/XceiverClientSpi.java +++ /dev/null @@ -1,135 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm; - -import com.google.common.annotations.VisibleForTesting; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandRequestProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandResponseProto; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; - -import java.io.Closeable; -import java.io.IOException; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * A Client for the storageContainer protocol. - */ -public abstract class XceiverClientSpi implements Closeable { - - final private AtomicInteger referenceCount; - private boolean isEvicted; - - XceiverClientSpi() { - this.referenceCount = new AtomicInteger(0); - this.isEvicted = false; - } - - void incrementReference() { - this.referenceCount.incrementAndGet(); - } - - void decrementReference() { - this.referenceCount.decrementAndGet(); - cleanup(); - } - - void setEvicted() { - isEvicted = true; - cleanup(); - } - - // close the xceiverClient only if, - // 1) there is no refcount on the client - // 2) it has been evicted from the cache. - private void cleanup() { - if (referenceCount.get() == 0 && isEvicted) { - close(); - } - } - - @VisibleForTesting - public int getRefcount() { - return referenceCount.get(); - } - - /** - * Connects to the leader in the pipeline. - */ - public abstract void connect() throws Exception; - - @Override - public abstract void close(); - - /** - * Returns the pipeline of machines that host the container used by this - * client. - * - * @return pipeline of machines that host the container - */ - public abstract Pipeline getPipeline(); - - /** - * Sends a given command to server and gets the reply back. - * @param request Request - * @return Response to the command - * @throws IOException - */ - public ContainerCommandResponseProto sendCommand( - ContainerCommandRequestProto request) throws IOException { - try { - return sendCommandAsync(request).get(); - } catch (ExecutionException | InterruptedException e) { - throw new IOException("Failed to command " + request, e); - } - } - - /** - * Sends a given command to server gets a waitable future back. - * - * @param request Request - * @return Response to the command - * @throws IOException - */ - public abstract CompletableFuture - sendCommandAsync(ContainerCommandRequestProto request) - throws IOException, ExecutionException, InterruptedException; - - /** - * Create a pipeline. - */ - public abstract void createPipeline() throws IOException; - - /** - * Destroy a pipeline. - * @throws IOException - */ - public abstract void destroyPipeline() throws IOException; - - /** - * Returns pipeline Type. - * - * @return - {Stand_Alone, Ratis or Chained} - */ - public abstract HddsProtos.ReplicationType getPipelineType(); -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/client/ScmClient.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/client/ScmClient.java deleted file mode 100644 index 184c5478fdf..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/client/ScmClient.java +++ /dev/null @@ -1,174 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.client; - -import org.apache.hadoop.classification.InterfaceStability; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerWithPipeline; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerData; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; - -import java.io.Closeable; -import java.io.IOException; -import java.util.List; - -/** - * The interface to call into underlying container layer. - * - * Written as interface to allow easy testing: implement a mock container layer - * for standalone testing of CBlock API without actually calling into remote - * containers. Actual container layer can simply re-implement this. - * - * NOTE this is temporarily needed class. When SCM containers are full-fledged, - * this interface will likely be removed. - */ -@InterfaceStability.Unstable -public interface ScmClient extends Closeable { - /** - * Creates a Container on SCM and returns the pipeline. - * @return ContainerInfo - * @throws IOException - */ - ContainerWithPipeline createContainer(String owner) throws IOException; - - /** - * Gets a container by Name -- Throws if the container does not exist. - * @param containerId - Container ID - * @return Pipeline - * @throws IOException - */ - ContainerInfo getContainer(long containerId) throws IOException; - - /** - * Gets a container by Name -- Throws if the container does not exist. - * @param containerId - Container ID - * @return ContainerWithPipeline - * @throws IOException - */ - ContainerWithPipeline getContainerWithPipeline(long containerId) - throws IOException; - - /** - * Close a container. - * - * @param containerId - ID of the container. - * @param pipeline - Pipeline where the container is located. - * @throws IOException - */ - void closeContainer(long containerId, Pipeline pipeline) throws IOException; - - /** - * Close a container. - * - * @param containerId - ID of the container. - * @throws IOException - */ - void closeContainer(long containerId) throws IOException; - - /** - * Deletes an existing container. - * @param containerId - ID of the container. - * @param pipeline - Pipeline that represents the container. - * @param force - true to forcibly delete the container. - * @throws IOException - */ - void deleteContainer(long containerId, Pipeline pipeline, boolean force) - throws IOException; - - /** - * Deletes an existing container. - * @param containerId - ID of the container. - * @param force - true to forcibly delete the container. - * @throws IOException - */ - void deleteContainer(long containerId, boolean force) throws IOException; - - /** - * Lists a range of containers and get their info. - * - * @param startContainerID start containerID. - * @param count count must be > 0. - * - * @return a list of pipeline. - * @throws IOException - */ - List listContainer(long startContainerID, - int count) throws IOException; - - /** - * Read meta data from an existing container. - * @param containerID - ID of the container. - * @param pipeline - Pipeline where the container is located. - * @return ContainerInfo - * @throws IOException - */ - ContainerData readContainer(long containerID, Pipeline pipeline) - throws IOException; - - /** - * Read meta data from an existing container. - * @param containerID - ID of the container. - * @return ContainerInfo - * @throws IOException - */ - ContainerData readContainer(long containerID) - throws IOException; - - /** - * Gets the container size -- Computed by SCM from Container Reports. - * @param containerID - ID of the container. - * @return number of bytes used by this container. - * @throws IOException - */ - long getContainerSize(long containerID) throws IOException; - - /** - * Creates a Container on SCM and returns the pipeline. - * @param type - Replication Type. - * @param replicationFactor - Replication Factor - * @return ContainerInfo - * @throws IOException - in case of error. - */ - ContainerWithPipeline createContainer(HddsProtos.ReplicationType type, - HddsProtos.ReplicationFactor replicationFactor, - String owner) throws IOException; - - /** - * Returns a set of Nodes that meet a query criteria. - * @param nodeStatuses - Criteria that we want the node to have. - * @param queryScope - Query scope - Cluster or pool. - * @param poolName - if it is pool, a pool name is required. - * @return A set of nodes that meet the requested criteria. - * @throws IOException - */ - List queryNode(HddsProtos.NodeState nodeStatuses, - HddsProtos.QueryScope queryScope, String poolName) throws IOException; - - /** - * Creates a specified replication pipeline. - * @param type - Type - * @param factor - Replication factor - * @param nodePool - Set of machines. - * @throws IOException - */ - Pipeline createReplicationPipeline(HddsProtos.ReplicationType type, - HddsProtos.ReplicationFactor factor, HddsProtos.NodePool nodePool) - throws IOException; -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/client/package-info.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/client/package-info.java deleted file mode 100644 index e2f7033d7fa..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/client/package-info.java +++ /dev/null @@ -1,24 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.client; - -/** - * This package contains classes for the client of the storage container - * protocol. - */ diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerID.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerID.java deleted file mode 100644 index 49af297130a..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerID.java +++ /dev/null @@ -1,107 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ - -package org.apache.hadoop.hdds.scm.container; - -import com.google.common.base.Preconditions; -import org.apache.commons.lang3.builder.CompareToBuilder; -import org.apache.commons.lang3.builder.EqualsBuilder; -import org.apache.commons.lang3.builder.HashCodeBuilder; - -/** - * Container ID is an integer that is a value between 1..MAX_CONTAINER ID. - *

- * We are creating a specific type for this to avoid mixing this with - * normal integers in code. - */ -public class ContainerID implements Comparable { - - private final long id; - - /** - * Constructs ContainerID. - * - * @param id int - */ - public ContainerID(long id) { - Preconditions.checkState(id > 0, - "Container ID should be a positive long. "+ id); - this.id = id; - } - - /** - * Factory method for creation of ContainerID. - * @param containerID long - * @return ContainerID. - */ - public static ContainerID valueof(long containerID) { - return new ContainerID(containerID); - } - - /** - * Returns int representation of ID. - * - * @return int - */ - public long getId() { - return id; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (o == null || getClass() != o.getClass()) { - return false; - } - - ContainerID that = (ContainerID) o; - - return new EqualsBuilder() - .append(getId(), that.getId()) - .isEquals(); - } - - @Override - public int hashCode() { - return new HashCodeBuilder(61, 71) - .append(getId()) - .toHashCode(); - } - - @Override - public int compareTo(Object o) { - Preconditions.checkNotNull(o); - if(getClass() != o.getClass()) { - throw new ClassCastException("ContainerID class expected. found:" + - o.getClass().toString()); - } - - ContainerID that = (ContainerID) o; - return new CompareToBuilder() - .append(this.getId(), that.getId()) - .build(); - } - - @Override - public String toString() { - return "id=" + id; - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/AllocatedBlock.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/AllocatedBlock.java deleted file mode 100644 index 63781a87dd5..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/AllocatedBlock.java +++ /dev/null @@ -1,79 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.container.common.helpers; - -import org.apache.hadoop.hdds.client.BlockID; - -/** - * Allocated block wraps the result returned from SCM#allocateBlock which - * contains a Pipeline and the key. - */ -public final class AllocatedBlock { - private Pipeline pipeline; - private BlockID blockID; - // Indicates whether the client should create container before writing block. - private boolean shouldCreateContainer; - - /** - * Builder for AllocatedBlock. - */ - public static class Builder { - private Pipeline pipeline; - private BlockID blockID; - private boolean shouldCreateContainer; - - public Builder setPipeline(Pipeline p) { - this.pipeline = p; - return this; - } - - public Builder setBlockID(BlockID blockId) { - this.blockID = blockId; - return this; - } - - public Builder setShouldCreateContainer(boolean shouldCreate) { - this.shouldCreateContainer = shouldCreate; - return this; - } - - public AllocatedBlock build() { - return new AllocatedBlock(pipeline, blockID, shouldCreateContainer); - } - } - - private AllocatedBlock(Pipeline pipeline, BlockID blockID, - boolean shouldCreateContainer) { - this.pipeline = pipeline; - this.blockID = blockID; - this.shouldCreateContainer = shouldCreateContainer; - } - - public Pipeline getPipeline() { - return pipeline; - } - - public BlockID getBlockID() { - return blockID; - } - - public boolean getCreateContainer() { - return shouldCreateContainer; - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/BlockNotCommittedException.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/BlockNotCommittedException.java deleted file mode 100644 index 86f5a66cf4c..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/BlockNotCommittedException.java +++ /dev/null @@ -1,36 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.container.common.helpers; - -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; - -/** - * Exceptions thrown when a block is yet to be committed on the datanode. - */ -public class BlockNotCommittedException extends StorageContainerException { - - /** - * Constructs an {@code IOException} with the specified detail message. - * - * @param message The detail message (which is saved for later retrieval by - * the {@link #getMessage()} method) - */ - public BlockNotCommittedException(String message) { - super(message, ContainerProtos.Result.BLOCK_NOT_COMMITTED); - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/ContainerInfo.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/ContainerInfo.java deleted file mode 100644 index 5abcd14c521..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/ContainerInfo.java +++ /dev/null @@ -1,482 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.container.common.helpers; - -import static java.lang.Math.max; - -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.PropertyAccessor; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ObjectWriter; -import com.google.common.base.Preconditions; -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.util.Arrays; -import java.util.Comparator; -import org.apache.commons.lang3.builder.EqualsBuilder; -import org.apache.commons.lang3.builder.HashCodeBuilder; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationFactor; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationType; -import org.apache.hadoop.hdds.scm.container.ContainerID; -import org.apache.hadoop.util.Time; - -/** - * Class wraps ozone container info. - */ -public class ContainerInfo implements Comparator, - Comparable, Externalizable { - - private static final ObjectWriter WRITER; - private static final String SERIALIZATION_ERROR_MSG = "Java serialization not" - + " supported. Use protobuf instead."; - - static { - ObjectMapper mapper = new ObjectMapper(); - mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); - mapper - .setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE); - WRITER = mapper.writer(); - } - - private HddsProtos.LifeCycleState state; - @JsonIgnore - private PipelineID pipelineID; - private ReplicationFactor replicationFactor; - private ReplicationType replicationType; - // Bytes allocated by SCM for clients. - private long allocatedBytes; - // Actual container usage, updated through heartbeat. - private long usedBytes; - private long numberOfKeys; - private long lastUsed; - // The wall-clock ms since the epoch at which the current state enters. - private long stateEnterTime; - private String owner; - private long containerID; - private long deleteTransactionId; - /** - * Allows you to maintain private data on ContainerInfo. This is not - * serialized via protobuf, just allows us to maintain some private data. - */ - @JsonIgnore - private byte[] data; - - ContainerInfo( - long containerID, - HddsProtos.LifeCycleState state, - PipelineID pipelineID, - long allocatedBytes, - long usedBytes, - long numberOfKeys, - long stateEnterTime, - String owner, - long deleteTransactionId, - ReplicationFactor replicationFactor, - ReplicationType repType) { - this.containerID = containerID; - this.pipelineID = pipelineID; - this.allocatedBytes = allocatedBytes; - this.usedBytes = usedBytes; - this.numberOfKeys = numberOfKeys; - this.lastUsed = Time.monotonicNow(); - this.state = state; - this.stateEnterTime = stateEnterTime; - this.owner = owner; - this.deleteTransactionId = deleteTransactionId; - this.replicationFactor = replicationFactor; - this.replicationType = repType; - } - - public ContainerInfo(ContainerInfo info) { - this(info.getContainerID(), info.getState(), info.getPipelineID(), - info.getAllocatedBytes(), info.getUsedBytes(), info.getNumberOfKeys(), - info.getStateEnterTime(), info.getOwner(), - info.getDeleteTransactionId(), info.getReplicationFactor(), - info.getReplicationType()); - } - /** - * Needed for serialization findbugs. - */ - public ContainerInfo() { - } - - public static ContainerInfo fromProtobuf(HddsProtos.SCMContainerInfo info) { - ContainerInfo.Builder builder = new ContainerInfo.Builder(); - return builder.setPipelineID( - PipelineID.getFromProtobuf(info.getPipelineID())) - .setAllocatedBytes(info.getAllocatedBytes()) - .setUsedBytes(info.getUsedBytes()) - .setNumberOfKeys(info.getNumberOfKeys()) - .setState(info.getState()) - .setStateEnterTime(info.getStateEnterTime()) - .setOwner(info.getOwner()) - .setContainerID(info.getContainerID()) - .setDeleteTransactionId(info.getDeleteTransactionId()) - .setReplicationFactor(info.getReplicationFactor()) - .setReplicationType(info.getReplicationType()) - .build(); - } - - public long getContainerID() { - return containerID; - } - - public HddsProtos.LifeCycleState getState() { - return state; - } - - public void setState(HddsProtos.LifeCycleState state) { - this.state = state; - } - - public long getStateEnterTime() { - return stateEnterTime; - } - - public ReplicationFactor getReplicationFactor() { - return replicationFactor; - } - - public PipelineID getPipelineID() { - return pipelineID; - } - - public long getAllocatedBytes() { - return allocatedBytes; - } - - /** - * Set Allocated bytes. - * - * @param size - newly allocated bytes -- negative size is case of deletes - * can be used. - */ - public void updateAllocatedBytes(long size) { - this.allocatedBytes += size; - } - - public long getUsedBytes() { - return usedBytes; - } - - public long getNumberOfKeys() { - return numberOfKeys; - } - - public long getDeleteTransactionId() { - return deleteTransactionId; - } - - public void updateDeleteTransactionId(long transactionId) { - deleteTransactionId = max(transactionId, deleteTransactionId); - } - - public ContainerID containerID() { - return new ContainerID(getContainerID()); - } - - /** - * Gets the last used time from SCM's perspective. - * - * @return time in milliseconds. - */ - public long getLastUsed() { - return lastUsed; - } - - public ReplicationType getReplicationType() { - return replicationType; - } - - public void updateLastUsedTime() { - lastUsed = Time.monotonicNow(); - } - - public void allocate(long size) { - // should we also have total container size in ContainerInfo - // and check before allocating? - allocatedBytes += size; - } - - public HddsProtos.SCMContainerInfo getProtobuf() { - HddsProtos.SCMContainerInfo.Builder builder = - HddsProtos.SCMContainerInfo.newBuilder(); - Preconditions.checkState(containerID > 0); - return builder.setAllocatedBytes(getAllocatedBytes()) - .setContainerID(getContainerID()) - .setUsedBytes(getUsedBytes()) - .setNumberOfKeys(getNumberOfKeys()).setState(getState()) - .setStateEnterTime(getStateEnterTime()).setContainerID(getContainerID()) - .setDeleteTransactionId(getDeleteTransactionId()) - .setPipelineID(getPipelineID().getProtobuf()) - .setReplicationFactor(getReplicationFactor()) - .setReplicationType(getReplicationType()) - .setOwner(getOwner()) - .build(); - } - - public String getOwner() { - return owner; - } - - public void setOwner(String owner) { - this.owner = owner; - } - - @Override - public String toString() { - return "ContainerInfo{" - + "id=" + containerID - + ", state=" + state - + ", pipelineID=" + pipelineID - + ", stateEnterTime=" + stateEnterTime - + ", owner=" + owner - + '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (o == null || getClass() != o.getClass()) { - return false; - } - - ContainerInfo that = (ContainerInfo) o; - - return new EqualsBuilder() - .append(getContainerID(), that.getContainerID()) - - // TODO : Fix this later. If we add these factors some tests fail. - // So Commenting this to continue and will enforce this with - // Changes in pipeline where we remove Container Name to - // SCMContainerinfo from Pipeline. - // .append(pipeline.getFactor(), that.pipeline.getFactor()) - // .append(pipeline.getType(), that.pipeline.getType()) - .append(owner, that.owner) - .isEquals(); - } - - @Override - public int hashCode() { - return new HashCodeBuilder(11, 811) - .append(getContainerID()) - .append(getOwner()) - .toHashCode(); - } - - /** - * Compares its two arguments for order. Returns a negative integer, zero, or - * a positive integer as the first argument is less than, equal to, or greater - * than the second.

- * - * @param o1 the first object to be compared. - * @param o2 the second object to be compared. - * @return a negative integer, zero, or a positive integer as the first - * argument is less than, equal to, or greater than the second. - * @throws NullPointerException if an argument is null and this comparator - * does not permit null arguments - * @throws ClassCastException if the arguments' types prevent them from - * being compared by this comparator. - */ - @Override - public int compare(ContainerInfo o1, ContainerInfo o2) { - return Long.compare(o1.getLastUsed(), o2.getLastUsed()); - } - - /** - * Compares this object with the specified object for order. Returns a - * negative integer, zero, or a positive integer as this object is less than, - * equal to, or greater than the specified object. - * - * @param o the object to be compared. - * @return a negative integer, zero, or a positive integer as this object is - * less than, equal to, or greater than the specified object. - * @throws NullPointerException if the specified object is null - * @throws ClassCastException if the specified object's type prevents it - * from being compared to this object. - */ - @Override - public int compareTo(ContainerInfo o) { - return this.compare(this, o); - } - - /** - * Returns a JSON string of this object. - * - * @return String - json string - * @throws IOException - */ - public String toJsonString() throws IOException { - return WRITER.writeValueAsString(this); - } - - /** - * Returns private data that is set on this containerInfo. - * - * @return blob, the user can interpret it any way they like. - */ - public byte[] getData() { - if (this.data != null) { - return Arrays.copyOf(this.data, this.data.length); - } else { - return null; - } - } - - /** - * Set private data on ContainerInfo object. - * - * @param data -- private data. - */ - public void setData(byte[] data) { - if (data != null) { - this.data = Arrays.copyOf(data, data.length); - } - } - - /** - * Throws IOException as default java serialization is not supported. Use - * serialization via protobuf instead. - * - * @param out the stream to write the object to - * @throws IOException Includes any I/O exceptions that may occur - * @serialData Overriding methods should use this tag to describe - * the data layout of this Externalizable object. - * List the sequence of element types and, if possible, - * relate the element to a public/protected field and/or - * method of this Externalizable class. - */ - @Override - public void writeExternal(ObjectOutput out) throws IOException { - throw new IOException(SERIALIZATION_ERROR_MSG); - } - - /** - * Throws IOException as default java serialization is not supported. Use - * serialization via protobuf instead. - * - * @param in the stream to read data from in order to restore the object - * @throws IOException if I/O errors occur - * @throws ClassNotFoundException If the class for an object being - * restored cannot be found. - */ - @Override - public void readExternal(ObjectInput in) - throws IOException, ClassNotFoundException { - throw new IOException(SERIALIZATION_ERROR_MSG); - } - - /** - * Builder class for ContainerInfo. - */ - public static class Builder { - private HddsProtos.LifeCycleState state; - private long allocated; - private long used; - private long keys; - private long stateEnterTime; - private String owner; - private long containerID; - private long deleteTransactionId; - private PipelineID pipelineID; - private ReplicationFactor replicationFactor; - private ReplicationType replicationType; - - public Builder setReplicationType( - ReplicationType repType) { - this.replicationType = repType; - return this; - } - - public Builder setPipelineID(PipelineID pipelineId) { - this.pipelineID = pipelineId; - return this; - } - - public Builder setReplicationFactor(ReplicationFactor repFactor) { - this.replicationFactor = repFactor; - return this; - } - - public Builder setContainerID(long id) { - Preconditions.checkState(id >= 0); - this.containerID = id; - return this; - } - - public Builder setState(HddsProtos.LifeCycleState lifeCycleState) { - this.state = lifeCycleState; - return this; - } - - public Builder setAllocatedBytes(long bytesAllocated) { - this.allocated = bytesAllocated; - return this; - } - - public Builder setUsedBytes(long bytesUsed) { - this.used = bytesUsed; - return this; - } - - public Builder setNumberOfKeys(long keyCount) { - this.keys = keyCount; - return this; - } - - public Builder setStateEnterTime(long time) { - this.stateEnterTime = time; - return this; - } - - public Builder setOwner(String containerOwner) { - this.owner = containerOwner; - return this; - } - - public Builder setDeleteTransactionId(long deleteTransactionID) { - this.deleteTransactionId = deleteTransactionID; - return this; - } - - public ContainerInfo build() { - return new ContainerInfo(containerID, state, pipelineID, allocated, - used, keys, stateEnterTime, owner, deleteTransactionId, - replicationFactor, replicationType); - } - } - - /** - * Check if a container is in open state, this will check if the - * container is either open, allocated, creating or creating. - * Any containers in these states is managed as an open container by SCM. - */ - public boolean isContainerOpen() { - return state == HddsProtos.LifeCycleState.ALLOCATED || - state == HddsProtos.LifeCycleState.CREATING || - state == HddsProtos.LifeCycleState.OPEN || - state == HddsProtos.LifeCycleState.CLOSING; - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/ContainerWithPipeline.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/ContainerWithPipeline.java deleted file mode 100644 index 64f42b30767..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/ContainerWithPipeline.java +++ /dev/null @@ -1,132 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.container.common.helpers; - -import java.util.Comparator; -import org.apache.commons.lang3.builder.EqualsBuilder; -import org.apache.commons.lang3.builder.HashCodeBuilder; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; - -/** - * Class wraps ozone container info. - */ -public class ContainerWithPipeline implements Comparator, - Comparable { - - private final ContainerInfo containerInfo; - private final Pipeline pipeline; - - public ContainerWithPipeline(ContainerInfo containerInfo, Pipeline pipeline) { - this.containerInfo = containerInfo; - this.pipeline = pipeline; - } - - public ContainerInfo getContainerInfo() { - return containerInfo; - } - - public Pipeline getPipeline() { - return pipeline; - } - - public static ContainerWithPipeline fromProtobuf( - HddsProtos.ContainerWithPipeline allocatedContainer) { - return new ContainerWithPipeline( - ContainerInfo.fromProtobuf(allocatedContainer.getContainerInfo()), - Pipeline.getFromProtoBuf(allocatedContainer.getPipeline())); - } - - public HddsProtos.ContainerWithPipeline getProtobuf() { - HddsProtos.ContainerWithPipeline.Builder builder = - HddsProtos.ContainerWithPipeline.newBuilder(); - builder.setContainerInfo(getContainerInfo().getProtobuf()) - .setPipeline(getPipeline().getProtobufMessage()); - - return builder.build(); - } - - - @Override - public String toString() { - return containerInfo.toString() + " | " + pipeline.toString(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (o == null || getClass() != o.getClass()) { - return false; - } - - ContainerWithPipeline that = (ContainerWithPipeline) o; - - return new EqualsBuilder() - .append(getContainerInfo(), that.getContainerInfo()) - .append(getPipeline(), that.getPipeline()) - .isEquals(); - } - - @Override - public int hashCode() { - return new HashCodeBuilder(11, 811) - .append(getContainerInfo()) - .append(getPipeline()) - .toHashCode(); - } - - /** - * Compares its two arguments for order. Returns a negative integer, zero, or - * a positive integer as the first argument is less than, equal to, or greater - * than the second.

- * - * @param o1 the first object to be compared. - * @param o2 the second object to be compared. - * @return a negative integer, zero, or a positive integer as the first - * argument is less than, equal to, or greater than the second. - * @throws NullPointerException if an argument is null and this comparator - * does not permit null arguments - * @throws ClassCastException if the arguments' types prevent them from - * being compared by this comparator. - */ - @Override - public int compare(ContainerWithPipeline o1, ContainerWithPipeline o2) { - return o1.getContainerInfo().compareTo(o2.getContainerInfo()); - } - - /** - * Compares this object with the specified object for order. Returns a - * negative integer, zero, or a positive integer as this object is less than, - * equal to, or greater than the specified object. - * - * @param o the object to be compared. - * @return a negative integer, zero, or a positive integer as this object is - * less than, equal to, or greater than the specified object. - * @throws NullPointerException if the specified object is null - * @throws ClassCastException if the specified object's type prevents it - * from being compared to this object. - */ - @Override - public int compareTo(ContainerWithPipeline o) { - return this.compare(this, o); - } - -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/DeleteBlockResult.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/DeleteBlockResult.java deleted file mode 100644 index 5f5aaceb16a..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/DeleteBlockResult.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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.hdds.scm.container.common.helpers; - -import org.apache.hadoop.hdds.client.BlockID; - -import static org.apache.hadoop.hdds.protocol.proto - .ScmBlockLocationProtocolProtos.DeleteScmBlockResult; - -/** - * Class wraps storage container manager block deletion results. - */ -public class DeleteBlockResult { - private BlockID blockID; - private DeleteScmBlockResult.Result result; - - public DeleteBlockResult(final BlockID blockID, - final DeleteScmBlockResult.Result result) { - this.blockID = blockID; - this.result = result; - } - - /** - * Get block id deleted. - * @return block id. - */ - public BlockID getBlockID() { - return blockID; - } - - /** - * Get key deletion result. - * @return key deletion result. - */ - public DeleteScmBlockResult.Result getResult() { - return result; - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/Pipeline.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/Pipeline.java deleted file mode 100644 index c36ca1f934f..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/Pipeline.java +++ /dev/null @@ -1,315 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.container.common.helpers; - -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.JsonFilter; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.PropertyAccessor; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ObjectWriter; -import com.fasterxml.jackson.databind.ser.FilterProvider; -import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; -import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.List; - -/** - * A pipeline represents the group of machines over which a container lives. - */ -public class Pipeline { - static final String PIPELINE_INFO = "PIPELINE_INFO_FILTER"; - private static final ObjectWriter WRITER; - - static { - ObjectMapper mapper = new ObjectMapper(); - String[] ignorableFieldNames = {"leaderID", "datanodes"}; - FilterProvider filters = new SimpleFilterProvider() - .addFilter(PIPELINE_INFO, SimpleBeanPropertyFilter - .serializeAllExcept(ignorableFieldNames)); - mapper.setVisibility(PropertyAccessor.FIELD, - JsonAutoDetect.Visibility.ANY); - mapper.addMixIn(Object.class, MixIn.class); - - WRITER = mapper.writer(filters); - } - - @JsonIgnore - private String leaderID; - @JsonIgnore - private Map datanodes; - private HddsProtos.LifeCycleState lifeCycleState; - private HddsProtos.ReplicationType type; - private HddsProtos.ReplicationFactor factor; - private PipelineID id; - - /** - * Constructs a new pipeline data structure. - * - * @param leaderID - Leader datanode id - * @param lifeCycleState - Pipeline State - * @param replicationType - Replication protocol - * @param replicationFactor - replication count on datanodes - * @param id - pipeline ID - */ - public Pipeline(String leaderID, HddsProtos.LifeCycleState lifeCycleState, - HddsProtos.ReplicationType replicationType, - HddsProtos.ReplicationFactor replicationFactor, PipelineID id) { - this.leaderID = leaderID; - this.lifeCycleState = lifeCycleState; - this.type = replicationType; - this.factor = replicationFactor; - this.id = id; - datanodes = new ConcurrentHashMap<>(); - } - - @Override - public int hashCode() { - return id.hashCode(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Pipeline that = (Pipeline) o; - - return id.equals(that.id) - && factor.equals(that.factor) - && type.equals(that.type) - && lifeCycleState.equals(that.lifeCycleState) - && leaderID.equals(that.leaderID); - - } - - /** - * Gets pipeline object from protobuf. - * - * @param pipelineProto - ProtoBuf definition for the pipeline. - * @return Pipeline Object - */ - public static Pipeline getFromProtoBuf( - HddsProtos.Pipeline pipelineProto) { - Preconditions.checkNotNull(pipelineProto); - Pipeline pipeline = - new Pipeline(pipelineProto.getLeaderID(), - pipelineProto.getState(), - pipelineProto.getType(), - pipelineProto.getFactor(), - PipelineID.getFromProtobuf(pipelineProto.getId())); - - for (HddsProtos.DatanodeDetailsProto dataID : - pipelineProto.getMembersList()) { - pipeline.addMember(DatanodeDetails.getFromProtoBuf(dataID)); - } - return pipeline; - } - - /** - * returns the replication count. - * @return Replication Factor - */ - public HddsProtos.ReplicationFactor getFactor() { - return factor; - } - - /** - * Returns the first machine in the set of datanodes. - * - * @return First Machine. - */ - @JsonIgnore - public DatanodeDetails getLeader() { - return getDatanodes().get(leaderID); - } - - /** - * Adds a datanode to pipeline - * @param datanodeDetails datanode to be added. - * @return true if the dn was not earlier present, false otherwise - */ - public boolean addMember(DatanodeDetails datanodeDetails) { - return datanodes.put(datanodeDetails.getUuid().toString(), - datanodeDetails) == null; - - } - - public void resetPipeline() { - // reset datanodes in pipeline and learn about them through - // pipeline reports on SCM restart - datanodes.clear(); - } - - public Map getDatanodes() { - return datanodes; - } - - public boolean isEmpty() { - return datanodes.isEmpty(); - } - /** - * Returns the leader host. - * - * @return First Machine. - */ - public String getLeaderHost() { - return getDatanodes() - .get(leaderID).getHostName(); - } - - /** - * - * @return lead - */ - public String getLeaderID() { - return leaderID; - } - /** - * Returns all machines that make up this pipeline. - * - * @return List of Machines. - */ - @JsonIgnore - public List getMachines() { - return new ArrayList<>(getDatanodes().values()); - } - - /** - * Returns all machines that make up this pipeline. - * - * @return List of Machines. - */ - public List getDatanodeHosts() { - List dataHosts = new ArrayList<>(); - for (DatanodeDetails datanode : getDatanodes().values()) { - dataHosts.add(datanode.getHostName()); - } - return dataHosts; - } - - /** - * Return a Protobuf Pipeline message from pipeline. - * - * @return Protobuf message - */ - @JsonIgnore - public HddsProtos.Pipeline getProtobufMessage() { - HddsProtos.Pipeline.Builder builder = - HddsProtos.Pipeline.newBuilder(); - for (DatanodeDetails datanode : datanodes.values()) { - builder.addMembers(datanode.getProtoBufMessage()); - } - builder.setLeaderID(leaderID); - - if (lifeCycleState != null) { - builder.setState(lifeCycleState); - } - if (type != null) { - builder.setType(type); - } - - if (factor != null) { - builder.setFactor(factor); - } - - if (id != null) { - builder.setId(id.getProtobuf()); - } - return builder.build(); - } - - /** - * Gets the State of the pipeline. - * - * @return - LifeCycleStates. - */ - public HddsProtos.LifeCycleState getLifeCycleState() { - return lifeCycleState; - } - - /** - * Update the State of the pipeline. - */ - public void setLifeCycleState(HddsProtos.LifeCycleState nextState) { - lifeCycleState = nextState; - } - - /** - * Gets the pipeline id. - * - * @return - Id of the pipeline - */ - public PipelineID getId() { - return id; - } - - /** - * Returns the type. - * - * @return type - Standalone, Ratis, Chained. - */ - public HddsProtos.ReplicationType getType() { - return type; - } - - @Override - public String toString() { - final StringBuilder b = new StringBuilder(getClass().getSimpleName()) - .append("["); - getDatanodes().keySet().forEach( - node -> b.append(node.endsWith(getLeaderID()) ? "*" + id : id)); - b.append(" id:").append(id); - if (getType() != null) { - b.append(" type:").append(getType().toString()); - } - if (getFactor() != null) { - b.append(" factor:").append(getFactor().toString()); - } - if (getLifeCycleState() != null) { - b.append(" State:").append(getLifeCycleState().toString()); - } - return b.toString(); - } - - /** - * Returns a JSON string of this object. - * - * @return String - json string - * @throws IOException - */ - public String toJsonString() throws IOException { - return WRITER.writeValueAsString(this); - } - - @JsonFilter(PIPELINE_INFO) - class MixIn { - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/PipelineID.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/PipelineID.java deleted file mode 100644 index 6e27a71f3f7..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/PipelineID.java +++ /dev/null @@ -1,97 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.container.common.helpers; - -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.ratis.protocol.RaftGroupId; - -import java.util.UUID; - -/** - * ID for the pipeline, the ID is based on UUID so that it can be used - * in Ratis as RaftGroupId, GroupID is used by the datanodes to initialize - * the ratis group they are part of. - */ -public final class PipelineID implements Comparable { - - private UUID id; - private RaftGroupId groupId; - - private PipelineID(UUID id) { - this.id = id; - this.groupId = RaftGroupId.valueOf(id); - } - - public static PipelineID randomId() { - return new PipelineID(UUID.randomUUID()); - } - - public static PipelineID valueOf(UUID id) { - return new PipelineID(id); - } - - public static PipelineID valueOf(RaftGroupId groupId) { - return valueOf(groupId.getUuid()); - } - - public RaftGroupId getRaftGroupID() { - return groupId; - } - - public UUID getId() { - return id; - } - - public HddsProtos.PipelineID getProtobuf() { - return HddsProtos.PipelineID.newBuilder().setId(id.toString()).build(); - } - - public static PipelineID getFromProtobuf(HddsProtos.PipelineID protos) { - return new PipelineID(UUID.fromString(protos.getId())); - } - - @Override - public String toString() { - return "pipelineId=" + id; - } - - @Override - public int compareTo(PipelineID o) { - return this.id.compareTo(o.id); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - PipelineID that = (PipelineID) o; - - return id.equals(that.id); - } - - @Override - public int hashCode() { - return id.hashCode(); - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/StorageContainerException.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/StorageContainerException.java deleted file mode 100644 index f1405fff946..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/StorageContainerException.java +++ /dev/null @@ -1,104 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.container.common.helpers; - -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; - -import java.io.IOException; - -/** - * Exceptions thrown from the Storage Container. - */ -public class StorageContainerException extends IOException { - private ContainerProtos.Result result; - - /** - * Constructs an {@code IOException} with {@code null} - * as its error detail message. - */ - public StorageContainerException(ContainerProtos.Result result) { - this.result = result; - } - - /** - * Constructs an {@code IOException} with the specified detail message. - * - * @param message The detail message (which is saved for later retrieval by - * the {@link #getMessage()} method) - * @param result - The result code - */ - public StorageContainerException(String message, - ContainerProtos.Result result) { - super(message); - this.result = result; - } - - /** - * Constructs an {@code IOException} with the specified detail message - * and cause. - *

- *

Note that the detail message associated with {@code cause} is - * not automatically incorporated into this exception's detail - * message. - * - * @param message The detail message (which is saved for later retrieval by - * the {@link #getMessage()} method) - * - * @param cause The cause (which is saved for later retrieval by the {@link - * #getCause()} method). (A null value is permitted, and indicates that the - * cause is nonexistent or unknown.) - * - * @param result - The result code - * @since 1.6 - */ - public StorageContainerException(String message, Throwable cause, - ContainerProtos.Result result) { - super(message, cause); - this.result = result; - } - - /** - * Constructs an {@code IOException} with the specified cause and a - * detail message of {@code (cause==null ? null : cause.toString())} - * (which typically contains the class and detail message of {@code cause}). - * This constructor is useful for IO exceptions that are little more - * than wrappers for other throwables. - * - * @param cause The cause (which is saved for later retrieval by the {@link - * #getCause()} method). (A null value is permitted, and indicates that the - * cause is nonexistent or unknown.) - * @param result - The result code - * @since 1.6 - */ - public StorageContainerException(Throwable cause, ContainerProtos.Result - result) { - super(cause); - this.result = result; - } - - /** - * Returns Result. - * - * @return Result. - */ - public ContainerProtos.Result getResult() { - return result; - } - - -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/package-info.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/package-info.java deleted file mode 100644 index ffe0d3d4d99..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/package-info.java +++ /dev/null @@ -1,22 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.container.common.helpers; -/** - Contains protocol buffer helper classes and utilites used in - impl. - **/ \ No newline at end of file diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/package-info.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/package-info.java deleted file mode 100644 index d13dcb1f6c4..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/package-info.java +++ /dev/null @@ -1,18 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.container; diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/package-info.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/package-info.java deleted file mode 100644 index 3c544db3ab9..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/package-info.java +++ /dev/null @@ -1,24 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm; - -/** - * This package contains classes for the client of the storage container - * protocol. - */ diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocol/LocatedContainer.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocol/LocatedContainer.java deleted file mode 100644 index 14ee3d2f80b..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocol/LocatedContainer.java +++ /dev/null @@ -1,127 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.protocol; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.hdfs.protocol.DatanodeInfo; - -import java.util.Set; - -/** - * Holds the nodes that currently host the container for an object key hash. - */ -@InterfaceAudience.Private -public final class LocatedContainer { - private final String key; - private final String matchedKeyPrefix; - private final String containerName; - private final Set locations; - private final DatanodeInfo leader; - - /** - * Creates a LocatedContainer. - * - * @param key object key - * @param matchedKeyPrefix prefix of key that was used to find the location - * @param containerName container name - * @param locations nodes that currently host the container - * @param leader node that currently acts as pipeline leader - */ - public LocatedContainer(String key, String matchedKeyPrefix, - String containerName, Set locations, DatanodeInfo leader) { - this.key = key; - this.matchedKeyPrefix = matchedKeyPrefix; - this.containerName = containerName; - this.locations = locations; - this.leader = leader; - } - - /** - * Returns the container name. - * - * @return container name - */ - public String getContainerName() { - return this.containerName; - } - - /** - * Returns the object key. - * - * @return object key - */ - public String getKey() { - return this.key; - } - - /** - * Returns the node that currently acts as pipeline leader. - * - * @return node that currently acts as pipeline leader - */ - public DatanodeInfo getLeader() { - return this.leader; - } - - /** - * Returns the nodes that currently host the container. - * - * @return Set nodes that currently host the container - */ - public Set getLocations() { - return this.locations; - } - - /** - * Returns the prefix of the key that was used to find the location. - * - * @return prefix of the key that was used to find the location - */ - public String getMatchedKeyPrefix() { - return this.matchedKeyPrefix; - } - - @Override - public boolean equals(Object otherObj) { - if (otherObj == null) { - return false; - } - if (!(otherObj instanceof LocatedContainer)) { - return false; - } - LocatedContainer other = (LocatedContainer)otherObj; - return this.key == null ? other.key == null : this.key.equals(other.key); - } - - @Override - public int hashCode() { - return key.hashCode(); - } - - @Override - public String toString() { - return getClass().getSimpleName() - + "{key=" + key - + "; matchedKeyPrefix=" + matchedKeyPrefix - + "; containerName=" + containerName - + "; locations=" + locations - + "; leader=" + leader - + "}"; - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocol/ScmBlockLocationProtocol.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocol/ScmBlockLocationProtocol.java deleted file mode 100644 index c8d4a809fa5..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocol/ScmBlockLocationProtocol.java +++ /dev/null @@ -1,60 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.protocol; - -import org.apache.hadoop.hdds.scm.ScmInfo; -import org.apache.hadoop.hdds.scm.container.common.helpers.AllocatedBlock; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationFactor; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationType; -import org.apache.hadoop.ozone.common.BlockGroup; -import org.apache.hadoop.ozone.common.DeleteBlockGroupResult; - -import java.io.IOException; -import java.util.List; - -/** - * ScmBlockLocationProtocol is used by an HDFS node to find the set of nodes - * to read/write a block. - */ -public interface ScmBlockLocationProtocol { - - /** - * Asks SCM where a block should be allocated. SCM responds with the - * set of datanodes that should be used creating this block. - * @param size - size of the block. - * @return allocated block accessing info (key, pipeline). - * @throws IOException - */ - AllocatedBlock allocateBlock(long size, ReplicationType type, - ReplicationFactor factor, String owner) throws IOException; - - /** - * Delete blocks for a set of object keys. - * - * @param keyBlocksInfoList Map of object key and its blocks. - * @return list of block deletion results. - * @throws IOException if there is any failure. - */ - List - deleteKeyBlocks(List keyBlocksInfoList) throws IOException; - - /** - * Gets the Clusterid and SCM Id from SCM. - */ - ScmInfo getScmInfo() throws IOException; -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocol/ScmLocatedBlock.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocol/ScmLocatedBlock.java deleted file mode 100644 index 6cbdee42387..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocol/ScmLocatedBlock.java +++ /dev/null @@ -1,100 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.protocol; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.hdfs.protocol.DatanodeInfo; - -import java.util.List; -import java.util.stream.Collectors; - -/** - * Holds the nodes that currently host the block for a block key. - */ -@InterfaceAudience.Private -public final class ScmLocatedBlock { - private final String key; - private final List locations; - private final DatanodeInfo leader; - - /** - * Creates a ScmLocatedBlock. - * - * @param key object key - * @param locations nodes that currently host the block - * @param leader node that currently acts as pipeline leader - */ - public ScmLocatedBlock(final String key, final List locations, - final DatanodeInfo leader) { - this.key = key; - this.locations = locations; - this.leader = leader; - } - - /** - * Returns the object key. - * - * @return object key - */ - public String getKey() { - return this.key; - } - - /** - * Returns the node that currently acts as pipeline leader. - * - * @return node that currently acts as pipeline leader - */ - public DatanodeInfo getLeader() { - return this.leader; - } - - /** - * Returns the nodes that currently host the block. - * - * @return List nodes that currently host the block - */ - public List getLocations() { - return this.locations; - } - - @Override - public boolean equals(Object otherObj) { - if (otherObj == null) { - return false; - } - if (!(otherObj instanceof ScmLocatedBlock)) { - return false; - } - ScmLocatedBlock other = (ScmLocatedBlock)otherObj; - return this.key == null ? other.key == null : this.key.equals(other.key); - } - - @Override - public int hashCode() { - return key.hashCode(); - } - - @Override - public String toString() { - return getClass().getSimpleName() + "{key=" + key + "; locations=" - + locations.stream().map(loc -> loc.toString()).collect(Collectors - .joining(",")) + "; leader=" + leader + "}"; - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocol/StorageContainerLocationProtocol.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocol/StorageContainerLocationProtocol.java deleted file mode 100644 index e38077fc807..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocol/StorageContainerLocationProtocol.java +++ /dev/null @@ -1,152 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.hdds.scm.protocol; - -import org.apache.hadoop.hdds.scm.ScmInfo; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerWithPipeline; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos.ObjectStageChangeRequestProto; - -import java.io.IOException; -import java.util.List; - -/** - * ContainerLocationProtocol is used by an HDFS node to find the set of nodes - * that currently host a container. - */ -public interface StorageContainerLocationProtocol { - /** - * Asks SCM where a container should be allocated. SCM responds with the - * set of datanodes that should be used creating this container. - * - */ - ContainerWithPipeline allocateContainer( - HddsProtos.ReplicationType replicationType, - HddsProtos.ReplicationFactor factor, String owner) - throws IOException; - - /** - * Ask SCM the location of the container. SCM responds with a group of - * nodes where this container and its replicas are located. - * - * @param containerID - ID of the container. - * @return ContainerInfo - the container info such as where the pipeline - * is located. - * @throws IOException - */ - ContainerInfo getContainer(long containerID) throws IOException; - - /** - * Ask SCM the location of the container. SCM responds with a group of - * nodes where this container and its replicas are located. - * - * @param containerID - ID of the container. - * @return ContainerWithPipeline - the container info with the pipeline. - * @throws IOException - */ - ContainerWithPipeline getContainerWithPipeline(long containerID) - throws IOException; - - /** - * Ask SCM a list of containers with a range of container names - * and the limit of count. - * Search container names between start name(exclusive), and - * use prefix name to filter the result. the max size of the - * searching range cannot exceed the value of count. - * - * @param startContainerID start container ID. - * @param count count, if count < 0, the max size is unlimited.( - * Usually the count will be replace with a very big - * value instead of being unlimited in case the db is very big) - * - * @return a list of container. - * @throws IOException - */ - List listContainer(long startContainerID, int count) - throws IOException; - - /** - * Deletes a container in SCM. - * - * @param containerID - * @throws IOException - * if failed to delete the container mapping from db store - * or container doesn't exist. - */ - void deleteContainer(long containerID) throws IOException; - - /** - * Queries a list of Node Statuses. - * @param state - * @return List of Datanodes. - */ - List queryNode(HddsProtos.NodeState state, - HddsProtos.QueryScope queryScope, String poolName) throws IOException; - - /** - * Notify from client when begin or finish creating objects like pipeline - * or containers on datanodes. - * Container will be in Operational state after that. - * @param type object type - * @param id object id - * @param op operation type (e.g., create, close, delete) - * @param stage creation stage - */ - void notifyObjectStageChange( - ObjectStageChangeRequestProto.Type type, long id, - ObjectStageChangeRequestProto.Op op, - ObjectStageChangeRequestProto.Stage stage) throws IOException; - - /** - * Creates a replication pipeline of a specified type. - * @param type - replication type - * @param factor - factor 1 or 3 - * @param nodePool - optional machine list to build a pipeline. - * @throws IOException - */ - Pipeline createReplicationPipeline(HddsProtos.ReplicationType type, - HddsProtos.ReplicationFactor factor, HddsProtos.NodePool nodePool) - throws IOException; - - /** - * Returns information about SCM. - * - * @return {@link ScmInfo} - * @throws IOException - */ - ScmInfo getScmInfo() throws IOException; - - /** - * Check if SCM is in chill mode. - * - * @return Returns true if SCM is in chill mode else returns false. - * @throws IOException - */ - boolean inChillMode() throws IOException; - - /** - * Force SCM out of Chill mode. - * - * @return returns true if operation is successful. - * @throws IOException - */ - boolean forceExitChillMode() throws IOException; -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocol/package-info.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocol/package-info.java deleted file mode 100644 index b56a749453f..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocol/package-info.java +++ /dev/null @@ -1,19 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.protocol; diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocolPB/ScmBlockLocationProtocolClientSideTranslatorPB.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocolPB/ScmBlockLocationProtocolClientSideTranslatorPB.java deleted file mode 100644 index aed0fb7c22c..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocolPB/ScmBlockLocationProtocolClientSideTranslatorPB.java +++ /dev/null @@ -1,173 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.scm.protocolPB; - -import com.google.common.base.Preconditions; -import com.google.protobuf.RpcController; -import com.google.protobuf.ServiceException; -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.hdds.client.BlockID; -import org.apache.hadoop.hdds.scm.ScmInfo; -import org.apache.hadoop.hdds.scm.container.common.helpers.AllocatedBlock; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.scm.protocol.ScmBlockLocationProtocol; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.protocol.proto.ScmBlockLocationProtocolProtos - .AllocateScmBlockRequestProto; -import org.apache.hadoop.hdds.protocol.proto.ScmBlockLocationProtocolProtos - .AllocateScmBlockResponseProto; -import org.apache.hadoop.hdds.protocol.proto.ScmBlockLocationProtocolProtos - .DeleteScmKeyBlocksRequestProto; -import org.apache.hadoop.hdds.protocol.proto.ScmBlockLocationProtocolProtos - .DeleteScmKeyBlocksResponseProto; -import org.apache.hadoop.hdds.protocol.proto.ScmBlockLocationProtocolProtos - .KeyBlocks; -import org.apache.hadoop.ipc.ProtobufHelper; -import org.apache.hadoop.ipc.ProtocolTranslator; -import org.apache.hadoop.ipc.RPC; -import org.apache.hadoop.ozone.common.BlockGroup; -import org.apache.hadoop.ozone.common.DeleteBlockGroupResult; - -import java.io.Closeable; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -/** - * This class is the client-side translator to translate the requests made on - * the {@link ScmBlockLocationProtocol} interface to the RPC server - * implementing {@link ScmBlockLocationProtocolPB}. - */ -@InterfaceAudience.Private -public final class ScmBlockLocationProtocolClientSideTranslatorPB - implements ScmBlockLocationProtocol, ProtocolTranslator, Closeable { - - /** - * RpcController is not used and hence is set to null. - */ - private static final RpcController NULL_RPC_CONTROLLER = null; - - private final ScmBlockLocationProtocolPB rpcProxy; - - /** - * Creates a new StorageContainerLocationProtocolClientSideTranslatorPB. - * - * @param rpcProxy {@link StorageContainerLocationProtocolPB} RPC proxy - */ - public ScmBlockLocationProtocolClientSideTranslatorPB( - ScmBlockLocationProtocolPB rpcProxy) { - this.rpcProxy = rpcProxy; - } - - /** - * Asks SCM where a block should be allocated. SCM responds with the - * set of datanodes that should be used creating this block. - * @param size - size of the block. - * @return allocated block accessing info (key, pipeline). - * @throws IOException - */ - @Override - public AllocatedBlock allocateBlock(long size, - HddsProtos.ReplicationType type, HddsProtos.ReplicationFactor factor, - String owner) throws IOException { - Preconditions.checkArgument(size > 0, "block size must be greater than 0"); - - AllocateScmBlockRequestProto request = - AllocateScmBlockRequestProto.newBuilder().setSize(size).setType(type) - .setFactor(factor).setOwner(owner).build(); - final AllocateScmBlockResponseProto response; - try { - response = rpcProxy.allocateScmBlock(NULL_RPC_CONTROLLER, request); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - if (response.getErrorCode() != - AllocateScmBlockResponseProto.Error.success) { - throw new IOException(response.hasErrorMessage() ? - response.getErrorMessage() : "Allocate block failed."); - } - AllocatedBlock.Builder builder = new AllocatedBlock.Builder() - .setBlockID(BlockID.getFromProtobuf(response.getBlockID())) - .setPipeline(Pipeline.getFromProtoBuf(response.getPipeline())) - .setShouldCreateContainer(response.getCreateContainer()); - return builder.build(); - } - - /** - * Delete the set of keys specified. - * - * @param keyBlocksInfoList batch of block keys to delete. - * @return list of block deletion results. - * @throws IOException if there is any failure. - * - */ - @Override - public List deleteKeyBlocks( - List keyBlocksInfoList) throws IOException { - List keyBlocksProto = keyBlocksInfoList.stream() - .map(BlockGroup::getProto).collect(Collectors.toList()); - DeleteScmKeyBlocksRequestProto request = DeleteScmKeyBlocksRequestProto - .newBuilder().addAllKeyBlocks(keyBlocksProto).build(); - - final DeleteScmKeyBlocksResponseProto resp; - try { - resp = rpcProxy.deleteScmKeyBlocks(NULL_RPC_CONTROLLER, request); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - List results = - new ArrayList<>(resp.getResultsCount()); - results.addAll(resp.getResultsList().stream().map( - result -> new DeleteBlockGroupResult(result.getObjectKey(), - DeleteBlockGroupResult - .convertBlockResultProto(result.getBlockResultsList()))) - .collect(Collectors.toList())); - return results; - } - - /** - * Gets the cluster Id and Scm Id from SCM. - * @return ScmInfo - * @throws IOException - */ - @Override - public ScmInfo getScmInfo() throws IOException { - HddsProtos.GetScmInfoRequestProto request = - HddsProtos.GetScmInfoRequestProto.getDefaultInstance(); - HddsProtos.GetScmInfoRespsonseProto resp; - try { - resp = rpcProxy.getScmInfo(NULL_RPC_CONTROLLER, request); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - ScmInfo.Builder builder = new ScmInfo.Builder() - .setClusterId(resp.getClusterId()) - .setScmId(resp.getScmId()); - return builder.build(); - } - - @Override - public Object getUnderlyingProxyObject() { - return rpcProxy; - } - - @Override - public void close() { - RPC.stopProxy(rpcProxy); - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocolPB/ScmBlockLocationProtocolPB.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocolPB/ScmBlockLocationProtocolPB.java deleted file mode 100644 index 837c95b2aa0..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocolPB/ScmBlockLocationProtocolPB.java +++ /dev/null @@ -1,35 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.protocolPB; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.hdds.protocol.proto.ScmBlockLocationProtocolProtos - .ScmBlockLocationProtocolService; -import org.apache.hadoop.ipc.ProtocolInfo; - -/** - * Protocol used from an HDFS node to StorageContainerManager. This extends the - * Protocol Buffers service interface to add Hadoop-specific annotations. - */ -@ProtocolInfo(protocolName = - "org.apache.hadoop.ozone.protocol.ScmBlockLocationProtocol", - protocolVersion = 1) -@InterfaceAudience.Private -public interface ScmBlockLocationProtocolPB - extends ScmBlockLocationProtocolService.BlockingInterface { -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocolPB/StorageContainerLocationProtocolClientSideTranslatorPB.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocolPB/StorageContainerLocationProtocolClientSideTranslatorPB.java deleted file mode 100644 index 16819e99e9e..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocolPB/StorageContainerLocationProtocolClientSideTranslatorPB.java +++ /dev/null @@ -1,371 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.scm.protocolPB; - -import com.google.common.base.Preconditions; -import com.google.protobuf.RpcController; -import com.google.protobuf.ServiceException; -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos.ForceExitChillModeRequestProto; -import org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos.ForceExitChillModeResponseProto; -import org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos.GetContainerWithPipelineRequestProto; -import org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos.GetContainerWithPipelineResponseProto; -import org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos.InChillModeRequestProto; -import org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos.InChillModeResponseProto; -import org.apache.hadoop.hdds.scm.ScmInfo; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerWithPipeline; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.scm.protocol.StorageContainerLocationProtocol; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos.ContainerRequestProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos.ContainerResponseProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos.GetContainerRequestProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos.GetContainerResponseProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos.NodeQueryRequestProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos.NodeQueryResponseProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos.ObjectStageChangeRequestProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos.PipelineRequestProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos.PipelineResponseProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos.SCMDeleteContainerRequestProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos.SCMListContainerRequestProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos.SCMListContainerResponseProto; -import org.apache.hadoop.ipc.ProtobufHelper; -import org.apache.hadoop.ipc.ProtocolTranslator; -import org.apache.hadoop.ipc.RPC; - -import java.io.Closeable; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * This class is the client-side translator to translate the requests made on - * the {@link StorageContainerLocationProtocol} interface to the RPC server - * implementing {@link StorageContainerLocationProtocolPB}. - */ -@InterfaceAudience.Private -public final class StorageContainerLocationProtocolClientSideTranslatorPB - implements StorageContainerLocationProtocol, ProtocolTranslator, Closeable { - - /** - * RpcController is not used and hence is set to null. - */ - private static final RpcController NULL_RPC_CONTROLLER = null; - - private final StorageContainerLocationProtocolPB rpcProxy; - - /** - * Creates a new StorageContainerLocationProtocolClientSideTranslatorPB. - * - * @param rpcProxy {@link StorageContainerLocationProtocolPB} RPC proxy - */ - public StorageContainerLocationProtocolClientSideTranslatorPB( - StorageContainerLocationProtocolPB rpcProxy) { - this.rpcProxy = rpcProxy; - } - - /** - * Asks SCM where a container should be allocated. SCM responds with the set - * of datanodes that should be used creating this container. Ozone/SCM only - * supports replication factor of either 1 or 3. - * @param type - Replication Type - * @param factor - Replication Count - * @return - * @throws IOException - */ - @Override - public ContainerWithPipeline allocateContainer( - HddsProtos.ReplicationType type, HddsProtos.ReplicationFactor factor, - String owner) throws IOException { - - ContainerRequestProto request = ContainerRequestProto.newBuilder() - .setReplicationFactor(factor) - .setReplicationType(type) - .setOwner(owner) - .build(); - - final ContainerResponseProto response; - try { - response = rpcProxy.allocateContainer(NULL_RPC_CONTROLLER, request); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - if (response.getErrorCode() != ContainerResponseProto.Error.success) { - throw new IOException(response.hasErrorMessage() ? - response.getErrorMessage() : "Allocate container failed."); - } - return ContainerWithPipeline.fromProtobuf( - response.getContainerWithPipeline()); - } - - public ContainerInfo getContainer(long containerID) throws IOException { - Preconditions.checkState(containerID >= 0, - "Container ID cannot be negative"); - GetContainerRequestProto request = GetContainerRequestProto - .newBuilder() - .setContainerID(containerID) - .build(); - try { - GetContainerResponseProto response = - rpcProxy.getContainer(NULL_RPC_CONTROLLER, request); - return ContainerInfo.fromProtobuf(response.getContainerInfo()); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - } - - /** - * {@inheritDoc} - */ - public ContainerWithPipeline getContainerWithPipeline(long containerID) - throws IOException { - Preconditions.checkState(containerID >= 0, - "Container ID cannot be negative"); - GetContainerWithPipelineRequestProto request = - GetContainerWithPipelineRequestProto.newBuilder() - .setContainerID(containerID).build(); - try { - GetContainerWithPipelineResponseProto response = - rpcProxy.getContainerWithPipeline(NULL_RPC_CONTROLLER, request); - return ContainerWithPipeline.fromProtobuf( - response.getContainerWithPipeline()); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - } - - /** - * {@inheritDoc} - */ - @Override - public List listContainer(long startContainerID, int count) - throws IOException { - Preconditions.checkState(startContainerID >= 0, - "Container ID cannot be negative."); - Preconditions.checkState(count > 0, - "Container count must be greater than 0."); - SCMListContainerRequestProto.Builder builder = SCMListContainerRequestProto - .newBuilder(); - builder.setStartContainerID(startContainerID); - builder.setCount(count); - SCMListContainerRequestProto request = builder.build(); - - try { - SCMListContainerResponseProto response = - rpcProxy.listContainer(NULL_RPC_CONTROLLER, request); - List containerList = new ArrayList<>(); - for (HddsProtos.SCMContainerInfo containerInfoProto : response - .getContainersList()) { - containerList.add(ContainerInfo.fromProtobuf(containerInfoProto)); - } - return containerList; - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - } - - /** - * Ask SCM to delete a container by name. SCM will remove - * the container mapping in its database. - * - * @param containerID - * @throws IOException - */ - @Override - public void deleteContainer(long containerID) - throws IOException { - Preconditions.checkState(containerID >= 0, - "Container ID cannot be negative"); - SCMDeleteContainerRequestProto request = SCMDeleteContainerRequestProto - .newBuilder() - .setContainerID(containerID) - .build(); - try { - rpcProxy.deleteContainer(NULL_RPC_CONTROLLER, request); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - } - - /** - * Queries a list of Node Statuses. - * - * @param nodeStatuses - * @return List of Datanodes. - */ - @Override - public List queryNode(HddsProtos.NodeState - nodeStatuses, HddsProtos.QueryScope queryScope, String poolName) - throws IOException { - // TODO : We support only cluster wide query right now. So ignoring checking - // queryScope and poolName - Preconditions.checkNotNull(nodeStatuses); - NodeQueryRequestProto request = NodeQueryRequestProto.newBuilder() - .setState(nodeStatuses) - .setScope(queryScope).setPoolName(poolName).build(); - try { - NodeQueryResponseProto response = - rpcProxy.queryNode(NULL_RPC_CONTROLLER, request); - return response.getDatanodesList(); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - - } - - /** - * Notify from client that creates object on datanodes. - * @param type object type - * @param id object id - * @param op operation type (e.g., create, close, delete) - * @param stage object creation stage : begin/complete - */ - @Override - public void notifyObjectStageChange( - ObjectStageChangeRequestProto.Type type, long id, - ObjectStageChangeRequestProto.Op op, - ObjectStageChangeRequestProto.Stage stage) throws IOException { - Preconditions.checkState(id >= 0, - "Object id cannot be negative."); - ObjectStageChangeRequestProto request = - ObjectStageChangeRequestProto.newBuilder() - .setType(type) - .setId(id) - .setOp(op) - .setStage(stage) - .build(); - try { - rpcProxy.notifyObjectStageChange(NULL_RPC_CONTROLLER, request); - } catch(ServiceException e){ - throw ProtobufHelper.getRemoteException(e); - } - } - - /** - * Creates a replication pipeline of a specified type. - * - * @param replicationType - replication type - * @param factor - factor 1 or 3 - * @param nodePool - optional machine list to build a pipeline. - * @throws IOException - */ - @Override - public Pipeline createReplicationPipeline(HddsProtos.ReplicationType - replicationType, HddsProtos.ReplicationFactor factor, HddsProtos - .NodePool nodePool) throws IOException { - PipelineRequestProto request = PipelineRequestProto.newBuilder() - .setNodePool(nodePool) - .setReplicationFactor(factor) - .setReplicationType(replicationType) - .build(); - try { - PipelineResponseProto response = - rpcProxy.allocatePipeline(NULL_RPC_CONTROLLER, request); - if (response.getErrorCode() == - PipelineResponseProto.Error.success) { - Preconditions.checkState(response.hasPipeline(), "With success, " + - "must come a pipeline"); - return Pipeline.getFromProtoBuf(response.getPipeline()); - } else { - String errorMessage = String.format("create replication pipeline " + - "failed. code : %s Message: %s", response.getErrorCode(), - response.hasErrorMessage() ? response.getErrorMessage() : ""); - throw new IOException(errorMessage); - } - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - } - - @Override - public ScmInfo getScmInfo() throws IOException { - HddsProtos.GetScmInfoRequestProto request = - HddsProtos.GetScmInfoRequestProto.getDefaultInstance(); - try { - HddsProtos.GetScmInfoRespsonseProto resp = rpcProxy.getScmInfo( - NULL_RPC_CONTROLLER, request); - ScmInfo.Builder builder = new ScmInfo.Builder() - .setClusterId(resp.getClusterId()) - .setScmId(resp.getScmId()); - return builder.build(); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - - } - - /** - * Check if SCM is in chill mode. - * - * @return Returns true if SCM is in chill mode else returns false. - * @throws IOException - */ - @Override - public boolean inChillMode() throws IOException { - InChillModeRequestProto request = - InChillModeRequestProto.getDefaultInstance(); - try { - InChillModeResponseProto resp = rpcProxy.inChillMode( - NULL_RPC_CONTROLLER, request); - return resp.getInChillMode(); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - } - - /** - * Force SCM out of Chill mode. - * - * @return returns true if operation is successful. - * @throws IOException - */ - @Override - public boolean forceExitChillMode() throws IOException { - ForceExitChillModeRequestProto request = - ForceExitChillModeRequestProto.getDefaultInstance(); - try { - ForceExitChillModeResponseProto resp = rpcProxy - .forceExitChillMode(NULL_RPC_CONTROLLER, request); - return resp.getExitedChillMode(); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - } - - @Override - public Object getUnderlyingProxyObject() { - return rpcProxy; - } - - @Override - public void close() { - RPC.stopProxy(rpcProxy); - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocolPB/StorageContainerLocationProtocolPB.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocolPB/StorageContainerLocationProtocolPB.java deleted file mode 100644 index f234ad31298..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocolPB/StorageContainerLocationProtocolPB.java +++ /dev/null @@ -1,36 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.protocolPB; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos - .StorageContainerLocationProtocolService; -import org.apache.hadoop.ipc.ProtocolInfo; - -/** - * Protocol used from an HDFS node to StorageContainerManager. This extends the - * Protocol Buffers service interface to add Hadoop-specific annotations. - */ -@ProtocolInfo(protocolName = - "org.apache.hadoop.ozone.protocol.StorageContainerLocationProtocol", - protocolVersion = 1) -@InterfaceAudience.Private -public interface StorageContainerLocationProtocolPB - extends StorageContainerLocationProtocolService.BlockingInterface { -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocolPB/package-info.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocolPB/package-info.java deleted file mode 100644 index 652ae60973c..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocolPB/package-info.java +++ /dev/null @@ -1,24 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.protocolPB; - -/** - * This package contains classes for the client of the storage container - * protocol. - */ diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/storage/ContainerProtocolCalls.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/storage/ContainerProtocolCalls.java deleted file mode 100644 index 6b7a3284729..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/storage/ContainerProtocolCalls.java +++ /dev/null @@ -1,432 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.storage; - -import org.apache.hadoop.hdds.scm.container.common.helpers - .BlockNotCommittedException; -import org.apache.ratis.shaded.com.google.protobuf.ByteString; -import org.apache.hadoop.hdds.scm.XceiverClientSpi; -import org.apache.hadoop.hdds.scm.container.common.helpers - .StorageContainerException; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ChunkInfo; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandRequestProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandResponseProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .CloseContainerRequestProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .DatanodeBlockID; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .GetBlockRequestProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .GetBlockResponseProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .GetSmallFileRequestProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .GetSmallFileResponseProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.BlockData; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .PutBlockRequestProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .PutSmallFileRequestProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ReadChunkRequestProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ReadChunkResponseProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ReadContainerRequestProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ReadContainerResponseProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.Type; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .WriteChunkRequestProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.KeyValue; -import org.apache.hadoop.hdds.client.BlockID; - -import java.io.IOException; - -/** - * Implementation of all container protocol calls performed by Container - * clients. - */ -public final class ContainerProtocolCalls { - - /** - * There is no need to instantiate this class. - */ - private ContainerProtocolCalls() { - } - - /** - * Calls the container protocol to get a container block. - * - * @param xceiverClient client to perform call - * @param datanodeBlockID blockID to identify container - * @param traceID container protocol call args - * @return container protocol get block response - * @throws IOException if there is an I/O error while performing the call - */ - public static GetBlockResponseProto getBlock(XceiverClientSpi xceiverClient, - DatanodeBlockID datanodeBlockID, String traceID) throws IOException { - GetBlockRequestProto.Builder readBlockRequest = GetBlockRequestProto - .newBuilder() - .setBlockID(datanodeBlockID); - String id = xceiverClient.getPipeline().getLeader().getUuidString(); - - ContainerCommandRequestProto request = ContainerCommandRequestProto - .newBuilder() - .setCmdType(Type.GetBlock) - .setContainerID(datanodeBlockID.getContainerID()) - .setTraceID(traceID) - .setDatanodeUuid(id) - .setGetBlock(readBlockRequest) - .build(); - ContainerCommandResponseProto response = xceiverClient.sendCommand(request); - validateContainerResponse(response); - - return response.getGetBlock(); - } - - /** - * Calls the container protocol to get the length of a committed block. - * - * @param xceiverClient client to perform call - * @param blockID blockId for the Block - * @param traceID container protocol call args - * @return container protocol getLastCommittedBlockLength response - * @throws IOException if there is an I/O error while performing the call - */ - public static ContainerProtos.GetCommittedBlockLengthResponseProto - getCommittedBlockLength( - XceiverClientSpi xceiverClient, BlockID blockID, String traceID) - throws IOException { - ContainerProtos.GetCommittedBlockLengthRequestProto.Builder - getBlockLengthRequestBuilder = - ContainerProtos.GetCommittedBlockLengthRequestProto.newBuilder(). - setBlockID(blockID.getDatanodeBlockIDProtobuf()); - String id = xceiverClient.getPipeline().getLeader().getUuidString(); - ContainerCommandRequestProto request = - ContainerCommandRequestProto.newBuilder() - .setCmdType(Type.GetCommittedBlockLength) - .setContainerID(blockID.getContainerID()) - .setTraceID(traceID) - .setDatanodeUuid(id) - .setGetCommittedBlockLength(getBlockLengthRequestBuilder).build(); - ContainerCommandResponseProto response = xceiverClient.sendCommand(request); - validateContainerResponse(response); - return response.getGetCommittedBlockLength(); - } - - /** - * Calls the container protocol to put a container block. - * - * @param xceiverClient client to perform call - * @param containerBlockData block data to identify container - * @param traceID container protocol call args - * @throws IOException if there is an I/O error while performing the call - */ - public static void putBlock(XceiverClientSpi xceiverClient, - BlockData containerBlockData, String traceID) throws IOException { - PutBlockRequestProto.Builder createBlockRequest = PutBlockRequestProto - .newBuilder() - .setBlockData(containerBlockData); - String id = xceiverClient.getPipeline().getLeader().getUuidString(); - ContainerCommandRequestProto request = ContainerCommandRequestProto - .newBuilder() - .setCmdType(Type.PutBlock) - .setContainerID(containerBlockData.getBlockID().getContainerID()) - .setTraceID(traceID) - .setDatanodeUuid(id) - .setPutBlock(createBlockRequest) - .build(); - ContainerCommandResponseProto response = xceiverClient.sendCommand(request); - validateContainerResponse(response); - } - - /** - * Calls the container protocol to read a chunk. - * - * @param xceiverClient client to perform call - * @param chunk information about chunk to read - * @param blockID ID of the block - * @param traceID container protocol call args - * @return container protocol read chunk response - * @throws IOException if there is an I/O error while performing the call - */ - public static ReadChunkResponseProto readChunk(XceiverClientSpi xceiverClient, - ChunkInfo chunk, BlockID blockID, String traceID) throws IOException { - ReadChunkRequestProto.Builder readChunkRequest = ReadChunkRequestProto - .newBuilder() - .setBlockID(blockID.getDatanodeBlockIDProtobuf()) - .setChunkData(chunk); - String id = xceiverClient.getPipeline().getLeader().getUuidString(); - ContainerCommandRequestProto request = ContainerCommandRequestProto - .newBuilder() - .setCmdType(Type.ReadChunk) - .setContainerID(blockID.getContainerID()) - .setTraceID(traceID) - .setDatanodeUuid(id) - .setReadChunk(readChunkRequest) - .build(); - ContainerCommandResponseProto response = xceiverClient.sendCommand(request); - validateContainerResponse(response); - return response.getReadChunk(); - } - - /** - * Calls the container protocol to write a chunk. - * - * @param xceiverClient client to perform call - * @param chunk information about chunk to write - * @param blockID ID of the block - * @param data the data of the chunk to write - * @param traceID container protocol call args - * @throws IOException if there is an I/O error while performing the call - */ - public static void writeChunk(XceiverClientSpi xceiverClient, ChunkInfo chunk, - BlockID blockID, ByteString data, String traceID) - throws IOException { - WriteChunkRequestProto.Builder writeChunkRequest = WriteChunkRequestProto - .newBuilder() - .setBlockID(blockID.getDatanodeBlockIDProtobuf()) - .setChunkData(chunk) - .setData(data); - String id = xceiverClient.getPipeline().getLeader().getUuidString(); - ContainerCommandRequestProto request = ContainerCommandRequestProto - .newBuilder() - .setCmdType(Type.WriteChunk) - .setContainerID(blockID.getContainerID()) - .setTraceID(traceID) - .setDatanodeUuid(id) - .setWriteChunk(writeChunkRequest) - .build(); - ContainerCommandResponseProto response = xceiverClient.sendCommand(request); - validateContainerResponse(response); - } - - /** - * Allows writing a small file using single RPC. This takes the container - * name, block name and data to write sends all that data to the container - * using a single RPC. This API is designed to be used for files which are - * smaller than 1 MB. - * - * @param client - client that communicates with the container. - * @param blockID - ID of the block - * @param data - Data to be written into the container. - * @param traceID - Trace ID for logging purpose. - * @throws IOException - */ - public static void writeSmallFile(XceiverClientSpi client, - BlockID blockID, byte[] data, String traceID) - throws IOException { - - BlockData containerBlockData = - BlockData.newBuilder().setBlockID(blockID.getDatanodeBlockIDProtobuf()) - .build(); - PutBlockRequestProto.Builder createBlockRequest = - PutBlockRequestProto.newBuilder() - .setBlockData(containerBlockData); - - KeyValue keyValue = - KeyValue.newBuilder().setKey("OverWriteRequested").setValue("true") - .build(); - ChunkInfo chunk = - ChunkInfo.newBuilder().setChunkName(blockID.getLocalID() - + "_chunk").setOffset(0).setLen(data.length). - addMetadata(keyValue).build(); - - PutSmallFileRequestProto putSmallFileRequest = - PutSmallFileRequestProto.newBuilder().setChunkInfo(chunk) - .setBlock(createBlockRequest).setData(ByteString.copyFrom(data)) - .build(); - - String id = client.getPipeline().getLeader().getUuidString(); - ContainerCommandRequestProto request = - ContainerCommandRequestProto.newBuilder() - .setCmdType(Type.PutSmallFile) - .setContainerID(blockID.getContainerID()) - .setTraceID(traceID) - .setDatanodeUuid(id) - .setPutSmallFile(putSmallFileRequest) - .build(); - ContainerCommandResponseProto response = client.sendCommand(request); - validateContainerResponse(response); - } - - /** - * createContainer call that creates a container on the datanode. - * @param client - client - * @param containerID - ID of container - * @param traceID - traceID - * @throws IOException - */ - public static void createContainer(XceiverClientSpi client, long containerID, - String traceID) throws IOException { - ContainerProtos.CreateContainerRequestProto.Builder createRequest = - ContainerProtos.CreateContainerRequestProto - .newBuilder(); - createRequest.setContainerType(ContainerProtos.ContainerType - .KeyValueContainer); - - String id = client.getPipeline().getLeader().getUuidString(); - ContainerCommandRequestProto.Builder request = - ContainerCommandRequestProto.newBuilder(); - request.setCmdType(ContainerProtos.Type.CreateContainer); - request.setContainerID(containerID); - request.setCreateContainer(createRequest.build()); - request.setDatanodeUuid(id); - request.setTraceID(traceID); - ContainerCommandResponseProto response = client.sendCommand( - request.build()); - validateContainerResponse(response); - } - - /** - * Deletes a container from a pipeline. - * - * @param client - * @param force whether or not to forcibly delete the container. - * @param traceID - * @throws IOException - */ - public static void deleteContainer(XceiverClientSpi client, long containerID, - boolean force, String traceID) throws IOException { - ContainerProtos.DeleteContainerRequestProto.Builder deleteRequest = - ContainerProtos.DeleteContainerRequestProto.newBuilder(); - deleteRequest.setForceDelete(force); - String id = client.getPipeline().getLeader().getUuidString(); - - ContainerCommandRequestProto.Builder request = - ContainerCommandRequestProto.newBuilder(); - request.setCmdType(ContainerProtos.Type.DeleteContainer); - request.setContainerID(containerID); - request.setDeleteContainer(deleteRequest); - request.setTraceID(traceID); - request.setDatanodeUuid(id); - ContainerCommandResponseProto response = - client.sendCommand(request.build()); - validateContainerResponse(response); - } - - /** - * Close a container. - * - * @param client - * @param containerID - * @param traceID - * @throws IOException - */ - public static void closeContainer(XceiverClientSpi client, - long containerID, String traceID) throws IOException { - String id = client.getPipeline().getLeader().getUuidString(); - - ContainerCommandRequestProto.Builder request = - ContainerCommandRequestProto.newBuilder(); - request.setCmdType(Type.CloseContainer); - request.setContainerID(containerID); - request.setCloseContainer(CloseContainerRequestProto.getDefaultInstance()); - request.setTraceID(traceID); - request.setDatanodeUuid(id); - ContainerCommandResponseProto response = - client.sendCommand(request.build()); - validateContainerResponse(response); - } - - /** - * readContainer call that gets meta data from an existing container. - * - * @param client - client - * @param traceID - trace ID - * @throws IOException - */ - public static ReadContainerResponseProto readContainer( - XceiverClientSpi client, long containerID, - String traceID) throws IOException { - String id = client.getPipeline().getLeader().getUuidString(); - - ContainerCommandRequestProto.Builder request = - ContainerCommandRequestProto.newBuilder(); - request.setCmdType(Type.ReadContainer); - request.setContainerID(containerID); - request.setReadContainer(ReadContainerRequestProto.getDefaultInstance()); - request.setDatanodeUuid(id); - request.setTraceID(traceID); - ContainerCommandResponseProto response = - client.sendCommand(request.build()); - validateContainerResponse(response); - - return response.getReadContainer(); - } - - /** - * Reads the data given the blockID. - * - * @param client - * @param blockID - ID of the block - * @param traceID - trace ID - * @return GetSmallFileResponseProto - * @throws IOException - */ - public static GetSmallFileResponseProto readSmallFile(XceiverClientSpi client, - BlockID blockID, String traceID) throws IOException { - GetBlockRequestProto.Builder getBlock = GetBlockRequestProto - .newBuilder() - .setBlockID(blockID.getDatanodeBlockIDProtobuf()); - ContainerProtos.GetSmallFileRequestProto getSmallFileRequest = - GetSmallFileRequestProto - .newBuilder().setBlock(getBlock) - .build(); - String id = client.getPipeline().getLeader().getUuidString(); - - ContainerCommandRequestProto request = ContainerCommandRequestProto - .newBuilder() - .setCmdType(Type.GetSmallFile) - .setContainerID(blockID.getContainerID()) - .setTraceID(traceID) - .setDatanodeUuid(id) - .setGetSmallFile(getSmallFileRequest) - .build(); - ContainerCommandResponseProto response = client.sendCommand(request); - validateContainerResponse(response); - - return response.getGetSmallFile(); - } - - /** - * Validates a response from a container protocol call. Any non-successful - * return code is mapped to a corresponding exception and thrown. - * - * @param response container protocol call response - * @throws IOException if the container protocol call failed - */ - private static void validateContainerResponse( - ContainerCommandResponseProto response - ) throws StorageContainerException { - if (response.getResult() == ContainerProtos.Result.SUCCESS) { - return; - } else if (response.getResult() - == ContainerProtos.Result.BLOCK_NOT_COMMITTED) { - throw new BlockNotCommittedException(response.getMessage()); - } - throw new StorageContainerException( - response.getMessage(), response.getResult()); - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/storage/package-info.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/storage/package-info.java deleted file mode 100644 index 8e981586bd6..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/storage/package-info.java +++ /dev/null @@ -1,23 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.storage; - -/** - * This package contains StorageContainerManager classes. - */ diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneAcl.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneAcl.java deleted file mode 100644 index 1827b23bf15..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneAcl.java +++ /dev/null @@ -1,233 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package org.apache.hadoop.ozone; - -import java.util.Objects; - -/** - * OzoneACL classes define bucket ACLs used in OZONE. - * - * ACLs in Ozone follow this pattern. - *

    - *
  • user:name:rw - *
  • group:name:rw - *
  • world::rw - *
- */ -public class OzoneAcl { - private OzoneACLType type; - private String name; - private OzoneACLRights rights; - - /** - * Constructor for OzoneAcl. - */ - public OzoneAcl() { - } - - /** - * Constructor for OzoneAcl. - * - * @param type - Type - * @param name - Name of user - * @param rights - Rights - */ - public OzoneAcl(OzoneACLType type, String name, OzoneACLRights rights) { - this.name = name; - this.rights = rights; - this.type = type; - if (type == OzoneACLType.WORLD && name.length() != 0) { - throw new IllegalArgumentException("Unexpected name part in world type"); - } - if (((type == OzoneACLType.USER) || (type == OzoneACLType.GROUP)) - && (name.length() == 0)) { - throw new IllegalArgumentException("User or group name is required"); - } - } - - /** - * Parses an ACL string and returns the ACL object. - * - * @param acl - Acl String , Ex. user:anu:rw - * - * @return - Ozone ACLs - */ - public static OzoneAcl parseAcl(String acl) throws IllegalArgumentException { - if ((acl == null) || acl.isEmpty()) { - throw new IllegalArgumentException("ACLs cannot be null or empty"); - } - String[] parts = acl.trim().split(":"); - if (parts.length < 3) { - throw new IllegalArgumentException("ACLs are not in expected format"); - } - - OzoneACLType aclType = OzoneACLType.valueOf(parts[0].toUpperCase()); - OzoneACLRights rights = OzoneACLRights.getACLRight(parts[2].toLowerCase()); - - // TODO : Support sanitation of these user names by calling into - // userAuth Interface. - return new OzoneAcl(aclType, parts[1], rights); - } - - @Override - public String toString() { - return type + ":" + name + ":" + OzoneACLRights.getACLRightsString(rights); - } - - /** - * Returns a hash code value for the object. This method is - * supported for the benefit of hash tables. - * - * @return a hash code value for this object. - * - * @see Object#equals(Object) - * @see System#identityHashCode - */ - @Override - public int hashCode() { - return Objects.hash(this.getName(), this.getRights().toString(), - this.getType().toString()); - } - - /** - * Returns name. - * - * @return name - */ - public String getName() { - return name; - } - - /** - * Returns Rights. - * - * @return - Rights - */ - public OzoneACLRights getRights() { - return rights; - } - - /** - * Returns Type. - * - * @return type - */ - public OzoneACLType getType() { - return type; - } - - /** - * Indicates whether some other object is "equal to" this one. - * - * @param obj the reference object with which to compare. - * - * @return {@code true} if this object is the same as the obj - * argument; {@code false} otherwise. - */ - @Override - public boolean equals(Object obj) { - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - OzoneAcl otherAcl = (OzoneAcl) obj; - return otherAcl.getName().equals(this.getName()) && - otherAcl.getRights() == this.getRights() && - otherAcl.getType() == this.getType(); - } - - /** - * ACL types. - */ - public enum OzoneACLType { - USER(OzoneConsts.OZONE_ACL_USER_TYPE), - GROUP(OzoneConsts.OZONE_ACL_GROUP_TYPE), - WORLD(OzoneConsts.OZONE_ACL_WORLD_TYPE); - - /** - * String value for this Enum. - */ - private final String value; - - /** - * Init OzoneACLtypes enum. - * - * @param val String type for this enum. - */ - OzoneACLType(String val) { - value = val; - } - } - - /** - * ACL rights. - */ - public enum OzoneACLRights { - READ, WRITE, READ_WRITE; - - /** - * Returns the ACL rights based on passed in String. - * - * @param type ACL right string - * - * @return OzoneACLRights - */ - public static OzoneACLRights getACLRight(String type) { - if (type == null || type.isEmpty()) { - throw new IllegalArgumentException("ACL right cannot be empty"); - } - - switch (type) { - case OzoneConsts.OZONE_ACL_READ: - return OzoneACLRights.READ; - case OzoneConsts.OZONE_ACL_WRITE: - return OzoneACLRights.WRITE; - case OzoneConsts.OZONE_ACL_READ_WRITE: - case OzoneConsts.OZONE_ACL_WRITE_READ: - return OzoneACLRights.READ_WRITE; - default: - throw new IllegalArgumentException("ACL right is not recognized"); - } - - } - - /** - * Returns String representation of ACL rights. - * @param acl OzoneACLRights - * @return String representation of acl - */ - public static String getACLRightsString(OzoneACLRights acl) { - switch(acl) { - case READ: - return OzoneConsts.OZONE_ACL_READ; - case WRITE: - return OzoneConsts.OZONE_ACL_WRITE; - case READ_WRITE: - return OzoneConsts.OZONE_ACL_READ_WRITE; - default: - throw new IllegalArgumentException("ACL right is not recognized"); - } - } - - } - -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneConfigKeys.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneConfigKeys.java deleted file mode 100644 index 599b4e80bf2..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneConfigKeys.java +++ /dev/null @@ -1,308 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.classification.InterfaceStability; -import org.apache.hadoop.hdds.client.ReplicationFactor; -import org.apache.hadoop.hdds.client.ReplicationType; -import org.apache.hadoop.hdds.scm.ScmConfigKeys; - -import org.apache.ratis.shaded.proto.RaftProtos.ReplicationLevel; -import org.apache.ratis.util.TimeDuration; - -/** - * This class contains constants for configuration keys used in Ozone. - */ -@InterfaceAudience.Public -@InterfaceStability.Unstable -public final class OzoneConfigKeys { - public static final String OZONE_TAGS_SYSTEM_KEY = - "ozone.tags.system"; - public static final String DFS_CONTAINER_IPC_PORT = - "dfs.container.ipc"; - public static final int DFS_CONTAINER_IPC_PORT_DEFAULT = 9859; - - /** - * - * When set to true, allocate a random free port for ozone container, - * so that a mini cluster is able to launch multiple containers on a node. - * - * When set to false (default), container port is fixed as specified by - * DFS_CONTAINER_IPC_PORT_DEFAULT. - */ - public static final String DFS_CONTAINER_IPC_RANDOM_PORT = - "dfs.container.ipc.random.port"; - public static final boolean DFS_CONTAINER_IPC_RANDOM_PORT_DEFAULT = - false; - - /** - * Ratis Port where containers listen to. - */ - public static final String DFS_CONTAINER_RATIS_IPC_PORT = - "dfs.container.ratis.ipc"; - public static final int DFS_CONTAINER_RATIS_IPC_PORT_DEFAULT = 9858; - - /** - * When set to true, allocate a random free port for ozone container, so that - * a mini cluster is able to launch multiple containers on a node. - */ - public static final String DFS_CONTAINER_RATIS_IPC_RANDOM_PORT = - "dfs.container.ratis.ipc.random.port"; - public static final boolean DFS_CONTAINER_RATIS_IPC_RANDOM_PORT_DEFAULT = - false; - public static final String OZONE_ENABLED = - "ozone.enabled"; - public static final boolean OZONE_ENABLED_DEFAULT = false; - public static final String OZONE_TRACE_ENABLED_KEY = - "ozone.trace.enabled"; - public static final boolean OZONE_TRACE_ENABLED_DEFAULT = false; - - public static final String OZONE_METADATA_DIRS = - "ozone.metadata.dirs"; - - public static final String OZONE_METADATA_STORE_IMPL = - "ozone.metastore.impl"; - public static final String OZONE_METADATA_STORE_IMPL_LEVELDB = - "LevelDB"; - public static final String OZONE_METADATA_STORE_IMPL_ROCKSDB = - "RocksDB"; - public static final String OZONE_METADATA_STORE_IMPL_DEFAULT = - OZONE_METADATA_STORE_IMPL_ROCKSDB; - - public static final String OZONE_METADATA_STORE_ROCKSDB_STATISTICS = - "ozone.metastore.rocksdb.statistics"; - - public static final String OZONE_METADATA_STORE_ROCKSDB_STATISTICS_DEFAULT = - "ALL"; - public static final String OZONE_METADATA_STORE_ROCKSDB_STATISTICS_OFF = - "OFF"; - - public static final String OZONE_CONTAINER_CACHE_SIZE = - "ozone.container.cache.size"; - public static final int OZONE_CONTAINER_CACHE_DEFAULT = 1024; - - public static final String OZONE_SCM_BLOCK_SIZE_IN_MB = - "ozone.scm.block.size.in.mb"; - public static final long OZONE_SCM_BLOCK_SIZE_DEFAULT = 256; - - /** - * Ozone administrator users delimited by comma. - * If not set, only the user who launches an ozone service will be the - * admin user. This property must be set if ozone services are started by - * different users. Otherwise the RPC layer will reject calls from - * other servers which are started by users not in the list. - * */ - public static final String OZONE_ADMINISTRATORS = - "ozone.administrators"; - - public static final String OZONE_CLIENT_PROTOCOL = - "ozone.client.protocol"; - - // This defines the overall connection limit for the connection pool used in - // RestClient. - public static final String OZONE_REST_CLIENT_HTTP_CONNECTION_MAX = - "ozone.rest.client.http.connection.max"; - public static final int OZONE_REST_CLIENT_HTTP_CONNECTION_DEFAULT = 100; - - // This defines the connection limit per one HTTP route/host. - public static final String OZONE_REST_CLIENT_HTTP_CONNECTION_PER_ROUTE_MAX = - "ozone.rest.client.http.connection.per-route.max"; - - public static final int - OZONE_REST_CLIENT_HTTP_CONNECTION_PER_ROUTE_MAX_DEFAULT = 20; - - public static final String OZONE_CLIENT_SOCKET_TIMEOUT = - "ozone.client.socket.timeout"; - public static final int OZONE_CLIENT_SOCKET_TIMEOUT_DEFAULT = 5000; - public static final String OZONE_CLIENT_CONNECTION_TIMEOUT = - "ozone.client.connection.timeout"; - public static final int OZONE_CLIENT_CONNECTION_TIMEOUT_DEFAULT = 5000; - - public static final String OZONE_REPLICATION = "ozone.replication"; - public static final int OZONE_REPLICATION_DEFAULT = - ReplicationFactor.THREE.getValue(); - - public static final String OZONE_REPLICATION_TYPE = "ozone.replication.type"; - public static final String OZONE_REPLICATION_TYPE_DEFAULT = - ReplicationType.RATIS.toString(); - - /** - * Configuration property to configure the cache size of client list calls. - */ - public static final String OZONE_CLIENT_LIST_CACHE_SIZE = - "ozone.client.list.cache"; - public static final int OZONE_CLIENT_LIST_CACHE_SIZE_DEFAULT = 1000; - - /** - * Configuration properties for Ozone Block Deleting Service. - */ - public static final String OZONE_BLOCK_DELETING_SERVICE_INTERVAL = - "ozone.block.deleting.service.interval"; - public static final String OZONE_BLOCK_DELETING_SERVICE_INTERVAL_DEFAULT - = "60s"; - - /** - * The interval of open key clean service. - */ - public static final String OZONE_OPEN_KEY_CLEANUP_SERVICE_INTERVAL_SECONDS = - "ozone.open.key.cleanup.service.interval.seconds"; - public static final int - OZONE_OPEN_KEY_CLEANUP_SERVICE_INTERVAL_SECONDS_DEFAULT - = 24 * 3600; // a total of 24 hour - - /** - * An open key gets cleaned up when it is being in open state for too long. - */ - public static final String OZONE_OPEN_KEY_EXPIRE_THRESHOLD_SECONDS = - "ozone.open.key.expire.threshold"; - public static final int OZONE_OPEN_KEY_EXPIRE_THRESHOLD_SECONDS_DEFAULT = - 24 * 3600; - - public static final String OZONE_BLOCK_DELETING_SERVICE_TIMEOUT = - "ozone.block.deleting.service.timeout"; - public static final String OZONE_BLOCK_DELETING_SERVICE_TIMEOUT_DEFAULT - = "300s"; // 300s for default - - public static final String OZONE_KEY_PREALLOCATION_MAXSIZE = - "ozone.key.preallocation.maxsize"; - public static final long OZONE_KEY_PREALLOCATION_MAXSIZE_DEFAULT - = 128 * OzoneConsts.MB; - - public static final String OZONE_BLOCK_DELETING_LIMIT_PER_CONTAINER = - "ozone.block.deleting.limit.per.task"; - public static final int OZONE_BLOCK_DELETING_LIMIT_PER_CONTAINER_DEFAULT - = 1000; - - public static final String OZONE_BLOCK_DELETING_CONTAINER_LIMIT_PER_INTERVAL - = "ozone.block.deleting.container.limit.per.interval"; - public static final int - OZONE_BLOCK_DELETING_CONTAINER_LIMIT_PER_INTERVAL_DEFAULT = 10; - - public static final String OZONE_CLIENT_MAX_RETRIES = - "ozone.client.max.retries"; - public static final int OZONE_CLIENT_MAX_RETRIES_DEFAULT = 50; - - public static final String OZONE_CLIENT_RETRY_INTERVAL = - "ozone.client.retry.interval"; - public static final String OZONE_CLIENT_RETRY_INTERVAL_DEFAULT = "200ms"; - - public static final String DFS_CONTAINER_RATIS_ENABLED_KEY - = ScmConfigKeys.DFS_CONTAINER_RATIS_ENABLED_KEY; - public static final boolean DFS_CONTAINER_RATIS_ENABLED_DEFAULT - = ScmConfigKeys.DFS_CONTAINER_RATIS_ENABLED_DEFAULT; - public static final String DFS_CONTAINER_RATIS_RPC_TYPE_KEY - = ScmConfigKeys.DFS_CONTAINER_RATIS_RPC_TYPE_KEY; - public static final String DFS_CONTAINER_RATIS_RPC_TYPE_DEFAULT - = ScmConfigKeys.DFS_CONTAINER_RATIS_RPC_TYPE_DEFAULT; - public static final String DFS_CONTAINER_RATIS_NUM_WRITE_CHUNK_THREADS_KEY - = ScmConfigKeys.DFS_CONTAINER_RATIS_NUM_WRITE_CHUNK_THREADS_KEY; - public static final int DFS_CONTAINER_RATIS_NUM_WRITE_CHUNK_THREADS_DEFAULT - = ScmConfigKeys.DFS_CONTAINER_RATIS_NUM_WRITE_CHUNK_THREADS_DEFAULT; - public static final String DFS_CONTAINER_RATIS_REPLICATION_LEVEL_KEY - = ScmConfigKeys.DFS_CONTAINER_RATIS_REPLICATION_LEVEL_KEY; - public static final ReplicationLevel - DFS_CONTAINER_RATIS_REPLICATION_LEVEL_DEFAULT - = ScmConfigKeys.DFS_CONTAINER_RATIS_REPLICATION_LEVEL_DEFAULT; - public static final String DFS_CONTAINER_RATIS_SEGMENT_SIZE_KEY - = ScmConfigKeys.DFS_CONTAINER_RATIS_SEGMENT_SIZE_KEY; - public static final int DFS_CONTAINER_RATIS_SEGMENT_SIZE_DEFAULT - = ScmConfigKeys.DFS_CONTAINER_RATIS_SEGMENT_SIZE_DEFAULT; - public static final String DFS_CONTAINER_RATIS_SEGMENT_PREALLOCATED_SIZE_KEY - = ScmConfigKeys.DFS_CONTAINER_RATIS_SEGMENT_PREALLOCATED_SIZE_KEY; - public static final int DFS_CONTAINER_RATIS_SEGMENT_PREALLOCATED_SIZE_DEFAULT - = ScmConfigKeys.DFS_CONTAINER_RATIS_SEGMENT_PREALLOCATED_SIZE_DEFAULT; - public static final int DFS_CONTAINER_CHUNK_MAX_SIZE - = ScmConfigKeys.OZONE_SCM_CHUNK_MAX_SIZE; - public static final String DFS_CONTAINER_RATIS_DATANODE_STORAGE_DIR = - "dfs.container.ratis.datanode.storage.dir"; - public static final String DFS_RATIS_CLIENT_REQUEST_TIMEOUT_DURATION_KEY = - ScmConfigKeys.DFS_RATIS_CLIENT_REQUEST_TIMEOUT_DURATION_KEY; - public static final TimeDuration - DFS_RATIS_CLIENT_REQUEST_TIMEOUT_DURATION_DEFAULT = - ScmConfigKeys.DFS_RATIS_CLIENT_REQUEST_TIMEOUT_DURATION_DEFAULT; - public static final String DFS_RATIS_CLIENT_REQUEST_MAX_RETRIES_KEY = - ScmConfigKeys.DFS_RATIS_CLIENT_REQUEST_MAX_RETRIES_KEY; - public static final int DFS_RATIS_CLIENT_REQUEST_MAX_RETRIES_DEFAULT = - ScmConfigKeys.DFS_RATIS_CLIENT_REQUEST_MAX_RETRIES_DEFAULT; - public static final String DFS_RATIS_CLIENT_REQUEST_RETRY_INTERVAL_KEY = - ScmConfigKeys.DFS_RATIS_CLIENT_REQUEST_RETRY_INTERVAL_KEY; - public static final TimeDuration - DFS_RATIS_CLIENT_REQUEST_RETRY_INTERVAL_DEFAULT = - ScmConfigKeys.DFS_RATIS_CLIENT_REQUEST_RETRY_INTERVAL_DEFAULT; - public static final String DFS_RATIS_SERVER_RETRY_CACHE_TIMEOUT_DURATION_KEY = - ScmConfigKeys.DFS_RATIS_SERVER_RETRY_CACHE_TIMEOUT_DURATION_KEY; - public static final TimeDuration - DFS_RATIS_SERVER_RETRY_CACHE_TIMEOUT_DURATION_DEFAULT = - ScmConfigKeys.DFS_RATIS_SERVER_RETRY_CACHE_TIMEOUT_DURATION_DEFAULT; - public static final String DFS_RATIS_SERVER_REQUEST_TIMEOUT_DURATION_KEY = - ScmConfigKeys.DFS_RATIS_SERVER_REQUEST_TIMEOUT_DURATION_KEY; - public static final TimeDuration - DFS_RATIS_SERVER_REQUEST_TIMEOUT_DURATION_DEFAULT = - ScmConfigKeys.DFS_RATIS_SERVER_REQUEST_TIMEOUT_DURATION_DEFAULT; - public static final String - DFS_RATIS_LEADER_ELECTION_MINIMUM_TIMEOUT_DURATION_KEY = - ScmConfigKeys.DFS_RATIS_LEADER_ELECTION_MINIMUM_TIMEOUT_DURATION_KEY; - public static final TimeDuration - DFS_RATIS_LEADER_ELECTION_MINIMUM_TIMEOUT_DURATION_DEFAULT = - ScmConfigKeys.DFS_RATIS_LEADER_ELECTION_MINIMUM_TIMEOUT_DURATION_DEFAULT; - - public static final String DFS_RATIS_SERVER_FAILURE_DURATION_KEY = - ScmConfigKeys.DFS_RATIS_SERVER_FAILURE_DURATION_KEY; - public static final TimeDuration - DFS_RATIS_SERVER_FAILURE_DURATION_DEFAULT = - ScmConfigKeys.DFS_RATIS_SERVER_FAILURE_DURATION_DEFAULT; - - public static final String OZONE_SCM_WEB_AUTHENTICATION_KERBEROS_PRINCIPAL = - "ozone.web.authentication.kerberos.principal"; - - public static final String HDDS_DATANODE_PLUGINS_KEY = - "hdds.datanode.plugins"; - - public static final String - HDDS_DATANODE_STORAGE_UTILIZATION_WARNING_THRESHOLD = - "hdds.datanode.storage.utilization.warning.threshold"; - public static final double - HDDS_DATANODE_STORAGE_UTILIZATION_WARNING_THRESHOLD_DEFAULT = 0.95; - public static final String - HDDS_DATANODE_STORAGE_UTILIZATION_CRITICAL_THRESHOLD = - "hdds.datanode.storage.utilization.critical.threshold"; - public static final double - HDDS_DATANODE_STORAGE_UTILIZATION_CRITICAL_THRESHOLD_DEFAULT = 0.75; - - public static final String - HDDS_WRITE_LOCK_REPORTING_THRESHOLD_MS_KEY = - "hdds.write.lock.reporting.threshold.ms"; - public static final long - HDDS_WRITE_LOCK_REPORTING_THRESHOLD_MS_DEFAULT = 5000L; - public static final String - HDDS_LOCK_SUPPRESS_WARNING_INTERVAL_MS_KEY = - "hdds.lock.suppress.warning.interval.ms"; - public static final long - HDDS_LOCK_SUPPRESS_WARNING_INTERVAL_MS_DEAFULT = 10000L; - - public static final String OZONE_CONTAINER_COPY_WORKDIR = - "hdds.datanode.replication.work.dir"; - - /** - * There is no need to instantiate this class. - */ - private OzoneConfigKeys() { - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneConsts.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneConsts.java deleted file mode 100644 index 0a15ec8b6ec..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneConsts.java +++ /dev/null @@ -1,216 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone; - -import org.apache.hadoop.classification.InterfaceAudience; - -/** - * Set of constants used in Ozone implementation. - */ -@InterfaceAudience.Private -public final class OzoneConsts { - - - public static final String STORAGE_DIR = "scm"; - public static final String SCM_ID = "scmUuid"; - - public static final String OZONE_SIMPLE_ROOT_USER = "root"; - public static final String OZONE_SIMPLE_HDFS_USER = "hdfs"; - - public static final String STORAGE_ID = "storageID"; - public static final String DATANODE_UUID = "datanodeUuid"; - public static final String CLUSTER_ID = "clusterID"; - public static final String LAYOUTVERSION = "layOutVersion"; - public static final String CTIME = "ctime"; - /* - * BucketName length is used for both buckets and volume lengths - */ - public static final int OZONE_MIN_BUCKET_NAME_LENGTH = 3; - public static final int OZONE_MAX_BUCKET_NAME_LENGTH = 63; - - public static final String OZONE_ACL_USER_TYPE = "user"; - public static final String OZONE_ACL_GROUP_TYPE = "group"; - public static final String OZONE_ACL_WORLD_TYPE = "world"; - - public static final String OZONE_ACL_READ = "r"; - public static final String OZONE_ACL_WRITE = "w"; - public static final String OZONE_ACL_READ_WRITE = "rw"; - public static final String OZONE_ACL_WRITE_READ = "wr"; - - public static final String OZONE_DATE_FORMAT = - "EEE, dd MMM yyyy HH:mm:ss zzz"; - public static final String OZONE_TIME_ZONE = "GMT"; - - public static final String OZONE_COMPONENT = "component"; - public static final String OZONE_FUNCTION = "function"; - public static final String OZONE_RESOURCE = "resource"; - public static final String OZONE_USER = "user"; - public static final String OZONE_REQUEST = "request"; - - public static final String OZONE_URI_SCHEME = "o3"; - public static final String OZONE_HTTP_SCHEME = "http"; - public static final String OZONE_URI_DELIMITER = "/"; - - public static final String CONTAINER_EXTENSION = ".container"; - public static final String CONTAINER_META = ".meta"; - - // Refer to {@link ContainerReader} for container storage layout on disk. - public static final String CONTAINER_PREFIX = "containers"; - public static final String CONTAINER_META_PATH = "metadata"; - public static final String CONTAINER_TEMPORARY_CHUNK_PREFIX = "tmp"; - public static final String CONTAINER_CHUNK_NAME_DELIMITER = "."; - public static final String CONTAINER_ROOT_PREFIX = "repository"; - - public static final String FILE_HASH = "SHA-256"; - public final static String CHUNK_OVERWRITE = "OverWriteRequested"; - - public static final int CHUNK_SIZE = 1 * 1024 * 1024; // 1 MB - public static final long KB = 1024L; - public static final long MB = KB * 1024L; - public static final long GB = MB * 1024L; - public static final long TB = GB * 1024L; - - /** - * level DB names used by SCM and data nodes. - */ - public static final String CONTAINER_DB_SUFFIX = "container.db"; - public static final String PIPELINE_DB_SUFFIX = "pipeline.db"; - public static final String SCM_CONTAINER_DB = "scm-" + CONTAINER_DB_SUFFIX; - public static final String SCM_PIPELINE_DB = "scm-" + PIPELINE_DB_SUFFIX; - public static final String DN_CONTAINER_DB = "-dn-"+ CONTAINER_DB_SUFFIX; - public static final String DELETED_BLOCK_DB = "deletedBlock.db"; - public static final String OM_DB_NAME = "om.db"; - - public static final String STORAGE_DIR_CHUNKS = "chunks"; - - /** - * Supports Bucket Versioning. - */ - public enum Versioning { - NOT_DEFINED, ENABLED, DISABLED; - - public static Versioning getVersioning(boolean versioning) { - return versioning ? ENABLED : DISABLED; - } - } - - public static final String DELETING_KEY_PREFIX = "#deleting#"; - public static final String DELETED_KEY_PREFIX = "#deleted#"; - public static final String DELETE_TRANSACTION_KEY_PREFIX = "#delTX#"; - - /** - * OM LevelDB prefixes. - * - * OM DB stores metadata as KV pairs with certain prefixes, - * prefix is used to improve the performance to get related - * metadata. - * - * OM DB Schema: - * ---------------------------------------------------------- - * | KEY | VALUE | - * ---------------------------------------------------------- - * | $userName | VolumeList | - * ---------------------------------------------------------- - * | /#volumeName | VolumeInfo | - * ---------------------------------------------------------- - * | /#volumeName/#bucketName | BucketInfo | - * ---------------------------------------------------------- - * | /volumeName/bucketName/keyName | KeyInfo | - * ---------------------------------------------------------- - * | #deleting#/volumeName/bucketName/keyName | KeyInfo | - * ---------------------------------------------------------- - */ - - public static final String OM_KEY_PREFIX = "/"; - public static final String OM_USER_PREFIX = "$"; - - /** - * Max OM Quota size of 1024 PB. - */ - public static final long MAX_QUOTA_IN_BYTES = 1024L * 1024 * TB; - - /** - * Max number of keys returned per list buckets operation. - */ - public static final int MAX_LISTBUCKETS_SIZE = 1024; - - /** - * Max number of keys returned per list keys operation. - */ - public static final int MAX_LISTKEYS_SIZE = 1024; - - /** - * Max number of volumes returned per list volumes operation. - */ - public static final int MAX_LISTVOLUMES_SIZE = 1024; - - public static final int INVALID_PORT = -1; - - - // The ServiceListJSONServlet context attribute where OzoneManager - // instance gets stored. - public static final String OM_CONTEXT_ATTRIBUTE = "ozone.om"; - - private OzoneConsts() { - // Never Constructed - } - - // YAML fields for .container files - public static final String CONTAINER_ID = "containerID"; - public static final String CONTAINER_TYPE = "containerType"; - public static final String STATE = "state"; - public static final String METADATA = "metadata"; - public static final String MAX_SIZE = "maxSize"; - public static final String METADATA_PATH = "metadataPath"; - public static final String CHUNKS_PATH = "chunksPath"; - public static final String CONTAINER_DB_TYPE = "containerDBType"; - public static final String CHECKSUM = "checksum"; - - // For OM Audit usage - public static final String VOLUME = "volume"; - public static final String BUCKET = "bucket"; - public static final String KEY = "key"; - public static final String QUOTA = "quota"; - public static final String QUOTA_IN_BYTES = "quotaInBytes"; - public static final String CLIENT_ID = "clientID"; - public static final String OWNER = "owner"; - public static final String ADMIN = "admin"; - public static final String USERNAME = "username"; - public static final String PREV_KEY = "prevKey"; - public static final String START_KEY = "startKey"; - public static final String MAX_KEYS = "maxKeys"; - public static final String PREFIX = "prefix"; - public static final String KEY_PREFIX = "keyPrefix"; - public static final String ACLS = "acls"; - public static final String USER_ACL = "userAcl"; - public static final String ADD_ACLS = "addAcls"; - public static final String REMOVE_ACLS = "removeAcls"; - public static final String MAX_NUM_OF_BUCKETS = "maxNumOfBuckets"; - public static final String TO_KEY_NAME = "toKeyName"; - public static final String STORAGE_TYPE = "storageType"; - public static final String IS_VERSION_ENABLED = "isVersionEnabled"; - public static final String CREATION_TIME = "creationTime"; - public static final String DATA_SIZE = "dataSize"; - public static final String REPLICATION_TYPE = "replicationType"; - public static final String REPLICATION_FACTOR = "replicationFactor"; - public static final String KEY_LOCATION_INFO = "keyLocationInfo"; - - - -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/AuditAction.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/AuditAction.java deleted file mode 100644 index 8c1d6f0c67d..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/AuditAction.java +++ /dev/null @@ -1,30 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.audit; - -/** - * Interface to define AuditAction. - */ -public interface AuditAction { - /** - * Implementation must override. - * @return String - */ - String getAction(); -} - diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/AuditEventStatus.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/AuditEventStatus.java deleted file mode 100644 index 098ab6b2f7f..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/AuditEventStatus.java +++ /dev/null @@ -1,36 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.audit; - -/** - * Enum to define AuditEventStatus values. - */ -public enum AuditEventStatus { - SUCCESS("SUCCESS"), - FAILURE("FAILURE"); - - private String status; - - AuditEventStatus(String status){ - this.status = status; - } - - public String getStatus() { - return status; - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/AuditLogger.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/AuditLogger.java deleted file mode 100644 index 9357774313b..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/AuditLogger.java +++ /dev/null @@ -1,76 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.audit; - -import com.google.common.annotations.VisibleForTesting; -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Marker; -import org.apache.logging.log4j.spi.ExtendedLogger; - - -/** - * Class to define Audit Logger for Ozone. - */ -public class AuditLogger { - - private ExtendedLogger logger; - private static final String FQCN = AuditLogger.class.getName(); - private static final Marker WRITE_MARKER = AuditMarker.WRITE.getMarker(); - private static final Marker READ_MARKER = AuditMarker.READ.getMarker(); - - /** - * Parametrized Constructor to initialize logger. - * @param type Audit Logger Type - */ - public AuditLogger(AuditLoggerType type){ - initializeLogger(type); - } - - /** - * Initializes the logger with specific type. - * @param loggerType specified one of the values from enum AuditLoggerType. - */ - private void initializeLogger(AuditLoggerType loggerType){ - this.logger = LogManager.getContext(false).getLogger(loggerType.getType()); - } - - @VisibleForTesting - public ExtendedLogger getLogger() { - return logger; - } - - public void logWriteSuccess(AuditMessage msg) { - this.logger.logIfEnabled(FQCN, Level.INFO, WRITE_MARKER, msg, null); - } - - public void logWriteFailure(AuditMessage msg) { - this.logger.logIfEnabled(FQCN, Level.ERROR, WRITE_MARKER, msg, - msg.getThrowable()); - } - - public void logReadSuccess(AuditMessage msg) { - this.logger.logIfEnabled(FQCN, Level.INFO, READ_MARKER, msg, null); - } - - public void logReadFailure(AuditMessage msg) { - this.logger.logIfEnabled(FQCN, Level.ERROR, READ_MARKER, msg, - msg.getThrowable()); - } - -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/AuditLoggerType.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/AuditLoggerType.java deleted file mode 100644 index 18241c7712a..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/AuditLoggerType.java +++ /dev/null @@ -1,37 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.audit; - -/** - * Enumeration for defining types of Audit Loggers in Ozone. - */ -public enum AuditLoggerType { - DNLOGGER("DNAudit"), - OMLOGGER("OMAudit"), - SCMLOGGER("SCMAudit"); - - private String type; - - public String getType() { - return type; - } - - AuditLoggerType(String type){ - this.type = type; - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/AuditMarker.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/AuditMarker.java deleted file mode 100644 index 505b9580715..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/AuditMarker.java +++ /dev/null @@ -1,38 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.audit; - -import org.apache.logging.log4j.Marker; -import org.apache.logging.log4j.MarkerManager; - -/** - * Defines audit marker types. - */ -public enum AuditMarker { - WRITE(MarkerManager.getMarker("WRITE")), - READ(MarkerManager.getMarker("READ")); - - private Marker marker; - - AuditMarker(Marker marker){ - this.marker = marker; - } - - public Marker getMarker(){ - return marker; - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/AuditMessage.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/AuditMessage.java deleted file mode 100644 index 1569ffe3ba7..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/AuditMessage.java +++ /dev/null @@ -1,131 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.audit; - -import org.apache.logging.log4j.message.Message; - -import java.util.Map; - -/** - * Defines audit message structure. - */ -public class AuditMessage implements Message { - - private String message; - private Throwable throwable; - - private static final String MSG_PATTERN = - "user=%s | ip=%s | op=%s %s | ret=%s"; - - public AuditMessage(){ - - } - - @Override - public String getFormattedMessage() { - return message; - } - - @Override - public String getFormat() { - return null; - } - - @Override - public Object[] getParameters() { - return new Object[0]; - } - - @Override - public Throwable getThrowable() { - return throwable; - } - - /** - * Use when there are custom string to be added to default msg. - * @param customMessage custom string - */ - private void appendMessage(String customMessage) { - this.message += customMessage; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public void setThrowable(Throwable throwable) { - this.throwable = throwable; - } - - /** - * Builder class for AuditMessage. - */ - public static class Builder { - private Throwable throwable; - private String user; - private String ip; - private String op; - private Map params; - private String ret; - - public Builder(){ - - } - - public Builder setUser(String usr){ - this.user = usr; - return this; - } - - public Builder atIp(String ipAddr){ - this.ip = ipAddr; - return this; - } - - public Builder forOperation(String operation){ - this.op = operation; - return this; - } - - public Builder withParams(Map args){ - this.params = args; - return this; - } - - public Builder withResult(String result){ - this.ret = result; - return this; - } - - public Builder withException(Throwable ex){ - this.throwable = ex; - return this; - } - - public AuditMessage build(){ - AuditMessage auditMessage = new AuditMessage(); - auditMessage.message = String.format(MSG_PATTERN, - this.user, this.ip, this.op, this.params, this.ret); - auditMessage.throwable = this.throwable; - return auditMessage; - } - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/Auditable.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/Auditable.java deleted file mode 100644 index d388bca72f1..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/Auditable.java +++ /dev/null @@ -1,32 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.audit; - -import java.util.Map; - -/** - * Interface to make an entity auditable. - */ -public interface Auditable { - /** - * Must override in implementation. - * @return Map with values to be logged in audit. - */ - Map toAuditMap(); -} - diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/Auditor.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/Auditor.java deleted file mode 100644 index 51c029868bf..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/Auditor.java +++ /dev/null @@ -1,33 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.audit; - -import java.util.Map; - -/** - * Interface to mark an actor as Auditor. - */ -public interface Auditor { - - AuditMessage buildAuditMessageForSuccess( - AuditAction op, Map auditMap); - - AuditMessage buildAuditMessageForFailure( - AuditAction op, Map auditMap, Throwable throwable); - -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/package-info.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/package-info.java deleted file mode 100644 index c8284fd8ff3..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/package-info.java +++ /dev/null @@ -1,138 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.audit; -/** - ****************************************************************************** - * Important - * 1. Any changes to classes in this package can render the logging - * framework broken. - * 2. The logger framework has been designed keeping in mind future - * plans to build a log parser. - * 3. Please exercise great caution when attempting changes in this package. - ****************************************************************************** - * - * - * This package lays the foundation for Audit logging in Ozone. - * AuditLogging in Ozone has been built using log4j2 which brings in new - * features that facilitate turning on/off selective audit events by using - * MarkerFilter, checking for change in logging configuration periodically - * and reloading the changes, use of disruptor framework for improved - * Asynchronous logging. - * - * The log4j2 configurations can be specified in XML, YAML, JSON and - * Properties file. For Ozone, we are using the Properties file due to sheer - * simplicity, readability and ease of modification. - * - * log4j2 configuration file can be passed to startup command with option - * -Dlog4j.configurationFile unlike -Dlog4j.configuration in log4j 1.x - * - ****************************************************************************** - * Understanding the Audit Logging framework in Ozone. - ****************************************************************************** - * **** Auditable *** - * This is an interface to mark an entity as auditable. - * This interface must be implemented by entities requiring audit logging. - * For example - OMVolumeArgs, OMBucketArgs. - * The implementing class must override toAuditMap() to return an - * instance of Map where both Key and Value are String. - * - * Key: must contain printable US ASCII characters - * May not contain a space, =, ], or " - * If the key is multi word then use camel case. - * - * Value: if it is a collection/array, then it must be converted to a comma - * delimited string - * - * *** AuditAction *** - * This is an interface to define the various type of actions to be audited. - * To ensure separation of concern, for each sub-component you must create an - * Enum to implement AuditAction. - * Structure of Enum can be referred from the test class DummyAction. - * - * For starters, we expect following 3 implementations of AuditAction: - * OMAction - to define action types for Ozone Manager - * SCMAction - to define action types for Storage Container manager - * DNAction - to define action types for Datanode - * - * *** AuditEventStatus *** - * Enum to define Audit event status like success and failure. - * This is used in AuditLogger.logXXX() methods. - * - * * *** AuditLogger *** - * This is where the audit logging magic unfolds. - * The class has 2 Markers defined - READ and WRITE. - * These markers are used to tag when logging events. - * - * *** AuditLoggerType *** - * Enum to define the various AuditLoggers in Ozone - * - * *** AuditMarker *** - * Enum to define various Audit Markers used in AuditLogging. - * - * *** AuditMessage *** - * Entity to define an audit message to be logged - * It will generate a message formatted as: - * user=xxx ip=xxx op=XXXX_XXXX {key=val, key1=val1..} ret=XXXXXX - * - * *** Auditor *** - * Interface to mark an actor class as Auditor - * Must be implemented by class where we want to log audit events - * Implementing class must override and implement methods - * buildAuditMessageForSuccess and buildAuditMessageForFailure. - * - * **************************************************************************** - * Usage - * **************************************************************************** - * Using the AuditLogger to log events: - * 1. Get a logger by specifying the appropriate logger type - * Example: ExtendedLogger AUDIT = new AuditLogger(AuditLoggerType.OMLogger) - * - * 2. Construct an instance of AuditMessage - * - * 3. Log Read/Write and Success/Failure event as needed. - * Example - * AUDIT.logWriteSuccess(buildAuditMessageForSuccess(params)) - * - * 4. Log Level implicitly defaults to INFO for xxxxSuccess() and ERROR for - * xxxxFailure() - * AUDIT.logWriteSuccess(buildAuditMessageForSuccess(params)) - * AUDIT.logWriteFailure(buildAuditMessageForSuccess(params)) - * - * See sample invocations in src/test in the following class: - * org.apache.hadoop.ozone.audit.TestOzoneAuditLogger - * - * **************************************************************************** - * Defining new Logger types - * **************************************************************************** - * New Logger type can be added with following steps: - * 1. Update AuditLoggerType to add the new type - * 2. Create new Enum by implementing AuditAction if needed - * 3. Ensure the required entity implements Auditable - * - * **************************************************************************** - * Defining new Marker types - * **************************************************************************** - * New Markers can be configured as follows: - * 1. Define new markers in AuditMarker - * 2. Get the Marker in AuditLogger for use in the log methods, example: - * private static final Marker WRITE_MARKER = AuditMarker.WRITE.getMarker(); - * 3. Define log methods in AuditLogger to use the new Marker type - * 4. Call these new methods from the required classes to audit with these - * new markers - * 5. The marker based filtering can be configured in log4j2 configurations - * Refer log4j2.properties in src/test/resources for a sample. - */ diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/BlockGroup.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/BlockGroup.java deleted file mode 100644 index 7a5403f290d..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/BlockGroup.java +++ /dev/null @@ -1,97 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.common; - -import org.apache.hadoop.hdds.client.BlockID; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.protocol.proto.ScmBlockLocationProtocolProtos - .KeyBlocks; - -import java.util.ArrayList; -import java.util.List; - -/** - * A group of blocks relations relevant, e.g belong to a certain object key. - */ -public final class BlockGroup { - - private String groupID; - private List blockIDs; - private BlockGroup(String groupID, List blockIDs) { - this.groupID = groupID; - this.blockIDs = blockIDs; - } - - public List getBlockIDList() { - return blockIDs; - } - - public String getGroupID() { - return groupID; - } - - public KeyBlocks getProto() { - KeyBlocks.Builder kbb = KeyBlocks.newBuilder(); - for (BlockID block : blockIDs) { - kbb.addBlocks(block.getProtobuf()); - } - return kbb.setKey(groupID).build(); - } - - /** - * Parses a KeyBlocks proto to a group of blocks. - * @param proto KeyBlocks proto. - * @return a group of blocks. - */ - public static BlockGroup getFromProto(KeyBlocks proto) { - List blockIDs = new ArrayList<>(); - for (HddsProtos.BlockID block : proto.getBlocksList()) { - blockIDs.add(new BlockID(block.getContainerID(), block.getLocalID())); - } - return BlockGroup.newBuilder().setKeyName(proto.getKey()) - .addAllBlockIDs(blockIDs).build(); - } - - public static Builder newBuilder() { - return new Builder(); - } - - /** - * BlockGroup instance builder. - */ - public static class Builder { - - private String groupID; - private List blockIDs; - - public Builder setKeyName(String blockGroupID) { - this.groupID = blockGroupID; - return this; - } - - public Builder addAllBlockIDs(List keyBlocks) { - this.blockIDs = keyBlocks; - return this; - } - - public BlockGroup build() { - return new BlockGroup(groupID, blockIDs); - } - } - -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/DeleteBlockGroupResult.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/DeleteBlockGroupResult.java deleted file mode 100644 index 892b6951534..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/DeleteBlockGroupResult.java +++ /dev/null @@ -1,97 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.common; - -import org.apache.hadoop.hdds.client.BlockID; -import org.apache.hadoop.hdds.scm.container.common.helpers.DeleteBlockResult; -import org.apache.hadoop.hdds.protocol.proto.ScmBlockLocationProtocolProtos - .DeleteScmBlockResult; -import org.apache.hadoop.hdds.protocol.proto.ScmBlockLocationProtocolProtos - .DeleteScmBlockResult.Result; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -/** - * Result to delete a group of blocks. - */ -public class DeleteBlockGroupResult { - private String objectKey; - private List blockResultList; - public DeleteBlockGroupResult(String objectKey, - List blockResultList) { - this.objectKey = objectKey; - this.blockResultList = blockResultList; - } - - public String getObjectKey() { - return objectKey; - } - - public List getBlockResultList() { - return blockResultList; - } - - public List getBlockResultProtoList() { - List resultProtoList = - new ArrayList<>(blockResultList.size()); - for (DeleteBlockResult result : blockResultList) { - DeleteScmBlockResult proto = DeleteScmBlockResult.newBuilder() - .setBlockID(result.getBlockID().getProtobuf()) - .setResult(result.getResult()).build(); - resultProtoList.add(proto); - } - return resultProtoList; - } - - public static List convertBlockResultProto( - List results) { - List protoResults = new ArrayList<>(results.size()); - for (DeleteScmBlockResult result : results) { - protoResults.add(new DeleteBlockResult(BlockID.getFromProtobuf( - result.getBlockID()), result.getResult())); - } - return protoResults; - } - - /** - * Only if all blocks are successfully deleted, this group is considered - * to be successfully executed. - * - * @return true if all blocks are successfully deleted, false otherwise. - */ - public boolean isSuccess() { - for (DeleteBlockResult result : blockResultList) { - if (result.getResult() != Result.success) { - return false; - } - } - return true; - } - - /** - * @return A list of deletion failed block IDs. - */ - public List getFailedBlocks() { - List failedBlocks = blockResultList.stream() - .filter(result -> result.getResult() != Result.success) - .map(DeleteBlockResult::getBlockID).collect(Collectors.toList()); - return failedBlocks; - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/InconsistentStorageStateException.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/InconsistentStorageStateException.java deleted file mode 100644 index 518b5194781..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/InconsistentStorageStateException.java +++ /dev/null @@ -1,51 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.common; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.classification.InterfaceStability; - -import java.io.File; -import java.io.IOException; - -/** - * The exception is thrown when file system state is inconsistent - * and is not recoverable. - */ -@InterfaceAudience.Private -@InterfaceStability.Evolving -public class InconsistentStorageStateException extends IOException { - private static final long serialVersionUID = 1L; - - public InconsistentStorageStateException(String descr) { - super(descr); - } - - public InconsistentStorageStateException(File dir, String descr) { - super("Directory " + getFilePath(dir) + " is in an inconsistent state: " - + descr); - } - - private static String getFilePath(File dir) { - try { - return dir.getCanonicalPath(); - } catch (IOException e) { - } - return dir.getPath(); - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/Storage.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/Storage.java deleted file mode 100644 index 1826a58b023..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/Storage.java +++ /dev/null @@ -1,249 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.common; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.fs.FileUtil; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeType; -import org.apache.hadoop.util.Time; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.nio.file.DirectoryStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Properties; - -/** - * Storage information file. This Class defines the methods to check - * the consistency of the storage dir and the version file. - *

- * Local storage information is stored in a separate file VERSION. - * It contains type of the node, - * the storage layout version, the SCM id, and - * the OM/SCM state creation time. - * - */ -@InterfaceAudience.Private -public abstract class Storage { - private static final Logger LOG = LoggerFactory.getLogger(Storage.class); - - public static final String STORAGE_DIR_CURRENT = "current"; - protected static final String STORAGE_FILE_VERSION = "VERSION"; - public static final String CONTAINER_DIR = "containerDir"; - - private final NodeType nodeType; - private final File root; - private final File storageDir; - - private StorageState state; - private StorageInfo storageInfo; - - - /** - * Determines the state of the Version file. - */ - public enum StorageState { - NON_EXISTENT, NOT_INITIALIZED, INITIALIZED - } - - public Storage(NodeType type, File root, String sdName) - throws IOException { - this.nodeType = type; - this.root = root; - this.storageDir = new File(root, sdName); - this.state = getStorageState(); - if (state == StorageState.INITIALIZED) { - this.storageInfo = new StorageInfo(type, getVersionFile()); - } else { - this.storageInfo = new StorageInfo( - nodeType, StorageInfo.newClusterID(), Time.now()); - setNodeProperties(); - } - } - - /** - * Gets the path of the Storage dir. - * @return Stoarge dir path - */ - public String getStorageDir() { - return storageDir.getAbsoluteFile().toString(); - } - - /** - * Gets the state of the version file. - * @return the state of the Version file - */ - public StorageState getState() { - return state; - } - - public NodeType getNodeType() { - return storageInfo.getNodeType(); - } - - public String getClusterID() { - return storageInfo.getClusterID(); - } - - public long getCreationTime() { - return storageInfo.getCreationTime(); - } - - public void setClusterId(String clusterId) throws IOException { - if (state == StorageState.INITIALIZED) { - throw new IOException( - "Storage directory " + storageDir + " already initialized."); - } else { - storageInfo.setClusterId(clusterId); - } - } - - /** - * Retreives the storageInfo instance to read/write the common - * version file properties. - * @return the instance of the storageInfo class - */ - protected StorageInfo getStorageInfo() { - return storageInfo; - } - - abstract protected Properties getNodeProperties(); - - /** - * Sets the Node properties spaecific to OM/SCM. - */ - private void setNodeProperties() { - Properties nodeProperties = getNodeProperties(); - if (nodeProperties != null) { - for (String key : nodeProperties.stringPropertyNames()) { - storageInfo.setProperty(key, nodeProperties.getProperty(key)); - } - } - } - - /** - * Directory {@code current} contains latest files defining - * the file system meta-data. - * - * @return the directory path - */ - private File getCurrentDir() { - return new File(storageDir, STORAGE_DIR_CURRENT); - } - - /** - * File {@code VERSION} contains the following fields: - *

    - *
  1. node type
  2. - *
  3. OM/SCM state creation time
  4. - *
  5. other fields specific for this node type
  6. - *
- * The version file is always written last during storage directory updates. - * The existence of the version file indicates that all other files have - * been successfully written in the storage directory, the storage is valid - * and does not need to be recovered. - * - * @return the version file path - */ - private File getVersionFile() { - return new File(getCurrentDir(), STORAGE_FILE_VERSION); - } - - - /** - * Check to see if current/ directory is empty. This method is used - * before determining to format the directory. - * @throws IOException if unable to list files under the directory. - */ - private void checkEmptyCurrent() throws IOException { - File currentDir = getCurrentDir(); - if (!currentDir.exists()) { - // if current/ does not exist, it's safe to format it. - return; - } - try (DirectoryStream dirStream = Files - .newDirectoryStream(currentDir.toPath())) { - if (dirStream.iterator().hasNext()) { - throw new InconsistentStorageStateException(getCurrentDir(), - "Can't initialize the storage directory because the current " - + "it is not empty."); - } - } - } - - /** - * Check consistency of the storage directory. - * - * @return state {@link StorageState} of the storage directory - * @throws IOException - */ - private StorageState getStorageState() throws IOException { - assert root != null : "root is null"; - String rootPath = root.getCanonicalPath(); - try { // check that storage exists - if (!root.exists()) { - // storage directory does not exist - LOG.warn("Storage directory " + rootPath + " does not exist"); - return StorageState.NON_EXISTENT; - } - // or is inaccessible - if (!root.isDirectory()) { - LOG.warn(rootPath + "is not a directory"); - return StorageState.NON_EXISTENT; - } - if (!FileUtil.canWrite(root)) { - LOG.warn("Cannot access storage directory " + rootPath); - return StorageState.NON_EXISTENT; - } - } catch (SecurityException ex) { - LOG.warn("Cannot access storage directory " + rootPath, ex); - return StorageState.NON_EXISTENT; - } - - // check whether current directory is valid - File versionFile = getVersionFile(); - boolean hasCurrent = versionFile.exists(); - - if (hasCurrent) { - return StorageState.INITIALIZED; - } else { - checkEmptyCurrent(); - return StorageState.NOT_INITIALIZED; - } - } - - /** - * Creates the Version file if not present, - * otherwise returns with IOException. - * @throws IOException - */ - public void initialize() throws IOException { - if (state == StorageState.INITIALIZED) { - throw new IOException("Storage directory already initialized."); - } - if (!getCurrentDir().mkdirs()) { - throw new IOException("Cannot create directory " + getCurrentDir()); - } - storageInfo.writeTo(getVersionFile()); - } - -} - diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/StorageInfo.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/StorageInfo.java deleted file mode 100644 index 0e98a4c8a9f..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/StorageInfo.java +++ /dev/null @@ -1,183 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.common; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeType; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.util.Properties; -import java.util.UUID; - -/** - * Common class for storage information. This class defines the common - * properties and functions to set them , write them into the version file - * and read them from the version file. - * - */ -@InterfaceAudience.Private -public class StorageInfo { - - private Properties properties = new Properties(); - - /** - * Property to hold node type. - */ - private static final String NODE_TYPE = "nodeType"; - /** - * Property to hold ID of the cluster. - */ - private static final String CLUSTER_ID = "clusterID"; - /** - * Property to hold creation time of the storage. - */ - private static final String CREATION_TIME = "cTime"; - - /** - * Constructs StorageInfo instance. - * @param type - * Type of the node using the storage - * @param cid - * Cluster ID - * @param cT - * Cluster creation Time - - * @throws IOException - */ - public StorageInfo(NodeType type, String cid, long cT) - throws IOException { - Preconditions.checkNotNull(type); - Preconditions.checkNotNull(cid); - Preconditions.checkNotNull(cT); - properties.setProperty(NODE_TYPE, type.name()); - properties.setProperty(CLUSTER_ID, cid); - properties.setProperty(CREATION_TIME, String.valueOf(cT)); - } - - public StorageInfo(NodeType type, File propertiesFile) - throws IOException { - this.properties = readFrom(propertiesFile); - verifyNodeType(type); - verifyClusterId(); - verifyCreationTime(); - } - - public NodeType getNodeType() { - return NodeType.valueOf(properties.getProperty(NODE_TYPE)); - } - - public String getClusterID() { - return properties.getProperty(CLUSTER_ID); - } - - public Long getCreationTime() { - String creationTime = properties.getProperty(CREATION_TIME); - if(creationTime != null) { - return Long.parseLong(creationTime); - } - return null; - } - - public String getProperty(String key) { - return properties.getProperty(key); - } - - public void setProperty(String key, String value) { - properties.setProperty(key, value); - } - - public void setClusterId(String clusterId) { - properties.setProperty(CLUSTER_ID, clusterId); - } - - private void verifyNodeType(NodeType type) - throws InconsistentStorageStateException { - NodeType nodeType = getNodeType(); - Preconditions.checkNotNull(nodeType); - if(type != nodeType) { - throw new InconsistentStorageStateException("Expected NodeType: " + type + - ", but found: " + nodeType); - } - } - - private void verifyClusterId() - throws InconsistentStorageStateException { - String clusterId = getClusterID(); - Preconditions.checkNotNull(clusterId); - if(clusterId.isEmpty()) { - throw new InconsistentStorageStateException("Cluster ID not found"); - } - } - - private void verifyCreationTime() { - Long creationTime = getCreationTime(); - Preconditions.checkNotNull(creationTime); - } - - - public void writeTo(File to) - throws IOException { - try (RandomAccessFile file = new RandomAccessFile(to, "rws"); - FileOutputStream out = new FileOutputStream(file.getFD())) { - file.seek(0); - /* - * If server is interrupted before this line, - * the version file will remain unchanged. - */ - properties.store(out, null); - /* - * Now the new fields are flushed to the head of the file, but file - * length can still be larger then required and therefore the file can - * contain whole or corrupted fields from its old contents in the end. - * If server is interrupted here and restarted later these extra fields - * either should not effect server behavior or should be handled - * by the server correctly. - */ - file.setLength(out.getChannel().position()); - } - } - - private Properties readFrom(File from) throws IOException { - try (RandomAccessFile file = new RandomAccessFile(from, "rws"); - FileInputStream in = new FileInputStream(file.getFD())) { - Properties props = new Properties(); - file.seek(0); - props.load(in); - return props; - } - } - - /** - * Generate new clusterID. - * - * clusterID is a persistent attribute of the cluster. - * It is generated when the cluster is created and remains the same - * during the life cycle of the cluster. When a new SCM node is initialized, - * if this is a new cluster, a new clusterID is generated and stored. - * @return new clusterID - */ - public static String newClusterID() { - return "CID-" + UUID.randomUUID().toString(); - } - -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/package-info.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/package-info.java deleted file mode 100644 index 6517e5897ea..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/package-info.java +++ /dev/null @@ -1,18 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.common; \ No newline at end of file diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/statemachine/InvalidStateTransitionException.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/statemachine/InvalidStateTransitionException.java deleted file mode 100644 index 9aeff248381..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/statemachine/InvalidStateTransitionException.java +++ /dev/null @@ -1,42 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.common.statemachine; - -/** - * Class wraps invalid state transition exception. - */ -public class InvalidStateTransitionException extends Exception { - private Enum currentState; - private Enum event; - - public InvalidStateTransitionException(Enum currentState, Enum event) { - super("Invalid event: " + event + " at " + currentState + " state."); - this.currentState = currentState; - this.event = event; - } - - public Enum getCurrentState() { - return currentState; - } - - public Enum getEvent() { - return event; - } - -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/statemachine/StateMachine.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/statemachine/StateMachine.java deleted file mode 100644 index bf8cbd596ed..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/statemachine/StateMachine.java +++ /dev/null @@ -1,68 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.common.statemachine; - -import com.google.common.base.Supplier; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -/** - * Template class that wraps simple event driven state machine. - * @param states allowed - * @param events allowed - */ -public class StateMachine, EVENT extends Enum> { - private STATE initialState; - private Set finalStates; - - private final LoadingCache> transitions = - CacheBuilder.newBuilder().build( - CacheLoader.from((Supplier>) () -> new HashMap())); - - public StateMachine(STATE initState, Set finalStates) { - this.initialState = initState; - this.finalStates = finalStates; - } - - public STATE getInitialState() { - return initialState; - } - - public Set getFinalStates() { - return finalStates; - } - - public STATE getNextState(STATE from, EVENT e) - throws InvalidStateTransitionException { - STATE target = transitions.getUnchecked(e).get(from); - if (target == null) { - throw new InvalidStateTransitionException(from, e); - } - return target; - } - - public void addTransition(STATE from, STATE to, EVENT e) { - transitions.getUnchecked(e).put(from, to); - } -} \ No newline at end of file diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/statemachine/package-info.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/statemachine/package-info.java deleted file mode 100644 index 045409e3ed2..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/common/statemachine/package-info.java +++ /dev/null @@ -1,21 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.common.statemachine; -/** - state machine template class for ozone. - **/ \ No newline at end of file diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/container/common/helpers/BlockData.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/container/common/helpers/BlockData.java deleted file mode 100644 index 0c1d4277756..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/container/common/helpers/BlockData.java +++ /dev/null @@ -1,255 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.common.helpers; - -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdds.client.BlockID; -import com.google.common.base.Preconditions; - -import java.io.IOException; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; -import java.util.ArrayList; - -/** - * Helper class to convert Protobuf to Java classes. - */ -public class BlockData { - private final BlockID blockID; - private final Map metadata; - - /** - * Represent a list of chunks. - * In order to reduce memory usage, chunkList is declared as an - * {@link Object}. - * When #elements == 0, chunkList is null. - * When #elements == 1, chunkList refers to the only element. - * When #elements > 1, chunkList refers to the list. - * - * Please note : when we are working with blocks, we don't care what they - * point to. So we We don't read chunkinfo nor validate them. It is - * responsibility of higher layer like ozone. We just read and write data - * from network. - */ - private Object chunkList; - - /** - * total size of the key. - */ - private long size; - - /** - * Constructs a BlockData Object. - * - * @param blockID - */ - public BlockData(BlockID blockID) { - this.blockID = blockID; - this.metadata = new TreeMap<>(); - this.size = 0; - } - - /** - * Returns a blockData object from the protobuf data. - * - * @param data - Protobuf data. - * @return - BlockData - * @throws IOException - */ - public static BlockData getFromProtoBuf(ContainerProtos.BlockData data) throws - IOException { - BlockData blockData = new BlockData( - BlockID.getFromProtobuf(data.getBlockID())); - for (int x = 0; x < data.getMetadataCount(); x++) { - blockData.addMetadata(data.getMetadata(x).getKey(), - data.getMetadata(x).getValue()); - } - blockData.setChunks(data.getChunksList()); - if (data.hasSize()) { - Preconditions.checkArgument(data.getSize() == blockData.getSize()); - } - return blockData; - } - - /** - * Returns a Protobuf message from BlockData. - * @return Proto Buf Message. - */ - public ContainerProtos.BlockData getProtoBufMessage() { - ContainerProtos.BlockData.Builder builder = - ContainerProtos.BlockData.newBuilder(); - builder.setBlockID(this.blockID.getDatanodeBlockIDProtobuf()); - for (Map.Entry entry : metadata.entrySet()) { - ContainerProtos.KeyValue.Builder keyValBuilder = - ContainerProtos.KeyValue.newBuilder(); - builder.addMetadata(keyValBuilder.setKey(entry.getKey()) - .setValue(entry.getValue()).build()); - } - builder.addAllChunks(getChunks()); - builder.setSize(size); - return builder.build(); - } - - /** - * Adds metadata. - * - * @param key - Key - * @param value - Value - * @throws IOException - */ - public synchronized void addMetadata(String key, String value) throws - IOException { - if (this.metadata.containsKey(key)) { - throw new IOException("This key already exists. Key " + key); - } - metadata.put(key, value); - } - - public synchronized Map getMetadata() { - return Collections.unmodifiableMap(this.metadata); - } - - /** - * Returns value of a key. - */ - public synchronized String getValue(String key) { - return metadata.get(key); - } - - /** - * Deletes a metadata entry from the map. - * - * @param key - Key - */ - public synchronized void deleteKey(String key) { - metadata.remove(key); - } - - @SuppressWarnings("unchecked") - private List castChunkList() { - return (List)chunkList; - } - - /** - * Returns chunks list. - * - * @return list of chunkinfo. - */ - public List getChunks() { - return chunkList == null? Collections.emptyList() - : chunkList instanceof ContainerProtos.ChunkInfo? - Collections.singletonList((ContainerProtos.ChunkInfo)chunkList) - : Collections.unmodifiableList(castChunkList()); - } - - /** - * Adds chinkInfo to the list. - */ - public void addChunk(ContainerProtos.ChunkInfo chunkInfo) { - if (chunkList == null) { - chunkList = chunkInfo; - } else { - final List list; - if (chunkList instanceof ContainerProtos.ChunkInfo) { - list = new ArrayList<>(2); - list.add((ContainerProtos.ChunkInfo)chunkList); - chunkList = list; - } else { - list = castChunkList(); - } - list.add(chunkInfo); - } - size += chunkInfo.getLen(); - } - - /** - * removes the chunk. - */ - public boolean removeChunk(ContainerProtos.ChunkInfo chunkInfo) { - final boolean removed; - if (chunkList instanceof List) { - final List list = castChunkList(); - removed = list.remove(chunkInfo); - if (list.size() == 1) { - chunkList = list.get(0); - } - } else if (chunkInfo.equals(chunkList)) { - chunkList = null; - removed = true; - } else { - removed = false; - } - - if (removed) { - size -= chunkInfo.getLen(); - } - return removed; - } - - /** - * Returns container ID. - * - * @return long. - */ - public long getContainerID() { - return blockID.getContainerID(); - } - - /** - * Returns LocalID. - * @return long. - */ - public long getLocalID() { - return blockID.getLocalID(); - } - - /** - * Return Block ID. - * @return BlockID. - */ - public BlockID getBlockID() { - return blockID; - } - - /** - * Sets Chunk list. - * - * @param chunks - List of chunks. - */ - public void setChunks(List chunks) { - if (chunks == null) { - chunkList = null; - size = 0L; - } else { - final int n = chunks.size(); - chunkList = n == 0? null: n == 1? chunks.get(0): chunks; - size = chunks.parallelStream().mapToLong( - ContainerProtos.ChunkInfo::getLen).sum(); - } - } - - /** - * Get the total size of chunks allocated for the key. - * @return total size of the key. - */ - public long getSize() { - return size; - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/container/common/helpers/ChunkInfo.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/container/common/helpers/ChunkInfo.java deleted file mode 100644 index 21916b585e6..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/container/common/helpers/ChunkInfo.java +++ /dev/null @@ -1,184 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.helpers; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; - -import java.io.IOException; -import java.util.Map; -import java.util.TreeMap; - -/** - * Java class that represents ChunkInfo ProtoBuf class. This helper class allows - * us to convert to and from protobuf to normal java. - */ -public class ChunkInfo { - private final String chunkName; - private final long offset; - private final long len; - private String checksum; - private final Map metadata; - - - /** - * Constructs a ChunkInfo. - * - * @param chunkName - File Name where chunk lives. - * @param offset - offset where Chunk Starts. - * @param len - Length of the Chunk. - */ - public ChunkInfo(String chunkName, long offset, long len) { - this.chunkName = chunkName; - this.offset = offset; - this.len = len; - this.metadata = new TreeMap<>(); - } - - /** - * Adds metadata. - * - * @param key - Key Name. - * @param value - Value. - * @throws IOException - */ - public void addMetadata(String key, String value) throws IOException { - synchronized (this.metadata) { - if (this.metadata.containsKey(key)) { - throw new IOException("This key already exists. Key " + key); - } - metadata.put(key, value); - } - } - - /** - * Gets a Chunkinfo class from the protobuf definitions. - * - * @param info - Protobuf class - * @return ChunkInfo - * @throws IOException - */ - public static ChunkInfo getFromProtoBuf(ContainerProtos.ChunkInfo info) - throws IOException { - Preconditions.checkNotNull(info); - - ChunkInfo chunkInfo = new ChunkInfo(info.getChunkName(), info.getOffset(), - info.getLen()); - - for (int x = 0; x < info.getMetadataCount(); x++) { - chunkInfo.addMetadata(info.getMetadata(x).getKey(), - info.getMetadata(x).getValue()); - } - - - if (info.hasChecksum()) { - chunkInfo.setChecksum(info.getChecksum()); - } - return chunkInfo; - } - - /** - * Returns a ProtoBuf Message from ChunkInfo. - * - * @return Protocol Buffer Message - */ - public ContainerProtos.ChunkInfo getProtoBufMessage() { - ContainerProtos.ChunkInfo.Builder builder = ContainerProtos - .ChunkInfo.newBuilder(); - - builder.setChunkName(this.getChunkName()); - builder.setOffset(this.getOffset()); - builder.setLen(this.getLen()); - if (this.getChecksum() != null && !this.getChecksum().isEmpty()) { - builder.setChecksum(this.getChecksum()); - } - - for (Map.Entry entry : metadata.entrySet()) { - ContainerProtos.KeyValue.Builder keyValBuilder = - ContainerProtos.KeyValue.newBuilder(); - builder.addMetadata(keyValBuilder.setKey(entry.getKey()) - .setValue(entry.getValue()).build()); - } - - return builder.build(); - } - - /** - * Returns the chunkName. - * - * @return - String - */ - public String getChunkName() { - return chunkName; - } - - /** - * Gets the start offset of the given chunk in physical file. - * - * @return - long - */ - public long getOffset() { - return offset; - } - - /** - * Returns the length of the Chunk. - * - * @return long - */ - public long getLen() { - return len; - } - - /** - * Returns the SHA256 value of this chunk. - * - * @return - Hash String - */ - public String getChecksum() { - return checksum; - } - - /** - * Sets the Hash value of this chunk. - * - * @param checksum - Hash String. - */ - public void setChecksum(String checksum) { - this.checksum = checksum; - } - - /** - * Returns Metadata associated with this Chunk. - * - * @return - Map of Key,values. - */ - public Map getMetadata() { - return metadata; - } - - @Override - public String toString() { - return "ChunkInfo{" + - "chunkName='" + chunkName + - ", offset=" + offset + - ", len=" + len + - '}'; - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/container/common/helpers/package-info.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/container/common/helpers/package-info.java deleted file mode 100644 index fa5df113d87..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/container/common/helpers/package-info.java +++ /dev/null @@ -1,23 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.helpers; - -/** - * Helper classes for the container protocol communication. - */ \ No newline at end of file diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/Lease.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/Lease.java deleted file mode 100644 index dfa93156dab..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/Lease.java +++ /dev/null @@ -1,189 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.lease; - -import org.apache.hadoop.util.Time; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.Callable; - -/** - * This class represents the lease created on a resource. Callback can be - * registered on the lease which will be executed in case of timeout. - * - * @param Resource type for which the lease can be associated - */ -public class Lease { - - /** - * The resource for which this lease is created. - */ - private final T resource; - - private final long creationTime; - - /** - * Lease lifetime in milliseconds. - */ - private volatile long leaseTimeout; - - private boolean expired; - - /** - * Functions to be called in case of timeout. - */ - private List> callbacks; - - - /** - * Creates a lease on the specified resource with given timeout. - * - * @param resource - * Resource for which the lease has to be created - * @param timeout - * Lease lifetime in milliseconds - */ - public Lease(T resource, long timeout) { - this.resource = resource; - this.leaseTimeout = timeout; - this.callbacks = Collections.synchronizedList(new ArrayList<>()); - this.creationTime = Time.monotonicNow(); - this.expired = false; - } - - /** - * Returns true if the lease has expired, else false. - * - * @return true if expired, else false - */ - public boolean hasExpired() { - return expired; - } - - /** - * Registers a callback which will be executed in case of timeout. Callbacks - * are executed in a separate Thread. - * - * @param callback - * The Callable which has to be executed - * @throws LeaseExpiredException - * If the lease has already timed out - */ - public void registerCallBack(Callable callback) - throws LeaseExpiredException { - if(hasExpired()) { - throw new LeaseExpiredException("Resource: " + resource); - } - callbacks.add(callback); - } - - /** - * Returns the time elapsed since the creation of lease. - * - * @return elapsed time in milliseconds - * @throws LeaseExpiredException - * If the lease has already timed out - */ - public long getElapsedTime() throws LeaseExpiredException { - if(hasExpired()) { - throw new LeaseExpiredException("Resource: " + resource); - } - return Time.monotonicNow() - creationTime; - } - - /** - * Returns the time available before timeout. - * - * @return remaining time in milliseconds - * @throws LeaseExpiredException - * If the lease has already timed out - */ - public long getRemainingTime() throws LeaseExpiredException { - if(hasExpired()) { - throw new LeaseExpiredException("Resource: " + resource); - } - return leaseTimeout - getElapsedTime(); - } - - /** - * Returns total lease lifetime. - * - * @return total lifetime of lease in milliseconds - * @throws LeaseExpiredException - * If the lease has already timed out - */ - public long getLeaseLifeTime() throws LeaseExpiredException { - if(hasExpired()) { - throw new LeaseExpiredException("Resource: " + resource); - } - return leaseTimeout; - } - - /** - * Renews the lease timeout period. - * - * @param timeout - * Time to be added to the lease in milliseconds - * @throws LeaseExpiredException - * If the lease has already timed out - */ - public void renew(long timeout) throws LeaseExpiredException { - if(hasExpired()) { - throw new LeaseExpiredException("Resource: " + resource); - } - leaseTimeout += timeout; - } - - @Override - public int hashCode() { - return resource.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if(obj instanceof Lease) { - return resource.equals(((Lease) obj).resource); - } - return false; - } - - @Override - public String toString() { - return "Lease<" + resource.toString() + ">"; - } - - /** - * Returns the callbacks to be executed for the lease in case of timeout. - * - * @return callbacks to be executed - */ - List> getCallbacks() { - return callbacks; - } - - /** - * Expires/Invalidates the lease. - */ - void invalidate() { - callbacks = null; - expired = true; - } - -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/LeaseAlreadyExistException.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/LeaseAlreadyExistException.java deleted file mode 100644 index a39ea22df10..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/LeaseAlreadyExistException.java +++ /dev/null @@ -1,46 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.lease; - -/** - * This exception represents that there is already a lease acquired on the - * same resource. - */ -public class LeaseAlreadyExistException extends LeaseException { - - /** - * Constructs an {@code LeaseAlreadyExistException} with {@code null} - * as its error detail message. - */ - public LeaseAlreadyExistException() { - super(); - } - - /** - * Constructs an {@code LeaseAlreadyExistException} with the specified - * detail message. - * - * @param message - * The detail message (which is saved for later retrieval - * by the {@link #getMessage()} method) - */ - public LeaseAlreadyExistException(String message) { - super(message); - } - -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/LeaseCallbackExecutor.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/LeaseCallbackExecutor.java deleted file mode 100644 index 1b7391bf5d8..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/LeaseCallbackExecutor.java +++ /dev/null @@ -1,65 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.lease; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.List; -import java.util.concurrent.Callable; - -/** - * This class is responsible for executing the callbacks of a lease in case of - * timeout. - */ -public class LeaseCallbackExecutor implements Runnable { - - private static final Logger LOG = LoggerFactory.getLogger(Lease.class); - - private final T resource; - private final List> callbacks; - - /** - * Constructs LeaseCallbackExecutor instance with list of callbacks. - * - * @param resource - * The resource for which the callbacks are executed - * @param callbacks - * Callbacks to be executed by this executor - */ - public LeaseCallbackExecutor(T resource, List> callbacks) { - this.resource = resource; - this.callbacks = callbacks; - } - - @Override - public void run() { - if(LOG.isDebugEnabled()) { - LOG.debug("Executing callbacks for lease on {}", resource); - } - for(Callable callback : callbacks) { - try { - callback.call(); - } catch (Exception e) { - LOG.warn("Exception while executing callback for lease on {}", - resource, e); - } - } - } - -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/LeaseException.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/LeaseException.java deleted file mode 100644 index 418f4127df7..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/LeaseException.java +++ /dev/null @@ -1,45 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.lease; - -/** - * This exception represents all lease related exceptions. - */ -public class LeaseException extends Exception { - - /** - * Constructs an {@code LeaseException} with {@code null} - * as its error detail message. - */ - public LeaseException() { - super(); - } - - /** - * Constructs an {@code LeaseException} with the specified - * detail message. - * - * @param message - * The detail message (which is saved for later retrieval - * by the {@link #getMessage()} method) - */ - public LeaseException(String message) { - super(message); - } - -} \ No newline at end of file diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/LeaseExpiredException.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/LeaseExpiredException.java deleted file mode 100644 index 440a023beff..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/LeaseExpiredException.java +++ /dev/null @@ -1,45 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.lease; - -/** - * This exception represents that the lease that is being accessed has expired. - */ -public class LeaseExpiredException extends LeaseException { - - /** - * Constructs an {@code LeaseExpiredException} with {@code null} - * as its error detail message. - */ - public LeaseExpiredException() { - super(); - } - - /** - * Constructs an {@code LeaseExpiredException} with the specified - * detail message. - * - * @param message - * The detail message (which is saved for later retrieval - * by the {@link #getMessage()} method) - */ - public LeaseExpiredException(String message) { - super(message); - } - -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/LeaseManager.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/LeaseManager.java deleted file mode 100644 index 756a41af089..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/LeaseManager.java +++ /dev/null @@ -1,251 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.lease; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.List; -import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -/** - * LeaseManager is someone who can provide you leases based on your - * requirement. If you want to return the lease back before it expires, - * you can give it back to Lease Manager. He is the one responsible for - * the lifecycle of leases. The resource for which lease is created - * should have proper {@code equals} method implementation, resource - * equality is checked while the lease is created. - * - * @param Type of leases that this lease manager can create - */ -public class LeaseManager { - - private static final Logger LOG = - LoggerFactory.getLogger(LeaseManager.class); - - private final String name; - private final long defaultTimeout; - private Map> activeLeases; - private LeaseMonitor leaseMonitor; - private Thread leaseMonitorThread; - private boolean isRunning; - - /** - * Creates an instance of lease manager. - * - * @param name - * Name for the LeaseManager instance. - * @param defaultTimeout - * Default timeout in milliseconds to be used for lease creation. - */ - public LeaseManager(String name, long defaultTimeout) { - this.name = name; - this.defaultTimeout = defaultTimeout; - } - - /** - * Starts the lease manager service. - */ - public void start() { - LOG.debug("Starting {} LeaseManager service", name); - activeLeases = new ConcurrentHashMap<>(); - leaseMonitor = new LeaseMonitor(); - leaseMonitorThread = new Thread(leaseMonitor); - leaseMonitorThread.setName(name + "-LeaseManager#LeaseMonitor"); - leaseMonitorThread.setDaemon(true); - leaseMonitorThread.setUncaughtExceptionHandler((thread, throwable) -> { - // Let us just restart this thread after logging an error. - // if this thread is not running we cannot handle Lease expiry. - LOG.error("LeaseMonitor thread encountered an error. Thread: {}", - thread.toString(), throwable); - leaseMonitorThread.start(); - }); - LOG.debug("Starting {}-LeaseManager#LeaseMonitor Thread", name); - leaseMonitorThread.start(); - isRunning = true; - } - - /** - * Returns a lease for the specified resource with default timeout. - * - * @param resource - * Resource for which lease has to be created - * @throws LeaseAlreadyExistException - * If there is already a lease on the resource - */ - public synchronized Lease acquire(T resource) - throws LeaseAlreadyExistException { - return acquire(resource, defaultTimeout); - } - - /** - * Returns a lease for the specified resource with the timeout provided. - * - * @param resource - * Resource for which lease has to be created - * @param timeout - * The timeout in milliseconds which has to be set on the lease - * @throws LeaseAlreadyExistException - * If there is already a lease on the resource - */ - public synchronized Lease acquire(T resource, long timeout) - throws LeaseAlreadyExistException { - checkStatus(); - if(LOG.isDebugEnabled()) { - LOG.debug("Acquiring lease on {} for {} milliseconds", resource, timeout); - } - if(activeLeases.containsKey(resource)) { - throw new LeaseAlreadyExistException("Resource: " + resource); - } - Lease lease = new Lease<>(resource, timeout); - activeLeases.put(resource, lease); - leaseMonitorThread.interrupt(); - return lease; - } - - /** - * Returns a lease associated with the specified resource. - * - * @param resource - * Resource for which the lease has to be returned - * @throws LeaseNotFoundException - * If there is no active lease on the resource - */ - public Lease get(T resource) throws LeaseNotFoundException { - checkStatus(); - Lease lease = activeLeases.get(resource); - if(lease != null) { - return lease; - } - throw new LeaseNotFoundException("Resource: " + resource); - } - - /** - * Releases the lease associated with the specified resource. - * - * @param resource - * The for which the lease has to be released - * @throws LeaseNotFoundException - * If there is no active lease on the resource - */ - public synchronized void release(T resource) - throws LeaseNotFoundException { - checkStatus(); - if(LOG.isDebugEnabled()) { - LOG.debug("Releasing lease on {}", resource); - } - Lease lease = activeLeases.remove(resource); - if(lease == null) { - throw new LeaseNotFoundException("Resource: " + resource); - } - lease.invalidate(); - } - - /** - * Shuts down the LeaseManager and releases the resources. All the active - * {@link Lease} will be released (callbacks on leases will not be - * executed). - */ - public void shutdown() { - checkStatus(); - LOG.debug("Shutting down LeaseManager service"); - leaseMonitor.disable(); - leaseMonitorThread.interrupt(); - for(T resource : activeLeases.keySet()) { - try { - release(resource); - } catch(LeaseNotFoundException ex) { - //Ignore the exception, someone might have released the lease - } - } - isRunning = false; - } - - /** - * Throws {@link LeaseManagerNotRunningException} if the service is not - * running. - */ - private void checkStatus() { - if(!isRunning) { - throw new LeaseManagerNotRunningException("LeaseManager not running."); - } - } - - /** - * Monitors the leases and expires them based on the timeout, also - * responsible for executing the callbacks of expired leases. - */ - private final class LeaseMonitor implements Runnable { - - private boolean monitor = true; - private ExecutorService executorService; - - private LeaseMonitor() { - this.monitor = true; - this.executorService = Executors.newCachedThreadPool(); - } - - @Override - public void run() { - while(monitor) { - LOG.debug("{}-LeaseMonitor: checking for lease expiry", name); - long sleepTime = Long.MAX_VALUE; - - for (T resource : activeLeases.keySet()) { - try { - Lease lease = get(resource); - long remainingTime = lease.getRemainingTime(); - if (remainingTime <= 0) { - //Lease has timed out - List> leaseCallbacks = lease.getCallbacks(); - release(resource); - executorService.execute( - new LeaseCallbackExecutor(resource, leaseCallbacks)); - } else { - sleepTime = remainingTime > sleepTime ? - sleepTime : remainingTime; - } - } catch (LeaseNotFoundException | LeaseExpiredException ex) { - //Ignore the exception, someone might have released the lease - } - } - - try { - if(!Thread.interrupted()) { - Thread.sleep(sleepTime); - } - } catch (InterruptedException ignored) { - // This means a new lease is added to activeLeases. - } - } - } - - /** - * Disables lease monitor, next interrupt call on the thread - * will stop lease monitor. - */ - public void disable() { - monitor = false; - } - } - -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/LeaseManagerNotRunningException.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/LeaseManagerNotRunningException.java deleted file mode 100644 index ced31de4394..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/LeaseManagerNotRunningException.java +++ /dev/null @@ -1,45 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.lease; - -/** - * This exception represents that there LeaseManager service is not running. - */ -public class LeaseManagerNotRunningException extends RuntimeException { - - /** - * Constructs an {@code LeaseManagerNotRunningException} with {@code null} - * as its error detail message. - */ - public LeaseManagerNotRunningException() { - super(); - } - - /** - * Constructs an {@code LeaseManagerNotRunningException} with the specified - * detail message. - * - * @param message - * The detail message (which is saved for later retrieval - * by the {@link #getMessage()} method) - */ - public LeaseManagerNotRunningException(String message) { - super(message); - } - -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/LeaseNotFoundException.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/LeaseNotFoundException.java deleted file mode 100644 index c292d332323..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/LeaseNotFoundException.java +++ /dev/null @@ -1,46 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.lease; - -/** - * This exception represents that the lease that is being accessed does not - * exist. - */ -public class LeaseNotFoundException extends LeaseException { - - /** - * Constructs an {@code LeaseNotFoundException} with {@code null} - * as its error detail message. - */ - public LeaseNotFoundException() { - super(); - } - - /** - * Constructs an {@code LeaseNotFoundException} with the specified - * detail message. - * - * @param message - * The detail message (which is saved for later retrieval - * by the {@link #getMessage()} method) - */ - public LeaseNotFoundException(String message) { - super(message); - } - -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/package-info.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/package-info.java deleted file mode 100644 index 48ee2e1c6ab..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lease/package-info.java +++ /dev/null @@ -1,26 +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 - * - * 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. - */ - -/** - * A generic lease management API which can be used if a service - * needs any kind of lease management. - */ - -package org.apache.hadoop.ozone.lease; -/* - This package contains lease management related classes. - */ \ No newline at end of file diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lock/ActiveLock.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lock/ActiveLock.java deleted file mode 100644 index c3020844927..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lock/ActiveLock.java +++ /dev/null @@ -1,101 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.lock; - -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -/** - * Lock implementation which also maintains counter. - */ -public final class ActiveLock { - - private Lock lock; - private AtomicInteger count; - - /** - * Use ActiveLock#newInstance to create instance. - */ - private ActiveLock() { - this.lock = new ReentrantLock(); - this.count = new AtomicInteger(0); - } - - /** - * Creates a new instance of ActiveLock. - * - * @return new ActiveLock - */ - public static ActiveLock newInstance() { - return new ActiveLock(); - } - - /** - * Acquires the lock. - * - *

If the lock is not available then the current thread becomes - * disabled for thread scheduling purposes and lies dormant until the - * lock has been acquired. - */ - public void lock() { - lock.lock(); - } - - /** - * Releases the lock. - */ - public void unlock() { - lock.unlock(); - } - - /** - * Increment the active count of the lock. - */ - void incrementActiveCount() { - count.incrementAndGet(); - } - - /** - * Decrement the active count of the lock. - */ - void decrementActiveCount() { - count.decrementAndGet(); - } - - /** - * Returns the active count on the lock. - * - * @return Number of active leases on the lock. - */ - int getActiveLockCount() { - return count.get(); - } - - /** - * Resets the active count on the lock. - */ - void resetCounter() { - count.set(0); - } - - @Override - public String toString() { - return lock.toString(); - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lock/LockManager.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lock/LockManager.java deleted file mode 100644 index 49cf544626b..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lock/LockManager.java +++ /dev/null @@ -1,101 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.lock; - -import org.apache.commons.pool2.impl.GenericObjectPool; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.HddsConfigKeys; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Manages the locks on a given resource. A new lock is created for each - * and every unique resource. Uniqueness of resource depends on the - * {@code equals} implementation of it. - */ -public class LockManager { - - private static final Logger LOG = LoggerFactory.getLogger(LockManager.class); - - private final Map activeLocks = new ConcurrentHashMap<>(); - private final GenericObjectPool lockPool = - new GenericObjectPool<>(new PooledLockFactory()); - - /** - * Creates new LockManager instance. - * - * @param conf Configuration object - */ - public LockManager(Configuration conf) { - int maxPoolSize = conf.getInt(HddsConfigKeys.HDDS_LOCK_MAX_CONCURRENCY, - HddsConfigKeys.HDDS_LOCK_MAX_CONCURRENCY_DEFAULT); - lockPool.setMaxTotal(maxPoolSize); - } - - - /** - * Acquires the lock on given resource. - * - *

If the lock is not available then the current thread becomes - * disabled for thread scheduling purposes and lies dormant until the - * lock has been acquired. - */ - public void lock(T resource) { - activeLocks.compute(resource, (k, v) -> { - ActiveLock lock; - try { - if (v == null) { - lock = lockPool.borrowObject(); - } else { - lock = v; - } - lock.incrementActiveCount(); - } catch (Exception ex) { - LOG.error("Unable to obtain lock.", ex); - throw new RuntimeException(ex); - } - return lock; - }).lock(); - } - - /** - * Releases the lock on given resource. - */ - public void unlock(T resource) { - ActiveLock lock = activeLocks.get(resource); - if (lock == null) { - // Someone is releasing a lock which was never acquired. Log and return. - LOG.warn("Trying to release the lock on {}, which was never acquired.", - resource); - return; - } - lock.unlock(); - activeLocks.computeIfPresent(resource, (k, v) -> { - v.decrementActiveCount(); - if (v.getActiveLockCount() != 0) { - return v; - } - lockPool.returnObject(v); - return null; - }); - } - -} \ No newline at end of file diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lock/PooledLockFactory.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lock/PooledLockFactory.java deleted file mode 100644 index 4c24ef74b28..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lock/PooledLockFactory.java +++ /dev/null @@ -1,43 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.lock; - -import org.apache.commons.pool2.BasePooledObjectFactory; -import org.apache.commons.pool2.PooledObject; -import org.apache.commons.pool2.impl.DefaultPooledObject; - -/** - * Pool factory to create {@code ActiveLock} instances. - */ -public class PooledLockFactory extends BasePooledObjectFactory { - - @Override - public ActiveLock create() throws Exception { - return ActiveLock.newInstance(); - } - - @Override - public PooledObject wrap(ActiveLock activeLock) { - return new DefaultPooledObject<>(activeLock); - } - - @Override - public void activateObject(PooledObject pooledObject) { - pooledObject.getObject().resetCounter(); - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lock/package-info.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lock/package-info.java deleted file mode 100644 index 5c677ced745..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/lock/package-info.java +++ /dev/null @@ -1,21 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.lock; -/* - This package contains the lock related classes. - */ \ No newline at end of file diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/package-info.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/package-info.java deleted file mode 100644 index db399db25ab..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/package-info.java +++ /dev/null @@ -1,35 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone; - -/** - This package contains class that support ozone implementation on the datanode - side. - - Main parts of ozone on datanode are: - - 1. REST Interface - This code lives under the web directory and listens to the - WebHDFS port. - - 2. Datanode container classes: This support persistence of ozone objects on - datanode. These classes live under container directory. - - 3. Client and Shell: We also support a ozone REST client lib, they are under - web/client and web/ozShell. - - */ diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/protocolPB/ScmBlockLocationProtocolServerSideTranslatorPB.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/protocolPB/ScmBlockLocationProtocolServerSideTranslatorPB.java deleted file mode 100644 index 37a13095f6c..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/protocolPB/ScmBlockLocationProtocolServerSideTranslatorPB.java +++ /dev/null @@ -1,134 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.protocolPB; - -import com.google.protobuf.RpcController; -import com.google.protobuf.ServiceException; -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.hdds.scm.ScmInfo; -import org.apache.hadoop.hdds.scm.container.common.helpers.AllocatedBlock; -import org.apache.hadoop.hdds.scm.protocol.ScmBlockLocationProtocol; -import org.apache.hadoop.hdds.scm.protocol.StorageContainerLocationProtocol; -import org.apache.hadoop.hdds.scm.protocolPB.ScmBlockLocationProtocolPB; -import org.apache.hadoop.hdds.scm.protocolPB.StorageContainerLocationProtocolPB; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.protocol.proto.ScmBlockLocationProtocolProtos - .AllocateScmBlockRequestProto; -import org.apache.hadoop.hdds.protocol.proto.ScmBlockLocationProtocolProtos - .AllocateScmBlockResponseProto; -import org.apache.hadoop.hdds.protocol.proto.ScmBlockLocationProtocolProtos - .DeleteKeyBlocksResultProto; -import org.apache.hadoop.hdds.protocol.proto.ScmBlockLocationProtocolProtos - .DeleteScmKeyBlocksRequestProto; -import org.apache.hadoop.hdds.protocol.proto.ScmBlockLocationProtocolProtos - .DeleteScmKeyBlocksResponseProto; -import org.apache.hadoop.ozone.common.BlockGroup; -import org.apache.hadoop.ozone.common.DeleteBlockGroupResult; - -import java.io.IOException; -import java.util.List; -import java.util.stream.Collectors; - -/** - * This class is the server-side translator that forwards requests received on - * {@link StorageContainerLocationProtocolPB} to the - * {@link StorageContainerLocationProtocol} server implementation. - */ -@InterfaceAudience.Private -public final class ScmBlockLocationProtocolServerSideTranslatorPB - implements ScmBlockLocationProtocolPB { - - private final ScmBlockLocationProtocol impl; - - /** - * Creates a new ScmBlockLocationProtocolServerSideTranslatorPB. - * - * @param impl {@link ScmBlockLocationProtocol} server implementation - */ - public ScmBlockLocationProtocolServerSideTranslatorPB( - ScmBlockLocationProtocol impl) throws IOException { - this.impl = impl; - } - - @Override - public AllocateScmBlockResponseProto allocateScmBlock( - RpcController controller, AllocateScmBlockRequestProto request) - throws ServiceException { - try { - AllocatedBlock allocatedBlock = - impl.allocateBlock(request.getSize(), request.getType(), - request.getFactor(), request.getOwner()); - if (allocatedBlock != null) { - return - AllocateScmBlockResponseProto.newBuilder() - .setBlockID(allocatedBlock.getBlockID().getProtobuf()) - .setPipeline(allocatedBlock.getPipeline().getProtobufMessage()) - .setCreateContainer(allocatedBlock.getCreateContainer()) - .setErrorCode(AllocateScmBlockResponseProto.Error.success) - .build(); - } else { - return AllocateScmBlockResponseProto.newBuilder() - .setErrorCode(AllocateScmBlockResponseProto.Error.unknownFailure) - .build(); - } - } catch (IOException e) { - throw new ServiceException(e); - } - } - - @Override - public DeleteScmKeyBlocksResponseProto deleteScmKeyBlocks( - RpcController controller, DeleteScmKeyBlocksRequestProto req) - throws ServiceException { - DeleteScmKeyBlocksResponseProto.Builder resp = - DeleteScmKeyBlocksResponseProto.newBuilder(); - try { - List infoList = req.getKeyBlocksList().stream() - .map(BlockGroup::getFromProto).collect(Collectors.toList()); - final List results = - impl.deleteKeyBlocks(infoList); - for (DeleteBlockGroupResult result: results) { - DeleteKeyBlocksResultProto.Builder deleteResult = - DeleteKeyBlocksResultProto - .newBuilder() - .setObjectKey(result.getObjectKey()) - .addAllBlockResults(result.getBlockResultProtoList()); - resp.addResults(deleteResult.build()); - } - } catch (IOException ex) { - throw new ServiceException(ex); - } - return resp.build(); - } - - @Override - public HddsProtos.GetScmInfoRespsonseProto getScmInfo( - RpcController controller, HddsProtos.GetScmInfoRequestProto req) - throws ServiceException { - ScmInfo scmInfo; - try { - scmInfo = impl.getScmInfo(); - } catch (IOException ex) { - throw new ServiceException(ex); - } - return HddsProtos.GetScmInfoRespsonseProto.newBuilder() - .setClusterId(scmInfo.getClusterId()) - .setScmId(scmInfo.getScmId()) - .build(); - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/protocolPB/StorageContainerLocationProtocolServerSideTranslatorPB.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/protocolPB/StorageContainerLocationProtocolServerSideTranslatorPB.java deleted file mode 100644 index d2723f08569..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/protocolPB/StorageContainerLocationProtocolServerSideTranslatorPB.java +++ /dev/null @@ -1,253 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.protocolPB; - -import com.google.protobuf.RpcController; -import com.google.protobuf.ServiceException; -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos.InChillModeRequestProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos.InChillModeResponseProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos.ForceExitChillModeRequestProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos.ForceExitChillModeResponseProto; -import org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos.GetContainerWithPipelineRequestProto; -import org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos.GetContainerWithPipelineResponseProto; -import org.apache.hadoop.hdds.scm.ScmInfo; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerWithPipeline; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo; -import org.apache.hadoop.hdds.scm.protocol.StorageContainerLocationProtocol; -import org.apache.hadoop.hdds.scm.protocolPB.StorageContainerLocationProtocolPB; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos.ContainerRequestProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos.ContainerResponseProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos.GetContainerRequestProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos.GetContainerResponseProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos.ObjectStageChangeRequestProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos.ObjectStageChangeResponseProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos.PipelineRequestProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos.PipelineResponseProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos.SCMDeleteContainerRequestProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos.SCMDeleteContainerResponseProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos.SCMListContainerRequestProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos.SCMListContainerResponseProto; - -import java.io.IOException; -import java.util.List; - -/** - * This class is the server-side translator that forwards requests received on - * {@link StorageContainerLocationProtocolPB} to the - * {@link StorageContainerLocationProtocol} server implementation. - */ -@InterfaceAudience.Private -public final class StorageContainerLocationProtocolServerSideTranslatorPB - implements StorageContainerLocationProtocolPB { - - private final StorageContainerLocationProtocol impl; - - /** - * Creates a new StorageContainerLocationProtocolServerSideTranslatorPB. - * - * @param impl {@link StorageContainerLocationProtocol} server implementation - */ - public StorageContainerLocationProtocolServerSideTranslatorPB( - StorageContainerLocationProtocol impl) throws IOException { - this.impl = impl; - } - - @Override - public ContainerResponseProto allocateContainer(RpcController unused, - ContainerRequestProto request) throws ServiceException { - try { - ContainerWithPipeline containerWithPipeline = impl - .allocateContainer(request.getReplicationType(), - request.getReplicationFactor(), request.getOwner()); - return ContainerResponseProto.newBuilder() - .setContainerWithPipeline(containerWithPipeline.getProtobuf()) - .setErrorCode(ContainerResponseProto.Error.success) - .build(); - - } catch (IOException e) { - throw new ServiceException(e); - } - } - - @Override - public GetContainerResponseProto getContainer( - RpcController controller, GetContainerRequestProto request) - throws ServiceException { - try { - ContainerInfo container = impl.getContainer(request.getContainerID()); - return GetContainerResponseProto.newBuilder() - .setContainerInfo(container.getProtobuf()) - .build(); - } catch (IOException e) { - throw new ServiceException(e); - } - } - - @Override - public GetContainerWithPipelineResponseProto getContainerWithPipeline( - RpcController controller, GetContainerWithPipelineRequestProto request) - throws ServiceException { - try { - ContainerWithPipeline container = impl - .getContainerWithPipeline(request.getContainerID()); - return GetContainerWithPipelineResponseProto.newBuilder() - .setContainerWithPipeline(container.getProtobuf()) - .build(); - } catch (IOException e) { - throw new ServiceException(e); - } - } - - @Override - public SCMListContainerResponseProto listContainer(RpcController controller, - SCMListContainerRequestProto request) throws ServiceException { - try { - long startContainerID = 0; - int count = -1; - - // Arguments check. - if (request.hasStartContainerID()) { - // End container name is given. - startContainerID = request.getStartContainerID(); - } - count = request.getCount(); - List containerList = - impl.listContainer(startContainerID, count); - SCMListContainerResponseProto.Builder builder = - SCMListContainerResponseProto.newBuilder(); - for (ContainerInfo container : containerList) { - builder.addContainers(container.getProtobuf()); - } - return builder.build(); - } catch (IOException e) { - throw new ServiceException(e); - } - } - - @Override - public SCMDeleteContainerResponseProto deleteContainer( - RpcController controller, SCMDeleteContainerRequestProto request) - throws ServiceException { - try { - impl.deleteContainer(request.getContainerID()); - return SCMDeleteContainerResponseProto.newBuilder().build(); - } catch (IOException e) { - throw new ServiceException(e); - } - } - - @Override - public StorageContainerLocationProtocolProtos.NodeQueryResponseProto - queryNode(RpcController controller, - StorageContainerLocationProtocolProtos.NodeQueryRequestProto request) - throws ServiceException { - try { - HddsProtos.NodeState nodeState = request.getState(); - List datanodes = impl.queryNode(nodeState, - request.getScope(), request.getPoolName()); - return StorageContainerLocationProtocolProtos - .NodeQueryResponseProto.newBuilder() - .addAllDatanodes(datanodes) - .build(); - } catch (Exception e) { - throw new ServiceException(e); - } - } - - @Override - public ObjectStageChangeResponseProto notifyObjectStageChange( - RpcController controller, ObjectStageChangeRequestProto request) - throws ServiceException { - try { - impl.notifyObjectStageChange(request.getType(), request.getId(), - request.getOp(), request.getStage()); - return ObjectStageChangeResponseProto.newBuilder().build(); - } catch (IOException e) { - throw new ServiceException(e); - } - } - - @Override - public PipelineResponseProto allocatePipeline( - RpcController controller, PipelineRequestProto request) - throws ServiceException { - // TODO : Wiring this up requires one more patch. - return null; - } - - @Override - public HddsProtos.GetScmInfoRespsonseProto getScmInfo( - RpcController controller, HddsProtos.GetScmInfoRequestProto req) - throws ServiceException { - try { - ScmInfo scmInfo = impl.getScmInfo(); - return HddsProtos.GetScmInfoRespsonseProto.newBuilder() - .setClusterId(scmInfo.getClusterId()) - .setScmId(scmInfo.getScmId()) - .build(); - } catch (IOException ex) { - throw new ServiceException(ex); - } - - } - - @Override - public InChillModeResponseProto inChillMode( - RpcController controller, - InChillModeRequestProto request) throws ServiceException { - try { - return InChillModeResponseProto.newBuilder() - .setInChillMode(impl.inChillMode()).build(); - } catch (IOException ex) { - throw new ServiceException(ex); - } - } - - @Override - public ForceExitChillModeResponseProto forceExitChillMode( - RpcController controller, ForceExitChillModeRequestProto request) - throws ServiceException { - try { - return ForceExitChillModeResponseProto.newBuilder() - .setExitedChillMode(impl.forceExitChillMode()).build(); - } catch (IOException ex) { - throw new ServiceException(ex); - } - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/protocolPB/package-info.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/protocolPB/package-info.java deleted file mode 100644 index 860386d9fdc..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/protocolPB/package-info.java +++ /dev/null @@ -1,24 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.protocolPB; - -/** - * This package contains classes for the Protocol Buffers binding of Ozone - * protocols. - */ diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/web/utils/JsonUtils.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/web/utils/JsonUtils.java deleted file mode 100644 index af56da394cd..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/web/utils/JsonUtils.java +++ /dev/null @@ -1,71 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.web.utils; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ObjectReader; -import com.fasterxml.jackson.databind.ObjectWriter; -import com.fasterxml.jackson.databind.type.CollectionType; - -import java.io.IOException; -import java.util.List; - -/** - * JSON Utility functions used in ozone. - */ -public final class JsonUtils { - - // Reuse ObjectMapper instance for improving performance. - // ObjectMapper is thread safe as long as we always configure instance - // before use. - private static final ObjectMapper MAPPER = new ObjectMapper(); - private static final ObjectReader READER = MAPPER.readerFor(Object.class); - private static final ObjectWriter WRITTER = - MAPPER.writerWithDefaultPrettyPrinter(); - - private JsonUtils() { - // Never constructed - } - - public static String toJsonStringWithDefaultPrettyPrinter(String jsonString) - throws IOException { - Object json = READER.readValue(jsonString); - return WRITTER.writeValueAsString(json); - } - - public static String toJsonString(Object obj) throws IOException { - return MAPPER.writeValueAsString(obj); - } - - /** - * Deserialize a list of elements from a given string, - * each element in the list is in the given type. - * - * @param str json string. - * @param elementType element type. - * @return List of elements of type elementType - * @throws IOException - */ - public static List toJsonList(String str, Class elementType) - throws IOException { - CollectionType type = MAPPER.getTypeFactory() - .constructCollectionType(List.class, elementType); - return MAPPER.readValue(str, type); - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/web/utils/package-info.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/web/utils/package-info.java deleted file mode 100644 index e5812c00d94..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/web/utils/package-info.java +++ /dev/null @@ -1,19 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.web.utils; diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/BackgroundService.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/BackgroundService.java deleted file mode 100644 index 5718008b415..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/BackgroundService.java +++ /dev/null @@ -1,161 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.utils; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.Lists; -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.List; -import java.util.concurrent.CompletionService; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorCompletionService; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -/** - * An abstract class for a background service in ozone. - * A background service schedules multiple child tasks in parallel - * in a certain period. In each interval, it waits until all the tasks - * finish execution and then schedule next interval. - */ -public abstract class BackgroundService { - - @VisibleForTesting - public static final Logger LOG = - LoggerFactory.getLogger(BackgroundService.class); - - // Executor to launch child tasks - private final ScheduledExecutorService exec; - private final ThreadGroup threadGroup; - private final ThreadFactory threadFactory; - private final String serviceName; - private final long interval; - private final long serviceTimeout; - private final TimeUnit unit; - private final PeriodicalTask service; - - public BackgroundService(String serviceName, long interval, - TimeUnit unit, int threadPoolSize, long serviceTimeout) { - this.interval = interval; - this.unit = unit; - this.serviceName = serviceName; - this.serviceTimeout = serviceTimeout; - threadGroup = new ThreadGroup(serviceName); - ThreadFactory tf = r -> new Thread(threadGroup, r); - threadFactory = new ThreadFactoryBuilder() - .setThreadFactory(tf) - .setDaemon(true) - .setNameFormat(serviceName + "#%d") - .build(); - exec = Executors.newScheduledThreadPool(threadPoolSize, threadFactory); - service = new PeriodicalTask(); - } - - protected ExecutorService getExecutorService() { - return this.exec; - } - - @VisibleForTesting - public int getThreadCount() { - return threadGroup.activeCount(); - } - - @VisibleForTesting - public void triggerBackgroundTaskForTesting() { - service.run(); - } - - // start service - public void start() { - exec.scheduleWithFixedDelay(service, 0, interval, unit); - } - - public abstract BackgroundTaskQueue getTasks(); - - /** - * Run one or more background tasks concurrently. - * Wait until all tasks to return the result. - */ - public class PeriodicalTask implements Runnable { - @Override - public synchronized void run() { - LOG.debug("Running background service : {}", serviceName); - BackgroundTaskQueue tasks = getTasks(); - if (tasks.isEmpty()) { - // No task found, or some problems to init tasks - // return and retry in next interval. - return; - } - - LOG.debug("Number of background tasks to execute : {}", tasks.size()); - CompletionService taskCompletionService = - new ExecutorCompletionService<>(exec); - - List> results = Lists.newArrayList(); - while (tasks.size() > 0) { - BackgroundTask task = tasks.poll(); - Future result = - taskCompletionService.submit(task); - results.add(result); - } - - results.parallelStream().forEach(taskResultFuture -> { - try { - // Collect task results - BackgroundTaskResult result = serviceTimeout > 0 - ? taskResultFuture.get(serviceTimeout, unit) - : taskResultFuture.get(); - if (LOG.isDebugEnabled()) { - LOG.debug("task execution result size {}", result.getSize()); - } - } catch (InterruptedException | ExecutionException e) { - LOG.warn( - "Background task fails to execute, " - + "retrying in next interval", e); - } catch (TimeoutException e) { - LOG.warn("Background task executes timed out, " - + "retrying in next interval", e); - } - }); - } - } - - // shutdown and make sure all threads are properly released. - public void shutdown() { - LOG.info("Shutting down service {}", this.serviceName); - exec.shutdown(); - try { - if (!exec.awaitTermination(60, TimeUnit.SECONDS)) { - exec.shutdownNow(); - } - } catch (InterruptedException e) { - exec.shutdownNow(); - } - if (threadGroup.activeCount() == 0 && !threadGroup.isDestroyed()) { - threadGroup.destroy(); - } - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/BackgroundTask.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/BackgroundTask.java deleted file mode 100644 index 47e8ebc98fd..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/BackgroundTask.java +++ /dev/null @@ -1,28 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.utils; - -import java.util.concurrent.Callable; - -/** - * A task thread to run by {@link BackgroundService}. - */ -public interface BackgroundTask extends Callable { - - int getPriority(); -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/BackgroundTaskQueue.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/BackgroundTaskQueue.java deleted file mode 100644 index b56ef0c804b..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/BackgroundTaskQueue.java +++ /dev/null @@ -1,64 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.utils; - -import java.util.PriorityQueue; - -/** - * A priority queue that stores a number of {@link BackgroundTask}. - */ -public class BackgroundTaskQueue { - - private final PriorityQueue tasks; - - public BackgroundTaskQueue() { - tasks = new PriorityQueue<>((task1, task2) - -> task1.getPriority() - task2.getPriority()); - } - - /** - * @return the head task in this queue. - */ - public synchronized BackgroundTask poll() { - return tasks.poll(); - } - - /** - * Add a {@link BackgroundTask} to the queue, - * the task will be sorted by its priority. - * - * @param task - */ - public synchronized void add(BackgroundTask task) { - tasks.add(task); - } - - /** - * @return true if the queue contains no task, false otherwise. - */ - public synchronized boolean isEmpty() { - return tasks.isEmpty(); - } - - /** - * @return the size of the queue. - */ - public synchronized int size() { - return tasks.size(); - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/BackgroundTaskResult.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/BackgroundTaskResult.java deleted file mode 100644 index 198300fb5f5..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/BackgroundTaskResult.java +++ /dev/null @@ -1,44 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.utils; - -/** - * Result of a {@link BackgroundTask}. - */ -public interface BackgroundTaskResult { - - /** - * Returns the size of entries included in this result. - */ - int getSize(); - - /** - * An empty task result implementation. - */ - class EmptyTaskResult implements BackgroundTaskResult { - - public static EmptyTaskResult newResult() { - return new EmptyTaskResult(); - } - - @Override - public int getSize() { - return 0; - } - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/BatchOperation.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/BatchOperation.java deleted file mode 100644 index 47699ebba80..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/BatchOperation.java +++ /dev/null @@ -1,90 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.utils; - -import com.google.common.collect.Lists; - -import java.util.List; - -/** - * An utility class to store a batch of DB write operations. - */ -public class BatchOperation { - - /** - * Enum for write operations. - */ - public enum Operation { - DELETE, PUT - } - - private List operations = - Lists.newArrayList(); - - /** - * Add a PUT operation into the batch. - */ - public void put(byte[] key, byte[] value) { - operations.add(new SingleOperation(Operation.PUT, key, value)); - } - - /** - * Add a DELETE operation into the batch. - */ - public void delete(byte[] key) { - operations.add(new SingleOperation(Operation.DELETE, key, null)); - - } - - public List getOperations() { - return operations; - } - - /** - * A SingleOperation represents a PUT or DELETE operation - * and the data the operation needs to manipulates. - */ - public static class SingleOperation { - - private Operation opt; - private byte[] key; - private byte[] value; - - public SingleOperation(Operation opt, byte[] key, byte[] value) { - this.opt = opt; - if (key == null) { - throw new IllegalArgumentException("key cannot be null"); - } - this.key = key.clone(); - this.value = value == null ? null : value.clone(); - } - - public Operation getOpt() { - return opt; - } - - public byte[] getKey() { - return key.clone(); - } - - public byte[] getValue() { - return value == null ? null : value.clone(); - } - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/EntryConsumer.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/EntryConsumer.java deleted file mode 100644 index c4073986118..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/EntryConsumer.java +++ /dev/null @@ -1,38 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.utils; - -import java.io.IOException; - -/** - * A consumer for metadata store key-value entries. - * Used by {@link MetadataStore} class. - */ -@FunctionalInterface -public interface EntryConsumer { - - /** - * Consumes a key and value and produces a boolean result. - * @param key key - * @param value value - * @return a boolean value produced by the consumer - * @throws IOException - */ - boolean consume(byte[] key, byte[] value) throws IOException; -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/HddsVersionInfo.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/HddsVersionInfo.java deleted file mode 100644 index e7f697a0c50..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/HddsVersionInfo.java +++ /dev/null @@ -1,184 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.utils; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.classification.InterfaceStability; -import org.apache.hadoop.io.IOUtils; -import org.apache.hadoop.util.ClassUtil; -import org.apache.hadoop.util.ThreadUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Properties; - -/** - * This class returns build information about Hadoop components. - */ -@InterfaceAudience.Public -@InterfaceStability.Stable -public class HddsVersionInfo { - private static final Logger LOG = LoggerFactory.getLogger( - HddsVersionInfo.class); - - private Properties info; - - protected HddsVersionInfo(String component) { - info = new Properties(); - String versionInfoFile = component + "-version-info.properties"; - InputStream is = null; - try { - is = ThreadUtil.getResourceAsStream(HddsVersionInfo.class.getClassLoader(), - versionInfoFile); - info.load(is); - } catch (IOException ex) { - LoggerFactory.getLogger(getClass()).warn("Could not read '" + - versionInfoFile + "', " + ex.toString(), ex); - } finally { - IOUtils.closeStream(is); - } - } - - protected String _getVersion() { - return info.getProperty("version", "Unknown"); - } - - protected String _getRevision() { - return info.getProperty("revision", "Unknown"); - } - - protected String _getBranch() { - return info.getProperty("branch", "Unknown"); - } - - protected String _getDate() { - return info.getProperty("date", "Unknown"); - } - - protected String _getUser() { - return info.getProperty("user", "Unknown"); - } - - protected String _getUrl() { - return info.getProperty("url", "Unknown"); - } - - protected String _getSrcChecksum() { - return info.getProperty("srcChecksum", "Unknown"); - } - - protected String _getBuildVersion(){ - return _getVersion() + - " from " + _getRevision() + - " by " + _getUser() + - " source checksum " + _getSrcChecksum(); - } - - protected String _getProtocVersion() { - return info.getProperty("protocVersion", "Unknown"); - } - - private static final HddsVersionInfo HDDS_VERSION_INFO = - new HddsVersionInfo("hdds"); - /** - * Get the HDDS version. - * @return the Hdds version string, eg. "0.6.3-dev" - */ - public static String getVersion() { - return HDDS_VERSION_INFO._getVersion(); - } - - /** - * Get the Git commit hash of the repository when compiled. - * @return the commit hash, eg. "18f64065d5db6208daf50b02c1b5ed4ee3ce547a" - */ - public static String getRevision() { - return HDDS_VERSION_INFO._getRevision(); - } - - /** - * Get the branch on which this originated. - * @return The branch name, e.g. "trunk" or "branches/branch-0.20" - */ - public static String getBranch() { - return HDDS_VERSION_INFO._getBranch(); - } - - /** - * The date that HDDS was compiled. - * @return the compilation date in unix date format - */ - public static String getDate() { - return HDDS_VERSION_INFO._getDate(); - } - - /** - * The user that compiled HDDS. - * @return the username of the user - */ - public static String getUser() { - return HDDS_VERSION_INFO._getUser(); - } - - /** - * Get the URL for the HDDS repository. - * @return the URL of the Hdds repository - */ - public static String getUrl() { - return HDDS_VERSION_INFO._getUrl(); - } - - /** - * Get the checksum of the source files from which HDDS was built. - * @return the checksum of the source files - */ - public static String getSrcChecksum() { - return HDDS_VERSION_INFO._getSrcChecksum(); - } - - /** - * Returns the buildVersion which includes version, - * revision, user and date. - * @return the buildVersion - */ - public static String getBuildVersion(){ - return HDDS_VERSION_INFO._getBuildVersion(); - } - - /** - * Returns the protoc version used for the build. - * @return the protoc version - */ - public static String getProtocVersion(){ - return HDDS_VERSION_INFO._getProtocVersion(); - } - - public static void main(String[] args) { - System.out.println("Using HDDS " + getVersion()); - System.out.println("Source code repository " + getUrl() + " -r " + - getRevision()); - System.out.println("Compiled by " + getUser() + " on " + getDate()); - System.out.println("Compiled with protoc " + getProtocVersion()); - System.out.println("From source with checksum " + getSrcChecksum()); - LOG.debug("This command was run using " + - ClassUtil.findContainingJar(HddsVersionInfo.class)); - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/LevelDBStore.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/LevelDBStore.java deleted file mode 100644 index ed116a381c3..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/LevelDBStore.java +++ /dev/null @@ -1,387 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.utils; - -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.hadoop.utils.MetadataKeyFilters.MetadataKeyFilter; -import org.fusesource.leveldbjni.JniDBFactory; -import org.iq80.leveldb.DB; -import org.iq80.leveldb.DBIterator; -import org.iq80.leveldb.Options; -import org.iq80.leveldb.ReadOptions; -import org.iq80.leveldb.Snapshot; -import org.iq80.leveldb.WriteBatch; -import org.iq80.leveldb.WriteOptions; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -/** - * LevelDB interface. - */ -public class LevelDBStore implements MetadataStore { - - private static final Logger LOG = - LoggerFactory.getLogger(LevelDBStore.class); - - private DB db; - private final File dbFile; - private final Options dbOptions; - private final WriteOptions writeOptions; - - public LevelDBStore(File dbPath, boolean createIfMissing) - throws IOException { - dbOptions = new Options(); - dbOptions.createIfMissing(createIfMissing); - this.dbFile = dbPath; - this.writeOptions = new WriteOptions().sync(true); - openDB(dbPath, dbOptions); - } - - /** - * Opens a DB file. - * - * @param dbPath - DB File path - * @throws IOException - */ - public LevelDBStore(File dbPath, Options options) - throws IOException { - dbOptions = options; - this.dbFile = dbPath; - this.writeOptions = new WriteOptions().sync(true); - openDB(dbPath, dbOptions); - } - - private void openDB(File dbPath, Options options) throws IOException { - if (dbPath.getParentFile().mkdirs()) { - LOG.debug("Db path {} created.", dbPath.getParentFile()); - } - db = JniDBFactory.factory.open(dbPath, options); - if (LOG.isDebugEnabled()) { - LOG.debug("LevelDB successfully opened"); - LOG.debug("[Option] cacheSize = " + options.cacheSize()); - LOG.debug("[Option] createIfMissing = " + options.createIfMissing()); - LOG.debug("[Option] blockSize = " + options.blockSize()); - LOG.debug("[Option] compressionType= " + options.compressionType()); - LOG.debug("[Option] maxOpenFiles= " + options.maxOpenFiles()); - LOG.debug("[Option] writeBufferSize= "+ options.writeBufferSize()); - } - } - - /** - * Puts a Key into file. - * - * @param key - key - * @param value - value - */ - @Override - public void put(byte[] key, byte[] value) { - db.put(key, value, writeOptions); - } - - /** - * Get Key. - * - * @param key key - * @return value - */ - @Override - public byte[] get(byte[] key) { - return db.get(key); - } - - /** - * Delete Key. - * - * @param key - Key - */ - @Override - public void delete(byte[] key) { - db.delete(key); - } - - /** - * Closes the DB. - * - * @throws IOException - */ - @Override - public void close() throws IOException { - if (db != null){ - db.close(); - } - } - - /** - * Returns true if the DB is empty. - * - * @return boolean - * @throws IOException - */ - @Override - public boolean isEmpty() throws IOException { - try (DBIterator iter = db.iterator()) { - iter.seekToFirst(); - boolean hasNext = !iter.hasNext(); - return hasNext; - } - } - - /** - * Returns the actual levelDB object. - * @return DB handle. - */ - public DB getDB() { - return db; - } - - /** - * Returns an iterator on all the key-value pairs in the DB. - * @return an iterator on DB entries. - */ - public DBIterator getIterator() { - return db.iterator(); - } - - - @Override - public void destroy() throws IOException { - close(); - JniDBFactory.factory.destroy(dbFile, dbOptions); - } - - @Override - public ImmutablePair peekAround(int offset, - byte[] from) throws IOException, IllegalArgumentException { - try (DBIterator it = db.iterator()) { - if (from == null) { - it.seekToFirst(); - } else { - it.seek(from); - } - if (!it.hasNext()) { - return null; - } - switch (offset) { - case 0: - Entry current = it.next(); - return new ImmutablePair<>(current.getKey(), current.getValue()); - case 1: - if (it.next() != null && it.hasNext()) { - Entry next = it.peekNext(); - return new ImmutablePair<>(next.getKey(), next.getValue()); - } - break; - case -1: - if (it.hasPrev()) { - Entry prev = it.peekPrev(); - return new ImmutablePair<>(prev.getKey(), prev.getValue()); - } - break; - default: - throw new IllegalArgumentException( - "Position can only be -1, 0 " + "or 1, but found " + offset); - } - } - return null; - } - - @Override - public void iterate(byte[] from, EntryConsumer consumer) - throws IOException { - try (DBIterator iter = db.iterator()) { - if (from != null) { - iter.seek(from); - } else { - iter.seekToFirst(); - } - while (iter.hasNext()) { - Entry current = iter.next(); - if (!consumer.consume(current.getKey(), - current.getValue())) { - break; - } - } - } - } - - /** - * Compacts the DB by removing deleted keys etc. - * @throws IOException if there is an error. - */ - @Override - public void compactDB() throws IOException { - if(db != null) { - // From LevelDB docs : begin == null and end == null means the whole DB. - db.compactRange(null, null); - } - } - - @Override - public void writeBatch(BatchOperation operation) throws IOException { - List operations = - operation.getOperations(); - if (!operations.isEmpty()) { - try (WriteBatch writeBatch = db.createWriteBatch()) { - for (BatchOperation.SingleOperation opt : operations) { - switch (opt.getOpt()) { - case DELETE: - writeBatch.delete(opt.getKey()); - break; - case PUT: - writeBatch.put(opt.getKey(), opt.getValue()); - break; - default: - throw new IllegalArgumentException("Invalid operation " - + opt.getOpt()); - } - } - db.write(writeBatch); - } - } - } - - @Override - public List> getRangeKVs(byte[] startKey, - int count, MetadataKeyFilters.MetadataKeyFilter... filters) - throws IOException, IllegalArgumentException { - return getRangeKVs(startKey, count, false, filters); - } - - @Override - public List> getSequentialRangeKVs(byte[] startKey, - int count, MetadataKeyFilters.MetadataKeyFilter... filters) - throws IOException, IllegalArgumentException { - return getRangeKVs(startKey, count, true, filters); - } - - /** - * Returns a certain range of key value pairs as a list based on a - * startKey or count. Further a {@link MetadataKeyFilter} can be added to - * filter keys if necessary. To prevent race conditions while listing - * entries, this implementation takes a snapshot and lists the entries from - * the snapshot. This may, on the other hand, cause the range result slight - * different with actual data if data is updating concurrently. - *

- * If the startKey is specified and found in levelDB, this key and the keys - * after this key will be included in the result. If the startKey is null - * all entries will be included as long as other conditions are satisfied. - * If the given startKey doesn't exist, an empty list will be returned. - *

- * The count argument is to limit number of total entries to return, - * the value for count must be an integer greater than 0. - *

- * This method allows to specify one or more {@link MetadataKeyFilter} - * to filter keys by certain condition. Once given, only the entries - * whose key passes all the filters will be included in the result. - * - * @param startKey a start key. - * @param count max number of entries to return. - * @param filters customized one or more {@link MetadataKeyFilter}. - * @return a list of entries found in the database or an empty list if the - * startKey is invalid. - * @throws IOException if there are I/O errors. - * @throws IllegalArgumentException if count is less than 0. - */ - private List> getRangeKVs(byte[] startKey, - int count, boolean sequential, MetadataKeyFilter... filters) - throws IOException { - List> result = new ArrayList<>(); - long start = System.currentTimeMillis(); - if (count < 0) { - throw new IllegalArgumentException( - "Invalid count given " + count + ", count must be greater than 0"); - } - Snapshot snapShot = null; - DBIterator dbIter = null; - try { - snapShot = db.getSnapshot(); - ReadOptions readOptions = new ReadOptions().snapshot(snapShot); - dbIter = db.iterator(readOptions); - if (startKey == null) { - dbIter.seekToFirst(); - } else { - if (db.get(startKey) == null) { - // Key not found, return empty list - return result; - } - dbIter.seek(startKey); - } - while (dbIter.hasNext() && result.size() < count) { - byte[] preKey = dbIter.hasPrev() ? dbIter.peekPrev().getKey() : null; - byte[] nextKey = dbIter.hasNext() ? dbIter.peekNext().getKey() : null; - Entry current = dbIter.next(); - - if (filters == null) { - result.add(current); - } else { - if (Arrays.asList(filters).stream().allMatch( - entry -> entry.filterKey(preKey, current.getKey(), nextKey))) { - result.add(current); - } else { - if (result.size() > 0 && sequential) { - // if the caller asks for a sequential range of results, - // and we met a dis-match, abort iteration from here. - // if result is empty, we continue to look for the first match. - break; - } - } - } - } - } finally { - if (snapShot != null) { - snapShot.close(); - } - if (dbIter != null) { - dbIter.close(); - } - if (LOG.isDebugEnabled()) { - if (filters != null) { - for (MetadataKeyFilters.MetadataKeyFilter filter : filters) { - int scanned = filter.getKeysScannedNum(); - int hinted = filter.getKeysHintedNum(); - if (scanned > 0 || hinted > 0) { - LOG.debug( - "getRangeKVs ({}) numOfKeysScanned={}, numOfKeysHinted={}", - filter.getClass().getSimpleName(), filter.getKeysScannedNum(), - filter.getKeysHintedNum()); - } - } - } - long end = System.currentTimeMillis(); - long timeConsumed = end - start; - LOG.debug("Time consumed for getRangeKVs() is {}ms," - + " result length is {}.", timeConsumed, result.size()); - } - } - return result; - } - - @Override - public MetaStoreIterator iterator() { - return new LevelDBStoreIterator(db.iterator()); - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/LevelDBStoreIterator.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/LevelDBStoreIterator.java deleted file mode 100644 index 7b62f7ad43e..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/LevelDBStoreIterator.java +++ /dev/null @@ -1,64 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.utils; - -import org.iq80.leveldb.DBIterator; -import java.util.Map; -import java.util.NoSuchElementException; - -import org.apache.hadoop.utils.MetadataStore.KeyValue; - - -/** - * LevelDB store iterator. - */ -public class LevelDBStoreIterator implements MetaStoreIterator { - - - private DBIterator levelDBIterator; - - public LevelDBStoreIterator(DBIterator iterator) { - this.levelDBIterator = iterator; - levelDBIterator.seekToFirst(); - } - - @Override - public boolean hasNext() { - return levelDBIterator.hasNext(); - } - - @Override - public KeyValue next() { - if(levelDBIterator.hasNext()) { - Map.Entry entry = levelDBIterator.next(); - return KeyValue.create(entry.getKey(), entry.getValue()); - } - throw new NoSuchElementException("LevelDB Store has no more elements"); - } - - @Override - public void seekToFirst() { - levelDBIterator.seekToFirst(); - } - - @Override - public void seekToLast() { - levelDBIterator.seekToLast(); - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/MetaStoreIterator.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/MetaStoreIterator.java deleted file mode 100644 index 52d0a3efd3b..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/MetaStoreIterator.java +++ /dev/null @@ -1,39 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.utils; - -import java.util.Iterator; - -/** - * Iterator for MetaDataStore DB. - * @param - */ -public interface MetaStoreIterator extends Iterator { - - /** - * seek to first entry. - */ - void seekToFirst(); - - /** - * seek to last entry. - */ - void seekToLast(); - -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/MetadataKeyFilters.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/MetadataKeyFilters.java deleted file mode 100644 index a3430f868d0..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/MetadataKeyFilters.java +++ /dev/null @@ -1,205 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.utils; - -import com.google.common.base.Preconditions; -import com.google.common.base.Strings; -import org.apache.hadoop.hdfs.DFSUtil; -import org.apache.hadoop.ozone.OzoneConsts; - -import java.util.ArrayList; -import java.util.List; - -/** - * An utility class to filter levelDB keys. - */ -public final class MetadataKeyFilters { - - private static KeyPrefixFilter deletingKeyFilter = - new MetadataKeyFilters.KeyPrefixFilter() - .addFilter(OzoneConsts.DELETING_KEY_PREFIX); - - private static KeyPrefixFilter deletedKeyFilter = - new MetadataKeyFilters.KeyPrefixFilter() - .addFilter(OzoneConsts.DELETED_KEY_PREFIX); - - private static KeyPrefixFilter normalKeyFilter = - new MetadataKeyFilters.KeyPrefixFilter() - .addFilter(OzoneConsts.DELETING_KEY_PREFIX, true) - .addFilter(OzoneConsts.DELETED_KEY_PREFIX, true) - .addFilter(OzoneConsts.DELETE_TRANSACTION_KEY_PREFIX, true); - - private MetadataKeyFilters() { - } - - public static KeyPrefixFilter getDeletingKeyFilter() { - return deletingKeyFilter; - } - - public static KeyPrefixFilter getDeletedKeyFilter() { - return deletedKeyFilter; - } - - public static KeyPrefixFilter getNormalKeyFilter() { - return normalKeyFilter; - } - /** - * Interface for levelDB key filters. - */ - public interface MetadataKeyFilter { - /** - * Filter levelDB key with a certain condition. - * - * @param preKey previous key. - * @param currentKey current key. - * @param nextKey next key. - * @return true if a certain condition satisfied, return false otherwise. - */ - boolean filterKey(byte[] preKey, byte[] currentKey, byte[] nextKey); - - default int getKeysScannedNum() { - return 0; - } - - default int getKeysHintedNum() { - return 0; - } - } - - /** - * Utility class to filter key by a string prefix. This filter - * assumes keys can be parsed to a string. - */ - public static class KeyPrefixFilter implements MetadataKeyFilter { - - private List positivePrefixList = new ArrayList<>(); - private List negativePrefixList = new ArrayList<>(); - private boolean atleastOnePositiveMatch; - private int keysScanned = 0; - private int keysHinted = 0; - - public KeyPrefixFilter() {} - - /** - * KeyPrefixFilter constructor. It is made of positive and negative prefix - * list. PositivePrefixList is the list of prefixes which are accepted - * whereas negativePrefixList contains the list of prefixes which are - * rejected. - * - * @param atleastOnePositiveMatch if positive it requires key to be accepted - * by atleast one positive filter. - */ - public KeyPrefixFilter(boolean atleastOnePositiveMatch) { - this.atleastOnePositiveMatch = atleastOnePositiveMatch; - } - - public KeyPrefixFilter addFilter(String keyPrefix) { - addFilter(keyPrefix, false); - return this; - } - - public KeyPrefixFilter addFilter(String keyPrefix, boolean negative) { - Preconditions.checkArgument(!Strings.isNullOrEmpty(keyPrefix), - "KeyPrefix is null or empty: " + keyPrefix); - // keyPrefix which needs to be added should not be prefix of any opposing - // filter already present. If keyPrefix is a negative filter it should not - // be a prefix of any positive filter. Nor should any opposing filter be - // a prefix of keyPrefix. - // For example if b0 is accepted b can not be rejected and - // if b is accepted b0 can not be rejected. If these scenarios need to be - // handled we need to add priorities. - if (negative) { - Preconditions.checkArgument(positivePrefixList.stream().noneMatch( - prefix -> prefix.startsWith(keyPrefix) || keyPrefix - .startsWith(prefix)), - "KeyPrefix: " + keyPrefix + " already accepted."); - this.negativePrefixList.add(keyPrefix); - } else { - Preconditions.checkArgument(negativePrefixList.stream().noneMatch( - prefix -> prefix.startsWith(keyPrefix) || keyPrefix - .startsWith(prefix)), - "KeyPrefix: " + keyPrefix + " already rejected."); - this.positivePrefixList.add(keyPrefix); - } - return this; - } - - @Override - public boolean filterKey(byte[] preKey, byte[] currentKey, - byte[] nextKey) { - keysScanned++; - if (currentKey == null) { - return false; - } - boolean accept; - - // There are no filters present - if (positivePrefixList.isEmpty() && negativePrefixList.isEmpty()) { - return true; - } - - accept = !positivePrefixList.isEmpty() && positivePrefixList.stream() - .anyMatch(prefix -> { - byte[] prefixBytes = DFSUtil.string2Bytes(prefix); - return prefixMatch(prefixBytes, currentKey); - }); - if (accept) { - keysHinted++; - return true; - } else if (atleastOnePositiveMatch) { - return false; - } - - accept = !negativePrefixList.isEmpty() && negativePrefixList.stream() - .allMatch(prefix -> { - byte[] prefixBytes = DFSUtil.string2Bytes(prefix); - return !prefixMatch(prefixBytes, currentKey); - }); - if (accept) { - keysHinted++; - return true; - } - - return false; - } - - @Override - public int getKeysScannedNum() { - return keysScanned; - } - - @Override - public int getKeysHintedNum() { - return keysHinted; - } - - private static boolean prefixMatch(byte[] prefix, byte[] key) { - Preconditions.checkNotNull(prefix); - Preconditions.checkNotNull(key); - if (key.length < prefix.length) { - return false; - } - for (int i = 0; i < prefix.length; i++) { - if (key[i] != prefix[i]) { - return false; - } - } - return true; - } - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/MetadataStore.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/MetadataStore.java deleted file mode 100644 index 7d3bc6ba9a1..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/MetadataStore.java +++ /dev/null @@ -1,227 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.utils; - -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.hadoop.classification.InterfaceStability; -import org.apache.hadoop.utils.MetadataKeyFilters.MetadataKeyFilter; - -import java.io.Closeable; -import java.io.IOException; -import java.util.List; -import java.util.Map; - -/** - * Interface for key-value store that stores ozone metadata. - * Ozone metadata is stored as key value pairs, both key and value - * are arbitrary byte arrays. - */ -@InterfaceStability.Evolving -public interface MetadataStore extends Closeable{ - - /** - * Puts a key-value pair into the store. - * - * @param key metadata key - * @param value metadata value - */ - void put(byte[] key, byte[] value) throws IOException; - - /** - * @return true if the metadata store is empty. - * - * @throws IOException - */ - boolean isEmpty() throws IOException; - - /** - * Returns the value mapped to the given key in byte array. - * - * @param key metadata key - * @return value in byte array - * @throws IOException - */ - byte[] get(byte[] key) throws IOException; - - /** - * Deletes a key from the metadata store. - * - * @param key metadata key - * @throws IOException - */ - void delete(byte[] key) throws IOException; - - /** - * Returns a certain range of key value pairs as a list based on a - * startKey or count. Further a {@link MetadataKeyFilter} can be added to - * filter keys if necessary. To prevent race conditions while listing - * entries, this implementation takes a snapshot and lists the entries from - * the snapshot. This may, on the other hand, cause the range result slight - * different with actual data if data is updating concurrently. - *

- * If the startKey is specified and found in levelDB, this key and the keys - * after this key will be included in the result. If the startKey is null - * all entries will be included as long as other conditions are satisfied. - * If the given startKey doesn't exist and empty list will be returned. - *

- * The count argument is to limit number of total entries to return, - * the value for count must be an integer greater than 0. - *

- * This method allows to specify one or more {@link MetadataKeyFilter} - * to filter keys by certain condition. Once given, only the entries - * whose key passes all the filters will be included in the result. - * - * @param startKey a start key. - * @param count max number of entries to return. - * @param filters customized one or more {@link MetadataKeyFilter}. - * @return a list of entries found in the database or an empty list if the - * startKey is invalid. - * @throws IOException if there are I/O errors. - * @throws IllegalArgumentException if count is less than 0. - */ - List> getRangeKVs(byte[] startKey, - int count, MetadataKeyFilter... filters) - throws IOException, IllegalArgumentException; - - /** - * This method is very similar to {@link #getRangeKVs}, the only - * different is this method is supposed to return a sequential range - * of elements based on the filters. While iterating the elements, - * if it met any entry that cannot pass the filter, the iterator will stop - * from this point without looking for next match. If no filter is given, - * this method behaves just like {@link #getRangeKVs}. - * - * @param startKey a start key. - * @param count max number of entries to return. - * @param filters customized one or more {@link MetadataKeyFilter}. - * @return a list of entries found in the database. - * @throws IOException - * @throws IllegalArgumentException - */ - List> getSequentialRangeKVs(byte[] startKey, - int count, MetadataKeyFilter... filters) - throws IOException, IllegalArgumentException; - - /** - * A batch of PUT, DELETE operations handled as a single atomic write. - * - * @throws IOException write fails - */ - void writeBatch(BatchOperation operation) throws IOException; - - /** - * Compact the entire database. - * @throws IOException - */ - void compactDB() throws IOException; - - /** - * Destroy the content of the specified database, - * a destroyed database will not be able to load again. - * Be very careful with this method. - * - * @throws IOException if I/O error happens - */ - void destroy() throws IOException; - - /** - * Seek the database to a certain key, returns the key-value - * pairs around this key based on the given offset. Note, this method - * can only support offset -1 (left), 0 (current) and 1 (right), - * any other offset given will cause a {@link IllegalArgumentException}. - * - * @param offset offset to the key - * @param from from which key - * @return a key-value pair - * @throws IOException - */ - ImmutablePair peekAround(int offset, byte[] from) - throws IOException, IllegalArgumentException; - - /** - * Iterates entries in the database from a certain key. - * Applies the given {@link EntryConsumer} to the key and value of - * each entry, the function produces a boolean result which is used - * as the criteria to exit from iteration. - * - * @param from the start key - * @param consumer - * a {@link EntryConsumer} applied to each key and value. If the consumer - * returns true, continues the iteration to next entry; otherwise exits - * the iteration. - * @throws IOException - */ - void iterate(byte[] from, EntryConsumer consumer) - throws IOException; - - /** - * Returns the iterator for this metadata store. - * @return MetaStoreIterator - */ - MetaStoreIterator iterator(); - - /** - * Class used to represent the key and value pair of a db entry. - */ - class KeyValue { - - private final byte[] key; - private final byte[] value; - - /** - * KeyValue Constructor, used to represent a key and value of a db entry. - * @param key - * @param value - */ - private KeyValue(byte[] key, byte[] value) { - this.key = key; - this.value = value; - } - - /** - * Return key. - * @return byte[] - */ - public byte[] getKey() { - byte[] result = new byte[key.length]; - System.arraycopy(key, 0, result, 0, key.length); - return result; - } - - /** - * Return value. - * @return byte[] - */ - public byte[] getValue() { - byte[] result = new byte[value.length]; - System.arraycopy(value, 0, result, 0, value.length); - return result; - } - - /** - * Create a KeyValue pair. - * @param key - * @param value - * @return KeyValue object. - */ - public static KeyValue create(byte[] key, byte[] value) { - return new KeyValue(key, value); - } - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/MetadataStoreBuilder.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/MetadataStoreBuilder.java deleted file mode 100644 index 85cebed6503..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/MetadataStoreBuilder.java +++ /dev/null @@ -1,152 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.utils; - -import com.google.common.annotations.VisibleForTesting; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.ozone.OzoneConfigKeys; -import org.iq80.leveldb.Options; -import org.rocksdb.BlockBasedTableConfig; -import org.rocksdb.Statistics; -import org.rocksdb.StatsLevel; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; - -import static org.apache.hadoop.ozone.OzoneConfigKeys - .OZONE_METADATA_STORE_IMPL_LEVELDB; -import static org.apache.hadoop.ozone.OzoneConfigKeys - .OZONE_METADATA_STORE_IMPL_ROCKSDB; -import static org.apache.hadoop.ozone.OzoneConfigKeys - .OZONE_METADATA_STORE_ROCKSDB_STATISTICS; -import static org.apache.hadoop.ozone.OzoneConfigKeys - .OZONE_METADATA_STORE_ROCKSDB_STATISTICS_DEFAULT; -import static org.apache.hadoop.ozone.OzoneConfigKeys - .OZONE_METADATA_STORE_ROCKSDB_STATISTICS_OFF; - -/** - * Builder for metadata store. - */ -public class MetadataStoreBuilder { - - @VisibleForTesting - static final Logger LOG = - LoggerFactory.getLogger(MetadataStoreBuilder.class); - private File dbFile; - private long cacheSize; - private boolean createIfMissing = true; - private Configuration conf; - private String dbType; - - public static MetadataStoreBuilder newBuilder() { - return new MetadataStoreBuilder(); - } - - public MetadataStoreBuilder setDbFile(File dbPath) { - this.dbFile = dbPath; - return this; - } - - public MetadataStoreBuilder setCacheSize(long cache) { - this.cacheSize = cache; - return this; - } - - public MetadataStoreBuilder setCreateIfMissing(boolean doCreate) { - this.createIfMissing = doCreate; - return this; - } - - public MetadataStoreBuilder setConf(Configuration configuration) { - this.conf = configuration; - return this; - } - - /** - * Set the container DB Type. - * @param type - * @return MetadataStoreBuilder - */ - public MetadataStoreBuilder setDBType(String type) { - this.dbType = type; - return this; - } - - - public MetadataStore build() throws IOException { - if (dbFile == null) { - throw new IllegalArgumentException("Failed to build metadata store, " - + "dbFile is required but not found"); - } - - // Build db store based on configuration - MetadataStore store = null; - - if(dbType == null) { - LOG.debug("dbType is null, using "); - dbType = conf == null ? - OzoneConfigKeys.OZONE_METADATA_STORE_IMPL_DEFAULT : - conf.getTrimmed(OzoneConfigKeys.OZONE_METADATA_STORE_IMPL, - OzoneConfigKeys.OZONE_METADATA_STORE_IMPL_DEFAULT); - LOG.debug("dbType is null, using dbType {} from ozone configuration", - dbType); - } else { - LOG.debug("Using dbType {} for metastore", dbType); - } - if (OZONE_METADATA_STORE_IMPL_LEVELDB.equals(dbType)) { - Options options = new Options(); - options.createIfMissing(createIfMissing); - if (cacheSize > 0) { - options.cacheSize(cacheSize); - } - store = new LevelDBStore(dbFile, options); - } else if (OZONE_METADATA_STORE_IMPL_ROCKSDB.equals(dbType)) { - org.rocksdb.Options opts = new org.rocksdb.Options(); - opts.setCreateIfMissing(createIfMissing); - - if (cacheSize > 0) { - BlockBasedTableConfig tableConfig = new BlockBasedTableConfig(); - tableConfig.setBlockCacheSize(cacheSize); - opts.setTableFormatConfig(tableConfig); - } - - String rocksDbStat = conf == null ? - OZONE_METADATA_STORE_ROCKSDB_STATISTICS_DEFAULT : - conf.getTrimmed(OZONE_METADATA_STORE_ROCKSDB_STATISTICS, - OZONE_METADATA_STORE_ROCKSDB_STATISTICS_DEFAULT); - - if (!rocksDbStat.equals(OZONE_METADATA_STORE_ROCKSDB_STATISTICS_OFF)) { - Statistics statistics = new Statistics(); - statistics.setStatsLevel(StatsLevel.valueOf(rocksDbStat)); - opts = opts.setStatistics(statistics); - - } - store = new RocksDBStore(dbFile, opts); - } else { - throw new IllegalArgumentException("Invalid argument for " - + OzoneConfigKeys.OZONE_METADATA_STORE_IMPL - + ". Expecting " + OZONE_METADATA_STORE_IMPL_LEVELDB - + " or " + OZONE_METADATA_STORE_IMPL_ROCKSDB - + ", but met " + dbType); - } - return store; - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/RocksDBStore.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/RocksDBStore.java deleted file mode 100644 index 379d9e9d1db..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/RocksDBStore.java +++ /dev/null @@ -1,388 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.utils; - -import com.google.common.base.Preconditions; -import org.apache.commons.io.FileUtils; -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.hadoop.metrics2.util.MBeans; -import org.apache.ratis.shaded.com.google.common.annotations.VisibleForTesting; -import org.rocksdb.DbPath; -import org.rocksdb.Options; -import org.rocksdb.RocksDB; -import org.rocksdb.RocksDBException; -import org.rocksdb.RocksIterator; -import org.rocksdb.WriteBatch; -import org.rocksdb.WriteOptions; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.management.ObjectName; -import java.io.File; -import java.io.IOException; -import java.util.AbstractMap; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * RocksDB implementation of ozone metadata store. - */ -public class RocksDBStore implements MetadataStore { - - private static final Logger LOG = - LoggerFactory.getLogger(RocksDBStore.class); - - private RocksDB db = null; - private File dbLocation; - private WriteOptions writeOptions; - private Options dbOptions; - private ObjectName statMBeanName; - - public RocksDBStore(File dbFile, Options options) - throws IOException { - Preconditions.checkNotNull(dbFile, "DB file location cannot be null"); - RocksDB.loadLibrary(); - dbOptions = options; - dbLocation = dbFile; - writeOptions = new WriteOptions(); - try { - - db = RocksDB.open(dbOptions, dbLocation.getAbsolutePath()); - if (dbOptions.statistics() != null) { - - Map jmxProperties = new HashMap(); - jmxProperties.put("dbName", dbFile.getName()); - statMBeanName = MBeans.register("Ozone", "RocksDbStore", jmxProperties, - new RocksDBStoreMBean(dbOptions.statistics())); - if (statMBeanName == null) { - LOG.warn("jmx registration failed during RocksDB init, db path :{}", - dbFile.getAbsolutePath()); - } - } - } catch (RocksDBException e) { - throw new IOException( - "Failed init RocksDB, db path : " + dbFile.getAbsolutePath(), e); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("RocksDB successfully opened."); - LOG.debug("[Option] dbLocation= {}", dbLocation.getAbsolutePath()); - LOG.debug("[Option] createIfMissing = {}", options.createIfMissing()); - LOG.debug("[Option] compactionPriority= {}", options.compactionStyle()); - LOG.debug("[Option] compressionType= {}", options.compressionType()); - LOG.debug("[Option] maxOpenFiles= {}", options.maxOpenFiles()); - LOG.debug("[Option] writeBufferSize= {}", options.writeBufferSize()); - } - } - - public static IOException toIOException(String msg, RocksDBException e) { - String statusCode = e.getStatus() == null ? "N/A" : - e.getStatus().getCodeString(); - String errMessage = e.getMessage() == null ? "Unknown error" : - e.getMessage(); - String output = msg + "; status : " + statusCode - + "; message : " + errMessage; - return new IOException(output, e); - } - - @Override - public void put(byte[] key, byte[] value) throws IOException { - try { - db.put(writeOptions, key, value); - } catch (RocksDBException e) { - throw toIOException("Failed to put key-value to metadata store", e); - } - } - - @Override - public boolean isEmpty() throws IOException { - RocksIterator it = null; - try { - it = db.newIterator(); - it.seekToFirst(); - return !it.isValid(); - } finally { - if (it != null) { - it.close(); - } - } - } - - @Override - public byte[] get(byte[] key) throws IOException { - try { - return db.get(key); - } catch (RocksDBException e) { - throw toIOException("Failed to get the value for the given key", e); - } - } - - @Override - public void delete(byte[] key) throws IOException { - try { - db.delete(key); - } catch (RocksDBException e) { - throw toIOException("Failed to delete the given key", e); - } - } - - @Override - public List> getRangeKVs(byte[] startKey, - int count, MetadataKeyFilters.MetadataKeyFilter... filters) - throws IOException, IllegalArgumentException { - return getRangeKVs(startKey, count, false, filters); - } - - @Override - public List> getSequentialRangeKVs(byte[] startKey, - int count, MetadataKeyFilters.MetadataKeyFilter... filters) - throws IOException, IllegalArgumentException { - return getRangeKVs(startKey, count, true, filters); - } - - private List> getRangeKVs(byte[] startKey, - int count, boolean sequential, - MetadataKeyFilters.MetadataKeyFilter... filters) - throws IOException, IllegalArgumentException { - List> result = new ArrayList<>(); - long start = System.currentTimeMillis(); - if (count < 0) { - throw new IllegalArgumentException( - "Invalid count given " + count + ", count must be greater than 0"); - } - RocksIterator it = null; - try { - it = db.newIterator(); - if (startKey == null) { - it.seekToFirst(); - } else { - if(get(startKey) == null) { - // Key not found, return empty list - return result; - } - it.seek(startKey); - } - while(it.isValid() && result.size() < count) { - byte[] currentKey = it.key(); - byte[] currentValue = it.value(); - - it.prev(); - final byte[] prevKey = it.isValid() ? it.key() : null; - - it.seek(currentKey); - it.next(); - final byte[] nextKey = it.isValid() ? it.key() : null; - - if (filters == null) { - result.add(new AbstractMap.SimpleImmutableEntry<>(currentKey, - currentValue)); - } else { - if (Arrays.asList(filters).stream() - .allMatch(entry -> entry.filterKey(prevKey, - currentKey, nextKey))) { - result.add(new AbstractMap.SimpleImmutableEntry<>(currentKey, - currentValue)); - } else { - if (result.size() > 0 && sequential) { - // if the caller asks for a sequential range of results, - // and we met a dis-match, abort iteration from here. - // if result is empty, we continue to look for the first match. - break; - } - } - } - } - } finally { - if (it != null) { - it.close(); - } - long end = System.currentTimeMillis(); - long timeConsumed = end - start; - if (LOG.isDebugEnabled()) { - if (filters != null) { - for (MetadataKeyFilters.MetadataKeyFilter filter : filters) { - int scanned = filter.getKeysScannedNum(); - int hinted = filter.getKeysHintedNum(); - if (scanned > 0 || hinted > 0) { - LOG.debug( - "getRangeKVs ({}) numOfKeysScanned={}, numOfKeysHinted={}", - filter.getClass().getSimpleName(), filter.getKeysScannedNum(), - filter.getKeysHintedNum()); - } - } - } - LOG.debug("Time consumed for getRangeKVs() is {}ms," - + " result length is {}.", timeConsumed, result.size()); - } - } - return result; - } - - @Override - public void writeBatch(BatchOperation operation) - throws IOException { - List operations = - operation.getOperations(); - if (!operations.isEmpty()) { - try (WriteBatch writeBatch = new WriteBatch()) { - for (BatchOperation.SingleOperation opt : operations) { - switch (opt.getOpt()) { - case DELETE: - writeBatch.delete(opt.getKey()); - break; - case PUT: - writeBatch.put(opt.getKey(), opt.getValue()); - break; - default: - throw new IllegalArgumentException("Invalid operation " - + opt.getOpt()); - } - } - db.write(writeOptions, writeBatch); - } catch (RocksDBException e) { - throw toIOException("Batch write operation failed", e); - } - } - } - - @Override - public void compactDB() throws IOException { - if (db != null) { - try { - db.compactRange(); - } catch (RocksDBException e) { - throw toIOException("Failed to compact db", e); - } - } - } - - private void deleteQuietly(File fileOrDir) { - if (fileOrDir != null && fileOrDir.exists()) { - try { - FileUtils.forceDelete(fileOrDir); - } catch (IOException e) { - LOG.warn("Failed to delete dir {}", fileOrDir.getAbsolutePath(), e); - } - } - } - - @Override - public void destroy() throws IOException { - // Make sure db is closed. - close(); - - // There is no destroydb java API available, - // equivalently we can delete all db directories. - deleteQuietly(dbLocation); - deleteQuietly(new File(dbOptions.dbLogDir())); - deleteQuietly(new File(dbOptions.walDir())); - List dbPaths = dbOptions.dbPaths(); - if (dbPaths != null) { - dbPaths.forEach(dbPath -> { - deleteQuietly(new File(dbPath.toString())); - }); - } - } - - @Override - public ImmutablePair peekAround(int offset, - byte[] from) throws IOException, IllegalArgumentException { - RocksIterator it = null; - try { - it = db.newIterator(); - if (from == null) { - it.seekToFirst(); - } else { - it.seek(from); - } - if (!it.isValid()) { - return null; - } - - switch (offset) { - case 0: - break; - case 1: - it.next(); - break; - case -1: - it.prev(); - break; - default: - throw new IllegalArgumentException( - "Position can only be -1, 0 " + "or 1, but found " + offset); - } - return it.isValid() ? new ImmutablePair<>(it.key(), it.value()) : null; - } finally { - if (it != null) { - it.close(); - } - } - } - - @Override - public void iterate(byte[] from, EntryConsumer consumer) - throws IOException { - RocksIterator it = null; - try { - it = db.newIterator(); - if (from != null) { - it.seek(from); - } else { - it.seekToFirst(); - } - while (it.isValid()) { - if (!consumer.consume(it.key(), it.value())) { - break; - } - it.next(); - } - } finally { - if (it != null) { - it.close(); - } - } - } - - @Override - public void close() throws IOException { - if (statMBeanName != null) { - MBeans.unregister(statMBeanName); - statMBeanName = null; - } - if (db != null) { - db.close(); - } - - } - - @VisibleForTesting - protected ObjectName getStatMBeanName() { - return statMBeanName; - } - - @Override - public MetaStoreIterator iterator() { - return new RocksDBStoreIterator(db.newIterator()); - } - -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/RocksDBStoreIterator.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/RocksDBStoreIterator.java deleted file mode 100644 index 6e9b6958da1..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/RocksDBStoreIterator.java +++ /dev/null @@ -1,66 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package org.apache.hadoop.utils; - -import org.rocksdb.RocksIterator; - -import java.util.NoSuchElementException; - -import org.apache.hadoop.utils.MetadataStore.KeyValue; - -/** - * RocksDB store iterator. - */ -public class RocksDBStoreIterator implements MetaStoreIterator { - - private RocksIterator rocksDBIterator; - - public RocksDBStoreIterator(RocksIterator iterator) { - this.rocksDBIterator = iterator; - rocksDBIterator.seekToFirst(); - } - - @Override - public boolean hasNext() { - return rocksDBIterator.isValid(); - } - - @Override - public KeyValue next() { - if (rocksDBIterator.isValid()) { - KeyValue value = KeyValue.create(rocksDBIterator.key(), rocksDBIterator - .value()); - rocksDBIterator.next(); - return value; - } - throw new NoSuchElementException("RocksDB Store has no more elements"); - } - - @Override - public void seekToFirst() { - rocksDBIterator.seekToFirst(); - } - - @Override - public void seekToLast() { - rocksDBIterator.seekToLast(); - } - -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/RocksDBStoreMBean.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/RocksDBStoreMBean.java deleted file mode 100644 index 88c093e62bf..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/RocksDBStoreMBean.java +++ /dev/null @@ -1,144 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.utils; - -import org.rocksdb.HistogramData; -import org.rocksdb.HistogramType; -import org.rocksdb.Statistics; -import org.rocksdb.TickerType; - -import javax.management.Attribute; -import javax.management.AttributeList; -import javax.management.AttributeNotFoundException; -import javax.management.DynamicMBean; -import javax.management.InvalidAttributeValueException; -import javax.management.MBeanAttributeInfo; -import javax.management.MBeanException; -import javax.management.MBeanInfo; -import javax.management.ReflectionException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * Adapter JMX bean to publish all the Rocksdb metrics. - */ -public class RocksDBStoreMBean implements DynamicMBean { - - private Statistics statistics; - - private Set histogramAttributes = new HashSet<>(); - - public RocksDBStoreMBean(Statistics statistics) { - this.statistics = statistics; - histogramAttributes.add("Average"); - histogramAttributes.add("Median"); - histogramAttributes.add("Percentile95"); - histogramAttributes.add("Percentile99"); - histogramAttributes.add("StandardDeviation"); - } - - @Override - public Object getAttribute(String attribute) - throws AttributeNotFoundException, MBeanException, ReflectionException { - for (String histogramAttribute : histogramAttributes) { - if (attribute.endsWith("_" + histogramAttribute.toUpperCase())) { - String keyName = attribute - .substring(0, attribute.length() - histogramAttribute.length() - 1); - try { - HistogramData histogram = - statistics.getHistogramData(HistogramType.valueOf(keyName)); - try { - Method method = - HistogramData.class.getMethod("get" + histogramAttribute); - return method.invoke(histogram); - } catch (Exception e) { - throw new ReflectionException(e, - "Can't read attribute " + attribute); - } - } catch (IllegalArgumentException exception) { - throw new AttributeNotFoundException( - "No such attribute in RocksDB stats: " + attribute); - } - } - } - try { - return statistics.getTickerCount(TickerType.valueOf(attribute)); - } catch (IllegalArgumentException ex) { - throw new AttributeNotFoundException( - "No such attribute in RocksDB stats: " + attribute); - } - } - - @Override - public void setAttribute(Attribute attribute) - throws AttributeNotFoundException, InvalidAttributeValueException, - MBeanException, ReflectionException { - - } - - @Override - public AttributeList getAttributes(String[] attributes) { - AttributeList result = new AttributeList(); - for (String attributeName : attributes) { - try { - Object value = getAttribute(attributeName); - result.add(value); - } catch (Exception e) { - //TODO - } - } - return result; - } - - @Override - public AttributeList setAttributes(AttributeList attributes) { - return null; - } - - @Override - public Object invoke(String actionName, Object[] params, String[] signature) - throws MBeanException, ReflectionException { - return null; - } - - @Override - public MBeanInfo getMBeanInfo() { - - List attributes = new ArrayList<>(); - for (TickerType tickerType : TickerType.values()) { - attributes.add(new MBeanAttributeInfo(tickerType.name(), "long", - "RocksDBStat: " + tickerType.name(), true, false, false)); - } - for (HistogramType histogramType : HistogramType.values()) { - for (String histogramAttribute : histogramAttributes) { - attributes.add(new MBeanAttributeInfo( - histogramType.name() + "_" + histogramAttribute.toUpperCase(), - "long", "RocksDBStat: " + histogramType.name(), true, false, - false)); - } - } - - return new MBeanInfo("", "RocksDBStat", - attributes.toArray(new MBeanAttributeInfo[0]), null, null, null); - - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/DBConfigFromFile.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/DBConfigFromFile.java deleted file mode 100644 index 94370b1cd5b..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/DBConfigFromFile.java +++ /dev/null @@ -1,146 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.hadoop.utils.db; - -import com.google.common.base.Preconditions; -import org.eclipse.jetty.util.StringUtil; -import org.rocksdb.ColumnFamilyDescriptor; -import org.rocksdb.DBOptions; -import org.rocksdb.Env; -import org.rocksdb.OptionsUtil; -import org.rocksdb.RocksDBException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.List; - -/** - * A Class that controls the standard config options of RocksDB. - *

- * Important : Some of the functions in this file are magic functions designed - * for the use of OZONE developers only. Due to that this information is - * documented in this files only and is *not* intended for end user consumption. - * Please do not use this information to tune your production environments. - * Please remember the SpiderMan principal; with great power comes great - * responsibility. - */ -public final class DBConfigFromFile { - private static final Logger LOG = - LoggerFactory.getLogger(DBConfigFromFile.class); - - public static final String CONFIG_DIR = "HADOOP_CONF_DIR"; - - private DBConfigFromFile() { - } - - public static File getConfigLocation() throws IOException { - String path = System.getenv(CONFIG_DIR); - - // Make testing easy. - // If there is No Env. defined, let us try to read the JVM property - if (StringUtil.isBlank(path)) { - path = System.getProperty(CONFIG_DIR); - } - - if (StringUtil.isBlank(path)) { - LOG.debug("Unable to find the configuration directory. " - + "Please make sure that HADOOP_CONF_DIR is setup correctly."); - } - if(StringUtil.isBlank(path)){ - return null; - } - return new File(path); - - } - - /** - * This class establishes a magic pattern where we look for DBFile.ini as the - * options for RocksDB. - * - * @param dbFileName - The DBFile Name. For example, OzoneManager.db - * @return Name of the DB File options - */ - public static String getOptionsFileNameFromDB(String dbFileName) { - Preconditions.checkNotNull(dbFileName); - return dbFileName + ".ini"; - } - - /** - * One of the Magic functions designed for the use of Ozone Developers *ONLY*. - * This function takes the name of DB file and looks up the a .ini file that - * follows the ROCKSDB config format and uses that file for DBOptions and - * Column family Options. The Format for this file is specified by RockDB. - *

- * Here is a sample config from RocksDB sample Repo. - *

- * https://github.com/facebook/rocksdb/blob/master/examples - * /rocksdb_option_file_example.ini - *

- * We look for a specific pattern, say OzoneManager.db will have its configs - * specified in OzoneManager.db.ini. This option is used only by the - * performance testing group to allow tuning of all parameters freely. - *

- * For the end users we offer a set of Predefined options that is easy to use - * and the user does not need to become an expert in RockDB config. - *

- * This code assumes the .ini file is placed in the same directory as normal - * config files. That is in $HADOOP_DIR/etc/hadoop. For example, if we want to - * control OzoneManager.db configs from a file, we need to create a file - * called OzoneManager.db.ini and place that file in $HADOOP_DIR/etc/hadoop. - * - * @param dbFileName - The DB File Name, for example, OzoneManager.db. - * @param cfDescs - ColumnFamily Handles. - * @return DBOptions, Options to be used for opening/creating the DB. - * @throws IOException - */ - public static DBOptions readFromFile(String dbFileName, - List cfDescs) throws IOException { - Preconditions.checkNotNull(dbFileName); - Preconditions.checkNotNull(cfDescs); - Preconditions.checkArgument(cfDescs.size() > 0); - - //TODO: Add Documentation on how to support RocksDB Mem Env. - Env env = Env.getDefault(); - DBOptions options = null; - File configLocation = getConfigLocation(); - if(configLocation != null && - StringUtil.isNotBlank(configLocation.toString())){ - Path optionsFile = Paths.get(configLocation.toString(), - getOptionsFileNameFromDB(dbFileName)); - - if (optionsFile.toFile().exists()) { - options = new DBOptions(); - try { - OptionsUtil.loadOptionsFromFile(optionsFile.toString(), - env, options, cfDescs, true); - - } catch (RocksDBException rdEx) { - RDBTable.toIOException("Unable to find/open Options file.", rdEx); - } - } - } - return options; - } - -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/DBProfile.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/DBProfile.java deleted file mode 100644 index 4d3d6bc7700..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/DBProfile.java +++ /dev/null @@ -1,120 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.hadoop.utils.db; - -import org.apache.hadoop.conf.StorageUnit; -import org.rocksdb.BlockBasedTableConfig; -import org.rocksdb.BloomFilter; -import org.rocksdb.ColumnFamilyOptions; -import org.rocksdb.CompactionStyle; -import org.rocksdb.DBOptions; - -import java.math.BigDecimal; - -/** - * User visible configs based RocksDB tuning page. Documentation for Options. - *

- * https://github.com/facebook/rocksdb/blob/master/include/rocksdb/options.h - *

- * Most tuning parameters are based on this URL. - *

- * https://github.com/facebook/rocksdb/wiki/Setup-Options-and-Basic-Tuning - */ -public enum DBProfile { - //TODO : Add more profiles like TEST etc. - SSD { - @Override - public String toString() { - return "DBProfile.SSD"; - } - - @Override - public ColumnFamilyOptions getColumnFamilyOptions() { - - // Set BlockCacheSize to 256 MB. This should not be an issue for HADOOP. - final long blockCacheSize = toLong(StorageUnit.MB.toBytes(256.00)); - - // Set the Default block size to 16KB - final long blockSize = toLong(StorageUnit.KB.toBytes(16)); - - // Write Buffer Size -- set to 128 MB - final long writeBufferSize = toLong(StorageUnit.MB.toBytes(128)); - - return new ColumnFamilyOptions() - .setLevelCompactionDynamicLevelBytes(true) - .setWriteBufferSize(writeBufferSize) - .setTableFormatConfig( - new BlockBasedTableConfig() - .setBlockCacheSize(blockCacheSize) - .setBlockSize(blockSize) - .setCacheIndexAndFilterBlocks(true) - .setPinL0FilterAndIndexBlocksInCache(true) - .setFilter(new BloomFilter())); - } - - @Override - public DBOptions getDBOptions() { - final int maxBackgroundCompactions = 4; - final int maxBackgroundFlushes = 2; - final long bytesPerSync = toLong(StorageUnit.MB.toBytes(1.00)); - final boolean createIfMissing = true; - final boolean createMissingColumnFamilies = true; - return new DBOptions() - .setIncreaseParallelism(Runtime.getRuntime().availableProcessors()) - .setMaxBackgroundCompactions(maxBackgroundCompactions) - .setMaxBackgroundFlushes(maxBackgroundFlushes) - .setBytesPerSync(bytesPerSync) - .setCreateIfMissing(createIfMissing) - .setCreateMissingColumnFamilies(createMissingColumnFamilies); - } - - - }, - DISK { - @Override - public String toString() { - return "DBProfile.DISK"; - } - - @Override - public DBOptions getDBOptions() { - final long readAheadSize = toLong(StorageUnit.MB.toBytes(4.00)); - return SSD.getDBOptions().setCompactionReadaheadSize(readAheadSize); - } - - @Override - public ColumnFamilyOptions getColumnFamilyOptions() { - ColumnFamilyOptions columnFamilyOptions = SSD.getColumnFamilyOptions(); - columnFamilyOptions.setCompactionStyle(CompactionStyle.LEVEL); - return columnFamilyOptions; - } - - - }; - - private static long toLong(double value) { - BigDecimal temp = new BigDecimal(value); - return temp.longValue(); - } - - public abstract DBOptions getDBOptions(); - - public abstract ColumnFamilyOptions getColumnFamilyOptions(); -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/DBStore.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/DBStore.java deleted file mode 100644 index 6947a83c8e0..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/DBStore.java +++ /dev/null @@ -1,115 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.hadoop.utils.db; - -import org.apache.hadoop.classification.InterfaceStability; -import org.rocksdb.WriteBatch; - -import java.io.IOException; -import java.util.ArrayList; - -/** - * The DBStore interface provides the ability to create Tables, which store - * a specific type of Key-Value pair. Some DB interfaces like LevelDB will not - * be able to do this. In those case a Table creation will map to a default - * store. - * - */ -@InterfaceStability.Evolving -public interface DBStore extends AutoCloseable { - - /** - * Gets an existing TableStore. - * - * @param name - Name of the TableStore to get - * @return - TableStore. - * @throws IOException on Failure - */ - Table getTable(String name) throws IOException; - - /** - * Lists the Known list of Tables in a DB. - * - * @return List of Tables, in case of Rocks DB and LevelDB we will return at - * least one entry called DEFAULT. - * @throws IOException on Failure - */ - ArrayList listTables() throws IOException; - - /** - * Compact the entire database. - * - * @throws IOException on Failure - */ - void compactDB() throws IOException; - - /** - * Moves a key from the Source Table to the destination Table. - * - * @param key - Key to move. - * @param source - Source Table. - * @param dest - Destination Table. - * @throws IOException on Failure - */ - void move(byte[] key, Table source, Table dest) throws IOException; - - /** - * Moves a key from the Source Table to the destination Table and updates the - * destination to the new value. - * - * @param key - Key to move. - * @param value - new value to write to the destination table. - * @param source - Source Table. - * @param dest - Destination Table. - * @throws IOException on Failure - */ - void move(byte[] key, byte[] value, Table source, Table dest) - throws IOException; - - /** - * Moves a key from the Source Table to the destination Table and updates the - * destination with the new key name and value. - * This is similar to deleting an entry in one table and adding an entry in - * another table, here it is done atomically. - * - * @param sourceKey - Key to move. - * @param destKey - Destination key name. - * @param value - new value to write to the destination table. - * @param source - Source Table. - * @param dest - Destination Table. - * @throws IOException on Failure - */ - void move(byte[] sourceKey, byte[] destKey, byte[] value, - Table source, Table dest) throws IOException; - - /** - * Returns an estimated count of keys in this DB. - * - * @return long, estimate of keys in the DB. - */ - long getEstimatedKeyCount() throws IOException; - - /** - * Writes a transaction into the DB using the default write Options. - * @param batch - Batch to write. - */ - void write(WriteBatch batch) throws IOException; - -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/DBStoreBuilder.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/DBStoreBuilder.java deleted file mode 100644 index 5ba9b9c87d3..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/DBStoreBuilder.java +++ /dev/null @@ -1,201 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.hadoop.utils.db; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.conf.Configuration; - -import org.apache.hadoop.hdfs.DFSUtil; -import org.eclipse.jetty.util.StringUtil; -import org.rocksdb.ColumnFamilyDescriptor; -import org.rocksdb.ColumnFamilyOptions; -import org.rocksdb.DBOptions; -import org.rocksdb.RocksDB; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; - -import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_DB_PROFILE; -import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_DEFAULT_DB_PROFILE; - -/** - * DBStore Builder. - */ -public final class DBStoreBuilder { - private static final Logger LOG = - LoggerFactory.getLogger(DBStoreBuilder.class); - private Set tables; - private DBProfile dbProfile; - private DBOptions rocksDBOption; - private String dbname; - private Path dbPath; - private List tableNames; - private Configuration configuration; - - private DBStoreBuilder(Configuration configuration) { - tables = new HashSet<>(); - tableNames = new LinkedList<>(); - this.configuration = configuration; - } - - public static DBStoreBuilder newBuilder(Configuration configuration) { - return new DBStoreBuilder(configuration); - } - - public DBStoreBuilder setProfile(DBProfile profile) { - dbProfile = profile; - return this; - } - - public DBStoreBuilder setName(String name) { - dbname = name; - return this; - } - - public DBStoreBuilder addTable(String tableName) { - tableNames.add(tableName); - return this; - } - - public DBStoreBuilder addTable(String tableName, ColumnFamilyOptions option) - throws IOException { - TableConfig tableConfig = new TableConfig(tableName, option); - if (!tables.add(tableConfig)) { - String message = "Unable to add the table: " + tableName + - ". Please check if this table name is already in use."; - LOG.error(message); - throw new IOException(message); - } - LOG.info("using custom profile for table: {}", tableName); - return this; - } - - public DBStoreBuilder setDBOption(DBOptions option) { - rocksDBOption = option; - return this; - } - - public DBStoreBuilder setPath(Path path) { - Preconditions.checkNotNull(path); - dbPath = path; - return this; - } - - /** - * Builds a DBStore instance and returns that. - * - * @return DBStore - */ - public DBStore build() throws IOException { - if(StringUtil.isBlank(dbname) || (dbPath == null)) { - LOG.error("Required Parameter missing."); - throw new IOException("Required parameter is missing. Please make sure " - + "sure Path and DB name is provided."); - } - processDBProfile(); - processTables(); - DBOptions options = getDbProfile(); - File dbFile = getDBFile(); - if (!dbFile.getParentFile().exists()) { - throw new IOException("The DB destination directory should exist."); - } - return new RDBStore(dbFile, options, tables); - } - - /** - * if the DBProfile is not set, we will default to using default from the - * config file. - */ - private void processDBProfile() { - if (dbProfile == null) { - dbProfile = this.configuration.getEnum(HDDS_DB_PROFILE, - HDDS_DEFAULT_DB_PROFILE); - } - } - - private void processTables() throws IOException { - if (tableNames.size() > 0) { - for (String name : tableNames) { - addTable(name, dbProfile.getColumnFamilyOptions()); - LOG.info("Using default column profile:{} for Table:{}", - dbProfile.toString(), name); - } - } - addTable(DFSUtil.bytes2String(RocksDB.DEFAULT_COLUMN_FAMILY), - dbProfile.getColumnFamilyOptions()); - LOG.info("Using default column profile:{} for Table:{}", - dbProfile.toString(), - DFSUtil.bytes2String(RocksDB.DEFAULT_COLUMN_FAMILY)); - } - - private DBOptions getDbProfile() { - if (rocksDBOption != null) { - return rocksDBOption; - } - DBOptions option = null; - if (StringUtil.isNotBlank(dbname)) { - List columnFamilyDescriptors = new LinkedList<>(); - - for (TableConfig tc : tables) { - columnFamilyDescriptors.add(tc.getDescriptor()); - } - - if (columnFamilyDescriptors.size() > 0) { - try { - option = DBConfigFromFile.readFromFile(dbname, - columnFamilyDescriptors); - if(option != null) { - LOG.info("Using Configs from {}.ini file", dbname); - } - } catch (IOException ex) { - LOG.info("Unable to read ROCKDB config", ex); - } - } - } - - if (option == null) { - LOG.info("Using default options. {}", dbProfile.toString()); - return dbProfile.getDBOptions(); - } - return option; - } - - private File getDBFile() throws IOException { - if (dbPath == null) { - LOG.error("DB path is required."); - throw new IOException("A Path to for DB file is needed."); - } - - if (StringUtil.isBlank(dbname)) { - LOG.error("DBName is a required."); - throw new IOException("A valid DB name is required."); - } - return Paths.get(dbPath.toString(), dbname).toFile(); - } - -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/RDBStore.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/RDBStore.java deleted file mode 100644 index 5078b3e96cf..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/RDBStore.java +++ /dev/null @@ -1,270 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.hadoop.utils.db; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdfs.DFSUtil; -import org.apache.hadoop.metrics2.util.MBeans; -import org.apache.hadoop.utils.RocksDBStoreMBean; -import org.apache.ratis.shaded.com.google.common.annotations.VisibleForTesting; -import org.rocksdb.ColumnFamilyDescriptor; -import org.rocksdb.ColumnFamilyHandle; - -import org.rocksdb.DBOptions; -import org.rocksdb.RocksDB; -import org.rocksdb.RocksDBException; -import org.rocksdb.WriteBatch; -import org.rocksdb.WriteOptions; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.management.ObjectName; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * RocksDB Store that supports creating Tables in DB. - */ -public class RDBStore implements DBStore { - private static final Logger LOG = - LoggerFactory.getLogger(RDBStore.class); - private final RocksDB db; - private final File dbLocation; - private final WriteOptions writeOptions; - private final DBOptions dbOptions; - private final Hashtable handleTable; - private ObjectName statMBeanName; - - public RDBStore(File dbFile, DBOptions options, Set families) - throws IOException { - Preconditions.checkNotNull(dbFile, "DB file location cannot be null"); - Preconditions.checkNotNull(families); - Preconditions.checkArgument(families.size() > 0); - handleTable = new Hashtable<>(); - - final List columnFamilyDescriptors = - new ArrayList<>(); - final List columnFamilyHandles = new ArrayList<>(); - - for (TableConfig family : families) { - columnFamilyDescriptors.add(family.getDescriptor()); - } - - dbOptions = options; - dbLocation = dbFile; - // TODO: Read from the next Config. - writeOptions = new WriteOptions(); - - try { - db = RocksDB.open(dbOptions, dbLocation.getAbsolutePath(), - columnFamilyDescriptors, columnFamilyHandles); - - for (int x = 0; x < columnFamilyHandles.size(); x++) { - handleTable.put( - DFSUtil.bytes2String(columnFamilyHandles.get(x).getName()), - columnFamilyHandles.get(x)); - } - - if (dbOptions.statistics() != null) { - Map jmxProperties = new HashMap<>(); - jmxProperties.put("dbName", dbFile.getName()); - statMBeanName = MBeans.register("Ozone", "RocksDbStore", jmxProperties, - new RocksDBStoreMBean(dbOptions.statistics())); - if (statMBeanName == null) { - LOG.warn("jmx registration failed during RocksDB init, db path :{}", - dbFile.getAbsolutePath()); - } - } - - } catch (RocksDBException e) { - throw toIOException( - "Failed init RocksDB, db path : " + dbFile.getAbsolutePath(), e); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("RocksDB successfully opened."); - LOG.debug("[Option] dbLocation= {}", dbLocation.getAbsolutePath()); - LOG.debug("[Option] createIfMissing = {}", options.createIfMissing()); - LOG.debug("[Option] maxOpenFiles= {}", options.maxOpenFiles()); - } - } - - public static IOException toIOException(String msg, RocksDBException e) { - String statusCode = e.getStatus() == null ? "N/A" : - e.getStatus().getCodeString(); - String errMessage = e.getMessage() == null ? "Unknown error" : - e.getMessage(); - String output = msg + "; status : " + statusCode - + "; message : " + errMessage; - return new IOException(output, e); - } - - @Override - public void compactDB() throws IOException { - if (db != null) { - try { - db.compactRange(); - } catch (RocksDBException e) { - throw toIOException("Failed to compact db", e); - } - } - } - - @Override - public void close() throws IOException { - - for (final ColumnFamilyHandle handle : handleTable.values()) { - handle.close(); - } - - if (statMBeanName != null) { - MBeans.unregister(statMBeanName); - statMBeanName = null; - } - - if (db != null) { - db.close(); - } - - if (dbOptions != null) { - dbOptions.close(); - } - - if (writeOptions != null) { - writeOptions.close(); - } - } - - @Override - public void move(byte[] key, Table source, Table dest) throws IOException { - RDBTable sourceTable; - RDBTable destTable; - if (source instanceof RDBTable) { - sourceTable = (RDBTable) source; - } else { - LOG.error("Unexpected Table type. Expected RocksTable Store for Source."); - throw new IOException("Unexpected TableStore Type in source. Expected " - + "RocksDBTable."); - } - - if (dest instanceof RDBTable) { - destTable = (RDBTable) dest; - } else { - LOG.error("Unexpected Table type. Expected RocksTable Store for Dest."); - throw new IOException("Unexpected TableStore Type in dest. Expected " - + "RocksDBTable."); - } - try (WriteBatch batch = new WriteBatch()) { - byte[] value = sourceTable.get(key); - batch.put(destTable.getHandle(), key, value); - batch.delete(sourceTable.getHandle(), key); - db.write(writeOptions, batch); - } catch (RocksDBException rockdbException) { - LOG.error("Move of key failed. Key:{}", DFSUtil.bytes2String(key)); - throw toIOException("Unable to move key: " + DFSUtil.bytes2String(key), - rockdbException); - } - } - - - @Override - public void move(byte[] key, byte[] value, Table source, - Table dest) throws IOException { - move(key, key, value, source, dest); - } - - @Override - public void move(byte[] sourceKey, byte[] destKey, byte[] value, Table source, - Table dest) throws IOException { - RDBTable sourceTable; - RDBTable destTable; - if (source instanceof RDBTable) { - sourceTable = (RDBTable) source; - } else { - LOG.error("Unexpected Table type. Expected RocksTable Store for Source."); - throw new IOException("Unexpected TableStore Type in source. Expected " - + "RocksDBTable."); - } - - if (dest instanceof RDBTable) { - destTable = (RDBTable) dest; - } else { - LOG.error("Unexpected Table type. Expected RocksTable Store for Dest."); - throw new IOException("Unexpected TableStore Type in dest. Expected " - + "RocksDBTable."); - } - try (WriteBatch batch = new WriteBatch()) { - batch.put(destTable.getHandle(), destKey, value); - batch.delete(sourceTable.getHandle(), sourceKey); - db.write(writeOptions, batch); - } catch (RocksDBException rockdbException) { - LOG.error("Move of key failed. Key:{}", DFSUtil.bytes2String(sourceKey)); - throw toIOException("Unable to move key: " + - DFSUtil.bytes2String(sourceKey), rockdbException); - } - } - - @Override - public long getEstimatedKeyCount() throws IOException { - try { - return db.getLongProperty("rocksdb.estimate-num-keys"); - } catch (RocksDBException e) { - throw toIOException("Unable to get the estimated count.", e); - } - } - - @Override - public void write(WriteBatch batch) throws IOException { - try { - db.write(writeOptions, batch); - } catch (RocksDBException e) { - throw toIOException("Unable to write the batch.", e); - } - } - - @VisibleForTesting - protected ObjectName getStatMBeanName() { - return statMBeanName; - } - - @Override - public Table getTable(String name) throws IOException { - ColumnFamilyHandle handle = handleTable.get(name); - if (handle == null) { - throw new IOException("No such table in this DB. TableName : " + name); - } - return new RDBTable(this.db, handle, this.writeOptions); - } - - @Override - public ArrayList
listTables() throws IOException { - ArrayList
returnList = new ArrayList<>(); - for (ColumnFamilyHandle handle : handleTable.values()) { - returnList.add(new RDBTable(db, handle, writeOptions)); - } - return returnList; - } -} \ No newline at end of file diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/RDBStoreIterator.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/RDBStoreIterator.java deleted file mode 100644 index f1f2df62242..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/RDBStoreIterator.java +++ /dev/null @@ -1,88 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.hadoop.utils.db; - -import org.apache.hadoop.utils.db.Table.KeyValue; -import org.rocksdb.RocksIterator; - -import java.io.IOException; -import java.util.NoSuchElementException; -import java.util.function.Consumer; - -/** - * RocksDB store iterator. - */ -public class RDBStoreIterator implements TableIterator { - - private RocksIterator rocksDBIterator; - - public RDBStoreIterator(RocksIterator iterator) { - this.rocksDBIterator = iterator; - rocksDBIterator.seekToFirst(); - } - - @Override - public void forEachRemaining(Consumer action) { - while(hasNext()) { - action.accept(next()); - } - } - - @Override - public boolean hasNext() { - return rocksDBIterator.isValid(); - } - - @Override - public Table.KeyValue next() { - if (rocksDBIterator.isValid()) { - KeyValue value = KeyValue.create(rocksDBIterator.key(), rocksDBIterator - .value()); - rocksDBIterator.next(); - return value; - } - throw new NoSuchElementException("RocksDB Store has no more elements"); - } - - @Override - public void seekToFirst() { - rocksDBIterator.seekToFirst(); - } - - @Override - public void seekToLast() { - rocksDBIterator.seekToLast(); - } - - @Override - public KeyValue seek(byte[] key) { - rocksDBIterator.seek(key); - if (rocksDBIterator.isValid()) { - return KeyValue.create(rocksDBIterator.key(), - rocksDBIterator.value()); - } - return null; - } - - @Override - public void close() throws IOException { - rocksDBIterator.close(); - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/RDBTable.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/RDBTable.java deleted file mode 100644 index 8cf6b3533fb..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/RDBTable.java +++ /dev/null @@ -1,173 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.hadoop.utils.db; - -import org.apache.hadoop.hdfs.DFSUtil; -import org.rocksdb.ColumnFamilyHandle; -import org.rocksdb.ReadOptions; -import org.rocksdb.RocksDB; -import org.rocksdb.RocksDBException; -import org.rocksdb.WriteBatch; -import org.rocksdb.WriteOptions; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; - -/** - * RocksDB implementation of ozone metadata store. - */ -public class RDBTable implements Table { - - private static final Logger LOG = - LoggerFactory.getLogger(RDBTable.class); - - private final RocksDB db; - private final ColumnFamilyHandle handle; - private final WriteOptions writeOptions; - - /** - * Constructs a TableStore. - * - * @param db - DBstore that we are using. - * @param handle - ColumnFamily Handle. - * @param writeOptions - RocksDB write Options. - */ - public RDBTable(RocksDB db, ColumnFamilyHandle handle, - WriteOptions writeOptions) { - this.db = db; - this.handle = handle; - this.writeOptions = writeOptions; - } - - /** - * Converts RocksDB exception to IOE. - * @param msg - Message to add to exception. - * @param e - Original Exception. - * @return IOE. - */ - public static IOException toIOException(String msg, RocksDBException e) { - String statusCode = e.getStatus() == null ? "N/A" : - e.getStatus().getCodeString(); - String errMessage = e.getMessage() == null ? "Unknown error" : - e.getMessage(); - String output = msg + "; status : " + statusCode - + "; message : " + errMessage; - return new IOException(output, e); - } - - /** - * Returns the Column family Handle. - * - * @return ColumnFamilyHandle. - */ - @Override - public ColumnFamilyHandle getHandle() { - return handle; - } - - @Override - public void put(byte[] key, byte[] value) throws IOException { - try { - db.put(handle, writeOptions, key, value); - } catch (RocksDBException e) { - LOG.error("Failed to write to DB. Key: {}", new String(key, - StandardCharsets.UTF_8)); - throw toIOException("Failed to put key-value to metadata " - + "store", e); - } - } - - @Override - public boolean isEmpty() throws IOException { - try (TableIterator keyIter = iterator()) { - keyIter.seekToFirst(); - return !keyIter.hasNext(); - } - } - - @Override - public byte[] get(byte[] key) throws IOException { - try { - return db.get(handle, key); - } catch (RocksDBException e) { - throw toIOException( - "Failed to get the value for the given key", e); - } - } - - @Override - public void delete(byte[] key) throws IOException { - try { - db.delete(handle, key); - } catch (RocksDBException e) { - throw toIOException("Failed to delete the given key", e); - } - } - - @Override - public void writeBatch(WriteBatch operation) throws IOException { - try { - db.write(writeOptions, operation); - } catch (RocksDBException e) { - throw toIOException("Batch write operation failed", e); - } - } - -// @Override -// public void iterate(byte[] from, EntryConsumer consumer) -// throws IOException { -// -// try (RocksIterator it = db.newIterator(handle)) { -// if (from != null) { -// it.seek(from); -// } else { -// it.seekToFirst(); -// } -// while (it.isValid()) { -// if (!consumer.consume(it.key(), it.value())) { -// break; -// } -// it.next(); -// } -// } -// } - - @Override - public TableIterator iterator() { - ReadOptions readOptions = new ReadOptions(); - return new RDBStoreIterator(db.newIterator(handle, readOptions)); - } - - @Override - public String getName() throws IOException { - try { - return DFSUtil.bytes2String(this.getHandle().getName()); - } catch (RocksDBException rdbEx) { - throw toIOException("Unable to get the table name.", rdbEx); - } - } - - @Override - public void close() throws Exception { - // Nothing do for a Column Family. - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/Table.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/Table.java deleted file mode 100644 index 39425852926..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/Table.java +++ /dev/null @@ -1,150 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.hadoop.utils.db; - -import org.apache.hadoop.classification.InterfaceStability; -import org.rocksdb.ColumnFamilyHandle; -import org.rocksdb.WriteBatch; - -import java.io.IOException; - -/** - * Interface for key-value store that stores ozone metadata. Ozone metadata is - * stored as key value pairs, both key and value are arbitrary byte arrays. Each - * Table Stores a certain kind of keys and values. This allows a DB to have - * different kind of tables. - */ -@InterfaceStability.Evolving -public interface Table extends AutoCloseable { - - /** - * Puts a key-value pair into the store. - * - * @param key metadata key - * @param value metadata value - */ - void put(byte[] key, byte[] value) throws IOException; - - /** - * @return true if the metadata store is empty. - * @throws IOException on Failure - */ - boolean isEmpty() throws IOException; - - /** - * Returns the value mapped to the given key in byte array or returns null - * if the key is not found. - * - * @param key metadata key - * @return value in byte array or null if the key is not found. - * @throws IOException on Failure - */ - byte[] get(byte[] key) throws IOException; - - /** - * Deletes a key from the metadata store. - * - * @param key metadata key - * @throws IOException on Failure - */ - void delete(byte[] key) throws IOException; - - /** - * Return the Column Family handle. TODO: This leaks an RockDB abstraction - * into Ozone code, cleanup later. - * - * @return ColumnFamilyHandle - */ - ColumnFamilyHandle getHandle(); - - /** - * A batch of PUT, DELETE operations handled as a single atomic write. - * - * @throws IOException write fails - */ - void writeBatch(WriteBatch operation) throws IOException; - - /** - * Returns the iterator for this metadata store. - * - * @return MetaStoreIterator - */ - TableIterator iterator(); - - /** - * Returns the Name of this Table. - * @return - Table Name. - * @throws IOException on failure. - */ - String getName() throws IOException; - - /** - * Class used to represent the key and value pair of a db entry. - */ - class KeyValue { - - private final byte[] key; - private final byte[] value; - - /** - * KeyValue Constructor, used to represent a key and value of a db entry. - * - * @param key - Key Bytes - * @param value - Value bytes - */ - private KeyValue(byte[] key, byte[] value) { - this.key = key; - this.value = value; - } - - /** - * Create a KeyValue pair. - * - * @param key - Key Bytes - * @param value - Value bytes - * @return KeyValue object. - */ - public static KeyValue create(byte[] key, byte[] value) { - return new KeyValue(key, value); - } - - /** - * Return key. - * - * @return byte[] - */ - public byte[] getKey() { - byte[] result = new byte[key.length]; - System.arraycopy(key, 0, result, 0, key.length); - return result; - } - - /** - * Return value. - * - * @return byte[] - */ - public byte[] getValue() { - byte[] result = new byte[value.length]; - System.arraycopy(value, 0, result, 0, value.length); - return result; - } - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/TableConfig.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/TableConfig.java deleted file mode 100644 index 897028a821f..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/TableConfig.java +++ /dev/null @@ -1,93 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.hadoop.utils.db; - -import org.apache.commons.lang3.builder.EqualsBuilder; -import org.apache.commons.lang3.builder.HashCodeBuilder; -import org.apache.hadoop.hdfs.DFSUtil; -import org.rocksdb.ColumnFamilyDescriptor; -import org.rocksdb.ColumnFamilyOptions; - -/** - * Class that maintains Table Configuration. - */ -public class TableConfig { - private final String name; - private final ColumnFamilyOptions columnFamilyOptions; - - - /** - * Constructs a Table Config. - * @param name - Name of the Table. - * @param columnFamilyOptions - Column Family options. - */ - public TableConfig(String name, ColumnFamilyOptions columnFamilyOptions) { - this.name = name; - this.columnFamilyOptions = columnFamilyOptions; - } - - /** - * Returns the Name for this Table. - * @return - Name String - */ - public String getName() { - return name; - } - - /** - * Returns a ColumnFamilyDescriptor for this table. - * @return ColumnFamilyDescriptor - */ - public ColumnFamilyDescriptor getDescriptor() { - return new ColumnFamilyDescriptor(DFSUtil.string2Bytes(name), - columnFamilyOptions); - } - - /** - * Returns Column family options for this Table. - * @return ColumnFamilyOptions used for the Table. - */ - public ColumnFamilyOptions getColumnFamilyOptions() { - return columnFamilyOptions; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (o == null || getClass() != o.getClass()) { - return false; - } - - TableConfig that = (TableConfig) o; - return new EqualsBuilder() - .append(getName(), that.getName()) - .isEquals(); - } - - @Override - public int hashCode() { - return new HashCodeBuilder(17, 37) - .append(getName()) - .toHashCode(); - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/TableIterator.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/TableIterator.java deleted file mode 100644 index 83a8f3c8385..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/TableIterator.java +++ /dev/null @@ -1,50 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.hadoop.utils.db; - -import java.io.Closeable; -import java.util.Iterator; - -/** - * Iterator for MetaDataStore DB. - * - * @param - */ -public interface TableIterator extends Iterator, Closeable { - - /** - * seek to first entry. - */ - void seekToFirst(); - - /** - * seek to last entry. - */ - void seekToLast(); - - /** - * Seek to the specific key. - * - * @param key - Bytes that represent the key. - * @return T. - */ - T seek(byte[] key); - -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/package-info.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/package-info.java deleted file mode 100644 index 17d676d9283..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/db/package-info.java +++ /dev/null @@ -1,22 +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 - * - * 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. - * - */ -/** - * Database interfaces for Ozone. - */ -package org.apache.hadoop.utils.db; \ No newline at end of file diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/package-info.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/package-info.java deleted file mode 100644 index 44663379129..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/package-info.java +++ /dev/null @@ -1,18 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.utils; diff --git a/hadoop-hdds/common/src/main/java/org/apache/ratis/RatisHelper.java b/hadoop-hdds/common/src/main/java/org/apache/ratis/RatisHelper.java deleted file mode 100644 index 04bfeb2e848..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/ratis/RatisHelper.java +++ /dev/null @@ -1,207 +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 - * - * 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.ratis; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.ozone.OzoneConfigKeys; -import org.apache.ratis.client.RaftClient; -import org.apache.ratis.conf.RaftProperties; -import org.apache.ratis.grpc.GrpcConfigKeys; -import org.apache.ratis.protocol.RaftGroup; -import org.apache.ratis.protocol.RaftGroupId; -import org.apache.ratis.protocol.RaftPeer; -import org.apache.ratis.protocol.RaftPeerId; -import org.apache.ratis.retry.RetryPolicies; -import org.apache.ratis.retry.RetryPolicy; -import org.apache.ratis.rpc.RpcType; -import org.apache.ratis.shaded.com.google.protobuf.ByteString; -import org.apache.ratis.shaded.proto.RaftProtos; -import org.apache.ratis.util.Preconditions; -import org.apache.ratis.util.SizeInBytes; -import org.apache.ratis.util.TimeDuration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -import static org.apache.hadoop.ozone.OzoneConfigKeys.DFS_RATIS_LEADER_ELECTION_MINIMUM_TIMEOUT_DURATION_DEFAULT; -import static org.apache.hadoop.ozone.OzoneConfigKeys.DFS_RATIS_LEADER_ELECTION_MINIMUM_TIMEOUT_DURATION_KEY; - -/** - * Ratis helper methods. - */ -public interface RatisHelper { - Logger LOG = LoggerFactory.getLogger(RatisHelper.class); - - static String toRaftPeerIdString(DatanodeDetails id) { - return id.getUuidString(); - } - - static UUID toDatanodeId(String peerIdString) { - return UUID.fromString(peerIdString); - } - - static UUID toDatanodeId(RaftPeerId peerId) { - return toDatanodeId(peerId.toString()); - } - - static UUID toDatanodeId(RaftProtos.RaftPeerProto peerId) { - return toDatanodeId(RaftPeerId.valueOf(peerId.getId())); - } - - static String toRaftPeerAddressString(DatanodeDetails id) { - return id.getIpAddress() + ":" + - id.getPort(DatanodeDetails.Port.Name.RATIS).getValue(); - } - - static RaftPeerId toRaftPeerId(DatanodeDetails id) { - return RaftPeerId.valueOf(toRaftPeerIdString(id)); - } - - static RaftPeer toRaftPeer(DatanodeDetails id) { - return new RaftPeer(toRaftPeerId(id), toRaftPeerAddressString(id)); - } - - static List toRaftPeers(Pipeline pipeline) { - return toRaftPeers(pipeline.getMachines()); - } - - static List toRaftPeers( - List datanodes) { - return datanodes.stream().map(RatisHelper::toRaftPeer) - .collect(Collectors.toList()); - } - - /* TODO: use a dummy id for all groups for the moment. - * It should be changed to a unique id for each group. - */ - RaftGroupId DUMMY_GROUP_ID = - RaftGroupId.valueOf(ByteString.copyFromUtf8("AOzoneRatisGroup")); - - RaftGroup EMPTY_GROUP = new RaftGroup(DUMMY_GROUP_ID, - Collections.emptyList()); - - static RaftGroup emptyRaftGroup() { - return EMPTY_GROUP; - } - - static RaftGroup newRaftGroup(Collection peers) { - return peers.isEmpty()? emptyRaftGroup() - : new RaftGroup(DUMMY_GROUP_ID, peers); - } - - static RaftGroup newRaftGroup(RaftGroupId groupId, - Collection peers) { - final List newPeers = peers.stream() - .map(RatisHelper::toRaftPeer) - .collect(Collectors.toList()); - return peers.isEmpty() ? new RaftGroup(groupId, Collections.emptyList()) - : new RaftGroup(groupId, newPeers); - } - - static RaftGroup newRaftGroup(Pipeline pipeline) { - return new RaftGroup(pipeline.getId().getRaftGroupID(), - toRaftPeers(pipeline)); - } - - static RaftClient newRaftClient(RpcType rpcType, Pipeline pipeline, - RetryPolicy retryPolicy) { - return newRaftClient(rpcType, toRaftPeerId(pipeline.getLeader()), - newRaftGroup(pipeline.getId().getRaftGroupID(), pipeline.getMachines()), - retryPolicy); - } - - static RaftClient newRaftClient(RpcType rpcType, RaftPeer leader, - RetryPolicy retryPolicy) { - return newRaftClient(rpcType, leader.getId(), - newRaftGroup(new ArrayList<>(Arrays.asList(leader))), retryPolicy); - } - - static RaftClient newRaftClient(RpcType rpcType, RaftPeer leader, - RaftGroup group, RetryPolicy retryPolicy) { - return newRaftClient(rpcType, leader.getId(), group, retryPolicy); - } - - static RaftClient newRaftClient(RpcType rpcType, RaftPeerId leader, - RaftGroup group, RetryPolicy retryPolicy) { - LOG.trace("newRaftClient: {}, leader={}, group={}", rpcType, leader, group); - final RaftProperties properties = new RaftProperties(); - RaftConfigKeys.Rpc.setType(properties, rpcType); - - GrpcConfigKeys.setMessageSizeMax(properties, - SizeInBytes.valueOf(OzoneConfigKeys.DFS_CONTAINER_CHUNK_MAX_SIZE)); - - return RaftClient.newBuilder() - .setRaftGroup(group) - .setLeaderId(leader) - .setProperties(properties) - .setRetryPolicy(retryPolicy) - .build(); - } - - static RetryPolicy createRetryPolicy(Configuration conf) { - int maxRetryCount = - conf.getInt(OzoneConfigKeys.DFS_RATIS_CLIENT_REQUEST_MAX_RETRIES_KEY, - OzoneConfigKeys. - DFS_RATIS_CLIENT_REQUEST_MAX_RETRIES_DEFAULT); - long retryInterval = conf.getTimeDuration(OzoneConfigKeys. - DFS_RATIS_CLIENT_REQUEST_RETRY_INTERVAL_KEY, OzoneConfigKeys. - DFS_RATIS_CLIENT_REQUEST_RETRY_INTERVAL_DEFAULT - .toInt(TimeUnit.MILLISECONDS), TimeUnit.MILLISECONDS); - long leaderElectionTimeout = conf.getTimeDuration( - DFS_RATIS_LEADER_ELECTION_MINIMUM_TIMEOUT_DURATION_KEY, - DFS_RATIS_LEADER_ELECTION_MINIMUM_TIMEOUT_DURATION_DEFAULT - .toInt(TimeUnit.MILLISECONDS), TimeUnit.MILLISECONDS); - long clientRequestTimeout = conf.getTimeDuration( - OzoneConfigKeys.DFS_RATIS_CLIENT_REQUEST_TIMEOUT_DURATION_KEY, - OzoneConfigKeys.DFS_RATIS_CLIENT_REQUEST_TIMEOUT_DURATION_DEFAULT - .toInt(TimeUnit.MILLISECONDS), TimeUnit.MILLISECONDS); - long retryCacheTimeout = conf.getTimeDuration( - OzoneConfigKeys.DFS_RATIS_SERVER_RETRY_CACHE_TIMEOUT_DURATION_KEY, - OzoneConfigKeys.DFS_RATIS_SERVER_RETRY_CACHE_TIMEOUT_DURATION_DEFAULT - .toInt(TimeUnit.MILLISECONDS), TimeUnit.MILLISECONDS); - Preconditions - .assertTrue(maxRetryCount * retryInterval > 5 * leaderElectionTimeout, - "Please make sure dfs.ratis.client.request.max.retries * " - + "dfs.ratis.client.request.retry.interval > " - + "5 * dfs.ratis.leader.election.minimum.timeout.duration"); - Preconditions.assertTrue( - maxRetryCount * (retryInterval + clientRequestTimeout) - < retryCacheTimeout, - "Please make sure " - + "(dfs.ratis.client.request.max.retries * " - + "(dfs.ratis.client.request.retry.interval + " - + "dfs.ratis.client.request.timeout.duration)) " - + "< dfs.ratis.server.retry-cache.timeout.duration"); - TimeDuration sleepDuration = - TimeDuration.valueOf(retryInterval, TimeUnit.MILLISECONDS); - RetryPolicy retryPolicy = RetryPolicies - .retryUpToMaximumCountWithFixedSleep(maxRetryCount, sleepDuration); - return retryPolicy; - } -} diff --git a/hadoop-hdds/common/src/main/java/org/apache/ratis/package-info.java b/hadoop-hdds/common/src/main/java/org/apache/ratis/package-info.java deleted file mode 100644 index c13c20c6060..00000000000 --- a/hadoop-hdds/common/src/main/java/org/apache/ratis/package-info.java +++ /dev/null @@ -1,22 +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 - * - * 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.ratis; - -/** - * This package contains classes related to Apache Ratis. - */ diff --git a/hadoop-hdds/common/src/main/proto/DatanodeContainerProtocol.proto b/hadoop-hdds/common/src/main/proto/DatanodeContainerProtocol.proto deleted file mode 100644 index 7be8a62c296..00000000000 --- a/hadoop-hdds/common/src/main/proto/DatanodeContainerProtocol.proto +++ /dev/null @@ -1,451 +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 - * - * 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. - */ - -/** - * These .proto interfaces are private and Unstable. - * Please see http://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-common/InterfaceClassification.html - * for what changes are allowed for a *Unstable* .proto interface. - */ - -// This file contains protocol buffers that are used to transfer data -// to and from the datanode. -syntax = "proto2"; -option java_package = "org.apache.hadoop.hdds.protocol.datanode.proto"; -option java_outer_classname = "ContainerProtos"; -option java_generate_equals_and_hash = true; -package hadoop.hdds.datanode; - -/** - * Commands that are used to manipulate the state of containers on a datanode. - * - * These commands allow us to work against the datanode - from - * StorageContainer Manager as well as clients. - * - * 1. CreateContainer - This call is usually made by Storage Container - * manager, when we need to create a new container on a given datanode. - * - * 2. ReadContainer - Allows end user to stat a container. For example - * this allows us to return the metadata of a container. - * - * 3. UpdateContainer - Updates a container metadata. - - * 4. DeleteContainer - This call is made to delete a container. - * - * 5. ListContainer - Returns the list of containers on this - * datanode. This will be used by tests and tools. - * - * 6. PutBlock - Given a valid container, creates a block. - * - * 7. GetBlock - Allows user to read the metadata of a block. - * - * 8. DeleteBlock - Deletes a given block. - * - * 9. ListBlock - Returns a list of blocks that are present inside - * a given container. - * - * 10. ReadChunk - Allows us to read a chunk. - * - * 11. DeleteChunk - Delete an unused chunk. - * - * 12. WriteChunk - Allows us to write a chunk - * - * 13. ListChunk - Given a Container/Block returns the list of Chunks. - * - * 14. CompactChunk - Re-writes a chunk based on Offsets. - * - * 15. PutSmallFile - A single RPC that combines both putBlock and WriteChunk. - * - * 16. GetSmallFile - A single RPC that combines both getBlock and ReadChunk. - * - * 17. CloseContainer - Closes an open container and makes it immutable. - * - * 18. CopyContainer - Copies a container from a remote machine. - */ - -enum Type { - CreateContainer = 1; - ReadContainer = 2; - UpdateContainer = 3; - DeleteContainer = 4; - ListContainer = 5; - - PutBlock = 6; - GetBlock = 7; - DeleteBlock = 8; - ListBlock = 9; - - ReadChunk = 10; - DeleteChunk = 11; - WriteChunk = 12; - ListChunk = 13; - CompactChunk = 14; - - /** Combines Block and Chunk Operation into Single RPC. */ - PutSmallFile = 15; - GetSmallFile = 16; - CloseContainer = 17; - GetCommittedBlockLength = 18; -} - - -enum Result { - SUCCESS = 1; - UNSUPPORTED_REQUEST = 2; - MALFORMED_REQUEST = 3; - CONTAINER_INTERNAL_ERROR = 4; - INVALID_CONFIG = 5; - INVALID_FILE_HASH_FOUND = 6; - CONTAINER_EXISTS = 7; - NO_SUCH_ALGORITHM = 8; - CONTAINER_NOT_FOUND = 9; - IO_EXCEPTION = 10; - UNABLE_TO_READ_METADATA_DB = 11; - NO_SUCH_BLOCK = 12; - OVERWRITE_FLAG_REQUIRED = 13; - UNABLE_TO_FIND_DATA_DIR = 14; - INVALID_WRITE_SIZE = 15; - CHECKSUM_MISMATCH = 16; - UNABLE_TO_FIND_CHUNK = 17; - PROTOC_DECODING_ERROR = 18; - INVALID_ARGUMENT = 19; - PUT_SMALL_FILE_ERROR = 20; - GET_SMALL_FILE_ERROR = 21; - CLOSED_CONTAINER_IO = 22; - ERROR_CONTAINER_NOT_EMPTY = 23; - ERROR_IN_COMPACT_DB = 24; - UNCLOSED_CONTAINER_IO = 25; - DELETE_ON_OPEN_CONTAINER = 26; - CLOSED_CONTAINER_RETRY = 27; - INVALID_CONTAINER_STATE = 28; - DISK_OUT_OF_SPACE = 29; - CONTAINER_ALREADY_EXISTS = 30; - CONTAINER_METADATA_ERROR = 31; - CONTAINER_FILES_CREATE_ERROR = 32; - CONTAINER_CHECKSUM_ERROR = 33; - UNKNOWN_CONTAINER_TYPE = 34; - BLOCK_NOT_COMMITTED = 35; -} - -/** - * Block ID that uniquely identify a block in Datanode. - */ -message DatanodeBlockID { - required int64 containerID = 1; - required int64 localID = 2; -} - -message KeyValue { - required string key = 1; - optional string value = 2; -} - -/** - * Lifecycle states of a container in Datanode. - */ -enum ContainerLifeCycleState { - OPEN = 1; - CLOSING = 2; - CLOSED = 3; - INVALID = 4; -} - -message ContainerCommandRequestProto { - required Type cmdType = 1; // Type of the command - - // A string that identifies this command, we generate Trace ID in Ozone - // frontend and this allows us to trace that command all over ozone. - optional string traceID = 2; - - required int64 containerID = 3; - required string datanodeUuid = 4; - - // One of the following command is available when the corresponding - // cmdType is set. At the protocol level we allow only - // one command in each packet. - // TODO : Upgrade to Protobuf 2.6 or later. - optional CreateContainerRequestProto createContainer = 5; - optional ReadContainerRequestProto readContainer = 6; - optional UpdateContainerRequestProto updateContainer = 7; - optional DeleteContainerRequestProto deleteContainer = 8; - optional ListContainerRequestProto listContainer = 9; - optional CloseContainerRequestProto closeContainer = 10; - - optional PutBlockRequestProto putBlock = 11; - optional GetBlockRequestProto getBlock = 12; - optional DeleteBlockRequestProto deleteBlock = 13; - optional ListBlockRequestProto listBlock = 14; - - optional ReadChunkRequestProto readChunk = 15; - optional WriteChunkRequestProto writeChunk = 16; - optional DeleteChunkRequestProto deleteChunk = 17; - optional ListChunkRequestProto listChunk = 18; - - optional PutSmallFileRequestProto putSmallFile = 19; - optional GetSmallFileRequestProto getSmallFile = 20; - - optional GetCommittedBlockLengthRequestProto getCommittedBlockLength = 21; -} - -message ContainerCommandResponseProto { - required Type cmdType = 1; - optional string traceID = 2; - - required Result result = 3; - optional string message = 4; - - optional CreateContainerResponseProto createContainer = 5; - optional ReadContainerResponseProto readContainer = 6; - optional UpdateContainerResponseProto updateContainer = 7; - optional DeleteContainerResponseProto deleteContainer = 8; - optional ListContainerResponseProto listContainer = 9; - optional CloseContainerResponseProto closeContainer = 10; - - optional PutBlockResponseProto putBlock = 11; - optional GetBlockResponseProto getBlock = 12; - optional DeleteBlockResponseProto deleteBlock = 13; - optional ListBlockResponseProto listBlock = 14; - - optional WriteChunkResponseProto writeChunk = 15; - optional ReadChunkResponseProto readChunk = 16; - optional DeleteChunkResponseProto deleteChunk = 17; - optional ListChunkResponseProto listChunk = 18; - - optional PutSmallFileResponseProto putSmallFile = 19; - optional GetSmallFileResponseProto getSmallFile = 20; - - optional GetCommittedBlockLengthResponseProto getCommittedBlockLength = 21; -} - -message ContainerData { - required int64 containerID = 1; - repeated KeyValue metadata = 2; - optional string containerPath = 4; - optional int64 bytesUsed = 6; - optional int64 size = 7; - optional int64 blockCount = 8; - optional ContainerLifeCycleState state = 9 [default = OPEN]; - optional ContainerType containerType = 10 [default = KeyValueContainer]; -} - -enum ContainerType { - KeyValueContainer = 1; -} - - -// Container Messages. -message CreateContainerRequestProto { - repeated KeyValue metadata = 2; - optional ContainerType containerType = 3 [default = KeyValueContainer]; -} - -message CreateContainerResponseProto { -} - -message ReadContainerRequestProto { -} - -message ReadContainerResponseProto { - optional ContainerData containerData = 1; -} - -message UpdateContainerRequestProto { - repeated KeyValue metadata = 2; - optional bool forceUpdate = 3 [default = false]; -} - -message UpdateContainerResponseProto { -} - -message DeleteContainerRequestProto { - optional bool forceDelete = 2 [default = false]; -} - -message DeleteContainerResponseProto { -} - -message ListContainerRequestProto { - optional uint32 count = 2; // Max Results to return -} - -message ListContainerResponseProto { - repeated ContainerData containerData = 1; -} - -message CloseContainerRequestProto { -} - -message CloseContainerResponseProto { - optional string hash = 1; - optional int64 containerID = 2; -} - -message BlockData { - required DatanodeBlockID blockID = 1; - optional int64 flags = 2; // for future use. - repeated KeyValue metadata = 3; - repeated ChunkInfo chunks = 4; - optional int64 size = 5; -} - -// Block Messages. -message PutBlockRequestProto { - required BlockData blockData = 1; -} - -message PutBlockResponseProto { - required GetCommittedBlockLengthResponseProto committedBlockLength = 1; -} - -message GetBlockRequestProto { - required DatanodeBlockID blockID = 1; -} - -message GetBlockResponseProto { - required BlockData blockData = 1; -} - - -message DeleteBlockRequestProto { - required DatanodeBlockID blockID = 1; -} - -message GetCommittedBlockLengthRequestProto { - required DatanodeBlockID blockID = 1; -} - -message GetCommittedBlockLengthResponseProto { - required DatanodeBlockID blockID = 1; - required int64 blockLength = 2; -} - -message DeleteBlockResponseProto { -} - -message ListBlockRequestProto { - optional int64 startLocalID = 2; - required uint32 count = 3; - -} - -message ListBlockResponseProto { - repeated BlockData blockData = 1; -} - -// Chunk Operations - -message ChunkInfo { - required string chunkName = 1; - required uint64 offset = 2; - required uint64 len = 3; - optional string checksum = 4; - repeated KeyValue metadata = 5; -} - -enum Stage { - WRITE_DATA = 1; - COMMIT_DATA = 2; - COMBINED = 3; -} - -message WriteChunkRequestProto { - required DatanodeBlockID blockID = 1; - required ChunkInfo chunkData = 2; - optional bytes data = 3; - optional Stage stage = 4 [default = COMBINED]; -} - -message WriteChunkResponseProto { -} - -message ReadChunkRequestProto { - required DatanodeBlockID blockID = 1; - required ChunkInfo chunkData = 2; -} - -message ReadChunkResponseProto { - required DatanodeBlockID blockID = 1; - required ChunkInfo chunkData = 2; - required bytes data = 3; -} - -message DeleteChunkRequestProto { - required DatanodeBlockID blockID = 1; - required ChunkInfo chunkData = 2; -} - -message DeleteChunkResponseProto { -} - -message ListChunkRequestProto { - required DatanodeBlockID blockID = 1; - required string prevChunkName = 2; - required uint32 count = 3; -} - -message ListChunkResponseProto { - repeated ChunkInfo chunkData = 1; -} - -/** For small file access combines write chunk and putBlock into a single -RPC */ - -message PutSmallFileRequestProto { - required PutBlockRequestProto block = 1; - required ChunkInfo chunkInfo = 2; - required bytes data = 3; -} - - -message PutSmallFileResponseProto { - -} - -message GetSmallFileRequestProto { - required GetBlockRequestProto block = 1; -} - -message GetSmallFileResponseProto { - required ReadChunkResponseProto data = 1; -} - -message CopyContainerRequestProto { - required int64 containerID = 1; - required uint64 readOffset = 2; - optional uint64 len = 3; -} - -message CopyContainerResponseProto { - required int64 containerID = 1; - required uint64 readOffset = 2; - required uint64 len = 3; - required bool eof = 4; - required bytes data = 5; - optional int64 checksum = 6; -} - -service XceiverClientProtocolService { - // A client-to-datanode RPC to send container commands - rpc send(stream ContainerCommandRequestProto) returns - (stream ContainerCommandResponseProto) {}; - -} - -service IntraDatanodeProtocolService { - // An intradatanode service to copy the raw containerdata betwen nodes - rpc download (CopyContainerRequestProto) returns (stream CopyContainerResponseProto); -} \ No newline at end of file diff --git a/hadoop-hdds/common/src/main/proto/ScmBlockLocationProtocol.proto b/hadoop-hdds/common/src/main/proto/ScmBlockLocationProtocol.proto deleted file mode 100644 index 9b4e0acabac..00000000000 --- a/hadoop-hdds/common/src/main/proto/ScmBlockLocationProtocol.proto +++ /dev/null @@ -1,136 +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 - * - * 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. - */ - -/** - * These .proto interfaces are private and unstable. - * Please see http://wiki.apache.org/hadoop/Compatibility - * for what changes are allowed for a *unstable* .proto interface. - */ - -option java_package = "org.apache.hadoop.hdds.protocol.proto"; -option java_outer_classname = "ScmBlockLocationProtocolProtos"; -option java_generic_services = true; -option java_generate_equals_and_hash = true; -package hadoop.hdds; - -import "hdfs.proto"; -import "hdds.proto"; - - -// SCM Block protocol - -/** -* Request send to SCM asking allocate block of specified size. -*/ -message AllocateScmBlockRequestProto { - required uint64 size = 1; - required ReplicationType type = 2; - required hadoop.hdds.ReplicationFactor factor = 3; - required string owner = 4; - -} - -/** - * A delete key request sent by OM to SCM, it contains - * multiple number of keys (and their blocks). - */ -message DeleteScmKeyBlocksRequestProto { - repeated KeyBlocks keyBlocks = 1; -} - -/** - * A object key and all its associated blocks. - * We need to encapsulate object key name plus the blocks in this potocol - * because SCM needs to response OM with the keys it has deleted. - * If the response only contains blocks, it will be very expensive for - * OM to figure out what keys have been deleted. - */ -message KeyBlocks { - required string key = 1; - repeated BlockID blocks = 2; -} - -/** - * A delete key response from SCM to OM, it contains multiple child-results. - * Each child-result represents a key deletion result, only if all blocks of - * a key are successfully deleted, this key result is considered as succeed. - */ -message DeleteScmKeyBlocksResponseProto { - repeated DeleteKeyBlocksResultProto results = 1; -} - -/** - * A key deletion result. It contains all the block deletion results. - */ -message DeleteKeyBlocksResultProto { - required string objectKey = 1; - repeated DeleteScmBlockResult blockResults = 2; -} - -message DeleteScmBlockResult { - enum Result { - success = 1; - chillMode = 2; - errorNotFound = 3; - unknownFailure = 4; - } - required Result result = 1; - required BlockID blockID = 2; -} - -/** - * Reply from SCM indicating that the container. - */ -message AllocateScmBlockResponseProto { - enum Error { - success = 1; - errorNotEnoughSpace = 2; - errorSizeTooBig = 3; - unknownFailure = 4; - } - required Error errorCode = 1; - optional BlockID blockID = 2; - optional hadoop.hdds.Pipeline pipeline = 3; - optional bool createContainer = 4; - optional string errorMessage = 5; -} - -/** - * Protocol used from OzoneManager to StorageContainerManager. - * See request and response messages for details of the RPC calls. - */ -service ScmBlockLocationProtocolService { - - /** - * Creates a block entry in SCM. - */ - rpc allocateScmBlock(AllocateScmBlockRequestProto) - returns (AllocateScmBlockResponseProto); - - /** - * Deletes blocks for a set of object keys from SCM. - */ - rpc deleteScmKeyBlocks(DeleteScmKeyBlocksRequestProto) - returns (DeleteScmKeyBlocksResponseProto); - - /** - * Gets the scmInfo from SCM. - */ - rpc getScmInfo(hadoop.hdds.GetScmInfoRequestProto) - returns (hadoop.hdds.GetScmInfoRespsonseProto); -} diff --git a/hadoop-hdds/common/src/main/proto/StorageContainerLocationProtocol.proto b/hadoop-hdds/common/src/main/proto/StorageContainerLocationProtocol.proto deleted file mode 100644 index fb01d6a0b10..00000000000 --- a/hadoop-hdds/common/src/main/proto/StorageContainerLocationProtocol.proto +++ /dev/null @@ -1,239 +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 - * - * 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. - */ - -/** - * These .proto interfaces are private and unstable. - * Please see http://wiki.apache.org/hadoop/Compatibility - * for what changes are allowed for a *unstable* .proto interface. - */ - -option java_package = "org.apache.hadoop.hdds.protocol.proto"; -option java_outer_classname = "StorageContainerLocationProtocolProtos"; -option java_generic_services = true; -option java_generate_equals_and_hash = true; -package hadoop.hdds; - -import "hdfs.proto"; -import "hdds.proto"; - -/** -* Request send to SCM asking where the container should be created. -*/ -message ContainerRequestProto { - // Ozone only support replciation of either 1 or 3. - required ReplicationFactor replicationFactor = 2; - required ReplicationType replicationType = 3; - required string owner = 4; - -} - -/** - * Reply from SCM indicating that the container. - */ -message ContainerResponseProto { - enum Error { - success = 1; - errorContainerAlreadyExists = 2; - errorContainerMissing = 3; - } - required Error errorCode = 1; - required ContainerWithPipeline containerWithPipeline = 2; - optional string errorMessage = 3; -} - -message GetContainerRequestProto { - required int64 containerID = 1; -} - -message GetContainerResponseProto { - required SCMContainerInfo containerInfo = 1; -} - -message GetContainerWithPipelineRequestProto { - required int64 containerID = 1; -} - -message GetContainerWithPipelineResponseProto { - required ContainerWithPipeline containerWithPipeline = 1; -} - -message SCMListContainerRequestProto { - required uint32 count = 1; - optional uint64 startContainerID = 2; - } - -message SCMListContainerResponseProto { - repeated SCMContainerInfo containers = 1; -} - -message SCMDeleteContainerRequestProto { - required int64 containerID = 1; -} - -message SCMDeleteContainerResponseProto { - // Empty response -} - -message ObjectStageChangeRequestProto { - enum Type { - container = 1; - pipeline = 2; - } - // delete/copy operation may be added later - enum Op { - create = 1; - close = 2; - } - enum Stage { - begin = 1; - complete = 2; - } - required int64 id = 1; - required Type type = 2; - required Op op= 3; - required Stage stage = 4; -} - -message ObjectStageChangeResponseProto { - // Empty response -} - -/* - NodeQueryRequest sends a request to SCM asking to send a list of nodes that - match the NodeState that we are requesting. -*/ -message NodeQueryRequestProto { - required NodeState state = 1; - required QueryScope scope = 2; - optional string poolName = 3; // if scope is pool, then pool name is needed. -} - -message NodeQueryResponseProto { - repeated Node datanodes = 1; -} - -/** - Request to create a replication pipeline. - */ -message PipelineRequestProto { - required ReplicationType replicationType = 1; - required ReplicationFactor replicationFactor = 2; - - // if datanodes are specified then pipelines are created using those - // datanodes. - optional NodePool nodePool = 3; - optional string pipelineID = 4; -} - -message PipelineResponseProto { - enum Error { - success = 1; - errorPipelineAlreadyExists = 2; - } - required Error errorCode = 1; - optional Pipeline pipeline = 2; - optional string errorMessage = 3; -} - - -message InChillModeRequestProto { -} - -message InChillModeResponseProto { - required bool inChillMode = 1; -} - -message ForceExitChillModeRequestProto { -} - -message ForceExitChillModeResponseProto { - required bool exitedChillMode = 1; -} - -/** - * Protocol used from an HDFS node to StorageContainerManager. See the request - * and response messages for details of the RPC calls. - */ -service StorageContainerLocationProtocolService { - - /** - * Creates a container entry in SCM. - */ - rpc allocateContainer(ContainerRequestProto) returns (ContainerResponseProto); - - /** - * Returns the pipeline for a given container. - */ - rpc getContainer(GetContainerRequestProto) returns (GetContainerResponseProto); - - /** - * Returns the pipeline for a given container. - */ - rpc getContainerWithPipeline(GetContainerWithPipelineRequestProto) returns (GetContainerWithPipelineResponseProto); - - rpc listContainer(SCMListContainerRequestProto) returns (SCMListContainerResponseProto); - - /** - * Deletes a container in SCM. - */ - rpc deleteContainer(SCMDeleteContainerRequestProto) returns (SCMDeleteContainerResponseProto); - - /** - * Returns a set of Nodes that meet a criteria. - */ - rpc queryNode(NodeQueryRequestProto) returns (NodeQueryResponseProto); - - /** - * Notify from client when begin or finish container or pipeline operations on datanodes. - */ - rpc notifyObjectStageChange(ObjectStageChangeRequestProto) returns (ObjectStageChangeResponseProto); - - /* - * Apis that Manage Pipelines. - * - * Pipelines are abstractions offered by SCM and Datanode that allows users - * to create a replication pipeline. - * - * These following APIs allow command line programs like SCM CLI to list - * and manage pipelines. - */ - - /** - * Creates a replication pipeline. - */ - rpc allocatePipeline(PipelineRequestProto) - returns (PipelineResponseProto); - - /** - * Returns information about SCM. - */ - rpc getScmInfo(GetScmInfoRequestProto) - returns (GetScmInfoRespsonseProto); - - /** - * Checks if SCM is in ChillMode. - */ - rpc inChillMode(InChillModeRequestProto) - returns (InChillModeResponseProto); - - /** - * Returns information about SCM. - */ - rpc forceExitChillMode(ForceExitChillModeRequestProto) - returns (ForceExitChillModeResponseProto); -} diff --git a/hadoop-hdds/common/src/main/proto/hdds.proto b/hadoop-hdds/common/src/main/proto/hdds.proto deleted file mode 100644 index dedc57bb76c..00000000000 --- a/hadoop-hdds/common/src/main/proto/hdds.proto +++ /dev/null @@ -1,194 +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 - * - * 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. - */ - -/** - * These .proto interfaces are private and unstable. - * Please see http://wiki.apache.org/hadoop/Compatibility - * for what changes are allowed for a *unstable* .proto interface. - */ - -option java_package = "org.apache.hadoop.hdds.protocol.proto"; -option java_outer_classname = "HddsProtos"; -option java_generic_services = true; -option java_generate_equals_and_hash = true; -package hadoop.hdds; - -message DatanodeDetailsProto { - required string uuid = 1; // UUID assigned to the Datanode. - required string ipAddress = 2; // IP address - required string hostName = 3; // hostname - repeated Port ports = 4; -} - -message Port { - required string name = 1; - required uint32 value = 2; -} - -message PipelineID { - required string id = 1; -} - -message Pipeline { - required string leaderID = 1; - repeated DatanodeDetailsProto members = 2; - optional LifeCycleState state = 3 [default = OPEN]; - optional ReplicationType type = 4 [default = STAND_ALONE]; - optional ReplicationFactor factor = 5 [default = ONE]; - required PipelineID id = 6; -} - -message KeyValue { - required string key = 1; - optional string value = 2; -} - -/** - * Type of the node. - */ -enum NodeType { - OM = 1; // Ozone Manager - SCM = 2; // Storage Container Manager - DATANODE = 3; // DataNode -} - -// Should we rename NodeState to DatanodeState? -/** - * Enum that represents the Node State. This is used in calls to getNodeList - * and getNodeCount. - */ -enum NodeState { - HEALTHY = 1; - STALE = 2; - DEAD = 3; - DECOMMISSIONING = 4; - DECOMMISSIONED = 5; -} - -enum QueryScope { - CLUSTER = 1; - POOL = 2; -} - -message Node { - required DatanodeDetailsProto nodeID = 1; - repeated NodeState nodeStates = 2; -} - -message NodePool { - repeated Node nodes = 1; -} - -/** - * LifeCycleState for SCM object creation state machine: - * ->Allocated: allocated on SCM but clean has not started creating it yet. - * ->Creating: allocated and assigned to client to create but not ack-ed yet. - * ->Open: allocated on SCM and created on datanodes and ack-ed by a client. - * ->Close: container closed due to space all used or error? - * ->Timeout -> container failed to create on datanodes or ack-ed by client. - * ->Deleting(TBD) -> container will be deleted after timeout - * 1. ALLOCATE-ed containers on SCM can't serve key/block related operation - * until ACK-ed explicitly which changes the state to OPEN. - * 2. Only OPEN/CLOSED containers can serve key/block related operation. - * 3. ALLOCATE-ed containers that are not ACK-ed timely will be TIMEOUT and - * CLEANUP asynchronously. - */ - -enum LifeCycleState { - ALLOCATED = 1; - CREATING = 2; // Used for container allocated/created by different client. - OPEN =3; // Mostly an update to SCM via HB or client call. - CLOSING = 4; - CLOSED = 5; // !!State after this has not been used yet. - DELETING = 6; - DELETED = 7; // object is deleted. -} - -enum LifeCycleEvent { - CREATE = 1; // A request to client to create this object - CREATED = 2; - FINALIZE = 3; - CLOSE = 4; // !!Event after this has not been used yet. - UPDATE = 5; - TIMEOUT = 6; // creation has timed out from SCM's View. - DELETE = 7; - CLEANUP = 8; -} - -message SCMContainerInfo { - required int64 containerID = 1; - required LifeCycleState state = 2; - optional PipelineID pipelineID = 3; - // This is not total size of container, but space allocated by SCM for - // clients to write blocks - required uint64 allocatedBytes = 4; - required uint64 usedBytes = 5; - required uint64 numberOfKeys = 6; - optional int64 stateEnterTime = 7; - required string owner = 8; - optional int64 deleteTransactionId = 9; - required ReplicationFactor replicationFactor = 10; - required ReplicationType replicationType = 11; -} - -message ContainerWithPipeline { - required SCMContainerInfo containerInfo = 1; - required Pipeline pipeline = 2; -} - -message GetScmInfoRequestProto { -} - -message GetScmInfoRespsonseProto { - required string clusterId = 1; - required string scmId = 2; -} - - -enum ReplicationType { - RATIS = 1; - STAND_ALONE = 2; - CHAINED = 3; -} - -enum ReplicationFactor { - ONE = 1; - THREE = 3; -} - -enum ScmOps { - allocateBlock = 1; - keyBlocksInfoList = 2; - getScmInfo = 3; - deleteBlock = 4; - createReplicationPipeline = 5; - allocateContainer = 6; - getContainer = 7; - getContainerWithPipeline = 8; - listContainer = 9; - deleteContainer = 10; - queryNode = 11; -} - -/** - * Block ID that uniquely identify a block by SCM. - */ -message BlockID { - required int64 containerID = 1; - required int64 localID = 2; -} diff --git a/hadoop-hdds/common/src/main/resources/hdds-version-info.properties b/hadoop-hdds/common/src/main/resources/hdds-version-info.properties deleted file mode 100644 index 2cbd817ebbf..00000000000 --- a/hadoop-hdds/common/src/main/resources/hdds-version-info.properties +++ /dev/null @@ -1,26 +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 -# -# 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. -# - -version=${declared.hdds.version} -revision=${version-info.scm.commit} -branch=${version-info.scm.branch} -user=${user.name} -date=${version-info.build.time} -url=${version-info.scm.uri} -srcChecksum=${version-info.source.md5} -protocVersion=${protobuf.version} diff --git a/hadoop-hdds/common/src/main/resources/ozone-default.xml b/hadoop-hdds/common/src/main/resources/ozone-default.xml deleted file mode 100644 index b7c967d0ae6..00000000000 --- a/hadoop-hdds/common/src/main/resources/ozone-default.xml +++ /dev/null @@ -1,1299 +0,0 @@ - - - - - - - - - - - - - - - - ozone.container.cache.size - 1024 - PERFORMANCE, CONTAINER, STORAGE - The open container is cached on the data node side. We maintain - an LRU - cache for caching the recently used containers. This setting controls the - size of that cache. - - - - dfs.container.ipc - 9859 - OZONE, CONTAINER, MANAGEMENT - The ipc port number of container. - - - dfs.container.ipc.random.port - false - OZONE, DEBUG, CONTAINER - Allocates a random free port for ozone container. This is used - only while - running unit tests. - - - - dfs.container.ratis.datanode.storage.dir - - OZONE, CONTAINER, STORAGE, MANAGEMENT, RATIS - This directory is used for storing Ratis metadata like logs. If - this is - not set then default metadata dirs is used. A warning will be logged if - this not set. Ideally, this should be mapped to a fast disk like an SSD. - - - - hdds.datanode.dir - - OZONE, CONTAINER, STORAGE, MANAGEMENT - Determines where on the local filesystem HDDS data will be - stored. Defaults to dfs.datanode.data.dir if not specified. - The directories should be tagged with corresponding storage types - ([SSD]/[DISK]/[ARCHIVE]/[RAM_DISK]) for storage policies. The default - storage type will be DISK if the directory does not have a storage type - tagged explicitly. - - - - hdds.datanode.volume.choosing.policy - - OZONE, CONTAINER, STORAGE, MANAGEMENT - - The class name of the policy for choosing volumes in the list of - directories. Defaults to - org.apache.hadoop.ozone.container.common.volume.RoundRobinVolumeChoosingPolicy. - This volume choosing policy selects volumes in a round-robin order. - - - - dfs.container.ratis.enabled - false - OZONE, MANAGEMENT, PIPELINE, RATIS - Ozone supports different kinds of replication pipelines. Ratis - is one of - the replication pipeline supported by ozone. - - - - dfs.container.ratis.ipc - 9858 - OZONE, CONTAINER, PIPELINE, RATIS, MANAGEMENT - The ipc port number of container. - - - dfs.container.ratis.ipc.random.port - false - OZONE,DEBUG - Allocates a random free port for ozone ratis port for the - container. This - is used only while running unit tests. - - - - dfs.container.ratis.rpc.type - GRPC - OZONE, RATIS, MANAGEMENT - Ratis supports different kinds of transports like netty, GRPC, - Hadoop RPC - etc. This picks one of those for this cluster. - - - - dfs.container.ratis.num.write.chunk.threads - 60 - OZONE, RATIS, PERFORMANCE - Maximum number of threads in the thread pool that Ratis - will use for writing chunks (60 by default). - - - - dfs.container.ratis.replication.level - MAJORITY - OZONE, RATIS - Replication level to be used by datanode for submitting a - container command to ratis. Available replication levels are ALL and - MAJORTIY, MAJORITY is used as the default replication level. - - - - dfs.container.ratis.segment.size - 1073741824 - OZONE, RATIS, PERFORMANCE - The size of the raft segment used by Apache Ratis on datanodes. - (1 GB by default) - - - - dfs.container.ratis.segment.preallocated.size - 134217728 - OZONE, RATIS, PERFORMANCE - The size of the buffer which is preallocated for raft segment - used by Apache Ratis on datanodes.(128 MB by default) - - - - dfs.ratis.client.request.timeout.duration - 3s - OZONE, RATIS, MANAGEMENT - The timeout duration for ratis client request. - - - dfs.ratis.client.request.max.retries - 180 - OZONE, RATIS, MANAGEMENT - Number of retries for ratis client request. - - - dfs.ratis.client.request.retry.interval - 100ms - OZONE, RATIS, MANAGEMENT - Interval between successive retries for a ratis client request. - - - - dfs.ratis.server.retry-cache.timeout.duration - 600000ms - OZONE, RATIS, MANAGEMENT - Retry Cache entry timeout for ratis server. - - - dfs.ratis.server.request.timeout.duration - 3s - OZONE, RATIS, MANAGEMENT - The timeout duration for ratis server request. - - - dfs.ratis.leader.election.minimum.timeout.duration - 1s - OZONE, RATIS, MANAGEMENT - The minimum timeout duration for ratis leader election. - Default is 1s. - - - - dfs.ratis.server.failure.duration - 120s - OZONE, RATIS, MANAGEMENT - The timeout duration for ratis server failure detection, - once the threshold has reached, the ratis state machine will be informed - about the failure in the ratis ring - - - - hdds.node.report.interval - 60000ms - OZONE, CONTAINER, MANAGEMENT - Time interval of the datanode to send node report. Each - datanode periodically send node report to SCM. Unit could be - defined with postfix (ns,ms,s,m,h,d) - - - hdds.container.report.interval - 60000ms - OZONE, CONTAINER, MANAGEMENT - Time interval of the datanode to send container report. Each - datanode periodically send container report to SCM. Unit could be - defined with postfix (ns,ms,s,m,h,d) - - - hdds.command.status.report.interval - 60000ms - OZONE, CONTAINER, MANAGEMENT - Time interval of the datanode to send status of command - execution. Each datanode periodically the execution status of commands - received from SCM to SCM. Unit could be defined with postfix - (ns,ms,s,m,h,d) - - - hdds.pipeline.report.interval - 60000ms - OZONE, PIPELINE, MANAGEMENT - Time interval of the datanode to send pipeline report. Each - datanode periodically send pipeline report to SCM. Unit could be - defined with postfix (ns,ms,s,m,h,d) - - - - ozone.administrators - - OZONE, SECURITY - Ozone administrator users delimited by the comma. - If not set, only the user who launches an ozone service will be the admin - user. This property must be set if ozone services are started by different - users. Otherwise, the RPC layer will reject calls from other servers which - are started by users not in the list. - - - - ozone.block.deleting.container.limit.per.interval - 10 - OZONE, PERFORMANCE, SCM - A maximum number of containers to be scanned by block deleting - service per - time interval. The block deleting service spawns a thread to handle block - deletions in a container. This property is used to throttle the number of - threads spawned for block deletions. - - - - ozone.block.deleting.limit.per.task - 1000 - OZONE, PERFORMANCE, SCM - A maximum number of blocks to be deleted by block deleting - service per - time interval. This property is used to throttle the actual number of - block deletions on a data node per container. - - - - ozone.block.deleting.service.interval - 1m - OZONE, PERFORMANCE, SCM - Time interval of the block deleting service. - The block deleting service runs on each datanode periodically and - deletes blocks queued for deletion. Unit could be defined with - postfix (ns,ms,s,m,h,d) - - - - ozone.block.deleting.service.timeout - 300000ms - OZONE, PERFORMANCE, SCM - A timeout value of block deletion service. If this is set - greater than 0, - the service will stop waiting for the block deleting completion after this - time. If timeout happens to a large proportion of block deletion, this - needs to be increased with ozone.block.deleting.limit.per.task. This - setting supports multiple time unit suffixes as described in - dfs.heartbeat.interval. If no suffix is specified, then milliseconds is - assumed. - - - - ozone.client.connection.timeout - 5000ms - OZONE, PERFORMANCE, CLIENT - Connection timeout for Ozone client in milliseconds. - - - - ozone.client.max.retries - 50 - OZONE, CLIENT - Maximum number of retries by Ozone Client on encountering - exception while fetching committed block length. - - - - ozone.client.retry.interval - 200ms - OZONE, CLIENT - Interval between retries by Ozone Client on encountering - exception while fetching committed block length. - - - - ozone.client.protocol - org.apache.hadoop.ozone.client.rpc.RpcClient - OZONE, CLIENT, MANAGEMENT - Protocol class to be used by the client to connect to ozone - cluster. - The build-in implementation includes: - org.apache.hadoop.ozone.client.rpc.RpcClient for RPC - org.apache.hadoop.ozone.client.rest.RestClient for REST - The default is the RpClient. Please do not change this unless you have a - very good understanding of what you are doing. - - - - ozone.client.socket.timeout - 5000ms - OZONE, CLIENT - Socket timeout for Ozone client. Unit could be defined with - postfix (ns,ms,s,m,h,d) - - - ozone.enabled - false - OZONE, REQUIRED - - Status of the Ozone Object Storage service is enabled. - Set to true to enable Ozone. - Set to false to disable Ozone. - Unless this value is set to true, Ozone services will not be started in - the cluster. - - Please note: By default ozone is disabled on a hadoop cluster. - - - - ozone.key.deleting.limit.per.task - 1000 - OM, PERFORMANCE - - A maximum number of keys to be scanned by key deleting service - per time interval in OM. Those keys are sent to delete metadata and - generate transactions in SCM for next async deletion between SCM - and DataNode. - - - - ozone.om.address - - OM, REQUIRED - - The address of the Ozone OM service. This allows clients to discover - the address of the OM. - - - - ozone.om.group.rights - READ_WRITE - OM, SECURITY - - Default group permissions in Ozone OM. - - - - ozone.om.handler.count.key - 20 - OM, PERFORMANCE - - The number of RPC handler threads for OM service endpoints. - - - - ozone.om.http-address - 0.0.0.0:9874 - OM, MANAGEMENT - - The address and the base port where the OM web UI will listen on. - - If the port is 0, then the server will start on a free port. However, it - is best to specify a well-known port, so it is easy to connect and see - the OM management UI. - - - - ozone.om.http-bind-host - 0.0.0.0 - OM, MANAGEMENT - - The actual address the OM web server will bind to. If this optional - the address is set, it overrides only the hostname portion of - ozone.om.http-address. - - - - ozone.om.http.enabled - true - OM, MANAGEMENT - - Property to enable or disable OM web user interface. - - - - ozone.om.https-address - 0.0.0.0:9875 - OM, MANAGEMENT, SECURITY - - The address and the base port where the OM web UI will listen - on using HTTPS. - If the port is 0 then the server will start on a free port. - - - - ozone.om.https-bind-host - 0.0.0.0 - OM, MANAGEMENT, SECURITY - - The actual address the OM web server will bind to using HTTPS. - If this optional address is set, it overrides only the hostname portion of - ozone.om.http-address. - - - - ozone.om.keytab.file - - OM, SECURITY - - The keytab file for Kerberos authentication in OM. - - - - ozone.om.db.cache.size.mb - 128 - OM, PERFORMANCE - - The size of OM DB cache in MB that used for caching files. - This value is set to an abnormally low value in the default configuration. - That is to make unit testing easy. Generally, this value should be set to - something like 16GB or more, if you intend to use Ozone at scale. - - A large value for this key allows a proportionally larger amount of OM - metadata to be cached in memory. This makes OM operations faster. - - - - ozone.om.user.max.volume - 1024 - OM, MANAGEMENT - - The maximum number of volumes a user can have on a cluster.Increasing or - decreasing this number has no real impact on ozone cluster. This is - defined only for operational purposes. Only an administrator can create a - volume, once a volume is created there are no restrictions on the number - of buckets or keys inside each bucket a user can create. - - - - ozone.om.user.rights - READ_WRITE - OM, SECURITY - - Default user permissions used in OM. - - - - ozone.metadata.dirs - - OZONE, OM, SCM, CONTAINER, REQUIRED, STORAGE - - Ozone metadata is shared among OM, which acts as the namespace - manager for ozone, SCM which acts as the block manager and data nodes - which maintain the name of the key(Key Name and BlockIDs). This - replicated and distributed metadata store is maintained under the - directory pointed by this key. Since metadata can be I/O intensive, at - least on OM and SCM we recommend having SSDs. If you have the luxury - of mapping this path to SSDs on all machines in the cluster, that will - be excellent. - - If Ratis metadata directories are not specified, Ratis server will emit a - warning and use this path for storing its metadata too. - - - - ozone.metastore.impl - RocksDB - OZONE, OM, SCM, CONTAINER, STORAGE - - Ozone metadata store implementation. Ozone metadata are well - distributed to multiple services such as ozoneManager, scm. They are stored in - some local key-value databases. This property determines which database - library to use. Supported value is either LevelDB or RocksDB. - - - - - ozone.metastore.rocksdb.statistics - ALL - OZONE, OM, SCM, STORAGE, PERFORMANCE - - The statistics level of the rocksdb store. If you use any value from - org.rocksdb.StatsLevel (eg. ALL or EXCEPT_DETAILED_TIMERS), the rocksdb - statistics will be exposed over JMX bean with the choosed setting. Set - it to OFF to not initialize rocksdb statistics at all. Please note that - collection of statistics could have 5-10% performance penalty. - Check the rocksdb documentation for more details. - - - - - ozone.scm.block.client.address - - OZONE, SCM - The address of the Ozone SCM block client service. If not - defined value of ozone.scm.client.address is used. - - - - ozone.scm.block.client.bind.host - 0.0.0.0 - OZONE, SCM - - The hostname or IP address used by the SCM block client - endpoint to bind. - - - - ozone.scm.block.client.port - 9863 - OZONE, SCM - - The port number of the Ozone SCM block client service. - - - - ozone.scm.block.deletion.max.retry - 4096 - OZONE, SCM - - SCM wraps up many blocks in a deletion transaction and sends that to data - node for physical deletion periodically. This property determines how many - times SCM is going to retry sending a deletion operation to the data node. - - - - ozone.scm.block.size.in.mb - 256 - OZONE, SCM - - The default size of a scm block in bytes. This is maps to the default - Ozone block size. - - - - ozone.scm.chunk.size - 16777216 - OZONE, SCM, CONTAINER, PERFORMANCE - - The chunk size for reading/writing chunk operations in bytes. - - The chunk size defaults to 8MB. If the value configured is more than the - maximum size (16MB), it will be reset to the maximum size. This maps to - the network packet sizes and file write operations in the client to - datanode protocol. - - - - ozone.scm.client.address - - OZONE, SCM, REQUIRED - - The address of the Ozone SCM client service. This is a required setting. - - It is a string in the host:port format. The port number is optional - and defaults to 9860. - - - - ozone.scm.client.bind.host - 0.0.0.0 - OZONE, SCM, MANAGEMENT - The hostname or IP address used by the SCM client endpoint to - bind. - This setting is used by the SCM only and never used by clients. - - The setting can be useful in multi-homed setups to restrict the - availability of the SCM client service to a specific interface. - - The default is appropriate for most clusters. - - - - ozone.scm.client.port - 9860 - OZONE, SCM, MANAGEMENT - The port number of the Ozone SCM client service. - - - ozone.scm.keyvalue.container.deletion-choosing.policy - - org.apache.hadoop.ozone.container.common.impl.TopNOrderedContainerDeletionChoosingPolicy - - OZONE, MANAGEMENT - - The policy used for choosing desired keyvalue containers for block deletion. - Datanode selects some containers to process block deletion - in a certain interval defined by ozone.block.deleting.service.interval. - The number of containers to process in each interval is defined - by ozone.block.deleting.container.limit.per.interval. This property is - used to configure the policy applied while selecting containers. - There are two policies supporting now: - RandomContainerDeletionChoosingPolicy and - TopNOrderedContainerDeletionChoosingPolicy. - org.apache.hadoop.ozone.container.common.impl.RandomContainerDeletionChoosingPolicy - implements a simply random policy that to return a random list of - containers. - org.apache.hadoop.ozone.container.common.impl.TopNOrderedContainerDeletionChoosingPolicy - implements a policy that choosing top count number of containers in a - pending-deletion-blocks's num - based descending order. - - - - ozone.scm.container.placement.impl - - org.apache.hadoop.hdds.scm.container.placement.algorithms.SCMContainerPlacementRandom - - OZONE, MANAGEMENT - Placement policy class for containers. - Defaults to SCMContainerPlacementRandom.class - - - - ozone.scm.container.provision_batch_size - 20 - OZONE, PERFORMANCE - Pre-provision specified number of containers for block - allocation. - - - - ozone.scm.container.size - 5GB - OZONE, PERFORMANCE, MANAGEMENT - - Default container size used by Ozone. - There are two considerations while picking this number. The speed at which - a container can be replicated, determined by the network speed and the - metadata that each container generates. So selecting a large number - creates less SCM metadata, but recovery time will be more. 5GB is a number - that maps to quick replication times in gigabit networks, but still - balances the amount of metadata. - - - - ozone.scm.datanode.address - - OZONE, MANAGEMENT - - The address of the Ozone SCM service used for internal - communication between the DataNodes and the SCM. - - It is a string in the host:port format. The port number is optional - and defaults to 9861. - - This setting is optional. If unspecified then the hostname portion - is picked from the ozone.scm.client.address setting and the - default service port of 9861 is chosen. - - - - ozone.scm.datanode.bind.host - - OZONE, MANAGEMENT - - The hostname or IP address used by the SCM service endpoint to - bind. - - - - ozone.scm.datanode.id - - OZONE, MANAGEMENT - The path that datanodes will use to store the datanode ID. - If this value is not set, then datanode ID is created under the - metadata directory. - - - - ozone.scm.datanode.port - 9861 - OZONE, MANAGEMENT - - The port number of the Ozone SCM service. - - - - ozone.scm.db.cache.size.mb - 128 - OZONE, PERFORMANCE - SCM keeps track of the Containers in the cluster. This DB holds - the container metadata. This value is set to a small value to make the - unit - testing runs smooth. In production, we recommend a value of 16GB or - higher. This allows SCM to avoid disk I/O's while looking up the container - location. - - - - ozone.scm.dead.node.interval - 10m - OZONE, MANAGEMENT - - The interval between heartbeats before a node is tagged as dead. - - - - ozone.scm.handler.count.key - 10 - OZONE, MANAGEMENT, PERFORMANCE - - The number of RPC handler threads for each SCM service - endpoint. - - The default is appropriate for small clusters (tens of nodes). - - Set a value that is appropriate for the cluster size. Generally, HDFS - recommends RPC handler count is set to 20 * log2(Cluster Size) with an - upper limit of 200. However, SCM will not have the same amount of - traffic as Namenode, so a value much smaller than that will work well too. - - - - hdds.heartbeat.interval - 30s - OZONE, MANAGEMENT - - The heartbeat interval from a data node to SCM. Yes, - it is not three but 30, since most data nodes will heart beating via Ratis - heartbeats. If a client is not able to talk to a data node, it will notify - OM/SCM eventually. So a 30 second HB seems to work. This assumes that - replication strategy used is Ratis if not, this value should be set to - something smaller like 3 seconds. - - - - ozone.scm.heartbeat.log.warn.interval.count - 10 - OZONE, MANAGEMENT - - Defines how frequently we will log the missing of a heartbeat to SCM. - For example in the default case, we will write a warning message for each - ten consecutive heartbeats that we miss to SCM. This helps in reducing - clutter in a data node log, but trade off is that logs will have less of - this statement. - - - - ozone.scm.heartbeat.rpc-timeout - 1000 - OZONE, MANAGEMENT - - Timeout value for the RPC from Datanode to SCM in milliseconds. - - - - ozone.scm.heartbeat.thread.interval - 3s - OZONE, MANAGEMENT - - When a heartbeat from the data node arrives on SCM, It is queued for - processing with the time stamp of when the heartbeat arrived. There is a - heartbeat processing thread inside SCM that runs at a specified interval. - This value controls how frequently this thread is run. - - There are some assumptions build into SCM such as this value should allow - the heartbeat processing thread to run at least three times more - frequently than heartbeats and at least five times more than stale node - detection time. If you specify a wrong value, SCM will gracefully refuse - to run. For more info look at the node manager tests in SCM. - - In short, you don't need to change this. - - - - ozone.scm.http-address - 0.0.0.0:9876 - OZONE, MANAGEMENT - - The address and the base port where the SCM web ui will listen on. - - If the port is 0 then the server will start on a free port. - - - - ozone.scm.http-bind-host - 0.0.0.0 - OZONE, MANAGEMENT - - The actual address the SCM web server will bind to. If this - optional address is set, it overrides only the hostname portion of - ozone.scm.http-address. - - - - ozone.scm.http.enabled - true - OZONE, MANAGEMENT - - Property to enable or disable SCM web ui. - - - - ozone.scm.https-address - 0.0.0.0:9877 - OZONE, MANAGEMENT - - The address and the base port where the SCM web UI will listen - on using HTTPS. - - If the port is 0 then the server will start on a free port. - - - - ozone.scm.https-bind-host - 0.0.0.0 - OZONE, MANAGEMENT - - The actual address the SCM web server will bind to using HTTPS. - If this optional address is set, it overrides only the hostname portion of - ozone.scm.http-address. - - - - ozone.scm.keytab.file - - OZONE, SECURITY - - The keytab file for Kerberos authentication in SCM. - - - - ozone.scm.names - - OZONE, REQUIRED - - The value of this property is a set of DNS | DNS:PORT | IP - Address | IP:PORT. Written as a comma separated string. e.g. scm1, - scm2:8020, 7.7.7.7:7777. - This property allows datanodes to discover where SCM is, so that - datanodes can send heartbeat to SCM. - - - - ozone.scm.stale.node.interval - 90s - OZONE, MANAGEMENT - - The interval for stale node flagging. Please - see ozone.scm.heartbeat.thread.interval before changing this value. - - - - ozone.trace.enabled - false - OZONE, DEBUG - - Setting this flag to true dumps the HTTP request/ response in - the logs. Very useful when debugging REST protocol. - - - - ozone.web.authentication.kerberos.principal - - OZONE, SECURITY - - The server principal used by the SCM and OM for web UI SPNEGO - authentication when Kerberos security is enabled. This is typically set to - HTTP/_HOST@REALM.TLD The SPNEGO server principal begins with the prefix - HTTP/ by convention. - - If the value is '*', the web server will attempt to login with - every principal specified in the keytab file. - - - - - - scm.container.client.idle.threshold - 10s - OZONE, PERFORMANCE - - In the standalone pipelines, the SCM clients use netty to - communicate with the container. It also uses connection pooling to - reduce client side overheads. This allows a connection to stay idle for - a while before the connection is closed. - - - - scm.container.client.max.size - 256 - OZONE, PERFORMANCE - - Controls the maximum number of connections that we cached via - clientconnection pooling. If the number of connection - exceed this count then the oldest idle connection is evicted. - - - - - scm.container.client.max.outstanding.requests - 100 - OZONE, PERFORMANCE - - Controls the maximum number of outstanding async requests that can be - handled by the Standalone as well as Ratis client. - - - - - ozone.scm.container.creation.lease.timeout - 60s - OZONE, SCM - - Container creation timeout in milliseconds to be used by SCM. When - BEGIN_CREATE event happens the container is moved from ALLOCATED to - CREATING state, SCM will now wait for the configured amount of time - to get COMPLETE_CREATE event if it doesn't receive it will move the - container to DELETING. - - - - - ozone.key.preallocation.maxsize - 134217728 - OZONE, OM, PERFORMANCE - - When a new key write request is sent to OM, if a size is requested, at most - 128MB of size is allocated at request time. If client needs more space for the - write, separate block allocation requests will be made. - - - - - ozone.client.list.cache - 1000 - OZONE, PERFORMANCE - - Configuration property to configure the cache size of client list calls. - - - - - ozone.replication - 3 - OZONE, CLIENT - - Default replication value. The actual number of replications can be - specified when writing the key. The default is used if replication - is not specified. Supported values: 1 and 3. - - - - - ozone.replication.type - RATIS - OZONE, CLIENT - - Default replication type to be used while writing key into ozone. The - value can be specified when writing the key, default is used when - nothing is specified. Supported values: RATIS, STAND_ALONE and CHAINED. - - - - hdds.container.close.threshold - 0.9f - OZONE, DATANODE - - This determines the threshold to be used for closing a container. - When the container used percentage reaches this threshold, - the container will be closed. Value should be a positive, non-zero - percentage in float notation (X.Yf), with 1.0f meaning 100%. - - - - ozone.rest.client.http.connection.max - 100 - OZONE, CLIENT - - This defines the overall connection limit for the connection pool used in - RestClient. - - - - ozone.rest.client.http.connection.per-route.max - 20 - OZONE, CLIENT - - This defines the connection limit per one HTTP route/host. Total max - connection is limited by ozone.rest.client.http.connection.max property. - - - - - ozone.open.key.cleanup.service.interval.seconds - 86400 - OZONE, OM, PERFORMANCE - - A background job periodically checks open key entries and delete the expired ones. This entry controls the - interval of this cleanup check. - - - - - ozone.open.key.expire.threshold - 86400 - OZONE, OM, PERFORMANCE - - Controls how long an open key operation is considered active. Specifically, if a key - has been open longer than the value of this config entry, that open key is considered as - expired (e.g. due to client crash). Default to 24 hours. - - - - - hadoop.tags.custom - OZONE,MANAGEMENT,SECURITY,PERFORMANCE,DEBUG,CLIENT,SERVER,OM,SCM,CRITICAL,RATIS,CONTAINER,REQUIRED,REST,STORAGE,PIPELINE,STANDALONE,S3GATEWAY - - - - ozone.tags.system - OZONE,MANAGEMENT,SECURITY,PERFORMANCE,DEBUG,CLIENT,SERVER,OM,SCM,CRITICAL,RATIS,CONTAINER,REQUIRED,REST,STORAGE,PIPELINE,STANDALONE,S3GATEWAY - - - - - hdds.rest.rest-csrf.enabled - false - - If true, then enables Object Store REST server protection against - cross-site request forgery (CSRF). - - - - - hdds.rest.http-address - 0.0.0.0:9880 - The http address of Object Store REST server inside the - datanode. - - - - - hdds.rest.netty.high.watermark - 65535 - - High watermark configuration to Netty for Object Store REST server. - - - - - hdds.rest.netty.low.watermark - 32768 - - Low watermark configuration to Netty for Object Store REST server. - - - - - hdds.datanode.plugins - org.apache.hadoop.ozone.web.OzoneHddsDatanodeService - - Comma-separated list of HDDS datanode plug-ins to be activated when - HDDS service starts as part of datanode. - - - - hdds.datanode.storage.utilization.warning.threshold - 0.75 - OZONE, SCM, MANAGEMENT - - If a datanode overall storage utilization exceeds more than this - value, a warning will be logged while processing the nodeReport in SCM. - - - - - hdds.datanode.storage.utilization.critical.threshold - 0.95 - OZONE, SCM, MANAGEMENT - - If a datanode overall storage utilization exceeds more than this - value, the datanode will be marked out of space. - - - - - hdds.write.lock.reporting.threshold.ms - 5000 - OZONE, DATANODE, MANAGEMENT - - When a write lock is held for a long time, this will be logged as the - lock is released. This sets how long the lock must be held for logging - to occur. - - - - - hdds.lock.suppress.warning.interval.ms - 10000 - OZONE, DATANODE, MANAGEMENT - - Instrumentation reporting long critical sections will suppress - consecutive warnings within this interval. - - - - - hdds.command.status.report.interval - 30s - OZONE, DATANODE, MANAGEMENT - Time interval of the datanode to send status of commands - executed since last report. Unit could be defined with - postfix (ns,ms,s,m,h,d) - - - ozone.scm.pipeline.creation.lease.timeout - 60s - OZONE, SCM, PIPELINE - - Pipeline creation timeout in milliseconds to be used by SCM. When - BEGIN_CREATE event happens the pipeline is moved from ALLOCATED to - CREATING state, SCM will now wait for the configured amount of time - to get COMPLETE_CREATE event if it doesn't receive it will move the - pipeline to DELETING. - - - - - hdds.scm.chillmode.threshold.pct - 0.99 - HDDS,SCM,OPERATION - % of containers which should have at least one - reported replica before SCM comes out of chill mode. - - - - - hdds.scm.chillmode.enabled - true - HDDS,SCM,OPERATION - Boolean value to enable or disable SCM chill mode. - - - - - hdds.container.action.max.limit - 20 - DATANODE - - Maximum number of Container Actions sent by the datanode to SCM in a - single heartbeat. - - - - - hdds.pipeline.action.max.limit - 20 - DATANODE - - Maximum number of Pipeline Actions sent by the datanode to SCM in a - single heartbeat. - - - - hdds.scm.watcher.timeout - 10m - OZONE, SCM, MANAGEMENT - - Timeout for the watchers of the HDDS SCM CommandWatchers. After this - duration the Copy/Delete container commands will be sent again to the - datanode unless the datanode confirms the completion. - - - - - hdds.db.profile - SSD - OZONE, OM, PERFORMANCE, REQUIRED - This property allows user to pick a configuration - that tunes the RocksDB settings for the hardware it is running - on. Right now, we have SSD and DISK as profile options. - - - - hdds.datanode.replication.work.dir - DATANODE - Temporary which is used during the container replication - betweeen datanodes. Should have enough space to store multiple container - (in compressed format), but doesn't require fast io access such as SSD. - - - - - hdds.lock.max.concurrency - 100 - HDDS - Locks in HDDS/Ozone uses object pool to maintain active locks - in the system, this property defines the max limit for the locks that - will be maintained in the pool. - - - - - ozone.s3g.authentication.kerberos.principal - - OZONE, S3GATEWAY - The server principal used by Ozone S3Gateway server. This is - typically set to - HTTP/_HOST@REALM.TLD The SPNEGO server principal begins with the prefix - HTTP/ by convention. - - - - ozone.s3g.domain.name - - OZONE, S3GATEWAY - List of Ozone S3Gateway domain names. If multiple - domain names to be provided, they should be a "," seperated. - This parameter is only required when virtual host style pattern is - followed. - - - - ozone.s3g.http-address - 0.0.0.0:9878 - OZONE, S3GATEWAY - The address and the base port where the Ozone S3Gateway - Server will - listen on. - - - - ozone.s3g.http-bind-host - 0.0.0.0 - OZONE, S3GATEWAY - The actual address the HTTP server will bind to. If this optional address - is set, it overrides only the hostname portion of ozone.s3g.http-address. - This is useful for making the Ozone S3Gateway HTTP server listen on all - interfaces by setting it to 0.0.0.0. - - - - ozone.s3g.http.enabled - true - OZONE, S3GATEWAY - The boolean which enables the Ozone S3Gateway server - . - - - - ozone.s3g.https-address - - OZONE, S3GATEWAY - Ozone S3Gateway serverHTTPS server address and port - . - - - - ozone.s3g.https-bind-host - - OZONE, S3GATEWAY - The actual address the HTTPS server will bind to. If this optional address - is set, it overrides only the hostname portion of ozone.s3g.https-address. - This is useful for making the Ozone S3Gateway HTTPS server listen on all - interfaces by setting it to 0.0.0.0. - - - - ozone.s3g.keytab.file - - OZONE, S3GATEWAY - The keytab file used by the S3Gateway server to login as its - service principal. - - - - diff --git a/hadoop-hdds/common/src/test/java/org/apache/hadoop/hdds/scm/package-info.java b/hadoop-hdds/common/src/test/java/org/apache/hadoop/hdds/scm/package-info.java deleted file mode 100644 index 796694171f4..00000000000 --- a/hadoop-hdds/common/src/test/java/org/apache/hadoop/hdds/scm/package-info.java +++ /dev/null @@ -1,21 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm; -/** - Test cases for SCM client classes. - */ \ No newline at end of file diff --git a/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/TestOzoneAcls.java b/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/TestOzoneAcls.java deleted file mode 100644 index 03c45c50198..00000000000 --- a/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/TestOzoneAcls.java +++ /dev/null @@ -1,141 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone; - -import org.junit.Test; - -import java.util.HashMap; -import java.util.Set; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -/** - * This class is to test acl stoarge and retreival in ozone store. - */ -public class TestOzoneAcls { - - @Test - public void testAclParse() { - HashMap testMatrix; - testMatrix = new HashMap<>(); - - testMatrix.put("user:bilbo:r", Boolean.TRUE); - testMatrix.put("user:bilbo:w", Boolean.TRUE); - testMatrix.put("user:bilbo:rw", Boolean.TRUE); - testMatrix.put("user:bilbo:wr", Boolean.TRUE); - testMatrix.put(" user:bilbo:wr ", Boolean.TRUE); - - - // ACLs makes no judgement on the quality of - // user names. it is for the userAuth interface - // to determine if a user name is really a name - testMatrix.put(" user:*:rw", Boolean.TRUE); - testMatrix.put(" user:~!:rw", Boolean.TRUE); - - - testMatrix.put("", Boolean.FALSE); - testMatrix.put(null, Boolean.FALSE); - testMatrix.put(" user:bilbo:", Boolean.FALSE); - testMatrix.put(" user:bilbo:rx", Boolean.FALSE); - testMatrix.put(" user:bilbo:mk", Boolean.FALSE); - testMatrix.put(" user::rw", Boolean.FALSE); - testMatrix.put("user11:bilbo:rw", Boolean.FALSE); - testMatrix.put(" user:::rw", Boolean.FALSE); - - testMatrix.put(" group:hobbit:r", Boolean.TRUE); - testMatrix.put(" group:hobbit:w", Boolean.TRUE); - testMatrix.put(" group:hobbit:rw", Boolean.TRUE); - testMatrix.put(" group:hobbit:wr", Boolean.TRUE); - testMatrix.put(" group:*:rw", Boolean.TRUE); - testMatrix.put(" group:~!:rw", Boolean.TRUE); - - testMatrix.put(" group:hobbit:", Boolean.FALSE); - testMatrix.put(" group:hobbit:rx", Boolean.FALSE); - testMatrix.put(" group:hobbit:mk", Boolean.FALSE); - testMatrix.put(" group::", Boolean.FALSE); - testMatrix.put(" group::rw", Boolean.FALSE); - testMatrix.put(" group22:hobbit:", Boolean.FALSE); - testMatrix.put(" group:::rw", Boolean.FALSE); - - testMatrix.put("JUNK group:hobbit:r", Boolean.FALSE); - testMatrix.put("JUNK group:hobbit:w", Boolean.FALSE); - testMatrix.put("JUNK group:hobbit:rw", Boolean.FALSE); - testMatrix.put("JUNK group:hobbit:wr", Boolean.FALSE); - testMatrix.put("JUNK group:*:rw", Boolean.FALSE); - testMatrix.put("JUNK group:~!:rw", Boolean.FALSE); - - testMatrix.put(" world::r", Boolean.TRUE); - testMatrix.put(" world::w", Boolean.TRUE); - testMatrix.put(" world::rw", Boolean.TRUE); - testMatrix.put(" world::wr", Boolean.TRUE); - - testMatrix.put(" world:bilbo:w", Boolean.FALSE); - testMatrix.put(" world:bilbo:rw", Boolean.FALSE); - - Set keys = testMatrix.keySet(); - for (String key : keys) { - if (testMatrix.get(key)) { - OzoneAcl.parseAcl(key); - } else { - try { - OzoneAcl.parseAcl(key); - // should never get here since parseAcl will throw - fail("An exception was expected but did not happen."); - } catch (IllegalArgumentException e) { - // nothing to do - } - } - } - } - - @Test - public void testAclValues() { - OzoneAcl acl = OzoneAcl.parseAcl("user:bilbo:rw"); - assertEquals(acl.getName(), "bilbo"); - assertEquals(OzoneAcl.OzoneACLRights.READ_WRITE, acl.getRights()); - assertEquals(OzoneAcl.OzoneACLType.USER, acl.getType()); - - acl = OzoneAcl.parseAcl("user:bilbo:wr"); - assertEquals("bilbo", acl.getName()); - assertEquals(OzoneAcl.OzoneACLRights.READ_WRITE, acl.getRights()); - assertEquals(OzoneAcl.OzoneACLType.USER, acl.getType()); - - acl = OzoneAcl.parseAcl("user:bilbo:r"); - assertEquals("bilbo", acl.getName()); - assertEquals(OzoneAcl.OzoneACLRights.READ, acl.getRights()); - assertEquals(OzoneAcl.OzoneACLType.USER, acl.getType()); - - acl = OzoneAcl.parseAcl("user:bilbo:w"); - assertEquals("bilbo", acl.getName()); - assertEquals(OzoneAcl.OzoneACLRights.WRITE, acl.getRights()); - assertEquals(OzoneAcl.OzoneACLType.USER, acl.getType()); - - acl = OzoneAcl.parseAcl("group:hobbit:wr"); - assertEquals(acl.getName(), "hobbit"); - assertEquals(OzoneAcl.OzoneACLRights.READ_WRITE, acl.getRights()); - assertEquals(OzoneAcl.OzoneACLType.GROUP, acl.getType()); - - acl = OzoneAcl.parseAcl("world::wr"); - assertEquals(acl.getName(), ""); - assertEquals(OzoneAcl.OzoneACLRights.READ_WRITE, acl.getRights()); - assertEquals(OzoneAcl.OzoneACLType.WORLD, acl.getType()); - } - -} diff --git a/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/audit/DummyAction.java b/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/audit/DummyAction.java deleted file mode 100644 index 6044c0a2f55..00000000000 --- a/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/audit/DummyAction.java +++ /dev/null @@ -1,51 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.audit; - -/** - * Enum to define Dummy AuditAction Type for test. - */ -public enum DummyAction implements AuditAction { - - CREATE_VOLUME("CREATE_VOLUME"), - CREATE_BUCKET("CREATE_BUCKET"), - CREATE_KEY("CREATE_KEY"), - READ_VOLUME("READ_VOLUME"), - READ_BUCKET("READ_BUCKET"), - READ_KEY("READ_BUCKET"), - UPDATE_VOLUME("UPDATE_VOLUME"), - UPDATE_BUCKET("UPDATE_BUCKET"), - UPDATE_KEY("UPDATE_KEY"), - DELETE_VOLUME("DELETE_VOLUME"), - DELETE_BUCKET("DELETE_BUCKET"), - DELETE_KEY("DELETE_KEY"), - SET_OWNER("SET_OWNER"), - SET_QUOTA("SET_QUOTA"); - - private String action; - - DummyAction(String action) { - this.action = action; - } - - @Override - public String getAction() { - return this.action; - } - -} diff --git a/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/audit/DummyEntity.java b/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/audit/DummyEntity.java deleted file mode 100644 index 0c2d98fab29..00000000000 --- a/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/audit/DummyEntity.java +++ /dev/null @@ -1,57 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.audit; - -import java.util.HashMap; -import java.util.Map; - -/** - * DummyEntity that implements Auditable for test purpose. - */ -public class DummyEntity implements Auditable { - - private String key1; - private String key2; - - public DummyEntity(){ - this.key1 = "value1"; - this.key2 = "value2"; - } - public String getKey1() { - return key1; - } - - public void setKey1(String key1) { - this.key1 = key1; - } - - public String getKey2() { - return key2; - } - - public void setKey2(String key2) { - this.key2 = key2; - } - - @Override - public Map toAuditMap() { - Map auditMap = new HashMap<>(); - auditMap.put("key1", this.key1); - auditMap.put("key2", this.key2); - return auditMap; - } -} diff --git a/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/audit/TestOzoneAuditLogger.java b/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/audit/TestOzoneAuditLogger.java deleted file mode 100644 index 77a6c0baddd..00000000000 --- a/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/audit/TestOzoneAuditLogger.java +++ /dev/null @@ -1,166 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.audit; - -import org.apache.commons.io.FileUtils; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.util.List; -import java.util.Map; - -import static org.junit.Assert.assertTrue; - -/** - * Test Ozone Audit Logger. - */ -public class TestOzoneAuditLogger { - - private static final Logger LOG = - LoggerFactory.getLogger(TestOzoneAuditLogger.class.getName()); - - private static final AuditLogger AUDIT = - new AuditLogger(AuditLoggerType.OMLOGGER); - - private static final String SUCCESS = AuditEventStatus.SUCCESS.name(); - private static final String FAILURE = AuditEventStatus.FAILURE.name(); - - private static final Map PARAMS = - new DummyEntity().toAuditMap(); - - private static final AuditMessage WRITE_FAIL_MSG = - new AuditMessage.Builder() - .setUser("john") - .atIp("192.168.0.1") - .forOperation(DummyAction.CREATE_VOLUME.name()) - .withParams(PARAMS) - .withResult(FAILURE) - .withException(null).build(); - - private static final AuditMessage WRITE_SUCCESS_MSG = - new AuditMessage.Builder() - .setUser("john") - .atIp("192.168.0.1") - .forOperation(DummyAction.CREATE_VOLUME.name()) - .withParams(PARAMS) - .withResult(SUCCESS) - .withException(null).build(); - - private static final AuditMessage READ_FAIL_MSG = - new AuditMessage.Builder() - .setUser("john") - .atIp("192.168.0.1") - .forOperation(DummyAction.READ_VOLUME.name()) - .withParams(PARAMS) - .withResult(FAILURE) - .withException(null).build(); - - private static final AuditMessage READ_SUCCESS_MSG = - new AuditMessage.Builder() - .setUser("john") - .atIp("192.168.0.1") - .forOperation(DummyAction.READ_VOLUME.name()) - .withParams(PARAMS) - .withResult(SUCCESS) - .withException(null).build(); - - @BeforeClass - public static void setUp(){ - System.setProperty("log4j.configurationFile", "log4j2.properties"); - } - - @AfterClass - public static void tearDown() { - File file = new File("audit.log"); - if (FileUtils.deleteQuietly(file)) { - LOG.info(file.getName() + - " has been deleted as all tests have completed."); - } else { - LOG.info("audit.log could not be deleted."); - } - } - - /** - * Test to verify default log level is INFO when logging success events. - */ - @Test - public void verifyDefaultLogLevelForSuccess() throws IOException { - AUDIT.logWriteSuccess(WRITE_SUCCESS_MSG); - String expected = - "INFO | OMAudit | " + WRITE_SUCCESS_MSG.getFormattedMessage(); - verifyLog(expected); - } - - /** - * Test to verify default log level is ERROR when logging failure events. - */ - @Test - public void verifyDefaultLogLevelForFailure() throws IOException { - AUDIT.logWriteFailure(WRITE_FAIL_MSG); - String expected = - "ERROR | OMAudit | " + WRITE_FAIL_MSG.getFormattedMessage(); - verifyLog(expected); - } - - /** - * Test to verify no READ event is logged. - */ - @Test - public void notLogReadEvents() throws IOException { - AUDIT.logReadSuccess(READ_SUCCESS_MSG); - AUDIT.logReadFailure(READ_FAIL_MSG); - verifyNoLog(); - } - - private void verifyLog(String expected) throws IOException { - File file = new File("audit.log"); - List lines = FileUtils.readLines(file, (String)null); - final int retry = 5; - int i = 0; - while (lines.isEmpty() && i < retry) { - lines = FileUtils.readLines(file, (String)null); - try { - Thread.sleep(500 * (i + 1)); - } catch(InterruptedException ie) { - Thread.currentThread().interrupt(); - break; - } - i++; - } - - // When log entry is expected, the log file will contain one line and - // that must be equal to the expected string - assertTrue(lines.size() != 0); - assertTrue(expected.equalsIgnoreCase(lines.get(0))); - //empty the file - lines.remove(0); - FileUtils.writeLines(file, lines, false); - } - - private void verifyNoLog() throws IOException { - File file = new File("audit.log"); - List lines = FileUtils.readLines(file, (String)null); - // When no log entry is expected, the log file must be empty - assertTrue(lines.size() == 0); - } -} diff --git a/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/audit/package-info.java b/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/audit/package-info.java deleted file mode 100644 index 1222ad04e08..00000000000 --- a/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/audit/package-info.java +++ /dev/null @@ -1,23 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.audit; -/** - * Unit tests of Ozone Audit Logger. - * For test purpose, the log4j2 configuration is loaded from file at: - * src/test/resources/log4j2.properties - */ diff --git a/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/common/TestStateMachine.java b/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/common/TestStateMachine.java deleted file mode 100644 index c1470bb2efc..00000000000 --- a/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/common/TestStateMachine.java +++ /dev/null @@ -1,106 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.common; - -import org.apache.commons.collections.SetUtils; -import org.apache.hadoop.ozone.common.statemachine - .InvalidStateTransitionException; -import org.apache.hadoop.ozone.common.statemachine.StateMachine; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import java.util.HashSet; -import java.util.Set; - -import static org.apache.hadoop.ozone.common.TestStateMachine.STATES.CLEANUP; -import static org.apache.hadoop.ozone.common.TestStateMachine.STATES.CLOSED; -import static org.apache.hadoop.ozone.common.TestStateMachine.STATES.CREATING; -import static org.apache.hadoop.ozone.common.TestStateMachine.STATES.FINAL; -import static org.apache.hadoop.ozone.common.TestStateMachine.STATES.INIT; -import static org.apache.hadoop.ozone.common.TestStateMachine.STATES - .OPERATIONAL; - -/** - * This class is to test ozone common state machine. - */ -public class TestStateMachine { - - /** - * STATES used by the test state machine. - */ - public enum STATES {INIT, CREATING, OPERATIONAL, CLOSED, CLEANUP, FINAL}; - - /** - * EVENTS used by the test state machine. - */ - public enum EVENTS {ALLOCATE, CREATE, UPDATE, CLOSE, DELETE, TIMEOUT}; - - @Rule - public ExpectedException exception = ExpectedException.none(); - - @Test - public void testStateMachineStates() throws InvalidStateTransitionException { - Set finals = new HashSet<>(); - finals.add(FINAL); - - StateMachine stateMachine = - new StateMachine<>(INIT, finals); - - stateMachine.addTransition(INIT, CREATING, EVENTS.ALLOCATE); - stateMachine.addTransition(CREATING, OPERATIONAL, EVENTS.CREATE); - stateMachine.addTransition(OPERATIONAL, OPERATIONAL, EVENTS.UPDATE); - stateMachine.addTransition(OPERATIONAL, CLEANUP, EVENTS.DELETE); - stateMachine.addTransition(OPERATIONAL, CLOSED, EVENTS.CLOSE); - stateMachine.addTransition(CREATING, CLEANUP, EVENTS.TIMEOUT); - - // Initial and Final states - Assert.assertEquals("Initial State", INIT, stateMachine.getInitialState()); - Assert.assertTrue("Final States", SetUtils.isEqualSet(finals, - stateMachine.getFinalStates())); - - // Valid state transitions - Assert.assertEquals("STATE should be OPERATIONAL after being created", - OPERATIONAL, stateMachine.getNextState(CREATING, EVENTS.CREATE)); - Assert.assertEquals("STATE should be OPERATIONAL after being updated", - OPERATIONAL, stateMachine.getNextState(OPERATIONAL, EVENTS.UPDATE)); - Assert.assertEquals("STATE should be CLEANUP after being deleted", - CLEANUP, stateMachine.getNextState(OPERATIONAL, EVENTS.DELETE)); - Assert.assertEquals("STATE should be CLEANUP after being timeout", - CLEANUP, stateMachine.getNextState(CREATING, EVENTS.TIMEOUT)); - Assert.assertEquals("STATE should be CLOSED after being closed", - CLOSED, stateMachine.getNextState(OPERATIONAL, EVENTS.CLOSE)); - - // Negative cases: invalid transition - expectException(); - stateMachine.getNextState(OPERATIONAL, EVENTS.CREATE); - - expectException(); - stateMachine.getNextState(CREATING, EVENTS.CLOSE); - } - - /** - * We expect an InvalidStateTransitionException. - */ - private void expectException() { - exception.expect(InvalidStateTransitionException.class); - exception.expectMessage("Invalid event"); - } - -} diff --git a/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/lease/TestLeaseManager.java b/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/lease/TestLeaseManager.java deleted file mode 100644 index bdc70fc983a..00000000000 --- a/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/lease/TestLeaseManager.java +++ /dev/null @@ -1,373 +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 - * - * 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. - */ - -/** - * A generic lease management API which can be used if a service - * needs any kind of lease management. - */ - -package org.apache.hadoop.ozone.lease; - -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import java.util.HashMap; -import java.util.Map; - -/** - * Test class to check functionality and consistency of LeaseManager. - */ -public class TestLeaseManager { - - @Rule - public ExpectedException exception = ExpectedException.none(); - - /** - * Dummy resource on which leases can be acquired. - */ - private final class DummyResource { - - private final String name; - - private DummyResource(String name) { - this.name = name; - } - - @Override - public int hashCode() { - return name.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if(obj instanceof DummyResource) { - return name.equals(((DummyResource) obj).name); - } - return false; - } - } - - @Test - public void testLeaseAcquireAndRelease() throws LeaseException { - //It is assumed that the test case execution won't take more than 5 seconds, - //if it takes more time increase the defaultTimeout value of LeaseManager. - LeaseManager manager = new LeaseManager<>("Test", 5000); - manager.start(); - DummyResource resourceOne = new DummyResource("one"); - DummyResource resourceTwo = new DummyResource("two"); - DummyResource resourceThree = new DummyResource("three"); - Lease leaseOne = manager.acquire(resourceOne); - Lease leaseTwo = manager.acquire(resourceTwo); - Lease leaseThree = manager.acquire(resourceThree); - Assert.assertEquals(leaseOne, manager.get(resourceOne)); - Assert.assertEquals(leaseTwo, manager.get(resourceTwo)); - Assert.assertEquals(leaseThree, manager.get(resourceThree)); - Assert.assertFalse(leaseOne.hasExpired()); - Assert.assertFalse(leaseTwo.hasExpired()); - Assert.assertFalse(leaseThree.hasExpired()); - //The below releases should not throw LeaseNotFoundException. - manager.release(resourceOne); - manager.release(resourceTwo); - manager.release(resourceThree); - Assert.assertTrue(leaseOne.hasExpired()); - Assert.assertTrue(leaseTwo.hasExpired()); - Assert.assertTrue(leaseThree.hasExpired()); - manager.shutdown(); - } - - @Test - public void testLeaseAlreadyExist() throws LeaseException { - LeaseManager manager = new LeaseManager<>("Test", 5000); - manager.start(); - DummyResource resourceOne = new DummyResource("one"); - DummyResource resourceTwo = new DummyResource("two"); - Lease leaseOne = manager.acquire(resourceOne); - Lease leaseTwo = manager.acquire(resourceTwo); - Assert.assertEquals(leaseOne, manager.get(resourceOne)); - Assert.assertEquals(leaseTwo, manager.get(resourceTwo)); - - exception.expect(LeaseAlreadyExistException.class); - exception.expectMessage("Resource: " + resourceOne); - manager.acquire(resourceOne); - - manager.release(resourceOne); - manager.release(resourceTwo); - manager.shutdown(); - } - - @Test - public void testLeaseNotFound() throws LeaseException, InterruptedException { - LeaseManager manager = new LeaseManager<>("Test", 5000); - manager.start(); - DummyResource resourceOne = new DummyResource("one"); - DummyResource resourceTwo = new DummyResource("two"); - DummyResource resourceThree = new DummyResource("three"); - - //Case 1: lease was never acquired. - exception.expect(LeaseNotFoundException.class); - exception.expectMessage("Resource: " + resourceOne); - manager.get(resourceOne); - - //Case 2: lease is acquired and released. - Lease leaseTwo = manager.acquire(resourceTwo); - Assert.assertEquals(leaseTwo, manager.get(resourceTwo)); - Assert.assertFalse(leaseTwo.hasExpired()); - manager.release(resourceTwo); - Assert.assertTrue(leaseTwo.hasExpired()); - exception.expect(LeaseNotFoundException.class); - exception.expectMessage("Resource: " + resourceTwo); - manager.get(resourceTwo); - - //Case 3: lease acquired and timed out. - Lease leaseThree = manager.acquire(resourceThree); - Assert.assertEquals(leaseThree, manager.get(resourceThree)); - Assert.assertFalse(leaseThree.hasExpired()); - long sleepTime = leaseThree.getRemainingTime() + 1000; - try { - Thread.sleep(sleepTime); - } catch (InterruptedException ex) { - //even in case of interrupt we have to wait till lease times out. - Thread.sleep(sleepTime); - } - Assert.assertTrue(leaseThree.hasExpired()); - exception.expect(LeaseNotFoundException.class); - exception.expectMessage("Resource: " + resourceThree); - manager.get(resourceThree); - manager.shutdown(); - } - - @Test - public void testCustomLeaseTimeout() throws LeaseException { - LeaseManager manager = new LeaseManager<>("Test", 5000); - manager.start(); - DummyResource resourceOne = new DummyResource("one"); - DummyResource resourceTwo = new DummyResource("two"); - DummyResource resourceThree = new DummyResource("three"); - Lease leaseOne = manager.acquire(resourceOne); - Lease leaseTwo = manager.acquire(resourceTwo, 10000); - Lease leaseThree = manager.acquire(resourceThree, 50000); - Assert.assertEquals(leaseOne, manager.get(resourceOne)); - Assert.assertEquals(leaseTwo, manager.get(resourceTwo)); - Assert.assertEquals(leaseThree, manager.get(resourceThree)); - Assert.assertFalse(leaseOne.hasExpired()); - Assert.assertFalse(leaseTwo.hasExpired()); - Assert.assertFalse(leaseThree.hasExpired()); - Assert.assertEquals(5000, leaseOne.getLeaseLifeTime()); - Assert.assertEquals(10000, leaseTwo.getLeaseLifeTime()); - Assert.assertEquals(50000, leaseThree.getLeaseLifeTime()); - // Releasing of leases is done in shutdown, so don't have to worry about - // lease release - manager.shutdown(); - } - - @Test - public void testLeaseCallback() throws LeaseException, InterruptedException { - Map leaseStatus = new HashMap<>(); - LeaseManager manager = new LeaseManager<>("Test", 5000); - manager.start(); - DummyResource resourceOne = new DummyResource("one"); - Lease leaseOne = manager.acquire(resourceOne); - leaseStatus.put(resourceOne, "lease in use"); - leaseOne.registerCallBack(() -> { - leaseStatus.put(resourceOne, "lease expired"); - return null; - }); - // wait for lease to expire - long sleepTime = leaseOne.getRemainingTime() + 1000; - try { - Thread.sleep(sleepTime); - } catch (InterruptedException ex) { - //even in case of interrupt we have to wait till lease times out. - Thread.sleep(sleepTime); - } - Assert.assertTrue(leaseOne.hasExpired()); - exception.expect(LeaseNotFoundException.class); - exception.expectMessage("Resource: " + resourceOne); - manager.get(resourceOne); - // check if callback has been executed - Assert.assertEquals("lease expired", leaseStatus.get(resourceOne)); - } - - @Test - public void testCallbackExecutionInCaseOfLeaseRelease() - throws LeaseException, InterruptedException { - // Callbacks should not be executed in case of lease release - Map leaseStatus = new HashMap<>(); - LeaseManager manager = new LeaseManager<>("Test", 5000); - manager.start(); - DummyResource resourceOne = new DummyResource("one"); - Lease leaseOne = manager.acquire(resourceOne); - leaseStatus.put(resourceOne, "lease in use"); - leaseOne.registerCallBack(() -> { - leaseStatus.put(resourceOne, "lease expired"); - return null; - }); - leaseStatus.put(resourceOne, "lease released"); - manager.release(resourceOne); - Assert.assertTrue(leaseOne.hasExpired()); - exception.expect(LeaseNotFoundException.class); - exception.expectMessage("Resource: " + resourceOne); - manager.get(resourceOne); - Assert.assertEquals("lease released", leaseStatus.get(resourceOne)); - } - - @Test - public void testLeaseCallbackWithMultipleLeases() - throws LeaseException, InterruptedException { - Map leaseStatus = new HashMap<>(); - LeaseManager manager = new LeaseManager<>("Test", 5000); - manager.start(); - DummyResource resourceOne = new DummyResource("one"); - DummyResource resourceTwo = new DummyResource("two"); - DummyResource resourceThree = new DummyResource("three"); - DummyResource resourceFour = new DummyResource("four"); - DummyResource resourceFive = new DummyResource("five"); - Lease leaseOne = manager.acquire(resourceOne); - Lease leaseTwo = manager.acquire(resourceTwo); - Lease leaseThree = manager.acquire(resourceThree); - Lease leaseFour = manager.acquire(resourceFour); - Lease leaseFive = manager.acquire(resourceFive); - leaseStatus.put(resourceOne, "lease in use"); - leaseStatus.put(resourceTwo, "lease in use"); - leaseStatus.put(resourceThree, "lease in use"); - leaseStatus.put(resourceFour, "lease in use"); - leaseStatus.put(resourceFive, "lease in use"); - leaseOne.registerCallBack(() -> { - leaseStatus.put(resourceOne, "lease expired"); - return null; - }); - leaseTwo.registerCallBack(() -> { - leaseStatus.put(resourceTwo, "lease expired"); - return null; - }); - leaseThree.registerCallBack(() -> { - leaseStatus.put(resourceThree, "lease expired"); - return null; - }); - leaseFour.registerCallBack(() -> { - leaseStatus.put(resourceFour, "lease expired"); - return null; - }); - leaseFive.registerCallBack(() -> { - leaseStatus.put(resourceFive, "lease expired"); - return null; - }); - - // release lease one, two and three - leaseStatus.put(resourceOne, "lease released"); - manager.release(resourceOne); - leaseStatus.put(resourceTwo, "lease released"); - manager.release(resourceTwo); - leaseStatus.put(resourceThree, "lease released"); - manager.release(resourceThree); - - // wait for other leases to expire - long sleepTime = leaseFive.getRemainingTime() + 1000; - - try { - Thread.sleep(sleepTime); - } catch (InterruptedException ex) { - //even in case of interrupt we have to wait till lease times out. - Thread.sleep(sleepTime); - } - Assert.assertTrue(leaseOne.hasExpired()); - Assert.assertTrue(leaseTwo.hasExpired()); - Assert.assertTrue(leaseThree.hasExpired()); - Assert.assertTrue(leaseFour.hasExpired()); - Assert.assertTrue(leaseFive.hasExpired()); - - Assert.assertEquals("lease released", leaseStatus.get(resourceOne)); - Assert.assertEquals("lease released", leaseStatus.get(resourceTwo)); - Assert.assertEquals("lease released", leaseStatus.get(resourceThree)); - Assert.assertEquals("lease expired", leaseStatus.get(resourceFour)); - Assert.assertEquals("lease expired", leaseStatus.get(resourceFive)); - manager.shutdown(); - } - - @Test - public void testReuseReleasedLease() throws LeaseException { - LeaseManager manager = new LeaseManager<>("Test", 5000); - manager.start(); - DummyResource resourceOne = new DummyResource("one"); - Lease leaseOne = manager.acquire(resourceOne); - Assert.assertEquals(leaseOne, manager.get(resourceOne)); - Assert.assertFalse(leaseOne.hasExpired()); - - manager.release(resourceOne); - Assert.assertTrue(leaseOne.hasExpired()); - - Lease sameResourceLease = manager.acquire(resourceOne); - Assert.assertEquals(sameResourceLease, manager.get(resourceOne)); - Assert.assertFalse(sameResourceLease.hasExpired()); - - manager.release(resourceOne); - Assert.assertTrue(sameResourceLease.hasExpired()); - manager.shutdown(); - } - - @Test - public void testReuseTimedOutLease() - throws LeaseException, InterruptedException { - LeaseManager manager = new LeaseManager<>("Test", 5000); - manager.start(); - DummyResource resourceOne = new DummyResource("one"); - Lease leaseOne = manager.acquire(resourceOne); - Assert.assertEquals(leaseOne, manager.get(resourceOne)); - Assert.assertFalse(leaseOne.hasExpired()); - // wait for lease to expire - long sleepTime = leaseOne.getRemainingTime() + 1000; - try { - Thread.sleep(sleepTime); - } catch (InterruptedException ex) { - //even in case of interrupt we have to wait till lease times out. - Thread.sleep(sleepTime); - } - Assert.assertTrue(leaseOne.hasExpired()); - - Lease sameResourceLease = manager.acquire(resourceOne); - Assert.assertEquals(sameResourceLease, manager.get(resourceOne)); - Assert.assertFalse(sameResourceLease.hasExpired()); - - manager.release(resourceOne); - Assert.assertTrue(sameResourceLease.hasExpired()); - manager.shutdown(); - } - - @Test - public void testRenewLease() throws LeaseException, InterruptedException { - LeaseManager manager = new LeaseManager<>("Test", 5000); - manager.start(); - DummyResource resourceOne = new DummyResource("one"); - Lease leaseOne = manager.acquire(resourceOne); - Assert.assertEquals(leaseOne, manager.get(resourceOne)); - Assert.assertFalse(leaseOne.hasExpired()); - - // add 5 more seconds to the lease - leaseOne.renew(5000); - - Thread.sleep(5000); - - // lease should still be active - Assert.assertEquals(leaseOne, manager.get(resourceOne)); - Assert.assertFalse(leaseOne.hasExpired()); - manager.release(resourceOne); - manager.shutdown(); - } - -} diff --git a/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/lease/package-info.java b/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/lease/package-info.java deleted file mode 100644 index 1071309c730..00000000000 --- a/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/lease/package-info.java +++ /dev/null @@ -1,21 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.lease; -/* - This package contains lease management unit test classes. - */ \ No newline at end of file diff --git a/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/lock/TestLockManager.java b/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/lock/TestLockManager.java deleted file mode 100644 index fa3030d0c35..00000000000 --- a/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/lock/TestLockManager.java +++ /dev/null @@ -1,64 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.lock; - -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.junit.Assert; -import org.junit.Test; - -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * Test-cases to test LockManager. - */ -public class TestLockManager { - - @Test(timeout = 1000) - public void testWithDifferentResource() { - LockManager manager = new LockManager<>(new OzoneConfiguration()); - manager.lock("/resourceOne"); - // This should work, as they are different resource. - manager.lock("/resourceTwo"); - manager.unlock("/resourceOne"); - manager.unlock("/resourceTwo"); - Assert.assertTrue(true); - } - - @Test - public void testWithSameResource() throws Exception { - LockManager manager = new LockManager<>(new OzoneConfiguration()); - manager.lock("/resourceOne"); - AtomicBoolean gotLock = new AtomicBoolean(false); - new Thread(() -> { - manager.lock("/resourceOne"); - gotLock.set(true); - manager.unlock("/resourceOne"); - }).start(); - // Let's give some time for the new thread to run - Thread.sleep(100); - // Since the new thread is trying to get lock on same object, it will wait. - Assert.assertFalse(gotLock.get()); - manager.unlock("/resourceOne"); - // Since we have released the lock, the new thread should have the lock - // now - // Let's give some time for the new thread to run - Thread.sleep(100); - Assert.assertTrue(gotLock.get()); - } - -} \ No newline at end of file diff --git a/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/lock/package-info.java b/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/lock/package-info.java deleted file mode 100644 index a96bc16248c..00000000000 --- a/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/lock/package-info.java +++ /dev/null @@ -1,21 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.lock; -/* - This package contains the lock related test classes. - */ \ No newline at end of file diff --git a/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/package-info.java b/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/package-info.java deleted file mode 100644 index 0030d2e9e1c..00000000000 --- a/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/package-info.java +++ /dev/null @@ -1,21 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone; -/** - * Ozone related test helper classes and tests of common utils. - */ diff --git a/hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/TestHddsIdFactory.java b/hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/TestHddsIdFactory.java deleted file mode 100644 index a341ccc223a..00000000000 --- a/hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/TestHddsIdFactory.java +++ /dev/null @@ -1,77 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.utils; - -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.concurrent.Callable; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import org.apache.hadoop.hdds.HddsIdFactory; -import org.junit.After; -import static org.junit.Assert.assertEquals; - -import org.junit.Assert; -import org.junit.Test; - -/** - * Test the JMX interface for the rocksdb metastore implementation. - */ -public class TestHddsIdFactory { - - private static final Set ID_SET = ConcurrentHashMap.newKeySet(); - private static final int IDS_PER_THREAD = 10000; - private static final int NUM_OF_THREADS = 5; - - @After - public void cleanup() { - ID_SET.clear(); - } - - @Test - public void testGetLongId() throws Exception { - - ExecutorService executor = Executors.newFixedThreadPool(5); - List> tasks = new ArrayList<>(5); - addTasks(tasks); - List> result = executor.invokeAll(tasks); - assertEquals(IDS_PER_THREAD * NUM_OF_THREADS, ID_SET.size()); - for (Future r : result) { - assertEquals(r.get().intValue(), IDS_PER_THREAD); - } - } - - private void addTasks(List> tasks) { - for (int i = 0; i < NUM_OF_THREADS; i++) { - Callable task = () -> { - for (int idNum = 0; idNum < IDS_PER_THREAD; idNum++) { - long var = HddsIdFactory.getLongId(); - if (ID_SET.contains(var)) { - Assert.fail("Duplicate id found"); - } - ID_SET.add(var); - } - return IDS_PER_THREAD; - }; - tasks.add(task); - } - } -} \ No newline at end of file diff --git a/hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/TestMetadataStore.java b/hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/TestMetadataStore.java deleted file mode 100644 index 30fc7f313a0..00000000000 --- a/hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/TestMetadataStore.java +++ /dev/null @@ -1,590 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.utils; - -import static org.apache.hadoop.test.PlatformAssumptions.assumeNotWindows; - -import com.google.common.collect.Lists; -import org.apache.commons.io.FileUtils; -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdfs.DFSUtil; -import org.apache.hadoop.hdfs.DFSUtilClient; -import org.apache.hadoop.ozone.OzoneConfigKeys; -import org.apache.hadoop.test.GenericTestUtils; -import org.apache.hadoop.utils.MetadataStore.KeyValue; -import org.apache.hadoop.utils.MetadataKeyFilters.KeyPrefixFilter; -import org.apache.hadoop.utils.MetadataKeyFilters.MetadataKeyFilter; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.slf4j.event.Level; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.UUID; - -import java.util.concurrent.atomic.AtomicInteger; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import static org.junit.runners.Parameterized.Parameters; - -/** - * Test class for ozone metadata store. - */ -@RunWith(Parameterized.class) -public class TestMetadataStore { - - private final String storeImpl; - - public TestMetadataStore(String metadataImpl) { - this.storeImpl = metadataImpl; - } - - @Parameters - public static Collection data() { - return Arrays.asList(new Object[][] { - {OzoneConfigKeys.OZONE_METADATA_STORE_IMPL_LEVELDB}, - {OzoneConfigKeys.OZONE_METADATA_STORE_IMPL_ROCKSDB} - }); - } - - private MetadataStore store; - private File testDir; - private final static int MAX_GETRANGE_LENGTH = 100; - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Before - public void init() throws IOException { - if (OzoneConfigKeys.OZONE_METADATA_STORE_IMPL_ROCKSDB.equals(storeImpl)) { - // The initialization of RocksDB fails on Windows - assumeNotWindows(); - } - - testDir = GenericTestUtils.getTestDir(getClass().getSimpleName() - + "-" + storeImpl.toLowerCase()); - - Configuration conf = new OzoneConfiguration(); - conf.set(OzoneConfigKeys.OZONE_METADATA_STORE_IMPL, storeImpl); - - store = MetadataStoreBuilder.newBuilder() - .setConf(conf) - .setCreateIfMissing(true) - .setDbFile(testDir) - .build(); - - // Add 20 entries. - // {a0 : a-value0} to {a9 : a-value9} - // {b0 : b-value0} to {b9 : b-value9} - for (int i=0; i<10; i++) { - store.put(getBytes("a" + i), getBytes("a-value" + i)); - store.put(getBytes("b" + i), getBytes("b-value" + i)); - } - } - - @Test - public void testIterator() throws Exception { - Configuration conf = new OzoneConfiguration(); - conf.set(OzoneConfigKeys.OZONE_METADATA_STORE_IMPL, storeImpl); - File dbDir = GenericTestUtils.getRandomizedTestDir(); - MetadataStore dbStore = MetadataStoreBuilder.newBuilder() - .setConf(conf) - .setCreateIfMissing(true) - .setDbFile(dbDir) - .build(); - - //As database is empty, check whether iterator is working as expected or - // not. - MetaStoreIterator metaStoreIterator = dbStore.iterator(); - assertFalse(metaStoreIterator.hasNext()); - try { - metaStoreIterator.next(); - fail("testIterator failed"); - } catch (NoSuchElementException ex) { - GenericTestUtils.assertExceptionContains("Store has no more elements", - ex); - } - - for (int i = 0; i < 10; i++) { - store.put(getBytes("a" + i), getBytes("a-value" + i)); - } - - metaStoreIterator = dbStore.iterator(); - - int i = 0; - while (metaStoreIterator.hasNext()) { - KeyValue val = metaStoreIterator.next(); - assertEquals("a" + i, getString(val.getKey())); - assertEquals("a-value" + i, getString(val.getValue())); - i++; - } - - // As we have iterated all the keys in database, hasNext should return - // false and next() should throw NoSuchElement exception. - - assertFalse(metaStoreIterator.hasNext()); - try { - metaStoreIterator.next(); - fail("testIterator failed"); - } catch (NoSuchElementException ex) { - GenericTestUtils.assertExceptionContains("Store has no more elements", - ex); - } - FileUtils.deleteDirectory(dbDir); - - } - - @Test - public void testMetaStoreConfigDifferentFromType() throws IOException { - - Configuration conf = new OzoneConfiguration(); - conf.set(OzoneConfigKeys.OZONE_METADATA_STORE_IMPL, storeImpl); - String dbType; - GenericTestUtils.setLogLevel(MetadataStoreBuilder.LOG, Level.DEBUG); - GenericTestUtils.LogCapturer logCapturer = - GenericTestUtils.LogCapturer.captureLogs(MetadataStoreBuilder.LOG); - if(storeImpl.equals(OzoneConfigKeys.OZONE_METADATA_STORE_IMPL_LEVELDB)) { - dbType = "RocksDB"; - } else { - dbType = "LevelDB"; - } - - File dbDir = GenericTestUtils.getTestDir(getClass().getSimpleName() - + "-" + dbType.toLowerCase() + "-test"); - MetadataStore dbStore = MetadataStoreBuilder.newBuilder().setConf(conf) - .setCreateIfMissing(true).setDbFile(dbDir).setDBType(dbType).build(); - assertTrue(logCapturer.getOutput().contains("Using dbType " + dbType + "" + - " for metastore")); - dbStore.close(); - dbStore.destroy(); - FileUtils.deleteDirectory(dbDir); - - } - - @Test - public void testdbTypeNotSet() throws IOException { - - Configuration conf = new OzoneConfiguration(); - conf.set(OzoneConfigKeys.OZONE_METADATA_STORE_IMPL, storeImpl); - GenericTestUtils.setLogLevel(MetadataStoreBuilder.LOG, Level.DEBUG); - GenericTestUtils.LogCapturer logCapturer = - GenericTestUtils.LogCapturer.captureLogs(MetadataStoreBuilder.LOG); - - - File dbDir = GenericTestUtils.getTestDir(getClass().getSimpleName() - + "-" + storeImpl.toLowerCase() + "-test"); - MetadataStore dbStore = MetadataStoreBuilder.newBuilder().setConf(conf) - .setCreateIfMissing(true).setDbFile(dbDir).build(); - assertTrue(logCapturer.getOutput().contains("dbType is null, using dbType" + - " " + storeImpl)); - dbStore.close(); - dbStore.destroy(); - FileUtils.deleteDirectory(dbDir); - - } - - @After - public void cleanup() throws IOException { - if (store != null) { - store.close(); - store.destroy(); - } - if (testDir != null) { - FileUtils.deleteDirectory(testDir); - } - } - - private byte[] getBytes(String str) { - return str == null ? null : - DFSUtilClient.string2Bytes(str); - } - - private String getString(byte[] bytes) { - return bytes == null ? null : - DFSUtilClient.bytes2String(bytes); - } - - @Test - public void testGetDelete() throws IOException { - for (int i=0; i<10; i++) { - byte[] va = store.get(getBytes("a" + i)); - assertEquals("a-value" + i, getString(va)); - - byte[] vb = store.get(getBytes("b" + i)); - assertEquals("b-value" + i, getString(vb)); - } - - String keyToDel = "del-" + UUID.randomUUID().toString(); - store.put(getBytes(keyToDel), getBytes(keyToDel)); - assertEquals(keyToDel, getString(store.get(getBytes(keyToDel)))); - store.delete(getBytes(keyToDel)); - assertEquals(null, store.get(getBytes(keyToDel))); - } - - @Test - public void testPeekFrom() throws IOException { - // Test peek from an element that has prev as well as next - testPeek("a3", "a2", "a4"); - - // Test peek from an element that only has prev - testPeek("b9", "b8", null); - - // Test peek from an element that only has next - testPeek("a0", null, "a1"); - } - - private String getExpectedValue(String key) { - if (key == null) { - return null; - } - char[] arr = key.toCharArray(); - return new StringBuffer().append(arr[0]).append("-value") - .append(arr[arr.length - 1]).toString(); - } - - private void testPeek(String peekKey, String prevKey, String nextKey) - throws IOException { - // Look for current - String k = null; - String v = null; - ImmutablePair current = - store.peekAround(0, getBytes(peekKey)); - if (current != null) { - k = getString(current.getKey()); - v = getString(current.getValue()); - } - assertEquals(peekKey, k); - assertEquals(v, getExpectedValue(peekKey)); - - // Look for prev - k = null; - v = null; - ImmutablePair prev = - store.peekAround(-1, getBytes(peekKey)); - if (prev != null) { - k = getString(prev.getKey()); - v = getString(prev.getValue()); - } - assertEquals(prevKey, k); - assertEquals(v, getExpectedValue(prevKey)); - - // Look for next - k = null; - v = null; - ImmutablePair next = - store.peekAround(1, getBytes(peekKey)); - if (next != null) { - k = getString(next.getKey()); - v = getString(next.getValue()); - } - assertEquals(nextKey, k); - assertEquals(v, getExpectedValue(nextKey)); - } - - @Test - public void testIterateKeys() throws IOException { - // iterate keys from b0 - ArrayList result = Lists.newArrayList(); - store.iterate(getBytes("b0"), (k, v) -> { - // b-value{i} - String value = getString(v); - char num = value.charAt(value.length() - 1); - // each value adds 1 - int i = Character.getNumericValue(num) + 1; - value = value.substring(0, value.length() - 1) + i; - result.add(value); - return true; - }); - - assertFalse(result.isEmpty()); - for (int i=0; i { - result.add(getString(v)); - return true; - }); - assertTrue(result.isEmpty()); - - // iterate from the beginning - result.clear(); - store.iterate(null, (k, v) -> { - result.add(getString(v)); - return true; - }); - assertEquals(20, result.size()); - } - - @Test - public void testGetRangeKVs() throws IOException { - List> result = null; - - // Set empty startKey will return values from beginning. - result = store.getRangeKVs(null, 5); - assertEquals(5, result.size()); - assertEquals("a-value2", getString(result.get(2).getValue())); - - // Empty list if startKey doesn't exist. - result = store.getRangeKVs(getBytes("a12"), 5); - assertEquals(0, result.size()); - - // Returns max available entries after a valid startKey. - result = store.getRangeKVs(getBytes("b0"), MAX_GETRANGE_LENGTH); - assertEquals(10, result.size()); - assertEquals("b0", getString(result.get(0).getKey())); - assertEquals("b-value0", getString(result.get(0).getValue())); - result = store.getRangeKVs(getBytes("b0"), 5); - assertEquals(5, result.size()); - - // Both startKey and count are honored. - result = store.getRangeKVs(getBytes("a9"), 2); - assertEquals(2, result.size()); - assertEquals("a9", getString(result.get(0).getKey())); - assertEquals("a-value9", getString(result.get(0).getValue())); - assertEquals("b0", getString(result.get(1).getKey())); - assertEquals("b-value0", getString(result.get(1).getValue())); - - // Filter keys by prefix. - // It should returns all "b*" entries. - MetadataKeyFilter filter1 = new KeyPrefixFilter().addFilter("b"); - result = store.getRangeKVs(null, 100, filter1); - assertEquals(10, result.size()); - assertTrue(result.stream().allMatch(entry -> - new String(entry.getKey()).startsWith("b") - )); - assertEquals(20, filter1.getKeysScannedNum()); - assertEquals(10, filter1.getKeysHintedNum()); - result = store.getRangeKVs(null, 3, filter1); - assertEquals(3, result.size()); - result = store.getRangeKVs(getBytes("b3"), 1, filter1); - assertEquals("b-value3", getString(result.get(0).getValue())); - - // Define a customized filter that filters keys by suffix. - // Returns all "*2" entries. - MetadataKeyFilter filter2 = (preKey, currentKey, nextKey) - -> getString(currentKey).endsWith("2"); - result = store.getRangeKVs(null, MAX_GETRANGE_LENGTH, filter2); - assertEquals(2, result.size()); - assertEquals("a2", getString(result.get(0).getKey())); - assertEquals("b2", getString(result.get(1).getKey())); - result = store.getRangeKVs(null, 1, filter2); - assertEquals(1, result.size()); - assertEquals("a2", getString(result.get(0).getKey())); - - // Apply multiple filters. - result = store.getRangeKVs(null, MAX_GETRANGE_LENGTH, filter1, filter2); - assertEquals(1, result.size()); - assertEquals("b2", getString(result.get(0).getKey())); - assertEquals("b-value2", getString(result.get(0).getValue())); - - // If filter is null, no effect. - result = store.getRangeKVs(null, 1, null); - assertEquals(1, result.size()); - assertEquals("a0", getString(result.get(0).getKey())); - } - - @Test - public void testGetSequentialRangeKVs() throws IOException { - MetadataKeyFilter suffixFilter = (preKey, currentKey, nextKey) - -> DFSUtil.bytes2String(currentKey).endsWith("2"); - // Suppose to return a2 and b2 - List> result = - store.getRangeKVs(null, MAX_GETRANGE_LENGTH, suffixFilter); - assertEquals(2, result.size()); - assertEquals("a2", DFSUtil.bytes2String(result.get(0).getKey())); - assertEquals("b2", DFSUtil.bytes2String(result.get(1).getKey())); - - // Suppose to return just a2, because when it iterates to a3, - // the filter no long matches and it should stop from there. - result = store.getSequentialRangeKVs(null, - MAX_GETRANGE_LENGTH, suffixFilter); - assertEquals(1, result.size()); - assertEquals("a2", DFSUtil.bytes2String(result.get(0).getKey())); - } - - @Test - public void testGetRangeLength() throws IOException { - List> result = null; - - result = store.getRangeKVs(null, 0); - assertEquals(0, result.size()); - - result = store.getRangeKVs(null, 1); - assertEquals(1, result.size()); - - // Count less than zero is invalid. - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("Invalid count given"); - store.getRangeKVs(null, -1); - } - - @Test - public void testInvalidStartKey() throws IOException { - // If startKey is invalid, the returned list should be empty. - List> kvs = - store.getRangeKVs(getBytes("unknownKey"), MAX_GETRANGE_LENGTH); - assertEquals(kvs.size(), 0); - } - - @Test - public void testDestroyDB() throws IOException { - // create a new DB to test db destroy - Configuration conf = new OzoneConfiguration(); - conf.set(OzoneConfigKeys.OZONE_METADATA_STORE_IMPL, storeImpl); - - File dbDir = GenericTestUtils.getTestDir(getClass().getSimpleName() - + "-" + storeImpl.toLowerCase() + "-toDestroy"); - MetadataStore dbStore = MetadataStoreBuilder.newBuilder() - .setConf(conf) - .setCreateIfMissing(true) - .setDbFile(dbDir) - .build(); - - dbStore.put(getBytes("key1"), getBytes("value1")); - dbStore.put(getBytes("key2"), getBytes("value2")); - - assertFalse(dbStore.isEmpty()); - assertTrue(dbDir.exists()); - assertTrue(dbDir.listFiles().length > 0); - - dbStore.destroy(); - - assertFalse(dbDir.exists()); - } - - @Test - public void testBatchWrite() throws IOException { - Configuration conf = new OzoneConfiguration(); - conf.set(OzoneConfigKeys.OZONE_METADATA_STORE_IMPL, storeImpl); - - File dbDir = GenericTestUtils.getTestDir(getClass().getSimpleName() - + "-" + storeImpl.toLowerCase() + "-batchWrite"); - MetadataStore dbStore = MetadataStoreBuilder.newBuilder() - .setConf(conf) - .setCreateIfMissing(true) - .setDbFile(dbDir) - .build(); - - List expectedResult = Lists.newArrayList(); - for (int i = 0; i<10; i++) { - dbStore.put(getBytes("batch-" + i), getBytes("batch-value-" + i)); - expectedResult.add("batch-" + i); - } - - BatchOperation batch = new BatchOperation(); - batch.delete(getBytes("batch-2")); - batch.delete(getBytes("batch-3")); - batch.delete(getBytes("batch-4")); - batch.put(getBytes("batch-new-2"), getBytes("batch-new-value-2")); - - expectedResult.remove("batch-2"); - expectedResult.remove("batch-3"); - expectedResult.remove("batch-4"); - expectedResult.add("batch-new-2"); - - dbStore.writeBatch(batch); - - Iterator it = expectedResult.iterator(); - AtomicInteger count = new AtomicInteger(0); - dbStore.iterate(null, (key, value) -> { - count.incrementAndGet(); - return it.hasNext() && it.next().equals(getString(key)); - }); - - assertEquals(8, count.get()); - } - - @Test - public void testKeyPrefixFilter() throws IOException { - List> result = null; - RuntimeException exception = null; - - try { - new KeyPrefixFilter().addFilter("b0", true).addFilter("b"); - } catch (IllegalArgumentException e) { - exception = e; - } - assertTrue(exception.getMessage().contains("KeyPrefix: b already " + - "rejected")); - - try { - new KeyPrefixFilter().addFilter("b0").addFilter("b", true); - } catch (IllegalArgumentException e) { - exception = e; - } - assertTrue(exception.getMessage().contains("KeyPrefix: b already " + - "accepted")); - - try { - new KeyPrefixFilter().addFilter("b", true).addFilter("b0"); - } catch (IllegalArgumentException e) { - exception = e; - } - assertTrue(exception.getMessage().contains("KeyPrefix: b0 already " + - "rejected")); - - try { - new KeyPrefixFilter().addFilter("b").addFilter("b0", true); - } catch (IllegalArgumentException e) { - exception = e; - } - assertTrue(exception.getMessage().contains("KeyPrefix: b0 already " + - "accepted")); - - MetadataKeyFilter filter1 = new KeyPrefixFilter(true) - .addFilter("a0") - .addFilter("a1") - .addFilter("b", true); - result = store.getRangeKVs(null, 100, filter1); - assertEquals(2, result.size()); - assertTrue(result.stream().anyMatch(entry -> new String(entry.getKey()) - .startsWith("a0")) && result.stream().anyMatch(entry -> new String( - entry.getKey()).startsWith("a1"))); - - filter1 = new KeyPrefixFilter(true).addFilter("b", true); - result = store.getRangeKVs(null, 100, filter1); - assertEquals(0, result.size()); - - filter1 = new KeyPrefixFilter().addFilter("b", true); - result = store.getRangeKVs(null, 100, filter1); - assertEquals(10, result.size()); - assertTrue(result.stream().allMatch(entry -> new String(entry.getKey()) - .startsWith("a"))); - } -} diff --git a/hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/TestRocksDBStoreMBean.java b/hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/TestRocksDBStoreMBean.java deleted file mode 100644 index a7ce60bbeb1..00000000000 --- a/hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/TestRocksDBStoreMBean.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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.utils; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.ozone.OzoneConfigKeys; -import org.apache.hadoop.test.GenericTestUtils; -import org.junit.Assert; -import org.junit.Test; - -import javax.management.MBeanServer; -import java.io.File; -import java.lang.management.ManagementFactory; - -/** - * Test the JMX interface for the rocksdb metastore implementation. - */ -public class TestRocksDBStoreMBean { - - @Test - public void testJmxBeans() throws Exception { - File testDir = - GenericTestUtils.getTestDir(getClass().getSimpleName() + "-withstat"); - - Configuration conf = new OzoneConfiguration(); - conf.set(OzoneConfigKeys.OZONE_METADATA_STORE_IMPL, - OzoneConfigKeys.OZONE_METADATA_STORE_IMPL_ROCKSDB); - - RocksDBStore metadataStore = - (RocksDBStore) MetadataStoreBuilder.newBuilder().setConf(conf) - .setCreateIfMissing(true).setDbFile(testDir).build(); - - for (int i = 0; i < 10; i++) { - metadataStore.put("key".getBytes(), "value".getBytes()); - } - - MBeanServer platformMBeanServer = - ManagementFactory.getPlatformMBeanServer(); - Thread.sleep(2000); - - Object keysWritten = platformMBeanServer - .getAttribute(metadataStore.getStatMBeanName(), "NUMBER_KEYS_WRITTEN"); - - Assert.assertEquals(10L, keysWritten); - - Object dbWriteAverage = platformMBeanServer - .getAttribute(metadataStore.getStatMBeanName(), "DB_WRITE_AVERAGE"); - Assert.assertTrue((double) dbWriteAverage > 0); - - metadataStore.close(); - - } - - @Test() - public void testDisabledStat() throws Exception { - File testDir = GenericTestUtils - .getTestDir(getClass().getSimpleName() + "-withoutstat"); - - Configuration conf = new OzoneConfiguration(); - conf.set(OzoneConfigKeys.OZONE_METADATA_STORE_IMPL, - OzoneConfigKeys.OZONE_METADATA_STORE_IMPL_ROCKSDB); - conf.set(OzoneConfigKeys.OZONE_METADATA_STORE_ROCKSDB_STATISTICS, - OzoneConfigKeys.OZONE_METADATA_STORE_ROCKSDB_STATISTICS_OFF); - - RocksDBStore metadataStore = - (RocksDBStore) MetadataStoreBuilder.newBuilder().setConf(conf) - .setCreateIfMissing(true).setDbFile(testDir).build(); - - Assert.assertNull(metadataStore.getStatMBeanName()); - } -} \ No newline at end of file diff --git a/hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/db/TestDBConfigFromFile.java b/hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/db/TestDBConfigFromFile.java deleted file mode 100644 index b20ca70d33b..00000000000 --- a/hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/db/TestDBConfigFromFile.java +++ /dev/null @@ -1,116 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.hadoop.utils.db; - -import org.apache.commons.io.FileUtils; -import org.apache.hadoop.hdfs.DFSUtil; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.rocksdb.ColumnFamilyDescriptor; -import org.rocksdb.ColumnFamilyOptions; -import org.rocksdb.DBOptions; -import org.rocksdb.RocksDB; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import static org.apache.hadoop.utils.db.DBConfigFromFile.getOptionsFileNameFromDB; - -/** - * DBConf tests. - */ -public class TestDBConfigFromFile { - private final static String DB_FILE = "test.db"; - private final static String INI_FILE = getOptionsFileNameFromDB(DB_FILE); - @Rule - public TemporaryFolder folder = new TemporaryFolder(); - - @Before - public void setUp() throws Exception { - System.setProperty(DBConfigFromFile.CONFIG_DIR, - folder.newFolder().toString()); - ClassLoader classLoader = getClass().getClassLoader(); - File testData = new File(classLoader.getResource(INI_FILE).getFile()); - File dest = Paths.get( - System.getProperty(DBConfigFromFile.CONFIG_DIR), INI_FILE).toFile(); - FileUtils.copyFile(testData, dest); - } - - @After - public void tearDown() throws Exception { - } - - @Test - public void readFromFile() throws IOException { - final List families = - Arrays.asList(DFSUtil.bytes2String(RocksDB.DEFAULT_COLUMN_FAMILY), - "First", "Second", "Third", - "Fourth", "Fifth", - "Sixth"); - final List columnFamilyDescriptors = - new ArrayList<>(); - for (String family : families) { - columnFamilyDescriptors.add( - new ColumnFamilyDescriptor(family.getBytes(StandardCharsets.UTF_8), - new ColumnFamilyOptions())); - } - - final DBOptions options = DBConfigFromFile.readFromFile(DB_FILE, - columnFamilyDescriptors); - - // Some Random Values Defined in the test.db.ini, we verify that we are - // able to get values that are defined in the test.db.ini. - Assert.assertNotNull(options); - Assert.assertEquals(551615L, options.maxManifestFileSize()); - Assert.assertEquals(1000L, options.keepLogFileNum()); - Assert.assertEquals(1048576, options.writableFileMaxBufferSize()); - } - - @Test - public void readFromFileInvalidConfig() throws IOException { - final List families = - Arrays.asList(DFSUtil.bytes2String(RocksDB.DEFAULT_COLUMN_FAMILY), - "First", "Second", "Third", - "Fourth", "Fifth", - "Sixth"); - final List columnFamilyDescriptors = - new ArrayList<>(); - for (String family : families) { - columnFamilyDescriptors.add( - new ColumnFamilyDescriptor(family.getBytes(StandardCharsets.UTF_8), - new ColumnFamilyOptions())); - } - - final DBOptions options = DBConfigFromFile.readFromFile("badfile.db.ini", - columnFamilyDescriptors); - - // This has to return a Null, since we have config defined for badfile.db - Assert.assertNull(options); - } -} \ No newline at end of file diff --git a/hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/db/TestDBStoreBuilder.java b/hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/db/TestDBStoreBuilder.java deleted file mode 100644 index 3e1f364f090..00000000000 --- a/hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/db/TestDBStoreBuilder.java +++ /dev/null @@ -1,174 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.hadoop.utils.db; - -import org.apache.commons.lang3.RandomStringUtils; -import org.apache.hadoop.conf.Configuration; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; - -/** - * Tests RDBStore creation. - */ -public class TestDBStoreBuilder { - - @Rule - public TemporaryFolder folder = new TemporaryFolder(); - @Rule - public ExpectedException thrown = ExpectedException.none(); - - @Before - public void setUp() throws Exception { - System.setProperty(DBConfigFromFile.CONFIG_DIR, - folder.newFolder().toString()); - } - - @Test - public void builderWithoutAnyParams() throws IOException { - Configuration conf = new Configuration(); - thrown.expect(IOException.class); - DBStoreBuilder.newBuilder(conf).build(); - } - - @Test - public void builderWithOneParamV1() throws IOException { - Configuration conf = new Configuration(); - thrown.expect(IOException.class); - DBStoreBuilder.newBuilder(conf) - .setName("Test.db") - .build(); - } - - @Test - public void builderWithOneParamV2() throws IOException { - Configuration conf = new Configuration(); - File newFolder = folder.newFolder(); - if(!newFolder.exists()) { - Assert.assertTrue(newFolder.mkdirs()); - } - thrown.expect(IOException.class); - DBStoreBuilder.newBuilder(conf) - .setPath(newFolder.toPath()) - .build(); - } - - @Test - public void builderWithOpenClose() throws Exception { - Configuration conf = new Configuration(); - File newFolder = folder.newFolder(); - if(!newFolder.exists()) { - Assert.assertTrue(newFolder.mkdirs()); - } - DBStore dbStore = DBStoreBuilder.newBuilder(conf) - .setName("Test.db") - .setPath(newFolder.toPath()) - .build(); - // Nothing to do just open and Close. - dbStore.close(); - } - - @Test - public void builderWithDoubleTableName() throws Exception { - Configuration conf = new Configuration(); - File newFolder = folder.newFolder(); - if(!newFolder.exists()) { - Assert.assertTrue(newFolder.mkdirs()); - } - thrown.expect(IOException.class); - DBStoreBuilder.newBuilder(conf) - .setName("Test.db") - .setPath(newFolder.toPath()) - .addTable("FIRST") - .addTable("FIRST") - .build(); - // Nothing to do , This will throw so we do not have to close. - - } - - @Test - public void builderWithDataWrites() throws Exception { - Configuration conf = new Configuration(); - File newFolder = folder.newFolder(); - if(!newFolder.exists()) { - Assert.assertTrue(newFolder.mkdirs()); - } - try (DBStore dbStore = DBStoreBuilder.newBuilder(conf) - .setName("Test.db") - .setPath(newFolder.toPath()) - .addTable("First") - .addTable("Second") - .build()) { - try (Table firstTable = dbStore.getTable("First")) { - byte[] key = - RandomStringUtils.random(9).getBytes(StandardCharsets.UTF_8); - byte[] value = - RandomStringUtils.random(9).getBytes(StandardCharsets.UTF_8); - firstTable.put(key, value); - byte[] temp = firstTable.get(key); - Arrays.equals(value, temp); - } - - try (Table secondTable = dbStore.getTable("Second")) { - Assert.assertTrue(secondTable.isEmpty()); - } - } - } - - @Test - public void builderWithDiskProfileWrites() throws Exception { - Configuration conf = new Configuration(); - File newFolder = folder.newFolder(); - if(!newFolder.exists()) { - Assert.assertTrue(newFolder.mkdirs()); - } - try (DBStore dbStore = DBStoreBuilder.newBuilder(conf) - .setName("Test.db") - .setPath(newFolder.toPath()) - .addTable("First") - .addTable("Second") - .setProfile(DBProfile.DISK) - .build()) { - try (Table firstTable = dbStore.getTable("First")) { - byte[] key = - RandomStringUtils.random(9).getBytes(StandardCharsets.UTF_8); - byte[] value = - RandomStringUtils.random(9).getBytes(StandardCharsets.UTF_8); - firstTable.put(key, value); - byte[] temp = firstTable.get(key); - Arrays.equals(value, temp); - } - - try (Table secondTable = dbStore.getTable("Second")) { - Assert.assertTrue(secondTable.isEmpty()); - } - } - } - - -} \ No newline at end of file diff --git a/hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/db/TestRDBStore.java b/hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/db/TestRDBStore.java deleted file mode 100644 index 0b673d38d29..00000000000 --- a/hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/db/TestRDBStore.java +++ /dev/null @@ -1,255 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.hadoop.utils.db; - -import org.apache.commons.lang3.RandomStringUtils; -import org.apache.hadoop.hdfs.DFSUtil; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; -import org.rocksdb.ColumnFamilyOptions; -import org.rocksdb.DBOptions; -import org.rocksdb.RocksDB; -import org.rocksdb.Statistics; -import org.rocksdb.StatsLevel; - -import javax.management.MBeanServer; -import java.io.IOException; -import java.lang.management.ManagementFactory; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * RDBStore Tests. - */ -public class TestRDBStore { - private final List families = - Arrays.asList(DFSUtil.bytes2String(RocksDB.DEFAULT_COLUMN_FAMILY), - "First", "Second", "Third", - "Fourth", "Fifth", - "Sixth"); - @Rule - public TemporaryFolder folder = new TemporaryFolder(); - @Rule - public ExpectedException thrown = ExpectedException.none(); - private RDBStore rdbStore = null; - private DBOptions options = null; - private Set configSet; - - @Before - public void setUp() throws Exception { - options = new DBOptions(); - options.setCreateIfMissing(true); - options.setCreateMissingColumnFamilies(true); - - Statistics statistics = new Statistics(); - statistics.setStatsLevel(StatsLevel.ALL); - options = options.setStatistics(statistics); - configSet = new HashSet<>(); - for(String name : families) { - TableConfig newConfig = new TableConfig(name, new ColumnFamilyOptions()); - configSet.add(newConfig); - } - rdbStore = new RDBStore(folder.newFolder(), options, configSet); - } - - @After - public void tearDown() throws Exception { - if (rdbStore != null) { - rdbStore.close(); - } - } - - @Test - public void compactDB() throws Exception { - try (RDBStore newStore = - new RDBStore(folder.newFolder(), options, configSet)) { - Assert.assertNotNull("DB Store cannot be null", newStore); - try (Table firstTable = newStore.getTable(families.get(1))) { - Assert.assertNotNull("Table cannot be null", firstTable); - for (int x = 0; x < 100; x++) { - byte[] key = - RandomStringUtils.random(10).getBytes(StandardCharsets.UTF_8); - byte[] value = - RandomStringUtils.random(10).getBytes(StandardCharsets.UTF_8); - firstTable.put(key, value); - } - } - // This test does not assert anything if there is any error this test - // will throw and fail. - newStore.compactDB(); - } - } - - @Test - public void close() throws Exception { - RDBStore newStore = - new RDBStore(folder.newFolder(), options, configSet); - Assert.assertNotNull("DBStore cannot be null", newStore); - // This test does not assert anything if there is any error this test - // will throw and fail. - newStore.close(); - } - - @Test - public void moveKey() throws Exception { - byte[] key = - RandomStringUtils.random(10).getBytes(StandardCharsets.UTF_8); - byte[] value = - RandomStringUtils.random(10).getBytes(StandardCharsets.UTF_8); - - try (Table firstTable = rdbStore.getTable(families.get(1))) { - firstTable.put(key, value); - try (Table secondTable = rdbStore.getTable(families.get(2))) { - rdbStore.move(key, firstTable, secondTable); - byte[] newvalue = secondTable.get(key); - // Make sure we have value in the second table - Assert.assertNotNull(newvalue); - //and it is same as what we wrote to the FirstTable - Assert.assertArrayEquals(value, newvalue); - } - // After move this key must not exist in the first table. - Assert.assertNull(firstTable.get(key)); - } - } - - @Test - public void moveWithValue() throws Exception { - byte[] key = - RandomStringUtils.random(10).getBytes(StandardCharsets.UTF_8); - byte[] value = - RandomStringUtils.random(10).getBytes(StandardCharsets.UTF_8); - - byte[] nextValue = - RandomStringUtils.random(10).getBytes(StandardCharsets.UTF_8); - try (Table firstTable = rdbStore.getTable(families.get(1))) { - firstTable.put(key, value); - try (Table secondTable = rdbStore.getTable(families.get(2))) { - rdbStore.move(key, nextValue, firstTable, secondTable); - byte[] newvalue = secondTable.get(key); - // Make sure we have value in the second table - Assert.assertNotNull(newvalue); - //and it is not same as what we wrote to the FirstTable, and equals - // the new value. - Assert.assertArrayEquals(nextValue, nextValue); - } - } - - } - - @Test - public void getEstimatedKeyCount() throws Exception { - try (RDBStore newStore = - new RDBStore(folder.newFolder(), options, configSet)) { - Assert.assertNotNull("DB Store cannot be null", newStore); - // Write 100 keys to the first table. - try (Table firstTable = newStore.getTable(families.get(1))) { - Assert.assertNotNull("Table cannot be null", firstTable); - for (int x = 0; x < 100; x++) { - byte[] key = - RandomStringUtils.random(10).getBytes(StandardCharsets.UTF_8); - byte[] value = - RandomStringUtils.random(10).getBytes(StandardCharsets.UTF_8); - firstTable.put(key, value); - } - } - - // Write 100 keys to the secondTable table. - try (Table secondTable = newStore.getTable(families.get(2))) { - Assert.assertNotNull("Table cannot be null", secondTable); - for (int x = 0; x < 100; x++) { - byte[] key = - RandomStringUtils.random(10).getBytes(StandardCharsets.UTF_8); - byte[] value = - RandomStringUtils.random(10).getBytes(StandardCharsets.UTF_8); - secondTable.put(key, value); - } - } - // Let us make sure that our estimate is not off by 10% - Assert.assertTrue(newStore.getEstimatedKeyCount() > 180 - || newStore.getEstimatedKeyCount() < 220); - } - } - - @Test - public void getStatMBeanName() throws Exception { - - try (Table firstTable = rdbStore.getTable(families.get(1))) { - for (int y = 0; y < 100; y++) { - byte[] key = - RandomStringUtils.random(10).getBytes(StandardCharsets.UTF_8); - byte[] value = - RandomStringUtils.random(10).getBytes(StandardCharsets.UTF_8); - firstTable.put(key, value); - } - } - MBeanServer platformMBeanServer = - ManagementFactory.getPlatformMBeanServer(); - Thread.sleep(2000); - - Object keysWritten = platformMBeanServer - .getAttribute(rdbStore.getStatMBeanName(), "NUMBER_KEYS_WRITTEN"); - - Assert.assertTrue(((Long) keysWritten) >= 99L); - - Object dbWriteAverage = platformMBeanServer - .getAttribute(rdbStore.getStatMBeanName(), "DB_WRITE_AVERAGE"); - Assert.assertTrue((double) dbWriteAverage > 0); - } - - @Test - public void getTable() throws Exception { - for (String tableName : families) { - try (Table table = rdbStore.getTable(tableName)) { - Assert.assertNotNull(tableName + "is null", table); - } - } - thrown.expect(IOException.class); - rdbStore.getTable("ATableWithNoName"); - } - - @Test - public void listTables() throws Exception { - List

tableList = rdbStore.listTables(); - Assert.assertNotNull("Table list cannot be null", tableList); - Map hashTable = new HashMap<>(); - - for (Table t : tableList) { - hashTable.put(t.getName(), t); - } - - int count = families.size(); - // Assert that we have all the tables in the list and no more. - for (String name : families) { - Assert.assertTrue(hashTable.containsKey(name)); - count--; - } - Assert.assertEquals(0, count); - } -} \ No newline at end of file diff --git a/hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/db/TestRDBTableStore.java b/hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/db/TestRDBTableStore.java deleted file mode 100644 index cd25548403a..00000000000 --- a/hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/db/TestRDBTableStore.java +++ /dev/null @@ -1,198 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.hadoop.utils.db; - -import org.apache.commons.lang3.RandomStringUtils; -import org.apache.hadoop.hdfs.DFSUtil; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.rocksdb.ColumnFamilyOptions; -import org.rocksdb.DBOptions; -import org.rocksdb.RocksDB; -import org.rocksdb.Statistics; -import org.rocksdb.StatsLevel; -import org.rocksdb.WriteBatch; - -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; - -/** - * Tests for RocksDBTable Store. - */ -public class TestRDBTableStore { - private static int count = 0; - private final List families = - Arrays.asList(DFSUtil.bytes2String(RocksDB.DEFAULT_COLUMN_FAMILY), - "First", "Second", "Third", - "Fourth", "Fifth", - "Sixth"); - @Rule - public TemporaryFolder folder = new TemporaryFolder(); - private RDBStore rdbStore = null; - private DBOptions options = null; - - @Before - public void setUp() throws Exception { - options = new DBOptions(); - options.setCreateIfMissing(true); - options.setCreateMissingColumnFamilies(true); - - Statistics statistics = new Statistics(); - statistics.setStatsLevel(StatsLevel.ALL); - options = options.setStatistics(statistics); - - Set configSet = new HashSet<>(); - for(String name : families) { - TableConfig newConfig = new TableConfig(name, new ColumnFamilyOptions()); - configSet.add(newConfig); - } - rdbStore = new RDBStore(folder.newFolder(), options, configSet); - } - - @After - public void tearDown() throws Exception { - if (rdbStore != null) { - rdbStore.close(); - } - } - - @Test - public void toIOException() { - } - - @Test - public void getHandle() throws Exception { - try (Table testTable = rdbStore.getTable("First")) { - Assert.assertNotNull(testTable); - Assert.assertNotNull(testTable.getHandle()); - } - } - - @Test - public void putGetAndEmpty() throws Exception { - try (Table testTable = rdbStore.getTable("First")) { - byte[] key = - RandomStringUtils.random(10).getBytes(StandardCharsets.UTF_8); - byte[] value = - RandomStringUtils.random(10).getBytes(StandardCharsets.UTF_8); - testTable.put(key, value); - Assert.assertFalse(testTable.isEmpty()); - byte[] readValue = testTable.get(key); - Assert.assertArrayEquals(value, readValue); - } - try (Table secondTable = rdbStore.getTable("Second")) { - Assert.assertTrue(secondTable.isEmpty()); - } - } - - @Test - public void delete() throws Exception { - List deletedKeys = new LinkedList<>(); - List validKeys = new LinkedList<>(); - byte[] value = - RandomStringUtils.random(10).getBytes(StandardCharsets.UTF_8); - for (int x = 0; x < 100; x++) { - deletedKeys.add( - RandomStringUtils.random(10).getBytes(StandardCharsets.UTF_8)); - } - - for (int x = 0; x < 100; x++) { - validKeys.add( - RandomStringUtils.random(10).getBytes(StandardCharsets.UTF_8)); - } - - // Write all the keys and delete the keys scheduled for delete. - //Assert we find only expected keys in the Table. - try (Table testTable = rdbStore.getTable("Fourth")) { - for (int x = 0; x < deletedKeys.size(); x++) { - testTable.put(deletedKeys.get(x), value); - testTable.delete(deletedKeys.get(x)); - } - - for (int x = 0; x < validKeys.size(); x++) { - testTable.put(validKeys.get(x), value); - } - - for (int x = 0; x < validKeys.size(); x++) { - Assert.assertNotNull(testTable.get(validKeys.get(0))); - } - - for (int x = 0; x < deletedKeys.size(); x++) { - Assert.assertNull(testTable.get(deletedKeys.get(0))); - } - } - } - - @Test - public void writeBatch() throws Exception { - WriteBatch batch = new WriteBatch(); - try (Table testTable = rdbStore.getTable("Fifth")) { - byte[] key = - RandomStringUtils.random(10).getBytes(StandardCharsets.UTF_8); - byte[] value = - RandomStringUtils.random(10).getBytes(StandardCharsets.UTF_8); - batch.put(testTable.getHandle(), key, value); - testTable.writeBatch(batch); - Assert.assertNotNull(testTable.get(key)); - } - batch.close(); - } - - private static boolean consume(Table.KeyValue keyValue) { - count++; - Assert.assertNotNull(keyValue.getKey()); - return true; - } - - @Test - public void forEachAndIterator() throws Exception { - final int iterCount = 100; - try (Table testTable = rdbStore.getTable("Sixth")) { - for (int x = 0; x < iterCount; x++) { - byte[] key = - RandomStringUtils.random(10).getBytes(StandardCharsets.UTF_8); - byte[] value = - RandomStringUtils.random(10).getBytes(StandardCharsets.UTF_8); - testTable.put(key, value); - } - int localCount = 0; - try (TableIterator iter = testTable.iterator()) { - while (iter.hasNext()) { - Table.KeyValue keyValue = iter.next(); - localCount++; - } - - Assert.assertEquals(iterCount, localCount); - iter.seekToFirst(); - iter.forEachRemaining(TestRDBTableStore::consume); - Assert.assertEquals(iterCount, count); - - } - } - } -} \ No newline at end of file diff --git a/hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/db/package-info.java b/hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/db/package-info.java deleted file mode 100644 index f06855e038a..00000000000 --- a/hadoop-hdds/common/src/test/java/org/apache/hadoop/utils/db/package-info.java +++ /dev/null @@ -1,22 +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 - * - * 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. - * - */ -/** - * Tests for the DB Utilities. - */ -package org.apache.hadoop.utils.db; \ No newline at end of file diff --git a/hadoop-hdds/common/src/test/resources/log4j2.properties b/hadoop-hdds/common/src/test/resources/log4j2.properties deleted file mode 100644 index cef69e11b0e..00000000000 --- a/hadoop-hdds/common/src/test/resources/log4j2.properties +++ /dev/null @@ -1,76 +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 -#

-# 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. -# -name=PropertiesConfig - -# Checks for config change periodically and reloads -monitorInterval=5 - -filter=read, write -# filter.read.onMatch = DENY avoids logging all READ events -# filter.read.onMatch = ACCEPT permits logging all READ events -# The above two settings ignore the log levels in configuration -# filter.read.onMatch = NEUTRAL permits logging of only those READ events -# which are attempted at log level equal or greater than log level specified -# in the configuration -filter.read.type = MarkerFilter -filter.read.marker = READ -filter.read.onMatch = DENY -filter.read.onMismatch = NEUTRAL - -# filter.write.onMatch = DENY avoids logging all WRITE events -# filter.write.onMatch = ACCEPT permits logging all WRITE events -# The above two settings ignore the log levels in configuration -# filter.write.onMatch = NEUTRAL permits logging of only those WRITE events -# which are attempted at log level equal or greater than log level specified -# in the configuration -filter.write.type = MarkerFilter -filter.write.marker = WRITE -filter.write.onMatch = NEUTRAL -filter.write.onMismatch = NEUTRAL - -# Log Levels are organized from most specific to least: -# OFF (most specific, no logging) -# FATAL (most specific, little data) -# ERROR -# WARN -# INFO -# DEBUG -# TRACE (least specific, a lot of data) -# ALL (least specific, all data) - -appenders = console, audit -appender.console.type = Console -appender.console.name = STDOUT -appender.console.layout.type = PatternLayout -appender.console.layout.pattern = %-5level | %c{1} | %msg%n - -appender.audit.type = File -appender.audit.name = AUDITLOG -appender.audit.fileName=audit.log -appender.audit.layout.type=PatternLayout -appender.audit.layout.pattern= %-5level | %c{1} | %msg%n - -loggers=audit -logger.audit.type=AsyncLogger -logger.audit.name=OMAudit -logger.audit.level = INFO -logger.audit.appenderRefs = audit -logger.audit.appenderRef.file.ref = AUDITLOG - -rootLogger.level = INFO -rootLogger.appenderRefs = stdout -rootLogger.appenderRef.stdout.ref = STDOUT diff --git a/hadoop-hdds/common/src/test/resources/test.db.ini b/hadoop-hdds/common/src/test/resources/test.db.ini deleted file mode 100644 index 6666cd28b2d..00000000000 --- a/hadoop-hdds/common/src/test/resources/test.db.ini +++ /dev/null @@ -1,145 +0,0 @@ -# This is a RocksDB option file. -# -# A typical RocksDB options file has four sections, which are -# Version section, DBOptions section, at least one CFOptions -# section, and one TableOptions section for each column family. -# The RocksDB options file in general follows the basic INI -# file format with the following extensions / modifications: -# -# * Escaped characters -# We escaped the following characters: -# - \n -- line feed - new line -# - \r -- carriage return -# - \\ -- backslash \ -# - \: -- colon symbol : -# - \# -- hash tag # -# * Comments -# We support # style comments. Comments can appear at the ending -# part of a line. -# * Statements -# A statement is of the form option_name = value. -# Each statement contains a '=', where extra white-spaces -# are supported. However, we don't support multi-lined statement. -# Furthermore, each line can only contain at most one statement. -# * Sections -# Sections are of the form [SecitonTitle "SectionArgument"], -# where section argument is optional. -# * List -# We use colon-separated string to represent a list. -# For instance, n1:n2:n3:n4 is a list containing four values. -# -# Below is an example of a RocksDB options file: - - -#----------------------IMPORTANT------------------------------------# -### FAKE VALUES FOR TESTING ONLY ### DO NOT USE THESE FOR PRODUCTION. -#----------------------IMPORTANT------------------------------------# -[DBOptions] - stats_dump_period_sec=600 - max_manifest_file_size=551615 - bytes_per_sync=8388608 - delayed_write_rate=2097152 - WAL_ttl_seconds=0 - WAL_size_limit_MB=0 - max_subcompactions=1 - wal_dir= - wal_bytes_per_sync=0 - db_write_buffer_size=0 - keep_log_file_num=1000 - table_cache_numshardbits=4 - max_file_opening_threads=1 - writable_file_max_buffer_size=1048576 - random_access_max_buffer_size=1048576 - use_fsync=false - max_total_wal_size=0 - max_open_files=-1 - skip_stats_update_on_db_open=false - max_background_compactions=16 - manifest_preallocation_size=4194304 - max_background_flushes=7 - is_fd_close_on_exec=true - max_log_file_size=0 - advise_random_on_open=true - create_missing_column_families=false - paranoid_checks=true - delete_obsolete_files_period_micros=21600000000 - log_file_time_to_roll=0 - compaction_readahead_size=0 - create_if_missing=false - use_adaptive_mutex=false - enable_thread_tracking=false - allow_fallocate=true - error_if_exists=false - recycle_log_file_num=0 - skip_log_error_on_recovery=false - db_log_dir= - new_table_reader_for_compaction_inputs=true - allow_mmap_reads=false - allow_mmap_writes=false - use_direct_reads=false - use_direct_writes=false - - -[CFOptions "default"] - compaction_style=kCompactionStyleLevel - compaction_filter=nullptr - num_levels=6 - table_factory=BlockBasedTable - comparator=leveldb.BytewiseComparator - max_sequential_skip_in_iterations=8 - soft_rate_limit=0.000000 - max_bytes_for_level_base=1073741824 - memtable_prefix_bloom_probes=6 - memtable_prefix_bloom_bits=0 - memtable_prefix_bloom_huge_page_tlb_size=0 - max_successive_merges=0 - arena_block_size=16777216 - min_write_buffer_number_to_merge=1 - target_file_size_multiplier=1 - source_compaction_factor=1 - max_bytes_for_level_multiplier=8 - max_bytes_for_level_multiplier_additional=2:3:5 - compaction_filter_factory=nullptr - max_write_buffer_number=8 - level0_stop_writes_trigger=20 - compression=kSnappyCompression - level0_file_num_compaction_trigger=4 - purge_redundant_kvs_while_flush=true - max_write_buffer_number_to_maintain=0 - memtable_factory=SkipListFactory - max_grandparent_overlap_factor=8 - expanded_compaction_factor=25 - hard_pending_compaction_bytes_limit=137438953472 - inplace_update_num_locks=10000 - level_compaction_dynamic_level_bytes=true - level0_slowdown_writes_trigger=12 - filter_deletes=false - verify_checksums_in_compaction=true - min_partial_merge_operands=2 - paranoid_file_checks=false - target_file_size_base=134217728 - optimize_filters_for_hits=false - merge_operator=PutOperator - compression_per_level=kNoCompression:kNoCompression:kNoCompression:kSnappyCompression:kSnappyCompression:kSnappyCompression - compaction_measure_io_stats=false - prefix_extractor=nullptr - bloom_locality=0 - write_buffer_size=134217728 - disable_auto_compactions=false - inplace_update_support=false - -[TableOptions/BlockBasedTable "default"] - format_version=2 - whole_key_filtering=true - no_block_cache=false - checksum=kCRC32c - filter_policy=rocksdb.BuiltinBloomFilter - block_size_deviation=10 - block_size=8192 - block_restart_interval=16 - cache_index_and_filter_blocks=false - pin_l0_filter_and_index_blocks_in_cache=false - pin_top_level_index_and_filter=false - index_type=kBinarySearch - hash_index_allow_collision=true - flush_block_policy_factory=FlushBlockBySizePolicyFactory \ No newline at end of file diff --git a/hadoop-hdds/container-service/dev-support/findbugsExcludeFile.xml b/hadoop-hdds/container-service/dev-support/findbugsExcludeFile.xml deleted file mode 100644 index 3571a8929e3..00000000000 --- a/hadoop-hdds/container-service/dev-support/findbugsExcludeFile.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - diff --git a/hadoop-hdds/container-service/pom.xml b/hadoop-hdds/container-service/pom.xml deleted file mode 100644 index 54c5fadce92..00000000000 --- a/hadoop-hdds/container-service/pom.xml +++ /dev/null @@ -1,109 +0,0 @@ - - - - 4.0.0 - - org.apache.hadoop - hadoop-hdds - 0.3.0-SNAPSHOT - - hadoop-hdds-container-service - 0.3.0-SNAPSHOT - Apache Hadoop Distributed Data Store Container Service - Apache Hadoop HDDS Container Service - jar - - - - org.apache.hadoop - hadoop-hdds-common - - - org.apache.hadoop - hadoop-hdds-server-framework - - - - org.mockito - mockito-core - 2.2.0 - test - - - - org.yaml - snakeyaml - 1.8 - - - - io.dropwizard.metrics - metrics-core - test - - - - - - - org.apache.hadoop - hadoop-maven-plugins - - - compile-protoc - - protoc - - - ${protobuf.version} - ${protoc.path} - - - ${basedir}/../../hadoop-common-project/hadoop-common/src/main/proto - - - ${basedir}/../../hadoop-hdfs-project/hadoop-hdfs-client/src/main/proto/ - - - ${basedir}/../../hadoop-hdfs-project/hadoop-hdfs/src/main/proto/ - - - ${basedir}/../../hadoop-hdds/common/src/main/proto/ - - ${basedir}/src/main/proto - - - ${basedir}/src/main/proto - - StorageContainerDatanodeProtocol.proto - - - - - - - - org.codehaus.mojo - findbugs-maven-plugin - - ${basedir}/dev-support/findbugsExcludeFile.xml - - - - - \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/hdds/scm/HddsServerUtil.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/hdds/scm/HddsServerUtil.java deleted file mode 100644 index d505be379ca..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/hdds/scm/HddsServerUtil.java +++ /dev/null @@ -1,336 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.hdds.scm; - -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; -import com.google.common.base.Strings; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.net.NetUtils; -import org.apache.hadoop.ozone.OzoneConfigKeys; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.net.InetSocketAddress; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -import static org.apache.hadoop.hdds.HddsConfigKeys - .HDDS_HEARTBEAT_INTERVAL; -import static org.apache.hadoop.hdds.HddsConfigKeys - .HDDS_HEARTBEAT_INTERVAL_DEFAULT; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_DEADNODE_INTERVAL; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_DEADNODE_INTERVAL_DEFAULT; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_HEARTBEAT_LOG_WARN_DEFAULT; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_HEARTBEAT_LOG_WARN_INTERVAL_COUNT; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_HEARTBEAT_PROCESS_INTERVAL; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_HEARTBEAT_RPC_TIMEOUT; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_HEARTBEAT_RPC_TIMEOUT_DEFAULT; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_STALENODE_INTERVAL; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_STALENODE_INTERVAL_DEFAULT; -import static org.apache.hadoop.hdds.HddsUtils.*; -import static org.apache.hadoop.hdds.server.ServerUtils.sanitizeUserArgs; - -/** - * Hdds stateless helper functions for server side components. - */ -public final class HddsServerUtil { - - private HddsServerUtil() { - } - - private static final Logger LOG = LoggerFactory.getLogger( - HddsServerUtil.class); - - /** - * Retrieve the socket address that should be used by DataNodes to connect - * to the SCM. - * - * @param conf - * @return Target InetSocketAddress for the SCM service endpoint. - */ - public static InetSocketAddress getScmAddressForDataNodes( - Configuration conf) { - // We try the following settings in decreasing priority to retrieve the - // target host. - // - OZONE_SCM_DATANODE_ADDRESS_KEY - // - OZONE_SCM_CLIENT_ADDRESS_KEY - // - final Optional host = getHostNameFromConfigKeys(conf, - ScmConfigKeys.OZONE_SCM_DATANODE_ADDRESS_KEY, - ScmConfigKeys.OZONE_SCM_CLIENT_ADDRESS_KEY); - - if (!host.isPresent()) { - throw new IllegalArgumentException( - ScmConfigKeys.OZONE_SCM_CLIENT_ADDRESS_KEY + - " must be defined. See" + - " https://wiki.apache.org/hadoop/Ozone#Configuration " - + "for details on configuring Ozone."); - } - - // If no port number is specified then we'll just try the defaultBindPort. - final Optional port = getPortNumberFromConfigKeys(conf, - ScmConfigKeys.OZONE_SCM_DATANODE_ADDRESS_KEY); - - InetSocketAddress addr = NetUtils.createSocketAddr(host.get() + ":" + - port.or(ScmConfigKeys.OZONE_SCM_DATANODE_PORT_DEFAULT)); - - return addr; - } - - /** - * Retrieve the socket address that should be used by clients to connect - * to the SCM. - * - * @param conf - * @return Target InetSocketAddress for the SCM client endpoint. - */ - public static InetSocketAddress getScmClientBindAddress( - Configuration conf) { - final Optional host = getHostNameFromConfigKeys(conf, - ScmConfigKeys.OZONE_SCM_CLIENT_BIND_HOST_KEY); - - final Optional port = getPortNumberFromConfigKeys(conf, - ScmConfigKeys.OZONE_SCM_CLIENT_ADDRESS_KEY); - - return NetUtils.createSocketAddr( - host.or(ScmConfigKeys.OZONE_SCM_CLIENT_BIND_HOST_DEFAULT) + ":" + - port.or(ScmConfigKeys.OZONE_SCM_CLIENT_PORT_DEFAULT)); - } - - /** - * Retrieve the socket address that should be used by clients to connect - * to the SCM Block service. - * - * @param conf - * @return Target InetSocketAddress for the SCM block client endpoint. - */ - public static InetSocketAddress getScmBlockClientBindAddress( - Configuration conf) { - final Optional host = getHostNameFromConfigKeys(conf, - ScmConfigKeys.OZONE_SCM_BLOCK_CLIENT_BIND_HOST_KEY); - - final Optional port = getPortNumberFromConfigKeys(conf, - ScmConfigKeys.OZONE_SCM_BLOCK_CLIENT_ADDRESS_KEY); - - return NetUtils.createSocketAddr( - host.or(ScmConfigKeys.OZONE_SCM_BLOCK_CLIENT_BIND_HOST_DEFAULT) + - ":" + port.or(ScmConfigKeys.OZONE_SCM_BLOCK_CLIENT_PORT_DEFAULT)); - } - - /** - * Retrieve the socket address that should be used by DataNodes to connect - * to the SCM. - * - * @param conf - * @return Target InetSocketAddress for the SCM service endpoint. - */ - public static InetSocketAddress getScmDataNodeBindAddress( - Configuration conf) { - final Optional host = getHostNameFromConfigKeys(conf, - ScmConfigKeys.OZONE_SCM_DATANODE_BIND_HOST_KEY); - - // If no port number is specified then we'll just try the defaultBindPort. - final Optional port = getPortNumberFromConfigKeys(conf, - ScmConfigKeys.OZONE_SCM_DATANODE_ADDRESS_KEY); - - return NetUtils.createSocketAddr( - host.or(ScmConfigKeys.OZONE_SCM_DATANODE_BIND_HOST_DEFAULT) + ":" + - port.or(ScmConfigKeys.OZONE_SCM_DATANODE_PORT_DEFAULT)); - } - - - /** - * Returns the interval in which the heartbeat processor thread runs. - * - * @param conf - Configuration - * @return long in Milliseconds. - */ - public static long getScmheartbeatCheckerInterval(Configuration conf) { - return conf.getTimeDuration(OZONE_SCM_HEARTBEAT_PROCESS_INTERVAL, - ScmConfigKeys.OZONE_SCM_HEARTBEAT_PROCESS_INTERVAL_DEFAULT, - TimeUnit.MILLISECONDS); - } - - /** - * Heartbeat Interval - Defines the heartbeat frequency from a datanode to - * SCM. - * - * @param conf - Ozone Config - * @return - HB interval in milli seconds. - */ - public static long getScmHeartbeatInterval(Configuration conf) { - return conf.getTimeDuration(HDDS_HEARTBEAT_INTERVAL, - HDDS_HEARTBEAT_INTERVAL_DEFAULT, TimeUnit.MILLISECONDS); - } - - /** - * Get the Stale Node interval, which is used by SCM to flag a datanode as - * stale, if the heartbeat from that node has been missing for this duration. - * - * @param conf - Configuration. - * @return - Long, Milliseconds to wait before flagging a node as stale. - */ - public static long getStaleNodeInterval(Configuration conf) { - - long staleNodeIntervalMs = - conf.getTimeDuration(OZONE_SCM_STALENODE_INTERVAL, - OZONE_SCM_STALENODE_INTERVAL_DEFAULT, TimeUnit.MILLISECONDS); - - long heartbeatThreadFrequencyMs = getScmheartbeatCheckerInterval(conf); - - long heartbeatIntervalMs = getScmHeartbeatInterval(conf); - - - // Make sure that StaleNodeInterval is configured way above the frequency - // at which we run the heartbeat thread. - // - // Here we check that staleNodeInterval is at least five times more than the - // frequency at which the accounting thread is going to run. - try { - sanitizeUserArgs(staleNodeIntervalMs, heartbeatThreadFrequencyMs, - 5, 1000); - } catch (IllegalArgumentException ex) { - LOG.error("Stale Node Interval is cannot be honored due to " + - "mis-configured {}. ex: {}", - OZONE_SCM_HEARTBEAT_PROCESS_INTERVAL, ex); - throw ex; - } - - // Make sure that stale node value is greater than configured value that - // datanodes are going to send HBs. - try { - sanitizeUserArgs(staleNodeIntervalMs, heartbeatIntervalMs, 3, 1000); - } catch (IllegalArgumentException ex) { - LOG.error("Stale Node Interval MS is cannot be honored due to " + - "mis-configured {}. ex: {}", HDDS_HEARTBEAT_INTERVAL, ex); - throw ex; - } - return staleNodeIntervalMs; - } - - /** - * Gets the interval for dead node flagging. This has to be a value that is - * greater than stale node value, and by transitive relation we also know - * that this value is greater than heartbeat interval and heartbeatProcess - * Interval. - * - * @param conf - Configuration. - * @return - the interval for dead node flagging. - */ - public static long getDeadNodeInterval(Configuration conf) { - long staleNodeIntervalMs = getStaleNodeInterval(conf); - long deadNodeIntervalMs = conf.getTimeDuration(OZONE_SCM_DEADNODE_INTERVAL, - OZONE_SCM_DEADNODE_INTERVAL_DEFAULT, - TimeUnit.MILLISECONDS); - - try { - // Make sure that dead nodes Ms is at least twice the time for staleNodes - // with a max of 1000 times the staleNodes. - sanitizeUserArgs(deadNodeIntervalMs, staleNodeIntervalMs, 2, 1000); - } catch (IllegalArgumentException ex) { - LOG.error("Dead Node Interval MS is cannot be honored due to " + - "mis-configured {}. ex: {}", OZONE_SCM_STALENODE_INTERVAL, ex); - throw ex; - } - return deadNodeIntervalMs; - } - - /** - * Timeout value for the RPC from Datanode to SCM, primarily used for - * Heartbeats and container reports. - * - * @param conf - Ozone Config - * @return - Rpc timeout in Milliseconds. - */ - public static long getScmRpcTimeOutInMilliseconds(Configuration conf) { - return conf.getTimeDuration(OZONE_SCM_HEARTBEAT_RPC_TIMEOUT, - OZONE_SCM_HEARTBEAT_RPC_TIMEOUT_DEFAULT, TimeUnit.MILLISECONDS); - } - - /** - * Log Warn interval. - * - * @param conf - Ozone Config - * @return - Log warn interval. - */ - public static int getLogWarnInterval(Configuration conf) { - return conf.getInt(OZONE_SCM_HEARTBEAT_LOG_WARN_INTERVAL_COUNT, - OZONE_SCM_HEARTBEAT_LOG_WARN_DEFAULT); - } - - /** - * returns the Container port. - * @param conf - Conf - * @return port number. - */ - public static int getContainerPort(Configuration conf) { - return conf.getInt(OzoneConfigKeys.DFS_CONTAINER_IPC_PORT, - OzoneConfigKeys.DFS_CONTAINER_IPC_PORT_DEFAULT); - } - - - /** - * Return the list of service addresses for the Ozone SCM. This method is used - * by the DataNodes to determine the service instances to connect to. - * - * @param conf - * @return list of SCM service addresses. - */ - public static Map> - getScmServiceRpcAddresses(Configuration conf) { - - final Map serviceInstances = new HashMap<>(); - serviceInstances.put(OZONE_SCM_SERVICE_INSTANCE_ID, - getScmAddressForDataNodes(conf)); - - final Map> services = - new HashMap<>(); - services.put(OZONE_SCM_SERVICE_ID, serviceInstances); - return services; - } - - public static String getOzoneDatanodeRatisDirectory(Configuration conf) { - final String ratisDir = File.separator + "ratis"; - String storageDir = conf.get( - OzoneConfigKeys.DFS_CONTAINER_RATIS_DATANODE_STORAGE_DIR); - - if (Strings.isNullOrEmpty(storageDir)) { - storageDir = conf.get(OzoneConfigKeys - .OZONE_METADATA_DIRS); - Preconditions.checkNotNull(storageDir, "ozone.metadata.dirs " + - "cannot be null, Please check your configs."); - storageDir = storageDir.concat(ratisDir); - LOG.warn("Storage directory for Ratis is not configured." + - "Mapping Ratis storage under {}. It is a good idea " + - "to map this to an SSD disk.", storageDir); - } - return storageDir; - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/hdds/scm/VersionInfo.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/hdds/scm/VersionInfo.java deleted file mode 100644 index 4e520466254..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/hdds/scm/VersionInfo.java +++ /dev/null @@ -1,81 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm; - -/** - * This is a class that tracks versions of SCM. - */ -public final class VersionInfo { - - // We will just be normal and use positive counting numbers for versions. - private final static VersionInfo[] VERSION_INFOS = - {new VersionInfo("First version of SCM", 1)}; - - - public static final String DESCRIPTION_KEY = "Description"; - private final String description; - private final int version; - - /** - * Never created outside this class. - * - * @param description -- description - * @param version -- version number - */ - private VersionInfo(String description, int version) { - this.description = description; - this.version = version; - } - - /** - * Returns all versions. - * - * @return Version info array. - */ - public static VersionInfo[] getAllVersions() { - return VERSION_INFOS.clone(); - } - - /** - * Returns the latest version. - * - * @return versionInfo - */ - public static VersionInfo getLatestVersion() { - return VERSION_INFOS[VERSION_INFOS.length - 1]; - } - - /** - * Return description. - * - * @return String - */ - public String getDescription() { - return description; - } - - /** - * Return the version. - * - * @return int. - */ - public int getVersion() { - return version; - } - -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/hdds/scm/package-info.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/hdds/scm/package-info.java deleted file mode 100644 index 590546896a4..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/hdds/scm/package-info.java +++ /dev/null @@ -1,19 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm; diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/HddsDatanodeService.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/HddsDatanodeService.java deleted file mode 100644 index 348196cbe75..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/HddsDatanodeService.java +++ /dev/null @@ -1,256 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import org.apache.hadoop.conf.Configurable; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.scm.ScmConfigKeys; -import org.apache.hadoop.hdds.HddsUtils; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdfs.DFSUtil; -import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem; -import org.apache.hadoop.ozone.container.common.helpers.ContainerUtils; -import org.apache.hadoop.ozone.container.common.statemachine - .DatanodeStateMachine; -import org.apache.hadoop.util.GenericOptionsParser; -import org.apache.hadoop.util.ServicePlugin; -import org.apache.hadoop.util.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.net.InetAddress; -import java.util.List; -import java.util.UUID; - -import static org.apache.hadoop.ozone.OzoneConfigKeys.HDDS_DATANODE_PLUGINS_KEY; -import static org.apache.hadoop.util.ExitUtil.terminate; - -/** - * Datanode service plugin to start the HDDS container services. - */ -public class HddsDatanodeService implements ServicePlugin { - - private static final Logger LOG = LoggerFactory.getLogger( - HddsDatanodeService.class); - - - private OzoneConfiguration conf; - private DatanodeDetails datanodeDetails; - private DatanodeStateMachine datanodeStateMachine; - private List plugins; - - /** - * Default constructor. - */ - public HddsDatanodeService() { - this(null); - } - - /** - * Constructs {@link HddsDatanodeService} using the provided {@code conf} - * value. - * - * @param conf OzoneConfiguration - */ - public HddsDatanodeService(Configuration conf) { - if (conf == null) { - this.conf = new OzoneConfiguration(); - } else { - this.conf = new OzoneConfiguration(conf); - } - } - - /** - * Starts HddsDatanode services. - * - * @param service The service instance invoking this method - */ - @Override - public void start(Object service) { - OzoneConfiguration.activate(); - if (service instanceof Configurable) { - conf = new OzoneConfiguration(((Configurable) service).getConf()); - } - if (HddsUtils.isHddsEnabled(conf)) { - try { - String hostname = HddsUtils.getHostName(conf); - String ip = InetAddress.getByName(hostname).getHostAddress(); - datanodeDetails = initializeDatanodeDetails(); - datanodeDetails.setHostName(hostname); - datanodeDetails.setIpAddress(ip); - datanodeStateMachine = new DatanodeStateMachine(datanodeDetails, conf); - startPlugins(); - // Starting HDDS Daemons - datanodeStateMachine.startDaemon(); - } catch (IOException e) { - throw new RuntimeException("Can't start the HDDS datanode plugin", e); - } - } - } - - /** - * Returns DatanodeDetails or null in case of Error. - * - * @return DatanodeDetails - */ - private DatanodeDetails initializeDatanodeDetails() - throws IOException { - String idFilePath = HddsUtils.getDatanodeIdFilePath(conf); - if (idFilePath == null || idFilePath.isEmpty()) { - LOG.error("A valid file path is needed for config setting {}", - ScmConfigKeys.OZONE_SCM_DATANODE_ID); - throw new IllegalArgumentException(ScmConfigKeys.OZONE_SCM_DATANODE_ID + - " must be defined. See" + - " https://wiki.apache.org/hadoop/Ozone#Configuration" + - " for details on configuring Ozone."); - } - - Preconditions.checkNotNull(idFilePath); - File idFile = new File(idFilePath); - if (idFile.exists()) { - return ContainerUtils.readDatanodeDetailsFrom(idFile); - } else { - // There is no datanode.id file, this might be the first time datanode - // is started. - String datanodeUuid = UUID.randomUUID().toString(); - return DatanodeDetails.newBuilder().setUuid(datanodeUuid).build(); - } - } - - /** - * Starts all the service plugins which are configured using - * OzoneConfigKeys.HDDS_DATANODE_PLUGINS_KEY. - */ - private void startPlugins() { - try { - plugins = conf.getInstances(HDDS_DATANODE_PLUGINS_KEY, - ServicePlugin.class); - } catch (RuntimeException e) { - String pluginsValue = conf.get(HDDS_DATANODE_PLUGINS_KEY); - LOG.error("Unable to load HDDS DataNode plugins. " + - "Specified list of plugins: {}", - pluginsValue, e); - throw e; - } - for (ServicePlugin plugin : plugins) { - try { - plugin.start(this); - LOG.info("Started plug-in {}", plugin); - } catch (Throwable t) { - LOG.warn("ServicePlugin {} could not be started", plugin, t); - } - } - } - - /** - * Returns the OzoneConfiguration used by this HddsDatanodeService. - * - * @return OzoneConfiguration - */ - public OzoneConfiguration getConf() { - return conf; - } - /** - * - * Return DatanodeDetails if set, return null otherwise. - * - * @return DatanodeDetails - */ - @VisibleForTesting - public DatanodeDetails getDatanodeDetails() { - return datanodeDetails; - } - - @VisibleForTesting - public DatanodeStateMachine getDatanodeStateMachine() { - return datanodeStateMachine; - } - - public void join() { - try { - datanodeStateMachine.join(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - LOG.info("Interrupted during StorageContainerManager join."); - } - } - - @Override - public void stop() { - if (plugins != null) { - for (ServicePlugin plugin : plugins) { - try { - plugin.stop(); - LOG.info("Stopped plug-in {}", plugin); - } catch (Throwable t) { - LOG.warn("ServicePlugin {} could not be stopped", plugin, t); - } - } - } - if (datanodeStateMachine != null) { - datanodeStateMachine.stopDaemon(); - } - } - - @Override - public void close() throws IOException { - if (plugins != null) { - for (ServicePlugin plugin : plugins) { - try { - plugin.close(); - } catch (Throwable t) { - LOG.warn("ServicePlugin {} could not be closed", plugin, t); - } - } - } - } - - public static HddsDatanodeService createHddsDatanodeService( - Configuration conf) { - return new HddsDatanodeService(conf); - } - - public static void main(String[] args) { - try { - if (DFSUtil.parseHelpArgument( - args, "Starts HDDS Datanode", System.out, false)) { - System.exit(0); - } - Configuration conf = new OzoneConfiguration(); - GenericOptionsParser hParser = new GenericOptionsParser(conf, args); - if (!hParser.isParseSuccessful()) { - GenericOptionsParser.printGenericCommandUsage(System.err); - System.exit(1); - } - StringUtils.startupShutdownMessage(HddsDatanodeService.class, args, LOG); - DefaultMetricsSystem.initialize("HddsDatanode"); - HddsDatanodeService hddsDatanodeService = - createHddsDatanodeService(conf); - hddsDatanodeService.start(null); - hddsDatanodeService.join(); - } catch (Throwable e) { - LOG.error("Exception in HddsDatanodeService.", e); - terminate(1, e); - } - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/DataNodeLayoutVersion.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/DataNodeLayoutVersion.java deleted file mode 100644 index 2d58c39a151..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/DataNodeLayoutVersion.java +++ /dev/null @@ -1,80 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.common; - -/** - * Datanode layout version which describes information about the layout version - * on the datanode. - */ -public final class DataNodeLayoutVersion { - - // We will just be normal and use positive counting numbers for versions. - private final static DataNodeLayoutVersion[] VERSION_INFOS = - {new DataNodeLayoutVersion(1, "HDDS Datanode LayOut Version 1")}; - - private final String description; - private final int version; - - /** - * Never created outside this class. - * - * @param description -- description - * @param version -- version number - */ - private DataNodeLayoutVersion(int version, String description) { - this.description = description; - this.version = version; - } - - /** - * Returns all versions. - * - * @return Version info array. - */ - public static DataNodeLayoutVersion[] getAllVersions() { - return VERSION_INFOS.clone(); - } - - /** - * Returns the latest version. - * - * @return versionInfo - */ - public static DataNodeLayoutVersion getLatestVersion() { - return VERSION_INFOS[VERSION_INFOS.length - 1]; - } - - /** - * Return description. - * - * @return String - */ - public String getDescription() { - return description; - } - - /** - * Return the version. - * - * @return int. - */ - public int getVersion() { - return version; - } - -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/ContainerMetrics.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/ContainerMetrics.java deleted file mode 100644 index 2879001c28b..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/ContainerMetrics.java +++ /dev/null @@ -1,121 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.helpers; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdfs.DFSConfigKeys; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.metrics2.MetricsSystem; -import org.apache.hadoop.metrics2.annotation.Metric; -import org.apache.hadoop.metrics2.annotation.Metrics; -import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem; -import org.apache.hadoop.metrics2.lib.MetricsRegistry; -import org.apache.hadoop.metrics2.lib.MutableCounterLong; -import org.apache.hadoop.metrics2.lib.MutableQuantiles; -import org.apache.hadoop.metrics2.lib.MutableRate; - -/** - * - * This class is for maintaining the various Storage Container - * DataNode statistics and publishing them through the metrics interfaces. - * This also registers the JMX MBean for RPC. - *

- * This class has a number of metrics variables that are publicly accessible; - * these variables (objects) have methods to update their values; - * for example: - *

{@link #numOps}.inc() - * - */ -@InterfaceAudience.Private -@Metrics(about="Storage Container DataNode Metrics", context="dfs") -public class ContainerMetrics { - @Metric private MutableCounterLong numOps; - private MutableCounterLong[] numOpsArray; - private MutableCounterLong[] opsBytesArray; - private MutableRate[] opsLatency; - private MutableQuantiles[][] opsLatQuantiles; - private MetricsRegistry registry = null; - - public ContainerMetrics(int[] intervals) { - int numEnumEntries = ContainerProtos.Type.values().length; - final int len = intervals.length; - this.numOpsArray = new MutableCounterLong[numEnumEntries]; - this.opsBytesArray = new MutableCounterLong[numEnumEntries]; - this.opsLatency = new MutableRate[numEnumEntries]; - this.opsLatQuantiles = new MutableQuantiles[numEnumEntries][len]; - this.registry = new MetricsRegistry("StorageContainerMetrics"); - for (int i = 0; i < numEnumEntries; i++) { - numOpsArray[i] = registry.newCounter( - "num" + ContainerProtos.Type.forNumber(i + 1), - "number of " + ContainerProtos.Type.forNumber(i + 1) + " ops", - (long) 0); - opsBytesArray[i] = registry.newCounter( - "bytes" + ContainerProtos.Type.forNumber(i + 1), - "bytes used by " + ContainerProtos.Type.forNumber(i + 1) + "op", - (long) 0); - opsLatency[i] = registry.newRate( - "latency" + ContainerProtos.Type.forNumber(i + 1), - ContainerProtos.Type.forNumber(i + 1) + " op"); - - for (int j = 0; j < len; j++) { - int interval = intervals[j]; - String quantileName = ContainerProtos.Type.forNumber(i + 1) + "Nanos" - + interval + "s"; - opsLatQuantiles[i][j] = registry.newQuantiles(quantileName, - "latency of Container ops", "ops", "latency", interval); - } - } - } - - public static ContainerMetrics create(Configuration conf) { - MetricsSystem ms = DefaultMetricsSystem.instance(); - // Percentile measurement is off by default, by watching no intervals - int[] intervals = - conf.getInts(DFSConfigKeys.DFS_METRICS_PERCENTILES_INTERVALS_KEY); - return ms.register("StorageContainerMetrics", - "Storage Container Node Metrics", - new ContainerMetrics(intervals)); - } - - public void incContainerOpsMetrics(ContainerProtos.Type type) { - numOps.incr(); - numOpsArray[type.ordinal()].incr(); - } - - public long getContainerOpsMetrics(ContainerProtos.Type type){ - return numOpsArray[type.ordinal()].value(); - } - - public void incContainerOpsLatencies(ContainerProtos.Type type, - long latencyNanos) { - opsLatency[type.ordinal()].add(latencyNanos); - for (MutableQuantiles q: opsLatQuantiles[type.ordinal()]) { - q.add(latencyNanos); - } - } - - public void incContainerBytesStats(ContainerProtos.Type type, long bytes) { - opsBytesArray[type.ordinal()].incr(bytes); - } - - public long getContainerBytesMetrics(ContainerProtos.Type type){ - return opsBytesArray[type.ordinal()].value(); - } -} \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/ContainerReport.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/ContainerReport.java deleted file mode 100644 index a4c1f2f4678..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/ContainerReport.java +++ /dev/null @@ -1,205 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.common.helpers; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.ContainerInfo; - - -/** - * Container Report iterates the closed containers and sends a container report - * to SCM. - */ -public class ContainerReport { - private static final int UNKNOWN = -1; - private final String finalhash; - private long size; - private long keyCount; - private long bytesUsed; - private long readCount; - private long writeCount; - private long readBytes; - private long writeBytes; - private long containerID; - - public long getContainerID() { - return containerID; - } - - public void setContainerID(long containerID) { - this.containerID = containerID; - } - - /** - * Constructs the ContainerReport. - * - * @param containerID - Container ID. - * @param finalhash - Final Hash. - */ - public ContainerReport(long containerID, String finalhash) { - this.containerID = containerID; - this.finalhash = finalhash; - this.size = UNKNOWN; - this.keyCount = UNKNOWN; - this.bytesUsed = 0L; - this.readCount = 0L; - this.readBytes = 0L; - this.writeCount = 0L; - this.writeBytes = 0L; - } - - /** - * Gets a containerReport from protobuf class. - * - * @param info - ContainerInfo. - * @return - ContainerReport. - */ - public static ContainerReport getFromProtoBuf(ContainerInfo info) { - Preconditions.checkNotNull(info); - ContainerReport report = new ContainerReport(info.getContainerID(), - info.getFinalhash()); - if (info.hasSize()) { - report.setSize(info.getSize()); - } - if (info.hasKeyCount()) { - report.setKeyCount(info.getKeyCount()); - } - if (info.hasUsed()) { - report.setBytesUsed(info.getUsed()); - } - if (info.hasReadCount()) { - report.setReadCount(info.getReadCount()); - } - if (info.hasReadBytes()) { - report.setReadBytes(info.getReadBytes()); - } - if (info.hasWriteCount()) { - report.setWriteCount(info.getWriteCount()); - } - if (info.hasWriteBytes()) { - report.setWriteBytes(info.getWriteBytes()); - } - - report.setContainerID(info.getContainerID()); - return report; - } - - /** - * Returns the final signature for this container. - * - * @return - hash - */ - public String getFinalhash() { - return finalhash; - } - - /** - * Returns a positive number it is a valid number, -1 if not known. - * - * @return size or -1 - */ - public long getSize() { - return size; - } - - /** - * Sets the size of the container on disk. - * - * @param size - int - */ - public void setSize(long size) { - this.size = size; - } - - /** - * Gets number of keys in the container if known. - * - * @return - Number of keys or -1 for not known. - */ - public long getKeyCount() { - return keyCount; - } - - /** - * Sets the key count. - * - * @param keyCount - Key Count - */ - public void setKeyCount(long keyCount) { - this.keyCount = keyCount; - } - - public long getReadCount() { - return readCount; - } - - public void setReadCount(long readCount) { - this.readCount = readCount; - } - - public long getWriteCount() { - return writeCount; - } - - public void setWriteCount(long writeCount) { - this.writeCount = writeCount; - } - - public long getReadBytes() { - return readBytes; - } - - public void setReadBytes(long readBytes) { - this.readBytes = readBytes; - } - - public long getWriteBytes() { - return writeBytes; - } - - public void setWriteBytes(long writeBytes) { - this.writeBytes = writeBytes; - } - - public long getBytesUsed() { - return bytesUsed; - } - - public void setBytesUsed(long bytesUsed) { - this.bytesUsed = bytesUsed; - } - - /** - * Gets a containerInfo protobuf message from ContainerReports. - * - * @return ContainerInfo - */ - public ContainerInfo getProtoBufMessage() { - return ContainerInfo.newBuilder() - .setKeyCount(this.getKeyCount()) - .setSize(this.getSize()) - .setUsed(this.getBytesUsed()) - .setReadCount(this.getReadCount()) - .setReadBytes(this.getReadBytes()) - .setWriteCount(this.getWriteCount()) - .setWriteBytes(this.getWriteBytes()) - .setFinalhash(this.getFinalhash()) - .setContainerID(this.getContainerID()) - .build(); - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/ContainerUtils.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/ContainerUtils.java deleted file mode 100644 index d96849e3c35..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/ContainerUtils.java +++ /dev/null @@ -1,305 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.helpers; - -import com.google.common.base.Preconditions; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import org.apache.commons.codec.digest.DigestUtils; -import org.apache.hadoop.fs.FileAlreadyExistsException; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandRequestProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandResponseProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.Result; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.scm.container.common.helpers - .StorageContainerException; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.container.common.impl.ContainerData; -import org.apache.hadoop.ozone.container.common.impl.ContainerDataYaml; -import org.apache.hadoop.ozone.container.common.impl.ContainerSet; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.file.Paths; -import org.yaml.snakeyaml.Yaml; - -import static org.apache.commons.io.FilenameUtils.removeExtension; -import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .Result.CONTAINER_CHECKSUM_ERROR; -import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .Result.NO_SUCH_ALGORITHM; -import static org.apache.hadoop.ozone.container.common.impl.ContainerData - .CHARSET_ENCODING; - -/** - * A set of helper functions to create proper responses. - */ -public final class ContainerUtils { - - private ContainerUtils() { - //never constructed. - } - - /** - * Returns a Container Command Response Builder with the specified result - * and message. - * @param request requestProto message. - * @param result result of the command. - * @param message response message. - * @return ContainerCommand Response Builder. - */ - public static ContainerCommandResponseProto.Builder - getContainerCommandResponse( - ContainerCommandRequestProto request, Result result, String message) { - return ContainerCommandResponseProto.newBuilder() - .setCmdType(request.getCmdType()) - .setTraceID(request.getTraceID()) - .setResult(result) - .setMessage(message); - } - - /** - * Returns a Container Command Response Builder. This call is used to build - * success responses. Calling function can add other fields to the response - * as required. - * @param request requestProto message. - * @return ContainerCommand Response Builder with result as SUCCESS. - */ - public static ContainerCommandResponseProto.Builder getSuccessResponseBuilder( - ContainerCommandRequestProto request) { - return - ContainerCommandResponseProto.newBuilder() - .setCmdType(request.getCmdType()) - .setTraceID(request.getTraceID()) - .setResult(Result.SUCCESS); - } - - /** - * Returns a Container Command Response. This call is used for creating null - * success responses. - * @param request requestProto message. - * @return ContainerCommand Response with result as SUCCESS. - */ - public static ContainerCommandResponseProto getSuccessResponse( - ContainerCommandRequestProto request) { - ContainerCommandResponseProto.Builder builder = - getContainerCommandResponse(request, Result.SUCCESS, ""); - return builder.build(); - } - - /** - * We found a command type but no associated payload for the command. Hence - * return malformed Command as response. - * - * @param request - Protobuf message. - * @return ContainerCommandResponseProto - MALFORMED_REQUEST. - */ - public static ContainerCommandResponseProto malformedRequest( - ContainerCommandRequestProto request) { - return getContainerCommandResponse(request, Result.MALFORMED_REQUEST, - "Cmd type does not match the payload.").build(); - } - - /** - * We found a command type that is not supported yet. - * - * @param request - Protobuf message. - * @return ContainerCommandResponseProto - UNSUPPORTED_REQUEST. - */ - public static ContainerCommandResponseProto unsupportedRequest( - ContainerCommandRequestProto request) { - return getContainerCommandResponse(request, Result.UNSUPPORTED_REQUEST, - "Server does not support this command yet.").build(); - } - - /** - * Logs the error and returns a response to the caller. - * - * @param log - Logger - * @param ex - Exception - * @param request - Request Object - * @return Response - */ - public static ContainerCommandResponseProto logAndReturnError( - Logger log, StorageContainerException ex, - ContainerCommandRequestProto request) { - log.info("Operation: {} : Trace ID: {} : Message: {} : Result: {}", - request.getCmdType().name(), request.getTraceID(), - ex.getMessage(), ex.getResult().getValueDescriptor().getName()); - return getContainerCommandResponse(request, ex.getResult(), ex.getMessage()) - .build(); - } - - /** - * get containerName from a container file. - * - * @param containerFile - File - * @return Name of the container. - */ - public static String getContainerNameFromFile(File containerFile) { - Preconditions.checkNotNull(containerFile); - return Paths.get(containerFile.getParent()).resolve( - removeExtension(containerFile.getName())).toString(); - } - - public static long getContainerIDFromFile(File containerFile) { - Preconditions.checkNotNull(containerFile); - String containerID = getContainerNameFromFile(containerFile); - return Long.parseLong(containerID); - } - - /** - * Verifies that this is indeed a new container. - * - * @param containerFile - Container File to verify - * @throws IOException - */ - public static void verifyIsNewContainer(File containerFile) throws - FileAlreadyExistsException { - Logger log = LoggerFactory.getLogger(ContainerSet.class); - Preconditions.checkNotNull(containerFile, "containerFile Should not be " + - "null"); - if (containerFile.getParentFile().exists()) { - log.error("Container already exists on disk. File: {}", containerFile - .toPath()); - throw new FileAlreadyExistsException("container already exists on " + - "disk."); - } - } - - public static String getContainerDbFileName(String containerName) { - return containerName + OzoneConsts.DN_CONTAINER_DB; - } - - /** - * Persistent a {@link DatanodeDetails} to a local file. - * - * @throws IOException when read/write error occurs - */ - public synchronized static void writeDatanodeDetailsTo( - DatanodeDetails datanodeDetails, File path) throws IOException { - if (path.exists()) { - if (!path.delete() || !path.createNewFile()) { - throw new IOException("Unable to overwrite the datanode ID file."); - } - } else { - if(!path.getParentFile().exists() && - !path.getParentFile().mkdirs()) { - throw new IOException("Unable to create datanode ID directories."); - } - } - try (FileOutputStream out = new FileOutputStream(path)) { - HddsProtos.DatanodeDetailsProto proto = - datanodeDetails.getProtoBufMessage(); - proto.writeTo(out); - } - } - - /** - * Read {@link DatanodeDetails} from a local ID file. - * - * @param path ID file local path - * @return {@link DatanodeDetails} - * @throws IOException If the id file is malformed or other I/O exceptions - */ - public synchronized static DatanodeDetails readDatanodeDetailsFrom(File path) - throws IOException { - if (!path.exists()) { - throw new IOException("Datanode ID file not found."); - } - try(FileInputStream in = new FileInputStream(path)) { - return DatanodeDetails.getFromProtoBuf( - HddsProtos.DatanodeDetailsProto.parseFrom(in)); - } catch (IOException e) { - throw new IOException("Failed to parse DatanodeDetails from " - + path.getAbsolutePath(), e); - } - } - - /** - * Verify that the checksum stored in containerData is equal to the - * computed checksum. - * @param containerData - * @throws IOException - */ - public static void verifyChecksum(ContainerData containerData) - throws IOException { - String storedChecksum = containerData.getChecksum(); - - Yaml yaml = ContainerDataYaml.getYamlForContainerType( - containerData.getContainerType()); - containerData.computeAndSetChecksum(yaml); - String computedChecksum = containerData.getChecksum(); - - if (storedChecksum == null || !storedChecksum.equals(computedChecksum)) { - throw new StorageContainerException("Container checksum error for " + - "ContainerID: " + containerData.getContainerID() + ". " + - "\nStored Checksum: " + storedChecksum + - "\nExpected Checksum: " + computedChecksum, - CONTAINER_CHECKSUM_ERROR); - } - } - - /** - * Return the SHA-256 chesksum of the containerData. - * @param containerDataYamlStr ContainerData as a Yaml String - * @return Checksum of the container data - * @throws StorageContainerException - */ - public static String getChecksum(String containerDataYamlStr) - throws StorageContainerException { - MessageDigest sha; - try { - sha = MessageDigest.getInstance(OzoneConsts.FILE_HASH); - sha.update(containerDataYamlStr.getBytes(CHARSET_ENCODING)); - return DigestUtils.sha256Hex(sha.digest()); - } catch (NoSuchAlgorithmException e) { - throw new StorageContainerException("Unable to create Message Digest, " + - "usually this is a java configuration issue.", NO_SUCH_ALGORITHM); - } - } - - /** - * Get the .container file from the containerBaseDir. - * @param containerBaseDir container base directory. The name of this - * directory is same as the containerID - * @return the .container file - */ - public static File getContainerFile(File containerBaseDir) { - // Container file layout is - // .../<>/metadata/<>.container - String containerFilePath = OzoneConsts.CONTAINER_META_PATH + File.separator - + getContainerID(containerBaseDir) + OzoneConsts.CONTAINER_EXTENSION; - return new File(containerBaseDir, containerFilePath); - } - - /** - * ContainerID can be decoded from the container base directory name. - */ - public static long getContainerID(File containerBaseDir) { - return Long.parseLong(containerBaseDir.getName()); - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/DatanodeVersionFile.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/DatanodeVersionFile.java deleted file mode 100644 index 4db6d3120fd..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/DatanodeVersionFile.java +++ /dev/null @@ -1,95 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.container.common.helpers; - -import org.apache.hadoop.ozone.OzoneConsts; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.util.Properties; - -/** - * This is a utility class which helps to create the version file on datanode - * and also validate the content of the version file. - */ -public class DatanodeVersionFile { - - private final String storageId; - private final String clusterId; - private final String datanodeUuid; - private final long cTime; - private final int layOutVersion; - - public DatanodeVersionFile(String storageId, String clusterId, - String datanodeUuid, long cTime, int layOutVersion) { - this.storageId = storageId; - this.clusterId = clusterId; - this.datanodeUuid = datanodeUuid; - this.cTime = cTime; - this.layOutVersion = layOutVersion; - } - - private Properties createProperties() { - Properties properties = new Properties(); - properties.setProperty(OzoneConsts.STORAGE_ID, storageId); - properties.setProperty(OzoneConsts.CLUSTER_ID, clusterId); - properties.setProperty(OzoneConsts.DATANODE_UUID, datanodeUuid); - properties.setProperty(OzoneConsts.CTIME, String.valueOf(cTime)); - properties.setProperty(OzoneConsts.LAYOUTVERSION, String.valueOf( - layOutVersion)); - return properties; - } - - /** - * Creates a version File in specified path. - * @param path - * @throws IOException - */ - public void createVersionFile(File path) throws - IOException { - try (RandomAccessFile file = new RandomAccessFile(path, "rws"); - FileOutputStream out = new FileOutputStream(file.getFD())) { - file.getChannel().truncate(0); - Properties properties = createProperties(); - /* - * If server is interrupted before this line, - * the version file will remain unchanged. - */ - properties.store(out, null); - } - } - - - /** - * Creates a property object from the specified file content. - * @param versionFile - * @return Properties - * @throws IOException - */ - public static Properties readFrom(File versionFile) throws IOException { - try (RandomAccessFile file = new RandomAccessFile(versionFile, "rws"); - FileInputStream in = new FileInputStream(file.getFD())) { - Properties props = new Properties(); - props.load(in); - return props; - } - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/DeletedContainerBlocksSummary.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/DeletedContainerBlocksSummary.java deleted file mode 100644 index 9d0ec957f28..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/DeletedContainerBlocksSummary.java +++ /dev/null @@ -1,104 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.container.common.helpers; - -import com.google.common.collect.Maps; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.DeletedBlocksTransaction; -import org.apache.hadoop.util.StringUtils; - -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * A helper class to wrap the info about under deletion container blocks. - */ -public final class DeletedContainerBlocksSummary { - - private final List blocks; - // key : txID - // value : times of this tx has been processed - private final Map txSummary; - // key : container name - // value : the number of blocks need to be deleted in this container - // if the message contains multiple entries for same block, - // blocks will be merged - private final Map blockSummary; - // total number of blocks in this message - private int numOfBlocks; - - private DeletedContainerBlocksSummary(List blocks) { - this.blocks = blocks; - txSummary = Maps.newHashMap(); - blockSummary = Maps.newHashMap(); - blocks.forEach(entry -> { - txSummary.put(entry.getTxID(), entry.getCount()); - if (blockSummary.containsKey(entry.getContainerID())) { - blockSummary.put(entry.getContainerID(), - blockSummary.get(entry.getContainerID()) - + entry.getLocalIDCount()); - } else { - blockSummary.put(entry.getContainerID(), entry.getLocalIDCount()); - } - numOfBlocks += entry.getLocalIDCount(); - }); - } - - public static DeletedContainerBlocksSummary getFrom( - List blocks) { - return new DeletedContainerBlocksSummary(blocks); - } - - public int getNumOfBlocks() { - return numOfBlocks; - } - - public int getNumOfContainers() { - return blockSummary.size(); - } - - public String getTXIDs() { - return String.join(",", txSummary.keySet() - .stream().map(String::valueOf).collect(Collectors.toList())); - } - - public String getTxIDSummary() { - List txSummaryEntry = txSummary.entrySet().stream() - .map(entry -> entry.getKey() + "(" + entry.getValue() + ")") - .collect(Collectors.toList()); - return "[" + String.join(",", txSummaryEntry) + "]"; - } - - @Override public String toString() { - StringBuffer sb = new StringBuffer(); - for (DeletedBlocksTransaction blks : blocks) { - sb.append(" ") - .append("TXID=") - .append(blks.getTxID()) - .append(", ") - .append("TimesProceed=") - .append(blks.getCount()) - .append(", ") - .append(blks.getContainerID()) - .append(" : [") - .append(StringUtils.join(',', blks.getLocalIDList())).append("]") - .append("\n"); - } - return sb.toString(); - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/KeyValueContainerReport.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/KeyValueContainerReport.java deleted file mode 100644 index b03487b5beb..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/KeyValueContainerReport.java +++ /dev/null @@ -1,117 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.common.helpers; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.ContainerInfo; - -import static java.lang.Math.max; - -/** - * KeyValueContainer Report iterates the closed containers and sends a - * container report to SCM. - */ -public class KeyValueContainerReport extends ContainerReport{ - private long deleteTransactionId; - - /** - * Constructs the KeyValueContainerReport. - * - * @param containerID - Container ID. - * @param finalhash - Final Hash. - */ - public KeyValueContainerReport(long containerID, String finalhash) { - super(containerID, finalhash); - this.deleteTransactionId = 0; - } - - /** - * Sets the deleteTransactionId if it is greater than existing. - * @param transactionId - deleteTransactionId - */ - public void updateDeleteTransactionId(long transactionId) { - this.deleteTransactionId = max(transactionId, deleteTransactionId); - } - - /** - * Gets the deleteTransactionId. - * @return - deleteTransactionId. - */ - public long getDeleteTransactionId() { - return this.deleteTransactionId; - } - - /** - * Gets a containerReport from protobuf class. - * - * @param info - ContainerInfo. - * @return - ContainerReport. - */ - public static KeyValueContainerReport getFromProtoBuf(ContainerInfo info) { - Preconditions.checkNotNull(info); - KeyValueContainerReport report = new KeyValueContainerReport( - info.getContainerID(), info.getFinalhash()); - if (info.hasSize()) { - report.setSize(info.getSize()); - } - if (info.hasKeyCount()) { - report.setKeyCount(info.getKeyCount()); - } - if (info.hasUsed()) { - report.setBytesUsed(info.getUsed()); - } - if (info.hasReadCount()) { - report.setReadCount(info.getReadCount()); - } - if (info.hasReadBytes()) { - report.setReadBytes(info.getReadBytes()); - } - if (info.hasWriteCount()) { - report.setWriteCount(info.getWriteCount()); - } - if (info.hasWriteBytes()) { - report.setWriteBytes(info.getWriteBytes()); - } - if (info.hasDeleteTransactionId()) { - report.updateDeleteTransactionId(info.getDeleteTransactionId()); - } - report.setContainerID(info.getContainerID()); - return report; - } - - /** - * Gets a containerInfo protobuf message from ContainerReports. - * - * @return ContainerInfo - */ - @Override - public ContainerInfo getProtoBufMessage() { - return ContainerInfo.newBuilder() - .setKeyCount(this.getKeyCount()) - .setSize(this.getSize()) - .setUsed(this.getBytesUsed()) - .setReadCount(this.getReadCount()) - .setReadBytes(this.getReadBytes()) - .setWriteCount(this.getWriteCount()) - .setWriteBytes(this.getWriteBytes()) - .setFinalhash(this.getFinalhash()) - .setContainerID(this.getContainerID()) - .setDeleteTransactionId(this.getDeleteTransactionId()) - .build(); - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/package-info.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/package-info.java deleted file mode 100644 index 21f31e1bbe3..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/package-info.java +++ /dev/null @@ -1,22 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.common.helpers; -/** - Contains protocol buffer helper classes and utilites used in - impl. - **/ \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/ChunkLayOutVersion.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/ChunkLayOutVersion.java deleted file mode 100644 index d1b1bd66493..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/ChunkLayOutVersion.java +++ /dev/null @@ -1,98 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.common.impl; - - -import com.google.common.base.Preconditions; - -/** - * Defines layout versions for the Chunks. - */ - -public final class ChunkLayOutVersion { - - private final static ChunkLayOutVersion[] CHUNK_LAYOUT_VERSION_INFOS = - {new ChunkLayOutVersion(1, "Data without checksums.")}; - - private int version; - private String description; - - - /** - * Never created outside this class. - * - * @param description -- description - * @param version -- version number - */ - private ChunkLayOutVersion(int version, String description) { - this.version = version; - this.description = description; - } - - /** - * Return ChunkLayOutVersion object for the chunkVersion. - * @param chunkVersion - * @return ChunkLayOutVersion - */ - public static ChunkLayOutVersion getChunkLayOutVersion(int chunkVersion) { - Preconditions.checkArgument((chunkVersion <= ChunkLayOutVersion - .getLatestVersion().getVersion())); - for(ChunkLayOutVersion chunkLayOutVersion : CHUNK_LAYOUT_VERSION_INFOS) { - if(chunkLayOutVersion.getVersion() == chunkVersion) { - return chunkLayOutVersion; - } - } - return null; - } - - /** - * Returns all versions. - * - * @return Version info array. - */ - public static ChunkLayOutVersion[] getAllVersions() { - return CHUNK_LAYOUT_VERSION_INFOS.clone(); - } - - /** - * Returns the latest version. - * - * @return versionInfo - */ - public static ChunkLayOutVersion getLatestVersion() { - return CHUNK_LAYOUT_VERSION_INFOS[CHUNK_LAYOUT_VERSION_INFOS.length - 1]; - } - - /** - * Return version. - * - * @return int - */ - public int getVersion() { - return version; - } - - /** - * Returns description. - * @return String - */ - public String getDescription() { - return description; - } - -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/ContainerData.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/ContainerData.java deleted file mode 100644 index efea20bdc4b..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/ContainerData.java +++ /dev/null @@ -1,435 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.common.impl; - -import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; -import java.io.IOException; -import java.nio.charset.Charset; -import java.util.List; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos. - ContainerType; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos. - ContainerLifeCycleState; -import org.apache.hadoop.ozone.container.common.helpers.ContainerUtils; -import org.apache.hadoop.ozone.container.common.volume.HddsVolume; - -import java.util.Collections; -import java.util.Map; -import java.util.TreeMap; -import java.util.concurrent.atomic.AtomicLong; -import org.yaml.snakeyaml.Yaml; - -import static org.apache.hadoop.ozone.OzoneConsts.CHECKSUM; -import static org.apache.hadoop.ozone.OzoneConsts.CONTAINER_ID; -import static org.apache.hadoop.ozone.OzoneConsts.CONTAINER_TYPE; -import static org.apache.hadoop.ozone.OzoneConsts.LAYOUTVERSION; -import static org.apache.hadoop.ozone.OzoneConsts.MAX_SIZE; -import static org.apache.hadoop.ozone.OzoneConsts.METADATA; -import static org.apache.hadoop.ozone.OzoneConsts.STATE; - -/** - * ContainerData is the in-memory representation of container metadata and is - * represented on disk by the .container file. - */ -public abstract class ContainerData { - - //Type of the container. - // For now, we support only KeyValueContainer. - private final ContainerType containerType; - - // Unique identifier for the container - private final long containerID; - - // Layout version of the container data - private final int layOutVersion; - - // Metadata of the container will be a key value pair. - // This can hold information like volume name, owner etc., - private final Map metadata; - - // State of the Container - private ContainerLifeCycleState state; - - private final long maxSize; - - /** parameters for read/write statistics on the container. **/ - private final AtomicLong readBytes; - private final AtomicLong writeBytes; - private final AtomicLong readCount; - private final AtomicLong writeCount; - private final AtomicLong bytesUsed; - private final AtomicLong keyCount; - - private HddsVolume volume; - - private String checksum; - public static final Charset CHARSET_ENCODING = Charset.forName("UTF-8"); - private static final String DUMMY_CHECKSUM = new String(new byte[64], - CHARSET_ENCODING); - - // Common Fields need to be stored in .container file. - protected static final List YAML_FIELDS = - Collections.unmodifiableList(Lists.newArrayList( - CONTAINER_TYPE, - CONTAINER_ID, - LAYOUTVERSION, - STATE, - METADATA, - MAX_SIZE, - CHECKSUM)); - - /** - * Creates a ContainerData Object, which holds metadata of the container. - * @param type - ContainerType - * @param containerId - ContainerId - * @param size - container maximum size in bytes - */ - protected ContainerData(ContainerType type, long containerId, long size) { - this(type, containerId, - ChunkLayOutVersion.getLatestVersion().getVersion(), size); - } - - /** - * Creates a ContainerData Object, which holds metadata of the container. - * @param type - ContainerType - * @param containerId - ContainerId - * @param layOutVersion - Container layOutVersion - * @param size - Container maximum size in bytes - */ - protected ContainerData(ContainerType type, long containerId, - int layOutVersion, long size) { - Preconditions.checkNotNull(type); - - this.containerType = type; - this.containerID = containerId; - this.layOutVersion = layOutVersion; - this.metadata = new TreeMap<>(); - this.state = ContainerLifeCycleState.OPEN; - this.readCount = new AtomicLong(0L); - this.readBytes = new AtomicLong(0L); - this.writeCount = new AtomicLong(0L); - this.writeBytes = new AtomicLong(0L); - this.bytesUsed = new AtomicLong(0L); - this.keyCount = new AtomicLong(0L); - this.maxSize = size; - setChecksumTo0ByteArray(); - } - - /** - * Returns the containerID. - */ - public long getContainerID() { - return containerID; - } - - /** - * Returns the path to base dir of the container. - * @return Path to base dir. - */ - public abstract String getContainerPath(); - - /** - * Returns the type of the container. - * @return ContainerType - */ - public ContainerType getContainerType() { - return containerType; - } - - - /** - * Returns the state of the container. - * @return ContainerLifeCycleState - */ - public synchronized ContainerLifeCycleState getState() { - return state; - } - - /** - * Set the state of the container. - * @param state - */ - public synchronized void setState(ContainerLifeCycleState state) { - this.state = state; - } - - /** - * Return's maximum size of the container in bytes. - * @return maxSize in bytes - */ - public long getMaxSize() { - return maxSize; - } - - /** - * Returns the layOutVersion of the actual container data format. - * @return layOutVersion - */ - public int getLayOutVersion() { - return ChunkLayOutVersion.getChunkLayOutVersion(layOutVersion).getVersion(); - } - - /** - * Add/Update metadata. - * We should hold the container lock before updating the metadata as this - * will be persisted on disk. Unless, we are reconstructing ContainerData - * from protoBuf or from on disk .container file in which case lock is not - * required. - */ - public void addMetadata(String key, String value) { - metadata.put(key, value); - } - - /** - * Retuns metadata of the container. - * @return metadata - */ - public Map getMetadata() { - return Collections.unmodifiableMap(this.metadata); - } - - /** - * Set metadata. - * We should hold the container lock before updating the metadata as this - * will be persisted on disk. Unless, we are reconstructing ContainerData - * from protoBuf or from on disk .container file in which case lock is not - * required. - */ - public void setMetadata(Map metadataMap) { - metadata.clear(); - metadata.putAll(metadataMap); - } - - /** - * checks if the container is open. - * @return - boolean - */ - public synchronized boolean isOpen() { - return ContainerLifeCycleState.OPEN == state; - } - - /** - * checks if the container is invalid. - * @return - boolean - */ - public synchronized boolean isValid() { - return !(ContainerLifeCycleState.INVALID == state); - } - - /** - * checks if the container is closed. - * @return - boolean - */ - public synchronized boolean isClosed() { - return ContainerLifeCycleState.CLOSED == state; - } - - /** - * Marks this container as closed. - */ - public synchronized void closeContainer() { - setState(ContainerLifeCycleState.CLOSED); - } - - /** - * Get the number of bytes read from the container. - * @return the number of bytes read from the container. - */ - public long getReadBytes() { - return readBytes.get(); - } - - /** - * Increase the number of bytes read from the container. - * @param bytes number of bytes read. - */ - public void incrReadBytes(long bytes) { - this.readBytes.addAndGet(bytes); - } - - /** - * Get the number of times the container is read. - * @return the number of times the container is read. - */ - public long getReadCount() { - return readCount.get(); - } - - /** - * Increase the number of container read count by 1. - */ - public void incrReadCount() { - this.readCount.incrementAndGet(); - } - - /** - * Get the number of bytes write into the container. - * @return the number of bytes write into the container. - */ - public long getWriteBytes() { - return writeBytes.get(); - } - - /** - * Increase the number of bytes write into the container. - * @param bytes the number of bytes write into the container. - */ - public void incrWriteBytes(long bytes) { - this.writeBytes.addAndGet(bytes); - } - - /** - * Get the number of writes into the container. - * @return the number of writes into the container. - */ - public long getWriteCount() { - return writeCount.get(); - } - - /** - * Increase the number of writes into the container by 1. - */ - public void incrWriteCount() { - this.writeCount.incrementAndGet(); - } - - /** - * Sets the number of bytes used by the container. - * @param used - */ - public void setBytesUsed(long used) { - this.bytesUsed.set(used); - } - - /** - * Get the number of bytes used by the container. - * @return the number of bytes used by the container. - */ - public long getBytesUsed() { - return bytesUsed.get(); - } - - /** - * Increase the number of bytes used by the container. - * @param used number of bytes used by the container. - * @return the current number of bytes used by the container afert increase. - */ - public long incrBytesUsed(long used) { - return this.bytesUsed.addAndGet(used); - } - - /** - * Decrease the number of bytes used by the container. - * @param reclaimed the number of bytes reclaimed from the container. - * @return the current number of bytes used by the container after decrease. - */ - public long decrBytesUsed(long reclaimed) { - return this.bytesUsed.addAndGet(-1L * reclaimed); - } - - /** - * Set the Volume for the Container. - * This should be called only from the createContainer. - * @param hddsVolume - */ - public void setVolume(HddsVolume hddsVolume) { - this.volume = hddsVolume; - } - - /** - * Returns the volume of the Container. - * @return HddsVolume - */ - public HddsVolume getVolume() { - return volume; - } - - /** - * Increments the number of keys in the container. - */ - public void incrKeyCount() { - this.keyCount.incrementAndGet(); - } - - /** - * Decrements number of keys in the container. - */ - public void decrKeyCount() { - this.keyCount.decrementAndGet(); - } - - /** - * Returns number of keys in the container. - * @return key count - */ - public long getKeyCount() { - return this.keyCount.get(); - } - - /** - * Set's number of keys in the container. - * @param count - */ - public void setKeyCount(long count) { - this.keyCount.set(count); - } - - public void setChecksumTo0ByteArray() { - this.checksum = DUMMY_CHECKSUM; - } - - public void setChecksum(String checkSum) { - this.checksum = checkSum; - } - - public String getChecksum() { - return this.checksum; - } - - /** - * Compute the checksum for ContainerData using the specified Yaml (based - * on ContainerType) and set the checksum. - * - * Checksum of ContainerData is calculated by setting the - * {@link ContainerData#checksum} field to a 64-byte array with all 0's - - * {@link ContainerData#DUMMY_CHECKSUM}. After the checksum is calculated, - * the checksum field is updated with this value. - * - * @param yaml Yaml for ContainerType to get the ContainerData as Yaml String - * @throws IOException - */ - public void computeAndSetChecksum(Yaml yaml) throws IOException { - // Set checksum to dummy value - 0 byte array, to calculate the checksum - // of rest of the data. - setChecksumTo0ByteArray(); - - // Dump yaml data into a string to compute its checksum - String containerDataYamlStr = yaml.dump(this); - - this.checksum = ContainerUtils.getChecksum(containerDataYamlStr); - } - - /** - * Returns a ProtoBuf Message from ContainerData. - * - * @return Protocol Buffer Message - */ - public abstract ContainerProtos.ContainerData getProtoBufMessage(); -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/ContainerDataYaml.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/ContainerDataYaml.java deleted file mode 100644 index 65262d4b738..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/ContainerDataYaml.java +++ /dev/null @@ -1,326 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.impl; - -import java.beans.IntrospectionException; -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStreamWriter; -import java.io.Writer; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; - -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerType; -import org.apache.hadoop.hdds.scm.container.common.helpers - .StorageContainerException; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.container.keyvalue.KeyValueContainerData; - -import com.google.common.base.Preconditions; -import static org.apache.hadoop.ozone.container.keyvalue - .KeyValueContainerData.KEYVALUE_YAML_TAG; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.yaml.snakeyaml.Yaml; -import org.yaml.snakeyaml.constructor.AbstractConstruct; -import org.yaml.snakeyaml.constructor.Constructor; -import org.yaml.snakeyaml.introspector.BeanAccess; -import org.yaml.snakeyaml.introspector.Property; -import org.yaml.snakeyaml.introspector.PropertyUtils; -import org.yaml.snakeyaml.nodes.MappingNode; -import org.yaml.snakeyaml.nodes.Node; -import org.yaml.snakeyaml.nodes.ScalarNode; -import org.yaml.snakeyaml.nodes.Tag; -import org.yaml.snakeyaml.representer.Representer; - -/** - * Class for creating and reading .container files. - */ - -public final class ContainerDataYaml { - - private static final Logger LOG = - LoggerFactory.getLogger(ContainerDataYaml.class); - - private ContainerDataYaml() { - - } - - /** - * Creates a .container file in yaml format. - * - * @param containerFile - * @param containerData - * @throws IOException - */ - public static void createContainerFile(ContainerType containerType, - ContainerData containerData, File containerFile) throws IOException { - Writer writer = null; - try { - // Create Yaml for given container type - Yaml yaml = getYamlForContainerType(containerType); - // Compute Checksum and update ContainerData - containerData.computeAndSetChecksum(yaml); - - // Write the ContainerData with checksum to Yaml file. - writer = new OutputStreamWriter(new FileOutputStream( - containerFile), "UTF-8"); - yaml.dump(containerData, writer); - - } finally { - try { - if (writer != null) { - writer.close(); - } - } catch (IOException ex) { - LOG.warn("Error occurred during closing the writer. ContainerID: " + - containerData.getContainerID()); - } - } - } - - /** - * Read the yaml file, and return containerData. - * - * @throws IOException - */ - public static ContainerData readContainerFile(File containerFile) - throws IOException { - Preconditions.checkNotNull(containerFile, "containerFile cannot be null"); - try (FileInputStream inputFileStream = new FileInputStream(containerFile)) { - return readContainer(inputFileStream); - } - - } - - /** - * Read the yaml file content, and return containerData. - * - * @throws IOException - */ - public static ContainerData readContainer(byte[] containerFileContent) - throws IOException { - return readContainer( - new ByteArrayInputStream(containerFileContent)); - } - - /** - * Read the yaml content, and return containerData. - * - * @throws IOException - */ - public static ContainerData readContainer(InputStream input) - throws IOException { - - ContainerData containerData; - PropertyUtils propertyUtils = new PropertyUtils(); - propertyUtils.setBeanAccess(BeanAccess.FIELD); - propertyUtils.setAllowReadOnlyProperties(true); - - Representer representer = new ContainerDataRepresenter(); - representer.setPropertyUtils(propertyUtils); - - Constructor containerDataConstructor = new ContainerDataConstructor(); - - Yaml yaml = new Yaml(containerDataConstructor, representer); - yaml.setBeanAccess(BeanAccess.FIELD); - - containerData = (ContainerData) - yaml.load(input); - - return containerData; - } - - /** - * Given a ContainerType this method returns a Yaml representation of - * the container properties. - * - * @param containerType type of container - * @return Yamal representation of container properties - * - * @throws StorageContainerException if the type is unrecognized - */ - public static Yaml getYamlForContainerType(ContainerType containerType) - throws StorageContainerException { - PropertyUtils propertyUtils = new PropertyUtils(); - propertyUtils.setBeanAccess(BeanAccess.FIELD); - propertyUtils.setAllowReadOnlyProperties(true); - - switch (containerType) { - case KeyValueContainer: - Representer representer = new ContainerDataRepresenter(); - representer.setPropertyUtils(propertyUtils); - representer.addClassTag( - KeyValueContainerData.class, - KeyValueContainerData.KEYVALUE_YAML_TAG); - - Constructor keyValueDataConstructor = new ContainerDataConstructor(); - - return new Yaml(keyValueDataConstructor, representer); - default: - throw new StorageContainerException("Unrecognized container Type " + - "format " + containerType, ContainerProtos.Result - .UNKNOWN_CONTAINER_TYPE); - } - } - - /** - * Representer class to define which fields need to be stored in yaml file. - */ - private static class ContainerDataRepresenter extends Representer { - @Override - protected Set getProperties(Class type) - throws IntrospectionException { - Set set = super.getProperties(type); - Set filtered = new TreeSet(); - - // When a new Container type is added, we need to add what fields need - // to be filtered here - if (type.equals(KeyValueContainerData.class)) { - List yamlFields = KeyValueContainerData.getYamlFields(); - // filter properties - for (Property prop : set) { - String name = prop.getName(); - if (yamlFields.contains(name)) { - filtered.add(prop); - } - } - } - return filtered; - } - } - - /** - * Constructor class for KeyValueData, which will be used by Yaml. - */ - private static class ContainerDataConstructor extends Constructor { - ContainerDataConstructor() { - //Adding our own specific constructors for tags. - // When a new Container type is added, we need to add yamlConstructor - // for that - this.yamlConstructors.put( - KEYVALUE_YAML_TAG, new ConstructKeyValueContainerData()); - this.yamlConstructors.put(Tag.INT, new ConstructLong()); - } - - private class ConstructKeyValueContainerData extends AbstractConstruct { - public Object construct(Node node) { - MappingNode mnode = (MappingNode) node; - Map nodes = constructMapping(mnode); - - //Needed this, as TAG.INT type is by default converted to Long. - long layOutVersion = (long) nodes.get(OzoneConsts.LAYOUTVERSION); - int lv = (int) layOutVersion; - - long size = (long) nodes.get(OzoneConsts.MAX_SIZE); - - //When a new field is added, it needs to be added here. - KeyValueContainerData kvData = new KeyValueContainerData( - (long) nodes.get(OzoneConsts.CONTAINER_ID), lv, size); - - kvData.setContainerDBType((String)nodes.get( - OzoneConsts.CONTAINER_DB_TYPE)); - kvData.setMetadataPath((String) nodes.get( - OzoneConsts.METADATA_PATH)); - kvData.setChunksPath((String) nodes.get(OzoneConsts.CHUNKS_PATH)); - Map meta = (Map) nodes.get(OzoneConsts.METADATA); - kvData.setMetadata(meta); - kvData.setChecksum((String) nodes.get(OzoneConsts.CHECKSUM)); - String state = (String) nodes.get(OzoneConsts.STATE); - switch (state) { - case "OPEN": - kvData.setState(ContainerProtos.ContainerLifeCycleState.OPEN); - break; - case "CLOSING": - kvData.setState(ContainerProtos.ContainerLifeCycleState.CLOSING); - break; - case "CLOSED": - kvData.setState(ContainerProtos.ContainerLifeCycleState.CLOSED); - break; - default: - throw new IllegalStateException("Unexpected " + - "ContainerLifeCycleState " + state + " for the containerId " + - nodes.get(OzoneConsts.CONTAINER_ID)); - } - return kvData; - } - } - - //Below code is taken from snake yaml, as snakeyaml tries to fit the - // number if it fits in integer, otherwise returns long. So, slightly - // modified the code to return long in all cases. - private class ConstructLong extends AbstractConstruct { - public Object construct(Node node) { - String value = constructScalar((ScalarNode) node).toString() - .replaceAll("_", ""); - int sign = +1; - char first = value.charAt(0); - if (first == '-') { - sign = -1; - value = value.substring(1); - } else if (first == '+') { - value = value.substring(1); - } - int base = 10; - if ("0".equals(value)) { - return Long.valueOf(0); - } else if (value.startsWith("0b")) { - value = value.substring(2); - base = 2; - } else if (value.startsWith("0x")) { - value = value.substring(2); - base = 16; - } else if (value.startsWith("0")) { - value = value.substring(1); - base = 8; - } else if (value.indexOf(':') != -1) { - String[] digits = value.split(":"); - int bes = 1; - int val = 0; - for (int i = 0, j = digits.length; i < j; i++) { - val += (Long.parseLong(digits[(j - i) - 1]) * bes); - bes *= 60; - } - return createNumber(sign, String.valueOf(val), 10); - } else { - return createNumber(sign, value, 10); - } - return createNumber(sign, value, base); - } - } - - private Number createNumber(int sign, String number, int radix) { - Number result; - if (sign < 0) { - number = "-" + number; - } - result = Long.valueOf(number, radix); - return result; - } - } - -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/ContainerSet.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/ContainerSet.java deleted file mode 100644 index 7f4f147fe39..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/ContainerSet.java +++ /dev/null @@ -1,220 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.impl; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableMap; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerReportsProto; -import org.apache.hadoop.hdds.scm.container.common.helpers - .StorageContainerException; -import org.apache.hadoop.ozone.container.common.interfaces.Container; -import org.apache.hadoop.ozone.container.common - .interfaces.ContainerDeletionChoosingPolicy; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentNavigableMap; -import java.util.concurrent.ConcurrentSkipListMap; -import java.util.stream.Collectors; - - -/** - * Class that manages Containers created on the datanode. - */ -public class ContainerSet { - - private static final Logger LOG = LoggerFactory.getLogger(ContainerSet.class); - - private final ConcurrentSkipListMap containerMap = new - ConcurrentSkipListMap<>(); - - /** - * Add Container to container map. - * @param container - * @return If container is added to containerMap returns true, otherwise - * false - */ - public boolean addContainer(Container container) throws - StorageContainerException { - Preconditions.checkNotNull(container, "container cannot be null"); - - long containerId = container.getContainerData().getContainerID(); - if(containerMap.putIfAbsent(containerId, container) == null) { - LOG.debug("Container with container Id {} is added to containerMap", - containerId); - return true; - } else { - LOG.warn("Container already exists with container Id {}", containerId); - throw new StorageContainerException("Container already exists with " + - "container Id " + containerId, - ContainerProtos.Result.CONTAINER_EXISTS); - } - } - - /** - * Returns the Container with specified containerId. - * @param containerId - * @return Container - */ - public Container getContainer(long containerId) { - Preconditions.checkState(containerId >= 0, - "Container Id cannot be negative."); - return containerMap.get(containerId); - } - - /** - * Removes the Container matching with specified containerId. - * @param containerId - * @return If container is removed from containerMap returns true, otherwise - * false - */ - public boolean removeContainer(long containerId) { - Preconditions.checkState(containerId >= 0, - "Container Id cannot be negative."); - Container removed = containerMap.remove(containerId); - if(removed == null) { - LOG.debug("Container with containerId {} is not present in " + - "containerMap", containerId); - return false; - } else { - LOG.debug("Container with containerId {} is removed from containerMap", - containerId); - return true; - } - } - - /** - * Return number of containers in container map. - * @return container count - */ - @VisibleForTesting - public int containerCount() { - return containerMap.size(); - } - - /** - * Return an container Iterator over {@link ContainerSet#containerMap}. - * @return Iterator - */ - public Iterator getContainerIterator() { - return containerMap.values().iterator(); - } - - /** - * Return an containerMap iterator over {@link ContainerSet#containerMap}. - * @return containerMap Iterator - */ - public Iterator> getContainerMapIterator() { - return containerMap.entrySet().iterator(); - } - - /** - * Return a copy of the containerMap. - * @return containerMap - */ - public Map getContainerMap() { - return ImmutableMap.copyOf(containerMap); - } - - /** - * A simple interface for container Iterations. - *

- * This call make no guarantees about consistency of the data between - * different list calls. It just returns the best known data at that point of - * time. It is possible that using this iteration you can miss certain - * container from the listing. - * - * @param startContainerId - Return containers with Id >= startContainerId. - * @param count - how many to return - * @param data - Actual containerData - * @throws StorageContainerException - */ - public void listContainer(long startContainerId, long count, - List data) throws - StorageContainerException { - Preconditions.checkNotNull(data, - "Internal assertion: data cannot be null"); - Preconditions.checkState(startContainerId >= 0, - "Start container Id cannot be negative"); - Preconditions.checkState(count > 0, - "max number of containers returned " + - "must be positive"); - LOG.debug("listContainer returns containerData starting from {} of count " + - "{}", startContainerId, count); - ConcurrentNavigableMap map; - if (startContainerId == 0) { - map = containerMap.tailMap(containerMap.firstKey(), true); - } else { - map = containerMap.tailMap(startContainerId, true); - } - int currentCount = 0; - for (Container entry : map.values()) { - if (currentCount < count) { - data.add(entry.getContainerData()); - currentCount++; - } else { - return; - } - } - } - - /** - * Get container report. - * - * @return The container report. - * @throws IOException - */ - public ContainerReportsProto getContainerReport() throws IOException { - LOG.debug("Starting container report iteration."); - - // No need for locking since containerMap is a ConcurrentSkipListMap - // And we can never get the exact state since close might happen - // after we iterate a point. - List containers = containerMap.values().stream().collect( - Collectors.toList()); - - ContainerReportsProto.Builder crBuilder = - ContainerReportsProto.newBuilder(); - - for (Container container: containers) { - crBuilder.addReports(container.getContainerReport()); - } - - return crBuilder.build(); - } - - public List chooseContainerForBlockDeletion(int count, - ContainerDeletionChoosingPolicy deletionPolicy) - throws StorageContainerException { - Map containerDataMap = containerMap.entrySet().stream() - .filter(e -> deletionPolicy.isValidContainerType( - e.getValue().getContainerType())) - .collect(Collectors.toMap(Map.Entry::getKey, - e -> e.getValue().getContainerData())); - return deletionPolicy - .chooseContainerForBlockDeletion(count, containerDataMap); - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/HddsDispatcher.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/HddsDispatcher.java deleted file mode 100644 index bb5002ae69e..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/HddsDispatcher.java +++ /dev/null @@ -1,213 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.impl; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import com.google.common.collect.Maps; -import org.apache.hadoop.hdds.HddsConfigKeys; -import org.apache.hadoop.hdds.HddsUtils; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerAction; -import org.apache.hadoop.hdds.scm.container.common.helpers.StorageContainerException; -import org.apache.hadoop.ozone.container.common.helpers.ContainerMetrics; -import org.apache.hadoop.ozone.container.common.helpers.ContainerUtils; -import org.apache.hadoop.ozone.container.common.interfaces.Container; -import org.apache.hadoop.ozone.container.common.interfaces.Handler; -import org.apache.hadoop.ozone.container.common.statemachine.StateContext; -import org.apache.hadoop.ozone.container.common.volume.VolumeSet; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandRequestProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandResponseProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerType; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerLifeCycleState; -import org.apache.hadoop.ozone.container.common.interfaces.ContainerDispatcher; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Map; -import java.util.Optional; - -/** - * Ozone Container dispatcher takes a call from the netty server and routes it - * to the right handler function. - */ -public class HddsDispatcher implements ContainerDispatcher { - - static final Logger LOG = LoggerFactory.getLogger(HddsDispatcher.class); - - private final Map handlers; - private final Configuration conf; - private final ContainerSet containerSet; - private final VolumeSet volumeSet; - private final StateContext context; - private final float containerCloseThreshold; - private String scmID; - private ContainerMetrics metrics; - - /** - * Constructs an OzoneContainer that receives calls from - * XceiverServerHandler. - */ - public HddsDispatcher(Configuration config, ContainerSet contSet, - VolumeSet volumes, StateContext context) { - this.conf = config; - this.containerSet = contSet; - this.volumeSet = volumes; - this.context = context; - this.handlers = Maps.newHashMap(); - this.metrics = ContainerMetrics.create(conf); - for (ContainerType containerType : ContainerType.values()) { - handlers.put(containerType, - Handler.getHandlerForContainerType( - containerType, conf, containerSet, volumeSet, metrics)); - } - this.containerCloseThreshold = conf.getFloat( - HddsConfigKeys.HDDS_CONTAINER_CLOSE_THRESHOLD, - HddsConfigKeys.HDDS_CONTAINER_CLOSE_THRESHOLD_DEFAULT); - - } - - @Override - public void init() { - } - - @Override - public void shutdown() { - // Shutdown the volumes - volumeSet.shutdown(); - } - - @Override - public ContainerCommandResponseProto dispatch( - ContainerCommandRequestProto msg) { - LOG.trace("Command {}, trace ID: {} ", msg.getCmdType().toString(), - msg.getTraceID()); - Preconditions.checkNotNull(msg); - - Container container = null; - ContainerType containerType = null; - ContainerCommandResponseProto responseProto = null; - long startTime = System.nanoTime(); - ContainerProtos.Type cmdType = msg.getCmdType(); - try { - long containerID = msg.getContainerID(); - - metrics.incContainerOpsMetrics(cmdType); - if (cmdType != ContainerProtos.Type.CreateContainer) { - container = getContainer(containerID); - containerType = getContainerType(container); - } else { - if (!msg.hasCreateContainer()) { - return ContainerUtils.malformedRequest(msg); - } - containerType = msg.getCreateContainer().getContainerType(); - } - } catch (StorageContainerException ex) { - return ContainerUtils.logAndReturnError(LOG, ex, msg); - } - // Small performance optimization. We check if the operation is of type - // write before trying to send CloseContainerAction. - if (!HddsUtils.isReadOnly(msg)) { - sendCloseContainerActionIfNeeded(container); - } - Handler handler = getHandler(containerType); - if (handler == null) { - StorageContainerException ex = new StorageContainerException("Invalid " + - "ContainerType " + containerType, - ContainerProtos.Result.CONTAINER_INTERNAL_ERROR); - return ContainerUtils.logAndReturnError(LOG, ex, msg); - } - responseProto = handler.handle(msg, container); - if (responseProto != null) { - metrics.incContainerOpsLatencies(cmdType, System.nanoTime() - startTime); - return responseProto; - } else { - return ContainerUtils.unsupportedRequest(msg); - } - } - - /** - * If the container usage reaches the close threshold we send Close - * ContainerAction to SCM. - * - * @param container current state of container - */ - private void sendCloseContainerActionIfNeeded(Container container) { - // We have to find a more efficient way to close a container. - Boolean isOpen = Optional.ofNullable(container) - .map(cont -> cont.getContainerState() == ContainerLifeCycleState.OPEN) - .orElse(Boolean.FALSE); - if (isOpen) { - ContainerData containerData = container.getContainerData(); - double containerUsedPercentage = 1.0f * containerData.getBytesUsed() / - containerData.getMaxSize(); - if (containerUsedPercentage >= containerCloseThreshold) { - ContainerAction action = ContainerAction.newBuilder() - .setContainerID(containerData.getContainerID()) - .setAction(ContainerAction.Action.CLOSE) - .setReason(ContainerAction.Reason.CONTAINER_FULL) - .build(); - context.addContainerActionIfAbsent(action); - } - } - } - - @Override - public Handler getHandler(ContainerProtos.ContainerType containerType) { - return handlers.get(containerType); - } - - @Override - public void setScmId(String scmId) { - Preconditions.checkNotNull(scmId, "scmId Cannot be null"); - if (this.scmID == null) { - this.scmID = scmId; - for (Map.Entry handlerMap : handlers.entrySet()) { - handlerMap.getValue().setScmID(scmID); - } - } - } - - @VisibleForTesting - public Container getContainer(long containerID) - throws StorageContainerException { - Container container = containerSet.getContainer(containerID); - if (container == null) { - throw new StorageContainerException( - "ContainerID " + containerID + " does not exist", - ContainerProtos.Result.CONTAINER_NOT_FOUND); - } - return container; - } - - private ContainerType getContainerType(Container container) { - return container.getContainerType(); - } - - @VisibleForTesting - public void setMetricsForTesting(ContainerMetrics containerMetrics) { - this.metrics = containerMetrics; - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/OpenContainerBlockMap.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/OpenContainerBlockMap.java deleted file mode 100644 index b736eb536ed..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/OpenContainerBlockMap.java +++ /dev/null @@ -1,151 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.impl; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdds.client.BlockID; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ChunkInfo; -import org.apache.hadoop.ozone.container.common.helpers.BlockData; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.function.Function; - -/** - * Map: containerId {@literal ->} (localId {@literal ->} {@link BlockData}). - * The outer container map does not entail locking for a better performance. - * The inner {@link BlockDataMap} is synchronized. - * - * This class will maintain list of open keys per container when closeContainer - * command comes, it should autocommit all open keys of a open container before - * marking the container as closed. - */ -public class OpenContainerBlockMap { - /** - * Map: localId {@literal ->} BlockData. - * - * In order to support {@link #getAll()}, the update operations are - * synchronized. - */ - static class BlockDataMap { - private final ConcurrentMap blocks = - new ConcurrentHashMap<>(); - - BlockData get(long localId) { - return blocks.get(localId); - } - - synchronized int removeAndGetSize(long localId) { - blocks.remove(localId); - return blocks.size(); - } - - synchronized BlockData computeIfAbsent( - long localId, Function f) { - return blocks.computeIfAbsent(localId, f); - } - - synchronized List getAll() { - return new ArrayList<>(blocks.values()); - } - } - - /** - * TODO : We may construct the openBlockMap by reading the Block Layout - * for each block inside a container listing all chunk files and reading the - * sizes. This will help to recreate the openKeys Map once the DataNode - * restarts. - * - * For now, we will track all open blocks of a container in the blockMap. - */ - private final ConcurrentMap containers = - new ConcurrentHashMap<>(); - - /** - * Removes the Container matching with specified containerId. - * @param containerId containerId - */ - public void removeContainer(long containerId) { - Preconditions - .checkState(containerId >= 0, "Container Id cannot be negative."); - containers.remove(containerId); - } - - public void addChunk(BlockID blockID, ChunkInfo info) { - Preconditions.checkNotNull(info); - containers.computeIfAbsent(blockID.getContainerID(), - id -> new BlockDataMap()).computeIfAbsent(blockID.getLocalID(), - id -> new BlockData(blockID)).addChunk(info); - } - - /** - * Removes the chunk from the chunkInfo list for the given block. - * @param blockID id of the block - * @param chunkInfo chunk info. - */ - public void removeChunk(BlockID blockID, ChunkInfo chunkInfo) { - Preconditions.checkNotNull(chunkInfo); - Preconditions.checkNotNull(blockID); - Optional.ofNullable(containers.get(blockID.getContainerID())) - .map(blocks -> blocks.get(blockID.getLocalID())) - .ifPresent(keyData -> keyData.removeChunk(chunkInfo)); - } - - /** - * Returns the list of open blocks to the openContainerBlockMap. - * @param containerId container id - * @return List of open blocks - */ - public List getOpenBlocks(long containerId) { - return Optional.ofNullable(containers.get(containerId)) - .map(BlockDataMap::getAll) - .orElseGet(Collections::emptyList); - } - - /** - * removes the block from the block map. - * @param blockID - block ID - */ - public void removeFromBlockMap(BlockID blockID) { - Preconditions.checkNotNull(blockID); - containers.computeIfPresent(blockID.getContainerID(), (containerId, blocks) - -> blocks.removeAndGetSize(blockID.getLocalID()) == 0? null: blocks); - } - - /** - * Returns true if the block exists in the map, false otherwise. - * - * @param blockID - Block ID. - * @return True, if it exists, false otherwise - */ - public boolean checkIfBlockExists(BlockID blockID) { - BlockDataMap keyDataMap = containers.get(blockID.getContainerID()); - return keyDataMap != null && keyDataMap.get(blockID.getLocalID()) != null; - } - - @VisibleForTesting - BlockDataMap getBlockDataMap(long containerId) { - return containers.get(containerId); - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/RandomContainerDeletionChoosingPolicy.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/RandomContainerDeletionChoosingPolicy.java deleted file mode 100644 index 5c6c319600e..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/RandomContainerDeletionChoosingPolicy.java +++ /dev/null @@ -1,70 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.common.impl; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdds.scm.container.common.helpers - .StorageContainerException; -import org.apache.hadoop.hdfs.DFSUtil; -import org.apache.hadoop.ozone.container.common.interfaces - .ContainerDeletionChoosingPolicy; -import org.apache.hadoop.ozone.container.keyvalue.KeyValueContainerData; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -/** - * Randomly choosing containers for block deletion. - */ -public class RandomContainerDeletionChoosingPolicy - implements ContainerDeletionChoosingPolicy { - private static final Logger LOG = - LoggerFactory.getLogger(RandomContainerDeletionChoosingPolicy.class); - - @Override - public List chooseContainerForBlockDeletion(int count, - Map candidateContainers) - throws StorageContainerException { - Preconditions.checkNotNull(candidateContainers, - "Internal assertion: candidate containers cannot be null"); - - int currentCount = 0; - List result = new LinkedList<>(); - ContainerData[] values = new ContainerData[candidateContainers.size()]; - // to get a shuffle list - for (ContainerData entry : DFSUtil.shuffle( - candidateContainers.values().toArray(values))) { - if (currentCount < count) { - result.add(entry); - currentCount++; - - LOG.debug("Select container {} for block deletion, " - + "pending deletion blocks num: {}.", - entry.getContainerID(), - ((KeyValueContainerData)entry).getNumPendingDeletionBlocks()); - } else { - break; - } - } - - return result; - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/StorageLocationReport.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/StorageLocationReport.java deleted file mode 100644 index 061d09bd4a5..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/StorageLocationReport.java +++ /dev/null @@ -1,300 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.impl; - -import org.apache.hadoop.fs.StorageType; -import org.apache.hadoop.hdds.protocol.proto. - StorageContainerDatanodeProtocolProtos.StorageReportProto; -import org.apache.hadoop.hdds.protocol.proto. - StorageContainerDatanodeProtocolProtos.StorageTypeProto; -import org.apache.hadoop.ozone.container.common.interfaces - .StorageLocationReportMXBean; - -import java.io.IOException; - -/** - * Storage location stats of datanodes that provide back store for containers. - * - */ -public final class StorageLocationReport implements - StorageLocationReportMXBean { - - private final String id; - private final boolean failed; - private final long capacity; - private final long scmUsed; - private final long remaining; - private final StorageType storageType; - private final String storageLocation; - - private StorageLocationReport(String id, boolean failed, long capacity, - long scmUsed, long remaining, StorageType storageType, - String storageLocation) { - this.id = id; - this.failed = failed; - this.capacity = capacity; - this.scmUsed = scmUsed; - this.remaining = remaining; - this.storageType = storageType; - this.storageLocation = storageLocation; - } - - public String getId() { - return id; - } - - public boolean isFailed() { - return failed; - } - - public long getCapacity() { - return capacity; - } - - public long getScmUsed() { - return scmUsed; - } - - public long getRemaining() { - return remaining; - } - - public String getStorageLocation() { - return storageLocation; - } - - @Override - public String getStorageTypeName() { - return storageType.name(); - } - - public StorageType getStorageType() { - return storageType; - } - - - private StorageTypeProto getStorageTypeProto() throws - IOException { - StorageTypeProto storageTypeProto; - switch (getStorageType()) { - case SSD: - storageTypeProto = StorageTypeProto.SSD; - break; - case DISK: - storageTypeProto = StorageTypeProto.DISK; - break; - case ARCHIVE: - storageTypeProto = StorageTypeProto.ARCHIVE; - break; - case PROVIDED: - storageTypeProto = StorageTypeProto.PROVIDED; - break; - case RAM_DISK: - storageTypeProto = StorageTypeProto.RAM_DISK; - break; - default: - throw new IOException("Illegal Storage Type specified"); - } - return storageTypeProto; - } - - private static StorageType getStorageType(StorageTypeProto proto) throws - IOException { - StorageType storageType; - switch (proto) { - case SSD: - storageType = StorageType.SSD; - break; - case DISK: - storageType = StorageType.DISK; - break; - case ARCHIVE: - storageType = StorageType.ARCHIVE; - break; - case PROVIDED: - storageType = StorageType.PROVIDED; - break; - case RAM_DISK: - storageType = StorageType.RAM_DISK; - break; - default: - throw new IOException("Illegal Storage Type specified"); - } - return storageType; - } - - /** - * Returns the SCMStorageReport protoBuf message for the Storage Location - * report. - * @return SCMStorageReport - * @throws IOException In case, the storage type specified is invalid. - */ - public StorageReportProto getProtoBufMessage() throws IOException{ - StorageReportProto.Builder srb = StorageReportProto.newBuilder(); - return srb.setStorageUuid(getId()) - .setCapacity(getCapacity()) - .setScmUsed(getScmUsed()) - .setRemaining(getRemaining()) - .setStorageType(getStorageTypeProto()) - .setStorageLocation(getStorageLocation()) - .setFailed(isFailed()) - .build(); - } - - /** - * Returns the StorageLocationReport from the protoBuf message. - * @param report SCMStorageReport - * @return StorageLocationReport - * @throws IOException in case of invalid storage type - */ - - public static StorageLocationReport getFromProtobuf(StorageReportProto report) - throws IOException { - StorageLocationReport.Builder builder = StorageLocationReport.newBuilder(); - builder.setId(report.getStorageUuid()) - .setStorageLocation(report.getStorageLocation()); - if (report.hasCapacity()) { - builder.setCapacity(report.getCapacity()); - } - if (report.hasScmUsed()) { - builder.setScmUsed(report.getScmUsed()); - } - if (report.hasStorageType()) { - builder.setStorageType(getStorageType(report.getStorageType())); - } - if (report.hasRemaining()) { - builder.setRemaining(report.getRemaining()); - } - - if (report.hasFailed()) { - builder.setFailed(report.getFailed()); - } - return builder.build(); - } - - /** - * Returns StorageLocation.Builder instance. - * - * @return StorageLocation.Builder - */ - public static Builder newBuilder() { - return new Builder(); - } - - /** - * Builder class for building StorageLocationReport. - */ - public static class Builder { - private String id; - private boolean failed; - private long capacity; - private long scmUsed; - private long remaining; - private StorageType storageType; - private String storageLocation; - - /** - * Sets the storageId. - * - * @param idValue storageId - * @return StorageLocationReport.Builder - */ - public Builder setId(String idValue) { - this.id = idValue; - return this; - } - - /** - * Sets whether the volume failed or not. - * - * @param failedValue whether volume failed or not - * @return StorageLocationReport.Builder - */ - public Builder setFailed(boolean failedValue) { - this.failed = failedValue; - return this; - } - - /** - * Sets the capacity of volume. - * - * @param capacityValue capacity - * @return StorageLocationReport.Builder - */ - public Builder setCapacity(long capacityValue) { - this.capacity = capacityValue; - return this; - } - /** - * Sets the scmUsed Value. - * - * @param scmUsedValue storage space used by scm - * @return StorageLocationReport.Builder - */ - public Builder setScmUsed(long scmUsedValue) { - this.scmUsed = scmUsedValue; - return this; - } - - /** - * Sets the remaining free space value. - * - * @param remainingValue remaining free space - * @return StorageLocationReport.Builder - */ - public Builder setRemaining(long remainingValue) { - this.remaining = remainingValue; - return this; - } - - /** - * Sets the storageType. - * - * @param storageTypeValue type of the storage used - * @return StorageLocationReport.Builder - */ - public Builder setStorageType(StorageType storageTypeValue) { - this.storageType = storageTypeValue; - return this; - } - - /** - * Sets the storageLocation. - * - * @param storageLocationValue location of the volume - * @return StorageLocationReport.Builder - */ - public Builder setStorageLocation(String storageLocationValue) { - this.storageLocation = storageLocationValue; - return this; - } - - /** - * Builds and returns StorageLocationReport instance. - * - * @return StorageLocationReport - */ - public StorageLocationReport build() { - return new StorageLocationReport(id, failed, capacity, scmUsed, - remaining, storageType, storageLocation); - } - - } - -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/TopNOrderedContainerDeletionChoosingPolicy.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/TopNOrderedContainerDeletionChoosingPolicy.java deleted file mode 100644 index b17680c4198..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/TopNOrderedContainerDeletionChoosingPolicy.java +++ /dev/null @@ -1,90 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.common.impl; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdds.scm.container.common.helpers - .StorageContainerException; -import org.apache.hadoop.ozone.container.common.interfaces - .ContainerDeletionChoosingPolicy; -import org.apache.hadoop.ozone.container.keyvalue.KeyValueContainerData; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Collections; -import java.util.Comparator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -/** - * TopN Ordered choosing policy that choosing containers based on pending - * deletion blocks' number. - */ -public class TopNOrderedContainerDeletionChoosingPolicy - implements ContainerDeletionChoosingPolicy { - private static final Logger LOG = - LoggerFactory.getLogger(TopNOrderedContainerDeletionChoosingPolicy.class); - - /** customized comparator used to compare differentiate container data. **/ - private static final Comparator - KEY_VALUE_CONTAINER_DATA_COMPARATOR = (KeyValueContainerData c1, - KeyValueContainerData c2) -> - Integer.compare(c2.getNumPendingDeletionBlocks(), - c1.getNumPendingDeletionBlocks()); - - @Override - public List chooseContainerForBlockDeletion(int count, - Map candidateContainers) - throws StorageContainerException { - Preconditions.checkNotNull(candidateContainers, - "Internal assertion: candidate containers cannot be null"); - - List result = new LinkedList<>(); - List orderedList = new LinkedList<>(); - for (ContainerData entry : candidateContainers.values()) { - orderedList.add((KeyValueContainerData)entry); - } - Collections.sort(orderedList, KEY_VALUE_CONTAINER_DATA_COMPARATOR); - - // get top N list ordered by pending deletion blocks' number - int currentCount = 0; - for (KeyValueContainerData entry : orderedList) { - if (currentCount < count) { - if (entry.getNumPendingDeletionBlocks() > 0) { - result.add(entry); - currentCount++; - - LOG.debug( - "Select container {} for block deletion, " - + "pending deletion blocks num: {}.", - entry.getContainerID(), - entry.getNumPendingDeletionBlocks()); - } else { - LOG.debug("Stop looking for next container, there is no" - + " pending deletion block contained in remaining containers."); - break; - } - } else { - break; - } - } - - return result; - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/package-info.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/package-info.java deleted file mode 100644 index 16da5d9deec..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/package-info.java +++ /dev/null @@ -1,22 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.common.impl; - -/** - This package is contains Ozone container implementation. -**/ \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/BlockIterator.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/BlockIterator.java deleted file mode 100644 index f6931e37a4c..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/BlockIterator.java +++ /dev/null @@ -1,57 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.interfaces; - - -import java.io.IOException; -import java.util.NoSuchElementException; - -/** - * Block Iterator for container. Each container type need to implement this - * interface. - * @param - */ -public interface BlockIterator { - - /** - * This checks if iterator has next element. If it has returns true, - * otherwise false. - * @return boolean - */ - boolean hasNext() throws IOException; - - /** - * Seek to first entry. - */ - void seekToFirst(); - - /** - * Seek to last entry. - */ - void seekToLast(); - - /** - * Get next block in the container. - * @return next block or null if there are no blocks - * @throws IOException - */ - T nextBlock() throws IOException, NoSuchElementException; - - -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/Container.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/Container.java deleted file mode 100644 index 9380f0cb36f..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/Container.java +++ /dev/null @@ -1,135 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.interfaces; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Map; - -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerLifeCycleState; -import org.apache.hadoop.hdds.scm.container.common.helpers - .StorageContainerException; -import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos; - -import org.apache.hadoop.hdfs.util.RwLock; -import org.apache.hadoop.ozone.container.common.impl.ContainerData; -import org.apache.hadoop.ozone.container.common.volume.VolumeSet; - -/** - * Interface for Container Operations. - */ -public interface Container extends RwLock { - - /** - * Creates a container. - * - * @throws StorageContainerException - */ - void create(VolumeSet volumeSet, VolumeChoosingPolicy volumeChoosingPolicy, - String scmId) throws StorageContainerException; - - /** - * Deletes the container. - * - * @param forceDelete - whether this container should be deleted forcibly. - * @throws StorageContainerException - */ - void delete(boolean forceDelete) throws StorageContainerException; - - /** - * Update the container. - * - * @param metaData - * @param forceUpdate if true, update container forcibly. - * @throws StorageContainerException - */ - void update(Map metaData, boolean forceUpdate) - throws StorageContainerException; - - /** - * Get metadata about the container. - * - * @return ContainerData - Container Data. - * @throws StorageContainerException - */ - CONTAINERDATA getContainerData(); - - /** - * Get the Container Lifecycle state. - * - * @return ContainerLifeCycleState - Container State. - * @throws StorageContainerException - */ - ContainerLifeCycleState getContainerState(); - - /** - * Closes a open container, if it is already closed or does not exist a - * StorageContainerException is thrown. - * - * @throws StorageContainerException - */ - void close() throws StorageContainerException; - - /** - * Return the ContainerType for the container. - */ - ContainerProtos.ContainerType getContainerType(); - - /** - * Returns containerFile. - */ - File getContainerFile(); - - /** - * updates the DeleteTransactionId. - * @param deleteTransactionId - */ - void updateDeleteTransactionId(long deleteTransactionId); - - /** - * Returns blockIterator for the container. - * @return BlockIterator - * @throws IOException - */ - BlockIterator blockIterator() throws IOException; - - /** - * Import the container from an external archive. - */ - void importContainerData(InputStream stream, - ContainerPacker packer) throws IOException; - - /** - * Export all the data of the container to one output archive with the help - * of the packer. - * - */ - void exportContainerData(OutputStream stream, - ContainerPacker packer) throws IOException; - - /** - * Returns containerReport for the container. - */ - StorageContainerDatanodeProtocolProtos.ContainerInfo getContainerReport() - throws StorageContainerException; -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/ContainerDeletionChoosingPolicy.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/ContainerDeletionChoosingPolicy.java deleted file mode 100644 index 84c4f903f37..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/ContainerDeletionChoosingPolicy.java +++ /dev/null @@ -1,58 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.common.interfaces; - -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdds.scm.container.common.helpers - .StorageContainerException; -import org.apache.hadoop.ozone.container.common.impl.ContainerData; - -import java.util.List; -import java.util.Map; - -/** - * This interface is used for choosing desired containers for - * block deletion. - */ -public interface ContainerDeletionChoosingPolicy { - - /** - * Chooses desired containers for block deletion. - * @param count - * how many to return - * @param candidateContainers - * candidate containers collection - * @return container data list - * @throws StorageContainerException - */ - List chooseContainerForBlockDeletion(int count, - Map candidateContainers) - throws StorageContainerException; - - /** - * Determine if the container has suitable type for this policy. - * @param type type of the container - * @return whether the container type suitable for this policy. - */ - default boolean isValidContainerType(ContainerProtos.ContainerType type) { - if (type == ContainerProtos.ContainerType.KeyValueContainer) { - return true; - } - return false; - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/ContainerDispatcher.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/ContainerDispatcher.java deleted file mode 100644 index 18644bb9c03..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/ContainerDispatcher.java +++ /dev/null @@ -1,65 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.interfaces; - -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandRequestProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandResponseProto; - -/** - * Dispatcher acts as the bridge between the transport layer and - * the actual container layer. This layer is capable of transforming - * protobuf objects into corresponding class and issue the function call - * into the lower layers. - * - * The reply from the request is dispatched to the client. - */ -public interface ContainerDispatcher { - /** - * Dispatches commands to container layer. - * @param msg - Command Request - * @return Command Response - */ - ContainerCommandResponseProto dispatch(ContainerCommandRequestProto msg); - - /** - * Initialize the Dispatcher. - */ - void init(); - - /** - * Shutdown Dispatcher services. - */ - void shutdown(); - - /** - * Returns the handler for the specified containerType. - * @param containerType - * @return - */ - Handler getHandler(ContainerProtos.ContainerType containerType); - - /** - * If scmId is not set, this will set scmId, otherwise it is a no-op. - * @param scmId - */ - void setScmId(String scmId); -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/ContainerLocationManager.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/ContainerLocationManager.java deleted file mode 100644 index 9c5fcea1639..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/ContainerLocationManager.java +++ /dev/null @@ -1,58 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.common.interfaces; - -import org.apache.hadoop.ozone.container.common.impl.StorageLocationReport; - -import java.io.IOException; -import java.nio.file.Path; - -/** - * Returns physical path locations, where the containers will be created. - */ -public interface ContainerLocationManager { - /** - * Returns the path where the container should be placed from a set of - * locations. - * - * @return A path where we should place this container and metadata. - * @throws IOException - */ - Path getContainerPath() throws IOException; - - /** - * Returns the path where the container Data file are stored. - * - * @return a path where we place the LevelDB and data files of a container. - * @throws IOException - */ - Path getDataPath(String containerName) throws IOException; - - /** - * Returns an array of storage location usage report. - * @return storage location usage report. - */ - StorageLocationReport[] getLocationReport() throws IOException; - - /** - * Supports clean shutdown of container. - * - * @throws IOException - */ - void shutdown() throws IOException; -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/ContainerLocationManagerMXBean.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/ContainerLocationManagerMXBean.java deleted file mode 100644 index 97d2dc3f202..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/ContainerLocationManagerMXBean.java +++ /dev/null @@ -1,34 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.common.interfaces; - -import java.io.IOException; - -/** - * Returns physical path locations, where the containers will be created. - */ -public interface ContainerLocationManagerMXBean { - - /** - * Returns an array of storage location usage report. - * - * @return storage location usage report. - */ - StorageLocationReportMXBean[] getLocationReport() throws IOException; - -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/ContainerPacker.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/ContainerPacker.java deleted file mode 100644 index 8308c23866b..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/ContainerPacker.java +++ /dev/null @@ -1,58 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.interfaces; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import org.apache.hadoop.ozone.container.common.impl.ContainerData; - -/** - * Service to pack/unpack ContainerData container data to/from a single byte - * stream. - */ -public interface ContainerPacker { - - /** - * Extract the container data to the path defined by the container. - *

- * This doesn't contain the extraction of the container descriptor file. - * - * @return the byte content of the descriptor (which won't be written to a - * file but returned). - */ - byte[] unpackContainerData(Container container, - InputStream inputStream) - throws IOException; - - /** - * Compress all the container data (chunk data, metadata db AND container - * descriptor) to one single archive. - */ - void pack(Container container, OutputStream destination) - throws IOException; - - /** - * Read the descriptor from the finished archive to get the data before - * importing the container. - */ - byte[] unpackContainerDescriptor(InputStream inputStream) - throws IOException; -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/Handler.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/Handler.java deleted file mode 100644 index 53e1c68a4ec..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/Handler.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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.interfaces; - - -import java.io.FileInputStream; -import java.io.IOException; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandRequestProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandResponseProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerType; -import org.apache.hadoop.ozone.container.common.helpers.ContainerMetrics; -import org.apache.hadoop.ozone.container.common.impl.ContainerSet; -import org.apache.hadoop.ozone.container.common.volume.VolumeSet; -import org.apache.hadoop.ozone.container.keyvalue.KeyValueHandler; -import org.apache.hadoop.ozone.container.keyvalue.TarContainerPacker; - -/** - * Dispatcher sends ContainerCommandRequests to Handler. Each Container Type - * should have an implementation for Handler. - */ -public abstract class Handler { - - protected final Configuration conf; - protected final ContainerSet containerSet; - protected final VolumeSet volumeSet; - protected String scmID; - protected final ContainerMetrics metrics; - - protected Handler(Configuration config, ContainerSet contSet, - VolumeSet volumeSet, ContainerMetrics containerMetrics) { - conf = config; - containerSet = contSet; - this.volumeSet = volumeSet; - this.metrics = containerMetrics; - } - - public static Handler getHandlerForContainerType(ContainerType containerType, - Configuration config, ContainerSet contSet, VolumeSet volumeSet, - ContainerMetrics metrics) { - switch (containerType) { - case KeyValueContainer: - return new KeyValueHandler(config, contSet, volumeSet, metrics); - default: - throw new IllegalArgumentException("Handler for ContainerType: " + - containerType + "doesn't exist."); - } - } - - public abstract ContainerCommandResponseProto handle( - ContainerCommandRequestProto msg, Container container); - - /** - * Import container data from a raw input stream. - */ - public abstract Container importContainer( - long containerID, - long maxSize, - FileInputStream rawContainerStream, - TarContainerPacker packer) - throws IOException; - - public void setScmID(String scmId) { - this.scmID = scmId; - } - -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/StorageLocationReportMXBean.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/StorageLocationReportMXBean.java deleted file mode 100644 index fd063678137..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/StorageLocationReportMXBean.java +++ /dev/null @@ -1,40 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.interfaces; - -/** - * Contract to define properties available on the JMX interface. - */ -public interface StorageLocationReportMXBean { - - String getId(); - - boolean isFailed(); - - long getCapacity(); - - long getScmUsed(); - - long getRemaining(); - - String getStorageLocation(); - - String getStorageTypeName(); - -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/VolumeChoosingPolicy.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/VolumeChoosingPolicy.java deleted file mode 100644 index 7de0e2a967d..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/VolumeChoosingPolicy.java +++ /dev/null @@ -1,46 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.common.interfaces; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.ozone.container.common.volume.HddsVolume; - -import java.io.IOException; -import java.util.List; - -/** - * This interface specifies the policy for choosing volumes to store replicas. - */ -@InterfaceAudience.Private -public interface VolumeChoosingPolicy { - - /** - * Choose a volume to place a container, - * given a list of volumes and the max container size sought for storage. - * - * The implementations of this interface must be thread-safe. - * - * @param volumes - a list of available volumes. - * @param maxContainerSize - the maximum size of the container for which a - * volume is sought. - * @return the chosen volume. - * @throws IOException when disks are unavailable or are full. - */ - HddsVolume chooseVolume(List volumes, long maxContainerSize) - throws IOException; -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/package-info.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/package-info.java deleted file mode 100644 index d83bf95c362..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/interfaces/package-info.java +++ /dev/null @@ -1,20 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.container.common.interfaces; -/** - This package contains common ozone container interfaces. - */ \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/package-info.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/package-info.java deleted file mode 100644 index 1638a36a13d..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/package-info.java +++ /dev/null @@ -1,28 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.common; -/** - Common Container Layer. At this layer the abstractions are: - - 1. Containers - Both data and metadata containers. - 2. Keys - Key/Value pairs that live inside a container. - 3. Chunks - Keys can be composed of many chunks. - - Ozone uses these abstractions to build Volumes, Buckets and Keys. - - **/ \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/CommandStatusReportPublisher.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/CommandStatusReportPublisher.java deleted file mode 100644 index 47368575c2f..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/CommandStatusReportPublisher.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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.container.common.report; - -import java.util.Iterator; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.CommandStatus.Status; -import org.apache.hadoop.hdds.protocol.proto. - StorageContainerDatanodeProtocolProtos.CommandStatusReportsProto; -import org.apache.hadoop.hdds.scm.HddsServerUtil; -import org.apache.hadoop.ozone.protocol.commands.CommandStatus; - -import static org.apache.hadoop.hdds.HddsConfigKeys - .HDDS_COMMAND_STATUS_REPORT_INTERVAL; -import static org.apache.hadoop.hdds.HddsConfigKeys - .HDDS_COMMAND_STATUS_REPORT_INTERVAL_DEFAULT; - -/** - * Publishes CommandStatusReport which will be sent to SCM as part of - * heartbeat. CommandStatusReport consist of the following information: - * - type : type of command. - * - status : status of command execution (PENDING, EXECUTED, FAILURE). - * - cmdId : Command id. - * - msg : optional message. - */ -public class CommandStatusReportPublisher extends - ReportPublisher { - - private long cmdStatusReportInterval = -1; - - @Override - protected long getReportFrequency() { - if (cmdStatusReportInterval == -1) { - cmdStatusReportInterval = getConf().getTimeDuration( - HDDS_COMMAND_STATUS_REPORT_INTERVAL, - HDDS_COMMAND_STATUS_REPORT_INTERVAL_DEFAULT, - TimeUnit.MILLISECONDS); - - long heartbeatFrequency = HddsServerUtil.getScmHeartbeatInterval( - getConf()); - - Preconditions.checkState( - heartbeatFrequency <= cmdStatusReportInterval, - HDDS_COMMAND_STATUS_REPORT_INTERVAL + - " cannot be configured lower than heartbeat frequency."); - } - return cmdStatusReportInterval; - } - - @Override - protected CommandStatusReportsProto getReport() { - Map map = this.getContext() - .getCommandStatusMap(); - Iterator iterator = map.keySet().iterator(); - CommandStatusReportsProto.Builder builder = CommandStatusReportsProto - .newBuilder(); - - iterator.forEachRemaining(key -> { - CommandStatus cmdStatus = map.get(key); - builder.addCmdStatus(cmdStatus.getProtoBufMessage()); - // If status is still pending then don't remove it from map as - // CommandHandler will change its status when it works on this command. - if (!cmdStatus.getStatus().equals(Status.PENDING)) { - map.remove(key); - } - }); - return builder.getCmdStatusCount() > 0 ? builder.build() : null; - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/ContainerReportPublisher.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/ContainerReportPublisher.java deleted file mode 100644 index ccb9a9aadac..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/ContainerReportPublisher.java +++ /dev/null @@ -1,85 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.container.common.report; - -import com.google.common.base.Preconditions; -import org.apache.commons.lang3.RandomUtils; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerReportsProto; -import org.apache.hadoop.hdds.scm.HddsServerUtil; - -import java.io.IOException; -import java.util.concurrent.TimeUnit; - -import static org.apache.hadoop.hdds.HddsConfigKeys - .HDDS_CONTAINER_REPORT_INTERVAL; -import static org.apache.hadoop.hdds.HddsConfigKeys - .HDDS_CONTAINER_REPORT_INTERVAL_DEFAULT; - - -/** - * Publishes ContainerReport which will be sent to SCM as part of heartbeat. - * ContainerReport consist of the following information about each containers: - * - containerID - * - size - * - used - * - keyCount - * - readCount - * - writeCount - * - readBytes - * - writeBytes - * - finalHash - * - LifeCycleState - * - */ -public class ContainerReportPublisher extends - ReportPublisher { - - private Long containerReportInterval = null; - - @Override - protected long getReportFrequency() { - if (containerReportInterval == null) { - containerReportInterval = getConf().getTimeDuration( - HDDS_CONTAINER_REPORT_INTERVAL, - HDDS_CONTAINER_REPORT_INTERVAL_DEFAULT, - TimeUnit.MILLISECONDS); - - long heartbeatFrequency = HddsServerUtil.getScmHeartbeatInterval( - getConf()); - - Preconditions.checkState( - heartbeatFrequency <= containerReportInterval, - HDDS_CONTAINER_REPORT_INTERVAL + - " cannot be configured lower than heartbeat frequency."); - } - // Add a random delay (0~30s) on top of the container report - // interval (60s) so tha the SCM is overwhelmed by the container reports - // sent in sync. - return containerReportInterval + getRandomReportDelay(); - } - - private long getRandomReportDelay() { - return RandomUtils.nextLong(0, containerReportInterval); - } - - @Override - protected ContainerReportsProto getReport() throws IOException { - return getContext().getParent().getContainer().getContainerReport(); - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/NodeReportPublisher.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/NodeReportPublisher.java deleted file mode 100644 index 6ac99dd4d32..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/NodeReportPublisher.java +++ /dev/null @@ -1,66 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.container.common.report; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.NodeReportProto; -import org.apache.hadoop.hdds.scm.HddsServerUtil; - -import java.io.IOException; -import java.util.concurrent.TimeUnit; - -import static org.apache.hadoop.hdds.HddsConfigKeys - .HDDS_NODE_REPORT_INTERVAL; -import static org.apache.hadoop.hdds.HddsConfigKeys - .HDDS_NODE_REPORT_INTERVAL_DEFAULT; - -/** - * Publishes NodeReport which will be sent to SCM as part of heartbeat. - * NodeReport consist of: - * - NodeIOStats - * - VolumeReports - */ -public class NodeReportPublisher extends ReportPublisher { - - private Long nodeReportInterval; - - @Override - protected long getReportFrequency() { - if (nodeReportInterval == null) { - nodeReportInterval = getConf().getTimeDuration( - HDDS_NODE_REPORT_INTERVAL, - HDDS_NODE_REPORT_INTERVAL_DEFAULT, - TimeUnit.MILLISECONDS); - - long heartbeatFrequency = HddsServerUtil.getScmHeartbeatInterval( - getConf()); - - Preconditions.checkState( - heartbeatFrequency <= nodeReportInterval, - HDDS_NODE_REPORT_INTERVAL + - " cannot be configured lower than heartbeat frequency."); - } - return nodeReportInterval; - } - - @Override - protected NodeReportProto getReport() throws IOException { - return getContext().getParent().getContainer().getNodeReport(); - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/PipelineReportPublisher.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/PipelineReportPublisher.java deleted file mode 100644 index e7f4347e9e4..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/PipelineReportPublisher.java +++ /dev/null @@ -1,73 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.container.common.report; - -import com.google.common.base.Preconditions; -import org.apache.commons.lang3.RandomUtils; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.PipelineReportsProto; -import org.apache.hadoop.hdds.scm.HddsServerUtil; - -import java.util.concurrent.TimeUnit; - -import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_PIPELINE_REPORT_INTERVAL; -import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_PIPELINE_REPORT_INTERVAL_DEFAULT; - - -/** - * Publishes Pipeline which will be sent to SCM as part of heartbeat. - * PipelineReport consist of the following information about each containers: - * - pipelineID - * - */ -public class PipelineReportPublisher extends - ReportPublisher { - - private Long pipelineReportInterval = null; - - @Override - protected long getReportFrequency() { - if (pipelineReportInterval == null) { - pipelineReportInterval = getConf().getTimeDuration( - HDDS_PIPELINE_REPORT_INTERVAL, - HDDS_PIPELINE_REPORT_INTERVAL_DEFAULT, - TimeUnit.MILLISECONDS); - - long heartbeatFrequency = HddsServerUtil.getScmHeartbeatInterval( - getConf()); - - Preconditions.checkState( - heartbeatFrequency <= pipelineReportInterval, - HDDS_PIPELINE_REPORT_INTERVAL + - " cannot be configured lower than heartbeat frequency."); - } - // Add a random delay (0~30s) on top of the pipeline report - // interval (60s) so tha the SCM is overwhelmed by the pipeline reports - // sent in sync. - return pipelineReportInterval + getRandomReportDelay(); - } - - private long getRandomReportDelay() { - return RandomUtils.nextLong(0, pipelineReportInterval); - } - - @Override - protected PipelineReportsProto getReport() { - return getContext().getParent().getContainer().getPipelineReport(); - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/ReportManager.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/ReportManager.java deleted file mode 100644 index 8097cd6364e..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/ReportManager.java +++ /dev/null @@ -1,148 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.container.common.report; - -import com.google.common.base.Preconditions; -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import com.google.protobuf.GeneratedMessage; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.ozone.container.common.statemachine.StateContext; -import org.apache.hadoop.util.concurrent.HadoopExecutors; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ScheduledExecutorService; - -/** - * ReportManager is responsible for managing all the {@link ReportPublisher} - * and also provides {@link ScheduledExecutorService} to ReportPublisher - * which should be used for scheduling the reports. - */ -public final class ReportManager { - - private final StateContext context; - private final List publishers; - private final ScheduledExecutorService executorService; - - /** - * Construction of {@link ReportManager} should be done via - * {@link ReportManager.Builder}. - * - * @param context StateContext which holds the report - * @param publishers List of publishers which generates report - */ - private ReportManager(StateContext context, - List publishers) { - this.context = context; - this.publishers = publishers; - this.executorService = HadoopExecutors.newScheduledThreadPool( - publishers.size(), - new ThreadFactoryBuilder().setDaemon(true) - .setNameFormat("Datanode ReportManager Thread - %d").build()); - } - - /** - * Initializes ReportManager, also initializes all the configured - * report publishers. - */ - public void init() { - for (ReportPublisher publisher : publishers) { - publisher.init(context, executorService); - } - } - - /** - * Shutdown the ReportManager. - */ - public void shutdown() { - executorService.shutdown(); - } - - /** - * Returns new {@link ReportManager.Builder} which can be used to construct. - * {@link ReportManager} - * @param conf - Conf - * @return builder - Builder. - */ - public static Builder newBuilder(Configuration conf) { - return new Builder(conf); - } - - /** - * Builder to construct {@link ReportManager}. - */ - public static final class Builder { - - private StateContext stateContext; - private List reportPublishers; - private ReportPublisherFactory publisherFactory; - - - private Builder(Configuration conf) { - this.reportPublishers = new ArrayList<>(); - this.publisherFactory = new ReportPublisherFactory(conf); - } - - /** - * Sets the {@link StateContext}. - * - * @param context StateContext - - * @return ReportManager.Builder - */ - public Builder setStateContext(StateContext context) { - stateContext = context; - return this; - } - - /** - * Adds publisher for the corresponding report. - * - * @param report report for which publisher needs to be added - * - * @return ReportManager.Builder - */ - public Builder addPublisherFor(Class report) { - reportPublishers.add(publisherFactory.getPublisherFor(report)); - return this; - } - - /** - * Adds new ReportPublisher to the ReportManager. - * - * @param publisher ReportPublisher - * - * @return ReportManager.Builder - */ - public Builder addPublisher(ReportPublisher publisher) { - reportPublishers.add(publisher); - return this; - } - - /** - * Build and returns ReportManager. - * - * @return {@link ReportManager} - */ - public ReportManager build() { - Preconditions.checkNotNull(stateContext); - return new ReportManager(stateContext, reportPublishers); - } - - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/ReportPublisher.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/ReportPublisher.java deleted file mode 100644 index e3910dbda1a..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/ReportPublisher.java +++ /dev/null @@ -1,115 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.container.common.report; - -import com.google.protobuf.GeneratedMessage; -import org.apache.hadoop.conf.Configurable; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.ozone.container.common.statemachine - .DatanodeStateMachine.DatanodeStates; -import org.apache.hadoop.ozone.container.common.statemachine.StateContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -/** - * Abstract class responsible for scheduling the reports based on the - * configured interval. All the ReportPublishers should extend this class. - */ -public abstract class ReportPublisher - implements Configurable, Runnable { - - private static final Logger LOG = LoggerFactory.getLogger( - ReportPublisher.class); - - private Configuration config; - private StateContext context; - private ScheduledExecutorService executor; - - /** - * Initializes ReportPublisher with stateContext and executorService. - * - * @param stateContext Datanode state context - * @param executorService ScheduledExecutorService to schedule reports - */ - public void init(StateContext stateContext, - ScheduledExecutorService executorService) { - this.context = stateContext; - this.executor = executorService; - this.executor.schedule(this, - getReportFrequency(), TimeUnit.MILLISECONDS); - } - - @Override - public void setConf(Configuration conf) { - config = conf; - } - - @Override - public Configuration getConf() { - return config; - } - - @Override - public void run() { - publishReport(); - if (!executor.isShutdown() || - !(context.getState() == DatanodeStates.SHUTDOWN)) { - executor.schedule(this, - getReportFrequency(), TimeUnit.MILLISECONDS); - } - } - - /** - * Generates and publishes the report to datanode state context. - */ - private void publishReport() { - try { - context.addReport(getReport()); - } catch (IOException e) { - LOG.error("Exception while publishing report.", e); - } - } - - /** - * Returns the frequency in which this particular report has to be scheduled. - * - * @return report interval in milliseconds - */ - protected abstract long getReportFrequency(); - - /** - * Generate and returns the report which has to be sent as part of heartbeat. - * - * @return datanode report - */ - protected abstract T getReport() throws IOException; - - /** - * Returns {@link StateContext}. - * - * @return stateContext report - */ - protected StateContext getContext() { - return context; - } - -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/ReportPublisherFactory.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/ReportPublisherFactory.java deleted file mode 100644 index 1c456a0519b..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/ReportPublisherFactory.java +++ /dev/null @@ -1,79 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.container.common.report; - -import com.google.protobuf.GeneratedMessage; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.protocol.proto. - StorageContainerDatanodeProtocolProtos.PipelineReportsProto; -import org.apache.hadoop.hdds.protocol.proto. - StorageContainerDatanodeProtocolProtos.CommandStatusReportsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerReportsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.NodeReportProto; -import org.apache.hadoop.util.ReflectionUtils; - -import java.util.HashMap; -import java.util.Map; - -/** - * Factory class to construct {@link ReportPublisher} for a report. - */ -public class ReportPublisherFactory { - - private final Configuration conf; - private final Map, - Class> report2publisher; - - /** - * Constructs {@link ReportPublisherFactory} instance. - * - * @param conf Configuration to be passed to the {@link ReportPublisher} - */ - public ReportPublisherFactory(Configuration conf) { - this.conf = conf; - this.report2publisher = new HashMap<>(); - - report2publisher.put(NodeReportProto.class, NodeReportPublisher.class); - report2publisher.put(ContainerReportsProto.class, - ContainerReportPublisher.class); - report2publisher.put(CommandStatusReportsProto.class, - CommandStatusReportPublisher.class); - report2publisher.put(PipelineReportsProto.class, - PipelineReportPublisher.class); - } - - /** - * Returns the ReportPublisher for the corresponding report. - * - * @param report report - * - * @return report publisher - */ - public ReportPublisher getPublisherFor( - Class report) { - Class publisherClass = - report2publisher.get(report); - if (publisherClass == null) { - throw new RuntimeException("No publisher found for report " + report); - } - return ReflectionUtils.newInstance(publisherClass, conf); - } - -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/package-info.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/package-info.java deleted file mode 100644 index 404b37a7b08..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/report/package-info.java +++ /dev/null @@ -1,80 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.common.report; -/** - * Datanode Reports: As part of heartbeat, datanode has to share its current - * state with SCM. The state of datanode is split into multiple reports which - * are sent along with heartbeat in a configured frequency. - * - * This package contains code which is responsible for sending reports from - * datanode to SCM. - * - * ReportPublisherFactory: Given a report this constructs corresponding - * {@link org.apache.hadoop.ozone.container.common.report.ReportPublisher}. - * - * ReportManager: Manages and initializes all the available ReportPublishers. - * - * ReportPublisher: Abstract class responsible for scheduling the reports - * based on the configured interval. All the ReportPublishers should extend - * {@link org.apache.hadoop.ozone.container.common.report.ReportPublisher} - * - * How to add new report: - * - * 1. Create a new ReportPublisher class which extends - * {@link org.apache.hadoop.ozone.container.common.report.ReportPublisher}. - * - * 2. Add a mapping Report to ReportPublisher entry in ReportPublisherFactory. - * - * 3. In DatanodeStateMachine add the report to ReportManager instance. - * - * - * - * Datanode Reports State Diagram: - * - * DatanodeStateMachine ReportManager ReportPublisher SCM - * | | | | - * | | | | - * | construct | | | - * |----------------->| | | - * | | | | - * | init | | | - * |----------------->| | | - * | | init | | - * | |------------->| | - * | | | | - * +--------+------------------+--------------+--------------------+------+ - * |loop | | | | | - * | | | publish | | | - * | |<-----------------+--------------| | | - * | | | report | | | - * | | | | | | - * | | | | | | - * | | heartbeat(rpc) | | | | - * | |------------------+--------------+------------------->| | - * | | | | | | - * | | | | | | - * +--------+------------------+--------------+--------------------+------+ - * | | | | - * | | | | - * | | | | - * | shutdown | | | - * |----------------->| | | - * | | | | - * | | | | - * - - - - - */ \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/DatanodeStateMachine.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/DatanodeStateMachine.java deleted file mode 100644 index 1bade8e279a..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/DatanodeStateMachine.java +++ /dev/null @@ -1,434 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.container.common.statemachine; - -import java.io.Closeable; -import java.io.IOException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.CommandStatusReportsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerReportsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.NodeReportProto; -import org.apache.hadoop.ozone.container.common.report.ReportManager; -import org.apache.hadoop.ozone.container.common.statemachine.commandhandler - .CloseContainerCommandHandler; -import org.apache.hadoop.ozone.container.common.statemachine.commandhandler - .CommandDispatcher; -import org.apache.hadoop.ozone.container.common.statemachine.commandhandler - .DeleteBlocksCommandHandler; -import org.apache.hadoop.ozone.container.common.statemachine.commandhandler - .ReplicateContainerCommandHandler; -import org.apache.hadoop.ozone.container.keyvalue.TarContainerPacker; -import org.apache.hadoop.ozone.container.ozoneimpl.OzoneContainer; -import org.apache.hadoop.ozone.container.replication.ContainerReplicator; -import org.apache.hadoop.ozone.container.replication.DownloadAndImportReplicator; -import org.apache.hadoop.ozone.container.replication.ReplicationSupervisor; -import org.apache.hadoop.ozone.container.replication.SimpleContainerDownloader; -import org.apache.hadoop.ozone.protocol.commands.SCMCommand; -import org.apache.hadoop.util.Time; -import org.apache.hadoop.util.concurrent.HadoopExecutors; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * State Machine Class. - */ -public class DatanodeStateMachine implements Closeable { - @VisibleForTesting - static final Logger LOG = - LoggerFactory.getLogger(DatanodeStateMachine.class); - private final ExecutorService executorService; - private final Configuration conf; - private final SCMConnectionManager connectionManager; - private StateContext context; - private final OzoneContainer container; - private DatanodeDetails datanodeDetails; - private final CommandDispatcher commandDispatcher; - private final ReportManager reportManager; - private long commandsHandled; - private AtomicLong nextHB; - private Thread stateMachineThread = null; - private Thread cmdProcessThread = null; - private final ReplicationSupervisor supervisor; - - /** - * Constructs a a datanode state machine. - * - * @param datanodeDetails - DatanodeDetails used to identify a datanode - * @param conf - Configuration. - */ - public DatanodeStateMachine(DatanodeDetails datanodeDetails, - Configuration conf) throws IOException { - this.conf = conf; - this.datanodeDetails = datanodeDetails; - executorService = HadoopExecutors.newCachedThreadPool( - new ThreadFactoryBuilder().setDaemon(true) - .setNameFormat("Datanode State Machine Thread - %d").build()); - connectionManager = new SCMConnectionManager(conf); - context = new StateContext(this.conf, DatanodeStates.getInitState(), this); - container = new OzoneContainer(this.datanodeDetails, - new OzoneConfiguration(conf), context); - nextHB = new AtomicLong(Time.monotonicNow()); - - ContainerReplicator replicator = - new DownloadAndImportReplicator(container.getContainerSet(), - container.getDispatcher(), - new SimpleContainerDownloader(conf), new TarContainerPacker()); - - supervisor = - new ReplicationSupervisor(container.getContainerSet(), replicator, 10); - - // When we add new handlers just adding a new handler here should do the - // trick. - commandDispatcher = CommandDispatcher.newBuilder() - .addHandler(new CloseContainerCommandHandler()) - .addHandler(new DeleteBlocksCommandHandler(container.getContainerSet(), - conf)) - .addHandler(new ReplicateContainerCommandHandler(conf, supervisor)) - .setConnectionManager(connectionManager) - .setContainer(container) - .setContext(context) - .build(); - - reportManager = ReportManager.newBuilder(conf) - .setStateContext(context) - .addPublisherFor(NodeReportProto.class) - .addPublisherFor(ContainerReportsProto.class) - .addPublisherFor(CommandStatusReportsProto.class) - .build(); - } - - /** - * - * Return DatanodeDetails if set, return null otherwise. - * - * @return DatanodeDetails - */ - public DatanodeDetails getDatanodeDetails() { - return datanodeDetails; - } - - - /** - * Returns the Connection manager for this state machine. - * - * @return - SCMConnectionManager. - */ - public SCMConnectionManager getConnectionManager() { - return connectionManager; - } - - public OzoneContainer getContainer() { - return this.container; - } - - /** - * Runs the state machine at a fixed frequency. - */ - private void start() throws IOException { - long now = 0; - - container.start(); - reportManager.init(); - initCommandHandlerThread(conf); - while (context.getState() != DatanodeStates.SHUTDOWN) { - try { - LOG.debug("Executing cycle Number : {}", context.getExecutionCount()); - long heartbeatFrequency = context.getHeartbeatFrequency(); - nextHB.set(Time.monotonicNow() + heartbeatFrequency); - context.execute(executorService, heartbeatFrequency, - TimeUnit.MILLISECONDS); - now = Time.monotonicNow(); - if (now < nextHB.get()) { - Thread.sleep(nextHB.get() - now); - } - } catch (InterruptedException e) { - // Ignore this exception. - } catch (Exception e) { - LOG.error("Unable to finish the execution.", e); - } - } - } - - /** - * Gets the current context. - * - * @return StateContext - */ - public StateContext getContext() { - return context; - } - - /** - * Sets the current context. - * - * @param context - Context - */ - public void setContext(StateContext context) { - this.context = context; - } - - /** - * Closes this stream and releases any system resources associated with it. If - * the stream is already closed then invoking this method has no effect. - *

- *

As noted in {@link AutoCloseable#close()}, cases where the close may - * fail require careful attention. It is strongly advised to relinquish the - * underlying resources and to internally mark the {@code Closeable} - * as closed, prior to throwing the {@code IOException}. - * - * @throws IOException if an I/O error occurs - */ - @Override - public void close() throws IOException { - if (stateMachineThread != null) { - stateMachineThread.interrupt(); - } - if (cmdProcessThread != null) { - cmdProcessThread.interrupt(); - } - context.setState(DatanodeStates.getLastState()); - executorService.shutdown(); - try { - if (!executorService.awaitTermination(5, TimeUnit.SECONDS)) { - executorService.shutdownNow(); - } - - if (!executorService.awaitTermination(5, TimeUnit.SECONDS)) { - LOG.error("Unable to shutdown state machine properly."); - } - } catch (InterruptedException e) { - LOG.error("Error attempting to shutdown.", e); - executorService.shutdownNow(); - Thread.currentThread().interrupt(); - } - - if (connectionManager != null) { - connectionManager.close(); - } - - if(container != null) { - container.stop(); - } - } - - /** - * States that a datanode can be in. GetNextState will move this enum from - * getInitState to getLastState. - */ - public enum DatanodeStates { - INIT(1), - RUNNING(2), - SHUTDOWN(3); - private final int value; - - /** - * Constructs states. - * - * @param value Enum Value - */ - DatanodeStates(int value) { - this.value = value; - } - - /** - * Returns the first State. - * - * @return First State. - */ - public static DatanodeStates getInitState() { - return INIT; - } - - /** - * The last state of endpoint states. - * - * @return last state. - */ - public static DatanodeStates getLastState() { - return SHUTDOWN; - } - - /** - * returns the numeric value associated with the endPoint. - * - * @return int. - */ - public int getValue() { - return value; - } - - /** - * Returns the next logical state that endPoint should move to. This - * function assumes the States are sequentially numbered. - * - * @return NextState. - */ - public DatanodeStates getNextState() { - if (this.value < getLastState().getValue()) { - int stateValue = this.getValue() + 1; - for (DatanodeStates iter : values()) { - if (stateValue == iter.getValue()) { - return iter; - } - } - } - return getLastState(); - } - } - - /** - * Start datanode state machine as a single thread daemon. - */ - public void startDaemon() { - Runnable startStateMachineTask = () -> { - try { - supervisor.start(); - start(); - LOG.info("Ozone container server started."); - } catch (Exception ex) { - LOG.error("Unable to start the DatanodeState Machine", ex); - } - }; - stateMachineThread = new ThreadFactoryBuilder() - .setDaemon(true) - .setNameFormat("Datanode State Machine Thread - %d") - .build().newThread(startStateMachineTask); - stateMachineThread.start(); - } - - /** - * Waits for DatanodeStateMachine to exit. - * - * @throws InterruptedException - */ - public void join() throws InterruptedException { - stateMachineThread.join(); - cmdProcessThread.join(); - } - - /** - * Stop the daemon thread of the datanode state machine. - */ - public synchronized void stopDaemon() { - try { - supervisor.stop(); - context.setState(DatanodeStates.SHUTDOWN); - reportManager.shutdown(); - this.close(); - LOG.info("Ozone container server stopped."); - } catch (IOException e) { - LOG.error("Stop ozone container server failed.", e); - } - } - - /** - * - * Check if the datanode state machine daemon is stopped. - * - * @return True if datanode state machine daemon is stopped - * and false otherwise. - */ - @VisibleForTesting - public boolean isDaemonStopped() { - return this.executorService.isShutdown() - && this.getContext().getExecutionCount() == 0 - && this.getContext().getState() == DatanodeStates.SHUTDOWN; - } - - /** - * Create a command handler thread. - * - * @param config - */ - private void initCommandHandlerThread(Configuration config) { - - /** - * Task that periodically checks if we have any outstanding commands. - * It is assumed that commands can be processed slowly and in order. - * This assumption might change in future. Right now due to this assumption - * we have single command queue process thread. - */ - Runnable processCommandQueue = () -> { - long now; - while (getContext().getState() != DatanodeStates.SHUTDOWN) { - SCMCommand command = getContext().getNextCommand(); - if (command != null) { - commandDispatcher.handle(command); - commandsHandled++; - } else { - try { - // Sleep till the next HB + 1 second. - now = Time.monotonicNow(); - if (nextHB.get() > now) { - Thread.sleep((nextHB.get() - now) + 1000L); - } - } catch (InterruptedException e) { - // Ignore this exception. - } - } - } - }; - - // We will have only one thread for command processing in a datanode. - cmdProcessThread = getCommandHandlerThread(processCommandQueue); - cmdProcessThread.start(); - } - - private Thread getCommandHandlerThread(Runnable processCommandQueue) { - Thread handlerThread = new Thread(processCommandQueue); - handlerThread.setDaemon(true); - handlerThread.setName("Command processor thread"); - handlerThread.setUncaughtExceptionHandler((Thread t, Throwable e) -> { - // Let us just restart this thread after logging a critical error. - // if this thread is not running we cannot handle commands from SCM. - LOG.error("Critical Error : Command processor thread encountered an " + - "error. Thread: {}", t.toString(), e); - getCommandHandlerThread(processCommandQueue).start(); - }); - return handlerThread; - } - - /** - * Returns the number of commands handled by the datanode. - * @return count - */ - @VisibleForTesting - public long getCommandHandled() { - return commandsHandled; - } - - /** - * returns the Command Dispatcher. - * @return CommandDispatcher - */ - @VisibleForTesting - public CommandDispatcher getCommandDispatcher() { - return commandDispatcher; - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/EndpointStateMachine.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/EndpointStateMachine.java deleted file mode 100644 index 5f78a333d98..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/EndpointStateMachine.java +++ /dev/null @@ -1,295 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.container.common.statemachine; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.ozone.protocol.VersionResponse; -import org.apache.hadoop.ozone.protocolPB - .StorageContainerDatanodeProtocolClientSideTranslatorPB; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.Closeable; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.time.ZonedDateTime; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -import static org.apache.hadoop.hdds.scm.HddsServerUtil.getLogWarnInterval; -import static org.apache.hadoop.hdds.scm.HddsServerUtil.getScmHeartbeatInterval; - -/** - * Endpoint is used as holder class that keeps state around the RPC endpoint. - */ -public class EndpointStateMachine - implements Closeable, EndpointStateMachineMBean { - static final Logger - LOG = LoggerFactory.getLogger(EndpointStateMachine.class); - private final StorageContainerDatanodeProtocolClientSideTranslatorPB endPoint; - private final AtomicLong missedCount; - private final InetSocketAddress address; - private final Lock lock; - private final Configuration conf; - private EndPointStates state; - private VersionResponse version; - private ZonedDateTime lastSuccessfulHeartbeat; - - /** - * Constructs RPC Endpoints. - * - * @param endPoint - RPC endPoint. - */ - public EndpointStateMachine(InetSocketAddress address, - StorageContainerDatanodeProtocolClientSideTranslatorPB endPoint, - Configuration conf) { - this.endPoint = endPoint; - this.missedCount = new AtomicLong(0); - this.address = address; - state = EndPointStates.getInitState(); - lock = new ReentrantLock(); - this.conf = conf; - } - - /** - * Takes a lock on this EndPoint so that other threads don't use this while we - * are trying to communicate via this endpoint. - */ - public void lock() { - lock.lock(); - } - - /** - * Unlocks this endpoint. - */ - public void unlock() { - lock.unlock(); - } - - /** - * Returns the version that we read from the server if anyone asks . - * - * @return - Version Response. - */ - public VersionResponse getVersion() { - return version; - } - - /** - * Sets the Version reponse we recieved from the SCM. - * - * @param version VersionResponse - */ - public void setVersion(VersionResponse version) { - this.version = version; - } - - /** - * Returns the current State this end point is in. - * - * @return - getState. - */ - public EndPointStates getState() { - return state; - } - - @Override - public int getVersionNumber() { - if (version != null) { - return version.getProtobufMessage().getSoftwareVersion(); - } else { - return -1; - } - } - - /** - * Sets the endpoint state. - * - * @param epState - end point state. - */ - public EndPointStates setState(EndPointStates epState) { - this.state = epState; - return this.state; - } - - /** - * Closes the connection. - * - * @throws IOException - */ - @Override - public void close() throws IOException { - if (endPoint != null) { - endPoint.close(); - } - } - - /** - * We maintain a count of how many times we missed communicating with a - * specific SCM. This is not made atomic since the access to this is always - * guarded by the read or write lock. That is, it is serialized. - */ - public void incMissed() { - this.missedCount.incrementAndGet(); - } - - /** - * Returns the value of the missed count. - * - * @return int - */ - public long getMissedCount() { - return this.missedCount.get(); - } - - @Override - public String getAddressString() { - return getAddress().toString(); - } - - public void zeroMissedCount() { - this.missedCount.set(0); - } - - /** - * Returns the InetAddress of the endPoint. - * - * @return - EndPoint. - */ - public InetSocketAddress getAddress() { - return this.address; - } - - /** - * Returns real RPC endPoint. - * - * @return rpc client. - */ - public StorageContainerDatanodeProtocolClientSideTranslatorPB - getEndPoint() { - return endPoint; - } - - /** - * Returns the string that represents this endpoint. - * - * @return - String - */ - public String toString() { - return address.toString(); - } - - /** - * Logs exception if needed. - * @param ex - Exception - */ - public void logIfNeeded(Exception ex) { - LOG.trace("Incrementing the Missed count. Ex : {}", ex); - this.incMissed(); - if (this.getMissedCount() % getLogWarnInterval(conf) == - 0) { - LOG.error( - "Unable to communicate to SCM server at {} for past {} seconds.", - this.getAddress().getHostString() + ":" + this.getAddress().getPort(), - TimeUnit.MILLISECONDS.toSeconds( - this.getMissedCount() * getScmHeartbeatInterval(this.conf)), ex); - } - } - - - /** - * States that an Endpoint can be in. - *

- * This is a sorted list of states that EndPoint will traverse. - *

- * GetNextState will move this enum from getInitState to getLastState. - */ - public enum EndPointStates { - GETVERSION(1), - REGISTER(2), - HEARTBEAT(3), - SHUTDOWN(4); // if you add value after this please edit getLastState too. - private final int value; - - /** - * Constructs endPointStates. - * - * @param value state. - */ - EndPointStates(int value) { - this.value = value; - } - - /** - * Returns the first State. - * - * @return First State. - */ - public static EndPointStates getInitState() { - return GETVERSION; - } - - /** - * The last state of endpoint states. - * - * @return last state. - */ - public static EndPointStates getLastState() { - return SHUTDOWN; - } - - /** - * returns the numeric value associated with the endPoint. - * - * @return int. - */ - public int getValue() { - return value; - } - - /** - * Returns the next logical state that endPoint should move to. - * The next state is computed by adding 1 to the current state. - * - * @return NextState. - */ - public EndPointStates getNextState() { - if (this.getValue() < getLastState().getValue()) { - int stateValue = this.getValue() + 1; - for (EndPointStates iter : values()) { - if (stateValue == iter.getValue()) { - return iter; - } - } - } - return getLastState(); - } - } - - public long getLastSuccessfulHeartbeat() { - return lastSuccessfulHeartbeat == null ? - 0 : - lastSuccessfulHeartbeat.toEpochSecond(); - } - - public void setLastSuccessfulHeartbeat( - ZonedDateTime lastSuccessfulHeartbeat) { - this.lastSuccessfulHeartbeat = lastSuccessfulHeartbeat; - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/EndpointStateMachineMBean.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/EndpointStateMachineMBean.java deleted file mode 100644 index 4f64bde0b3e..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/EndpointStateMachineMBean.java +++ /dev/null @@ -1,34 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.container.common.statemachine; - - -/** - * JMX representation of an EndpointStateMachine. - */ -public interface EndpointStateMachineMBean { - - long getMissedCount(); - - String getAddressString(); - - EndpointStateMachine.EndPointStates getState(); - - int getVersionNumber(); - - long getLastSuccessfulHeartbeat(); -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/SCMConnectionManager.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/SCMConnectionManager.java deleted file mode 100644 index 775a91a3d4f..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/SCMConnectionManager.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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.container.common.statemachine; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.io.IOUtils; -import org.apache.hadoop.ipc.ProtobufRpcEngine; -import org.apache.hadoop.ipc.RPC; -import org.apache.hadoop.metrics2.util.MBeans; -import org.apache.hadoop.net.NetUtils; -import org.apache.hadoop.ozone.protocolPB - .StorageContainerDatanodeProtocolClientSideTranslatorPB; -import org.apache.hadoop.ozone.protocolPB.StorageContainerDatanodeProtocolPB; -import org.apache.hadoop.security.UserGroupInformation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.management.ObjectName; -import java.io.Closeable; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -import static org.apache.hadoop.hdds.scm.HddsServerUtil - .getScmRpcTimeOutInMilliseconds; - -/** - * SCMConnectionManager - Acts as a class that manages the membership - * information of the SCMs that we are working with. - */ -public class SCMConnectionManager - implements Closeable, SCMConnectionManagerMXBean { - private static final Logger LOG = - LoggerFactory.getLogger(SCMConnectionManager.class); - - private final ReadWriteLock mapLock; - private final Map scmMachines; - - private final int rpcTimeout; - private final Configuration conf; - private ObjectName jmxBean; - - public SCMConnectionManager(Configuration conf) { - this.mapLock = new ReentrantReadWriteLock(); - Long timeOut = getScmRpcTimeOutInMilliseconds(conf); - this.rpcTimeout = timeOut.intValue(); - this.scmMachines = new HashMap<>(); - this.conf = conf; - jmxBean = MBeans.register("HddsDatanode", - "SCMConnectionManager", - this); - } - - - /** - * Returns Config. - * - * @return ozoneConfig. - */ - public Configuration getConf() { - return conf; - } - - /** - * Get RpcTimeout. - * - * @return - Return RPC timeout. - */ - public int getRpcTimeout() { - return rpcTimeout; - } - - - /** - * Takes a read lock. - */ - public void readLock() { - this.mapLock.readLock().lock(); - } - - /** - * Releases the read lock. - */ - public void readUnlock() { - this.mapLock.readLock().unlock(); - } - - /** - * Takes the write lock. - */ - public void writeLock() { - this.mapLock.writeLock().lock(); - } - - /** - * Releases the write lock. - */ - public void writeUnlock() { - this.mapLock.writeLock().unlock(); - } - - /** - * adds a new SCM machine to the target set. - * - * @param address - Address of the SCM machine to send heatbeat to. - * @throws IOException - */ - public void addSCMServer(InetSocketAddress address) throws IOException { - writeLock(); - try { - if (scmMachines.containsKey(address)) { - LOG.warn("Trying to add an existing SCM Machine to Machines group. " + - "Ignoring the request."); - return; - } - RPC.setProtocolEngine(conf, StorageContainerDatanodeProtocolPB.class, - ProtobufRpcEngine.class); - long version = - RPC.getProtocolVersion(StorageContainerDatanodeProtocolPB.class); - - StorageContainerDatanodeProtocolPB rpcProxy = RPC.getProxy( - StorageContainerDatanodeProtocolPB.class, version, - address, UserGroupInformation.getCurrentUser(), conf, - NetUtils.getDefaultSocketFactory(conf), getRpcTimeout()); - - StorageContainerDatanodeProtocolClientSideTranslatorPB rpcClient = - new StorageContainerDatanodeProtocolClientSideTranslatorPB(rpcProxy); - - EndpointStateMachine endPoint = - new EndpointStateMachine(address, rpcClient, conf); - scmMachines.put(address, endPoint); - } finally { - writeUnlock(); - } - } - - /** - * Removes a SCM machine for the target set. - * - * @param address - Address of the SCM machine to send heatbeat to. - * @throws IOException - */ - public void removeSCMServer(InetSocketAddress address) throws IOException { - writeLock(); - try { - if (!scmMachines.containsKey(address)) { - LOG.warn("Trying to remove a non-existent SCM machine. " + - "Ignoring the request."); - return; - } - - EndpointStateMachine endPoint = scmMachines.get(address); - endPoint.close(); - scmMachines.remove(address); - } finally { - writeUnlock(); - } - } - - /** - * Returns all known RPCEndpoints. - * - * @return - List of RPC Endpoints. - */ - public Collection getValues() { - return scmMachines.values(); - } - - @Override - public void close() throws IOException { - getValues().forEach(endpointStateMachine - -> IOUtils.cleanupWithLogger(LOG, endpointStateMachine)); - if (jmxBean != null) { - MBeans.unregister(jmxBean); - jmxBean = null; - } - } - - @Override - public List getSCMServers() { - readLock(); - try { - return Collections - .unmodifiableList(new ArrayList<>(scmMachines.values())); - - } finally { - readUnlock(); - } - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/SCMConnectionManagerMXBean.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/SCMConnectionManagerMXBean.java deleted file mode 100644 index 25ef16379a6..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/SCMConnectionManagerMXBean.java +++ /dev/null @@ -1,27 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.container.common.statemachine; - -import java.util.List; - -/** - * JMX information about the connected SCM servers. - */ -public interface SCMConnectionManagerMXBean { - - List getSCMServers(); -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/StateContext.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/StateContext.java deleted file mode 100644 index 12c196b1bd6..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/StateContext.java +++ /dev/null @@ -1,504 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.container.common.statemachine; - -import com.google.common.base.Preconditions; -import com.google.protobuf.GeneratedMessage; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMCommandProto.Type; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.PipelineAction; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerAction; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.CommandStatus.Status; -import org.apache.hadoop.ozone.container.common.states.DatanodeState; -import org.apache.hadoop.ozone.container.common.states.datanode - .InitDatanodeState; -import org.apache.hadoop.ozone.container.common.states.datanode - .RunningDatanodeState; -import org.apache.hadoop.ozone.protocol.commands.CommandStatus; -import org.apache.hadoop.ozone.protocol.commands.CommandStatus - .CommandStatusBuilder; -import org.apache.hadoop.ozone.protocol.commands - .DeleteBlockCommandStatus.DeleteBlockCommandStatusBuilder; -import org.apache.hadoop.ozone.protocol.commands.SCMCommand; - -import static java.lang.Math.min; -import static org.apache.hadoop.hdds.scm.HddsServerUtil.getScmHeartbeatInterval; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.LinkedList; -import java.util.List; -import java.util.Queue; -import java.util.ArrayList; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; -import java.util.function.Consumer; - -import static org.apache.hadoop.ozone.OzoneConsts.INVALID_PORT; - -/** - * Current Context of State Machine. - */ -public class StateContext { - static final Logger LOG = - LoggerFactory.getLogger(StateContext.class); - private final Queue commandQueue; - private final Map cmdStatusMap; - private final Lock lock; - private final DatanodeStateMachine parent; - private final AtomicLong stateExecutionCount; - private final Configuration conf; - private final List reports; - private final Queue containerActions; - private final Queue pipelineActions; - private DatanodeStateMachine.DatanodeStates state; - - /** - * Starting with a 2 sec heartbeat frequency which will be updated to the - * real HB frequency after scm registration. With this method the - * initial registration could be significant faster. - */ - private AtomicLong heartbeatFrequency = new AtomicLong(2000); - - /** - * Constructs a StateContext. - * - * @param conf - Configration - * @param state - State - * @param parent Parent State Machine - */ - public StateContext(Configuration conf, DatanodeStateMachine.DatanodeStates - state, DatanodeStateMachine parent) { - this.conf = conf; - this.state = state; - this.parent = parent; - commandQueue = new LinkedList<>(); - cmdStatusMap = new ConcurrentHashMap<>(); - reports = new LinkedList<>(); - containerActions = new LinkedList<>(); - pipelineActions = new LinkedList<>(); - lock = new ReentrantLock(); - stateExecutionCount = new AtomicLong(0); - } - - /** - * Returns the ContainerStateMachine class that holds this state. - * - * @return ContainerStateMachine. - */ - public DatanodeStateMachine getParent() { - return parent; - } - - /** - * Get the container server port. - * @return The container server port if available, return -1 if otherwise - */ - public int getContainerPort() { - return parent == null ? - INVALID_PORT : parent.getContainer().getContainerServerPort(); - } - - /** - * Gets the Ratis Port. - * @return int , return -1 if not valid. - */ - public int getRatisPort() { - return parent == null ? - INVALID_PORT : parent.getContainer().getRatisContainerServerPort(); - } - - /** - * Returns true if we are entering a new state. - * - * @return boolean - */ - boolean isEntering() { - return stateExecutionCount.get() == 0; - } - - /** - * Returns true if we are exiting from the current state. - * - * @param newState - newState. - * @return boolean - */ - boolean isExiting(DatanodeStateMachine.DatanodeStates newState) { - boolean isExiting = state != newState && stateExecutionCount.get() > 0; - if(isExiting) { - stateExecutionCount.set(0); - } - return isExiting; - } - - /** - * Returns the current state the machine is in. - * - * @return state. - */ - public DatanodeStateMachine.DatanodeStates getState() { - return state; - } - - /** - * Sets the current state of the machine. - * - * @param state state. - */ - public void setState(DatanodeStateMachine.DatanodeStates state) { - this.state = state; - } - - /** - * Adds the report to report queue. - * - * @param report report to be added - */ - public void addReport(GeneratedMessage report) { - if (report != null) { - synchronized (reports) { - reports.add(report); - } - } - } - - /** - * Adds the reports which could not be sent by heartbeat back to the - * reports list. - * - * @param reportsToPutBack list of reports which failed to be sent by - * heartbeat. - */ - public void putBackReports(List reportsToPutBack) { - synchronized (reports) { - reports.addAll(0, reportsToPutBack); - } - } - - /** - * Returns all the available reports from the report queue, or empty list if - * the queue is empty. - * - * @return List - */ - public List getAllAvailableReports() { - return getReports(Integer.MAX_VALUE); - } - - /** - * Returns available reports from the report queue with a max limit on - * list size, or empty list if the queue is empty. - * - * @return List - */ - public List getReports(int maxLimit) { - List reportsToReturn = new LinkedList<>(); - synchronized (reports) { - List tempList = reports.subList( - 0, min(reports.size(), maxLimit)); - reportsToReturn.addAll(tempList); - tempList.clear(); - } - return reportsToReturn; - } - - - /** - * Adds the ContainerAction to ContainerAction queue. - * - * @param containerAction ContainerAction to be added - */ - public void addContainerAction(ContainerAction containerAction) { - synchronized (containerActions) { - containerActions.add(containerAction); - } - } - - /** - * Add ContainerAction to ContainerAction queue if it's not present. - * - * @param containerAction ContainerAction to be added - */ - public void addContainerActionIfAbsent(ContainerAction containerAction) { - synchronized (containerActions) { - if (!containerActions.contains(containerAction)) { - containerActions.add(containerAction); - } - } - } - - /** - * Returns all the pending ContainerActions from the ContainerAction queue, - * or empty list if the queue is empty. - * - * @return List - */ - public List getAllPendingContainerActions() { - return getPendingContainerAction(Integer.MAX_VALUE); - } - - /** - * Returns pending ContainerActions from the ContainerAction queue with a - * max limit on list size, or empty list if the queue is empty. - * - * @return List - */ - public List getPendingContainerAction(int maxLimit) { - List containerActionList = new ArrayList<>(); - synchronized (containerActions) { - if (!containerActions.isEmpty()) { - int size = containerActions.size(); - int limit = size > maxLimit ? maxLimit : size; - for (int count = 0; count < limit; count++) { - // we need to remove the action from the containerAction queue - // as well - ContainerAction action = containerActions.poll(); - Preconditions.checkNotNull(action); - containerActionList.add(action); - } - } - return containerActionList; - } - } - - /** - * Add PipelineAction to PipelineAction queue if it's not present. - * - * @param pipelineAction PipelineAction to be added - */ - public void addPipelineActionIfAbsent(PipelineAction pipelineAction) { - synchronized (pipelineActions) { - /** - * If pipelineAction queue already contains entry for the pipeline id - * with same action, we should just return. - * Note: We should not use pipelineActions.contains(pipelineAction) here - * as, pipelineAction has a msg string. So even if two msgs differ though - * action remains same on the given pipeline, it will end up adding it - * multiple times here. - */ - for (PipelineAction pipelineActionIter : pipelineActions) { - if (pipelineActionIter.getAction() == pipelineAction.getAction() - && pipelineActionIter.hasClosePipeline() && pipelineAction - .hasClosePipeline() - && pipelineActionIter.getClosePipeline().getPipelineID() - .equals(pipelineAction.getClosePipeline().getPipelineID())) { - return; - } - } - pipelineActions.add(pipelineAction); - } - } - - /** - * Returns pending PipelineActions from the PipelineAction queue with a - * max limit on list size, or empty list if the queue is empty. - * - * @return List - */ - public List getPendingPipelineAction(int maxLimit) { - List pipelineActionList = new ArrayList<>(); - synchronized (pipelineActions) { - if (!pipelineActions.isEmpty()) { - int size = pipelineActions.size(); - int limit = size > maxLimit ? maxLimit : size; - for (int count = 0; count < limit; count++) { - pipelineActionList.add(pipelineActions.poll()); - } - } - return pipelineActionList; - } - } - - /** - * Returns the next task to get executed by the datanode state machine. - * @return A callable that will be executed by the - * {@link DatanodeStateMachine} - */ - @SuppressWarnings("unchecked") - public DatanodeState getTask() { - switch (this.state) { - case INIT: - return new InitDatanodeState(this.conf, parent.getConnectionManager(), - this); - case RUNNING: - return new RunningDatanodeState(this.conf, parent.getConnectionManager(), - this); - case SHUTDOWN: - return null; - default: - throw new IllegalArgumentException("Not Implemented yet."); - } - } - - /** - * Executes the required state function. - * - * @param service - Executor Service - * @param time - seconds to wait - * @param unit - Seconds. - * @throws InterruptedException - * @throws ExecutionException - * @throws TimeoutException - */ - public void execute(ExecutorService service, long time, TimeUnit unit) - throws InterruptedException, ExecutionException, TimeoutException { - stateExecutionCount.incrementAndGet(); - DatanodeState task = getTask(); - if (this.isEntering()) { - task.onEnter(); - } - task.execute(service); - DatanodeStateMachine.DatanodeStates newState = task.await(time, unit); - if (this.state != newState) { - if (LOG.isDebugEnabled()) { - LOG.debug("Task {} executed, state transited from {} to {}", - task.getClass().getSimpleName(), this.state, newState); - } - if (isExiting(newState)) { - task.onExit(); - } - this.setState(newState); - } - } - - /** - * Returns the next command or null if it is empty. - * - * @return SCMCommand or Null. - */ - public SCMCommand getNextCommand() { - lock.lock(); - try { - return commandQueue.poll(); - } finally { - lock.unlock(); - } - } - - /** - * Adds a command to the State Machine queue. - * - * @param command - SCMCommand. - */ - public void addCommand(SCMCommand command) { - lock.lock(); - try { - commandQueue.add(command); - } finally { - lock.unlock(); - } - this.addCmdStatus(command); - } - - /** - * Returns the count of the Execution. - * @return long - */ - public long getExecutionCount() { - return stateExecutionCount.get(); - } - - /** - * Returns the next {@link CommandStatus} or null if it is empty. - * - * @return {@link CommandStatus} or Null. - */ - public CommandStatus getCmdStatus(Long key) { - return cmdStatusMap.get(key); - } - - /** - * Adds a {@link CommandStatus} to the State Machine. - * - * @param status - {@link CommandStatus}. - */ - public void addCmdStatus(Long key, CommandStatus status) { - cmdStatusMap.put(key, status); - } - - /** - * Adds a {@link CommandStatus} to the State Machine for given SCMCommand. - * - * @param cmd - {@link SCMCommand}. - */ - public void addCmdStatus(SCMCommand cmd) { - CommandStatusBuilder statusBuilder; - if (cmd.getType() == Type.deleteBlocksCommand) { - statusBuilder = new DeleteBlockCommandStatusBuilder(); - } else { - statusBuilder = CommandStatusBuilder.newBuilder(); - } - this.addCmdStatus(cmd.getId(), - statusBuilder.setCmdId(cmd.getId()) - .setStatus(Status.PENDING) - .setType(cmd.getType()) - .build()); - } - - /** - * Get map holding all {@link CommandStatus} objects. - * - */ - public Map getCommandStatusMap() { - return cmdStatusMap; - } - - /** - * Remove object from cache in StateContext#cmdStatusMap. - * - */ - public void removeCommandStatus(Long cmdId) { - cmdStatusMap.remove(cmdId); - } - - /** - * Updates status of a pending status command. - * @param cmdId command id - * @param cmdStatusUpdater Consumer to update command status. - * @return true if command status updated successfully else false. - */ - public boolean updateCommandStatus(Long cmdId, - Consumer cmdStatusUpdater) { - if(cmdStatusMap.containsKey(cmdId)) { - cmdStatusUpdater.accept(cmdStatusMap.get(cmdId)); - return true; - } - return false; - } - - public void configureHeartbeatFrequency(){ - heartbeatFrequency.set(getScmHeartbeatInterval(conf)); - } - - /** - * Return current heartbeat frequency in ms. - */ - public long getHeartbeatFrequency() { - return heartbeatFrequency.get(); - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/CloseContainerCommandHandler.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/CloseContainerCommandHandler.java deleted file mode 100644 index 2c3db6195e0..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/CloseContainerCommandHandler.java +++ /dev/null @@ -1,159 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.container.common.statemachine.commandhandler; - -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMCommandProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.CloseContainerCommandProto; -import org.apache.hadoop.ozone.container.common.statemachine - .SCMConnectionManager; -import org.apache.hadoop.ozone.container.common.statemachine.StateContext; -import org.apache.hadoop.ozone.container.ozoneimpl.OzoneContainer; -import org.apache.hadoop.ozone.protocol.commands.SCMCommand; -import org.apache.hadoop.util.Time; -import org.apache.ratis.protocol.NotLeaderException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.UUID; - -/** - * Handler for close container command received from SCM. - */ -public class CloseContainerCommandHandler implements CommandHandler { - static final Logger LOG = - LoggerFactory.getLogger(CloseContainerCommandHandler.class); - private int invocationCount; - private long totalTime; - private boolean cmdExecuted; - - /** - * Constructs a ContainerReport handler. - */ - public CloseContainerCommandHandler() { - } - - /** - * Handles a given SCM command. - * - * @param command - SCM Command - * @param container - Ozone Container. - * @param context - Current Context. - * @param connectionManager - The SCMs that we are talking to. - */ - @Override - public void handle(SCMCommand command, OzoneContainer container, - StateContext context, SCMConnectionManager connectionManager) { - LOG.debug("Processing Close Container command."); - invocationCount++; - cmdExecuted = false; - long startTime = Time.monotonicNow(); - // TODO: define this as INVALID_CONTAINER_ID in HddsConsts.java (TBA) - long containerID = -1; - try { - - CloseContainerCommandProto - closeContainerProto = - CloseContainerCommandProto - .parseFrom(command.getProtoBufMessage()); - containerID = closeContainerProto.getContainerID(); - if (container.getContainerSet().getContainer(containerID) - .getContainerData().isClosed()) { - LOG.debug("Container {} is already closed", containerID); - // It might happen that the where the first attempt of closing the - // container failed with NOT_LEADER_EXCEPTION. In such cases, SCM will - // retry to check the container got really closed via Ratis. - // In such cases of the retry attempt, if the container is already - // closed via Ratis, we should just return. - cmdExecuted = true; - return; - } - HddsProtos.PipelineID pipelineID = closeContainerProto.getPipelineID(); - HddsProtos.ReplicationType replicationType = - closeContainerProto.getReplicationType(); - - ContainerProtos.ContainerCommandRequestProto.Builder request = - ContainerProtos.ContainerCommandRequestProto.newBuilder(); - request.setCmdType(ContainerProtos.Type.CloseContainer); - request.setContainerID(containerID); - request.setCloseContainer( - ContainerProtos.CloseContainerRequestProto.getDefaultInstance()); - request.setTraceID(UUID.randomUUID().toString()); - request.setDatanodeUuid( - context.getParent().getDatanodeDetails().getUuidString()); - // submit the close container request for the XceiverServer to handle - container.submitContainerRequest( - request.build(), replicationType, pipelineID); - } catch (Exception e) { - if (e instanceof NotLeaderException) { - // If the particular datanode is not the Ratis leader, the close - // container command will not be executed by the follower but will be - // executed by Ratis stateMachine transactions via leader to follower. - // There can also be case where the datanode is in candidate state. - // In these situations, NotLeaderException is thrown. Remove the status - // from cmdStatus Map here so that it will be retried only by SCM if the - // leader could not not close the container after a certain time. - context.removeCommandStatus(containerID); - LOG.info(e.getLocalizedMessage()); - } else { - LOG.error("Can't close container " + containerID, e); - cmdExecuted = false; - } - } finally { - updateCommandStatus(context, command, - (cmdStatus) -> cmdStatus.setStatus(cmdExecuted), LOG); - long endTime = Time.monotonicNow(); - totalTime += endTime - startTime; - } - } - - /** - * Returns the command type that this command handler handles. - * - * @return Type - */ - @Override - public SCMCommandProto.Type getCommandType() { - return SCMCommandProto.Type.closeContainerCommand; - } - - /** - * Returns number of times this handler has been invoked. - * - * @return int - */ - @Override - public int getInvocationCount() { - return invocationCount; - } - - /** - * Returns the average time this function takes to run. - * - * @return long - */ - @Override - public long getAverageRunTime() { - if (invocationCount > 0) { - return totalTime / invocationCount; - } - return 0; - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/CommandDispatcher.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/CommandDispatcher.java deleted file mode 100644 index 5163d9851a2..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/CommandDispatcher.java +++ /dev/null @@ -1,182 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.container.common.statemachine.commandhandler; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMCommandProto.Type; -import org.apache.hadoop.ozone.container.common.statemachine.SCMConnectionManager; -import org.apache.hadoop.ozone.container.common.statemachine.StateContext; -import org.apache.hadoop.ozone.container.ozoneimpl.OzoneContainer; -import org.apache.hadoop.ozone.protocol.commands.SCMCommand; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -/** - * Dispatches command to the correct handler. - */ -public final class CommandDispatcher { - static final Logger LOG = - LoggerFactory.getLogger(CommandDispatcher.class); - private final StateContext context; - private final Map handlerMap; - private final OzoneContainer container; - private final SCMConnectionManager connectionManager; - - /** - * Constructs a command Dispatcher. - * @param context - Context. - */ - /** - * Constructs a command dispatcher. - * - * @param container - Ozone Container - * @param context - Context - * @param handlers - Set of handlers. - */ - private CommandDispatcher(OzoneContainer container, SCMConnectionManager - connectionManager, StateContext context, - CommandHandler... handlers) { - Preconditions.checkNotNull(context); - Preconditions.checkNotNull(handlers); - Preconditions.checkArgument(handlers.length > 0); - Preconditions.checkNotNull(container); - Preconditions.checkNotNull(connectionManager); - this.context = context; - this.container = container; - this.connectionManager = connectionManager; - handlerMap = new HashMap<>(); - for (CommandHandler h : handlers) { - if(handlerMap.containsKey(h.getCommandType())){ - LOG.error("Duplicate handler for the same command. Exiting. Handle " + - "key : { }", h.getCommandType().getDescriptorForType().getName()); - throw new IllegalArgumentException("Duplicate handler for the same " + - "command."); - } - handlerMap.put(h.getCommandType(), h); - } - } - - public CommandHandler getCloseContainerHandler() { - return handlerMap.get(Type.closeContainerCommand); - } - - /** - * Dispatch the command to the correct handler. - * - * @param command - SCM Command. - */ - public void handle(SCMCommand command) { - Preconditions.checkNotNull(command); - CommandHandler handler = handlerMap.get(command.getType()); - if (handler != null) { - handler.handle(command, container, context, connectionManager); - } else { - LOG.error("Unknown SCM Command queued. There is no handler for this " + - "command. Command: {}", command.getType().getDescriptorForType() - .getName()); - } - } - - public static Builder newBuilder() { - return new Builder(); - } - - /** - * Helper class to construct command dispatcher. - */ - public static class Builder { - private final List handlerList; - private OzoneContainer container; - private StateContext context; - private SCMConnectionManager connectionManager; - - public Builder() { - handlerList = new LinkedList<>(); - } - - /** - * Adds a handler. - * - * @param handler - handler - * @return Builder - */ - public Builder addHandler(CommandHandler handler) { - Preconditions.checkNotNull(handler); - handlerList.add(handler); - return this; - } - - /** - * Add the OzoneContainer. - * - * @param ozoneContainer - ozone container. - * @return Builder - */ - public Builder setContainer(OzoneContainer ozoneContainer) { - Preconditions.checkNotNull(ozoneContainer); - this.container = ozoneContainer; - return this; - } - - /** - * Set the Connection Manager. - * - * @param scmConnectionManager - * @return this - */ - public Builder setConnectionManager(SCMConnectionManager - scmConnectionManager) { - Preconditions.checkNotNull(scmConnectionManager); - this.connectionManager = scmConnectionManager; - return this; - } - - /** - * Sets the Context. - * - * @param stateContext - StateContext - * @return this - */ - public Builder setContext(StateContext stateContext) { - Preconditions.checkNotNull(stateContext); - this.context = stateContext; - return this; - } - - /** - * Builds a command Dispatcher. - * @return Command Dispatcher. - */ - public CommandDispatcher build() { - Preconditions.checkNotNull(this.connectionManager, "Missing connection" + - " manager."); - Preconditions.checkNotNull(this.container, "Missing container."); - Preconditions.checkNotNull(this.context, "Missing context."); - Preconditions.checkArgument(this.handlerList.size() > 0); - return new CommandDispatcher(this.container, this.connectionManager, - this.context, handlerList.toArray( - new CommandHandler[handlerList.size()])); - } - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/CommandHandler.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/CommandHandler.java deleted file mode 100644 index 1ea0ea84515..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/CommandHandler.java +++ /dev/null @@ -1,75 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.container.common.statemachine.commandhandler; - -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMCommandProto; -import org.apache.hadoop.ozone.container.common.statemachine - .SCMConnectionManager; -import org.apache.hadoop.ozone.container.common.statemachine.StateContext; -import org.apache.hadoop.ozone.container.ozoneimpl.OzoneContainer; -import org.apache.hadoop.ozone.protocol.commands.CommandStatus; -import org.apache.hadoop.ozone.protocol.commands.SCMCommand; -import org.slf4j.Logger; - -import java.util.function.Consumer; - -/** - * Generic interface for handlers. - */ -public interface CommandHandler { - - /** - * Handles a given SCM command. - * @param command - SCM Command - * @param container - Ozone Container. - * @param context - Current Context. - * @param connectionManager - The SCMs that we are talking to. - */ - void handle(SCMCommand command, OzoneContainer container, - StateContext context, SCMConnectionManager connectionManager); - - /** - * Returns the command type that this command handler handles. - * @return Type - */ - SCMCommandProto.Type getCommandType(); - - /** - * Returns number of times this handler has been invoked. - * @return int - */ - int getInvocationCount(); - - /** - * Returns the average time this function takes to run. - * @return long - */ - long getAverageRunTime(); - - /** - * Default implementation for updating command status. - */ - default void updateCommandStatus(StateContext context, SCMCommand command, - Consumer cmdStatusUpdater, Logger log) { - if (!context.updateCommandStatus(command.getId(), cmdStatusUpdater)) { - log.debug("{} with Id:{} not found.", command.getType(), - command.getId()); - } - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/DeleteBlocksCommandHandler.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/DeleteBlocksCommandHandler.java deleted file mode 100644 index aa63fb48f4d..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/DeleteBlocksCommandHandler.java +++ /dev/null @@ -1,266 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.container.common.statemachine.commandhandler; - -import com.google.common.primitives.Longs; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMCommandProto; -import org.apache.hadoop.hdds.scm.container.common.helpers - .StorageContainerException; -import org.apache.hadoop.hdfs.DFSUtil; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerBlocksDeletionACKProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerBlocksDeletionACKProto - .DeleteBlockTransactionResult; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.DeletedBlocksTransaction; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.container.common.helpers - .DeletedContainerBlocksSummary; -import org.apache.hadoop.ozone.container.common.interfaces.Container; -import org.apache.hadoop.ozone.container.keyvalue.KeyValueContainerData; -import org.apache.hadoop.ozone.container.keyvalue.helpers.BlockUtils; -import org.apache.hadoop.ozone.container.common.impl.ContainerSet; -import org.apache.hadoop.ozone.container.common.statemachine - .SCMConnectionManager; -import org.apache.hadoop.ozone.container.common.statemachine.StateContext; -import org.apache.hadoop.ozone.container.ozoneimpl.OzoneContainer; -import org.apache.hadoop.ozone.protocol.commands.CommandStatus; -import org.apache.hadoop.ozone.protocol.commands.DeleteBlockCommandStatus; -import org.apache.hadoop.ozone.protocol.commands.DeleteBlocksCommand; -import org.apache.hadoop.ozone.protocol.commands.SCMCommand; -import org.apache.hadoop.util.Time; -import org.apache.hadoop.utils.BatchOperation; -import org.apache.hadoop.utils.MetadataStore; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.List; -import java.util.function.Consumer; - -import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .Result.CONTAINER_NOT_FOUND; - -/** - * Handle block deletion commands. - */ -public class DeleteBlocksCommandHandler implements CommandHandler { - - public static final Logger LOG = - LoggerFactory.getLogger(DeleteBlocksCommandHandler.class); - - private final ContainerSet containerSet; - private final Configuration conf; - private int invocationCount; - private long totalTime; - private boolean cmdExecuted; - - public DeleteBlocksCommandHandler(ContainerSet cset, - Configuration conf) { - this.containerSet = cset; - this.conf = conf; - } - - @Override - public void handle(SCMCommand command, OzoneContainer container, - StateContext context, SCMConnectionManager connectionManager) { - cmdExecuted = false; - long startTime = Time.monotonicNow(); - ContainerBlocksDeletionACKProto blockDeletionACK = null; - try { - if (command.getType() != SCMCommandProto.Type.deleteBlocksCommand) { - LOG.warn("Skipping handling command, expected command " - + "type {} but found {}", - SCMCommandProto.Type.deleteBlocksCommand, command.getType()); - return; - } - LOG.debug("Processing block deletion command."); - invocationCount++; - - // move blocks to deleting state. - // this is a metadata update, the actual deletion happens in another - // recycling thread. - DeleteBlocksCommand cmd = (DeleteBlocksCommand) command; - List containerBlocks = cmd.blocksTobeDeleted(); - - DeletedContainerBlocksSummary summary = - DeletedContainerBlocksSummary.getFrom(containerBlocks); - LOG.info("Start to delete container blocks, TXIDs={}, " - + "numOfContainers={}, numOfBlocks={}", - summary.getTxIDSummary(), - summary.getNumOfContainers(), - summary.getNumOfBlocks()); - - ContainerBlocksDeletionACKProto.Builder resultBuilder = - ContainerBlocksDeletionACKProto.newBuilder(); - containerBlocks.forEach(entry -> { - DeleteBlockTransactionResult.Builder txResultBuilder = - DeleteBlockTransactionResult.newBuilder(); - txResultBuilder.setTxID(entry.getTxID()); - long containerId = entry.getContainerID(); - try { - Container cont = containerSet.getContainer(containerId); - if (cont == null) { - throw new StorageContainerException("Unable to find the container " - + containerId, CONTAINER_NOT_FOUND); - } - ContainerProtos.ContainerType containerType = cont.getContainerType(); - switch (containerType) { - case KeyValueContainer: - KeyValueContainerData containerData = (KeyValueContainerData) - cont.getContainerData(); - deleteKeyValueContainerBlocks(containerData, entry); - txResultBuilder.setContainerID(containerId) - .setSuccess(true); - break; - default: - LOG.error( - "Delete Blocks Command Handler is not implemented for " + - "containerType {}", containerType); - } - } catch (IOException e) { - LOG.warn("Failed to delete blocks for container={}, TXID={}", - entry.getContainerID(), entry.getTxID(), e); - txResultBuilder.setContainerID(containerId) - .setSuccess(false); - } - resultBuilder.addResults(txResultBuilder.build()) - .setDnId(context.getParent().getDatanodeDetails() - .getUuid().toString()); - }); - blockDeletionACK = resultBuilder.build(); - - // Send ACK back to SCM as long as meta updated - // TODO Or we should wait until the blocks are actually deleted? - if (!containerBlocks.isEmpty()) { - if (LOG.isDebugEnabled()) { - LOG.debug("Sending following block deletion ACK to SCM"); - for (DeleteBlockTransactionResult result : blockDeletionACK - .getResultsList()) { - LOG.debug(result.getTxID() + " : " + result.getSuccess()); - } - } - } - cmdExecuted = true; - } finally { - final ContainerBlocksDeletionACKProto deleteAck = - blockDeletionACK; - Consumer statusUpdater = (cmdStatus) -> { - cmdStatus.setStatus(cmdExecuted); - ((DeleteBlockCommandStatus) cmdStatus).setBlocksDeletionAck(deleteAck); - }; - updateCommandStatus(context, command, statusUpdater, LOG); - long endTime = Time.monotonicNow(); - totalTime += endTime - startTime; - } - } - - /** - * Move a bunch of blocks from a container to deleting state. This is a meta - * update, the actual deletes happen in async mode. - * - * @param containerData - KeyValueContainerData - * @param delTX a block deletion transaction. - * @throws IOException if I/O error occurs. - */ - private void deleteKeyValueContainerBlocks( - KeyValueContainerData containerData, DeletedBlocksTransaction delTX) - throws IOException { - long containerId = delTX.getContainerID(); - if (LOG.isDebugEnabled()) { - LOG.debug("Processing Container : {}, DB path : {}", containerId, - containerData.getMetadataPath()); - } - - if (delTX.getTxID() < containerData.getDeleteTransactionId()) { - LOG.debug(String.format("Ignoring delete blocks for containerId: %d." - + " Outdated delete transactionId %d < %d", containerId, - delTX.getTxID(), containerData.getDeleteTransactionId())); - return; - } - - int newDeletionBlocks = 0; - MetadataStore containerDB = BlockUtils.getDB(containerData, conf); - for (Long blk : delTX.getLocalIDList()) { - BatchOperation batch = new BatchOperation(); - byte[] blkBytes = Longs.toByteArray(blk); - byte[] blkInfo = containerDB.get(blkBytes); - if (blkInfo != null) { - byte[] deletingKeyBytes = - DFSUtil.string2Bytes(OzoneConsts.DELETING_KEY_PREFIX + blk); - byte[] deletedKeyBytes = - DFSUtil.string2Bytes(OzoneConsts.DELETED_KEY_PREFIX + blk); - if (containerDB.get(deletingKeyBytes) != null - || containerDB.get(deletedKeyBytes) != null) { - LOG.debug(String.format( - "Ignoring delete for block %d in container %d." - + " Entry already added.", blk, containerId)); - continue; - } - // Found the block in container db, - // use an atomic update to change its state to deleting. - batch.put(deletingKeyBytes, blkInfo); - batch.delete(blkBytes); - try { - containerDB.writeBatch(batch); - newDeletionBlocks++; - LOG.debug("Transited Block {} to DELETING state in container {}", - blk, containerId); - } catch (IOException e) { - // if some blocks failed to delete, we fail this TX, - // without sending this ACK to SCM, SCM will resend the TX - // with a certain number of retries. - throw new IOException( - "Failed to delete blocks for TXID = " + delTX.getTxID(), e); - } - } else { - LOG.debug("Block {} not found or already under deletion in" - + " container {}, skip deleting it.", blk, containerId); - } - } - - containerDB - .put(DFSUtil.string2Bytes(OzoneConsts.DELETE_TRANSACTION_KEY_PREFIX), - Longs.toByteArray(delTX.getTxID())); - containerData - .updateDeleteTransactionId(delTX.getTxID()); - // update pending deletion blocks count in in-memory container status - containerData.incrPendingDeletionBlocks(newDeletionBlocks); - } - - @Override - public SCMCommandProto.Type getCommandType() { - return SCMCommandProto.Type.deleteBlocksCommand; - } - - @Override - public int getInvocationCount() { - return this.invocationCount; - } - - @Override - public long getAverageRunTime() { - if (invocationCount > 0) { - return totalTime / invocationCount; - } - return 0; - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/ReplicateContainerCommandHandler.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/ReplicateContainerCommandHandler.java deleted file mode 100644 index 81d162d2803..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/ReplicateContainerCommandHandler.java +++ /dev/null @@ -1,102 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.container.common.statemachine.commandhandler; - -import java.util.List; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMCommandProto; -import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMCommandProto.Type; -import org.apache.hadoop.ozone.container.common.statemachine.SCMConnectionManager; -import org.apache.hadoop.ozone.container.common.statemachine.StateContext; -import org.apache.hadoop.ozone.container.ozoneimpl.OzoneContainer; -import org.apache.hadoop.ozone.container.replication.ReplicationSupervisor; -import org.apache.hadoop.ozone.container.replication.ReplicationTask; -import org.apache.hadoop.ozone.protocol.commands.ReplicateContainerCommand; -import org.apache.hadoop.ozone.protocol.commands.SCMCommand; - -import com.google.common.base.Preconditions; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Command handler to copy containers from sources. - */ -public class ReplicateContainerCommandHandler implements CommandHandler { - - static final Logger LOG = - LoggerFactory.getLogger(ReplicateContainerCommandHandler.class); - - private int invocationCount; - - private long totalTime; - - private Configuration conf; - - private ReplicationSupervisor supervisor; - - public ReplicateContainerCommandHandler( - Configuration conf, - ReplicationSupervisor supervisor) { - this.conf = conf; - this.supervisor = supervisor; - } - - @Override - public void handle(SCMCommand command, OzoneContainer container, - StateContext context, SCMConnectionManager connectionManager) { - - ReplicateContainerCommand replicateCommand = - (ReplicateContainerCommand) command; - try { - List sourceDatanodes = - replicateCommand.getSourceDatanodes(); - long containerID = replicateCommand.getContainerID(); - - Preconditions.checkArgument(sourceDatanodes.size() > 0, - String.format("Replication command is received for container %d " - + "but the size of source datanodes was 0.", containerID)); - - ReplicationTask replicationTask = - new ReplicationTask(containerID, sourceDatanodes); - supervisor.addTask(replicationTask); - - } finally { - updateCommandStatus(context, command, - (cmdStatus) -> cmdStatus.setStatus(true), LOG); - } - } - - @Override - public SCMCommandProto.Type getCommandType() { - return Type.replicateContainerCommand; - } - - @Override - public int getInvocationCount() { - return this.invocationCount; - } - - @Override - public long getAverageRunTime() { - if (invocationCount > 0) { - return totalTime / invocationCount; - } - return 0; - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/package-info.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/package-info.java deleted file mode 100644 index 1e9c8dc5eee..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/package-info.java +++ /dev/null @@ -1,18 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.common.statemachine.commandhandler; \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/package-info.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/package-info.java deleted file mode 100644 index feb2f812ac8..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/package-info.java +++ /dev/null @@ -1,28 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.common.statemachine; -/** - - State machine class is used by the container to denote various states a - container can be in and also is used for command processing. - - Container has the following states. - - Start - > getVersion -> Register -> Running -> Shutdown - - */ \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/DatanodeState.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/DatanodeState.java deleted file mode 100644 index 75142afd10c..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/DatanodeState.java +++ /dev/null @@ -1,55 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.common.states; - -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -/** - * State Interface that allows tasks to maintain states. - */ -public interface DatanodeState { - /** - * Called before entering this state. - */ - void onEnter(); - - /** - * Called After exiting this state. - */ - void onExit(); - - /** - * Executes one or more tasks that is needed by this state. - * - * @param executor - ExecutorService - */ - void execute(ExecutorService executor); - - /** - * Wait for execute to finish. - * - * @param time - Time - * @param timeUnit - Unit of time. - */ - T await(long time, TimeUnit timeUnit) - throws InterruptedException, ExecutionException, TimeoutException; - -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/datanode/InitDatanodeState.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/datanode/InitDatanodeState.java deleted file mode 100644 index 995f172d273..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/datanode/InitDatanodeState.java +++ /dev/null @@ -1,182 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.container.common.states.datanode; - -import com.google.common.base.Strings; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.HddsUtils; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.scm.ScmConfigKeys; -import org.apache.hadoop.ozone.container.common.helpers.ContainerUtils; -import org.apache.hadoop.ozone.container.common.statemachine - .DatanodeStateMachine; -import org.apache.hadoop.ozone.container.common.statemachine - .SCMConnectionManager; -import org.apache.hadoop.ozone.container.common.statemachine.StateContext; -import org.apache.hadoop.ozone.container.common.states.DatanodeState; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.util.Collection; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import static org.apache.hadoop.hdds.HddsUtils.getSCMAddresses; - -/** - * Init Datanode State is the task that gets run when we are in Init State. - */ -public class InitDatanodeState implements DatanodeState, - Callable { - static final Logger LOG = LoggerFactory.getLogger(InitDatanodeState.class); - private final SCMConnectionManager connectionManager; - private final Configuration conf; - private final StateContext context; - private Future result; - - /** - * Create InitDatanodeState Task. - * - * @param conf - Conf - * @param connectionManager - Connection Manager - * @param context - Current Context - */ - public InitDatanodeState(Configuration conf, - SCMConnectionManager connectionManager, - StateContext context) { - this.conf = conf; - this.connectionManager = connectionManager; - this.context = context; - } - - /** - * Computes a result, or throws an exception if unable to do so. - * - * @return computed result - * @throws Exception if unable to compute a result - */ - @Override - public DatanodeStateMachine.DatanodeStates call() throws Exception { - Collection addresses = null; - try { - addresses = getSCMAddresses(conf); - } catch (IllegalArgumentException e) { - if(!Strings.isNullOrEmpty(e.getMessage())) { - LOG.error("Failed to get SCM addresses: " + e.getMessage()); - } - return DatanodeStateMachine.DatanodeStates.SHUTDOWN; - } - - if (addresses == null || addresses.isEmpty()) { - LOG.error("Null or empty SCM address list found."); - return DatanodeStateMachine.DatanodeStates.SHUTDOWN; - } else { - for (InetSocketAddress addr : addresses) { - if (addr.isUnresolved()) { - LOG.warn("One SCM address ({}) can't (yet?) be resolved. Postpone " - + "initialization.", addr); - - //skip any further initialization. DatanodeStateMachine will try it - // again after the hb frequency - return this.context.getState(); - } - } - for (InetSocketAddress addr : addresses) { - connectionManager.addSCMServer(addr); - } - } - - // If datanode ID is set, persist it to the ID file. - persistContainerDatanodeDetails(); - - return this.context.getState().getNextState(); - } - - /** - * Persist DatanodeDetails to datanode.id file. - */ - private void persistContainerDatanodeDetails() { - String dataNodeIDPath = HddsUtils.getDatanodeIdFilePath(conf); - if (Strings.isNullOrEmpty(dataNodeIDPath)) { - LOG.error("A valid file path is needed for config setting {}", - ScmConfigKeys.OZONE_SCM_DATANODE_ID); - this.context.setState(DatanodeStateMachine.DatanodeStates.SHUTDOWN); - return; - } - File idPath = new File(dataNodeIDPath); - DatanodeDetails datanodeDetails = this.context.getParent() - .getDatanodeDetails(); - if (datanodeDetails != null && !idPath.exists()) { - try { - ContainerUtils.writeDatanodeDetailsTo(datanodeDetails, idPath); - } catch (IOException ex) { - // As writing DatanodeDetails in to datanodeid file failed, which is - // a critical thing, so shutting down the state machine. - LOG.error("Writing to {} failed {}", dataNodeIDPath, ex.getMessage()); - this.context.setState(DatanodeStateMachine.DatanodeStates.SHUTDOWN); - return; - } - LOG.info("DatanodeDetails is persisted to {}", dataNodeIDPath); - } - } - - /** - * Called before entering this state. - */ - @Override - public void onEnter() { - LOG.trace("Entering init container state"); - } - - /** - * Called After exiting this state. - */ - @Override - public void onExit() { - LOG.trace("Exiting init container state"); - } - - /** - * Executes one or more tasks that is needed by this state. - * - * @param executor - ExecutorService - */ - @Override - public void execute(ExecutorService executor) { - result = executor.submit(this); - } - - /** - * Wait for execute to finish. - * - * @param time - Time - * @param timeUnit - Unit of time. - */ - @Override - public DatanodeStateMachine.DatanodeStates await(long time, - TimeUnit timeUnit) throws InterruptedException, - ExecutionException, TimeoutException { - return result.get(time, timeUnit); - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/datanode/RunningDatanodeState.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/datanode/RunningDatanodeState.java deleted file mode 100644 index ec2358ae18b..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/datanode/RunningDatanodeState.java +++ /dev/null @@ -1,178 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.container.common.states.datanode; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.ozone.container.common.statemachine.DatanodeStateMachine; -import org.apache.hadoop.ozone.container.common.statemachine.EndpointStateMachine; -import org.apache.hadoop.ozone.container.common.statemachine.SCMConnectionManager; -import org.apache.hadoop.ozone.container.common.statemachine.StateContext; -import org.apache.hadoop.ozone.container.common.states.DatanodeState; -import org.apache.hadoop.ozone.container.common.states.endpoint.HeartbeatEndpointTask; -import org.apache.hadoop.ozone.container.common.states.endpoint.RegisterEndpointTask; -import org.apache.hadoop.ozone.container.common.states.endpoint.VersionEndpointTask; -import org.apache.hadoop.util.Time; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.CompletionService; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorCompletionService; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -/** - * Class that implements handshake with SCM. - */ -public class RunningDatanodeState implements DatanodeState { - static final Logger - LOG = LoggerFactory.getLogger(RunningDatanodeState.class); - private final SCMConnectionManager connectionManager; - private final Configuration conf; - private final StateContext context; - private CompletionService ecs; - - public RunningDatanodeState(Configuration conf, - SCMConnectionManager connectionManager, - StateContext context) { - this.connectionManager = connectionManager; - this.conf = conf; - this.context = context; - } - - /** - * Called before entering this state. - */ - @Override - public void onEnter() { - LOG.trace("Entering handshake task."); - } - - /** - * Called After exiting this state. - */ - @Override - public void onExit() { - LOG.trace("Exiting handshake task."); - } - - /** - * Executes one or more tasks that is needed by this state. - * - * @param executor - ExecutorService - */ - @Override - public void execute(ExecutorService executor) { - ecs = new ExecutorCompletionService<>(executor); - for (EndpointStateMachine endpoint : connectionManager.getValues()) { - Callable endpointTask - = getEndPointTask(endpoint); - ecs.submit(endpointTask); - } - } - //TODO : Cache some of these tasks instead of creating them - //all the time. - private Callable - getEndPointTask(EndpointStateMachine endpoint) { - switch (endpoint.getState()) { - case GETVERSION: - return new VersionEndpointTask(endpoint, conf, context.getParent() - .getContainer()); - case REGISTER: - return RegisterEndpointTask.newBuilder() - .setConfig(conf) - .setEndpointStateMachine(endpoint) - .setContext(context) - .setDatanodeDetails(context.getParent().getDatanodeDetails()) - .setOzoneContainer(context.getParent().getContainer()) - .build(); - case HEARTBEAT: - return HeartbeatEndpointTask.newBuilder() - .setConfig(conf) - .setEndpointStateMachine(endpoint) - .setDatanodeDetails(context.getParent().getDatanodeDetails()) - .setContext(context) - .build(); - case SHUTDOWN: - break; - default: - throw new IllegalArgumentException("Illegal Argument."); - } - return null; - } - - /** - * Computes the next state the container state machine must move to by looking - * at all the state of endpoints. - *

- * if any endpoint state has moved to Shutdown, either we have an - * unrecoverable error or we have been told to shutdown. Either case the - * datanode state machine should move to Shutdown state, otherwise we - * remain in the Running state. - * - * @return next container state. - */ - private DatanodeStateMachine.DatanodeStates - computeNextContainerState( - List> results) { - for (Future state : results) { - try { - if (state.get() == EndpointStateMachine.EndPointStates.SHUTDOWN) { - // if any endpoint tells us to shutdown we move to shutdown state. - return DatanodeStateMachine.DatanodeStates.SHUTDOWN; - } - } catch (InterruptedException | ExecutionException e) { - LOG.error("Error in executing end point task.", e); - } - } - return DatanodeStateMachine.DatanodeStates.RUNNING; - } - - /** - * Wait for execute to finish. - * - * @param duration - Time - * @param timeUnit - Unit of duration. - */ - @Override - public DatanodeStateMachine.DatanodeStates - await(long duration, TimeUnit timeUnit) - throws InterruptedException, ExecutionException, TimeoutException { - int count = connectionManager.getValues().size(); - int returned = 0; - long timeLeft = timeUnit.toMillis(duration); - long startTime = Time.monotonicNow(); - List> results = new - LinkedList<>(); - - while (returned < count && timeLeft > 0) { - Future result = - ecs.poll(timeLeft, TimeUnit.MILLISECONDS); - if (result != null) { - results.add(result); - returned++; - } - timeLeft = timeLeft - (Time.monotonicNow() - startTime); - } - return computeNextContainerState(results); - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/datanode/package-info.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/datanode/package-info.java deleted file mode 100644 index 6b8d16c6d39..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/datanode/package-info.java +++ /dev/null @@ -1,21 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.container.common.states.datanode; -/** - This package contians files that guide the state transitions from - Init->Running->Shutdown for the datanode. - */ \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/endpoint/HeartbeatEndpointTask.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/endpoint/HeartbeatEndpointTask.java deleted file mode 100644 index 4fd72ec208e..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/endpoint/HeartbeatEndpointTask.java +++ /dev/null @@ -1,385 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.states.endpoint; - -import com.google.common.base.Preconditions; -import com.google.protobuf.Descriptors; -import com.google.protobuf.GeneratedMessage; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.DatanodeDetailsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.PipelineActionsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.PipelineAction; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerActionsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerAction; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMHeartbeatRequestProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMCommandProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMHeartbeatResponseProto; -import org.apache.hadoop.ozone.container.common.helpers - .DeletedContainerBlocksSummary; -import org.apache.hadoop.ozone.container.common.statemachine - .EndpointStateMachine; -import org.apache.hadoop.ozone.container.common.statemachine - .EndpointStateMachine.EndPointStates; -import org.apache.hadoop.ozone.container.common.statemachine.StateContext; -import org.apache.hadoop.ozone.protocol.commands.CloseContainerCommand; -import org.apache.hadoop.ozone.protocol.commands.DeleteBlocksCommand; -import org.apache.hadoop.ozone.protocol.commands.ReplicateContainerCommand; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.time.ZonedDateTime; -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.Callable; - -import static org.apache.hadoop.hdds.HddsConfigKeys - .HDDS_CONTAINER_ACTION_MAX_LIMIT; -import static org.apache.hadoop.hdds.HddsConfigKeys - .HDDS_CONTAINER_ACTION_MAX_LIMIT_DEFAULT; -import static org.apache.hadoop.hdds.HddsConfigKeys - .HDDS_PIPELINE_ACTION_MAX_LIMIT; -import static org.apache.hadoop.hdds.HddsConfigKeys - .HDDS_PIPELINE_ACTION_MAX_LIMIT_DEFAULT; - -/** - * Heartbeat class for SCMs. - */ -public class HeartbeatEndpointTask - implements Callable { - static final Logger LOG = - LoggerFactory.getLogger(HeartbeatEndpointTask.class); - private final EndpointStateMachine rpcEndpoint; - private final Configuration conf; - private DatanodeDetailsProto datanodeDetailsProto; - private StateContext context; - private int maxContainerActionsPerHB; - private int maxPipelineActionsPerHB; - - /** - * Constructs a SCM heart beat. - * - * @param conf Config. - */ - public HeartbeatEndpointTask(EndpointStateMachine rpcEndpoint, - Configuration conf, StateContext context) { - this.rpcEndpoint = rpcEndpoint; - this.conf = conf; - this.context = context; - this.maxContainerActionsPerHB = conf.getInt(HDDS_CONTAINER_ACTION_MAX_LIMIT, - HDDS_CONTAINER_ACTION_MAX_LIMIT_DEFAULT); - this.maxPipelineActionsPerHB = conf.getInt(HDDS_PIPELINE_ACTION_MAX_LIMIT, - HDDS_PIPELINE_ACTION_MAX_LIMIT_DEFAULT); - } - - /** - * Get the container Node ID proto. - * - * @return ContainerNodeIDProto - */ - public DatanodeDetailsProto getDatanodeDetailsProto() { - return datanodeDetailsProto; - } - - /** - * Set container node ID proto. - * - * @param datanodeDetailsProto - the node id. - */ - public void setDatanodeDetailsProto(DatanodeDetailsProto - datanodeDetailsProto) { - this.datanodeDetailsProto = datanodeDetailsProto; - } - - /** - * Computes a result, or throws an exception if unable to do so. - * - * @return computed result - * @throws Exception if unable to compute a result - */ - @Override - public EndpointStateMachine.EndPointStates call() throws Exception { - rpcEndpoint.lock(); - SCMHeartbeatRequestProto.Builder requestBuilder = null; - try { - Preconditions.checkState(this.datanodeDetailsProto != null); - - requestBuilder = SCMHeartbeatRequestProto.newBuilder() - .setDatanodeDetails(datanodeDetailsProto); - addReports(requestBuilder); - addContainerActions(requestBuilder); - addPipelineActions(requestBuilder); - SCMHeartbeatResponseProto reponse = rpcEndpoint.getEndPoint() - .sendHeartbeat(requestBuilder.build()); - processResponse(reponse, datanodeDetailsProto); - rpcEndpoint.setLastSuccessfulHeartbeat(ZonedDateTime.now()); - rpcEndpoint.zeroMissedCount(); - } catch (IOException ex) { - // put back the reports which failed to be sent - putBackReports(requestBuilder); - rpcEndpoint.logIfNeeded(ex); - } finally { - rpcEndpoint.unlock(); - } - return rpcEndpoint.getState(); - } - - // TODO: Make it generic. - private void putBackReports(SCMHeartbeatRequestProto.Builder requestBuilder) { - List reports = new LinkedList<>(); - if (requestBuilder.hasContainerReport()) { - reports.add(requestBuilder.getContainerReport()); - } - if (requestBuilder.hasNodeReport()) { - reports.add(requestBuilder.getNodeReport()); - } - if (requestBuilder.getCommandStatusReportsCount() != 0) { - for (GeneratedMessage msg : requestBuilder - .getCommandStatusReportsList()) { - reports.add(msg); - } - } - context.putBackReports(reports); - } - - /** - * Adds all the available reports to heartbeat. - * - * @param requestBuilder builder to which the report has to be added. - */ - private void addReports(SCMHeartbeatRequestProto.Builder requestBuilder) { - for (GeneratedMessage report : context.getAllAvailableReports()) { - String reportName = report.getDescriptorForType().getFullName(); - for (Descriptors.FieldDescriptor descriptor : - SCMHeartbeatRequestProto.getDescriptor().getFields()) { - String heartbeatFieldName = descriptor.getMessageType().getFullName(); - if (heartbeatFieldName.equals(reportName)) { - if (descriptor.isRepeated()) { - requestBuilder.addRepeatedField(descriptor, report); - } else { - requestBuilder.setField(descriptor, report); - } - } - } - } - } - - /** - * Adds all the pending ContainerActions to the heartbeat. - * - * @param requestBuilder builder to which the report has to be added. - */ - private void addContainerActions( - SCMHeartbeatRequestProto.Builder requestBuilder) { - List actions = context.getPendingContainerAction( - maxContainerActionsPerHB); - if (!actions.isEmpty()) { - ContainerActionsProto cap = ContainerActionsProto.newBuilder() - .addAllContainerActions(actions) - .build(); - requestBuilder.setContainerActions(cap); - } - } - - /** - * Adds all the pending PipelineActions to the heartbeat. - * - * @param requestBuilder builder to which the report has to be added. - */ - private void addPipelineActions( - SCMHeartbeatRequestProto.Builder requestBuilder) { - List actions = context.getPendingPipelineAction( - maxPipelineActionsPerHB); - if (!actions.isEmpty()) { - PipelineActionsProto pap = PipelineActionsProto.newBuilder() - .addAllPipelineActions(actions) - .build(); - requestBuilder.setPipelineActions(pap); - } - } - - /** - * Returns a builder class for HeartbeatEndpointTask task. - * @return Builder. - */ - public static Builder newBuilder() { - return new Builder(); - } - - /** - * Add this command to command processing Queue. - * - * @param response - SCMHeartbeat response. - */ - private void processResponse(SCMHeartbeatResponseProto response, - final DatanodeDetailsProto datanodeDetails) { - Preconditions.checkState(response.getDatanodeUUID() - .equalsIgnoreCase(datanodeDetails.getUuid()), - "Unexpected datanode ID in the response."); - // Verify the response is indeed for this datanode. - for (SCMCommandProto commandResponseProto : response - .getCommandsList()) { - switch (commandResponseProto.getCommandType()) { - case reregisterCommand: - if (rpcEndpoint.getState() == EndPointStates.HEARTBEAT) { - if (LOG.isDebugEnabled()) { - LOG.debug("Received SCM notification to register." - + " Interrupt HEARTBEAT and transit to REGISTER state."); - } - rpcEndpoint.setState(EndPointStates.REGISTER); - } else { - if (LOG.isDebugEnabled()) { - LOG.debug("Illegal state {} found, expecting {}.", - rpcEndpoint.getState().name(), EndPointStates.HEARTBEAT); - } - } - break; - case deleteBlocksCommand: - DeleteBlocksCommand db = DeleteBlocksCommand - .getFromProtobuf( - commandResponseProto.getDeleteBlocksCommandProto()); - if (!db.blocksTobeDeleted().isEmpty()) { - if (LOG.isDebugEnabled()) { - LOG.debug(DeletedContainerBlocksSummary - .getFrom(db.blocksTobeDeleted()) - .toString()); - } - this.context.addCommand(db); - } - break; - case closeContainerCommand: - CloseContainerCommand closeContainer = - CloseContainerCommand.getFromProtobuf( - commandResponseProto.getCloseContainerCommandProto()); - if (LOG.isDebugEnabled()) { - LOG.debug("Received SCM container close request for container {}", - closeContainer.getContainerID()); - } - this.context.addCommand(closeContainer); - break; - case replicateContainerCommand: - ReplicateContainerCommand replicateContainerCommand = - ReplicateContainerCommand.getFromProtobuf( - commandResponseProto.getReplicateContainerCommandProto()); - if (LOG.isDebugEnabled()) { - LOG.debug("Received SCM container replicate request for container {}", - replicateContainerCommand.getContainerID()); - } - this.context.addCommand(replicateContainerCommand); - break; - default: - throw new IllegalArgumentException("Unknown response : " - + commandResponseProto.getCommandType().name()); - } - } - } - - /** - * Builder class for HeartbeatEndpointTask. - */ - public static class Builder { - private EndpointStateMachine endPointStateMachine; - private Configuration conf; - private DatanodeDetails datanodeDetails; - private StateContext context; - - /** - * Constructs the builder class. - */ - public Builder() { - } - - /** - * Sets the endpoint state machine. - * - * @param rpcEndPoint - Endpoint state machine. - * @return Builder - */ - public Builder setEndpointStateMachine(EndpointStateMachine rpcEndPoint) { - this.endPointStateMachine = rpcEndPoint; - return this; - } - - /** - * Sets the Config. - * - * @param config - config - * @return Builder - */ - public Builder setConfig(Configuration config) { - this.conf = config; - return this; - } - - /** - * Sets the NodeID. - * - * @param dnDetails - NodeID proto - * @return Builder - */ - public Builder setDatanodeDetails(DatanodeDetails dnDetails) { - this.datanodeDetails = dnDetails; - return this; - } - - /** - * Sets the context. - * @param stateContext - State context. - * @return this. - */ - public Builder setContext(StateContext stateContext) { - this.context = stateContext; - return this; - } - - public HeartbeatEndpointTask build() { - if (endPointStateMachine == null) { - LOG.error("No endpoint specified."); - throw new IllegalArgumentException("A valid endpoint state machine is" + - " needed to construct HeartbeatEndpointTask task"); - } - - if (conf == null) { - LOG.error("No config specified."); - throw new IllegalArgumentException("A valid configration is needed to" + - " construct HeartbeatEndpointTask task"); - } - - if (datanodeDetails == null) { - LOG.error("No datanode specified."); - throw new IllegalArgumentException("A vaild Node ID is needed to " + - "construct HeartbeatEndpointTask task"); - } - - HeartbeatEndpointTask task = new HeartbeatEndpointTask(this - .endPointStateMachine, this.conf, this.context); - task.setDatanodeDetailsProto(datanodeDetails.getProtoBufMessage()); - return task; - } - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/endpoint/RegisterEndpointTask.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/endpoint/RegisterEndpointTask.java deleted file mode 100644 index 690aa015b14..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/endpoint/RegisterEndpointTask.java +++ /dev/null @@ -1,257 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.container.common.states.endpoint; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import org.apache.commons.lang3.StringUtils; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.PipelineReportsProto; -import org.apache.hadoop.ozone.container.common.statemachine - .EndpointStateMachine; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.NodeReportProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerReportsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMRegisteredResponseProto; -import org.apache.hadoop.ozone.container.common.statemachine.StateContext; -import org.apache.hadoop.ozone.container.ozoneimpl.OzoneContainer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.UUID; -import java.util.concurrent.Callable; -import java.util.concurrent.Future; - -/** - * Register a container with SCM. - */ -public final class RegisterEndpointTask implements - Callable { - static final Logger LOG = LoggerFactory.getLogger(RegisterEndpointTask.class); - - private final EndpointStateMachine rpcEndPoint; - private final Configuration conf; - private Future result; - private DatanodeDetails datanodeDetails; - private final OzoneContainer datanodeContainerManager; - private StateContext stateContext; - - /** - * Creates a register endpoint task. - * - * @param rpcEndPoint - endpoint - * @param conf - conf - * @param ozoneContainer - container - */ - @VisibleForTesting - public RegisterEndpointTask(EndpointStateMachine rpcEndPoint, - Configuration conf, OzoneContainer ozoneContainer, - StateContext context) { - this.rpcEndPoint = rpcEndPoint; - this.conf = conf; - this.datanodeContainerManager = ozoneContainer; - this.stateContext = context; - - } - - /** - * Get the DatanodeDetails. - * - * @return DatanodeDetailsProto - */ - public DatanodeDetails getDatanodeDetails() { - return datanodeDetails; - } - - /** - * Set the contiainerNodeID Proto. - * - * @param datanodeDetails - Container Node ID. - */ - public void setDatanodeDetails( - DatanodeDetails datanodeDetails) { - this.datanodeDetails = datanodeDetails; - } - - /** - * Computes a result, or throws an exception if unable to do so. - * - * @return computed result - * @throws Exception if unable to compute a result - */ - @Override - public EndpointStateMachine.EndPointStates call() throws Exception { - - if (getDatanodeDetails() == null) { - LOG.error("DatanodeDetails cannot be null in RegisterEndpoint task, " + - "shutting down the endpoint."); - return rpcEndPoint.setState(EndpointStateMachine.EndPointStates.SHUTDOWN); - } - - rpcEndPoint.lock(); - try { - - ContainerReportsProto containerReport = datanodeContainerManager - .getContainerReport(); - NodeReportProto nodeReport = datanodeContainerManager.getNodeReport(); - PipelineReportsProto pipelineReportsProto = - datanodeContainerManager.getPipelineReport(); - // TODO : Add responses to the command Queue. - SCMRegisteredResponseProto response = rpcEndPoint.getEndPoint() - .register(datanodeDetails.getProtoBufMessage(), nodeReport, - containerReport, pipelineReportsProto); - Preconditions.checkState(UUID.fromString(response.getDatanodeUUID()) - .equals(datanodeDetails.getUuid()), - "Unexpected datanode ID in the response."); - Preconditions.checkState(!StringUtils.isBlank(response.getClusterID()), - "Invalid cluster ID in the response."); - if (response.hasHostname() && response.hasIpAddress()) { - datanodeDetails.setHostName(response.getHostname()); - datanodeDetails.setIpAddress(response.getIpAddress()); - } - EndpointStateMachine.EndPointStates nextState = - rpcEndPoint.getState().getNextState(); - rpcEndPoint.setState(nextState); - rpcEndPoint.zeroMissedCount(); - this.stateContext.configureHeartbeatFrequency(); - } catch (IOException ex) { - rpcEndPoint.logIfNeeded(ex); - } finally { - rpcEndPoint.unlock(); - } - - return rpcEndPoint.getState(); - } - - /** - * Returns a builder class for RegisterEndPoint task. - * - * @return Builder. - */ - public static Builder newBuilder() { - return new Builder(); - } - - /** - * Builder class for RegisterEndPoint task. - */ - public static class Builder { - private EndpointStateMachine endPointStateMachine; - private Configuration conf; - private DatanodeDetails datanodeDetails; - private OzoneContainer container; - private StateContext context; - - /** - * Constructs the builder class. - */ - public Builder() { - } - - /** - * Sets the endpoint state machine. - * - * @param rpcEndPoint - Endpoint state machine. - * @return Builder - */ - public Builder setEndpointStateMachine(EndpointStateMachine rpcEndPoint) { - this.endPointStateMachine = rpcEndPoint; - return this; - } - - /** - * Sets the Config. - * - * @param config - config - * @return Builder. - */ - public Builder setConfig(Configuration config) { - this.conf = config; - return this; - } - - /** - * Sets the NodeID. - * - * @param dnDetails - NodeID proto - * @return Builder - */ - public Builder setDatanodeDetails(DatanodeDetails dnDetails) { - this.datanodeDetails = dnDetails; - return this; - } - - /** - * Sets the ozonecontainer. - * @param ozoneContainer - * @return Builder - */ - public Builder setOzoneContainer(OzoneContainer ozoneContainer) { - this.container = ozoneContainer; - return this; - } - - public Builder setContext(StateContext stateContext) { - this.context = stateContext; - return this; - } - - public RegisterEndpointTask build() { - if (endPointStateMachine == null) { - LOG.error("No endpoint specified."); - throw new IllegalArgumentException("A valid endpoint state machine is" + - " needed to construct RegisterEndPoint task"); - } - - if (conf == null) { - LOG.error("No config specified."); - throw new IllegalArgumentException( - "A valid configuration is needed to construct RegisterEndpoint " - + "task"); - } - - if (datanodeDetails == null) { - LOG.error("No datanode specified."); - throw new IllegalArgumentException("A vaild Node ID is needed to " + - "construct RegisterEndpoint task"); - } - - if (container == null) { - LOG.error("Container is not specified"); - throw new IllegalArgumentException("Container is not specified to " + - "construct RegisterEndpoint task"); - } - - if (context == null) { - LOG.error("StateContext is not specified"); - throw new IllegalArgumentException("Container is not specified to " + - "construct RegisterEndpoint task"); - } - - RegisterEndpointTask task = new RegisterEndpointTask(this - .endPointStateMachine, this.conf, this.container, this.context); - task.setDatanodeDetails(datanodeDetails); - return task; - } - - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/endpoint/VersionEndpointTask.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/endpoint/VersionEndpointTask.java deleted file mode 100644 index 64e078d2967..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/endpoint/VersionEndpointTask.java +++ /dev/null @@ -1,112 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.container.common.states.endpoint; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMVersionResponseProto; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.container.common.statemachine - .EndpointStateMachine; -import org.apache.hadoop.ozone.container.common.utils.HddsVolumeUtil; -import org.apache.hadoop.ozone.container.common.volume.HddsVolume; -import org.apache.hadoop.ozone.container.common.volume.VolumeSet; -import org.apache.hadoop.ozone.container.ozoneimpl.OzoneContainer; -import org.apache.hadoop.ozone.protocol.VersionResponse; -import org.apache.hadoop.util.DiskChecker.DiskOutOfSpaceException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.Map; -import java.util.concurrent.Callable; - -/** - * Task that returns version. - */ -public class VersionEndpointTask implements - Callable { - public static final Logger LOG = LoggerFactory.getLogger(VersionEndpointTask - .class); - private final EndpointStateMachine rpcEndPoint; - private final Configuration configuration; - private final OzoneContainer ozoneContainer; - - public VersionEndpointTask(EndpointStateMachine rpcEndPoint, - Configuration conf, OzoneContainer container) { - this.rpcEndPoint = rpcEndPoint; - this.configuration = conf; - this.ozoneContainer = container; - } - - /** - * Computes a result, or throws an exception if unable to do so. - * - * @return computed result - * @throws Exception if unable to compute a result - */ - @Override - public EndpointStateMachine.EndPointStates call() throws Exception { - rpcEndPoint.lock(); - try{ - SCMVersionResponseProto versionResponse = - rpcEndPoint.getEndPoint().getVersion(null); - VersionResponse response = VersionResponse.getFromProtobuf( - versionResponse); - rpcEndPoint.setVersion(response); - VolumeSet volumeSet = ozoneContainer.getVolumeSet(); - Map volumeMap = volumeSet.getVolumeMap(); - - String scmId = response.getValue(OzoneConsts.SCM_ID); - String clusterId = response.getValue(OzoneConsts.CLUSTER_ID); - - Preconditions.checkNotNull(scmId, "Reply from SCM: scmId cannot be " + - "null"); - Preconditions.checkNotNull(clusterId, "Reply from SCM: clusterId " + - "cannot be null"); - - // If version file does not exist create version file and also set scmId - for (Map.Entry entry : volumeMap.entrySet()) { - HddsVolume hddsVolume = entry.getValue(); - boolean result = HddsVolumeUtil.checkVolume(hddsVolume, scmId, - clusterId, LOG); - if (!result) { - volumeSet.failVolume(hddsVolume.getHddsRootDir().getPath()); - } - } - if (volumeSet.getVolumesList().size() == 0) { - // All volumes are inconsistent state - throw new DiskOutOfSpaceException("All configured Volumes are in " + - "Inconsistent State"); - } - ozoneContainer.getDispatcher().setScmId(scmId); - - EndpointStateMachine.EndPointStates nextState = - rpcEndPoint.getState().getNextState(); - rpcEndPoint.setState(nextState); - rpcEndPoint.zeroMissedCount(); - } catch (DiskOutOfSpaceException ex) { - rpcEndPoint.setState(EndpointStateMachine.EndPointStates.SHUTDOWN); - } catch(IOException ex) { - rpcEndPoint.logIfNeeded(ex); - } finally { - rpcEndPoint.unlock(); - } - return rpcEndPoint.getState(); - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/endpoint/package-info.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/endpoint/package-info.java deleted file mode 100644 index 112259834dd..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/endpoint/package-info.java +++ /dev/null @@ -1,20 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.container.common.states.endpoint; -/** - This package contains code for RPC endpoints transitions. - */ \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/package-info.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/package-info.java deleted file mode 100644 index 92c953ff410..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/package-info.java +++ /dev/null @@ -1,18 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.common.states; diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/GrpcXceiverService.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/GrpcXceiverService.java deleted file mode 100644 index db4a86aa8c5..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/GrpcXceiverService.java +++ /dev/null @@ -1,80 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.transport.server; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandRequestProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandResponseProto; -import org.apache.hadoop.hdds.protocol.datanode.proto - .XceiverClientProtocolServiceGrpc; -import org.apache.hadoop.ozone.container.common.interfaces.ContainerDispatcher; -import org.apache.ratis.shaded.io.grpc.stub.StreamObserver; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * Grpc Service for handling Container Commands on datanode. - */ -public class GrpcXceiverService extends - XceiverClientProtocolServiceGrpc.XceiverClientProtocolServiceImplBase { - public static final Logger - LOG = LoggerFactory.getLogger(GrpcXceiverService.class); - - private final ContainerDispatcher dispatcher; - - public GrpcXceiverService(ContainerDispatcher dispatcher) { - this.dispatcher = dispatcher; - } - - @Override - public StreamObserver send( - StreamObserver responseObserver) { - return new StreamObserver() { - private final AtomicBoolean isClosed = new AtomicBoolean(false); - - @Override - public void onNext(ContainerCommandRequestProto request) { - try { - ContainerCommandResponseProto resp = dispatcher.dispatch(request); - responseObserver.onNext(resp); - } catch (Throwable e) { - LOG.error("{} got exception when processing" - + " ContainerCommandRequestProto {}: {}", request, e); - responseObserver.onError(e); - } - } - - @Override - public void onError(Throwable t) { - // for now we just log a msg - LOG.error("{}: ContainerCommand send on error. Exception: {}", t); - } - - @Override - public void onCompleted() { - if (isClosed.compareAndSet(false, true)) { - LOG.debug("{}: ContainerCommand send completed"); - responseObserver.onCompleted(); - } - } - }; - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/XceiverServerGrpc.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/XceiverServerGrpc.java deleted file mode 100644 index c51da98fa83..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/XceiverServerGrpc.java +++ /dev/null @@ -1,150 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.transport.server; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandRequestProto; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.PipelineReport; -import org.apache.hadoop.hdds.scm.container.common.helpers.PipelineID; -import org.apache.hadoop.hdds.scm.container.common.helpers. - StorageContainerException; -import org.apache.hadoop.ozone.OzoneConfigKeys; -import org.apache.hadoop.ozone.container.common.interfaces.ContainerDispatcher; - -import org.apache.ratis.shaded.io.grpc.BindableService; -import org.apache.ratis.shaded.io.grpc.Server; -import org.apache.ratis.shaded.io.grpc.ServerBuilder; -import org.apache.ratis.shaded.io.grpc.netty.NettyServerBuilder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.net.SocketAddress; -import java.util.Collections; -import java.util.List; -import java.util.UUID; - -/** - * Creates a Grpc server endpoint that acts as the communication layer for - * Ozone containers. - */ -public final class XceiverServerGrpc implements XceiverServerSpi { - private static final Logger - LOG = LoggerFactory.getLogger(XceiverServerGrpc.class); - private int port; - private UUID id; - private Server server; - private final ContainerDispatcher storageContainer; - - /** - * Constructs a Grpc server class. - * - * @param conf - Configuration - */ - public XceiverServerGrpc(DatanodeDetails datanodeDetails, Configuration conf, - ContainerDispatcher dispatcher, BindableService... additionalServices) { - Preconditions.checkNotNull(conf); - - this.id = datanodeDetails.getUuid(); - this.port = conf.getInt(OzoneConfigKeys.DFS_CONTAINER_IPC_PORT, - OzoneConfigKeys.DFS_CONTAINER_IPC_PORT_DEFAULT); - // Get an available port on current node and - // use that as the container port - if (conf.getBoolean(OzoneConfigKeys.DFS_CONTAINER_IPC_RANDOM_PORT, - OzoneConfigKeys.DFS_CONTAINER_IPC_RANDOM_PORT_DEFAULT)) { - try (ServerSocket socket = new ServerSocket()) { - socket.setReuseAddress(true); - SocketAddress address = new InetSocketAddress(0); - socket.bind(address); - this.port = socket.getLocalPort(); - LOG.info("Found a free port for the server : {}", this.port); - } catch (IOException e) { - LOG.error("Unable find a random free port for the server, " - + "fallback to use default port {}", this.port, e); - } - } - datanodeDetails.setPort( - DatanodeDetails.newPort(DatanodeDetails.Port.Name.STANDALONE, port)); - server = ((NettyServerBuilder) ServerBuilder.forPort(port)) - .maxInboundMessageSize(OzoneConfigKeys.DFS_CONTAINER_CHUNK_MAX_SIZE) - .addService(new GrpcXceiverService(dispatcher)) - .build(); - NettyServerBuilder nettyServerBuilder = - ((NettyServerBuilder) ServerBuilder.forPort(port)) - .maxInboundMessageSize(OzoneConfigKeys.DFS_CONTAINER_CHUNK_MAX_SIZE) - .addService(new GrpcXceiverService(dispatcher)); - for (BindableService service : additionalServices) { - nettyServerBuilder.addService(service); - } - server = nettyServerBuilder.build(); - storageContainer = dispatcher; - } - - @Override - public int getIPCPort() { - return this.port; - } - - /** - * Returns the Replication type supported by this end-point. - * - * @return enum -- {Stand_Alone, Ratis, Grpc, Chained} - */ - @Override - public HddsProtos.ReplicationType getServerType() { - return HddsProtos.ReplicationType.STAND_ALONE; - } - - @Override - public void start() throws IOException { - server.start(); - } - - @Override - public void stop() { - server.shutdown(); - } - - @Override - public void submitRequest(ContainerCommandRequestProto request, - HddsProtos.PipelineID pipelineID) throws IOException { - ContainerProtos.ContainerCommandResponseProto response = - storageContainer.dispatch(request); - if (response.getResult() != ContainerProtos.Result.SUCCESS) { - throw new StorageContainerException(response.getMessage(), - response.getResult()); - } - } - - @Override - public List getPipelineReport() { - return Collections.singletonList( - PipelineReport.newBuilder() - .setPipelineID(PipelineID.valueOf(id).getProtobuf()) - .build()); - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/XceiverServerSpi.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/XceiverServerSpi.java deleted file mode 100644 index 8c3fa5c8ddf..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/XceiverServerSpi.java +++ /dev/null @@ -1,61 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.transport.server; - -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandRequestProto; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.PipelineReport; - -import java.io.IOException; -import java.util.List; - -/** A server endpoint that acts as the communication layer for Ozone - * containers. */ -public interface XceiverServerSpi { - /** Starts the server. */ - void start() throws IOException; - - /** Stops a running server. */ - void stop(); - - /** Get server IPC port. */ - int getIPCPort(); - - /** - * Returns the Replication type supported by this end-point. - * @return enum -- {Stand_Alone, Ratis, Chained} - */ - HddsProtos.ReplicationType getServerType(); - - /** - * submits a containerRequest to be performed by the replication pipeline. - * @param request ContainerCommandRequest - */ - void submitRequest(ContainerCommandRequestProto request, - HddsProtos.PipelineID pipelineID) - throws IOException; - - /** - * Get pipeline report for the XceiverServer instance. - * @return list of report for each pipeline. - */ - List getPipelineReport(); -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/package-info.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/package-info.java deleted file mode 100644 index 59c96f13496..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/package-info.java +++ /dev/null @@ -1,24 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.transport.server; - -/** - * This package contains classes for the server of the storage container - * protocol. - */ diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/ratis/CSMMetrics.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/ratis/CSMMetrics.java deleted file mode 100644 index b6aed605a68..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/ratis/CSMMetrics.java +++ /dev/null @@ -1,115 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.common.transport.server.ratis; - -import com.google.common.annotations.VisibleForTesting; -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.metrics2.MetricsSystem; -import org.apache.hadoop.metrics2.annotation.Metric; -import org.apache.hadoop.metrics2.annotation.Metrics; -import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem; -import org.apache.hadoop.metrics2.lib.MutableCounterLong; - -/** - * This class is for maintaining Container State Machine statistics. - */ -@InterfaceAudience.Private -@Metrics(about="Container State Machine Metrics", context="dfs") -public class CSMMetrics { - public static final String SOURCE_NAME = - CSMMetrics.class.getSimpleName(); - - // ratis op metrics metrics - private @Metric MutableCounterLong numWriteStateMachineOps; - private @Metric MutableCounterLong numReadStateMachineOps; - private @Metric MutableCounterLong numApplyTransactionOps; - - // Failure Metrics - private @Metric MutableCounterLong numWriteStateMachineFails; - private @Metric MutableCounterLong numReadStateMachineFails; - private @Metric MutableCounterLong numApplyTransactionFails; - - public CSMMetrics() { - } - - public static CSMMetrics create() { - MetricsSystem ms = DefaultMetricsSystem.instance(); - return ms.register(SOURCE_NAME, - "Container State Machine", - new CSMMetrics()); - } - - public void incNumWriteStateMachineOps() { - numWriteStateMachineOps.incr(); - } - - public void incNumReadStateMachineOps() { - numReadStateMachineOps.incr(); - } - - public void incNumApplyTransactionsOps() { - numApplyTransactionOps.incr(); - } - - public void incNumWriteStateMachineFails() { - numWriteStateMachineFails.incr(); - } - - public void incNumReadStateMachineFails() { - numReadStateMachineFails.incr(); - } - - public void incNumApplyTransactionsFails() { - numApplyTransactionFails.incr(); - } - - @VisibleForTesting - public long getNumWriteStateMachineOps() { - return numWriteStateMachineOps.value(); - } - - @VisibleForTesting - public long getNumReadStateMachineOps() { - return numReadStateMachineOps.value(); - } - - @VisibleForTesting - public long getNumApplyTransactionsOps() { - return numApplyTransactionOps.value(); - } - - @VisibleForTesting - public long getNumWriteStateMachineFails() { - return numWriteStateMachineFails.value(); - } - - @VisibleForTesting - public long getNumReadStateMachineFails() { - return numReadStateMachineFails.value(); - } - - @VisibleForTesting - public long getNumApplyTransactionsFails() { - return numApplyTransactionFails.value(); - } - - public void unRegister() { - MetricsSystem ms = DefaultMetricsSystem.instance(); - ms.unregisterSource(SOURCE_NAME); - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/ratis/ContainerStateMachine.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/ratis/ContainerStateMachine.java deleted file mode 100644 index a7bef86b222..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/ratis/ContainerStateMachine.java +++ /dev/null @@ -1,656 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.transport.server.ratis; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdds.HddsUtils; -import org.apache.ratis.protocol.RaftGroup; -import org.apache.ratis.protocol.RaftGroupId; -import org.apache.ratis.server.RaftServer; -import org.apache.ratis.shaded.com.google.protobuf - .InvalidProtocolBufferException; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.Type; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.Stage; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandRequestProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandResponseProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .WriteChunkRequestProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ReadChunkRequestProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ReadChunkResponseProto; -import org.apache.hadoop.ozone.container.common.interfaces.ContainerDispatcher; -import org.apache.ratis.protocol.Message; -import org.apache.ratis.protocol.RaftClientRequest; -import org.apache.ratis.server.storage.RaftStorage; -import org.apache.ratis.shaded.com.google.protobuf.ByteString; -import org.apache.ratis.shaded.proto.RaftProtos.RoleInfoProto; -import org.apache.ratis.shaded.proto.RaftProtos.LogEntryProto; -import org.apache.ratis.shaded.proto.RaftProtos.SMLogEntryProto; -import org.apache.ratis.statemachine.StateMachineStorage; -import org.apache.ratis.statemachine.TransactionContext; -import org.apache.ratis.statemachine.impl.BaseStateMachine; -import org.apache.ratis.statemachine.impl.SimpleStateMachineStorage; -import org.apache.ratis.statemachine.impl.TransactionContextImpl; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.stream.Collectors; - -/** A {@link org.apache.ratis.statemachine.StateMachine} for containers. - * - * The stateMachine is responsible for handling different types of container - * requests. The container requests can be divided into readonly and write - * requests. - * - * Read only requests are classified in - * {@link org.apache.hadoop.hdds.HddsUtils#isReadOnly} - * and these readonly requests are replied from the {@link #query(Message)}. - * - * The write requests can be divided into requests with user data - * (WriteChunkRequest) and other request without user data. - * - * Inorder to optimize the write throughput, the writeChunk request is - * processed in 2 phases. The 2 phases are divided in - * {@link #startTransaction(RaftClientRequest)}, in the first phase the user - * data is written directly into the state machine via - * {@link #writeStateMachineData} and in the second phase the - * transaction is committed via {@link #applyTransaction(TransactionContext)} - * - * For the requests with no stateMachine data, the transaction is directly - * committed through - * {@link #applyTransaction(TransactionContext)} - * - * There are 2 ordering operation which are enforced right now in the code, - * 1) Write chunk operation are executed after the create container operation, - * the write chunk operation will fail otherwise as the container still hasn't - * been created. Hence the create container operation has been split in the - * {@link #startTransaction(RaftClientRequest)}, this will help in synchronizing - * the calls in {@link #writeStateMachineData} - * - * 2) Write chunk commit operation is executed after write chunk state machine - * operation. This will ensure that commit operation is sync'd with the state - * machine operation. - * - * Synchronization between {@link #writeStateMachineData} and - * {@link #applyTransaction} need to be enforced in the StateMachine - * implementation. For example, synchronization between writeChunk and - * createContainer in {@link ContainerStateMachine}. - * - * PutBlock is synchronized with WriteChunk operations, PutBlock for a block is - * executed only after all the WriteChunk preceding the PutBlock have finished. - * - * CloseContainer is synchronized with WriteChunk and PutBlock operations, - * CloseContainer for a container is processed after all the preceding write - * operations for the container have finished. - * */ -public class ContainerStateMachine extends BaseStateMachine { - static final Logger LOG = LoggerFactory.getLogger( - ContainerStateMachine.class); - private final SimpleStateMachineStorage storage - = new SimpleStateMachineStorage(); - private final ContainerDispatcher dispatcher; - private ThreadPoolExecutor chunkExecutor; - private final XceiverServerRatis ratisServer; - private final ConcurrentHashMap> - writeChunkFutureMap; - private final ConcurrentHashMap stateMachineMap; - /** - * CSM metrics. - */ - private final CSMMetrics metrics; - - public ContainerStateMachine(ContainerDispatcher dispatcher, - ThreadPoolExecutor chunkExecutor, XceiverServerRatis ratisServer) { - this.dispatcher = dispatcher; - this.chunkExecutor = chunkExecutor; - this.ratisServer = ratisServer; - this.writeChunkFutureMap = new ConcurrentHashMap<>(); - this.stateMachineMap = new ConcurrentHashMap<>(); - metrics = CSMMetrics.create(); - } - - @Override - public StateMachineStorage getStateMachineStorage() { - return storage; - } - - public CSMMetrics getMetrics() { - return metrics; - } - - @Override - public void initialize( - RaftServer server, RaftGroupId id, RaftStorage raftStorage) - throws IOException { - super.initialize(server, id, raftStorage); - storage.init(raftStorage); - // TODO handle snapshots - - // TODO: Add a flag that tells you that initialize has been called. - // Check with Ratis if this feature is done in Ratis. - } - - @Override - public TransactionContext startTransaction(RaftClientRequest request) - throws IOException { - final ContainerCommandRequestProto proto = - getRequestProto(request.getMessage().getContent()); - - final SMLogEntryProto log; - if (proto.getCmdType() == Type.WriteChunk) { - final WriteChunkRequestProto write = proto.getWriteChunk(); - // create the state machine data proto - final WriteChunkRequestProto dataWriteChunkProto = - WriteChunkRequestProto - .newBuilder(write) - .setStage(Stage.WRITE_DATA) - .build(); - ContainerCommandRequestProto dataContainerCommandProto = - ContainerCommandRequestProto - .newBuilder(proto) - .setWriteChunk(dataWriteChunkProto) - .build(); - - // create the log entry proto - final WriteChunkRequestProto commitWriteChunkProto = - WriteChunkRequestProto.newBuilder() - .setBlockID(write.getBlockID()) - .setChunkData(write.getChunkData()) - // skipping the data field as it is - // already set in statemachine data proto - .setStage(Stage.COMMIT_DATA) - .build(); - ContainerCommandRequestProto commitContainerCommandProto = - ContainerCommandRequestProto - .newBuilder(proto) - .setWriteChunk(commitWriteChunkProto) - .build(); - - log = SMLogEntryProto.newBuilder() - .setData(commitContainerCommandProto.toByteString()) - .setStateMachineData(dataContainerCommandProto.toByteString()) - .build(); - } else if (proto.getCmdType() == Type.CreateContainer) { - log = SMLogEntryProto.newBuilder() - .setData(request.getMessage().getContent()) - .setStateMachineData(request.getMessage().getContent()) - .build(); - } else { - log = SMLogEntryProto.newBuilder() - .setData(request.getMessage().getContent()) - .build(); - } - return new TransactionContextImpl(this, request, log); - } - - private ContainerCommandRequestProto getRequestProto(ByteString request) - throws InvalidProtocolBufferException { - return ContainerCommandRequestProto.parseFrom(request); - } - - private ContainerCommandResponseProto dispatchCommand( - ContainerCommandRequestProto requestProto) { - LOG.trace("dispatch {}", requestProto); - ContainerCommandResponseProto response = dispatcher.dispatch(requestProto); - LOG.trace("response {}", response); - return response; - } - - private Message runCommand(ContainerCommandRequestProto requestProto) { - return dispatchCommand(requestProto)::toByteString; - } - - /* - * writeStateMachineData calls are not synchronized with each other - * and also with applyTransaction. - */ - @Override - public CompletableFuture writeStateMachineData(LogEntryProto entry) { - try { - metrics.incNumWriteStateMachineOps(); - final ContainerCommandRequestProto requestProto = - getRequestProto(entry.getSmLogEntry().getStateMachineData()); - Type cmdType = requestProto.getCmdType(); - long containerId = requestProto.getContainerID(); - stateMachineMap - .computeIfAbsent(containerId, k -> new StateMachineHelper()); - CompletableFuture stateMachineFuture = - stateMachineMap.get(containerId) - .handleStateMachineData(requestProto, entry.getIndex()); - if (stateMachineFuture == null) { - throw new IllegalStateException( - "Cmd Type:" + cmdType + " should not have state machine data"); - } - return stateMachineFuture; - } catch (IOException e) { - metrics.incNumWriteStateMachineFails(); - return completeExceptionally(e); - } - } - - @Override - public CompletableFuture query(Message request) { - try { - metrics.incNumReadStateMachineOps(); - final ContainerCommandRequestProto requestProto = - getRequestProto(request.getContent()); - return CompletableFuture.completedFuture(runCommand(requestProto)); - } catch (IOException e) { - metrics.incNumReadStateMachineFails(); - return completeExceptionally(e); - } - } - - private LogEntryProto readStateMachineData(LogEntryProto entry, - ContainerCommandRequestProto requestProto) { - WriteChunkRequestProto writeChunkRequestProto = - requestProto.getWriteChunk(); - // Assert that store log entry is for COMMIT_DATA, the WRITE_DATA is - // written through writeStateMachineData. - Preconditions.checkArgument(writeChunkRequestProto.getStage() - == Stage.COMMIT_DATA); - - // prepare the chunk to be read - ReadChunkRequestProto.Builder readChunkRequestProto = - ReadChunkRequestProto.newBuilder() - .setBlockID(writeChunkRequestProto.getBlockID()) - .setChunkData(writeChunkRequestProto.getChunkData()); - ContainerCommandRequestProto dataContainerCommandProto = - ContainerCommandRequestProto.newBuilder(requestProto) - .setCmdType(Type.ReadChunk) - .setReadChunk(readChunkRequestProto) - .build(); - - // read the chunk - ContainerCommandResponseProto response = - dispatchCommand(dataContainerCommandProto); - ReadChunkResponseProto responseProto = response.getReadChunk(); - - // assert that the response has data in it. - Preconditions.checkNotNull(responseProto.getData()); - - // reconstruct the write chunk request - final WriteChunkRequestProto.Builder dataWriteChunkProto = - WriteChunkRequestProto.newBuilder(writeChunkRequestProto) - // adding the state machine data - .setData(responseProto.getData()) - .setStage(Stage.WRITE_DATA); - - ContainerCommandRequestProto.Builder newStateMachineProto = - ContainerCommandRequestProto.newBuilder(requestProto) - .setWriteChunk(dataWriteChunkProto); - - return recreateLogEntryProto(entry, - newStateMachineProto.build().toByteString()); - } - - private LogEntryProto recreateLogEntryProto(LogEntryProto entry, - ByteString stateMachineData) { - // recreate the log entry - final SMLogEntryProto log = - SMLogEntryProto.newBuilder(entry.getSmLogEntry()) - .setStateMachineData(stateMachineData) - .build(); - return LogEntryProto.newBuilder(entry).setSmLogEntry(log).build(); - } - - /** - * Returns the combined future of all the writeChunks till the given log - * index. The Raft log worker will wait for the stateMachineData to complete - * flush as well. - * - * @param index log index till which the stateMachine data needs to be flushed - * @return Combined future of all writeChunks till the log index given. - */ - @Override - public CompletableFuture flushStateMachineData(long index) { - List> futureList = - writeChunkFutureMap.entrySet().stream().filter(x -> x.getKey() <= index) - .map(x -> x.getValue()).collect(Collectors.toList()); - CompletableFuture combinedFuture = CompletableFuture.allOf( - futureList.toArray(new CompletableFuture[futureList.size()])); - return combinedFuture; - } - /* - * This api is used by the leader while appending logs to the follower - * This allows the leader to read the state machine data from the - * state machine implementation in case cached state machine data has been - * evicted. - */ - @Override - public CompletableFuture readStateMachineData( - LogEntryProto entry) { - SMLogEntryProto smLogEntryProto = entry.getSmLogEntry(); - if (!smLogEntryProto.getStateMachineData().isEmpty()) { - return CompletableFuture.completedFuture(entry); - } - - try { - final ContainerCommandRequestProto requestProto = - getRequestProto(entry.getSmLogEntry().getData()); - // readStateMachineData should only be called for "write" to Ratis. - Preconditions.checkArgument(!HddsUtils.isReadOnly(requestProto)); - - if (requestProto.getCmdType() == Type.WriteChunk) { - return CompletableFuture.supplyAsync(() -> - readStateMachineData(entry, requestProto), - chunkExecutor); - } else if (requestProto.getCmdType() == Type.CreateContainer) { - LogEntryProto log = - recreateLogEntryProto(entry, requestProto.toByteString()); - return CompletableFuture.completedFuture(log); - } else { - throw new IllegalStateException("Cmd type:" + requestProto.getCmdType() - + " cannot have state machine data"); - } - } catch (Exception e) { - LOG.error("unable to read stateMachineData:" + e); - return completeExceptionally(e); - } - } - - /* - * ApplyTransaction calls in Ratis are sequential. - */ - @Override - public CompletableFuture applyTransaction(TransactionContext trx) { - try { - metrics.incNumApplyTransactionsOps(); - ContainerCommandRequestProto requestProto = - getRequestProto(trx.getSMLogEntry().getData()); - Preconditions.checkState(!HddsUtils.isReadOnly(requestProto)); - stateMachineMap.computeIfAbsent(requestProto.getContainerID(), - k -> new StateMachineHelper()); - long index = - trx.getLogEntry() == null ? -1 : trx.getLogEntry().getIndex(); - return stateMachineMap.get(requestProto.getContainerID()) - .executeContainerCommand(requestProto, index); - } catch (IOException e) { - metrics.incNumApplyTransactionsFails(); - return completeExceptionally(e); - } - } - - private static CompletableFuture completeExceptionally(Exception e) { - final CompletableFuture future = new CompletableFuture<>(); - future.completeExceptionally(e); - return future; - } - - @Override - public void notifySlowness(RaftGroup group, RoleInfoProto roleInfoProto) { - ratisServer.handleNodeSlowness(group, roleInfoProto); - } - - @Override - public void notifyExtendedNoLeader(RaftGroup group, - RoleInfoProto roleInfoProto) { - ratisServer.handleNoLeader(group, roleInfoProto); - } - - @Override - public void close() throws IOException { - } - - /** - * Class to manage the future tasks for writeChunks. - */ - static class CommitChunkFutureMap { - private final ConcurrentHashMap> - block2ChunkMap = new ConcurrentHashMap<>(); - - synchronized int removeAndGetSize(long index) { - block2ChunkMap.remove(index); - return block2ChunkMap.size(); - } - - synchronized CompletableFuture add(long index, - CompletableFuture future) { - return block2ChunkMap.put(index, future); - } - - synchronized List> getAll() { - return new ArrayList<>(block2ChunkMap.values()); - } - } - - /** - * This class maintains maps and provide utilities to enforce synchronization - * among createContainer, writeChunk, putBlock and closeContainer. - */ - private class StateMachineHelper { - - private CompletableFuture createContainerFuture; - - // Map for maintaining all writeChunk futures mapped to blockId - private final ConcurrentHashMap - block2ChunkMap; - - // Map for putBlock futures - private final ConcurrentHashMap> - blockCommitMap; - - StateMachineHelper() { - createContainerFuture = null; - block2ChunkMap = new ConcurrentHashMap<>(); - blockCommitMap = new ConcurrentHashMap<>(); - } - - // The following section handles writeStateMachineData transactions - // on a container - - // enqueue the create container future during writeStateMachineData - // so that the write stateMachine data phase of writeChunk wait on - // create container to finish. - private CompletableFuture handleCreateContainer() { - createContainerFuture = new CompletableFuture<>(); - return CompletableFuture.completedFuture(() -> ByteString.EMPTY); - } - - // This synchronizes on create container to finish - private CompletableFuture handleWriteChunk( - ContainerCommandRequestProto requestProto, long entryIndex) { - CompletableFuture containerOpFuture; - - if (createContainerFuture != null) { - containerOpFuture = createContainerFuture - .thenApplyAsync(v -> runCommand(requestProto), chunkExecutor); - } else { - containerOpFuture = CompletableFuture - .supplyAsync(() -> runCommand(requestProto), chunkExecutor); - } - writeChunkFutureMap.put(entryIndex, containerOpFuture); - return containerOpFuture; - } - - CompletableFuture handleStateMachineData( - final ContainerCommandRequestProto requestProto, long index) { - Type cmdType = requestProto.getCmdType(); - if (cmdType == Type.CreateContainer) { - return handleCreateContainer(); - } else if (cmdType == Type.WriteChunk) { - return handleWriteChunk(requestProto, index); - } else { - return null; - } - } - - // The following section handles applyTransaction transactions - // on a container - - private CompletableFuture handlePutBlock( - ContainerCommandRequestProto requestProto) { - List> futureList = new ArrayList<>(); - long localId = - requestProto.getPutBlock().getBlockData().getBlockID().getLocalID(); - // Need not wait for create container future here as it has already - // finished. - if (block2ChunkMap.get(localId) != null) { - futureList.addAll(block2ChunkMap.get(localId).getAll()); - } - CompletableFuture effectiveFuture = - runCommandAfterFutures(futureList, requestProto); - - CompletableFuture putBlockFuture = - effectiveFuture.thenApply(message -> { - blockCommitMap.remove(localId); - return message; - }); - blockCommitMap.put(localId, putBlockFuture); - return putBlockFuture; - } - - // Close Container should be executed only if all pending WriteType - // container cmds get executed. Transactions which can return a future - // are WriteChunk and PutBlock. - private CompletableFuture handleCloseContainer( - ContainerCommandRequestProto requestProto) { - List> futureList = new ArrayList<>(); - - // No need to wait for create container future here as it should have - // already finished. - block2ChunkMap.values().forEach(b -> futureList.addAll(b.getAll())); - futureList.addAll(blockCommitMap.values()); - - // There are pending write Chunk/PutBlock type requests - // Queue this closeContainer request behind all these requests - CompletableFuture closeContainerFuture = - runCommandAfterFutures(futureList, requestProto); - - return closeContainerFuture.thenApply(message -> { - stateMachineMap.remove(requestProto.getContainerID()); - return message; - }); - } - - private CompletableFuture handleChunkCommit( - ContainerCommandRequestProto requestProto, long index) { - WriteChunkRequestProto write = requestProto.getWriteChunk(); - // the data field has already been removed in start Transaction - Preconditions.checkArgument(!write.hasData()); - CompletableFuture stateMachineFuture = - writeChunkFutureMap.remove(index); - CompletableFuture commitChunkFuture = stateMachineFuture - .thenComposeAsync(v -> CompletableFuture - .completedFuture(runCommand(requestProto))); - - long localId = requestProto.getWriteChunk().getBlockID().getLocalID(); - // Put the applyTransaction Future again to the Map. - // closeContainer should synchronize with this. - block2ChunkMap - .computeIfAbsent(localId, id -> new CommitChunkFutureMap()) - .add(index, commitChunkFuture); - return commitChunkFuture.thenApply(message -> { - block2ChunkMap.computeIfPresent(localId, (containerId, chunks) - -> chunks.removeAndGetSize(index) == 0? null: chunks); - return message; - }); - } - - private CompletableFuture runCommandAfterFutures( - List> futureList, - ContainerCommandRequestProto requestProto) { - CompletableFuture effectiveFuture; - if (futureList.isEmpty()) { - effectiveFuture = CompletableFuture - .supplyAsync(() -> runCommand(requestProto)); - - } else { - CompletableFuture allFuture = CompletableFuture.allOf( - futureList.toArray(new CompletableFuture[futureList.size()])); - effectiveFuture = allFuture - .thenApplyAsync(v -> runCommand(requestProto)); - } - return effectiveFuture; - } - - CompletableFuture handleCreateContainer( - ContainerCommandRequestProto requestProto) { - CompletableFuture future = - CompletableFuture.completedFuture(runCommand(requestProto)); - future.thenAccept(m -> { - createContainerFuture.complete(m); - createContainerFuture = null; - }); - return future; - } - - CompletableFuture handleOtherCommands( - ContainerCommandRequestProto requestProto) { - return CompletableFuture.completedFuture(runCommand(requestProto)); - } - - CompletableFuture executeContainerCommand( - ContainerCommandRequestProto requestProto, long index) { - Type cmdType = requestProto.getCmdType(); - switch (cmdType) { - case WriteChunk: - return handleChunkCommit(requestProto, index); - case CloseContainer: - return handleCloseContainer(requestProto); - case PutBlock: - return handlePutBlock(requestProto); - case CreateContainer: - return handleCreateContainer(requestProto); - default: - return handleOtherCommands(requestProto); - } - } - } - - @VisibleForTesting - public ConcurrentHashMap getStateMachineMap() { - return stateMachineMap; - } - - @VisibleForTesting - public CompletableFuture getCreateContainerFuture(long containerId) { - StateMachineHelper helper = stateMachineMap.get(containerId); - return helper == null ? null : helper.createContainerFuture; - } - - @VisibleForTesting - public List> getCommitChunkFutureMap( - long containerId) { - StateMachineHelper helper = stateMachineMap.get(containerId); - if (helper != null) { - List> futureList = new ArrayList<>(); - stateMachineMap.get(containerId).block2ChunkMap.values() - .forEach(b -> futureList.addAll(b.getAll())); - return futureList; - } - return null; - } - - @VisibleForTesting - public Collection> getWriteChunkFutureMap() { - return writeChunkFutureMap.values(); - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/ratis/XceiverServerRatis.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/ratis/XceiverServerRatis.java deleted file mode 100644 index c2ef504c988..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/ratis/XceiverServerRatis.java +++ /dev/null @@ -1,429 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.transport.server.ratis; - -import com.google.common.annotations.VisibleForTesting; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandRequestProto; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.PipelineReport; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ClosePipelineInfo; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.PipelineAction; -import org.apache.hadoop.hdds.scm.HddsServerUtil; -import org.apache.hadoop.hdds.scm.container.common.helpers.PipelineID; -import org.apache.hadoop.ozone.OzoneConfigKeys; -import org.apache.hadoop.ozone.container.common.interfaces.ContainerDispatcher; -import org.apache.hadoop.ozone.container.common.statemachine.StateContext; -import org.apache.hadoop.ozone.container.common.transport.server - .XceiverServerSpi; -import org.apache.ratis.RaftConfigKeys; -import org.apache.ratis.RatisHelper; -import org.apache.ratis.client.RaftClientConfigKeys; -import org.apache.ratis.conf.RaftProperties; -import org.apache.ratis.grpc.GrpcConfigKeys; -import org.apache.ratis.netty.NettyConfigKeys; -import org.apache.ratis.protocol.RaftClientRequest; -import org.apache.ratis.protocol.Message; -import org.apache.ratis.protocol.RaftClientReply; -import org.apache.ratis.protocol.ClientId; -import org.apache.ratis.protocol.NotLeaderException; -import org.apache.ratis.protocol.StateMachineException; -import org.apache.ratis.protocol.RaftPeerId; -import org.apache.ratis.protocol.RaftGroup; -import org.apache.ratis.protocol.RaftGroupId; -import org.apache.ratis.rpc.RpcType; -import org.apache.ratis.rpc.SupportedRpcType; -import org.apache.ratis.server.RaftServer; -import org.apache.ratis.server.RaftServerConfigKeys; -import org.apache.ratis.shaded.proto.RaftProtos; -import org.apache.ratis.shaded.proto.RaftProtos.RoleInfoProto; -import org.apache.ratis.shaded.proto.RaftProtos.ReplicationLevel; -import org.apache.ratis.util.SizeInBytes; -import org.apache.ratis.util.TimeDuration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.net.SocketAddress; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.UUID; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; - -/** - * Creates a ratis server endpoint that acts as the communication layer for - * Ozone containers. - */ -public final class XceiverServerRatis implements XceiverServerSpi { - static final Logger LOG = LoggerFactory.getLogger(XceiverServerRatis.class); - private static final AtomicLong CALL_ID_COUNTER = new AtomicLong(); - - private static long nextCallId() { - return CALL_ID_COUNTER.getAndIncrement() & Long.MAX_VALUE; - } - - private final int port; - private final RaftServer server; - private ThreadPoolExecutor chunkExecutor; - private ClientId clientId = ClientId.randomId(); - private final StateContext context; - private final ReplicationLevel replicationLevel; - private long nodeFailureTimeoutMs; - - private XceiverServerRatis(DatanodeDetails dd, int port, - ContainerDispatcher dispatcher, Configuration conf, StateContext context) - throws IOException { - Objects.requireNonNull(dd, "id == null"); - this.port = port; - RaftProperties serverProperties = newRaftProperties(conf); - final int numWriteChunkThreads = conf.getInt( - OzoneConfigKeys.DFS_CONTAINER_RATIS_NUM_WRITE_CHUNK_THREADS_KEY, - OzoneConfigKeys.DFS_CONTAINER_RATIS_NUM_WRITE_CHUNK_THREADS_DEFAULT); - chunkExecutor = - new ThreadPoolExecutor(numWriteChunkThreads, numWriteChunkThreads, - 100, TimeUnit.SECONDS, - new ArrayBlockingQueue<>(1024), - new ThreadPoolExecutor.CallerRunsPolicy()); - this.context = context; - this.replicationLevel = - conf.getEnum(OzoneConfigKeys.DFS_CONTAINER_RATIS_REPLICATION_LEVEL_KEY, - OzoneConfigKeys.DFS_CONTAINER_RATIS_REPLICATION_LEVEL_DEFAULT); - ContainerStateMachine stateMachine = - new ContainerStateMachine(dispatcher, chunkExecutor, this); - this.server = RaftServer.newBuilder() - .setServerId(RatisHelper.toRaftPeerId(dd)) - .setProperties(serverProperties) - .setStateMachine(stateMachine) - .build(); - } - - - private RaftProperties newRaftProperties(Configuration conf) { - final RaftProperties properties = new RaftProperties(); - - // Set rpc type - final String rpcType = conf.get( - OzoneConfigKeys.DFS_CONTAINER_RATIS_RPC_TYPE_KEY, - OzoneConfigKeys.DFS_CONTAINER_RATIS_RPC_TYPE_DEFAULT); - final RpcType rpc = SupportedRpcType.valueOfIgnoreCase(rpcType); - RaftConfigKeys.Rpc.setType(properties, rpc); - - // set raft segment size - final int raftSegmentSize = conf.getInt( - OzoneConfigKeys.DFS_CONTAINER_RATIS_SEGMENT_SIZE_KEY, - OzoneConfigKeys.DFS_CONTAINER_RATIS_SEGMENT_SIZE_DEFAULT); - RaftServerConfigKeys.Log.setSegmentSizeMax(properties, - SizeInBytes.valueOf(raftSegmentSize)); - - // set raft segment pre-allocated size - final int raftSegmentPreallocatedSize = conf.getInt( - OzoneConfigKeys.DFS_CONTAINER_RATIS_SEGMENT_PREALLOCATED_SIZE_KEY, - OzoneConfigKeys.DFS_CONTAINER_RATIS_SEGMENT_PREALLOCATED_SIZE_DEFAULT); - RaftServerConfigKeys.Log.Appender.setBufferCapacity(properties, - SizeInBytes.valueOf(raftSegmentPreallocatedSize)); - RaftServerConfigKeys.Log.setPreallocatedSize(properties, - SizeInBytes.valueOf(raftSegmentPreallocatedSize)); - - // Set max write buffer size, which is the scm chunk size - final int maxChunkSize = OzoneConfigKeys.DFS_CONTAINER_CHUNK_MAX_SIZE; - RaftServerConfigKeys.Log.setWriteBufferSize(properties, - SizeInBytes.valueOf(maxChunkSize)); - - // Set the client requestTimeout - TimeUnit timeUnit = - OzoneConfigKeys.DFS_RATIS_CLIENT_REQUEST_TIMEOUT_DURATION_DEFAULT - .getUnit(); - long duration = conf.getTimeDuration( - OzoneConfigKeys.DFS_RATIS_CLIENT_REQUEST_TIMEOUT_DURATION_KEY, - OzoneConfigKeys.DFS_RATIS_CLIENT_REQUEST_TIMEOUT_DURATION_DEFAULT - .getDuration(), timeUnit); - final TimeDuration clientRequestTimeout = - TimeDuration.valueOf(duration, timeUnit); - RaftClientConfigKeys.Rpc - .setRequestTimeout(properties, clientRequestTimeout); - - // Set the server Request timeout - timeUnit = OzoneConfigKeys.DFS_RATIS_SERVER_REQUEST_TIMEOUT_DURATION_DEFAULT - .getUnit(); - duration = conf.getTimeDuration( - OzoneConfigKeys.DFS_RATIS_SERVER_REQUEST_TIMEOUT_DURATION_KEY, - OzoneConfigKeys.DFS_RATIS_SERVER_REQUEST_TIMEOUT_DURATION_DEFAULT - .getDuration(), timeUnit); - final TimeDuration serverRequestTimeout = - TimeDuration.valueOf(duration, timeUnit); - RaftServerConfigKeys.Rpc - .setRequestTimeout(properties, serverRequestTimeout); - - // set timeout for a retry cache entry - timeUnit = - OzoneConfigKeys.DFS_RATIS_SERVER_RETRY_CACHE_TIMEOUT_DURATION_DEFAULT - .getUnit(); - duration = conf.getTimeDuration( - OzoneConfigKeys.DFS_RATIS_SERVER_RETRY_CACHE_TIMEOUT_DURATION_KEY, - OzoneConfigKeys.DFS_RATIS_SERVER_RETRY_CACHE_TIMEOUT_DURATION_DEFAULT - .getDuration(), timeUnit); - final TimeDuration retryCacheTimeout = - TimeDuration.valueOf(duration, timeUnit); - RaftServerConfigKeys.RetryCache - .setExpiryTime(properties, retryCacheTimeout); - - // Set the ratis leader election timeout - TimeUnit leaderElectionMinTimeoutUnit = - OzoneConfigKeys. - DFS_RATIS_LEADER_ELECTION_MINIMUM_TIMEOUT_DURATION_DEFAULT - .getUnit(); - duration = conf.getTimeDuration( - OzoneConfigKeys.DFS_RATIS_LEADER_ELECTION_MINIMUM_TIMEOUT_DURATION_KEY, - OzoneConfigKeys. - DFS_RATIS_LEADER_ELECTION_MINIMUM_TIMEOUT_DURATION_DEFAULT - .getDuration(), leaderElectionMinTimeoutUnit); - final TimeDuration leaderElectionMinTimeout = - TimeDuration.valueOf(duration, leaderElectionMinTimeoutUnit); - RaftServerConfigKeys.Rpc - .setTimeoutMin(properties, leaderElectionMinTimeout); - long leaderElectionMaxTimeout = - leaderElectionMinTimeout.toLong(TimeUnit.MILLISECONDS) + 200; - RaftServerConfigKeys.Rpc.setTimeoutMax(properties, - TimeDuration.valueOf(leaderElectionMaxTimeout, TimeUnit.MILLISECONDS)); - // Enable batch append on raft server - RaftServerConfigKeys.Log.Appender.setBatchEnabled(properties, true); - - // Set the maximum cache segments - RaftServerConfigKeys.Log.setMaxCachedSegmentNum(properties, 2); - - // set the node failure timeout - timeUnit = OzoneConfigKeys.DFS_RATIS_SERVER_FAILURE_DURATION_DEFAULT - .getUnit(); - duration = conf.getTimeDuration( - OzoneConfigKeys.DFS_RATIS_SERVER_FAILURE_DURATION_KEY, - OzoneConfigKeys.DFS_RATIS_SERVER_FAILURE_DURATION_DEFAULT - .getDuration(), timeUnit); - final TimeDuration nodeFailureTimeout = - TimeDuration.valueOf(duration, timeUnit); - RaftServerConfigKeys.setLeaderElectionTimeout(properties, - nodeFailureTimeout); - RaftServerConfigKeys.Rpc.setSlownessTimeout(properties, - nodeFailureTimeout); - nodeFailureTimeoutMs = nodeFailureTimeout.toLong(TimeUnit.MILLISECONDS); - - // Set the ratis storage directory - String storageDir = HddsServerUtil.getOzoneDatanodeRatisDirectory(conf); - RaftServerConfigKeys.setStorageDir(properties, new File(storageDir)); - - // For grpc set the maximum message size - GrpcConfigKeys.setMessageSizeMax(properties, - SizeInBytes.valueOf(maxChunkSize + raftSegmentPreallocatedSize)); - - // Set the ratis port number - if (rpc == SupportedRpcType.GRPC) { - GrpcConfigKeys.Server.setPort(properties, port); - } else if (rpc == SupportedRpcType.NETTY) { - NettyConfigKeys.Server.setPort(properties, port); - } - return properties; - } - - public static XceiverServerRatis newXceiverServerRatis( - DatanodeDetails datanodeDetails, Configuration ozoneConf, - ContainerDispatcher dispatcher, StateContext context) throws IOException { - int localPort = ozoneConf.getInt( - OzoneConfigKeys.DFS_CONTAINER_RATIS_IPC_PORT, - OzoneConfigKeys.DFS_CONTAINER_RATIS_IPC_PORT_DEFAULT); - - // Get an available port on current node and - // use that as the container port - if (ozoneConf.getBoolean(OzoneConfigKeys - .DFS_CONTAINER_RATIS_IPC_RANDOM_PORT, - OzoneConfigKeys.DFS_CONTAINER_RATIS_IPC_RANDOM_PORT_DEFAULT)) { - try (ServerSocket socket = new ServerSocket()) { - socket.setReuseAddress(true); - SocketAddress address = new InetSocketAddress(0); - socket.bind(address); - localPort = socket.getLocalPort(); - LOG.info("Found a free port for the server : {}", localPort); - } catch (IOException e) { - LOG.error("Unable find a random free port for the server, " - + "fallback to use default port {}", localPort, e); - } - } - datanodeDetails.setPort( - DatanodeDetails.newPort(DatanodeDetails.Port.Name.RATIS, localPort)); - return new XceiverServerRatis(datanodeDetails, localPort, - dispatcher, ozoneConf, context); - } - - @Override - public void start() throws IOException { - LOG.info("Starting {} {} at port {}", getClass().getSimpleName(), - server.getId(), getIPCPort()); - chunkExecutor.prestartAllCoreThreads(); - server.start(); - } - - @Override - public void stop() { - try { - chunkExecutor.shutdown(); - server.close(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - public int getIPCPort() { - return port; - } - - /** - * Returns the Replication type supported by this end-point. - * - * @return enum -- {Stand_Alone, Ratis, Chained} - */ - @Override - public HddsProtos.ReplicationType getServerType() { - return HddsProtos.ReplicationType.RATIS; - } - - @VisibleForTesting - public RaftServer getServer() { - return server; - } - - private void processReply(RaftClientReply reply) throws IOException { - // NotLeader exception is thrown only when the raft server to which the - // request is submitted is not the leader. The request will be rejected - // and will eventually be executed once the request comes via the leader - // node. - NotLeaderException notLeaderException = reply.getNotLeaderException(); - if (notLeaderException != null) { - throw notLeaderException; - } - StateMachineException stateMachineException = - reply.getStateMachineException(); - if (stateMachineException != null) { - throw stateMachineException; - } - } - - @Override - public void submitRequest(ContainerCommandRequestProto request, - HddsProtos.PipelineID pipelineID) throws IOException { - RaftClientReply reply; - RaftClientRequest raftClientRequest = - createRaftClientRequest(request, pipelineID, - RaftClientRequest.writeRequestType(replicationLevel)); - try { - reply = server.submitClientRequestAsync(raftClientRequest).get(); - } catch (Exception e) { - throw new IOException(e.getMessage(), e); - } - processReply(reply); - } - - private RaftClientRequest createRaftClientRequest( - ContainerCommandRequestProto request, HddsProtos.PipelineID pipelineID, - RaftClientRequest.Type type) { - return new RaftClientRequest(clientId, server.getId(), - PipelineID.getFromProtobuf(pipelineID).getRaftGroupID(), - nextCallId(), 0, Message.valueOf(request.toByteString()), type); - } - - private void handlePipelineFailure(RaftGroupId groupId, - RoleInfoProto roleInfoProto) { - String msg; - UUID datanode = RatisHelper.toDatanodeId(roleInfoProto.getSelf()); - RaftPeerId id = RaftPeerId.valueOf(roleInfoProto.getSelf().getId()); - switch (roleInfoProto.getRole()) { - case CANDIDATE: - msg = datanode + " is in candidate state for " + - roleInfoProto.getCandidateInfo().getLastLeaderElapsedTimeMs() + "ms"; - break; - case LEADER: - StringBuilder sb = new StringBuilder(); - sb.append(datanode).append(" has not seen follower/s"); - for (RaftProtos.ServerRpcProto follower : roleInfoProto.getLeaderInfo() - .getFollowerInfoList()) { - if (follower.getLastRpcElapsedTimeMs() > nodeFailureTimeoutMs) { - sb.append(" ").append(RatisHelper.toDatanodeId(follower.getId())) - .append(" for ").append(follower.getLastRpcElapsedTimeMs()) - .append("ms"); - } - } - msg = sb.toString(); - break; - default: - LOG.error("unknown state:" + roleInfoProto.getRole()); - throw new IllegalStateException("node" + id + " is in illegal role " - + roleInfoProto.getRole()); - } - - PipelineID pipelineID = PipelineID.valueOf(groupId); - ClosePipelineInfo.Builder closePipelineInfo = - ClosePipelineInfo.newBuilder() - .setPipelineID(pipelineID.getProtobuf()) - .setReason(ClosePipelineInfo.Reason.PIPELINE_FAILED) - .setDetailedReason(msg); - - PipelineAction action = PipelineAction.newBuilder() - .setClosePipeline(closePipelineInfo) - .setAction(PipelineAction.Action.CLOSE) - .build(); - context.addPipelineActionIfAbsent(action); - LOG.debug( - "pipeline Action " + action.getAction() + " on pipeline " + pipelineID - + ".Reason : " + action.getClosePipeline().getDetailedReason()); - } - - @Override - public List getPipelineReport() { - try { - Iterable gids = server.getGroupIds(); - List reports = new ArrayList<>(); - for (RaftGroupId groupId : gids) { - reports.add(PipelineReport.newBuilder() - .setPipelineID(PipelineID.valueOf(groupId).getProtobuf()) - .build()); - } - return reports; - } catch (Exception e) { - return null; - } - } - - void handleNodeSlowness(RaftGroup group, RoleInfoProto roleInfoProto) { - handlePipelineFailure(group.getGroupId(), roleInfoProto); - } - - void handleNoLeader(RaftGroup group, RoleInfoProto roleInfoProto) { - handlePipelineFailure(group.getGroupId(), roleInfoProto); - } -} \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/ratis/package-info.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/ratis/package-info.java deleted file mode 100644 index 8debfe02837..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/transport/server/ratis/package-info.java +++ /dev/null @@ -1,23 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.common.transport.server.ratis; - -/** - * This package contains classes for the server implementation - * using Apache Ratis - */ diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/utils/ContainerCache.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/utils/ContainerCache.java deleted file mode 100644 index c63eb731c7a..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/utils/ContainerCache.java +++ /dev/null @@ -1,172 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.utils; - -import com.google.common.base.Preconditions; -import org.apache.commons.collections.MapIterator; -import org.apache.commons.collections.map.LRUMap; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.ozone.OzoneConfigKeys; -import org.apache.hadoop.utils.MetadataStore; -import org.apache.hadoop.utils.MetadataStoreBuilder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -/** - * container cache is a LRUMap that maintains the DB handles. - */ -public final class ContainerCache extends LRUMap { - private static final Logger LOG = - LoggerFactory.getLogger(ContainerCache.class); - private final Lock lock = new ReentrantLock(); - private static ContainerCache cache; - private static final float LOAD_FACTOR = 0.75f; - /** - * Constructs a cache that holds DBHandle references. - */ - private ContainerCache(int maxSize, float loadFactor, boolean - scanUntilRemovable) { - super(maxSize, loadFactor, scanUntilRemovable); - } - - /** - * Return a singleton instance of {@link ContainerCache} - * that holds the DB handlers. - * - * @param conf - Configuration. - * @return A instance of {@link ContainerCache}. - */ - public synchronized static ContainerCache getInstance(Configuration conf) { - if (cache == null) { - int cacheSize = conf.getInt(OzoneConfigKeys.OZONE_CONTAINER_CACHE_SIZE, - OzoneConfigKeys.OZONE_CONTAINER_CACHE_DEFAULT); - cache = new ContainerCache(cacheSize, LOAD_FACTOR, true); - } - return cache; - } - - /** - * Closes a db instance. - * - * @param containerID - ID of the container to be closed. - * @param db - db instance to close. - */ - private void closeDB(long containerID, MetadataStore db) { - if (db != null) { - try { - db.close(); - } catch (IOException e) { - LOG.error("Error closing DB. Container: " + containerID, e); - } - } - } - - /** - * Closes all the db instances and resets the cache. - */ - public void shutdownCache() { - lock.lock(); - try { - // iterate the cache and close each db - MapIterator iterator = cache.mapIterator(); - while (iterator.hasNext()) { - iterator.next(); - MetadataStore db = (MetadataStore) iterator.getValue(); - closeDB(((Number)iterator.getKey()).longValue(), db); - } - // reset the cache - cache.clear(); - } finally { - lock.unlock(); - } - } - - /** - * {@inheritDoc} - */ - @Override - protected boolean removeLRU(LinkEntry entry) { - lock.lock(); - try { - MetadataStore db = (MetadataStore) entry.getValue(); - closeDB(((Number)entry.getKey()).longValue(), db); - } finally { - lock.unlock(); - } - return true; - } - - /** - * Returns a DB handle if available, create the handler otherwise. - * - * @param containerID - ID of the container. - * @param containerDBType - DB type of the container. - * @param containerDBPath - DB path of the container. - * @return MetadataStore. - */ - public MetadataStore getDB(long containerID, String containerDBType, String - containerDBPath) - throws IOException { - Preconditions.checkState(containerID >= 0, - "Container ID cannot be negative."); - lock.lock(); - try { - MetadataStore db = (MetadataStore) this.get(containerID); - - if (db == null) { - db = MetadataStoreBuilder.newBuilder() - .setDbFile(new File(containerDBPath)) - .setCreateIfMissing(false) - .setDBType(containerDBType) - .build(); - this.put(containerID, db); - } - return db; - } catch (Exception e) { - LOG.error("Error opening DB. Container:{} ContainerPath:{}", - containerID, containerDBPath, e); - throw e; - } finally { - lock.unlock(); - } - } - - /** - * Remove a DB handler from cache. - * - * @param containerID - ID of the container. - */ - public void removeDB(long containerID) { - Preconditions.checkState(containerID >= 0, - "Container ID cannot be negative."); - lock.lock(); - try { - MetadataStore db = (MetadataStore)this.get(containerID); - closeDB(containerID, db); - this.remove(containerID); - } finally { - lock.unlock(); - } - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/utils/HddsVolumeUtil.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/utils/HddsVolumeUtil.java deleted file mode 100644 index bc0bd056b1d..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/utils/HddsVolumeUtil.java +++ /dev/null @@ -1,219 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.utils; - -import com.google.common.annotations.VisibleForTesting; -import org.apache.commons.lang3.StringUtils; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.common.InconsistentStorageStateException; -import org.apache.hadoop.ozone.container.common.DataNodeLayoutVersion; -import org.apache.hadoop.ozone.container.common.volume.HddsVolume; -import org.apache.hadoop.util.Time; -import org.slf4j.Logger; - -import java.io.File; -import java.io.IOException; -import java.util.Properties; -import java.util.UUID; - -/** - * A util class for {@link HddsVolume}. - */ -public final class HddsVolumeUtil { - - // Private constructor for Utility class. Unused. - private HddsVolumeUtil() { - } - - private static final String VERSION_FILE = "VERSION"; - private static final String STORAGE_ID_PREFIX = "DS-"; - - public static File getVersionFile(File rootDir) { - return new File(rootDir, VERSION_FILE); - } - - public static String generateUuid() { - return STORAGE_ID_PREFIX + UUID.randomUUID(); - } - - /** - * Get hddsRoot from volume root. If volumeRoot points to hddsRoot, it is - * returned as is. - * For a volumeRoot /data/disk1, the hddsRoot is /data/disk1/hdds. - * @param volumeRoot root of the volume. - * @return hddsRoot of the volume. - */ - public static String getHddsRoot(String volumeRoot) { - if (volumeRoot.endsWith(HddsVolume.HDDS_VOLUME_DIR)) { - return volumeRoot; - } else { - File hddsRoot = new File(volumeRoot, HddsVolume.HDDS_VOLUME_DIR); - return hddsRoot.getPath(); - } - } - - /** - * Returns storageID if it is valid. Throws an exception otherwise. - */ - @VisibleForTesting - public static String getStorageID(Properties props, File versionFile) - throws InconsistentStorageStateException { - return getProperty(props, OzoneConsts.STORAGE_ID, versionFile); - } - - /** - * Returns clusterID if it is valid. It should match the clusterID from the - * Datanode. Throws an exception otherwise. - */ - @VisibleForTesting - public static String getClusterID(Properties props, File versionFile, - String clusterID) throws InconsistentStorageStateException { - String cid = getProperty(props, OzoneConsts.CLUSTER_ID, versionFile); - - if (clusterID == null) { - return cid; - } - if (!clusterID.equals(cid)) { - throw new InconsistentStorageStateException("Mismatched " + - "ClusterIDs. Version File : " + versionFile + " has clusterID: " + - cid + " and Datanode has clusterID: " + clusterID); - } - return cid; - } - - /** - * Returns datanodeUuid if it is valid. It should match the UUID of the - * Datanode. Throws an exception otherwise. - */ - @VisibleForTesting - public static String getDatanodeUUID(Properties props, File versionFile, - String datanodeUuid) - throws InconsistentStorageStateException { - String datanodeID = getProperty(props, OzoneConsts.DATANODE_UUID, - versionFile); - - if (datanodeUuid != null && !datanodeUuid.equals(datanodeID)) { - throw new InconsistentStorageStateException("Mismatched " + - "DatanodeUUIDs. Version File : " + versionFile + " has datanodeUuid: " - + datanodeID + " and Datanode has datanodeUuid: " + datanodeUuid); - } - return datanodeID; - } - - /** - * Returns creationTime if it is valid. Throws an exception otherwise. - */ - @VisibleForTesting - public static long getCreationTime(Properties props, File versionFile) - throws InconsistentStorageStateException { - String cTimeStr = getProperty(props, OzoneConsts.CTIME, versionFile); - - long cTime = Long.parseLong(cTimeStr); - long currentTime = Time.now(); - if (cTime > currentTime || cTime < 0) { - throw new InconsistentStorageStateException("Invalid Creation time in " + - "Version File : " + versionFile + " - " + cTime + ". Current system" + - " time is " + currentTime); - } - return cTime; - } - - /** - * Returns layOutVersion if it is valid. Throws an exception otherwise. - */ - @VisibleForTesting - public static int getLayOutVersion(Properties props, File versionFile) throws - InconsistentStorageStateException { - String lvStr = getProperty(props, OzoneConsts.LAYOUTVERSION, versionFile); - - int lv = Integer.parseInt(lvStr); - if(DataNodeLayoutVersion.getLatestVersion().getVersion() != lv) { - throw new InconsistentStorageStateException("Invalid layOutVersion. " + - "Version file has layOutVersion as " + lv + " and latest Datanode " + - "layOutVersion is " + - DataNodeLayoutVersion.getLatestVersion().getVersion()); - } - return lv; - } - - private static String getProperty(Properties props, String propName, File - versionFile) - throws InconsistentStorageStateException { - String value = props.getProperty(propName); - if (StringUtils.isBlank(value)) { - throw new InconsistentStorageStateException("Invalid " + propName + - ". Version File : " + versionFile + " has null or empty " + propName); - } - return value; - } - - /** - * Check Volume is consistent state or not. - * @param hddsVolume - * @param scmId - * @param clusterId - * @param logger - * @return true - if volume is in consistent state, otherwise false. - */ - public static boolean checkVolume(HddsVolume hddsVolume, String scmId, String - clusterId, Logger logger) { - File hddsRoot = hddsVolume.getHddsRootDir(); - String volumeRoot = hddsRoot.getPath(); - File scmDir = new File(hddsRoot, scmId); - - try { - hddsVolume.format(clusterId); - } catch (IOException ex) { - logger.error("Error during formatting volume {}, exception is {}", - volumeRoot, ex); - return false; - } - - File[] hddsFiles = hddsRoot.listFiles(); - - if(hddsFiles == null) { - // This is the case for IOException, where listFiles returns null. - // So, we fail the volume. - return false; - } else if (hddsFiles.length == 1) { - // DN started for first time or this is a newly added volume. - // So we create scm directory. - if (!scmDir.mkdir()) { - logger.error("Unable to create scmDir {}", scmDir); - return false; - } - return true; - } else if(hddsFiles.length == 2) { - // The files should be Version and SCM directory - if (scmDir.exists()) { - return true; - } else { - logger.error("Volume {} is in Inconsistent state, expected scm " + - "directory {} does not exist", volumeRoot, scmDir - .getAbsolutePath()); - return false; - } - } else { - // The hdds root dir should always have 2 files. One is Version file - // and other is SCM directory. - return false; - } - - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/utils/package-info.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/utils/package-info.java deleted file mode 100644 index 08264f084a0..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/utils/package-info.java +++ /dev/null @@ -1,18 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.common.utils; \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/HddsVolume.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/HddsVolume.java deleted file mode 100644 index 6b90146753a..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/HddsVolume.java +++ /dev/null @@ -1,408 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.volume; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.GetSpaceUsed; -import org.apache.hadoop.fs.StorageType; -import org.apache.hadoop.hdfs.server.datanode.StorageLocation; -import org.apache.hadoop.ozone.common.InconsistentStorageStateException; -import org.apache.hadoop.ozone.container.common.DataNodeLayoutVersion; -import org.apache.hadoop.ozone.container.common.helpers.DatanodeVersionFile; -import org.apache.hadoop.ozone.container.common.impl.ChunkLayOutVersion; -import org.apache.hadoop.ozone.container.common.utils.HddsVolumeUtil; - -import org.apache.hadoop.util.Time; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.util.Properties; -import java.util.UUID; - -/** - * HddsVolume represents volume in a datanode. {@link VolumeSet} maitains a - * list of HddsVolumes, one for each volume in the Datanode. - * {@link VolumeInfo} in encompassed by this class. - * - * The disk layout per volume is as follows: - * ../hdds/VERSION - * ../hdds/<>/current/<>/<>/metadata - * ../hdds/<>/current/<>/<>/<> - * - * Each hdds volume has its own VERSION file. The hdds volume will have one - * scmUuid directory for each SCM it is a part of (currently only one SCM is - * supported). - * - * During DN startup, if the VERSION file exists, we verify that the - * clusterID in the version file matches the clusterID from SCM. - */ -public final class HddsVolume { - - private static final Logger LOG = LoggerFactory.getLogger(HddsVolume.class); - - public static final String HDDS_VOLUME_DIR = "hdds"; - - private final File hddsRootDir; - private final VolumeInfo volumeInfo; - private VolumeState state; - private final VolumeIOStats volumeIOStats; - - // VERSION file properties - private String storageID; // id of the file system - private String clusterID; // id of the cluster - private String datanodeUuid; // id of the DataNode - private long cTime; // creation time of the file system state - private int layoutVersion; // layout version of the storage data - - /** - * Builder for HddsVolume. - */ - public static class Builder { - private final String volumeRootStr; - private Configuration conf; - private StorageType storageType; - private long configuredCapacity; - - private String datanodeUuid; - private String clusterID; - private boolean failedVolume = false; - - public Builder(String rootDirStr) { - this.volumeRootStr = rootDirStr; - } - - public Builder conf(Configuration config) { - this.conf = config; - return this; - } - - public Builder storageType(StorageType st) { - this.storageType = st; - return this; - } - - public Builder configuredCapacity(long capacity) { - this.configuredCapacity = capacity; - return this; - } - - public Builder datanodeUuid(String datanodeUUID) { - this.datanodeUuid = datanodeUUID; - return this; - } - - public Builder clusterID(String cid) { - this.clusterID = cid; - return this; - } - - // This is added just to create failed volume objects, which will be used - // to create failed HddsVolume objects in the case of any exceptions caused - // during creating HddsVolume object. - public Builder failedVolume(boolean failed) { - this.failedVolume = failed; - return this; - } - - public HddsVolume build() throws IOException { - return new HddsVolume(this); - } - } - - private HddsVolume(Builder b) throws IOException { - if (!b.failedVolume) { - StorageLocation location = StorageLocation.parse(b.volumeRootStr); - hddsRootDir = new File(location.getUri().getPath(), HDDS_VOLUME_DIR); - this.state = VolumeState.NOT_INITIALIZED; - this.clusterID = b.clusterID; - this.datanodeUuid = b.datanodeUuid; - this.volumeIOStats = new VolumeIOStats(); - - VolumeInfo.Builder volumeBuilder = - new VolumeInfo.Builder(b.volumeRootStr, b.conf) - .storageType(b.storageType) - .configuredCapacity(b.configuredCapacity); - this.volumeInfo = volumeBuilder.build(); - - LOG.info("Creating Volume: " + this.hddsRootDir + " of storage type : " + - b.storageType + " and capacity : " + volumeInfo.getCapacity()); - - initialize(); - } else { - // Builder is called with failedVolume set, so create a failed volume - // HddsVolumeObject. - hddsRootDir = new File(b.volumeRootStr); - volumeIOStats = null; - volumeInfo = null; - storageID = UUID.randomUUID().toString(); - state = VolumeState.FAILED; - } - } - - public VolumeInfo getVolumeInfo() { - return volumeInfo; - } - - /** - * Initializes the volume. - * Creates the Version file if not present, - * otherwise returns with IOException. - * @throws IOException - */ - private void initialize() throws IOException { - VolumeState intialVolumeState = analyzeVolumeState(); - switch (intialVolumeState) { - case NON_EXISTENT: - // Root directory does not exist. Create it. - if (!hddsRootDir.mkdir()) { - throw new IOException("Cannot create directory " + hddsRootDir); - } - setState(VolumeState.NOT_FORMATTED); - createVersionFile(); - break; - case NOT_FORMATTED: - // Version File does not exist. Create it. - createVersionFile(); - break; - case NOT_INITIALIZED: - // Version File exists. Verify its correctness and update property fields. - readVersionFile(); - setState(VolumeState.NORMAL); - break; - case INCONSISTENT: - // Volume Root is in an inconsistent state. Skip loading this volume. - throw new IOException("Volume is in an " + VolumeState.INCONSISTENT + - " state. Skipped loading volume: " + hddsRootDir.getPath()); - default: - throw new IOException("Unrecognized initial state : " + - intialVolumeState + "of volume : " + hddsRootDir); - } - } - - private VolumeState analyzeVolumeState() { - if (!hddsRootDir.exists()) { - // Volume Root does not exist. - return VolumeState.NON_EXISTENT; - } - if (!hddsRootDir.isDirectory()) { - // Volume Root exists but is not a directory. - return VolumeState.INCONSISTENT; - } - File[] files = hddsRootDir.listFiles(); - if (files == null || files.length == 0) { - // Volume Root exists and is empty. - return VolumeState.NOT_FORMATTED; - } - if (!getVersionFile().exists()) { - // Volume Root is non empty but VERSION file does not exist. - return VolumeState.INCONSISTENT; - } - // Volume Root and VERSION file exist. - return VolumeState.NOT_INITIALIZED; - } - - public void format(String cid) throws IOException { - Preconditions.checkNotNull(cid, "clusterID cannot be null while " + - "formatting Volume"); - this.clusterID = cid; - initialize(); - } - - /** - * Create Version File and write property fields into it. - * @throws IOException - */ - private void createVersionFile() throws IOException { - this.storageID = HddsVolumeUtil.generateUuid(); - this.cTime = Time.now(); - this.layoutVersion = ChunkLayOutVersion.getLatestVersion().getVersion(); - - if (this.clusterID == null || datanodeUuid == null) { - // HddsDatanodeService does not have the cluster information yet. Wait - // for registration with SCM. - LOG.debug("ClusterID not available. Cannot format the volume {}", - this.hddsRootDir.getPath()); - setState(VolumeState.NOT_FORMATTED); - } else { - // Write the version file to disk. - writeVersionFile(); - setState(VolumeState.NORMAL); - } - } - - private void writeVersionFile() throws IOException { - Preconditions.checkNotNull(this.storageID, - "StorageID cannot be null in Version File"); - Preconditions.checkNotNull(this.clusterID, - "ClusterID cannot be null in Version File"); - Preconditions.checkNotNull(this.datanodeUuid, - "DatanodeUUID cannot be null in Version File"); - Preconditions.checkArgument(this.cTime > 0, - "Creation Time should be positive"); - Preconditions.checkArgument(this.layoutVersion == - DataNodeLayoutVersion.getLatestVersion().getVersion(), - "Version File should have the latest LayOutVersion"); - - File versionFile = getVersionFile(); - LOG.debug("Writing Version file to disk, {}", versionFile); - - DatanodeVersionFile dnVersionFile = new DatanodeVersionFile(this.storageID, - this.clusterID, this.datanodeUuid, this.cTime, this.layoutVersion); - dnVersionFile.createVersionFile(versionFile); - } - - /** - * Read Version File and update property fields. - * Get common storage fields. - * Should be overloaded if additional fields need to be read. - * - * @throws IOException on error - */ - private void readVersionFile() throws IOException { - File versionFile = getVersionFile(); - Properties props = DatanodeVersionFile.readFrom(versionFile); - if (props.isEmpty()) { - throw new InconsistentStorageStateException( - "Version file " + versionFile + " is missing"); - } - - LOG.debug("Reading Version file from disk, {}", versionFile); - this.storageID = HddsVolumeUtil.getStorageID(props, versionFile); - this.clusterID = HddsVolumeUtil.getClusterID(props, versionFile, - this.clusterID); - this.datanodeUuid = HddsVolumeUtil.getDatanodeUUID(props, versionFile, - this.datanodeUuid); - this.cTime = HddsVolumeUtil.getCreationTime(props, versionFile); - this.layoutVersion = HddsVolumeUtil.getLayOutVersion(props, versionFile); - } - - private File getVersionFile() { - return HddsVolumeUtil.getVersionFile(hddsRootDir); - } - - public File getHddsRootDir() { - return hddsRootDir; - } - - public StorageType getStorageType() { - if(volumeInfo != null) { - return volumeInfo.getStorageType(); - } - return StorageType.DEFAULT; - } - - public String getStorageID() { - return storageID; - } - - public String getClusterID() { - return clusterID; - } - - public String getDatanodeUuid() { - return datanodeUuid; - } - - public long getCTime() { - return cTime; - } - - public int getLayoutVersion() { - return layoutVersion; - } - - public VolumeState getStorageState() { - return state; - } - - public long getCapacity() throws IOException { - if(volumeInfo != null) { - return volumeInfo.getCapacity(); - } - return 0; - } - - public long getAvailable() throws IOException { - if(volumeInfo != null) { - return volumeInfo.getAvailable(); - } - return 0; - } - - public void setState(VolumeState state) { - this.state = state; - } - - public boolean isFailed() { - return (state == VolumeState.FAILED); - } - - public VolumeIOStats getVolumeIOStats() { - return volumeIOStats; - } - - public void failVolume() { - setState(VolumeState.FAILED); - if (volumeInfo != null) { - volumeInfo.shutdownUsageThread(); - } - } - - public void shutdown() { - this.state = VolumeState.NON_EXISTENT; - if (volumeInfo != null) { - volumeInfo.shutdownUsageThread(); - } - } - - /** - * VolumeState represents the different states a HddsVolume can be in. - * NORMAL => Volume can be used for storage - * FAILED => Volume has failed due and can no longer be used for - * storing containers. - * NON_EXISTENT => Volume Root dir does not exist - * INCONSISTENT => Volume Root dir is not empty but VERSION file is - * missing or Volume Root dir is not a directory - * NOT_FORMATTED => Volume Root exists but not formatted (no VERSION file) - * NOT_INITIALIZED => VERSION file exists but has not been verified for - * correctness. - */ - public enum VolumeState { - NORMAL, - FAILED, - NON_EXISTENT, - INCONSISTENT, - NOT_FORMATTED, - NOT_INITIALIZED - } - - /** - * Only for testing. Do not use otherwise. - */ - @VisibleForTesting - public void setScmUsageForTesting(GetSpaceUsed scmUsageForTest) { - if (volumeInfo != null) { - volumeInfo.setScmUsageForTesting(scmUsageForTest); - } - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/RoundRobinVolumeChoosingPolicy.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/RoundRobinVolumeChoosingPolicy.java deleted file mode 100644 index 75c92ec024b..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/RoundRobinVolumeChoosingPolicy.java +++ /dev/null @@ -1,83 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.volume; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.ozone.container.common.interfaces.VolumeChoosingPolicy; -import org.apache.hadoop.util.DiskChecker.DiskOutOfSpaceException; - -import java.io.IOException; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * Choose volumes in round-robin order. - * The caller should synchronize access to the list of volumes. - */ -public class RoundRobinVolumeChoosingPolicy implements VolumeChoosingPolicy { - - public static final Log LOG = LogFactory.getLog( - RoundRobinVolumeChoosingPolicy.class); - - // Stores the index of the next volume to be returned. - private AtomicInteger nextVolumeIndex = new AtomicInteger(0); - - @Override - public HddsVolume chooseVolume(List volumes, - long maxContainerSize) throws IOException { - - // No volumes available to choose from - if (volumes.size() < 1) { - throw new DiskOutOfSpaceException("No more available volumes"); - } - - // since volumes could've been removed because of the failure - // make sure we are not out of bounds - int nextIndex = nextVolumeIndex.get(); - int currentVolumeIndex = nextIndex < volumes.size() ? nextIndex : 0; - - int startVolumeIndex = currentVolumeIndex; - long maxAvailable = 0; - - while (true) { - final HddsVolume volume = volumes.get(currentVolumeIndex); - long availableVolumeSize = volume.getAvailable(); - - currentVolumeIndex = (currentVolumeIndex + 1) % volumes.size(); - - if (availableVolumeSize > maxContainerSize) { - nextVolumeIndex.compareAndSet(nextIndex, currentVolumeIndex); - return volume; - } - - if (availableVolumeSize > maxAvailable) { - maxAvailable = availableVolumeSize; - } - - if (currentVolumeIndex == startVolumeIndex) { - throw new DiskOutOfSpaceException("Out of space: " - + "The volume with the most available space (=" + maxAvailable - + " B) is less than the container size (=" + maxContainerSize - + " B)."); - } - - } - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/VolumeIOStats.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/VolumeIOStats.java deleted file mode 100644 index 9e2eb221e81..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/VolumeIOStats.java +++ /dev/null @@ -1,139 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.volume; - -import java.util.concurrent.atomic.AtomicLong; - -/** - * This class is used to track Volume IO stats for each HDDS Volume. - */ -public class VolumeIOStats { - - private final AtomicLong readBytes; - private final AtomicLong readOpCount; - private final AtomicLong writeBytes; - private final AtomicLong writeOpCount; - private final AtomicLong readTime; - private final AtomicLong writeTime; - - public VolumeIOStats() { - readBytes = new AtomicLong(0); - readOpCount = new AtomicLong(0); - writeBytes = new AtomicLong(0); - writeOpCount = new AtomicLong(0); - readTime = new AtomicLong(0); - writeTime = new AtomicLong(0); - } - - /** - * Increment number of bytes read from the volume. - * @param bytesRead - */ - public void incReadBytes(long bytesRead) { - readBytes.addAndGet(bytesRead); - } - - /** - * Increment the read operations performed on the volume. - */ - public void incReadOpCount() { - readOpCount.incrementAndGet(); - } - - /** - * Increment number of bytes written on to the volume. - * @param bytesWritten - */ - public void incWriteBytes(long bytesWritten) { - writeBytes.addAndGet(bytesWritten); - } - - /** - * Increment the write operations performed on the volume. - */ - public void incWriteOpCount() { - writeOpCount.incrementAndGet(); - } - - /** - * Increment the time taken by read operation on the volume. - * @param time - */ - public void incReadTime(long time) { - readTime.addAndGet(time); - } - - /** - * Increment the time taken by write operation on the volume. - * @param time - */ - public void incWriteTime(long time) { - writeTime.addAndGet(time); - } - - /** - * Returns total number of bytes read from the volume. - * @return long - */ - public long getReadBytes() { - return readBytes.get(); - } - - /** - * Returns total number of bytes written to the volume. - * @return long - */ - public long getWriteBytes() { - return writeBytes.get(); - } - - /** - * Returns total number of read operations performed on the volume. - * @return long - */ - public long getReadOpCount() { - return readOpCount.get(); - } - - /** - * Returns total number of write operations performed on the volume. - * @return long - */ - public long getWriteOpCount() { - return writeOpCount.get(); - } - - /** - * Returns total read operations time on the volume. - * @return long - */ - public long getReadTime() { - return readTime.get(); - } - - /** - * Returns total write operations time on the volume. - * @return long - */ - public long getWriteTime() { - return writeTime.get(); - } - - -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/VolumeInfo.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/VolumeInfo.java deleted file mode 100644 index 62fca6312d8..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/VolumeInfo.java +++ /dev/null @@ -1,140 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.volume; - -import com.google.common.annotations.VisibleForTesting; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.GetSpaceUsed; -import org.apache.hadoop.fs.StorageType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; - -/** - * Stores information about a disk/volume. - */ -public class VolumeInfo { - - private static final Logger LOG = LoggerFactory.getLogger(VolumeInfo.class); - - private final String rootDir; - private final StorageType storageType; - - // Space usage calculator - private VolumeUsage usage; - // Capacity configured. This is useful when we want to - // limit the visible capacity for tests. If negative, then we just - // query from the filesystem. - private long configuredCapacity; - - /** - * Builder for VolumeInfo. - */ - public static class Builder { - private final Configuration conf; - private final String rootDir; - private StorageType storageType; - private long configuredCapacity; - - public Builder(String root, Configuration config) { - this.rootDir = root; - this.conf = config; - } - - public Builder storageType(StorageType st) { - this.storageType = st; - return this; - } - - public Builder configuredCapacity(long capacity) { - this.configuredCapacity = capacity; - return this; - } - - public VolumeInfo build() throws IOException { - return new VolumeInfo(this); - } - } - - private VolumeInfo(Builder b) throws IOException { - - this.rootDir = b.rootDir; - File root = new File(this.rootDir); - - Boolean succeeded = root.isDirectory() || root.mkdirs(); - - if (!succeeded) { - LOG.error("Unable to create the volume root dir at : {}", root); - throw new IOException("Unable to create the volume root dir at " + root); - } - - this.storageType = (b.storageType != null ? - b.storageType : StorageType.DEFAULT); - - this.configuredCapacity = (b.configuredCapacity != 0 ? - b.configuredCapacity : -1); - - this.usage = new VolumeUsage(root, b.conf); - } - - public long getCapacity() { - return configuredCapacity < 0 ? usage.getCapacity() : configuredCapacity; - } - - public long getAvailable() throws IOException { - return usage.getAvailable(); - } - - public long getScmUsed() throws IOException { - return usage.getScmUsed(); - } - - protected void shutdownUsageThread() { - if (usage != null) { - usage.shutdown(); - } - usage = null; - } - - public String getRootDir() { - return this.rootDir; - } - - public StorageType getStorageType() { - return this.storageType; - } - - /** - * Only for testing. Do not use otherwise. - */ - @VisibleForTesting - public void setScmUsageForTesting(GetSpaceUsed scmUsageForTest) { - usage.setScmUsageForTesting(scmUsageForTest); - } - - /** - * Only for testing. Do not use otherwise. - */ - @VisibleForTesting - public VolumeUsage getUsageForTesting() { - return usage; - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/VolumeSet.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/VolumeSet.java deleted file mode 100644 index 06f48fc2936..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/VolumeSet.java +++ /dev/null @@ -1,406 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.volume; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.StorageType; - -import static org.apache.hadoop.hdds.scm.ScmConfigKeys.HDDS_DATANODE_DIR_KEY; -import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_DATANODE_DATA_DIR_KEY; -import static org.apache.hadoop.util.RunJar.SHUTDOWN_HOOK_PRIORITY; - -import org.apache.hadoop.hdfs.server.datanode.StorageLocation; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.NodeReportProto; -import org.apache.hadoop.ozone.OzoneConfigKeys; -import org.apache.hadoop.ozone.common.InconsistentStorageStateException; -import org.apache.hadoop.ozone.container.common.impl.StorageLocationReport; -import org.apache.hadoop.ozone.container.common.utils.HddsVolumeUtil; -import org.apache.hadoop.ozone.container.common.volume.HddsVolume.VolumeState; -import org.apache.hadoop.ozone.container.common.interfaces.VolumeChoosingPolicy; -import org.apache.hadoop.util.AutoCloseableLock; -import org.apache.hadoop.util.DiskChecker.DiskOutOfSpaceException; -import org.apache.hadoop.util.InstrumentedLock; -import org.apache.hadoop.util.ShutdownHookManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.EnumMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.ReentrantLock; - -/** - * VolumeSet to manage volumes in a DataNode. - */ -public class VolumeSet { - - private static final Logger LOG = LoggerFactory.getLogger(VolumeSet.class); - - private Configuration conf; - - /** - * {@link VolumeSet#volumeMap} maintains a map of all active volumes in the - * DataNode. Each volume has one-to-one mapping with a volumeInfo object. - */ - private Map volumeMap; - /** - * {@link VolumeSet#failedVolumeMap} maintains a map of volumes which have - * failed. The keys in this map and {@link VolumeSet#volumeMap} are - * mutually exclusive. - */ - private Map failedVolumeMap; - - /** - * {@link VolumeSet#volumeStateMap} maintains a list of active volumes per - * StorageType. - */ - private EnumMap> volumeStateMap; - - /** - * Lock to synchronize changes to the VolumeSet. Any update to - * {@link VolumeSet#volumeMap}, {@link VolumeSet#failedVolumeMap}, or - * {@link VolumeSet#volumeStateMap} should be done after acquiring this lock. - */ - private final AutoCloseableLock volumeSetLock; - - private final String datanodeUuid; - private String clusterID; - - private Runnable shutdownHook; - - public VolumeSet(String dnUuid, Configuration conf) - throws IOException { - this(dnUuid, null, conf); - } - - public VolumeSet(String dnUuid, String clusterID, Configuration conf) - throws IOException { - this.datanodeUuid = dnUuid; - this.clusterID = clusterID; - this.conf = conf; - this.volumeSetLock = new AutoCloseableLock( - new InstrumentedLock(getClass().getName(), LOG, - new ReentrantLock(true), - conf.getTimeDuration( - OzoneConfigKeys.HDDS_WRITE_LOCK_REPORTING_THRESHOLD_MS_KEY, - OzoneConfigKeys.HDDS_WRITE_LOCK_REPORTING_THRESHOLD_MS_DEFAULT, - TimeUnit.MILLISECONDS), - conf.getTimeDuration( - OzoneConfigKeys.HDDS_LOCK_SUPPRESS_WARNING_INTERVAL_MS_KEY, - OzoneConfigKeys.HDDS_LOCK_SUPPRESS_WARNING_INTERVAL_MS_DEAFULT, - TimeUnit.MILLISECONDS))); - - initializeVolumeSet(); - } - - // Add DN volumes configured through ConfigKeys to volumeMap. - private void initializeVolumeSet() throws IOException { - volumeMap = new ConcurrentHashMap<>(); - failedVolumeMap = new ConcurrentHashMap<>(); - volumeStateMap = new EnumMap<>(StorageType.class); - - Collection rawLocations = conf.getTrimmedStringCollection( - HDDS_DATANODE_DIR_KEY); - if (rawLocations.isEmpty()) { - rawLocations = conf.getTrimmedStringCollection(DFS_DATANODE_DATA_DIR_KEY); - } - if (rawLocations.isEmpty()) { - throw new IllegalArgumentException("No location configured in either " - + HDDS_DATANODE_DIR_KEY + " or " + DFS_DATANODE_DATA_DIR_KEY); - } - - for (StorageType storageType : StorageType.values()) { - volumeStateMap.put(storageType, new ArrayList()); - } - - for (String locationString : rawLocations) { - try { - StorageLocation location = StorageLocation.parse(locationString); - - HddsVolume hddsVolume = createVolume(location.getUri().getPath(), - location.getStorageType()); - - checkAndSetClusterID(hddsVolume.getClusterID()); - - volumeMap.put(hddsVolume.getHddsRootDir().getPath(), hddsVolume); - volumeStateMap.get(hddsVolume.getStorageType()).add(hddsVolume); - LOG.info("Added Volume : {} to VolumeSet", - hddsVolume.getHddsRootDir().getPath()); - } catch (IOException e) { - HddsVolume volume = new HddsVolume.Builder(locationString) - .failedVolume(true).build(); - failedVolumeMap.put(locationString, volume); - LOG.error("Failed to parse the storage location: " + locationString, e); - } - } - - if (volumeMap.size() == 0) { - throw new DiskOutOfSpaceException("No storage location configured"); - } - - // Ensure volume threads are stopped and scm df is saved during shutdown. - shutdownHook = () -> { - saveVolumeSetUsed(); - }; - ShutdownHookManager.get().addShutdownHook(shutdownHook, - SHUTDOWN_HOOK_PRIORITY); - } - - /** - * If Version file exists and the {@link VolumeSet#clusterID} is not set yet, - * assign it the value from Version file. Otherwise, check that the given - * id matches with the id from version file. - * @param idFromVersionFile value of the property from Version file - * @throws InconsistentStorageStateException - */ - private void checkAndSetClusterID(String idFromVersionFile) - throws InconsistentStorageStateException { - // If the clusterID is null (not set), assign it the value - // from version file. - if (this.clusterID == null) { - this.clusterID = idFromVersionFile; - return; - } - - // If the clusterID is already set, it should match with the value from the - // version file. - if (!idFromVersionFile.equals(this.clusterID)) { - throw new InconsistentStorageStateException( - "Mismatched ClusterIDs. VolumeSet has: " + this.clusterID + - ", and version file has: " + idFromVersionFile); - } - } - - public void acquireLock() { - volumeSetLock.acquire(); - } - - public void releaseLock() { - volumeSetLock.release(); - } - - private HddsVolume createVolume(String locationString, - StorageType storageType) throws IOException { - HddsVolume.Builder volumeBuilder = new HddsVolume.Builder(locationString) - .conf(conf) - .datanodeUuid(datanodeUuid) - .clusterID(clusterID) - .storageType(storageType); - return volumeBuilder.build(); - } - - - // Add a volume to VolumeSet - public boolean addVolume(String dataDir) { - return addVolume(dataDir, StorageType.DEFAULT); - } - - // Add a volume to VolumeSet - public boolean addVolume(String volumeRoot, StorageType storageType) { - String hddsRoot = HddsVolumeUtil.getHddsRoot(volumeRoot); - boolean success; - - try (AutoCloseableLock lock = volumeSetLock.acquire()) { - if (volumeMap.containsKey(hddsRoot)) { - LOG.warn("Volume : {} already exists in VolumeMap", hddsRoot); - success = false; - } else { - if (failedVolumeMap.containsKey(hddsRoot)) { - failedVolumeMap.remove(hddsRoot); - } - - HddsVolume hddsVolume = createVolume(volumeRoot, storageType); - volumeMap.put(hddsVolume.getHddsRootDir().getPath(), hddsVolume); - volumeStateMap.get(hddsVolume.getStorageType()).add(hddsVolume); - - LOG.info("Added Volume : {} to VolumeSet", - hddsVolume.getHddsRootDir().getPath()); - success = true; - } - } catch (IOException ex) { - LOG.error("Failed to add volume " + volumeRoot + " to VolumeSet", ex); - success = false; - } - return success; - } - - // Mark a volume as failed - public void failVolume(String dataDir) { - String hddsRoot = HddsVolumeUtil.getHddsRoot(dataDir); - - try (AutoCloseableLock lock = volumeSetLock.acquire()) { - if (volumeMap.containsKey(hddsRoot)) { - HddsVolume hddsVolume = volumeMap.get(hddsRoot); - hddsVolume.failVolume(); - - volumeMap.remove(hddsRoot); - volumeStateMap.get(hddsVolume.getStorageType()).remove(hddsVolume); - failedVolumeMap.put(hddsRoot, hddsVolume); - - LOG.info("Moving Volume : {} to failed Volumes", hddsRoot); - } else if (failedVolumeMap.containsKey(hddsRoot)) { - LOG.info("Volume : {} is not active", hddsRoot); - } else { - LOG.warn("Volume : {} does not exist in VolumeSet", hddsRoot); - } - } - } - - // Remove a volume from the VolumeSet completely. - public void removeVolume(String dataDir) throws IOException { - String hddsRoot = HddsVolumeUtil.getHddsRoot(dataDir); - - try (AutoCloseableLock lock = volumeSetLock.acquire()) { - if (volumeMap.containsKey(hddsRoot)) { - HddsVolume hddsVolume = volumeMap.get(hddsRoot); - hddsVolume.shutdown(); - - volumeMap.remove(hddsRoot); - volumeStateMap.get(hddsVolume.getStorageType()).remove(hddsVolume); - - LOG.info("Removed Volume : {} from VolumeSet", hddsRoot); - } else if (failedVolumeMap.containsKey(hddsRoot)) { - HddsVolume hddsVolume = failedVolumeMap.get(hddsRoot); - hddsVolume.setState(VolumeState.NON_EXISTENT); - - failedVolumeMap.remove(hddsRoot); - LOG.info("Removed Volume : {} from failed VolumeSet", hddsRoot); - } else { - LOG.warn("Volume : {} does not exist in VolumeSet", hddsRoot); - } - } - } - - public HddsVolume chooseVolume(long containerSize, - VolumeChoosingPolicy choosingPolicy) throws IOException { - return choosingPolicy.chooseVolume(getVolumesList(), containerSize); - } - - /** - * This method, call shutdown on each volume to shutdown volume usage - * thread and write scmUsed on each volume. - */ - private void saveVolumeSetUsed() { - for (HddsVolume hddsVolume : volumeMap.values()) { - try { - hddsVolume.shutdown(); - } catch (Exception ex) { - LOG.error("Failed to shutdown volume : " + hddsVolume.getHddsRootDir(), - ex); - } - } - } - - /** - * Shutdown's the volumeset, if saveVolumeSetUsed is false, call's - * {@link VolumeSet#saveVolumeSetUsed}. - */ - public void shutdown() { - saveVolumeSetUsed(); - if (shutdownHook != null) { - ShutdownHookManager.get().removeShutdownHook(shutdownHook); - } - } - - @VisibleForTesting - public List getVolumesList() { - return ImmutableList.copyOf(volumeMap.values()); - } - - @VisibleForTesting - public List getFailedVolumesList() { - return ImmutableList.copyOf(failedVolumeMap.values()); - } - - @VisibleForTesting - public Map getVolumeMap() { - return ImmutableMap.copyOf(volumeMap); - } - - @VisibleForTesting - public Map> getVolumeStateMap() { - return ImmutableMap.copyOf(volumeStateMap); - } - - public StorageContainerDatanodeProtocolProtos.NodeReportProto getNodeReport() - throws IOException { - boolean failed; - StorageLocationReport[] reports = new StorageLocationReport[volumeMap - .size() + failedVolumeMap.size()]; - int counter = 0; - HddsVolume hddsVolume; - for (Map.Entry entry : volumeMap.entrySet()) { - hddsVolume = entry.getValue(); - VolumeInfo volumeInfo = hddsVolume.getVolumeInfo(); - long scmUsed = 0; - long remaining = 0; - failed = false; - try { - scmUsed = volumeInfo.getScmUsed(); - remaining = volumeInfo.getAvailable(); - } catch (IOException ex) { - LOG.warn("Failed to get scmUsed and remaining for container " + - "storage location {}", volumeInfo.getRootDir()); - // reset scmUsed and remaining if df/du failed. - scmUsed = 0; - remaining = 0; - failed = true; - } - - StorageLocationReport.Builder builder = - StorageLocationReport.newBuilder(); - builder.setStorageLocation(volumeInfo.getRootDir()) - .setId(hddsVolume.getStorageID()) - .setFailed(failed) - .setCapacity(hddsVolume.getCapacity()) - .setRemaining(remaining) - .setScmUsed(scmUsed) - .setStorageType(hddsVolume.getStorageType()); - StorageLocationReport r = builder.build(); - reports[counter++] = r; - } - for (Map.Entry entry : failedVolumeMap.entrySet()) { - hddsVolume = entry.getValue(); - StorageLocationReport.Builder builder = StorageLocationReport - .newBuilder(); - builder.setStorageLocation(hddsVolume.getHddsRootDir() - .getAbsolutePath()).setId(hddsVolume.getStorageID()).setFailed(true) - .setCapacity(0).setRemaining(0).setScmUsed(0).setStorageType( - hddsVolume.getStorageType()); - StorageLocationReport r = builder.build(); - reports[counter++] = r; - } - NodeReportProto.Builder nrb = NodeReportProto.newBuilder(); - for (int i = 0; i < reports.length; i++) { - nrb.addStorageReport(reports[i].getProtoBufMessage()); - } - return nrb.build(); - } -} \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/VolumeUsage.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/VolumeUsage.java deleted file mode 100644 index 2c7563e0859..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/VolumeUsage.java +++ /dev/null @@ -1,181 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.volume; - -import com.google.common.annotations.VisibleForTesting; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.CachingGetSpaceUsed; -import org.apache.hadoop.fs.DF; -import org.apache.hadoop.fs.GetSpaceUsed; -import org.apache.hadoop.io.IOUtils; -import org.apache.hadoop.util.Time; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.nio.charset.StandardCharsets; -import java.util.Scanner; - -/** - * Class that wraps the space df of the Datanode Volumes used by SCM - * containers. - */ -public class VolumeUsage { - private static final Logger LOG = LoggerFactory.getLogger(VolumeUsage.class); - - private final File rootDir; - private final DF df; - private final File scmUsedFile; - private GetSpaceUsed scmUsage; - - private static final String DU_CACHE_FILE = "scmUsed"; - private volatile boolean scmUsedSaved = false; - - VolumeUsage(File dataLoc, Configuration conf) - throws IOException { - this.rootDir = dataLoc; - - // SCM used cache file - scmUsedFile = new File(rootDir, DU_CACHE_FILE); - // get overall disk df - this.df = new DF(rootDir, conf); - - startScmUsageThread(conf); - } - - void startScmUsageThread(Configuration conf) throws IOException { - // get SCM specific df - this.scmUsage = new CachingGetSpaceUsed.Builder().setPath(rootDir) - .setConf(conf) - .setInitialUsed(loadScmUsed()) - .build(); - } - - long getCapacity() { - long capacity = df.getCapacity(); - return (capacity > 0) ? capacity : 0; - } - - /* - * Calculate the available space in the volume. - */ - long getAvailable() throws IOException { - long remaining = getCapacity() - getScmUsed(); - long available = df.getAvailable(); - if (remaining > available) { - remaining = available; - } - return (remaining > 0) ? remaining : 0; - } - - long getScmUsed() throws IOException{ - return scmUsage.getUsed(); - } - - public void shutdown() { - saveScmUsed(); - - if (scmUsage instanceof CachingGetSpaceUsed) { - IOUtils.cleanupWithLogger(null, ((CachingGetSpaceUsed) scmUsage)); - } - } - - /** - * Read in the cached DU value and return it if it is less than 600 seconds - * old (DU update interval). Slight imprecision of scmUsed is not critical - * and skipping DU can significantly shorten the startup time. - * If the cached value is not available or too old, -1 is returned. - */ - long loadScmUsed() { - long cachedScmUsed; - long mtime; - Scanner sc; - - try { - sc = new Scanner(scmUsedFile, "UTF-8"); - } catch (FileNotFoundException fnfe) { - return -1; - } - - try { - // Get the recorded scmUsed from the file. - if (sc.hasNextLong()) { - cachedScmUsed = sc.nextLong(); - } else { - return -1; - } - // Get the recorded mtime from the file. - if (sc.hasNextLong()) { - mtime = sc.nextLong(); - } else { - return -1; - } - - // Return the cached value if mtime is okay. - if (mtime > 0 && (Time.now() - mtime < 600000L)) { - LOG.info("Cached ScmUsed found for {} : {} ", rootDir, - cachedScmUsed); - return cachedScmUsed; - } - return -1; - } finally { - sc.close(); - } - } - - /** - * Write the current scmUsed to the cache file. - */ - void saveScmUsed() { - if (scmUsedFile.exists() && !scmUsedFile.delete()) { - LOG.warn("Failed to delete old scmUsed file in {}.", rootDir); - } - OutputStreamWriter out = null; - try { - long used = getScmUsed(); - if (used > 0) { - out = new OutputStreamWriter(new FileOutputStream(scmUsedFile), - StandardCharsets.UTF_8); - // mtime is written last, so that truncated writes won't be valid. - out.write(Long.toString(used) + " " + Long.toString(Time.now())); - out.flush(); - out.close(); - out = null; - } - } catch (IOException ioe) { - // If write failed, the volume might be bad. Since the cache file is - // not critical, log the error and continue. - LOG.warn("Failed to write scmUsed to " + scmUsedFile, ioe); - } finally { - IOUtils.cleanupWithLogger(null, out); - } - } - - /** - * Only for testing. Do not use otherwise. - */ - @VisibleForTesting - public void setScmUsageForTesting(GetSpaceUsed scmUsageForTest) { - this.scmUsage = scmUsageForTest; - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/package-info.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/package-info.java deleted file mode 100644 index 86093c6015c..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/package-info.java +++ /dev/null @@ -1,21 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.container.common.volume; -/** - This package contains volume/ disk related classes. - */ \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueBlockIterator.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueBlockIterator.java deleted file mode 100644 index 535af29c190..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueBlockIterator.java +++ /dev/null @@ -1,148 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.keyvalue; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.container.common.helpers.BlockData; -import org.apache.hadoop.ozone.container.common.helpers.ContainerUtils; -import org.apache.hadoop.ozone.container.common.impl.ContainerData; -import org.apache.hadoop.ozone.container.common.impl.ContainerDataYaml; -import org.apache.hadoop.ozone.container.common.interfaces.BlockIterator; -import org.apache.hadoop.ozone.container.keyvalue.helpers.BlockUtils; -import org.apache.hadoop.ozone.container.keyvalue.helpers.KeyValueContainerLocationUtil; -import org.apache.hadoop.utils.MetaStoreIterator; -import org.apache.hadoop.utils.MetadataKeyFilters; -import org.apache.hadoop.utils.MetadataKeyFilters.KeyPrefixFilter; -import org.apache.hadoop.utils.MetadataStore; -import org.apache.hadoop.utils.MetadataStore.KeyValue; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.util.NoSuchElementException; - - -/** - * Block Iterator for KeyValue Container. This block iterator returns blocks - * which match with the {@link MetadataKeyFilters.KeyPrefixFilter}. If no - * filter is specified, then default filter used is - * {@link MetadataKeyFilters#getNormalKeyFilter()} - */ -@InterfaceAudience.Public -public class KeyValueBlockIterator implements BlockIterator { - - private static final Logger LOG = LoggerFactory.getLogger( - KeyValueBlockIterator.class); - - private MetaStoreIterator blockIterator; - private static KeyPrefixFilter defaultBlockFilter = MetadataKeyFilters - .getNormalKeyFilter(); - private KeyPrefixFilter blockFilter; - private BlockData nextBlock; - private long containerId; - - /** - * KeyValueBlockIterator to iterate blocks in a container. - * @param id - container id - * @param path - container base path - * @throws IOException - */ - - public KeyValueBlockIterator(long id, File path) - throws IOException { - this(id, path, defaultBlockFilter); - } - - /** - * KeyValueBlockIterator to iterate blocks in a container. - * @param id - container id - * @param path - container base path - * @param filter - Block filter, filter to be applied for blocks - * @throws IOException - */ - public KeyValueBlockIterator(long id, File path, KeyPrefixFilter filter) - throws IOException { - containerId = id; - File metdataPath = new File(path, OzoneConsts.METADATA); - File containerFile = ContainerUtils.getContainerFile(metdataPath - .getParentFile()); - ContainerData containerData = ContainerDataYaml.readContainerFile( - containerFile); - KeyValueContainerData keyValueContainerData = (KeyValueContainerData) - containerData; - keyValueContainerData.setDbFile(KeyValueContainerLocationUtil - .getContainerDBFile(metdataPath, containerId)); - MetadataStore metadataStore = BlockUtils.getDB(keyValueContainerData, new - OzoneConfiguration()); - blockIterator = metadataStore.iterator(); - blockFilter = filter; - } - - /** - * This method returns blocks matching with the filter. - * @return next block or null if no more blocks - * @throws IOException - */ - @Override - public BlockData nextBlock() throws IOException, NoSuchElementException { - if (nextBlock != null) { - BlockData currentBlock = nextBlock; - nextBlock = null; - return currentBlock; - } - if(hasNext()) { - return nextBlock(); - } - throw new NoSuchElementException("Block Iterator reached end for " + - "ContainerID " + containerId); - } - - @Override - public boolean hasNext() throws IOException { - if (nextBlock != null) { - return true; - } - if (blockIterator.hasNext()) { - KeyValue block = blockIterator.next(); - if (blockFilter.filterKey(null, block.getKey(), null)) { - nextBlock = BlockUtils.getBlockData(block.getValue()); - LOG.trace("Block matching with filter found: blockID is : {} for " + - "containerID {}", nextBlock.getLocalID(), containerId); - return true; - } - hasNext(); - } - return false; - } - - @Override - public void seekToFirst() { - nextBlock = null; - blockIterator.seekToFirst(); - } - - @Override - public void seekToLast() { - nextBlock = null; - blockIterator.seekToLast(); - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueContainer.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueContainer.java deleted file mode 100644 index 09d40546f0f..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueContainer.java +++ /dev/null @@ -1,576 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.keyvalue; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; -import java.util.Map; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.FileAlreadyExistsException; -import org.apache.hadoop.fs.FileUtil; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerLifeCycleState; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerType; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos; -import org.apache.hadoop.hdds.scm.container.common.helpers - .StorageContainerException; -import org.apache.hadoop.io.nativeio.NativeIO; -import org.apache.hadoop.ozone.OzoneConfigKeys; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.container.common.helpers.ContainerUtils; -import org.apache.hadoop.ozone.container.common.impl.ContainerDataYaml; -import org.apache.hadoop.ozone.container.common.interfaces.Container; -import org.apache.hadoop.ozone.container.common.interfaces.ContainerPacker; -import org.apache.hadoop.ozone.container.common.interfaces.VolumeChoosingPolicy; -import org.apache.hadoop.ozone.container.common.volume.HddsVolume; -import org.apache.hadoop.ozone.container.common.volume.VolumeSet; -import org.apache.hadoop.ozone.container.keyvalue.helpers.BlockUtils; -import org.apache.hadoop.ozone.container.keyvalue.helpers - .KeyValueContainerLocationUtil; -import org.apache.hadoop.ozone.container.keyvalue.helpers.KeyValueContainerUtil; -import org.apache.hadoop.util.DiskChecker.DiskOutOfSpaceException; -import org.apache.hadoop.utils.MetadataStore; - -import com.google.common.base.Preconditions; -import org.apache.commons.io.FileUtils; -import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .Result.CONTAINER_ALREADY_EXISTS; -import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .Result.CONTAINER_FILES_CREATE_ERROR; -import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .Result.CONTAINER_INTERNAL_ERROR; -import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .Result.DISK_OUT_OF_SPACE; -import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .Result.ERROR_IN_COMPACT_DB; -import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .Result.INVALID_CONTAINER_STATE; -import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .Result.UNSUPPORTED_REQUEST; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Class to perform KeyValue Container operations. - */ -public class KeyValueContainer implements Container { - - private static final Logger LOG = LoggerFactory.getLogger(Container.class); - - // Use a non-fair RW lock for better throughput, we may revisit this decision - // if this causes fairness issues. - private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); - - private final KeyValueContainerData containerData; - private Configuration config; - - public KeyValueContainer(KeyValueContainerData containerData, Configuration - ozoneConfig) { - Preconditions.checkNotNull(containerData, "KeyValueContainerData cannot " + - "be null"); - Preconditions.checkNotNull(ozoneConfig, "Ozone configuration cannot " + - "be null"); - this.config = ozoneConfig; - this.containerData = containerData; - } - - @Override - public void create(VolumeSet volumeSet, VolumeChoosingPolicy - volumeChoosingPolicy, String scmId) throws StorageContainerException { - Preconditions.checkNotNull(volumeChoosingPolicy, "VolumeChoosingPolicy " + - "cannot be null"); - Preconditions.checkNotNull(volumeSet, "VolumeSet cannot be null"); - Preconditions.checkNotNull(scmId, "scmId cannot be null"); - - File containerMetaDataPath = null; - //acquiring volumeset lock and container lock - volumeSet.acquireLock(); - long maxSize = containerData.getMaxSize(); - try { - HddsVolume containerVolume = volumeChoosingPolicy.chooseVolume(volumeSet - .getVolumesList(), maxSize); - String hddsVolumeDir = containerVolume.getHddsRootDir().toString(); - - long containerID = containerData.getContainerID(); - - containerMetaDataPath = KeyValueContainerLocationUtil - .getContainerMetaDataPath(hddsVolumeDir, scmId, containerID); - containerData.setMetadataPath(containerMetaDataPath.getPath()); - - File chunksPath = KeyValueContainerLocationUtil.getChunksLocationPath( - hddsVolumeDir, scmId, containerID); - - // Check if it is new Container. - ContainerUtils.verifyIsNewContainer(containerMetaDataPath); - - //Create Metadata path chunks path and metadata db - File dbFile = getContainerDBFile(); - KeyValueContainerUtil.createContainerMetaData(containerMetaDataPath, - chunksPath, dbFile, config); - - String impl = config.getTrimmed(OzoneConfigKeys.OZONE_METADATA_STORE_IMPL, - OzoneConfigKeys.OZONE_METADATA_STORE_IMPL_DEFAULT); - - //Set containerData for the KeyValueContainer. - containerData.setChunksPath(chunksPath.getPath()); - containerData.setContainerDBType(impl); - containerData.setDbFile(dbFile); - containerData.setVolume(containerVolume); - - // Create .container file - File containerFile = getContainerFile(); - createContainerFile(containerFile); - - } catch (StorageContainerException ex) { - if (containerMetaDataPath != null && containerMetaDataPath.getParentFile() - .exists()) { - FileUtil.fullyDelete(containerMetaDataPath.getParentFile()); - } - throw ex; - } catch (DiskOutOfSpaceException ex) { - throw new StorageContainerException("Container creation failed, due to " + - "disk out of space", ex, DISK_OUT_OF_SPACE); - } catch (FileAlreadyExistsException ex) { - throw new StorageContainerException("Container creation failed because " + - "ContainerFile already exists", ex, CONTAINER_ALREADY_EXISTS); - } catch (IOException ex) { - if (containerMetaDataPath != null && containerMetaDataPath.getParentFile() - .exists()) { - FileUtil.fullyDelete(containerMetaDataPath.getParentFile()); - } - throw new StorageContainerException("Container creation failed.", ex, - CONTAINER_INTERNAL_ERROR); - } finally { - volumeSet.releaseLock(); - } - } - - /** - * Set all of the path realted container data fields based on the name - * conventions. - * - * @param scmId - * @param containerVolume - * @param hddsVolumeDir - */ - public void populatePathFields(String scmId, - HddsVolume containerVolume, String hddsVolumeDir) { - - long containerId = containerData.getContainerID(); - - File containerMetaDataPath = KeyValueContainerLocationUtil - .getContainerMetaDataPath(hddsVolumeDir, scmId, containerId); - - File chunksPath = KeyValueContainerLocationUtil.getChunksLocationPath( - hddsVolumeDir, scmId, containerId); - File dbFile = KeyValueContainerLocationUtil.getContainerDBFile( - containerMetaDataPath, containerId); - - //Set containerData for the KeyValueContainer. - containerData.setMetadataPath(containerMetaDataPath.getPath()); - containerData.setChunksPath(chunksPath.getPath()); - containerData.setDbFile(dbFile); - containerData.setVolume(containerVolume); - } - - /** - * Writes to .container file. - * - * @param containerFile container file name - * @param isCreate True if creating a new file. False is updating an - * existing container file. - * @throws StorageContainerException - */ - private void writeToContainerFile(File containerFile, boolean isCreate) - throws StorageContainerException { - File tempContainerFile = null; - long containerId = containerData.getContainerID(); - try { - tempContainerFile = createTempFile(containerFile); - ContainerDataYaml.createContainerFile( - ContainerType.KeyValueContainer, containerData, tempContainerFile); - - // NativeIO.renameTo is an atomic function. But it might fail if the - // container file already exists. Hence, we handle the two cases - // separately. - if (isCreate) { - NativeIO.renameTo(tempContainerFile, containerFile); - } else { - Files.move(tempContainerFile.toPath(), containerFile.toPath(), - StandardCopyOption.REPLACE_EXISTING); - } - - } catch (IOException ex) { - throw new StorageContainerException("Error while creating/ updating " + - ".container file. ContainerID: " + containerId, ex, - CONTAINER_FILES_CREATE_ERROR); - } finally { - if (tempContainerFile != null && tempContainerFile.exists()) { - if (!tempContainerFile.delete()) { - LOG.warn("Unable to delete container temporary file: {}.", - tempContainerFile.getAbsolutePath()); - } - } - } - } - - private void createContainerFile(File containerFile) - throws StorageContainerException { - writeToContainerFile(containerFile, true); - } - - private void updateContainerFile(File containerFile) - throws StorageContainerException { - writeToContainerFile(containerFile, false); - } - - - @Override - public void delete(boolean forceDelete) - throws StorageContainerException { - long containerId = containerData.getContainerID(); - try { - KeyValueContainerUtil.removeContainer(containerData, config, forceDelete); - } catch (StorageContainerException ex) { - throw ex; - } catch (IOException ex) { - // TODO : An I/O error during delete can leave partial artifacts on the - // disk. We will need the cleaner thread to cleanup this information. - String errMsg = String.format("Failed to cleanup container. ID: %d", - containerId); - LOG.error(errMsg, ex); - throw new StorageContainerException(errMsg, ex, CONTAINER_INTERNAL_ERROR); - } - } - - @Override - public void close() throws StorageContainerException { - - //TODO: writing .container file and compaction can be done - // asynchronously, otherwise rpc call for this will take a lot of time to - // complete this action - try { - writeLock(); - - containerData.closeContainer(); - File containerFile = getContainerFile(); - // update the new container data to .container File - updateContainerFile(containerFile); - - } catch (StorageContainerException ex) { - // Failed to update .container file. Reset the state to CLOSING - containerData.setState(ContainerLifeCycleState.CLOSING); - throw ex; - } finally { - writeUnlock(); - } - - // It is ok if this operation takes a bit of time. - // Close container is not expected to be instantaneous. - try { - MetadataStore db = BlockUtils.getDB(containerData, config); - db.compactDB(); - } catch (StorageContainerException ex) { - throw ex; - } catch (IOException ex) { - LOG.error("Error in DB compaction while closing container", ex); - throw new StorageContainerException(ex, ERROR_IN_COMPACT_DB); - } - } - - @Override - public KeyValueContainerData getContainerData() { - return containerData; - } - - @Override - public ContainerLifeCycleState getContainerState() { - return containerData.getState(); - } - - @Override - public ContainerType getContainerType() { - return ContainerType.KeyValueContainer; - } - - @Override - public void update(Map metadata, boolean forceUpdate) - throws StorageContainerException { - - // TODO: Now, when writing the updated data to .container file, we are - // holding lock and writing data to disk. We can have async implementation - // to flush the update container data to disk. - long containerId = containerData.getContainerID(); - if(!containerData.isValid()) { - LOG.debug("Invalid container data. ContainerID: {}", containerId); - throw new StorageContainerException("Invalid container data. " + - "ContainerID: " + containerId, INVALID_CONTAINER_STATE); - } - if (!forceUpdate && !containerData.isOpen()) { - throw new StorageContainerException( - "Updating a closed container without force option is not allowed. " + - "ContainerID: " + containerId, UNSUPPORTED_REQUEST); - } - - Map oldMetadata = containerData.getMetadata(); - try { - writeLock(); - for (Map.Entry entry : metadata.entrySet()) { - containerData.addMetadata(entry.getKey(), entry.getValue()); - } - - File containerFile = getContainerFile(); - // update the new container data to .container File - updateContainerFile(containerFile); - } catch (StorageContainerException ex) { - containerData.setMetadata(oldMetadata); - throw ex; - } finally { - writeUnlock(); - } - } - - @Override - public void updateDeleteTransactionId(long deleteTransactionId) { - containerData.updateDeleteTransactionId(deleteTransactionId); - } - - @Override - public KeyValueBlockIterator blockIterator() throws IOException{ - return new KeyValueBlockIterator(containerData.getContainerID(), new File( - containerData.getContainerPath())); - } - - @Override - public void importContainerData(InputStream input, - ContainerPacker packer) throws IOException { - writeLock(); - try { - if (getContainerFile().exists()) { - String errorMessage = String.format( - "Can't import container (cid=%d) data to a specific location" - + " as the container descriptor (%s) has already been exist.", - getContainerData().getContainerID(), - getContainerFile().getAbsolutePath()); - throw new IOException(errorMessage); - } - //copy the values from the input stream to the final destination - // directory. - byte[] descriptorContent = packer.unpackContainerData(this, input); - - Preconditions.checkNotNull(descriptorContent, - "Container descriptor is missing from the container archive: " - + getContainerData().getContainerID()); - - //now, we have extracted the container descriptor from the previous - //datanode. We can load it and upload it with the current data - // (original metadata + current filepath fields) - KeyValueContainerData originalContainerData = - (KeyValueContainerData) ContainerDataYaml - .readContainer(descriptorContent); - - - containerData.setState(originalContainerData.getState()); - containerData - .setContainerDBType(originalContainerData.getContainerDBType()); - containerData.setBytesUsed(originalContainerData.getBytesUsed()); - - //rewriting the yaml file with new checksum calculation. - update(originalContainerData.getMetadata(), true); - - //fill in memory stat counter (keycount, byte usage) - KeyValueContainerUtil.parseKVContainerData(containerData, config); - - } catch (Exception ex) { - //delete all the temporary data in case of any exception. - try { - FileUtils.deleteDirectory(new File(containerData.getMetadataPath())); - FileUtils.deleteDirectory(new File(containerData.getChunksPath())); - FileUtils.deleteDirectory(getContainerFile()); - } catch (Exception deleteex) { - LOG.error( - "Can not cleanup destination directories after a container import" - + " error (cid" + - containerData.getContainerID() + ")", deleteex); - } - throw ex; - } finally { - writeUnlock(); - } - } - - @Override - public void exportContainerData(OutputStream destination, - ContainerPacker packer) throws IOException { - if (getContainerData().getState() != ContainerLifeCycleState.CLOSED) { - throw new IllegalStateException( - "Only closed containers could be exported: ContainerId=" - + getContainerData().getContainerID()); - } - packer.pack(this, destination); - } - - /** - * Acquire read lock. - */ - public void readLock() { - this.lock.readLock().lock(); - - } - - /** - * Release read lock. - */ - public void readUnlock() { - this.lock.readLock().unlock(); - } - - /** - * Check if the current thread holds read lock. - */ - public boolean hasReadLock() { - return this.lock.readLock().tryLock(); - } - - /** - * Acquire write lock. - */ - public void writeLock() { - this.lock.writeLock().lock(); - } - - /** - * Release write lock. - */ - public void writeUnlock() { - this.lock.writeLock().unlock(); - - } - - /** - * Check if the current thread holds write lock. - */ - public boolean hasWriteLock() { - return this.lock.writeLock().isHeldByCurrentThread(); - } - - /** - * Acquire read lock, unless interrupted while waiting. - * @throws InterruptedException - */ - @Override - public void readLockInterruptibly() throws InterruptedException { - this.lock.readLock().lockInterruptibly(); - } - - /** - * Acquire write lock, unless interrupted while waiting. - * @throws InterruptedException - */ - @Override - public void writeLockInterruptibly() throws InterruptedException { - this.lock.writeLock().lockInterruptibly(); - - } - - /** - * Returns containerFile. - * @return .container File name - */ - @Override - public File getContainerFile() { - return new File(containerData.getMetadataPath(), containerData - .getContainerID() + OzoneConsts.CONTAINER_EXTENSION); - } - - /** - * Returns KeyValueContainerReport for the KeyValueContainer. - */ - @Override - public StorageContainerDatanodeProtocolProtos.ContainerInfo - getContainerReport() throws StorageContainerException{ - StorageContainerDatanodeProtocolProtos.ContainerInfo.Builder ciBuilder = - StorageContainerDatanodeProtocolProtos.ContainerInfo.newBuilder(); - ciBuilder.setContainerID(containerData.getContainerID()) - .setReadCount(containerData.getReadCount()) - .setWriteCount(containerData.getWriteCount()) - .setReadBytes(containerData.getReadBytes()) - .setWriteBytes(containerData.getWriteBytes()) - .setKeyCount(containerData.getKeyCount()) - .setUsed(containerData.getBytesUsed()) - .setState(getHddsState()) - .setDeleteTransactionId(containerData.getDeleteTransactionId()); - return ciBuilder.build(); - } - - /** - * Returns LifeCycle State of the container. - * @return LifeCycle State of the container in HddsProtos format - * @throws StorageContainerException - */ - private HddsProtos.LifeCycleState getHddsState() - throws StorageContainerException { - HddsProtos.LifeCycleState state; - switch (containerData.getState()) { - case OPEN: - state = HddsProtos.LifeCycleState.OPEN; - break; - case CLOSING: - state = HddsProtos.LifeCycleState.CLOSING; - break; - case CLOSED: - state = HddsProtos.LifeCycleState.CLOSED; - break; - default: - throw new StorageContainerException("Invalid Container state found: " + - containerData.getContainerID(), INVALID_CONTAINER_STATE); - } - return state; - } - - /** - * Returns container DB file. - * @return - */ - public File getContainerDBFile() { - return new File(containerData.getMetadataPath(), containerData - .getContainerID() + OzoneConsts.DN_CONTAINER_DB); - } - - /** - * Creates a temporary file. - * @param file - * @return - * @throws IOException - */ - private File createTempFile(File file) throws IOException{ - return File.createTempFile("tmp_" + System.currentTimeMillis() + "_", - file.getName(), file.getParentFile()); - } - -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueContainerData.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueContainerData.java deleted file mode 100644 index 7ffdbf558ea..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueContainerData.java +++ /dev/null @@ -1,297 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.keyvalue; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.Lists; -import java.util.Collections; - -import org.apache.hadoop.conf.StorageSize; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdds.scm.ScmConfigKeys; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.container.common.impl.ContainerData; -import org.yaml.snakeyaml.nodes.Tag; - - -import java.io.File; -import java.io.IOException; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; - -import static java.lang.Math.max; -import static org.apache.hadoop.ozone.OzoneConsts.CHUNKS_PATH; -import static org.apache.hadoop.ozone.OzoneConsts.CONTAINER_DB_TYPE; -import static org.apache.hadoop.ozone.OzoneConsts.METADATA_PATH; - -/** - * This class represents the KeyValueContainer metadata, which is the - * in-memory representation of container metadata and is represented on disk - * by the .container file. - */ -public class KeyValueContainerData extends ContainerData { - - // Yaml Tag used for KeyValueContainerData. - public static final Tag KEYVALUE_YAML_TAG = new Tag("KeyValueContainerData"); - - // Fields need to be stored in .container file. - private static final List KV_YAML_FIELDS; - - // Path to Container metadata Level DB/RocksDB Store and .container file. - private String metadataPath; - - // Path to Physical file system where chunks are stored. - private String chunksPath; - - //Type of DB used to store key to chunks mapping - private String containerDBType; - - private File dbFile = null; - - /** - * Number of pending deletion blocks in KeyValueContainer. - */ - private final AtomicInteger numPendingDeletionBlocks; - - private long deleteTransactionId; - - static { - // Initialize YAML fields - KV_YAML_FIELDS = Lists.newArrayList(); - KV_YAML_FIELDS.addAll(YAML_FIELDS); - KV_YAML_FIELDS.add(METADATA_PATH); - KV_YAML_FIELDS.add(CHUNKS_PATH); - KV_YAML_FIELDS.add(CONTAINER_DB_TYPE); - } - - /** - * Constructs KeyValueContainerData object. - * @param id - ContainerId - * @param size - maximum size of the container in bytes - */ - public KeyValueContainerData(long id, long size) { - super(ContainerProtos.ContainerType.KeyValueContainer, id, size); - this.numPendingDeletionBlocks = new AtomicInteger(0); - this.deleteTransactionId = 0; - } - - /** - * Constructs KeyValueContainerData object. - * @param id - ContainerId - * @param layOutVersion - * @param size - maximum size of the container in bytes - */ - public KeyValueContainerData(long id, int layOutVersion, long size) { - super(ContainerProtos.ContainerType.KeyValueContainer, id, layOutVersion, - size); - this.numPendingDeletionBlocks = new AtomicInteger(0); - this.deleteTransactionId = 0; - } - - - /** - * Sets Container dbFile. This should be called only during creation of - * KeyValue container. - * @param containerDbFile - */ - public void setDbFile(File containerDbFile) { - dbFile = containerDbFile; - } - - /** - * Returns container DB file. - * @return dbFile - */ - public File getDbFile() { - return dbFile; - } - - /** - * Returns container metadata path. - * @return - Physical path where container file and checksum is stored. - */ - public String getMetadataPath() { - return metadataPath; - } - - /** - * Sets container metadata path. - * - * @param path - String. - */ - public void setMetadataPath(String path) { - this.metadataPath = path; - } - - /** - * Returns the path to base dir of the container. - * @return Path to base dir - */ - public String getContainerPath() { - if (metadataPath == null) { - return null; - } - return new File(metadataPath).getParent(); - } - - /** - * Get chunks path. - * @return - Path where chunks are stored - */ - public String getChunksPath() { - return chunksPath; - } - - /** - * Set chunks Path. - * @param chunkPath - File path. - */ - public void setChunksPath(String chunkPath) { - this.chunksPath = chunkPath; - } - - /** - * Returns the DBType used for the container. - * @return containerDBType - */ - public String getContainerDBType() { - return containerDBType; - } - - /** - * Sets the DBType used for the container. - * @param containerDBType - */ - public void setContainerDBType(String containerDBType) { - this.containerDBType = containerDBType; - } - - /** - * Increase the count of pending deletion blocks. - * - * @param numBlocks increment number - */ - public void incrPendingDeletionBlocks(int numBlocks) { - this.numPendingDeletionBlocks.addAndGet(numBlocks); - } - - /** - * Decrease the count of pending deletion blocks. - * - * @param numBlocks decrement number - */ - public void decrPendingDeletionBlocks(int numBlocks) { - this.numPendingDeletionBlocks.addAndGet(-1 * numBlocks); - } - - /** - * Get the number of pending deletion blocks. - */ - public int getNumPendingDeletionBlocks() { - return this.numPendingDeletionBlocks.get(); - } - - /** - * Sets deleteTransactionId to latest delete transactionId for the container. - * - * @param transactionId latest transactionId of the container. - */ - public void updateDeleteTransactionId(long transactionId) { - deleteTransactionId = max(transactionId, deleteTransactionId); - } - - /** - * Return the latest deleteTransactionId of the container. - */ - public long getDeleteTransactionId() { - return deleteTransactionId; - } - - /** - * Returns a ProtoBuf Message from ContainerData. - * - * @return Protocol Buffer Message - */ - public ContainerProtos.ContainerData getProtoBufMessage() { - ContainerProtos.ContainerData.Builder builder = ContainerProtos - .ContainerData.newBuilder(); - builder.setContainerID(this.getContainerID()); - builder.setContainerPath(this.getMetadataPath()); - builder.setState(this.getState()); - - for (Map.Entry entry : getMetadata().entrySet()) { - ContainerProtos.KeyValue.Builder keyValBuilder = - ContainerProtos.KeyValue.newBuilder(); - builder.addMetadata(keyValBuilder.setKey(entry.getKey()) - .setValue(entry.getValue()).build()); - } - - if (this.getBytesUsed() >= 0) { - builder.setBytesUsed(this.getBytesUsed()); - } - - if(this.getContainerType() != null) { - builder.setContainerType(ContainerProtos.ContainerType.KeyValueContainer); - } - - return builder.build(); - } - - public static List getYamlFields() { - return Collections.unmodifiableList(KV_YAML_FIELDS); - } - - /** - * Constructs a KeyValueContainerData object from ProtoBuf classes. - * - * @param protoData - ProtoBuf Message - * @throws IOException - */ - @VisibleForTesting - public static KeyValueContainerData getFromProtoBuf( - ContainerProtos.ContainerData protoData) throws IOException { - // TODO: Add containerMaxSize to ContainerProtos.ContainerData - StorageSize storageSize = StorageSize.parse( - ScmConfigKeys.OZONE_SCM_CONTAINER_SIZE_DEFAULT); - KeyValueContainerData data = new KeyValueContainerData( - protoData.getContainerID(), - (long)storageSize.getUnit().toBytes(storageSize.getValue())); - for (int x = 0; x < protoData.getMetadataCount(); x++) { - data.addMetadata(protoData.getMetadata(x).getKey(), - protoData.getMetadata(x).getValue()); - } - - if (protoData.hasContainerPath()) { - String metadataPath = protoData.getContainerPath()+ File.separator + - OzoneConsts.CONTAINER_META_PATH; - data.setMetadataPath(metadataPath); - } - - if (protoData.hasState()) { - data.setState(protoData.getState()); - } - - if (protoData.hasBytesUsed()) { - data.setBytesUsed(protoData.getBytesUsed()); - } - - return data; - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueHandler.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueHandler.java deleted file mode 100644 index 5be6e2849b7..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueHandler.java +++ /dev/null @@ -1,850 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.keyvalue; - -import java.io.FileInputStream; -import java.io.IOException; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.ReentrantLock; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.conf.StorageUnit; -import org.apache.hadoop.hdds.client.BlockID; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandRequestProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandResponseProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerLifeCycleState; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerType; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .GetSmallFileRequestProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.KeyValue; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .PutSmallFileRequestProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.Type; -import org.apache.hadoop.hdds.scm.ScmConfigKeys; -import org.apache.hadoop.hdds.scm.container.common.helpers - .StorageContainerException; -import org.apache.hadoop.ozone.container.common.helpers.BlockData; -import org.apache.hadoop.ozone.container.common.helpers.ChunkInfo; -import org.apache.hadoop.ozone.container.common.helpers.ContainerMetrics; -import org.apache.hadoop.ozone.container.common.helpers.ContainerUtils; -import org.apache.hadoop.ozone.container.common.impl.ContainerSet; -import org.apache.hadoop.ozone.container.common.impl.OpenContainerBlockMap; -import org.apache.hadoop.ozone.container.common.interfaces.Container; -import org.apache.hadoop.ozone.container.common.interfaces.Handler; -import org.apache.hadoop.ozone.container.common.interfaces.VolumeChoosingPolicy; -import org.apache.hadoop.ozone.container.common.volume.HddsVolume; -import org.apache.hadoop.ozone.container.common.volume - .RoundRobinVolumeChoosingPolicy; -import org.apache.hadoop.ozone.container.common.volume.VolumeSet; -import org.apache.hadoop.ozone.container.keyvalue.helpers.ChunkUtils; -import org.apache.hadoop.ozone.container.keyvalue.helpers.BlockUtils; -import org.apache.hadoop.ozone.container.keyvalue.helpers.KeyValueContainerUtil; -import org.apache.hadoop.ozone.container.keyvalue.helpers.SmallFileUtils; -import org.apache.hadoop.ozone.container.keyvalue.impl.ChunkManagerImpl; -import org.apache.hadoop.ozone.container.keyvalue.impl.BlockManagerImpl; -import org.apache.hadoop.ozone.container.keyvalue.interfaces.ChunkManager; -import org.apache.hadoop.ozone.container.keyvalue.interfaces.BlockManager; -import org.apache.hadoop.ozone.container.keyvalue.statemachine.background - .BlockDeletingService; -import org.apache.hadoop.util.AutoCloseableLock; -import org.apache.hadoop.util.ReflectionUtils; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import com.google.protobuf.ByteString; -import static org.apache.hadoop.hdds.HddsConfigKeys - .HDDS_DATANODE_VOLUME_CHOOSING_POLICY; -import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .Result.BLOCK_NOT_COMMITTED; -import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .Result.CLOSED_CONTAINER_IO; -import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .Result.CONTAINER_INTERNAL_ERROR; -import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .Result.DELETE_ON_OPEN_CONTAINER; -import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .Result.GET_SMALL_FILE_ERROR; -import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .Result.INVALID_CONTAINER_STATE; -import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .Result.IO_EXCEPTION; -import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .Result.PUT_SMALL_FILE_ERROR; -import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .Stage; -import static org.apache.hadoop.ozone.OzoneConfigKeys - .OZONE_BLOCK_DELETING_SERVICE_INTERVAL; -import static org.apache.hadoop.ozone.OzoneConfigKeys - .OZONE_BLOCK_DELETING_SERVICE_INTERVAL_DEFAULT; -import static org.apache.hadoop.ozone.OzoneConfigKeys - .OZONE_BLOCK_DELETING_SERVICE_TIMEOUT; -import static org.apache.hadoop.ozone.OzoneConfigKeys - .OZONE_BLOCK_DELETING_SERVICE_TIMEOUT_DEFAULT; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Handler for KeyValue Container type. - */ -public class KeyValueHandler extends Handler { - - private static final Logger LOG = LoggerFactory.getLogger( - KeyValueHandler.class); - - private final ContainerType containerType; - private final BlockManager blockManager; - private final ChunkManager chunkManager; - private final BlockDeletingService blockDeletingService; - private final VolumeChoosingPolicy volumeChoosingPolicy; - private final long maxContainerSize; - private final AutoCloseableLock handlerLock; - private final OpenContainerBlockMap openContainerBlockMap; - - public KeyValueHandler(Configuration config, ContainerSet contSet, - VolumeSet volSet, ContainerMetrics metrics) { - super(config, contSet, volSet, metrics); - containerType = ContainerType.KeyValueContainer; - blockManager = new BlockManagerImpl(config); - chunkManager = new ChunkManagerImpl(); - long svcInterval = config - .getTimeDuration(OZONE_BLOCK_DELETING_SERVICE_INTERVAL, - OZONE_BLOCK_DELETING_SERVICE_INTERVAL_DEFAULT, - TimeUnit.MILLISECONDS); - long serviceTimeout = config - .getTimeDuration(OZONE_BLOCK_DELETING_SERVICE_TIMEOUT, - OZONE_BLOCK_DELETING_SERVICE_TIMEOUT_DEFAULT, - TimeUnit.MILLISECONDS); - this.blockDeletingService = - new BlockDeletingService(containerSet, svcInterval, serviceTimeout, - TimeUnit.MILLISECONDS, config); - blockDeletingService.start(); - volumeChoosingPolicy = ReflectionUtils.newInstance(conf.getClass( - HDDS_DATANODE_VOLUME_CHOOSING_POLICY, RoundRobinVolumeChoosingPolicy - .class, VolumeChoosingPolicy.class), conf); - maxContainerSize = (long)config.getStorageSize( - ScmConfigKeys.OZONE_SCM_CONTAINER_SIZE, - ScmConfigKeys.OZONE_SCM_CONTAINER_SIZE_DEFAULT, StorageUnit.BYTES); - // this handler lock is used for synchronizing createContainer Requests, - // so using a fair lock here. - handlerLock = new AutoCloseableLock(new ReentrantLock(true)); - openContainerBlockMap = new OpenContainerBlockMap(); - } - - @VisibleForTesting - public VolumeChoosingPolicy getVolumeChoosingPolicyForTesting() { - return volumeChoosingPolicy; - } - /** - * Returns OpenContainerBlockMap instance. - * - * @return OpenContainerBlockMap - */ - public OpenContainerBlockMap getOpenContainerBlockMap() { - return openContainerBlockMap; - } - - @Override - public ContainerCommandResponseProto handle( - ContainerCommandRequestProto request, Container container) { - - Type cmdType = request.getCmdType(); - KeyValueContainer kvContainer = (KeyValueContainer) container; - switch(cmdType) { - case CreateContainer: - return handleCreateContainer(request, kvContainer); - case ReadContainer: - return handleReadContainer(request, kvContainer); - case UpdateContainer: - return handleUpdateContainer(request, kvContainer); - case DeleteContainer: - return handleDeleteContainer(request, kvContainer); - case ListContainer: - return handleUnsupportedOp(request); - case CloseContainer: - return handleCloseContainer(request, kvContainer); - case PutBlock: - return handlePutBlock(request, kvContainer); - case GetBlock: - return handleGetBlock(request, kvContainer); - case DeleteBlock: - return handleDeleteBlock(request, kvContainer); - case ListBlock: - return handleUnsupportedOp(request); - case ReadChunk: - return handleReadChunk(request, kvContainer); - case DeleteChunk: - return handleDeleteChunk(request, kvContainer); - case WriteChunk: - return handleWriteChunk(request, kvContainer); - case ListChunk: - return handleUnsupportedOp(request); - case CompactChunk: - return handleUnsupportedOp(request); - case PutSmallFile: - return handlePutSmallFile(request, kvContainer); - case GetSmallFile: - return handleGetSmallFile(request, kvContainer); - case GetCommittedBlockLength: - return handleGetCommittedBlockLength(request, kvContainer); - default: - return null; - } - } - - @VisibleForTesting - public ChunkManager getChunkManager() { - return this.chunkManager; - } - - @VisibleForTesting - public BlockManager getBlockManager() { - return this.blockManager; - } - - /** - * Handles Create Container Request. If successful, adds the container to - * ContainerSet. - */ - ContainerCommandResponseProto handleCreateContainer( - ContainerCommandRequestProto request, KeyValueContainer kvContainer) { - if (!request.hasCreateContainer()) { - LOG.debug("Malformed Create Container request. trace ID: {}", - request.getTraceID()); - return ContainerUtils.malformedRequest(request); - } - // Create Container request should be passed a null container as the - // container would be created here. - Preconditions.checkArgument(kvContainer == null); - - long containerID = request.getContainerID(); - - KeyValueContainerData newContainerData = new KeyValueContainerData( - containerID, maxContainerSize); - // TODO: Add support to add metadataList to ContainerData. Add metadata - // to container during creation. - KeyValueContainer newContainer = new KeyValueContainer( - newContainerData, conf); - - try { - handlerLock.acquire(); - if (containerSet.getContainer(containerID) == null) { - newContainer.create(volumeSet, volumeChoosingPolicy, scmID); - containerSet.addContainer(newContainer); - } else { - throw new StorageContainerException("Container already exists with " + - "container Id " + containerID, ContainerProtos.Result - .CONTAINER_EXISTS); - } - } catch (StorageContainerException ex) { - return ContainerUtils.logAndReturnError(LOG, ex, request); - } finally { - handlerLock.release(); - } - - return ContainerUtils.getSuccessResponse(request); - } - - public void populateContainerPathFields(KeyValueContainer container, - long maxSize) throws IOException { - volumeSet.acquireLock(); - try { - HddsVolume containerVolume = volumeChoosingPolicy.chooseVolume(volumeSet - .getVolumesList(), maxSize); - String hddsVolumeDir = containerVolume.getHddsRootDir().toString(); - container.populatePathFields(scmID, containerVolume, hddsVolumeDir); - } finally { - volumeSet.releaseLock(); - } - } - - /** - * Handles Read Container Request. Returns the ContainerData as response. - */ - ContainerCommandResponseProto handleReadContainer( - ContainerCommandRequestProto request, KeyValueContainer kvContainer) { - if (!request.hasReadContainer()) { - LOG.debug("Malformed Read Container request. trace ID: {}", - request.getTraceID()); - return ContainerUtils.malformedRequest(request); - } - - KeyValueContainerData containerData = kvContainer.getContainerData(); - return KeyValueContainerUtil.getReadContainerResponse( - request, containerData); - } - - - /** - * Handles Update Container Request. If successful, the container metadata - * is updated. - */ - ContainerCommandResponseProto handleUpdateContainer( - ContainerCommandRequestProto request, KeyValueContainer kvContainer) { - - if (!request.hasUpdateContainer()) { - LOG.debug("Malformed Update Container request. trace ID: {}", - request.getTraceID()); - return ContainerUtils.malformedRequest(request); - } - - boolean forceUpdate = request.getUpdateContainer().getForceUpdate(); - List keyValueList = - request.getUpdateContainer().getMetadataList(); - Map metadata = new HashMap<>(); - for (KeyValue keyValue : keyValueList) { - metadata.put(keyValue.getKey(), keyValue.getValue()); - } - - try { - if (!metadata.isEmpty()) { - kvContainer.update(metadata, forceUpdate); - } - } catch (StorageContainerException ex) { - return ContainerUtils.logAndReturnError(LOG, ex, request); - } - return ContainerUtils.getSuccessResponse(request); - } - - /** - * Handles Delete Container Request. - * Open containers cannot be deleted. - * Holds writeLock on ContainerSet till the container is removed from - * containerMap. On disk deletion of container files will happen - * asynchronously without the lock. - */ - ContainerCommandResponseProto handleDeleteContainer( - ContainerCommandRequestProto request, KeyValueContainer kvContainer) { - - if (!request.hasDeleteContainer()) { - LOG.debug("Malformed Delete container request. trace ID: {}", - request.getTraceID()); - return ContainerUtils.malformedRequest(request); - } - - boolean forceDelete = request.getDeleteContainer().getForceDelete(); - kvContainer.writeLock(); - try { - // Check if container is open - if (kvContainer.getContainerData().isOpen()) { - kvContainer.writeUnlock(); - throw new StorageContainerException( - "Deletion of Open Container is not allowed.", - DELETE_ON_OPEN_CONTAINER); - } else if (!forceDelete && kvContainer.getContainerData().getKeyCount() - > 0) { - // If the container is not empty and cannot be deleted forcibly, - // then throw a SCE to stop deleting. - kvContainer.writeUnlock(); - throw new StorageContainerException( - "Container cannot be deleted because it is not empty.", - ContainerProtos.Result.ERROR_CONTAINER_NOT_EMPTY); - } else { - long containerId = kvContainer.getContainerData().getContainerID(); - containerSet.removeContainer(containerId); - openContainerBlockMap.removeContainer(containerId); - // Release the lock first. - // Avoid holding write locks for disk operations - kvContainer.writeUnlock(); - - kvContainer.delete(forceDelete); - } - } catch (StorageContainerException ex) { - return ContainerUtils.logAndReturnError(LOG, ex, request); - } finally { - if (kvContainer.hasWriteLock()) { - kvContainer.writeUnlock(); - } - } - return ContainerUtils.getSuccessResponse(request); - } - - /** - * Handles Close Container Request. An open container is closed. - */ - ContainerCommandResponseProto handleCloseContainer( - ContainerCommandRequestProto request, KeyValueContainer kvContainer) { - - if (!request.hasCloseContainer()) { - LOG.debug("Malformed Update Container request. trace ID: {}", - request.getTraceID()); - return ContainerUtils.malformedRequest(request); - } - - long containerID = kvContainer.getContainerData().getContainerID(); - ContainerLifeCycleState containerState = kvContainer.getContainerState(); - - try { - if (containerState == ContainerLifeCycleState.CLOSED) { - LOG.debug("Container {} is already closed.", containerID); - return ContainerUtils.getSuccessResponse(request); - } else if (containerState == ContainerLifeCycleState.INVALID) { - LOG.debug("Invalid container data. ContainerID: {}", containerID); - throw new StorageContainerException("Invalid container data. " + - "ContainerID: " + containerID, INVALID_CONTAINER_STATE); - } - - KeyValueContainerData kvData = kvContainer.getContainerData(); - - // remove the container from open block map once, all the blocks - // have been committed and the container is closed - kvData.setState(ContainerProtos.ContainerLifeCycleState.CLOSING); - commitPendingBlocks(kvContainer); - kvContainer.close(); - // make sure the the container open keys from BlockMap gets removed - openContainerBlockMap.removeContainer(kvData.getContainerID()); - } catch (StorageContainerException ex) { - return ContainerUtils.logAndReturnError(LOG, ex, request); - } catch (IOException ex) { - return ContainerUtils.logAndReturnError(LOG, - new StorageContainerException("Close Container failed", ex, - IO_EXCEPTION), request); - } - - return ContainerUtils.getSuccessResponse(request); - } - - /** - * Handle Put Block operation. Calls BlockManager to process the request. - */ - ContainerCommandResponseProto handlePutBlock( - ContainerCommandRequestProto request, KeyValueContainer kvContainer) { - - long blockLength; - if (!request.hasPutBlock()) { - LOG.debug("Malformed Put Key request. trace ID: {}", - request.getTraceID()); - return ContainerUtils.malformedRequest(request); - } - - try { - checkContainerOpen(kvContainer); - - BlockData blockData = BlockData.getFromProtoBuf( - request.getPutBlock().getBlockData()); - long numBytes = blockData.getProtoBufMessage().toByteArray().length; - blockLength = commitKey(blockData, kvContainer); - metrics.incContainerBytesStats(Type.PutBlock, numBytes); - } catch (StorageContainerException ex) { - return ContainerUtils.logAndReturnError(LOG, ex, request); - } catch (IOException ex) { - return ContainerUtils.logAndReturnError(LOG, - new StorageContainerException("Put Key failed", ex, IO_EXCEPTION), - request); - } - - return BlockUtils.putBlockResponseSuccess(request, blockLength); - } - - private void commitPendingBlocks(KeyValueContainer kvContainer) - throws IOException { - long containerId = kvContainer.getContainerData().getContainerID(); - List pendingBlocks = - this.openContainerBlockMap.getOpenBlocks(containerId); - for(BlockData blockData : pendingBlocks) { - commitKey(blockData, kvContainer); - } - } - - private long commitKey(BlockData blockData, KeyValueContainer kvContainer) - throws IOException { - Preconditions.checkNotNull(blockData); - long length = blockManager.putBlock(kvContainer, blockData); - //update the open key Map in containerManager - this.openContainerBlockMap.removeFromBlockMap(blockData.getBlockID()); - return length; - } - /** - * Handle Get Block operation. Calls BlockManager to process the request. - */ - ContainerCommandResponseProto handleGetBlock( - ContainerCommandRequestProto request, KeyValueContainer kvContainer) { - - if (!request.hasGetBlock()) { - LOG.debug("Malformed Get Key request. trace ID: {}", - request.getTraceID()); - return ContainerUtils.malformedRequest(request); - } - - BlockData responseData; - try { - BlockID blockID = BlockID.getFromProtobuf( - request.getGetBlock().getBlockID()); - responseData = blockManager.getBlock(kvContainer, blockID); - long numBytes = responseData.getProtoBufMessage().toByteArray().length; - metrics.incContainerBytesStats(Type.GetBlock, numBytes); - - } catch (StorageContainerException ex) { - return ContainerUtils.logAndReturnError(LOG, ex, request); - } catch (IOException ex) { - return ContainerUtils.logAndReturnError(LOG, - new StorageContainerException("Get Key failed", ex, IO_EXCEPTION), - request); - } - - return BlockUtils.getBlockDataResponse(request, responseData); - } - - /** - * Handles GetCommittedBlockLength operation. - * Calls BlockManager to process the request. - */ - ContainerCommandResponseProto handleGetCommittedBlockLength( - ContainerCommandRequestProto request, KeyValueContainer kvContainer) { - if (!request.hasGetCommittedBlockLength()) { - LOG.debug("Malformed Get Key request. trace ID: {}", - request.getTraceID()); - return ContainerUtils.malformedRequest(request); - } - - long blockLength; - try { - BlockID blockID = BlockID - .getFromProtobuf(request.getGetCommittedBlockLength().getBlockID()); - // Check if it really exists in the openContainerBlockMap - if (openContainerBlockMap.checkIfBlockExists(blockID)) { - String msg = "Block " + blockID + " is not committed yet."; - throw new StorageContainerException(msg, BLOCK_NOT_COMMITTED); - } - blockLength = blockManager.getCommittedBlockLength(kvContainer, blockID); - } catch (StorageContainerException ex) { - return ContainerUtils.logAndReturnError(LOG, ex, request); - } catch (IOException ex) { - return ContainerUtils.logAndReturnError(LOG, - new StorageContainerException("GetCommittedBlockLength failed", ex, - IO_EXCEPTION), request); - } - - return BlockUtils.getBlockLengthResponse(request, blockLength); - } - - /** - * Handle Delete Block operation. Calls BlockManager to process the request. - */ - ContainerCommandResponseProto handleDeleteBlock( - ContainerCommandRequestProto request, KeyValueContainer kvContainer) { - - if (!request.hasDeleteBlock()) { - LOG.debug("Malformed Delete Key request. trace ID: {}", - request.getTraceID()); - return ContainerUtils.malformedRequest(request); - } - - try { - checkContainerOpen(kvContainer); - - BlockID blockID = BlockID.getFromProtobuf( - request.getDeleteBlock().getBlockID()); - - blockManager.deleteBlock(kvContainer, blockID); - } catch (StorageContainerException ex) { - return ContainerUtils.logAndReturnError(LOG, ex, request); - } catch (IOException ex) { - return ContainerUtils.logAndReturnError(LOG, - new StorageContainerException("Delete Key failed", ex, IO_EXCEPTION), - request); - } - - return BlockUtils.getBlockResponseSuccess(request); - } - - /** - * Handle Read Chunk operation. Calls ChunkManager to process the request. - */ - ContainerCommandResponseProto handleReadChunk( - ContainerCommandRequestProto request, KeyValueContainer kvContainer) { - - if (!request.hasReadChunk()) { - LOG.debug("Malformed Read Chunk request. trace ID: {}", - request.getTraceID()); - return ContainerUtils.malformedRequest(request); - } - - ChunkInfo chunkInfo; - byte[] data; - try { - BlockID blockID = BlockID.getFromProtobuf( - request.getReadChunk().getBlockID()); - chunkInfo = ChunkInfo.getFromProtoBuf(request.getReadChunk() - .getChunkData()); - Preconditions.checkNotNull(chunkInfo); - - data = chunkManager.readChunk(kvContainer, blockID, chunkInfo); - metrics.incContainerBytesStats(Type.ReadChunk, data.length); - } catch (StorageContainerException ex) { - return ContainerUtils.logAndReturnError(LOG, ex, request); - } catch (IOException ex) { - return ContainerUtils.logAndReturnError(LOG, - new StorageContainerException("Read Chunk failed", ex, IO_EXCEPTION), - request); - } - - return ChunkUtils.getReadChunkResponse(request, data, chunkInfo); - } - - /** - * Handle Delete Chunk operation. Calls ChunkManager to process the request. - */ - ContainerCommandResponseProto handleDeleteChunk( - ContainerCommandRequestProto request, KeyValueContainer kvContainer) { - - if (!request.hasDeleteChunk()) { - LOG.debug("Malformed Delete Chunk request. trace ID: {}", - request.getTraceID()); - return ContainerUtils.malformedRequest(request); - } - - try { - checkContainerOpen(kvContainer); - - BlockID blockID = BlockID.getFromProtobuf( - request.getDeleteChunk().getBlockID()); - ContainerProtos.ChunkInfo chunkInfoProto = request.getDeleteChunk() - .getChunkData(); - ChunkInfo chunkInfo = ChunkInfo.getFromProtoBuf(chunkInfoProto); - Preconditions.checkNotNull(chunkInfo); - - chunkManager.deleteChunk(kvContainer, blockID, chunkInfo); - openContainerBlockMap.removeChunk(blockID, chunkInfoProto); - } catch (StorageContainerException ex) { - return ContainerUtils.logAndReturnError(LOG, ex, request); - } catch (IOException ex) { - return ContainerUtils.logAndReturnError(LOG, - new StorageContainerException("Delete Chunk failed", ex, - IO_EXCEPTION), request); - } - - return ChunkUtils.getChunkResponseSuccess(request); - } - - /** - * Handle Write Chunk operation. Calls ChunkManager to process the request. - */ - ContainerCommandResponseProto handleWriteChunk( - ContainerCommandRequestProto request, KeyValueContainer kvContainer) { - - if (!request.hasWriteChunk()) { - LOG.debug("Malformed Write Chunk request. trace ID: {}", - request.getTraceID()); - return ContainerUtils.malformedRequest(request); - } - - try { - checkContainerOpen(kvContainer); - - BlockID blockID = BlockID.getFromProtobuf( - request.getWriteChunk().getBlockID()); - ContainerProtos.ChunkInfo chunkInfoProto = - request.getWriteChunk().getChunkData(); - ChunkInfo chunkInfo = ChunkInfo.getFromProtoBuf(chunkInfoProto); - Preconditions.checkNotNull(chunkInfo); - - byte[] data = null; - if (request.getWriteChunk().getStage() == Stage.WRITE_DATA || - request.getWriteChunk().getStage() == Stage.COMBINED) { - data = request.getWriteChunk().getData().toByteArray(); - } - - chunkManager.writeChunk(kvContainer, blockID, chunkInfo, data, - request.getWriteChunk().getStage()); - - // We should increment stats after writeChunk - if (request.getWriteChunk().getStage() == Stage.WRITE_DATA || - request.getWriteChunk().getStage() == Stage.COMBINED) { - metrics.incContainerBytesStats(Type.WriteChunk, request.getWriteChunk() - .getChunkData().getLen()); - } - - if (request.getWriteChunk().getStage() == Stage.COMMIT_DATA - || request.getWriteChunk().getStage() == Stage.COMBINED) { - // the openContainerBlockMap should be updated only during - // COMMIT_STAGE of handling write chunk request. - openContainerBlockMap.addChunk(blockID, chunkInfoProto); - } - } catch (StorageContainerException ex) { - return ContainerUtils.logAndReturnError(LOG, ex, request); - } catch (IOException ex) { - return ContainerUtils.logAndReturnError(LOG, - new StorageContainerException("Write Chunk failed", ex, IO_EXCEPTION), - request); - } - - return ChunkUtils.getChunkResponseSuccess(request); - } - - /** - * Handle Put Small File operation. Writes the chunk and associated key - * using a single RPC. Calls BlockManager and ChunkManager to process the - * request. - */ - ContainerCommandResponseProto handlePutSmallFile( - ContainerCommandRequestProto request, KeyValueContainer kvContainer) { - - if (!request.hasPutSmallFile()) { - LOG.debug("Malformed Put Small File request. trace ID: {}", - request.getTraceID()); - return ContainerUtils.malformedRequest(request); - } - PutSmallFileRequestProto putSmallFileReq = - request.getPutSmallFile(); - - try { - checkContainerOpen(kvContainer); - - BlockID blockID = BlockID.getFromProtobuf(putSmallFileReq.getBlock() - .getBlockData().getBlockID()); - BlockData blockData = BlockData.getFromProtoBuf( - putSmallFileReq.getBlock().getBlockData()); - Preconditions.checkNotNull(blockData); - - ChunkInfo chunkInfo = ChunkInfo.getFromProtoBuf( - putSmallFileReq.getChunkInfo()); - Preconditions.checkNotNull(chunkInfo); - byte[] data = putSmallFileReq.getData().toByteArray(); - // chunks will be committed as a part of handling putSmallFile - // here. There is no need to maintain this info in openContainerBlockMap. - chunkManager.writeChunk( - kvContainer, blockID, chunkInfo, data, Stage.COMBINED); - - List chunks = new LinkedList<>(); - chunks.add(chunkInfo.getProtoBufMessage()); - blockData.setChunks(chunks); - blockManager.putBlock(kvContainer, blockData); - metrics.incContainerBytesStats(Type.PutSmallFile, data.length); - - } catch (StorageContainerException ex) { - return ContainerUtils.logAndReturnError(LOG, ex, request); - } catch (IOException ex) { - return ContainerUtils.logAndReturnError(LOG, - new StorageContainerException("Read Chunk failed", ex, - PUT_SMALL_FILE_ERROR), request); - } - - return SmallFileUtils.getPutFileResponseSuccess(request); - } - - /** - * Handle Get Small File operation. Gets a data stream using a key. This - * helps in reducing the RPC overhead for small files. Calls BlockManager and - * ChunkManager to process the request. - */ - ContainerCommandResponseProto handleGetSmallFile( - ContainerCommandRequestProto request, KeyValueContainer kvContainer) { - - if (!request.hasGetSmallFile()) { - LOG.debug("Malformed Get Small File request. trace ID: {}", - request.getTraceID()); - return ContainerUtils.malformedRequest(request); - } - - GetSmallFileRequestProto getSmallFileReq = request.getGetSmallFile(); - - try { - BlockID blockID = BlockID.getFromProtobuf(getSmallFileReq.getBlock() - .getBlockID()); - BlockData responseData = blockManager.getBlock(kvContainer, blockID); - - ContainerProtos.ChunkInfo chunkInfo = null; - ByteString dataBuf = ByteString.EMPTY; - for (ContainerProtos.ChunkInfo chunk : responseData.getChunks()) { - byte[] data = chunkManager.readChunk(kvContainer, blockID, - ChunkInfo.getFromProtoBuf(chunk)); - ByteString current = ByteString.copyFrom(data); - dataBuf = dataBuf.concat(current); - chunkInfo = chunk; - } - metrics.incContainerBytesStats(Type.GetSmallFile, dataBuf.size()); - return SmallFileUtils.getGetSmallFileResponseSuccess(request, dataBuf - .toByteArray(), ChunkInfo.getFromProtoBuf(chunkInfo)); - } catch (StorageContainerException e) { - return ContainerUtils.logAndReturnError(LOG, e, request); - } catch (IOException ex) { - return ContainerUtils.logAndReturnError(LOG, - new StorageContainerException("Write Chunk failed", ex, - GET_SMALL_FILE_ERROR), request); - } - } - - /** - * Handle unsupported operation. - */ - ContainerCommandResponseProto handleUnsupportedOp( - ContainerCommandRequestProto request) { - // TODO : remove all unsupported operations or handle them. - return ContainerUtils.unsupportedRequest(request); - } - - /** - * Check if container is open. Throw exception otherwise. - * @param kvContainer - * @throws StorageContainerException - */ - private void checkContainerOpen(KeyValueContainer kvContainer) - throws StorageContainerException { - - ContainerLifeCycleState containerState = kvContainer.getContainerState(); - - if (containerState == ContainerLifeCycleState.OPEN) { - return; - } else { - String msg = "Requested operation not allowed as ContainerState is " + - containerState; - ContainerProtos.Result result = null; - switch (containerState) { - case CLOSING: - case CLOSED: - result = CLOSED_CONTAINER_IO; - break; - case INVALID: - result = INVALID_CONTAINER_STATE; - break; - default: - result = CONTAINER_INTERNAL_ERROR; - } - - throw new StorageContainerException(msg, result); - } - } - - public Container importContainer(long containerID, long maxSize, - FileInputStream rawContainerStream, - TarContainerPacker packer) - throws IOException { - - KeyValueContainerData containerData = - new KeyValueContainerData(containerID, - maxSize); - - KeyValueContainer container = new KeyValueContainer(containerData, - conf); - - populateContainerPathFields(container, maxSize); - container.importContainerData(rawContainerStream, packer); - return container; - - } -} \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/TarContainerPacker.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/TarContainerPacker.java deleted file mode 100644 index 13689a705ce..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/TarContainerPacker.java +++ /dev/null @@ -1,249 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.keyvalue; - -import java.io.BufferedOutputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.stream.Collectors; - -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.container.common.interfaces.Container; -import org.apache.hadoop.ozone.container.common.interfaces.ContainerPacker; - -import com.google.common.base.Preconditions; -import org.apache.commons.compress.archivers.ArchiveEntry; -import org.apache.commons.compress.archivers.ArchiveOutputStream; -import org.apache.commons.compress.archivers.tar.TarArchiveEntry; -import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; -import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; -import org.apache.commons.compress.compressors.CompressorException; -import org.apache.commons.compress.compressors.CompressorInputStream; -import org.apache.commons.compress.compressors.CompressorOutputStream; -import org.apache.commons.compress.compressors.CompressorStreamFactory; -import org.apache.commons.io.IOUtils; - -/** - * Compress/uncompress KeyValueContainer data to a tar.gz archive. - */ -public class TarContainerPacker - implements ContainerPacker { - - private static final String CHUNKS_DIR_NAME = OzoneConsts.STORAGE_DIR_CHUNKS; - - private static final String DB_DIR_NAME = "db"; - - private static final String CONTAINER_FILE_NAME = "container.yaml"; - - - - /** - * Given an input stream (tar file) extract the data to the specified - * directories. - * - * @param container container which defines the destination structure. - * @param inputStream the input stream. - * @throws IOException - */ - @Override - public byte[] unpackContainerData(Container container, - InputStream inputStream) - throws IOException { - byte[] descriptorFileContent = null; - try { - KeyValueContainerData containerData = container.getContainerData(); - CompressorInputStream compressorInputStream = - new CompressorStreamFactory() - .createCompressorInputStream(CompressorStreamFactory.GZIP, - inputStream); - - TarArchiveInputStream tarInput = - new TarArchiveInputStream(compressorInputStream); - - TarArchiveEntry entry = tarInput.getNextTarEntry(); - while (entry != null) { - String name = entry.getName(); - if (name.startsWith(DB_DIR_NAME + "/")) { - Path destinationPath = containerData.getDbFile().toPath() - .resolve(name.substring(DB_DIR_NAME.length() + 1)); - extractEntry(tarInput, entry.getSize(), destinationPath); - } else if (name.startsWith(CHUNKS_DIR_NAME + "/")) { - Path destinationPath = Paths.get(containerData.getChunksPath()) - .resolve(name.substring(CHUNKS_DIR_NAME.length() + 1)); - extractEntry(tarInput, entry.getSize(), destinationPath); - } else if (name.equals(CONTAINER_FILE_NAME)) { - //Don't do anything. Container file should be unpacked in a - //separated step by unpackContainerDescriptor call. - descriptorFileContent = readEntry(tarInput, entry); - } else { - throw new IllegalArgumentException( - "Unknown entry in the tar file: " + "" + name); - } - entry = tarInput.getNextTarEntry(); - } - return descriptorFileContent; - - } catch (CompressorException e) { - throw new IOException( - "Can't uncompress the given container: " + container - .getContainerData().getContainerID(), - e); - } - } - - private void extractEntry(TarArchiveInputStream tarInput, long size, - Path path) throws IOException { - Preconditions.checkNotNull(path, "Path element should not be null"); - Path parent = Preconditions.checkNotNull(path.getParent(), - "Path element should have a parent directory"); - Files.createDirectories(parent); - try (BufferedOutputStream bos = new BufferedOutputStream( - new FileOutputStream(path.toAbsolutePath().toString()))) { - int bufferSize = 1024; - byte[] buffer = new byte[bufferSize + 1]; - long remaining = size; - while (remaining > 0) { - int read = - tarInput.read(buffer, 0, (int) Math.min(remaining, bufferSize)); - if (read >= 0) { - remaining -= read; - bos.write(buffer, 0, read); - } else { - remaining = 0; - } - } - } - - } - - /** - * Given a containerData include all the required container data/metadata - * in a tar file. - * - * @param container Container to archive (data + metadata). - * @param destination Destination tar file/stream. - * @throws IOException - */ - @Override - public void pack(Container container, - OutputStream destination) - throws IOException { - - KeyValueContainerData containerData = container.getContainerData(); - - try (CompressorOutputStream gzippedOut = new CompressorStreamFactory() - .createCompressorOutputStream(CompressorStreamFactory.GZIP, - destination)) { - - try (ArchiveOutputStream archiveOutputStream = new TarArchiveOutputStream( - gzippedOut)) { - - includePath(containerData.getDbFile().toString(), DB_DIR_NAME, - archiveOutputStream); - - includePath(containerData.getChunksPath(), CHUNKS_DIR_NAME, - archiveOutputStream); - - includeFile(container.getContainerFile(), - CONTAINER_FILE_NAME, - archiveOutputStream); - } - } catch (CompressorException e) { - throw new IOException( - "Can't compress the container: " + containerData.getContainerID(), - e); - } - - } - - @Override - public byte[] unpackContainerDescriptor(InputStream inputStream) - throws IOException { - try { - CompressorInputStream compressorInputStream = - new CompressorStreamFactory() - .createCompressorInputStream(CompressorStreamFactory.GZIP, - inputStream); - - TarArchiveInputStream tarInput = - new TarArchiveInputStream(compressorInputStream); - - TarArchiveEntry entry = tarInput.getNextTarEntry(); - while (entry != null) { - String name = entry.getName(); - if (name.equals(CONTAINER_FILE_NAME)) { - return readEntry(tarInput, entry); - } - entry = tarInput.getNextTarEntry(); - } - - } catch (CompressorException e) { - throw new IOException( - "Can't read the container descriptor from the container archive", - e); - } - throw new IOException( - "Container descriptor is missing from the container archive."); - } - - private byte[] readEntry(TarArchiveInputStream tarInput, - TarArchiveEntry entry) throws IOException { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - int bufferSize = 1024; - byte[] buffer = new byte[bufferSize + 1]; - long remaining = entry.getSize(); - while (remaining > 0) { - int read = - tarInput.read(buffer, 0, (int) Math.min(remaining, bufferSize)); - remaining -= read; - bos.write(buffer, 0, read); - } - return bos.toByteArray(); - } - - private void includePath(String containerPath, String subdir, - ArchiveOutputStream archiveOutputStream) throws IOException { - - for (Path path : Files.list(Paths.get(containerPath)) - .collect(Collectors.toList())) { - - includeFile(path.toFile(), subdir + "/" + path.getFileName(), - archiveOutputStream); - } - } - - private void includeFile(File file, String entryName, - ArchiveOutputStream archiveOutputStream) throws IOException { - ArchiveEntry archiveEntry = - archiveOutputStream.createArchiveEntry(file, entryName); - archiveOutputStream.putArchiveEntry(archiveEntry); - try (FileInputStream fis = new FileInputStream(file)) { - IOUtils.copy(fis, archiveOutputStream); - } - archiveOutputStream.closeArchiveEntry(); - } - -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/helpers/BlockUtils.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/helpers/BlockUtils.java deleted file mode 100644 index f5cc8477740..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/helpers/BlockUtils.java +++ /dev/null @@ -1,199 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.keyvalue.helpers; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandRequestProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandResponseProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .GetBlockResponseProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos. - GetCommittedBlockLengthResponseProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos. - PutBlockResponseProto; -import org.apache.hadoop.hdds.scm.container.common.helpers - .StorageContainerException; -import org.apache.hadoop.ozone.container.common.helpers.BlockData; -import org.apache.hadoop.ozone.container.common.helpers.ContainerUtils; -import org.apache.hadoop.ozone.container.keyvalue.KeyValueContainerData; -import org.apache.hadoop.ozone.container.common.utils.ContainerCache; -import org.apache.hadoop.utils.MetadataStore; - -import java.io.IOException; - -import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .Result.NO_SUCH_BLOCK; -import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .Result.UNABLE_TO_READ_METADATA_DB; - -/** - * Utils functions to help block functions. - */ -public final class BlockUtils { - - /** Never constructed. **/ - private BlockUtils() { - - } - /** - * Get a DB handler for a given container. - * If the handler doesn't exist in cache yet, first create one and - * add into cache. This function is called with containerManager - * ReadLock held. - * - * @param containerData containerData. - * @param conf configuration. - * @return MetadataStore handle. - * @throws StorageContainerException - */ - public static MetadataStore getDB(KeyValueContainerData containerData, - Configuration conf) throws - StorageContainerException { - Preconditions.checkNotNull(containerData); - ContainerCache cache = ContainerCache.getInstance(conf); - Preconditions.checkNotNull(cache); - Preconditions.checkNotNull(containerData.getDbFile()); - try { - return cache.getDB(containerData.getContainerID(), containerData - .getContainerDBType(), containerData.getDbFile().getAbsolutePath()); - } catch (IOException ex) { - String message = String.format("Error opening DB. Container:%s " + - "ContainerPath:%s", containerData.getContainerID(), containerData - .getDbFile().getPath()); - throw new StorageContainerException(message, UNABLE_TO_READ_METADATA_DB); - } - } - /** - * Remove a DB handler from cache. - * - * @param container - Container data. - * @param conf - Configuration. - */ - public static void removeDB(KeyValueContainerData container, Configuration - conf) { - Preconditions.checkNotNull(container); - ContainerCache cache = ContainerCache.getInstance(conf); - Preconditions.checkNotNull(cache); - cache.removeDB(container.getContainerID()); - } - - /** - * Shutdown all DB Handles. - * - * @param cache - Cache for DB Handles. - */ - @SuppressWarnings("unchecked") - public static void shutdownCache(ContainerCache cache) { - cache.shutdownCache(); - } - - /** - * Parses the {@link BlockData} from a bytes array. - * - * @param bytes Block data in bytes. - * @return Block data. - * @throws IOException if the bytes array is malformed or invalid. - */ - public static BlockData getBlockData(byte[] bytes) throws IOException { - try { - ContainerProtos.BlockData blockData = ContainerProtos.BlockData.parseFrom( - bytes); - BlockData data = BlockData.getFromProtoBuf(blockData); - return data; - } catch (IOException e) { - throw new StorageContainerException("Failed to parse block data from " + - "the bytes array.", NO_SUCH_BLOCK); - } - } - - /** - * Returns putBlock response success. - * @param msg - Request. - * @return Response. - */ - public static ContainerCommandResponseProto putBlockResponseSuccess( - ContainerCommandRequestProto msg, long blockLength) { - GetCommittedBlockLengthResponseProto.Builder - committedBlockLengthResponseBuilder = - getCommittedBlockLengthResponseBuilder(blockLength, - msg.getPutBlock().getBlockData().getBlockID()); - PutBlockResponseProto.Builder putKeyResponse = - PutBlockResponseProto.newBuilder(); - putKeyResponse - .setCommittedBlockLength(committedBlockLengthResponseBuilder); - ContainerProtos.ContainerCommandResponseProto.Builder builder = - ContainerUtils.getSuccessResponseBuilder(msg); - builder.setPutBlock(putKeyResponse); - return builder.build(); - } - /** - * Returns successful blockResponse. - * @param msg - Request. - * @return Response. - */ - public static ContainerCommandResponseProto getBlockResponseSuccess( - ContainerCommandRequestProto msg) { - return ContainerUtils.getSuccessResponse(msg); - } - - - public static ContainerCommandResponseProto getBlockDataResponse( - ContainerCommandRequestProto msg, BlockData data) { - GetBlockResponseProto.Builder getBlock = ContainerProtos - .GetBlockResponseProto - .newBuilder(); - getBlock.setBlockData(data.getProtoBufMessage()); - ContainerProtos.ContainerCommandResponseProto.Builder builder = - ContainerUtils.getSuccessResponseBuilder(msg); - builder.setGetBlock(getBlock); - return builder.build(); - } - - /** - * Returns successful getCommittedBlockLength Response. - * @param msg - Request. - * @return Response. - */ - public static ContainerCommandResponseProto getBlockLengthResponse( - ContainerCommandRequestProto msg, long blockLength) { - GetCommittedBlockLengthResponseProto.Builder - committedBlockLengthResponseBuilder = - getCommittedBlockLengthResponseBuilder(blockLength, - msg.getGetCommittedBlockLength().getBlockID()); - ContainerProtos.ContainerCommandResponseProto.Builder builder = - ContainerUtils.getSuccessResponseBuilder(msg); - builder.setGetCommittedBlockLength(committedBlockLengthResponseBuilder); - return builder.build(); - } - - private static GetCommittedBlockLengthResponseProto.Builder - getCommittedBlockLengthResponseBuilder(long blockLength, - ContainerProtos.DatanodeBlockID blockID) { - ContainerProtos.GetCommittedBlockLengthResponseProto.Builder - getCommittedBlockLengthResponseBuilder = ContainerProtos. - GetCommittedBlockLengthResponseProto.newBuilder(); - getCommittedBlockLengthResponseBuilder.setBlockLength(blockLength); - getCommittedBlockLengthResponseBuilder.setBlockID(blockID); - return getCommittedBlockLengthResponseBuilder; - } -} \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/helpers/ChunkUtils.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/helpers/ChunkUtils.java deleted file mode 100644 index 62e328eac95..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/helpers/ChunkUtils.java +++ /dev/null @@ -1,357 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.keyvalue.helpers; - -import com.google.common.base.Preconditions; -import org.apache.commons.codec.binary.Hex; -import org.apache.commons.codec.digest.DigestUtils; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandRequestProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandResponseProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ReadChunkResponseProto; -import org.apache.hadoop.hdds.scm.container.common.helpers - .StorageContainerException; -import org.apache.hadoop.io.IOUtils; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.container.common.helpers.ChunkInfo; -import org.apache.hadoop.ozone.container.common.helpers.ContainerUtils; -import org.apache.hadoop.ozone.container.keyvalue.KeyValueContainerData; -import org.apache.hadoop.ozone.container.keyvalue.impl.ChunkManagerImpl; -import org.apache.ratis.shaded.com.google.protobuf.ByteString; -import org.apache.hadoop.ozone.container.common.volume.VolumeIOStats; -import org.apache.hadoop.util.Time; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.AsynchronousFileChannel; -import java.nio.channels.FileLock; -import java.nio.file.StandardOpenOption; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.concurrent.ExecutionException; - -import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.Result.*; - -/** - * Utility methods for chunk operations for KeyValue container. - */ -public final class ChunkUtils { - - /** Never constructed. **/ - private ChunkUtils() { - - } - - /** - * Writes the data in chunk Info to the specified location in the chunkfile. - * - * @param chunkFile - File to write data to. - * @param chunkInfo - Data stream to write. - * @param data - The data buffer. - * @param volumeIOStats - * @throws StorageContainerException - */ - public static void writeData(File chunkFile, ChunkInfo chunkInfo, - byte[] data, VolumeIOStats volumeIOStats) throws - StorageContainerException, ExecutionException, InterruptedException, - NoSuchAlgorithmException { - - Logger log = LoggerFactory.getLogger(ChunkManagerImpl.class); - if (data.length != chunkInfo.getLen()) { - String err = String.format("data array does not match the length " + - "specified. DataLen: %d Byte Array: %d", - chunkInfo.getLen(), data.length); - log.error(err); - throw new StorageContainerException(err, INVALID_WRITE_SIZE); - } - - AsynchronousFileChannel file = null; - FileLock lock = null; - - try { - if (chunkInfo.getChecksum() != null && - !chunkInfo.getChecksum().isEmpty()) { - verifyChecksum(chunkInfo, data, log); - } - - long writeTimeStart = Time.monotonicNow(); - file = - AsynchronousFileChannel.open(chunkFile.toPath(), - StandardOpenOption.CREATE, - StandardOpenOption.WRITE, - StandardOpenOption.SPARSE, - StandardOpenOption.SYNC); - lock = file.lock().get(); - int size = file.write(ByteBuffer.wrap(data), chunkInfo.getOffset()).get(); - // Increment volumeIO stats here. - volumeIOStats.incWriteTime(Time.monotonicNow() - writeTimeStart); - volumeIOStats.incWriteOpCount(); - volumeIOStats.incWriteBytes(size); - if (size != data.length) { - log.error("Invalid write size found. Size:{} Expected: {} ", size, - data.length); - throw new StorageContainerException("Invalid write size found. " + - "Size: " + size + " Expected: " + data.length, INVALID_WRITE_SIZE); - } - } catch (StorageContainerException ex) { - throw ex; - } catch(IOException e) { - throw new StorageContainerException(e, IO_EXCEPTION); - - } finally { - if (lock != null) { - try { - lock.release(); - } catch (IOException e) { - log.error("Unable to release lock ??, Fatal Error."); - throw new StorageContainerException(e, CONTAINER_INTERNAL_ERROR); - - } - } - if (file != null) { - try { - file.close(); - } catch (IOException e) { - throw new StorageContainerException("Error closing chunk file", - e, CONTAINER_INTERNAL_ERROR); - } - } - } - } - - /** - * Reads data from an existing chunk file. - * - * @param chunkFile - file where data lives. - * @param data - chunk definition. - * @param volumeIOStats - * @return ByteBuffer - * @throws StorageContainerException - * @throws ExecutionException - * @throws InterruptedException - */ - public static ByteBuffer readData(File chunkFile, ChunkInfo data, - VolumeIOStats volumeIOStats) - throws - StorageContainerException, ExecutionException, InterruptedException, - NoSuchAlgorithmException { - Logger log = LoggerFactory.getLogger(ChunkManagerImpl.class); - - if (!chunkFile.exists()) { - log.error("Unable to find the chunk file. chunk info : {}", - data.toString()); - throw new StorageContainerException("Unable to find the chunk file. " + - "chunk info " + - data.toString(), UNABLE_TO_FIND_CHUNK); - } - - AsynchronousFileChannel file = null; - FileLock lock = null; - try { - long readStartTime = Time.monotonicNow(); - file = - AsynchronousFileChannel.open(chunkFile.toPath(), - StandardOpenOption.READ); - lock = file.lock(data.getOffset(), data.getLen(), true).get(); - - ByteBuffer buf = ByteBuffer.allocate((int) data.getLen()); - file.read(buf, data.getOffset()).get(); - - // Increment volumeIO stats here. - volumeIOStats.incReadTime(Time.monotonicNow() - readStartTime); - volumeIOStats.incReadOpCount(); - volumeIOStats.incReadBytes(data.getLen()); - if (data.getChecksum() != null && !data.getChecksum().isEmpty()) { - verifyChecksum(data, buf.array(), log); - } - return buf; - } catch (IOException e) { - throw new StorageContainerException(e, IO_EXCEPTION); - } finally { - if (lock != null) { - try { - lock.release(); - } catch (IOException e) { - log.error("I/O error is lock release."); - } - } - if (file != null) { - IOUtils.closeStream(file); - } - } - } - - /** - * Verifies the checksum of a chunk against the data buffer. - * - * @param chunkInfo - Chunk Info. - * @param data - data buffer - * @param log - log - * @throws NoSuchAlgorithmException - * @throws StorageContainerException - */ - private static void verifyChecksum(ChunkInfo chunkInfo, byte[] data, Logger - log) throws NoSuchAlgorithmException, StorageContainerException { - MessageDigest sha = MessageDigest.getInstance(OzoneConsts.FILE_HASH); - sha.update(data); - if (!Hex.encodeHexString(sha.digest()).equals( - chunkInfo.getChecksum())) { - log.error("Checksum mismatch. Provided: {} , computed: {}", - chunkInfo.getChecksum(), DigestUtils.sha256Hex(sha.digest())); - throw new StorageContainerException("Checksum mismatch. Provided: " + - chunkInfo.getChecksum() + " , computed: " + - DigestUtils.sha256Hex(sha.digest()), CHECKSUM_MISMATCH); - } - } - - /** - * Validates chunk data and returns a file object to Chunk File that we are - * expected to write data to. - * - * @param chunkFile - chunkFile to write data into. - * @param info - chunk info. - * @return boolean isOverwrite - * @throws StorageContainerException - */ - public static boolean validateChunkForOverwrite(File chunkFile, - ChunkInfo info) throws StorageContainerException { - - Logger log = LoggerFactory.getLogger(ChunkManagerImpl.class); - - if (isOverWriteRequested(chunkFile, info)) { - if (!isOverWritePermitted(info)) { - log.error("Rejecting write chunk request. Chunk overwrite " + - "without explicit request. {}", info.toString()); - throw new StorageContainerException("Rejecting write chunk request. " + - "OverWrite flag required." + info.toString(), - OVERWRITE_FLAG_REQUIRED); - } - return true; - } - return false; - } - - /** - * Validates that Path to chunk file exists. - * - * @param containerData - Container Data - * @param info - Chunk info - * @return - File. - * @throws StorageContainerException - */ - public static File getChunkFile(KeyValueContainerData containerData, - ChunkInfo info) throws - StorageContainerException { - - Preconditions.checkNotNull(containerData, "Container data can't be null"); - Logger log = LoggerFactory.getLogger(ChunkManagerImpl.class); - - String chunksPath = containerData.getChunksPath(); - if (chunksPath == null) { - log.error("Chunks path is null in the container data"); - throw new StorageContainerException("Unable to get Chunks directory.", - UNABLE_TO_FIND_DATA_DIR); - } - File chunksLoc = new File(chunksPath); - if (!chunksLoc.exists()) { - log.error("Chunks path does not exist"); - throw new StorageContainerException("Unable to get Chunks directory.", - UNABLE_TO_FIND_DATA_DIR); - } - - return chunksLoc.toPath().resolve(info.getChunkName()).toFile(); - } - - /** - * Checks if we are getting a request to overwrite an existing range of - * chunk. - * - * @param chunkFile - File - * @param chunkInfo - Buffer to write - * @return bool - */ - public static boolean isOverWriteRequested(File chunkFile, ChunkInfo - chunkInfo) { - - if (!chunkFile.exists()) { - return false; - } - - long offset = chunkInfo.getOffset(); - return offset < chunkFile.length(); - } - - /** - * Overwrite is permitted if an only if the user explicitly asks for it. We - * permit this iff the key/value pair contains a flag called - * [OverWriteRequested, true]. - * - * @param chunkInfo - Chunk info - * @return true if the user asks for it. - */ - public static boolean isOverWritePermitted(ChunkInfo chunkInfo) { - String overWrite = chunkInfo.getMetadata().get(OzoneConsts.CHUNK_OVERWRITE); - return (overWrite != null) && - (!overWrite.isEmpty()) && - (Boolean.valueOf(overWrite)); - } - - /** - * Returns a CreateContainer Response. This call is used by create and delete - * containers which have null success responses. - * - * @param msg Request - * @return Response. - */ - public static ContainerCommandResponseProto getChunkResponseSuccess( - ContainerCommandRequestProto msg) { - return ContainerUtils.getSuccessResponse(msg); - } - - /** - * Gets a response to the read chunk calls. - * - * @param msg - Msg - * @param data - Data - * @param info - Info - * @return Response. - */ - public static ContainerCommandResponseProto getReadChunkResponse( - ContainerCommandRequestProto msg, byte[] data, ChunkInfo info) { - Preconditions.checkNotNull(msg); - Preconditions.checkNotNull(data, "Chunk data is null"); - Preconditions.checkNotNull(info, "Chunk Info is null"); - - ReadChunkResponseProto.Builder response = - ReadChunkResponseProto.newBuilder(); - response.setChunkData(info.getProtoBufMessage()); - response.setData(ByteString.copyFrom(data)); - response.setBlockID(msg.getReadChunk().getBlockID()); - - ContainerCommandResponseProto.Builder builder = - ContainerUtils.getSuccessResponseBuilder(msg); - builder.setReadChunk(response); - return builder.build(); - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/helpers/KeyValueContainerLocationUtil.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/helpers/KeyValueContainerLocationUtil.java deleted file mode 100644 index 0a81ed8449e..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/helpers/KeyValueContainerLocationUtil.java +++ /dev/null @@ -1,109 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.keyvalue.helpers; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.common.Storage; - -import java.io.File; - -/** - * Class which provides utility methods for container locations. - */ -public final class KeyValueContainerLocationUtil { - - /* Never constructed. */ - private KeyValueContainerLocationUtil() { - - } - /** - * Returns Container Metadata Location. - * @param hddsVolumeDir base dir of the hdds volume where scm directories - * are stored - * @param scmId - * @param containerId - * @return containerMetadata Path to container metadata location where - * .container file will be stored. - */ - public static File getContainerMetaDataPath(String hddsVolumeDir, String scmId, - long containerId) { - String containerMetaDataPath = getBaseContainerLocation(hddsVolumeDir, scmId, - containerId); - containerMetaDataPath = containerMetaDataPath + File.separator + - OzoneConsts.CONTAINER_META_PATH; - return new File(containerMetaDataPath); - } - - - /** - * Returns Container Chunks Location. - * @param baseDir - * @param scmId - * @param containerId - * @return chunksPath - */ - public static File getChunksLocationPath(String baseDir, String scmId, - long containerId) { - String chunksPath = getBaseContainerLocation(baseDir, scmId, containerId) - + File.separator + OzoneConsts.STORAGE_DIR_CHUNKS; - return new File(chunksPath); - } - - /** - * Returns base directory for specified container. - * @param hddsVolumeDir - * @param scmId - * @param containerId - * @return base directory for container. - */ - private static String getBaseContainerLocation(String hddsVolumeDir, String scmId, - long containerId) { - Preconditions.checkNotNull(hddsVolumeDir, "Base Directory cannot be null"); - Preconditions.checkNotNull(scmId, "scmUuid cannot be null"); - Preconditions.checkState(containerId >= 0, - "Container Id cannot be negative."); - - String containerSubDirectory = getContainerSubDirectory(containerId); - - String containerMetaDataPath = hddsVolumeDir + File.separator + scmId + - File.separator + Storage.STORAGE_DIR_CURRENT + File.separator + - containerSubDirectory + File.separator + containerId; - - return containerMetaDataPath; - } - - /** - * Returns subdirectory, where this container needs to be placed. - * @param containerId - * @return container sub directory - */ - private static String getContainerSubDirectory(long containerId){ - int directory = (int) ((containerId >> 9) & 0xFF); - return Storage.CONTAINER_DIR + directory; - } - - /** - * Return containerDB File. - */ - public static File getContainerDBFile(File containerMetaDataPath, - long containerID) { - return new File(containerMetaDataPath, containerID + OzoneConsts - .DN_CONTAINER_DB); - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/helpers/KeyValueContainerUtil.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/helpers/KeyValueContainerUtil.java deleted file mode 100644 index 4f2b3a2a919..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/helpers/KeyValueContainerUtil.java +++ /dev/null @@ -1,226 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.keyvalue.helpers; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.List; -import java.util.Map; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandRequestProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandResponseProto; -import org.apache.hadoop.ozone.container.common.helpers.ContainerUtils; -import org.apache.hadoop.ozone.container.common.helpers.BlockData; -import org.apache.hadoop.ozone.container.keyvalue.KeyValueContainerData; -import org.apache.hadoop.utils.MetadataKeyFilters; -import org.apache.hadoop.utils.MetadataStore; -import org.apache.hadoop.utils.MetadataStoreBuilder; - -import com.google.common.base.Preconditions; -import org.apache.commons.io.FileUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Class which defines utility methods for KeyValueContainer. - */ - -public final class KeyValueContainerUtil { - - /* Never constructed. */ - private KeyValueContainerUtil() { - - } - - private static final Logger LOG = LoggerFactory.getLogger( - KeyValueContainerUtil.class); - - /** - * creates metadata path, chunks path and metadata DB for the specified - * container. - * - * @param containerMetaDataPath - * @throws IOException - */ - public static void createContainerMetaData(File containerMetaDataPath, File - chunksPath, File dbFile, Configuration conf) throws IOException { - Preconditions.checkNotNull(containerMetaDataPath); - Preconditions.checkNotNull(conf); - - if (!containerMetaDataPath.mkdirs()) { - LOG.error("Unable to create directory for metadata storage. Path: {}", - containerMetaDataPath); - throw new IOException("Unable to create directory for metadata storage." + - " Path: " + containerMetaDataPath); - } - MetadataStore store = MetadataStoreBuilder.newBuilder().setConf(conf) - .setCreateIfMissing(true).setDbFile(dbFile).build(); - - // we close since the SCM pre-creates containers. - // we will open and put Db handle into a cache when keys are being created - // in a container. - - store.close(); - - if (!chunksPath.mkdirs()) { - LOG.error("Unable to create chunks directory Container {}", - chunksPath); - //clean up container metadata path and metadata db - FileUtils.deleteDirectory(containerMetaDataPath); - FileUtils.deleteDirectory(containerMetaDataPath.getParentFile()); - throw new IOException("Unable to create directory for data storage." + - " Path: " + chunksPath); - } - } - - /** - * remove Container if it is empty. - *

- * There are three things we need to delete. - *

- * 1. Container file and metadata file. 2. The Level DB file 3. The path that - * we created on the data location. - * - * @param containerData - Data of the container to remove. - * @param conf - configuration of the cluster. - * @param forceDelete - whether this container should be deleted forcibly. - * @throws IOException - */ - public static void removeContainer(KeyValueContainerData containerData, - Configuration conf, boolean forceDelete) - throws IOException { - Preconditions.checkNotNull(containerData); - File containerMetaDataPath = new File(containerData - .getMetadataPath()); - File chunksPath = new File(containerData.getChunksPath()); - - // Close the DB connection and remove the DB handler from cache - BlockUtils.removeDB(containerData, conf); - - // Delete the Container MetaData path. - FileUtils.deleteDirectory(containerMetaDataPath); - - //Delete the Container Chunks Path. - FileUtils.deleteDirectory(chunksPath); - - //Delete Container directory - FileUtils.deleteDirectory(containerMetaDataPath.getParentFile()); - } - - /** - * Returns a ReadContainer Response. - * - * @param request Request - * @param containerData - data - * @return Response. - */ - public static ContainerCommandResponseProto getReadContainerResponse( - ContainerCommandRequestProto request, - KeyValueContainerData containerData) { - Preconditions.checkNotNull(containerData); - - ContainerProtos.ReadContainerResponseProto.Builder response = - ContainerProtos.ReadContainerResponseProto.newBuilder(); - response.setContainerData(containerData.getProtoBufMessage()); - - ContainerCommandResponseProto.Builder builder = - ContainerUtils.getSuccessResponseBuilder(request); - builder.setReadContainer(response); - return builder.build(); - } - - /** - * Parse KeyValueContainerData and verify checksum. - * @param kvContainerData - * @param config - * @throws IOException - */ - public static void parseKVContainerData(KeyValueContainerData kvContainerData, - Configuration config) throws IOException { - - long containerID = kvContainerData.getContainerID(); - File metadataPath = new File(kvContainerData.getMetadataPath()); - - // Verify Checksum - ContainerUtils.verifyChecksum(kvContainerData); - - File dbFile = KeyValueContainerLocationUtil.getContainerDBFile( - metadataPath, containerID); - if (!dbFile.exists()) { - LOG.error("Container DB file is missing for ContainerID {}. " + - "Skipping loading of this container.", containerID); - // Don't further process this container, as it is missing db file. - return; - } - kvContainerData.setDbFile(dbFile); - - MetadataStore metadata = BlockUtils.getDB(kvContainerData, config); - long bytesUsed = 0; - List> liveKeys = metadata - .getRangeKVs(null, Integer.MAX_VALUE, - MetadataKeyFilters.getNormalKeyFilter()); - bytesUsed = liveKeys.parallelStream().mapToLong(e-> { - BlockData blockData; - try { - blockData = BlockUtils.getBlockData(e.getValue()); - return blockData.getSize(); - } catch (IOException ex) { - return 0L; - } - }).sum(); - kvContainerData.setBytesUsed(bytesUsed); - kvContainerData.setKeyCount(liveKeys.size()); - } - - /** - * Returns the path where data or chunks live for a given container. - * - * @param kvContainerData - KeyValueContainerData - * @return - Path to the chunks directory - */ - public static Path getDataDirectory(KeyValueContainerData kvContainerData) { - - String chunksPath = kvContainerData.getChunksPath(); - Preconditions.checkNotNull(chunksPath); - - return Paths.get(chunksPath); - } - - /** - * Container metadata directory -- here is where the level DB and - * .container file lives. - * - * @param kvContainerData - KeyValueContainerData - * @return Path to the metadata directory - */ - public static Path getMetadataDirectory( - KeyValueContainerData kvContainerData) { - - String metadataPath = kvContainerData.getMetadataPath(); - Preconditions.checkNotNull(metadataPath); - - return Paths.get(metadataPath); - - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/helpers/SmallFileUtils.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/helpers/SmallFileUtils.java deleted file mode 100644 index 34953633aa1..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/helpers/SmallFileUtils.java +++ /dev/null @@ -1,84 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.keyvalue.helpers; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.ozone.container.common.helpers.ChunkInfo; -import org.apache.hadoop.ozone.container.common.helpers.ContainerUtils; -import org.apache.ratis.shaded.com.google.protobuf.ByteString; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandRequestProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandResponseProto; - -/** - * File Utils are helper routines used by putSmallFile and getSmallFile - * RPCs. - */ -public final class SmallFileUtils { - /** - * Never Constructed. - */ - private SmallFileUtils() { - } - - /** - * Gets a response for the putSmallFile RPC. - * @param msg - ContainerCommandRequestProto - * @return - ContainerCommandResponseProto - */ - public static ContainerCommandResponseProto getPutFileResponseSuccess( - ContainerCommandRequestProto msg) { - ContainerProtos.PutSmallFileResponseProto.Builder getResponse = - ContainerProtos.PutSmallFileResponseProto.newBuilder(); - ContainerCommandResponseProto.Builder builder = - ContainerUtils.getSuccessResponseBuilder(msg); - builder.setCmdType(ContainerProtos.Type.PutSmallFile); - builder.setPutSmallFile(getResponse); - return builder.build(); - } - - /** - * Gets a response to the read small file call. - * @param msg - Msg - * @param data - Data - * @param info - Info - * @return Response. - */ - public static ContainerCommandResponseProto getGetSmallFileResponseSuccess( - ContainerCommandRequestProto msg, byte[] data, ChunkInfo info) { - Preconditions.checkNotNull(msg); - - ContainerProtos.ReadChunkResponseProto.Builder readChunkresponse = - ContainerProtos.ReadChunkResponseProto.newBuilder(); - readChunkresponse.setChunkData(info.getProtoBufMessage()); - readChunkresponse.setData(ByteString.copyFrom(data)); - readChunkresponse.setBlockID(msg.getGetSmallFile().getBlock().getBlockID()); - - ContainerProtos.GetSmallFileResponseProto.Builder getSmallFile = - ContainerProtos.GetSmallFileResponseProto.newBuilder(); - getSmallFile.setData(readChunkresponse.build()); - ContainerCommandResponseProto.Builder builder = - ContainerUtils.getSuccessResponseBuilder(msg); - builder.setCmdType(ContainerProtos.Type.GetSmallFile); - builder.setGetSmallFile(getSmallFile); - return builder.build(); - } - -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/helpers/package-info.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/helpers/package-info.java deleted file mode 100644 index 041f485deae..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/helpers/package-info.java +++ /dev/null @@ -1,21 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.keyvalue.helpers; -/** - This package contains utility classes for KeyValue container type. - **/ \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/impl/BlockManagerImpl.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/impl/BlockManagerImpl.java deleted file mode 100644 index 54c15fb268d..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/impl/BlockManagerImpl.java +++ /dev/null @@ -1,229 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.keyvalue.impl; - -import com.google.common.base.Preconditions; -import com.google.common.primitives.Longs; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.client.BlockID; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdds.scm.container.common.helpers.StorageContainerException; - -import org.apache.hadoop.ozone.container.common.helpers.BlockData; -import org.apache.hadoop.ozone.container.keyvalue.KeyValueContainerData; -import org.apache.hadoop.ozone.container.keyvalue.helpers.BlockUtils; -import org.apache.hadoop.ozone.container.common.interfaces.Container; -import org.apache.hadoop.ozone.container.keyvalue.interfaces.BlockManager; -import org.apache.hadoop.ozone.container.common.utils.ContainerCache; -import org.apache.hadoop.utils.MetadataStore; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.Result.NO_SUCH_BLOCK; - -/** - * This class is for performing block related operations on the KeyValue - * Container. - */ -public class BlockManagerImpl implements BlockManager { - - static final Logger LOG = LoggerFactory.getLogger(BlockManagerImpl.class); - - private Configuration config; - - /** - * Constructs a Block Manager. - * - * @param conf - Ozone configuration - */ - public BlockManagerImpl(Configuration conf) { - Preconditions.checkNotNull(conf, "Config cannot be null"); - this.config = conf; - } - - /** - * Puts or overwrites a block. - * - * @param container - Container for which block need to be added. - * @param data - BlockData. - * @return length of the block. - * @throws IOException - */ - public long putBlock(Container container, BlockData data) throws IOException { - Preconditions.checkNotNull(data, "BlockData cannot be null for put " + - "operation."); - Preconditions.checkState(data.getContainerID() >= 0, "Container Id " + - "cannot be negative"); - // We are not locking the key manager since LevelDb serializes all actions - // against a single DB. We rely on DB level locking to avoid conflicts. - MetadataStore db = BlockUtils.getDB((KeyValueContainerData) container - .getContainerData(), config); - - // This is a post condition that acts as a hint to the user. - // Should never fail. - Preconditions.checkNotNull(db, "DB cannot be null here"); - db.put(Longs.toByteArray(data.getLocalID()), data.getProtoBufMessage() - .toByteArray()); - - // Increment keycount here - container.getContainerData().incrKeyCount(); - return data.getSize(); - } - - /** - * Gets an existing block. - * - * @param container - Container from which block need to be fetched. - * @param blockID - BlockID of the block. - * @return Key Data. - * @throws IOException - */ - public BlockData getBlock(Container container, BlockID blockID) - throws IOException { - Preconditions.checkNotNull(blockID, - "BlockID cannot be null in GetBlock request"); - Preconditions.checkNotNull(blockID.getContainerID(), - "Container name cannot be null"); - - KeyValueContainerData containerData = (KeyValueContainerData) container - .getContainerData(); - MetadataStore db = BlockUtils.getDB(containerData, config); - // This is a post condition that acts as a hint to the user. - // Should never fail. - Preconditions.checkNotNull(db, "DB cannot be null here"); - byte[] kData = db.get(Longs.toByteArray(blockID.getLocalID())); - if (kData == null) { - throw new StorageContainerException("Unable to find the block.", - NO_SUCH_BLOCK); - } - ContainerProtos.BlockData blockData = - ContainerProtos.BlockData.parseFrom(kData); - return BlockData.getFromProtoBuf(blockData); - } - - /** - * Returns the length of the committed block. - * - * @param container - Container from which block need to be fetched. - * @param blockID - BlockID of the block. - * @return length of the block. - * @throws IOException in case, the block key does not exist in db. - */ - @Override - public long getCommittedBlockLength(Container container, BlockID blockID) - throws IOException { - KeyValueContainerData containerData = (KeyValueContainerData) container - .getContainerData(); - MetadataStore db = BlockUtils.getDB(containerData, config); - // This is a post condition that acts as a hint to the user. - // Should never fail. - Preconditions.checkNotNull(db, "DB cannot be null here"); - byte[] kData = db.get(Longs.toByteArray(blockID.getLocalID())); - if (kData == null) { - throw new StorageContainerException("Unable to find the block.", - NO_SUCH_BLOCK); - } - ContainerProtos.BlockData blockData = - ContainerProtos.BlockData.parseFrom(kData); - return blockData.getSize(); - } - - /** - * Deletes an existing block. - * - * @param container - Container from which block need to be deleted. - * @param blockID - ID of the block. - * @throws StorageContainerException - */ - public void deleteBlock(Container container, BlockID blockID) throws - IOException { - Preconditions.checkNotNull(blockID, "block ID cannot be null."); - Preconditions.checkState(blockID.getContainerID() >= 0, - "Container ID cannot be negative."); - Preconditions.checkState(blockID.getLocalID() >= 0, - "Local ID cannot be negative."); - - KeyValueContainerData cData = (KeyValueContainerData) container - .getContainerData(); - MetadataStore db = BlockUtils.getDB(cData, config); - // This is a post condition that acts as a hint to the user. - // Should never fail. - Preconditions.checkNotNull(db, "DB cannot be null here"); - // Note : There is a race condition here, since get and delete - // are not atomic. Leaving it here since the impact is refusing - // to delete a Block which might have just gotten inserted after - // the get check. - byte[] kKey = Longs.toByteArray(blockID.getLocalID()); - byte[] kData = db.get(kKey); - if (kData == null) { - throw new StorageContainerException("Unable to find the block.", - NO_SUCH_BLOCK); - } - db.delete(kKey); - - // Decrement blockcount here - container.getContainerData().decrKeyCount(); - } - - /** - * List blocks in a container. - * - * @param container - Container from which blocks need to be listed. - * @param startLocalID - Key to start from, 0 to begin. - * @param count - Number of blocks to return. - * @return List of Blocks that match the criteria. - */ - @Override - public List listBlock(Container container, long startLocalID, int - count) throws IOException { - Preconditions.checkNotNull(container, "container cannot be null"); - Preconditions.checkState(startLocalID >= 0, "startLocal ID cannot be " + - "negative"); - Preconditions.checkArgument(count > 0, - "Count must be a positive number."); - container.readLock(); - List result = null; - KeyValueContainerData cData = (KeyValueContainerData) container - .getContainerData(); - MetadataStore db = BlockUtils.getDB(cData, config); - result = new ArrayList<>(); - byte[] startKeyInBytes = Longs.toByteArray(startLocalID); - List> range = db.getSequentialRangeKVs( - startKeyInBytes, count, null); - for (Map.Entry entry : range) { - BlockData value = BlockUtils.getBlockData(entry.getValue()); - BlockData data = new BlockData(value.getBlockID()); - result.add(data); - } - return result; - } - - /** - * Shutdown KeyValueContainerManager. - */ - public void shutdown() { - BlockUtils.shutdownCache(ContainerCache.getInstance(config)); - } - -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/impl/ChunkManagerImpl.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/impl/ChunkManagerImpl.java deleted file mode 100644 index ce317bd3edc..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/impl/ChunkManagerImpl.java +++ /dev/null @@ -1,254 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.keyvalue.impl; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.fs.FileUtil; -import org.apache.hadoop.hdds.client.BlockID; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdds.scm.container.common.helpers.StorageContainerException; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.container.common.helpers.ChunkInfo; -import org.apache.hadoop.ozone.container.keyvalue.KeyValueContainerData; -import org.apache.hadoop.ozone.container.common.volume.HddsVolume; -import org.apache.hadoop.ozone.container.common.volume.VolumeIOStats; -import org.apache.hadoop.ozone.container.keyvalue.helpers.ChunkUtils; -import org.apache.hadoop.ozone.container.common.impl.ChunkLayOutVersion; -import org.apache.hadoop.ozone.container.keyvalue.interfaces.ChunkManager; -import org.apache.hadoop.ozone.container.common.interfaces.Container; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; -import java.security.NoSuchAlgorithmException; -import java.util.concurrent.ExecutionException; - -import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .Result.CONTAINER_INTERNAL_ERROR; -import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .Result.NO_SUCH_ALGORITHM; -import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.Result.UNSUPPORTED_REQUEST; - -/** - * This class is for performing chunk related operations. - */ -public class ChunkManagerImpl implements ChunkManager { - static final Logger LOG = LoggerFactory.getLogger(ChunkManagerImpl.class); - - /** - * writes a given chunk. - * - * @param container - Container for the chunk - * @param blockID - ID of the block - * @param info - ChunkInfo - * @param data - data of the chunk - * @param stage - Stage of the Chunk operation - * @throws StorageContainerException - */ - public void writeChunk(Container container, BlockID blockID, ChunkInfo info, - byte[] data, ContainerProtos.Stage stage) - throws StorageContainerException { - - try { - - KeyValueContainerData containerData = (KeyValueContainerData) container - .getContainerData(); - HddsVolume volume = containerData.getVolume(); - VolumeIOStats volumeIOStats = volume.getVolumeIOStats(); - - File chunkFile = ChunkUtils.getChunkFile(containerData, info); - - boolean isOverwrite = ChunkUtils.validateChunkForOverwrite( - chunkFile, info); - File tmpChunkFile = getTmpChunkFile(chunkFile, info); - - LOG.debug("writing chunk:{} chunk stage:{} chunk file:{} tmp chunk file", - info.getChunkName(), stage, chunkFile, tmpChunkFile); - - switch (stage) { - case WRITE_DATA: - // Initially writes to temporary chunk file. - ChunkUtils.writeData(tmpChunkFile, info, data, volumeIOStats); - // No need to increment container stats here, as still data is not - // committed here. - break; - case COMMIT_DATA: - // commit the data, means move chunk data from temporary chunk file - // to actual chunk file. - commitChunk(tmpChunkFile, chunkFile); - // Increment container stats here, as we commit the data. - containerData.incrBytesUsed(info.getLen()); - containerData.incrWriteCount(); - containerData.incrWriteBytes(info.getLen()); - break; - case COMBINED: - // directly write to the chunk file - ChunkUtils.writeData(chunkFile, info, data, volumeIOStats); - if (!isOverwrite) { - containerData.incrBytesUsed(info.getLen()); - } - containerData.incrWriteCount(); - containerData.incrWriteBytes(info.getLen()); - break; - default: - throw new IOException("Can not identify write operation."); - } - } catch (StorageContainerException ex) { - throw ex; - } catch (NoSuchAlgorithmException ex) { - LOG.error("write data failed. error: {}", ex); - throw new StorageContainerException("Internal error: ", ex, - NO_SUCH_ALGORITHM); - } catch (ExecutionException | IOException ex) { - LOG.error("write data failed. error: {}", ex); - throw new StorageContainerException("Internal error: ", ex, - CONTAINER_INTERNAL_ERROR); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - LOG.error("write data failed. error: {}", e); - throw new StorageContainerException("Internal error: ", e, - CONTAINER_INTERNAL_ERROR); - } - } - - /** - * reads the data defined by a chunk. - * - * @param container - Container for the chunk - * @param blockID - ID of the block. - * @param info - ChunkInfo. - * @return byte array - * @throws StorageContainerException - * TODO: Right now we do not support partial reads and writes of chunks. - * TODO: Explore if we need to do that for ozone. - */ - public byte[] readChunk(Container container, BlockID blockID, ChunkInfo info) - throws StorageContainerException { - try { - KeyValueContainerData containerData = (KeyValueContainerData) container - .getContainerData(); - ByteBuffer data; - HddsVolume volume = containerData.getVolume(); - VolumeIOStats volumeIOStats = volume.getVolumeIOStats(); - - // Checking here, which layout version the container is, and reading - // the chunk file in that format. - // In version1, we verify checksum if it is available and return data - // of the chunk file. - if (containerData.getLayOutVersion() == ChunkLayOutVersion - .getLatestVersion().getVersion()) { - File chunkFile = ChunkUtils.getChunkFile(containerData, info); - data = ChunkUtils.readData(chunkFile, info, volumeIOStats); - containerData.incrReadCount(); - long length = chunkFile.length(); - containerData.incrReadBytes(length); - return data.array(); - } - } catch(NoSuchAlgorithmException ex) { - LOG.error("read data failed. error: {}", ex); - throw new StorageContainerException("Internal error: ", - ex, NO_SUCH_ALGORITHM); - } catch (ExecutionException ex) { - LOG.error("read data failed. error: {}", ex); - throw new StorageContainerException("Internal error: ", - ex, CONTAINER_INTERNAL_ERROR); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - LOG.error("read data failed. error: {}", e); - throw new StorageContainerException("Internal error: ", - e, CONTAINER_INTERNAL_ERROR); - } - return null; - } - - /** - * Deletes a given chunk. - * - * @param container - Container for the chunk - * @param blockID - ID of the block - * @param info - Chunk Info - * @throws StorageContainerException - */ - public void deleteChunk(Container container, BlockID blockID, ChunkInfo info) - throws StorageContainerException { - Preconditions.checkNotNull(blockID, "Block ID cannot be null."); - KeyValueContainerData containerData = (KeyValueContainerData) container - .getContainerData(); - // Checking here, which layout version the container is, and performing - // deleting chunk operation. - // In version1, we have only chunk file. - if (containerData.getLayOutVersion() == ChunkLayOutVersion - .getLatestVersion().getVersion()) { - File chunkFile = ChunkUtils.getChunkFile(containerData, info); - if ((info.getOffset() == 0) && (info.getLen() == chunkFile.length())) { - FileUtil.fullyDelete(chunkFile); - containerData.decrBytesUsed(chunkFile.length()); - } else { - LOG.error("Not Supported Operation. Trying to delete a " + - "chunk that is in shared file. chunk info : " + info.toString()); - throw new StorageContainerException("Not Supported Operation. " + - "Trying to delete a chunk that is in shared file. chunk info : " - + info.toString(), UNSUPPORTED_REQUEST); - } - } - } - - /** - * Shutdown the chunkManager. - * - * In the chunkManager we haven't acquired any resources, so nothing to do - * here. - */ - - public void shutdown() { - //TODO: need to revisit this during integration of container IO. - } - - /** - * Returns the temporary chunkFile path. - * @param chunkFile - * @param info - * @return temporary chunkFile path - * @throws StorageContainerException - */ - private File getTmpChunkFile(File chunkFile, ChunkInfo info) - throws StorageContainerException { - return new File(chunkFile.getParent(), - chunkFile.getName() + - OzoneConsts.CONTAINER_CHUNK_NAME_DELIMITER + - OzoneConsts.CONTAINER_TEMPORARY_CHUNK_PREFIX); - } - - /** - * Commit the chunk by renaming the temporary chunk file to chunk file. - * @param tmpChunkFile - * @param chunkFile - * @throws IOException - */ - private void commitChunk(File tmpChunkFile, File chunkFile) throws - IOException { - Files.move(tmpChunkFile.toPath(), chunkFile.toPath(), - StandardCopyOption.REPLACE_EXISTING); - } - -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/impl/package-info.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/impl/package-info.java deleted file mode 100644 index 564b50e8a4d..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/impl/package-info.java +++ /dev/null @@ -1,21 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.keyvalue.impl; -/** - * Chunk manager and block manager implementations for keyvalue container type. - */ diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/interfaces/BlockManager.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/interfaces/BlockManager.java deleted file mode 100644 index 35ed22a6c4d..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/interfaces/BlockManager.java +++ /dev/null @@ -1,84 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.container.keyvalue.interfaces; - -import org.apache.hadoop.hdds.client.BlockID; -import org.apache.hadoop.hdds.scm.container.common.helpers.StorageContainerException; -import org.apache.hadoop.ozone.container.common.helpers.BlockData; -import org.apache.hadoop.ozone.container.common.interfaces.Container; - -import java.io.IOException; -import java.util.List; - -/** - * BlockManager is for performing key related operations on the container. - */ -public interface BlockManager { - - /** - * Puts or overwrites a block. - * - * @param container - Container for which block need to be added. - * @param data - Block Data. - * @return length of the Block. - * @throws IOException - */ - long putBlock(Container container, BlockData data) throws IOException; - - /** - * Gets an existing block. - * - * @param container - Container from which block need to be get. - * @param blockID - BlockID of the Block. - * @return Block Data. - * @throws IOException - */ - BlockData getBlock(Container container, BlockID blockID) throws IOException; - - /** - * Deletes an existing block. - * - * @param container - Container from which block need to be deleted. - * @param blockID - ID of the block. - * @throws StorageContainerException - */ - void deleteBlock(Container container, BlockID blockID) throws IOException; - - /** - * List blocks in a container. - * - * @param container - Container from which blocks need to be listed. - * @param startLocalID - Block to start from, 0 to begin. - * @param count - Number of blocks to return. - * @return List of Blocks that match the criteria. - */ - List listBlock(Container container, long startLocalID, int count) - throws IOException; - - /** - * Returns the last committed block length for the block. - * @param blockID blockId - */ - long getCommittedBlockLength(Container container, BlockID blockID) - throws IOException; - - /** - * Shutdown ContainerManager. - */ - void shutdown(); -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/interfaces/ChunkManager.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/interfaces/ChunkManager.java deleted file mode 100644 index 7134be1d34d..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/interfaces/ChunkManager.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.apache.hadoop.ozone.container.keyvalue.interfaces; - -/* - * 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. - */ - -import org.apache.hadoop.hdds.client.BlockID; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdds.scm.container.common.helpers.StorageContainerException; -import org.apache.hadoop.ozone.container.common.helpers.ChunkInfo; -import org.apache.hadoop.ozone.container.common.interfaces.Container; - -/** - * Chunk Manager allows read, write, delete and listing of chunks in - * a container. - */ - -public interface ChunkManager { - - /** - * writes a given chunk. - * - * @param container - Container for the chunk - * @param blockID - ID of the block. - * @param info - ChunkInfo. - * @param stage - Chunk Stage write. - * @throws StorageContainerException - */ - void writeChunk(Container container, BlockID blockID, ChunkInfo info, - byte[] data, ContainerProtos.Stage stage) - throws StorageContainerException; - - /** - * reads the data defined by a chunk. - * - * @param container - Container for the chunk - * @param blockID - ID of the block. - * @param info - ChunkInfo. - * @return byte array - * @throws StorageContainerException - * - * TODO: Right now we do not support partial reads and writes of chunks. - * TODO: Explore if we need to do that for ozone. - */ - byte[] readChunk(Container container, BlockID blockID, ChunkInfo info) throws - StorageContainerException; - - /** - * Deletes a given chunk. - * - * @param container - Container for the chunk - * @param blockID - ID of the block. - * @param info - Chunk Info - * @throws StorageContainerException - */ - void deleteChunk(Container container, BlockID blockID, ChunkInfo info) throws - StorageContainerException; - - // TODO : Support list operations. - - /** - * Shutdown the chunkManager. - */ - void shutdown(); - -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/interfaces/package-info.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/interfaces/package-info.java deleted file mode 100644 index 512909451f0..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/interfaces/package-info.java +++ /dev/null @@ -1,21 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.keyvalue.interfaces; -/** - * Chunk manager and block manager interfaces for keyvalue container type. - */ diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/package-info.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/package-info.java deleted file mode 100644 index 53c9f1e0f97..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/package-info.java +++ /dev/null @@ -1,21 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.keyvalue; -/** - This package contains classes for KeyValue container type. - **/ \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/statemachine/background/BlockDeletingService.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/statemachine/background/BlockDeletingService.java deleted file mode 100644 index d96fbfacb5d..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/statemachine/background/BlockDeletingService.java +++ /dev/null @@ -1,258 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.container.keyvalue.statemachine.background; - -import com.google.common.collect.Lists; -import org.apache.hadoop.hdds.scm.ScmConfigKeys; -import org.apache.hadoop.ozone.container.common.impl.ContainerData; -import org.apache.hadoop.ozone.container.common.impl.ContainerSet; -import org.apache.hadoop.ozone.container.common.impl.TopNOrderedContainerDeletionChoosingPolicy; -import org.apache.hadoop.ozone.container.common.interfaces.ContainerDeletionChoosingPolicy; -import org.apache.hadoop.ozone.container.keyvalue.KeyValueContainerData; -import org.apache.hadoop.ozone.container.keyvalue.helpers.BlockUtils; -import org.apache.hadoop.util.ReflectionUtils; -import org.apache.ratis.shaded.com.google.protobuf - .InvalidProtocolBufferException; -import org.apache.commons.io.FileUtils; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.scm.container.common.helpers - .StorageContainerException; -import org.apache.hadoop.hdfs.DFSUtil; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.util.Time; -import org.apache.hadoop.utils.BackgroundService; -import org.apache.hadoop.utils.BackgroundTask; -import org.apache.hadoop.utils.BackgroundTaskQueue; -import org.apache.hadoop.utils.BackgroundTaskResult; -import org.apache.hadoop.utils.BatchOperation; -import org.apache.hadoop.utils.MetadataKeyFilters.KeyPrefixFilter; -import org.apache.hadoop.utils.MetadataStore; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -import static org.apache.hadoop.ozone.OzoneConfigKeys - .OZONE_BLOCK_DELETING_CONTAINER_LIMIT_PER_INTERVAL; -import static org.apache.hadoop.ozone.OzoneConfigKeys - .OZONE_BLOCK_DELETING_CONTAINER_LIMIT_PER_INTERVAL_DEFAULT; -import static org.apache.hadoop.ozone.OzoneConfigKeys - .OZONE_BLOCK_DELETING_LIMIT_PER_CONTAINER; -import static org.apache.hadoop.ozone.OzoneConfigKeys - .OZONE_BLOCK_DELETING_LIMIT_PER_CONTAINER_DEFAULT; - -/** - * A per-datanode container block deleting service takes in charge - * of deleting staled ozone blocks. - */ -// TODO: Fix BlockDeletingService to work with new StorageLayer -public class BlockDeletingService extends BackgroundService{ - - private static final Logger LOG = - LoggerFactory.getLogger(BlockDeletingService.class); - - private ContainerSet containerSet; - private ContainerDeletionChoosingPolicy containerDeletionPolicy; - private final Configuration conf; - - // Throttle number of blocks to delete per task, - // set to 1 for testing - private final int blockLimitPerTask; - - // Throttle the number of containers to process concurrently at a time, - private final int containerLimitPerInterval; - - // Task priority is useful when a to-delete block has weight. - private final static int TASK_PRIORITY_DEFAULT = 1; - // Core pool size for container tasks - private final static int BLOCK_DELETING_SERVICE_CORE_POOL_SIZE = 10; - - public BlockDeletingService(ContainerSet containerSet, long serviceInterval, - long serviceTimeout, TimeUnit timeUnit, Configuration conf) { - super("BlockDeletingService", serviceInterval, timeUnit, - BLOCK_DELETING_SERVICE_CORE_POOL_SIZE, serviceTimeout); - this.containerSet = containerSet; - containerDeletionPolicy = ReflectionUtils.newInstance(conf.getClass( - ScmConfigKeys.OZONE_SCM_KEY_VALUE_CONTAINER_DELETION_CHOOSING_POLICY, - TopNOrderedContainerDeletionChoosingPolicy.class, - ContainerDeletionChoosingPolicy.class), conf); - this.conf = conf; - this.blockLimitPerTask = conf.getInt( - OZONE_BLOCK_DELETING_LIMIT_PER_CONTAINER, - OZONE_BLOCK_DELETING_LIMIT_PER_CONTAINER_DEFAULT); - this.containerLimitPerInterval = conf.getInt( - OZONE_BLOCK_DELETING_CONTAINER_LIMIT_PER_INTERVAL, - OZONE_BLOCK_DELETING_CONTAINER_LIMIT_PER_INTERVAL_DEFAULT); - } - - - @Override - public BackgroundTaskQueue getTasks() { - BackgroundTaskQueue queue = new BackgroundTaskQueue(); - List containers = Lists.newArrayList(); - try { - // We at most list a number of containers a time, - // in case there are too many containers and start too many workers. - // We must ensure there is no empty container in this result. - // The chosen result depends on what container deletion policy is - // configured. - containers = containerSet.chooseContainerForBlockDeletion( - containerLimitPerInterval, containerDeletionPolicy); - if (containers.size() > 0) { - LOG.info("Plan to choose {} containers for block deletion, " - + "actually returns {} valid containers.", - containerLimitPerInterval, containers.size()); - } - - for(ContainerData container : containers) { - BlockDeletingTask containerTask = - new BlockDeletingTask(container, TASK_PRIORITY_DEFAULT); - queue.add(containerTask); - } - } catch (StorageContainerException e) { - LOG.warn("Failed to initiate block deleting tasks, " - + "caused by unable to get containers info. " - + "Retry in next interval. ", e); - } catch (Exception e) { - // In case listContainer call throws any uncaught RuntimeException. - if (LOG.isDebugEnabled()) { - LOG.debug("Unexpected error occurs during deleting blocks.", e); - } - } - return queue; - } - - private static class ContainerBackgroundTaskResult - implements BackgroundTaskResult { - private List deletedBlockIds; - - ContainerBackgroundTaskResult() { - deletedBlockIds = new LinkedList<>(); - } - - public void addBlockId(String blockId) { - deletedBlockIds.add(blockId); - } - - public void addAll(List blockIds) { - deletedBlockIds.addAll(blockIds); - } - - public List getDeletedBlocks() { - return deletedBlockIds; - } - - @Override - public int getSize() { - return deletedBlockIds.size(); - } - } - - private class BlockDeletingTask - implements BackgroundTask { - - private final int priority; - private final KeyValueContainerData containerData; - - BlockDeletingTask(ContainerData containerName, int priority) { - this.priority = priority; - this.containerData = (KeyValueContainerData) containerName; - } - - @Override - public BackgroundTaskResult call() throws Exception { - ContainerBackgroundTaskResult crr = new ContainerBackgroundTaskResult(); - long startTime = Time.monotonicNow(); - // Scan container's db and get list of under deletion blocks - MetadataStore meta = BlockUtils.getDB( - (KeyValueContainerData) containerData, conf); - // # of blocks to delete is throttled - KeyPrefixFilter filter = - new KeyPrefixFilter().addFilter(OzoneConsts.DELETING_KEY_PREFIX); - List> toDeleteBlocks = - meta.getSequentialRangeKVs(null, blockLimitPerTask, filter); - if (toDeleteBlocks.isEmpty()) { - LOG.debug("No under deletion block found in container : {}", - containerData.getContainerID()); - } - - List succeedBlocks = new LinkedList<>(); - LOG.debug("Container : {}, To-Delete blocks : {}", - containerData.getContainerID(), toDeleteBlocks.size()); - File dataDir = new File(containerData.getChunksPath()); - if (!dataDir.exists() || !dataDir.isDirectory()) { - LOG.error("Invalid container data dir {} : " - + "does not exist or not a directory", dataDir.getAbsolutePath()); - return crr; - } - - toDeleteBlocks.forEach(entry -> { - String blockName = DFSUtil.bytes2String(entry.getKey()); - LOG.debug("Deleting block {}", blockName); - try { - ContainerProtos.BlockData data = - ContainerProtos.BlockData.parseFrom(entry.getValue()); - for (ContainerProtos.ChunkInfo chunkInfo : data.getChunksList()) { - File chunkFile = dataDir.toPath() - .resolve(chunkInfo.getChunkName()).toFile(); - if (FileUtils.deleteQuietly(chunkFile)) { - LOG.debug("block {} chunk {} deleted", blockName, - chunkFile.getAbsolutePath()); - } - } - succeedBlocks.add(blockName); - } catch (InvalidProtocolBufferException e) { - LOG.error("Failed to parse block info for block {}", blockName, e); - } - }); - - // Once files are deleted... replace deleting entries with deleted entries - BatchOperation batch = new BatchOperation(); - succeedBlocks.forEach(entry -> { - String blockId = - entry.substring(OzoneConsts.DELETING_KEY_PREFIX.length()); - String deletedEntry = OzoneConsts.DELETED_KEY_PREFIX + blockId; - batch.put(DFSUtil.string2Bytes(deletedEntry), - DFSUtil.string2Bytes(blockId)); - batch.delete(DFSUtil.string2Bytes(entry)); - }); - meta.writeBatch(batch); - // update count of pending deletion blocks in in-memory container status - containerData.decrPendingDeletionBlocks(succeedBlocks.size()); - - if (!succeedBlocks.isEmpty()) { - LOG.info("Container: {}, deleted blocks: {}, task elapsed time: {}ms", - containerData.getContainerID(), succeedBlocks.size(), - Time.monotonicNow() - startTime); - } - crr.addAll(succeedBlocks); - return crr; - } - - @Override - public int getPriority() { - return priority; - } - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/statemachine/background/package-info.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/statemachine/background/package-info.java deleted file mode 100644 index 69d80425ab7..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/statemachine/background/package-info.java +++ /dev/null @@ -1,18 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.keyvalue.statemachine.background; \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/ozoneimpl/ContainerReader.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/ozoneimpl/ContainerReader.java deleted file mode 100644 index c3a41262ce0..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/ozoneimpl/ContainerReader.java +++ /dev/null @@ -1,208 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.ozoneimpl; - -import com.google.common.base.Preconditions; -import com.google.common.primitives.Longs; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdds.scm.container.common.helpers - .StorageContainerException; -import org.apache.hadoop.hdfs.DFSUtil; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.common.Storage; -import org.apache.hadoop.ozone.container.common.helpers.ContainerUtils; -import org.apache.hadoop.ozone.container.common.impl.ContainerData; -import org.apache.hadoop.ozone.container.common.impl.ContainerSet; -import org.apache.hadoop.ozone.container.common.volume.HddsVolume; -import org.apache.hadoop.ozone.container.common.volume.VolumeSet; -import org.apache.hadoop.ozone.container.keyvalue.KeyValueContainer; -import org.apache.hadoop.ozone.container.keyvalue.KeyValueContainerData; -import org.apache.hadoop.ozone.container.common.impl.ContainerDataYaml; -import org.apache.hadoop.ozone.container.keyvalue.helpers.BlockUtils; -import org.apache.hadoop.ozone.container.keyvalue.helpers.KeyValueContainerUtil; -import org.apache.hadoop.utils.MetadataKeyFilters; -import org.apache.hadoop.utils.MetadataStore; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.FileFilter; -import java.io.IOException; - -/** - * Class used to read .container files from Volume and build container map. - * - * Layout of the container directory on disk is as follows: - * - * ../hdds/VERSION - * ../hdds/<>/current/<>/</metadata/<>.container - * ../hdds/<>/current/<>/</<> - * - * Some ContainerTypes will have extra metadata other than the .container - * file. For example, KeyValueContainer will have a .db file. This .db file - * will also be stored in the metadata folder along with the .container file. - * - * ../hdds/<>/current/<>/</metadata/<>.db - * - * Note that the <> is dependent on the ContainerType. - * For KeyValueContainers, the data is stored in a "chunks" folder. As such, - * the <> layout for KeyValueContainers is - * - * ../hdds/<>/current/<>/</chunks/<> - * - */ -public class ContainerReader implements Runnable { - - private static final Logger LOG = LoggerFactory.getLogger( - ContainerReader.class); - private HddsVolume hddsVolume; - private final ContainerSet containerSet; - private final OzoneConfiguration config; - private final File hddsVolumeDir; - private final VolumeSet volumeSet; - - ContainerReader(VolumeSet volSet, HddsVolume volume, ContainerSet cset, - OzoneConfiguration conf) { - Preconditions.checkNotNull(volume); - this.hddsVolume = volume; - this.hddsVolumeDir = hddsVolume.getHddsRootDir(); - this.containerSet = cset; - this.config = conf; - this.volumeSet = volSet; - } - - @Override - public void run() { - try { - readVolume(hddsVolumeDir); - } catch (RuntimeException ex) { - LOG.info("Caught an Run time exception during reading container files" + - " from Volume {}", hddsVolumeDir); - } - } - - public void readVolume(File hddsVolumeRootDir) { - Preconditions.checkNotNull(hddsVolumeRootDir, "hddsVolumeRootDir" + - "cannot be null"); - - //filtering scm directory - File[] scmDir = hddsVolumeRootDir.listFiles(new FileFilter() { - @Override - public boolean accept(File pathname) { - return pathname.isDirectory(); - } - }); - - if (scmDir == null) { - LOG.error("IO error for the volume {}, skipped loading", - hddsVolumeRootDir); - volumeSet.failVolume(hddsVolumeRootDir.getPath()); - return; - } - - if (scmDir.length > 1) { - LOG.error("Volume {} is in Inconsistent state", hddsVolumeRootDir); - volumeSet.failVolume(hddsVolumeRootDir.getPath()); - return; - } - - for (File scmLoc : scmDir) { - File currentDir = new File(scmLoc, Storage.STORAGE_DIR_CURRENT); - File[] containerTopDirs = currentDir.listFiles(); - if (containerTopDirs != null) { - for (File containerTopDir : containerTopDirs) { - if (containerTopDir.isDirectory()) { - File[] containerDirs = containerTopDir.listFiles(); - if (containerDirs != null) { - for (File containerDir : containerDirs) { - File containerFile = ContainerUtils.getContainerFile( - containerDir); - long containerID = ContainerUtils.getContainerID(containerDir); - if (containerFile.exists()) { - verifyContainerFile(containerID, containerFile); - } else { - LOG.error("Missing .container file for ContainerID: {}", - containerDir.getName()); - } - } - } - } - } - } - } - } - - private void verifyContainerFile(long containerID, File containerFile) { - try { - ContainerData containerData = ContainerDataYaml.readContainerFile( - containerFile); - if (containerID != containerData.getContainerID()) { - LOG.error("Invalid ContainerID in file {}. " + - "Skipping loading of this container.", containerFile); - return; - } - verifyContainerData(containerData); - } catch (IOException ex) { - LOG.error("Failed to parse ContainerFile for ContainerID: {}", - containerID, ex); - } - } - - public void verifyContainerData(ContainerData containerData) - throws IOException { - switch (containerData.getContainerType()) { - case KeyValueContainer: - if (containerData instanceof KeyValueContainerData) { - KeyValueContainerData kvContainerData = (KeyValueContainerData) - containerData; - containerData.setVolume(hddsVolume); - - KeyValueContainerUtil.parseKVContainerData(kvContainerData, config); - KeyValueContainer kvContainer = new KeyValueContainer( - kvContainerData, config); - MetadataStore containerDB = BlockUtils.getDB(kvContainerData, config); - MetadataKeyFilters.KeyPrefixFilter filter = - new MetadataKeyFilters.KeyPrefixFilter() - .addFilter(OzoneConsts.DELETING_KEY_PREFIX); - int numPendingDeletionBlocks = - containerDB.getSequentialRangeKVs(null, Integer.MAX_VALUE, filter) - .size(); - kvContainerData.incrPendingDeletionBlocks(numPendingDeletionBlocks); - byte[] delTxnId = containerDB.get( - DFSUtil.string2Bytes(OzoneConsts.DELETE_TRANSACTION_KEY_PREFIX)); - if (delTxnId != null) { - kvContainerData - .updateDeleteTransactionId(Longs.fromByteArray(delTxnId)); - } - containerSet.addContainer(kvContainer); - } else { - throw new StorageContainerException("Container File is corrupted. " + - "ContainerType is KeyValueContainer but cast to " + - "KeyValueContainerData failed. ", - ContainerProtos.Result.CONTAINER_METADATA_ERROR); - } - break; - default: - throw new StorageContainerException("Unrecognized ContainerType " + - containerData.getContainerType(), - ContainerProtos.Result.UNKNOWN_CONTAINER_TYPE); - } - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/ozoneimpl/OzoneContainer.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/ozoneimpl/OzoneContainer.java deleted file mode 100644 index 503112dab24..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/ozoneimpl/OzoneContainer.java +++ /dev/null @@ -1,236 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.ozoneimpl; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.PipelineID; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationType; -import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.PipelineReportsProto; -import org.apache.hadoop.ozone.container.common.impl.ContainerSet; -import org.apache.hadoop.ozone.container.common.impl.HddsDispatcher; -import org.apache.hadoop.ozone.container.common.interfaces.ContainerDispatcher; -import org.apache.hadoop.ozone.container.common.statemachine.StateContext; -import org.apache.hadoop.ozone.container.common.transport.server.XceiverServerGrpc; -import org.apache.hadoop.ozone.container.common.transport.server.XceiverServerSpi; -import org.apache.hadoop.ozone.container.common.transport.server.ratis.XceiverServerRatis; -import org.apache.hadoop.ozone.container.common.volume.HddsVolume; -import org.apache.hadoop.ozone.container.common.volume.VolumeSet; - -import org.apache.hadoop.ozone.container.replication.GrpcReplicationService; -import org.apache.hadoop.ozone.container.replication - .OnDemandContainerReplicationSource; -import org.apache.hadoop.util.DiskChecker.DiskOutOfSpaceException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.*; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -import static org.apache.hadoop.ozone.OzoneConsts.INVALID_PORT; - -/** - * Ozone main class sets up the network servers and initializes the container - * layer. - */ -public class OzoneContainer { - - public static final Logger LOG = LoggerFactory.getLogger( - OzoneContainer.class); - - private final HddsDispatcher hddsDispatcher; - private final DatanodeDetails dnDetails; - private final OzoneConfiguration config; - private final VolumeSet volumeSet; - private final ContainerSet containerSet; - private final Map servers; - - /** - * Construct OzoneContainer object. - * @param datanodeDetails - * @param conf - * @throws DiskOutOfSpaceException - * @throws IOException - */ - public OzoneContainer(DatanodeDetails datanodeDetails, OzoneConfiguration - conf, StateContext context) throws IOException { - this.dnDetails = datanodeDetails; - this.config = conf; - this.volumeSet = new VolumeSet(datanodeDetails.getUuidString(), conf); - this.containerSet = new ContainerSet(); - buildContainerSet(); - hddsDispatcher = new HddsDispatcher(config, containerSet, volumeSet, - context); - servers = new HashMap<>(); - servers.put(ReplicationType.STAND_ALONE, - new XceiverServerGrpc(datanodeDetails, config, hddsDispatcher, - createReplicationService())); - servers.put(ReplicationType.RATIS, XceiverServerRatis - .newXceiverServerRatis(datanodeDetails, config, hddsDispatcher, - context)); - } - - private GrpcReplicationService createReplicationService() { - return new GrpcReplicationService( - new OnDemandContainerReplicationSource(containerSet)); - } - - /** - * Build's container map. - */ - public void buildContainerSet() { - Iterator volumeSetIterator = volumeSet.getVolumesList() - .iterator(); - ArrayList volumeThreads = new ArrayList(); - - //TODO: diskchecker should be run before this, to see how disks are. - // And also handle disk failure tolerance need to be added - while (volumeSetIterator.hasNext()) { - HddsVolume volume = volumeSetIterator.next(); - File hddsVolumeRootDir = volume.getHddsRootDir(); - Thread thread = new Thread(new ContainerReader(volumeSet, volume, - containerSet, config)); - thread.start(); - volumeThreads.add(thread); - } - - try { - for (int i = 0; i < volumeThreads.size(); i++) { - volumeThreads.get(i).join(); - } - } catch (InterruptedException ex) { - LOG.info("Volume Threads Interrupted exception", ex); - } - - } - - /** - * Starts serving requests to ozone container. - * - * @throws IOException - */ - public void start() throws IOException { - LOG.info("Attempting to start container services."); - for (XceiverServerSpi serverinstance : servers.values()) { - serverinstance.start(); - } - hddsDispatcher.init(); - } - - /** - * Stop Container Service on the datanode. - */ - public void stop() { - //TODO: at end of container IO integration work. - LOG.info("Attempting to stop container services."); - for(XceiverServerSpi serverinstance: servers.values()) { - serverinstance.stop(); - } - hddsDispatcher.shutdown(); - } - - - @VisibleForTesting - public ContainerSet getContainerSet() { - return containerSet; - } - /** - * Returns container report. - * @return - container report. - * @throws IOException - */ - public StorageContainerDatanodeProtocolProtos.ContainerReportsProto - getContainerReport() throws IOException { - return this.containerSet.getContainerReport(); - } - - public PipelineReportsProto getPipelineReport() { - PipelineReportsProto.Builder pipelineReportsProto = - PipelineReportsProto.newBuilder(); - for (XceiverServerSpi serverInstance : servers.values()) { - pipelineReportsProto - .addAllPipelineReport(serverInstance.getPipelineReport()); - } - return pipelineReportsProto.build(); - } - - /** - * Submit ContainerRequest. - * @param request - * @param replicationType - * @param pipelineID - */ - public void submitContainerRequest( - ContainerProtos.ContainerCommandRequestProto request, - ReplicationType replicationType, - PipelineID pipelineID) throws IOException { - LOG.info("submitting {} request over {} server for container {}", - request.getCmdType(), replicationType, request.getContainerID()); - Preconditions.checkState(servers.containsKey(replicationType)); - servers.get(replicationType).submitRequest(request, pipelineID); - } - - private int getPortByType(ReplicationType replicationType) { - return servers.containsKey(replicationType) ? - servers.get(replicationType).getIPCPort() : INVALID_PORT; - } - - /** - * Returns the container servers IPC port. - * - * @return Container servers IPC port. - */ - public int getContainerServerPort() { - return getPortByType(ReplicationType.STAND_ALONE); - } - - /** - * Returns the Ratis container Server IPC port. - * - * @return Ratis port. - */ - public int getRatisContainerServerPort() { - return getPortByType(ReplicationType.RATIS); - } - - /** - * Returns node report of container storage usage. - */ - public StorageContainerDatanodeProtocolProtos.NodeReportProto getNodeReport() - throws IOException { - return volumeSet.getNodeReport(); - } - - @VisibleForTesting - public ContainerDispatcher getDispatcher() { - return this.hddsDispatcher; - } - - public VolumeSet getVolumeSet() { - return volumeSet; - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/ozoneimpl/package-info.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/ozoneimpl/package-info.java deleted file mode 100644 index c99c038b244..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/ozoneimpl/package-info.java +++ /dev/null @@ -1,21 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.ozoneimpl; -/** - Ozone main that calls into the container layer -**/ \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/ContainerDownloader.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/ContainerDownloader.java deleted file mode 100644 index 9511241fb5f..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/ContainerDownloader.java +++ /dev/null @@ -1,40 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.replication; - -import java.io.Closeable; -import java.nio.file.Path; -import java.util.List; -import java.util.concurrent.CompletableFuture; - -import org.apache.hadoop.hdds.protocol.DatanodeDetails; - -/** - * Service to download container data from other datanodes. - *

- * The implementation of this interface should copy the raw container data in - * compressed form to working directory. - *

- * A smart implementation would use multiple sources to do parallel download. - */ -public interface ContainerDownloader extends Closeable { - - CompletableFuture getContainerDataFromReplicas(long containerId, - List sources); - -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/ContainerReplicationSource.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/ContainerReplicationSource.java deleted file mode 100644 index 69582f799f8..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/ContainerReplicationSource.java +++ /dev/null @@ -1,49 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.replication; - -import java.io.IOException; -import java.io.OutputStream; - -/** - * Contract to prepare provide the container in binary form.. - *

- * Prepare will be called when container is closed. An implementation could - * precache any binary representation of a container and store the pre packede - * images. - */ -public interface ContainerReplicationSource { - - /** - * Prepare for the replication. - * - * @param containerId The name of the container the package. - */ - void prepare(long containerId); - - /** - * Copy the container data to an output stream. - * - * @param containerId Container to replicate - * @param destination The destination stream to copy all the container data. - * @throws IOException - */ - void copyData(long containerId, OutputStream destination) - throws IOException; - -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/ContainerReplicator.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/ContainerReplicator.java deleted file mode 100644 index 827b9d69e8b..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/ContainerReplicator.java +++ /dev/null @@ -1,27 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.replication; - -/** - * Service to do the real replication task. - * - * An implementation should download the container and im - */ -public interface ContainerReplicator { - void replicate(ReplicationTask task); -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/ContainerStreamingOutput.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/ContainerStreamingOutput.java deleted file mode 100644 index f7fd8a4957d..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/ContainerStreamingOutput.java +++ /dev/null @@ -1,45 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.replication; - -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.core.StreamingOutput; -import java.io.IOException; -import java.io.OutputStream; - -/** - * JAX-RS streaming output to return the binary container data. - */ -public class ContainerStreamingOutput implements StreamingOutput { - - private long containerId; - - private ContainerReplicationSource containerReplicationSource; - - public ContainerStreamingOutput(long containerId, - ContainerReplicationSource containerReplicationSource) { - this.containerId = containerId; - this.containerReplicationSource = containerReplicationSource; - } - - @Override - public void write(OutputStream outputStream) - throws IOException, WebApplicationException { - containerReplicationSource.copyData(containerId, outputStream); - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/DownloadAndImportReplicator.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/DownloadAndImportReplicator.java deleted file mode 100644 index 5ef584184a0..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/DownloadAndImportReplicator.java +++ /dev/null @@ -1,136 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.replication; - -import java.io.FileInputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.List; -import java.util.concurrent.CompletableFuture; - -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.ozone.container.common.impl.ContainerData; -import org.apache.hadoop.ozone.container.common.impl.ContainerDataYaml; -import org.apache.hadoop.ozone.container.common.impl.ContainerSet; -import org.apache.hadoop.ozone.container.common.interfaces.Container; -import org.apache.hadoop.ozone.container.common.interfaces.ContainerDispatcher; -import org.apache.hadoop.ozone.container.common.interfaces.Handler; -import org.apache.hadoop.ozone.container.keyvalue.TarContainerPacker; -import org.apache.hadoop.ozone.container.replication.ReplicationTask.Status; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Default replication implementation. - *

- * This class does the real job. Executes the download and import the container - * to the container set. - */ -public class DownloadAndImportReplicator implements ContainerReplicator { - - private static final Logger LOG = - LoggerFactory.getLogger(DownloadAndImportReplicator.class); - - private final ContainerSet containerSet; - - private final ContainerDispatcher containerDispatcher; - - private final ContainerDownloader downloader; - - private final TarContainerPacker packer; - - public DownloadAndImportReplicator( - ContainerSet containerSet, - ContainerDispatcher containerDispatcher, - ContainerDownloader downloader, - TarContainerPacker packer) { - this.containerSet = containerSet; - this.containerDispatcher = containerDispatcher; - this.downloader = downloader; - this.packer = packer; - } - - public void importContainer(long containerID, Path tarFilePath) { - try { - ContainerData originalContainerData; - try (FileInputStream tempContainerTarStream = new FileInputStream( - tarFilePath.toFile())) { - byte[] containerDescriptorYaml = - packer.unpackContainerDescriptor(tempContainerTarStream); - originalContainerData = ContainerDataYaml.readContainer( - containerDescriptorYaml); - } - - try (FileInputStream tempContainerTarStream = new FileInputStream( - tarFilePath.toFile())) { - - Handler handler = containerDispatcher.getHandler( - originalContainerData.getContainerType()); - - Container container = handler.importContainer(containerID, - originalContainerData.getMaxSize(), - tempContainerTarStream, - packer); - - containerSet.addContainer(container); - } - - } catch (Exception e) { - LOG.error( - "Can't import the downloaded container data id=" + containerID, - e); - try { - Files.delete(tarFilePath); - } catch (Exception ex) { - LOG.error( - "Container import is failed and the downloaded file can't be " - + "deleted: " - + tarFilePath.toAbsolutePath().toString()); - } - } - } - - @Override - public void replicate(ReplicationTask task) { - long containerID = task.getContainerId(); - - List sourceDatanodes = task.getSources(); - - LOG.info("Starting replication of container {} from {}", containerID, - sourceDatanodes); - - CompletableFuture tempTarFile = downloader - .getContainerDataFromReplicas(containerID, - sourceDatanodes); - - try { - //wait for the download. This thread pool is limiting the paralell - //downloads, so it's ok to block here and wait for the full download. - Path path = tempTarFile.get(); - LOG.info("Container {} is downloaded, starting to import.", - containerID); - importContainer(containerID, path); - LOG.info("Container {} is replicated successfully", containerID); - task.setStatus(Status.DONE); - } catch (Exception e) { - LOG.error("Container replication was unsuccessful .", e); - task.setStatus(Status.FAILED); - } - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/GrpcReplicationClient.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/GrpcReplicationClient.java deleted file mode 100644 index 3aafb0cb0e5..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/GrpcReplicationClient.java +++ /dev/null @@ -1,169 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.replication; - -import java.io.BufferedOutputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.concurrent.CompletableFuture; - -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .CopyContainerRequestProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .CopyContainerResponseProto; -import org.apache.hadoop.hdds.protocol.datanode.proto - .IntraDatanodeProtocolServiceGrpc; -import org.apache.hadoop.hdds.protocol.datanode.proto - .IntraDatanodeProtocolServiceGrpc.IntraDatanodeProtocolServiceStub; -import org.apache.hadoop.ozone.OzoneConfigKeys; - -import com.google.common.base.Preconditions; -import org.apache.ratis.shaded.io.grpc.ManagedChannel; -import org.apache.ratis.shaded.io.grpc.netty.NettyChannelBuilder; -import org.apache.ratis.shaded.io.grpc.stub.StreamObserver; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Client to read container data from Grpc. - */ -public class GrpcReplicationClient { - - private static final Logger LOG = - LoggerFactory.getLogger(GrpcReplicationClient.class); - - private final ManagedChannel channel; - - private final IntraDatanodeProtocolServiceStub client; - - private final Path workingDirectory; - - public GrpcReplicationClient(String host, - int port, Path workingDir) { - - channel = NettyChannelBuilder.forAddress(host, port) - .usePlaintext() - .maxInboundMessageSize(OzoneConfigKeys.DFS_CONTAINER_CHUNK_MAX_SIZE) - .build(); - client = IntraDatanodeProtocolServiceGrpc.newStub(channel); - this.workingDirectory = workingDir; - - } - - public CompletableFuture download(long containerId) { - CopyContainerRequestProto request = - CopyContainerRequestProto.newBuilder() - .setContainerID(containerId) - .setLen(-1) - .setReadOffset(0) - .build(); - - CompletableFuture response = new CompletableFuture<>(); - - Path destinationPath = - getWorkingDirectory().resolve("container-" + containerId + ".tar.gz"); - - client.download(request, - new StreamDownloader(containerId, response, destinationPath)); - return response; - } - - private Path getWorkingDirectory() { - return workingDirectory; - } - - public void shutdown() { - channel.shutdown(); - } - - /** - * Grpc stream observer to ComletableFuture adapter. - */ - public static class StreamDownloader - implements StreamObserver { - - private final CompletableFuture response; - - private final long containerId; - - private BufferedOutputStream stream; - - private Path outputPath; - - public StreamDownloader(long containerId, CompletableFuture response, - Path outputPath) { - this.response = response; - this.containerId = containerId; - this.outputPath = outputPath; - try { - outputPath = Preconditions.checkNotNull(outputPath); - Path parentPath = Preconditions.checkNotNull(outputPath.getParent()); - Files.createDirectories(parentPath); - stream = - new BufferedOutputStream(new FileOutputStream(outputPath.toFile())); - } catch (IOException e) { - throw new RuntimeException("OutputPath can't be used: " + outputPath, - e); - } - - } - - @Override - public void onNext(CopyContainerResponseProto chunk) { - try { - stream.write(chunk.getData().toByteArray()); - } catch (IOException e) { - response.completeExceptionally(e); - } - } - - @Override - public void onError(Throwable throwable) { - try { - stream.close(); - LOG.error("Container download was unsuccessfull", throwable); - try { - Files.delete(outputPath); - } catch (IOException ex) { - LOG.error( - "Error happened during the download but can't delete the " - + "temporary destination.", ex); - } - response.completeExceptionally(throwable); - } catch (IOException e) { - response.completeExceptionally(e); - } - } - - @Override - public void onCompleted() { - try { - stream.close(); - LOG.info("Container is downloaded to {}", outputPath); - response.complete(outputPath); - } catch (IOException e) { - response.completeExceptionally(e); - } - - } - } - -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/GrpcReplicationService.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/GrpcReplicationService.java deleted file mode 100644 index d8f696f47d9..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/GrpcReplicationService.java +++ /dev/null @@ -1,130 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.replication; - -import java.io.ByteArrayOutputStream; -import java.io.Closeable; -import java.io.IOException; -import java.io.OutputStream; - -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .CopyContainerRequestProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .CopyContainerResponseProto; -import org.apache.hadoop.hdds.protocol.datanode.proto - .IntraDatanodeProtocolServiceGrpc; - -import org.apache.ratis.shaded.com.google.protobuf.ByteString; -import org.apache.ratis.shaded.io.grpc.stub.StreamObserver; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Service to make containers available for replication. - */ -public class GrpcReplicationService extends - IntraDatanodeProtocolServiceGrpc.IntraDatanodeProtocolServiceImplBase { - - private static final Logger LOG = - LoggerFactory.getLogger(GrpcReplicationService.class); - - private final ContainerReplicationSource containerReplicationSource; - - public GrpcReplicationService( - ContainerReplicationSource containerReplicationSource) { - this.containerReplicationSource = containerReplicationSource; - } - - @Override - public void download(CopyContainerRequestProto request, - StreamObserver responseObserver) { - LOG.info("Streaming container data ({}) to other datanode", - request.getContainerID()); - try { - GrpcOutputStream outputStream = - new GrpcOutputStream(responseObserver, request.getContainerID()); - containerReplicationSource - .copyData(request.getContainerID(), outputStream); - - } catch (IOException e) { - LOG.error("Can't stream the container data", e); - responseObserver.onError(e); - } - } - - private static class GrpcOutputStream extends OutputStream - implements Closeable { - - private static final int BUFFER_SIZE_IN_BYTES = 1024 * 1024; - - private final StreamObserver responseObserver; - - private final ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - - private long containerId; - - private int readOffset = 0; - - private int writtenBytes; - - GrpcOutputStream( - StreamObserver responseObserver, - long containerId) { - this.responseObserver = responseObserver; - this.containerId = containerId; - } - - @Override - public void write(int b) throws IOException { - try { - buffer.write(b); - if (buffer.size() > BUFFER_SIZE_IN_BYTES) { - flushBuffer(false); - } - } catch (Exception ex) { - responseObserver.onError(ex); - } - } - - private void flushBuffer(boolean eof) { - if (buffer.size() > 0) { - CopyContainerResponseProto response = - CopyContainerResponseProto.newBuilder() - .setContainerID(containerId) - .setData(ByteString.copyFrom(buffer.toByteArray())) - .setEof(eof) - .setReadOffset(readOffset) - .setLen(buffer.size()) - .build(); - responseObserver.onNext(response); - readOffset += buffer.size(); - writtenBytes += buffer.size(); - buffer.reset(); - } - } - - @Override - public void close() throws IOException { - flushBuffer(true); - LOG.info("{} bytes written to the rpc stream from container {}", - writtenBytes, containerId); - responseObserver.onCompleted(); - } - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/OnDemandContainerReplicationSource.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/OnDemandContainerReplicationSource.java deleted file mode 100644 index d557b548b41..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/OnDemandContainerReplicationSource.java +++ /dev/null @@ -1,76 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.replication; - -import java.io.IOException; -import java.io.OutputStream; - -import org.apache.hadoop.ozone.container.common.impl.ContainerSet; -import org.apache.hadoop.ozone.container.common.interfaces.Container; -import org.apache.hadoop.ozone.container.common.interfaces.ContainerPacker; -import org.apache.hadoop.ozone.container.keyvalue.TarContainerPacker; - -import com.google.common.base.Preconditions; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * A naive implementation of the replication source which creates a tar file - * on-demand without pre-create the compressed archives. - */ -public class OnDemandContainerReplicationSource - implements ContainerReplicationSource { - - private static final Logger LOG = - LoggerFactory.getLogger(ContainerReplicationSource.class); - - private ContainerSet containerSet; - - private ContainerPacker packer = new TarContainerPacker(); - - public OnDemandContainerReplicationSource( - ContainerSet containerSet) { - this.containerSet = containerSet; - } - - @Override - public void prepare(long containerId) { - - } - - @Override - public void copyData(long containerId, OutputStream destination) - throws IOException { - - Container container = containerSet.getContainer(containerId); - - Preconditions - .checkNotNull(container, "Container is not found " + containerId); - - switch (container.getContainerType()) { - case KeyValueContainer: - packer.pack(container, - destination); - break; - default: - LOG.warn("Container type " + container.getContainerType() - + " is not replicable as no compression algorithm for that."); - } - - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/ReplicationSupervisor.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/ReplicationSupervisor.java deleted file mode 100644 index 1d8d5f655e7..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/ReplicationSupervisor.java +++ /dev/null @@ -1,142 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.replication; - -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; - -import org.apache.hadoop.ozone.container.common.impl.ContainerSet; -import org.apache.hadoop.ozone.container.replication.ReplicationTask.Status; - -import com.google.common.annotations.VisibleForTesting; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Single point to schedule the downloading tasks based on priorities. - */ -public class ReplicationSupervisor { - - private static final Logger LOG = - LoggerFactory.getLogger(ReplicationSupervisor.class); - - private final Set threadPool = new HashSet<>(); - - private final Map queue = new TreeMap(); - - private final ContainerSet containerSet; - - private final ContainerReplicator replicator; - - private final int poolSize; - - public ReplicationSupervisor( - ContainerSet containerSet, - ContainerReplicator replicator, int poolSize) { - this.containerSet = containerSet; - this.replicator = replicator; - this.poolSize = poolSize; - } - - public synchronized void addTask(ReplicationTask task) { - queue.putIfAbsent(task.getContainerId(), task); - synchronized (threadPool) { - threadPool.notify(); - } - } - - public void start() { - for (int i = 0; i < poolSize; i++) { - Worker worker = new Worker(); - Thread thread = new Thread(worker, "ContainerReplication-" + i); - thread.setDaemon(true); - thread.start(); - threadPool.add(worker); - } - } - - public synchronized ReplicationTask selectTask() { - for (ReplicationTask task : queue.values()) { - if (task.getStatus() == Status.QUEUED) { - if (containerSet.getContainer(task.getContainerId()) == null) { - task.setStatus(Status.DOWNLOADING); - return task; - } else { - LOG.debug("Container {} has already been downloaded.", - task.getContainerId()); - queue.remove(task.getContainerId()); - } - } else if (task.getStatus() == Status.FAILED) { - LOG.error( - "Container {} can't be downloaded from any of the datanodes.", - task.getContainerId()); - queue.remove(task.getContainerId()); - } else if (task.getStatus() == Status.DONE) { - queue.remove(task.getContainerId()); - LOG.info("Container {} is replicated.", task.getContainerId()); - } - } - //no available task. - return null; - } - - public void stop() { - for (Worker worker : threadPool) { - worker.stop(); - } - } - - @VisibleForTesting - public int getQueueSize() { - return queue.size(); - } - - private class Worker implements Runnable { - - private boolean running = true; - - @Override - public void run() { - try { - while (running) { - ReplicationTask task = selectTask(); - if (task == null) { - synchronized (threadPool) { - threadPool.wait(); - } - } else { - replicator.replicate(task); - } - } - } catch (Exception ex) { - LOG.error("Error on doing replication", ex); - try { - Thread.sleep(200); - } catch (InterruptedException e) { - LOG.error("Error on waiting after failed replication task", e); - } - } - } - - public void stop() { - running = false; - } - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/ReplicationTask.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/ReplicationTask.java deleted file mode 100644 index 90198110b59..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/ReplicationTask.java +++ /dev/null @@ -1,102 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.replication; - -import java.time.Instant; -import java.util.List; -import java.util.Objects; - -import org.apache.hadoop.hdds.protocol.DatanodeDetails; - -/** - * The task to download a container from the sources. - */ -public class ReplicationTask { - - private volatile Status status = Status.QUEUED; - - private final long containerId; - - private List sources; - - private final Instant queued = Instant.now(); - - public ReplicationTask(long containerId, - List sources) { - this.containerId = containerId; - this.sources = sources; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - ReplicationTask that = (ReplicationTask) o; - return containerId == that.containerId; - } - - @Override - public int hashCode() { - return Objects.hash(containerId); - } - - public long getContainerId() { - return containerId; - } - - public List getSources() { - return sources; - } - - public Status getStatus() { - return status; - } - - public void setStatus( - Status status) { - this.status = status; - } - - @Override - public String toString() { - return "ReplicationTask{" + - "status=" + status + - ", containerId=" + containerId + - ", sources=" + sources + - ", queued=" + queued + - '}'; - } - - public Instant getQueued() { - return queued; - } - - /** - * Status of the replication. - */ - public enum Status { - QUEUED, - DOWNLOADING, - FAILED, - DONE - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/SimpleContainerDownloader.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/SimpleContainerDownloader.java deleted file mode 100644 index a461a98f236..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/SimpleContainerDownloader.java +++ /dev/null @@ -1,121 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.replication; - -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import java.util.function.Function; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.DatanodeDetails.Port.Name; -import org.apache.hadoop.ozone.OzoneConfigKeys; - -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Simple ContainerDownloaderImplementation to download the missing container - * from the first available datanode. - *

- * This is not the most effective implementation as it uses only one source - * for he container download. - */ -public class SimpleContainerDownloader implements ContainerDownloader { - - private static final Logger LOG = - LoggerFactory.getLogger(SimpleContainerDownloader.class); - - private final Path workingDirectory; - - private ExecutorService executor; - - public SimpleContainerDownloader(Configuration conf) { - - String workDirString = - conf.get(OzoneConfigKeys.OZONE_CONTAINER_COPY_WORKDIR); - - if (workDirString == null) { - workingDirectory = Paths.get(System.getProperty("java.io.tmpdir")) - .resolve("container-copy"); - } else { - workingDirectory = Paths.get(workDirString); - } - - ThreadFactory build = new ThreadFactoryBuilder().setDaemon(true) - .setNameFormat("Container downloader thread - %d").build(); - executor = Executors.newSingleThreadExecutor(build); - LOG.info("Starting container downloader service to copy " - + "containers to replicate."); - } - - @Override - public CompletableFuture getContainerDataFromReplicas(long containerId, - List sourceDatanodes) { - - CompletableFuture result = null; - for (DatanodeDetails datanode : sourceDatanodes) { - try { - - if (result == null) { - GrpcReplicationClient grpcReplicationClient = - new GrpcReplicationClient(datanode.getIpAddress(), - datanode.getPort(Name.STANDALONE).getValue(), - workingDirectory); - result = grpcReplicationClient.download(containerId); - } else { - result = result.thenApply(CompletableFuture::completedFuture) - .exceptionally(t -> { - LOG.error("Error on replicating container: " + containerId, t); - GrpcReplicationClient grpcReplicationClient = - new GrpcReplicationClient(datanode.getIpAddress(), - datanode.getPort(Name.STANDALONE).getValue(), - workingDirectory); - return grpcReplicationClient.download(containerId); - }).thenCompose(Function.identity()); - } - } catch (Exception ex) { - LOG.error(String.format( - "Container %s download from datanode %s was unsuccessful. " - + "Trying the next datanode", containerId, datanode), ex); - } - - } - return result; - - } - - @Override - public void close() throws IOException { - try { - executor.awaitTermination(10, TimeUnit.SECONDS); - } catch (InterruptedException e) { - LOG.error("Can't stop container downloader gracefully", e); - } - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/package-info.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/package-info.java deleted file mode 100644 index 38a853c72a0..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/replication/package-info.java +++ /dev/null @@ -1,21 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.replication; -/** - Classes to replicate container data between datanodes. -**/ \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/package-info.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/package-info.java deleted file mode 100644 index 1a510128398..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/package-info.java +++ /dev/null @@ -1,23 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone; - -/** - * Generic ozone specific classes. - */ \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/StorageContainerDatanodeProtocol.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/StorageContainerDatanodeProtocol.java deleted file mode 100644 index e3b5370d917..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/StorageContainerDatanodeProtocol.java +++ /dev/null @@ -1,75 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.protocol; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.DatanodeDetailsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.PipelineReportsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMHeartbeatRequestProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerReportsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMHeartbeatResponseProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.NodeReportProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMRegisteredResponseProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMVersionRequestProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMVersionResponseProto; - -import java.io.IOException; - -/** - * The protocol spoken between datanodes and SCM. For specifics please the - * Protoc file that defines this protocol. - */ -@InterfaceAudience.Private -public interface StorageContainerDatanodeProtocol { - /** - * Returns SCM version. - * @return Version info. - */ - SCMVersionResponseProto getVersion(SCMVersionRequestProto versionRequest) - throws IOException; - - /** - * Used by data node to send a Heartbeat. - * @param heartbeat Heartbeat - * @return - SCMHeartbeatResponseProto - * @throws IOException - */ - SCMHeartbeatResponseProto sendHeartbeat(SCMHeartbeatRequestProto heartbeat) - throws IOException; - - /** - * Register Datanode. - * @param datanodeDetails - Datanode Details. - * @param nodeReport - Node Report. - * @param containerReportsRequestProto - Container Reports. - * @return SCM Command. - */ - SCMRegisteredResponseProto register( - DatanodeDetailsProto datanodeDetails, - NodeReportProto nodeReport, - ContainerReportsProto containerReportsRequestProto, - PipelineReportsProto pipelineReports) throws IOException; - -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/StorageContainerNodeProtocol.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/StorageContainerNodeProtocol.java deleted file mode 100644 index b3c3eb359ec..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/StorageContainerNodeProtocol.java +++ /dev/null @@ -1,70 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.protocol; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.PipelineReportsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.NodeReportProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMVersionRequestProto; -import org.apache.hadoop.ozone.protocol.commands.RegisteredCommand; -import org.apache.hadoop.ozone.protocol.commands.SCMCommand; - -import java.util.List; - -/** - * The protocol spoken between datanodes and SCM. - * - * Please note that the full protocol spoken between a datanode and SCM is - * separated into 2 interfaces. One interface that deals with node state and - * another interface that deals with containers. - * - * This interface has functions that deals with the state of datanode. - */ -@InterfaceAudience.Private -public interface StorageContainerNodeProtocol { - /** - * Gets the version info from SCM. - * @param versionRequest - version Request. - * @return - returns SCM version info and other required information needed - * by datanode. - */ - VersionResponse getVersion(SCMVersionRequestProto versionRequest); - - /** - * Register the node if the node finds that it is not registered with any SCM. - * @param datanodeDetails DatanodeDetails - * @param nodeReport NodeReportProto - * @param pipelineReport PipelineReportsProto - * @return SCMHeartbeatResponseProto - */ - RegisteredCommand register(DatanodeDetails datanodeDetails, - NodeReportProto nodeReport, - PipelineReportsProto pipelineReport); - - /** - * Send heartbeat to indicate the datanode is alive and doing well. - * @param datanodeDetails - Datanode ID. - * @return SCMheartbeat response list - */ - List processHeartbeat(DatanodeDetails datanodeDetails); - -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/VersionResponse.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/VersionResponse.java deleted file mode 100644 index 4d328d3d1e6..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/VersionResponse.java +++ /dev/null @@ -1,154 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.protocol; - -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.KeyValue; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMVersionResponseProto; - -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * Version response class. - */ -public class VersionResponse { - private final int version; - private final Map values; - - /** - * Creates a version response class. - * @param version - * @param values - */ - public VersionResponse(int version, Map values) { - this.version = version; - this.values = values; - } - - /** - * Creates a version Response class. - * @param version - */ - public VersionResponse(int version) { - this.version = version; - this.values = new HashMap<>(); - } - - /** - * Returns a new Builder. - * @return - Builder. - */ - public static Builder newBuilder() { - return new Builder(); - } - - /** - * Returns this class from protobuf message. - * @param response - SCMVersionResponseProto - * @return VersionResponse - */ - public static VersionResponse getFromProtobuf(SCMVersionResponseProto - response) { - return new VersionResponse(response.getSoftwareVersion(), - response.getKeysList().stream() - .collect(Collectors.toMap(KeyValue::getKey, - KeyValue::getValue))); - } - - /** - * Adds a value to version Response. - * @param key - String - * @param value - String - */ - public void put(String key, String value) { - if (this.values.containsKey(key)) { - throw new IllegalArgumentException("Duplicate key in version response"); - } - values.put(key, value); - } - - /** - * Return a protobuf message. - * @return SCMVersionResponseProto. - */ - public SCMVersionResponseProto getProtobufMessage() { - - List list = new LinkedList<>(); - for (Map.Entry entry : values.entrySet()) { - list.add(KeyValue.newBuilder().setKey(entry.getKey()). - setValue(entry.getValue()).build()); - } - return - SCMVersionResponseProto.newBuilder() - .setSoftwareVersion(this.version) - .addAllKeys(list).build(); - } - - public String getValue(String key) { - return this.values.get(key); - } - - /** - * Builder class. - */ - public static class Builder { - private int version; - private Map values; - - Builder() { - values = new HashMap<>(); - } - - /** - * Sets the version. - * @param ver - version - * @return Builder - */ - public Builder setVersion(int ver) { - this.version = ver; - return this; - } - - /** - * Adds a value to version Response. - * @param key - String - * @param value - String - */ - public Builder addValue(String key, String value) { - if (this.values.containsKey(key)) { - throw new IllegalArgumentException("Duplicate key in version response"); - } - values.put(key, value); - return this; - } - - /** - * Builds the version response. - * @return VersionResponse. - */ - public VersionResponse build() { - return new VersionResponse(this.version, this.values); - } - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/CloseContainerCommand.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/CloseContainerCommand.java deleted file mode 100644 index c2c20a4742f..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/CloseContainerCommand.java +++ /dev/null @@ -1,84 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.protocol.commands; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMCommandProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.CloseContainerCommandProto; -import org.apache.hadoop.hdds.scm.container.common.helpers.PipelineID; - -/** - * Asks datanode to close a container. - */ -public class CloseContainerCommand - extends SCMCommand { - - private HddsProtos.ReplicationType replicationType; - private PipelineID pipelineID; - - public CloseContainerCommand(long containerID, - HddsProtos.ReplicationType replicationType, - PipelineID pipelineID) { - super(containerID); - this.replicationType = replicationType; - this.pipelineID = pipelineID; - } - - /** - * Returns the type of this command. - * - * @return Type - */ - @Override - public SCMCommandProto.Type getType() { - return SCMCommandProto.Type.closeContainerCommand; - } - - /** - * Gets the protobuf message of this object. - * - * @return A protobuf message. - */ - @Override - public byte[] getProtoBufMessage() { - return getProto().toByteArray(); - } - - public CloseContainerCommandProto getProto() { - return CloseContainerCommandProto.newBuilder() - .setContainerID(getId()) - .setCmdId(getId()) - .setReplicationType(replicationType) - .setPipelineID(pipelineID.getProtobuf()) - .build(); - } - - public static CloseContainerCommand getFromProtobuf( - CloseContainerCommandProto closeContainerProto) { - Preconditions.checkNotNull(closeContainerProto); - return new CloseContainerCommand(closeContainerProto.getCmdId(), - closeContainerProto.getReplicationType(), - PipelineID.getFromProtobuf(closeContainerProto.getPipelineID())); - } - - public long getContainerID() { - return getId(); - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/CommandForDatanode.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/CommandForDatanode.java deleted file mode 100644 index 69337fb7c87..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/CommandForDatanode.java +++ /dev/null @@ -1,51 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.protocol.commands; - -import java.util.UUID; - -import com.google.protobuf.GeneratedMessage; -import org.apache.hadoop.hdds.server.events.IdentifiableEventPayload; - -/** - * Command for the datanode with the destination address. - */ -public class CommandForDatanode implements - IdentifiableEventPayload { - - private final UUID datanodeId; - - private final SCMCommand command; - - public CommandForDatanode(UUID datanodeId, SCMCommand command) { - this.datanodeId = datanodeId; - this.command = command; - } - - public UUID getDatanodeId() { - return datanodeId; - } - - public SCMCommand getCommand() { - return command; - } - - public long getId() { - return command.getId(); - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/CommandStatus.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/CommandStatus.java deleted file mode 100644 index 4b3ce840dce..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/CommandStatus.java +++ /dev/null @@ -1,164 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.protocol.commands; - -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.CommandStatus.Status; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMCommandProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMCommandProto.Type; - -/** - * A class that is used to communicate status of datanode commands. - */ -public class CommandStatus { - - private SCMCommandProto.Type type; - private Long cmdId; - private Status status; - private String msg; - - CommandStatus(Type type, Long cmdId, Status status, String msg) { - this.type = type; - this.cmdId = cmdId; - this.status = status; - this.msg = msg; - } - - public Type getType() { - return type; - } - - public Long getCmdId() { - return cmdId; - } - - public Status getStatus() { - return status; - } - - public String getMsg() { - return msg; - } - - /** - * To allow change of status once commandStatus is initialized. - * - * @param status - */ - public void setStatus(Status status) { - this.status = status; - } - - public void setStatus(boolean cmdExecuted) { - setStatus(cmdExecuted ? Status.EXECUTED : Status.FAILED); - } - - /** - * Returns a CommandStatus from the protocol buffers. - * - * @param cmdStatusProto - protoBuf Message - * @return CommandStatus - */ - public CommandStatus getFromProtoBuf( - StorageContainerDatanodeProtocolProtos.CommandStatus cmdStatusProto) { - return CommandStatusBuilder.newBuilder() - .setCmdId(cmdStatusProto.getCmdId()) - .setStatus(cmdStatusProto.getStatus()) - .setType(cmdStatusProto.getType()) - .setMsg(cmdStatusProto.getMsg()) - .build(); - } - /** - * Returns a CommandStatus from the protocol buffers. - * - * @return StorageContainerDatanodeProtocolProtos.CommandStatus - */ - public StorageContainerDatanodeProtocolProtos.CommandStatus - getProtoBufMessage() { - StorageContainerDatanodeProtocolProtos.CommandStatus.Builder builder = - StorageContainerDatanodeProtocolProtos.CommandStatus.newBuilder() - .setCmdId(this.getCmdId()) - .setStatus(this.getStatus()) - .setType(this.getType()); - if (this.getMsg() != null) { - builder.setMsg(this.getMsg()); - } - return builder.build(); - } - - /** - * Builder class for CommandStatus. - */ - public static class CommandStatusBuilder { - - private SCMCommandProto.Type type; - private Long cmdId; - private StorageContainerDatanodeProtocolProtos.CommandStatus.Status status; - private String msg; - - CommandStatusBuilder() { - } - - public static CommandStatusBuilder newBuilder() { - return new CommandStatusBuilder(); - } - - public Type getType() { - return type; - } - - public Long getCmdId() { - return cmdId; - } - - public Status getStatus() { - return status; - } - - public String getMsg() { - return msg; - } - - public CommandStatusBuilder setType(Type commandType) { - this.type = commandType; - return this; - } - - public CommandStatusBuilder setCmdId(Long commandId) { - this.cmdId = commandId; - return this; - } - - public CommandStatusBuilder setStatus(Status commandStatus) { - this.status = commandStatus; - return this; - } - - public CommandStatusBuilder setMsg(String message) { - this.msg = message; - return this; - } - - public CommandStatus build() { - return new CommandStatus(type, cmdId, status, msg); - } - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/DeleteBlockCommandStatus.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/DeleteBlockCommandStatus.java deleted file mode 100644 index 2659ab37041..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/DeleteBlockCommandStatus.java +++ /dev/null @@ -1,92 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.protocol.commands; - -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMCommandProto.Type; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerBlocksDeletionACKProto; - -public class DeleteBlockCommandStatus extends CommandStatus { - - private ContainerBlocksDeletionACKProto blocksDeletionAck = null; - - public DeleteBlockCommandStatus(Type type, Long cmdId, - StorageContainerDatanodeProtocolProtos.CommandStatus.Status status, - String msg, ContainerBlocksDeletionACKProto blocksDeletionAck) { - super(type, cmdId, status, msg); - this.blocksDeletionAck = blocksDeletionAck; - } - - public void setBlocksDeletionAck( - ContainerBlocksDeletionACKProto deletionAck) { - blocksDeletionAck = deletionAck; - } - - @Override - public CommandStatus getFromProtoBuf( - StorageContainerDatanodeProtocolProtos.CommandStatus cmdStatusProto) { - return DeleteBlockCommandStatusBuilder.newBuilder() - .setBlockDeletionAck(cmdStatusProto.getBlockDeletionAck()) - .setCmdId(cmdStatusProto.getCmdId()) - .setStatus(cmdStatusProto.getStatus()) - .setType(cmdStatusProto.getType()) - .setMsg(cmdStatusProto.getMsg()) - .build(); - } - - @Override - public StorageContainerDatanodeProtocolProtos.CommandStatus getProtoBufMessage() { - StorageContainerDatanodeProtocolProtos.CommandStatus.Builder builder = - StorageContainerDatanodeProtocolProtos.CommandStatus.newBuilder() - .setCmdId(this.getCmdId()) - .setStatus(this.getStatus()) - .setType(this.getType()); - if (blocksDeletionAck != null) { - builder.setBlockDeletionAck(blocksDeletionAck); - } - if (this.getMsg() != null) { - builder.setMsg(this.getMsg()); - } - return builder.build(); - } - - public static final class DeleteBlockCommandStatusBuilder - extends CommandStatusBuilder { - private ContainerBlocksDeletionACKProto blocksDeletionAck = null; - - public static DeleteBlockCommandStatusBuilder newBuilder() { - return new DeleteBlockCommandStatusBuilder(); - } - - public DeleteBlockCommandStatusBuilder setBlockDeletionAck( - ContainerBlocksDeletionACKProto deletionAck) { - this.blocksDeletionAck = deletionAck; - return this; - } - - @Override - public CommandStatus build() { - return new DeleteBlockCommandStatus(getType(), getCmdId(), getStatus(), - getMsg(), blocksDeletionAck); - } - - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/DeleteBlocksCommand.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/DeleteBlocksCommand.java deleted file mode 100644 index 07feeff6c1b..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/DeleteBlocksCommand.java +++ /dev/null @@ -1,75 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.protocol.commands; - -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMCommandProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.DeletedBlocksTransaction; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.DeleteBlocksCommandProto; - -import java.util.List; - -/** - * A SCM command asks a datanode to delete a number of blocks. - */ -public class DeleteBlocksCommand extends - SCMCommand { - - private List blocksTobeDeleted; - - - public DeleteBlocksCommand(List blocks) { - super(); - this.blocksTobeDeleted = blocks; - } - - // Should be called only for protobuf conversion - private DeleteBlocksCommand(List blocks, - long id) { - super(id); - this.blocksTobeDeleted = blocks; - } - - public List blocksTobeDeleted() { - return this.blocksTobeDeleted; - } - - @Override - public SCMCommandProto.Type getType() { - return SCMCommandProto.Type.deleteBlocksCommand; - } - - @Override - public byte[] getProtoBufMessage() { - return getProto().toByteArray(); - } - - public static DeleteBlocksCommand getFromProtobuf( - DeleteBlocksCommandProto deleteBlocksProto) { - return new DeleteBlocksCommand(deleteBlocksProto - .getDeletedBlocksTransactionsList(), deleteBlocksProto.getCmdId()); - } - - public DeleteBlocksCommandProto getProto() { - return DeleteBlocksCommandProto.newBuilder() - .setCmdId(getId()) - .addAllDeletedBlocksTransactions(blocksTobeDeleted).build(); - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/RegisteredCommand.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/RegisteredCommand.java deleted file mode 100644 index 3a5da72f482..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/RegisteredCommand.java +++ /dev/null @@ -1,215 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.protocol.commands; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMRegisteredResponseProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMRegisteredResponseProto - .ErrorCode; - -/** - * Response to Datanode Register call. - */ -public class RegisteredCommand { - private String datanodeUUID; - private String clusterID; - private ErrorCode error; - private String hostname; - private String ipAddress; - - public RegisteredCommand(final ErrorCode error, final String datanodeUUID, - final String clusterID) { - this(error, datanodeUUID, clusterID, null, null); - } - public RegisteredCommand(final ErrorCode error, final String datanodeUUID, - final String clusterID, final String hostname, final String ipAddress) { - this.datanodeUUID = datanodeUUID; - this.clusterID = clusterID; - this.error = error; - this.hostname = hostname; - this.ipAddress = ipAddress; - } - - /** - * Returns a new builder. - * - * @return - Builder - */ - public static Builder newBuilder() { - return new Builder(); - } - - /** - * Returns datanode UUID. - * - * @return - Datanode ID. - */ - public String getDatanodeUUID() { - return datanodeUUID; - } - - /** - * Returns cluster ID. - * - * @return -- ClusterID - */ - public String getClusterID() { - return clusterID; - } - - /** - * Returns ErrorCode. - * - * @return - ErrorCode - */ - public ErrorCode getError() { - return error; - } - - /** - * Returns the hostname. - * - * @return - hostname - */ - public String getHostName() { - return hostname; - } - - /** - * Returns the ipAddress of the dataNode. - */ - public String getIpAddress() { - return ipAddress; - } - - /** - * Gets the protobuf message of this object. - * - * @return A protobuf message. - */ - public byte[] getProtoBufMessage() { - SCMRegisteredResponseProto.Builder builder = - SCMRegisteredResponseProto.newBuilder() - .setClusterID(this.clusterID) - .setDatanodeUUID(this.datanodeUUID) - .setErrorCode(this.error); - if (hostname != null && ipAddress != null) { - builder.setHostname(hostname).setIpAddress(ipAddress); - } - return builder.build().toByteArray(); - } - - /** - * A builder class to verify all values are sane. - */ - public static class Builder { - private String datanodeUUID; - private String clusterID; - private ErrorCode error; - private String ipAddress; - private String hostname; - - /** - * sets UUID. - * - * @param dnUUID - datanode UUID - * @return Builder - */ - public Builder setDatanodeUUID(String dnUUID) { - this.datanodeUUID = dnUUID; - return this; - } - - /** - * Create this object from a Protobuf message. - * - * @param response - RegisteredCmdResponseProto - * @return RegisteredCommand - */ - public RegisteredCommand getFromProtobuf(SCMRegisteredResponseProto - response) { - Preconditions.checkNotNull(response); - if (response.hasHostname() && response.hasIpAddress()) { - return new RegisteredCommand(response.getErrorCode(), - response.getDatanodeUUID(), response.getClusterID(), - response.getHostname(), response.getIpAddress()); - } else { - return new RegisteredCommand(response.getErrorCode(), - response.getDatanodeUUID(), response.getClusterID()); - } - } - - /** - * Sets cluster ID. - * - * @param cluster - clusterID - * @return Builder - */ - public Builder setClusterID(String cluster) { - this.clusterID = cluster; - return this; - } - - /** - * Sets Error code. - * - * @param errorCode - error code - * @return Builder - */ - public Builder setErrorCode(ErrorCode errorCode) { - this.error = errorCode; - return this; - } - - /** - * sets the hostname. - */ - public Builder setHostname(String host) { - this.hostname = host; - return this; - } - - public Builder setIpAddress(String ipAddr) { - this.ipAddress = ipAddr; - return this; - } - - /** - * Build the command object. - * - * @return RegisteredCommand - */ - public RegisteredCommand build() { - if ((this.error == ErrorCode.success) && (this.datanodeUUID == null - || this.datanodeUUID.isEmpty()) || (this.clusterID == null - || this.clusterID.isEmpty())) { - throw new IllegalArgumentException("On success, RegisteredCommand " - + "needs datanodeUUID and ClusterID."); - } - if (hostname != null && ipAddress != null) { - return new RegisteredCommand(this.error, this.datanodeUUID, - this.clusterID, this.hostname, this.ipAddress); - } else { - return new RegisteredCommand(this.error, this.datanodeUUID, - this.clusterID); - } - } - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/ReplicateContainerCommand.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/ReplicateContainerCommand.java deleted file mode 100644 index 85302853952..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/ReplicateContainerCommand.java +++ /dev/null @@ -1,102 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.protocol.commands; - -import java.util.List; -import java.util.stream.Collectors; - -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ReplicateContainerCommandProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ReplicateContainerCommandProto - .Builder; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMCommandProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMCommandProto.Type; - -import com.google.common.base.Preconditions; - -/** - * SCM command to request replication of a container. - */ -public class ReplicateContainerCommand - extends SCMCommand { - - private final long containerID; - private final List sourceDatanodes; - - public ReplicateContainerCommand(long containerID, - List sourceDatanodes) { - super(); - this.containerID = containerID; - this.sourceDatanodes = sourceDatanodes; - } - - // Should be called only for protobuf conversion - public ReplicateContainerCommand(long containerID, - List sourceDatanodes, long id) { - super(id); - this.containerID = containerID; - this.sourceDatanodes = sourceDatanodes; - } - - @Override - public Type getType() { - return SCMCommandProto.Type.replicateContainerCommand; - } - - @Override - public byte[] getProtoBufMessage() { - return getProto().toByteArray(); - } - - public ReplicateContainerCommandProto getProto() { - Builder builder = ReplicateContainerCommandProto.newBuilder() - .setCmdId(getId()) - .setContainerID(containerID); - for (DatanodeDetails dd : sourceDatanodes) { - builder.addSources(dd.getProtoBufMessage()); - } - return builder.build(); - } - - public static ReplicateContainerCommand getFromProtobuf( - ReplicateContainerCommandProto protoMessage) { - Preconditions.checkNotNull(protoMessage); - - List datanodeDetails = - protoMessage.getSourcesList() - .stream() - .map(DatanodeDetails::getFromProtoBuf) - .collect(Collectors.toList()); - - return new ReplicateContainerCommand(protoMessage.getContainerID(), - datanodeDetails, protoMessage.getCmdId()); - - } - - public long getContainerID() { - return containerID; - } - - public List getSourceDatanodes() { - return sourceDatanodes; - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/ReregisterCommand.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/ReregisterCommand.java deleted file mode 100644 index 09f361d7b6a..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/ReregisterCommand.java +++ /dev/null @@ -1,67 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.protocol.commands; - -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMCommandProto; - -import static org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ReregisterCommandProto; - -/** - * Informs a datanode to register itself with SCM again. - */ -public class ReregisterCommand extends - SCMCommand{ - - /** - * Returns the type of this command. - * - * @return Type - */ - @Override - public SCMCommandProto.Type getType() { - return SCMCommandProto.Type.reregisterCommand; - } - - /** - * Gets the protobuf message of this object. - * - * @return A protobuf message. - */ - @Override - public byte[] getProtoBufMessage() { - return getProto().toByteArray(); - } - - /** - * Not implemented for ReregisterCommand. - * - * @return cmdId. - */ - @Override - public long getId() { - return 0; - } - - public ReregisterCommandProto getProto() { - return ReregisterCommandProto - .newBuilder() - .build(); - } -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/SCMCommand.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/SCMCommand.java deleted file mode 100644 index 5773bf1825b..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/SCMCommand.java +++ /dev/null @@ -1,62 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.protocol.commands; - -import com.google.protobuf.GeneratedMessage; -import org.apache.hadoop.hdds.HddsIdFactory; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMCommandProto; -import org.apache.hadoop.hdds.server.events.IdentifiableEventPayload; - -/** - * A class that acts as the base class to convert between Java and SCM - * commands in protobuf format. - * @param - */ -public abstract class SCMCommand implements - IdentifiableEventPayload { - private long id; - - SCMCommand() { - this.id = HddsIdFactory.getLongId(); - } - - SCMCommand(long id) { - this.id = id; - } - /** - * Returns the type of this command. - * @return Type - */ - public abstract SCMCommandProto.Type getType(); - - /** - * Gets the protobuf message of this object. - * @return A protobuf message. - */ - public abstract byte[] getProtoBufMessage(); - - /** - * Gets the commandId of this object. - * @return uuid. - */ - public long getId() { - return id; - } - -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/package-info.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/package-info.java deleted file mode 100644 index 7083c1b154d..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/package-info.java +++ /dev/null @@ -1,21 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.protocol.commands; -/** - Set of classes that help in protoc conversions. - **/ diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/package-info.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/package-info.java deleted file mode 100644 index a718fa7476f..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/package-info.java +++ /dev/null @@ -1,23 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.protocol; - -/** - * This package contains classes for HDDS protocol definitions. - */ diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocolPB/StorageContainerDatanodeProtocolClientSideTranslatorPB.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocolPB/StorageContainerDatanodeProtocolClientSideTranslatorPB.java deleted file mode 100644 index 4e1e27e1801..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocolPB/StorageContainerDatanodeProtocolClientSideTranslatorPB.java +++ /dev/null @@ -1,167 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.protocolPB; - -import com.google.protobuf.RpcController; -import com.google.protobuf.ServiceException; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.DatanodeDetailsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.PipelineReportsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerReportsProto; - -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMHeartbeatRequestProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMHeartbeatResponseProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.NodeReportProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMRegisterRequestProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMRegisteredResponseProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMVersionRequestProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMVersionResponseProto; -import org.apache.hadoop.ipc.ProtobufHelper; -import org.apache.hadoop.ipc.ProtocolTranslator; -import org.apache.hadoop.ipc.RPC; -import org.apache.hadoop.ozone.protocol.StorageContainerDatanodeProtocol; - -import java.io.Closeable; -import java.io.IOException; - -/** - * This class is the client-side translator to translate the requests made on - * the {@link StorageContainerDatanodeProtocol} interface to the RPC server - * implementing {@link StorageContainerDatanodeProtocolPB}. - */ -public class StorageContainerDatanodeProtocolClientSideTranslatorPB - implements StorageContainerDatanodeProtocol, ProtocolTranslator, Closeable { - - /** - * RpcController is not used and hence is set to null. - */ - private static final RpcController NULL_RPC_CONTROLLER = null; - private final StorageContainerDatanodeProtocolPB rpcProxy; - - /** - * Constructs a Client side interface that calls into SCM datanode protocol. - * - * @param rpcProxy - Proxy for RPC. - */ - public StorageContainerDatanodeProtocolClientSideTranslatorPB( - StorageContainerDatanodeProtocolPB rpcProxy) { - this.rpcProxy = rpcProxy; - } - - /** - * Closes this stream and releases any system resources associated with it. If - * the stream is already closed then invoking this method has no effect. - *

- *

As noted in {@link AutoCloseable#close()}, cases where the close may - * fail require careful attention. It is strongly advised to relinquish the - * underlying resources and to internally mark the {@code Closeable} - * as closed, prior to throwing the {@code IOException}. - * - * @throws IOException if an I/O error occurs - */ - @Override - public void close() throws IOException { - RPC.stopProxy(rpcProxy); - } - - /** - * Return the proxy object underlying this protocol translator. - * - * @return the proxy object underlying this protocol translator. - */ - @Override - public Object getUnderlyingProxyObject() { - return rpcProxy; - } - - /** - * Returns SCM version. - * - * @param unused - set to null and unused. - * @return Version info. - */ - @Override - public SCMVersionResponseProto getVersion(SCMVersionRequestProto - unused) throws IOException { - SCMVersionRequestProto request = - SCMVersionRequestProto.newBuilder().build(); - final SCMVersionResponseProto response; - try { - response = rpcProxy.getVersion(NULL_RPC_CONTROLLER, request); - } catch (ServiceException ex) { - throw ProtobufHelper.getRemoteException(ex); - } - return response; - } - - /** - * Send by datanode to SCM. - * - * @param heartbeat node heartbeat - * @throws IOException - */ - - @Override - public SCMHeartbeatResponseProto sendHeartbeat( - SCMHeartbeatRequestProto heartbeat) throws IOException { - final SCMHeartbeatResponseProto resp; - try { - resp = rpcProxy.sendHeartbeat(NULL_RPC_CONTROLLER, heartbeat); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - return resp; - } - - /** - * Register Datanode. - * - * @param datanodeDetailsProto - Datanode Details - * @param nodeReport - Node Report. - * @param containerReportsRequestProto - Container Reports. - * @return SCM Command. - */ - @Override - public SCMRegisteredResponseProto register( - DatanodeDetailsProto datanodeDetailsProto, NodeReportProto nodeReport, - ContainerReportsProto containerReportsRequestProto, - PipelineReportsProto pipelineReportsProto) - throws IOException { - SCMRegisterRequestProto.Builder req = - SCMRegisterRequestProto.newBuilder(); - req.setDatanodeDetails(datanodeDetailsProto); - req.setContainerReport(containerReportsRequestProto); - req.setPipelineReports(pipelineReportsProto); - req.setNodeReport(nodeReport); - final SCMRegisteredResponseProto response; - try { - response = rpcProxy.register(NULL_RPC_CONTROLLER, req.build()); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - return response; - } - -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocolPB/StorageContainerDatanodeProtocolPB.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocolPB/StorageContainerDatanodeProtocolPB.java deleted file mode 100644 index 9b28b5ae98d..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocolPB/StorageContainerDatanodeProtocolPB.java +++ /dev/null @@ -1,34 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.protocolPB; - -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos - .StorageContainerDatanodeProtocolService; -import org.apache.hadoop.ipc.ProtocolInfo; - -/** - * Protocol used from a datanode to StorageContainerManager. This extends - * the Protocol Buffers service interface to add Hadoop-specific annotations. - */ - -@ProtocolInfo(protocolName = - "org.apache.hadoop.ozone.protocol.StorageContainerDatanodeProtocol", - protocolVersion = 1) -public interface StorageContainerDatanodeProtocolPB extends - StorageContainerDatanodeProtocolService.BlockingInterface { -} diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocolPB/StorageContainerDatanodeProtocolServerSideTranslatorPB.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocolPB/StorageContainerDatanodeProtocolServerSideTranslatorPB.java deleted file mode 100644 index 862233276aa..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocolPB/StorageContainerDatanodeProtocolServerSideTranslatorPB.java +++ /dev/null @@ -1,94 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.protocolPB; - -import com.google.protobuf.RpcController; -import com.google.protobuf.ServiceException; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.PipelineReportsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.NodeReportProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMRegisterRequestProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMRegisteredResponseProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMVersionRequestProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMVersionResponseProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerReportsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMHeartbeatRequestProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMHeartbeatResponseProto; -import org.apache.hadoop.ozone.protocol.StorageContainerDatanodeProtocol; - -import java.io.IOException; - -/** - * This class is the server-side translator that forwards requests received on - * {@link StorageContainerDatanodeProtocolPB} to the {@link - * StorageContainerDatanodeProtocol} server implementation. - */ -public class StorageContainerDatanodeProtocolServerSideTranslatorPB - implements StorageContainerDatanodeProtocolPB { - - private final StorageContainerDatanodeProtocol impl; - - public StorageContainerDatanodeProtocolServerSideTranslatorPB( - StorageContainerDatanodeProtocol impl) { - this.impl = impl; - } - - @Override - public SCMVersionResponseProto getVersion(RpcController controller, - SCMVersionRequestProto request) - throws ServiceException { - try { - return impl.getVersion(request); - } catch (IOException e) { - throw new ServiceException(e); - } - } - - @Override - public SCMRegisteredResponseProto register(RpcController controller, - SCMRegisterRequestProto request) throws ServiceException { - try { - ContainerReportsProto containerRequestProto = request - .getContainerReport(); - NodeReportProto dnNodeReport = request.getNodeReport(); - PipelineReportsProto pipelineReport = request.getPipelineReports(); - return impl.register(request.getDatanodeDetails(), dnNodeReport, - containerRequestProto, pipelineReport); - } catch (IOException e) { - throw new ServiceException(e); - } - } - - @Override - public SCMHeartbeatResponseProto sendHeartbeat(RpcController controller, - SCMHeartbeatRequestProto request) throws ServiceException { - try { - return impl.sendHeartbeat(request); - } catch (IOException e) { - throw new ServiceException(e); - } - } - -} \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocolPB/package-info.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocolPB/package-info.java deleted file mode 100644 index 378a8f389cf..00000000000 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocolPB/package-info.java +++ /dev/null @@ -1,19 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.protocolPB; diff --git a/hadoop-hdds/container-service/src/main/proto/StorageContainerDatanodeProtocol.proto b/hadoop-hdds/container-service/src/main/proto/StorageContainerDatanodeProtocol.proto deleted file mode 100644 index 982029c91b2..00000000000 --- a/hadoop-hdds/container-service/src/main/proto/StorageContainerDatanodeProtocol.proto +++ /dev/null @@ -1,386 +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 - * - * 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. - */ - -/** - * These .proto interfaces are private and unstable. - * Please see http://wiki.apache.org/hadoop/Compatibility - * for what changes are allowed for a *unstable* .proto interface. - */ - -option java_package = "org.apache.hadoop.hdds.protocol.proto"; - -option java_outer_classname = "StorageContainerDatanodeProtocolProtos"; - -option java_generic_services = true; - -option java_generate_equals_and_hash = true; - -package hadoop.hdds; - -import "hdds.proto"; - -/** - * Request for version info of the software stack on the server. - */ -message SCMVersionRequestProto {} - -/** -* Generic response that is send to a version request. This allows keys to be -* added on the fly and protocol to remain stable. -*/ -message SCMVersionResponseProto { - required uint32 softwareVersion = 1; - repeated hadoop.hdds.KeyValue keys = 2; -} - -message SCMRegisterRequestProto { - required DatanodeDetailsProto datanodeDetails = 1; - required NodeReportProto nodeReport = 2; - required ContainerReportsProto containerReport = 3; - required PipelineReportsProto pipelineReports = 4; -} - -/** - * Datanode ID returned by the SCM. This is similar to name node - * registeration of a datanode. - */ -message SCMRegisteredResponseProto { - enum ErrorCode { - success = 1; - errorNodeNotPermitted = 2; - } - required ErrorCode errorCode = 1; - required string datanodeUUID = 2; - required string clusterID = 3; - optional SCMNodeAddressList addressList = 4; - optional string hostname = 5; - optional string ipAddress = 6; -} - -/** -* This message is send by data node to indicate that it is alive or it is -* registering with the node manager. -*/ -message SCMHeartbeatRequestProto { - required DatanodeDetailsProto datanodeDetails = 1; - optional NodeReportProto nodeReport = 2; - optional ContainerReportsProto containerReport = 3; - repeated CommandStatusReportsProto commandStatusReports = 4; - optional ContainerActionsProto containerActions = 5; - optional PipelineActionsProto pipelineActions = 6; - optional PipelineReportsProto pipelineReports = 7; -} - -/* - * A group of commands for the datanode to execute - */ -message SCMHeartbeatResponseProto { - required string datanodeUUID = 1; - repeated SCMCommandProto commands = 2; -} - -message SCMNodeAddressList { - repeated string addressList = 1; -} - -/** -* This message is send along with the heart beat to report datanode -* storage utilization to SCM. -*/ -message NodeReportProto { - repeated StorageReportProto storageReport = 1; -} - -message StorageReportProto { - required string storageUuid = 1; - required string storageLocation = 2; - optional uint64 capacity = 3 [default = 0]; - optional uint64 scmUsed = 4 [default = 0]; - optional uint64 remaining = 5 [default = 0]; - optional StorageTypeProto storageType = 6 [default = DISK]; - optional bool failed = 7 [default = false]; -} - -/** - * Types of recognized storage media. - */ -enum StorageTypeProto { - DISK = 1; - SSD = 2; - ARCHIVE = 3; - RAM_DISK = 4; - PROVIDED = 5; -} - -message ContainerReportsProto { - repeated ContainerInfo reports = 1; -} - -message CommandStatusReportsProto { - repeated CommandStatus cmdStatus = 1; -} - -message CommandStatus { - enum Status { - PENDING = 1; - EXECUTED = 2; - FAILED = 3; - } - required int64 cmdId = 1; - required Status status = 2 [default = PENDING]; - required SCMCommandProto.Type type = 3; - optional string msg = 4; - optional ContainerBlocksDeletionACKProto blockDeletionAck = 5; -} - -message ContainerActionsProto { - repeated ContainerAction containerActions = 1; -} - -message ContainerAction { - enum Action { - CLOSE = 1; - } - - enum Reason { - CONTAINER_FULL = 1; - } - - required int64 containerID = 1; - required Action action = 2; - optional Reason reason = 3; -} - -message PipelineReport { - required PipelineID pipelineID = 1; -} - -message PipelineReportsProto { - repeated PipelineReport pipelineReport = 1; -} - -message PipelineActionsProto { - repeated PipelineAction pipelineActions = 1; -} - -message ClosePipelineInfo { - enum Reason { - PIPELINE_FAILED = 1; - } - required PipelineID pipelineID = 1; - optional Reason reason = 3; - optional string detailedReason = 4; -} - -message PipelineAction { - enum Action { - CLOSE = 1; - } - - /** - * Action will be used to identify the correct pipeline action. - */ - required Action action = 1; - optional ClosePipelineInfo closePipeline = 2; -} - -/** -A container report contains the following information. -*/ -message ContainerInfo { - required int64 containerID = 1; - optional int64 size = 2; - optional int64 used = 3; - optional int64 keyCount = 4; - // TODO: move the io count to separate message - optional int64 readCount = 5; - optional int64 writeCount = 6; - optional int64 readBytes = 7; - optional int64 writeBytes = 8; - optional string finalhash = 9; - optional hadoop.hdds.LifeCycleState state = 10; - optional int64 deleteTransactionId = 11; -} - -/* - * These are commands returned by SCM for to the datanode to execute. - */ -message SCMCommandProto { - enum Type { - reregisterCommand = 1; - deleteBlocksCommand = 2; - closeContainerCommand = 3; - deleteContainerCommand = 4; - replicateContainerCommand = 5; - } - // TODO: once we start using protoc 3.x, refactor this message using "oneof" - required Type commandType = 1; - optional ReregisterCommandProto reregisterCommandProto = 2; - optional DeleteBlocksCommandProto deleteBlocksCommandProto = 3; - optional CloseContainerCommandProto closeContainerCommandProto = 4; - optional DeleteContainerCommandProto deleteContainerCommandProto = 5; - optional ReplicateContainerCommandProto replicateContainerCommandProto = 6; -} - -/** - * SCM informs a datanode to register itself again. - * With recieving this command, datanode will transit to REGISTER state. - */ -message ReregisterCommandProto {} - - -// HB response from SCM, contains a list of block deletion transactions. -message DeleteBlocksCommandProto { - repeated DeletedBlocksTransaction deletedBlocksTransactions = 1; - required int64 cmdId = 3; -} - -// The deleted blocks which are stored in deletedBlock.db of scm. -// We don't use BlockID because this only contians multiple localIDs -// of the same containerID. -message DeletedBlocksTransaction { - required int64 txID = 1; - required int64 containerID = 2; - repeated int64 localID = 3; - // the retry time of sending deleting command to datanode. - required int32 count = 4; -} - -// ACK message datanode sent to SCM, contains the result of -// block deletion transactions. -message ContainerBlocksDeletionACKProto { - message DeleteBlockTransactionResult { - required int64 txID = 1; - required int64 containerID = 2; - required bool success = 3; - } - repeated DeleteBlockTransactionResult results = 1; - required string dnId = 2; -} - -/** -This command asks the datanode to close a specific container. -*/ -message CloseContainerCommandProto { - required int64 containerID = 1; - required hadoop.hdds.ReplicationType replicationType = 2; - required int64 cmdId = 3; - required PipelineID pipelineID = 4; -} - -/** -This command asks the datanode to delete a specific container. -*/ -message DeleteContainerCommandProto { - required int64 containerID = 1; - required int64 cmdId = 2; -} - -/** -This command asks the datanode to replicate a container from specific sources. -*/ -message ReplicateContainerCommandProto { - required int64 containerID = 1; - repeated DatanodeDetailsProto sources = 2; - required int64 cmdId = 3; -} - -/** - * Protocol used from a datanode to StorageContainerManager. - * - * Please see the request and response messages for details of the RPC calls. - * - * Here is a simple state diagram that shows how a datanode would boot up and - * communicate with SCM. - * - * ----------------------- - * | Start | - * ---------- ------------ - * | - * | - * | - * | - * | - * | - * | - * ----------v------------- - * | Searching for SCM ------------ - * ---------- ------------- | - * | | - * | | - * | ----------v------------- - * | | Register if needed | - * | ----------- ------------ - * | | - * v | - * ----------- ---------------- | - * --------- Heartbeat state <-------- - * | --------^------------------- - * | | - * | | - * | | - * | | - * | | - * | | - * | | - * ------------------ - * - * - * - * Here is how this protocol is used by the datanode. When a datanode boots up - * it moves into a stated called SEARCHING_SCM. In this state datanode is - * trying to establish communication with the SCM. The address of the SCMs are - * retrieved from the configuration information. - * - * In the SEARCHING_SCM state, only rpc call made by datanode is a getVersion - * call to SCM. Once any of the SCMs reply, datanode checks if it has a local - * persisted datanode ID. If it has this means that this datanode is already - * registered with some SCM. If this file is not found, datanode assumes that - * it needs to do a registration. - * - * If registration is need datanode moves into REGISTER state. It will - * send a register call with DatanodeDetailsProto data structure and presist - * that info. - * - * The response to the command contains clusterID. This information is - * also persisted by the datanode and moves into heartbeat state. - * - * Once in the heartbeat state, datanode sends heartbeats and container reports - * to SCM and process commands issued by SCM until it is shutdown. - * - */ -service StorageContainerDatanodeProtocolService { - - /** - * Gets the version information from the SCM. - */ - rpc getVersion (SCMVersionRequestProto) returns (SCMVersionResponseProto); - - /** - * Registers a data node with SCM. - */ - rpc register (SCMRegisterRequestProto) returns (SCMRegisteredResponseProto); - - /** - * Send heartbeat from datanode to SCM. HB's under SCM looks more - * like life line protocol than HB's under HDFS. In other words, it is - * extremely light weight and contains no data payload. - */ - rpc sendHeartbeat (SCMHeartbeatRequestProto) returns (SCMHeartbeatResponseProto); - -} diff --git a/hadoop-hdds/container-service/src/main/resources/META-INF/services/com.sun.jersey.spi.container.ContainerProvider b/hadoop-hdds/container-service/src/main/resources/META-INF/services/com.sun.jersey.spi.container.ContainerProvider deleted file mode 100644 index 2e103fea7b7..00000000000 --- a/hadoop-hdds/container-service/src/main/resources/META-INF/services/com.sun.jersey.spi.container.ContainerProvider +++ /dev/null @@ -1,16 +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 -# -# 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. - -org.apache.hadoop.ozone.web.netty.ObjectStoreJerseyContainerProvider diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/ContainerTestUtils.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/ContainerTestUtils.java deleted file mode 100644 index 923440e2382..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/ContainerTestUtils.java +++ /dev/null @@ -1,68 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.container.common; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.io.retry.RetryPolicies; -import org.apache.hadoop.ipc.ProtobufRpcEngine; -import org.apache.hadoop.ipc.RPC; -import org.apache.hadoop.net.NetUtils; -import org.apache.hadoop.ozone.container.common.statemachine - .EndpointStateMachine; -import org.apache.hadoop.ozone.protocolPB - .StorageContainerDatanodeProtocolClientSideTranslatorPB; -import org.apache.hadoop.ozone.protocolPB.StorageContainerDatanodeProtocolPB; -import org.apache.hadoop.security.UserGroupInformation; - -import java.net.InetSocketAddress; - -/** - * Helper utility to test containers. - */ -public final class ContainerTestUtils { - - private ContainerTestUtils() { - } - - /** - * Creates an Endpoint class for testing purpose. - * - * @param conf - Conf - * @param address - InetAddres - * @param rpcTimeout - rpcTimeOut - * @return EndPoint - * @throws Exception - */ - public static EndpointStateMachine createEndpoint(Configuration conf, - InetSocketAddress address, int rpcTimeout) throws Exception { - RPC.setProtocolEngine(conf, StorageContainerDatanodeProtocolPB.class, - ProtobufRpcEngine.class); - long version = - RPC.getProtocolVersion(StorageContainerDatanodeProtocolPB.class); - - StorageContainerDatanodeProtocolPB rpcProxy = RPC.getProtocolProxy( - StorageContainerDatanodeProtocolPB.class, version, - address, UserGroupInformation.getCurrentUser(), conf, - NetUtils.getDefaultSocketFactory(conf), rpcTimeout, - RetryPolicies.TRY_ONCE_THEN_FAIL).getProxy(); - - StorageContainerDatanodeProtocolClientSideTranslatorPB rpcClient = - new StorageContainerDatanodeProtocolClientSideTranslatorPB(rpcProxy); - return new EndpointStateMachine(address, rpcClient, conf); - } -} diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/SCMTestUtils.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/SCMTestUtils.java deleted file mode 100644 index a24f096ddb1..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/SCMTestUtils.java +++ /dev/null @@ -1,129 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.container.common; - -import com.google.protobuf.BlockingService; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdfs.DFSUtil; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos - .StorageContainerDatanodeProtocolService; -import org.apache.hadoop.ipc.ProtobufRpcEngine; -import org.apache.hadoop.ipc.RPC; -import org.apache.hadoop.ozone.OzoneConfigKeys; -import org.apache.hadoop.ozone.protocol.StorageContainerDatanodeProtocol; -import org.apache.hadoop.ozone.protocolPB.StorageContainerDatanodeProtocolPB; -import org.apache.hadoop.ozone.protocolPB - .StorageContainerDatanodeProtocolServerSideTranslatorPB; -import org.apache.hadoop.test.GenericTestUtils; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.ServerSocket; - -import static org.apache.hadoop.hdds.scm.ScmConfigKeys.HDDS_DATANODE_DIR_KEY; - -/** - * Test Endpoint class. - */ -public final class SCMTestUtils { - /** - * Never constructed. - */ - private SCMTestUtils() { - } - - /** - * Starts an RPC server, if configured. - * - * @param conf configuration - * @param addr configured address of RPC server - * @param protocol RPC protocol provided by RPC server - * @param instance RPC protocol implementation instance - * @param handlerCount RPC server handler count - * @return RPC server - * @throws IOException if there is an I/O error while creating RPC server - */ - private static RPC.Server startRpcServer(Configuration conf, - InetSocketAddress addr, Class - protocol, BlockingService instance, int handlerCount) - throws IOException { - RPC.Server rpcServer = new RPC.Builder(conf) - .setProtocol(protocol) - .setInstance(instance) - .setBindAddress(addr.getHostString()) - .setPort(addr.getPort()) - .setNumHandlers(handlerCount) - .setVerbose(false) - .setSecretManager(null) - .build(); - - DFSUtil.addPBProtocol(conf, protocol, instance, rpcServer); - return rpcServer; - } - - - /** - * Start Datanode RPC server. - */ - public static RPC.Server startScmRpcServer(Configuration configuration, - StorageContainerDatanodeProtocol server, - InetSocketAddress rpcServerAddresss, int handlerCount) throws - IOException { - RPC.setProtocolEngine(configuration, - StorageContainerDatanodeProtocolPB.class, - ProtobufRpcEngine.class); - - BlockingService scmDatanodeService = - StorageContainerDatanodeProtocolService. - newReflectiveBlockingService( - new StorageContainerDatanodeProtocolServerSideTranslatorPB( - server)); - - RPC.Server scmServer = startRpcServer(configuration, rpcServerAddresss, - StorageContainerDatanodeProtocolPB.class, scmDatanodeService, - handlerCount); - - scmServer.start(); - return scmServer; - } - - public static InetSocketAddress getReuseableAddress() throws IOException { - try (ServerSocket socket = new ServerSocket(0)) { - socket.setReuseAddress(true); - int port = socket.getLocalPort(); - String addr = InetAddress.getLoopbackAddress().getHostAddress(); - return new InetSocketAddress(addr, port); - } - } - - public static OzoneConfiguration getConf() { - OzoneConfiguration conf = new OzoneConfiguration(); - conf.set(HDDS_DATANODE_DIR_KEY, GenericTestUtils - .getRandomizedTempPath()); - conf.set(OzoneConfigKeys.OZONE_METADATA_DIRS, GenericTestUtils - .getRandomizedTempPath()); - return conf; - } - - public static OzoneConfiguration getOzoneConf() { - return new OzoneConfiguration(); - } - -} diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/ScmTestMock.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/ScmTestMock.java deleted file mode 100644 index 3e45596f37e..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/ScmTestMock.java +++ /dev/null @@ -1,353 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.container.common; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerReportsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.PipelineReportsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.CommandStatusReportsProto; -import org.apache.hadoop.hdds.protocol.proto. - StorageContainerDatanodeProtocolProtos.CommandStatus; -import org.apache.hadoop.hdds.scm.VersionInfo; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.DatanodeDetailsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMHeartbeatRequestProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerInfo; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMCommandProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMHeartbeatResponseProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.NodeReportProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.StorageReportProto; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.protocol.StorageContainerDatanodeProtocol; -import org.apache.hadoop.ozone.protocol.VersionResponse; - -import java.io.IOException; -import java.util.*; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * SCM RPC mock class. - */ -public class ScmTestMock implements StorageContainerDatanodeProtocol { - private int rpcResponseDelay; - private AtomicInteger heartbeatCount = new AtomicInteger(0); - private AtomicInteger rpcCount = new AtomicInteger(0); - private AtomicInteger containerReportsCount = new AtomicInteger(0); - private String clusterId; - private String scmId; - - public ScmTestMock() { - clusterId = UUID.randomUUID().toString(); - scmId = UUID.randomUUID().toString(); - } - - // Map of datanode to containers - private Map> nodeContainers = - new HashMap(); - private Map nodeReports = new HashMap<>(); - private AtomicInteger commandStatusReport = new AtomicInteger(0); - private List cmdStatusList = new LinkedList<>(); - private List scmCommandRequests = new LinkedList<>(); - /** - * Returns the number of heartbeats made to this class. - * - * @return int - */ - public int getHeartbeatCount() { - return heartbeatCount.get(); - } - - /** - * Returns the number of RPC calls made to this mock class instance. - * - * @return - Number of RPC calls serviced by this class. - */ - public int getRpcCount() { - return rpcCount.get(); - } - - /** - * Gets the RPC response delay. - * - * @return delay in milliseconds. - */ - public int getRpcResponseDelay() { - return rpcResponseDelay; - } - - /** - * Sets the RPC response delay. - * - * @param rpcResponseDelay - delay in milliseconds. - */ - public void setRpcResponseDelay(int rpcResponseDelay) { - this.rpcResponseDelay = rpcResponseDelay; - } - - /** - * Returns the number of container reports server has seen. - * @return int - */ - public int getContainerReportsCount() { - return containerReportsCount.get(); - } - - /** - * Returns the number of containers that have been reported so far. - * @return - count of reported containers. - */ - public long getContainerCount() { - return nodeContainers.values().parallelStream().mapToLong((containerMap)->{ - return containerMap.size(); - }).sum(); - } - - /** - * Get the number keys reported from container reports. - * @return - number of keys reported. - */ - public long getKeyCount() { - return nodeContainers.values().parallelStream().mapToLong((containerMap)->{ - return containerMap.values().parallelStream().mapToLong((container) -> { - return container.getKeyCount(); - }).sum(); - }).sum(); - } - - /** - * Get the number of bytes used from container reports. - * @return - number of bytes used. - */ - public long getBytesUsed() { - return nodeContainers.values().parallelStream().mapToLong((containerMap)->{ - return containerMap.values().parallelStream().mapToLong((container) -> { - return container.getUsed(); - }).sum(); - }).sum(); - } - - /** - * Returns SCM version. - * - * @return Version info. - */ - @Override - public StorageContainerDatanodeProtocolProtos.SCMVersionResponseProto - getVersion(StorageContainerDatanodeProtocolProtos - .SCMVersionRequestProto unused) throws IOException { - rpcCount.incrementAndGet(); - sleepIfNeeded(); - VersionInfo versionInfo = VersionInfo.getLatestVersion(); - return VersionResponse.newBuilder() - .setVersion(versionInfo.getVersion()) - .addValue(VersionInfo.DESCRIPTION_KEY, versionInfo.getDescription()) - .addValue(OzoneConsts.SCM_ID, scmId) - .addValue(OzoneConsts.CLUSTER_ID, clusterId) - .build().getProtobufMessage(); - - } - - private void sleepIfNeeded() { - if (getRpcResponseDelay() > 0) { - try { - Thread.sleep(getRpcResponseDelay()); - } catch (InterruptedException ex) { - // Just ignore this exception. - } - } - } - - /** - * Used by data node to send a Heartbeat. - * - * @param heartbeat - node heartbeat. - * @return - SCMHeartbeatResponseProto - * @throws IOException - */ - @Override - public StorageContainerDatanodeProtocolProtos.SCMHeartbeatResponseProto - sendHeartbeat(SCMHeartbeatRequestProto heartbeat) throws IOException { - rpcCount.incrementAndGet(); - heartbeatCount.incrementAndGet(); - if (heartbeat.getCommandStatusReportsCount() != 0) { - for (CommandStatusReportsProto statusReport : heartbeat - .getCommandStatusReportsList()) { - cmdStatusList.addAll(statusReport.getCmdStatusList()); - commandStatusReport.incrementAndGet(); - } - } - sleepIfNeeded(); - return SCMHeartbeatResponseProto.newBuilder().addAllCommands( - scmCommandRequests) - .setDatanodeUUID(heartbeat.getDatanodeDetails().getUuid()) - .build(); - } - - /** - * Register Datanode. - * - * @param datanodeDetailsProto DatanodDetailsProto. - * @return SCM Command. - */ - @Override - public StorageContainerDatanodeProtocolProtos - .SCMRegisteredResponseProto register( - DatanodeDetailsProto datanodeDetailsProto, NodeReportProto nodeReport, - ContainerReportsProto containerReportsRequestProto, - PipelineReportsProto pipelineReportsProto) - throws IOException { - rpcCount.incrementAndGet(); - updateNodeReport(datanodeDetailsProto, nodeReport); - updateContainerReport(containerReportsRequestProto, datanodeDetailsProto); - sleepIfNeeded(); - return StorageContainerDatanodeProtocolProtos.SCMRegisteredResponseProto - .newBuilder().setClusterID(UUID.randomUUID().toString()) - .setDatanodeUUID(datanodeDetailsProto.getUuid()).setErrorCode( - StorageContainerDatanodeProtocolProtos - .SCMRegisteredResponseProto.ErrorCode.success).build(); - } - - /** - * Update nodeReport. - * @param datanodeDetailsProto - * @param nodeReport - */ - public void updateNodeReport(DatanodeDetailsProto datanodeDetailsProto, - NodeReportProto nodeReport) { - DatanodeDetails datanode = DatanodeDetails.getFromProtoBuf( - datanodeDetailsProto); - NodeReportProto.Builder nodeReportProto = NodeReportProto.newBuilder(); - - List storageReports = - nodeReport.getStorageReportList(); - - for(StorageReportProto report : storageReports) { - nodeReportProto.addStorageReport(report); - } - - nodeReports.put(datanode, nodeReportProto.build()); - - } - - /** - * Update the cotainerReport. - * - * @param reports Container report - * @param datanodeDetails DataNode Info - * @throws IOException - */ - public void updateContainerReport( - StorageContainerDatanodeProtocolProtos.ContainerReportsProto reports, - DatanodeDetailsProto datanodeDetails) throws IOException { - Preconditions.checkNotNull(reports); - containerReportsCount.incrementAndGet(); - DatanodeDetails datanode = DatanodeDetails.getFromProtoBuf( - datanodeDetails); - if (reports.getReportsCount() > 0) { - Map containers = nodeContainers.get(datanode); - if (containers == null) { - containers = new LinkedHashMap(); - nodeContainers.put(datanode, containers); - } - - for (StorageContainerDatanodeProtocolProtos.ContainerInfo report : reports - .getReportsList()) { - containers.put(report.getContainerID(), report); - } - } - } - - - /** - * Return the number of StorageReports of a datanode. - * @param datanodeDetails - * @return count of containers of a datanode - */ - public int getNodeReportsCount(DatanodeDetails datanodeDetails) { - return nodeReports.get(datanodeDetails).getStorageReportCount(); - } - - /** - * Returns the number of containers of a datanode. - * @param datanodeDetails - * @return count of storage reports of a datanode - */ - public int getContainerCountsForDatanode(DatanodeDetails datanodeDetails) { - Map cr = nodeContainers.get(datanodeDetails); - if(cr != null) { - return cr.size(); - } - return 0; - } - - /** - * Reset the mock Scm for test to get a fresh start without rebuild MockScm. - */ - public void reset() { - heartbeatCount.set(0); - rpcCount.set(0); - containerReportsCount.set(0); - nodeContainers.clear(); - - } - - public int getCommandStatusReportCount() { - return commandStatusReport.get(); - } - - public List getCmdStatusList() { - return cmdStatusList; - } - - public List getScmCommandRequests() { - return scmCommandRequests; - } - - public void clearScmCommandRequests() { - scmCommandRequests.clear(); - } - - public void addScmCommandRequest(SCMCommandProto scmCmd) { - scmCommandRequests.add(scmCmd); - } - - /** - * Set scmId. - * @param id - */ - public void setScmId(String id) { - this.scmId = id; - } - - /** - * Set scmId. - * @return scmId - */ - public String getScmId() { - return scmId; - } -} diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/TestChunkLayOutVersion.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/TestChunkLayOutVersion.java deleted file mode 100644 index a4e0028e108..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/TestChunkLayOutVersion.java +++ /dev/null @@ -1,42 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common; - -import org.apache.hadoop.ozone.container.common.impl.ChunkLayOutVersion; -import org.junit.Assert; -import org.junit.Test; - -/** - * This class tests ChunkLayOutVersion. - */ -public class TestChunkLayOutVersion { - - @Test - public void testChunkLayOutVersion() { - - // Check Latest Version and description - Assert.assertEquals(1, ChunkLayOutVersion.getLatestVersion().getVersion()); - Assert.assertEquals("Data without checksums.", ChunkLayOutVersion - .getLatestVersion().getDescription()); - - Assert.assertEquals(1, ChunkLayOutVersion.getAllVersions().length); - - } - -} diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/TestDatanodeLayOutVersion.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/TestDatanodeLayOutVersion.java deleted file mode 100644 index 5cabef295f3..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/TestDatanodeLayOutVersion.java +++ /dev/null @@ -1,38 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.container.common; - -import org.junit.Assert; -import org.junit.Test; - -/** - * This class tests DatanodeLayOutVersion. - */ -public class TestDatanodeLayOutVersion { - - @Test - public void testDatanodeLayOutVersion() { - // Check Latest Version and description - Assert.assertEquals(1, DataNodeLayoutVersion.getLatestVersion() - .getVersion()); - Assert.assertEquals("HDDS Datanode LayOut Version 1", DataNodeLayoutVersion - .getLatestVersion().getDescription()); - Assert.assertEquals(DataNodeLayoutVersion.getAllVersions().length, - DataNodeLayoutVersion.getAllVersions().length); - } -} diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/TestDatanodeStateMachine.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/TestDatanodeStateMachine.java deleted file mode 100644 index 3fc0dd04e5c..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/TestDatanodeStateMachine.java +++ /dev/null @@ -1,424 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.container.common; - -import com.google.common.collect.Maps; -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.FileUtil; -import org.apache.hadoop.hdds.scm.ScmConfigKeys; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.ipc.RPC; -import org.apache.hadoop.ozone.OzoneConfigKeys; -import org.apache.hadoop.ozone.container.common.helpers.ContainerUtils; -import org.apache.hadoop.ozone.container.common.statemachine - .DatanodeStateMachine; -import org.apache.hadoop.ozone.container.common.statemachine - .EndpointStateMachine; -import org.apache.hadoop.ozone.container.common.statemachine - .SCMConnectionManager; -import org.apache.hadoop.ozone.container.common.states.DatanodeState; -import org.apache.hadoop.ozone.container.common.states.datanode - .InitDatanodeState; -import org.apache.hadoop.ozone.container.common.states.datanode - .RunningDatanodeState; -import org.apache.hadoop.test.GenericTestUtils; -import org.apache.hadoop.util.concurrent.HadoopExecutors; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.nio.file.Paths; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import static org.apache.hadoop.hdds.scm.ScmConfigKeys.HDDS_DATANODE_DIR_KEY; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_HEARTBEAT_RPC_TIMEOUT; -import static org.junit.Assert.assertTrue; - -/** - * Tests the datanode state machine class and its states. - */ -public class TestDatanodeStateMachine { - private static final Logger LOG = - LoggerFactory.getLogger(TestDatanodeStateMachine.class); - // Changing it to 1, as current code checks for multiple scm directories, - // and fail if exists - private final int scmServerCount = 1; - private List serverAddresses; - private List scmServers; - private List mockServers; - private ExecutorService executorService; - private Configuration conf; - private File testRoot; - - @Before - public void setUp() throws Exception { - conf = SCMTestUtils.getConf(); - conf.setTimeDuration(OZONE_SCM_HEARTBEAT_RPC_TIMEOUT, 500, - TimeUnit.MILLISECONDS); - conf.setBoolean(OzoneConfigKeys.DFS_CONTAINER_RATIS_IPC_RANDOM_PORT, true); - serverAddresses = new LinkedList<>(); - scmServers = new LinkedList<>(); - mockServers = new LinkedList<>(); - for (int x = 0; x < scmServerCount; x++) { - int port = SCMTestUtils.getReuseableAddress().getPort(); - String address = "127.0.0.1"; - serverAddresses.add(address + ":" + port); - ScmTestMock mock = new ScmTestMock(); - scmServers.add(SCMTestUtils.startScmRpcServer(conf, mock, - new InetSocketAddress(address, port), 10)); - mockServers.add(mock); - } - - conf.setStrings(ScmConfigKeys.OZONE_SCM_NAMES, - serverAddresses.toArray(new String[0])); - - String path = GenericTestUtils - .getTempPath(TestDatanodeStateMachine.class.getSimpleName()); - testRoot = new File(path); - if (!testRoot.mkdirs()) { - LOG.info("Required directories {} already exist.", testRoot); - } - - File dataDir = new File(testRoot, "data"); - conf.set(HDDS_DATANODE_DIR_KEY, dataDir.getAbsolutePath()); - if (!dataDir.mkdirs()) { - LOG.info("Data dir create failed."); - } - conf.set(OzoneConfigKeys.OZONE_METADATA_DIRS, - new File(testRoot, "scm").getAbsolutePath()); - path = Paths.get(path.toString(), - TestDatanodeStateMachine.class.getSimpleName() + ".id").toString(); - conf.set(ScmConfigKeys.OZONE_SCM_DATANODE_ID, path); - executorService = HadoopExecutors.newCachedThreadPool( - new ThreadFactoryBuilder().setDaemon(true) - .setNameFormat("Test Data Node State Machine Thread - %d").build()); - } - - @After - public void tearDown() throws Exception { - try { - if (executorService != null) { - executorService.shutdown(); - try { - if (!executorService.awaitTermination(5, TimeUnit.SECONDS)) { - executorService.shutdownNow(); - } - - if (!executorService.awaitTermination(5, TimeUnit.SECONDS)) { - LOG.error("Unable to shutdown properly."); - } - } catch (InterruptedException e) { - LOG.error("Error attempting to shutdown.", e); - executorService.shutdownNow(); - } - } - for (RPC.Server s : scmServers) { - s.stop(); - } - } catch (Exception e) { - //ignore all execption from the shutdown - } finally { - FileUtil.fullyDelete(testRoot); - } - } - - /** - * Assert that starting statemachine executes the Init State. - * - * @throws InterruptedException - */ - @Test - public void testStartStopDatanodeStateMachine() throws IOException, - InterruptedException, TimeoutException { - try (DatanodeStateMachine stateMachine = - new DatanodeStateMachine(getNewDatanodeDetails(), conf)) { - stateMachine.startDaemon(); - SCMConnectionManager connectionManager = - stateMachine.getConnectionManager(); - GenericTestUtils.waitFor(() -> connectionManager.getValues().size() == 1, - 1000, 30000); - - stateMachine.stopDaemon(); - assertTrue(stateMachine.isDaemonStopped()); - } - } - - /** - * This test explores the state machine by invoking each call in sequence just - * like as if the state machine would call it. Because this is a test we are - * able to verify each of the assumptions. - *

- * Here is what happens at High level. - *

- * 1. We start the datanodeStateMachine in the INIT State. - *

- * 2. We invoke the INIT state task. - *

- * 3. That creates a set of RPC endpoints that are ready to connect to SCMs. - *

- * 4. We assert that we have moved to the running state for the - * DatanodeStateMachine. - *

- * 5. We get the task for the Running State - Executing that running state, - * makes the first network call in of the state machine. The Endpoint is in - * the GETVERSION State and we invoke the task. - *

- * 6. We assert that this call was a success by checking that each of the - * endponts now have version response that it got from the SCM server that it - * was talking to and also each of the mock server serviced one RPC call. - *

- * 7. Since the Register is done now, next calls to get task will return - * HeartbeatTask, which sends heartbeats to SCM. We assert that we get right - * task from sub-system below. - * - * @throws IOException - */ - @Test - public void testDatanodeStateContext() throws IOException, - InterruptedException, ExecutionException, TimeoutException { - // There is no mini cluster started in this test, - // create a ID file so that state machine could load a fake datanode ID. - File idPath = new File( - conf.get(ScmConfigKeys.OZONE_SCM_DATANODE_ID)); - idPath.delete(); - DatanodeDetails datanodeDetails = getNewDatanodeDetails(); - DatanodeDetails.Port port = DatanodeDetails.newPort( - DatanodeDetails.Port.Name.STANDALONE, - OzoneConfigKeys.DFS_CONTAINER_IPC_PORT_DEFAULT); - datanodeDetails.setPort(port); - ContainerUtils.writeDatanodeDetailsTo(datanodeDetails, idPath); - - try (DatanodeStateMachine stateMachine = - new DatanodeStateMachine(datanodeDetails, conf)) { - DatanodeStateMachine.DatanodeStates currentState = - stateMachine.getContext().getState(); - Assert.assertEquals(DatanodeStateMachine.DatanodeStates.INIT, - currentState); - - DatanodeState task = - stateMachine.getContext().getTask(); - Assert.assertEquals(InitDatanodeState.class, task.getClass()); - - task.execute(executorService); - DatanodeStateMachine.DatanodeStates newState = - task.await(2, TimeUnit.SECONDS); - - for (EndpointStateMachine endpoint : - stateMachine.getConnectionManager().getValues()) { - // We assert that each of the is in State GETVERSION. - Assert.assertEquals(EndpointStateMachine.EndPointStates.GETVERSION, - endpoint.getState()); - } - - // The Datanode has moved into Running State, since endpoints are created. - // We move to running state when we are ready to issue RPC calls to SCMs. - Assert.assertEquals(DatanodeStateMachine.DatanodeStates.RUNNING, - newState); - - // If we had called context.execute instead of calling into each state - // this would have happened automatically. - stateMachine.getContext().setState(newState); - task = stateMachine.getContext().getTask(); - Assert.assertEquals(RunningDatanodeState.class, task.getClass()); - - // This execute will invoke getVersion calls against all SCM endpoints - // that we know of. - - task.execute(executorService); - newState = task.await(10, TimeUnit.SECONDS); - // If we are in running state, we should be in running. - Assert.assertEquals(DatanodeStateMachine.DatanodeStates.RUNNING, - newState); - - for (EndpointStateMachine endpoint : - stateMachine.getConnectionManager().getValues()) { - - // Since the earlier task.execute called into GetVersion, the - // endPointState Machine should move to REGISTER state. - Assert.assertEquals(EndpointStateMachine.EndPointStates.REGISTER, - endpoint.getState()); - - // We assert that each of the end points have gotten a version from the - // SCM Server. - Assert.assertNotNull(endpoint.getVersion()); - } - - // We can also assert that all mock servers have received only one RPC - // call at this point of time. - for (ScmTestMock mock : mockServers) { - Assert.assertEquals(1, mock.getRpcCount()); - } - - // This task is the Running task, but running task executes tasks based - // on the state of Endpoints, hence this next call will be a Register at - // the endpoint RPC level. - task = stateMachine.getContext().getTask(); - task.execute(executorService); - newState = task.await(2, TimeUnit.SECONDS); - - // If we are in running state, we should be in running. - Assert.assertEquals(DatanodeStateMachine.DatanodeStates.RUNNING, - newState); - - for (ScmTestMock mock : mockServers) { - Assert.assertEquals(2, mock.getRpcCount()); - } - - // This task is the Running task, but running task executes tasks based - // on the state of Endpoints, hence this next call will be a - // HeartbeatTask at the endpoint RPC level. - task = stateMachine.getContext().getTask(); - task.execute(executorService); - newState = task.await(2, TimeUnit.SECONDS); - - // If we are in running state, we should be in running. - Assert.assertEquals(DatanodeStateMachine.DatanodeStates.RUNNING, - newState); - - - for (ScmTestMock mock : mockServers) { - Assert.assertEquals(1, mock.getHeartbeatCount()); - } - } - } - - @Test - public void testDatanodeStateMachineWithIdWriteFail() throws Exception { - - File idPath = new File( - conf.get(ScmConfigKeys.OZONE_SCM_DATANODE_ID)); - idPath.delete(); - DatanodeDetails datanodeDetails = getNewDatanodeDetails(); - DatanodeDetails.Port port = DatanodeDetails.newPort( - DatanodeDetails.Port.Name.STANDALONE, - OzoneConfigKeys.DFS_CONTAINER_IPC_PORT_DEFAULT); - datanodeDetails.setPort(port); - - try (DatanodeStateMachine stateMachine = - new DatanodeStateMachine(datanodeDetails, conf)) { - DatanodeStateMachine.DatanodeStates currentState = - stateMachine.getContext().getState(); - Assert.assertEquals(DatanodeStateMachine.DatanodeStates.INIT, - currentState); - - DatanodeState task = - stateMachine.getContext().getTask(); - Assert.assertEquals(InitDatanodeState.class, task.getClass()); - - //Set the idPath to read only, state machine will fail to write - // datanodeId file and set the state to shutdown. - idPath.getParentFile().mkdirs(); - idPath.getParentFile().setReadOnly(); - - task.execute(executorService); - DatanodeStateMachine.DatanodeStates newState = - task.await(2, TimeUnit.SECONDS); - - //As, we have changed the permission of idPath to readable, writing - // will fail and it will set the state to shutdown. - Assert.assertEquals(DatanodeStateMachine.DatanodeStates.SHUTDOWN, - newState); - - //Setting back to writable. - idPath.getParentFile().setWritable(true); - } - } - - /** - * Test state transition with a list of invalid scm configurations, - * and verify the state transits to SHUTDOWN each time. - */ - @Test - public void testDatanodeStateMachineWithInvalidConfiguration() - throws Exception { - LinkedList> confList = - new LinkedList>(); - confList.add(Maps.immutableEntry(ScmConfigKeys.OZONE_SCM_NAMES, "")); - - // Invalid ozone.scm.names - /** Empty **/ - confList.add(Maps.immutableEntry( - ScmConfigKeys.OZONE_SCM_NAMES, "")); - /** Invalid schema **/ - confList.add(Maps.immutableEntry( - ScmConfigKeys.OZONE_SCM_NAMES, "x..y")); - /** Invalid port **/ - confList.add(Maps.immutableEntry( - ScmConfigKeys.OZONE_SCM_NAMES, "scm:xyz")); - /** Port out of range **/ - confList.add(Maps.immutableEntry( - ScmConfigKeys.OZONE_SCM_NAMES, "scm:123456")); - // Invalid ozone.scm.datanode.id - /** Empty **/ - confList.add(Maps.immutableEntry( - ScmConfigKeys.OZONE_SCM_DATANODE_ID, "")); - - confList.forEach((entry) -> { - Configuration perTestConf = new Configuration(conf); - perTestConf.setStrings(entry.getKey(), entry.getValue()); - LOG.info("Test with {} = {}", entry.getKey(), entry.getValue()); - try (DatanodeStateMachine stateMachine = new DatanodeStateMachine( - getNewDatanodeDetails(), perTestConf)) { - DatanodeStateMachine.DatanodeStates currentState = - stateMachine.getContext().getState(); - Assert.assertEquals(DatanodeStateMachine.DatanodeStates.INIT, - currentState); - DatanodeState task = - stateMachine.getContext().getTask(); - task.execute(executorService); - DatanodeStateMachine.DatanodeStates newState = - task.await(2, TimeUnit.SECONDS); - Assert.assertEquals(DatanodeStateMachine.DatanodeStates.SHUTDOWN, - newState); - } catch (Exception e) { - Assert.fail("Unexpected exception found"); - } - }); - } - - private DatanodeDetails getNewDatanodeDetails() { - DatanodeDetails.Port containerPort = DatanodeDetails.newPort( - DatanodeDetails.Port.Name.STANDALONE, 0); - DatanodeDetails.Port ratisPort = DatanodeDetails.newPort( - DatanodeDetails.Port.Name.RATIS, 0); - DatanodeDetails.Port restPort = DatanodeDetails.newPort( - DatanodeDetails.Port.Name.REST, 0); - return DatanodeDetails.newBuilder() - .setUuid(UUID.randomUUID().toString()) - .setHostName("localhost") - .setIpAddress("127.0.0.1") - .addPort(containerPort) - .addPort(ratisPort) - .addPort(restPort) - .build(); - } -} diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/TestKeyValueContainerData.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/TestKeyValueContainerData.java deleted file mode 100644 index f991520cc46..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/TestKeyValueContainerData.java +++ /dev/null @@ -1,88 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common; - -import org.apache.hadoop.conf.StorageUnit; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.ozone.container.keyvalue.KeyValueContainerData; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -import java.util.concurrent.atomic.AtomicLong; - -/** - * This class is used to test the KeyValueContainerData. - */ -public class TestKeyValueContainerData { - - private static final long MAXSIZE = (long) StorageUnit.GB.toBytes(5); - @Test - public void testKeyValueData() { - long containerId = 1L; - ContainerProtos.ContainerType containerType = ContainerProtos - .ContainerType.KeyValueContainer; - String path = "/tmp"; - String containerDBType = "RocksDB"; - ContainerProtos.ContainerLifeCycleState state = ContainerProtos - .ContainerLifeCycleState.CLOSED; - AtomicLong val = new AtomicLong(0); - - KeyValueContainerData kvData = new KeyValueContainerData(containerId, - MAXSIZE); - - assertEquals(containerType, kvData.getContainerType()); - assertEquals(containerId, kvData.getContainerID()); - assertEquals(ContainerProtos.ContainerLifeCycleState.OPEN, kvData - .getState()); - assertEquals(0, kvData.getMetadata().size()); - assertEquals(0, kvData.getNumPendingDeletionBlocks()); - assertEquals(val.get(), kvData.getReadBytes()); - assertEquals(val.get(), kvData.getWriteBytes()); - assertEquals(val.get(), kvData.getReadCount()); - assertEquals(val.get(), kvData.getWriteCount()); - assertEquals(val.get(), kvData.getKeyCount()); - assertEquals(val.get(), kvData.getNumPendingDeletionBlocks()); - assertEquals(MAXSIZE, kvData.getMaxSize()); - - kvData.setState(state); - kvData.setContainerDBType(containerDBType); - kvData.setChunksPath(path); - kvData.setMetadataPath(path); - kvData.incrReadBytes(10); - kvData.incrWriteBytes(10); - kvData.incrReadCount(); - kvData.incrWriteCount(); - kvData.incrKeyCount(); - kvData.incrPendingDeletionBlocks(1); - - assertEquals(state, kvData.getState()); - assertEquals(containerDBType, kvData.getContainerDBType()); - assertEquals(path, kvData.getChunksPath()); - assertEquals(path, kvData.getMetadataPath()); - - assertEquals(10, kvData.getReadBytes()); - assertEquals(10, kvData.getWriteBytes()); - assertEquals(1, kvData.getReadCount()); - assertEquals(1, kvData.getWriteCount()); - assertEquals(1, kvData.getKeyCount()); - assertEquals(1, kvData.getNumPendingDeletionBlocks()); - } - -} diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/helpers/TestDatanodeVersionFile.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/helpers/TestDatanodeVersionFile.java deleted file mode 100644 index 58892227a65..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/helpers/TestDatanodeVersionFile.java +++ /dev/null @@ -1,134 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.container.common.helpers; - -import org.apache.hadoop.ozone.common.InconsistentStorageStateException; -import org.apache.hadoop.ozone.container.common.DataNodeLayoutVersion; -import org.apache.hadoop.ozone.container.common.utils.HddsVolumeUtil; -import org.apache.hadoop.test.GenericTestUtils; -import org.apache.hadoop.util.Time; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; - -import java.io.File; -import java.io.IOException; -import java.util.Properties; -import java.util.UUID; - -import static org.junit.Assert.*; - -/** - * This class tests {@link DatanodeVersionFile}. - */ -public class TestDatanodeVersionFile { - - private File versionFile; - private DatanodeVersionFile dnVersionFile; - private Properties properties; - - private String storageID; - private String clusterID; - private String datanodeUUID; - private long cTime; - private int lv; - - @Rule - public TemporaryFolder folder= new TemporaryFolder(); - - @Before - public void setup() throws IOException { - versionFile = folder.newFile("Version"); - storageID = UUID.randomUUID().toString(); - clusterID = UUID.randomUUID().toString(); - datanodeUUID = UUID.randomUUID().toString(); - cTime = Time.now(); - lv = DataNodeLayoutVersion.getLatestVersion().getVersion(); - - dnVersionFile = new DatanodeVersionFile( - storageID, clusterID, datanodeUUID, cTime, lv); - - dnVersionFile.createVersionFile(versionFile); - - properties = dnVersionFile.readFrom(versionFile); - } - - @Test - public void testCreateAndReadVersionFile() throws IOException{ - - //Check VersionFile exists - assertTrue(versionFile.exists()); - - assertEquals(storageID, HddsVolumeUtil.getStorageID( - properties, versionFile)); - assertEquals(clusterID, HddsVolumeUtil.getClusterID( - properties, versionFile, clusterID)); - assertEquals(datanodeUUID, HddsVolumeUtil.getDatanodeUUID( - properties, versionFile, datanodeUUID)); - assertEquals(cTime, HddsVolumeUtil.getCreationTime( - properties, versionFile)); - assertEquals(lv, HddsVolumeUtil.getLayOutVersion( - properties, versionFile)); - } - - @Test - public void testIncorrectClusterId() throws IOException{ - try { - String randomClusterID = UUID.randomUUID().toString(); - HddsVolumeUtil.getClusterID(properties, versionFile, - randomClusterID); - fail("Test failure in testIncorrectClusterId"); - } catch (InconsistentStorageStateException ex) { - GenericTestUtils.assertExceptionContains("Mismatched ClusterIDs", ex); - } - } - - @Test - public void testVerifyCTime() throws IOException{ - long invalidCTime = -10; - dnVersionFile = new DatanodeVersionFile( - storageID, clusterID, datanodeUUID, invalidCTime, lv); - dnVersionFile.createVersionFile(versionFile); - properties = dnVersionFile.readFrom(versionFile); - - try { - HddsVolumeUtil.getCreationTime(properties, versionFile); - fail("Test failure in testVerifyCTime"); - } catch (InconsistentStorageStateException ex) { - GenericTestUtils.assertExceptionContains("Invalid Creation time in " + - "Version File : " + versionFile, ex); - } - } - - @Test - public void testVerifyLayOut() throws IOException{ - int invalidLayOutVersion = 100; - dnVersionFile = new DatanodeVersionFile( - storageID, clusterID, datanodeUUID, cTime, invalidLayOutVersion); - dnVersionFile.createVersionFile(versionFile); - Properties props = dnVersionFile.readFrom(versionFile); - - try { - HddsVolumeUtil.getLayOutVersion(props, versionFile); - fail("Test failure in testVerifyLayOut"); - } catch (InconsistentStorageStateException ex) { - GenericTestUtils.assertExceptionContains("Invalid layOutVersion.", ex); - } - } -} diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/impl/TestContainerDataYaml.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/impl/TestContainerDataYaml.java deleted file mode 100644 index c7b9e0aff80..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/impl/TestContainerDataYaml.java +++ /dev/null @@ -1,219 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.impl; - -import org.apache.hadoop.conf.StorageUnit; -import org.apache.hadoop.fs.FileSystemTestHelper; -import org.apache.hadoop.fs.FileUtil; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.ozone.container.common.helpers.ContainerUtils; -import org.apache.hadoop.ozone.container.keyvalue.KeyValueContainerData; -import org.apache.hadoop.test.GenericTestUtils; -import org.junit.Test; - -import java.io.File; -import java.io.IOException; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -/** - * This class tests create/read .container files. - */ -public class TestContainerDataYaml { - - private static long testContainerID = 1234; - - private static String testRoot = new FileSystemTestHelper().getTestRootDir(); - - private static final long MAXSIZE = (long) StorageUnit.GB.toBytes(5); - - /** - * Creates a .container file. cleanup() should be called at the end of the - * test when container file is created. - */ - private File createContainerFile(long containerID) throws IOException { - new File(testRoot).mkdirs(); - - String containerPath = containerID + ".container"; - - KeyValueContainerData keyValueContainerData = new KeyValueContainerData( - containerID, MAXSIZE); - keyValueContainerData.setContainerDBType("RocksDB"); - keyValueContainerData.setMetadataPath(testRoot); - keyValueContainerData.setChunksPath(testRoot); - - File containerFile = new File(testRoot, containerPath); - - // Create .container file with ContainerData - ContainerDataYaml.createContainerFile(ContainerProtos.ContainerType - .KeyValueContainer, keyValueContainerData, containerFile); - - //Check .container file exists or not. - assertTrue(containerFile.exists()); - - return containerFile; - } - - private void cleanup() { - FileUtil.fullyDelete(new File(testRoot)); - } - - @Test - public void testCreateContainerFile() throws IOException { - long containerID = testContainerID++; - - File containerFile = createContainerFile(containerID); - - // Read from .container file, and verify data. - KeyValueContainerData kvData = (KeyValueContainerData) ContainerDataYaml - .readContainerFile(containerFile); - assertEquals(containerID, kvData.getContainerID()); - assertEquals(ContainerProtos.ContainerType.KeyValueContainer, kvData - .getContainerType()); - assertEquals("RocksDB", kvData.getContainerDBType()); - assertEquals(containerFile.getParent(), kvData.getMetadataPath()); - assertEquals(containerFile.getParent(), kvData.getChunksPath()); - assertEquals(ContainerProtos.ContainerLifeCycleState.OPEN, kvData - .getState()); - assertEquals(1, kvData.getLayOutVersion()); - assertEquals(0, kvData.getMetadata().size()); - assertEquals(MAXSIZE, kvData.getMaxSize()); - - // Update ContainerData. - kvData.addMetadata("VOLUME", "hdfs"); - kvData.addMetadata("OWNER", "ozone"); - kvData.setState(ContainerProtos.ContainerLifeCycleState.CLOSED); - - - ContainerDataYaml.createContainerFile(ContainerProtos.ContainerType - .KeyValueContainer, kvData, containerFile); - - // Reading newly updated data from .container file - kvData = (KeyValueContainerData) ContainerDataYaml.readContainerFile( - containerFile); - - // verify data. - assertEquals(containerID, kvData.getContainerID()); - assertEquals(ContainerProtos.ContainerType.KeyValueContainer, kvData - .getContainerType()); - assertEquals("RocksDB", kvData.getContainerDBType()); - assertEquals(containerFile.getParent(), kvData.getMetadataPath()); - assertEquals(containerFile.getParent(), kvData.getChunksPath()); - assertEquals(ContainerProtos.ContainerLifeCycleState.CLOSED, kvData - .getState()); - assertEquals(1, kvData.getLayOutVersion()); - assertEquals(2, kvData.getMetadata().size()); - assertEquals("hdfs", kvData.getMetadata().get("VOLUME")); - assertEquals("ozone", kvData.getMetadata().get("OWNER")); - assertEquals(MAXSIZE, kvData.getMaxSize()); - } - - @Test - public void testIncorrectContainerFile() throws IOException{ - try { - String containerFile = "incorrect.container"; - //Get file from resources folder - ClassLoader classLoader = getClass().getClassLoader(); - File file = new File(classLoader.getResource(containerFile).getFile()); - KeyValueContainerData kvData = (KeyValueContainerData) ContainerDataYaml - .readContainerFile(file); - fail("testIncorrectContainerFile failed"); - } catch (IllegalStateException ex) { - GenericTestUtils.assertExceptionContains("Unexpected " + - "ContainerLifeCycleState", ex); - } - } - - - @Test - public void testCheckBackWardCompatabilityOfContainerFile() throws - IOException { - // This test is for if we upgrade, and then .container files added by new - // server will have new fields added to .container file, after a while we - // decided to rollback. Then older ozone can read .container files - // created or not. - - try { - String containerFile = "additionalfields.container"; - //Get file from resources folder - ClassLoader classLoader = getClass().getClassLoader(); - File file = new File(classLoader.getResource(containerFile).getFile()); - KeyValueContainerData kvData = (KeyValueContainerData) ContainerDataYaml - .readContainerFile(file); - ContainerUtils.verifyChecksum(kvData); - - //Checking the Container file data is consistent or not - assertEquals(ContainerProtos.ContainerLifeCycleState.CLOSED, kvData - .getState()); - assertEquals("RocksDB", kvData.getContainerDBType()); - assertEquals(ContainerProtos.ContainerType.KeyValueContainer, kvData - .getContainerType()); - assertEquals(9223372036854775807L, kvData.getContainerID()); - assertEquals("/hdds/current/aed-fg4-hji-jkl/containerDir0/1", kvData - .getChunksPath()); - assertEquals("/hdds/current/aed-fg4-hji-jkl/containerDir0/1", kvData - .getMetadataPath()); - assertEquals(1, kvData.getLayOutVersion()); - assertEquals(2, kvData.getMetadata().size()); - - } catch (Exception ex) { - ex.printStackTrace(); - fail("testCheckBackWardCompatabilityOfContainerFile failed"); - } - } - - /** - * Test to verify {@link ContainerUtils#verifyChecksum(ContainerData)}. - */ - @Test - public void testChecksumInContainerFile() throws IOException { - long containerID = testContainerID++; - - File containerFile = createContainerFile(containerID); - - // Read from .container file, and verify data. - KeyValueContainerData kvData = (KeyValueContainerData) ContainerDataYaml - .readContainerFile(containerFile); - ContainerUtils.verifyChecksum(kvData); - - cleanup(); - } - - /** - * Test to verify incorrect checksum is detected. - */ - @Test - public void testIncorrectChecksum() { - try { - String containerFile = "incorrect.checksum.container"; - //Get file from resources folder - ClassLoader classLoader = getClass().getClassLoader(); - File file = new File(classLoader.getResource(containerFile).getFile()); - KeyValueContainerData kvData = (KeyValueContainerData) ContainerDataYaml - .readContainerFile(file); - ContainerUtils.verifyChecksum(kvData); - fail("testIncorrectChecksum failed"); - } catch (Exception ex) { - GenericTestUtils.assertExceptionContains("Container checksum error for " + - "ContainerID:", ex); - } - } -} diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/impl/TestContainerSet.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/impl/TestContainerSet.java deleted file mode 100644 index af322eaecc5..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/impl/TestContainerSet.java +++ /dev/null @@ -1,182 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.container.common.impl; - -import org.apache.hadoop.conf.StorageUnit; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerReportsProto; -import org.apache.hadoop.hdds.scm.container.common.helpers.StorageContainerException; -import org.apache.hadoop.ozone.container.common.interfaces.Container; - -import org.apache.hadoop.ozone.container.keyvalue.KeyValueContainer; -import org.apache.hadoop.ozone.container.keyvalue.KeyValueContainerData; -import org.apache.hadoop.test.GenericTestUtils; -import org.junit.Test; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -/** - * Class used to test ContainerSet operations. - */ -public class TestContainerSet { - - @Test - public void testAddGetRemoveContainer() throws StorageContainerException { - ContainerSet containerSet = new ContainerSet(); - long containerId = 100L; - ContainerProtos.ContainerLifeCycleState state = ContainerProtos - .ContainerLifeCycleState.CLOSED; - - KeyValueContainerData kvData = new KeyValueContainerData(containerId, - (long) StorageUnit.GB.toBytes(5)); - kvData.setState(state); - KeyValueContainer keyValueContainer = new KeyValueContainer(kvData, new - OzoneConfiguration()); - - //addContainer - boolean result = containerSet.addContainer(keyValueContainer); - assertTrue(result); - try { - result = containerSet.addContainer(keyValueContainer); - fail("Adding same container ID twice should fail."); - } catch (StorageContainerException ex) { - GenericTestUtils.assertExceptionContains("Container already exists with" + - " container Id " + containerId, ex); - } - - //getContainer - KeyValueContainer container = (KeyValueContainer) containerSet - .getContainer(containerId); - KeyValueContainerData keyValueContainerData = (KeyValueContainerData) - container.getContainerData(); - assertEquals(containerId, keyValueContainerData.getContainerID()); - assertEquals(state, keyValueContainerData.getState()); - assertNull(containerSet.getContainer(1000L)); - - //removeContainer - assertTrue(containerSet.removeContainer(containerId)); - assertFalse(containerSet.removeContainer(1000L)); - } - - @Test - public void testIteratorsAndCount() throws StorageContainerException { - - ContainerSet containerSet = createContainerSet(); - - assertEquals(10, containerSet.containerCount()); - - // Using containerIterator. - Iterator containerIterator = containerSet.getContainerIterator(); - - int count = 0; - while(containerIterator.hasNext()) { - Container kv = containerIterator.next(); - ContainerData containerData = kv.getContainerData(); - long containerId = containerData.getContainerID(); - if (containerId%2 == 0) { - assertEquals(ContainerProtos.ContainerLifeCycleState.CLOSED, - containerData.getState()); - } else { - assertEquals(ContainerProtos.ContainerLifeCycleState.OPEN, - containerData.getState()); - } - count++; - } - assertEquals(10, count); - - //Using containerMapIterator. - Iterator> containerMapIterator = containerSet - .getContainerMapIterator(); - - count = 0; - while (containerMapIterator.hasNext()) { - Container kv = containerMapIterator.next().getValue(); - ContainerData containerData = kv.getContainerData(); - long containerId = containerData.getContainerID(); - if (containerId%2 == 0) { - assertEquals(ContainerProtos.ContainerLifeCycleState.CLOSED, - containerData.getState()); - } else { - assertEquals(ContainerProtos.ContainerLifeCycleState.OPEN, - containerData.getState()); - } - count++; - } - assertEquals(10, count); - - } - - - @Test - public void testGetContainerReport() throws IOException { - - ContainerSet containerSet = createContainerSet(); - - ContainerReportsProto containerReportsRequestProto = containerSet - .getContainerReport(); - - assertEquals(10, containerReportsRequestProto.getReportsList().size()); - } - - - - @Test - public void testListContainer() throws StorageContainerException { - ContainerSet containerSet = createContainerSet(); - - List result = new ArrayList<>(); - containerSet.listContainer(2, 5, result); - - assertEquals(5, result.size()); - - for(ContainerData containerData : result) { - assertTrue(containerData.getContainerID() >=2 && containerData - .getContainerID()<=6); - } - } - - private ContainerSet createContainerSet() throws StorageContainerException { - ContainerSet containerSet = new ContainerSet(); - for (int i=0; i<10; i++) { - KeyValueContainerData kvData = new KeyValueContainerData(i, - (long) StorageUnit.GB.toBytes(5)); - if (i%2 == 0) { - kvData.setState(ContainerProtos.ContainerLifeCycleState.CLOSED); - } else { - kvData.setState(ContainerProtos.ContainerLifeCycleState.OPEN); - } - KeyValueContainer kv = new KeyValueContainer(kvData, new - OzoneConfiguration()); - containerSet.addContainer(kv); - } - return containerSet; - } - -} diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/impl/TestHddsDispatcher.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/impl/TestHddsDispatcher.java deleted file mode 100644 index fc622b2d195..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/impl/TestHddsDispatcher.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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.impl; - -import org.apache.commons.codec.digest.DigestUtils; -import org.apache.commons.io.FileUtils; -import org.apache.hadoop.conf.StorageUnit; -import org.apache.hadoop.hdds.client.BlockID; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdds.protocol.datanode.proto - .ContainerProtos.ContainerCommandResponseProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandRequestProto; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .WriteChunkRequestProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerAction; -import org.apache.hadoop.ozone.container.common.interfaces.Container; -import org.apache.hadoop.ozone.container.common.statemachine.StateContext; -import org.apache.hadoop.ozone.container.common.volume.RoundRobinVolumeChoosingPolicy; -import org.apache.hadoop.ozone.container.common.volume.VolumeSet; -import org.apache.hadoop.ozone.container.keyvalue.KeyValueContainer; -import org.apache.hadoop.ozone.container.keyvalue.KeyValueContainerData; -import org.apache.hadoop.test.GenericTestUtils; -import org.apache.ratis.shaded.com.google.protobuf.ByteString; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import java.io.File; -import java.io.IOException; -import java.util.UUID; - -import static org.apache.hadoop.hdds.scm.ScmConfigKeys.HDDS_DATANODE_DIR_KEY; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -/** - * Test-cases to verify the functionality of HddsDispatcher. - */ -public class TestHddsDispatcher { - - @Test - public void testContainerCloseActionWhenFull() throws IOException { - String testDir = GenericTestUtils.getTempPath( - TestHddsDispatcher.class.getSimpleName()); - try { - UUID scmId = UUID.randomUUID(); - OzoneConfiguration conf = new OzoneConfiguration(); - conf.set(HDDS_DATANODE_DIR_KEY, testDir); - DatanodeDetails dd = randomDatanodeDetails(); - ContainerSet containerSet = new ContainerSet(); - VolumeSet volumeSet = new VolumeSet(dd.getUuidString(), conf); - StateContext context = Mockito.mock(StateContext.class); - KeyValueContainerData containerData = new KeyValueContainerData(1L, - (long) StorageUnit.GB.toBytes(1)); - Container container = new KeyValueContainer(containerData, conf); - container.create(volumeSet, new RoundRobinVolumeChoosingPolicy(), - scmId.toString()); - containerSet.addContainer(container); - HddsDispatcher hddsDispatcher = new HddsDispatcher( - conf, containerSet, volumeSet, context); - hddsDispatcher.setScmId(scmId.toString()); - ContainerCommandResponseProto responseOne = hddsDispatcher.dispatch( - getWriteChunkRequest(dd.getUuidString(), 1L, 1L)); - Assert.assertEquals(ContainerProtos.Result.SUCCESS, - responseOne.getResult()); - verify(context, times(0)) - .addContainerActionIfAbsent(Mockito.any(ContainerAction.class)); - containerData.setBytesUsed(Double.valueOf( - StorageUnit.MB.toBytes(950)).longValue()); - ContainerCommandResponseProto responseTwo = hddsDispatcher.dispatch( - getWriteChunkRequest(dd.getUuidString(), 1L, 2L)); - Assert.assertEquals(ContainerProtos.Result.SUCCESS, - responseTwo.getResult()); - verify(context, times(1)) - .addContainerActionIfAbsent(Mockito.any(ContainerAction.class)); - - } finally { - FileUtils.deleteDirectory(new File(testDir)); - } - - } - - // This method has to be removed once we move scm/TestUtils.java - // from server-scm project to container-service or to common project. - private static DatanodeDetails randomDatanodeDetails() { - DatanodeDetails.Port containerPort = DatanodeDetails.newPort( - DatanodeDetails.Port.Name.STANDALONE, 0); - DatanodeDetails.Port ratisPort = DatanodeDetails.newPort( - DatanodeDetails.Port.Name.RATIS, 0); - DatanodeDetails.Port restPort = DatanodeDetails.newPort( - DatanodeDetails.Port.Name.REST, 0); - DatanodeDetails.Builder builder = DatanodeDetails.newBuilder(); - builder.setUuid(UUID.randomUUID().toString()) - .setHostName("localhost") - .setIpAddress("127.0.0.1") - .addPort(containerPort) - .addPort(ratisPort) - .addPort(restPort); - return builder.build(); - } - - private ContainerCommandRequestProto getWriteChunkRequest( - String datanodeId, Long containerId, Long localId) { - - ByteString data = ByteString.copyFrom( - UUID.randomUUID().toString().getBytes()); - ContainerProtos.ChunkInfo chunk = ContainerProtos.ChunkInfo - .newBuilder() - .setChunkName( - DigestUtils.md5Hex("dummy-key") + "_stream_" - + containerId + "_chunk_" + localId) - .setOffset(0) - .setLen(data.size()) - .build(); - - WriteChunkRequestProto.Builder writeChunkRequest = WriteChunkRequestProto - .newBuilder() - .setBlockID(new BlockID(containerId, localId) - .getDatanodeBlockIDProtobuf()) - .setChunkData(chunk) - .setData(data); - - return ContainerCommandRequestProto - .newBuilder() - .setContainerID(containerId) - .setCmdType(ContainerProtos.Type.WriteChunk) - .setTraceID(UUID.randomUUID().toString()) - .setDatanodeUuid(datanodeId) - .setWriteChunk(writeChunkRequest) - .build(); - } - -} \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/impl/package-info.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/impl/package-info.java deleted file mode 100644 index 07c78c04989..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/impl/package-info.java +++ /dev/null @@ -1,22 +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 - * - * 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. - * - */ -/** - * Datanode container related test-cases. - */ -package org.apache.hadoop.ozone.container.common.impl; \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/interfaces/TestHandler.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/interfaces/TestHandler.java deleted file mode 100644 index b6582952bbd..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/interfaces/TestHandler.java +++ /dev/null @@ -1,80 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.interfaces; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.ozone.container.common.impl.ContainerSet; -import org.apache.hadoop.ozone.container.common.impl.HddsDispatcher; -import org.apache.hadoop.ozone.container.common.volume.VolumeSet; -import org.apache.hadoop.ozone.container.keyvalue.KeyValueHandler; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestRule; -import org.junit.rules.Timeout; -import org.mockito.Mockito; - -/** - * Tests Handler interface. - */ -public class TestHandler { - @Rule - public TestRule timeout = new Timeout(300000); - - private Configuration conf; - private HddsDispatcher dispatcher; - private ContainerSet containerSet; - private VolumeSet volumeSet; - private Handler handler; - - @Before - public void setup() throws Exception { - this.conf = new Configuration(); - this.containerSet = Mockito.mock(ContainerSet.class); - this.volumeSet = Mockito.mock(VolumeSet.class); - - this.dispatcher = new HddsDispatcher(conf, containerSet, volumeSet, null); - } - - @Test - public void testGetKeyValueHandler() throws Exception { - Handler kvHandler = dispatcher.getHandler( - ContainerProtos.ContainerType.KeyValueContainer); - - Assert.assertTrue("getHandlerForContainerType returned incorrect handler", - (kvHandler instanceof KeyValueHandler)); - } - - @Test - public void testGetHandlerForInvalidContainerType() { - // When new ContainerProtos.ContainerType are added, increment the code - // for invalid enum. - ContainerProtos.ContainerType invalidContainerType = - ContainerProtos.ContainerType.forNumber(2); - - Assert.assertEquals("New ContainerType detected. Not an invalid " + - "containerType", invalidContainerType, null); - - Handler handler = dispatcher.getHandler(invalidContainerType); - Assert.assertEquals("Get Handler for Invalid ContainerType should " + - "return null.", handler, null); - } -} diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/package-info.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/package-info.java deleted file mode 100644 index ca3d29dada1..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/package-info.java +++ /dev/null @@ -1,22 +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 - * - * 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. - * - */ -/** - * SCM Testing and Mocking Utils. - */ -package org.apache.hadoop.ozone.container.common; \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/report/TestReportManager.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/report/TestReportManager.java deleted file mode 100644 index aae388dd5a1..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/report/TestReportManager.java +++ /dev/null @@ -1,52 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.container.common.report; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.ozone.container.common.statemachine.StateContext; -import org.junit.Test; -import org.mockito.Mockito; - -import java.util.concurrent.ScheduledExecutorService; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -/** - * Test cases to test {@link ReportManager}. - */ -public class TestReportManager { - - @Test - public void testReportManagerInit() { - Configuration conf = new OzoneConfiguration(); - StateContext dummyContext = Mockito.mock(StateContext.class); - ReportPublisher dummyPublisher = Mockito.mock(ReportPublisher.class); - ReportManager.Builder builder = ReportManager.newBuilder(conf); - builder.setStateContext(dummyContext); - builder.addPublisher(dummyPublisher); - ReportManager reportManager = builder.build(); - reportManager.init(); - verify(dummyPublisher, times(1)).init(eq(dummyContext), - any(ScheduledExecutorService.class)); - - } -} diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/report/TestReportPublisher.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/report/TestReportPublisher.java deleted file mode 100644 index 1e82326ff4a..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/report/TestReportPublisher.java +++ /dev/null @@ -1,200 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.container.common.report; - -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import com.google.protobuf.GeneratedMessage; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.HddsIdFactory; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto. - StorageContainerDatanodeProtocolProtos.CommandStatus.Status; -import org.apache.hadoop.hdds.protocol.proto. - StorageContainerDatanodeProtocolProtos.SCMCommandProto.Type; -import org.apache.hadoop.ozone.container.common.statemachine.StateContext; -import org.apache.hadoop.ozone.protocol.commands.CommandStatus; -import org.apache.hadoop.util.concurrent.HadoopExecutors; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import org.mockito.Mockito; - -import java.util.Random; -import java.util.UUID; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -/** - * Test cases to test {@link ReportPublisher}. - */ -public class TestReportPublisher { - - private static Configuration config; - - @BeforeClass - public static void setup() { - config = new OzoneConfiguration(); - } - - /** - * Dummy report publisher for testing. - */ - private class DummyReportPublisher extends ReportPublisher { - - private final long frequency; - private int getReportCount = 0; - - DummyReportPublisher(long frequency) { - this.frequency = frequency; - } - - @Override - protected long getReportFrequency() { - return frequency; - } - - @Override - protected GeneratedMessage getReport() { - getReportCount++; - return null; - } - } - - @Test - public void testReportPublisherInit() { - ReportPublisher publisher = new DummyReportPublisher(0); - StateContext dummyContext = Mockito.mock(StateContext.class); - ScheduledExecutorService dummyExecutorService = Mockito.mock( - ScheduledExecutorService.class); - publisher.init(dummyContext, dummyExecutorService); - verify(dummyExecutorService, times(1)).schedule(publisher, - 0, TimeUnit.MILLISECONDS); - } - - @Test - public void testScheduledReport() throws InterruptedException { - ReportPublisher publisher = new DummyReportPublisher(100); - StateContext dummyContext = Mockito.mock(StateContext.class); - ScheduledExecutorService executorService = HadoopExecutors - .newScheduledThreadPool(1, - new ThreadFactoryBuilder().setDaemon(true) - .setNameFormat("Unit test ReportManager Thread - %d").build()); - publisher.init(dummyContext, executorService); - Thread.sleep(150); - Assert.assertEquals(1, ((DummyReportPublisher) publisher).getReportCount); - Thread.sleep(100); - Assert.assertEquals(2, ((DummyReportPublisher) publisher).getReportCount); - executorService.shutdown(); - } - - @Test - public void testPublishReport() throws InterruptedException { - ReportPublisher publisher = new DummyReportPublisher(100); - StateContext dummyContext = Mockito.mock(StateContext.class); - ScheduledExecutorService executorService = HadoopExecutors - .newScheduledThreadPool(1, - new ThreadFactoryBuilder().setDaemon(true) - .setNameFormat("Unit test ReportManager Thread - %d").build()); - publisher.init(dummyContext, executorService); - Thread.sleep(150); - executorService.shutdown(); - Assert.assertEquals(1, ((DummyReportPublisher) publisher).getReportCount); - verify(dummyContext, times(1)).addReport(null); - - } - - @Test - public void testCommandStatusPublisher() throws InterruptedException { - StateContext dummyContext = Mockito.mock(StateContext.class); - ReportPublisher publisher = new CommandStatusReportPublisher(); - final Map cmdStatusMap = new ConcurrentHashMap<>(); - when(dummyContext.getCommandStatusMap()).thenReturn(cmdStatusMap); - publisher.setConf(config); - - ScheduledExecutorService executorService = HadoopExecutors - .newScheduledThreadPool(1, - new ThreadFactoryBuilder().setDaemon(true) - .setNameFormat("Unit test ReportManager Thread - %d").build()); - publisher.init(dummyContext, executorService); - Assert.assertNull(((CommandStatusReportPublisher) publisher).getReport()); - - // Insert to status object to state context map and then get the report. - CommandStatus obj1 = CommandStatus.CommandStatusBuilder.newBuilder() - .setCmdId(HddsIdFactory.getLongId()) - .setType(Type.deleteBlocksCommand) - .setStatus(Status.PENDING) - .build(); - CommandStatus obj2 = CommandStatus.CommandStatusBuilder.newBuilder() - .setCmdId(HddsIdFactory.getLongId()) - .setType(Type.closeContainerCommand) - .setStatus(Status.EXECUTED) - .build(); - cmdStatusMap.put(obj1.getCmdId(), obj1); - cmdStatusMap.put(obj2.getCmdId(), obj2); - Assert.assertEquals("Should publish report with 2 status objects", 2, - ((CommandStatusReportPublisher) publisher).getReport() - .getCmdStatusCount()); - Assert.assertEquals( - "Next report should have 1 status objects as command status o" - + "bjects are still in Pending state", - 1, ((CommandStatusReportPublisher) publisher).getReport() - .getCmdStatusCount()); - Assert.assertTrue( - "Next report should have 1 status objects as command status " - + "objects are still in Pending state", - ((CommandStatusReportPublisher) publisher).getReport() - .getCmdStatusList().get(0).getStatus().equals(Status.PENDING)); - executorService.shutdown(); - } - - /** - * Get a datanode details. - * - * @return DatanodeDetails - */ - private static DatanodeDetails getDatanodeDetails() { - String uuid = UUID.randomUUID().toString(); - Random random = new Random(); - String ipAddress = - random.nextInt(256) + "." + random.nextInt(256) + "." + random - .nextInt(256) + "." + random.nextInt(256); - - DatanodeDetails.Port containerPort = DatanodeDetails.newPort( - DatanodeDetails.Port.Name.STANDALONE, 0); - DatanodeDetails.Port ratisPort = DatanodeDetails.newPort( - DatanodeDetails.Port.Name.RATIS, 0); - DatanodeDetails.Port restPort = DatanodeDetails.newPort( - DatanodeDetails.Port.Name.REST, 0); - DatanodeDetails.Builder builder = DatanodeDetails.newBuilder(); - builder.setUuid(uuid) - .setHostName("localhost") - .setIpAddress(ipAddress) - .addPort(containerPort) - .addPort(ratisPort) - .addPort(restPort); - return builder.build(); - } - -} diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/report/TestReportPublisherFactory.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/report/TestReportPublisherFactory.java deleted file mode 100644 index f8c5fe5e275..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/report/TestReportPublisherFactory.java +++ /dev/null @@ -1,68 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.container.common.report; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerReportsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.NodeReportProto; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -/** - * Test cases to test ReportPublisherFactory. - */ -public class TestReportPublisherFactory { - - @Rule - public ExpectedException exception = ExpectedException.none(); - - @Test - public void testGetContainerReportPublisher() { - Configuration conf = new OzoneConfiguration(); - ReportPublisherFactory factory = new ReportPublisherFactory(conf); - ReportPublisher publisher = factory - .getPublisherFor(ContainerReportsProto.class); - Assert.assertEquals(ContainerReportPublisher.class, publisher.getClass()); - Assert.assertEquals(conf, publisher.getConf()); - } - - @Test - public void testGetNodeReportPublisher() { - Configuration conf = new OzoneConfiguration(); - ReportPublisherFactory factory = new ReportPublisherFactory(conf); - ReportPublisher publisher = factory - .getPublisherFor(NodeReportProto.class); - Assert.assertEquals(NodeReportPublisher.class, publisher.getClass()); - Assert.assertEquals(conf, publisher.getConf()); - } - - @Test - public void testInvalidReportPublisher() { - Configuration conf = new OzoneConfiguration(); - ReportPublisherFactory factory = new ReportPublisherFactory(conf); - exception.expect(RuntimeException.class); - exception.expectMessage("No publisher found for report"); - factory.getPublisherFor(HddsProtos.DatanodeDetailsProto.class); - } -} diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/report/package-info.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/report/package-info.java deleted file mode 100644 index 37615bc7536..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/report/package-info.java +++ /dev/null @@ -1,22 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.common.report; -/** - * This package has test cases for all the report publishers which generates - * reports that are sent to SCM via heartbeat. - */ \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/package-info.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/package-info.java deleted file mode 100644 index 05ac76d1439..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/package-info.java +++ /dev/null @@ -1,22 +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 - * - * 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. - */ - -/** - * Tests for command handlers. - */ -package org.apache.hadoop.ozone.container.common.statemachine.commandhandler; diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/states/endpoint/TestHeartbeatEndpointTask.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/states/endpoint/TestHeartbeatEndpointTask.java deleted file mode 100644 index 606940b5106..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/states/endpoint/TestHeartbeatEndpointTask.java +++ /dev/null @@ -1,295 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.states.endpoint; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerAction; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.CommandStatusReportsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerReportsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.NodeReportProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMHeartbeatResponseProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMHeartbeatRequestProto; -import org.apache.hadoop.ozone.container.common.statemachine - .DatanodeStateMachine; -import org.apache.hadoop.ozone.container.common.statemachine - .DatanodeStateMachine.DatanodeStates; -import org.apache.hadoop.ozone.container.common.statemachine - .EndpointStateMachine; -import org.apache.hadoop.ozone.container.common.statemachine.StateContext; -import org.apache.hadoop.ozone.protocolPB - .StorageContainerDatanodeProtocolClientSideTranslatorPB; - -import org.junit.Assert; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; - -import java.util.UUID; - -/** - * This class tests the functionality of HeartbeatEndpointTask. - */ -public class TestHeartbeatEndpointTask { - - - @Test - public void testheartbeatWithoutReports() throws Exception { - StorageContainerDatanodeProtocolClientSideTranslatorPB scm = - Mockito.mock( - StorageContainerDatanodeProtocolClientSideTranslatorPB.class); - ArgumentCaptor argument = ArgumentCaptor - .forClass(SCMHeartbeatRequestProto.class); - Mockito.when(scm.sendHeartbeat(argument.capture())) - .thenAnswer(invocation -> - SCMHeartbeatResponseProto.newBuilder() - .setDatanodeUUID( - ((SCMHeartbeatRequestProto)invocation.getArgument(0)) - .getDatanodeDetails().getUuid()) - .build()); - - HeartbeatEndpointTask endpointTask = getHeartbeatEndpointTask(scm); - endpointTask.call(); - SCMHeartbeatRequestProto heartbeat = argument.getValue(); - Assert.assertTrue(heartbeat.hasDatanodeDetails()); - Assert.assertFalse(heartbeat.hasNodeReport()); - Assert.assertFalse(heartbeat.hasContainerReport()); - Assert.assertTrue(heartbeat.getCommandStatusReportsCount() == 0); - Assert.assertFalse(heartbeat.hasContainerActions()); - } - - @Test - public void testheartbeatWithNodeReports() throws Exception { - Configuration conf = new OzoneConfiguration(); - StateContext context = new StateContext(conf, DatanodeStates.RUNNING, - Mockito.mock(DatanodeStateMachine.class)); - - StorageContainerDatanodeProtocolClientSideTranslatorPB scm = - Mockito.mock( - StorageContainerDatanodeProtocolClientSideTranslatorPB.class); - ArgumentCaptor argument = ArgumentCaptor - .forClass(SCMHeartbeatRequestProto.class); - Mockito.when(scm.sendHeartbeat(argument.capture())) - .thenAnswer(invocation -> - SCMHeartbeatResponseProto.newBuilder() - .setDatanodeUUID( - ((SCMHeartbeatRequestProto)invocation.getArgument(0)) - .getDatanodeDetails().getUuid()) - .build()); - - HeartbeatEndpointTask endpointTask = getHeartbeatEndpointTask( - conf, context, scm); - context.addReport(NodeReportProto.getDefaultInstance()); - endpointTask.call(); - SCMHeartbeatRequestProto heartbeat = argument.getValue(); - Assert.assertTrue(heartbeat.hasDatanodeDetails()); - Assert.assertTrue(heartbeat.hasNodeReport()); - Assert.assertFalse(heartbeat.hasContainerReport()); - Assert.assertTrue(heartbeat.getCommandStatusReportsCount() == 0); - Assert.assertFalse(heartbeat.hasContainerActions()); - } - - @Test - public void testheartbeatWithContainerReports() throws Exception { - Configuration conf = new OzoneConfiguration(); - StateContext context = new StateContext(conf, DatanodeStates.RUNNING, - Mockito.mock(DatanodeStateMachine.class)); - - StorageContainerDatanodeProtocolClientSideTranslatorPB scm = - Mockito.mock( - StorageContainerDatanodeProtocolClientSideTranslatorPB.class); - ArgumentCaptor argument = ArgumentCaptor - .forClass(SCMHeartbeatRequestProto.class); - Mockito.when(scm.sendHeartbeat(argument.capture())) - .thenAnswer(invocation -> - SCMHeartbeatResponseProto.newBuilder() - .setDatanodeUUID( - ((SCMHeartbeatRequestProto)invocation.getArgument(0)) - .getDatanodeDetails().getUuid()) - .build()); - - HeartbeatEndpointTask endpointTask = getHeartbeatEndpointTask( - conf, context, scm); - context.addReport(ContainerReportsProto.getDefaultInstance()); - endpointTask.call(); - SCMHeartbeatRequestProto heartbeat = argument.getValue(); - Assert.assertTrue(heartbeat.hasDatanodeDetails()); - Assert.assertFalse(heartbeat.hasNodeReport()); - Assert.assertTrue(heartbeat.hasContainerReport()); - Assert.assertTrue(heartbeat.getCommandStatusReportsCount() == 0); - Assert.assertFalse(heartbeat.hasContainerActions()); - } - - @Test - public void testheartbeatWithCommandStatusReports() throws Exception { - Configuration conf = new OzoneConfiguration(); - StateContext context = new StateContext(conf, DatanodeStates.RUNNING, - Mockito.mock(DatanodeStateMachine.class)); - - StorageContainerDatanodeProtocolClientSideTranslatorPB scm = - Mockito.mock( - StorageContainerDatanodeProtocolClientSideTranslatorPB.class); - ArgumentCaptor argument = ArgumentCaptor - .forClass(SCMHeartbeatRequestProto.class); - Mockito.when(scm.sendHeartbeat(argument.capture())) - .thenAnswer(invocation -> - SCMHeartbeatResponseProto.newBuilder() - .setDatanodeUUID( - ((SCMHeartbeatRequestProto)invocation.getArgument(0)) - .getDatanodeDetails().getUuid()) - .build()); - - HeartbeatEndpointTask endpointTask = getHeartbeatEndpointTask( - conf, context, scm); - context.addReport(CommandStatusReportsProto.getDefaultInstance()); - endpointTask.call(); - SCMHeartbeatRequestProto heartbeat = argument.getValue(); - Assert.assertTrue(heartbeat.hasDatanodeDetails()); - Assert.assertFalse(heartbeat.hasNodeReport()); - Assert.assertFalse(heartbeat.hasContainerReport()); - Assert.assertTrue(heartbeat.getCommandStatusReportsCount() != 0); - Assert.assertFalse(heartbeat.hasContainerActions()); - } - - @Test - public void testheartbeatWithContainerActions() throws Exception { - Configuration conf = new OzoneConfiguration(); - StateContext context = new StateContext(conf, DatanodeStates.RUNNING, - Mockito.mock(DatanodeStateMachine.class)); - - StorageContainerDatanodeProtocolClientSideTranslatorPB scm = - Mockito.mock( - StorageContainerDatanodeProtocolClientSideTranslatorPB.class); - ArgumentCaptor argument = ArgumentCaptor - .forClass(SCMHeartbeatRequestProto.class); - Mockito.when(scm.sendHeartbeat(argument.capture())) - .thenAnswer(invocation -> - SCMHeartbeatResponseProto.newBuilder() - .setDatanodeUUID( - ((SCMHeartbeatRequestProto)invocation.getArgument(0)) - .getDatanodeDetails().getUuid()) - .build()); - - HeartbeatEndpointTask endpointTask = getHeartbeatEndpointTask( - conf, context, scm); - context.addContainerAction(getContainerAction()); - endpointTask.call(); - SCMHeartbeatRequestProto heartbeat = argument.getValue(); - Assert.assertTrue(heartbeat.hasDatanodeDetails()); - Assert.assertFalse(heartbeat.hasNodeReport()); - Assert.assertFalse(heartbeat.hasContainerReport()); - Assert.assertTrue(heartbeat.getCommandStatusReportsCount() == 0); - Assert.assertTrue(heartbeat.hasContainerActions()); - } - - @Test - public void testheartbeatWithAllReports() throws Exception { - Configuration conf = new OzoneConfiguration(); - StateContext context = new StateContext(conf, DatanodeStates.RUNNING, - Mockito.mock(DatanodeStateMachine.class)); - - StorageContainerDatanodeProtocolClientSideTranslatorPB scm = - Mockito.mock( - StorageContainerDatanodeProtocolClientSideTranslatorPB.class); - ArgumentCaptor argument = ArgumentCaptor - .forClass(SCMHeartbeatRequestProto.class); - Mockito.when(scm.sendHeartbeat(argument.capture())) - .thenAnswer(invocation -> - SCMHeartbeatResponseProto.newBuilder() - .setDatanodeUUID( - ((SCMHeartbeatRequestProto)invocation.getArgument(0)) - .getDatanodeDetails().getUuid()) - .build()); - - HeartbeatEndpointTask endpointTask = getHeartbeatEndpointTask( - conf, context, scm); - context.addReport(NodeReportProto.getDefaultInstance()); - context.addReport(ContainerReportsProto.getDefaultInstance()); - context.addReport(CommandStatusReportsProto.getDefaultInstance()); - context.addContainerAction(getContainerAction()); - endpointTask.call(); - SCMHeartbeatRequestProto heartbeat = argument.getValue(); - Assert.assertTrue(heartbeat.hasDatanodeDetails()); - Assert.assertTrue(heartbeat.hasNodeReport()); - Assert.assertTrue(heartbeat.hasContainerReport()); - Assert.assertTrue(heartbeat.getCommandStatusReportsCount() != 0); - Assert.assertTrue(heartbeat.hasContainerActions()); - } - - /** - * Creates HeartbeatEndpointTask for the given StorageContainerManager proxy. - * - * @param proxy StorageContainerDatanodeProtocolClientSideTranslatorPB - * - * @return HeartbeatEndpointTask - */ - private HeartbeatEndpointTask getHeartbeatEndpointTask( - StorageContainerDatanodeProtocolClientSideTranslatorPB proxy) { - Configuration conf = new OzoneConfiguration(); - StateContext context = new StateContext(conf, DatanodeStates.RUNNING, - Mockito.mock(DatanodeStateMachine.class)); - return getHeartbeatEndpointTask(conf, context, proxy); - - } - - /** - * Creates HeartbeatEndpointTask with the given conf, context and - * StorageContainerManager client side proxy. - * - * @param conf Configuration - * @param context StateContext - * @param proxy StorageContainerDatanodeProtocolClientSideTranslatorPB - * - * @return HeartbeatEndpointTask - */ - private HeartbeatEndpointTask getHeartbeatEndpointTask( - Configuration conf, - StateContext context, - StorageContainerDatanodeProtocolClientSideTranslatorPB proxy) { - DatanodeDetails datanodeDetails = DatanodeDetails.newBuilder() - .setUuid(UUID.randomUUID().toString()) - .setHostName("localhost") - .setIpAddress("127.0.0.1") - .build(); - EndpointStateMachine endpointStateMachine = Mockito - .mock(EndpointStateMachine.class); - Mockito.when(endpointStateMachine.getEndPoint()).thenReturn(proxy); - return HeartbeatEndpointTask.newBuilder() - .setConfig(conf) - .setDatanodeDetails(datanodeDetails) - .setContext(context) - .setEndpointStateMachine(endpointStateMachine) - .build(); - } - - private ContainerAction getContainerAction() { - ContainerAction.Builder builder = ContainerAction.newBuilder(); - builder.setContainerID(1L) - .setAction(ContainerAction.Action.CLOSE) - .setReason(ContainerAction.Reason.CONTAINER_FULL); - return builder.build(); - } -} \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/states/endpoint/package-info.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/states/endpoint/package-info.java deleted file mode 100644 index d120a5cd4b7..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/states/endpoint/package-info.java +++ /dev/null @@ -1,18 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.container.common.states.endpoint; diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/volume/TestHddsVolume.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/volume/TestHddsVolume.java deleted file mode 100644 index 7755345d42a..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/volume/TestHddsVolume.java +++ /dev/null @@ -1,145 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.volume; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.GetSpaceUsed; -import org.apache.hadoop.fs.StorageType; -import org.apache.hadoop.ozone.container.common.helpers.DatanodeVersionFile; -import org.apache.hadoop.ozone.container.common.utils.HddsVolumeUtil; -import static org.junit.Assert.*; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.mockito.Mockito; - -import java.io.File; -import java.util.Properties; -import java.util.UUID; - -/** - * Unit tests for {@link HddsVolume}. - */ -public class TestHddsVolume { - - @Rule - public TemporaryFolder folder = new TemporaryFolder(); - - private static final String DATANODE_UUID = UUID.randomUUID().toString(); - private static final String CLUSTER_ID = UUID.randomUUID().toString(); - private static final Configuration CONF = new Configuration(); - private static final String DU_CACHE_FILE = "scmUsed"; - - private File rootDir; - private HddsVolume volume; - private File versionFile; - - @Before - public void setup() throws Exception { - rootDir = new File(folder.getRoot(), HddsVolume.HDDS_VOLUME_DIR); - volume = new HddsVolume.Builder(folder.getRoot().getPath()) - .datanodeUuid(DATANODE_UUID) - .conf(CONF) - .build(); - versionFile = HddsVolumeUtil.getVersionFile(rootDir); - } - - @Test - public void testHddsVolumeInitialization() throws Exception { - - // The initial state of HddsVolume should be "NOT_FORMATTED" when - // clusterID is not specified and the version file should not be written - // to disk. - assertTrue(volume.getClusterID() == null); - assertEquals(volume.getStorageType(), StorageType.DEFAULT); - assertEquals(volume.getStorageState(), - HddsVolume.VolumeState.NOT_FORMATTED); - assertFalse("Version file should not be created when clusterID is not " + - "known.", versionFile.exists()); - - - // Format the volume with clusterID. - volume.format(CLUSTER_ID); - - // The state of HddsVolume after formatting with clusterID should be - // NORMAL and the version file should exist. - assertTrue("Volume format should create Version file", - versionFile.exists()); - assertEquals(volume.getClusterID(), CLUSTER_ID); - assertEquals(volume.getStorageState(), HddsVolume.VolumeState.NORMAL); - } - - @Test - public void testReadPropertiesFromVersionFile() throws Exception { - volume.format(CLUSTER_ID); - - Properties properties = DatanodeVersionFile.readFrom(versionFile); - - String storageID = HddsVolumeUtil.getStorageID(properties, versionFile); - String clusterID = HddsVolumeUtil.getClusterID( - properties, versionFile, CLUSTER_ID); - String datanodeUuid = HddsVolumeUtil.getDatanodeUUID( - properties, versionFile, DATANODE_UUID); - long cTime = HddsVolumeUtil.getCreationTime( - properties, versionFile); - int layoutVersion = HddsVolumeUtil.getLayOutVersion( - properties, versionFile); - - assertEquals(volume.getStorageID(), storageID); - assertEquals(volume.getClusterID(), clusterID); - assertEquals(volume.getDatanodeUuid(), datanodeUuid); - assertEquals(volume.getCTime(), cTime); - assertEquals(volume.getLayoutVersion(), layoutVersion); - } - - @Test - public void testShutdown() throws Exception{ - // Return dummy value > 0 for scmUsage so that scm cache file is written - // during shutdown. - GetSpaceUsed scmUsageMock = Mockito.mock(GetSpaceUsed.class); - volume.setScmUsageForTesting(scmUsageMock); - Mockito.when(scmUsageMock.getUsed()).thenReturn(Long.valueOf(100)); - - assertTrue("Available volume should be positive", - volume.getAvailable() > 0); - - // Shutdown the volume. - volume.shutdown(); - - // Volume state should be "NON_EXISTENT" when volume is shutdown. - assertEquals(volume.getStorageState(), - HddsVolume.VolumeState.NON_EXISTENT); - - // Volume should save scmUsed cache file once volume is shutdown - File scmUsedFile = new File(folder.getRoot(), DU_CACHE_FILE); - System.out.println("scmUsedFile: " + scmUsedFile); - assertTrue("scmUsed cache file should be saved on shutdown", - scmUsedFile.exists()); - - try { - // Volume.getAvailable() should fail with NullPointerException as usage - // is shutdown. - volume.getAvailable(); - fail("HddsVolume#shutdown test failed"); - } catch (Exception ex){ - assertTrue(ex instanceof NullPointerException); - } - } -} diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/volume/TestRoundRobinVolumeChoosingPolicy.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/volume/TestRoundRobinVolumeChoosingPolicy.java deleted file mode 100644 index 80594d35245..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/volume/TestRoundRobinVolumeChoosingPolicy.java +++ /dev/null @@ -1,126 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.volume; - -import org.apache.hadoop.fs.GetSpaceUsed; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdfs.DFSConfigKeys; -import org.apache.hadoop.hdfs.MiniDFSCluster; -import org.apache.hadoop.util.DiskChecker.DiskOutOfSpaceException; -import org.apache.hadoop.util.ReflectionUtils; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import java.io.IOException; -import java.util.List; -import java.util.UUID; - -/** - * Tests {@link RoundRobinVolumeChoosingPolicy}. - */ -public class TestRoundRobinVolumeChoosingPolicy { - - private RoundRobinVolumeChoosingPolicy policy; - private List volumes; - - private final String baseDir = MiniDFSCluster.getBaseDirectory(); - private final String volume1 = baseDir + "disk1"; - private final String volume2 = baseDir + "disk2"; - private static final String DUMMY_IP_ADDR = "0.0.0.0"; - - @Before - public void setup() throws Exception { - OzoneConfiguration conf = new OzoneConfiguration(); - String dataDirKey = volume1 + "," + volume2; - conf.set(DFSConfigKeys.DFS_DATANODE_DATA_DIR_KEY, dataDirKey); - policy = ReflectionUtils.newInstance( - RoundRobinVolumeChoosingPolicy.class, null); - VolumeSet volumeSet = new VolumeSet(UUID.randomUUID().toString(), conf); - volumes = volumeSet.getVolumesList(); - } - - @Test - public void testRRVolumeChoosingPolicy() throws Exception { - HddsVolume hddsVolume1 = volumes.get(0); - HddsVolume hddsVolume2 = volumes.get(1); - - // Set available space in volume1 to 100L - setAvailableSpace(hddsVolume1, 100L); - - // Set available space in volume1 to 200L - setAvailableSpace(hddsVolume2, 200L); - - Assert.assertEquals(100L, hddsVolume1.getAvailable()); - Assert.assertEquals(200L, hddsVolume2.getAvailable()); - - // Test two rounds of round-robin choosing - Assert.assertEquals(hddsVolume1, policy.chooseVolume(volumes, 0)); - Assert.assertEquals(hddsVolume2, policy.chooseVolume(volumes, 0)); - Assert.assertEquals(hddsVolume1, policy.chooseVolume(volumes, 0)); - Assert.assertEquals(hddsVolume2, policy.chooseVolume(volumes, 0)); - - // The first volume has only 100L space, so the policy should - // choose the second one in case we ask for more. - Assert.assertEquals(hddsVolume2, - policy.chooseVolume(volumes, 150)); - - // Fail if no volume has enough space available - try { - policy.chooseVolume(volumes, Long.MAX_VALUE); - Assert.fail(); - } catch (IOException e) { - // Passed. - } - } - - @Test - public void testRRPolicyExceptionMessage() throws Exception { - HddsVolume hddsVolume1 = volumes.get(0); - HddsVolume hddsVolume2 = volumes.get(1); - - // Set available space in volume1 to 100L - setAvailableSpace(hddsVolume1, 100L); - - // Set available space in volume1 to 200L - setAvailableSpace(hddsVolume2, 200L); - - int blockSize = 300; - try { - policy.chooseVolume(volumes, blockSize); - Assert.fail("expected to throw DiskOutOfSpaceException"); - } catch(DiskOutOfSpaceException e) { - Assert.assertEquals("Not returnig the expected message", - "Out of space: The volume with the most available space (=" + 200 - + " B) is less than the container size (=" + blockSize + " B).", - e.getMessage()); - } - } - - private void setAvailableSpace(HddsVolume hddsVolume, long availableSpace) - throws IOException { - GetSpaceUsed scmUsageMock = Mockito.mock(GetSpaceUsed.class); - hddsVolume.setScmUsageForTesting(scmUsageMock); - // Set used space to capacity -requiredAvailableSpace so that - // getAvailable() returns us the specified availableSpace. - Mockito.when(scmUsageMock.getUsed()).thenReturn( - (hddsVolume.getCapacity() - availableSpace)); - } -} diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/volume/TestVolumeSet.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/volume/TestVolumeSet.java deleted file mode 100644 index fca68b19acc..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/volume/TestVolumeSet.java +++ /dev/null @@ -1,254 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.common.volume; - -import java.io.IOException; -import org.apache.commons.io.FileUtils; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.fs.FileUtil; -import org.apache.hadoop.fs.Path; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdfs.DFSConfigKeys; -import org.apache.hadoop.hdfs.MiniDFSCluster; -import org.apache.hadoop.ozone.container.common.utils.HddsVolumeUtil; -import org.apache.hadoop.test.GenericTestUtils; -import org.apache.hadoop.test.GenericTestUtils.LogCapturer; - -import static org.apache.hadoop.hdds.scm.ScmConfigKeys.HDDS_DATANODE_DIR_KEY; -import static org.apache.hadoop.ozone.container.common.volume.HddsVolume - .HDDS_VOLUME_DIR; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.Timeout; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -/** - * Tests {@link VolumeSet} operations. - */ -public class TestVolumeSet { - - private OzoneConfiguration conf; - private VolumeSet volumeSet; - private final String baseDir = MiniDFSCluster.getBaseDirectory(); - private final String volume1 = baseDir + "disk1"; - private final String volume2 = baseDir + "disk2"; - private final List volumes = new ArrayList<>(); - - private static final String DUMMY_IP_ADDR = "0.0.0.0"; - - private void initializeVolumeSet() throws Exception { - volumeSet = new VolumeSet(UUID.randomUUID().toString(), conf); - } - - @Rule - public Timeout testTimeout = new Timeout(300_000); - - @Before - public void setup() throws Exception { - conf = new OzoneConfiguration(); - String dataDirKey = volume1 + "," + volume2; - volumes.add(volume1); - volumes.add(volume2); - conf.set(DFSConfigKeys.DFS_DATANODE_DATA_DIR_KEY, dataDirKey); - initializeVolumeSet(); - } - - @After - public void shutdown() throws IOException { - // Delete the hdds volume root dir - List hddsVolumes = new ArrayList<>(); - hddsVolumes.addAll(volumeSet.getVolumesList()); - hddsVolumes.addAll(volumeSet.getFailedVolumesList()); - - for (HddsVolume volume : hddsVolumes) { - FileUtils.deleteDirectory(volume.getHddsRootDir()); - } - volumeSet.shutdown(); - - FileUtil.fullyDelete(new File(baseDir)); - } - - private boolean checkVolumeExistsInVolumeSet(String volume) { - for (HddsVolume hddsVolume : volumeSet.getVolumesList()) { - if (hddsVolume.getHddsRootDir().getPath().equals( - HddsVolumeUtil.getHddsRoot(volume))) { - return true; - } - } - return false; - } - - @Test - public void testVolumeSetInitialization() throws Exception { - - List volumesList = volumeSet.getVolumesList(); - - // VolumeSet initialization should add volume1 and volume2 to VolumeSet - assertEquals("VolumeSet intialization is incorrect", - volumesList.size(), volumes.size()); - assertTrue("VolumeSet not initailized correctly", - checkVolumeExistsInVolumeSet(volume1)); - assertTrue("VolumeSet not initailized correctly", - checkVolumeExistsInVolumeSet(volume2)); - } - - @Test - public void testAddVolume() { - - assertEquals(2, volumeSet.getVolumesList().size()); - - // Add a volume to VolumeSet - String volume3 = baseDir + "disk3"; - boolean success = volumeSet.addVolume(volume3); - - assertTrue(success); - assertEquals(3, volumeSet.getVolumesList().size()); - assertTrue("AddVolume did not add requested volume to VolumeSet", - checkVolumeExistsInVolumeSet(volume3)); - } - - @Test - public void testFailVolume() throws Exception { - - //Fail a volume - volumeSet.failVolume(volume1); - - // Failed volume should not show up in the volumeList - assertEquals(1, volumeSet.getVolumesList().size()); - - // Failed volume should be added to FailedVolumeList - assertEquals("Failed volume not present in FailedVolumeMap", - 1, volumeSet.getFailedVolumesList().size()); - assertEquals("Failed Volume list did not match", - HddsVolumeUtil.getHddsRoot(volume1), - volumeSet.getFailedVolumesList().get(0).getHddsRootDir().getPath()); - assertTrue(volumeSet.getFailedVolumesList().get(0).isFailed()); - - // Failed volume should not exist in VolumeMap - Path volume1Path = new Path(volume1); - assertFalse(volumeSet.getVolumeMap().containsKey(volume1Path)); - } - - @Test - public void testRemoveVolume() throws Exception { - - assertEquals(2, volumeSet.getVolumesList().size()); - - // Remove a volume from VolumeSet - volumeSet.removeVolume(volume1); - assertEquals(1, volumeSet.getVolumesList().size()); - - // Attempting to remove a volume which does not exist in VolumeSet should - // log a warning. - LogCapturer logs = LogCapturer.captureLogs( - LogFactory.getLog(VolumeSet.class)); - volumeSet.removeVolume(volume1); - assertEquals(1, volumeSet.getVolumesList().size()); - String expectedLogMessage = "Volume : " + - HddsVolumeUtil.getHddsRoot(volume1) + " does not exist in VolumeSet"; - assertTrue("Log output does not contain expected log message: " - + expectedLogMessage, logs.getOutput().contains(expectedLogMessage)); - } - - @Test - public void testVolumeInInconsistentState() throws Exception { - assertEquals(2, volumeSet.getVolumesList().size()); - - // Add a volume to VolumeSet - String volume3 = baseDir + "disk3"; - - // Create the root volume dir and create a sub-directory within it. - File newVolume = new File(volume3, HDDS_VOLUME_DIR); - System.out.println("new volume root: " + newVolume); - newVolume.mkdirs(); - assertTrue("Failed to create new volume root", newVolume.exists()); - File dataDir = new File(newVolume, "chunks"); - dataDir.mkdirs(); - assertTrue(dataDir.exists()); - - // The new volume is in an inconsistent state as the root dir is - // non-empty but the version file does not exist. Add Volume should - // return false. - boolean success = volumeSet.addVolume(volume3); - - assertFalse(success); - assertEquals(2, volumeSet.getVolumesList().size()); - assertTrue("AddVolume should fail for an inconsistent volume", - !checkVolumeExistsInVolumeSet(volume3)); - - // Delete volume3 - File volume = new File(volume3); - FileUtils.deleteDirectory(volume); - } - - @Test - public void testShutdown() throws Exception { - List volumesList = volumeSet.getVolumesList(); - - volumeSet.shutdown(); - - // Verify that the volumes are shutdown and the volumeUsage is set to null. - for (HddsVolume volume : volumesList) { - Assert.assertNull(volume.getVolumeInfo().getUsageForTesting()); - try { - // getAvailable() should throw null pointer exception as usage is null. - volume.getAvailable(); - fail("Volume shutdown failed."); - } catch (NullPointerException ex) { - // Do Nothing. Exception is expected. - } - } - } - - @Test - public void testFailVolumes() throws Exception{ - VolumeSet volSet = null; - File readOnlyVolumePath = new File(baseDir); - //Set to readonly, so that this volume will be failed - readOnlyVolumePath.setReadOnly(); - File volumePath = GenericTestUtils.getRandomizedTestDir(); - OzoneConfiguration ozoneConfig = new OzoneConfiguration(); - ozoneConfig.set(HDDS_DATANODE_DIR_KEY, readOnlyVolumePath.getAbsolutePath() - + "," + volumePath.getAbsolutePath()); - volSet = new VolumeSet(UUID.randomUUID().toString(), ozoneConfig); - assertTrue(volSet.getFailedVolumesList().size() == 1); - assertEquals(readOnlyVolumePath, volSet.getFailedVolumesList().get(0) - .getHddsRootDir()); - - //Set back to writable - try { - readOnlyVolumePath.setWritable(true); - } finally { - FileUtil.fullyDelete(volumePath); - } - - } -} diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestBlockManagerImpl.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestBlockManagerImpl.java deleted file mode 100644 index 6fe6d81ee43..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestBlockManagerImpl.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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.keyvalue; - -import org.apache.hadoop.conf.StorageUnit; -import org.apache.hadoop.hdds.client.BlockID; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdds.scm.container.common.helpers.StorageContainerException; -import org.apache.hadoop.ozone.container.common.helpers.BlockData; -import org.apache.hadoop.ozone.container.common.helpers.ChunkInfo; -import org.apache.hadoop.ozone.container.common.volume - .RoundRobinVolumeChoosingPolicy; -import org.apache.hadoop.ozone.container.common.volume.VolumeSet; -import org.apache.hadoop.ozone.container.common.volume.HddsVolume; -import org.apache.hadoop.ozone.container.keyvalue.impl.BlockManagerImpl; -import org.apache.hadoop.test.GenericTestUtils; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.mockito.Mockito; - -import java.io.IOException; -import java.util.LinkedList; -import java.util.List; -import java.util.UUID; - -import static org.junit.Assert.*; -import static org.mockito.ArgumentMatchers.anyList; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.mock; - -/** - * This class is used to test key related operations on the container. - */ -public class TestBlockManagerImpl { - - private OzoneConfiguration config; - private String scmId = UUID.randomUUID().toString(); - private VolumeSet volumeSet; - private RoundRobinVolumeChoosingPolicy volumeChoosingPolicy; - private KeyValueContainerData keyValueContainerData; - private KeyValueContainer keyValueContainer; - private BlockData blockData; - private BlockManagerImpl blockManager; - private BlockID blockID; - - @Rule - public TemporaryFolder folder = new TemporaryFolder(); - - - @Before - public void setUp() throws Exception { - config = new OzoneConfiguration(); - - HddsVolume hddsVolume = new HddsVolume.Builder(folder.getRoot() - .getAbsolutePath()).conf(config).datanodeUuid(UUID.randomUUID() - .toString()).build(); - - volumeSet = mock(VolumeSet.class); - - volumeChoosingPolicy = mock(RoundRobinVolumeChoosingPolicy.class); - Mockito.when(volumeChoosingPolicy.chooseVolume(anyList(), anyLong())) - .thenReturn(hddsVolume); - - keyValueContainerData = new KeyValueContainerData(1L, - (long) StorageUnit.GB.toBytes(5)); - - keyValueContainer = new KeyValueContainer( - keyValueContainerData, config); - - keyValueContainer.create(volumeSet, volumeChoosingPolicy, scmId); - - // Creating BlockData - blockID = new BlockID(1L, 1L); - blockData = new BlockData(blockID); - blockData.addMetadata("VOLUME", "ozone"); - blockData.addMetadata("OWNER", "hdfs"); - List chunkList = new LinkedList<>(); - ChunkInfo info = new ChunkInfo(String.format("%d.data.%d", blockID - .getLocalID(), 0), 0, 1024); - chunkList.add(info.getProtoBufMessage()); - blockData.setChunks(chunkList); - - // Create KeyValueContainerManager - blockManager = new BlockManagerImpl(config); - - } - - @Test - public void testPutAndGetBlock() throws Exception { - assertEquals(0, keyValueContainer.getContainerData().getKeyCount()); - //Put Block - blockManager.putBlock(keyValueContainer, blockData); - - assertEquals(1, keyValueContainer.getContainerData().getKeyCount()); - //Get Block - BlockData fromGetBlockData = blockManager.getBlock(keyValueContainer, - blockData.getBlockID()); - - assertEquals(blockData.getContainerID(), fromGetBlockData.getContainerID()); - assertEquals(blockData.getLocalID(), fromGetBlockData.getLocalID()); - assertEquals(blockData.getChunks().size(), - fromGetBlockData.getChunks().size()); - assertEquals(blockData.getMetadata().size(), fromGetBlockData.getMetadata() - .size()); - - } - - - @Test - public void testDeleteBlock() throws Exception { - try { - assertEquals(0, - keyValueContainer.getContainerData().getKeyCount()); - //Put Block - blockManager.putBlock(keyValueContainer, blockData); - assertEquals(1, - keyValueContainer.getContainerData().getKeyCount()); - //Delete Block - blockManager.deleteBlock(keyValueContainer, blockID); - assertEquals(0, - keyValueContainer.getContainerData().getKeyCount()); - try { - blockManager.getBlock(keyValueContainer, blockID); - fail("testDeleteBlock"); - } catch (StorageContainerException ex) { - GenericTestUtils.assertExceptionContains( - "Unable to find the block", ex); - } - } catch (IOException ex) { - fail("testDeleteBlock failed"); - } - } - - @Test - public void testListBlock() throws Exception { - try { - blockManager.putBlock(keyValueContainer, blockData); - List listBlockData = blockManager.listBlock( - keyValueContainer, 1, 10); - assertNotNull(listBlockData); - assertTrue(listBlockData.size() == 1); - - for (long i = 2; i <= 10; i++) { - blockID = new BlockID(1L, i); - blockData = new BlockData(blockID); - blockData.addMetadata("VOLUME", "ozone"); - blockData.addMetadata("OWNER", "hdfs"); - List chunkList = new LinkedList<>(); - ChunkInfo info = new ChunkInfo(String.format("%d.data.%d", blockID - .getLocalID(), 0), 0, 1024); - chunkList.add(info.getProtoBufMessage()); - blockData.setChunks(chunkList); - blockManager.putBlock(keyValueContainer, blockData); - } - - listBlockData = blockManager.listBlock( - keyValueContainer, 1, 10); - assertNotNull(listBlockData); - assertTrue(listBlockData.size() == 10); - - } catch (IOException ex) { - fail("testListBlock failed"); - } - } - - @Test - public void testGetNoSuchBlock() throws Exception { - try { - assertEquals(0, - keyValueContainer.getContainerData().getKeyCount()); - //Put Block - blockManager.putBlock(keyValueContainer, blockData); - assertEquals(1, - keyValueContainer.getContainerData().getKeyCount()); - //Delete Block - blockManager.deleteBlock(keyValueContainer, blockID); - assertEquals(0, - keyValueContainer.getContainerData().getKeyCount()); - try { - //Since the block has been deleted, we should not be able to find it - blockManager.getBlock(keyValueContainer, blockID); - fail("testGetNoSuchBlock failed"); - } catch (StorageContainerException ex) { - GenericTestUtils.assertExceptionContains( - "Unable to find the block", ex); - assertEquals(ContainerProtos.Result.NO_SUCH_BLOCK, ex.getResult()); - } - } catch (IOException ex) { - fail("testGetNoSuchBlock failed"); - } - } -} diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestChunkManagerImpl.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestChunkManagerImpl.java deleted file mode 100644 index 3c0876b7a74..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestChunkManagerImpl.java +++ /dev/null @@ -1,292 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.keyvalue; - -import org.apache.hadoop.conf.StorageUnit; -import org.apache.hadoop.hdds.client.BlockID; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdds.scm.container.common.helpers.StorageContainerException; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.container.common.helpers.ChunkInfo; -import org.apache.hadoop.ozone.container.keyvalue.helpers.ChunkUtils; -import org.apache.hadoop.ozone.container.common.volume.HddsVolume; -import org.apache.hadoop.ozone.container.common.volume.RoundRobinVolumeChoosingPolicy; -import org.apache.hadoop.ozone.container.common.volume.VolumeIOStats; -import org.apache.hadoop.ozone.container.common.volume.VolumeSet; -import org.apache.hadoop.ozone.container.keyvalue.impl.ChunkManagerImpl; -import org.apache.hadoop.test.GenericTestUtils; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.mockito.Mockito; - -import java.io.File; -import java.util.Arrays; -import java.util.UUID; - -import static org.junit.Assert.*; -import static org.mockito.ArgumentMatchers.anyList; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.mock; - -/** - * This class is used to test ChunkManager operations. - */ -public class TestChunkManagerImpl { - - private OzoneConfiguration config; - private String scmId = UUID.randomUUID().toString(); - private VolumeSet volumeSet; - private RoundRobinVolumeChoosingPolicy volumeChoosingPolicy; - private HddsVolume hddsVolume; - private KeyValueContainerData keyValueContainerData; - private KeyValueContainer keyValueContainer; - private BlockID blockID; - private ChunkManagerImpl chunkManager; - private ChunkInfo chunkInfo; - private byte[] data; - - @Rule - public TemporaryFolder folder = new TemporaryFolder(); - - @Before - public void setUp() throws Exception { - config = new OzoneConfiguration(); - hddsVolume = new HddsVolume.Builder(folder.getRoot() - .getAbsolutePath()).conf(config).datanodeUuid(UUID.randomUUID() - .toString()).build(); - - volumeSet = mock(VolumeSet.class); - - volumeChoosingPolicy = mock(RoundRobinVolumeChoosingPolicy.class); - Mockito.when(volumeChoosingPolicy.chooseVolume(anyList(), anyLong())) - .thenReturn(hddsVolume); - - keyValueContainerData = new KeyValueContainerData(1L, - (long) StorageUnit.GB.toBytes(5)); - - keyValueContainer = new KeyValueContainer(keyValueContainerData, config); - - keyValueContainer.create(volumeSet, volumeChoosingPolicy, scmId); - - data = "testing write chunks".getBytes(); - // Creating BlockData - blockID = new BlockID(1L, 1L); - chunkInfo = new ChunkInfo(String.format("%d.data.%d", blockID - .getLocalID(), 0), 0, data.length); - - // Create a ChunkManager object. - chunkManager = new ChunkManagerImpl(); - - } - - @Test - public void testWriteChunkStageWriteAndCommit() throws Exception { - //As in Setup, we try to create container, these paths should exist. - assertTrue(keyValueContainerData.getChunksPath() != null); - File chunksPath = new File(keyValueContainerData.getChunksPath()); - assertTrue(chunksPath.exists()); - // Initially chunks folder should be empty. - assertTrue(chunksPath.listFiles().length == 0); - - // As no chunks are written to the volume writeBytes should be 0 - checkWriteIOStats(0, 0); - chunkManager.writeChunk(keyValueContainer, blockID, chunkInfo, data, - ContainerProtos.Stage.WRITE_DATA); - // Now a chunk file is being written with Stage WRITE_DATA, so it should - // create a temporary chunk file. - assertTrue(chunksPath.listFiles().length == 1); - - File chunkFile = ChunkUtils.getChunkFile(keyValueContainerData, chunkInfo); - File tempChunkFile = new File(chunkFile.getParent(), - chunkFile.getName() + - OzoneConsts.CONTAINER_CHUNK_NAME_DELIMITER + - OzoneConsts.CONTAINER_TEMPORARY_CHUNK_PREFIX); - - // As chunk write stage is WRITE_DATA, temp chunk file will be created. - assertTrue(tempChunkFile.exists()); - - checkWriteIOStats(data.length, 1); - - chunkManager.writeChunk(keyValueContainer, blockID, chunkInfo, data, - ContainerProtos.Stage.COMMIT_DATA); - - checkWriteIOStats(data.length, 1); - - // Old temp file should have been renamed to chunk file. - assertTrue(chunksPath.listFiles().length == 1); - - // As commit happened, chunk file should exist. - assertTrue(chunkFile.exists()); - assertFalse(tempChunkFile.exists()); - - } - - @Test - public void testWriteChunkIncorrectLength() throws Exception { - try { - long randomLength = 200L; - chunkInfo = new ChunkInfo(String.format("%d.data.%d", blockID - .getLocalID(), 0), 0, randomLength); - chunkManager.writeChunk(keyValueContainer, blockID, chunkInfo, data, - ContainerProtos.Stage.WRITE_DATA); - fail("testWriteChunkIncorrectLength failed"); - } catch (StorageContainerException ex) { - // As we got an exception, writeBytes should be 0. - checkWriteIOStats(0, 0); - GenericTestUtils.assertExceptionContains("data array does not match " + - "the length ", ex); - assertEquals(ContainerProtos.Result.INVALID_WRITE_SIZE, ex.getResult()); - } - } - - @Test - public void testWriteChunkStageCombinedData() throws Exception { - //As in Setup, we try to create container, these paths should exist. - assertTrue(keyValueContainerData.getChunksPath() != null); - File chunksPath = new File(keyValueContainerData.getChunksPath()); - assertTrue(chunksPath.exists()); - // Initially chunks folder should be empty. - assertTrue(chunksPath.listFiles().length == 0); - checkWriteIOStats(0, 0); - chunkManager.writeChunk(keyValueContainer, blockID, chunkInfo, data, - ContainerProtos.Stage.COMBINED); - // Now a chunk file is being written with Stage COMBINED_DATA, so it should - // create a chunk file. - assertTrue(chunksPath.listFiles().length == 1); - File chunkFile = ChunkUtils.getChunkFile(keyValueContainerData, chunkInfo); - assertTrue(chunkFile.exists()); - checkWriteIOStats(data.length, 1); - } - - @Test - public void testReadChunk() throws Exception { - checkWriteIOStats(0, 0); - chunkManager.writeChunk(keyValueContainer, blockID, chunkInfo, data, - ContainerProtos.Stage.COMBINED); - checkWriteIOStats(data.length, 1); - checkReadIOStats(0, 0); - byte[] expectedData = chunkManager.readChunk(keyValueContainer, blockID, - chunkInfo); - assertEquals(expectedData.length, data.length); - assertTrue(Arrays.equals(expectedData, data)); - checkReadIOStats(data.length, 1); - } - - @Test - public void testDeleteChunk() throws Exception { - File chunksPath = new File(keyValueContainerData.getChunksPath()); - chunkManager.writeChunk(keyValueContainer, blockID, chunkInfo, data, - ContainerProtos.Stage.COMBINED); - assertTrue(chunksPath.listFiles().length == 1); - chunkManager.deleteChunk(keyValueContainer, blockID, chunkInfo); - assertTrue(chunksPath.listFiles().length == 0); - } - - @Test - public void testDeleteChunkUnsupportedRequest() throws Exception { - try { - chunkManager.writeChunk(keyValueContainer, blockID, chunkInfo, data, - ContainerProtos.Stage.COMBINED); - long randomLength = 200L; - chunkInfo = new ChunkInfo(String.format("%d.data.%d", blockID - .getLocalID(), 0), 0, randomLength); - chunkManager.deleteChunk(keyValueContainer, blockID, chunkInfo); - fail("testDeleteChunkUnsupportedRequest"); - } catch (StorageContainerException ex) { - GenericTestUtils.assertExceptionContains("Not Supported Operation.", ex); - assertEquals(ContainerProtos.Result.UNSUPPORTED_REQUEST, ex.getResult()); - } - } - - @Test - public void testWriteChunkChecksumMismatch() throws Exception { - try { - chunkInfo = new ChunkInfo(String.format("%d.data.%d", blockID - .getLocalID(), 0), 0, data.length); - //Setting checksum to some value. - chunkInfo.setChecksum("some garbage"); - chunkManager.writeChunk(keyValueContainer, blockID, chunkInfo, data, - ContainerProtos.Stage.COMBINED); - fail("testWriteChunkChecksumMismatch failed"); - } catch (StorageContainerException ex) { - GenericTestUtils.assertExceptionContains("Checksum mismatch.", ex); - assertEquals(ContainerProtos.Result.CHECKSUM_MISMATCH, ex.getResult()); - } - } - - @Test - public void testReadChunkFileNotExists() throws Exception { - try { - // trying to read a chunk, where chunk file does not exist - byte[] expectedData = chunkManager.readChunk(keyValueContainer, blockID, - chunkInfo); - fail("testReadChunkFileNotExists failed"); - } catch (StorageContainerException ex) { - GenericTestUtils.assertExceptionContains("Unable to find the chunk " + - "file.", ex); - assertEquals(ContainerProtos.Result.UNABLE_TO_FIND_CHUNK, ex.getResult()); - } - } - - @Test - public void testWriteAndReadChunkMultipleTimes() throws Exception { - for (int i=0; i<100; i++) { - chunkInfo = new ChunkInfo(String.format("%d.data.%d", blockID - .getLocalID(), i), 0, data.length); - chunkManager.writeChunk(keyValueContainer, blockID, chunkInfo, data, - ContainerProtos.Stage.COMBINED); - } - checkWriteIOStats(data.length*100, 100); - assertTrue(hddsVolume.getVolumeIOStats().getWriteTime() > 0); - - for (int i=0; i<100; i++) { - chunkInfo = new ChunkInfo(String.format("%d.data.%d", blockID - .getLocalID(), i), 0, data.length); - chunkManager.readChunk(keyValueContainer, blockID, chunkInfo); - } - checkReadIOStats(data.length*100, 100); - assertTrue(hddsVolume.getVolumeIOStats().getReadTime() > 0); - } - - - /** - * Check WriteIO stats. - * @param length - * @param opCount - */ - private void checkWriteIOStats(long length, long opCount) { - VolumeIOStats volumeIOStats = hddsVolume.getVolumeIOStats(); - assertEquals(length, volumeIOStats.getWriteBytes()); - assertEquals(opCount, volumeIOStats.getWriteOpCount()); - } - - /** - * Check ReadIO stats. - * @param length - * @param opCount - */ - private void checkReadIOStats(long length, long opCount) { - VolumeIOStats volumeIOStats = hddsVolume.getVolumeIOStats(); - assertEquals(length, volumeIOStats.getReadBytes()); - assertEquals(opCount, volumeIOStats.getReadOpCount()); - } -} diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestKeyValueBlockIterator.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestKeyValueBlockIterator.java deleted file mode 100644 index fbc5ad033a9..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestKeyValueBlockIterator.java +++ /dev/null @@ -1,277 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.keyvalue; - -import com.google.common.primitives.Longs; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.conf.StorageUnit; -import org.apache.hadoop.fs.FileUtil; -import org.apache.hadoop.hdds.client.BlockID; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdfs.DFSUtil; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.container.common.helpers.BlockData; -import org.apache.hadoop.ozone.container.common.helpers.ChunkInfo; -import org.apache.hadoop.ozone.container.common.volume.RoundRobinVolumeChoosingPolicy; -import org.apache.hadoop.ozone.container.common.volume.VolumeSet; -import org.apache.hadoop.ozone.container.keyvalue.helpers.BlockUtils; -import org.apache.hadoop.test.GenericTestUtils; -import org.apache.hadoop.utils.MetadataKeyFilters; -import org.apache.hadoop.utils.MetadataStore; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import java.io.File; -import java.util.Arrays; -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.UUID; - -import static org.apache.hadoop.hdds.scm.ScmConfigKeys.HDDS_DATANODE_DIR_KEY; -import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_METADATA_STORE_IMPL; -import static org.apache.hadoop.ozone.OzoneConfigKeys - .OZONE_METADATA_STORE_IMPL_LEVELDB; -import static org.apache.hadoop.ozone.OzoneConfigKeys - .OZONE_METADATA_STORE_IMPL_ROCKSDB; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -/** - * This class is used to test KeyValue container block iterator. - */ -@RunWith(Parameterized.class) -public class TestKeyValueBlockIterator { - - private KeyValueContainer container; - private KeyValueContainerData containerData; - private VolumeSet volumeSet; - private Configuration conf; - private File testRoot; - - private final String storeImpl; - - public TestKeyValueBlockIterator(String metadataImpl) { - this.storeImpl = metadataImpl; - } - - @Parameterized.Parameters - public static Collection data() { - return Arrays.asList(new Object[][] { - {OZONE_METADATA_STORE_IMPL_LEVELDB}, - {OZONE_METADATA_STORE_IMPL_ROCKSDB}}); - } - - @Before - public void setUp() throws Exception { - testRoot = GenericTestUtils.getRandomizedTestDir(); - conf = new OzoneConfiguration(); - conf.set(HDDS_DATANODE_DIR_KEY, testRoot.getAbsolutePath()); - conf.set(OZONE_METADATA_STORE_IMPL, storeImpl); - volumeSet = new VolumeSet(UUID.randomUUID().toString(), conf); - } - - - @After - public void tearDown() { - volumeSet.shutdown(); - FileUtil.fullyDelete(testRoot); - } - - @Test - public void testKeyValueBlockIteratorWithMixedBlocks() throws Exception { - - long containerID = 100L; - int deletedBlocks = 5; - int normalBlocks = 5; - createContainerWithBlocks(containerID, normalBlocks, deletedBlocks); - String containerPath = new File(containerData.getMetadataPath()) - .getParent(); - KeyValueBlockIterator keyValueBlockIterator = new KeyValueBlockIterator( - containerID, new File(containerPath)); - - int counter = 0; - while(keyValueBlockIterator.hasNext()) { - BlockData blockData = keyValueBlockIterator.nextBlock(); - assertEquals(blockData.getLocalID(), counter++); - } - - assertFalse(keyValueBlockIterator.hasNext()); - - keyValueBlockIterator.seekToFirst(); - counter = 0; - while(keyValueBlockIterator.hasNext()) { - BlockData blockData = keyValueBlockIterator.nextBlock(); - assertEquals(blockData.getLocalID(), counter++); - } - assertFalse(keyValueBlockIterator.hasNext()); - - try { - keyValueBlockIterator.nextBlock(); - } catch (NoSuchElementException ex) { - GenericTestUtils.assertExceptionContains("Block Iterator reached end " + - "for ContainerID " + containerID, ex); - } - } - - @Test - public void testKeyValueBlockIteratorWithNextBlock() throws Exception { - long containerID = 101L; - createContainerWithBlocks(containerID, 2, 0); - String containerPath = new File(containerData.getMetadataPath()) - .getParent(); - KeyValueBlockIterator keyValueBlockIterator = new KeyValueBlockIterator( - containerID, new File(containerPath)); - long blockID = 0L; - assertEquals(blockID++, keyValueBlockIterator.nextBlock().getLocalID()); - assertEquals(blockID, keyValueBlockIterator.nextBlock().getLocalID()); - - try { - keyValueBlockIterator.nextBlock(); - } catch (NoSuchElementException ex) { - GenericTestUtils.assertExceptionContains("Block Iterator reached end " + - "for ContainerID " + containerID, ex); - } - } - - @Test - public void testKeyValueBlockIteratorWithHasNext() throws Exception { - long containerID = 102L; - createContainerWithBlocks(containerID, 2, 0); - String containerPath = new File(containerData.getMetadataPath()) - .getParent(); - KeyValueBlockIterator keyValueBlockIterator = new KeyValueBlockIterator( - containerID, new File(containerPath)); - long blockID = 0L; - - // Even calling multiple times hasNext() should not move entry forward. - assertTrue(keyValueBlockIterator.hasNext()); - assertTrue(keyValueBlockIterator.hasNext()); - assertTrue(keyValueBlockIterator.hasNext()); - assertTrue(keyValueBlockIterator.hasNext()); - assertTrue(keyValueBlockIterator.hasNext()); - assertEquals(blockID++, keyValueBlockIterator.nextBlock().getLocalID()); - - assertTrue(keyValueBlockIterator.hasNext()); - assertTrue(keyValueBlockIterator.hasNext()); - assertTrue(keyValueBlockIterator.hasNext()); - assertTrue(keyValueBlockIterator.hasNext()); - assertTrue(keyValueBlockIterator.hasNext()); - assertEquals(blockID, keyValueBlockIterator.nextBlock().getLocalID()); - - keyValueBlockIterator.seekToLast(); - assertTrue(keyValueBlockIterator.hasNext()); - assertEquals(blockID, keyValueBlockIterator.nextBlock().getLocalID()); - - keyValueBlockIterator.seekToFirst(); - blockID = 0L; - assertEquals(blockID++, keyValueBlockIterator.nextBlock().getLocalID()); - assertEquals(blockID, keyValueBlockIterator.nextBlock().getLocalID()); - - try { - keyValueBlockIterator.nextBlock(); - } catch (NoSuchElementException ex) { - GenericTestUtils.assertExceptionContains("Block Iterator reached end " + - "for ContainerID " + containerID, ex); - } - - - } - - @Test - public void testKeyValueBlockIteratorWithFilter() throws Exception { - long containerId = 103L; - int deletedBlocks = 5; - int normalBlocks = 5; - createContainerWithBlocks(containerId, normalBlocks, deletedBlocks); - String containerPath = new File(containerData.getMetadataPath()) - .getParent(); - KeyValueBlockIterator keyValueBlockIterator = new KeyValueBlockIterator( - containerId, new File(containerPath), MetadataKeyFilters - .getDeletingKeyFilter()); - - int counter = 5; - while(keyValueBlockIterator.hasNext()) { - BlockData blockData = keyValueBlockIterator.nextBlock(); - assertEquals(blockData.getLocalID(), counter++); - } - } - - @Test - public void testKeyValueBlockIteratorWithOnlyDeletedBlocks() throws - Exception { - long containerId = 104L; - createContainerWithBlocks(containerId, 0, 5); - String containerPath = new File(containerData.getMetadataPath()) - .getParent(); - KeyValueBlockIterator keyValueBlockIterator = new KeyValueBlockIterator( - containerId, new File(containerPath)); - //As all blocks are deleted blocks, blocks does not match with normal key - // filter. - assertFalse(keyValueBlockIterator.hasNext()); - } - - /** - * Creates a container with specified number of normal blocks and deleted - * blocks. First it will insert normal blocks, and then it will insert - * deleted blocks. - * @param containerId - * @param normalBlocks - * @param deletedBlocks - * @throws Exception - */ - private void createContainerWithBlocks(long containerId, int - normalBlocks, int deletedBlocks) throws - Exception { - containerData = new KeyValueContainerData(containerId, - (long) StorageUnit.GB.toBytes(1)); - container = new KeyValueContainer(containerData, conf); - container.create(volumeSet, new RoundRobinVolumeChoosingPolicy(), UUID - .randomUUID().toString()); - MetadataStore metadataStore = BlockUtils.getDB(containerData, conf); - - List chunkList = new LinkedList<>(); - ChunkInfo info = new ChunkInfo("chunkfile", 0, 1024); - chunkList.add(info.getProtoBufMessage()); - - for (int i=0; i chunkList = new LinkedList<>(); - ChunkInfo info = new ChunkInfo(String.format("%d.data.%d", blockID - .getLocalID(), 0), 0, 1024); - chunkList.add(info.getProtoBufMessage()); - blockData.setChunks(chunkList); - metadataStore.put(Longs.toByteArray(blockID.getLocalID()), blockData - .getProtoBufMessage().toByteArray()); - } - - } - - @SuppressWarnings("RedundantCast") - @Test - public void testCreateContainer() throws Exception { - - // Create Container. - keyValueContainer.create(volumeSet, volumeChoosingPolicy, scmId); - - keyValueContainerData = keyValueContainer - .getContainerData(); - - String containerMetaDataPath = keyValueContainerData - .getMetadataPath(); - String chunksPath = keyValueContainerData.getChunksPath(); - - // Check whether containerMetaDataPath and chunksPath exists or not. - assertTrue(containerMetaDataPath != null); - assertTrue(chunksPath != null); - File containerMetaDataLoc = new File(containerMetaDataPath); - - //Check whether container file and container db file exists or not. - assertTrue(keyValueContainer.getContainerFile().exists(), - ".Container File does not exist"); - assertTrue(keyValueContainer.getContainerDBFile().exists(), "Container " + - "DB does not exist"); - } - - @Test - public void testContainerImportExport() throws Exception { - - long containerId = keyValueContainer.getContainerData().getContainerID(); - // Create Container. - keyValueContainer.create(volumeSet, volumeChoosingPolicy, scmId); - - - keyValueContainerData = keyValueContainer - .getContainerData(); - - keyValueContainerData.setState(ContainerLifeCycleState.CLOSED); - - int numberOfKeysToWrite = 12; - //write one few keys to check the key count after import - MetadataStore metadataStore = BlockUtils.getDB(keyValueContainerData, conf); - for (int i = 0; i < numberOfKeysToWrite; i++) { - metadataStore.put(("test" + i).getBytes(), "test".getBytes()); - } - metadataStore.close(); - - Map metadata = new HashMap<>(); - metadata.put("key1", "value1"); - keyValueContainer.update(metadata, true); - - //destination path - File folderToExport = folder.newFile("exported.tar.gz"); - - TarContainerPacker packer = new TarContainerPacker(); - - //export the container - try (FileOutputStream fos = new FileOutputStream(folderToExport)) { - keyValueContainer - .exportContainerData(fos, packer); - } - - //delete the original one - keyValueContainer.delete(true); - - //create a new one - KeyValueContainerData containerData = - new KeyValueContainerData(containerId, 1, - keyValueContainerData.getMaxSize()); - KeyValueContainer container = new KeyValueContainer(containerData, conf); - - HddsVolume containerVolume = volumeChoosingPolicy.chooseVolume(volumeSet - .getVolumesList(), 1); - String hddsVolumeDir = containerVolume.getHddsRootDir().toString(); - - container.populatePathFields(scmId, containerVolume, hddsVolumeDir); - try (FileInputStream fis = new FileInputStream(folderToExport)) { - container.importContainerData(fis, packer); - } - - Assert.assertEquals("value1", containerData.getMetadata().get("key1")); - Assert.assertEquals(keyValueContainerData.getContainerDBType(), - containerData.getContainerDBType()); - Assert.assertEquals(keyValueContainerData.getState(), - containerData.getState()); - Assert.assertEquals(numberOfKeysToWrite, - containerData.getKeyCount()); - Assert.assertEquals(keyValueContainerData.getLayOutVersion(), - containerData.getLayOutVersion()); - Assert.assertEquals(keyValueContainerData.getMaxSize(), - containerData.getMaxSize()); - Assert.assertEquals(keyValueContainerData.getBytesUsed(), - containerData.getBytesUsed()); - - //Can't overwrite existing container - try { - try (FileInputStream fis = new FileInputStream(folderToExport)) { - container.importContainerData(fis, packer); - } - fail("Container is imported twice. Previous files are overwritten"); - } catch (Exception ex) { - //all good - } - - } - - @Test - public void testDuplicateContainer() throws Exception { - try { - // Create Container. - keyValueContainer.create(volumeSet, volumeChoosingPolicy, scmId); - keyValueContainer.create(volumeSet, volumeChoosingPolicy, scmId); - fail("testDuplicateContainer failed"); - } catch (StorageContainerException ex) { - GenericTestUtils.assertExceptionContains("ContainerFile already " + - "exists", ex); - assertEquals(ContainerProtos.Result.CONTAINER_ALREADY_EXISTS, ex - .getResult()); - } - } - - @Test - public void testDiskFullExceptionCreateContainer() throws Exception { - - Mockito.when(volumeChoosingPolicy.chooseVolume(anyList(), anyLong())) - .thenThrow(DiskChecker.DiskOutOfSpaceException.class); - try { - keyValueContainer.create(volumeSet, volumeChoosingPolicy, scmId); - fail("testDiskFullExceptionCreateContainer failed"); - } catch (StorageContainerException ex) { - GenericTestUtils.assertExceptionContains("disk out of space", - ex); - assertEquals(ContainerProtos.Result.DISK_OUT_OF_SPACE, ex.getResult()); - } - } - - @Test - public void testDeleteContainer() throws Exception { - keyValueContainerData.setState(ContainerProtos.ContainerLifeCycleState - .CLOSED); - keyValueContainer = new KeyValueContainer( - keyValueContainerData, conf); - keyValueContainer.create(volumeSet, volumeChoosingPolicy, scmId); - keyValueContainer.delete(true); - - String containerMetaDataPath = keyValueContainerData - .getMetadataPath(); - File containerMetaDataLoc = new File(containerMetaDataPath); - - assertFalse("Container directory still exists", containerMetaDataLoc - .getParentFile().exists()); - - assertFalse("Container File still exists", - keyValueContainer.getContainerFile().exists()); - assertFalse("Container DB file still exists", - keyValueContainer.getContainerDBFile().exists()); - } - - - @Test - public void testCloseContainer() throws Exception { - keyValueContainer.create(volumeSet, volumeChoosingPolicy, scmId); - keyValueContainer.close(); - - keyValueContainerData = keyValueContainer - .getContainerData(); - - assertEquals(ContainerProtos.ContainerLifeCycleState.CLOSED, - keyValueContainerData.getState()); - - //Check state in the .container file - String containerMetaDataPath = keyValueContainerData - .getMetadataPath(); - File containerFile = keyValueContainer.getContainerFile(); - - keyValueContainerData = (KeyValueContainerData) ContainerDataYaml - .readContainerFile(containerFile); - assertEquals(ContainerProtos.ContainerLifeCycleState.CLOSED, - keyValueContainerData.getState()); - } - - @Test - public void testUpdateContainer() throws IOException { - keyValueContainer.create(volumeSet, volumeChoosingPolicy, scmId); - Map metadata = new HashMap<>(); - metadata.put("VOLUME", "ozone"); - metadata.put("OWNER", "hdfs"); - keyValueContainer.update(metadata, true); - - keyValueContainerData = keyValueContainer - .getContainerData(); - - assertEquals(2, keyValueContainerData.getMetadata().size()); - - //Check metadata in the .container file - File containerFile = keyValueContainer.getContainerFile(); - - keyValueContainerData = (KeyValueContainerData) ContainerDataYaml - .readContainerFile(containerFile); - assertEquals(2, keyValueContainerData.getMetadata().size()); - - } - - @Test - public void testUpdateContainerUnsupportedRequest() throws Exception { - try { - keyValueContainerData.setState(ContainerProtos.ContainerLifeCycleState - .CLOSED); - keyValueContainer = new KeyValueContainer(keyValueContainerData, conf); - keyValueContainer.create(volumeSet, volumeChoosingPolicy, scmId); - Map metadata = new HashMap<>(); - metadata.put("VOLUME", "ozone"); - keyValueContainer.update(metadata, false); - fail("testUpdateContainerUnsupportedRequest failed"); - } catch (StorageContainerException ex) { - GenericTestUtils.assertExceptionContains("Updating a closed container " + - "without force option is not allowed", ex); - assertEquals(ContainerProtos.Result.UNSUPPORTED_REQUEST, ex - .getResult()); - } - } - - -} diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestKeyValueHandler.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestKeyValueHandler.java deleted file mode 100644 index e1904c17ff3..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestKeyValueHandler.java +++ /dev/null @@ -1,292 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.keyvalue; - - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.conf.StorageUnit; -import org.apache.hadoop.fs.FileUtil; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerCommandRequestProto; -import org.apache.hadoop.hdds.scm.container.common.helpers - .StorageContainerException; -import org.apache.hadoop.hdfs.MiniDFSCluster; -import org.apache.hadoop.ozone.container.common.helpers.ContainerMetrics; -import org.apache.hadoop.ozone.container.common.impl.ContainerSet; -import org.apache.hadoop.ozone.container.common.impl.HddsDispatcher; -import org.apache.hadoop.ozone.container.common.volume.VolumeSet; -import org.apache.hadoop.test.GenericTestUtils; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestRule; -import org.junit.rules.Timeout; - -import org.mockito.Mockito; - -import static org.apache.hadoop.hdds.HddsConfigKeys - .HDDS_DATANODE_VOLUME_CHOOSING_POLICY; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys.HDDS_DATANODE_DIR_KEY; -import static org.junit.Assert.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.doCallRealMethod; -import static org.mockito.Mockito.times; - - -import java.io.File; -import java.util.UUID; - -/** - * Unit tests for {@link KeyValueHandler}. - */ -public class TestKeyValueHandler { - - @Rule - public TestRule timeout = new Timeout(300000); - - private static HddsDispatcher dispatcher; - private static KeyValueHandler handler; - - private final static String DATANODE_UUID = UUID.randomUUID().toString(); - - private final String baseDir = MiniDFSCluster.getBaseDirectory(); - private final String volume = baseDir + "disk1"; - - private static final long DUMMY_CONTAINER_ID = 9999; - - @BeforeClass - public static void setup() throws StorageContainerException { - // Create mock HddsDispatcher and KeyValueHandler. - handler = Mockito.mock(KeyValueHandler.class); - dispatcher = Mockito.mock(HddsDispatcher.class); - Mockito.when(dispatcher.getHandler(any())).thenReturn(handler); - Mockito.when(dispatcher.dispatch(any())).thenCallRealMethod(); - Mockito.when(dispatcher.getContainer(anyLong())).thenReturn( - Mockito.mock(KeyValueContainer.class)); - Mockito.when(handler.handle(any(), any())).thenCallRealMethod(); - doCallRealMethod().when(dispatcher).setMetricsForTesting(any()); - dispatcher.setMetricsForTesting(Mockito.mock(ContainerMetrics.class)); - } - - @Test - /** - * Test that Handler handles different command types correctly. - */ - public void testHandlerCommandHandling() throws Exception { - - // Test Create Container Request handling - ContainerCommandRequestProto createContainerRequest = - ContainerProtos.ContainerCommandRequestProto.newBuilder() - .setCmdType(ContainerProtos.Type.CreateContainer) - .setContainerID(DUMMY_CONTAINER_ID) - .setDatanodeUuid(DATANODE_UUID) - .setCreateContainer(ContainerProtos.CreateContainerRequestProto - .getDefaultInstance()) - .build(); - dispatcher.dispatch(createContainerRequest); - Mockito.verify(handler, times(1)).handleCreateContainer( - any(ContainerCommandRequestProto.class), any()); - - // Test Read Container Request handling - ContainerCommandRequestProto readContainerRequest = - getDummyCommandRequestProto(ContainerProtos.Type.ReadContainer); - dispatcher.dispatch(readContainerRequest); - Mockito.verify(handler, times(1)).handleReadContainer( - any(ContainerCommandRequestProto.class), any()); - - // Test Update Container Request handling - ContainerCommandRequestProto updateContainerRequest = - getDummyCommandRequestProto(ContainerProtos.Type.UpdateContainer); - dispatcher.dispatch(updateContainerRequest); - Mockito.verify(handler, times(1)).handleUpdateContainer( - any(ContainerCommandRequestProto.class), any()); - - // Test Delete Container Request handling - ContainerCommandRequestProto deleteContainerRequest = - getDummyCommandRequestProto(ContainerProtos.Type.DeleteContainer); - dispatcher.dispatch(deleteContainerRequest); - Mockito.verify(handler, times(1)).handleDeleteContainer( - any(ContainerCommandRequestProto.class), any()); - - // Test List Container Request handling - ContainerCommandRequestProto listContainerRequest = - getDummyCommandRequestProto(ContainerProtos.Type.ListContainer); - dispatcher.dispatch(listContainerRequest); - Mockito.verify(handler, times(1)).handleUnsupportedOp( - any(ContainerCommandRequestProto.class)); - - // Test Close Container Request handling - ContainerCommandRequestProto closeContainerRequest = - getDummyCommandRequestProto(ContainerProtos.Type.CloseContainer); - dispatcher.dispatch(closeContainerRequest); - Mockito.verify(handler, times(1)).handleCloseContainer( - any(ContainerCommandRequestProto.class), any()); - - // Test Put Block Request handling - ContainerCommandRequestProto putBlockRequest = - getDummyCommandRequestProto(ContainerProtos.Type.PutBlock); - dispatcher.dispatch(putBlockRequest); - Mockito.verify(handler, times(1)).handlePutBlock( - any(ContainerCommandRequestProto.class), any()); - - // Test Get Block Request handling - ContainerCommandRequestProto getBlockRequest = - getDummyCommandRequestProto(ContainerProtos.Type.GetBlock); - dispatcher.dispatch(getBlockRequest); - Mockito.verify(handler, times(1)).handleGetBlock( - any(ContainerCommandRequestProto.class), any()); - - // Test Delete Block Request handling - ContainerCommandRequestProto deleteBlockRequest = - getDummyCommandRequestProto(ContainerProtos.Type.DeleteBlock); - dispatcher.dispatch(deleteBlockRequest); - Mockito.verify(handler, times(1)).handleDeleteBlock( - any(ContainerCommandRequestProto.class), any()); - - // Test List Block Request handling - ContainerCommandRequestProto listBlockRequest = - getDummyCommandRequestProto(ContainerProtos.Type.ListBlock); - dispatcher.dispatch(listBlockRequest); - Mockito.verify(handler, times(2)).handleUnsupportedOp( - any(ContainerCommandRequestProto.class)); - - // Test Read Chunk Request handling - ContainerCommandRequestProto readChunkRequest = - getDummyCommandRequestProto(ContainerProtos.Type.ReadChunk); - dispatcher.dispatch(readChunkRequest); - Mockito.verify(handler, times(1)).handleReadChunk( - any(ContainerCommandRequestProto.class), any()); - - // Test Delete Chunk Request handling - ContainerCommandRequestProto deleteChunkRequest = - getDummyCommandRequestProto(ContainerProtos.Type.DeleteChunk); - dispatcher.dispatch(deleteChunkRequest); - Mockito.verify(handler, times(1)).handleDeleteChunk( - any(ContainerCommandRequestProto.class), any()); - - // Test Write Chunk Request handling - ContainerCommandRequestProto writeChunkRequest = - getDummyCommandRequestProto(ContainerProtos.Type.WriteChunk); - dispatcher.dispatch(writeChunkRequest); - Mockito.verify(handler, times(1)).handleWriteChunk( - any(ContainerCommandRequestProto.class), any()); - - // Test List Chunk Request handling - ContainerCommandRequestProto listChunkRequest = - getDummyCommandRequestProto(ContainerProtos.Type.ListChunk); - dispatcher.dispatch(listChunkRequest); - Mockito.verify(handler, times(3)).handleUnsupportedOp( - any(ContainerCommandRequestProto.class)); - - // Test Put Small File Request handling - ContainerCommandRequestProto putSmallFileRequest = - getDummyCommandRequestProto(ContainerProtos.Type.PutSmallFile); - dispatcher.dispatch(putSmallFileRequest); - Mockito.verify(handler, times(1)).handlePutSmallFile( - any(ContainerCommandRequestProto.class), any()); - - // Test Get Small File Request handling - ContainerCommandRequestProto getSmallFileRequest = - getDummyCommandRequestProto(ContainerProtos.Type.GetSmallFile); - dispatcher.dispatch(getSmallFileRequest); - Mockito.verify(handler, times(1)).handleGetSmallFile( - any(ContainerCommandRequestProto.class), any()); - } - - @Test - public void testVolumeSetInKeyValueHandler() throws Exception{ - File path = GenericTestUtils.getRandomizedTestDir(); - try { - Configuration conf = new OzoneConfiguration(); - conf.set(HDDS_DATANODE_DIR_KEY, path.getAbsolutePath()); - ContainerSet cset = new ContainerSet(); - int[] interval = new int[1]; - interval[0] = 2; - ContainerMetrics metrics = new ContainerMetrics(interval); - VolumeSet volumeSet = new VolumeSet(UUID.randomUUID().toString(), conf); - KeyValueHandler keyValueHandler = new KeyValueHandler(conf, cset, - volumeSet, metrics); - assertEquals(keyValueHandler.getVolumeChoosingPolicyForTesting() - .getClass().getName(), "org.apache.hadoop.ozone.container.common" + - ".volume.RoundRobinVolumeChoosingPolicy"); - - //Set a class which is not of sub class of VolumeChoosingPolicy - conf.set(HDDS_DATANODE_VOLUME_CHOOSING_POLICY, - "org.apache.hadoop.ozone.container.common.impl.HddsDispatcher"); - try { - new KeyValueHandler(conf, cset, volumeSet, metrics); - } catch (RuntimeException ex) { - GenericTestUtils.assertExceptionContains("class org.apache.hadoop" + - ".ozone.container.common.impl.HddsDispatcher not org.apache" + - ".hadoop.ozone.container.common.interfaces.VolumeChoosingPolicy", - ex); - } - } finally { - FileUtil.fullyDelete(path); - } - } - - private ContainerCommandRequestProto getDummyCommandRequestProto( - ContainerProtos.Type cmdType) { - ContainerCommandRequestProto request = - ContainerProtos.ContainerCommandRequestProto.newBuilder() - .setCmdType(cmdType) - .setContainerID(DUMMY_CONTAINER_ID) - .setDatanodeUuid(DATANODE_UUID) - .build(); - - return request; - } - - - @Test - public void testCloseInvalidContainer() { - long containerID = 1234L; - Configuration conf = new Configuration(); - KeyValueContainerData kvData = new KeyValueContainerData(containerID, - (long) StorageUnit.GB.toBytes(1)); - KeyValueContainer container = new KeyValueContainer(kvData, conf); - kvData.setState(ContainerProtos.ContainerLifeCycleState.INVALID); - - // Create Close container request - ContainerCommandRequestProto closeContainerRequest = - ContainerProtos.ContainerCommandRequestProto.newBuilder() - .setCmdType(ContainerProtos.Type.CloseContainer) - .setContainerID(DUMMY_CONTAINER_ID) - .setDatanodeUuid(DATANODE_UUID) - .setCloseContainer(ContainerProtos.CloseContainerRequestProto - .getDefaultInstance()) - .build(); - dispatcher.dispatch(closeContainerRequest); - - Mockito.when(handler.handleCloseContainer(any(), any())) - .thenCallRealMethod(); - // Closing invalid container should return error response. - ContainerProtos.ContainerCommandResponseProto response = - handler.handleCloseContainer(closeContainerRequest, container); - - Assert.assertTrue("Close container should return Invalid container error", - response.getResult().equals( - ContainerProtos.Result.INVALID_CONTAINER_STATE)); - } -} diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestTarContainerPacker.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestTarContainerPacker.java deleted file mode 100644 index a599f721696..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestTarContainerPacker.java +++ /dev/null @@ -1,231 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.keyvalue; - -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.ozone.container.common.interfaces.ContainerPacker; - -import org.apache.commons.compress.archivers.tar.TarArchiveEntry; -import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; -import org.apache.commons.compress.compressors.CompressorException; -import org.apache.commons.compress.compressors.CompressorInputStream; -import org.apache.commons.compress.compressors.CompressorStreamFactory; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; - -/** - * Test the tar/untar for a given container. - */ -public class TestTarContainerPacker { - - private static final String TEST_DB_FILE_NAME = "test1"; - - private static final String TEST_DB_FILE_CONTENT = "test1"; - - private static final String TEST_CHUNK_FILE_NAME = "chunk1"; - - private static final String TEST_CHUNK_FILE_CONTENT = "This is a chunk"; - - private static final String TEST_DESCRIPTOR_FILE_CONTENT = "descriptor"; - - private ContainerPacker packer = new TarContainerPacker(); - - private static final Path SOURCE_CONTAINER_ROOT = - Paths.get("target/test/data/packer-source-dir"); - - private static final Path DEST_CONTAINER_ROOT = - Paths.get("target/test/data/packer-dest-dir"); - - @BeforeClass - public static void init() throws IOException { - initDir(SOURCE_CONTAINER_ROOT); - initDir(DEST_CONTAINER_ROOT); - } - - private static void initDir(Path path) throws IOException { - if (path.toFile().exists()) { - FileUtils.deleteDirectory(path.toFile()); - } - path.toFile().mkdirs(); - } - - private KeyValueContainerData createContainer(long id, Path dir, - OzoneConfiguration conf) throws IOException { - - Path containerDir = dir.resolve("container" + id); - Path dbDir = containerDir.resolve("db"); - Path dataDir = containerDir.resolve("data"); - Files.createDirectories(dbDir); - Files.createDirectories(dataDir); - - KeyValueContainerData containerData = new KeyValueContainerData(id, -1); - containerData.setChunksPath(dataDir.toString()); - containerData.setMetadataPath(dbDir.getParent().toString()); - containerData.setDbFile(dbDir.toFile()); - - - return containerData; - } - - @Test - public void pack() throws IOException, CompressorException { - - //GIVEN - OzoneConfiguration conf = new OzoneConfiguration(); - - KeyValueContainerData sourceContainerData = - createContainer(1L, SOURCE_CONTAINER_ROOT, conf); - - KeyValueContainer sourceContainer = - new KeyValueContainer(sourceContainerData, conf); - - //sample db file in the metadata directory - try (FileWriter writer = new FileWriter( - sourceContainerData.getDbFile().toPath() - .resolve(TEST_DB_FILE_NAME) - .toFile())) { - IOUtils.write(TEST_DB_FILE_CONTENT, writer); - } - - //sample chunk file in the chunk directory - try (FileWriter writer = new FileWriter( - Paths.get(sourceContainerData.getChunksPath()) - .resolve(TEST_CHUNK_FILE_NAME) - .toFile())) { - IOUtils.write(TEST_CHUNK_FILE_CONTENT, writer); - } - - //sample container descriptor file - try (FileWriter writer = new FileWriter( - sourceContainer.getContainerFile())) { - IOUtils.write(TEST_DESCRIPTOR_FILE_CONTENT, writer); - } - - Path targetFile = - SOURCE_CONTAINER_ROOT.getParent().resolve("container.tar.gz"); - - //WHEN: pack it - try (FileOutputStream output = new FileOutputStream(targetFile.toFile())) { - packer.pack(sourceContainer, output); - } - - //THEN: check the result - try (FileInputStream input = new FileInputStream(targetFile.toFile())) { - CompressorInputStream uncompressed = new CompressorStreamFactory() - .createCompressorInputStream(CompressorStreamFactory.GZIP, input); - TarArchiveInputStream tarStream = new TarArchiveInputStream(uncompressed); - - TarArchiveEntry entry; - Map entries = new HashMap<>(); - while ((entry = tarStream.getNextTarEntry()) != null) { - entries.put(entry.getName(), entry); - } - - Assert.assertTrue( - entries.containsKey("container.yaml")); - - } - - //read the container descriptor only - try (FileInputStream input = new FileInputStream(targetFile.toFile())) { - String containerYaml = new String(packer.unpackContainerDescriptor(input), - Charset.forName(StandardCharsets.UTF_8.name())); - Assert.assertEquals(TEST_DESCRIPTOR_FILE_CONTENT, containerYaml); - } - - KeyValueContainerData destinationContainerData = - createContainer(2L, DEST_CONTAINER_ROOT, conf); - - KeyValueContainer destinationContainer = - new KeyValueContainer(destinationContainerData, conf); - - String descriptor = ""; - - //unpackContainerData - try (FileInputStream input = new FileInputStream(targetFile.toFile())) { - descriptor = - new String(packer.unpackContainerData(destinationContainer, input), - Charset.forName(StandardCharsets.UTF_8.name())); - } - - assertExampleMetadataDbIsGood( - destinationContainerData.getDbFile().toPath()); - assertExampleChunkFileIsGood( - Paths.get(destinationContainerData.getChunksPath())); - Assert.assertFalse( - "Descriptor file should not been exctarcted by the " - + "unpackContainerData Call", - destinationContainer.getContainerFile().exists()); - Assert.assertEquals(TEST_DESCRIPTOR_FILE_CONTENT, descriptor); - - } - - - private void assertExampleMetadataDbIsGood(Path dbPath) - throws IOException { - - Path dbFile = dbPath.resolve(TEST_DB_FILE_NAME); - - Assert.assertTrue( - "example DB file is missing after pack/unpackContainerData: " + dbFile, - Files.exists(dbFile)); - - try (FileInputStream testFile = new FileInputStream(dbFile.toFile())) { - List strings = IOUtils - .readLines(testFile, Charset.forName(StandardCharsets.UTF_8.name())); - Assert.assertEquals(1, strings.size()); - Assert.assertEquals(TEST_DB_FILE_CONTENT, strings.get(0)); - } - } - - private void assertExampleChunkFileIsGood(Path chunkDirPath) - throws IOException { - - Path chunkFile = chunkDirPath.resolve(TEST_CHUNK_FILE_NAME); - - Assert.assertTrue( - "example chunk file is missing after pack/unpackContainerData: " - + chunkFile, - Files.exists(chunkFile)); - - try (FileInputStream testFile = new FileInputStream(chunkFile.toFile())) { - List strings = IOUtils - .readLines(testFile, Charset.forName(StandardCharsets.UTF_8.name())); - Assert.assertEquals(1, strings.size()); - Assert.assertEquals(TEST_CHUNK_FILE_CONTENT, strings.get(0)); - } - } - -} \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/ozoneimpl/TestOzoneContainer.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/ozoneimpl/TestOzoneContainer.java deleted file mode 100644 index fea126b5da8..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/ozoneimpl/TestOzoneContainer.java +++ /dev/null @@ -1,120 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.ozoneimpl; - - -import org.apache.hadoop.conf.StorageUnit; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.scm.ScmConfigKeys; -import org.apache.hadoop.ozone.OzoneConfigKeys; -import org.apache.hadoop.ozone.container.common.impl.ContainerSet; -import org.apache.hadoop.ozone.container.common.volume.HddsVolume; -import org.apache.hadoop.ozone.container.common.volume.RoundRobinVolumeChoosingPolicy; -import org.apache.hadoop.ozone.container.common.volume.VolumeSet; -import org.apache.hadoop.ozone.container.keyvalue.KeyValueContainer; -import org.apache.hadoop.ozone.container.keyvalue.KeyValueContainerData; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import java.util.Random; -import java.util.UUID; - - -import static org.junit.Assert.assertEquals; - -/** - * This class is used to test OzoneContainer. - */ -public class TestOzoneContainer { - - @Rule - public TemporaryFolder folder = new TemporaryFolder(); - - - private OzoneConfiguration conf; - private String scmId = UUID.randomUUID().toString(); - private VolumeSet volumeSet; - private RoundRobinVolumeChoosingPolicy volumeChoosingPolicy; - private KeyValueContainerData keyValueContainerData; - private KeyValueContainer keyValueContainer; - private final DatanodeDetails datanodeDetails = createDatanodeDetails(); - - @Before - public void setUp() throws Exception { - conf = new OzoneConfiguration(); - conf.set(ScmConfigKeys.HDDS_DATANODE_DIR_KEY, folder.getRoot() - .getAbsolutePath()); - conf.set(OzoneConfigKeys.OZONE_METADATA_DIRS, - folder.newFolder().getAbsolutePath()); - } - - @Test - public void testBuildContainerMap() throws Exception { - volumeSet = new VolumeSet(datanodeDetails.getUuidString(), conf); - volumeChoosingPolicy = new RoundRobinVolumeChoosingPolicy(); - - // Format the volumes - for (HddsVolume volume : volumeSet.getVolumesList()) { - volume.format(UUID.randomUUID().toString()); - } - - // Add containers to disk - for (int i=0; i<10; i++) { - keyValueContainerData = new KeyValueContainerData(i, - (long) StorageUnit.GB.toBytes(1)); - keyValueContainer = new KeyValueContainer( - keyValueContainerData, conf); - keyValueContainer.create(volumeSet, volumeChoosingPolicy, scmId); - } - - // When OzoneContainer is started, the containers from disk should be - // loaded into the containerSet. - OzoneContainer ozoneContainer = new - OzoneContainer(datanodeDetails, conf, null); - ContainerSet containerset = ozoneContainer.getContainerSet(); - assertEquals(10, containerset.containerCount()); - } - - - private DatanodeDetails createDatanodeDetails() { - Random random = new Random(); - String ipAddress = - random.nextInt(256) + "." + random.nextInt(256) + "." + random - .nextInt(256) + "." + random.nextInt(256); - - String uuid = UUID.randomUUID().toString(); - String hostName = uuid; - DatanodeDetails.Port containerPort = DatanodeDetails.newPort( - DatanodeDetails.Port.Name.STANDALONE, 0); - DatanodeDetails.Port ratisPort = DatanodeDetails.newPort( - DatanodeDetails.Port.Name.RATIS, 0); - DatanodeDetails.Port restPort = DatanodeDetails.newPort( - DatanodeDetails.Port.Name.REST, 0); - DatanodeDetails.Builder builder = DatanodeDetails.newBuilder(); - builder.setUuid(uuid) - .setHostName("localhost") - .setIpAddress(ipAddress) - .addPort(containerPort) - .addPort(ratisPort) - .addPort(restPort); - return builder.build(); - } -} diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/replication/TestReplicationSupervisor.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/replication/TestReplicationSupervisor.java deleted file mode 100644 index d433319fa7b..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/replication/TestReplicationSupervisor.java +++ /dev/null @@ -1,143 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.container.replication; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.ozone.container.common.impl.ContainerSet; -import org.apache.hadoop.ozone.container.keyvalue.KeyValueContainer; -import org.apache.hadoop.ozone.container.keyvalue.KeyValueContainerData; - -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -/** - * Test the replication supervisor. - */ -public class TestReplicationSupervisor { - - private OzoneConfiguration conf = new OzoneConfiguration(); - - @Test - public void normal() { - //GIVEN - ContainerSet set = new ContainerSet(); - - FakeReplicator replicator = new FakeReplicator(set); - ReplicationSupervisor supervisor = - new ReplicationSupervisor(set, replicator, 5); - - List datanodes = IntStream.range(1, 3) - .mapToObj(v -> Mockito.mock(DatanodeDetails.class)) - .collect(Collectors.toList()); - - try { - supervisor.start(); - //WHEN - supervisor.addTask(new ReplicationTask(1L, datanodes)); - supervisor.addTask(new ReplicationTask(1L, datanodes)); - supervisor.addTask(new ReplicationTask(1L, datanodes)); - supervisor.addTask(new ReplicationTask(2L, datanodes)); - supervisor.addTask(new ReplicationTask(2L, datanodes)); - supervisor.addTask(new ReplicationTask(3L, datanodes)); - try { - Thread.sleep(300); - } catch (InterruptedException e) { - e.printStackTrace(); - } - //THEN - System.out.println(replicator.replicated.get(0)); - - Assert - .assertEquals(3, replicator.replicated.size()); - - } finally { - supervisor.stop(); - } - } - - @Test - public void duplicateMessageAfterAWhile() throws InterruptedException { - //GIVEN - ContainerSet set = new ContainerSet(); - - FakeReplicator replicator = new FakeReplicator(set); - ReplicationSupervisor supervisor = - new ReplicationSupervisor(set, replicator, 2); - - List datanodes = IntStream.range(1, 3) - .mapToObj(v -> Mockito.mock(DatanodeDetails.class)) - .collect(Collectors.toList()); - - try { - supervisor.start(); - //WHEN - supervisor.addTask(new ReplicationTask(1L, datanodes)); - Thread.sleep(400); - supervisor.addTask(new ReplicationTask(1L, datanodes)); - Thread.sleep(300); - - //THEN - System.out.println(replicator.replicated.get(0)); - - Assert - .assertEquals(1, replicator.replicated.size()); - - //the last item is still in the queue as we cleanup the queue during the - // selection - Assert.assertEquals(1, supervisor.getQueueSize()); - - } finally { - supervisor.stop(); - } - } - - private class FakeReplicator implements ContainerReplicator { - - private List replicated = new ArrayList<>(); - - private ContainerSet containerSet; - - FakeReplicator(ContainerSet set) { - this.containerSet = set; - } - - @Override - public void replicate(ReplicationTask task) { - KeyValueContainerData kvcd = - new KeyValueContainerData(task.getContainerId(), 100L); - KeyValueContainer kvc = - new KeyValueContainer(kvcd, conf); - try { - //download is slow - Thread.sleep(100); - replicated.add(task); - containerSet.addContainer(kvc); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } -} \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/replication/package-info.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/replication/package-info.java deleted file mode 100644 index 5c905e02870..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/replication/package-info.java +++ /dev/null @@ -1,22 +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 - * - * 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. - * - */ -/** - * Tests for the container replication. - */ -package org.apache.hadoop.ozone.container.replication; \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/testutils/BlockDeletingServiceTestImpl.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/testutils/BlockDeletingServiceTestImpl.java deleted file mode 100644 index 115b5e2cf84..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/testutils/BlockDeletingServiceTestImpl.java +++ /dev/null @@ -1,104 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.container.testutils; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.ozone.container.common.impl.ContainerSet; -import org.apache.hadoop.ozone.container.keyvalue.statemachine.background - .BlockDeletingService; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * A test class implementation for {@link BlockDeletingService}. - */ -public class BlockDeletingServiceTestImpl - extends BlockDeletingService { - - // the service timeout - private static final int SERVICE_TIMEOUT_IN_MILLISECONDS = 0; - - // tests only - private CountDownLatch latch; - private Thread testingThread; - private AtomicInteger numOfProcessed = new AtomicInteger(0); - - public BlockDeletingServiceTestImpl(ContainerSet containerSet, - int serviceInterval, Configuration conf) { - super(containerSet, serviceInterval, SERVICE_TIMEOUT_IN_MILLISECONDS, - TimeUnit.MILLISECONDS, conf); - } - - @VisibleForTesting - public void runDeletingTasks() { - if (latch.getCount() > 0) { - this.latch.countDown(); - } else { - throw new IllegalStateException("Count already reaches zero"); - } - } - - @VisibleForTesting - public boolean isStarted() { - return latch != null && testingThread.isAlive(); - } - - public int getTimesOfProcessed() { - return numOfProcessed.get(); - } - - // Override the implementation to start a single on-call control thread. - @Override public void start() { - PeriodicalTask svc = new PeriodicalTask(); - // In test mode, relies on a latch countdown to runDeletingTasks tasks. - Runnable r = () -> { - while (true) { - latch = new CountDownLatch(1); - try { - latch.await(); - } catch (InterruptedException e) { - break; - } - Future future = this.getExecutorService().submit(svc); - try { - // for tests, we only wait for 3s for completion - future.get(3, TimeUnit.SECONDS); - numOfProcessed.incrementAndGet(); - } catch (Exception e) { - return; - } - } - }; - - testingThread = new ThreadFactoryBuilder() - .setDaemon(true) - .build() - .newThread(r); - testingThread.start(); - } - - @Override - public void shutdown() { - testingThread.interrupt(); - super.shutdown(); - } -} diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/testutils/package-info.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/testutils/package-info.java deleted file mode 100644 index 4e8a90bf1d4..00000000000 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/testutils/package-info.java +++ /dev/null @@ -1,18 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.container.testutils; -// Helper classes for ozone and container tests. \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/test/resources/additionalfields.container b/hadoop-hdds/container-service/src/test/resources/additionalfields.container deleted file mode 100644 index fff5304bea2..00000000000 --- a/hadoop-hdds/container-service/src/test/resources/additionalfields.container +++ /dev/null @@ -1,12 +0,0 @@ -! -containerDBType: RocksDB -chunksPath: /hdds/current/aed-fg4-hji-jkl/containerDir0/1 -containerID: 9223372036854775807 -containerType: KeyValueContainer -metadataPath: /hdds/current/aed-fg4-hji-jkl/containerDir0/1 -layOutVersion: 1 -maxSize: 5368709120 -metadata: {OWNER: ozone, VOLUME: hdfs} -state: CLOSED -aclEnabled: true -checksum: c5b5373b8755c4e7199478dcaded9d996f9aca089704e08950259cdb0f290680 \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/test/resources/incorrect.checksum.container b/hadoop-hdds/container-service/src/test/resources/incorrect.checksum.container deleted file mode 100644 index d06ba571281..00000000000 --- a/hadoop-hdds/container-service/src/test/resources/incorrect.checksum.container +++ /dev/null @@ -1,11 +0,0 @@ -! -containerDBType: RocksDB -chunksPath: /hdds/current/aed-fg4-hji-jkl/containerdir0/1 -containerID: 9223372036854775807 -containerType: KeyValueContainer -metadataPath: /hdds/current/aed-fg4-hji-jkl/containerdir0/1 -layOutVersion: 1 -maxSize: 5368709120 -metadata: {OWNER: ozone, VOLUME: hdfs} -state: OPEN -checksum: 08bc9d390f9183aeed3cf33c789e2a07310bba60f3cf55941caccc939db8670f \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/test/resources/incorrect.container b/hadoop-hdds/container-service/src/test/resources/incorrect.container deleted file mode 100644 index 0053ab29212..00000000000 --- a/hadoop-hdds/container-service/src/test/resources/incorrect.container +++ /dev/null @@ -1,11 +0,0 @@ -! -containerDBType: RocksDB -chunksPath: /hdds/current/aed-fg4-hji-jkl/containerDir0/1 -containerID: 9223372036854775807 -containerType: KeyValueContainer -metadataPath: /hdds/current/aed-fg4-hji-jkl/containerDir0/1 -layOutVersion: 1 -maxSize: 5368709120 -metadata: {OWNER: ozone, VOLUME: hdfs} -state: INVALID -checksum: 08bc9d390f9183aeed3cf33c789e2a07310bba60f3cf55941caccc939db8670f \ No newline at end of file diff --git a/hadoop-hdds/container-service/src/test/resources/log4j.properties b/hadoop-hdds/container-service/src/test/resources/log4j.properties deleted file mode 100644 index bb5cbe5ec32..00000000000 --- a/hadoop-hdds/container-service/src/test/resources/log4j.properties +++ /dev/null @@ -1,23 +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 -# -# 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. -# -# log4j configuration used during build and unit tests - -log4j.rootLogger=INFO,stdout -log4j.threshold=ALL -log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p %c{2} (%F:%M(%L)) - %m%n diff --git a/hadoop-hdds/framework/README.md b/hadoop-hdds/framework/README.md deleted file mode 100644 index 0eda3f5eddb..00000000000 --- a/hadoop-hdds/framework/README.md +++ /dev/null @@ -1,24 +0,0 @@ - - -# Server framework for HDDS/Ozone - -This project contains generic utilities and resources for all the HDDS/Ozone -server-side components. - -The project is shared between the server/service projects but not with the -client packages. \ No newline at end of file diff --git a/hadoop-hdds/framework/pom.xml b/hadoop-hdds/framework/pom.xml deleted file mode 100644 index 511f32131ce..00000000000 --- a/hadoop-hdds/framework/pom.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - 4.0.0 - - org.apache.hadoop - hadoop-hdds - 0.3.0-SNAPSHOT - - hadoop-hdds-server-framework - 0.3.0-SNAPSHOT - Apache Hadoop Distributed Data Store Server Framework - Apache Hadoop HDDS Server Framework - jar - - - - org.apache.hadoop - hadoop-hdds-common - - - org.mockito - mockito-all - test - - - - - - - org.apache.maven.plugins - maven-antrun-plugin - - - copy web resources - compile - - run - - - - - - - - - - - - - - - diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/BaseHttpServer.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/BaseHttpServer.java deleted file mode 100644 index da5d8dae4ad..00000000000 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/BaseHttpServer.java +++ /dev/null @@ -1,222 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.hdds.server; - -import com.google.common.base.Optional; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdfs.DFSConfigKeys; -import org.apache.hadoop.hdfs.DFSUtil; -import org.apache.hadoop.hdds.conf.HddsConfServlet; -import org.apache.hadoop.http.HttpConfig; -import org.apache.hadoop.http.HttpServer2; -import org.apache.hadoop.net.NetUtils; -import org.eclipse.jetty.webapp.WebAppContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.servlet.http.HttpServlet; -import java.io.IOException; -import java.net.InetSocketAddress; - -import static org.apache.hadoop.hdds.HddsUtils.getHostNameFromConfigKeys; -import static org.apache.hadoop.hdds.HddsUtils.getPortNumberFromConfigKeys; - -/** - * Base class for HTTP server of the Ozone related components. - */ -public abstract class BaseHttpServer { - - private static final Logger LOG = - LoggerFactory.getLogger(BaseHttpServer.class); - - private HttpServer2 httpServer; - private final Configuration conf; - - private InetSocketAddress httpAddress; - private InetSocketAddress httpsAddress; - - private HttpConfig.Policy policy; - - private String name; - - public BaseHttpServer(Configuration conf, String name) throws IOException { - this.name = name; - this.conf = conf; - if (isEnabled()) { - policy = DFSUtil.getHttpPolicy(conf); - if (policy.isHttpEnabled()) { - this.httpAddress = getHttpBindAddress(); - } - if (policy.isHttpsEnabled()) { - this.httpsAddress = getHttpsBindAddress(); - } - HttpServer2.Builder builder = null; - builder = DFSUtil.httpServerTemplateForNNAndJN(conf, this.httpAddress, - this.httpsAddress, name, getSpnegoPrincipal(), getKeytabFile()); - - final boolean xFrameEnabled = conf.getBoolean( - DFSConfigKeys.DFS_XFRAME_OPTION_ENABLED, - DFSConfigKeys.DFS_XFRAME_OPTION_ENABLED_DEFAULT); - - final String xFrameOptionValue = conf.getTrimmed( - DFSConfigKeys.DFS_XFRAME_OPTION_VALUE, - DFSConfigKeys.DFS_XFRAME_OPTION_VALUE_DEFAULT); - - builder.configureXFrame(xFrameEnabled).setXFrameOption(xFrameOptionValue); - - httpServer = builder.build(); - httpServer.addServlet("conf", "/conf", HddsConfServlet.class); - - } - - } - - /** - * Add a servlet to BaseHttpServer. - * - * @param servletName The name of the servlet - * @param pathSpec The path spec for the servlet - * @param clazz The servlet class - */ - protected void addServlet(String servletName, String pathSpec, - Class clazz) { - httpServer.addServlet(servletName, pathSpec, clazz); - } - - /** - * Returns the WebAppContext associated with this HttpServer. - * - * @return WebAppContext - */ - protected WebAppContext getWebAppContext() { - return httpServer.getWebAppContext(); - } - - protected InetSocketAddress getBindAddress(String bindHostKey, - String addressKey, String bindHostDefault, int bindPortdefault) { - final Optional bindHost = - getHostNameFromConfigKeys(conf, bindHostKey); - - final Optional addressPort = - getPortNumberFromConfigKeys(conf, addressKey); - - final Optional addresHost = - getHostNameFromConfigKeys(conf, addressKey); - - String hostName = bindHost.or(addresHost).or(bindHostDefault); - - return NetUtils.createSocketAddr( - hostName + ":" + addressPort.or(bindPortdefault)); - } - - /** - * Retrieve the socket address that should be used by clients to connect - * to the HTTPS web interface. - * - * @return Target InetSocketAddress for the Ozone HTTPS endpoint. - */ - public InetSocketAddress getHttpsBindAddress() { - return getBindAddress(getHttpsBindHostKey(), getHttpsAddressKey(), - getBindHostDefault(), getHttpsBindPortDefault()); - } - - /** - * Retrieve the socket address that should be used by clients to connect - * to the HTTP web interface. - *

- * * @return Target InetSocketAddress for the Ozone HTTP endpoint. - */ - public InetSocketAddress getHttpBindAddress() { - return getBindAddress(getHttpBindHostKey(), getHttpAddressKey(), - getBindHostDefault(), getHttpBindPortDefault()); - - } - - public void start() throws IOException { - if (httpServer != null && isEnabled()) { - httpServer.start(); - updateConnectorAddress(); - } - - } - - private boolean isEnabled() { - return conf.getBoolean(getEnabledKey(), true); - } - - public void stop() throws Exception { - if (httpServer != null) { - httpServer.stop(); - } - } - - /** - * Update the configured listen address based on the real port - *

- * (eg. replace :0 with real port) - */ - public void updateConnectorAddress() { - int connIdx = 0; - if (policy.isHttpEnabled()) { - httpAddress = httpServer.getConnectorAddress(connIdx++); - String realAddress = NetUtils.getHostPortString(httpAddress); - conf.set(getHttpAddressKey(), realAddress); - LOG.info( - String.format("HTTP server of %s is listening at http://%s", - name.toUpperCase(), realAddress)); - } - - if (policy.isHttpsEnabled()) { - httpsAddress = httpServer.getConnectorAddress(connIdx); - String realAddress = NetUtils.getHostPortString(httpsAddress); - conf.set(getHttpsAddressKey(), realAddress); - LOG.info( - String.format("HTTP server of %s is listening at https://%s", - name.toUpperCase(), realAddress)); - } - } - - public InetSocketAddress getHttpAddress() { - return httpAddress; - } - - public InetSocketAddress getHttpsAddress() { - return httpsAddress; - } - - protected abstract String getHttpAddressKey(); - - protected abstract String getHttpsAddressKey(); - - protected abstract String getHttpBindHostKey(); - - protected abstract String getHttpsBindHostKey(); - - protected abstract String getBindHostDefault(); - - protected abstract int getHttpBindPortDefault(); - - protected abstract int getHttpsBindPortDefault(); - - protected abstract String getKeytabFile(); - - protected abstract String getSpnegoPrincipal(); - - protected abstract String getEnabledKey(); - -} diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/ServerUtils.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/ServerUtils.java deleted file mode 100644 index c6d85d8b4fc..00000000000 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/ServerUtils.java +++ /dev/null @@ -1,144 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.hdds.server; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.ipc.RPC; -import org.apache.hadoop.ozone.OzoneConfigKeys; -import org.apache.http.client.methods.HttpRequestBase; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.net.InetSocketAddress; - -/** - * Generic utilities for all HDDS/Ozone servers. - */ -public final class ServerUtils { - - private static final Logger LOG = LoggerFactory.getLogger( - ServerUtils.class); - - private ServerUtils() { - } - - /** - * Checks that a given value is with a range. - * - * For example, sanitizeUserArgs(17, 3, 5, 10) - * ensures that 17 is greater/equal than 3 * 5 and less/equal to 3 * 10. - * - * @param valueTocheck - value to check - * @param baseValue - the base value that is being used. - * @param minFactor - range min - a 2 here makes us ensure that value - * valueTocheck is at least twice the baseValue. - * @param maxFactor - range max - * @return long - */ - public static long sanitizeUserArgs(long valueTocheck, long baseValue, - long minFactor, long maxFactor) - throws IllegalArgumentException { - if ((valueTocheck >= (baseValue * minFactor)) && - (valueTocheck <= (baseValue * maxFactor))) { - return valueTocheck; - } - String errMsg = String.format("%d is not within min = %d or max = " + - "%d", valueTocheck, baseValue * minFactor, baseValue * maxFactor); - throw new IllegalArgumentException(errMsg); - } - - - /** - * After starting an RPC server, updates configuration with the actual - * listening address of that server. The listening address may be different - * from the configured address if, for example, the configured address uses - * port 0 to request use of an ephemeral port. - * - * @param conf configuration to update - * @param rpcAddressKey configuration key for RPC server address - * @param addr configured address - * @param rpcServer started RPC server. - */ - public static InetSocketAddress updateRPCListenAddress( - OzoneConfiguration conf, String rpcAddressKey, - InetSocketAddress addr, RPC.Server rpcServer) { - return updateListenAddress(conf, rpcAddressKey, addr, - rpcServer.getListenerAddress()); - } - - - /** - * After starting an server, updates configuration with the actual - * listening address of that server. The listening address may be different - * from the configured address if, for example, the configured address uses - * port 0 to request use of an ephemeral port. - * - * @param conf configuration to update - * @param addressKey configuration key for RPC server address - * @param addr configured address - * @param listenAddr the real listening address. - */ - public static InetSocketAddress updateListenAddress(OzoneConfiguration conf, - String addressKey, InetSocketAddress addr, InetSocketAddress listenAddr) { - InetSocketAddress updatedAddr = new InetSocketAddress(addr.getHostString(), - listenAddr.getPort()); - conf.set(addressKey, - addr.getHostString() + ":" + listenAddr.getPort()); - return updatedAddr; - } - - - /** - * Releases a http connection if the request is not null. - * @param request - */ - public static void releaseConnection(HttpRequestBase request) { - if (request != null) { - request.releaseConnection(); - } - } - - - /** - * Checks and creates Ozone Metadir Path if it does not exist. - * - * @param conf - Configuration - * - * @return File MetaDir - */ - public static File getOzoneMetaDirPath(Configuration conf) { - String metaDirPath = conf.getTrimmed(OzoneConfigKeys - .OZONE_METADATA_DIRS); - Preconditions.checkNotNull(metaDirPath); - File dirPath = new File(metaDirPath); - if (!dirPath.exists() && !dirPath.mkdirs()) { - throw new IllegalArgumentException("Unable to create paths. Path: " + - dirPath); - } - return dirPath; - } - - public static void setOzoneMetaDirPath(OzoneConfiguration conf, - String path) { - conf.set(OzoneConfigKeys.OZONE_METADATA_DIRS, path); - } - -} diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/ServiceRuntimeInfo.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/ServiceRuntimeInfo.java deleted file mode 100644 index bcd75f3f215..00000000000 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/ServiceRuntimeInfo.java +++ /dev/null @@ -1,64 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.server; - -/** - * Common runtime information for any service components. - * - * Note: it's intentional to not use MXBean or MBean as a suffix of the name. - * - * Most of the services extends the ServiceRuntimeInfoImpl class and also - * implements a specific MXBean interface which extends this interface. - * - * This inheritance from multiple path could confuse the jmx system and - * some jmx properties could be disappeared. - * - * The solution is to always extend this interface and use the jmx naming - * convention in the new interface.. - */ -public interface ServiceRuntimeInfo { - - /** - * Gets the version of Hadoop. - * - * @return the version - */ - String getVersion(); - - /** - * Get the version of software running on the Namenode. - * - * @return a string representing the version - */ - String getSoftwareVersion(); - - /** - * Get the compilation information which contains date, user and branch. - * - * @return the compilation information, as a JSON string. - */ - String getCompileInfo(); - - /** - * Gets the NN start time in milliseconds. - * - * @return the NN start time in msec - */ - long getStartedTimeInMillis(); - -} diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/ServiceRuntimeInfoImpl.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/ServiceRuntimeInfoImpl.java deleted file mode 100644 index 36d6b64a688..00000000000 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/ServiceRuntimeInfoImpl.java +++ /dev/null @@ -1,55 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.server; - -import org.apache.hadoop.util.VersionInfo; - -/** - * Helper base class to report the standard version and runtime information. - * - */ -public class ServiceRuntimeInfoImpl implements ServiceRuntimeInfo { - - private long startedTimeInMillis; - - @Override - public String getVersion() { - return VersionInfo.getVersion() + ", r" + VersionInfo.getRevision(); - } - - @Override - public String getSoftwareVersion() { - return VersionInfo.getVersion(); - } - - @Override - public String getCompileInfo() { - return VersionInfo.getDate() + " by " + VersionInfo.getUser() + " from " - + VersionInfo.getBranch(); - } - - @Override - public long getStartedTimeInMillis() { - return startedTimeInMillis; - } - - public void setStartTime() { - startedTimeInMillis = System.currentTimeMillis(); - } - -} diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/Event.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/Event.java deleted file mode 100644 index 810c8b3437a..00000000000 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/Event.java +++ /dev/null @@ -1,42 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.server.events; - -/** - * Identifier of an async event. - * - * @param THe message payload type of this event. - */ -public interface Event { - - /** - * The type of the event payload. Payload contains all the required data - * to process the event. - * - */ - Class getPayloadType(); - - /** - * The human readable name of the event. - * - * Used for display in thread names - * and monitoring. - * - */ - String getName(); -} diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/EventExecutor.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/EventExecutor.java deleted file mode 100644 index 42578394162..00000000000 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/EventExecutor.java +++ /dev/null @@ -1,68 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.server.events; - -/** - * Executors defined the way how an EventHandler should be called. - *

- * Executors are used only by the EventQueue and they do the thread separation - * between the caller and the EventHandler. - *

- * Executors should guarantee that only one thread is executing one - * EventHandler at the same time. - * - * @param the payload type of the event. - */ -public interface EventExecutor extends AutoCloseable { - - /** - * Process an event payload. - * - * @param handler the handler to process the payload - * @param eventPayload to be processed. - * @param publisher to send response/other message forward to the chain. - */ - void onMessage(EventHandler handler, - PAYLOAD eventPayload, - EventPublisher - publisher); - - /** - * Return the number of the failed events. - */ - long failedEvents(); - - - /** - * Return the number of the processed events. - */ - long successfulEvents(); - - /** - * Return the number of the not-yet processed events. - */ - long queuedEvents(); - - /** - * The human readable name for the event executor. - *

- * Used in monitoring and logging. - * - */ - String getName(); -} diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/EventHandler.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/EventHandler.java deleted file mode 100644 index f40fc9e4f15..00000000000 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/EventHandler.java +++ /dev/null @@ -1,33 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.server.events; - -/** - * Processor to react on an event. - * - * EventExecutors should guarantee that the implementations are called only - * from one thread. - * - * @param - */ -@FunctionalInterface -public interface EventHandler { - - void onMessage(PAYLOAD payload, EventPublisher publisher); - -} diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/EventPublisher.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/EventPublisher.java deleted file mode 100644 index a47fb5721e2..00000000000 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/EventPublisher.java +++ /dev/null @@ -1,28 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.server.events; - -/** - * Client interface to send a new event. - */ -public interface EventPublisher { - - > void - fireEvent(EVENT_TYPE event, PAYLOAD payload); - -} diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/EventQueue.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/EventQueue.java deleted file mode 100644 index 9aeab7bfc38..00000000000 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/EventQueue.java +++ /dev/null @@ -1,251 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.server.events; - -import com.google.common.annotations.VisibleForTesting; - -import org.apache.hadoop.util.StringUtils; -import org.apache.hadoop.util.Time; - -import com.google.common.base.Preconditions; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.atomic.AtomicLong; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -/** - * Simple async event processing utility. - *

- * Event queue handles a collection of event handlers and routes the incoming - * events to one (or more) event handler. - */ -public class EventQueue implements EventPublisher, AutoCloseable { - - private static final Logger LOG = - LoggerFactory.getLogger(EventQueue.class); - - private static final String EXECUTOR_NAME_SEPARATOR = "For"; - - private final Map>> executors = - new HashMap<>(); - - private final AtomicLong queuedCount = new AtomicLong(0); - - private final AtomicLong eventCount = new AtomicLong(0); - - private boolean isRunning = true; - - public > void addHandler( - EVENT_TYPE event, EventHandler handler) { - this.addHandler(event, handler, generateHandlerName(handler)); - } - - /** - * Add new handler to the event queue. - *

- * By default a separated single thread executor will be dedicated to - * deliver the events to the registered event handler. - * - * @param event Triggering event. - * @param handler Handler of event (will be called from a separated - * thread) - * @param handlerName The name of handler (should be unique together with - * the event name) - * @param The type of the event payload. - * @param The type of the event identifier. - */ - public > void addHandler( - EVENT_TYPE event, EventHandler handler, String handlerName) { - validateEvent(event); - Preconditions.checkNotNull(handler, "Handler name should not be null."); - String executorName = - StringUtils.camelize(event.getName()) + EXECUTOR_NAME_SEPARATOR - + handlerName; - this.addHandler(event, new SingleThreadExecutor<>(executorName), handler); - } - - private > void validateEvent(EVENT_TYPE event) { - Preconditions - .checkArgument(!event.getName().contains(EXECUTOR_NAME_SEPARATOR), - "Event name should not contain " + EXECUTOR_NAME_SEPARATOR - + " string."); - - } - - private String generateHandlerName(EventHandler handler) { - if (!"".equals(handler.getClass().getSimpleName())) { - return handler.getClass().getSimpleName(); - } else { - return handler.getClass().getName(); - } - } - - /** - * Add event handler with custom executor. - * - * @param event Triggering event. - * @param executor The executor imlementation to deliver events from a - * separated threads. Please keep in your mind that - * registering metrics is the responsibility of the - * caller. - * @param handler Handler of event (will be called from a separated - * thread) - * @param The type of the event payload. - * @param The type of the event identifier. - */ - public > void addHandler( - EVENT_TYPE event, EventExecutor executor, - EventHandler handler) { - if (!isRunning) { - LOG.warn("Not adding handler for {}, EventQueue is not running", event); - return; - } - validateEvent(event); - executors.putIfAbsent(event, new HashMap<>()); - executors.get(event).putIfAbsent(executor, new ArrayList<>()); - - executors.get(event).get(executor).add(handler); - } - - - - /** - * Route an event with payload to the right listener(s). - * - * @param event The event identifier - * @param payload The payload of the event. - * @throws IllegalArgumentException If there is no EventHandler for - * the specific event. - */ - public > void fireEvent( - EVENT_TYPE event, PAYLOAD payload) { - - if (!isRunning) { - LOG.warn("Processing of {} is skipped, EventQueue is not running", event); - return; - } - - Map> eventExecutorListMap = - this.executors.get(event); - - eventCount.incrementAndGet(); - if (eventExecutorListMap != null) { - - for (Map.Entry> executorAndHandlers : - eventExecutorListMap.entrySet()) { - - for (EventHandler handler : executorAndHandlers.getValue()) { - queuedCount.incrementAndGet(); - if (LOG.isDebugEnabled()) { - LOG.debug("Delivering event {} to executor/handler {}: {}", - event.getName(), - executorAndHandlers.getKey().getName(), - payload); - } - executorAndHandlers.getKey() - .onMessage(handler, payload, this); - - } - } - - } else { - LOG.warn("No event handler registered for event " + event); - } - - } - - /** - * This is just for unit testing, don't use it for production code. - *

- * It waits for all messages to be processed. If one event handler invokes an - * other one, the later one also should be finished. - *

- * Long counter overflow is not handled, therefore it's safe only for unit - * testing. - *

- * This method is just eventually consistent. In some cases it could return - * even if there are new messages in some of the handler. But in a simple - * case (one message) it will return only if the message is processed and - * all the dependent messages (messages which are sent by current handlers) - * are processed. - * - * @param timeout Timeout in seconds to wait for the processing. - */ - @VisibleForTesting - public void processAll(long timeout) { - long currentTime = Time.now(); - while (true) { - - if (!isRunning) { - LOG.warn("Processing of event skipped. EventQueue is not running"); - return; - } - - long processed = 0; - - Stream allExecutor = this.executors.values().stream() - .flatMap(handlerMap -> handlerMap.keySet().stream()); - - boolean allIdle = - allExecutor.allMatch(executor -> executor.queuedEvents() == executor - .successfulEvents() + executor.failedEvents()); - - if (allIdle) { - return; - } - - try { - Thread.sleep(100); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - if (Time.now() > currentTime + timeout) { - throw new AssertionError( - "Messages are not processed in the given timeframe. Queued: " - + queuedCount.get() + " Processed: " + processed); - } - } - } - - public void close() { - - isRunning = false; - - Set allExecutors = this.executors.values().stream() - .flatMap(handlerMap -> handlerMap.keySet().stream()) - .collect(Collectors.toSet()); - - allExecutors.forEach(executor -> { - try { - executor.close(); - } catch (Exception ex) { - LOG.error("Can't close the executor " + executor.getName(), ex); - } - }); - } - - -} diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/EventWatcher.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/EventWatcher.java deleted file mode 100644 index ba5078b402c..00000000000 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/EventWatcher.java +++ /dev/null @@ -1,209 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.server.events; - -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import org.apache.hadoop.metrics2.MetricsSystem; -import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem; -import org.apache.hadoop.ozone.lease.Lease; -import org.apache.hadoop.ozone.lease.LeaseAlreadyExistException; -import org.apache.hadoop.ozone.lease.LeaseExpiredException; -import org.apache.hadoop.ozone.lease.LeaseManager; -import org.apache.hadoop.ozone.lease.LeaseNotFoundException; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import org.apache.commons.collections.map.HashedMap; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Event watcher the (re)send a message after timeout. - *

- * Event watcher will send the tracked payload/event after a timeout period - * unless a confirmation from the original event (completion event) is arrived. - * - * @param The type of the events which are tracked. - * @param The type of event which could cancel the - * tracking. - */ -@SuppressWarnings("CheckStyle") -public abstract class EventWatcher { - - private static final Logger LOG = LoggerFactory.getLogger(EventWatcher.class); - - private final Event startEvent; - - private final Event completionEvent; - - private final LeaseManager leaseManager; - - private final EventWatcherMetrics metrics; - - private final String name; - - protected final Map trackedEventsByID = - new ConcurrentHashMap<>(); - - protected final Set trackedEvents = new HashSet<>(); - - private final Map startTrackingTimes = new HashedMap(); - - public EventWatcher(String name, Event startEvent, - Event completionEvent, - LeaseManager leaseManager) { - this.startEvent = startEvent; - this.completionEvent = completionEvent; - this.leaseManager = leaseManager; - this.metrics = new EventWatcherMetrics(); - Preconditions.checkNotNull(name); - if (name.equals("")) { - name = getClass().getSimpleName(); - } - if (name.equals("")) { - //for anonymous inner classes - name = getClass().getName(); - } - this.name = name; - } - - public EventWatcher(Event startEvent, - Event completionEvent, - LeaseManager leaseManager) { - this("", startEvent, completionEvent, leaseManager); - } - - public void start(EventQueue queue) { - - queue.addHandler(startEvent, this::handleStartEvent); - - queue.addHandler(completionEvent, (completionPayload, publisher) -> { - try { - handleCompletion(completionPayload, publisher); - } catch (LeaseNotFoundException e) { - //It's already done. Too late, we already retried it. - //Not a real problem. - LOG.warn("Completion event without active lease. Id={}", - completionPayload.getId()); - } - }); - - MetricsSystem ms = DefaultMetricsSystem.instance(); - ms.register(name, "EventWatcher metrics", metrics); - } - - private synchronized void handleStartEvent(TIMEOUT_PAYLOAD payload, - EventPublisher publisher) { - metrics.incrementTrackedEvents(); - long identifier = payload.getId(); - startTrackingTimes.put(identifier, System.currentTimeMillis()); - - trackedEventsByID.put(identifier, payload); - trackedEvents.add(payload); - try { - Lease lease = leaseManager.acquire(identifier); - try { - lease.registerCallBack(() -> { - handleTimeout(publisher, identifier); - return null; - }); - - } catch (LeaseExpiredException e) { - handleTimeout(publisher, identifier); - } - } catch (LeaseAlreadyExistException e) { - //No problem at all. But timer is not reset. - } - } - - protected synchronized void handleCompletion(COMPLETION_PAYLOAD - completionPayload, EventPublisher publisher) throws - LeaseNotFoundException { - metrics.incrementCompletedEvents(); - long id = completionPayload.getId(); - leaseManager.release(id); - TIMEOUT_PAYLOAD payload = trackedEventsByID.remove(id); - trackedEvents.remove(payload); - long originalTime = startTrackingTimes.remove(id); - metrics.updateFinishingTime(System.currentTimeMillis() - originalTime); - onFinished(publisher, payload); - } - - private synchronized void handleTimeout(EventPublisher publisher, - long identifier) { - metrics.incrementTimedOutEvents(); - TIMEOUT_PAYLOAD payload = trackedEventsByID.remove(identifier); - trackedEvents.remove(payload); - startTrackingTimes.remove(payload.getId()); - onTimeout(publisher, payload); - } - - - /** - * Check if a specific payload is in-progress. - */ - public synchronized boolean contains(TIMEOUT_PAYLOAD payload) { - return trackedEvents.contains(payload); - } - - public synchronized boolean remove(TIMEOUT_PAYLOAD payload) { - try { - leaseManager.release(payload.getId()); - } catch (LeaseNotFoundException e) { - LOG.warn("Completion event without active lease. Id={}", - payload.getId()); - } - trackedEventsByID.remove(payload.getId()); - return trackedEvents.remove(payload); - - } - - protected abstract void onTimeout( - EventPublisher publisher, TIMEOUT_PAYLOAD payload); - - protected abstract void onFinished( - EventPublisher publisher, TIMEOUT_PAYLOAD payload); - - public List getTimeoutEvents( - Predicate predicate) { - return trackedEventsByID.values().stream().filter(predicate) - .collect(Collectors.toList()); - } - - @VisibleForTesting - protected EventWatcherMetrics getMetrics() { - return metrics; - } - - /** - * Returns a tracked event to which the specified id is - * mapped, or {@code null} if there is no mapping for the id. - */ - public TIMEOUT_PAYLOAD getTrackedEventbyId(long id) { - return trackedEventsByID.get(id); - } -} diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/EventWatcherMetrics.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/EventWatcherMetrics.java deleted file mode 100644 index 1db81a98890..00000000000 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/EventWatcherMetrics.java +++ /dev/null @@ -1,79 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.server.events; - -import org.apache.hadoop.metrics2.annotation.Metric; -import org.apache.hadoop.metrics2.lib.MutableCounterLong; -import org.apache.hadoop.metrics2.lib.MutableRate; - -import com.google.common.annotations.VisibleForTesting; - -/** - * Metrics for any event watcher. - */ -public class EventWatcherMetrics { - - @Metric() - private MutableCounterLong trackedEvents; - - @Metric() - private MutableCounterLong timedOutEvents; - - @Metric() - private MutableCounterLong completedEvents; - - @Metric() - private MutableRate completionTime; - - public void incrementTrackedEvents() { - trackedEvents.incr(); - } - - public void incrementTimedOutEvents() { - timedOutEvents.incr(); - } - - public void incrementCompletedEvents() { - completedEvents.incr(); - } - - @VisibleForTesting - public void updateFinishingTime(long duration) { - completionTime.add(duration); - } - - @VisibleForTesting - public MutableCounterLong getTrackedEvents() { - return trackedEvents; - } - - @VisibleForTesting - public MutableCounterLong getTimedOutEvents() { - return timedOutEvents; - } - - @VisibleForTesting - public MutableCounterLong getCompletedEvents() { - return completedEvents; - } - - @VisibleForTesting - public MutableRate getCompletionTime() { - return completionTime; - } -} diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/IdentifiableEventPayload.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/IdentifiableEventPayload.java deleted file mode 100644 index 3faa8e70d1b..00000000000 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/IdentifiableEventPayload.java +++ /dev/null @@ -1,28 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.server.events; - -/** - * Event with an additional unique identifier. - * - */ -public interface IdentifiableEventPayload { - - long getId(); - -} diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/SingleThreadExecutor.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/SingleThreadExecutor.java deleted file mode 100644 index 3253f2d5db2..00000000000 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/SingleThreadExecutor.java +++ /dev/null @@ -1,118 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.server.events; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -import org.apache.hadoop.metrics2.annotation.Metric; -import org.apache.hadoop.metrics2.annotation.Metrics; -import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem; -import org.apache.hadoop.metrics2.lib.MutableCounterLong; - -/** - * Simple EventExecutor to call all the event handler one-by-one. - * - * @param - */ -@Metrics(context = "EventQueue") -public class SingleThreadExecutor implements EventExecutor { - - public static final String THREAD_NAME_PREFIX = "EventQueue"; - - private static final Logger LOG = - LoggerFactory.getLogger(SingleThreadExecutor.class); - - private final String name; - - private final ThreadPoolExecutor executor; - - @Metric - private MutableCounterLong queued; - - @Metric - private MutableCounterLong done; - - @Metric - private MutableCounterLong failed; - - /** - * Create SingleThreadExecutor. - * - * @param name Unique name used in monitoring and metrics. - */ - public SingleThreadExecutor(String name) { - this.name = name; - DefaultMetricsSystem.instance() - .register("EventQueue" + name, "Event Executor metrics ", this); - - LinkedBlockingQueue workQueue = new LinkedBlockingQueue<>(); - executor = - new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, workQueue, - runnable -> { - Thread thread = new Thread(runnable); - thread.setName(THREAD_NAME_PREFIX + "-" + name); - return thread; - }); - - } - - @Override - public void onMessage(EventHandler handler, T message, EventPublisher - publisher) { - queued.incr(); - executor.execute(() -> { - try { - handler.onMessage(message, publisher); - done.incr(); - } catch (Exception ex) { - LOG.error("Error on execution message {}", message, ex); - failed.incr(); - } - }); - } - - @Override - public long failedEvents() { - return failed.value(); - } - - @Override - public long successfulEvents() { - return done.value(); - } - - @Override - public long queuedEvents() { - return queued.value(); - } - - @Override - public void close() { - executor.shutdown(); - } - - @Override - public String getName() { - return name; - } -} diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/TypedEvent.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/TypedEvent.java deleted file mode 100644 index 27bba3ab6b4..00000000000 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/TypedEvent.java +++ /dev/null @@ -1,58 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.server.events; - -/** - * Basic event implementation to implement custom events. - * - * @param - */ -public class TypedEvent implements Event { - - private final Class payloadType; - - private final String name; - - public TypedEvent(Class payloadType, String name) { - this.payloadType = payloadType; - this.name = name; - } - - public TypedEvent(Class payloadType) { - this.payloadType = payloadType; - this.name = payloadType.getSimpleName(); - } - - @Override - public Class getPayloadType() { - return payloadType; - } - - @Override - public String getName() { - return name; - } - - @Override - public String toString() { - return "TypedEvent{" + - "payloadType=" + payloadType.getSimpleName() + - ", name='" + name + '\'' + - '}'; - } -} diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/package-info.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/package-info.java deleted file mode 100644 index 89999ee6d8a..00000000000 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/events/package-info.java +++ /dev/null @@ -1,23 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.server.events; - -/** - * Simple event queue implementation for hdds/ozone components. - */ \ No newline at end of file diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/package-info.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/package-info.java deleted file mode 100644 index 35ad5e7f496..00000000000 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/package-info.java +++ /dev/null @@ -1,23 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.server; - -/** - * Common server side utilities for all the hdds/ozone server components. - */ \ No newline at end of file diff --git a/hadoop-hdds/framework/src/main/resources/webapps/datanode/dn.js b/hadoop-hdds/framework/src/main/resources/webapps/datanode/dn.js deleted file mode 100644 index 3b671671de2..00000000000 --- a/hadoop-hdds/framework/src/main/resources/webapps/datanode/dn.js +++ /dev/null @@ -1,92 +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 - * - * 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. - */ -(function () { - "use strict"; - - var data = {ozone: {enabled: false}}; - - dust.loadSource(dust.compile($('#tmpl-dn').html(), 'dn')); - - function loadDatanodeInfo() { - $.get('/jmx?qry=Hadoop:service=DataNode,name=DataNodeInfo', function(resp) { - data.dn = workaround(resp.beans[0]); - data.dn.HostName = resp.beans[0]['DatanodeHostname']; - render(); - }).fail(show_err_msg); - } - - function loadOzoneScmInfo() { - $.get('/jmx?qry=Hadoop:service=OzoneDataNode,name=SCMConnectionManager', function (resp) { - if (resp.beans.length > 0) { - data.ozone.SCMServers = resp.beans[0].SCMServers; - data.ozone.enabled = true; - render(); - } - }).fail(show_err_msg); - } - - function loadOzoneStorageInfo() { - $.get('/jmx?qry=Hadoop:service=OzoneDataNode,name=ContainerLocationManager', function (resp) { - if (resp.beans.length > 0) { - data.ozone.LocationReport = resp.beans[0].LocationReport; - data.ozone.enabled = true; - render(); - } - }).fail(show_err_msg); - } - - function workaround(dn) { - function node_map_to_array(nodes) { - var res = []; - for (var n in nodes) { - var p = nodes[n]; - p.name = n; - res.push(p); - } - return res; - } - - dn.VolumeInfo = node_map_to_array(JSON.parse(dn.VolumeInfo)); - dn.BPServiceActorInfo = JSON.parse(dn.BPServiceActorInfo); - - return dn; - } - - function render() { - var base = dust.makeBase({ - 'helper_relative_time' : function (chunk, ctx, bodies, params) { - var value = dust.helpers.tap(params.value, chunk, ctx); - return chunk.write(moment().subtract(Number(value), 'seconds').fromNow(true)); - } - }); - dust.render('dn', base.push(data), function(err, out) { - $('#tab-overview').html(out); - $('#tab-overview').addClass('active'); - }); - } - - function show_err_msg() { - $('#alert-panel-body').html("Failed to load datanode information"); - $('#alert-panel').show(); - } - - loadDatanodeInfo(); - loadOzoneScmInfo(); - loadOzoneStorageInfo(); - -})(); diff --git a/hadoop-hdds/framework/src/main/resources/webapps/static/angular-1.6.4.min.js b/hadoop-hdds/framework/src/main/resources/webapps/static/angular-1.6.4.min.js deleted file mode 100644 index c4bf158ece9..00000000000 --- a/hadoop-hdds/framework/src/main/resources/webapps/static/angular-1.6.4.min.js +++ /dev/null @@ -1,332 +0,0 @@ -/* - AngularJS v1.6.4 - (c) 2010-2017 Google, Inc. http://angularjs.org - License: MIT -*/ -(function(x){'use strict';function L(a,b){b=b||Error;return function(){var d=arguments[0],c;c="["+(a?a+":":"")+d+"] http://errors.angularjs.org/1.6.4/"+(a?a+"/":"")+d;for(d=1;dc)return"...";var d=b.$$hashKey,f;if(H(a)){f=0;for(var g=a.length;f").append(a).html();try{return a[0].nodeType===Ia?Q(d):d.match(/^(<[^>]+>)/)[1].replace(/^<([\w-]+)/,function(a,b){return"<"+Q(b)})}catch(c){return Q(d)}}function Qc(a){try{return decodeURIComponent(a)}catch(b){}}function Rc(a){var b={};q((a||"").split("&"),function(a){var c,e,f;a&&(e=a=a.replace(/\+/g,"%20"),c=a.indexOf("="),-1!==c&&(e=a.substring(0,c),f=a.substring(c+1)),e=Qc(e),u(e)&&(f= -u(f)?Qc(f):!0,ua.call(b,e)?H(b[e])?b[e].push(f):b[e]=[b[e],f]:b[e]=f))});return b}function Zb(a){var b=[];q(a,function(a,c){H(a)?q(a,function(a){b.push($(c,!0)+(!0===a?"":"="+$(a,!0)))}):b.push($(c,!0)+(!0===a?"":"="+$(a,!0)))});return b.length?b.join("&"):""}function db(a){return $(a,!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+")}function $(a,b){return encodeURIComponent(a).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%3B/gi,";").replace(/%20/g, -b?"%20":"+")}function te(a,b){var d,c,e=Ja.length;for(c=0;c protocol indicates an extension, document.location.href does not match."))} -function Sc(a,b,d){C(d)||(d={});d=S({strictDi:!1},d);var c=function(){a=B(a);if(a.injector()){var c=a[0]===x.document?"document":xa(a);throw Fa("btstrpd",c.replace(//,">"));}b=b||[];b.unshift(["$provide",function(b){b.value("$rootElement",a)}]);d.debugInfoEnabled&&b.push(["$compileProvider",function(a){a.debugInfoEnabled(!0)}]);b.unshift("ng");c=eb(b,d.strictDi);c.invoke(["$rootScope","$rootElement","$compile","$injector",function(a,b,c,d){a.$apply(function(){b.data("$injector", -d);c(b)(a)})}]);return c},e=/^NG_ENABLE_DEBUG_INFO!/,f=/^NG_DEFER_BOOTSTRAP!/;x&&e.test(x.name)&&(d.debugInfoEnabled=!0,x.name=x.name.replace(e,""));if(x&&!f.test(x.name))return c();x.name=x.name.replace(f,"");ea.resumeBootstrap=function(a){q(a,function(a){b.push(a)});return c()};D(ea.resumeDeferredBootstrap)&&ea.resumeDeferredBootstrap()}function we(){x.name="NG_ENABLE_DEBUG_INFO!"+x.name;x.location.reload()}function xe(a){a=ea.element(a).injector();if(!a)throw Fa("test");return a.get("$$testability")} -function Tc(a,b){b=b||"_";return a.replace(ye,function(a,c){return(c?b:"")+a.toLowerCase()})}function ze(){var a;if(!Uc){var b=rb();(na=w(b)?x.jQuery:b?x[b]:void 0)&&na.fn.on?(B=na,S(na.fn,{scope:Na.scope,isolateScope:Na.isolateScope,controller:Na.controller,injector:Na.injector,inheritedData:Na.inheritedData}),a=na.cleanData,na.cleanData=function(b){for(var c,e=0,f;null!=(f=b[e]);e++)(c=na._data(f,"events"))&&c.$destroy&&na(f).triggerHandler("$destroy");a(b)}):B=W;ea.element=B;Uc=!0}}function fb(a, -b,d){if(!a)throw Fa("areq",b||"?",d||"required");return a}function sb(a,b,d){d&&H(a)&&(a=a[a.length-1]);fb(D(a),b,"not a function, got "+(a&&"object"===typeof a?a.constructor.name||"Object":typeof a));return a}function Ka(a,b){if("hasOwnProperty"===a)throw Fa("badname",b);}function Vc(a,b,d){if(!b)return a;b=b.split(".");for(var c,e=a,f=b.length,g=0;g")+c[2];for(c=c[0];c--;)d=d.lastChild;f=ab(f,d.childNodes); -d=e.firstChild;d.textContent=""}else f.push(b.createTextNode(a));e.textContent="";e.innerHTML="";q(f,function(a){e.appendChild(a)});return e}function W(a){if(a instanceof W)return a;var b;F(a)&&(a=T(a),b=!0);if(!(this instanceof W)){if(b&&"<"!==a.charAt(0))throw dc("nosel");return new W(a)}if(b){b=x.document;var d;a=(d=dg.exec(a))?[b.createElement(d[1])]:(d=dd(a,b))?d.childNodes:[];ec(this,a)}else D(a)?ed(a):ec(this,a)}function fc(a){return a.cloneNode(!0)}function xb(a,b){!b&&bc(a)&&B.cleanData([a]); -a.querySelectorAll&&B.cleanData(a.querySelectorAll("*"))}function fd(a,b,d,c){if(u(c))throw dc("offargs");var e=(c=yb(a))&&c.events,f=c&&c.handle;if(f)if(b){var g=function(b){var c=e[b];u(d)&&$a(c||[],d);u(d)&&c&&0l&&this.remove(p.key);return b}},get:function(a){if(l";b=ta.firstChild.attributes;var d=b[0];b.removeNamedItem(d.name);d.value=c;a.attributes.setNamedItem(d)}function La(a, -b){try{a.addClass(b)}catch(c){}}function ca(a,b,c,d,e){a instanceof B||(a=B(a));var f=Ma(a,b,a,c,d,e);ca.$$addScopeClass(a);var g=null;return function(b,c,d){if(!a)throw fa("multilink");fb(b,"scope");e&&e.needsNewScope&&(b=b.$parent.$new());d=d||{};var h=d.parentBoundTranscludeFn,k=d.transcludeControllers;d=d.futureParentElement;h&&h.$$boundTransclude&&(h=h.$$boundTransclude);g||(g=(d=d&&d[0])?"foreignobject"!==wa(d)&&ma.call(d).match(/SVG/)?"svg":"html":"html");d="html"!==g?B(ha(g,B("

").append(a).html())): -c?Na.clone.call(a):a;if(k)for(var l in k)d.data("$"+l+"Controller",k[l].instance);ca.$$addScopeInfo(d,b);c&&c(d,b);f&&f(b,d,d,h);c||(a=f=null);return d}}function Ma(a,b,c,d,e,f){function g(a,c,d,e){var f,k,l,m,n,p,r;if(K)for(r=Array(c.length),m=0;my.priority)break;if(x=y.scope)y.templateUrl||(C(x)?($("new/isolated scope",E||K,y,v),E=y):$("new/isolated scope",E,y,v)),K=K||y;P=y.name;if(!u&&(y.replace&&(y.templateUrl||y.template)||y.transclude&&!y.$$tlb)){for(x=z+1;u=a[x++];)if(u.transclude&&!u.$$tlb||u.replace&&(u.templateUrl||u.template)){La=!0;break}u=!0}!y.templateUrl&& -y.controller&&(G=G||V(),$("'"+P+"' controller",G[P],y,v),G[P]=y);if(x=y.transclude)if(J=!0,y.$$tlb||($("transclusion",t,y,v),t=y),"element"===x)X=!0,p=y.priority,N=v,v=d.$$element=B(ca.$$createComment(P,d[P])),b=v[0],ka(f,va.call(N,0),b),N[0].$$parentNode=N[0].parentNode,A=kc(La,N,e,p,g&&g.name,{nonTlbTranscludeDirective:t});else{var ja=V();if(C(x)){N=[];var Q=V(),jb=V();q(x,function(a,b){var c="?"===a.charAt(0);a=c?a.substring(1):a;Q[a]=b;ja[b]=null;jb[b]=c});q(v.contents(),function(a){var b=Q[Ba(wa(a))]; -b?(jb[b]=!0,ja[b]=ja[b]||[],ja[b].push(a)):N.push(a)});q(jb,function(a,b){if(!a)throw fa("reqslot",b);});for(var ic in ja)ja[ic]&&(ja[ic]=kc(La,ja[ic],e))}else N=B(fc(b)).contents();v.empty();A=kc(La,N,e,void 0,void 0,{needsNewScope:y.$$isolateScope||y.$$newScope});A.$$slots=ja}if(y.template)if(O=!0,$("template",I,y,v),I=y,x=D(y.template)?y.template(v,d):y.template,x=Ea(x),y.replace){g=y;N=cc.test(x)?pd(ha(y.templateNamespace,T(x))):[];b=N[0];if(1!==N.length||1!==b.nodeType)throw fa("tplrt",P,""); -ka(f,v,b);F={$attr:{}};x=jc(b,[],F);var Y=a.splice(z+1,a.length-(z+1));(E||K)&&aa(x,E,K);a=a.concat(x).concat(Y);da(d,F);F=a.length}else v.html(x);if(y.templateUrl)O=!0,$("template",I,y,v),I=y,y.replace&&(g=y),n=ga(a.splice(z,a.length-z),v,d,f,J&&A,h,k,{controllerDirectives:G,newScopeDirective:K!==y&&K,newIsolateScopeDirective:E,templateDirective:I,nonTlbTranscludeDirective:t}),F=a.length;else if(y.compile)try{R=y.compile(v,d,A);var Z=y.$$originalDirective||y;D(R)?m(null,bb(Z,R),Ma,L):R&&m(bb(Z,R.pre), -bb(Z,R.post),Ma,L)}catch(ea){c(ea,xa(v))}y.terminal&&(n.terminal=!0,p=Math.max(p,y.priority))}n.scope=K&&!0===K.scope;n.transcludeOnThisElement=J;n.templateOnThisElement=O;n.transclude=A;l.hasElementTranscludeDirective=X;return n}function U(a,b,c,d){var e;if(F(b)){var f=b.match(l);b=b.substring(f[0].length);var g=f[1]||f[3],f="?"===f[2];"^^"===g?c=c.parent():e=(e=d&&d[b])&&e.instance;if(!e){var h="$"+b+"Controller";e=g?c.inheritedData(h):c.data(h)}if(!e&&!f)throw fa("ctreq",b,a);}else if(H(b))for(e= -[],g=0,f=b.length;gc.priority)&&-1!==c.restrict.indexOf(e)){k&&(c=Vb(c,{$$start:k,$$end:l}));if(!c.$$bindings){var K=m=c,r=c.name,t={isolateScope:null,bindToController:null};C(K.scope)&&(!0===K.bindToController?(t.bindToController=d(K.scope,r,!0),t.isolateScope={}):t.isolateScope=d(K.scope,r,!1));C(K.bindToController)&&(t.bindToController=d(K.bindToController,r,!0));if(t.bindToController&&!K.controller)throw fa("noctrl", -r);m=m.$$bindings=t;C(m.isolateScope)&&(c.$$isolateBindings=m.isolateScope)}b.push(c);m=c}}return m}function Z(b){if(f.hasOwnProperty(b))for(var c=a.get(b+"Directive"),d=0,e=c.length;d"+b+"";return c.childNodes[0].childNodes;default:return b}}function oa(a,b){if("srcdoc"===b)return y.HTML;var c=wa(a);if("src"===b||"ngSrc"===b){if(-1===["img","video","audio","source","track"].indexOf(c))return y.RESOURCE_URL}else if("xlinkHref"===b||"form"===c&&"action"===b||"link"===c&&"href"===b)return y.RESOURCE_URL}function pa(a, -c,d,e,f){var g=oa(a,e),h=k[e]||f,l=b(d,!f,g,h);if(l){if("multiple"===e&&"select"===wa(a))throw fa("selmulti",xa(a));if(m.test(e))throw fa("nodomevents");c.push({priority:100,compile:function(){return{pre:function(a,c,f){c=f.$$observers||(f.$$observers=V());var k=f[e];k!==d&&(l=k&&b(k,!0,g,h),d=k);l&&(f[e]=l(a),(c[e]||(c[e]=[])).$$inter=!0,(f.$$observers&&f.$$observers[e].$$scope||a).$watch(l,function(a,b){"class"===e&&a!==b?f.$updateClass(a,b):f.$set(e,a)}))}}}})}}function ka(a,b,c){var d=b[0],e= -b.length,f=d.parentNode,g,h;if(a)for(g=0,h=a.length;g=b)return a;for(;b--;){var d=a[b];(8===d.nodeType||d.nodeType===Ia&&""===d.nodeValue.trim())&&sg.call(a,b,1)}return a}function qg(a,b){if(b&&F(b))return b;if(F(a)){var d=sd.exec(a);if(d)return d[3]}}function wf(){var a={},b=!1;this.has=function(b){return a.hasOwnProperty(b)};this.register=function(b,c){Ka(b,"controller");C(b)? -S(a,b):a[b]=c};this.allowGlobals=function(){b=!0};this.$get=["$injector","$window",function(d,c){function e(a,b,c,d){if(!a||!C(a.$scope))throw L("$controller")("noscp",d,b);a.$scope[b]=c}return function(f,g,h,k){var l,m,n;h=!0===h;k&&F(k)&&(n=k);if(F(f)){k=f.match(sd);if(!k)throw td("ctrlfmt",f);m=k[1];n=n||k[3];f=a.hasOwnProperty(m)?a[m]:Vc(g.$scope,m,!0)||(b?Vc(c,m,!0):void 0);if(!f)throw td("ctrlreg",m);sb(f,m,!0)}if(h)return h=(H(f)?f[f.length-1]:f).prototype,l=Object.create(h||null),n&&e(g,n, -l,m||f.name),S(function(){var a=d.invoke(f,l,g,m);a!==l&&(C(a)||D(a))&&(l=a,n&&e(g,n,l,m||f.name));return l},{instance:l,identifier:n});l=d.instantiate(f,g,m);n&&e(g,n,l,m||f.name);return l}}]}function xf(){this.$get=["$window",function(a){return B(a.document)}]}function yf(){this.$get=["$document","$rootScope",function(a,b){function d(){e=c.hidden}var c=a[0],e=c&&c.hidden;a.on("visibilitychange",d);b.$on("$destroy",function(){a.off("visibilitychange",d)});return function(){return e}}]}function zf(){this.$get= -["$log",function(a){return function(b,d){a.error.apply(a,arguments)}}]}function mc(a){return C(a)?ga(a)?a.toISOString():cb(a):a}function Ef(){this.$get=function(){return function(a){if(!a)return"";var b=[];Kc(a,function(a,c){null===a||w(a)||(H(a)?q(a,function(a){b.push($(c)+"="+$(mc(a)))}):b.push($(c)+"="+$(mc(a))))});return b.join("&")}}}function Ff(){this.$get=function(){return function(a){function b(a,e,f){null===a||w(a)||(H(a)?q(a,function(a,c){b(a,e+"["+(C(a)?c:"")+"]")}):C(a)&&!ga(a)?Kc(a,function(a, -c){b(a,e+(f?"":"[")+c+(f?"":"]"))}):d.push($(e)+"="+$(mc(a))))}if(!a)return"";var d=[];b(a,"",!0);return d.join("&")}}}function nc(a,b){if(F(a)){var d=a.replace(tg,"").trim();if(d){var c=b("Content-Type");(c=c&&0===c.indexOf(ud))||(c=(c=d.match(ug))&&vg[c[0]].test(d));if(c)try{a=Oc(d)}catch(e){throw oc("baddata",a,e);}}}return a}function vd(a){var b=V(),d;F(a)?q(a.split("\n"),function(a){d=a.indexOf(":");var e=Q(T(a.substr(0,d)));a=T(a.substr(d+1));e&&(b[e]=b[e]?b[e]+", "+a:a)}):C(a)&&q(a,function(a, -d){var f=Q(d),g=T(a);f&&(b[f]=b[f]?b[f]+", "+g:g)});return b}function wd(a){var b;return function(d){b||(b=vd(a));return d?(d=b[Q(d)],void 0===d&&(d=null),d):b}}function xd(a,b,d,c){if(D(c))return c(a,b,d);q(c,function(c){a=c(a,b,d)});return a}function Df(){var a=this.defaults={transformResponse:[nc],transformRequest:[function(a){return C(a)&&"[object File]"!==ma.call(a)&&"[object Blob]"!==ma.call(a)&&"[object FormData]"!==ma.call(a)?cb(a):a}],headers:{common:{Accept:"application/json, text/plain, */*"}, -post:pa(pc),put:pa(pc),patch:pa(pc)},xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",paramSerializer:"$httpParamSerializer",jsonpCallbackParam:"callback"},b=!1;this.useApplyAsync=function(a){return u(a)?(b=!!a,this):b};var d=this.interceptors=[];this.$get=["$browser","$httpBackend","$$cookieReader","$cacheFactory","$rootScope","$q","$injector","$sce",function(c,e,f,g,h,k,l,m){function n(b){function d(a,b){for(var c=0,e=b.length;ca?b:k.reject(b)}if(!C(b))throw L("$http")("badreq",b);if(!F(m.valueOf(b.url)))throw L("$http")("badreq",b.url);var g=S({method:"get",transformRequest:a.transformRequest,transformResponse:a.transformResponse,paramSerializer:a.paramSerializer,jsonpCallbackParam:a.jsonpCallbackParam},b);g.headers= -function(b){var c=a.headers,d=S({},b.headers),f,g,h,c=S({},c.common,c[Q(b.method)]);a:for(f in c){g=Q(f);for(h in d)if(Q(h)===g)continue a;d[f]=c[f]}return e(d,pa(b))}(b);g.method=ub(g.method);g.paramSerializer=F(g.paramSerializer)?l.get(g.paramSerializer):g.paramSerializer;c.$$incOutstandingRequestCount();var h=[],n=[];b=k.resolve(g);q(t,function(a){(a.request||a.requestError)&&h.unshift(a.request,a.requestError);(a.response||a.responseError)&&n.push(a.response,a.responseError)});b=d(b,h);b=b.then(function(b){var c= -b.headers,d=xd(b.data,wd(c),void 0,b.transformRequest);w(d)&&q(c,function(a,b){"content-type"===Q(b)&&delete c[b]});w(b.withCredentials)&&!w(a.withCredentials)&&(b.withCredentials=a.withCredentials);return p(b,d).then(f,f)});b=d(b,n);return b=b.finally(function(){c.$$completeOutstandingRequest(z)})}function p(c,d){function g(a){if(a){var c={};q(a,function(a,d){c[d]=function(c){function d(){a(c)}b?h.$applyAsync(d):h.$$phase?d():h.$apply(d)}});return c}}function l(a,c,d,e){function f(){p(c,a,d,e)}O&& -(200<=a&&300>a?O.put(R,[a,c,vd(d),e]):O.remove(R));b?h.$applyAsync(f):(f(),h.$$phase||h.$apply())}function p(a,b,d,e){b=-1<=b?b:0;(200<=b&&300>b?G.resolve:G.reject)({data:a,status:b,headers:wd(d),config:c,statusText:e})}function K(a){p(a.data,a.status,pa(a.headers()),a.statusText)}function t(){var a=n.pendingRequests.indexOf(c);-1!==a&&n.pendingRequests.splice(a,1)}var G=k.defer(),y=G.promise,O,X,P=c.headers,s="jsonp"===Q(c.method),R=c.url;s?R=m.getTrustedResourceUrl(R):F(R)||(R=m.valueOf(R));R=r(R, -c.paramSerializer(c.params));s&&(R=J(R,c.jsonpCallbackParam));n.pendingRequests.push(c);y.then(t,t);!c.cache&&!a.cache||!1===c.cache||"GET"!==c.method&&"JSONP"!==c.method||(O=C(c.cache)?c.cache:C(a.cache)?a.cache:v);O&&(X=O.get(R),u(X)?X&&D(X.then)?X.then(K,K):H(X)?p(X[1],X[0],pa(X[2]),X[3]):p(X,200,{},"OK"):O.put(R,y));w(X)&&((X=yd(c.url)?f()[c.xsrfCookieName||a.xsrfCookieName]:void 0)&&(P[c.xsrfHeaderName||a.xsrfHeaderName]=X),e(c.method,R,d,l,P,c.timeout,c.withCredentials,c.responseType,g(c.eventHandlers), -g(c.uploadEventHandlers)));return y}function r(a,b){0=l&&(q.resolve(t),v(A.$$intervalId),delete g[A.$$intervalId]);M||a.$apply()},k);g[A.$$intervalId]=q;return A}var g={};f.cancel=function(a){return a&&a.$$intervalId in g?(g[a.$$intervalId].promise.catch(z),g[a.$$intervalId].reject("canceled"),b.clearInterval(a.$$intervalId),delete g[a.$$intervalId],!0):!1};return f}]}function qc(a){a=a.split("/");for(var b=a.length;b--;)a[b]= -db(a[b]);return a.join("/")}function zd(a,b){var d=Ca(a);b.$$protocol=d.protocol;b.$$host=d.hostname;b.$$port=Z(d.port)||xg[d.protocol]||null}function Ad(a,b){if(yg.test(a))throw kb("badpath",a);var d="/"!==a.charAt(0);d&&(a="/"+a);var c=Ca(a);b.$$path=decodeURIComponent(d&&"/"===c.pathname.charAt(0)?c.pathname.substring(1):c.pathname);b.$$search=Rc(c.search);b.$$hash=decodeURIComponent(c.hash);b.$$path&&"/"!==b.$$path.charAt(0)&&(b.$$path="/"+b.$$path)}function rc(a,b){return a.slice(0,b.length)=== -b}function ka(a,b){if(rc(b,a))return b.substr(a.length)}function Aa(a){var b=a.indexOf("#");return-1===b?a:a.substr(0,b)}function lb(a){return a.replace(/(#.+)|#$/,"$1")}function sc(a,b,d){this.$$html5=!0;d=d||"";zd(a,this);this.$$parse=function(a){var d=ka(b,a);if(!F(d))throw kb("ipthprfx",a,b);Ad(d,this);this.$$path||(this.$$path="/");this.$$compose()};this.$$compose=function(){var a=Zb(this.$$search),d=this.$$hash?"#"+db(this.$$hash):"";this.$$url=qc(this.$$path)+(a?"?"+a:"")+d;this.$$absUrl=b+ -this.$$url.substr(1);this.$$urlUpdatedByLocation=!0};this.$$parseLinkUrl=function(c,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f,g;u(f=ka(a,c))?(g=f,g=d&&u(f=ka(d,f))?b+(ka("/",f)||f):a+g):u(f=ka(b,c))?g=b+f:b===c+"/"&&(g=b);g&&this.$$parse(g);return!!g}}function tc(a,b,d){zd(a,this);this.$$parse=function(c){var e=ka(a,c)||ka(b,c),f;w(e)||"#"!==e.charAt(0)?this.$$html5?f=e:(f="",w(e)&&(a=c,this.replace())):(f=ka(d,e),w(f)&&(f=e));Ad(f,this);c=this.$$path;var e=a,g=/^\/[A-Z]:(\/.*)/;rc(f, -e)&&(f=f.replace(e,""));g.exec(f)||(c=(f=g.exec(c))?f[1]:c);this.$$path=c;this.$$compose()};this.$$compose=function(){var b=Zb(this.$$search),e=this.$$hash?"#"+db(this.$$hash):"";this.$$url=qc(this.$$path)+(b?"?"+b:"")+e;this.$$absUrl=a+(this.$$url?d+this.$$url:"");this.$$urlUpdatedByLocation=!0};this.$$parseLinkUrl=function(b,d){return Aa(a)===Aa(b)?(this.$$parse(b),!0):!1}}function Bd(a,b,d){this.$$html5=!0;tc.apply(this,arguments);this.$$parseLinkUrl=function(c,e){if(e&&"#"===e[0])return this.hash(e.slice(1)), -!0;var f,g;a===Aa(c)?f=c:(g=ka(b,c))?f=a+d+g:b===c+"/"&&(f=b);f&&this.$$parse(f);return!!f};this.$$compose=function(){var b=Zb(this.$$search),e=this.$$hash?"#"+db(this.$$hash):"";this.$$url=qc(this.$$path)+(b?"?"+b:"")+e;this.$$absUrl=a+d+this.$$url;this.$$urlUpdatedByLocation=!0}}function Jb(a){return function(){return this[a]}}function Cd(a,b){return function(d){if(w(d))return this[a];this[a]=b(d);this.$$compose();return this}}function Jf(){var a="!",b={enabled:!1,requireBase:!0,rewriteLinks:!0}; -this.hashPrefix=function(b){return u(b)?(a=b,this):a};this.html5Mode=function(a){if(Ha(a))return b.enabled=a,this;if(C(a)){Ha(a.enabled)&&(b.enabled=a.enabled);Ha(a.requireBase)&&(b.requireBase=a.requireBase);if(Ha(a.rewriteLinks)||F(a.rewriteLinks))b.rewriteLinks=a.rewriteLinks;return this}return b};this.$get=["$rootScope","$browser","$sniffer","$rootElement","$window",function(d,c,e,f,g){function h(a,b,d){var e=l.url(),f=l.$$state;try{c.url(a,b,d),l.$$state=c.state()}catch(g){throw l.url(e),l.$$state= -f,g;}}function k(a,b){d.$broadcast("$locationChangeSuccess",l.absUrl(),a,l.$$state,b)}var l,m;m=c.baseHref();var n=c.url(),p;if(b.enabled){if(!m&&b.requireBase)throw kb("nobase");p=n.substring(0,n.indexOf("/",n.indexOf("//")+2))+(m||"/");m=e.history?sc:Bd}else p=Aa(n),m=tc;var r=p.substr(0,Aa(p).lastIndexOf("/")+1);l=new m(p,r,"#"+a);l.$$parseLinkUrl(n,n);l.$$state=c.state();var J=/^\s*(javascript|mailto):/i;f.on("click",function(a){var e=b.rewriteLinks;if(e&&!a.ctrlKey&&!a.metaKey&&!a.shiftKey&& -2!==a.which&&2!==a.button){for(var h=B(a.target);"a"!==wa(h[0]);)if(h[0]===f[0]||!(h=h.parent())[0])return;if(!F(e)||!w(h.attr(e))){var e=h.prop("href"),k=h.attr("href")||h.attr("xlink:href");C(e)&&"[object SVGAnimatedString]"===e.toString()&&(e=Ca(e.animVal).href);J.test(e)||!e||h.attr("target")||a.isDefaultPrevented()||!l.$$parseLinkUrl(e,k)||(a.preventDefault(),l.absUrl()!==c.url()&&(d.$apply(),g.angular["ff-684208-preventDefault"]=!0))}}});lb(l.absUrl())!==lb(n)&&c.url(l.absUrl(),!0);var v=!0; -c.onUrlChange(function(a,b){rc(a,r)?(d.$evalAsync(function(){var c=l.absUrl(),e=l.$$state,f;a=lb(a);l.$$parse(a);l.$$state=b;f=d.$broadcast("$locationChangeStart",a,c,b,e).defaultPrevented;l.absUrl()===a&&(f?(l.$$parse(c),l.$$state=e,h(c,!1,e)):(v=!1,k(c,e)))}),d.$$phase||d.$digest()):g.location.href=a});d.$watch(function(){if(v||l.$$urlUpdatedByLocation){l.$$urlUpdatedByLocation=!1;var a=lb(c.url()),b=lb(l.absUrl()),f=c.state(),g=l.$$replace,m=a!==b||l.$$html5&&e.history&&f!==l.$$state;if(v||m)v= -!1,d.$evalAsync(function(){var b=l.absUrl(),c=d.$broadcast("$locationChangeStart",b,a,l.$$state,f).defaultPrevented;l.absUrl()===b&&(c?(l.$$parse(a),l.$$state=f):(m&&h(b,g,f===l.$$state?null:l.$$state),k(a,f)))})}l.$$replace=!1});return l}]}function Kf(){var a=!0,b=this;this.debugEnabled=function(b){return u(b)?(a=b,this):a};this.$get=["$window",function(d){function c(a){a instanceof Error&&(a.stack&&f?a=a.message&&-1===a.stack.indexOf(a.message)?"Error: "+a.message+"\n"+a.stack:a.stack:a.sourceURL&& -(a=a.message+"\n"+a.sourceURL+":"+a.line));return a}function e(a){var b=d.console||{},e=b[a]||b.log||z;a=!1;try{a=!!e.apply}catch(f){}return a?function(){var a=[];q(arguments,function(b){a.push(c(b))});return e.apply(b,a)}:function(a,b){e(a,null==b?"":b)}}var f=za||/\bEdge\//.test(d.navigator&&d.navigator.userAgent);return{log:e("log"),info:e("info"),warn:e("warn"),error:e("error"),debug:function(){var c=e("debug");return function(){a&&c.apply(b,arguments)}}()}}]}function zg(a){return a+""}function Ag(a, -b){return"undefined"!==typeof a?a:b}function Dd(a,b){return"undefined"===typeof a?b:"undefined"===typeof b?a:a+b}function U(a,b){var d,c,e;switch(a.type){case s.Program:d=!0;q(a.body,function(a){U(a.expression,b);d=d&&a.expression.constant});a.constant=d;break;case s.Literal:a.constant=!0;a.toWatch=[];break;case s.UnaryExpression:U(a.argument,b);a.constant=a.argument.constant;a.toWatch=a.argument.toWatch;break;case s.BinaryExpression:U(a.left,b);U(a.right,b);a.constant=a.left.constant&&a.right.constant; -a.toWatch=a.left.toWatch.concat(a.right.toWatch);break;case s.LogicalExpression:U(a.left,b);U(a.right,b);a.constant=a.left.constant&&a.right.constant;a.toWatch=a.constant?[]:[a];break;case s.ConditionalExpression:U(a.test,b);U(a.alternate,b);U(a.consequent,b);a.constant=a.test.constant&&a.alternate.constant&&a.consequent.constant;a.toWatch=a.constant?[]:[a];break;case s.Identifier:a.constant=!1;a.toWatch=[a];break;case s.MemberExpression:U(a.object,b);a.computed&&U(a.property,b);a.constant=a.object.constant&& -(!a.computed||a.property.constant);a.toWatch=[a];break;case s.CallExpression:d=e=a.filter?!b(a.callee.name).$stateful:!1;c=[];q(a.arguments,function(a){U(a,b);d=d&&a.constant;a.constant||c.push.apply(c,a.toWatch)});a.constant=d;a.toWatch=e?c:[a];break;case s.AssignmentExpression:U(a.left,b);U(a.right,b);a.constant=a.left.constant&&a.right.constant;a.toWatch=[a];break;case s.ArrayExpression:d=!0;c=[];q(a.elements,function(a){U(a,b);d=d&&a.constant;a.constant||c.push.apply(c,a.toWatch)});a.constant= -d;a.toWatch=c;break;case s.ObjectExpression:d=!0;c=[];q(a.properties,function(a){U(a.value,b);d=d&&a.value.constant&&!a.computed;a.value.constant||c.push.apply(c,a.value.toWatch);a.computed&&(U(a.key,b),a.key.constant||c.push.apply(c,a.key.toWatch))});a.constant=d;a.toWatch=c;break;case s.ThisExpression:a.constant=!1;a.toWatch=[];break;case s.LocalsExpression:a.constant=!1,a.toWatch=[]}}function Ed(a){if(1===a.length){a=a[0].expression;var b=a.toWatch;return 1!==b.length?b:b[0]!==a?b:void 0}}function Fd(a){return a.type=== -s.Identifier||a.type===s.MemberExpression}function Gd(a){if(1===a.body.length&&Fd(a.body[0].expression))return{type:s.AssignmentExpression,left:a.body[0].expression,right:{type:s.NGValueParameter},operator:"="}}function Hd(a){this.$filter=a}function Id(a){this.$filter=a}function uc(a,b,d){this.ast=new s(a,d);this.astCompiler=d.csp?new Id(b):new Hd(b)}function vc(a){return D(a.valueOf)?a.valueOf():Bg.call(a)}function Lf(){var a=V(),b={"true":!0,"false":!1,"null":null,undefined:void 0},d,c;this.addLiteral= -function(a,c){b[a]=c};this.setIdentifierFns=function(a,b){d=a;c=b;return this};this.$get=["$filter",function(e){function f(a,b,c){return null==a||null==b?a===b:"object"!==typeof a||(a=vc(a),"object"!==typeof a||c)?a===b||a!==a&&b!==b:!1}function g(a,b,c,d,e){var g=d.inputs,h;if(1===g.length){var k=f,g=g[0];return a.$watch(function(a){var b=g(a);f(b,k,d.literal)||(h=d(a,void 0,void 0,[b]),k=b&&vc(b));return h},b,c,e)}for(var l=[],m=[],n=0,E=g.length;n=c.$$state.status&&e&&e.length&&a(function(){for(var a,c,f=0,g=e.length;fa)for(b in l++,f)ua.call(e,b)||(t--,delete f[b])}else f!==e&&(f=e,l++);return l}}c.$stateful=!0;var d=this,e,f,h,k=1t&&(w=4-t,u[w]||(u[w]=[]),u[w].push({msg:D(a.exp)?"fn: "+(a.exp.name||a.exp.toString()):a.exp,newVal:g,oldVal:k}));else if(a===c){r=!1;break a}}catch(B){f(B)}if(!(p=q.$$watchersCount&&q.$$childHead||q!==this&&q.$$nextSibling))for(;q!==this&&!(p=q.$$nextSibling);)q=q.$parent}while(q=p);if((r||s.length)&&!t--)throw M.$$phase= -null,d("infdig",b,u);}while(r||s.length);for(M.$$phase=null;Iza)throw ta("iequirks");var c=pa(oa);c.isEnabled=function(){return a};c.trustAs=d.trustAs;c.getTrusted=d.getTrusted;c.valueOf=d.valueOf;a||(c.trustAs=c.getTrusted=function(a,b){return b},c.valueOf=Ya);c.parseAs=function(a,d){var e=b(d);return e.literal&&e.constant?e:b(d,function(b){return c.getTrusted(a,b)})};var e=c.parseAs, -f=c.getTrusted,g=c.trustAs;q(oa,function(a,b){var d=Q(b);c[("parse_as_"+d).replace(xc,gb)]=function(b){return e(a,b)};c[("get_trusted_"+d).replace(xc,gb)]=function(b){return f(a,b)};c[("trust_as_"+d).replace(xc,gb)]=function(b){return g(a,b)}});return c}]}function Rf(){this.$get=["$window","$document",function(a,b){var d={},c=!((!a.nw||!a.nw.process)&&a.chrome&&(a.chrome.app&&a.chrome.app.runtime||!a.chrome.app&&a.chrome.runtime&&a.chrome.runtime.id))&&a.history&&a.history.pushState,e=Z((/android (\d+)/.exec(Q((a.navigator|| -{}).userAgent))||[])[1]),f=/Boxee/i.test((a.navigator||{}).userAgent),g=b[0]||{},h=g.body&&g.body.style,k=!1,l=!1;h&&(k=!!("transition"in h||"webkitTransition"in h),l=!!("animation"in h||"webkitAnimation"in h));return{history:!(!c||4>e||f),hasEvent:function(a){if("input"===a&&za)return!1;if(w(d[a])){var b=g.createElement("div");d[a]="on"+a in b}return d[a]},csp:Ga(),transitions:k,animations:l,android:e}}]}function Tf(){var a;this.httpOptions=function(b){return b?(a=b,this):a};this.$get=["$exceptionHandler", -"$templateCache","$http","$q","$sce",function(b,d,c,e,f){function g(h,k){g.totalPendingRequests++;if(!F(h)||w(d.get(h)))h=f.getTrustedResourceUrl(h);var l=c.defaults&&c.defaults.transformResponse;H(l)?l=l.filter(function(a){return a!==nc}):l===nc&&(l=null);return c.get(h,S({cache:d,transformResponse:l},a)).finally(function(){g.totalPendingRequests--}).then(function(a){d.put(h,a.data);return a.data},function(a){k||(a=Dg("tpload",h,a.status,a.statusText),b(a));return e.reject(a)})}g.totalPendingRequests= -0;return g}]}function Uf(){this.$get=["$rootScope","$browser","$location",function(a,b,d){return{findBindings:function(a,b,d){a=a.getElementsByClassName("ng-binding");var g=[];q(a,function(a){var c=ea.element(a).data("$binding");c&&q(c,function(c){d?(new RegExp("(^|\\s)"+Kd(b)+"(\\s|\\||$)")).test(c)&&g.push(a):-1!==c.indexOf(b)&&g.push(a)})});return g},findModels:function(a,b,d){for(var g=["ng-","data-ng-","ng\\:"],h=0;hc&&(c=e),c+=+a.slice(e+1),a=a.substring(0,e)):0>c&&(c=a.length);for(e=0;a.charAt(e)===zc;e++); -if(e===(g=a.length))d=[0],c=1;else{for(g--;a.charAt(g)===zc;)g--;c-=e;d=[];for(f=0;e<=g;e++,f++)d[f]=+a.charAt(e)}c>Ud&&(d=d.splice(0,Ud-1),b=c-1,c=1);return{d:d,e:b,i:c}}function Lg(a,b,d,c){var e=a.d,f=e.length-a.i;b=w(b)?Math.min(Math.max(d,f),c):+b;d=b+a.i;c=e[d];if(0d-1){for(c=0;c>d;c--)e.unshift(0),a.i++;e.unshift(1);a.i++}else e[d- -1]++;for(;fh;)k.unshift(0),h++;0=b.lgSize&&h.unshift(k.splice(-b.lgSize,k.length).join(""));k.length> -b.gSize;)h.unshift(k.splice(-b.gSize,k.length).join(""));k.length&&h.unshift(k.join(""));k=h.join(d);f.length&&(k+=c+f.join(""));e&&(k+="e+"+e)}return 0>a&&!g?b.negPre+k+b.negSuf:b.posPre+k+b.posSuf}function Kb(a,b,d,c){var e="";if(0>a||c&&0>=a)c?a=-a+1:(a=-a,e="-");for(a=""+a;a.length-d)f+=d;0===f&&-12===d&&(f=12);return Kb(f,b,c,e)}}function mb(a,b,d){return function(c,e){var f= -c["get"+a](),g=ub((d?"STANDALONE":"")+(b?"SHORT":"")+a);return e[g][f]}}function Vd(a){var b=(new Date(a,0,1)).getDay();return new Date(a,0,(4>=b?5:12)-b)}function Wd(a){return function(b){var d=Vd(b.getFullYear());b=+new Date(b.getFullYear(),b.getMonth(),b.getDate()+(4-b.getDay()))-+d;b=1+Math.round(b/6048E5);return Kb(b,a)}}function Ac(a,b){return 0>=a.getFullYear()?b.ERAS[0]:b.ERAS[1]}function Pd(a){function b(a){var b;if(b=a.match(d)){a=new Date(0);var f=0,g=0,h=b[8]?a.setUTCFullYear:a.setFullYear, -k=b[8]?a.setUTCHours:a.setHours;b[9]&&(f=Z(b[9]+b[10]),g=Z(b[9]+b[11]));h.call(a,Z(b[1]),Z(b[2])-1,Z(b[3]));f=Z(b[4]||0)-f;g=Z(b[5]||0)-g;h=Z(b[6]||0);b=Math.round(1E3*parseFloat("0."+(b[7]||0)));k.call(a,f,g,h,b)}return a}var d=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(c,d,f){var g="",h=[],k,l;d=d||"mediumDate";d=a.DATETIME_FORMATS[d]||d;F(c)&&(c=Mg.test(c)?Z(c):b(c));ba(c)&&(c=new Date(c));if(!ga(c)||!isFinite(c.getTime()))return c; -for(;d;)(l=Ng.exec(d))?(h=ab(h,l,1),d=h.pop()):(h.push(d),d=null);var m=c.getTimezoneOffset();f&&(m=Pc(f,m),c=Yb(c,f,!0));q(h,function(b){k=Og[b];g+=k?k(c,a.DATETIME_FORMATS,m):"''"===b?"'":b.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return g}}function Fg(){return function(a,b){w(b)&&(b=2);return cb(a,b)}}function Gg(){return function(a,b,d){b=Infinity===Math.abs(Number(b))?Number(b):Z(b);if(da(b))return a;ba(a)&&(a=a.toString());if(!qa(a))return a;d=!d||isNaN(d)?0:Z(d);d=0>d?Math.max(0,a.length+ -d):d;return 0<=b?Bc(a,d,d+b):0===d?Bc(a,b,a.length):Bc(a,Math.max(0,d+b),d)}}function Bc(a,b,d){return F(a)?a.slice(b,d):va.call(a,b,d)}function Rd(a){function b(b){return b.map(function(b){var c=1,d=Ya;if(D(b))d=b;else if(F(b)){if("+"===b.charAt(0)||"-"===b.charAt(0))c="-"===b.charAt(0)?-1:1,b=b.substring(1);if(""!==b&&(d=a(b),d.constant))var e=d(),d=function(a){return a[e]}}return{get:d,descending:c}})}function d(a){switch(typeof a){case "number":case "boolean":case "string":return!0;default:return!1}} -function c(a,b){var c=0,d=a.type,k=b.type;if(d===k){var k=a.value,l=b.value;"string"===d?(k=k.toLowerCase(),l=l.toLowerCase()):"object"===d&&(C(k)&&(k=a.index),C(l)&&(l=b.index));k!==l&&(c=kb||37<=b&&40>=b||m(a,this,this.value)});if(e.hasEvent("paste"))b.on("paste cut", -m)}b.on("change",l);if(ae[g]&&c.$$hasNativeValidators&&g===d.type)b.on("keydown wheel mousedown",function(a){if(!k){var b=this.validity,c=b.badInput,d=b.typeMismatch;k=f.defer(function(){k=null;b.badInput===c&&b.typeMismatch===d||l(a)})}});c.$render=function(){var a=c.$isEmpty(c.$viewValue)?"":c.$viewValue;b.val()!==a&&b.val(a)}}function Nb(a,b){return function(d,c){var e,f;if(ga(d))return d;if(F(d)){'"'===d.charAt(0)&&'"'===d.charAt(d.length-1)&&(d=d.substring(1,d.length-1));if(Pg.test(d))return new Date(d); -a.lastIndex=0;if(e=a.exec(d))return e.shift(),f=c?{yyyy:c.getFullYear(),MM:c.getMonth()+1,dd:c.getDate(),HH:c.getHours(),mm:c.getMinutes(),ss:c.getSeconds(),sss:c.getMilliseconds()/1E3}:{yyyy:1970,MM:1,dd:1,HH:0,mm:0,ss:0,sss:0},q(e,function(a,c){c=v};g.$observe("min",function(a){v=p(a);h.$validate()})}if(u(g.max)||g.ngMax){var t; -h.$validators.max=function(a){return!n(a)||w(t)||d(a)<=t};g.$observe("max",function(a){t=p(a);h.$validate()})}}}function Dc(a,b,d,c){(c.$$hasNativeValidators=C(b[0].validity))&&c.$parsers.push(function(a){var c=b.prop("validity")||{};return c.badInput||c.typeMismatch?void 0:a})}function be(a){a.$$parserName="number";a.$parsers.push(function(b){if(a.$isEmpty(b))return null;if(Qg.test(b))return parseFloat(b)});a.$formatters.push(function(b){if(!a.$isEmpty(b)){if(!ba(b))throw pb("numfmt",b);b=b.toString()}return b})} -function Sa(a){u(a)&&!ba(a)&&(a=parseFloat(a));return da(a)?void 0:a}function Ec(a){var b=a.toString(),d=b.indexOf(".");return-1===d?-1a&&(a=/e-(\d+)$/.exec(b))?Number(a[1]):0:b.length-d-1}function ce(a,b,d){a=Number(a);var c=(a|0)!==a,e=(b|0)!==b,f=(d|0)!==d;if(c||e||f){var g=c?Ec(a):0,h=e?Ec(b):0,k=f?Ec(d):0,g=Math.max(g,h,k),g=Math.pow(10,g);a*=g;b*=g;d*=g;c&&(a=Math.round(a));e&&(b=Math.round(b));f&&(d=Math.round(d))}return 0===(a-b)%d}function de(a,b,d,c,e){if(u(c)){a=a(c);if(!a.constant)throw pb("constexpr", -d,c);return a(b)}return e}function Fc(a,b){function d(a,b){if(!a||!a.length)return[];if(!b||!b.length)return a;var c=[],d=0;a:for(;d(?:<\/\1>|)$/, -cc=/<|&#?\w+;/,bg=/<([\w:-]+)/,cg=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,ha={option:[1,'"],thead:[1,"
","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ha.optgroup=ha.option;ha.tbody=ha.tfoot=ha.colgroup=ha.caption=ha.thead;ha.th=ha.td;var jg=x.Node.prototype.contains||function(a){return!!(this.compareDocumentPosition(a)& -16)},Na=W.prototype={ready:ed,toString:function(){var a=[];q(this,function(b){a.push(""+b)});return"["+a.join(", ")+"]"},eq:function(a){return 0<=a?B(this[a]):B(this[this.length+a])},length:0,push:Tg,sort:[].sort,splice:[].splice},Fb={};q("multiple selected checked disabled readOnly required open".split(" "),function(a){Fb[Q(a)]=a});var jd={};q("input select option textarea button form details".split(" "),function(a){jd[a]=!0});var rd={ngMinlength:"minlength",ngMaxlength:"maxlength",ngMin:"min",ngMax:"max", -ngPattern:"pattern",ngStep:"step"};q({data:hc,removeData:gc,hasData:function(a){for(var b in hb[a.ng339])return!0;return!1},cleanData:function(a){for(var b=0,d=a.length;b/,mg=/^[^(]*\(\s*([^)]*)\)/m,Wg=/,/,Xg=/^\s*(_?)(\S+?)\1\s*$/,kg=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg,ya=L("$injector");eb.$$annotate=function(a,b,d){var c;if("function"===typeof a){if(!(c=a.$inject)){c=[];if(a.length){if(b)throw F(d)&&d||(d=a.name||ng(a)),ya("strictdi",d);b=ld(a);q(b[1].split(Wg),function(a){a.replace(Xg,function(a,b,d){c.push(d)})})}a.$inject=c}}else H(a)?(b=a.length-1,sb(a[b],"fn"),c=a.slice(0,b)):sb(a,"fn", -!0);return c};var fe=L("$animate"),qf=function(){this.$get=z},rf=function(){var a=new Gb,b=[];this.$get=["$$AnimateRunner","$rootScope",function(d,c){function e(a,b,c){var d=!1;b&&(b=F(b)?b.split(" "):H(b)?b:[],q(b,function(b){b&&(d=!0,a[b]=c)}));return d}function f(){q(b,function(b){var c=a.get(b);if(c){var d=og(b.attr("class")),e="",f="";q(c,function(a,b){a!==!!d[b]&&(a?e+=(e.length?" ":"")+b:f+=(f.length?" ":"")+b)});q(b,function(a){e&&Cb(a,e);f&&Bb(a,f)});a.delete(b)}});b.length=0}return{enabled:z, -on:z,off:z,pin:z,push:function(g,h,k,l){l&&l();k=k||{};k.from&&g.css(k.from);k.to&&g.css(k.to);if(k.addClass||k.removeClass)if(h=k.addClass,l=k.removeClass,k=a.get(g)||{},h=e(k,h,!0),l=e(k,l,!1),h||l)a.set(g,k),b.push(g),1===b.length&&c.$$postDigest(f);g=new d;g.complete();return g}}}]},of=["$provide",function(a){var b=this,d=null;this.$$registeredAnimations=Object.create(null);this.register=function(c,d){if(c&&"."!==c.charAt(0))throw fe("notcsel",c);var f=c+"-animation";b.$$registeredAnimations[c.substr(1)]= -f;a.factory(f,d)};this.classNameFilter=function(a){if(1===arguments.length&&(d=a instanceof RegExp?a:null)&&/[(\s|\/)]ng-animate[(\s|\/)]/.test(d.toString()))throw d=null,fe("nongcls","ng-animate");return d};this.$get=["$$animateQueue",function(a){function b(a,c,d){if(d){var e;a:{for(e=0;e <= >= && || ! = |".split(" "),function(a){Qb[a]=!0});var $g={n:"\n",f:"\f",r:"\r",t:"\t",v:"\v","'":"'",'"':'"'},wc=function(a){this.options=a};wc.prototype={constructor:wc,lex:function(a){this.text=a;this.index=0;for(this.tokens=[];this.index=a&&"string"===typeof a},isWhitespace:function(a){return" "===a||"\r"===a||"\t"===a||"\n"===a||"\v"===a||"\u00a0"===a},isIdentifierStart:function(a){return this.options.isIdentifierStart?this.options.isIdentifierStart(a,this.codePointAt(a)):this.isValidIdentifierStart(a)},isValidIdentifierStart:function(a){return"a"<=a&&"z">=a||"A"<=a&&"Z">=a||"_"===a||"$"===a},isIdentifierContinue:function(a){return this.options.isIdentifierContinue? -this.options.isIdentifierContinue(a,this.codePointAt(a)):this.isValidIdentifierContinue(a)},isValidIdentifierContinue:function(a,b){return this.isValidIdentifierStart(a,b)||this.isNumber(a)},codePointAt:function(a){return 1===a.length?a.charCodeAt(0):(a.charCodeAt(0)<<10)+a.charCodeAt(1)-56613888},peekMultichar:function(){var a=this.text.charAt(this.index),b=this.peek();if(!b)return a;var d=a.charCodeAt(0),c=b.charCodeAt(0);return 55296<=d&&56319>=d&&56320<=c&&57343>=c?a+b:a},isExpOperator:function(a){return"-"=== -a||"+"===a||this.isNumber(a)},throwError:function(a,b,d){d=d||this.index;b=u(b)?"s "+b+"-"+this.index+" ["+this.text.substring(b,d)+"]":" "+d;throw Ua("lexerr",a,b,this.text);},readNumber:function(){for(var a="",b=this.index;this.index","<=",">=");)a={type:s.BinaryExpression,operator:b.text,left:a,right:this.additive()};return a},additive:function(){for(var a=this.multiplicative(),b;b=this.expect("+","-");)a={type:s.BinaryExpression,operator:b.text,left:a,right:this.multiplicative()};return a},multiplicative:function(){for(var a=this.unary(),b;b=this.expect("*","/","%");)a={type:s.BinaryExpression,operator:b.text,left:a,right:this.unary()};return a}, -unary:function(){var a;return(a=this.expect("+","-","!"))?{type:s.UnaryExpression,operator:a.text,prefix:!0,argument:this.unary()}:this.primary()},primary:function(){var a;this.expect("(")?(a=this.filterChain(),this.consume(")")):this.expect("[")?a=this.arrayDeclaration():this.expect("{")?a=this.object():this.selfReferential.hasOwnProperty(this.peek().text)?a=ra(this.selfReferential[this.consume().text]):this.options.literals.hasOwnProperty(this.peek().text)?a={type:s.Literal,value:this.options.literals[this.consume().text]}: -this.peek().identifier?a=this.identifier():this.peek().constant?a=this.constant():this.throwError("not a primary expression",this.peek());for(var b;b=this.expect("(","[",".");)"("===b.text?(a={type:s.CallExpression,callee:a,arguments:this.parseArguments()},this.consume(")")):"["===b.text?(a={type:s.MemberExpression,object:a,property:this.expression(),computed:!0},this.consume("]")):"."===b.text?a={type:s.MemberExpression,object:a,property:this.identifier(),computed:!1}:this.throwError("IMPOSSIBLE"); -return a},filter:function(a){a=[a];for(var b={type:s.CallExpression,callee:this.identifier(),arguments:a,filter:!0};this.expect(":");)a.push(this.expression());return b},parseArguments:function(){var a=[];if(")"!==this.peekToken().text){do a.push(this.filterChain());while(this.expect(","))}return a},identifier:function(){var a=this.consume();a.identifier||this.throwError("is not a valid identifier",a);return{type:s.Identifier,name:a.text}},constant:function(){return{type:s.Literal,value:this.consume().value}}, -arrayDeclaration:function(){var a=[];if("]"!==this.peekToken().text){do{if(this.peek("]"))break;a.push(this.expression())}while(this.expect(","))}this.consume("]");return{type:s.ArrayExpression,elements:a}},object:function(){var a=[],b;if("}"!==this.peekToken().text){do{if(this.peek("}"))break;b={type:s.Property,kind:"init"};this.peek().constant?(b.key=this.constant(),b.computed=!1,this.consume(":"),b.value=this.expression()):this.peek().identifier?(b.key=this.identifier(),b.computed=!1,this.peek(":")? -(this.consume(":"),b.value=this.expression()):b.value=b.key):this.peek("[")?(this.consume("["),b.key=this.expression(),this.consume("]"),b.computed=!0,this.consume(":"),b.value=this.expression()):this.throwError("invalid key",this.peek());a.push(b)}while(this.expect(","))}this.consume("}");return{type:s.ObjectExpression,properties:a}},throwError:function(a,b){throw Ua("syntax",b.text,a,b.index+1,this.text,this.text.substring(b.index));},consume:function(a){if(0===this.tokens.length)throw Ua("ueoe", -this.text);var b=this.expect(a);b||this.throwError("is unexpected, expecting ["+a+"]",this.peek());return b},peekToken:function(){if(0===this.tokens.length)throw Ua("ueoe",this.text);return this.tokens[0]},peek:function(a,b,d,c){return this.peekAhead(0,a,b,d,c)},peekAhead:function(a,b,d,c,e){if(this.tokens.length>a){a=this.tokens[a];var f=a.text;if(f===b||f===d||f===c||f===e||!(b||d||c||e))return a}return!1},expect:function(a,b,d,c){return(a=this.peek(a,b,d,c))?(this.tokens.shift(),a):!1},selfReferential:{"this":{type:s.ThisExpression}, -$locals:{type:s.LocalsExpression}}};Hd.prototype={compile:function(a){var b=this;this.state={nextId:0,filters:{},fn:{vars:[],body:[],own:{}},assign:{vars:[],body:[],own:{}},inputs:[]};U(a,b.$filter);var d="",c;this.stage="assign";if(c=Gd(a))this.state.computing="assign",d=this.nextId(),this.recurse(c,d),this.return_(d),d="fn.assign="+this.generateFunction("assign","s,v,l");c=Ed(a.body);b.stage="inputs";q(c,function(a,c){var d="fn"+c;b.state[d]={vars:[],body:[],own:{}};b.state.computing=d;var h=b.nextId(); -b.recurse(a,h);b.return_(h);b.state.inputs.push(d);a.watchId=c});this.state.computing="fn";this.stage="main";this.recurse(a);a='"'+this.USE+" "+this.STRICT+'";\n'+this.filterPrefix()+"var fn="+this.generateFunction("fn","s,l,a,i")+d+this.watchFns()+"return fn;";a=(new Function("$filter","getStringValue","ifDefined","plus",a))(this.$filter,zg,Ag,Dd);this.state=this.stage=void 0;return a},USE:"use",STRICT:"strict",watchFns:function(){var a=[],b=this.state.inputs,d=this;q(b,function(b){a.push("var "+ -b+"="+d.generateFunction(b,"s"))});b.length&&a.push("fn.inputs=["+b.join(",")+"];");return a.join("")},generateFunction:function(a,b){return"function("+b+"){"+this.varsPrefix(a)+this.body(a)+"};"},filterPrefix:function(){var a=[],b=this;q(this.state.filters,function(d,c){a.push(d+"=$filter("+b.escape(c)+")")});return a.length?"var "+a.join(",")+";":""},varsPrefix:function(a){return this.state[a].vars.length?"var "+this.state[a].vars.join(",")+";":""},body:function(a){return this.state[a].body.join("")}, -recurse:function(a,b,d,c,e,f){var g,h,k=this,l,m,n;c=c||z;if(!f&&u(a.watchId))b=b||this.nextId(),this.if_("i",this.lazyAssign(b,this.computedMember("i",a.watchId)),this.lazyRecurse(a,b,d,c,e,!0));else switch(a.type){case s.Program:q(a.body,function(b,c){k.recurse(b.expression,void 0,void 0,function(a){h=a});c!==a.body.length-1?k.current().body.push(h,";"):k.return_(h)});break;case s.Literal:m=this.escape(a.value);this.assign(b,m);c(b||m);break;case s.UnaryExpression:this.recurse(a.argument,void 0, -void 0,function(a){h=a});m=a.operator+"("+this.ifDefined(h,0)+")";this.assign(b,m);c(m);break;case s.BinaryExpression:this.recurse(a.left,void 0,void 0,function(a){g=a});this.recurse(a.right,void 0,void 0,function(a){h=a});m="+"===a.operator?this.plus(g,h):"-"===a.operator?this.ifDefined(g,0)+a.operator+this.ifDefined(h,0):"("+g+")"+a.operator+"("+h+")";this.assign(b,m);c(m);break;case s.LogicalExpression:b=b||this.nextId();k.recurse(a.left,b);k.if_("&&"===a.operator?b:k.not(b),k.lazyRecurse(a.right, -b));c(b);break;case s.ConditionalExpression:b=b||this.nextId();k.recurse(a.test,b);k.if_(b,k.lazyRecurse(a.alternate,b),k.lazyRecurse(a.consequent,b));c(b);break;case s.Identifier:b=b||this.nextId();d&&(d.context="inputs"===k.stage?"s":this.assign(this.nextId(),this.getHasOwnProperty("l",a.name)+"?l:s"),d.computed=!1,d.name=a.name);k.if_("inputs"===k.stage||k.not(k.getHasOwnProperty("l",a.name)),function(){k.if_("inputs"===k.stage||"s",function(){e&&1!==e&&k.if_(k.isNull(k.nonComputedMember("s",a.name)), -k.lazyAssign(k.nonComputedMember("s",a.name),"{}"));k.assign(b,k.nonComputedMember("s",a.name))})},b&&k.lazyAssign(b,k.nonComputedMember("l",a.name)));c(b);break;case s.MemberExpression:g=d&&(d.context=this.nextId())||this.nextId();b=b||this.nextId();k.recurse(a.object,g,void 0,function(){k.if_(k.notNull(g),function(){a.computed?(h=k.nextId(),k.recurse(a.property,h),k.getStringValue(h),e&&1!==e&&k.if_(k.not(k.computedMember(g,h)),k.lazyAssign(k.computedMember(g,h),"{}")),m=k.computedMember(g,h),k.assign(b, -m),d&&(d.computed=!0,d.name=h)):(e&&1!==e&&k.if_(k.isNull(k.nonComputedMember(g,a.property.name)),k.lazyAssign(k.nonComputedMember(g,a.property.name),"{}")),m=k.nonComputedMember(g,a.property.name),k.assign(b,m),d&&(d.computed=!1,d.name=a.property.name))},function(){k.assign(b,"undefined")});c(b)},!!e);break;case s.CallExpression:b=b||this.nextId();a.filter?(h=k.filter(a.callee.name),l=[],q(a.arguments,function(a){var b=k.nextId();k.recurse(a,b);l.push(b)}),m=h+"("+l.join(",")+")",k.assign(b,m),c(b)): -(h=k.nextId(),g={},l=[],k.recurse(a.callee,h,g,function(){k.if_(k.notNull(h),function(){q(a.arguments,function(b){k.recurse(b,a.constant?void 0:k.nextId(),void 0,function(a){l.push(a)})});m=g.name?k.member(g.context,g.name,g.computed)+"("+l.join(",")+")":h+"("+l.join(",")+")";k.assign(b,m)},function(){k.assign(b,"undefined")});c(b)}));break;case s.AssignmentExpression:h=this.nextId();g={};this.recurse(a.left,void 0,g,function(){k.if_(k.notNull(g.context),function(){k.recurse(a.right,h);m=k.member(g.context, -g.name,g.computed)+a.operator+h;k.assign(b,m);c(b||m)})},1);break;case s.ArrayExpression:l=[];q(a.elements,function(b){k.recurse(b,a.constant?void 0:k.nextId(),void 0,function(a){l.push(a)})});m="["+l.join(",")+"]";this.assign(b,m);c(b||m);break;case s.ObjectExpression:l=[];n=!1;q(a.properties,function(a){a.computed&&(n=!0)});n?(b=b||this.nextId(),this.assign(b,"{}"),q(a.properties,function(a){a.computed?(g=k.nextId(),k.recurse(a.key,g)):g=a.key.type===s.Identifier?a.key.name:""+a.key.value;h=k.nextId(); -k.recurse(a.value,h);k.assign(k.member(b,g,a.computed),h)})):(q(a.properties,function(b){k.recurse(b.value,a.constant?void 0:k.nextId(),void 0,function(a){l.push(k.escape(b.key.type===s.Identifier?b.key.name:""+b.key.value)+":"+a)})}),m="{"+l.join(",")+"}",this.assign(b,m));c(b||m);break;case s.ThisExpression:this.assign(b,"s");c(b||"s");break;case s.LocalsExpression:this.assign(b,"l");c(b||"l");break;case s.NGValueParameter:this.assign(b,"v"),c(b||"v")}},getHasOwnProperty:function(a,b){var d=a+"."+ -b,c=this.current().own;c.hasOwnProperty(d)||(c[d]=this.nextId(!1,a+"&&("+this.escape(b)+" in "+a+")"));return c[d]},assign:function(a,b){if(a)return this.current().body.push(a,"=",b,";"),a},filter:function(a){this.state.filters.hasOwnProperty(a)||(this.state.filters[a]=this.nextId(!0));return this.state.filters[a]},ifDefined:function(a,b){return"ifDefined("+a+","+this.escape(b)+")"},plus:function(a,b){return"plus("+a+","+b+")"},return_:function(a){this.current().body.push("return ",a,";")},if_:function(a, -b,d){if(!0===a)b();else{var c=this.current().body;c.push("if(",a,"){");b();c.push("}");d&&(c.push("else{"),d(),c.push("}"))}},not:function(a){return"!("+a+")"},isNull:function(a){return a+"==null"},notNull:function(a){return a+"!=null"},nonComputedMember:function(a,b){var d=/[^$_a-zA-Z0-9]/g;return/^[$_a-zA-Z][$_a-zA-Z0-9]*$/.test(b)?a+"."+b:a+'["'+b.replace(d,this.stringEscapeFn)+'"]'},computedMember:function(a,b){return a+"["+b+"]"},member:function(a,b,d){return d?this.computedMember(a,b):this.nonComputedMember(a, -b)},getStringValue:function(a){this.assign(a,"getStringValue("+a+")")},lazyRecurse:function(a,b,d,c,e,f){var g=this;return function(){g.recurse(a,b,d,c,e,f)}},lazyAssign:function(a,b){var d=this;return function(){d.assign(a,b)}},stringEscapeRegex:/[^ a-zA-Z0-9]/g,stringEscapeFn:function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)},escape:function(a){if(F(a))return"'"+a.replace(this.stringEscapeRegex,this.stringEscapeFn)+"'";if(ba(a))return a.toString();if(!0===a)return"true";if(!1=== -a)return"false";if(null===a)return"null";if("undefined"===typeof a)return"undefined";throw Ua("esc");},nextId:function(a,b){var d="v"+this.state.nextId++;a||this.current().vars.push(d+(b?"="+b:""));return d},current:function(){return this.state[this.state.computing]}};Id.prototype={compile:function(a){var b=this;U(a,b.$filter);var d,c;if(d=Gd(a))c=this.recurse(d);d=Ed(a.body);var e;d&&(e=[],q(d,function(a,c){var d=b.recurse(a);a.input=d;e.push(d);a.watchId=c}));var f=[];q(a.body,function(a){f.push(b.recurse(a.expression))}); -a=0===a.body.length?z:1===a.body.length?f[0]:function(a,b){var c;q(f,function(d){c=d(a,b)});return c};c&&(a.assign=function(a,b,d){return c(a,d,b)});e&&(a.inputs=e);return a},recurse:function(a,b,d){var c,e,f=this,g;if(a.input)return this.inputs(a.input,a.watchId);switch(a.type){case s.Literal:return this.value(a.value,b);case s.UnaryExpression:return e=this.recurse(a.argument),this["unary"+a.operator](e,b);case s.BinaryExpression:return c=this.recurse(a.left),e=this.recurse(a.right),this["binary"+ -a.operator](c,e,b);case s.LogicalExpression:return c=this.recurse(a.left),e=this.recurse(a.right),this["binary"+a.operator](c,e,b);case s.ConditionalExpression:return this["ternary?:"](this.recurse(a.test),this.recurse(a.alternate),this.recurse(a.consequent),b);case s.Identifier:return f.identifier(a.name,b,d);case s.MemberExpression:return c=this.recurse(a.object,!1,!!d),a.computed||(e=a.property.name),a.computed&&(e=this.recurse(a.property)),a.computed?this.computedMember(c,e,b,d):this.nonComputedMember(c, -e,b,d);case s.CallExpression:return g=[],q(a.arguments,function(a){g.push(f.recurse(a))}),a.filter&&(e=this.$filter(a.callee.name)),a.filter||(e=this.recurse(a.callee,!0)),a.filter?function(a,c,d,f){for(var n=[],p=0;p":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)>b(c,e,f,g);return d?{value:c}:c}},"binary<=":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)<=b(c,e,f,g);return d?{value:c}:c}},"binary>=":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)>=b(c,e,f,g);return d?{value:c}: -c}},"binary&&":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)&&b(c,e,f,g);return d?{value:c}:c}},"binary||":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)||b(c,e,f,g);return d?{value:c}:c}},"ternary?:":function(a,b,d,c){return function(e,f,g,h){e=a(e,f,g,h)?b(e,f,g,h):d(e,f,g,h);return c?{value:e}:e}},value:function(a,b){return function(){return b?{context:void 0,name:void 0,value:a}:a}},identifier:function(a,b,d){return function(c,e,f,g){c=e&&a in e?e:c;d&&1!==d&&c&&null==c[a]&&(c[a]= -{});e=c?c[a]:void 0;return b?{context:c,name:a,value:e}:e}},computedMember:function(a,b,d,c){return function(e,f,g,h){var k=a(e,f,g,h),l,m;null!=k&&(l=b(e,f,g,h),l+="",c&&1!==c&&k&&!k[l]&&(k[l]={}),m=k[l]);return d?{context:k,name:l,value:m}:m}},nonComputedMember:function(a,b,d,c){return function(e,f,g,h){e=a(e,f,g,h);c&&1!==c&&e&&null==e[b]&&(e[b]={});f=null!=e?e[b]:void 0;return d?{context:e,name:b,value:f}:f}},inputs:function(a,b){return function(d,c,e,f){return f?f[b]:a(d,c,e)}}};uc.prototype= -{constructor:uc,parse:function(a){a=this.ast.ast(a);var b=this.astCompiler.compile(a);b.literal=0===a.body.length||1===a.body.length&&(a.body[0].expression.type===s.Literal||a.body[0].expression.type===s.ArrayExpression||a.body[0].expression.type===s.ObjectExpression);b.constant=a.constant;return b}};var ta=L("$sce"),oa={HTML:"html",CSS:"css",URL:"url",RESOURCE_URL:"resourceUrl",JS:"js"},xc=/_([a-z])/g,Dg=L("$compile"),aa=x.document.createElement("a"),Md=Ca(x.location.href);Nd.$inject=["$document"]; -cd.$inject=["$provide"];var Ud=22,Td=".",zc="0";Od.$inject=["$locale"];Qd.$inject=["$locale"];var Og={yyyy:Y("FullYear",4,0,!1,!0),yy:Y("FullYear",2,0,!0,!0),y:Y("FullYear",1,0,!1,!0),MMMM:mb("Month"),MMM:mb("Month",!0),MM:Y("Month",2,1),M:Y("Month",1,1),LLLL:mb("Month",!1,!0),dd:Y("Date",2),d:Y("Date",1),HH:Y("Hours",2),H:Y("Hours",1),hh:Y("Hours",2,-12),h:Y("Hours",1,-12),mm:Y("Minutes",2),m:Y("Minutes",1),ss:Y("Seconds",2),s:Y("Seconds",1),sss:Y("Milliseconds",3),EEEE:mb("Day"),EEE:mb("Day",!0), -a:function(a,b){return 12>a.getHours()?b.AMPMS[0]:b.AMPMS[1]},Z:function(a,b,d){a=-1*d;return a=(0<=a?"+":"")+(Kb(Math[0=a.getFullYear()?b.ERANAMES[0]:b.ERANAMES[1]}},Ng=/((?:[^yMLdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|L+|d+|H+|h+|m+|s+|a|Z|G+|w+))([\s\S]*)/,Mg=/^-?\d+$/;Pd.$inject=["$locale"];var Hg=la(Q),Ig=la(ub);Rd.$inject=["$parse"];var Fe=la({restrict:"E",compile:function(a, -b){if(!b.href&&!b.xlinkHref)return function(a,b){if("a"===b[0].nodeName.toLowerCase()){var e="[object SVGAnimatedString]"===ma.call(b.prop("href"))?"xlink:href":"href";b.on("click",function(a){b.attr(e)||a.preventDefault()})}}}}),vb={};q(Fb,function(a,b){function d(a,d,e){a.$watch(e[c],function(a){e.$set(b,!!a)})}if("multiple"!==a){var c=Ba("ng-"+b),e=d;"checked"===a&&(e=function(a,b,e){e.ngModel!==e[c]&&d(a,b,e)});vb[c]=function(){return{restrict:"A",priority:100,link:e}}}});q(rd,function(a,b){vb[b]= -function(){return{priority:100,link:function(a,c,e){if("ngPattern"===b&&"/"===e.ngPattern.charAt(0)&&(c=e.ngPattern.match(Sg))){e.$set("ngPattern",new RegExp(c[1],c[2]));return}a.$watch(e[b],function(a){e.$set(b,a)})}}}});q(["src","srcset","href"],function(a){var b=Ba("ng-"+a);vb[b]=function(){return{priority:99,link:function(d,c,e){var f=a,g=a;"href"===a&&"[object SVGAnimatedString]"===ma.call(c.prop("href"))&&(g="xlinkHref",e.$attr[g]="xlink:href",f=null);e.$observe(b,function(b){b?(e.$set(g,b), -za&&f&&c.prop(f,e[g])):"href"===a&&e.$set(g,null)})}}}});var Mb={$addControl:z,$$renameControl:function(a,b){a.$name=b},$removeControl:z,$setValidity:z,$setDirty:z,$setPristine:z,$setSubmitted:z};Lb.$inject=["$element","$attrs","$scope","$animate","$interpolate"];Lb.prototype={$rollbackViewValue:function(){q(this.$$controls,function(a){a.$rollbackViewValue()})},$commitViewValue:function(){q(this.$$controls,function(a){a.$commitViewValue()})},$addControl:function(a){Ka(a.$name,"input");this.$$controls.push(a); -a.$name&&(this[a.$name]=a);a.$$parentForm=this},$$renameControl:function(a,b){var d=a.$name;this[d]===a&&delete this[d];this[b]=a;a.$name=b},$removeControl:function(a){a.$name&&this[a.$name]===a&&delete this[a.$name];q(this.$pending,function(b,d){this.$setValidity(d,null,a)},this);q(this.$error,function(b,d){this.$setValidity(d,null,a)},this);q(this.$$success,function(b,d){this.$setValidity(d,null,a)},this);$a(this.$$controls,a);a.$$parentForm=Mb},$setDirty:function(){this.$$animate.removeClass(this.$$element, -Va);this.$$animate.addClass(this.$$element,Rb);this.$dirty=!0;this.$pristine=!1;this.$$parentForm.$setDirty()},$setPristine:function(){this.$$animate.setClass(this.$$element,Va,Rb+" ng-submitted");this.$dirty=!1;this.$pristine=!0;this.$submitted=!1;q(this.$$controls,function(a){a.$setPristine()})},$setUntouched:function(){q(this.$$controls,function(a){a.$setUntouched()})},$setSubmitted:function(){this.$$animate.addClass(this.$$element,"ng-submitted");this.$submitted=!0;this.$$parentForm.$setSubmitted()}}; -Zd({clazz:Lb,set:function(a,b,d){var c=a[b];c?-1===c.indexOf(d)&&c.push(d):a[b]=[d]},unset:function(a,b,d){var c=a[b];c&&($a(c,d),0===c.length&&delete a[b])}});var ge=function(a){return["$timeout","$parse",function(b,d){function c(a){return""===a?d('this[""]').assign:d(a).assign||z}return{name:"form",restrict:a?"EAC":"E",require:["form","^^?form"],controller:Lb,compile:function(d,f){d.addClass(Va).addClass(nb);var g=f.name?"name":a&&f.ngForm?"ngForm":!1;return{pre:function(a,d,e,f){var n=f[0];if(!("action"in -e)){var p=function(b){a.$apply(function(){n.$commitViewValue();n.$setSubmitted()});b.preventDefault()};d[0].addEventListener("submit",p);d.on("$destroy",function(){b(function(){d[0].removeEventListener("submit",p)},0,!1)})}(f[1]||n.$$parentForm).$addControl(n);var r=g?c(n.$name):z;g&&(r(a,n),e.$observe(g,function(b){n.$name!==b&&(r(a,void 0),n.$$parentForm.$$renameControl(n,b),r=c(n.$name),r(a,n))}));d.on("$destroy",function(){n.$$parentForm.$removeControl(n);r(a,void 0);S(n,Mb)})}}}}}]},Ge=ge(), -Se=ge(!0),Pg=/^\d{4,}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+(?:[+-][0-2]\d:[0-5]\d|Z)$/,ah=/^[a-z][a-z\d.+-]*:\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\s:/?#]+|\[[a-f\d:]+])(?::\d+)?(?:\/[^?#]*)?(?:\?[^#]*)?(?:#.*)?$/i,bh=/^(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+(\.[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/,Qg=/^\s*(-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/,he=/^(\d{4,})-(\d{2})-(\d{2})$/,ie=/^(\d{4,})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/, -Hc=/^(\d{4,})-W(\d\d)$/,je=/^(\d{4,})-(\d\d)$/,ke=/^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,ae=V();q(["date","datetime-local","month","time","week"],function(a){ae[a]=!0});var le={text:function(a,b,d,c,e,f){Ra(a,b,d,c,e,f);Cc(c)},date:ob("date",he,Nb(he,["yyyy","MM","dd"]),"yyyy-MM-dd"),"datetime-local":ob("datetimelocal",ie,Nb(ie,"yyyy MM dd HH mm ss sss".split(" ")),"yyyy-MM-ddTHH:mm:ss.sss"),time:ob("time",ke,Nb(ke,["HH","mm","ss","sss"]),"HH:mm:ss.sss"),week:ob("week",Hc,function(a,b){if(ga(a))return a; -if(F(a)){Hc.lastIndex=0;var d=Hc.exec(a);if(d){var c=+d[1],e=+d[2],f=d=0,g=0,h=0,k=Vd(c),e=7*(e-1);b&&(d=b.getHours(),f=b.getMinutes(),g=b.getSeconds(),h=b.getMilliseconds());return new Date(c,0,k.getDate()+e,d,f,g,h)}}return NaN},"yyyy-Www"),month:ob("month",je,Nb(je,["yyyy","MM"]),"yyyy-MM"),number:function(a,b,d,c,e,f){Dc(a,b,d,c);be(c);Ra(a,b,d,c,e,f);var g,h;if(u(d.min)||d.ngMin)c.$validators.min=function(a){return c.$isEmpty(a)||w(g)||a>=g},d.$observe("min",function(a){g=Sa(a);c.$validate()}); -if(u(d.max)||d.ngMax)c.$validators.max=function(a){return c.$isEmpty(a)||w(h)||a<=h},d.$observe("max",function(a){h=Sa(a);c.$validate()});if(u(d.step)||d.ngStep){var k;c.$validators.step=function(a,b){return c.$isEmpty(b)||w(k)||ce(b,g||0,k)};d.$observe("step",function(a){k=Sa(a);c.$validate()})}},url:function(a,b,d,c,e,f){Ra(a,b,d,c,e,f);Cc(c);c.$$parserName="url";c.$validators.url=function(a,b){var d=a||b;return c.$isEmpty(d)||ah.test(d)}},email:function(a,b,d,c,e,f){Ra(a,b,d,c,e,f);Cc(c);c.$$parserName= -"email";c.$validators.email=function(a,b){var d=a||b;return c.$isEmpty(d)||bh.test(d)}},radio:function(a,b,d,c){var e=!d.ngTrim||"false"!==T(d.ngTrim);w(d.name)&&b.attr("name",++qb);b.on("click",function(a){var g;b[0].checked&&(g=d.value,e&&(g=T(g)),c.$setViewValue(g,a&&a.type))});c.$render=function(){var a=d.value;e&&(a=T(a));b[0].checked=a===c.$viewValue};d.$observe("value",c.$render)},range:function(a,b,d,c,e,f){function g(a,c){b.attr(a,d[a]);d.$observe(a,c)}function h(a){n=Sa(a);da(c.$modelValue)|| -(m?(a=b.val(),n>a&&(a=n,b.val(a)),c.$setViewValue(a)):c.$validate())}function k(a){p=Sa(a);da(c.$modelValue)||(m?(a=b.val(),p=n},g("min",h));e&&(c.$validators.max=m?function(){return!0}:function(a,b){return c.$isEmpty(b)||w(p)||b<=p},g("max",k));f&&(c.$validators.step=m?function(){return!q.stepMismatch}:function(a,b){return c.$isEmpty(b)||w(r)||ce(b,n||0,r)},g("step",l))},checkbox:function(a,b,d,c,e,f,g,h){var k=de(h,a,"ngTrueValue",d.ngTrueValue,!0),l=de(h,a,"ngFalseValue", -d.ngFalseValue,!1);b.on("click",function(a){c.$setViewValue(b[0].checked,a&&a.type)});c.$render=function(){b[0].checked=c.$viewValue};c.$isEmpty=function(a){return!1===a};c.$formatters.push(function(a){return sa(a,k)});c.$parsers.push(function(a){return a?k:l})},hidden:z,button:z,submit:z,reset:z,file:z},Xc=["$browser","$sniffer","$filter","$parse",function(a,b,d,c){return{restrict:"E",require:["?ngModel"],link:{pre:function(e,f,g,h){h[0]&&(le[Q(g.type)]||le.text)(e,f,g,h[0],b,a,d,c)}}}}],ch=/^(true|false|\d+)$/, -kf=function(){function a(a,d,c){var e=u(c)?c:9===za?"":null;a.prop("value",e);d.$set("value",c)}return{restrict:"A",priority:100,compile:function(b,d){return ch.test(d.ngValue)?function(b,d,f){b=b.$eval(f.ngValue);a(d,f,b)}:function(b,d,f){b.$watch(f.ngValue,function(b){a(d,f,b)})}}}},Ke=["$compile",function(a){return{restrict:"AC",compile:function(b){a.$$addBindingClass(b);return function(b,c,e){a.$$addBindingInfo(c,e.ngBind);c=c[0];b.$watch(e.ngBind,function(a){c.textContent=$b(a)})}}}}],Me=["$interpolate", -"$compile",function(a,b){return{compile:function(d){b.$$addBindingClass(d);return function(c,d,f){c=a(d.attr(f.$attr.ngBindTemplate));b.$$addBindingInfo(d,c.expressions);d=d[0];f.$observe("ngBindTemplate",function(a){d.textContent=w(a)?"":a})}}}}],Le=["$sce","$parse","$compile",function(a,b,d){return{restrict:"A",compile:function(c,e){var f=b(e.ngBindHtml),g=b(e.ngBindHtml,function(b){return a.valueOf(b)});d.$$addBindingClass(c);return function(b,c,e){d.$$addBindingInfo(c,e.ngBindHtml);b.$watch(g, -function(){var d=f(b);c.html(a.getTrustedHtml(d)||"")})}}}}],jf=la({restrict:"A",require:"ngModel",link:function(a,b,d,c){c.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}),Ne=Fc("",!0),Pe=Fc("Odd",0),Oe=Fc("Even",1),Qe=Qa({compile:function(a,b){b.$set("ngCloak",void 0);a.removeClass("ng-cloak")}}),Re=[function(){return{restrict:"A",scope:!0,controller:"@",priority:500}}],bd={},dh={blur:!0,focus:!0};q("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "), -function(a){var b=Ba("ng-"+a);bd[b]=["$parse","$rootScope",function(d,c){return{restrict:"A",compile:function(e,f){var g=d(f[b]);return function(b,d){d.on(a,function(d){var e=function(){g(b,{$event:d})};dh[a]&&c.$$phase?b.$evalAsync(e):b.$apply(e)})}}}}]});var Ue=["$animate","$compile",function(a,b){return{multiElement:!0,transclude:"element",priority:600,terminal:!0,restrict:"A",$$tlb:!0,link:function(d,c,e,f,g){var h,k,l;d.$watch(e.ngIf,function(d){d?k||g(function(d,f){k=f;d[d.length++]=b.$$createComment("end ngIf", -e.ngIf);h={clone:d};a.enter(d,c.parent(),c)}):(l&&(l.remove(),l=null),k&&(k.$destroy(),k=null),h&&(l=tb(h.clone),a.leave(l).done(function(a){!1!==a&&(l=null)}),h=null))})}}}],Ve=["$templateRequest","$anchorScroll","$animate",function(a,b,d){return{restrict:"ECA",priority:400,terminal:!0,transclude:"element",controller:ea.noop,compile:function(c,e){var f=e.ngInclude||e.src,g=e.onload||"",h=e.autoscroll;return function(c,e,m,n,p){var r=0,q,s,t,w=function(){s&&(s.remove(),s=null);q&&(q.$destroy(),q= -null);t&&(d.leave(t).done(function(a){!1!==a&&(s=null)}),s=t,t=null)};c.$watch(f,function(f){var m=function(a){!1===a||!u(h)||h&&!c.$eval(h)||b()},s=++r;f?(a(f,!0).then(function(a){if(!c.$$destroyed&&s===r){var b=c.$new();n.template=a;a=p(b,function(a){w();d.enter(a,null,e).done(m)});q=b;t=a;q.$emit("$includeContentLoaded",f);c.$eval(g)}},function(){c.$$destroyed||s!==r||(w(),c.$emit("$includeContentError",f))}),c.$emit("$includeContentRequested",f)):(w(),n.template=null)})}}}}],mf=["$compile",function(a){return{restrict:"ECA", -priority:-400,require:"ngInclude",link:function(b,d,c,e){ma.call(d[0]).match(/SVG/)?(d.empty(),a(dd(e.template,x.document).childNodes)(b,function(a){d.append(a)},{futureParentElement:d})):(d.html(e.template),a(d.contents())(b))}}}],We=Qa({priority:450,compile:function(){return{pre:function(a,b,d){a.$eval(d.ngInit)}}}}),hf=function(){return{restrict:"A",priority:100,require:"ngModel",link:function(a,b,d,c){var e=d.ngList||", ",f="false"!==d.ngTrim,g=f?T(e):e;c.$parsers.push(function(a){if(!w(a)){var b= -[];a&&q(a.split(g),function(a){a&&b.push(f?T(a):a)});return b}});c.$formatters.push(function(a){if(H(a))return a.join(e)});c.$isEmpty=function(a){return!a||!a.length}}}},nb="ng-valid",Yd="ng-invalid",Va="ng-pristine",Rb="ng-dirty",pb=L("ngModel");Ob.$inject="$scope $exceptionHandler $attrs $element $parse $animate $timeout $q $interpolate".split(" ");Ob.prototype={$$initGetterSetters:function(){if(this.$options.getOption("getterSetter")){var a=this.$$parse(this.$$attr.ngModel+"()"),b=this.$$parse(this.$$attr.ngModel+ -"($$$p)");this.$$ngModelGet=function(b){var c=this.$$parsedNgModel(b);D(c)&&(c=a(b));return c};this.$$ngModelSet=function(a,c){D(this.$$parsedNgModel(a))?b(a,{$$$p:c}):this.$$parsedNgModelAssign(a,c)}}else if(!this.$$parsedNgModel.assign)throw pb("nonassign",this.$$attr.ngModel,xa(this.$$element));},$render:z,$isEmpty:function(a){return w(a)||""===a||null===a||a!==a},$$updateEmptyClasses:function(a){this.$isEmpty(a)?(this.$$animate.removeClass(this.$$element,"ng-not-empty"),this.$$animate.addClass(this.$$element, -"ng-empty")):(this.$$animate.removeClass(this.$$element,"ng-empty"),this.$$animate.addClass(this.$$element,"ng-not-empty"))},$setPristine:function(){this.$dirty=!1;this.$pristine=!0;this.$$animate.removeClass(this.$$element,Rb);this.$$animate.addClass(this.$$element,Va)},$setDirty:function(){this.$dirty=!0;this.$pristine=!1;this.$$animate.removeClass(this.$$element,Va);this.$$animate.addClass(this.$$element,Rb);this.$$parentForm.$setDirty()},$setUntouched:function(){this.$touched=!1;this.$untouched= -!0;this.$$animate.setClass(this.$$element,"ng-untouched","ng-touched")},$setTouched:function(){this.$touched=!0;this.$untouched=!1;this.$$animate.setClass(this.$$element,"ng-touched","ng-untouched")},$rollbackViewValue:function(){this.$$timeout.cancel(this.$$pendingDebounce);this.$viewValue=this.$$lastCommittedViewValue;this.$render()},$validate:function(){if(!da(this.$modelValue)){var a=this.$$lastCommittedViewValue,b=this.$$rawModelValue,d=this.$valid,c=this.$modelValue,e=this.$options.getOption("allowInvalid"), -f=this;this.$$runValidators(b,a,function(a){e||d===a||(f.$modelValue=a?b:void 0,f.$modelValue!==c&&f.$$writeModelToScope())})}},$$runValidators:function(a,b,d){function c(){var c=!0;q(k.$validators,function(d,e){var g=Boolean(d(a,b));c=c&&g;f(e,g)});return c?!0:(q(k.$asyncValidators,function(a,b){f(b,null)}),!1)}function e(){var c=[],d=!0;q(k.$asyncValidators,function(e,g){var k=e(a,b);if(!k||!D(k.then))throw pb("nopromise",k);f(g,void 0);c.push(k.then(function(){f(g,!0)},function(){d=!1;f(g,!1)}))}); -c.length?k.$$q.all(c).then(function(){g(d)},z):g(!0)}function f(a,b){h===k.$$currentValidationRunId&&k.$setValidity(a,b)}function g(a){h===k.$$currentValidationRunId&&d(a)}this.$$currentValidationRunId++;var h=this.$$currentValidationRunId,k=this;(function(){var a=k.$$parserName||"parse";if(w(k.$$parserValid))f(a,null);else return k.$$parserValid||(q(k.$validators,function(a,b){f(b,null)}),q(k.$asyncValidators,function(a,b){f(b,null)})),f(a,k.$$parserValid),k.$$parserValid;return!0})()?c()?e():g(!1): -g(!1)},$commitViewValue:function(){var a=this.$viewValue;this.$$timeout.cancel(this.$$pendingDebounce);if(this.$$lastCommittedViewValue!==a||""===a&&this.$$hasNativeValidators)this.$$updateEmptyClasses(a),this.$$lastCommittedViewValue=a,this.$pristine&&this.$setDirty(),this.$$parseAndValidate()},$$parseAndValidate:function(){var a=this.$$lastCommittedViewValue,b=this;if(this.$$parserValid=w(a)?void 0:!0)for(var d=0;de||c.$isEmpty(b)|| -b.length<=e}}}}},$c=function(){return{restrict:"A",require:"?ngModel",link:function(a,b,d,c){if(c){var e=0;d.$observe("minlength",function(a){e=Z(a)||0;c.$validate()});c.$validators.minlength=function(a,b){return c.$isEmpty(b)||b.length>=e}}}}};x.angular.bootstrap?x.console&&console.log("WARNING: Tried to load angular more than once."):(ze(),Ce(ea),ea.module("ngLocale",[],["$provide",function(a){function b(a){a+="";var b=a.indexOf(".");return-1==b?0:a.length-b-1}a.value("$locale",{DATETIME_FORMATS:{AMPMS:["AM", -"PM"],DAY:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),ERANAMES:["Before Christ","Anno Domini"],ERAS:["BC","AD"],FIRSTDAYOFWEEK:6,MONTH:"January February March April May June July August September October November December".split(" "),SHORTDAY:"Sun Mon Tue Wed Thu Fri Sat".split(" "),SHORTMONTH:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),STANDALONEMONTH:"January February March April May June July August September October November December".split(" "),WEEKENDRANGE:[5, -6],fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",medium:"MMM d, y h:mm:ss a",mediumDate:"MMM d, y",mediumTime:"h:mm:ss a","short":"M/d/yy h:mm a",shortDate:"M/d/yy",shortTime:"h:mm a"},NUMBER_FORMATS:{CURRENCY_SYM:"$",DECIMAL_SEP:".",GROUP_SEP:",",PATTERNS:[{gSize:3,lgSize:3,maxFrac:3,minFrac:0,minInt:1,negPre:"-",negSuf:"",posPre:"",posSuf:""},{gSize:3,lgSize:3,maxFrac:2,minFrac:2,minInt:1,negPre:"-\u00a4",negSuf:"",posPre:"\u00a4",posSuf:""}]},id:"en-us",localeID:"en_US",pluralCat:function(a, -c){var e=a|0,f=c;void 0===f&&(f=Math.min(b(a),3));Math.pow(10,f);return 1==e&&0==f?"one":"other"}})}]),B(function(){ue(x.document,Sc)}))})(window);!window.angular.$$csp().noInlineStyle&&window.angular.element(document.head).prepend(''); -//# sourceMappingURL=angular.min.js.map diff --git a/hadoop-hdds/framework/src/main/resources/webapps/static/angular-nvd3-1.0.9.min.js b/hadoop-hdds/framework/src/main/resources/webapps/static/angular-nvd3-1.0.9.min.js deleted file mode 100644 index 4aced5761e8..00000000000 --- a/hadoop-hdds/framework/src/main/resources/webapps/static/angular-nvd3-1.0.9.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(window){"use strict";var nv=window.nv;"undefined"!=typeof exports&&(nv=require("nvd3")),angular.module("nvd3",[]).directive("nvd3",["nvd3Utils",function(nvd3Utils){return{restrict:"AE",scope:{data:"=",options:"=",api:"=?",events:"=?",config:"=?",onReady:"&?"},link:function(scope,element,attrs){function configure(chart,options,chartType){chart&&options&&angular.forEach(chart,function(value,key){"_"===key[0]||("dispatch"===key?(void 0!==options[key]&&null!==options[key]||scope._config.extended&&(options[key]={}),configureEvents(value,options[key])):"tooltip"===key?(void 0!==options[key]&&null!==options[key]||scope._config.extended&&(options[key]={}),configure(chart[key],options[key],chartType)):"contentGenerator"===key?options[key]&&chart[key](options[key]):-1===["axis","clearHighlights","defined","highlightPoint","nvPointerEventsClass","options","rangeBand","rangeBands","scatter","open","close","node"].indexOf(key)&&(void 0===options[key]||null===options[key]?scope._config.extended&&(options[key]=value()):chart[key](options[key])))})}function configureEvents(dispatch,options){dispatch&&options&&angular.forEach(dispatch,function(value,key){void 0===options[key]||null===options[key]?scope._config.extended&&(options[key]=value.on):dispatch.on(key+"._",options[key])})}function configureWrapper(name){var _=nvd3Utils.deepExtend(defaultWrapper(name),scope.options[name]||{});scope._config.extended&&(scope.options[name]=_);var wrapElement=angular.element("

").html(_.html||"").addClass(name).addClass(_.className).removeAttr("style").css(_.css);_.html||wrapElement.text(_.text),_.enable&&("title"===name?element.prepend(wrapElement):"subtitle"===name?angular.element(element[0].querySelector(".title")).after(wrapElement):"caption"===name&&element.append(wrapElement))}function configureStyles(){var _=nvd3Utils.deepExtend(defaultStyles(),scope.options.styles||{});scope._config.extended&&(scope.options.styles=_),angular.forEach(_.classes,function(value,key){value?element.addClass(key):element.removeClass(key)}),element.removeAttr("style").css(_.css)}function defaultWrapper(_){switch(_){case"title":return{enable:!1,text:"Write Your Title",className:"h4",css:{width:scope.options.chart.width+"px",textAlign:"center"}};case"subtitle":return{enable:!1,text:"Write Your Subtitle",css:{width:scope.options.chart.width+"px",textAlign:"center"}};case"caption":return{enable:!1,text:"Figure 1. Write Your Caption text.",css:{width:scope.options.chart.width+"px",textAlign:"center"}}}}function defaultStyles(){return{classes:{"with-3d-shadow":!0,"with-transitions":!0,gallery:!1},css:{}}}function dataWatchFn(newData,oldData){newData!==oldData&&(scope._config.disabled||(scope._config.refreshDataOnly?scope.api.update():scope.api.refresh()))}var defaultConfig={extended:!1,visible:!0,disabled:!1,refreshDataOnly:!0,deepWatchOptions:!0,deepWatchData:!0,deepWatchDataDepth:2,debounce:10,debounceImmediate:!0};scope.isReady=!1,scope._config=angular.extend(defaultConfig,scope.config),scope.api={refresh:function(){scope.api.updateWithOptions(),scope.isReady=!0},refreshWithTimeout:function(t){setTimeout(function(){scope.api.refresh()},t)},update:function(){scope.chart&&scope.svg?"sunburstChart"===scope.options.chart.type?scope.svg.datum(angular.copy(scope.data)).call(scope.chart):scope.svg.datum(scope.data).call(scope.chart):scope.api.refresh()},updateWithTimeout:function(t){setTimeout(function(){scope.api.update()},t)},updateWithOptions:function(options){if(arguments.length){if(scope.options=options,scope._config.deepWatchOptions&&!scope._config.disabled)return}else options=scope.options;scope.api.clearElement(),angular.isDefined(options)!==!1&&scope._config.visible&&(scope.chart=nv.models[options.chart.type](),scope.chart.id=Math.random().toString(36).substr(2,15),angular.forEach(scope.chart,function(value,key){"_"===key[0]||["clearHighlights","highlightPoint","id","options","resizeHandler","state","open","close","tooltipContent"].indexOf(key)>=0||("dispatch"===key?(void 0!==options.chart[key]&&null!==options.chart[key]||scope._config.extended&&(options.chart[key]={}),configureEvents(scope.chart[key],options.chart[key])):["bars","bars1","bars2","boxplot","bullet","controls","discretebar","distX","distY","focus","interactiveLayer","legend","lines","lines1","lines2","multibar","pie","scatter","scatters1","scatters2","sparkline","stack1","stack2","sunburst","tooltip","x2Axis","xAxis","y1Axis","y2Axis","y3Axis","y4Axis","yAxis","yAxis1","yAxis2"].indexOf(key)>=0||"stacked"===key&&"stackedAreaChart"===options.chart.type?(void 0!==options.chart[key]&&null!==options.chart[key]||scope._config.extended&&(options.chart[key]={}),configure(scope.chart[key],options.chart[key],options.chart.type)):"focusHeight"===key&&"lineChart"===options.chart.type||"focusHeight"===key&&"lineWithFocusChart"===options.chart.type||("xTickFormat"!==key&&"yTickFormat"!==key||"lineWithFocusChart"!==options.chart.type)&&("tooltips"===key&&"boxPlotChart"===options.chart.type||("tooltipXContent"!==key&&"tooltipYContent"!==key||"scatterChart"!==options.chart.type)&&("x"!==key&&"y"!==key||"forceDirectedGraph"!==options.chart.type)&&(void 0===options.chart[key]||null===options.chart[key]?scope._config.extended&&("barColor"===key?options.chart[key]=value()():options.chart[key]=value()):scope.chart[key](options.chart[key]))))}),scope.api.updateWithData(),(options.title||scope._config.extended)&&configureWrapper("title"),(options.subtitle||scope._config.extended)&&configureWrapper("subtitle"),(options.caption||scope._config.extended)&&configureWrapper("caption"),(options.styles||scope._config.extended)&&configureStyles(),nv.addGraph(function(){return scope.chart?(scope.chart.resizeHandler&&scope.chart.resizeHandler.clear(),scope.chart.resizeHandler=nv.utils.windowResize(function(){scope.chart&&scope.chart.update&&scope.chart.update()}),void 0!==options.chart.zoom&&["scatterChart","lineChart","candlestickBarChart","cumulativeLineChart","historicalBarChart","ohlcBarChart","stackedAreaChart"].indexOf(options.chart.type)>-1&&nvd3Utils.zoom(scope,options),scope.chart):void 0},options.chart.callback))},updateWithData:function(data){if(arguments.length){if(scope.data=data,scope._config.deepWatchData&&!scope._config.disabled)return}else data="sunburstChart"===scope.options.chart.type?angular.copy(scope.data):scope.data;if(data){d3.select(element[0]).select("svg").remove();var h,w;scope.svg=d3.select(element[0]).insert("svg",".caption"),(h=scope.options.chart.height)&&(isNaN(+h)||(h+="px"),scope.svg.attr("height",h).style({height:h})),(w=scope.options.chart.width)?(isNaN(+w)||(w+="px"),scope.svg.attr("width",w).style({width:w})):scope.svg.attr("width","100%").style({width:"100%"}),scope.svg.datum(data).call(scope.chart),scope.chart&&scope.chart.zoomRender&&scope.chart.zoomRender()}},clearElement:function(){if(element.find(".title").remove(),element.find(".subtitle").remove(),element.find(".caption").remove(),element.empty(),scope.chart&&scope.chart.tooltip&&scope.chart.tooltip.id&&d3.select("#"+scope.chart.tooltip.id()).remove(),nv.graphs&&scope.chart)for(var i=nv.graphs.length-1;i>=0;i--)nv.graphs[i]&&nv.graphs[i].id===scope.chart.id&&nv.graphs.splice(i,1);nv.tooltip&&nv.tooltip.cleanup&&nv.tooltip.cleanup(),scope.chart&&scope.chart.resizeHandler&&scope.chart.resizeHandler.clear(),scope.chart=null},getScope:function(){return scope},getElement:function(){return element}},scope._config.deepWatchOptions&&scope.$watch("options",nvd3Utils.debounce(function(newOptions){scope._config.disabled||scope.api.refresh()},scope._config.debounce,scope._config.debounceImmediate),!0),scope._config.deepWatchData&&(1===scope._config.deepWatchDataDepth?scope.$watchCollection("data",dataWatchFn):scope.$watch("data",dataWatchFn,2===scope._config.deepWatchDataDepth)),scope.$watch("config",function(newConfig,oldConfig){newConfig!==oldConfig&&(scope._config=angular.extend(defaultConfig,newConfig),scope.api.refresh())},!0),scope._config.deepWatchOptions||scope._config.deepWatchData||scope.api.refresh(),angular.forEach(scope.events,function(eventHandler,event){scope.$on(event,function(e,args){return eventHandler(e,scope,args)})}),element.on("$destroy",function(){scope.api.clearElement()}),scope.$watch("isReady",function(isReady){isReady&&scope.onReady&&"function"==typeof scope.onReady()&&scope.onReady()(scope,element)})}}}]).factory("nvd3Utils",function(){return{debounce:function(func,wait,immediate){var timeout;return function(){var context=this,args=arguments,later=function(){timeout=null,immediate||func.apply(context,args)},callNow=immediate&&!timeout;clearTimeout(timeout),timeout=setTimeout(later,wait),callNow&&func.apply(context,args)}},deepExtend:function(dst){var me=this;return angular.forEach(arguments,function(obj){obj!==dst&&angular.forEach(obj,function(value,key){dst[key]&&dst[key].constructor&&dst[key].constructor===Object?me.deepExtend(dst[key],value):dst[key]=value})}),dst},zoom:function(scope,options){var zoom=options.chart.zoom,enabled="undefined"==typeof zoom.enabled||null===zoom.enabled?!0:zoom.enabled;if(enabled){var fixDomain,d3zoom,zoomed,unzoomed,zoomend,xScale=scope.chart.xAxis.scale(),yScale=scope.chart.yAxis.scale(),xDomain=scope.chart.xDomain||xScale.domain,yDomain=scope.chart.yDomain||yScale.domain,x_boundary=xScale.domain().slice(),y_boundary=yScale.domain().slice(),scale=zoom.scale||1,translate=zoom.translate||[0,0],scaleExtent=zoom.scaleExtent||[1,10],useFixedDomain=zoom.useFixedDomain||!1,useNiceScale=zoom.useNiceScale||!1,horizontalOff=zoom.horizontalOff||!1,verticalOff=zoom.verticalOff||!1,unzoomEventType=zoom.unzoomEventType||"dblclick.zoom";useNiceScale&&(xScale.nice(),yScale.nice()),fixDomain=function(domain,boundary){return domain[0]=Math.min(Math.max(domain[0],boundary[0]),boundary[1]-boundary[1]/scaleExtent[1]),domain[1]=Math.max(boundary[0]+boundary[1]/scaleExtent[1],Math.min(domain[1],boundary[1])),domain},zoomed=function(){if(void 0!==zoom.zoomed){var domains=zoom.zoomed(xScale.domain(),yScale.domain());horizontalOff||xDomain([domains.x1,domains.x2]),verticalOff||yDomain([domains.y1,domains.y2])}else horizontalOff||xDomain(useFixedDomain?fixDomain(xScale.domain(),x_boundary):xScale.domain()),verticalOff||yDomain(useFixedDomain?fixDomain(yScale.domain(),y_boundary):yScale.domain());scope.chart&&scope.chart.update()},unzoomed=function(){if(void 0!==zoom.unzoomed){var domains=zoom.unzoomed(xScale.domain(),yScale.domain());horizontalOff||xDomain([domains.x1,domains.x2]),verticalOff||yDomain([domains.y1,domains.y2])}else horizontalOff||xDomain(x_boundary),verticalOff||yDomain(y_boundary);d3zoom.scale(scale).translate(translate),scope.chart&&scope.chart.update()},zoomend=function(){void 0!==zoom.zoomend&&zoom.zoomend()},d3zoom=d3.behavior.zoom().x(xScale).y(yScale).scaleExtent(scaleExtent).on("zoom",zoomed).on("zoomend",zoomend),scope.svg&&(scope.svg.call(d3zoom),d3zoom.scale(scale).translate(translate).event(scope.svg),"none"!==unzoomEventType&&scope.svg.on(unzoomEventType,unzoomed)),scope.chart&&(scope.chart.zoomRender=function(){d3zoom.scale(scale).translate(translate),xScale=scope.chart.xAxis.scale(),yScale=scope.chart.yAxis.scale(),xDomain=scope.chart.xDomain||xScale.domain,yDomain=scope.chart.yDomain||yScale.domain,x_boundary=xScale.domain().slice(),y_boundary=yScale.domain().slice(),d3zoom.x(xScale).y(yScale),scope.svg.call(d3zoom),"none"!==unzoomEventType&&scope.svg.on(unzoomEventType,unzoomed)})}}}})}(window); \ No newline at end of file diff --git a/hadoop-hdds/framework/src/main/resources/webapps/static/angular-route-1.6.4.min.js b/hadoop-hdds/framework/src/main/resources/webapps/static/angular-route-1.6.4.min.js deleted file mode 100644 index 3f985d1422b..00000000000 --- a/hadoop-hdds/framework/src/main/resources/webapps/static/angular-route-1.6.4.min.js +++ /dev/null @@ -1,17 +0,0 @@ -/* - AngularJS v1.6.4 - (c) 2010-2017 Google, Inc. http://angularjs.org - License: MIT -*/ -(function(J,d){'use strict';function A(d){k&&d.get("$route")}function B(t,u,g){return{restrict:"ECA",terminal:!0,priority:400,transclude:"element",link:function(a,f,b,c,m){function v(){l&&(g.cancel(l),l=null);n&&(n.$destroy(),n=null);p&&(l=g.leave(p),l.done(function(a){!1!==a&&(l=null)}),p=null)}function E(){var b=t.current&&t.current.locals;if(d.isDefined(b&&b.$template)){var b=a.$new(),c=t.current;p=m(b,function(b){g.enter(b,null,p||f).done(function(b){!1===b||!d.isDefined(w)||w&&!a.$eval(w)||u()}); -v()});n=c.scope=b;n.$emit("$viewContentLoaded");n.$eval(k)}else v()}var n,p,l,w=b.autoscroll,k=b.onload||"";a.$on("$routeChangeSuccess",E);E()}}}function C(d,k,g){return{restrict:"ECA",priority:-400,link:function(a,f){var b=g.current,c=b.locals;f.html(c.$template);var m=d(f.contents());if(b.controller){c.$scope=a;var v=k(b.controller,c);b.controllerAs&&(a[b.controllerAs]=v);f.data("$ngControllerController",v);f.children().data("$ngControllerController",v)}a[b.resolveAs||"$resolve"]=c;m(a)}}}var x, -y,F,G,z=d.module("ngRoute",[]).info({angularVersion:"1.6.4"}).provider("$route",function(){function t(a,f){return d.extend(Object.create(a),f)}function u(a,d){var b=d.caseInsensitiveMatch,c={originalPath:a,regexp:a},g=c.keys=[];a=a.replace(/([().])/g,"\\$1").replace(/(\/)?:(\w+)(\*\?|[?*])?/g,function(a,b,d,c){a="?"===c||"*?"===c?"?":null;c="*"===c||"*?"===c?"*":null;g.push({name:d,optional:!!a});b=b||"";return""+(a?"":b)+"(?:"+(a?b:"")+(c&&"(.+?)"||"([^/]+)")+(a||"")+")"+(a||"")}).replace(/([/$*])/g, -"\\$1");c.regexp=new RegExp("^"+a+"$",b?"i":"");return c}x=d.isArray;y=d.isObject;F=d.isDefined;G=d.noop;var g={};this.when=function(a,f){var b;b=void 0;if(x(f)){b=b||[];for(var c=0,m=f.length;cn?-1:n>t?1:n>=t?0:NaN}function r(n){return null===n?NaN:+n}function i(n){return!isNaN(n)}function u(n){return{left:function(t,e,r,i){for(arguments.length<3&&(r=0),arguments.length<4&&(i=t.length);i>r;){var u=r+i>>>1;n(t[u],e)<0?r=u+1:i=u}return r},right:function(t,e,r,i){for(arguments.length<3&&(r=0),arguments.length<4&&(i=t.length);i>r;){var u=r+i>>>1;n(t[u],e)>0?i=u:r=u+1}return r}}}function o(n){return n.length}function a(n){for(var t=1;n*t%1;)t*=10;return t}function l(n,t){for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}function c(){this._=Object.create(null)}function f(n){return(n+="")===bo||n[0]===_o?_o+n:n}function s(n){return(n+="")[0]===_o?n.slice(1):n}function h(n){return f(n)in this._}function p(n){return(n=f(n))in this._&&delete this._[n]}function g(){var n=[];for(var t in this._)n.push(s(t));return n}function v(){var n=0;for(var t in this._)++n;return n}function d(){for(var n in this._)return!1;return!0}function y(){this._=Object.create(null)}function m(n){return n}function M(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function x(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.slice(1);for(var e=0,r=wo.length;r>e;++e){var i=wo[e]+t;if(i in n)return i}}function b(){}function _(){}function w(n){function t(){for(var t,r=e,i=-1,u=r.length;++ie;e++)for(var i,u=n[e],o=0,a=u.length;a>o;o++)(i=u[o])&&t(i,o,e);return n}function Z(n){return ko(n,qo),n}function V(n){var t,e;return function(r,i,u){var o,a=n[u].update,l=a.length;for(u!=e&&(e=u,t=0),i>=t&&(t=i+1);!(o=a[t])&&++t0&&(n=n.slice(0,a));var c=To.get(n);return c&&(n=c,l=B),a?t?i:r:t?b:u}function $(n,t){return function(e){var r=ao.event;ao.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{ao.event=r}}}function B(n,t){var e=$(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function W(e){var r=".dragsuppress-"+ ++Do,i="click"+r,u=ao.select(t(e)).on("touchmove"+r,S).on("dragstart"+r,S).on("selectstart"+r,S);if(null==Ro&&(Ro="onselectstart"in e?!1:x(e.style,"userSelect")),Ro){var o=n(e).style,a=o[Ro];o[Ro]="none"}return function(n){if(u.on(r,null),Ro&&(o[Ro]=a),n){var t=function(){u.on(i,null)};u.on(i,function(){S(),t()},!0),setTimeout(t,0)}}}function J(n,e){e.changedTouches&&(e=e.changedTouches[0]);var r=n.ownerSVGElement||n;if(r.createSVGPoint){var i=r.createSVGPoint();if(0>Po){var u=t(n);if(u.scrollX||u.scrollY){r=ao.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var o=r[0][0].getScreenCTM();Po=!(o.f||o.e),r.remove()}}return Po?(i.x=e.pageX,i.y=e.pageY):(i.x=e.clientX,i.y=e.clientY),i=i.matrixTransform(n.getScreenCTM().inverse()),[i.x,i.y]}var a=n.getBoundingClientRect();return[e.clientX-a.left-n.clientLeft,e.clientY-a.top-n.clientTop]}function G(){return ao.event.changedTouches[0].identifier}function K(n){return n>0?1:0>n?-1:0}function Q(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(t[1]-n[1])*(e[0]-n[0])}function nn(n){return n>1?0:-1>n?Fo:Math.acos(n)}function tn(n){return n>1?Io:-1>n?-Io:Math.asin(n)}function en(n){return((n=Math.exp(n))-1/n)/2}function rn(n){return((n=Math.exp(n))+1/n)/2}function un(n){return((n=Math.exp(2*n))-1)/(n+1)}function on(n){return(n=Math.sin(n/2))*n}function an(){}function ln(n,t,e){return this instanceof ln?(this.h=+n,this.s=+t,void(this.l=+e)):arguments.length<2?n instanceof ln?new ln(n.h,n.s,n.l):_n(""+n,wn,ln):new ln(n,t,e)}function cn(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?u+(o-u)*n/60:180>n?o:240>n?u+(o-u)*(240-n)/60:u}function i(n){return Math.round(255*r(n))}var u,o;return n=isNaN(n)?0:(n%=360)<0?n+360:n,t=isNaN(t)?0:0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,o=.5>=e?e*(1+t):e+t-e*t,u=2*e-o,new mn(i(n+120),i(n),i(n-120))}function fn(n,t,e){return this instanceof fn?(this.h=+n,this.c=+t,void(this.l=+e)):arguments.length<2?n instanceof fn?new fn(n.h,n.c,n.l):n instanceof hn?gn(n.l,n.a,n.b):gn((n=Sn((n=ao.rgb(n)).r,n.g,n.b)).l,n.a,n.b):new fn(n,t,e)}function sn(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),new hn(e,Math.cos(n*=Yo)*t,Math.sin(n)*t)}function hn(n,t,e){return this instanceof hn?(this.l=+n,this.a=+t,void(this.b=+e)):arguments.length<2?n instanceof hn?new hn(n.l,n.a,n.b):n instanceof fn?sn(n.h,n.c,n.l):Sn((n=mn(n)).r,n.g,n.b):new hn(n,t,e)}function pn(n,t,e){var r=(n+16)/116,i=r+t/500,u=r-e/200;return i=vn(i)*na,r=vn(r)*ta,u=vn(u)*ea,new mn(yn(3.2404542*i-1.5371385*r-.4985314*u),yn(-.969266*i+1.8760108*r+.041556*u),yn(.0556434*i-.2040259*r+1.0572252*u))}function gn(n,t,e){return n>0?new fn(Math.atan2(e,t)*Zo,Math.sqrt(t*t+e*e),n):new fn(NaN,NaN,n)}function vn(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function dn(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function yn(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.pow(n,1/2.4)-.055))}function mn(n,t,e){return this instanceof mn?(this.r=~~n,this.g=~~t,void(this.b=~~e)):arguments.length<2?n instanceof mn?new mn(n.r,n.g,n.b):_n(""+n,mn,cn):new mn(n,t,e)}function Mn(n){return new mn(n>>16,n>>8&255,255&n)}function xn(n){return Mn(n)+""}function bn(n){return 16>n?"0"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function _n(n,t,e){var r,i,u,o=0,a=0,l=0;if(r=/([a-z]+)\((.*)\)/.exec(n=n.toLowerCase()))switch(i=r[2].split(","),r[1]){case"hsl":return e(parseFloat(i[0]),parseFloat(i[1])/100,parseFloat(i[2])/100);case"rgb":return t(Nn(i[0]),Nn(i[1]),Nn(i[2]))}return(u=ua.get(n))?t(u.r,u.g,u.b):(null==n||"#"!==n.charAt(0)||isNaN(u=parseInt(n.slice(1),16))||(4===n.length?(o=(3840&u)>>4,o=o>>4|o,a=240&u,a=a>>4|a,l=15&u,l=l<<4|l):7===n.length&&(o=(16711680&u)>>16,a=(65280&u)>>8,l=255&u)),t(o,a,l))}function wn(n,t,e){var r,i,u=Math.min(n/=255,t/=255,e/=255),o=Math.max(n,t,e),a=o-u,l=(o+u)/2;return a?(i=.5>l?a/(o+u):a/(2-o-u),r=n==o?(t-e)/a+(e>t?6:0):t==o?(e-n)/a+2:(n-t)/a+4,r*=60):(r=NaN,i=l>0&&1>l?0:r),new ln(r,i,l)}function Sn(n,t,e){n=kn(n),t=kn(t),e=kn(e);var r=dn((.4124564*n+.3575761*t+.1804375*e)/na),i=dn((.2126729*n+.7151522*t+.072175*e)/ta),u=dn((.0193339*n+.119192*t+.9503041*e)/ea);return hn(116*i-16,500*(r-i),200*(i-u))}function kn(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function Nn(n){var t=parseFloat(n);return"%"===n.charAt(n.length-1)?Math.round(2.55*t):t}function En(n){return"function"==typeof n?n:function(){return n}}function An(n){return function(t,e,r){return 2===arguments.length&&"function"==typeof e&&(r=e,e=null),Cn(t,e,n,r)}}function Cn(n,t,e,r){function i(){var n,t=l.status;if(!t&&Ln(l)||t>=200&&300>t||304===t){try{n=e.call(u,l)}catch(r){return void o.error.call(u,r)}o.load.call(u,n)}else o.error.call(u,l)}var u={},o=ao.dispatch("beforesend","progress","load","error"),a={},l=new XMLHttpRequest,c=null;return!this.XDomainRequest||"withCredentials"in l||!/^(http(s)?:)?\/\//.test(n)||(l=new XDomainRequest),"onload"in l?l.onload=l.onerror=i:l.onreadystatechange=function(){l.readyState>3&&i()},l.onprogress=function(n){var t=ao.event;ao.event=n;try{o.progress.call(u,l)}finally{ao.event=t}},u.header=function(n,t){return n=(n+"").toLowerCase(),arguments.length<2?a[n]:(null==t?delete a[n]:a[n]=t+"",u)},u.mimeType=function(n){return arguments.length?(t=null==n?null:n+"",u):t},u.responseType=function(n){return arguments.length?(c=n,u):c},u.response=function(n){return e=n,u},["get","post"].forEach(function(n){u[n]=function(){return u.send.apply(u,[n].concat(co(arguments)))}}),u.send=function(e,r,i){if(2===arguments.length&&"function"==typeof r&&(i=r,r=null),l.open(e,n,!0),null==t||"accept"in a||(a.accept=t+",*/*"),l.setRequestHeader)for(var f in a)l.setRequestHeader(f,a[f]);return null!=t&&l.overrideMimeType&&l.overrideMimeType(t),null!=c&&(l.responseType=c),null!=i&&u.on("error",i).on("load",function(n){i(null,n)}),o.beforesend.call(u,l),l.send(null==r?null:r),u},u.abort=function(){return l.abort(),u},ao.rebind(u,o,"on"),null==r?u:u.get(zn(r))}function zn(n){return 1===n.length?function(t,e){n(null==t?e:null)}:n}function Ln(n){var t=n.responseType;return t&&"text"!==t?n.response:n.responseText}function qn(n,t,e){var r=arguments.length;2>r&&(t=0),3>r&&(e=Date.now());var i=e+t,u={c:n,t:i,n:null};return aa?aa.n=u:oa=u,aa=u,la||(ca=clearTimeout(ca),la=1,fa(Tn)),u}function Tn(){var n=Rn(),t=Dn()-n;t>24?(isFinite(t)&&(clearTimeout(ca),ca=setTimeout(Tn,t)),la=0):(la=1,fa(Tn))}function Rn(){for(var n=Date.now(),t=oa;t;)n>=t.t&&t.c(n-t.t)&&(t.c=null),t=t.n;return n}function Dn(){for(var n,t=oa,e=1/0;t;)t.c?(t.t8?function(n){return n/e}:function(n){return n*e},symbol:n}}function jn(n){var t=n.decimal,e=n.thousands,r=n.grouping,i=n.currency,u=r&&e?function(n,t){for(var i=n.length,u=[],o=0,a=r[0],l=0;i>0&&a>0&&(l+a+1>t&&(a=Math.max(1,t-l)),u.push(n.substring(i-=a,i+a)),!((l+=a+1)>t));)a=r[o=(o+1)%r.length];return u.reverse().join(e)}:m;return function(n){var e=ha.exec(n),r=e[1]||" ",o=e[2]||">",a=e[3]||"-",l=e[4]||"",c=e[5],f=+e[6],s=e[7],h=e[8],p=e[9],g=1,v="",d="",y=!1,m=!0;switch(h&&(h=+h.substring(1)),(c||"0"===r&&"="===o)&&(c=r="0",o="="),p){case"n":s=!0,p="g";break;case"%":g=100,d="%",p="f";break;case"p":g=100,d="%",p="r";break;case"b":case"o":case"x":case"X":"#"===l&&(v="0"+p.toLowerCase());case"c":m=!1;case"d":y=!0,h=0;break;case"s":g=-1,p="r"}"$"===l&&(v=i[0],d=i[1]),"r"!=p||h||(p="g"),null!=h&&("g"==p?h=Math.max(1,Math.min(21,h)):"e"!=p&&"f"!=p||(h=Math.max(0,Math.min(20,h)))),p=pa.get(p)||Fn;var M=c&&s;return function(n){var e=d;if(y&&n%1)return"";var i=0>n||0===n&&0>1/n?(n=-n,"-"):"-"===a?"":a;if(0>g){var l=ao.formatPrefix(n,h);n=l.scale(n),e=l.symbol+d}else n*=g;n=p(n,h);var x,b,_=n.lastIndexOf(".");if(0>_){var w=m?n.lastIndexOf("e"):-1;0>w?(x=n,b=""):(x=n.substring(0,w),b=n.substring(w))}else x=n.substring(0,_),b=t+n.substring(_+1);!c&&s&&(x=u(x,1/0));var S=v.length+x.length+b.length+(M?0:i.length),k=f>S?new Array(S=f-S+1).join(r):"";return M&&(x=u(k+x,k.length?f-b.length:1/0)),i+=v,n=x+b,("<"===o?i+n+k:">"===o?k+i+n:"^"===o?k.substring(0,S>>=1)+i+n+k.substring(S):i+(M?n:k+n))+e}}}function Fn(n){return n+""}function Hn(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function On(n,t,e){function r(t){var e=n(t),r=u(e,1);return r-t>t-e?e:r}function i(e){return t(e=n(new va(e-1)),1),e}function u(n,e){return t(n=new va(+n),e),n}function o(n,r,u){var o=i(n),a=[];if(u>1)for(;r>o;)e(o)%u||a.push(new Date(+o)),t(o,1);else for(;r>o;)a.push(new Date(+o)),t(o,1);return a}function a(n,t,e){try{va=Hn;var r=new Hn;return r._=n,o(r,t,e)}finally{va=Date}}n.floor=n,n.round=r,n.ceil=i,n.offset=u,n.range=o;var l=n.utc=In(n);return l.floor=l,l.round=In(r),l.ceil=In(i),l.offset=In(u),l.range=a,n}function In(n){return function(t,e){try{va=Hn;var r=new Hn;return r._=t,n(r,e)._}finally{va=Date}}}function Yn(n){function t(n){function t(t){for(var e,i,u,o=[],a=-1,l=0;++aa;){if(r>=c)return-1;if(i=t.charCodeAt(a++),37===i){if(o=t.charAt(a++),u=C[o in ya?t.charAt(a++):o],!u||(r=u(n,e,r))<0)return-1}else if(i!=e.charCodeAt(r++))return-1}return r}function r(n,t,e){_.lastIndex=0;var r=_.exec(t.slice(e));return r?(n.w=w.get(r[0].toLowerCase()),e+r[0].length):-1}function i(n,t,e){x.lastIndex=0;var r=x.exec(t.slice(e));return r?(n.w=b.get(r[0].toLowerCase()),e+r[0].length):-1}function u(n,t,e){N.lastIndex=0;var r=N.exec(t.slice(e));return r?(n.m=E.get(r[0].toLowerCase()),e+r[0].length):-1}function o(n,t,e){S.lastIndex=0;var r=S.exec(t.slice(e));return r?(n.m=k.get(r[0].toLowerCase()),e+r[0].length):-1}function a(n,t,r){return e(n,A.c.toString(),t,r)}function l(n,t,r){return e(n,A.x.toString(),t,r)}function c(n,t,r){return e(n,A.X.toString(),t,r)}function f(n,t,e){var r=M.get(t.slice(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}var s=n.dateTime,h=n.date,p=n.time,g=n.periods,v=n.days,d=n.shortDays,y=n.months,m=n.shortMonths;t.utc=function(n){function e(n){try{va=Hn;var t=new va;return t._=n,r(t)}finally{va=Date}}var r=t(n);return e.parse=function(n){try{va=Hn;var t=r.parse(n);return t&&t._}finally{va=Date}},e.toString=r.toString,e},t.multi=t.utc.multi=ct;var M=ao.map(),x=Vn(v),b=Xn(v),_=Vn(d),w=Xn(d),S=Vn(y),k=Xn(y),N=Vn(m),E=Xn(m);g.forEach(function(n,t){M.set(n.toLowerCase(),t)});var A={a:function(n){return d[n.getDay()]},A:function(n){return v[n.getDay()]},b:function(n){return m[n.getMonth()]},B:function(n){return y[n.getMonth()]},c:t(s),d:function(n,t){return Zn(n.getDate(),t,2)},e:function(n,t){return Zn(n.getDate(),t,2)},H:function(n,t){return Zn(n.getHours(),t,2)},I:function(n,t){return Zn(n.getHours()%12||12,t,2)},j:function(n,t){return Zn(1+ga.dayOfYear(n),t,3)},L:function(n,t){return Zn(n.getMilliseconds(),t,3)},m:function(n,t){return Zn(n.getMonth()+1,t,2)},M:function(n,t){return Zn(n.getMinutes(),t,2)},p:function(n){return g[+(n.getHours()>=12)]},S:function(n,t){return Zn(n.getSeconds(),t,2)},U:function(n,t){return Zn(ga.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return Zn(ga.mondayOfYear(n),t,2)},x:t(h),X:t(p),y:function(n,t){return Zn(n.getFullYear()%100,t,2)},Y:function(n,t){return Zn(n.getFullYear()%1e4,t,4)},Z:at,"%":function(){return"%"}},C={a:r,A:i,b:u,B:o,c:a,d:tt,e:tt,H:rt,I:rt,j:et,L:ot,m:nt,M:it,p:f,S:ut,U:Bn,w:$n,W:Wn,x:l,X:c,y:Gn,Y:Jn,Z:Kn,"%":lt};return t}function Zn(n,t,e){var r=0>n?"-":"",i=(r?-n:n)+"",u=i.length;return r+(e>u?new Array(e-u+1).join(t)+i:i)}function Vn(n){return new RegExp("^(?:"+n.map(ao.requote).join("|")+")","i")}function Xn(n){for(var t=new c,e=-1,r=n.length;++e68?1900:2e3)}function nt(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.m=r[0]-1,e+r[0].length):-1}function tt(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.d=+r[0],e+r[0].length):-1}function et(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+3));return r?(n.j=+r[0],e+r[0].length):-1}function rt(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.H=+r[0],e+r[0].length):-1}function it(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.M=+r[0],e+r[0].length):-1}function ut(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.S=+r[0],e+r[0].length):-1}function ot(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+3));return r?(n.L=+r[0],e+r[0].length):-1}function at(n){var t=n.getTimezoneOffset(),e=t>0?"-":"+",r=xo(t)/60|0,i=xo(t)%60;return e+Zn(r,"0",2)+Zn(i,"0",2)}function lt(n,t,e){Ma.lastIndex=0;var r=Ma.exec(t.slice(e,e+1));return r?e+r[0].length:-1}function ct(n){for(var t=n.length,e=-1;++e=0?1:-1,a=o*e,l=Math.cos(t),c=Math.sin(t),f=u*c,s=i*l+f*Math.cos(a),h=f*o*Math.sin(a);ka.add(Math.atan2(h,s)),r=n,i=l,u=c}var t,e,r,i,u;Na.point=function(o,a){Na.point=n,r=(t=o)*Yo,i=Math.cos(a=(e=a)*Yo/2+Fo/4),u=Math.sin(a)},Na.lineEnd=function(){n(t,e)}}function dt(n){var t=n[0],e=n[1],r=Math.cos(e);return[r*Math.cos(t),r*Math.sin(t),Math.sin(e)]}function yt(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]}function mt(n,t){return[n[1]*t[2]-n[2]*t[1],n[2]*t[0]-n[0]*t[2],n[0]*t[1]-n[1]*t[0]]}function Mt(n,t){n[0]+=t[0],n[1]+=t[1],n[2]+=t[2]}function xt(n,t){return[n[0]*t,n[1]*t,n[2]*t]}function bt(n){var t=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);n[0]/=t,n[1]/=t,n[2]/=t}function _t(n){return[Math.atan2(n[1],n[0]),tn(n[2])]}function wt(n,t){return xo(n[0]-t[0])a;++a)i.point((e=n[a])[0],e[1]);return void i.lineEnd()}var l=new Tt(e,n,null,!0),c=new Tt(e,null,l,!1);l.o=c,u.push(l),o.push(c),l=new Tt(r,n,null,!1),c=new Tt(r,null,l,!0),l.o=c,u.push(l),o.push(c)}}),o.sort(t),qt(u),qt(o),u.length){for(var a=0,l=e,c=o.length;c>a;++a)o[a].e=l=!l;for(var f,s,h=u[0];;){for(var p=h,g=!0;p.v;)if((p=p.n)===h)return;f=p.z,i.lineStart();do{if(p.v=p.o.v=!0,p.e){if(g)for(var a=0,c=f.length;c>a;++a)i.point((s=f[a])[0],s[1]);else r(p.x,p.n.x,1,i);p=p.n}else{if(g){f=p.p.z;for(var a=f.length-1;a>=0;--a)i.point((s=f[a])[0],s[1])}else r(p.x,p.p.x,-1,i);p=p.p}p=p.o,f=p.z,g=!g}while(!p.v);i.lineEnd()}}}function qt(n){if(t=n.length){for(var t,e,r=0,i=n[0];++r0){for(b||(u.polygonStart(),b=!0),u.lineStart();++o1&&2&t&&e.push(e.pop().concat(e.shift())),p.push(e.filter(Dt))}var p,g,v,d=t(u),y=i.invert(r[0],r[1]),m={point:o,lineStart:l,lineEnd:c,polygonStart:function(){m.point=f,m.lineStart=s,m.lineEnd=h,p=[],g=[]},polygonEnd:function(){m.point=o,m.lineStart=l,m.lineEnd=c,p=ao.merge(p);var n=Ot(y,g);p.length?(b||(u.polygonStart(),b=!0),Lt(p,Ut,n,e,u)):n&&(b||(u.polygonStart(),b=!0),u.lineStart(),e(null,null,1,u),u.lineEnd()),b&&(u.polygonEnd(),b=!1),p=g=null},sphere:function(){u.polygonStart(),u.lineStart(),e(null,null,1,u),u.lineEnd(),u.polygonEnd()}},M=Pt(),x=t(M),b=!1;return m}}function Dt(n){return n.length>1}function Pt(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:b,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function Ut(n,t){return((n=n.x)[0]<0?n[1]-Io-Uo:Io-n[1])-((t=t.x)[0]<0?t[1]-Io-Uo:Io-t[1])}function jt(n){var t,e=NaN,r=NaN,i=NaN;return{lineStart:function(){n.lineStart(),t=1},point:function(u,o){var a=u>0?Fo:-Fo,l=xo(u-e);xo(l-Fo)0?Io:-Io),n.point(i,r),n.lineEnd(),n.lineStart(),n.point(a,r),n.point(u,r),t=0):i!==a&&l>=Fo&&(xo(e-i)Uo?Math.atan((Math.sin(t)*(u=Math.cos(r))*Math.sin(e)-Math.sin(r)*(i=Math.cos(t))*Math.sin(n))/(i*u*o)):(t+r)/2}function Ht(n,t,e,r){var i;if(null==n)i=e*Io,r.point(-Fo,i),r.point(0,i),r.point(Fo,i),r.point(Fo,0),r.point(Fo,-i),r.point(0,-i),r.point(-Fo,-i),r.point(-Fo,0),r.point(-Fo,i);else if(xo(n[0]-t[0])>Uo){var u=n[0]a;++a){var c=t[a],f=c.length;if(f)for(var s=c[0],h=s[0],p=s[1]/2+Fo/4,g=Math.sin(p),v=Math.cos(p),d=1;;){d===f&&(d=0),n=c[d];var y=n[0],m=n[1]/2+Fo/4,M=Math.sin(m),x=Math.cos(m),b=y-h,_=b>=0?1:-1,w=_*b,S=w>Fo,k=g*M;if(ka.add(Math.atan2(k*_*Math.sin(w),v*x+k*Math.cos(w))),u+=S?b+_*Ho:b,S^h>=e^y>=e){var N=mt(dt(s),dt(n));bt(N);var E=mt(i,N);bt(E);var A=(S^b>=0?-1:1)*tn(E[2]);(r>A||r===A&&(N[0]||N[1]))&&(o+=S^b>=0?1:-1)}if(!d++)break;h=y,g=M,v=x,s=n}}return(-Uo>u||Uo>u&&-Uo>ka)^1&o}function It(n){function t(n,t){return Math.cos(n)*Math.cos(t)>u}function e(n){var e,u,l,c,f;return{lineStart:function(){c=l=!1,f=1},point:function(s,h){var p,g=[s,h],v=t(s,h),d=o?v?0:i(s,h):v?i(s+(0>s?Fo:-Fo),h):0;if(!e&&(c=l=v)&&n.lineStart(),v!==l&&(p=r(e,g),(wt(e,p)||wt(g,p))&&(g[0]+=Uo,g[1]+=Uo,v=t(g[0],g[1]))),v!==l)f=0,v?(n.lineStart(),p=r(g,e),n.point(p[0],p[1])):(p=r(e,g),n.point(p[0],p[1]),n.lineEnd()),e=p;else if(a&&e&&o^v){var y;d&u||!(y=r(g,e,!0))||(f=0,o?(n.lineStart(),n.point(y[0][0],y[0][1]),n.point(y[1][0],y[1][1]),n.lineEnd()):(n.point(y[1][0],y[1][1]),n.lineEnd(),n.lineStart(),n.point(y[0][0],y[0][1])))}!v||e&&wt(e,g)||n.point(g[0],g[1]),e=g,l=v,u=d},lineEnd:function(){l&&n.lineEnd(),e=null},clean:function(){return f|(c&&l)<<1}}}function r(n,t,e){var r=dt(n),i=dt(t),o=[1,0,0],a=mt(r,i),l=yt(a,a),c=a[0],f=l-c*c;if(!f)return!e&&n;var s=u*l/f,h=-u*c/f,p=mt(o,a),g=xt(o,s),v=xt(a,h);Mt(g,v);var d=p,y=yt(g,d),m=yt(d,d),M=y*y-m*(yt(g,g)-1);if(!(0>M)){var x=Math.sqrt(M),b=xt(d,(-y-x)/m);if(Mt(b,g),b=_t(b),!e)return b;var _,w=n[0],S=t[0],k=n[1],N=t[1];w>S&&(_=w,w=S,S=_);var E=S-w,A=xo(E-Fo)E;if(!A&&k>N&&(_=k,k=N,N=_),C?A?k+N>0^b[1]<(xo(b[0]-w)Fo^(w<=b[0]&&b[0]<=S)){var z=xt(d,(-y+x)/m);return Mt(z,g),[b,_t(z)]}}}function i(t,e){var r=o?n:Fo-n,i=0;return-r>t?i|=1:t>r&&(i|=2),-r>e?i|=4:e>r&&(i|=8),i}var u=Math.cos(n),o=u>0,a=xo(u)>Uo,l=ve(n,6*Yo);return Rt(t,e,l,o?[0,-n]:[-Fo,n-Fo])}function Yt(n,t,e,r){return function(i){var u,o=i.a,a=i.b,l=o.x,c=o.y,f=a.x,s=a.y,h=0,p=1,g=f-l,v=s-c;if(u=n-l,g||!(u>0)){if(u/=g,0>g){if(h>u)return;p>u&&(p=u)}else if(g>0){if(u>p)return;u>h&&(h=u)}if(u=e-l,g||!(0>u)){if(u/=g,0>g){if(u>p)return;u>h&&(h=u)}else if(g>0){if(h>u)return;p>u&&(p=u)}if(u=t-c,v||!(u>0)){if(u/=v,0>v){if(h>u)return;p>u&&(p=u)}else if(v>0){if(u>p)return;u>h&&(h=u)}if(u=r-c,v||!(0>u)){if(u/=v,0>v){if(u>p)return;u>h&&(h=u)}else if(v>0){if(h>u)return;p>u&&(p=u)}return h>0&&(i.a={x:l+h*g,y:c+h*v}),1>p&&(i.b={x:l+p*g,y:c+p*v}),i}}}}}}function Zt(n,t,e,r){function i(r,i){return xo(r[0]-n)0?0:3:xo(r[0]-e)0?2:1:xo(r[1]-t)0?1:0:i>0?3:2}function u(n,t){return o(n.x,t.x)}function o(n,t){var e=i(n,1),r=i(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}return function(a){function l(n){for(var t=0,e=d.length,r=n[1],i=0;e>i;++i)for(var u,o=1,a=d[i],l=a.length,c=a[0];l>o;++o)u=a[o],c[1]<=r?u[1]>r&&Q(c,u,n)>0&&++t:u[1]<=r&&Q(c,u,n)<0&&--t,c=u;return 0!==t}function c(u,a,l,c){var f=0,s=0;if(null==u||(f=i(u,l))!==(s=i(a,l))||o(u,a)<0^l>0){do c.point(0===f||3===f?n:e,f>1?r:t);while((f=(f+l+4)%4)!==s)}else c.point(a[0],a[1])}function f(i,u){return i>=n&&e>=i&&u>=t&&r>=u}function s(n,t){f(n,t)&&a.point(n,t)}function h(){C.point=g,d&&d.push(y=[]),S=!0,w=!1,b=_=NaN}function p(){v&&(g(m,M),x&&w&&E.rejoin(),v.push(E.buffer())),C.point=s,w&&a.lineEnd()}function g(n,t){n=Math.max(-Ha,Math.min(Ha,n)),t=Math.max(-Ha,Math.min(Ha,t));var e=f(n,t);if(d&&y.push([n,t]),S)m=n,M=t,x=e,S=!1,e&&(a.lineStart(),a.point(n,t));else if(e&&w)a.point(n,t);else{var r={a:{x:b,y:_},b:{x:n,y:t}};A(r)?(w||(a.lineStart(),a.point(r.a.x,r.a.y)),a.point(r.b.x,r.b.y),e||a.lineEnd(),k=!1):e&&(a.lineStart(),a.point(n,t),k=!1)}b=n,_=t,w=e}var v,d,y,m,M,x,b,_,w,S,k,N=a,E=Pt(),A=Yt(n,t,e,r),C={point:s,lineStart:h,lineEnd:p,polygonStart:function(){a=E,v=[],d=[],k=!0},polygonEnd:function(){a=N,v=ao.merge(v);var t=l([n,r]),e=k&&t,i=v.length;(e||i)&&(a.polygonStart(),e&&(a.lineStart(),c(null,null,1,a),a.lineEnd()),i&&Lt(v,u,t,c,a),a.polygonEnd()),v=d=y=null}};return C}}function Vt(n){var t=0,e=Fo/3,r=ae(n),i=r(t,e);return i.parallels=function(n){return arguments.length?r(t=n[0]*Fo/180,e=n[1]*Fo/180):[t/Fo*180,e/Fo*180]},i}function Xt(n,t){function e(n,t){var e=Math.sqrt(u-2*i*Math.sin(t))/i;return[e*Math.sin(n*=i),o-e*Math.cos(n)]}var r=Math.sin(n),i=(r+Math.sin(t))/2,u=1+r*(2*i-r),o=Math.sqrt(u)/i;return e.invert=function(n,t){var e=o-t;return[Math.atan2(n,e)/i,tn((u-(n*n+e*e)*i*i)/(2*i))]},e}function $t(){function n(n,t){Ia+=i*n-r*t,r=n,i=t}var t,e,r,i;$a.point=function(u,o){$a.point=n,t=r=u,e=i=o},$a.lineEnd=function(){n(t,e)}}function Bt(n,t){Ya>n&&(Ya=n),n>Va&&(Va=n),Za>t&&(Za=t),t>Xa&&(Xa=t)}function Wt(){function n(n,t){o.push("M",n,",",t,u)}function t(n,t){o.push("M",n,",",t),a.point=e}function e(n,t){o.push("L",n,",",t)}function r(){a.point=n}function i(){o.push("Z")}var u=Jt(4.5),o=[],a={point:n,lineStart:function(){a.point=t},lineEnd:r,polygonStart:function(){a.lineEnd=i},polygonEnd:function(){a.lineEnd=r,a.point=n},pointRadius:function(n){return u=Jt(n),a},result:function(){if(o.length){var n=o.join("");return o=[],n}}};return a}function Jt(n){return"m0,"+n+"a"+n+","+n+" 0 1,1 0,"+-2*n+"a"+n+","+n+" 0 1,1 0,"+2*n+"z"}function Gt(n,t){Ca+=n,za+=t,++La}function Kt(){function n(n,r){var i=n-t,u=r-e,o=Math.sqrt(i*i+u*u);qa+=o*(t+n)/2,Ta+=o*(e+r)/2,Ra+=o,Gt(t=n,e=r)}var t,e;Wa.point=function(r,i){Wa.point=n,Gt(t=r,e=i)}}function Qt(){Wa.point=Gt}function ne(){function n(n,t){var e=n-r,u=t-i,o=Math.sqrt(e*e+u*u);qa+=o*(r+n)/2,Ta+=o*(i+t)/2,Ra+=o,o=i*n-r*t,Da+=o*(r+n),Pa+=o*(i+t),Ua+=3*o,Gt(r=n,i=t)}var t,e,r,i;Wa.point=function(u,o){Wa.point=n,Gt(t=r=u,e=i=o)},Wa.lineEnd=function(){n(t,e)}}function te(n){function t(t,e){n.moveTo(t+o,e),n.arc(t,e,o,0,Ho)}function e(t,e){n.moveTo(t,e),a.point=r}function r(t,e){n.lineTo(t,e)}function i(){a.point=t}function u(){n.closePath()}var o=4.5,a={point:t,lineStart:function(){a.point=e},lineEnd:i,polygonStart:function(){a.lineEnd=u},polygonEnd:function(){a.lineEnd=i,a.point=t},pointRadius:function(n){return o=n,a},result:b};return a}function ee(n){function t(n){return(a?r:e)(n)}function e(t){return ue(t,function(e,r){e=n(e,r),t.point(e[0],e[1])})}function r(t){function e(e,r){e=n(e,r),t.point(e[0],e[1])}function r(){M=NaN,S.point=u,t.lineStart()}function u(e,r){var u=dt([e,r]),o=n(e,r);i(M,x,m,b,_,w,M=o[0],x=o[1],m=e,b=u[0],_=u[1],w=u[2],a,t),t.point(M,x)}function o(){S.point=e,t.lineEnd()}function l(){ -r(),S.point=c,S.lineEnd=f}function c(n,t){u(s=n,h=t),p=M,g=x,v=b,d=_,y=w,S.point=u}function f(){i(M,x,m,b,_,w,p,g,s,v,d,y,a,t),S.lineEnd=o,o()}var s,h,p,g,v,d,y,m,M,x,b,_,w,S={point:e,lineStart:r,lineEnd:o,polygonStart:function(){t.polygonStart(),S.lineStart=l},polygonEnd:function(){t.polygonEnd(),S.lineStart=r}};return S}function i(t,e,r,a,l,c,f,s,h,p,g,v,d,y){var m=f-t,M=s-e,x=m*m+M*M;if(x>4*u&&d--){var b=a+p,_=l+g,w=c+v,S=Math.sqrt(b*b+_*_+w*w),k=Math.asin(w/=S),N=xo(xo(w)-1)u||xo((m*z+M*L)/x-.5)>.3||o>a*p+l*g+c*v)&&(i(t,e,r,a,l,c,A,C,N,b/=S,_/=S,w,d,y),y.point(A,C),i(A,C,N,b,_,w,f,s,h,p,g,v,d,y))}}var u=.5,o=Math.cos(30*Yo),a=16;return t.precision=function(n){return arguments.length?(a=(u=n*n)>0&&16,t):Math.sqrt(u)},t}function re(n){var t=ee(function(t,e){return n([t*Zo,e*Zo])});return function(n){return le(t(n))}}function ie(n){this.stream=n}function ue(n,t){return{point:t,sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function oe(n){return ae(function(){return n})()}function ae(n){function t(n){return n=a(n[0]*Yo,n[1]*Yo),[n[0]*h+l,c-n[1]*h]}function e(n){return n=a.invert((n[0]-l)/h,(c-n[1])/h),n&&[n[0]*Zo,n[1]*Zo]}function r(){a=Ct(o=se(y,M,x),u);var n=u(v,d);return l=p-n[0]*h,c=g+n[1]*h,i()}function i(){return f&&(f.valid=!1,f=null),t}var u,o,a,l,c,f,s=ee(function(n,t){return n=u(n,t),[n[0]*h+l,c-n[1]*h]}),h=150,p=480,g=250,v=0,d=0,y=0,M=0,x=0,b=Fa,_=m,w=null,S=null;return t.stream=function(n){return f&&(f.valid=!1),f=le(b(o,s(_(n)))),f.valid=!0,f},t.clipAngle=function(n){return arguments.length?(b=null==n?(w=n,Fa):It((w=+n)*Yo),i()):w},t.clipExtent=function(n){return arguments.length?(S=n,_=n?Zt(n[0][0],n[0][1],n[1][0],n[1][1]):m,i()):S},t.scale=function(n){return arguments.length?(h=+n,r()):h},t.translate=function(n){return arguments.length?(p=+n[0],g=+n[1],r()):[p,g]},t.center=function(n){return arguments.length?(v=n[0]%360*Yo,d=n[1]%360*Yo,r()):[v*Zo,d*Zo]},t.rotate=function(n){return arguments.length?(y=n[0]%360*Yo,M=n[1]%360*Yo,x=n.length>2?n[2]%360*Yo:0,r()):[y*Zo,M*Zo,x*Zo]},ao.rebind(t,s,"precision"),function(){return u=n.apply(this,arguments),t.invert=u.invert&&e,r()}}function le(n){return ue(n,function(t,e){n.point(t*Yo,e*Yo)})}function ce(n,t){return[n,t]}function fe(n,t){return[n>Fo?n-Ho:-Fo>n?n+Ho:n,t]}function se(n,t,e){return n?t||e?Ct(pe(n),ge(t,e)):pe(n):t||e?ge(t,e):fe}function he(n){return function(t,e){return t+=n,[t>Fo?t-Ho:-Fo>t?t+Ho:t,e]}}function pe(n){var t=he(n);return t.invert=he(-n),t}function ge(n,t){function e(n,t){var e=Math.cos(t),a=Math.cos(n)*e,l=Math.sin(n)*e,c=Math.sin(t),f=c*r+a*i;return[Math.atan2(l*u-f*o,a*r-c*i),tn(f*u+l*o)]}var r=Math.cos(n),i=Math.sin(n),u=Math.cos(t),o=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),a=Math.cos(n)*e,l=Math.sin(n)*e,c=Math.sin(t),f=c*u-l*o;return[Math.atan2(l*u+c*o,a*r+f*i),tn(f*r-a*i)]},e}function ve(n,t){var e=Math.cos(n),r=Math.sin(n);return function(i,u,o,a){var l=o*t;null!=i?(i=de(e,i),u=de(e,u),(o>0?u>i:i>u)&&(i+=o*Ho)):(i=n+o*Ho,u=n-.5*l);for(var c,f=i;o>0?f>u:u>f;f-=l)a.point((c=_t([e,-r*Math.cos(f),-r*Math.sin(f)]))[0],c[1])}}function de(n,t){var e=dt(t);e[0]-=n,bt(e);var r=nn(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-Uo)%(2*Math.PI)}function ye(n,t,e){var r=ao.range(n,t-Uo,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function me(n,t,e){var r=ao.range(n,t-Uo,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function Me(n){return n.source}function xe(n){return n.target}function be(n,t,e,r){var i=Math.cos(t),u=Math.sin(t),o=Math.cos(r),a=Math.sin(r),l=i*Math.cos(n),c=i*Math.sin(n),f=o*Math.cos(e),s=o*Math.sin(e),h=2*Math.asin(Math.sqrt(on(r-t)+i*o*on(e-n))),p=1/Math.sin(h),g=h?function(n){var t=Math.sin(n*=h)*p,e=Math.sin(h-n)*p,r=e*l+t*f,i=e*c+t*s,o=e*u+t*a;return[Math.atan2(i,r)*Zo,Math.atan2(o,Math.sqrt(r*r+i*i))*Zo]}:function(){return[n*Zo,t*Zo]};return g.distance=h,g}function _e(){function n(n,i){var u=Math.sin(i*=Yo),o=Math.cos(i),a=xo((n*=Yo)-t),l=Math.cos(a);Ja+=Math.atan2(Math.sqrt((a=o*Math.sin(a))*a+(a=r*u-e*o*l)*a),e*u+r*o*l),t=n,e=u,r=o}var t,e,r;Ga.point=function(i,u){t=i*Yo,e=Math.sin(u*=Yo),r=Math.cos(u),Ga.point=n},Ga.lineEnd=function(){Ga.point=Ga.lineEnd=b}}function we(n,t){function e(t,e){var r=Math.cos(t),i=Math.cos(e),u=n(r*i);return[u*i*Math.sin(t),u*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),i=t(r),u=Math.sin(i),o=Math.cos(i);return[Math.atan2(n*u,r*o),Math.asin(r&&e*u/r)]},e}function Se(n,t){function e(n,t){o>0?-Io+Uo>t&&(t=-Io+Uo):t>Io-Uo&&(t=Io-Uo);var e=o/Math.pow(i(t),u);return[e*Math.sin(u*n),o-e*Math.cos(u*n)]}var r=Math.cos(n),i=function(n){return Math.tan(Fo/4+n/2)},u=n===t?Math.sin(n):Math.log(r/Math.cos(t))/Math.log(i(t)/i(n)),o=r*Math.pow(i(n),u)/u;return u?(e.invert=function(n,t){var e=o-t,r=K(u)*Math.sqrt(n*n+e*e);return[Math.atan2(n,e)/u,2*Math.atan(Math.pow(o/r,1/u))-Io]},e):Ne}function ke(n,t){function e(n,t){var e=u-t;return[e*Math.sin(i*n),u-e*Math.cos(i*n)]}var r=Math.cos(n),i=n===t?Math.sin(n):(r-Math.cos(t))/(t-n),u=r/i+n;return xo(i)i;i++){for(;r>1&&Q(n[e[r-2]],n[e[r-1]],n[i])<=0;)--r;e[r++]=i}return e.slice(0,r)}function qe(n,t){return n[0]-t[0]||n[1]-t[1]}function Te(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function Re(n,t,e,r){var i=n[0],u=e[0],o=t[0]-i,a=r[0]-u,l=n[1],c=e[1],f=t[1]-l,s=r[1]-c,h=(a*(l-c)-s*(i-u))/(s*o-a*f);return[i+h*o,l+h*f]}function De(n){var t=n[0],e=n[n.length-1];return!(t[0]-e[0]||t[1]-e[1])}function Pe(){rr(this),this.edge=this.site=this.circle=null}function Ue(n){var t=cl.pop()||new Pe;return t.site=n,t}function je(n){Be(n),ol.remove(n),cl.push(n),rr(n)}function Fe(n){var t=n.circle,e=t.x,r=t.cy,i={x:e,y:r},u=n.P,o=n.N,a=[n];je(n);for(var l=u;l.circle&&xo(e-l.circle.x)f;++f)c=a[f],l=a[f-1],nr(c.edge,l.site,c.site,i);l=a[0],c=a[s-1],c.edge=Ke(l.site,c.site,null,i),$e(l),$e(c)}function He(n){for(var t,e,r,i,u=n.x,o=n.y,a=ol._;a;)if(r=Oe(a,o)-u,r>Uo)a=a.L;else{if(i=u-Ie(a,o),!(i>Uo)){r>-Uo?(t=a.P,e=a):i>-Uo?(t=a,e=a.N):t=e=a;break}if(!a.R){t=a;break}a=a.R}var l=Ue(n);if(ol.insert(t,l),t||e){if(t===e)return Be(t),e=Ue(t.site),ol.insert(l,e),l.edge=e.edge=Ke(t.site,l.site),$e(t),void $e(e);if(!e)return void(l.edge=Ke(t.site,l.site));Be(t),Be(e);var c=t.site,f=c.x,s=c.y,h=n.x-f,p=n.y-s,g=e.site,v=g.x-f,d=g.y-s,y=2*(h*d-p*v),m=h*h+p*p,M=v*v+d*d,x={x:(d*m-p*M)/y+f,y:(h*M-v*m)/y+s};nr(e.edge,c,g,x),l.edge=Ke(c,n,null,x),e.edge=Ke(n,g,null,x),$e(t),$e(e)}}function Oe(n,t){var e=n.site,r=e.x,i=e.y,u=i-t;if(!u)return r;var o=n.P;if(!o)return-(1/0);e=o.site;var a=e.x,l=e.y,c=l-t;if(!c)return a;var f=a-r,s=1/u-1/c,h=f/c;return s?(-h+Math.sqrt(h*h-2*s*(f*f/(-2*c)-l+c/2+i-u/2)))/s+r:(r+a)/2}function Ie(n,t){var e=n.N;if(e)return Oe(e,t);var r=n.site;return r.y===t?r.x:1/0}function Ye(n){this.site=n,this.edges=[]}function Ze(n){for(var t,e,r,i,u,o,a,l,c,f,s=n[0][0],h=n[1][0],p=n[0][1],g=n[1][1],v=ul,d=v.length;d--;)if(u=v[d],u&&u.prepare())for(a=u.edges,l=a.length,o=0;l>o;)f=a[o].end(),r=f.x,i=f.y,c=a[++o%l].start(),t=c.x,e=c.y,(xo(r-t)>Uo||xo(i-e)>Uo)&&(a.splice(o,0,new tr(Qe(u.site,f,xo(r-s)Uo?{x:s,y:xo(t-s)Uo?{x:xo(e-g)Uo?{x:h,y:xo(t-h)Uo?{x:xo(e-p)=-jo)){var p=l*l+c*c,g=f*f+s*s,v=(s*p-c*g)/h,d=(l*g-f*p)/h,s=d+a,y=fl.pop()||new Xe;y.arc=n,y.site=i,y.x=v+o,y.y=s+Math.sqrt(v*v+d*d),y.cy=s,n.circle=y;for(var m=null,M=ll._;M;)if(y.yd||d>=a)return;if(h>g){if(u){if(u.y>=c)return}else u={x:d,y:l};e={x:d,y:c}}else{if(u){if(u.yr||r>1)if(h>g){if(u){if(u.y>=c)return}else u={x:(l-i)/r,y:l};e={x:(c-i)/r,y:c}}else{if(u){if(u.yp){if(u){if(u.x>=a)return}else u={x:o,y:r*o+i};e={x:a,y:r*a+i}}else{if(u){if(u.xu||s>o||r>h||i>p)){if(g=n.point){var g,v=t-n.x,d=e-n.y,y=v*v+d*d;if(l>y){var m=Math.sqrt(l=y);r=t-m,i=e-m,u=t+m,o=e+m,a=g}}for(var M=n.nodes,x=.5*(f+h),b=.5*(s+p),_=t>=x,w=e>=b,S=w<<1|_,k=S+4;k>S;++S)if(n=M[3&S])switch(3&S){case 0:c(n,f,s,x,b);break;case 1:c(n,x,s,h,b);break;case 2:c(n,f,b,x,p);break;case 3:c(n,x,b,h,p)}}}(n,r,i,u,o),a}function vr(n,t){n=ao.rgb(n),t=ao.rgb(t);var e=n.r,r=n.g,i=n.b,u=t.r-e,o=t.g-r,a=t.b-i;return function(n){return"#"+bn(Math.round(e+u*n))+bn(Math.round(r+o*n))+bn(Math.round(i+a*n))}}function dr(n,t){var e,r={},i={};for(e in n)e in t?r[e]=Mr(n[e],t[e]):i[e]=n[e];for(e in t)e in n||(i[e]=t[e]);return function(n){for(e in r)i[e]=r[e](n);return i}}function yr(n,t){return n=+n,t=+t,function(e){return n*(1-e)+t*e}}function mr(n,t){var e,r,i,u=hl.lastIndex=pl.lastIndex=0,o=-1,a=[],l=[];for(n+="",t+="";(e=hl.exec(n))&&(r=pl.exec(t));)(i=r.index)>u&&(i=t.slice(u,i),a[o]?a[o]+=i:a[++o]=i),(e=e[0])===(r=r[0])?a[o]?a[o]+=r:a[++o]=r:(a[++o]=null,l.push({i:o,x:yr(e,r)})),u=pl.lastIndex;return ur;++r)a[(e=l[r]).i]=e.x(n);return a.join("")})}function Mr(n,t){for(var e,r=ao.interpolators.length;--r>=0&&!(e=ao.interpolators[r](n,t)););return e}function xr(n,t){var e,r=[],i=[],u=n.length,o=t.length,a=Math.min(n.length,t.length);for(e=0;a>e;++e)r.push(Mr(n[e],t[e]));for(;u>e;++e)i[e]=n[e];for(;o>e;++e)i[e]=t[e];return function(n){for(e=0;a>e;++e)i[e]=r[e](n);return i}}function br(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function _r(n){return function(t){return 1-n(1-t)}}function wr(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function Sr(n){return n*n}function kr(n){return n*n*n}function Nr(n){if(0>=n)return 0;if(n>=1)return 1;var t=n*n,e=t*n;return 4*(.5>n?e:3*(n-t)+e-.75)}function Er(n){return function(t){return Math.pow(t,n)}}function Ar(n){return 1-Math.cos(n*Io)}function Cr(n){return Math.pow(2,10*(n-1))}function zr(n){return 1-Math.sqrt(1-n*n)}function Lr(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/Ho*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,-10*r)*Math.sin((r-e)*Ho/t)}}function qr(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function Tr(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function Rr(n,t){n=ao.hcl(n),t=ao.hcl(t);var e=n.h,r=n.c,i=n.l,u=t.h-e,o=t.c-r,a=t.l-i;return isNaN(o)&&(o=0,r=isNaN(r)?t.c:r),isNaN(u)?(u=0,e=isNaN(e)?t.h:e):u>180?u-=360:-180>u&&(u+=360),function(n){return sn(e+u*n,r+o*n,i+a*n)+""}}function Dr(n,t){n=ao.hsl(n),t=ao.hsl(t);var e=n.h,r=n.s,i=n.l,u=t.h-e,o=t.s-r,a=t.l-i;return isNaN(o)&&(o=0,r=isNaN(r)?t.s:r),isNaN(u)?(u=0,e=isNaN(e)?t.h:e):u>180?u-=360:-180>u&&(u+=360),function(n){return cn(e+u*n,r+o*n,i+a*n)+""}}function Pr(n,t){n=ao.lab(n),t=ao.lab(t);var e=n.l,r=n.a,i=n.b,u=t.l-e,o=t.a-r,a=t.b-i;return function(n){return pn(e+u*n,r+o*n,i+a*n)+""}}function Ur(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function jr(n){var t=[n.a,n.b],e=[n.c,n.d],r=Hr(t),i=Fr(t,e),u=Hr(Or(e,t,-i))||0;t[0]*e[1]180?t+=360:t-n>180&&(n+=360),r.push({i:e.push(Ir(e)+"rotate(",null,")")-2,x:yr(n,t)})):t&&e.push(Ir(e)+"rotate("+t+")")}function Vr(n,t,e,r){n!==t?r.push({i:e.push(Ir(e)+"skewX(",null,")")-2,x:yr(n,t)}):t&&e.push(Ir(e)+"skewX("+t+")")}function Xr(n,t,e,r){if(n[0]!==t[0]||n[1]!==t[1]){var i=e.push(Ir(e)+"scale(",null,",",null,")");r.push({i:i-4,x:yr(n[0],t[0])},{i:i-2,x:yr(n[1],t[1])})}else 1===t[0]&&1===t[1]||e.push(Ir(e)+"scale("+t+")")}function $r(n,t){var e=[],r=[];return n=ao.transform(n),t=ao.transform(t),Yr(n.translate,t.translate,e,r),Zr(n.rotate,t.rotate,e,r),Vr(n.skew,t.skew,e,r),Xr(n.scale,t.scale,e,r),n=t=null,function(n){for(var t,i=-1,u=r.length;++i=0;)e.push(i[r])}function oi(n,t){for(var e=[n],r=[];null!=(n=e.pop());)if(r.push(n),(u=n.children)&&(i=u.length))for(var i,u,o=-1;++oe;++e)(t=n[e][1])>i&&(r=e,i=t);return r}function yi(n){return n.reduce(mi,0)}function mi(n,t){return n+t[1]}function Mi(n,t){return xi(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function xi(n,t){for(var e=-1,r=+n[0],i=(n[1]-r)/t,u=[];++e<=t;)u[e]=i*e+r;return u}function bi(n){return[ao.min(n),ao.max(n)]}function _i(n,t){return n.value-t.value}function wi(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function Si(n,t){n._pack_next=t,t._pack_prev=n}function ki(n,t){var e=t.x-n.x,r=t.y-n.y,i=n.r+t.r;return.999*i*i>e*e+r*r}function Ni(n){function t(n){f=Math.min(n.x-n.r,f),s=Math.max(n.x+n.r,s),h=Math.min(n.y-n.r,h),p=Math.max(n.y+n.r,p)}if((e=n.children)&&(c=e.length)){var e,r,i,u,o,a,l,c,f=1/0,s=-(1/0),h=1/0,p=-(1/0);if(e.forEach(Ei),r=e[0],r.x=-r.r,r.y=0,t(r),c>1&&(i=e[1],i.x=i.r,i.y=0,t(i),c>2))for(u=e[2],zi(r,i,u),t(u),wi(r,u),r._pack_prev=u,wi(u,i),i=r._pack_next,o=3;c>o;o++){zi(r,i,u=e[o]);var g=0,v=1,d=1;for(a=i._pack_next;a!==i;a=a._pack_next,v++)if(ki(a,u)){g=1;break}if(1==g)for(l=r._pack_prev;l!==a._pack_prev&&!ki(l,u);l=l._pack_prev,d++);g?(d>v||v==d&&i.ro;o++)u=e[o],u.x-=y,u.y-=m,M=Math.max(M,u.r+Math.sqrt(u.x*u.x+u.y*u.y));n.r=M,e.forEach(Ai)}}function Ei(n){n._pack_next=n._pack_prev=n}function Ai(n){delete n._pack_next,delete n._pack_prev}function Ci(n,t,e,r){var i=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,i)for(var u=-1,o=i.length;++u=0;)t=i[u],t.z+=e,t.m+=e,e+=t.s+(r+=t.c)}function Pi(n,t,e){return n.a.parent===t.parent?n.a:e}function Ui(n){return 1+ao.max(n,function(n){return n.y})}function ji(n){return n.reduce(function(n,t){return n+t.x},0)/n.length}function Fi(n){var t=n.children;return t&&t.length?Fi(t[0]):n}function Hi(n){var t,e=n.children;return e&&(t=e.length)?Hi(e[t-1]):n}function Oi(n){return{x:n.x,y:n.y,dx:n.dx,dy:n.dy}}function Ii(n,t){var e=n.x+t[3],r=n.y+t[0],i=n.dx-t[1]-t[3],u=n.dy-t[0]-t[2];return 0>i&&(e+=i/2,i=0),0>u&&(r+=u/2,u=0),{x:e,y:r,dx:i,dy:u}}function Yi(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Zi(n){return n.rangeExtent?n.rangeExtent():Yi(n.range())}function Vi(n,t,e,r){var i=e(n[0],n[1]),u=r(t[0],t[1]);return function(n){return u(i(n))}}function Xi(n,t){var e,r=0,i=n.length-1,u=n[r],o=n[i];return u>o&&(e=r,r=i,i=e,e=u,u=o,o=e),n[r]=t.floor(u),n[i]=t.ceil(o),n}function $i(n){return n?{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}:Sl}function Bi(n,t,e,r){var i=[],u=[],o=0,a=Math.min(n.length,t.length)-1;for(n[a]2?Bi:Vi,l=r?Wr:Br;return o=i(n,t,l,e),a=i(t,n,l,Mr),u}function u(n){return o(n)}var o,a;return u.invert=function(n){return a(n)},u.domain=function(t){return arguments.length?(n=t.map(Number),i()):n},u.range=function(n){return arguments.length?(t=n,i()):t},u.rangeRound=function(n){return u.range(n).interpolate(Ur)},u.clamp=function(n){return arguments.length?(r=n,i()):r},u.interpolate=function(n){return arguments.length?(e=n,i()):e},u.ticks=function(t){return Qi(n,t)},u.tickFormat=function(t,e){return nu(n,t,e)},u.nice=function(t){return Gi(n,t),i()},u.copy=function(){return Wi(n,t,e,r)},i()}function Ji(n,t){return ao.rebind(n,t,"range","rangeRound","interpolate","clamp")}function Gi(n,t){return Xi(n,$i(Ki(n,t)[2])),Xi(n,$i(Ki(n,t)[2])),n}function Ki(n,t){null==t&&(t=10);var e=Yi(n),r=e[1]-e[0],i=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),u=t/r*i;return.15>=u?i*=10:.35>=u?i*=5:.75>=u&&(i*=2),e[0]=Math.ceil(e[0]/i)*i,e[1]=Math.floor(e[1]/i)*i+.5*i,e[2]=i,e}function Qi(n,t){return ao.range.apply(ao,Ki(n,t))}function nu(n,t,e){var r=Ki(n,t);if(e){var i=ha.exec(e);if(i.shift(),"s"===i[8]){var u=ao.formatPrefix(Math.max(xo(r[0]),xo(r[1])));return i[7]||(i[7]="."+tu(u.scale(r[2]))),i[8]="f",e=ao.format(i.join("")),function(n){return e(u.scale(n))+u.symbol}}i[7]||(i[7]="."+eu(i[8],r)),e=i.join("")}else e=",."+tu(r[2])+"f";return ao.format(e)}function tu(n){return-Math.floor(Math.log(n)/Math.LN10+.01)}function eu(n,t){var e=tu(t[2]);return n in kl?Math.abs(e-tu(Math.max(xo(t[0]),xo(t[1]))))+ +("e"!==n):e-2*("%"===n)}function ru(n,t,e,r){function i(n){return(e?Math.log(0>n?0:n):-Math.log(n>0?0:-n))/Math.log(t)}function u(n){return e?Math.pow(t,n):-Math.pow(t,-n)}function o(t){return n(i(t))}return o.invert=function(t){return u(n.invert(t))},o.domain=function(t){return arguments.length?(e=t[0]>=0,n.domain((r=t.map(Number)).map(i)),o):r},o.base=function(e){return arguments.length?(t=+e,n.domain(r.map(i)),o):t},o.nice=function(){var t=Xi(r.map(i),e?Math:El);return n.domain(t),r=t.map(u),o},o.ticks=function(){var n=Yi(r),o=[],a=n[0],l=n[1],c=Math.floor(i(a)),f=Math.ceil(i(l)),s=t%1?2:t;if(isFinite(f-c)){if(e){for(;f>c;c++)for(var h=1;s>h;h++)o.push(u(c)*h);o.push(u(c))}else for(o.push(u(c));c++0;h--)o.push(u(c)*h);for(c=0;o[c]l;f--);o=o.slice(c,f)}return o},o.tickFormat=function(n,e){if(!arguments.length)return Nl;arguments.length<2?e=Nl:"function"!=typeof e&&(e=ao.format(e));var r=Math.max(1,t*n/o.ticks().length);return function(n){var o=n/u(Math.round(i(n)));return t-.5>o*t&&(o*=t),r>=o?e(n):""}},o.copy=function(){return ru(n.copy(),t,e,r)},Ji(o,n)}function iu(n,t,e){function r(t){return n(i(t))}var i=uu(t),u=uu(1/t);return r.invert=function(t){return u(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(i)),r):e},r.ticks=function(n){return Qi(e,n)},r.tickFormat=function(n,t){return nu(e,n,t)},r.nice=function(n){return r.domain(Gi(e,n))},r.exponent=function(o){return arguments.length?(i=uu(t=o),u=uu(1/t),n.domain(e.map(i)),r):t},r.copy=function(){return iu(n.copy(),t,e)},Ji(r,n)}function uu(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function ou(n,t){function e(e){return u[((i.get(e)||("range"===t.t?i.set(e,n.push(e)):NaN))-1)%u.length]}function r(t,e){return ao.range(n.length).map(function(n){return t+e*n})}var i,u,o;return e.domain=function(r){if(!arguments.length)return n;n=[],i=new c;for(var u,o=-1,a=r.length;++oe?[NaN,NaN]:[e>0?a[e-1]:n[0],et?NaN:t/u+n,[t,t+1/u]},r.copy=function(){return lu(n,t,e)},i()}function cu(n,t){function e(e){return e>=e?t[ao.bisect(n,e)]:void 0}return e.domain=function(t){return arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.invertExtent=function(e){return e=t.indexOf(e),[n[e-1],n[e]]},e.copy=function(){return cu(n,t)},e}function fu(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return Qi(n,t)},t.tickFormat=function(t,e){return nu(n,t,e)},t.copy=function(){return fu(n)},t}function su(){return 0}function hu(n){return n.innerRadius}function pu(n){return n.outerRadius}function gu(n){return n.startAngle}function vu(n){return n.endAngle}function du(n){return n&&n.padAngle}function yu(n,t,e,r){return(n-e)*t-(t-r)*n>0?0:1}function mu(n,t,e,r,i){var u=n[0]-t[0],o=n[1]-t[1],a=(i?r:-r)/Math.sqrt(u*u+o*o),l=a*o,c=-a*u,f=n[0]+l,s=n[1]+c,h=t[0]+l,p=t[1]+c,g=(f+h)/2,v=(s+p)/2,d=h-f,y=p-s,m=d*d+y*y,M=e-r,x=f*p-h*s,b=(0>y?-1:1)*Math.sqrt(Math.max(0,M*M*m-x*x)),_=(x*y-d*b)/m,w=(-x*d-y*b)/m,S=(x*y+d*b)/m,k=(-x*d+y*b)/m,N=_-g,E=w-v,A=S-g,C=k-v;return N*N+E*E>A*A+C*C&&(_=S,w=k),[[_-l,w-c],[_*e/M,w*e/M]]}function Mu(n){function t(t){function o(){c.push("M",u(n(f),a))}for(var l,c=[],f=[],s=-1,h=t.length,p=En(e),g=En(r);++s1?n.join("L"):n+"Z"}function bu(n){return n.join("L")+"Z"}function _u(n){for(var t=0,e=n.length,r=n[0],i=[r[0],",",r[1]];++t1&&i.push("H",r[0]),i.join("")}function wu(n){for(var t=0,e=n.length,r=n[0],i=[r[0],",",r[1]];++t1){a=t[1],u=n[l],l++,r+="C"+(i[0]+o[0])+","+(i[1]+o[1])+","+(u[0]-a[0])+","+(u[1]-a[1])+","+u[0]+","+u[1];for(var c=2;c9&&(i=3*t/Math.sqrt(i),o[a]=i*e,o[a+1]=i*r));for(a=-1;++a<=l;)i=(n[Math.min(l,a+1)][0]-n[Math.max(0,a-1)][0])/(6*(1+o[a]*o[a])),u.push([i||0,o[a]*i||0]);return u}function Fu(n){return n.length<3?xu(n):n[0]+Au(n,ju(n))}function Hu(n){for(var t,e,r,i=-1,u=n.length;++i=t?o(n-t):void(f.c=o)}function o(e){var i=g.active,u=g[i];u&&(u.timer.c=null,u.timer.t=NaN,--g.count,delete g[i],u.event&&u.event.interrupt.call(n,n.__data__,u.index));for(var o in g)if(r>+o){var c=g[o];c.timer.c=null,c.timer.t=NaN,--g.count,delete g[o]}f.c=a,qn(function(){return f.c&&a(e||1)&&(f.c=null,f.t=NaN),1},0,l),g.active=r,v.event&&v.event.start.call(n,n.__data__,t),p=[],v.tween.forEach(function(e,r){(r=r.call(n,n.__data__,t))&&p.push(r)}),h=v.ease,s=v.duration}function a(i){for(var u=i/s,o=h(u),a=p.length;a>0;)p[--a].call(n,o);return u>=1?(v.event&&v.event.end.call(n,n.__data__,t),--g.count?delete g[r]:delete n[e],1):void 0}var l,f,s,h,p,g=n[e]||(n[e]={active:0,count:0}),v=g[r];v||(l=i.time,f=qn(u,0,l),v=g[r]={tween:new c,time:l,timer:f,delay:i.delay,duration:i.duration,ease:i.ease,index:t},i=null,++g.count)}function no(n,t,e){n.attr("transform",function(n){var r=t(n);return"translate("+(isFinite(r)?r:e(n))+",0)"})}function to(n,t,e){n.attr("transform",function(n){var r=t(n);return"translate(0,"+(isFinite(r)?r:e(n))+")"})}function eo(n){return n.toISOString()}function ro(n,t,e){function r(t){return n(t)}function i(n,e){var r=n[1]-n[0],i=r/e,u=ao.bisect(Kl,i);return u==Kl.length?[t.year,Ki(n.map(function(n){return n/31536e6}),e)[2]]:u?t[i/Kl[u-1]1?{floor:function(t){for(;e(t=n.floor(t));)t=io(t-1);return t},ceil:function(t){for(;e(t=n.ceil(t));)t=io(+t+1);return t}}:n))},r.ticks=function(n,t){var e=Yi(r.domain()),u=null==n?i(e,10):"number"==typeof n?i(e,n):!n.range&&[{range:n},t];return u&&(n=u[0],t=u[1]),n.range(e[0],io(+e[1]+1),1>t?1:t)},r.tickFormat=function(){return e},r.copy=function(){return ro(n.copy(),t,e)},Ji(r,n)}function io(n){return new Date(n)}function uo(n){return JSON.parse(n.responseText)}function oo(n){var t=fo.createRange();return t.selectNode(fo.body),t.createContextualFragment(n.responseText)}var ao={version:"3.5.17"},lo=[].slice,co=function(n){return lo.call(n)},fo=this.document;if(fo)try{co(fo.documentElement.childNodes)[0].nodeType}catch(so){co=function(n){for(var t=n.length,e=new Array(t);t--;)e[t]=n[t];return e}}if(Date.now||(Date.now=function(){return+new Date}),fo)try{fo.createElement("DIV").style.setProperty("opacity",0,"")}catch(ho){var po=this.Element.prototype,go=po.setAttribute,vo=po.setAttributeNS,yo=this.CSSStyleDeclaration.prototype,mo=yo.setProperty;po.setAttribute=function(n,t){go.call(this,n,t+"")},po.setAttributeNS=function(n,t,e){vo.call(this,n,t,e+"")},yo.setProperty=function(n,t,e){mo.call(this,n,t+"",e)}}ao.ascending=e,ao.descending=function(n,t){return n>t?-1:t>n?1:t>=n?0:NaN},ao.min=function(n,t){var e,r,i=-1,u=n.length;if(1===arguments.length){for(;++i=r){e=r;break}for(;++ir&&(e=r)}else{for(;++i=r){e=r;break}for(;++ir&&(e=r)}return e},ao.max=function(n,t){var e,r,i=-1,u=n.length;if(1===arguments.length){for(;++i=r){e=r;break}for(;++ie&&(e=r)}else{for(;++i=r){e=r;break}for(;++ie&&(e=r)}return e},ao.extent=function(n,t){var e,r,i,u=-1,o=n.length;if(1===arguments.length){for(;++u=r){e=i=r;break}for(;++ur&&(e=r),r>i&&(i=r))}else{for(;++u=r){e=i=r;break}for(;++ur&&(e=r),r>i&&(i=r))}return[e,i]},ao.sum=function(n,t){var e,r=0,u=n.length,o=-1;if(1===arguments.length)for(;++o1?l/(f-1):void 0},ao.deviation=function(){var n=ao.variance.apply(this,arguments);return n?Math.sqrt(n):n};var Mo=u(e);ao.bisectLeft=Mo.left,ao.bisect=ao.bisectRight=Mo.right,ao.bisector=function(n){return u(1===n.length?function(t,r){return e(n(t),r)}:n)},ao.shuffle=function(n,t,e){(u=arguments.length)<3&&(e=n.length,2>u&&(t=0));for(var r,i,u=e-t;u;)i=Math.random()*u--|0,r=n[u+t],n[u+t]=n[i+t],n[i+t]=r;return n},ao.permute=function(n,t){for(var e=t.length,r=new Array(e);e--;)r[e]=n[t[e]];return r},ao.pairs=function(n){for(var t,e=0,r=n.length-1,i=n[0],u=new Array(0>r?0:r);r>e;)u[e]=[t=i,i=n[++e]];return u},ao.transpose=function(n){if(!(i=n.length))return[];for(var t=-1,e=ao.min(n,o),r=new Array(e);++t=0;)for(r=n[i],t=r.length;--t>=0;)e[--o]=r[t];return e};var xo=Math.abs;ao.range=function(n,t,e){if(arguments.length<3&&(e=1,arguments.length<2&&(t=n,n=0)),(t-n)/e===1/0)throw new Error("infinite range");var r,i=[],u=a(xo(e)),o=-1;if(n*=u,t*=u,e*=u,0>e)for(;(r=n+e*++o)>t;)i.push(r/u);else for(;(r=n+e*++o)=u.length)return r?r.call(i,o):e?o.sort(e):o;for(var l,f,s,h,p=-1,g=o.length,v=u[a++],d=new c;++p=u.length)return n;var r=[],i=o[e++];return n.forEach(function(n,i){r.push({key:n,values:t(i,e)})}),i?r.sort(function(n,t){return i(n.key,t.key)}):r}var e,r,i={},u=[],o=[];return i.map=function(t,e){return n(e,t,0)},i.entries=function(e){return t(n(ao.map,e,0),0)},i.key=function(n){return u.push(n),i},i.sortKeys=function(n){return o[u.length-1]=n,i},i.sortValues=function(n){return e=n,i},i.rollup=function(n){return r=n,i},i},ao.set=function(n){var t=new y;if(n)for(var e=0,r=n.length;r>e;++e)t.add(n[e]);return t},l(y,{has:h,add:function(n){return this._[f(n+="")]=!0,n},remove:p,values:g,size:v,empty:d,forEach:function(n){for(var t in this._)n.call(this,s(t))}}),ao.behavior={},ao.rebind=function(n,t){for(var e,r=1,i=arguments.length;++r=0&&(r=n.slice(e+1),n=n.slice(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},ao.event=null,ao.requote=function(n){return n.replace(So,"\\$&")};var So=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,ko={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},No=function(n,t){return t.querySelector(n)},Eo=function(n,t){return t.querySelectorAll(n)},Ao=function(n,t){var e=n.matches||n[x(n,"matchesSelector")];return(Ao=function(n,t){return e.call(n,t)})(n,t)};"function"==typeof Sizzle&&(No=function(n,t){return Sizzle(n,t)[0]||null},Eo=Sizzle,Ao=Sizzle.matchesSelector),ao.selection=function(){return ao.select(fo.documentElement)};var Co=ao.selection.prototype=[];Co.select=function(n){var t,e,r,i,u=[];n=A(n);for(var o=-1,a=this.length;++o=0&&"xmlns"!==(e=n.slice(0,t))&&(n=n.slice(t+1)),Lo.hasOwnProperty(e)?{space:Lo[e],local:n}:n}},Co.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node();return n=ao.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(z(t,n[t]));return this}return this.each(z(n,t))},Co.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node(),r=(n=T(n)).length,i=-1;if(t=e.classList){for(;++ii){if("string"!=typeof n){2>i&&(e="");for(r in n)this.each(P(r,n[r],e));return this}if(2>i){var u=this.node();return t(u).getComputedStyle(u,null).getPropertyValue(n)}r=""}return this.each(P(n,e,r))},Co.property=function(n,t){if(arguments.length<2){if("string"==typeof n)return this.node()[n];for(t in n)this.each(U(t,n[t]));return this}return this.each(U(n,t))},Co.text=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?"":t}:null==n?function(){this.textContent=""}:function(){this.textContent=n}):this.node().textContent},Co.html=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?"":t}:null==n?function(){this.innerHTML=""}:function(){this.innerHTML=n}):this.node().innerHTML},Co.append=function(n){return n=j(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},Co.insert=function(n,t){return n=j(n),t=A(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments)||null)})},Co.remove=function(){return this.each(F)},Co.data=function(n,t){function e(n,e){var r,i,u,o=n.length,s=e.length,h=Math.min(o,s),p=new Array(s),g=new Array(s),v=new Array(o);if(t){var d,y=new c,m=new Array(o);for(r=-1;++rr;++r)g[r]=H(e[r]);for(;o>r;++r)v[r]=n[r]}g.update=p,g.parentNode=p.parentNode=v.parentNode=n.parentNode,a.push(g),l.push(p),f.push(v)}var r,i,u=-1,o=this.length;if(!arguments.length){for(n=new Array(o=(r=this[0]).length);++uu;u++){i.push(t=[]),t.parentNode=(e=this[u]).parentNode;for(var a=0,l=e.length;l>a;a++)(r=e[a])&&n.call(r,r.__data__,a,u)&&t.push(r)}return E(i)},Co.order=function(){for(var n=-1,t=this.length;++n=0;)(e=r[i])&&(u&&u!==e.nextSibling&&u.parentNode.insertBefore(e,u),u=e);return this},Co.sort=function(n){n=I.apply(this,arguments);for(var t=-1,e=this.length;++tn;n++)for(var e=this[n],r=0,i=e.length;i>r;r++){var u=e[r];if(u)return u}return null},Co.size=function(){var n=0;return Y(this,function(){++n}),n};var qo=[];ao.selection.enter=Z,ao.selection.enter.prototype=qo,qo.append=Co.append,qo.empty=Co.empty,qo.node=Co.node,qo.call=Co.call,qo.size=Co.size,qo.select=function(n){for(var t,e,r,i,u,o=[],a=-1,l=this.length;++ar){if("string"!=typeof n){2>r&&(t=!1);for(e in n)this.each(X(e,n[e],t));return this}if(2>r)return(r=this.node()["__on"+n])&&r._;e=!1}return this.each(X(n,t,e))};var To=ao.map({mouseenter:"mouseover",mouseleave:"mouseout"});fo&&To.forEach(function(n){"on"+n in fo&&To.remove(n)});var Ro,Do=0;ao.mouse=function(n){return J(n,k())};var Po=this.navigator&&/WebKit/.test(this.navigator.userAgent)?-1:0;ao.touch=function(n,t,e){if(arguments.length<3&&(e=t,t=k().changedTouches),t)for(var r,i=0,u=t.length;u>i;++i)if((r=t[i]).identifier===e)return J(n,r)},ao.behavior.drag=function(){function n(){this.on("mousedown.drag",u).on("touchstart.drag",o)}function e(n,t,e,u,o){return function(){function a(){var n,e,r=t(h,v);r&&(n=r[0]-M[0],e=r[1]-M[1],g|=n|e,M=r,p({type:"drag",x:r[0]+c[0],y:r[1]+c[1],dx:n,dy:e}))}function l(){t(h,v)&&(y.on(u+d,null).on(o+d,null),m(g),p({type:"dragend"}))}var c,f=this,s=ao.event.target.correspondingElement||ao.event.target,h=f.parentNode,p=r.of(f,arguments),g=0,v=n(),d=".drag"+(null==v?"":"-"+v),y=ao.select(e(s)).on(u+d,a).on(o+d,l),m=W(s),M=t(h,v);i?(c=i.apply(f,arguments),c=[c.x-M[0],c.y-M[1]]):c=[0,0],p({type:"dragstart"})}}var r=N(n,"drag","dragstart","dragend"),i=null,u=e(b,ao.mouse,t,"mousemove","mouseup"),o=e(G,ao.touch,m,"touchmove","touchend");return n.origin=function(t){return arguments.length?(i=t,n):i},ao.rebind(n,r,"on")},ao.touches=function(n,t){return arguments.length<2&&(t=k().touches),t?co(t).map(function(t){var e=J(n,t);return e.identifier=t.identifier,e}):[]};var Uo=1e-6,jo=Uo*Uo,Fo=Math.PI,Ho=2*Fo,Oo=Ho-Uo,Io=Fo/2,Yo=Fo/180,Zo=180/Fo,Vo=Math.SQRT2,Xo=2,$o=4;ao.interpolateZoom=function(n,t){var e,r,i=n[0],u=n[1],o=n[2],a=t[0],l=t[1],c=t[2],f=a-i,s=l-u,h=f*f+s*s;if(jo>h)r=Math.log(c/o)/Vo,e=function(n){return[i+n*f,u+n*s,o*Math.exp(Vo*n*r)]};else{var p=Math.sqrt(h),g=(c*c-o*o+$o*h)/(2*o*Xo*p),v=(c*c-o*o-$o*h)/(2*c*Xo*p),d=Math.log(Math.sqrt(g*g+1)-g),y=Math.log(Math.sqrt(v*v+1)-v);r=(y-d)/Vo,e=function(n){var t=n*r,e=rn(d),a=o/(Xo*p)*(e*un(Vo*t+d)-en(d));return[i+a*f,u+a*s,o*e/rn(Vo*t+d)]}}return e.duration=1e3*r,e},ao.behavior.zoom=function(){function n(n){n.on(L,s).on(Wo+".zoom",p).on("dblclick.zoom",g).on(R,h)}function e(n){return[(n[0]-k.x)/k.k,(n[1]-k.y)/k.k]}function r(n){return[n[0]*k.k+k.x,n[1]*k.k+k.y]}function i(n){k.k=Math.max(A[0],Math.min(A[1],n))}function u(n,t){t=r(t),k.x+=n[0]-t[0],k.y+=n[1]-t[1]}function o(t,e,r,o){t.__chart__={x:k.x,y:k.y,k:k.k},i(Math.pow(2,o)),u(d=e,r),t=ao.select(t),C>0&&(t=t.transition().duration(C)),t.call(n.event)}function a(){b&&b.domain(x.range().map(function(n){return(n-k.x)/k.k}).map(x.invert)),w&&w.domain(_.range().map(function(n){return(n-k.y)/k.k}).map(_.invert))}function l(n){z++||n({type:"zoomstart"})}function c(n){a(),n({type:"zoom",scale:k.k,translate:[k.x,k.y]})}function f(n){--z||(n({type:"zoomend"}),d=null)}function s(){function n(){a=1,u(ao.mouse(i),h),c(o)}function r(){s.on(q,null).on(T,null),p(a),f(o)}var i=this,o=D.of(i,arguments),a=0,s=ao.select(t(i)).on(q,n).on(T,r),h=e(ao.mouse(i)),p=W(i);Il.call(i),l(o)}function h(){function n(){var n=ao.touches(g);return p=k.k,n.forEach(function(n){n.identifier in d&&(d[n.identifier]=e(n))}),n}function t(){var t=ao.event.target;ao.select(t).on(x,r).on(b,a),_.push(t);for(var e=ao.event.changedTouches,i=0,u=e.length;u>i;++i)d[e[i].identifier]=null;var l=n(),c=Date.now();if(1===l.length){if(500>c-M){var f=l[0];o(g,f,d[f.identifier],Math.floor(Math.log(k.k)/Math.LN2)+1),S()}M=c}else if(l.length>1){var f=l[0],s=l[1],h=f[0]-s[0],p=f[1]-s[1];y=h*h+p*p}}function r(){var n,t,e,r,o=ao.touches(g);Il.call(g);for(var a=0,l=o.length;l>a;++a,r=null)if(e=o[a],r=d[e.identifier]){if(t)break;n=e,t=r}if(r){var f=(f=e[0]-n[0])*f+(f=e[1]-n[1])*f,s=y&&Math.sqrt(f/y);n=[(n[0]+e[0])/2,(n[1]+e[1])/2],t=[(t[0]+r[0])/2,(t[1]+r[1])/2],i(s*p)}M=null,u(n,t),c(v)}function a(){if(ao.event.touches.length){for(var t=ao.event.changedTouches,e=0,r=t.length;r>e;++e)delete d[t[e].identifier];for(var i in d)return void n()}ao.selectAll(_).on(m,null),w.on(L,s).on(R,h),N(),f(v)}var p,g=this,v=D.of(g,arguments),d={},y=0,m=".zoom-"+ao.event.changedTouches[0].identifier,x="touchmove"+m,b="touchend"+m,_=[],w=ao.select(g),N=W(g);t(),l(v),w.on(L,null).on(R,t)}function p(){var n=D.of(this,arguments);m?clearTimeout(m):(Il.call(this),v=e(d=y||ao.mouse(this)),l(n)),m=setTimeout(function(){m=null,f(n)},50),S(),i(Math.pow(2,.002*Bo())*k.k),u(d,v),c(n)}function g(){var n=ao.mouse(this),t=Math.log(k.k)/Math.LN2;o(this,n,e(n),ao.event.shiftKey?Math.ceil(t)-1:Math.floor(t)+1)}var v,d,y,m,M,x,b,_,w,k={x:0,y:0,k:1},E=[960,500],A=Jo,C=250,z=0,L="mousedown.zoom",q="mousemove.zoom",T="mouseup.zoom",R="touchstart.zoom",D=N(n,"zoomstart","zoom","zoomend");return Wo||(Wo="onwheel"in fo?(Bo=function(){return-ao.event.deltaY*(ao.event.deltaMode?120:1)},"wheel"):"onmousewheel"in fo?(Bo=function(){return ao.event.wheelDelta},"mousewheel"):(Bo=function(){return-ao.event.detail},"MozMousePixelScroll")),n.event=function(n){n.each(function(){var n=D.of(this,arguments),t=k;Hl?ao.select(this).transition().each("start.zoom",function(){k=this.__chart__||{x:0,y:0,k:1},l(n)}).tween("zoom:zoom",function(){var e=E[0],r=E[1],i=d?d[0]:e/2,u=d?d[1]:r/2,o=ao.interpolateZoom([(i-k.x)/k.k,(u-k.y)/k.k,e/k.k],[(i-t.x)/t.k,(u-t.y)/t.k,e/t.k]);return function(t){var r=o(t),a=e/r[2];this.__chart__=k={x:i-r[0]*a,y:u-r[1]*a,k:a},c(n)}}).each("interrupt.zoom",function(){f(n)}).each("end.zoom",function(){f(n)}):(this.__chart__=k,l(n),c(n),f(n))})},n.translate=function(t){return arguments.length?(k={x:+t[0],y:+t[1],k:k.k},a(),n):[k.x,k.y]},n.scale=function(t){return arguments.length?(k={x:k.x,y:k.y,k:null},i(+t),a(),n):k.k},n.scaleExtent=function(t){return arguments.length?(A=null==t?Jo:[+t[0],+t[1]],n):A},n.center=function(t){return arguments.length?(y=t&&[+t[0],+t[1]],n):y},n.size=function(t){return arguments.length?(E=t&&[+t[0],+t[1]],n):E},n.duration=function(t){return arguments.length?(C=+t,n):C},n.x=function(t){return arguments.length?(b=t,x=t.copy(),k={x:0,y:0,k:1},n):b},n.y=function(t){return arguments.length?(w=t,_=t.copy(),k={x:0,y:0,k:1},n):w},ao.rebind(n,D,"on")};var Bo,Wo,Jo=[0,1/0];ao.color=an,an.prototype.toString=function(){return this.rgb()+""},ao.hsl=ln;var Go=ln.prototype=new an;Go.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),new ln(this.h,this.s,this.l/n)},Go.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new ln(this.h,this.s,n*this.l)},Go.rgb=function(){return cn(this.h,this.s,this.l)},ao.hcl=fn;var Ko=fn.prototype=new an;Ko.brighter=function(n){return new fn(this.h,this.c,Math.min(100,this.l+Qo*(arguments.length?n:1)))},Ko.darker=function(n){return new fn(this.h,this.c,Math.max(0,this.l-Qo*(arguments.length?n:1)))},Ko.rgb=function(){return sn(this.h,this.c,this.l).rgb()},ao.lab=hn;var Qo=18,na=.95047,ta=1,ea=1.08883,ra=hn.prototype=new an;ra.brighter=function(n){return new hn(Math.min(100,this.l+Qo*(arguments.length?n:1)),this.a,this.b)},ra.darker=function(n){return new hn(Math.max(0,this.l-Qo*(arguments.length?n:1)),this.a,this.b)},ra.rgb=function(){return pn(this.l,this.a,this.b)},ao.rgb=mn;var ia=mn.prototype=new an;ia.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,i=30;return t||e||r?(t&&i>t&&(t=i),e&&i>e&&(e=i),r&&i>r&&(r=i),new mn(Math.min(255,t/n),Math.min(255,e/n),Math.min(255,r/n))):new mn(i,i,i)},ia.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new mn(n*this.r,n*this.g,n*this.b)},ia.hsl=function(){return wn(this.r,this.g,this.b)},ia.toString=function(){return"#"+bn(this.r)+bn(this.g)+bn(this.b)};var ua=ao.map({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074});ua.forEach(function(n,t){ua.set(n,Mn(t))}),ao.functor=En,ao.xhr=An(m),ao.dsv=function(n,t){function e(n,e,u){arguments.length<3&&(u=e,e=null);var o=Cn(n,t,null==e?r:i(e),u);return o.row=function(n){return arguments.length?o.response(null==(e=n)?r:i(n)):e},o}function r(n){return e.parse(n.responseText)}function i(n){return function(t){return e.parse(t.responseText,n)}}function u(t){return t.map(o).join(n)}function o(n){return a.test(n)?'"'+n.replace(/\"/g,'""')+'"':n}var a=new RegExp('["'+n+"\n]"),l=n.charCodeAt(0);return e.parse=function(n,t){var r;return e.parseRows(n,function(n,e){if(r)return r(n,e-1);var i=new Function("d","return {"+n.map(function(n,t){return JSON.stringify(n)+": d["+t+"]"}).join(",")+"}");r=t?function(n,e){return t(i(n),e)}:i})},e.parseRows=function(n,t){function e(){if(f>=c)return o;if(i)return i=!1,u;var t=f;if(34===n.charCodeAt(t)){for(var e=t;e++f;){var r=n.charCodeAt(f++),a=1;if(10===r)i=!0;else if(13===r)i=!0,10===n.charCodeAt(f)&&(++f,++a);else if(r!==l)continue;return n.slice(t,f-a)}return n.slice(t)}for(var r,i,u={},o={},a=[],c=n.length,f=0,s=0;(r=e())!==o;){for(var h=[];r!==u&&r!==o;)h.push(r),r=e();t&&null==(h=t(h,s++))||a.push(h)}return a},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new y,i=[];return t.forEach(function(n){for(var t in n)r.has(t)||i.push(r.add(t))}),[i.map(o).join(n)].concat(t.map(function(t){return i.map(function(n){return o(t[n])}).join(n)})).join("\n")},e.formatRows=function(n){return n.map(u).join("\n")},e},ao.csv=ao.dsv(",","text/csv"),ao.tsv=ao.dsv(" ","text/tab-separated-values");var oa,aa,la,ca,fa=this[x(this,"requestAnimationFrame")]||function(n){setTimeout(n,17)};ao.timer=function(){qn.apply(this,arguments)},ao.timer.flush=function(){Rn(),Dn()},ao.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)};var sa=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"].map(Un);ao.formatPrefix=function(n,t){var e=0;return(n=+n)&&(0>n&&(n*=-1),t&&(n=ao.round(n,Pn(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((e-1)/3)))),sa[8+e/3]};var ha=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,pa=ao.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=ao.round(n,Pn(n,t))).toFixed(Math.max(0,Math.min(20,Pn(n*(1+1e-15),t))))}}),ga=ao.time={},va=Date;Hn.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){da.setUTCDate.apply(this._,arguments)},setDay:function(){da.setUTCDay.apply(this._,arguments)},setFullYear:function(){da.setUTCFullYear.apply(this._,arguments)},setHours:function(){da.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){da.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){da.setUTCMinutes.apply(this._,arguments)},setMonth:function(){da.setUTCMonth.apply(this._,arguments)},setSeconds:function(){da.setUTCSeconds.apply(this._,arguments)},setTime:function(){da.setTime.apply(this._,arguments)}};var da=Date.prototype;ga.year=On(function(n){return n=ga.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),ga.years=ga.year.range,ga.years.utc=ga.year.utc.range,ga.day=On(function(n){var t=new va(2e3,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),ga.days=ga.day.range,ga.days.utc=ga.day.utc.range,ga.dayOfYear=function(n){var t=ga.year(n);return Math.floor((n-t-6e4*(n.getTimezoneOffset()-t.getTimezoneOffset()))/864e5)},["sunday","monday","tuesday","wednesday","thursday","friday","saturday"].forEach(function(n,t){t=7-t;var e=ga[n]=On(function(n){return(n=ga.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+7*Math.floor(t))},function(n){var e=ga.year(n).getDay();return Math.floor((ga.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});ga[n+"s"]=e.range,ga[n+"s"].utc=e.utc.range,ga[n+"OfYear"]=function(n){var e=ga.year(n).getDay();return Math.floor((ga.dayOfYear(n)+(e+t)%7)/7)}}),ga.week=ga.sunday,ga.weeks=ga.sunday.range,ga.weeks.utc=ga.sunday.utc.range,ga.weekOfYear=ga.sundayOfYear;var ya={"-":"",_:" ",0:"0"},ma=/^\s*\d+/,Ma=/^%/;ao.locale=function(n){return{numberFormat:jn(n),timeFormat:Yn(n)}};var xa=ao.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],dateTime:"%a %b %e %X %Y",date:"%m/%d/%Y",time:"%H:%M:%S",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"], -shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});ao.format=xa.numberFormat,ao.geo={},ft.prototype={s:0,t:0,add:function(n){st(n,this.t,ba),st(ba.s,this.s,this),this.s?this.t+=ba.t:this.s=ba.t},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var ba=new ft;ao.geo.stream=function(n,t){n&&_a.hasOwnProperty(n.type)?_a[n.type](n,t):ht(n,t)};var _a={Feature:function(n,t){ht(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,i=e.length;++rn?4*Fo+n:n,Na.lineStart=Na.lineEnd=Na.point=b}};ao.geo.bounds=function(){function n(n,t){M.push(x=[f=n,h=n]),s>t&&(s=t),t>p&&(p=t)}function t(t,e){var r=dt([t*Yo,e*Yo]);if(y){var i=mt(y,r),u=[i[1],-i[0],0],o=mt(u,i);bt(o),o=_t(o);var l=t-g,c=l>0?1:-1,v=o[0]*Zo*c,d=xo(l)>180;if(d^(v>c*g&&c*t>v)){var m=o[1]*Zo;m>p&&(p=m)}else if(v=(v+360)%360-180,d^(v>c*g&&c*t>v)){var m=-o[1]*Zo;s>m&&(s=m)}else s>e&&(s=e),e>p&&(p=e);d?g>t?a(f,t)>a(f,h)&&(h=t):a(t,h)>a(f,h)&&(f=t):h>=f?(f>t&&(f=t),t>h&&(h=t)):t>g?a(f,t)>a(f,h)&&(h=t):a(t,h)>a(f,h)&&(f=t)}else n(t,e);y=r,g=t}function e(){b.point=t}function r(){x[0]=f,x[1]=h,b.point=n,y=null}function i(n,e){if(y){var r=n-g;m+=xo(r)>180?r+(r>0?360:-360):r}else v=n,d=e;Na.point(n,e),t(n,e)}function u(){Na.lineStart()}function o(){i(v,d),Na.lineEnd(),xo(m)>Uo&&(f=-(h=180)),x[0]=f,x[1]=h,y=null}function a(n,t){return(t-=n)<0?t+360:t}function l(n,t){return n[0]-t[0]}function c(n,t){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:nka?(f=-(h=180),s=-(p=90)):m>Uo?p=90:-Uo>m&&(s=-90),x[0]=f,x[1]=h}};return function(n){p=h=-(f=s=1/0),M=[],ao.geo.stream(n,b);var t=M.length;if(t){M.sort(l);for(var e,r=1,i=M[0],u=[i];t>r;++r)e=M[r],c(e[0],i)||c(e[1],i)?(a(i[0],e[1])>a(i[0],i[1])&&(i[1]=e[1]),a(e[0],i[1])>a(i[0],i[1])&&(i[0]=e[0])):u.push(i=e);for(var o,e,g=-(1/0),t=u.length-1,r=0,i=u[t];t>=r;i=e,++r)e=u[r],(o=a(i[1],e[0]))>g&&(g=o,f=e[0],h=i[1])}return M=x=null,f===1/0||s===1/0?[[NaN,NaN],[NaN,NaN]]:[[f,s],[h,p]]}}(),ao.geo.centroid=function(n){Ea=Aa=Ca=za=La=qa=Ta=Ra=Da=Pa=Ua=0,ao.geo.stream(n,ja);var t=Da,e=Pa,r=Ua,i=t*t+e*e+r*r;return jo>i&&(t=qa,e=Ta,r=Ra,Uo>Aa&&(t=Ca,e=za,r=La),i=t*t+e*e+r*r,jo>i)?[NaN,NaN]:[Math.atan2(e,t)*Zo,tn(r/Math.sqrt(i))*Zo]};var Ea,Aa,Ca,za,La,qa,Ta,Ra,Da,Pa,Ua,ja={sphere:b,point:St,lineStart:Nt,lineEnd:Et,polygonStart:function(){ja.lineStart=At},polygonEnd:function(){ja.lineStart=Nt}},Fa=Rt(zt,jt,Ht,[-Fo,-Fo/2]),Ha=1e9;ao.geo.clipExtent=function(){var n,t,e,r,i,u,o={stream:function(n){return i&&(i.valid=!1),i=u(n),i.valid=!0,i},extent:function(a){return arguments.length?(u=Zt(n=+a[0][0],t=+a[0][1],e=+a[1][0],r=+a[1][1]),i&&(i.valid=!1,i=null),o):[[n,t],[e,r]]}};return o.extent([[0,0],[960,500]])},(ao.geo.conicEqualArea=function(){return Vt(Xt)}).raw=Xt,ao.geo.albers=function(){return ao.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},ao.geo.albersUsa=function(){function n(n){var u=n[0],o=n[1];return t=null,e(u,o),t||(r(u,o),t)||i(u,o),t}var t,e,r,i,u=ao.geo.albers(),o=ao.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),a=ao.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),l={point:function(n,e){t=[n,e]}};return n.invert=function(n){var t=u.scale(),e=u.translate(),r=(n[0]-e[0])/t,i=(n[1]-e[1])/t;return(i>=.12&&.234>i&&r>=-.425&&-.214>r?o:i>=.166&&.234>i&&r>=-.214&&-.115>r?a:u).invert(n)},n.stream=function(n){var t=u.stream(n),e=o.stream(n),r=a.stream(n);return{point:function(n,i){t.point(n,i),e.point(n,i),r.point(n,i)},sphere:function(){t.sphere(),e.sphere(),r.sphere()},lineStart:function(){t.lineStart(),e.lineStart(),r.lineStart()},lineEnd:function(){t.lineEnd(),e.lineEnd(),r.lineEnd()},polygonStart:function(){t.polygonStart(),e.polygonStart(),r.polygonStart()},polygonEnd:function(){t.polygonEnd(),e.polygonEnd(),r.polygonEnd()}}},n.precision=function(t){return arguments.length?(u.precision(t),o.precision(t),a.precision(t),n):u.precision()},n.scale=function(t){return arguments.length?(u.scale(t),o.scale(.35*t),a.scale(t),n.translate(u.translate())):u.scale()},n.translate=function(t){if(!arguments.length)return u.translate();var c=u.scale(),f=+t[0],s=+t[1];return e=u.translate(t).clipExtent([[f-.455*c,s-.238*c],[f+.455*c,s+.238*c]]).stream(l).point,r=o.translate([f-.307*c,s+.201*c]).clipExtent([[f-.425*c+Uo,s+.12*c+Uo],[f-.214*c-Uo,s+.234*c-Uo]]).stream(l).point,i=a.translate([f-.205*c,s+.212*c]).clipExtent([[f-.214*c+Uo,s+.166*c+Uo],[f-.115*c-Uo,s+.234*c-Uo]]).stream(l).point,n},n.scale(1070)};var Oa,Ia,Ya,Za,Va,Xa,$a={point:b,lineStart:b,lineEnd:b,polygonStart:function(){Ia=0,$a.lineStart=$t},polygonEnd:function(){$a.lineStart=$a.lineEnd=$a.point=b,Oa+=xo(Ia/2)}},Ba={point:Bt,lineStart:b,lineEnd:b,polygonStart:b,polygonEnd:b},Wa={point:Gt,lineStart:Kt,lineEnd:Qt,polygonStart:function(){Wa.lineStart=ne},polygonEnd:function(){Wa.point=Gt,Wa.lineStart=Kt,Wa.lineEnd=Qt}};ao.geo.path=function(){function n(n){return n&&("function"==typeof a&&u.pointRadius(+a.apply(this,arguments)),o&&o.valid||(o=i(u)),ao.geo.stream(n,o)),u.result()}function t(){return o=null,n}var e,r,i,u,o,a=4.5;return n.area=function(n){return Oa=0,ao.geo.stream(n,i($a)),Oa},n.centroid=function(n){return Ca=za=La=qa=Ta=Ra=Da=Pa=Ua=0,ao.geo.stream(n,i(Wa)),Ua?[Da/Ua,Pa/Ua]:Ra?[qa/Ra,Ta/Ra]:La?[Ca/La,za/La]:[NaN,NaN]},n.bounds=function(n){return Va=Xa=-(Ya=Za=1/0),ao.geo.stream(n,i(Ba)),[[Ya,Za],[Va,Xa]]},n.projection=function(n){return arguments.length?(i=(e=n)?n.stream||re(n):m,t()):e},n.context=function(n){return arguments.length?(u=null==(r=n)?new Wt:new te(n),"function"!=typeof a&&u.pointRadius(a),t()):r},n.pointRadius=function(t){return arguments.length?(a="function"==typeof t?t:(u.pointRadius(+t),+t),n):a},n.projection(ao.geo.albersUsa()).context(null)},ao.geo.transform=function(n){return{stream:function(t){var e=new ie(t);for(var r in n)e[r]=n[r];return e}}},ie.prototype={point:function(n,t){this.stream.point(n,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},ao.geo.projection=oe,ao.geo.projectionMutator=ae,(ao.geo.equirectangular=function(){return oe(ce)}).raw=ce.invert=ce,ao.geo.rotation=function(n){function t(t){return t=n(t[0]*Yo,t[1]*Yo),t[0]*=Zo,t[1]*=Zo,t}return n=se(n[0]%360*Yo,n[1]*Yo,n.length>2?n[2]*Yo:0),t.invert=function(t){return t=n.invert(t[0]*Yo,t[1]*Yo),t[0]*=Zo,t[1]*=Zo,t},t},fe.invert=ce,ao.geo.circle=function(){function n(){var n="function"==typeof r?r.apply(this,arguments):r,t=se(-n[0]*Yo,-n[1]*Yo,0).invert,i=[];return e(null,null,1,{point:function(n,e){i.push(n=t(n,e)),n[0]*=Zo,n[1]*=Zo}}),{type:"Polygon",coordinates:[i]}}var t,e,r=[0,0],i=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=ve((t=+r)*Yo,i*Yo),n):t},n.precision=function(r){return arguments.length?(e=ve(t*Yo,(i=+r)*Yo),n):i},n.angle(90)},ao.geo.distance=function(n,t){var e,r=(t[0]-n[0])*Yo,i=n[1]*Yo,u=t[1]*Yo,o=Math.sin(r),a=Math.cos(r),l=Math.sin(i),c=Math.cos(i),f=Math.sin(u),s=Math.cos(u);return Math.atan2(Math.sqrt((e=s*o)*e+(e=c*f-l*s*a)*e),l*f+c*s*a)},ao.geo.graticule=function(){function n(){return{type:"MultiLineString",coordinates:t()}}function t(){return ao.range(Math.ceil(u/d)*d,i,d).map(h).concat(ao.range(Math.ceil(c/y)*y,l,y).map(p)).concat(ao.range(Math.ceil(r/g)*g,e,g).filter(function(n){return xo(n%d)>Uo}).map(f)).concat(ao.range(Math.ceil(a/v)*v,o,v).filter(function(n){return xo(n%y)>Uo}).map(s))}var e,r,i,u,o,a,l,c,f,s,h,p,g=10,v=g,d=90,y=360,m=2.5;return n.lines=function(){return t().map(function(n){return{type:"LineString",coordinates:n}})},n.outline=function(){return{type:"Polygon",coordinates:[h(u).concat(p(l).slice(1),h(i).reverse().slice(1),p(c).reverse().slice(1))]}},n.extent=function(t){return arguments.length?n.majorExtent(t).minorExtent(t):n.minorExtent()},n.majorExtent=function(t){return arguments.length?(u=+t[0][0],i=+t[1][0],c=+t[0][1],l=+t[1][1],u>i&&(t=u,u=i,i=t),c>l&&(t=c,c=l,l=t),n.precision(m)):[[u,c],[i,l]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],a=+t[0][1],o=+t[1][1],r>e&&(t=r,r=e,e=t),a>o&&(t=a,a=o,o=t),n.precision(m)):[[r,a],[e,o]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(d=+t[0],y=+t[1],n):[d,y]},n.minorStep=function(t){return arguments.length?(g=+t[0],v=+t[1],n):[g,v]},n.precision=function(t){return arguments.length?(m=+t,f=ye(a,o,90),s=me(r,e,m),h=ye(c,l,90),p=me(u,i,m),n):m},n.majorExtent([[-180,-90+Uo],[180,90-Uo]]).minorExtent([[-180,-80-Uo],[180,80+Uo]])},ao.geo.greatArc=function(){function n(){return{type:"LineString",coordinates:[t||r.apply(this,arguments),e||i.apply(this,arguments)]}}var t,e,r=Me,i=xe;return n.distance=function(){return ao.geo.distance(t||r.apply(this,arguments),e||i.apply(this,arguments))},n.source=function(e){return arguments.length?(r=e,t="function"==typeof e?null:e,n):r},n.target=function(t){return arguments.length?(i=t,e="function"==typeof t?null:t,n):i},n.precision=function(){return arguments.length?n:0},n},ao.geo.interpolate=function(n,t){return be(n[0]*Yo,n[1]*Yo,t[0]*Yo,t[1]*Yo)},ao.geo.length=function(n){return Ja=0,ao.geo.stream(n,Ga),Ja};var Ja,Ga={sphere:b,point:b,lineStart:_e,lineEnd:b,polygonStart:b,polygonEnd:b},Ka=we(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(ao.geo.azimuthalEqualArea=function(){return oe(Ka)}).raw=Ka;var Qa=we(function(n){var t=Math.acos(n);return t&&t/Math.sin(t)},m);(ao.geo.azimuthalEquidistant=function(){return oe(Qa)}).raw=Qa,(ao.geo.conicConformal=function(){return Vt(Se)}).raw=Se,(ao.geo.conicEquidistant=function(){return Vt(ke)}).raw=ke;var nl=we(function(n){return 1/n},Math.atan);(ao.geo.gnomonic=function(){return oe(nl)}).raw=nl,Ne.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-Io]},(ao.geo.mercator=function(){return Ee(Ne)}).raw=Ne;var tl=we(function(){return 1},Math.asin);(ao.geo.orthographic=function(){return oe(tl)}).raw=tl;var el=we(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(ao.geo.stereographic=function(){return oe(el)}).raw=el,Ae.invert=function(n,t){return[-t,2*Math.atan(Math.exp(n))-Io]},(ao.geo.transverseMercator=function(){var n=Ee(Ae),t=n.center,e=n.rotate;return n.center=function(n){return n?t([-n[1],n[0]]):(n=t(),[n[1],-n[0]])},n.rotate=function(n){return n?e([n[0],n[1],n.length>2?n[2]+90:90]):(n=e(),[n[0],n[1],n[2]-90])},e([0,0,90])}).raw=Ae,ao.geom={},ao.geom.hull=function(n){function t(n){if(n.length<3)return[];var t,i=En(e),u=En(r),o=n.length,a=[],l=[];for(t=0;o>t;t++)a.push([+i.call(this,n[t],t),+u.call(this,n[t],t),t]);for(a.sort(qe),t=0;o>t;t++)l.push([a[t][0],-a[t][1]]);var c=Le(a),f=Le(l),s=f[0]===c[0],h=f[f.length-1]===c[c.length-1],p=[];for(t=c.length-1;t>=0;--t)p.push(n[a[c[t]][2]]);for(t=+s;t=r&&c.x<=u&&c.y>=i&&c.y<=o?[[r,o],[u,o],[u,i],[r,i]]:[];f.point=n[a]}),t}function e(n){return n.map(function(n,t){return{x:Math.round(u(n,t)/Uo)*Uo,y:Math.round(o(n,t)/Uo)*Uo,i:t}})}var r=Ce,i=ze,u=r,o=i,a=sl;return n?t(n):(t.links=function(n){return ar(e(n)).edges.filter(function(n){return n.l&&n.r}).map(function(t){return{source:n[t.l.i],target:n[t.r.i]}})},t.triangles=function(n){var t=[];return ar(e(n)).cells.forEach(function(e,r){for(var i,u,o=e.site,a=e.edges.sort(Ve),l=-1,c=a.length,f=a[c-1].edge,s=f.l===o?f.r:f.l;++l=c,h=r>=f,p=h<<1|s;n.leaf=!1,n=n.nodes[p]||(n.nodes[p]=hr()),s?i=c:a=c,h?o=f:l=f,u(n,t,e,r,i,o,a,l)}var f,s,h,p,g,v,d,y,m,M=En(a),x=En(l);if(null!=t)v=t,d=e,y=r,m=i;else if(y=m=-(v=d=1/0),s=[],h=[],g=n.length,o)for(p=0;g>p;++p)f=n[p],f.xy&&(y=f.x),f.y>m&&(m=f.y),s.push(f.x),h.push(f.y);else for(p=0;g>p;++p){var b=+M(f=n[p],p),_=+x(f,p);v>b&&(v=b),d>_&&(d=_),b>y&&(y=b),_>m&&(m=_),s.push(b),h.push(_)}var w=y-v,S=m-d;w>S?m=d+w:y=v+S;var k=hr();if(k.add=function(n){u(k,n,+M(n,++p),+x(n,p),v,d,y,m)},k.visit=function(n){pr(n,k,v,d,y,m)},k.find=function(n){return gr(k,n[0],n[1],v,d,y,m)},p=-1,null==t){for(;++p=0?n.slice(0,t):n,r=t>=0?n.slice(t+1):"in";return e=vl.get(e)||gl,r=dl.get(r)||m,br(r(e.apply(null,lo.call(arguments,1))))},ao.interpolateHcl=Rr,ao.interpolateHsl=Dr,ao.interpolateLab=Pr,ao.interpolateRound=Ur,ao.transform=function(n){var t=fo.createElementNS(ao.ns.prefix.svg,"g");return(ao.transform=function(n){if(null!=n){t.setAttribute("transform",n);var e=t.transform.baseVal.consolidate()}return new jr(e?e.matrix:yl)})(n)},jr.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var yl={a:1,b:0,c:0,d:1,e:0,f:0};ao.interpolateTransform=$r,ao.layout={},ao.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++ea*a/y){if(v>l){var c=t.charge/l;n.px-=u*c,n.py-=o*c}return!0}if(t.point&&l&&v>l){var c=t.pointCharge/l;n.px-=u*c,n.py-=o*c}}return!t.charge}}function t(n){n.px=ao.event.x,n.py=ao.event.y,l.resume()}var e,r,i,u,o,a,l={},c=ao.dispatch("start","tick","end"),f=[1,1],s=.9,h=ml,p=Ml,g=-30,v=xl,d=.1,y=.64,M=[],x=[];return l.tick=function(){if((i*=.99)<.005)return e=null,c.end({type:"end",alpha:i=0}),!0;var t,r,l,h,p,v,y,m,b,_=M.length,w=x.length;for(r=0;w>r;++r)l=x[r],h=l.source,p=l.target,m=p.x-h.x,b=p.y-h.y,(v=m*m+b*b)&&(v=i*o[r]*((v=Math.sqrt(v))-u[r])/v,m*=v,b*=v,p.x-=m*(y=h.weight+p.weight?h.weight/(h.weight+p.weight):.5),p.y-=b*y,h.x+=m*(y=1-y),h.y+=b*y);if((y=i*d)&&(m=f[0]/2,b=f[1]/2,r=-1,y))for(;++r<_;)l=M[r],l.x+=(m-l.x)*y,l.y+=(b-l.y)*y;if(g)for(ri(t=ao.geom.quadtree(M),i,a),r=-1;++r<_;)(l=M[r]).fixed||t.visit(n(l));for(r=-1;++r<_;)l=M[r],l.fixed?(l.x=l.px,l.y=l.py):(l.x-=(l.px-(l.px=l.x))*s,l.y-=(l.py-(l.py=l.y))*s);c.tick({type:"tick",alpha:i})},l.nodes=function(n){return arguments.length?(M=n,l):M},l.links=function(n){return arguments.length?(x=n,l):x},l.size=function(n){return arguments.length?(f=n,l):f},l.linkDistance=function(n){return arguments.length?(h="function"==typeof n?n:+n,l):h},l.distance=l.linkDistance,l.linkStrength=function(n){return arguments.length?(p="function"==typeof n?n:+n,l):p},l.friction=function(n){return arguments.length?(s=+n,l):s},l.charge=function(n){return arguments.length?(g="function"==typeof n?n:+n,l):g},l.chargeDistance=function(n){return arguments.length?(v=n*n,l):Math.sqrt(v)},l.gravity=function(n){return arguments.length?(d=+n,l):d},l.theta=function(n){return arguments.length?(y=n*n,l):Math.sqrt(y)},l.alpha=function(n){return arguments.length?(n=+n,i?n>0?i=n:(e.c=null,e.t=NaN,e=null,c.end({type:"end",alpha:i=0})):n>0&&(c.start({type:"start",alpha:i=n}),e=qn(l.tick)),l):i},l.start=function(){function n(n,r){if(!e){for(e=new Array(i),l=0;i>l;++l)e[l]=[];for(l=0;c>l;++l){var u=x[l];e[u.source.index].push(u.target),e[u.target.index].push(u.source)}}for(var o,a=e[t],l=-1,f=a.length;++lt;++t)(r=M[t]).index=t,r.weight=0;for(t=0;c>t;++t)r=x[t],"number"==typeof r.source&&(r.source=M[r.source]),"number"==typeof r.target&&(r.target=M[r.target]),++r.source.weight,++r.target.weight;for(t=0;i>t;++t)r=M[t],isNaN(r.x)&&(r.x=n("x",s)),isNaN(r.y)&&(r.y=n("y",v)),isNaN(r.px)&&(r.px=r.x),isNaN(r.py)&&(r.py=r.y);if(u=[],"function"==typeof h)for(t=0;c>t;++t)u[t]=+h.call(this,x[t],t);else for(t=0;c>t;++t)u[t]=h;if(o=[],"function"==typeof p)for(t=0;c>t;++t)o[t]=+p.call(this,x[t],t);else for(t=0;c>t;++t)o[t]=p;if(a=[],"function"==typeof g)for(t=0;i>t;++t)a[t]=+g.call(this,M[t],t);else for(t=0;i>t;++t)a[t]=g;return l.resume()},l.resume=function(){return l.alpha(.1)},l.stop=function(){return l.alpha(0)},l.drag=function(){return r||(r=ao.behavior.drag().origin(m).on("dragstart.force",Qr).on("drag.force",t).on("dragend.force",ni)),arguments.length?void this.on("mouseover.force",ti).on("mouseout.force",ei).call(r):r},ao.rebind(l,c,"on")};var ml=20,Ml=1,xl=1/0;ao.layout.hierarchy=function(){function n(i){var u,o=[i],a=[];for(i.depth=0;null!=(u=o.pop());)if(a.push(u),(c=e.call(n,u,u.depth))&&(l=c.length)){for(var l,c,f;--l>=0;)o.push(f=c[l]),f.parent=u,f.depth=u.depth+1;r&&(u.value=0),u.children=c}else r&&(u.value=+r.call(n,u,u.depth)||0),delete u.children;return oi(i,function(n){var e,i;t&&(e=n.children)&&e.sort(t),r&&(i=n.parent)&&(i.value+=n.value)}),a}var t=ci,e=ai,r=li;return n.sort=function(e){return arguments.length?(t=e,n):t},n.children=function(t){return arguments.length?(e=t,n):e},n.value=function(t){return arguments.length?(r=t,n):r},n.revalue=function(t){return r&&(ui(t,function(n){n.children&&(n.value=0)}),oi(t,function(t){var e;t.children||(t.value=+r.call(n,t,t.depth)||0),(e=t.parent)&&(e.value+=t.value)})),t},n},ao.layout.partition=function(){function n(t,e,r,i){var u=t.children;if(t.x=e,t.y=t.depth*i,t.dx=r,t.dy=i,u&&(o=u.length)){var o,a,l,c=-1;for(r=t.value?r/t.value:0;++cs?-1:1),g=ao.sum(c),v=g?(s-l*p)/g:0,d=ao.range(l),y=[];return null!=e&&d.sort(e===bl?function(n,t){return c[t]-c[n]}:function(n,t){return e(o[n],o[t])}),d.forEach(function(n){y[n]={data:o[n],value:a=c[n],startAngle:f,endAngle:f+=a*v+p,padAngle:h}}),y}var t=Number,e=bl,r=0,i=Ho,u=0;return n.value=function(e){return arguments.length?(t=e,n):t},n.sort=function(t){return arguments.length?(e=t,n):e},n.startAngle=function(t){return arguments.length?(r=t,n):r},n.endAngle=function(t){return arguments.length?(i=t,n):i},n.padAngle=function(t){return arguments.length?(u=t,n):u},n};var bl={};ao.layout.stack=function(){function n(a,l){if(!(h=a.length))return a;var c=a.map(function(e,r){return t.call(n,e,r)}),f=c.map(function(t){return t.map(function(t,e){return[u.call(n,t,e),o.call(n,t,e)]})}),s=e.call(n,f,l);c=ao.permute(c,s),f=ao.permute(f,s);var h,p,g,v,d=r.call(n,f,l),y=c[0].length;for(g=0;y>g;++g)for(i.call(n,c[0][g],v=d[g],f[0][g][1]),p=1;h>p;++p)i.call(n,c[p][g],v+=f[p-1][g][1],f[p][g][1]);return a}var t=m,e=gi,r=vi,i=pi,u=si,o=hi;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e="function"==typeof t?t:_l.get(t)||gi,n):e},n.offset=function(t){return arguments.length?(r="function"==typeof t?t:wl.get(t)||vi,n):r},n.x=function(t){return arguments.length?(u=t,n):u},n.y=function(t){return arguments.length?(o=t,n):o},n.out=function(t){return arguments.length?(i=t,n):i},n};var _l=ao.map({"inside-out":function(n){var t,e,r=n.length,i=n.map(di),u=n.map(yi),o=ao.range(r).sort(function(n,t){return i[n]-i[t]}),a=0,l=0,c=[],f=[];for(t=0;r>t;++t)e=o[t],l>a?(a+=u[e],c.push(e)):(l+=u[e],f.push(e));return f.reverse().concat(c)},reverse:function(n){return ao.range(n.length).reverse()},"default":gi}),wl=ao.map({silhouette:function(n){var t,e,r,i=n.length,u=n[0].length,o=[],a=0,l=[];for(e=0;u>e;++e){for(t=0,r=0;i>t;t++)r+=n[t][e][1];r>a&&(a=r),o.push(r)}for(e=0;u>e;++e)l[e]=(a-o[e])/2;return l},wiggle:function(n){var t,e,r,i,u,o,a,l,c,f=n.length,s=n[0],h=s.length,p=[];for(p[0]=l=c=0,e=1;h>e;++e){for(t=0,i=0;f>t;++t)i+=n[t][e][1];for(t=0,u=0,a=s[e][0]-s[e-1][0];f>t;++t){for(r=0,o=(n[t][e][1]-n[t][e-1][1])/(2*a);t>r;++r)o+=(n[r][e][1]-n[r][e-1][1])/a;u+=o*n[t][e][1]}p[e]=l-=i?u/i*a:0,c>l&&(c=l)}for(e=0;h>e;++e)p[e]-=c;return p},expand:function(n){var t,e,r,i=n.length,u=n[0].length,o=1/i,a=[];for(e=0;u>e;++e){for(t=0,r=0;i>t;t++)r+=n[t][e][1];if(r)for(t=0;i>t;t++)n[t][e][1]/=r;else for(t=0;i>t;t++)n[t][e][1]=o}for(e=0;u>e;++e)a[e]=0;return a},zero:vi});ao.layout.histogram=function(){function n(n,u){for(var o,a,l=[],c=n.map(e,this),f=r.call(this,c,u),s=i.call(this,f,c,u),u=-1,h=c.length,p=s.length-1,g=t?1:1/h;++u0)for(u=-1;++u=f[0]&&a<=f[1]&&(o=l[ao.bisect(s,a,1,p)-1],o.y+=g,o.push(n[u]));return l}var t=!0,e=Number,r=bi,i=Mi;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=En(t),n):r},n.bins=function(t){return arguments.length?(i="number"==typeof t?function(n){return xi(n,t)}:En(t),n):i},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},ao.layout.pack=function(){function n(n,u){var o=e.call(this,n,u),a=o[0],l=i[0],c=i[1],f=null==t?Math.sqrt:"function"==typeof t?t:function(){return t};if(a.x=a.y=0,oi(a,function(n){n.r=+f(n.value)}),oi(a,Ni),r){var s=r*(t?1:Math.max(2*a.r/l,2*a.r/c))/2;oi(a,function(n){n.r+=s}),oi(a,Ni),oi(a,function(n){n.r-=s})}return Ci(a,l/2,c/2,t?1:1/Math.max(2*a.r/l,2*a.r/c)),o}var t,e=ao.layout.hierarchy().sort(_i),r=0,i=[1,1];return n.size=function(t){return arguments.length?(i=t,n):i},n.radius=function(e){return arguments.length?(t=null==e||"function"==typeof e?e:+e,n):t},n.padding=function(t){return arguments.length?(r=+t,n):r},ii(n,e)},ao.layout.tree=function(){function n(n,i){var f=o.call(this,n,i),s=f[0],h=t(s);if(oi(h,e),h.parent.m=-h.z,ui(h,r),c)ui(s,u);else{var p=s,g=s,v=s;ui(s,function(n){n.xg.x&&(g=n),n.depth>v.depth&&(v=n)});var d=a(p,g)/2-p.x,y=l[0]/(g.x+a(g,p)/2+d),m=l[1]/(v.depth||1);ui(s,function(n){n.x=(n.x+d)*y,n.y=n.depth*m})}return f}function t(n){for(var t,e={A:null,children:[n]},r=[e];null!=(t=r.pop());)for(var i,u=t.children,o=0,a=u.length;a>o;++o)r.push((u[o]=i={_:u[o],parent:t,children:(i=u[o].children)&&i.slice()||[],A:null,a:null,z:0,m:0,c:0,s:0,t:null,i:o}).a=i);return e.children[0]}function e(n){var t=n.children,e=n.parent.children,r=n.i?e[n.i-1]:null;if(t.length){Di(n);var u=(t[0].z+t[t.length-1].z)/2;r?(n.z=r.z+a(n._,r._),n.m=n.z-u):n.z=u}else r&&(n.z=r.z+a(n._,r._));n.parent.A=i(n,r,n.parent.A||e[0])}function r(n){n._.x=n.z+n.parent.m,n.m+=n.parent.m}function i(n,t,e){if(t){for(var r,i=n,u=n,o=t,l=i.parent.children[0],c=i.m,f=u.m,s=o.m,h=l.m;o=Ti(o),i=qi(i),o&&i;)l=qi(l),u=Ti(u),u.a=n,r=o.z+s-i.z-c+a(o._,i._),r>0&&(Ri(Pi(o,n,e),n,r),c+=r,f+=r),s+=o.m,c+=i.m,h+=l.m,f+=u.m;o&&!Ti(u)&&(u.t=o,u.m+=s-f),i&&!qi(l)&&(l.t=i,l.m+=c-h,e=n)}return e}function u(n){n.x*=l[0],n.y=n.depth*l[1]}var o=ao.layout.hierarchy().sort(null).value(null),a=Li,l=[1,1],c=null;return n.separation=function(t){return arguments.length?(a=t,n):a},n.size=function(t){return arguments.length?(c=null==(l=t)?u:null,n):c?null:l},n.nodeSize=function(t){return arguments.length?(c=null==(l=t)?null:u,n):c?l:null},ii(n,o)},ao.layout.cluster=function(){function n(n,u){var o,a=t.call(this,n,u),l=a[0],c=0;oi(l,function(n){var t=n.children;t&&t.length?(n.x=ji(t),n.y=Ui(t)):(n.x=o?c+=e(n,o):0,n.y=0,o=n)});var f=Fi(l),s=Hi(l),h=f.x-e(f,s)/2,p=s.x+e(s,f)/2;return oi(l,i?function(n){n.x=(n.x-l.x)*r[0],n.y=(l.y-n.y)*r[1]}:function(n){n.x=(n.x-h)/(p-h)*r[0],n.y=(1-(l.y?n.y/l.y:1))*r[1]}),a}var t=ao.layout.hierarchy().sort(null).value(null),e=Li,r=[1,1],i=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(i=null==(r=t),n):i?null:r},n.nodeSize=function(t){return arguments.length?(i=null!=(r=t),n):i?r:null},ii(n,t)},ao.layout.treemap=function(){function n(n,t){for(var e,r,i=-1,u=n.length;++it?0:t),e.area=isNaN(r)||0>=r?0:r}function t(e){var u=e.children;if(u&&u.length){var o,a,l,c=s(e),f=[],h=u.slice(),g=1/0,v="slice"===p?c.dx:"dice"===p?c.dy:"slice-dice"===p?1&e.depth?c.dy:c.dx:Math.min(c.dx,c.dy);for(n(h,c.dx*c.dy/e.value),f.area=0;(l=h.length)>0;)f.push(o=h[l-1]),f.area+=o.area,"squarify"!==p||(a=r(f,v))<=g?(h.pop(),g=a):(f.area-=f.pop().area,i(f,v,c,!1),v=Math.min(c.dx,c.dy),f.length=f.area=0,g=1/0);f.length&&(i(f,v,c,!0),f.length=f.area=0),u.forEach(t)}}function e(t){var r=t.children;if(r&&r.length){var u,o=s(t),a=r.slice(),l=[];for(n(a,o.dx*o.dy/t.value),l.area=0;u=a.pop();)l.push(u),l.area+=u.area,null!=u.z&&(i(l,u.z?o.dx:o.dy,o,!a.length),l.length=l.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,i=0,u=1/0,o=-1,a=n.length;++oe&&(u=e),e>i&&(i=e));return r*=r,t*=t,r?Math.max(t*i*g/r,r/(t*u*g)):1/0}function i(n,t,e,r){var i,u=-1,o=n.length,a=e.x,c=e.y,f=t?l(n.area/t):0; -if(t==e.dx){for((r||f>e.dy)&&(f=e.dy);++ue.dx)&&(f=e.dx);++ue&&(t=1),1>e&&(n=0),function(){var e,r,i;do e=2*Math.random()-1,r=2*Math.random()-1,i=e*e+r*r;while(!i||i>1);return n+t*e*Math.sqrt(-2*Math.log(i)/i)}},logNormal:function(){var n=ao.random.normal.apply(ao,arguments);return function(){return Math.exp(n())}},bates:function(n){var t=ao.random.irwinHall(n);return function(){return t()/n}},irwinHall:function(n){return function(){for(var t=0,e=0;n>e;e++)t+=Math.random();return t}}},ao.scale={};var Sl={floor:m,ceil:m};ao.scale.linear=function(){return Wi([0,1],[0,1],Mr,!1)};var kl={s:1,g:1,p:1,r:1,e:1};ao.scale.log=function(){return ru(ao.scale.linear().domain([0,1]),10,!0,[1,10])};var Nl=ao.format(".0e"),El={floor:function(n){return-Math.ceil(-n)},ceil:function(n){return-Math.floor(-n)}};ao.scale.pow=function(){return iu(ao.scale.linear(),1,[0,1])},ao.scale.sqrt=function(){return ao.scale.pow().exponent(.5)},ao.scale.ordinal=function(){return ou([],{t:"range",a:[[]]})},ao.scale.category10=function(){return ao.scale.ordinal().range(Al)},ao.scale.category20=function(){return ao.scale.ordinal().range(Cl)},ao.scale.category20b=function(){return ao.scale.ordinal().range(zl)},ao.scale.category20c=function(){return ao.scale.ordinal().range(Ll)};var Al=[2062260,16744206,2924588,14034728,9725885,9197131,14907330,8355711,12369186,1556175].map(xn),Cl=[2062260,11454440,16744206,16759672,2924588,10018698,14034728,16750742,9725885,12955861,9197131,12885140,14907330,16234194,8355711,13092807,12369186,14408589,1556175,10410725].map(xn),zl=[3750777,5395619,7040719,10264286,6519097,9216594,11915115,13556636,9202993,12426809,15186514,15190932,8666169,11356490,14049643,15177372,8077683,10834324,13528509,14589654].map(xn),Ll=[3244733,7057110,10406625,13032431,15095053,16616764,16625259,16634018,3253076,7652470,10607003,13101504,7695281,10394312,12369372,14342891,6513507,9868950,12434877,14277081].map(xn);ao.scale.quantile=function(){return au([],[])},ao.scale.quantize=function(){return lu(0,1,[0,1])},ao.scale.threshold=function(){return cu([.5],[0,1])},ao.scale.identity=function(){return fu([0,1])},ao.svg={},ao.svg.arc=function(){function n(){var n=Math.max(0,+e.apply(this,arguments)),c=Math.max(0,+r.apply(this,arguments)),f=o.apply(this,arguments)-Io,s=a.apply(this,arguments)-Io,h=Math.abs(s-f),p=f>s?0:1;if(n>c&&(g=c,c=n,n=g),h>=Oo)return t(c,p)+(n?t(n,1-p):"")+"Z";var g,v,d,y,m,M,x,b,_,w,S,k,N=0,E=0,A=[];if((y=(+l.apply(this,arguments)||0)/2)&&(d=u===ql?Math.sqrt(n*n+c*c):+u.apply(this,arguments),p||(E*=-1),c&&(E=tn(d/c*Math.sin(y))),n&&(N=tn(d/n*Math.sin(y)))),c){m=c*Math.cos(f+E),M=c*Math.sin(f+E),x=c*Math.cos(s-E),b=c*Math.sin(s-E);var C=Math.abs(s-f-2*E)<=Fo?0:1;if(E&&yu(m,M,x,b)===p^C){var z=(f+s)/2;m=c*Math.cos(z),M=c*Math.sin(z),x=b=null}}else m=M=0;if(n){_=n*Math.cos(s-N),w=n*Math.sin(s-N),S=n*Math.cos(f+N),k=n*Math.sin(f+N);var L=Math.abs(f-s+2*N)<=Fo?0:1;if(N&&yu(_,w,S,k)===1-p^L){var q=(f+s)/2;_=n*Math.cos(q),w=n*Math.sin(q),S=k=null}}else _=w=0;if(h>Uo&&(g=Math.min(Math.abs(c-n)/2,+i.apply(this,arguments)))>.001){v=c>n^p?0:1;var T=g,R=g;if(Fo>h){var D=null==S?[_,w]:null==x?[m,M]:Re([m,M],[S,k],[x,b],[_,w]),P=m-D[0],U=M-D[1],j=x-D[0],F=b-D[1],H=1/Math.sin(Math.acos((P*j+U*F)/(Math.sqrt(P*P+U*U)*Math.sqrt(j*j+F*F)))/2),O=Math.sqrt(D[0]*D[0]+D[1]*D[1]);R=Math.min(g,(n-O)/(H-1)),T=Math.min(g,(c-O)/(H+1))}if(null!=x){var I=mu(null==S?[_,w]:[S,k],[m,M],c,T,p),Y=mu([x,b],[_,w],c,T,p);g===T?A.push("M",I[0],"A",T,",",T," 0 0,",v," ",I[1],"A",c,",",c," 0 ",1-p^yu(I[1][0],I[1][1],Y[1][0],Y[1][1]),",",p," ",Y[1],"A",T,",",T," 0 0,",v," ",Y[0]):A.push("M",I[0],"A",T,",",T," 0 1,",v," ",Y[0])}else A.push("M",m,",",M);if(null!=S){var Z=mu([m,M],[S,k],n,-R,p),V=mu([_,w],null==x?[m,M]:[x,b],n,-R,p);g===R?A.push("L",V[0],"A",R,",",R," 0 0,",v," ",V[1],"A",n,",",n," 0 ",p^yu(V[1][0],V[1][1],Z[1][0],Z[1][1]),",",1-p," ",Z[1],"A",R,",",R," 0 0,",v," ",Z[0]):A.push("L",V[0],"A",R,",",R," 0 0,",v," ",Z[0])}else A.push("L",_,",",w)}else A.push("M",m,",",M),null!=x&&A.push("A",c,",",c," 0 ",C,",",p," ",x,",",b),A.push("L",_,",",w),null!=S&&A.push("A",n,",",n," 0 ",L,",",1-p," ",S,",",k);return A.push("Z"),A.join("")}function t(n,t){return"M0,"+n+"A"+n+","+n+" 0 1,"+t+" 0,"+-n+"A"+n+","+n+" 0 1,"+t+" 0,"+n}var e=hu,r=pu,i=su,u=ql,o=gu,a=vu,l=du;return n.innerRadius=function(t){return arguments.length?(e=En(t),n):e},n.outerRadius=function(t){return arguments.length?(r=En(t),n):r},n.cornerRadius=function(t){return arguments.length?(i=En(t),n):i},n.padRadius=function(t){return arguments.length?(u=t==ql?ql:En(t),n):u},n.startAngle=function(t){return arguments.length?(o=En(t),n):o},n.endAngle=function(t){return arguments.length?(a=En(t),n):a},n.padAngle=function(t){return arguments.length?(l=En(t),n):l},n.centroid=function(){var n=(+e.apply(this,arguments)+ +r.apply(this,arguments))/2,t=(+o.apply(this,arguments)+ +a.apply(this,arguments))/2-Io;return[Math.cos(t)*n,Math.sin(t)*n]},n};var ql="auto";ao.svg.line=function(){return Mu(m)};var Tl=ao.map({linear:xu,"linear-closed":bu,step:_u,"step-before":wu,"step-after":Su,basis:zu,"basis-open":Lu,"basis-closed":qu,bundle:Tu,cardinal:Eu,"cardinal-open":ku,"cardinal-closed":Nu,monotone:Fu});Tl.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var Rl=[0,2/3,1/3,0],Dl=[0,1/3,2/3,0],Pl=[0,1/6,2/3,1/6];ao.svg.line.radial=function(){var n=Mu(Hu);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},wu.reverse=Su,Su.reverse=wu,ao.svg.area=function(){return Ou(m)},ao.svg.area.radial=function(){var n=Ou(Hu);return n.radius=n.x,delete n.x,n.innerRadius=n.x0,delete n.x0,n.outerRadius=n.x1,delete n.x1,n.angle=n.y,delete n.y,n.startAngle=n.y0,delete n.y0,n.endAngle=n.y1,delete n.y1,n},ao.svg.chord=function(){function n(n,a){var l=t(this,u,n,a),c=t(this,o,n,a);return"M"+l.p0+r(l.r,l.p1,l.a1-l.a0)+(e(l,c)?i(l.r,l.p1,l.r,l.p0):i(l.r,l.p1,c.r,c.p0)+r(c.r,c.p1,c.a1-c.a0)+i(c.r,c.p1,l.r,l.p0))+"Z"}function t(n,t,e,r){var i=t.call(n,e,r),u=a.call(n,i,r),o=l.call(n,i,r)-Io,f=c.call(n,i,r)-Io;return{r:u,a0:o,a1:f,p0:[u*Math.cos(o),u*Math.sin(o)],p1:[u*Math.cos(f),u*Math.sin(f)]}}function e(n,t){return n.a0==t.a0&&n.a1==t.a1}function r(n,t,e){return"A"+n+","+n+" 0 "+ +(e>Fo)+",1 "+t}function i(n,t,e,r){return"Q 0,0 "+r}var u=Me,o=xe,a=Iu,l=gu,c=vu;return n.radius=function(t){return arguments.length?(a=En(t),n):a},n.source=function(t){return arguments.length?(u=En(t),n):u},n.target=function(t){return arguments.length?(o=En(t),n):o},n.startAngle=function(t){return arguments.length?(l=En(t),n):l},n.endAngle=function(t){return arguments.length?(c=En(t),n):c},n},ao.svg.diagonal=function(){function n(n,i){var u=t.call(this,n,i),o=e.call(this,n,i),a=(u.y+o.y)/2,l=[u,{x:u.x,y:a},{x:o.x,y:a},o];return l=l.map(r),"M"+l[0]+"C"+l[1]+" "+l[2]+" "+l[3]}var t=Me,e=xe,r=Yu;return n.source=function(e){return arguments.length?(t=En(e),n):t},n.target=function(t){return arguments.length?(e=En(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},ao.svg.diagonal.radial=function(){var n=ao.svg.diagonal(),t=Yu,e=n.projection;return n.projection=function(n){return arguments.length?e(Zu(t=n)):t},n},ao.svg.symbol=function(){function n(n,r){return(Ul.get(t.call(this,n,r))||$u)(e.call(this,n,r))}var t=Xu,e=Vu;return n.type=function(e){return arguments.length?(t=En(e),n):t},n.size=function(t){return arguments.length?(e=En(t),n):e},n};var Ul=ao.map({circle:$u,cross:function(n){var t=Math.sqrt(n/5)/2;return"M"+-3*t+","+-t+"H"+-t+"V"+-3*t+"H"+t+"V"+-t+"H"+3*t+"V"+t+"H"+t+"V"+3*t+"H"+-t+"V"+t+"H"+-3*t+"Z"},diamond:function(n){var t=Math.sqrt(n/(2*Fl)),e=t*Fl;return"M0,"+-t+"L"+e+",0 0,"+t+" "+-e+",0Z"},square:function(n){var t=Math.sqrt(n)/2;return"M"+-t+","+-t+"L"+t+","+-t+" "+t+","+t+" "+-t+","+t+"Z"},"triangle-down":function(n){var t=Math.sqrt(n/jl),e=t*jl/2;return"M0,"+e+"L"+t+","+-e+" "+-t+","+-e+"Z"},"triangle-up":function(n){var t=Math.sqrt(n/jl),e=t*jl/2;return"M0,"+-e+"L"+t+","+e+" "+-t+","+e+"Z"}});ao.svg.symbolTypes=Ul.keys();var jl=Math.sqrt(3),Fl=Math.tan(30*Yo);Co.transition=function(n){for(var t,e,r=Hl||++Zl,i=Ku(n),u=[],o=Ol||{time:Date.now(),ease:Nr,delay:0,duration:250},a=-1,l=this.length;++au;u++){i.push(t=[]);for(var e=this[u],a=0,l=e.length;l>a;a++)(r=e[a])&&n.call(r,r.__data__,a,u)&&t.push(r)}return Wu(i,this.namespace,this.id)},Yl.tween=function(n,t){var e=this.id,r=this.namespace;return arguments.length<2?this.node()[r][e].tween.get(n):Y(this,null==t?function(t){t[r][e].tween.remove(n)}:function(i){i[r][e].tween.set(n,t)})},Yl.attr=function(n,t){function e(){this.removeAttribute(a)}function r(){this.removeAttributeNS(a.space,a.local)}function i(n){return null==n?e:(n+="",function(){var t,e=this.getAttribute(a);return e!==n&&(t=o(e,n),function(n){this.setAttribute(a,t(n))})})}function u(n){return null==n?r:(n+="",function(){var t,e=this.getAttributeNS(a.space,a.local);return e!==n&&(t=o(e,n),function(n){this.setAttributeNS(a.space,a.local,t(n))})})}if(arguments.length<2){for(t in n)this.attr(t,n[t]);return this}var o="transform"==n?$r:Mr,a=ao.ns.qualify(n);return Ju(this,"attr."+n,t,a.local?u:i)},Yl.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(i));return r&&function(n){this.setAttribute(i,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(i.space,i.local));return r&&function(n){this.setAttributeNS(i.space,i.local,r(n))}}var i=ao.ns.qualify(n);return this.tween("attr."+n,i.local?r:e)},Yl.style=function(n,e,r){function i(){this.style.removeProperty(n)}function u(e){return null==e?i:(e+="",function(){var i,u=t(this).getComputedStyle(this,null).getPropertyValue(n);return u!==e&&(i=Mr(u,e),function(t){this.style.setProperty(n,i(t),r)})})}var o=arguments.length;if(3>o){if("string"!=typeof n){2>o&&(e="");for(r in n)this.style(r,n[r],e);return this}r=""}return Ju(this,"style."+n,e,u)},Yl.styleTween=function(n,e,r){function i(i,u){var o=e.call(this,i,u,t(this).getComputedStyle(this,null).getPropertyValue(n));return o&&function(t){this.style.setProperty(n,o(t),r)}}return arguments.length<3&&(r=""),this.tween("style."+n,i)},Yl.text=function(n){return Ju(this,"text",n,Gu)},Yl.remove=function(){var n=this.namespace;return this.each("end.transition",function(){var t;this[n].count<2&&(t=this.parentNode)&&t.removeChild(this)})},Yl.ease=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].ease:("function"!=typeof n&&(n=ao.ease.apply(ao,arguments)),Y(this,function(r){r[e][t].ease=n}))},Yl.delay=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].delay:Y(this,"function"==typeof n?function(r,i,u){r[e][t].delay=+n.call(r,r.__data__,i,u)}:(n=+n,function(r){r[e][t].delay=n}))},Yl.duration=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].duration:Y(this,"function"==typeof n?function(r,i,u){r[e][t].duration=Math.max(1,n.call(r,r.__data__,i,u))}:(n=Math.max(1,n),function(r){r[e][t].duration=n}))},Yl.each=function(n,t){var e=this.id,r=this.namespace;if(arguments.length<2){var i=Ol,u=Hl;try{Hl=e,Y(this,function(t,i,u){Ol=t[r][e],n.call(t,t.__data__,i,u)})}finally{Ol=i,Hl=u}}else Y(this,function(i){var u=i[r][e];(u.event||(u.event=ao.dispatch("start","end","interrupt"))).on(n,t)});return this},Yl.transition=function(){for(var n,t,e,r,i=this.id,u=++Zl,o=this.namespace,a=[],l=0,c=this.length;c>l;l++){a.push(n=[]);for(var t=this[l],f=0,s=t.length;s>f;f++)(e=t[f])&&(r=e[o][i],Qu(e,f,o,u,{time:r.time,ease:r.ease,delay:r.delay+r.duration,duration:r.duration})),n.push(e)}return Wu(a,o,u)},ao.svg.axis=function(){function n(n){n.each(function(){var n,c=ao.select(this),f=this.__chart__||e,s=this.__chart__=e.copy(),h=null==l?s.ticks?s.ticks.apply(s,a):s.domain():l,p=null==t?s.tickFormat?s.tickFormat.apply(s,a):m:t,g=c.selectAll(".tick").data(h,s),v=g.enter().insert("g",".domain").attr("class","tick").style("opacity",Uo),d=ao.transition(g.exit()).style("opacity",Uo).remove(),y=ao.transition(g.order()).style("opacity",1),M=Math.max(i,0)+o,x=Zi(s),b=c.selectAll(".domain").data([0]),_=(b.enter().append("path").attr("class","domain"),ao.transition(b));v.append("line"),v.append("text");var w,S,k,N,E=v.select("line"),A=y.select("line"),C=g.select("text").text(p),z=v.select("text"),L=y.select("text"),q="top"===r||"left"===r?-1:1;if("bottom"===r||"top"===r?(n=no,w="x",k="y",S="x2",N="y2",C.attr("dy",0>q?"0em":".71em").style("text-anchor","middle"),_.attr("d","M"+x[0]+","+q*u+"V0H"+x[1]+"V"+q*u)):(n=to,w="y",k="x",S="y2",N="x2",C.attr("dy",".32em").style("text-anchor",0>q?"end":"start"),_.attr("d","M"+q*u+","+x[0]+"H0V"+x[1]+"H"+q*u)),E.attr(N,q*i),z.attr(k,q*M),A.attr(S,0).attr(N,q*i),L.attr(w,0).attr(k,q*M),s.rangeBand){var T=s,R=T.rangeBand()/2;f=s=function(n){return T(n)+R}}else f.rangeBand?f=s:d.call(n,s,f);v.call(n,f,s),y.call(n,s,s)})}var t,e=ao.scale.linear(),r=Vl,i=6,u=6,o=3,a=[10],l=null;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in Xl?t+"":Vl,n):r},n.ticks=function(){return arguments.length?(a=co(arguments),n):a},n.tickValues=function(t){return arguments.length?(l=t,n):l},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t){var e=arguments.length;return e?(i=+t,u=+arguments[e-1],n):i},n.innerTickSize=function(t){return arguments.length?(i=+t,n):i},n.outerTickSize=function(t){return arguments.length?(u=+t,n):u},n.tickPadding=function(t){return arguments.length?(o=+t,n):o},n.tickSubdivide=function(){return arguments.length&&n},n};var Vl="bottom",Xl={top:1,right:1,bottom:1,left:1};ao.svg.brush=function(){function n(t){t.each(function(){var t=ao.select(this).style("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush",u).on("touchstart.brush",u),o=t.selectAll(".background").data([0]);o.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),t.selectAll(".extent").data([0]).enter().append("rect").attr("class","extent").style("cursor","move");var a=t.selectAll(".resize").data(v,m);a.exit().remove(),a.enter().append("g").attr("class",function(n){return"resize "+n}).style("cursor",function(n){return $l[n]}).append("rect").attr("x",function(n){return/[ew]$/.test(n)?-3:null}).attr("y",function(n){return/^[ns]/.test(n)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),a.style("display",n.empty()?"none":null);var l,s=ao.transition(t),h=ao.transition(o);c&&(l=Zi(c),h.attr("x",l[0]).attr("width",l[1]-l[0]),r(s)),f&&(l=Zi(f),h.attr("y",l[0]).attr("height",l[1]-l[0]),i(s)),e(s)})}function e(n){n.selectAll(".resize").attr("transform",function(n){return"translate("+s[+/e$/.test(n)]+","+h[+/^s/.test(n)]+")"})}function r(n){n.select(".extent").attr("x",s[0]),n.selectAll(".extent,.n>rect,.s>rect").attr("width",s[1]-s[0])}function i(n){n.select(".extent").attr("y",h[0]),n.selectAll(".extent,.e>rect,.w>rect").attr("height",h[1]-h[0])}function u(){function u(){32==ao.event.keyCode&&(C||(M=null,L[0]-=s[1],L[1]-=h[1],C=2),S())}function v(){32==ao.event.keyCode&&2==C&&(L[0]+=s[1],L[1]+=h[1],C=0,S())}function d(){var n=ao.mouse(b),t=!1;x&&(n[0]+=x[0],n[1]+=x[1]),C||(ao.event.altKey?(M||(M=[(s[0]+s[1])/2,(h[0]+h[1])/2]),L[0]=s[+(n[0]f?(i=r,r=f):i=f),v[0]!=r||v[1]!=i?(e?a=null:o=null,v[0]=r,v[1]=i,!0):void 0}function m(){d(),k.style("pointer-events","all").selectAll(".resize").style("display",n.empty()?"none":null),ao.select("body").style("cursor",null),q.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touchend.brush",null).on("keydown.brush",null).on("keyup.brush",null),z(),w({type:"brushend"})}var M,x,b=this,_=ao.select(ao.event.target),w=l.of(b,arguments),k=ao.select(b),N=_.datum(),E=!/^(n|s)$/.test(N)&&c,A=!/^(e|w)$/.test(N)&&f,C=_.classed("extent"),z=W(b),L=ao.mouse(b),q=ao.select(t(b)).on("keydown.brush",u).on("keyup.brush",v);if(ao.event.changedTouches?q.on("touchmove.brush",d).on("touchend.brush",m):q.on("mousemove.brush",d).on("mouseup.brush",m),k.interrupt().selectAll("*").interrupt(),C)L[0]=s[0]-L[0],L[1]=h[0]-L[1];else if(N){var T=+/w$/.test(N),R=+/^n/.test(N);x=[s[1-T]-L[0],h[1-R]-L[1]],L[0]=s[T],L[1]=h[R]}else ao.event.altKey&&(M=L.slice());k.style("pointer-events","none").selectAll(".resize").style("display",null),ao.select("body").style("cursor",_.style("cursor")),w({type:"brushstart"}),d()}var o,a,l=N(n,"brushstart","brush","brushend"),c=null,f=null,s=[0,0],h=[0,0],p=!0,g=!0,v=Bl[0];return n.event=function(n){n.each(function(){var n=l.of(this,arguments),t={x:s,y:h,i:o,j:a},e=this.__chart__||t;this.__chart__=t,Hl?ao.select(this).transition().each("start.brush",function(){o=e.i,a=e.j,s=e.x,h=e.y,n({type:"brushstart"})}).tween("brush:brush",function(){var e=xr(s,t.x),r=xr(h,t.y);return o=a=null,function(i){s=t.x=e(i),h=t.y=r(i),n({type:"brush",mode:"resize"})}}).each("end.brush",function(){o=t.i,a=t.j,n({type:"brush",mode:"resize"}),n({type:"brushend"})}):(n({type:"brushstart"}),n({type:"brush",mode:"resize"}),n({type:"brushend"}))})},n.x=function(t){return arguments.length?(c=t,v=Bl[!c<<1|!f],n):c},n.y=function(t){return arguments.length?(f=t,v=Bl[!c<<1|!f],n):f},n.clamp=function(t){return arguments.length?(c&&f?(p=!!t[0],g=!!t[1]):c?p=!!t:f&&(g=!!t),n):c&&f?[p,g]:c?p:f?g:null},n.extent=function(t){var e,r,i,u,l;return arguments.length?(c&&(e=t[0],r=t[1],f&&(e=e[0],r=r[0]),o=[e,r],c.invert&&(e=c(e),r=c(r)),e>r&&(l=e,e=r,r=l),e==s[0]&&r==s[1]||(s=[e,r])),f&&(i=t[0],u=t[1],c&&(i=i[1],u=u[1]),a=[i,u],f.invert&&(i=f(i),u=f(u)),i>u&&(l=i,i=u,u=l),i==h[0]&&u==h[1]||(h=[i,u])),n):(c&&(o?(e=o[0],r=o[1]):(e=s[0],r=s[1],c.invert&&(e=c.invert(e),r=c.invert(r)),e>r&&(l=e,e=r,r=l))),f&&(a?(i=a[0],u=a[1]):(i=h[0],u=h[1],f.invert&&(i=f.invert(i),u=f.invert(u)),i>u&&(l=i,i=u,u=l))),c&&f?[[e,i],[r,u]]:c?[e,r]:f&&[i,u])},n.clear=function(){return n.empty()||(s=[0,0],h=[0,0],o=a=null),n},n.empty=function(){return!!c&&s[0]==s[1]||!!f&&h[0]==h[1]},ao.rebind(n,l,"on")};var $l={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},Bl=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]],Wl=ga.format=xa.timeFormat,Jl=Wl.utc,Gl=Jl("%Y-%m-%dT%H:%M:%S.%LZ");Wl.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?eo:Gl,eo.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},eo.toString=Gl.toString,ga.second=On(function(n){return new va(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),ga.seconds=ga.second.range,ga.seconds.utc=ga.second.utc.range,ga.minute=On(function(n){return new va(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),ga.minutes=ga.minute.range,ga.minutes.utc=ga.minute.utc.range,ga.hour=On(function(n){var t=n.getTimezoneOffset()/60;return new va(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),ga.hours=ga.hour.range,ga.hours.utc=ga.hour.utc.range,ga.month=On(function(n){return n=ga.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),ga.months=ga.month.range,ga.months.utc=ga.month.utc.range;var Kl=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Ql=[[ga.second,1],[ga.second,5],[ga.second,15],[ga.second,30],[ga.minute,1],[ga.minute,5],[ga.minute,15],[ga.minute,30],[ga.hour,1],[ga.hour,3],[ga.hour,6],[ga.hour,12],[ga.day,1],[ga.day,2],[ga.week,1],[ga.month,1],[ga.month,3],[ga.year,1]],nc=Wl.multi([[".%L",function(n){return n.getMilliseconds()}],[":%S",function(n){return n.getSeconds()}],["%I:%M",function(n){return n.getMinutes()}],["%I %p",function(n){return n.getHours()}],["%a %d",function(n){return n.getDay()&&1!=n.getDate()}],["%b %d",function(n){return 1!=n.getDate()}],["%B",function(n){return n.getMonth()}],["%Y",zt]]),tc={range:function(n,t,e){return ao.range(Math.ceil(n/e)*e,+t,e).map(io)},floor:m,ceil:m};Ql.year=ga.year,ga.scale=function(){return ro(ao.scale.linear(),Ql,nc)};var ec=Ql.map(function(n){return[n[0].utc,n[1]]}),rc=Jl.multi([[".%L",function(n){return n.getUTCMilliseconds()}],[":%S",function(n){return n.getUTCSeconds()}],["%I:%M",function(n){return n.getUTCMinutes()}],["%I %p",function(n){return n.getUTCHours()}],["%a %d",function(n){return n.getUTCDay()&&1!=n.getUTCDate()}],["%b %d",function(n){return 1!=n.getUTCDate()}],["%B",function(n){return n.getUTCMonth()}],["%Y",zt]]);ec.year=ga.year.utc,ga.scale.utc=function(){return ro(ao.scale.linear(),ec,rc)},ao.text=An(function(n){return n.responseText}),ao.json=function(n,t){return Cn(n,"application/json",uo,t)},ao.html=function(n,t){return Cn(n,"text/html",oo,t)},ao.xml=An(function(n){return n.responseXML}),"function"==typeof define&&define.amd?(this.d3=ao,define(ao)):"object"==typeof module&&module.exports?module.exports=ao:this.d3=ao}(); \ No newline at end of file diff --git a/hadoop-hdds/framework/src/main/resources/webapps/static/dfs-dust.js b/hadoop-hdds/framework/src/main/resources/webapps/static/dfs-dust.js deleted file mode 100644 index c7af6a18d3d..00000000000 --- a/hadoop-hdds/framework/src/main/resources/webapps/static/dfs-dust.js +++ /dev/null @@ -1,133 +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 - * - * 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. - */ -(function ($, dust, exports) { - "use strict"; - - var filters = { - 'fmt_bytes': function (v) { - var UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'ZB']; - var prev = 0, i = 0; - while (Math.floor(v) > 0 && i < UNITS.length) { - prev = v; - v /= 1024; - i += 1; - } - - if (i > 0 && i < UNITS.length) { - v = prev; - i -= 1; - } - return Math.round(v * 100) / 100 + ' ' + UNITS[i]; - }, - - 'fmt_percentage': function (v) { - return Math.round(v * 100) / 100 + '%'; - }, - 'elapsed': function(v) { - //elapsed sec from epoch sec - return Date.now() - v * 1000; - }, - 'fmt_time': function (v) { - var s = Math.floor(v / 1000), h = Math.floor(s / 3600); - s -= h * 3600; - var m = Math.floor(s / 60); - s -= m * 60; - - var res = s + " sec"; - if (m !== 0) { - res = m + " mins, " + res; - } - - if (h !== 0) { - res = h + " hrs, " + res; - } - - return res; - }, - - 'date_tostring' : function (v) { - return moment(Number(v)).format('ddd MMM DD HH:mm:ss ZZ YYYY'); - }, - - 'format_compile_info' : function (v) { - var info = v.split(" by ") - var date = moment(info[0]).format('ddd MMM DD HH:mm:ss ZZ YYYY'); - return date.concat(" by ").concat(info[1]); - }, - - 'helper_to_permission': function (v) { - var symbols = [ '---', '--x', '-w-', '-wx', 'r--', 'r-x', 'rw-', 'rwx' ]; - var vInt = parseInt(v, 8); - var sticky = (vInt & (1 << 9)) != 0; - - var res = ""; - for (var i = 0; i < 3; ++i) { - res = symbols[(v % 10)] + res; - v = Math.floor(v / 10); - } - - if (sticky) { - var otherExec = (vInt & 1) == 1; - res = res.substr(0, res.length - 1) + (otherExec ? 't' : 'T'); - } - - return res; - }, - - 'helper_to_directory' : function (v) { - return v === 'DIRECTORY' ? 'd' : '-'; - }, - - 'helper_to_acl_bit': function (v) { - return v ? '+' : ""; - }, - - 'fmt_number': function (v) { - return v.toLocaleString(); - } - }; - $.extend(dust.filters, filters); - - /** - * Load a sequence of JSON. - * - * beans is an array of tuples in the format of {url, name}. - */ - function load_json(beans, success_cb, error_cb) { - var data = {}, error = false, to_be_completed = beans.length; - - $.each(beans, function(idx, b) { - if (error) { - return false; - } - $.get(b.url, function (resp) { - data[b.name] = resp; - to_be_completed -= 1; - if (to_be_completed === 0) { - success_cb(data); - } - }).error(function (jqxhr, text, err) { - error = true; - error_cb(b.url, jqxhr, text, err); - }); - }); - } - - exports.load_json = load_json; - -}($, dust, window)); diff --git a/hadoop-hdds/framework/src/main/resources/webapps/static/nvd3-1.8.5.min.css b/hadoop-hdds/framework/src/main/resources/webapps/static/nvd3-1.8.5.min.css deleted file mode 100644 index b8a5c0f1a3e..00000000000 --- a/hadoop-hdds/framework/src/main/resources/webapps/static/nvd3-1.8.5.min.css +++ /dev/null @@ -1,2 +0,0 @@ -.nvd3 .nv-axis line,.nvd3 .nv-axis path{fill:none;shape-rendering:crispEdges}.nv-brush .extent,.nvd3 .background path,.nvd3 .nv-axis line,.nvd3 .nv-axis path{shape-rendering:crispEdges}.nv-distx,.nv-disty,.nv-noninteractive,.nvd3 .nv-axis,.nvd3.nv-pie .nv-label,.nvd3.nv-sparklineplus g.nv-hoverValue{pointer-events:none}.nvd3 .nv-axis{opacity:1}.nvd3 .nv-axis.nv-disabled,.nvd3 .nv-controlsWrap .nv-legend .nv-check-box .nv-check{opacity:0}.nvd3 .nv-axis path{stroke:#000;stroke-opacity:.75}.nvd3 .nv-axis path.domain{stroke-opacity:.75}.nvd3 .nv-axis.nv-x path.domain{stroke-opacity:0}.nvd3 .nv-axis line{stroke:#e5e5e5}.nvd3 .nv-axis .zero line, .nvd3 .nv-axis line.zero{stroke-opacity:.75}.nvd3 .nv-axis .nv-axisMaxMin text{font-weight:700}.nvd3 .x .nv-axis .nv-axisMaxMin text,.nvd3 .x2 .nv-axis .nv-axisMaxMin text,.nvd3 .x3 .nv-axis .nv-axisMaxMin text{text-anchor:middle}.nvd3 .nv-bars rect{fill-opacity:.75;transition:fill-opacity 250ms linear}.nvd3 .nv-bars rect.hover{fill-opacity:1}.nvd3 .nv-bars .hover rect{fill:#add8e6}.nvd3 .nv-bars text{fill:transparent}.nvd3 .nv-bars .hover text{fill:rgba(0,0,0,1)}.nvd3 .nv-discretebar .nv-groups rect,.nvd3 .nv-multibar .nv-groups rect,.nvd3 .nv-multibarHorizontal .nv-groups rect{stroke-opacity:0;transition:fill-opacity 250ms linear}.with-transitions .nv-candlestickBar .nv-ticks .nv-tick,.with-transitions .nvd3 .nv-groups .nv-point{transition:stroke-width 250ms linear,stroke-opacity 250ms linear}.nvd3 .nv-candlestickBar .nv-ticks rect:hover,.nvd3 .nv-discretebar .nv-groups rect:hover,.nvd3 .nv-multibar .nv-groups rect:hover,.nvd3 .nv-multibarHorizontal .nv-groups rect:hover{fill-opacity:1}.nvd3 .nv-discretebar .nv-groups text,.nvd3 .nv-multibarHorizontal .nv-groups text{font-weight:700;fill:rgba(0,0,0,1);stroke:transparent}.nvd3 .nv-boxplot circle{fill-opacity:.5}.nvd3 .nv-boxplot circle:hover,.nvd3 .nv-boxplot rect:hover{fill-opacity:1}.nvd3 line.nv-boxplot-median{stroke:#000}.nv-boxplot-tick:hover{stroke-width:2.5px}.nvd3.nv-bullet{font:10px sans-serif}.nvd3.nv-bullet .nv-measure{fill-opacity:.8}.nvd3.nv-bullet .nv-measure:hover{fill-opacity:1}.nvd3.nv-bullet .nv-marker{stroke:#000;stroke-width:2px}.nvd3.nv-bullet .nv-markerTriangle{stroke:#000;fill:#fff;stroke-width:1.5px}.nvd3.nv-bullet .nv-markerLine{stroke:#000;stroke-width:1.5px}.nvd3.nv-bullet .nv-tick line{stroke:#666;stroke-width:.5px}.nvd3.nv-bullet .nv-range.nv-s0{fill:#eee}.nvd3.nv-bullet .nv-range.nv-s1{fill:#ddd}.nvd3.nv-bullet .nv-range.nv-s2{fill:#ccc}.nvd3.nv-bullet .nv-title{font-size:14px;font-weight:700}.nvd3.nv-bullet .nv-subtitle{fill:#999}.nvd3.nv-bullet .nv-range{fill:#bababa;fill-opacity:.4}.nvd3.nv-bullet .nv-range:hover{fill-opacity:.7}.nvd3.nv-candlestickBar .nv-ticks .nv-tick{stroke-width:1px}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.hover{stroke-width:2px}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.positive rect{stroke:#2ca02c;fill:#2ca02c}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.negative rect{stroke:#d62728;fill:#d62728}.nvd3.nv-candlestickBar .nv-ticks line{stroke:#333}.nv-force-node{stroke:#fff;stroke-width:1.5px}.nv-force-link{stroke:#999;stroke-opacity:.6}.nv-force-node text{stroke-width:0}.nvd3 .nv-check-box .nv-box{fill-opacity:0;stroke-width:2}.nvd3 .nv-check-box .nv-check{fill-opacity:0;stroke-width:4}.nvd3 .nv-series.nv-disabled .nv-check-box .nv-check{fill-opacity:0;stroke-opacity:0}.nvd3.nv-linePlusBar .nv-bar rect{fill-opacity:.75}.nvd3.nv-linePlusBar .nv-bar rect:hover{fill-opacity:1}.nvd3 .nv-groups path.nv-line{fill:none}.nvd3 .nv-groups path.nv-area{stroke:none}.nvd3.nv-line .nvd3.nv-scatter .nv-groups .nv-point{fill-opacity:0;stroke-opacity:0}.nvd3.nv-scatter.nv-single-point .nv-groups .nv-point{fill-opacity:.5!important;stroke-opacity:.5!important}.nvd3 .nv-groups .nv-point.hover,.nvd3.nv-scatter .nv-groups .nv-point.hover{stroke-width:7px;fill-opacity:.95!important;stroke-opacity:.95!important}.nvd3 .nv-point-paths path{stroke:#aaa;stroke-opacity:0;fill:#eee;fill-opacity:0}.nvd3 .nv-indexLine{cursor:ew-resize}svg.nvd3-svg{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:block;width:100%;height:100%}.nvtooltip.with-3d-shadow,.with-3d-shadow .nvtooltip{box-shadow:0 5px 10px rgba(0,0,0,.2);border-radius:5px}.nvd3 text{font:400 12px Arial,sans-serif}.nvd3 .title{font:700 14px Arial,sans-serif}.nvd3 .nv-background{fill:#fff;fill-opacity:0}.nvd3.nv-noData{font-size:18px;font-weight:700}.nv-brush .extent{fill-opacity:.125}.nv-brush .resize path{fill:#eee;stroke:#666}.nvd3 .nv-legend .nv-series{cursor:pointer}.nvd3 .nv-legend .nv-disabled circle{fill-opacity:0}.nvd3 .nv-brush .extent{fill-opacity:0!important}.nvd3 .nv-brushBackground rect{stroke:#000;stroke-width:.4;fill:#fff;fill-opacity:.7}@media print{.nvd3 text{stroke-width:0;fill-opacity:1}}.nvd3.nv-ohlcBar .nv-ticks .nv-tick{stroke-width:1px}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.hover{stroke-width:2px}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.positive{stroke:#2ca02c}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.negative{stroke:#d62728}.nvd3 .background path{fill:none;stroke:#EEE;stroke-opacity:.4}.nvd3 .foreground path{fill:none;stroke-opacity:.7}.nvd3 .nv-parallelCoordinates-brush .extent{fill:#fff;fill-opacity:.6;stroke:gray;shape-rendering:crispEdges}.nvd3 .nv-parallelCoordinates .hover{fill-opacity:1;stroke-width:3px}.nvd3 .missingValuesline line{fill:none;stroke:#000;stroke-width:1;stroke-opacity:1;stroke-dasharray:5,5}.nvd3.nv-pie .nv-pie-title{font-size:24px;fill:rgba(19,196,249,.59)}.nvd3.nv-pie .nv-slice text{stroke:#000;stroke-width:0}.nvd3.nv-pie path{transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear;stroke:#fff;stroke-width:1px;stroke-opacity:1;fill-opacity:.7}.nvd3.nv-pie .hover path{fill-opacity:1}.nvd3.nv-pie .nv-label rect{fill-opacity:0;stroke-opacity:0}.nvd3 .nv-groups .nv-point.hover{stroke-width:20px;stroke-opacity:.5}.nvd3 .nv-scatter .nv-point.hover{fill-opacity:1}.nvd3.nv-sparkline path{fill:none}.nvd3.nv-sparklineplus .nv-hoverValue line{stroke:#333;stroke-width:1.5px}.nvd3.nv-sparklineplus,.nvd3.nv-sparklineplus g{pointer-events:all}.nvd3 .nv-interactiveGuideLine,.nvtooltip{pointer-events:none}.nvd3 .nv-hoverArea{fill-opacity:0;stroke-opacity:0}.nvd3.nv-sparklineplus .nv-xValue,.nvd3.nv-sparklineplus .nv-yValue{stroke-width:0;font-size:.9em;font-weight:400}.nvd3.nv-sparklineplus .nv-yValue{stroke:#f66}.nvd3.nv-sparklineplus .nv-maxValue{stroke:#2ca02c;fill:#2ca02c}.nvd3.nv-sparklineplus .nv-minValue{stroke:#d62728;fill:#d62728}.nvd3.nv-sparklineplus .nv-currentValue{font-weight:700;font-size:1.1em}.nvtooltip h3,.nvtooltip table td.key{font-weight:400}.nvd3.nv-stackedarea path.nv-area{fill-opacity:.7;stroke-opacity:0;transition:fill-opacity 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-stackedarea path.nv-area.hover{fill-opacity:.9}.nvd3.nv-stackedarea .nv-groups .nv-point{stroke-opacity:0;fill-opacity:0}.nvtooltip{position:absolute;color:rgba(0,0,0,1);padding:1px;z-index:10000;display:block;font-family:Arial,sans-serif;font-size:13px;text-align:left;white-space:nowrap;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background:rgba(255,255,255,.8);border:1px solid rgba(0,0,0,.5);border-radius:4px}.nvtooltip h3,.nvtooltip p{margin:0;text-align:center}.nvtooltip.with-transitions,.with-transitions .nvtooltip{transition:opacity 50ms linear;transition-delay:200ms}.nvtooltip.x-nvtooltip,.nvtooltip.y-nvtooltip{padding:8px}.nvtooltip h3{padding:4px 14px;line-height:18px;background-color:rgba(247,247,247,.75);color:rgba(0,0,0,1);border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.nvtooltip p{padding:5px 14px}.nvtooltip span{display:inline-block;margin:2px 0}.nvtooltip table{margin:6px;border-spacing:0}.nvtooltip table td{padding:2px 9px 2px 0;vertical-align:middle}.nvtooltip table td.key.total{font-weight:700}.nvtooltip table td.value{text-align:right;font-weight:700}.nvtooltip table td.percent{color:#a9a9a9}.nvtooltip table tr.highlight td{padding:1px 9px 1px 0;border-bottom-style:solid;border-bottom-width:1px;border-top-style:solid;border-top-width:1px}.nvtooltip table td.legend-color-guide div{vertical-align:middle;width:12px;height:12px;border:1px solid #999}.nvtooltip .footer{padding:3px;text-align:center}.nvtooltip-pending-removal{pointer-events:none;display:none}.nvd3 line.nv-guideline{stroke:#ccc} -/*# sourceMappingURL=nv.d3.min.css.map */ \ No newline at end of file diff --git a/hadoop-hdds/framework/src/main/resources/webapps/static/nvd3-1.8.5.min.css.map b/hadoop-hdds/framework/src/main/resources/webapps/static/nvd3-1.8.5.min.css.map deleted file mode 100644 index 63380e6e0df..00000000000 --- a/hadoop-hdds/framework/src/main/resources/webapps/static/nvd3-1.8.5.min.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["build/nv.d3.css"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/hadoop-hdds/framework/src/main/resources/webapps/static/nvd3-1.8.5.min.js b/hadoop-hdds/framework/src/main/resources/webapps/static/nvd3-1.8.5.min.js deleted file mode 100644 index 9cfd702277e..00000000000 --- a/hadoop-hdds/framework/src/main/resources/webapps/static/nvd3-1.8.5.min.js +++ /dev/null @@ -1,11 +0,0 @@ -/* nvd3 version 1.8.5 (https://github.com/novus/nvd3) 2016-12-01 */ - -!function(){var a={};a.dev=!1,a.tooltip=a.tooltip||{},a.utils=a.utils||{},a.models=a.models||{},a.charts={},a.logs={},a.dom={},"undefined"!=typeof module&&"undefined"!=typeof exports&&"undefined"==typeof d3&&(d3=require("d3")),a.dispatch=d3.dispatch("render_start","render_end"),Function.prototype.bind||(Function.prototype.bind=function(a){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var b=Array.prototype.slice.call(arguments,1),c=this,d=function(){},e=function(){return c.apply(this instanceof d&&a?this:a,b.concat(Array.prototype.slice.call(arguments)))};return d.prototype=this.prototype,e.prototype=new d,e}),a.dev&&(a.dispatch.on("render_start",function(b){a.logs.startTime=+new Date}),a.dispatch.on("render_end",function(b){a.logs.endTime=+new Date,a.logs.totalTime=a.logs.endTime-a.logs.startTime,a.log("total",a.logs.totalTime)})),a.log=function(){if(a.dev&&window.console&&console.log&&console.log.apply)console.log.apply(console,arguments);else if(a.dev&&window.console&&"function"==typeof console.log&&Function.prototype.bind){var b=Function.prototype.bind.call(console.log,console);b.apply(console,arguments)}return arguments[arguments.length-1]},a.deprecated=function(a,b){console&&console.warn&&console.warn("nvd3 warning: `"+a+"` has been deprecated. ",b||"")},a.render=function(b){b=b||1,a.render.active=!0,a.dispatch.render_start();var c=function(){for(var d,e,f=0;b>f&&(e=a.render.queue[f]);f++)d=e.generate(),typeof e.callback==typeof Function&&e.callback(d);a.render.queue.splice(0,f),a.render.queue.length?setTimeout(c):(a.dispatch.render_end(),a.render.active=!1)};setTimeout(c)},a.render.active=!1,a.render.queue=[],a.addGraph=function(b){typeof arguments[0]==typeof Function&&(b={generate:arguments[0],callback:arguments[1]}),a.render.queue.push(b),a.render.active||a.render()},"undefined"!=typeof module&&"undefined"!=typeof exports&&(module.exports=a),"undefined"!=typeof window&&(window.nv=a),a.dom.write=function(a){return void 0!==window.fastdom?fastdom.mutate(a):a()},a.dom.read=function(a){return void 0!==window.fastdom?fastdom.measure(a):a()},a.interactiveGuideline=function(){"use strict";function b(l){l.each(function(l){function m(){var a=d3.mouse(this),d=a[0],e=a[1],h=!0,i=!1;if(k&&(d=d3.event.offsetX,e=d3.event.offsetY,"svg"!==d3.event.target.tagName&&(h=!1),d3.event.target.className.baseVal.match("nv-legend")&&(i=!0)),h&&(d-=c.left,e-=c.top),"mouseout"===d3.event.type||0>d||0>e||d>o||e>p||d3.event.relatedTarget&&void 0===d3.event.relatedTarget.ownerSVGElement||i){if(k&&d3.event.relatedTarget&&void 0===d3.event.relatedTarget.ownerSVGElement&&(void 0===d3.event.relatedTarget.className||d3.event.relatedTarget.className.match(j.nvPointerEventsClass)))return;return g.elementMouseout({mouseX:d,mouseY:e}),b.renderGuideLine(null),void j.hidden(!0)}j.hidden(!1);var l="function"==typeof f.rangeBands,m=void 0;if(l){var n=d3.bisect(f.range(),d)-1;if(!(f.range()[n]+f.rangeBand()>=d))return g.elementMouseout({mouseX:d,mouseY:e}),b.renderGuideLine(null),void j.hidden(!0);m=f.domain()[d3.bisect(f.range(),d)-1]}else m=f.invert(d);g.elementMousemove({mouseX:d,mouseY:e,pointXValue:m}),"dblclick"===d3.event.type&&g.elementDblclick({mouseX:d,mouseY:e,pointXValue:m}),"click"===d3.event.type&&g.elementClick({mouseX:d,mouseY:e,pointXValue:m}),"mousedown"===d3.event.type&&g.elementMouseDown({mouseX:d,mouseY:e,pointXValue:m}),"mouseup"===d3.event.type&&g.elementMouseUp({mouseX:d,mouseY:e,pointXValue:m})}var n=d3.select(this),o=d||960,p=e||400,q=n.selectAll("g.nv-wrap.nv-interactiveLineLayer").data([l]),r=q.enter().append("g").attr("class"," nv-wrap nv-interactiveLineLayer");r.append("g").attr("class","nv-interactiveGuideLine"),i&&(i.on("touchmove",m).on("mousemove",m,!0).on("mouseout",m,!0).on("mousedown",m,!0).on("mouseup",m,!0).on("dblclick",m).on("click",m),b.guideLine=null,b.renderGuideLine=function(c){h&&(b.guideLine&&b.guideLine.attr("x1")===c||a.dom.write(function(){var b=q.select(".nv-interactiveGuideLine").selectAll("line").data(null!=c?[a.utils.NaNtoZero(c)]:[],String);b.enter().append("line").attr("class","nv-guideline").attr("x1",function(a){return a}).attr("x2",function(a){return a}).attr("y1",p).attr("y2",0),b.exit().remove()}))})})}var c={left:0,top:0},d=null,e=null,f=d3.scale.linear(),g=d3.dispatch("elementMousemove","elementMouseout","elementClick","elementDblclick","elementMouseDown","elementMouseUp"),h=!0,i=null,j=a.models.tooltip(),k=window.ActiveXObject;return j.duration(0).hideDelay(0).hidden(!1),b.dispatch=g,b.tooltip=j,b.margin=function(a){return arguments.length?(c.top="undefined"!=typeof a.top?a.top:c.top,c.left="undefined"!=typeof a.left?a.left:c.left,b):c},b.width=function(a){return arguments.length?(d=a,b):d},b.height=function(a){return arguments.length?(e=a,b):e},b.xScale=function(a){return arguments.length?(f=a,b):f},b.showGuideLine=function(a){return arguments.length?(h=a,b):h},b.svgContainer=function(a){return arguments.length?(i=a,b):i},b},a.interactiveBisect=function(a,b,c){"use strict";if(!(a instanceof Array))return null;var d;d="function"!=typeof c?function(a){return a.x}:c;var e=function(a,b){return d(a)-b},f=d3.bisector(e).left,g=d3.max([0,f(a,b)-1]),h=d(a[g]);if("undefined"==typeof h&&(h=g),h===b)return g;var i=d3.min([g+1,a.length-1]),j=d(a[i]);return"undefined"==typeof j&&(j=i),Math.abs(j-b)>=Math.abs(h-b)?g:i},a.nearestValueIndex=function(a,b,c){"use strict";var d=1/0,e=null;return a.forEach(function(a,f){var g=Math.abs(b-a);null!=a&&d>=g&&c>g&&(d=g,e=f)}),e},a.models.tooltip=function(){"use strict";function b(){if(!l||!l.node()){var a=[1];l=d3.select(document.body).select("#"+d).data(a),l.enter().append("div").attr("class","nvtooltip "+(i?i:"xy-tooltip")).attr("id",d).style("top",0).style("left",0).style("opacity",0).style("position","fixed").selectAll("div, table, td, tr").classed(q,!0).classed(q,!0),l.exit().remove()}}function c(){return n&&w(e)?(a.dom.write(function(){b();var a=u(e);a&&(l.node().innerHTML=a),y()}),c):void 0}var d="nvtooltip-"+Math.floor(1e5*Math.random()),e=null,f="w",g=25,h=0,i=null,j=!0,k=200,l=null,m={left:null,top:null},n=!0,o=100,p=!0,q="nv-pointer-events-none",r=function(a,b){return a},s=function(a){return a},t=function(a,b){return a},u=function(a){if(null===a)return"";var b=d3.select(document.createElement("table"));if(p){var c=b.selectAll("thead").data([a]).enter().append("thead");c.append("tr").append("td").attr("colspan",3).append("strong").classed("x-value",!0).html(s(a.value))}var d=b.selectAll("tbody").data([a]).enter().append("tbody"),e=d.selectAll("tr").data(function(a){return a.series}).enter().append("tr").classed("highlight",function(a){return a.highlight});e.append("td").classed("legend-color-guide",!0).append("div").style("background-color",function(a){return a.color}),e.append("td").classed("key",!0).classed("total",function(a){return!!a.total}).html(function(a,b){return t(a.key,b)}),e.append("td").classed("value",!0).html(function(a,b){return r(a.value,b)}),e.filter(function(a,b){return void 0!==a.percent}).append("td").classed("percent",!0).html(function(a,b){return"("+d3.format("%")(a.percent)+")"}),e.selectAll("td").each(function(a){if(a.highlight){var b=d3.scale.linear().domain([0,1]).range(["#fff",a.color]),c=.6;d3.select(this).style("border-bottom-color",b(c)).style("border-top-color",b(c))}});var f=b.node().outerHTML;return void 0!==a.footer&&(f+=""),f},v=function(){var a={left:null!==d3.event?d3.event.clientX:0,top:null!==d3.event?d3.event.clientY:0};if("none"!=getComputedStyle(document.body).transform){var b=document.body.getBoundingClientRect();a.left-=b.left,a.top-=b.top}return a},w=function(b){if(b&&b.series){if(a.utils.isArray(b.series))return!0;if(a.utils.isObject(b.series))return b.series=[b.series],!0}return!1},x=function(a){var b,c,d,e=l.node().offsetHeight,h=l.node().offsetWidth,i=document.documentElement.clientWidth,j=document.documentElement.clientHeight;switch(f){case"e":b=-h-g,c=-(e/2),a.left+b<0&&(b=g),(d=a.top+c)<0&&(c-=d),(d=a.top+c+e)>j&&(c-=d-j);break;case"w":b=g,c=-(e/2),a.left+b+h>i&&(b=-h-g),(d=a.top+c)<0&&(c-=d),(d=a.top+c+e)>j&&(c-=d-j);break;case"n":b=-(h/2)-5,c=g,a.top+c+e>j&&(c=-e-g),(d=a.left+b)<0&&(b-=d),(d=a.left+b+h)>i&&(b-=d-i);break;case"s":b=-(h/2),c=-e-g,a.top+c<0&&(c=g),(d=a.left+b)<0&&(b-=d),(d=a.left+b+h)>i&&(b-=d-i);break;case"center":b=-(h/2),c=-(e/2);break;default:b=0,c=0}return{left:b,top:c}},y=function(){a.dom.read(function(){var a=v(),b=x(a),c=a.left+b.left,d=a.top+b.top;if(j)l.interrupt().transition().delay(k).duration(0).style("opacity",0);else{var e="translate("+m.left+"px, "+m.top+"px)",f="translate("+Math.round(c)+"px, "+Math.round(d)+"px)",g=d3.interpolateString(e,f),h=l.style("opacity")<.1;l.interrupt().transition().duration(h?0:o).styleTween("transform",function(a){return g},"important").styleTween("-webkit-transform",function(a){return g}).style("-ms-transform",f).style("opacity",1)}m.left=c,m.top=d})};return c.nvPointerEventsClass=q,c.options=a.utils.optionsFunc.bind(c),c._options=Object.create({},{duration:{get:function(){return o},set:function(a){o=a}},gravity:{get:function(){return f},set:function(a){f=a}},distance:{get:function(){return g},set:function(a){g=a}},snapDistance:{get:function(){return h},set:function(a){h=a}},classes:{get:function(){return i},set:function(a){i=a}},enabled:{get:function(){return n},set:function(a){n=a}},hideDelay:{get:function(){return k},set:function(a){k=a}},contentGenerator:{get:function(){return u},set:function(a){u=a}},valueFormatter:{get:function(){return r},set:function(a){r=a}},headerFormatter:{get:function(){return s},set:function(a){s=a}},keyFormatter:{get:function(){return t},set:function(a){t=a}},headerEnabled:{get:function(){return p},set:function(a){p=a}},position:{get:function(){return v},set:function(a){v=a}},chartContainer:{get:function(){return document.body},set:function(b){a.deprecated("chartContainer","feature removed after 1.8.3")}},fixedTop:{get:function(){return null},set:function(b){a.deprecated("fixedTop","feature removed after 1.8.1")}},offset:{get:function(){return{left:0,top:0}},set:function(b){a.deprecated("offset","use chart.tooltip.distance() instead")}},hidden:{get:function(){return j},set:function(a){j!=a&&(j=!!a,c())}},data:{get:function(){return e},set:function(a){a.point&&(a.value=a.point.x,a.series=a.series||{},a.series.value=a.point.y,a.series.color=a.point.color||a.series.color),e=a}},node:{get:function(){return l.node()},set:function(a){}},id:{get:function(){return d},set:function(a){}}}),a.utils.initOptions(c),c},a.utils.windowSize=function(){var a={width:640,height:480};return window.innerWidth&&window.innerHeight?(a.width=window.innerWidth,a.height=window.innerHeight,a):"CSS1Compat"==document.compatMode&&document.documentElement&&document.documentElement.offsetWidth?(a.width=document.documentElement.offsetWidth,a.height=document.documentElement.offsetHeight,a):document.body&&document.body.offsetWidth?(a.width=document.body.offsetWidth,a.height=document.body.offsetHeight,a):a},a.utils.isArray=Array.isArray,a.utils.isObject=function(a){return null!==a&&"object"==typeof a},a.utils.isFunction=function(a){return"function"==typeof a},a.utils.isDate=function(a){return"[object Date]"===toString.call(a)},a.utils.isNumber=function(a){return!isNaN(a)&&"number"==typeof a},a.utils.windowResize=function(b){return window.addEventListener?window.addEventListener("resize",b):a.log("ERROR: Failed to bind to window.resize with: ",b),{callback:b,clear:function(){window.removeEventListener("resize",b)}}},a.utils.getColor=function(b){if(void 0===b)return a.utils.defaultColor();if(a.utils.isArray(b)){var c=d3.scale.ordinal().range(b);return function(a,b){var d=void 0===b?a:b;return a.color||c(d)}}return b},a.utils.defaultColor=function(){return a.utils.getColor(d3.scale.category20().range())},a.utils.customTheme=function(b,c,d){c=c||function(a){return a.key},d=d||d3.scale.category20().range();var e=d.length;return function(f,g){var h=c(f);return a.utils.isFunction(b[h])?b[h]():void 0!==b[h]?b[h]:(e||(e=d.length),e-=1,d[e])}},a.utils.pjax=function(b,c){var d=function(d){d3.html(d,function(d){var e=d3.select(c).node();e.parentNode.replaceChild(d3.select(d).select(c).node(),e),a.utils.pjax(b,c)})};d3.selectAll(b).on("click",function(){history.pushState(this.href,this.textContent,this.href),d(this.href),d3.event.preventDefault()}),d3.select(window).on("popstate",function(){d3.event.state&&d(d3.event.state)})},a.utils.calcApproxTextWidth=function(b){if(a.utils.isFunction(b.style)&&a.utils.isFunction(b.text)){var c=parseInt(b.style("font-size").replace("px",""),10),d=b.text().length;return a.utils.NaNtoZero(d*c*.5)}return 0},a.utils.NaNtoZero=function(b){return!a.utils.isNumber(b)||isNaN(b)||null===b||b===1/0||b===-(1/0)?0:b},d3.selection.prototype.watchTransition=function(a){var b=[this].concat([].slice.call(arguments,1));return a.transition.apply(a,b)},a.utils.renderWatch=function(b,c){if(!(this instanceof a.utils.renderWatch))return new a.utils.renderWatch(b,c);var d=void 0!==c?c:250,e=[],f=this;this.models=function(a){return a=[].slice.call(arguments,0),a.forEach(function(a){a.__rendered=!1,function(a){a.dispatch.on("renderEnd",function(b){a.__rendered=!0,f.renderEnd("model")})}(a),e.indexOf(a)<0&&e.push(a)}),this},this.reset=function(a){void 0!==a&&(d=a),e=[]},this.transition=function(a,b,c){if(b=arguments.length>1?[].slice.call(arguments,1):[],c=b.length>1?b.pop():void 0!==d?d:250,a.__rendered=!1,e.indexOf(a)<0&&e.push(a),0===c)return a.__rendered=!0,a.delay=function(){return this},a.duration=function(){return this},a;0===a.length?a.__rendered=!0:a.every(function(a){return!a.length})?a.__rendered=!0:a.__rendered=!1;var g=0;return a.transition().duration(c).each(function(){++g}).each("end",function(c,d){0===--g&&(a.__rendered=!0,f.renderEnd.apply(this,b))})},this.renderEnd=function(){e.every(function(a){return a.__rendered})&&(e.forEach(function(a){a.__rendered=!1}),b.renderEnd.apply(this,arguments))}},a.utils.deepExtend=function(b){var c=arguments.length>1?[].slice.call(arguments,1):[];c.forEach(function(c){for(var d in c){var e=a.utils.isArray(b[d]),f=a.utils.isObject(b[d]),g=a.utils.isObject(c[d]);f&&!e&&g?a.utils.deepExtend(b[d],c[d]):b[d]=c[d]}})},a.utils.state=function(){if(!(this instanceof a.utils.state))return new a.utils.state;var b={},c=function(){},d=function(){return{}},e=null,f=null;this.dispatch=d3.dispatch("change","set"),this.dispatch.on("set",function(a){c(a,!0)}),this.getter=function(a){return d=a,this},this.setter=function(a,b){return b||(b=function(){}),c=function(c,d){a(c),d&&b()},this},this.init=function(b){e=e||{},a.utils.deepExtend(e,b)};var g=function(){var a=d();if(JSON.stringify(a)===JSON.stringify(b))return!1;for(var c in a)void 0===b[c]&&(b[c]={}),b[c]=a[c],f=!0;return!0};this.update=function(){e&&(c(e,!1),e=null),g.call(this)&&this.dispatch.change(b)}},a.utils.optionsFunc=function(b){return b&&d3.map(b).forEach(function(b,c){a.utils.isFunction(this[b])&&this[b](c)}.bind(this)),this},a.utils.calcTicksX=function(b,c){var d=1,e=0;for(e;ed?f:d}return a.log("Requested number of ticks: ",b),a.log("Calculated max values to be: ",d),b=b>d?b=d-1:b,b=1>b?1:b,b=Math.floor(b),a.log("Calculating tick count as: ",b),b},a.utils.calcTicksY=function(b,c){return a.utils.calcTicksX(b,c)},a.utils.initOption=function(a,b){a._calls&&a._calls[b]?a[b]=a._calls[b]:(a[b]=function(c){return arguments.length?(a._overrides[b]=!0,a._options[b]=c,a):a._options[b]},a["_"+b]=function(c){return arguments.length?(a._overrides[b]||(a._options[b]=c),a):a._options[b]})},a.utils.initOptions=function(b){b._overrides=b._overrides||{};var c=Object.getOwnPropertyNames(b._options||{}),d=Object.getOwnPropertyNames(b._calls||{});c=c.concat(d);for(var e in c)a.utils.initOption(b,c[e])},a.utils.inheritOptionsD3=function(a,b,c){a._d3options=c.concat(a._d3options||[]),c.unshift(b),c.unshift(a),d3.rebind.apply(this,c)},a.utils.arrayUnique=function(a){return a.sort().filter(function(b,c){return!c||b!=a[c-1]})},a.utils.symbolMap=d3.map(),a.utils.symbol=function(){function b(b,e){var f=c.call(this,b,e),g=d.call(this,b,e);return-1!==d3.svg.symbolTypes.indexOf(f)?d3.svg.symbol().type(f).size(g)():a.utils.symbolMap.get(f)(g)}var c,d=64;return b.type=function(a){return arguments.length?(c=d3.functor(a),b):c},b.size=function(a){return arguments.length?(d=d3.functor(a),b):d},b},a.utils.inheritOptions=function(b,c){var d=Object.getOwnPropertyNames(c._options||{}),e=Object.getOwnPropertyNames(c._calls||{}),f=c._inherited||[],g=c._d3options||[],h=d.concat(e).concat(f).concat(g);h.unshift(c),h.unshift(b),d3.rebind.apply(this,h),b._inherited=a.utils.arrayUnique(d.concat(e).concat(f).concat(d).concat(b._inherited||[])),b._d3options=a.utils.arrayUnique(g.concat(b._d3options||[]))},a.utils.initSVG=function(a){a.classed({"nvd3-svg":!0})},a.utils.sanitizeHeight=function(a,b){return a||parseInt(b.style("height"),10)||400},a.utils.sanitizeWidth=function(a,b){return a||parseInt(b.style("width"),10)||960},a.utils.availableHeight=function(b,c,d){return Math.max(0,a.utils.sanitizeHeight(b,c)-d.top-d.bottom)},a.utils.availableWidth=function(b,c,d){return Math.max(0,a.utils.sanitizeWidth(b,c)-d.left-d.right)},a.utils.noData=function(b,c){var d=b.options(),e=d.margin(),f=d.noData(),g=null==f?["No Data Available."]:[f],h=a.utils.availableHeight(null,c,e),i=a.utils.availableWidth(null,c,e),j=e.left+i/2,k=e.top+h/2;c.selectAll("g").remove();var l=c.selectAll(".nv-noData").data(g);l.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),l.attr("x",j).attr("y",k).text(function(a){return a})},a.utils.wrapTicks=function(a,b){a.each(function(){for(var a,c=d3.select(this),d=c.text().split(/\s+/).reverse(),e=[],f=0,g=1.1,h=c.attr("y"),i=parseFloat(c.attr("dy")),j=c.text(null).append("tspan").attr("x",0).attr("y",h).attr("dy",i+"em");a=d.pop();)e.push(a),j.text(e.join(" ")),j.node().getComputedTextLength()>b&&(e.pop(),j.text(e.join(" ")),e=[a],j=c.append("tspan").attr("x",0).attr("y",h).attr("dy",++f*g+i+"em").text(a))})},a.utils.arrayEquals=function(b,c){if(b===c)return!0;if(!b||!c)return!1;if(b.length!=c.length)return!1;for(var d=0,e=b.length;e>d;d++)if(b[d]instanceof Array&&c[d]instanceof Array){if(!a.arrayEquals(b[d],c[d]))return!1}else if(b[d]!=c[d])return!1;return!0},a.models.axis=function(){"use strict";function b(g){return t.reset(),g.each(function(b){var g=d3.select(this);a.utils.initSVG(g);var q=g.selectAll("g.nv-wrap.nv-axis").data([b]),r=q.enter().append("g").attr("class","nvd3 nv-wrap nv-axis"),u=(r.append("g"),q.select("g"));null!==n?c.ticks(n):("top"==c.orient()||"bottom"==c.orient())&&c.ticks(Math.abs(d.range()[1]-d.range()[0])/100),u.watchTransition(t,"axis").call(c),s=s||c.scale();var v=c.tickFormat();null==v&&(v=s.tickFormat());var w=u.selectAll("text.nv-axislabel").data([h||null]);w.exit().remove(),void 0!==p&&u.selectAll("g").select("text").style("font-size",p);var x,y,z;switch(c.orient()){case"top":w.enter().append("text").attr("class","nv-axislabel"),z=0,1===d.range().length?z=m?2*d.range()[0]+d.rangeBand():0:2===d.range().length?z=m?d.range()[0]+d.range()[1]+d.rangeBand():d.range()[1]:d.range().length>2&&(z=d.range()[d.range().length-1]+(d.range()[1]-d.range()[0])),w.attr("text-anchor","middle").attr("y",0).attr("x",z/2),i&&(y=q.selectAll("g.nv-axisMaxMin").data(d.domain()),y.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-x",0==b?"nv-axisMin-x":"nv-axisMax-x"].join(" ")}).append("text"),y.exit().remove(),y.attr("transform",function(b,c){return"translate("+a.utils.NaNtoZero(d(b))+",0)"}).select("text").attr("dy","-0.5em").attr("y",-c.tickPadding()).attr("text-anchor","middle").text(function(a,b){var c=v(a);return(""+c).match("NaN")?"":c}),y.watchTransition(t,"min-max top").attr("transform",function(b,c){return"translate("+a.utils.NaNtoZero(d.range()[c])+",0)"}));break;case"bottom":x=o+36;var A=30,B=0,C=u.selectAll("g").select("text"),D="";if(j%360){C.attr("transform",""),C.each(function(a,b){var c=this.getBoundingClientRect(),d=c.width;B=c.height,d>A&&(A=d)}),D="rotate("+j+" 0,"+(B/2+c.tickPadding())+")";var E=Math.abs(Math.sin(j*Math.PI/180));x=(E?E*A:A)+30,C.attr("transform",D).style("text-anchor",j%360>0?"start":"end")}else l?C.attr("transform",function(a,b){return"translate(0,"+(b%2==0?"0":"12")+")"}):C.attr("transform","translate(0,0)");w.enter().append("text").attr("class","nv-axislabel"),z=0,1===d.range().length?z=m?2*d.range()[0]+d.rangeBand():0:2===d.range().length?z=m?d.range()[0]+d.range()[1]+d.rangeBand():d.range()[1]:d.range().length>2&&(z=d.range()[d.range().length-1]+(d.range()[1]-d.range()[0])),w.attr("text-anchor","middle").attr("y",x).attr("x",z/2),i&&(y=q.selectAll("g.nv-axisMaxMin").data([d.domain()[0],d.domain()[d.domain().length-1]]),y.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-x",0==b?"nv-axisMin-x":"nv-axisMax-x"].join(" ")}).append("text"),y.exit().remove(),y.attr("transform",function(b,c){return"translate("+a.utils.NaNtoZero(d(b)+(m?d.rangeBand()/2:0))+",0)"}).select("text").attr("dy",".71em").attr("y",c.tickPadding()).attr("transform",D).style("text-anchor",j?j%360>0?"start":"end":"middle").text(function(a,b){var c=v(a);return(""+c).match("NaN")?"":c}),y.watchTransition(t,"min-max bottom").attr("transform",function(b,c){return"translate("+a.utils.NaNtoZero(d(b)+(m?d.rangeBand()/2:0))+",0)"}));break;case"right":w.enter().append("text").attr("class","nv-axislabel"),w.style("text-anchor",k?"middle":"begin").attr("transform",k?"rotate(90)":"").attr("y",k?-Math.max(e.right,f)+12-(o||0):-10).attr("x",k?d3.max(d.range())/2:c.tickPadding()),i&&(y=q.selectAll("g.nv-axisMaxMin").data(d.domain()),y.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-y",0==b?"nv-axisMin-y":"nv-axisMax-y"].join(" ")}).append("text").style("opacity",0),y.exit().remove(),y.attr("transform",function(b,c){return"translate(0,"+a.utils.NaNtoZero(d(b))+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",c.tickPadding()).style("text-anchor","start").text(function(a,b){var c=v(a);return(""+c).match("NaN")?"":c}),y.watchTransition(t,"min-max right").attr("transform",function(b,c){return"translate(0,"+a.utils.NaNtoZero(d.range()[c])+")"}).select("text").style("opacity",1));break;case"left":w.enter().append("text").attr("class","nv-axislabel"),w.style("text-anchor",k?"middle":"end").attr("transform",k?"rotate(-90)":"").attr("y",k?-Math.max(e.left,f)+25-(o||0):-10).attr("x",k?-d3.max(d.range())/2:-c.tickPadding()),i&&(y=q.selectAll("g.nv-axisMaxMin").data(d.domain()),y.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-y",0==b?"nv-axisMin-y":"nv-axisMax-y"].join(" ")}).append("text").style("opacity",0),y.exit().remove(),y.attr("transform",function(b,c){return"translate(0,"+a.utils.NaNtoZero(s(b))+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",-c.tickPadding()).attr("text-anchor","end").text(function(a,b){var c=v(a);return(""+c).match("NaN")?"":c}),y.watchTransition(t,"min-max right").attr("transform",function(b,c){return"translate(0,"+a.utils.NaNtoZero(d.range()[c])+")"}).select("text").style("opacity",1))}if(w.text(function(a){return a}),!i||"left"!==c.orient()&&"right"!==c.orient()||(u.selectAll("g").each(function(a,b){d3.select(this).select("text").attr("opacity",1),(d(a)d.range()[0]-10)&&((a>1e-10||-1e-10>a)&&d3.select(this).attr("opacity",0),d3.select(this).select("text").attr("opacity",0))}),d.domain()[0]==d.domain()[1]&&0==d.domain()[0]&&q.selectAll("g.nv-axisMaxMin").style("opacity",function(a,b){return b?0:1})),i&&("top"===c.orient()||"bottom"===c.orient())){var F=[];q.selectAll("g.nv-axisMaxMin").each(function(a,b){try{b?F.push(d(a)-this.getBoundingClientRect().width-4):F.push(d(a)+this.getBoundingClientRect().width+4)}catch(c){b?F.push(d(a)-4):F.push(d(a)+4)}}),u.selectAll("g").each(function(a,b){(d(a)F[1])&&(a>1e-10||-1e-10>a?d3.select(this).remove():d3.select(this).select("text").remove())})}u.selectAll(".tick").filter(function(a){return!parseFloat(Math.round(1e5*a)/1e6)&&void 0!==a}).classed("zero",!0),s=d.copy()}),t.renderEnd("axis immediate"),b}var c=d3.svg.axis(),d=d3.scale.linear(),e={top:0,right:0,bottom:0,left:0},f=75,g=60,h=null,i=!0,j=0,k=!0,l=!1,m=!1,n=null,o=0,p=void 0,q=250,r=d3.dispatch("renderEnd");c.scale(d).orient("bottom").tickFormat(function(a){return a});var s,t=a.utils.renderWatch(r,q);return b.axis=c,b.dispatch=r,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{axisLabelDistance:{get:function(){return o},set:function(a){o=a}},staggerLabels:{get:function(){return l},set:function(a){l=a}},rotateLabels:{get:function(){return j},set:function(a){j=a}},rotateYLabel:{get:function(){return k},set:function(a){k=a}},showMaxMin:{get:function(){return i},set:function(a){i=a}},axisLabel:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return g},set:function(a){g=a}},ticks:{get:function(){return n},set:function(a){n=a}},width:{get:function(){return f},set:function(a){f=a}},fontSize:{get:function(){return p},set:function(a){p=a}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}},duration:{get:function(){return q},set:function(a){q=a,t.reset(q)}},scale:{get:function(){return d},set:function(e){d=e,c.scale(d),m="function"==typeof d.rangeBands,a.utils.inheritOptionsD3(b,d,["domain","range","rangeBand","rangeBands"])}}}),a.utils.initOptions(b),a.utils.inheritOptionsD3(b,c,["orient","tickValues","tickSubdivide","tickSize","tickPadding","tickFormat"]),a.utils.inheritOptionsD3(b,d,["domain","range","rangeBand","rangeBands"]),b},a.models.boxPlot=function(){"use strict";function b(l){return E.reset(),l.each(function(b){var l=j-i.left-i.right,F=k-i.top-i.bottom;A=d3.select(this),a.utils.initSVG(A),m.domain(c||b.map(function(a,b){return o(a,b)})).rangeBands(d||[0,l],.1);var G=[];if(!e){var H,I,J=[];b.forEach(function(a,b){var c=p(a),d=r(a),e=s(a),f=t(a),g=v(a);g&&g.forEach(function(a,b){J.push(w(a,b,void 0))}),e&&J.push(e),c&&J.push(c),d&&J.push(d),f&&J.push(f)}),H=d3.min(J),I=d3.max(J),G=[H,I]}n.domain(e||G),n.range(f||[F,0]),g=g||m,h=h||n.copy().range([n(0),n(0)]);var K=A.selectAll("g.nv-wrap").data([b]);K.enter().append("g").attr("class","nvd3 nv-wrap");K.attr("transform","translate("+i.left+","+i.top+")");var L=K.selectAll(".nv-boxplot").data(function(a){return a}),M=L.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6);L.attr("class","nv-boxplot").attr("transform",function(a,b,c){return"translate("+(m(o(a,b))+.05*m.rangeBand())+", 0)"}).classed("hover",function(a){return a.hover}),L.watchTransition(E,"nv-boxplot: boxplots").style("stroke-opacity",1).style("fill-opacity",.75).delay(function(a,c){return c*C/b.length}).attr("transform",function(a,b){return"translate("+(m(o(a,b))+.05*m.rangeBand())+", 0)"}),L.exit().remove(),M.each(function(a,b){var c=d3.select(this);[s,t].forEach(function(d){if(void 0!==d(a)&&null!==d(a)){var e=d===s?"low":"high";c.append("line").style("stroke",u(a)||z(a,b)).attr("class","nv-boxplot-whisker nv-boxplot-"+e),c.append("line").style("stroke",u(a)||z(a,b)).attr("class","nv-boxplot-tick nv-boxplot-"+e)}})});var N=function(){return null===D?.9*m.rangeBand():Math.min(75,.9*m.rangeBand())},O=function(){return.45*m.rangeBand()-N()/2},P=function(){return.45*m.rangeBand()+N()/2};[s,t].forEach(function(a){var b=a===s?"low":"high",c=a===s?p:r;L.select("line.nv-boxplot-whisker.nv-boxplot-"+b).watchTransition(E,"nv-boxplot: boxplots").attr("x1",.45*m.rangeBand()).attr("y1",function(b,c){return n(a(b))}).attr("x2",.45*m.rangeBand()).attr("y2",function(a,b){return n(c(a))}),L.select("line.nv-boxplot-tick.nv-boxplot-"+b).watchTransition(E,"nv-boxplot: boxplots").attr("x1",O).attr("y1",function(b,c){return n(a(b))}).attr("x2",P).attr("y2",function(b,c){return n(a(b))})}),[s,t].forEach(function(a){var b=a===s?"low":"high";M.selectAll(".nv-boxplot-"+b).on("mouseover",function(b,c,d){d3.select(this).classed("hover",!0),B.elementMouseover({series:{key:a(b),color:u(b)||z(b,d)},e:d3.event})}).on("mouseout",function(b,c,d){d3.select(this).classed("hover",!1),B.elementMouseout({series:{key:a(b),color:u(b)||z(b,d)},e:d3.event})}).on("mousemove",function(a,b){B.elementMousemove({e:d3.event})})}),M.append("rect").attr("class","nv-boxplot-box").on("mouseover",function(a,b){d3.select(this).classed("hover",!0),B.elementMouseover({key:o(a),value:o(a),series:[{key:"Q3",value:r(a),color:u(a)||z(a,b)},{key:"Q2",value:q(a),color:u(a)||z(a,b)},{key:"Q1",value:p(a),color:u(a)||z(a,b)}],data:a,index:b,e:d3.event})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),B.elementMouseout({key:o(a),value:o(a),series:[{key:"Q3",value:r(a),color:u(a)||z(a,b)},{key:"Q2",value:q(a),color:u(a)||z(a,b)},{key:"Q1",value:p(a),color:u(a)||z(a,b)}],data:a,index:b,e:d3.event})}).on("mousemove",function(a,b){B.elementMousemove({e:d3.event})}),L.select("rect.nv-boxplot-box").watchTransition(E,"nv-boxplot: boxes").attr("y",function(a,b){return n(r(a))}).attr("width",N).attr("x",O).attr("height",function(a,b){return Math.abs(n(r(a))-n(p(a)))||1}).style("fill",function(a,b){return u(a)||z(a,b)}).style("stroke",function(a,b){return u(a)||z(a,b)}),M.append("line").attr("class","nv-boxplot-median"),L.select("line.nv-boxplot-median").watchTransition(E,"nv-boxplot: boxplots line").attr("x1",O).attr("y1",function(a,b){return n(q(a))}).attr("x2",P).attr("y2",function(a,b){return n(q(a))});var Q=L.selectAll(".nv-boxplot-outlier").data(function(a){return v(a)||[]});Q.enter().append("circle").style("fill",function(a,b,c){return y(a,b,c)||z(a,c)}).style("stroke",function(a,b,c){return y(a,b,c)||z(a,c)}).style("z-index",9e3).on("mouseover",function(a,b,c){d3.select(this).classed("hover",!0),B.elementMouseover({series:{key:x(a,b,c),color:y(a,b,c)||z(a,c)},e:d3.event})}).on("mouseout",function(a,b,c){d3.select(this).classed("hover",!1),B.elementMouseout({series:{key:x(a,b,c),color:y(a,b,c)||z(a,c)},e:d3.event})}).on("mousemove",function(a,b){B.elementMousemove({e:d3.event})}),Q.attr("class","nv-boxplot-outlier"),Q.watchTransition(E,"nv-boxplot: nv-boxplot-outlier").attr("cx",.45*m.rangeBand()).attr("cy",function(a,b,c){return n(w(a,b,c))}).attr("r","3"),Q.exit().remove(),g=m.copy(),h=n.copy()}),E.renderEnd("nv-boxplot immediate"),b}var c,d,e,f,g,h,i={top:0,right:0,bottom:0,left:0},j=960,k=500,l=Math.floor(1e4*Math.random()),m=d3.scale.ordinal(),n=d3.scale.linear(),o=function(a){return a.label},p=function(a){return a.values.Q1},q=function(a){return a.values.Q2},r=function(a){return a.values.Q3},s=function(a){return a.values.whisker_low},t=function(a){return a.values.whisker_high},u=function(a){return a.color},v=function(a){return a.values.outliers},w=function(a,b,c){return a},x=function(a,b,c){return a},y=function(a,b,c){return void 0},z=a.utils.defaultColor(),A=null,B=d3.dispatch("elementMouseover","elementMouseout","elementMousemove","renderEnd"),C=250,D=null,E=a.utils.renderWatch(B,C);return b.dispatch=B,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return j},set:function(a){j=a}},height:{get:function(){return k},set:function(a){k=a}},maxBoxWidth:{get:function(){return D},set:function(a){D=a}},x:{get:function(){return o},set:function(a){o=a}},q1:{get:function(){return p},set:function(a){p=a}},q2:{get:function(){return q},set:function(a){q=a}},q3:{get:function(){return r},set:function(a){r=a}},wl:{get:function(){return s},set:function(a){s=a}},wh:{get:function(){return t},set:function(a){t=a}},itemColor:{get:function(){return u},set:function(a){u=a}},outliers:{get:function(){return v},set:function(a){ -v=a}},outlierValue:{get:function(){return w},set:function(a){w=a}},outlierLabel:{get:function(){return x},set:function(a){x=a}},outlierColor:{get:function(){return y},set:function(a){y=a}},xScale:{get:function(){return m},set:function(a){m=a}},yScale:{get:function(){return n},set:function(a){n=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return d},set:function(a){d=a}},yRange:{get:function(){return f},set:function(a){f=a}},id:{get:function(){return l},set:function(a){l=a}},y:{get:function(){return console.warn("BoxPlot 'y' chart option is deprecated. Please use model overrides instead."),{}},set:function(a){console.warn("BoxPlot 'y' chart option is deprecated. Please use model overrides instead.")}},margin:{get:function(){return i},set:function(a){i.top=void 0!==a.top?a.top:i.top,i.right=void 0!==a.right?a.right:i.right,i.bottom=void 0!==a.bottom?a.bottom:i.bottom,i.left=void 0!==a.left?a.left:i.left}},color:{get:function(){return z},set:function(b){z=a.utils.getColor(b)}},duration:{get:function(){return C},set:function(a){C=a,E.reset(C)}}}),a.utils.initOptions(b),b},a.models.boxPlotChart=function(){"use strict";function b(k){return t.reset(),t.models(e),l&&t.models(f),m&&t.models(g),k.each(function(k){var p=d3.select(this);a.utils.initSVG(p);var t=(i||parseInt(p.style("width"))||960)-h.left-h.right,u=(j||parseInt(p.style("height"))||400)-h.top-h.bottom;if(b.update=function(){r.beforeUpdate(),p.transition().duration(s).call(b)},b.container=this,!k||!k.length){var v=p.selectAll(".nv-noData").data([q]);return v.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),v.attr("x",h.left+t/2).attr("y",h.top+u/2).text(function(a){return a}),b}p.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale().clamp(!0);var w=p.selectAll("g.nv-wrap.nv-boxPlotWithAxes").data([k]),x=w.enter().append("g").attr("class","nvd3 nv-wrap nv-boxPlotWithAxes").append("g"),y=x.append("defs"),z=w.select("g");x.append("g").attr("class","nv-x nv-axis"),x.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),x.append("g").attr("class","nv-barsWrap"),z.attr("transform","translate("+h.left+","+h.top+")"),n&&z.select(".nv-y.nv-axis").attr("transform","translate("+t+",0)"),e.width(t).height(u);var A=z.select(".nv-barsWrap").datum(k.filter(function(a){return!a.disabled}));if(A.transition().call(e),y.append("clipPath").attr("id","nv-x-label-clip-"+e.id()).append("rect"),z.select("#nv-x-label-clip-"+e.id()+" rect").attr("width",c.rangeBand()*(o?2:1)).attr("height",16).attr("x",-c.rangeBand()/(o?1:2)),l){f.scale(c).ticks(a.utils.calcTicksX(t/100,k)).tickSize(-u,0),z.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),z.select(".nv-x.nv-axis").call(f);var B=z.select(".nv-x.nv-axis").selectAll("g");o&&B.selectAll("text").attr("transform",function(a,b,c){return"translate(0,"+(c%2===0?"5":"17")+")"})}m&&(g.scale(d).ticks(Math.floor(u/36)).tickSize(-t,0),z.select(".nv-y.nv-axis").call(g)),z.select(".nv-zeroLine line").attr("x1",0).attr("x2",t).attr("y1",d(0)).attr("y2",d(0))}),t.renderEnd("nv-boxplot chart immediate"),b}var c,d,e=a.models.boxPlot(),f=a.models.axis(),g=a.models.axis(),h={top:15,right:10,bottom:50,left:60},i=null,j=null,k=a.utils.getColor(),l=!0,m=!0,n=!1,o=!1,p=a.models.tooltip(),q="No Data Available.",r=d3.dispatch("beforeUpdate","renderEnd"),s=250;f.orient("bottom").showMaxMin(!1).tickFormat(function(a){return a}),g.orient(n?"right":"left").tickFormat(d3.format(",.1f")),p.duration(0);var t=a.utils.renderWatch(r,s);return e.dispatch.on("elementMouseover.tooltip",function(a){p.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(a){p.data(a).hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(a){p()}),b.dispatch=r,b.boxplot=e,b.xAxis=f,b.yAxis=g,b.tooltip=p,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return i},set:function(a){i=a}},height:{get:function(){return j},set:function(a){j=a}},staggerLabels:{get:function(){return o},set:function(a){o=a}},showXAxis:{get:function(){return l},set:function(a){l=a}},showYAxis:{get:function(){return m},set:function(a){m=a}},tooltipContent:{get:function(){return p},set:function(a){p=a}},noData:{get:function(){return q},set:function(a){q=a}},margin:{get:function(){return h},set:function(a){h.top=void 0!==a.top?a.top:h.top,h.right=void 0!==a.right?a.right:h.right,h.bottom=void 0!==a.bottom?a.bottom:h.bottom,h.left=void 0!==a.left?a.left:h.left}},duration:{get:function(){return s},set:function(a){s=a,t.reset(s),e.duration(s),f.duration(s),g.duration(s)}},color:{get:function(){return k},set:function(b){k=a.utils.getColor(b),e.color(k)}},rightAlignYAxis:{get:function(){return n},set:function(a){n=a,g.orient(a?"right":"left")}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.bullet=function(){"use strict";function b(a,b){var c=a.slice();a.sort(function(a,d){var e=c.indexOf(a),f=c.indexOf(d);return d3.descending(b[e],b[f])})}function c(e){return e.each(function(c,e){var s=p-d.left-d.right,y=q-d.top-d.bottom;r=d3.select(this),a.utils.initSVG(r);var z=g.call(this,c,e).slice(),A=h.call(this,c,e).slice(),B=i.call(this,c,e).slice(),C=j.call(this,c,e).slice(),D=k.call(this,c,e).slice(),E=l.call(this,c,e).slice(),F=m.call(this,c,e).slice(),G=n.call(this,c,e).slice();b(D,z),b(E,A),b(F,B),b(G,C),z.sort(d3.descending),A.sort(d3.descending),B.sort(d3.descending),C.sort(d3.descending);var H=d3.scale.linear().domain(d3.extent(d3.merge([o,z]))).range(f?[s,0]:[0,s]);this.__chart__||d3.scale.linear().domain([0,1/0]).range(H.range());this.__chart__=H;for(var I=(d3.min(z),d3.max(z),z[1],r.selectAll("g.nv-wrap.nv-bullet").data([c])),J=I.enter().append("g").attr("class","nvd3 nv-wrap nv-bullet"),K=J.append("g"),L=I.select("g"),e=0,M=z.length;M>e;e++){var N="nv-range nv-range"+e;2>=e&&(N=N+" nv-range"+w[e]),K.append("rect").attr("class",N)}K.append("rect").attr("class","nv-measure"),I.attr("transform","translate("+d.left+","+d.top+")");for(var O=function(a){return Math.abs(H(a)-H(0))},P=function(a){return H(0>a?a:0)},e=0,M=z.length;M>e;e++){var Q=z[e];L.select("rect.nv-range"+e).datum(Q).attr("height",y).transition().duration(x).attr("width",O(Q)).attr("x",P(Q))}L.select("rect.nv-measure").style("fill",t).attr("height",y/3).attr("y",y/3).on("mouseover",function(){u.elementMouseover({value:C[0],label:G[0]||"Current",color:d3.select(this).style("fill")})}).on("mousemove",function(){u.elementMousemove({value:C[0],label:G[0]||"Current",color:d3.select(this).style("fill")})}).on("mouseout",function(){u.elementMouseout({value:C[0],label:G[0]||"Current",color:d3.select(this).style("fill")})}).transition().duration(x).attr("width",0>C?H(0)-H(C[0]):H(C[0])-H(0)).attr("x",P(C));var R=y/6,S=A.map(function(a,b){return{value:a,label:E[b]}});K.selectAll("path.nv-markerTriangle").data(S).enter().append("path").attr("class","nv-markerTriangle").attr("d","M0,"+R+"L"+R+","+-R+" "+-R+","+-R+"Z").on("mouseover",function(a){u.elementMouseover({value:a.value,label:a.label||"Previous",color:d3.select(this).style("fill"),pos:[H(a.value),y/2]})}).on("mousemove",function(a){u.elementMousemove({value:a.value,label:a.label||"Previous",color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){u.elementMouseout({value:a.value,label:a.label||"Previous",color:d3.select(this).style("fill")})}),L.selectAll("path.nv-markerTriangle").data(S).transition().duration(x).attr("transform",function(a){return"translate("+H(a.value)+","+y/2+")"});var T=B.map(function(a,b){return{value:a,label:F[b]}});K.selectAll("line.nv-markerLine").data(T).enter().append("line").attr("cursor","").attr("class","nv-markerLine").attr("x1",function(a){return H(a.value)}).attr("y1","2").attr("x2",function(a){return H(a.value)}).attr("y2",y-2).on("mouseover",function(a){u.elementMouseover({value:a.value,label:a.label||"Previous",color:d3.select(this).style("fill"),pos:[H(a.value),y/2]})}).on("mousemove",function(a){u.elementMousemove({value:a.value,label:a.label||"Previous",color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){u.elementMouseout({value:a.value,label:a.label||"Previous",color:d3.select(this).style("fill")})}),L.selectAll("line.nv-markerLine").data(T).transition().duration(x).attr("x1",function(a){return H(a.value)}).attr("x2",function(a){return H(a.value)}),I.selectAll(".nv-range").on("mouseover",function(a,b){var c=D[b]||v[b];u.elementMouseover({value:a,label:c,color:d3.select(this).style("fill")})}).on("mousemove",function(){u.elementMousemove({value:C[0],label:G[0]||"Previous",color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){var c=D[b]||v[b];u.elementMouseout({value:a,label:c,color:d3.select(this).style("fill")})})}),c}var d={top:0,right:0,bottom:0,left:0},e="left",f=!1,g=function(a){return a.ranges},h=function(a){return a.markers?a.markers:[]},i=function(a){return a.markerLines?a.markerLines:[0]},j=function(a){return a.measures},k=function(a){return a.rangeLabels?a.rangeLabels:[]},l=function(a){return a.markerLabels?a.markerLabels:[]},m=function(a){return a.markerLineLabels?a.markerLineLabels:[]},n=function(a){return a.measureLabels?a.measureLabels:[]},o=[0],p=380,q=30,r=null,s=null,t=a.utils.getColor(["#1f77b4"]),u=d3.dispatch("elementMouseover","elementMouseout","elementMousemove"),v=["Maximum","Mean","Minimum"],w=["Max","Avg","Min"],x=1e3;return c.dispatch=u,c.options=a.utils.optionsFunc.bind(c),c._options=Object.create({},{ranges:{get:function(){return g},set:function(a){g=a}},markers:{get:function(){return h},set:function(a){h=a}},measures:{get:function(){return j},set:function(a){j=a}},forceX:{get:function(){return o},set:function(a){o=a}},width:{get:function(){return p},set:function(a){p=a}},height:{get:function(){return q},set:function(a){q=a}},tickFormat:{get:function(){return s},set:function(a){s=a}},duration:{get:function(){return x},set:function(a){x=a}},margin:{get:function(){return d},set:function(a){d.top=void 0!==a.top?a.top:d.top,d.right=void 0!==a.right?a.right:d.right,d.bottom=void 0!==a.bottom?a.bottom:d.bottom,d.left=void 0!==a.left?a.left:d.left}},orient:{get:function(){return e},set:function(a){e=a,f="right"==e||"bottom"==e}},color:{get:function(){return t},set:function(b){t=a.utils.getColor(b)}}}),a.utils.initOptions(c),c},a.models.bulletChart=function(){"use strict";function b(d){return d.each(function(e,o){var p=d3.select(this);a.utils.initSVG(p);var q=a.utils.availableWidth(k,p,g),r=l-g.top-g.bottom;if(b.update=function(){b(d)},b.container=this,!e||!h.call(this,e,o))return a.utils.noData(b,p),b;p.selectAll(".nv-noData").remove();var s=h.call(this,e,o).slice().sort(d3.descending),t=i.call(this,e,o).slice().sort(d3.descending),u=j.call(this,e,o).slice().sort(d3.descending),v=p.selectAll("g.nv-wrap.nv-bulletChart").data([e]),w=v.enter().append("g").attr("class","nvd3 nv-wrap nv-bulletChart"),x=w.append("g"),y=v.select("g");x.append("g").attr("class","nv-bulletWrap"),x.append("g").attr("class","nv-titles"),v.attr("transform","translate("+g.left+","+g.top+")");var z=d3.scale.linear().domain([0,Math.max(s[0],t[0]||0,u[0])]).range(f?[q,0]:[0,q]),A=this.__chart__||d3.scale.linear().domain([0,1/0]).range(z.range());this.__chart__=z;var B=x.select(".nv-titles").append("g").attr("text-anchor","end").attr("transform","translate(-6,"+(l-g.top-g.bottom)/2+")");B.append("text").attr("class","nv-title").text(function(a){return a.title}),B.append("text").attr("class","nv-subtitle").attr("dy","1em").text(function(a){return a.subtitle}),c.width(q).height(r);var C=y.select(".nv-bulletWrap");d3.transition(C).call(c);var D=m||z.tickFormat(q/100),E=y.selectAll("g.nv-tick").data(z.ticks(n?n:q/50),function(a){return this.textContent||D(a)}),F=E.enter().append("g").attr("class","nv-tick").attr("transform",function(a){return"translate("+A(a)+",0)"}).style("opacity",1e-6);F.append("line").attr("y1",r).attr("y2",7*r/6),F.append("text").attr("text-anchor","middle").attr("dy","1em").attr("y",7*r/6).text(D);var G=d3.transition(E).transition().duration(c.duration()).attr("transform",function(a){return"translate("+z(a)+",0)"}).style("opacity",1);G.select("line").attr("y1",r).attr("y2",7*r/6),G.select("text").attr("y",7*r/6),d3.transition(E.exit()).transition().duration(c.duration()).attr("transform",function(a){return"translate("+z(a)+",0)"}).style("opacity",1e-6).remove()}),d3.timer.flush(),b}var c=a.models.bullet(),d=a.models.tooltip(),e="left",f=!1,g={top:5,right:40,bottom:20,left:120},h=function(a){return a.ranges},i=function(a){return a.markers?a.markers:[]},j=function(a){return a.measures},k=null,l=55,m=null,n=null,o=null,p=d3.dispatch();return d.duration(0).headerEnabled(!1),c.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:a.label,value:a.value,color:a.color},d.data(a).hidden(!1)}),c.dispatch.on("elementMouseout.tooltip",function(a){d.hidden(!0)}),c.dispatch.on("elementMousemove.tooltip",function(a){d()}),b.bullet=c,b.dispatch=p,b.tooltip=d,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{ranges:{get:function(){return h},set:function(a){h=a}},markers:{get:function(){return i},set:function(a){i=a}},measures:{get:function(){return j},set:function(a){j=a}},width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},tickFormat:{get:function(){return m},set:function(a){m=a}},ticks:{get:function(){return n},set:function(a){n=a}},noData:{get:function(){return o},set:function(a){o=a}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},orient:{get:function(){return e},set:function(a){e=a,f="right"==e||"bottom"==e}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.candlestickBar=function(){"use strict";function b(x){return x.each(function(b){c=d3.select(this);var x=a.utils.availableWidth(i,c,h),y=a.utils.availableHeight(j,c,h);a.utils.initSVG(c);var A=x/b[0].values.length*.45;l.domain(d||d3.extent(b[0].values.map(n).concat(t))),v?l.range(f||[.5*x/b[0].values.length,x*(b[0].values.length-.5)/b[0].values.length]):l.range(f||[5+A/2,x-A/2-5]),m.domain(e||[d3.min(b[0].values.map(s).concat(u)),d3.max(b[0].values.map(r).concat(u))]).range(g||[y,0]),l.domain()[0]===l.domain()[1]&&(l.domain()[0]?l.domain([l.domain()[0]-.01*l.domain()[0],l.domain()[1]+.01*l.domain()[1]]):l.domain([-1,1])),m.domain()[0]===m.domain()[1]&&(m.domain()[0]?m.domain([m.domain()[0]+.01*m.domain()[0],m.domain()[1]-.01*m.domain()[1]]):m.domain([-1,1]));var B=d3.select(this).selectAll("g.nv-wrap.nv-candlestickBar").data([b[0].values]),C=B.enter().append("g").attr("class","nvd3 nv-wrap nv-candlestickBar"),D=C.append("defs"),E=C.append("g"),F=B.select("g");E.append("g").attr("class","nv-ticks"),B.attr("transform","translate("+h.left+","+h.top+")"),c.on("click",function(a,b){z.chartClick({data:a,index:b,pos:d3.event,id:k})}),D.append("clipPath").attr("id","nv-chart-clip-path-"+k).append("rect"),B.select("#nv-chart-clip-path-"+k+" rect").attr("width",x).attr("height",y),F.attr("clip-path",w?"url(#nv-chart-clip-path-"+k+")":"");var G=B.select(".nv-ticks").selectAll(".nv-tick").data(function(a){return a});G.exit().remove();var H=G.enter().append("g");G.attr("class",function(a,b,c){return(p(a,b)>q(a,b)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+c+"-"+b});H.append("line").attr("class","nv-candlestick-lines").attr("transform",function(a,b){return"translate("+l(n(a,b))+",0)"}).attr("x1",0).attr("y1",function(a,b){return m(r(a,b))}).attr("x2",0).attr("y2",function(a,b){return m(s(a,b))}),H.append("rect").attr("class","nv-candlestick-rects nv-bars").attr("transform",function(a,b){return"translate("+(l(n(a,b))-A/2)+","+(m(o(a,b))-(p(a,b)>q(a,b)?m(q(a,b))-m(p(a,b)):0))+")"}).attr("x",0).attr("y",0).attr("width",A).attr("height",function(a,b){var c=p(a,b),d=q(a,b);return c>d?m(d)-m(c):m(c)-m(d)});G.select(".nv-candlestick-lines").transition().attr("transform",function(a,b){return"translate("+l(n(a,b))+",0)"}).attr("x1",0).attr("y1",function(a,b){return m(r(a,b))}).attr("x2",0).attr("y2",function(a,b){return m(s(a,b))}),G.select(".nv-candlestick-rects").transition().attr("transform",function(a,b){return"translate("+(l(n(a,b))-A/2)+","+(m(o(a,b))-(p(a,b)>q(a,b)?m(q(a,b))-m(p(a,b)):0))+")"}).attr("x",0).attr("y",0).attr("width",A).attr("height",function(a,b){var c=p(a,b),d=q(a,b);return c>d?m(d)-m(c):m(c)-m(d)})}),b}var c,d,e,f,g,h={top:0,right:0,bottom:0,left:0},i=null,j=null,k=Math.floor(1e4*Math.random()),l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=function(a){return a.open},q=function(a){return a.close},r=function(a){return a.high},s=function(a){return a.low},t=[],u=[],v=!1,w=!0,x=a.utils.defaultColor(),y=!1,z=d3.dispatch("stateChange","changeState","renderEnd","chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove");return b.highlightPoint=function(a,d){b.clearHighlights(),c.select(".nv-candlestickBar .nv-tick-0-"+a).classed("hover",d)},b.clearHighlights=function(){c.select(".nv-candlestickBar .nv-tick.hover").classed("hover",!1)},b.dispatch=z,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return i},set:function(a){i=a}},height:{get:function(){return j},set:function(a){j=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},forceX:{get:function(){return t},set:function(a){t=a}},forceY:{get:function(){return u},set:function(a){u=a}},padData:{get:function(){return v},set:function(a){v=a}},clipEdge:{get:function(){return w},set:function(a){w=a}},id:{get:function(){return k},set:function(a){k=a}},interactive:{get:function(){return y},set:function(a){y=a}},x:{get:function(){return n},set:function(a){n=a}},y:{get:function(){return o},set:function(a){o=a}},open:{get:function(){return p()},set:function(a){p=a}},close:{get:function(){return q()},set:function(a){q=a}},high:{get:function(){return r},set:function(a){r=a}},low:{get:function(){return s},set:function(a){s=a}},margin:{get:function(){return h},set:function(a){h.top=void 0!=a.top?a.top:h.top,h.right=void 0!=a.right?a.right:h.right,h.bottom=void 0!=a.bottom?a.bottom:h.bottom,h.left=void 0!=a.left?a.left:h.left}},color:{get:function(){return x},set:function(b){x=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.cumulativeLineChart=function(){"use strict";function b(l){return I.reset(),I.models(f),s&&I.models(g),t&&I.models(h),l.each(function(l){function B(a,c){d3.select(b.container).style("cursor","ew-resize")}function F(a,b){H.x=d3.event.x,H.i=Math.round(G.invert(H.x)),L()}function I(a,c){d3.select(b.container).style("cursor","auto"),z.index=H.i,D.stateChange(z)}function L(){ba.data([H]);var a=b.duration();b.duration(0),b.update(),b.duration(a)}var M=d3.select(this);a.utils.initSVG(M),M.classed("nv-chart-"+y,!0);var N=a.utils.availableWidth(p,M,m),O=a.utils.availableHeight(q,M,m);if(b.update=function(){0===E?M.call(b):M.transition().duration(E).call(b)},b.container=this,z.setter(K(l),b.update).getter(J(l)).update(),z.disabled=l.map(function(a){return!!a.disabled}),!A){var P;A={};for(P in z)z[P]instanceof Array?A[P]=z[P].slice(0):A[P]=z[P]}var Q=d3.behavior.drag().on("dragstart",B).on("drag",F).on("dragend",I);if(!(l&&l.length&&l.filter(function(a){return a.values.length}).length))return a.utils.noData(b,M),b;if(M.selectAll(".nv-noData").remove(),d=f.xScale(),e=f.yScale(),x)f.yDomain(null);else{var R=l.filter(function(a){return!a.disabled}).map(function(a,b){var c=d3.extent(a.values,f.y());return c[0]<-.95&&(c[0]=-.95),[(c[0]-c[1])/(1+c[1]),(c[1]-c[0])/(1+c[0])]}),S=[d3.min(R,function(a){return a[0]}),d3.max(R,function(a){return a[1]})];f.yDomain(S)}G.domain([0,l[0].values.length-1]).range([0,N]).clamp(!0);var l=c(H.i,l),T=w?"none":"all",U=M.selectAll("g.nv-wrap.nv-cumulativeLine").data([l]),V=U.enter().append("g").attr("class","nvd3 nv-wrap nv-cumulativeLine").append("g"),W=U.select("g");if(V.append("g").attr("class","nv-interactive"),V.append("g").attr("class","nv-x nv-axis").style("pointer-events","none"),V.append("g").attr("class","nv-y nv-axis"),V.append("g").attr("class","nv-background"),V.append("g").attr("class","nv-linesWrap").style("pointer-events",T),V.append("g").attr("class","nv-avgLinesWrap").style("pointer-events","none"),V.append("g").attr("class","nv-legendWrap"),V.append("g").attr("class","nv-controlsWrap"),r?(i.width(N),W.select(".nv-legendWrap").datum(l).call(i),n||i.height()===m.top||(m.top=i.height(),O=a.utils.availableHeight(q,M,m)),W.select(".nv-legendWrap").attr("transform","translate(0,"+-m.top+")")):W.select(".nv-legendWrap").selectAll("*").remove(),v){var X=[{key:"Re-scale y-axis",disabled:!x}];j.width(140).color(["#444","#444","#444"]).rightAlign(!1).margin({top:5,right:0,bottom:5,left:20}),W.select(".nv-controlsWrap").datum(X).attr("transform","translate(0,"+-m.top+")").call(j)}else W.select(".nv-controlsWrap").selectAll("*").remove();U.attr("transform","translate("+m.left+","+m.top+")"),u&&W.select(".nv-y.nv-axis").attr("transform","translate("+N+",0)");var Y=l.filter(function(a){return a.tempDisabled});U.select(".tempDisabled").remove(),Y.length&&U.append("text").attr("class","tempDisabled").attr("x",N/2).attr("y","-.71em").style("text-anchor","end").text(Y.map(function(a){return a.key}).join(", ")+" values cannot be calculated for this time period."),w&&(k.width(N).height(O).margin({left:m.left,top:m.top}).svgContainer(M).xScale(d),U.select(".nv-interactive").call(k)),V.select(".nv-background").append("rect"),W.select(".nv-background rect").attr("width",N).attr("height",O),f.y(function(a){return a.display.y}).width(N).height(O).color(l.map(function(a,b){return a.color||o(a,b)}).filter(function(a,b){return!l[b].disabled&&!l[b].tempDisabled}));var Z=W.select(".nv-linesWrap").datum(l.filter(function(a){return!a.disabled&&!a.tempDisabled}));Z.call(f),l.forEach(function(a,b){a.seriesIndex=b});var $=l.filter(function(a){return!a.disabled&&!!C(a)}),_=W.select(".nv-avgLinesWrap").selectAll("line").data($,function(a){return a.key}),aa=function(a){var b=e(C(a));return 0>b?0:b>O?O:b};_.enter().append("line").style("stroke-width",2).style("stroke-dasharray","10,10").style("stroke",function(a,b){return f.color()(a,a.seriesIndex)}).attr("x1",0).attr("x2",N).attr("y1",aa).attr("y2",aa),_.style("stroke-opacity",function(a){var b=e(C(a));return 0>b||b>O?0:1}).attr("x1",0).attr("x2",N).attr("y1",aa).attr("y2",aa),_.exit().remove();var ba=Z.selectAll(".nv-indexLine").data([H]);ba.enter().append("rect").attr("class","nv-indexLine").attr("width",3).attr("x",-2).attr("fill","red").attr("fill-opacity",.5).style("pointer-events","all").call(Q),ba.attr("transform",function(a){return"translate("+G(a.i)+",0)"}).attr("height",O),s&&(g.scale(d)._ticks(a.utils.calcTicksX(N/70,l)).tickSize(-O,0),W.select(".nv-x.nv-axis").attr("transform","translate(0,"+e.range()[0]+")"),W.select(".nv-x.nv-axis").call(g)),t&&(h.scale(e)._ticks(a.utils.calcTicksY(O/36,l)).tickSize(-N,0),W.select(".nv-y.nv-axis").call(h)),W.select(".nv-background rect").on("click",function(){H.x=d3.mouse(this)[0],H.i=Math.round(G.invert(H.x)),z.index=H.i,D.stateChange(z),L()}),f.dispatch.on("elementClick",function(a){H.i=a.pointIndex,H.x=G(H.i),z.index=H.i,D.stateChange(z),L()}),j.dispatch.on("legendClick",function(a,c){a.disabled=!a.disabled,x=!a.disabled,z.rescaleY=x,D.stateChange(z),b.update()}),i.dispatch.on("stateChange",function(a){for(var c in a)z[c]=a[c];D.stateChange(z),b.update()}),k.dispatch.on("elementMousemove",function(c){f.clearHighlights();var d,e,i,j=[];if(l.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(g,h){e=a.interactiveBisect(g.values,c.pointXValue,b.x()),f.highlightPoint(h,e,!0);var k=g.values[e];"undefined"!=typeof k&&("undefined"==typeof d&&(d=k),"undefined"==typeof i&&(i=b.xScale()(b.x()(k,e))),j.push({key:g.key,value:b.y()(k,e),color:o(g,g.seriesIndex)}))}),j.length>2){var m=b.yScale().invert(c.mouseY),n=Math.abs(b.yScale().domain()[0]-b.yScale().domain()[1]),p=.03*n,q=a.nearestValueIndex(j.map(function(a){return a.value}),m,p);null!==q&&(j[q].highlight=!0)}var r=g.tickFormat()(b.x()(d,e),e);k.tooltip.valueFormatter(function(a,b){return h.tickFormat()(a)}).data({value:r,series:j})(),k.renderGuideLine(i)}),k.dispatch.on("elementMouseout",function(a){f.clearHighlights()}),D.on("changeState",function(a){"undefined"!=typeof a.disabled&&(l.forEach(function(b,c){b.disabled=a.disabled[c]}),z.disabled=a.disabled),"undefined"!=typeof a.index&&(H.i=a.index,H.x=G(H.i),z.index=a.index,ba.data([H])),"undefined"!=typeof a.rescaleY&&(x=a.rescaleY),b.update()})}),I.renderEnd("cumulativeLineChart immediate"),b}function c(a,b){return L||(L=f.y()),b.map(function(b,c){if(!b.values)return b;var d=b.values[a];if(null==d)return b;var e=L(d,a);return-.95>e&&!F?(b.tempDisabled=!0,b):(b.tempDisabled=!1,b.values=b.values.map(function(a,b){return a.display={y:(L(a,b)-e)/(1+e)},a}),b)})}var d,e,f=a.models.line(),g=a.models.axis(),h=a.models.axis(),i=a.models.legend(),j=a.models.legend(),k=a.interactiveGuideline(),l=a.models.tooltip(),m={top:30,right:30,bottom:50,left:60},n=null,o=a.utils.defaultColor(),p=null,q=null,r=!0,s=!0,t=!0,u=!1,v=!0,w=!1,x=!0,y=f.id(),z=a.utils.state(),A=null,B=null,C=function(a){return a.average},D=d3.dispatch("stateChange","changeState","renderEnd"),E=250,F=!1;z.index=0,z.rescaleY=x,g.orient("bottom").tickPadding(7),h.orient(u?"right":"left"),l.valueFormatter(function(a,b){return h.tickFormat()(a,b)}).headerFormatter(function(a,b){return g.tickFormat()(a,b)}),j.updateState(!1);var G=d3.scale.linear(),H={i:0,x:0},I=a.utils.renderWatch(D,E),J=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),index:H.i,rescaleY:x}}},K=function(a){return function(b){void 0!==b.index&&(H.i=b.index),void 0!==b.rescaleY&&(x=b.rescaleY),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};f.dispatch.on("elementMouseover.tooltip",function(a){var c={x:b.x()(a.point),y:b.y()(a.point),color:a.point.color};a.point=c,l.data(a).hidden(!1)}),f.dispatch.on("elementMouseout.tooltip",function(a){l.hidden(!0)});var L=null;return b.dispatch=D,b.lines=f,b.legend=i,b.controls=j,b.xAxis=g,b.yAxis=h,b.interactiveLayer=k,b.state=z,b.tooltip=l,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return p},set:function(a){p=a}},height:{get:function(){return q},set:function(a){q=a}},rescaleY:{get:function(){return x},set:function(a){x=a}},showControls:{get:function(){return v},set:function(a){v=a}},showLegend:{get:function(){return r},set:function(a){r=a}},average:{get:function(){return C},set:function(a){C=a}},defaultState:{get:function(){return A},set:function(a){A=a}},noData:{get:function(){return B},set:function(a){B=a}},showXAxis:{get:function(){return s},set:function(a){s=a}},showYAxis:{get:function(){return t},set:function(a){t=a}},noErrorCheck:{get:function(){return F},set:function(a){F=a}},margin:{get:function(){return m},set:function(a){void 0!==a.top&&(m.top=a.top,n=a.top),m.right=void 0!==a.right?a.right:m.right,m.bottom=void 0!==a.bottom?a.bottom:m.bottom,m.left=void 0!==a.left?a.left:m.left}},color:{get:function(){return o},set:function(b){o=a.utils.getColor(b),i.color(o)}},useInteractiveGuideline:{get:function(){return w},set:function(a){w=a,a===!0&&(b.interactive(!1),b.useVoronoi(!1))}},rightAlignYAxis:{get:function(){return u},set:function(a){u=a,h.orient(a?"right":"left")}},duration:{get:function(){return E},set:function(a){E=a,f.duration(E),g.duration(E),h.duration(E),I.reset(E)}}}),a.utils.inheritOptions(b,f),a.utils.initOptions(b),b},a.models.discreteBar=function(){"use strict";function b(m){return y.reset(),m.each(function(b){var m=k-j.left-j.right,x=l-j.top-j.bottom;c=d3.select(this),a.utils.initSVG(c),b.forEach(function(a,b){a.values.forEach(function(a){a.series=b})});var z=d&&e?[]:b.map(function(a){return a.values.map(function(a,b){return{x:p(a,b),y:q(a,b),y0:a.y0}})});n.domain(d||d3.merge(z).map(function(a){return a.x})).rangeBands(f||[0,m],.1),o.domain(e||d3.extent(d3.merge(z).map(function(a){return a.y}).concat(r))),t?o.range(g||[x-(o.domain()[0]<0?12:0),o.domain()[1]>0?12:0]):o.range(g||[x,0]),h=h||n,i=i||o.copy().range([o(0),o(0)]);var A=c.selectAll("g.nv-wrap.nv-discretebar").data([b]),B=A.enter().append("g").attr("class","nvd3 nv-wrap nv-discretebar"),C=B.append("g");A.select("g");C.append("g").attr("class","nv-groups"),A.attr("transform","translate("+j.left+","+j.top+")");var D=A.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});D.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),D.exit().watchTransition(y,"discreteBar: exit groups").style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),D.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}),D.watchTransition(y,"discreteBar: groups").style("stroke-opacity",1).style("fill-opacity",.75);var E=D.selectAll("g.nv-bar").data(function(a){return a.values});E.exit().remove();var F=E.enter().append("g").attr("transform",function(a,b,c){return"translate("+(n(p(a,b))+.05*n.rangeBand())+", "+o(0)+")"}).on("mouseover",function(a,b){d3.select(this).classed("hover",!0),v.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),v.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mousemove",function(a,b){v.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){var c=this;v.elementClick({data:a,index:b,color:d3.select(this).style("fill"),event:d3.event,element:c}),d3.event.stopPropagation()}).on("dblclick",function(a,b){v.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()});F.append("rect").attr("height",0).attr("width",.9*n.rangeBand()/b.length),t?(F.append("text").attr("text-anchor","middle"),E.select("text").text(function(a,b){return u(q(a,b))}).watchTransition(y,"discreteBar: bars text").attr("x",.9*n.rangeBand()/2).attr("y",function(a,b){return q(a,b)<0?o(q(a,b))-o(0)+12:-4})):E.selectAll("text").remove(),E.attr("class",function(a,b){return q(a,b)<0?"nv-bar negative":"nv-bar positive"}).style("fill",function(a,b){return a.color||s(a,b)}).style("stroke",function(a,b){return a.color||s(a,b)}).select("rect").attr("class",w).watchTransition(y,"discreteBar: bars rect").attr("width",.9*n.rangeBand()/b.length),E.watchTransition(y,"discreteBar: bars").attr("transform",function(a,b){var c=n(p(a,b))+.05*n.rangeBand(),d=q(a,b)<0?o(0):o(0)-o(q(a,b))<1?o(0)-1:o(q(a,b));return"translate("+c+", "+d+")"}).select("rect").attr("height",function(a,b){return Math.max(Math.abs(o(q(a,b))-o(0)),1)}),h=n.copy(),i=o.copy()}),y.renderEnd("discreteBar immediate"),b}var c,d,e,f,g,h,i,j={top:0,right:0,bottom:0,left:0},k=960,l=500,m=Math.floor(1e4*Math.random()),n=d3.scale.ordinal(),o=d3.scale.linear(),p=function(a){return a.x},q=function(a){return a.y},r=[0],s=a.utils.defaultColor(),t=!1,u=d3.format(",.2f"),v=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),w="discreteBar",x=250,y=a.utils.renderWatch(v,x);return b.dispatch=v,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},forceY:{get:function(){return r},set:function(a){r=a; -}},showValues:{get:function(){return t},set:function(a){t=a}},x:{get:function(){return p},set:function(a){p=a}},y:{get:function(){return q},set:function(a){q=a}},xScale:{get:function(){return n},set:function(a){n=a}},yScale:{get:function(){return o},set:function(a){o=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},valueFormat:{get:function(){return u},set:function(a){u=a}},id:{get:function(){return m},set:function(a){m=a}},rectClass:{get:function(){return w},set:function(a){w=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},color:{get:function(){return s},set:function(b){s=a.utils.getColor(b)}},duration:{get:function(){return x},set:function(a){x=a,y.reset(x)}}}),a.utils.initOptions(b),b},a.models.discreteBarChart=function(){"use strict";function b(i){return y.reset(),y.models(e),p&&y.models(f),q&&y.models(g),i.each(function(i){var n=d3.select(this);a.utils.initSVG(n);var v=a.utils.availableWidth(l,n,j),y=a.utils.availableHeight(m,n,j);if(b.update=function(){w.beforeUpdate(),n.transition().duration(x).call(b)},b.container=this,!(i&&i.length&&i.filter(function(a){return a.values.length}).length))return a.utils.noData(b,n),b;n.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale().clamp(!0);var z=n.selectAll("g.nv-wrap.nv-discreteBarWithAxes").data([i]),A=z.enter().append("g").attr("class","nvd3 nv-wrap nv-discreteBarWithAxes").append("g"),B=A.append("defs"),C=z.select("g");A.append("g").attr("class","nv-x nv-axis"),A.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),A.append("g").attr("class","nv-barsWrap"),A.append("g").attr("class","nv-legendWrap"),C.attr("transform","translate("+j.left+","+j.top+")"),o?(h.width(v),C.select(".nv-legendWrap").datum(i).call(h),k||h.height()===j.top||(j.top=h.height(),y=a.utils.availableHeight(m,n,j)),z.select(".nv-legendWrap").attr("transform","translate(0,"+-j.top+")")):C.select(".nv-legendWrap").selectAll("*").remove(),r&&C.select(".nv-y.nv-axis").attr("transform","translate("+v+",0)"),e.width(v).height(y);var D=C.select(".nv-barsWrap").datum(i.filter(function(a){return!a.disabled}));if(D.transition().call(e),B.append("clipPath").attr("id","nv-x-label-clip-"+e.id()).append("rect"),C.select("#nv-x-label-clip-"+e.id()+" rect").attr("width",c.rangeBand()*(s?2:1)).attr("height",16).attr("x",-c.rangeBand()/(s?1:2)),p){f.scale(c)._ticks(a.utils.calcTicksX(v/100,i)).tickSize(-y,0),C.select(".nv-x.nv-axis").attr("transform","translate(0,"+(d.range()[0]+(e.showValues()&&d.domain()[0]<0?16:0))+")"),C.select(".nv-x.nv-axis").call(f);var E=C.select(".nv-x.nv-axis").selectAll("g");s&&E.selectAll("text").attr("transform",function(a,b,c){return"translate(0,"+(c%2==0?"5":"17")+")"}),u&&E.selectAll(".tick text").attr("transform","rotate("+u+" 0,0)").style("text-anchor",u>0?"start":"end"),t&&C.selectAll(".tick text").call(a.utils.wrapTicks,b.xAxis.rangeBand())}q&&(g.scale(d)._ticks(a.utils.calcTicksY(y/36,i)).tickSize(-v,0),C.select(".nv-y.nv-axis").call(g)),C.select(".nv-zeroLine line").attr("x1",0).attr("x2",r?-v:v).attr("y1",d(0)).attr("y2",d(0))}),y.renderEnd("discreteBar chart immediate"),b}var c,d,e=a.models.discreteBar(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.models.tooltip(),j={top:15,right:10,bottom:50,left:60},k=null,l=null,m=null,n=a.utils.getColor(),o=!1,p=!0,q=!0,r=!1,s=!1,t=!1,u=0,v=null,w=d3.dispatch("beforeUpdate","renderEnd"),x=250;f.orient("bottom").showMaxMin(!1).tickFormat(function(a){return a}),g.orient(r?"right":"left").tickFormat(d3.format(",.1f")),i.duration(0).headerEnabled(!1).valueFormatter(function(a,b){return g.tickFormat()(a,b)}).keyFormatter(function(a,b){return f.tickFormat()(a,b)});var y=a.utils.renderWatch(w,x);return e.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:b.x()(a.data),value:b.y()(a.data),color:a.color},i.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(a){i.hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(a){i()}),b.dispatch=w,b.discretebar=e,b.legend=h,b.xAxis=f,b.yAxis=g,b.tooltip=i,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return l},set:function(a){l=a}},height:{get:function(){return m},set:function(a){m=a}},showLegend:{get:function(){return o},set:function(a){o=a}},staggerLabels:{get:function(){return s},set:function(a){s=a}},rotateLabels:{get:function(){return u},set:function(a){u=a}},wrapLabels:{get:function(){return t},set:function(a){t=!!a}},showXAxis:{get:function(){return p},set:function(a){p=a}},showYAxis:{get:function(){return q},set:function(a){q=a}},noData:{get:function(){return v},set:function(a){v=a}},margin:{get:function(){return j},set:function(a){void 0!==a.top&&(j.top=a.top,k=a.top),j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},duration:{get:function(){return x},set:function(a){x=a,y.reset(x),e.duration(x),f.duration(x),g.duration(x)}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),e.color(n),h.color(n)}},rightAlignYAxis:{get:function(){return r},set:function(a){r=a,g.orient(a?"right":"left")}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.distribution=function(){"use strict";function b(k){return m.reset(),k.each(function(b){var k=(e-("x"===g?d.left+d.right:d.top+d.bottom),"x"==g?"y":"x"),l=d3.select(this);a.utils.initSVG(l),c=c||j;var n=l.selectAll("g.nv-distribution").data([b]),o=n.enter().append("g").attr("class","nvd3 nv-distribution"),p=(o.append("g"),n.select("g"));n.attr("transform","translate("+d.left+","+d.top+")");var q=p.selectAll("g.nv-dist").data(function(a){return a},function(a){return a.key});q.enter().append("g"),q.attr("class",function(a,b){return"nv-dist nv-series-"+b}).style("stroke",function(a,b){return i(a,b)});var r=q.selectAll("line.nv-dist"+g).data(function(a){return a.values});r.enter().append("line").attr(g+"1",function(a,b){return c(h(a,b))}).attr(g+"2",function(a,b){return c(h(a,b))}),m.transition(q.exit().selectAll("line.nv-dist"+g),"dist exit").attr(g+"1",function(a,b){return j(h(a,b))}).attr(g+"2",function(a,b){return j(h(a,b))}).style("stroke-opacity",0).remove(),r.attr("class",function(a,b){return"nv-dist"+g+" nv-dist"+g+"-"+b}).attr(k+"1",0).attr(k+"2",f),m.transition(r,"dist").attr(g+"1",function(a,b){return j(h(a,b))}).attr(g+"2",function(a,b){return j(h(a,b))}),c=j.copy()}),m.renderEnd("distribution immediate"),b}var c,d={top:0,right:0,bottom:0,left:0},e=400,f=8,g="x",h=function(a){return a[g]},i=a.utils.defaultColor(),j=d3.scale.linear(),k=250,l=d3.dispatch("renderEnd"),m=a.utils.renderWatch(l,k);return b.options=a.utils.optionsFunc.bind(b),b.dispatch=l,b.margin=function(a){return arguments.length?(d.top="undefined"!=typeof a.top?a.top:d.top,d.right="undefined"!=typeof a.right?a.right:d.right,d.bottom="undefined"!=typeof a.bottom?a.bottom:d.bottom,d.left="undefined"!=typeof a.left?a.left:d.left,b):d},b.width=function(a){return arguments.length?(e=a,b):e},b.axis=function(a){return arguments.length?(g=a,b):g},b.size=function(a){return arguments.length?(f=a,b):f},b.getData=function(a){return arguments.length?(h=d3.functor(a),b):h},b.scale=function(a){return arguments.length?(j=a,b):j},b.color=function(c){return arguments.length?(i=a.utils.getColor(c),b):i},b.duration=function(a){return arguments.length?(k=a,m.reset(k),b):k},b},a.models.focus=function(b){"use strict";function c(u){return t.reset(),t.models(b),m&&t.models(f),n&&t.models(g),u.each(function(t){function u(a){var b=+("e"==a),c=b?1:-1,d=z/3;return"M"+.5*c+","+d+"A6,6 0 0 "+b+" "+6.5*c+","+(d+6)+"V"+(2*d-6)+"A6,6 0 0 "+b+" "+.5*c+","+2*d+"ZM"+2.5*c+","+(d+8)+"V"+(2*d-8)+"M"+4.5*c+","+(d+8)+"V"+(2*d-8)}function v(){h.empty()||h.extent(p),E.data([h.empty()?d.domain():p]).each(function(a,b){var c=d(a[0])-d.range()[0],e=y-d(a[1]);d3.select(this).select(".left").attr("width",0>c?0:c),d3.select(this).select(".right").attr("x",d(a[1])).attr("width",0>e?0:e)})}function w(a){p=h.empty()?null:h.extent();var b=h.empty()?d.domain():h.extent();r.brush({extent:b,brush:h}),v(),a&&r.onBrush(b)}var x=d3.select(this);a.utils.initSVG(x);var y=a.utils.availableWidth(k,x,i),z=l-i.top-i.bottom;c.update=function(){0===q?x.call(c):x.transition().duration(q).call(c)},c.container=this,d=b.xScale(),e=b.yScale();var A=x.selectAll("g.nv-focus").data([t]),B=A.enter().append("g").attr("class","nvd3 nv-focus").append("g"),C=A.select("g");A.attr("transform","translate("+i.left+","+i.top+")"),B.append("g").attr("class","nv-background").append("rect"),B.append("g").attr("class","nv-x nv-axis"),B.append("g").attr("class","nv-y nv-axis"),B.append("g").attr("class","nv-contentWrap"),B.append("g").attr("class","nv-brushBackground"),B.append("g").attr("class","nv-x nv-brush"),o&&C.select(".nv-y.nv-axis").attr("transform","translate("+y+",0)"),C.select(".nv-background rect").attr("width",y).attr("height",z),b.width(y).height(z).color(t.map(function(a,b){return a.color||j(a,b)}).filter(function(a,b){return!t[b].disabled}));var D=C.select(".nv-contentWrap").datum(t.filter(function(a){return!a.disabled}));d3.transition(D).call(b),h.x(d).on("brush",function(){w(s)}),h.on("brushend",function(){s||r.onBrush(h.empty()?d.domain():h.extent())}),p&&h.extent(p);var E=C.select(".nv-brushBackground").selectAll("g").data([p||h.extent()]),F=E.enter().append("g");F.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",z),F.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",z);var G=C.select(".nv-x.nv-brush").call(h);G.selectAll("rect").attr("height",z),G.selectAll(".resize").append("path").attr("d",u),w(!0),C.select(".nv-background rect").attr("width",y).attr("height",z),m&&(f.scale(d)._ticks(a.utils.calcTicksX(y/100,t)).tickSize(-z,0),C.select(".nv-x.nv-axis").attr("transform","translate(0,"+e.range()[0]+")"),d3.transition(C.select(".nv-x.nv-axis")).call(f)),n&&(g.scale(e)._ticks(a.utils.calcTicksY(z/36,t)).tickSize(-y,0),d3.transition(C.select(".nv-y.nv-axis")).call(g)),C.select(".nv-x.nv-axis").attr("transform","translate(0,"+e.range()[0]+")")}),t.renderEnd("focus immediate"),c}var d,e,b=b||a.models.line(),f=a.models.axis(),g=a.models.axis(),h=d3.svg.brush(),i={top:10,right:0,bottom:30,left:0},j=a.utils.defaultColor(),k=null,l=70,m=!0,n=!1,o=!1,p=null,q=250,r=d3.dispatch("brush","onBrush","renderEnd"),s=!0;b.interactive(!1),b.pointActive(function(a){return!1});var t=a.utils.renderWatch(r,q);return c.dispatch=r,c.content=b,c.brush=h,c.xAxis=f,c.yAxis=g,c.options=a.utils.optionsFunc.bind(c),c._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},showXAxis:{get:function(){return m},set:function(a){m=a}},showYAxis:{get:function(){return n},set:function(a){n=a}},brushExtent:{get:function(){return p},set:function(a){p=a}},syncBrushing:{get:function(){return s},set:function(a){s=a}},margin:{get:function(){return i},set:function(a){i.top=void 0!==a.top?a.top:i.top,i.right=void 0!==a.right?a.right:i.right,i.bottom=void 0!==a.bottom?a.bottom:i.bottom,i.left=void 0!==a.left?a.left:i.left}},duration:{get:function(){return q},set:function(a){q=a,t.reset(q),b.duration(q),f.duration(q),g.duration(q)}},color:{get:function(){return j},set:function(c){j=a.utils.getColor(c),b.color(j)}},interpolate:{get:function(){return b.interpolate()},set:function(a){b.interpolate(a)}},xTickFormat:{get:function(){return f.tickFormat()},set:function(a){f.tickFormat(a)}},yTickFormat:{get:function(){return g.tickFormat()},set:function(a){g.tickFormat(a)}},x:{get:function(){return b.x()},set:function(a){b.x(a)}},y:{get:function(){return b.y()},set:function(a){b.y(a)}},rightAlignYAxis:{get:function(){return o},set:function(a){o=a,g.orient(o?"right":"left")}}}),a.utils.inheritOptions(c,b),a.utils.initOptions(c),c},a.models.forceDirectedGraph=function(){"use strict";function b(g){return u.reset(),g.each(function(g){f=d3.select(this),a.utils.initSVG(f);var j=a.utils.availableWidth(d,f,c),u=a.utils.availableHeight(e,f,c);if(f.attr("width",j).attr("height",u),!(g&&g.links&&g.nodes))return a.utils.noData(b,f),b;f.selectAll(".nv-noData").remove(),f.selectAll("*").remove();var v=new Set;g.nodes.forEach(function(a){var b=Object.keys(a);b.forEach(function(a){v.add(a)})});var w=d3.layout.force().nodes(g.nodes).links(g.links).size([j,u]).linkStrength(k).friction(l).linkDistance(m).charge(n).gravity(o).theta(p).alpha(q).start(),x=f.selectAll(".link").data(g.links).enter().append("line").attr("class","nv-force-link").style("stroke-width",function(a){return Math.sqrt(a.value)}),y=f.selectAll(".node").data(g.nodes).enter().append("g").attr("class","nv-force-node").call(w.drag);y.append("circle").attr("r",r).style("fill",function(a){return h(a)}).on("mouseover",function(a){f.select(".nv-series-"+a.seriesIndex+" .nv-distx-"+a.pointIndex).attr("y1",a.py),f.select(".nv-series-"+a.seriesIndex+" .nv-disty-"+a.pointIndex).attr("x2",a.px);var b=h(a);a.series=[],v.forEach(function(c){a.series.push({color:b,key:c,value:a[c]})}),i.data(a).hidden(!1)}).on("mouseout",function(a){i.hidden(!0)}),i.headerFormatter(function(a){return"Node"}),t(x),s(y),w.on("tick",function(){x.attr("x1",function(a){return a.source.x}).attr("y1",function(a){return a.source.y}).attr("x2",function(a){return a.target.x}).attr("y2",function(a){return a.target.y}),y.attr("transform",function(a){return"translate("+a.x+", "+a.y+")"})})}),b}var c={top:2,right:0,bottom:2,left:0},d=400,e=32,f=null,g=d3.dispatch("renderEnd"),h=a.utils.getColor(["#000"]),i=a.models.tooltip(),j=null,k=.1,l=.9,m=30,n=-120,o=.1,p=.8,q=.1,r=5,s=function(a){},t=function(a){},u=a.utils.renderWatch(g);return b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},linkStrength:{get:function(){return k},set:function(a){k=a}},friction:{get:function(){return l},set:function(a){l=a}},linkDist:{get:function(){return m},set:function(a){m=a}},charge:{get:function(){return n},set:function(a){n=a}},gravity:{get:function(){return o},set:function(a){o=a}},theta:{get:function(){return p},set:function(a){p=a}},alpha:{get:function(){return q},set:function(a){q=a}},radius:{get:function(){return r},set:function(a){r=a}},x:{get:function(){return getX},set:function(a){getX=d3.functor(a)}},y:{get:function(){return getY},set:function(a){getY=d3.functor(a)}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},color:{get:function(){return h},set:function(b){h=a.utils.getColor(b)}},noData:{get:function(){return j},set:function(a){j=a}},nodeExtras:{get:function(){return s},set:function(a){s=a}},linkExtras:{get:function(){return t},set:function(a){t=a}}}),b.dispatch=g,b.tooltip=i,a.utils.initOptions(b),b},a.models.furiousLegend=function(){"use strict";function b(r){function s(a,b){return"furious"!=q?"#000":o?a.disengaged?h(a,b):"#fff":o?void 0:a.disabled?h(a,b):"#fff"}function t(a,b){return o&&"furious"==q?a.disengaged?"#fff":h(a,b):a.disabled?"#fff":h(a,b)}return r.each(function(b){var r=d-c.left-c.right,u=d3.select(this);a.utils.initSVG(u);var v=u.selectAll("g.nv-legend").data([b]),w=(v.enter().append("g").attr("class","nvd3 nv-legend").append("g"),v.select("g"));v.attr("transform","translate("+c.left+","+c.top+")");var x,y=w.selectAll(".nv-series").data(function(a){return"furious"!=q?a:a.filter(function(a){return o?!0:!a.disengaged})}),z=y.enter().append("g").attr("class","nv-series");if("classic"==q)z.append("circle").style("stroke-width",2).attr("class","nv-legend-symbol").attr("r",5),x=y.select("circle");else if("furious"==q){z.append("rect").style("stroke-width",2).attr("class","nv-legend-symbol").attr("rx",3).attr("ry",3),x=y.select("rect"),z.append("g").attr("class","nv-check-box").property("innerHTML",'').attr("transform","translate(-10,-8)scale(0.5)");var A=y.select(".nv-check-box");A.each(function(a,b){d3.select(this).selectAll("path").attr("stroke",s(a,b))})}z.append("text").attr("text-anchor","start").attr("class","nv-legend-text").attr("dy",".32em").attr("dx","8");var B=y.select("text.nv-legend-text");y.on("mouseover",function(a,b){p.legendMouseover(a,b)}).on("mouseout",function(a,b){p.legendMouseout(a,b)}).on("click",function(a,b){p.legendClick(a,b);var c=y.data();if(m){if("classic"==q)n?(c.forEach(function(a){a.disabled=!0}),a.disabled=!1):(a.disabled=!a.disabled,c.every(function(a){return a.disabled})&&c.forEach(function(a){a.disabled=!1}));else if("furious"==q)if(o)a.disengaged=!a.disengaged,a.userDisabled=void 0==a.userDisabled?!!a.disabled:a.userDisabled,a.disabled=a.disengaged||a.userDisabled;else if(!o){a.disabled=!a.disabled,a.userDisabled=a.disabled;var d=c.filter(function(a){return!a.disengaged});d.every(function(a){return a.userDisabled})&&c.forEach(function(a){a.disabled=a.userDisabled=!1})}p.stateChange({disabled:c.map(function(a){return!!a.disabled}),disengaged:c.map(function(a){return!!a.disengaged})})}}).on("dblclick",function(a,b){if(("furious"!=q||!o)&&(p.legendDblclick(a,b),m)){var c=y.data();c.forEach(function(a){a.disabled=!0,"furious"==q&&(a.userDisabled=a.disabled)}),a.disabled=!1,"furious"==q&&(a.userDisabled=a.disabled),p.stateChange({disabled:c.map(function(a){return!!a.disabled})})}}),y.classed("nv-disabled",function(a){return a.userDisabled}),y.exit().remove(),B.attr("fill",s).text(function(a){return g(f(a))});var C;switch(q){case"furious":C=23;break;case"classic":C=20}if(j){var D=[];y.each(function(b,c){var d;if(g(f(b))&&g(f(b)).length>i){var e=g(f(b)).substring(0,i);d=d3.select(this).select("text").text(e+"..."),d3.select(this).append("svg:title").text(g(f(b)))}else d=d3.select(this).select("text");var h;try{if(h=d.node().getComputedTextLength(),0>=h)throw Error()}catch(j){h=a.utils.calcApproxTextWidth(d)}D.push(h+k)});for(var E=0,F=0,G=[];r>F&&Er&&E>1;){G=[],E--;for(var H=0;H(G[H%E]||0)&&(G[H%E]=D[H]);F=G.reduce(function(a,b,c,d){return a+b})}for(var I=[],J=0,K=0;E>J;J++)I[J]=K,K+=G[J];y.attr("transform",function(a,b){return"translate("+I[b%E]+","+(5+Math.floor(b/E)*C)+")"}),l?w.attr("transform","translate("+(d-c.right-F)+","+c.top+")"):w.attr("transform","translate(0,"+c.top+")"),e=c.top+c.bottom+Math.ceil(D.length/E)*C}else{var L,M=5,N=5,O=0;y.attr("transform",function(a,b){var e=d3.select(this).select("text").node().getComputedTextLength()+k;return L=N,dO&&(O=N),"translate("+L+","+M+")"}),w.attr("transform","translate("+(d-c.right-O)+","+c.top+")"),e=c.top+c.bottom+M+15}"furious"==q&&x.attr("width",function(a,b){return B[0][b].getComputedTextLength()+27}).attr("height",18).attr("y",-9).attr("x",-15),x.style("fill",t).style("stroke",function(a,b){return a.color||h(a,b)})}),b}var c={top:5,right:0,bottom:5,left:0},d=400,e=20,f=function(a){return a.key},g=function(a){return a},h=a.utils.getColor(),i=20,j=!0,k=28,l=!0,m=!0,n=!1,o=!1,p=d3.dispatch("legendClick","legendDblclick","legendMouseover","legendMouseout","stateChange"),q="classic";return b.dispatch=p,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},key:{get:function(){return f},set:function(a){f=a}},keyFormatter:{get:function(){return g},set:function(a){g=a}},align:{get:function(){return j},set:function(a){j=a}},rightAlign:{get:function(){return l},set:function(a){l=a}},maxKeyLength:{get:function(){return i},set:function(a){i=a}},padding:{get:function(){return k},set:function(a){k=a}},updateState:{get:function(){return m},set:function(a){m=a}},radioButtonMode:{get:function(){return n},set:function(a){n=a}},expanded:{get:function(){return o},set:function(a){o=a}},vers:{get:function(){return q},set:function(a){q=a}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},color:{get:function(){return h},set:function(b){h=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.historicalBar=function(){"use strict";function b(x){return x.each(function(b){w.reset(),k=d3.select(this);var x=a.utils.availableWidth(h,k,g),y=a.utils.availableHeight(i,k,g);a.utils.initSVG(k),l.domain(c||d3.extent(b[0].values.map(n).concat(p))),r?l.range(e||[.5*x/b[0].values.length,x*(b[0].values.length-.5)/b[0].values.length]):l.range(e||[0,x]),m.domain(d||d3.extent(b[0].values.map(o).concat(q))).range(f||[y,0]),l.domain()[0]===l.domain()[1]&&(l.domain()[0]?l.domain([l.domain()[0]-.01*l.domain()[0],l.domain()[1]+.01*l.domain()[1]]):l.domain([-1,1])),m.domain()[0]===m.domain()[1]&&(m.domain()[0]?m.domain([m.domain()[0]+.01*m.domain()[0],m.domain()[1]-.01*m.domain()[1]]):m.domain([-1,1]));var z=k.selectAll("g.nv-wrap.nv-historicalBar-"+j).data([b[0].values]),A=z.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBar-"+j),B=A.append("defs"),C=A.append("g"),D=z.select("g");C.append("g").attr("class","nv-bars"),z.attr("transform","translate("+g.left+","+g.top+")"),k.on("click",function(a,b){u.chartClick({data:a,index:b,pos:d3.event,id:j})}),B.append("clipPath").attr("id","nv-chart-clip-path-"+j).append("rect"),z.select("#nv-chart-clip-path-"+j+" rect").attr("width",x).attr("height",y),D.attr("clip-path",s?"url(#nv-chart-clip-path-"+j+")":"");var E=z.select(".nv-bars").selectAll(".nv-bar").data(function(a){return a},function(a,b){return n(a,b)});E.exit().remove(),E.enter().append("rect").attr("x",0).attr("y",function(b,c){return a.utils.NaNtoZero(m(Math.max(0,o(b,c))))}).attr("height",function(b,c){return a.utils.NaNtoZero(Math.abs(m(o(b,c))-m(0)))}).attr("transform",function(a,c){return"translate("+(l(n(a,c))-x/b[0].values.length*.45)+",0)"}).on("mouseover",function(a,b){v&&(d3.select(this).classed("hover",!0),u.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")}))}).on("mouseout",function(a,b){v&&(d3.select(this).classed("hover",!1),u.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")}))}).on("mousemove",function(a,b){v&&u.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){if(v){var c=this;u.elementClick({data:a,index:b,color:d3.select(this).style("fill"),event:d3.event,element:c}),d3.event.stopPropagation()}}).on("dblclick",function(a,b){v&&(u.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation())}),E.attr("fill",function(a,b){return t(a,b)}).attr("class",function(a,b,c){return(o(a,b)<0?"nv-bar negative":"nv-bar positive")+" nv-bar-"+c+"-"+b}).watchTransition(w,"bars").attr("transform",function(a,c){return"translate("+(l(n(a,c))-x/b[0].values.length*.45)+",0)"}).attr("width",x/b[0].values.length*.9),E.watchTransition(w,"bars").attr("y",function(b,c){var d=o(b,c)<0?m(0):m(0)-m(o(b,c))<1?m(0)-1:m(o(b,c));return a.utils.NaNtoZero(d)}).attr("height",function(b,c){return a.utils.NaNtoZero(Math.max(Math.abs(m(o(b,c))-m(0)),1))})}),w.renderEnd("historicalBar immediate"),b}var c,d,e,f,g={top:0,right:0,bottom:0,left:0},h=null,i=null,j=Math.floor(1e4*Math.random()),k=null,l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=[],q=[0],r=!1,s=!0,t=a.utils.defaultColor(),u=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),v=!0,w=a.utils.renderWatch(u,0);return b.highlightPoint=function(a,b){k.select(".nv-bars .nv-bar-0-"+a).classed("hover",b)},b.clearHighlights=function(){k.select(".nv-bars .nv-bar.hover").classed("hover",!1)},b.dispatch=u,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},forceX:{get:function(){return p},set:function(a){p=a}},forceY:{get:function(){return q},set:function(a){q=a}},padData:{get:function(){return r},set:function(a){r=a}},x:{get:function(){return n},set:function(a){n=a}},y:{get:function(){return o},set:function(a){o=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},clipEdge:{get:function(){return s},set:function(a){s=a}},id:{get:function(){return j},set:function(a){j=a}},interactive:{get:function(){return v},set:function(a){v=a}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},color:{get:function(){return t},set:function(b){t=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.historicalBarChart=function(b){"use strict";function c(b){return b.each(function(k){A.reset(),A.models(f),r&&A.models(g),s&&A.models(h);var x=d3.select(this);a.utils.initSVG(x);var B=a.utils.availableWidth(o,x,l),C=a.utils.availableHeight(p,x,l);if(c.update=function(){x.transition().duration(z).call(c)},c.container=this,v.disabled=k.map(function(a){return!!a.disabled}),!w){var D;w={};for(D in v)v[D]instanceof Array?w[D]=v[D].slice(0):w[D]=v[D]}if(!(k&&k.length&&k.filter(function(a){return a.values.length}).length))return a.utils.noData(c,x),c;x.selectAll(".nv-noData").remove(),d=f.xScale(),e=f.yScale();var E=x.selectAll("g.nv-wrap.nv-historicalBarChart").data([k]),F=E.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBarChart").append("g"),G=E.select("g");F.append("g").attr("class","nv-x nv-axis"),F.append("g").attr("class","nv-y nv-axis"),F.append("g").attr("class","nv-barsWrap"),F.append("g").attr("class","nv-legendWrap"),F.append("g").attr("class","nv-interactive"),q?(i.width(B),G.select(".nv-legendWrap").datum(k).call(i),m||i.height()===l.top||(l.top=i.height(),C=a.utils.availableHeight(p,x,l)),E.select(".nv-legendWrap").attr("transform","translate(0,"+-l.top+")")):G.select(".nv-legendWrap").selectAll("*").remove(),E.attr("transform","translate("+l.left+","+l.top+")"),t&&G.select(".nv-y.nv-axis").attr("transform","translate("+B+",0)"),u&&(j.width(B).height(C).margin({left:l.left,top:l.top}).svgContainer(x).xScale(d),E.select(".nv-interactive").call(j)),f.width(B).height(C).color(k.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!k[b].disabled}));var H=G.select(".nv-barsWrap").datum(k.filter(function(a){return!a.disabled}));H.transition().call(f),r&&(g.scale(d)._ticks(a.utils.calcTicksX(B/100,k)).tickSize(-C,0),G.select(".nv-x.nv-axis").attr("transform","translate(0,"+e.range()[0]+")"),G.select(".nv-x.nv-axis").transition().call(g)),s&&(h.scale(e)._ticks(a.utils.calcTicksY(C/36,k)).tickSize(-B,0),G.select(".nv-y.nv-axis").transition().call(h)),j.dispatch.on("elementMousemove",function(b){f.clearHighlights();var d,e,i,l=[];k.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(g,h){e=a.interactiveBisect(g.values,b.pointXValue,c.x()),f.highlightPoint(e,!0);var j=g.values[e];void 0!==j&&(void 0===d&&(d=j),void 0===i&&(i=c.xScale()(c.x()(j,e))),l.push({key:g.key,value:c.y()(j,e),color:n(g,g.seriesIndex),data:g.values[e]}))});var m=g.tickFormat()(c.x()(d,e));j.tooltip.valueFormatter(function(a,b){return h.tickFormat()(a)}).data({value:m,index:e,series:l})(),j.renderGuideLine(i)}),j.dispatch.on("elementMouseout",function(a){y.tooltipHide(),f.clearHighlights()}),i.dispatch.on("legendClick",function(a,d){a.disabled=!a.disabled,k.filter(function(a){return!a.disabled}).length||k.map(function(a){return a.disabled=!1,E.selectAll(".nv-series").classed("disabled",!1),a}),v.disabled=k.map(function(a){return!!a.disabled}),y.stateChange(v),b.transition().call(c)}),i.dispatch.on("legendDblclick",function(a){k.forEach(function(a){a.disabled=!0}),a.disabled=!1,v.disabled=k.map(function(a){return!!a.disabled}),y.stateChange(v),c.update()}),y.on("changeState",function(a){"undefined"!=typeof a.disabled&&(k.forEach(function(b,c){b.disabled=a.disabled[c]}),v.disabled=a.disabled),c.update()})}),A.renderEnd("historicalBarChart immediate"),c}var d,e,f=b||a.models.historicalBar(),g=a.models.axis(),h=a.models.axis(),i=a.models.legend(),j=a.interactiveGuideline(),k=a.models.tooltip(),l={top:30,right:90,bottom:50,left:90},m=null,n=a.utils.defaultColor(),o=null,p=null,q=!1,r=!0,s=!0,t=!1,u=!1,v={},w=null,x=null,y=d3.dispatch("tooltipHide","stateChange","changeState","renderEnd"),z=250;g.orient("bottom").tickPadding(7),h.orient(t?"right":"left"),k.duration(0).headerEnabled(!1).valueFormatter(function(a,b){return h.tickFormat()(a,b)}).headerFormatter(function(a,b){return g.tickFormat()(a,b)});var A=a.utils.renderWatch(y,0);return f.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:c.x()(a.data),value:c.y()(a.data),color:a.color},k.data(a).hidden(!1)}),f.dispatch.on("elementMouseout.tooltip",function(a){k.hidden(!0)}),f.dispatch.on("elementMousemove.tooltip",function(a){k()}),c.dispatch=y,c.bars=f,c.legend=i,c.xAxis=g,c.yAxis=h,c.interactiveLayer=j,c.tooltip=k,c.options=a.utils.optionsFunc.bind(c),c._options=Object.create({},{width:{get:function(){return o},set:function(a){o=a}},height:{get:function(){return p},set:function(a){p=a}},showLegend:{get:function(){return q},set:function(a){q=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},defaultState:{get:function(){return w},set:function(a){w=a}},noData:{get:function(){return x},set:function(a){x=a}},margin:{get:function(){return l},set:function(a){void 0!==a.top&&(l.top=a.top,m=a.top),l.right=void 0!==a.right?a.right:l.right,l.bottom=void 0!==a.bottom?a.bottom:l.bottom,l.left=void 0!==a.left?a.left:l.left}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),i.color(n),f.color(n)}},duration:{get:function(){return z},set:function(a){z=a,A.reset(z),h.duration(z),g.duration(z)}},rightAlignYAxis:{get:function(){return t},set:function(a){t=a,h.orient(a?"right":"left")}},useInteractiveGuideline:{get:function(){return u},set:function(a){u=a,a===!0&&c.interactive(!1)}}}),a.utils.inheritOptions(c,f),a.utils.initOptions(c),c},a.models.ohlcBarChart=function(){var b=a.models.historicalBarChart(a.models.ohlcBar());return b.useInteractiveGuideline(!0),b.interactiveLayer.tooltip.contentGenerator(function(a){var c=a.series[0].data,d=c.open'+a.value+"
open:"+b.yAxis.tickFormat()(c.open)+"
close:"+b.yAxis.tickFormat()(c.close)+"
high"+b.yAxis.tickFormat()(c.high)+"
low:"+b.yAxis.tickFormat()(c.low)+"
"}),b},a.models.candlestickBarChart=function(){var b=a.models.historicalBarChart(a.models.candlestickBar());return b.useInteractiveGuideline(!0),b.interactiveLayer.tooltip.contentGenerator(function(a){var c=a.series[0].data,d=c.open'+a.value+"
open:"+b.yAxis.tickFormat()(c.open)+"
close:"+b.yAxis.tickFormat()(c.close)+"
high"+b.yAxis.tickFormat()(c.high)+"
low:"+b.yAxis.tickFormat()(c.low)+"
"; -}),b},a.models.legend=function(){"use strict";function b(r){function s(a,b){return"furious"!=q?"#000":o?a.disengaged?"#000":"#fff":o?void 0:(a.color||(a.color=h(a,b)),a.disabled?a.color:"#fff")}function t(a,b){return o&&"furious"==q&&a.disengaged?"#eee":a.color||h(a,b)}function u(a,b){return o&&"furious"==q?1:a.disabled?0:1}return r.each(function(b){var h=d-c.left-c.right,r=d3.select(this);a.utils.initSVG(r);var v=r.selectAll("g.nv-legend").data([b]),w=v.enter().append("g").attr("class","nvd3 nv-legend").append("g"),x=v.select("g");l?v.attr("transform","translate("+-c.right+","+c.top+")"):v.attr("transform","translate("+c.left+","+c.top+")");var y,z,A=x.selectAll(".nv-series").data(function(a){return"furious"!=q?a:a.filter(function(a){return o?!0:!a.disengaged})}),B=A.enter().append("g").attr("class","nv-series");switch(q){case"furious":z=23;break;case"classic":z=20}if("classic"==q)B.append("circle").style("stroke-width",2).attr("class","nv-legend-symbol").attr("r",5),y=A.select(".nv-legend-symbol");else if("furious"==q){B.append("rect").style("stroke-width",2).attr("class","nv-legend-symbol").attr("rx",3).attr("ry",3),y=A.select(".nv-legend-symbol"),B.append("g").attr("class","nv-check-box").property("innerHTML",'').attr("transform","translate(-10,-8)scale(0.5)");var C=A.select(".nv-check-box");C.each(function(a,b){d3.select(this).selectAll("path").attr("stroke",s(a,b))})}B.append("text").attr("text-anchor","start").attr("class","nv-legend-text").attr("dy",".32em").attr("dx","8");var D=A.select("text.nv-legend-text");A.on("mouseover",function(a,b){p.legendMouseover(a,b)}).on("mouseout",function(a,b){p.legendMouseout(a,b)}).on("click",function(a,b){p.legendClick(a,b);var c=A.data();if(m){if("classic"==q)n?(c.forEach(function(a){a.disabled=!0}),a.disabled=!1):(a.disabled=!a.disabled,c.every(function(a){return a.disabled})&&c.forEach(function(a){a.disabled=!1}));else if("furious"==q)if(o)a.disengaged=!a.disengaged,a.userDisabled=void 0==a.userDisabled?!!a.disabled:a.userDisabled,a.disabled=a.disengaged||a.userDisabled;else if(!o){a.disabled=!a.disabled,a.userDisabled=a.disabled;var d=c.filter(function(a){return!a.disengaged});d.every(function(a){return a.userDisabled})&&c.forEach(function(a){a.disabled=a.userDisabled=!1})}p.stateChange({disabled:c.map(function(a){return!!a.disabled}),disengaged:c.map(function(a){return!!a.disengaged})})}}).on("dblclick",function(a,b){if(("furious"!=q||!o)&&(p.legendDblclick(a,b),m)){var c=A.data();c.forEach(function(a){a.disabled=!0,"furious"==q&&(a.userDisabled=a.disabled)}),a.disabled=!1,"furious"==q&&(a.userDisabled=a.disabled),p.stateChange({disabled:c.map(function(a){return!!a.disabled})})}}),A.classed("nv-disabled",function(a){return a.userDisabled}),A.exit().remove(),D.attr("fill",s).text(function(a){return g(f(a))});var E=0;if(j){var F=[];A.each(function(b,c){var d;if(g(f(b))&&g(f(b)).length>i){var e=g(f(b)).substring(0,i);d=d3.select(this).select("text").text(e+"..."),d3.select(this).append("svg:title").text(g(f(b)))}else d=d3.select(this).select("text");var h;try{if(h=d.node().getComputedTextLength(),0>=h)throw Error()}catch(j){h=a.utils.calcApproxTextWidth(d)}F.push(h+k)});var G=0,H=[];for(E=0;h>E&&Gh&&G>1;){H=[],G--;for(var I=0;I(H[I%G]||0)&&(H[I%G]=F[I]);E=H.reduce(function(a,b,c,d){return a+b})}for(var J=[],K=0,L=0;G>K;K++)J[K]=L,L+=H[K];A.attr("transform",function(a,b){return"translate("+J[b%G]+","+(5+Math.floor(b/G)*z)+")"}),l?x.attr("transform","translate("+(d-c.right-E)+","+c.top+")"):x.attr("transform","translate(0,"+c.top+")"),e=c.top+c.bottom+Math.ceil(F.length/G)*z}else{var M,N=5,O=5,P=0;A.attr("transform",function(a,b){var e=d3.select(this).select("text").node().getComputedTextLength()+k;return M=O,dP&&(P=O),M+P>E&&(E=M+P),"translate("+M+","+N+")"}),x.attr("transform","translate("+(d-c.right-P)+","+c.top+")"),e=c.top+c.bottom+N+15}if("furious"==q){y.attr("width",function(a,b){return D[0][b].getComputedTextLength()+27}).attr("height",18).attr("y",-9).attr("x",-15),w.insert("rect",":first-child").attr("class","nv-legend-bg").attr("fill","#eee").attr("opacity",0);var Q=x.select(".nv-legend-bg");Q.transition().duration(300).attr("x",-z).attr("width",E+z-12).attr("height",e+10).attr("y",-c.top-10).attr("opacity",o?1:0)}y.style("fill",t).style("fill-opacity",u).style("stroke",t)}),b}var c={top:5,right:0,bottom:5,left:0},d=400,e=20,f=function(a){return a.key},g=function(a){return a},h=a.utils.getColor(),i=20,j=!0,k=32,l=!0,m=!0,n=!1,o=!1,p=d3.dispatch("legendClick","legendDblclick","legendMouseover","legendMouseout","stateChange"),q="classic";return b.dispatch=p,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},key:{get:function(){return f},set:function(a){f=a}},keyFormatter:{get:function(){return g},set:function(a){g=a}},align:{get:function(){return j},set:function(a){j=a}},maxKeyLength:{get:function(){return i},set:function(a){i=a}},rightAlign:{get:function(){return l},set:function(a){l=a}},padding:{get:function(){return k},set:function(a){k=a}},updateState:{get:function(){return m},set:function(a){m=a}},radioButtonMode:{get:function(){return n},set:function(a){n=a}},expanded:{get:function(){return o},set:function(a){o=a}},vers:{get:function(){return q},set:function(a){q=a}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},color:{get:function(){return h},set:function(b){h=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.line=function(){"use strict";function b(r){return v.reset(),v.models(e),r.each(function(b){i=d3.select(this);var r=a.utils.availableWidth(g,i,f),s=a.utils.availableHeight(h,i,f);a.utils.initSVG(i),c=e.xScale(),d=e.yScale(),t=t||c,u=u||d;var w=i.selectAll("g.nv-wrap.nv-line").data([b]),x=w.enter().append("g").attr("class","nvd3 nv-wrap nv-line"),y=x.append("defs"),z=x.append("g"),A=w.select("g");z.append("g").attr("class","nv-groups"),z.append("g").attr("class","nv-scatterWrap"),w.attr("transform","translate("+f.left+","+f.top+")"),e.width(r).height(s);var B=w.select(".nv-scatterWrap");B.call(e),y.append("clipPath").attr("id","nv-edge-clip-"+e.id()).append("rect"),w.select("#nv-edge-clip-"+e.id()+" rect").attr("width",r).attr("height",s>0?s:0),A.attr("clip-path",p?"url(#nv-edge-clip-"+e.id()+")":""),B.attr("clip-path",p?"url(#nv-edge-clip-"+e.id()+")":"");var C=w.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});C.enter().append("g").style("stroke-opacity",1e-6).style("stroke-width",function(a){return a.strokeWidth||j}).style("fill-opacity",1e-6),C.exit().remove(),C.attr("class",function(a,b){return(a.classed||"")+" nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return k(a,b)}).style("stroke",function(a,b){return k(a,b)}),C.watchTransition(v,"line: groups").style("stroke-opacity",1).style("fill-opacity",function(a){return a.fillOpacity||.5});var D=C.selectAll("path.nv-area").data(function(a){return o(a)?[a]:[]});D.enter().append("path").attr("class","nv-area").attr("d",function(b){return d3.svg.area().interpolate(q).defined(n).x(function(b,c){return a.utils.NaNtoZero(t(l(b,c)))}).y0(function(b,c){return a.utils.NaNtoZero(u(m(b,c)))}).y1(function(a,b){return u(d.domain()[0]<=0?d.domain()[1]>=0?0:d.domain()[1]:d.domain()[0])}).apply(this,[b.values])}),C.exit().selectAll("path.nv-area").remove(),D.watchTransition(v,"line: areaPaths").attr("d",function(b){return d3.svg.area().interpolate(q).defined(n).x(function(b,d){return a.utils.NaNtoZero(c(l(b,d)))}).y0(function(b,c){return a.utils.NaNtoZero(d(m(b,c)))}).y1(function(a,b){return d(d.domain()[0]<=0?d.domain()[1]>=0?0:d.domain()[1]:d.domain()[0])}).apply(this,[b.values])});var E=C.selectAll("path.nv-line").data(function(a){return[a.values]});E.enter().append("path").attr("class","nv-line").attr("d",d3.svg.line().interpolate(q).defined(n).x(function(b,c){return a.utils.NaNtoZero(t(l(b,c)))}).y(function(b,c){return a.utils.NaNtoZero(u(m(b,c)))})),E.watchTransition(v,"line: linePaths").attr("d",d3.svg.line().interpolate(q).defined(n).x(function(b,d){return a.utils.NaNtoZero(c(l(b,d)))}).y(function(b,c){return a.utils.NaNtoZero(d(m(b,c)))})),t=c.copy(),u=d.copy()}),v.renderEnd("line immediate"),b}var c,d,e=a.models.scatter(),f={top:0,right:0,bottom:0,left:0},g=960,h=500,i=null,j=1.5,k=a.utils.defaultColor(),l=function(a){return a.x},m=function(a){return a.y},n=function(a,b){return!isNaN(m(a,b))&&null!==m(a,b)},o=function(a){return a.area},p=!1,q="linear",r=250,s=d3.dispatch("elementClick","elementMouseover","elementMouseout","renderEnd");e.pointSize(16).pointDomain([16,256]);var t,u,v=a.utils.renderWatch(s,r);return b.dispatch=s,b.scatter=e,e.dispatch.on("elementClick",function(){s.elementClick.apply(this,arguments)}),e.dispatch.on("elementMouseover",function(){s.elementMouseover.apply(this,arguments)}),e.dispatch.on("elementMouseout",function(){s.elementMouseout.apply(this,arguments)}),b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},defined:{get:function(){return n},set:function(a){n=a}},interpolate:{get:function(){return q},set:function(a){q=a}},clipEdge:{get:function(){return p},set:function(a){p=a}},margin:{get:function(){return f},set:function(a){f.top=void 0!==a.top?a.top:f.top,f.right=void 0!==a.right?a.right:f.right,f.bottom=void 0!==a.bottom?a.bottom:f.bottom,f.left=void 0!==a.left?a.left:f.left}},duration:{get:function(){return r},set:function(a){r=a,v.reset(r),e.duration(r)}},isArea:{get:function(){return o},set:function(a){o=d3.functor(a)}},x:{get:function(){return l},set:function(a){l=a,e.x(a)}},y:{get:function(){return m},set:function(a){m=a,e.y(a)}},color:{get:function(){return k},set:function(b){k=a.utils.getColor(b),e.color(k)}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.lineChart=function(){"use strict";function b(j){return C.reset(),C.models(e),s&&C.models(f),t&&C.models(g),j.each(function(j){function z(){s&&M.select(".nv-focus .nv-x.nv-axis").transition().duration(B).call(f)}function C(){t&&M.select(".nv-focus .nv-y.nv-axis").transition().duration(B).call(g)}function F(a){var b=M.select(".nv-focus .nv-linesWrap").datum(j.filter(function(a){return!a.disabled}).map(function(b,c){return{key:b.key,area:b.area,classed:b.classed,values:b.values.filter(function(b,c){return e.x()(b,c)>=a[0]&&e.x()(b,c)<=a[1]}),disableTooltip:b.disableTooltip}}));b.transition().duration(B).call(e),z(),C()}var G=d3.select(this);a.utils.initSVG(G);var H=a.utils.availableWidth(o,G,l),I=a.utils.availableHeight(p,G,l)-(w?k.height():0);if(b.update=function(){0===B?G.call(b):G.transition().duration(B).call(b)},b.container=this,x.setter(E(j),b.update).getter(D(j)).update(),x.disabled=j.map(function(a){return!!a.disabled}),!y){var J;y={};for(J in x)x[J]instanceof Array?y[J]=x[J].slice(0):y[J]=x[J]}if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,G),b;G.selectAll(".nv-noData").remove(),k.dispatch.on("onBrush",function(a){F(a)}),c=e.xScale(),d=e.yScale();var K=G.selectAll("g.nv-wrap.nv-lineChart").data([j]),L=K.enter().append("g").attr("class","nvd3 nv-wrap nv-lineChart").append("g"),M=K.select("g");L.append("g").attr("class","nv-legendWrap");var N=L.append("g").attr("class","nv-focus");N.append("g").attr("class","nv-background").append("rect"),N.append("g").attr("class","nv-x nv-axis"),N.append("g").attr("class","nv-y nv-axis"),N.append("g").attr("class","nv-linesWrap"),N.append("g").attr("class","nv-interactive");L.append("g").attr("class","nv-focusWrap");q?(h.width(H),M.select(".nv-legendWrap").datum(j).call(h),"bottom"===r?K.select(".nv-legendWrap").attr("transform","translate(0,"+I+")"):"top"===r&&(m||h.height()===l.top||(l.top=h.height(),I=a.utils.availableHeight(p,G,l)-(w?k.height():0)),K.select(".nv-legendWrap").attr("transform","translate(0,"+-l.top+")"))):M.select(".nv-legendWrap").selectAll("*").remove(),K.attr("transform","translate("+l.left+","+l.top+")"),u&&M.select(".nv-y.nv-axis").attr("transform","translate("+H+",0)"),v&&(i.width(H).height(I).margin({left:l.left,top:l.top}).svgContainer(G).xScale(c),K.select(".nv-interactive").call(i)),M.select(".nv-focus .nv-background rect").attr("width",H).attr("height",I),e.width(H).height(I).color(j.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!j[b].disabled}));var O=M.select(".nv-linesWrap").datum(j.filter(function(a){return!a.disabled}));if(s&&f.scale(c)._ticks(a.utils.calcTicksX(H/100,j)).tickSize(-I,0),t&&g.scale(d)._ticks(a.utils.calcTicksY(I/36,j)).tickSize(-H,0),M.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+I+")"),w){k.width(H),M.select(".nv-focusWrap").attr("transform","translate(0,"+(I+l.bottom+k.margin().top)+")").datum(j.filter(function(a){return!a.disabled})).call(k);var P=k.brush.empty()?k.xDomain():k.brush.extent();null!==P&&F(P)}else O.call(e),z(),C();h.dispatch.on("stateChange",function(a){for(var c in a)x[c]=a[c];A.stateChange(x),b.update()}),i.dispatch.on("elementMousemove",function(d){e.clearHighlights();var f,h,l,m=[];if(j.filter(function(a,b){return a.seriesIndex=b,!a.disabled&&!a.disableTooltip}).forEach(function(g,i){var j=w?k.brush.empty()?k.xScale().domain():k.brush.extent():c.domain(),o=g.values.filter(function(a,b){return j[0]<=j[1]?e.x()(a,b)>=j[0]&&e.x()(a,b)<=j[1]:e.x()(a,b)>=j[1]&&e.x()(a,b)<=j[0]});h=a.interactiveBisect(o,d.pointXValue,e.x());var p=o[h],q=b.y()(p,h);null!==q&&e.highlightPoint(i,h,!0),void 0!==p&&(void 0===f&&(f=p),void 0===l&&(l=b.xScale()(b.x()(p,h))),m.push({key:g.key,value:q,color:n(g,g.seriesIndex),data:p}))}),m.length>2){var o=b.yScale().invert(d.mouseY),p=Math.abs(b.yScale().domain()[0]-b.yScale().domain()[1]),q=.03*p,r=a.nearestValueIndex(m.map(function(a){return a.value}),o,q);null!==r&&(m[r].highlight=!0)}var s=function(a,b){return null==a?"N/A":g.tickFormat()(a)};i.tooltip.valueFormatter(i.tooltip.valueFormatter()||s).data({value:b.x()(f,h),index:h,series:m})(),i.renderGuideLine(l)}),i.dispatch.on("elementClick",function(c){var d,f=[];j.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(e){var g=a.interactiveBisect(e.values,c.pointXValue,b.x()),h=e.values[g];if("undefined"!=typeof h){"undefined"==typeof d&&(d=b.xScale()(b.x()(h,g)));var i=b.yScale()(b.y()(h,g));f.push({point:h,pointIndex:g,pos:[d,i],seriesIndex:e.seriesIndex,series:e})}}),e.dispatch.elementClick(f)}),i.dispatch.on("elementMouseout",function(a){e.clearHighlights()}),A.on("changeState",function(a){"undefined"!=typeof a.disabled&&j.length===a.disabled.length&&(j.forEach(function(b,c){b.disabled=a.disabled[c]}),x.disabled=a.disabled),b.update()})}),C.renderEnd("lineChart immediate"),b}var c,d,e=a.models.line(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.interactiveGuideline(),j=a.models.tooltip(),k=a.models.focus(a.models.line()),l={top:30,right:20,bottom:50,left:60},m=null,n=a.utils.defaultColor(),o=null,p=null,q=!0,r="top",s=!0,t=!0,u=!1,v=!1,w=!1,x=a.utils.state(),y=null,z=null,A=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd"),B=250;f.orient("bottom").tickPadding(7),g.orient(u?"right":"left"),e.clipEdge(!0).duration(0),j.valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)}),i.tooltip.valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)});var C=a.utils.renderWatch(A,B),D=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},E=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return e.dispatch.on("elementMouseover.tooltip",function(a){a.series.disableTooltip||j.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(a){j.hidden(!0)}),b.dispatch=A,b.lines=e,b.legend=h,b.focus=k,b.xAxis=f,b.x2Axis=k.xAxis,b.yAxis=g,b.y2Axis=k.yAxis,b.interactiveLayer=i,b.tooltip=j,b.state=x,b.dispatch=A,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return o},set:function(a){o=a}},height:{get:function(){return p},set:function(a){p=a}},showLegend:{get:function(){return q},set:function(a){q=a}},legendPosition:{get:function(){return r},set:function(a){r=a}},showXAxis:{get:function(){return s},set:function(a){s=a}},showYAxis:{get:function(){return t},set:function(a){t=a}},defaultState:{get:function(){return y},set:function(a){y=a}},noData:{get:function(){return z},set:function(a){z=a}},focusEnable:{get:function(){return w},set:function(a){w=a}},focusHeight:{get:function(){return k.height()},set:function(a){k.height(a)}},focusShowAxisX:{get:function(){return k.showXAxis()},set:function(a){k.showXAxis(a)}},focusShowAxisY:{get:function(){return k.showYAxis()},set:function(a){k.showYAxis(a)}},brushExtent:{get:function(){return k.brushExtent()},set:function(a){k.brushExtent(a)}},focusMargin:{get:function(){return k.margin},set:function(a){void 0!==a.top&&(l.top=a.top,m=a.top),k.margin.right=void 0!==a.right?a.right:k.margin.right,k.margin.bottom=void 0!==a.bottom?a.bottom:k.margin.bottom,k.margin.left=void 0!==a.left?a.left:k.margin.left}},margin:{get:function(){return l},set:function(a){l.top=void 0!==a.top?a.top:l.top,l.right=void 0!==a.right?a.right:l.right,l.bottom=void 0!==a.bottom?a.bottom:l.bottom,l.left=void 0!==a.left?a.left:l.left}},duration:{get:function(){return B},set:function(a){B=a,C.reset(B),e.duration(B),k.duration(B),f.duration(B),g.duration(B)}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),h.color(n),e.color(n),k.color(n)}},interpolate:{get:function(){return e.interpolate()},set:function(a){e.interpolate(a),k.interpolate(a)}},xTickFormat:{get:function(){return f.tickFormat()},set:function(a){f.tickFormat(a),k.xTickFormat(a)}},yTickFormat:{get:function(){return g.tickFormat()},set:function(a){g.tickFormat(a),k.yTickFormat(a)}},x:{get:function(){return e.x()},set:function(a){e.x(a),k.x(a)}},y:{get:function(){return e.y()},set:function(a){e.y(a),k.y(a)}},rightAlignYAxis:{get:function(){return u},set:function(a){u=a,g.orient(u?"right":"left")}},useInteractiveGuideline:{get:function(){return v},set:function(a){v=a,v&&(e.interactive(!1),e.useVoronoi(!1))}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.lineWithFocusChart=function(){return a.models.lineChart().margin({bottom:30}).focusEnable(!0)},a.models.linePlusBarChart=function(){"use strict";function b(v){return v.each(function(v){function K(a){var b=+("e"==a),c=b?1:-1,d=$/3;return"M"+.5*c+","+d+"A6,6 0 0 "+b+" "+6.5*c+","+(d+6)+"V"+(2*d-6)+"A6,6 0 0 "+b+" "+.5*c+","+2*d+"ZM"+2.5*c+","+(d+8)+"V"+(2*d-8)+"M"+4.5*c+","+(d+8)+"V"+(2*d-8)}function S(){u.empty()||u.extent(J),na.data([u.empty()?e.domain():J]).each(function(a,b){var c=e(a[0])-e.range()[0],d=e.range()[1]-e(a[1]);d3.select(this).select(".left").attr("width",0>c?0:c),d3.select(this).select(".right").attr("x",e(a[1])).attr("width",0>d?0:d)})}function T(){J=u.empty()?null:u.extent(),c=u.empty()?e.domain():u.extent(),L.brush({extent:c,brush:u}),S(),l.width(Y).height(Z).color(v.map(function(a,b){return a.color||D(a,b)}).filter(function(a,b){return!v[b].disabled&&v[b].bar})),j.width(Y).height(Z).color(v.map(function(a,b){return a.color||D(a,b)}).filter(function(a,b){return!v[b].disabled&&!v[b].bar}));var b=ga.select(".nv-focus .nv-barsWrap").datum(aa.length?aa.map(function(a,b){return{key:a.key,values:a.values.filter(function(a,b){return l.x()(a,b)>=c[0]&&l.x()(a,b)<=c[1]})}}):[{values:[]}]),h=ga.select(".nv-focus .nv-linesWrap").datum(W(ba)?[{values:[]}]:ba.filter(function(a){return!a.disabled}).map(function(a,b){return{area:a.area,fillOpacity:a.fillOpacity,strokeWidth:a.strokeWidth,key:a.key,values:a.values.filter(function(a,b){return j.x()(a,b)>=c[0]&&j.x()(a,b)<=c[1]})}}));d=aa.length&&!R?l.xScale():j.xScale(),n.scale(d)._ticks(a.utils.calcTicksX(Y/100,v)).tickSize(-Z,0),n.domain([Math.ceil(c[0]),Math.floor(c[1])]),ga.select(".nv-x.nv-axis").transition().duration(M).call(n),b.transition().duration(M).call(l),h.transition().duration(M).call(j),ga.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),p.scale(f)._ticks(a.utils.calcTicksY(Z/36,v)).tickSize(-Y,0),q.scale(g)._ticks(a.utils.calcTicksY(Z/36,v)),R?q.tickSize(ba.length?0:-Y,0):q.tickSize(aa.length?0:-Y,0);var i=aa.length?1:0,k=ba.length&&!W(ba)?1:0,m=R?k:i,o=R?i:k;ga.select(".nv-focus .nv-y1.nv-axis").style("opacity",m),ga.select(".nv-focus .nv-y2.nv-axis").style("opacity",o).attr("transform","translate("+d.range()[1]+",0)"),ga.select(".nv-focus .nv-y1.nv-axis").transition().duration(M).call(p),ga.select(".nv-focus .nv-y2.nv-axis").transition().duration(M).call(q)}var X=d3.select(this);a.utils.initSVG(X);var Y=a.utils.availableWidth(z,X,w),Z=a.utils.availableHeight(A,X,w)-(F?I:0),$=I-y.top-y.bottom;if(b.update=function(){X.transition().duration(M).call(b)},b.container=this,N.setter(V(v),b.update).getter(U(v)).update(),N.disabled=v.map(function(a){return!!a.disabled}),!O){var _;O={};for(_ in N)N[_]instanceof Array?O[_]=N[_].slice(0):O[_]=N[_]}if(!(v&&v.length&&v.filter(function(a){return a.values.length}).length))return a.utils.noData(b,X),b;X.selectAll(".nv-noData").remove();var aa=v.filter(function(a){return!a.disabled&&a.bar}),ba=v.filter(function(a){return!a.bar});d=aa.length&&!R?l.xScale():j.xScale(),e=o.scale(),f=R?j.yScale():l.yScale(),g=R?l.yScale():j.yScale(),h=R?k.yScale():m.yScale(),i=R?m.yScale():k.yScale();var ca=v.filter(function(a){return!a.disabled&&(R?!a.bar:a.bar)}).map(function(a){return a.values.map(function(a,b){return{x:B(a,b),y:C(a,b)}})}),da=v.filter(function(a){return!a.disabled&&(R?a.bar:!a.bar)}).map(function(a){return a.values.map(function(a,b){return{x:B(a,b),y:C(a,b)}})});d.range([0,Y]),e.domain(d3.extent(d3.merge(ca.concat(da)),function(a){return a.x})).range([0,Y]);var ea=X.selectAll("g.nv-wrap.nv-linePlusBar").data([v]),fa=ea.enter().append("g").attr("class","nvd3 nv-wrap nv-linePlusBar").append("g"),ga=ea.select("g");fa.append("g").attr("class","nv-legendWrap");var ha=fa.append("g").attr("class","nv-focus");ha.append("g").attr("class","nv-x nv-axis"),ha.append("g").attr("class","nv-y1 nv-axis"),ha.append("g").attr("class","nv-y2 nv-axis"),ha.append("g").attr("class","nv-barsWrap"),ha.append("g").attr("class","nv-linesWrap");var ia=fa.append("g").attr("class","nv-context");if(ia.append("g").attr("class","nv-x nv-axis"),ia.append("g").attr("class","nv-y1 nv-axis"),ia.append("g").attr("class","nv-y2 nv-axis"),ia.append("g").attr("class","nv-barsWrap"),ia.append("g").attr("class","nv-linesWrap"),ia.append("g").attr("class","nv-brushBackground"),ia.append("g").attr("class","nv-x nv-brush"),E){var ja=t.align()?Y/2:Y,ka=t.align()?ja:0;t.width(ja),ga.select(".nv-legendWrap").datum(v.map(function(a){return a.originalKey=void 0===a.originalKey?a.key:a.originalKey,R?a.key=a.originalKey+(a.bar?Q:P):a.key=a.originalKey+(a.bar?P:Q),a})).call(t),x||t.height()===w.top||(w.top=t.height(),Z=a.utils.availableHeight(A,X,w)-I),ga.select(".nv-legendWrap").attr("transform","translate("+ka+","+-w.top+")")}else ga.select(".nv-legendWrap").selectAll("*").remove();ea.attr("transform","translate("+w.left+","+w.top+")"),ga.select(".nv-context").style("display",F?"initial":"none"),m.width(Y).height($).color(v.map(function(a,b){return a.color||D(a,b)}).filter(function(a,b){return!v[b].disabled&&v[b].bar})),k.width(Y).height($).color(v.map(function(a,b){return a.color||D(a,b)}).filter(function(a,b){return!v[b].disabled&&!v[b].bar}));var la=ga.select(".nv-context .nv-barsWrap").datum(aa.length?aa:[{values:[]}]),ma=ga.select(".nv-context .nv-linesWrap").datum(W(ba)?[{values:[]}]:ba.filter(function(a){return!a.disabled}));ga.select(".nv-context").attr("transform","translate(0,"+(Z+w.bottom+y.top)+")"),la.transition().call(m),ma.transition().call(k),H&&(o._ticks(a.utils.calcTicksX(Y/100,v)).tickSize(-$,0),ga.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+h.range()[0]+")"),ga.select(".nv-context .nv-x.nv-axis").transition().call(o)),G&&(r.scale(h)._ticks($/36).tickSize(-Y,0),s.scale(i)._ticks($/36).tickSize(aa.length?0:-Y,0),ga.select(".nv-context .nv-y3.nv-axis").style("opacity",aa.length?1:0).attr("transform","translate(0,"+e.range()[0]+")"),ga.select(".nv-context .nv-y2.nv-axis").style("opacity",ba.length?1:0).attr("transform","translate("+e.range()[1]+",0)"),ga.select(".nv-context .nv-y1.nv-axis").transition().call(r),ga.select(".nv-context .nv-y2.nv-axis").transition().call(s)),u.x(e).on("brush",T),J&&u.extent(J);var na=ga.select(".nv-brushBackground").selectAll("g").data([J||u.extent()]),oa=na.enter().append("g");oa.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",$),oa.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",$);var pa=ga.select(".nv-x.nv-brush").call(u);pa.selectAll("rect").attr("height",$),pa.selectAll(".resize").append("path").attr("d",K),t.dispatch.on("stateChange",function(a){for(var c in a)N[c]=a[c];L.stateChange(N),b.update()}),L.on("changeState",function(a){"undefined"!=typeof a.disabled&&(v.forEach(function(b,c){b.disabled=a.disabled[c]}),N.disabled=a.disabled),b.update()}),T()}),b}var c,d,e,f,g,h,i,j=a.models.line(),k=a.models.line(),l=a.models.historicalBar(),m=a.models.historicalBar(),n=a.models.axis(),o=a.models.axis(),p=a.models.axis(),q=a.models.axis(),r=a.models.axis(),s=a.models.axis(),t=a.models.legend(),u=d3.svg.brush(),v=a.models.tooltip(),w={top:30,right:30,bottom:30,left:60},x=null,y={top:0,right:30,bottom:20,left:60},z=null,A=null,B=function(a){return a.x},C=function(a){return a.y},D=a.utils.defaultColor(),E=!0,F=!0,G=!1,H=!0,I=50,J=null,K=null,L=d3.dispatch("brush","stateChange","changeState"),M=0,N=a.utils.state(),O=null,P=" (left axis)",Q=" (right axis)",R=!1;j.clipEdge(!0),k.interactive(!1),k.pointActive(function(a){return!1}),n.orient("bottom").tickPadding(5),p.orient("left"),q.orient("right"),o.orient("bottom").tickPadding(5),r.orient("left"),s.orient("right"),v.headerEnabled(!0).headerFormatter(function(a,b){return n.tickFormat()(a,b)});var S=function(){return R?{main:q,focus:s}:{main:p,focus:r}},T=function(){return R?{main:p,focus:r}:{main:q,focus:s}},U=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},V=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}},W=function(a){return a.every(function(a){return a.disabled})};return j.dispatch.on("elementMouseover.tooltip",function(a){v.duration(100).valueFormatter(function(a,b){return T().main.tickFormat()(a,b)}).data(a).hidden(!1)}),j.dispatch.on("elementMouseout.tooltip",function(a){v.hidden(!0)}),l.dispatch.on("elementMouseover.tooltip",function(a){a.value=b.x()(a.data),a.series={value:b.y()(a.data),color:a.color},v.duration(0).valueFormatter(function(a,b){return S().main.tickFormat()(a,b)}).data(a).hidden(!1)}),l.dispatch.on("elementMouseout.tooltip",function(a){v.hidden(!0)}),l.dispatch.on("elementMousemove.tooltip",function(a){v()}),b.dispatch=L,b.legend=t,b.lines=j,b.lines2=k,b.bars=l,b.bars2=m,b.xAxis=n,b.x2Axis=o,b.y1Axis=p,b.y2Axis=q,b.y3Axis=r,b.y4Axis=s,b.tooltip=v,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return z},set:function(a){z=a}},height:{get:function(){return A},set:function(a){A=a}},showLegend:{get:function(){return E},set:function(a){E=a}},brushExtent:{get:function(){return J},set:function(a){J=a}},noData:{get:function(){return K},set:function(a){K=a}},focusEnable:{get:function(){return F},set:function(a){F=a}},focusHeight:{get:function(){return I},set:function(a){I=a}},focusShowAxisX:{get:function(){return H},set:function(a){H=a}},focusShowAxisY:{get:function(){return G},set:function(a){G=a}},legendLeftAxisHint:{get:function(){return P},set:function(a){P=a}},legendRightAxisHint:{get:function(){return Q},set:function(a){Q=a}},margin:{get:function(){return w},set:function(a){void 0!==a.top&&(w.top=a.top,x=a.top),w.right=void 0!==a.right?a.right:w.right,w.bottom=void 0!==a.bottom?a.bottom:w.bottom,w.left=void 0!==a.left?a.left:w.left}},focusMargin:{get:function(){return y},set:function(a){y.top=void 0!==a.top?a.top:y.top,y.right=void 0!==a.right?a.right:y.right,y.bottom=void 0!==a.bottom?a.bottom:y.bottom,y.left=void 0!==a.left?a.left:y.left}},duration:{get:function(){return M},set:function(a){M=a}},color:{get:function(){return D},set:function(b){D=a.utils.getColor(b),t.color(D)}},x:{get:function(){return B},set:function(a){B=a,j.x(a),k.x(a),l.x(a),m.x(a)}},y:{get:function(){return C},set:function(a){C=a,j.y(a),k.y(a),l.y(a),m.y(a)}},switchYAxisOrder:{get:function(){return R},set:function(a){if(R!==a){var b=p;p=q,q=b;var c=r;r=s,s=c}R=a,p.orient("left"),q.orient("right"),r.orient("left"),s.orient("right")}}}),a.utils.inheritOptions(b,j),a.utils.initOptions(b),b},a.models.multiBar=function(){"use strict";function b(F){return D.reset(),F.each(function(b){var F=k-j.left-j.right,G=l-j.top-j.bottom;p=d3.select(this),a.utils.initSVG(p);var H=0;if(x&&b.length&&(x=[{values:b[0].values.map(function(a){return{x:a.x,y:0,series:a.series,size:.01}})}]),u){var I=d3.layout.stack().offset(v).values(function(a){return a.values}).y(r)(!b.length&&x?x:b);I.forEach(function(a,c){a.nonStackable?(b[c].nonStackableSeries=H++,I[c]=b[c]):c>0&&I[c-1].nonStackable&&I[c].values.map(function(a,b){a.y0-=I[c-1].values[b].y,a.y1=a.y0+a.y})}),b=I}b.forEach(function(a,b){a.values.forEach(function(c){c.series=b,c.key=a.key})}),u&&b.length>0&&b[0].values.map(function(a,c){var d=0,e=0;b.map(function(a,f){if(!b[f].nonStackable){var g=a.values[c];g.size=Math.abs(g.y),g.y<0?(g.y1=e,e-=g.size):(g.y1=g.size+d,d+=g.size)}})});var J=d&&e?[]:b.map(function(a,b){return a.values.map(function(a,c){return{x:q(a,c),y:r(a,c),y0:a.y0,y1:a.y1,idx:b}})});m.domain(d||d3.merge(J).map(function(a){return a.x})).rangeBands(f||[0,F],A),n.domain(e||d3.extent(d3.merge(J).map(function(a){var c=a.y;return u&&!b[a.idx].nonStackable&&(c=a.y>0?a.y1:a.y1+a.y),c}).concat(s))).range(g||[G,0]),m.domain()[0]===m.domain()[1]&&(m.domain()[0]?m.domain([m.domain()[0]-.01*m.domain()[0],m.domain()[1]+.01*m.domain()[1]]):m.domain([-1,1])),n.domain()[0]===n.domain()[1]&&(n.domain()[0]?n.domain([n.domain()[0]+.01*n.domain()[0],n.domain()[1]-.01*n.domain()[1]]):n.domain([-1,1])),h=h||m,i=i||n;var K=p.selectAll("g.nv-wrap.nv-multibar").data([b]),L=K.enter().append("g").attr("class","nvd3 nv-wrap nv-multibar"),M=L.append("defs"),N=L.append("g"),O=K.select("g");N.append("g").attr("class","nv-groups"),K.attr("transform","translate("+j.left+","+j.top+")"),M.append("clipPath").attr("id","nv-edge-clip-"+o).append("rect"),K.select("#nv-edge-clip-"+o+" rect").attr("width",F).attr("height",G),O.attr("clip-path",t?"url(#nv-edge-clip-"+o+")":"");var P=K.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a,b){return b});P.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6);var Q=D.transition(P.exit().selectAll("rect.nv-bar"),"multibarExit",Math.min(100,z)).attr("y",function(a,c,d){var e=i(0)||0;return u&&b[a.series]&&!b[a.series].nonStackable&&(e=i(a.y0)),e}).attr("height",0).remove();Q.delay&&Q.delay(function(a,b){var c=b*(z/(E+1))-b;return c}),P.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return w(a,b)}).style("stroke",function(a,b){ -return w(a,b)}),P.style("stroke-opacity",1).style("fill-opacity",B);var R=P.selectAll("rect.nv-bar").data(function(a){return x&&!b.length?x.values:a.values});R.exit().remove();R.enter().append("rect").attr("class",function(a,b){return r(a,b)<0?"nv-bar negative":"nv-bar positive"}).attr("x",function(a,c,d){return u&&!b[d].nonStackable?0:d*m.rangeBand()/b.length}).attr("y",function(a,c,d){return i(u&&!b[d].nonStackable?a.y0:0)||0}).attr("height",0).attr("width",function(a,c,d){return m.rangeBand()/(u&&!b[d].nonStackable?1:b.length)}).attr("transform",function(a,b){return"translate("+m(q(a,b))+",0)"});R.style("fill",function(a,b,c){return w(a,c,b)}).style("stroke",function(a,b,c){return w(a,c,b)}).on("mouseover",function(a,b){d3.select(this).classed("hover",!0),C.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),C.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mousemove",function(a,b){C.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){var c=this;C.elementClick({data:a,index:b,color:d3.select(this).style("fill"),event:d3.event,element:c}),d3.event.stopPropagation()}).on("dblclick",function(a,b){C.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}),R.attr("class",function(a,b){return r(a,b)<0?"nv-bar negative":"nv-bar positive"}).attr("transform",function(a,b){return"translate("+m(q(a,b))+",0)"}),y&&(c||(c=b.map(function(){return!0})),R.style("fill",function(a,b,d){return d3.rgb(y(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()}).style("stroke",function(a,b,d){return d3.rgb(y(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()}));var S=R.watchTransition(D,"multibar",Math.min(250,z)).delay(function(a,c){return c*z/b[0].values.length});u?S.attr("y",function(a,c,d){var e=0;return e=b[d].nonStackable?r(a,c)<0?n(0):n(0)-n(r(a,c))<-1?n(0)-1:n(r(a,c))||0:n(a.y1)}).attr("height",function(a,c,d){return b[d].nonStackable?Math.max(Math.abs(n(r(a,c))-n(0)),0)||0:Math.max(Math.abs(n(a.y+a.y0)-n(a.y0)),0)}).attr("x",function(a,c,d){var e=0;return b[d].nonStackable&&(e=a.series*m.rangeBand()/b.length,b.length!==H&&(e=b[d].nonStackableSeries*m.rangeBand()/(2*H))),e}).attr("width",function(a,c,d){if(b[d].nonStackable){var e=m.rangeBand()/H;return b.length!==H&&(e=m.rangeBand()/(2*H)),e}return m.rangeBand()}):S.attr("x",function(a,c){return a.series*m.rangeBand()/b.length}).attr("width",m.rangeBand()/b.length).attr("y",function(a,b){return r(a,b)<0?n(0):n(0)-n(r(a,b))<1?n(0)-1:n(r(a,b))||0}).attr("height",function(a,b){return Math.max(Math.abs(n(r(a,b))-n(0)),1)||0}),h=m.copy(),i=n.copy(),b[0]&&b[0].values&&(E=b[0].values.length)}),D.renderEnd("multibar immediate"),b}var c,d,e,f,g,h,i,j={top:0,right:0,bottom:0,left:0},k=960,l=500,m=d3.scale.ordinal(),n=d3.scale.linear(),o=Math.floor(1e4*Math.random()),p=null,q=function(a){return a.x},r=function(a){return a.y},s=[0],t=!0,u=!1,v="zero",w=a.utils.defaultColor(),x=!1,y=null,z=500,A=.1,B=.75,C=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),D=a.utils.renderWatch(C,z),E=0;return b.dispatch=C,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},x:{get:function(){return q},set:function(a){q=a}},y:{get:function(){return r},set:function(a){r=a}},xScale:{get:function(){return m},set:function(a){m=a}},yScale:{get:function(){return n},set:function(a){n=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},forceY:{get:function(){return s},set:function(a){s=a}},stacked:{get:function(){return u},set:function(a){u=a}},stackOffset:{get:function(){return v},set:function(a){v=a}},clipEdge:{get:function(){return t},set:function(a){t=a}},disabled:{get:function(){return c},set:function(a){c=a}},id:{get:function(){return o},set:function(a){o=a}},hideable:{get:function(){return x},set:function(a){x=a}},groupSpacing:{get:function(){return A},set:function(a){A=a}},fillOpacity:{get:function(){return B},set:function(a){B=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},duration:{get:function(){return z},set:function(a){z=a,D.reset(z)}},color:{get:function(){return w},set:function(b){w=a.utils.getColor(b)}},barColor:{get:function(){return y},set:function(b){y=b?a.utils.getColor(b):null}}}),a.utils.initOptions(b),b},a.models.multiBarChart=function(){"use strict";function b(C){return H.reset(),H.models(e),t&&H.models(f),u&&H.models(g),C.each(function(C){var H=d3.select(this);a.utils.initSVG(H);var L=a.utils.availableWidth(n,H,l),M=a.utils.availableHeight(o,H,l);if(b.update=function(){0===F?H.call(b):H.transition().duration(F).call(b)},b.container=this,A.setter(K(C),b.update).getter(J(C)).update(),A.disabled=C.map(function(a){return!!a.disabled}),!B){var N;B={};for(N in A)A[N]instanceof Array?B[N]=A[N].slice(0):B[N]=A[N]}if(!(C&&C.length&&C.filter(function(a){return a.values.length}).length))return a.utils.noData(b,H),b;H.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var O=H.selectAll("g.nv-wrap.nv-multiBarWithLegend").data([C]),P=O.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarWithLegend").append("g"),Q=O.select("g");if(P.append("g").attr("class","nv-x nv-axis"),P.append("g").attr("class","nv-y nv-axis"),P.append("g").attr("class","nv-barsWrap"),P.append("g").attr("class","nv-legendWrap"),P.append("g").attr("class","nv-controlsWrap"),P.append("g").attr("class","nv-interactive"),s?(i.width(L-E()),Q.select(".nv-legendWrap").datum(C).call(i),m||i.height()===l.top||(l.top=i.height(),M=a.utils.availableHeight(o,H,l)),Q.select(".nv-legendWrap").attr("transform","translate("+E()+","+-l.top+")")):Q.select(".nv-legendWrap").selectAll("*").remove(),q){var R=[{key:r.grouped||"Grouped",disabled:e.stacked()},{key:r.stacked||"Stacked",disabled:!e.stacked()}];j.width(E()).color(["#444","#444","#444"]),Q.select(".nv-controlsWrap").datum(R).attr("transform","translate(0,"+-l.top+")").call(j)}else Q.select(".nv-controlsWrap").selectAll("*").remove();O.attr("transform","translate("+l.left+","+l.top+")"),v&&Q.select(".nv-y.nv-axis").attr("transform","translate("+L+",0)"),e.disabled(C.map(function(a){return a.disabled})).width(L).height(M).color(C.map(function(a,b){return a.color||p(a,b)}).filter(function(a,b){return!C[b].disabled}));var S=Q.select(".nv-barsWrap").datum(C.filter(function(a){return!a.disabled}));if(S.call(e),t){f.scale(c)._ticks(a.utils.calcTicksX(L/100,C)).tickSize(-M,0),Q.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),Q.select(".nv-x.nv-axis").call(f);var T=Q.select(".nv-x.nv-axis > g").selectAll("g");if(T.selectAll("line, text").style("opacity",1),x){var U=function(a,b){return"translate("+a+","+b+")"},V=5,W=17;T.selectAll("text").attr("transform",function(a,b,c){return U(0,c%2==0?V:W)});var X=d3.selectAll(".nv-x.nv-axis .nv-wrap g g text")[0].length;Q.selectAll(".nv-x.nv-axis .nv-axisMaxMin text").attr("transform",function(a,b){return U(0,0===b||X%2!==0?W:V)})}y&&Q.selectAll(".tick text").call(a.utils.wrapTicks,b.xAxis.rangeBand()),w&&T.filter(function(a,b){return b%Math.ceil(C[0].values.length/(L/100))!==0}).selectAll("text, line").style("opacity",0),z&&T.selectAll(".tick text").attr("transform","rotate("+z+" 0,0)").style("text-anchor",z>0?"start":"end"),Q.select(".nv-x.nv-axis").selectAll("g.nv-axisMaxMin text").style("opacity",1)}u&&(g.scale(d)._ticks(a.utils.calcTicksY(M/36,C)).tickSize(-L,0),Q.select(".nv-y.nv-axis").call(g)),G&&(h.width(L).height(M).margin({left:l.left,top:l.top}).svgContainer(H).xScale(c),O.select(".nv-interactive").call(h)),i.dispatch.on("stateChange",function(a){for(var c in a)A[c]=a[c];D.stateChange(A),b.update()}),j.dispatch.on("legendClick",function(a,c){if(a.disabled){switch(R=R.map(function(a){return a.disabled=!0,a}),a.disabled=!1,a.key){case"Grouped":case r.grouped:e.stacked(!1);break;case"Stacked":case r.stacked:e.stacked(!0)}A.stacked=e.stacked(),D.stateChange(A),b.update()}}),D.on("changeState",function(a){"undefined"!=typeof a.disabled&&(C.forEach(function(b,c){b.disabled=a.disabled[c]}),A.disabled=a.disabled),"undefined"!=typeof a.stacked&&(e.stacked(a.stacked),A.stacked=a.stacked,I=a.stacked),b.update()}),G?(h.dispatch.on("elementMousemove",function(a){if(void 0!=a.pointXValue){var d,e,f,g,i=[];C.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(h,j){e=c.domain().indexOf(a.pointXValue);var k=h.values[e];void 0!==k&&(g=k.x,void 0===d&&(d=k),void 0===f&&(f=a.mouseX),i.push({key:h.key,value:b.y()(k,e),color:p(h,h.seriesIndex),data:h.values[e]}))}),h.tooltip.data({value:g,index:e,series:i})(),h.renderGuideLine(f)}}),h.dispatch.on("elementMouseout",function(a){h.tooltip.hidden(!0)})):(e.dispatch.on("elementMouseover.tooltip",function(a){a.value=b.x()(a.data),a.series={key:a.data.key,value:b.y()(a.data),color:a.color},k.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(a){k.hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(a){k()}))}),H.renderEnd("multibarchart immediate"),b}var c,d,e=a.models.multiBar(),f=a.models.axis(),g=a.models.axis(),h=a.interactiveGuideline(),i=a.models.legend(),j=a.models.legend(),k=a.models.tooltip(),l={top:30,right:20,bottom:50,left:60},m=null,n=null,o=null,p=a.utils.defaultColor(),q=!0,r={},s=!0,t=!0,u=!0,v=!1,w=!0,x=!1,y=!1,z=0,A=a.utils.state(),B=null,C=null,D=d3.dispatch("stateChange","changeState","renderEnd"),E=function(){return q?180:0},F=250,G=!1;A.stacked=!1,e.stacked(!1),f.orient("bottom").tickPadding(7).showMaxMin(!1).tickFormat(function(a){return a}),g.orient(v?"right":"left").tickFormat(d3.format(",.1f")),k.duration(0).valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)}),h.tooltip.valueFormatter(function(a,b){return null==a?"N/A":g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)}),h.tooltip.valueFormatter(function(a,b){return null==a?"N/A":g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)}),h.tooltip.duration(0).valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)}),j.updateState(!1);var H=a.utils.renderWatch(D),I=!1,J=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),stacked:I}}},K=function(a){return function(b){void 0!==b.stacked&&(I=b.stacked),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return b.dispatch=D,b.multibar=e,b.legend=i,b.controls=j,b.xAxis=f,b.yAxis=g,b.state=A,b.tooltip=k,b.interactiveLayer=h,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return n},set:function(a){n=a}},height:{get:function(){return o},set:function(a){o=a}},showLegend:{get:function(){return s},set:function(a){s=a}},showControls:{get:function(){return q},set:function(a){q=a}},controlLabels:{get:function(){return r},set:function(a){r=a}},showXAxis:{get:function(){return t},set:function(a){t=a}},showYAxis:{get:function(){return u},set:function(a){u=a}},defaultState:{get:function(){return B},set:function(a){B=a}},noData:{get:function(){return C},set:function(a){C=a}},reduceXTicks:{get:function(){return w},set:function(a){w=a}},rotateLabels:{get:function(){return z},set:function(a){z=a}},staggerLabels:{get:function(){return x},set:function(a){x=a}},wrapLabels:{get:function(){return y},set:function(a){y=!!a}},margin:{get:function(){return l},set:function(a){void 0!==a.top&&(l.top=a.top,m=a.top),l.right=void 0!==a.right?a.right:l.right,l.bottom=void 0!==a.bottom?a.bottom:l.bottom,l.left=void 0!==a.left?a.left:l.left}},duration:{get:function(){return F},set:function(a){F=a,e.duration(F),f.duration(F),g.duration(F),H.reset(F)}},color:{get:function(){return p},set:function(b){p=a.utils.getColor(b),i.color(p)}},rightAlignYAxis:{get:function(){return v},set:function(a){v=a,g.orient(v?"right":"left")}},useInteractiveGuideline:{get:function(){return G},set:function(a){G=a}},barColor:{get:function(){return e.barColor},set:function(a){e.barColor(a),i.color(function(a,b){return d3.rgb("#ccc").darker(1.5*b).toString()})}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.multiBarHorizontal=function(){"use strict";function b(m){return F.reset(),m.each(function(b){var m=k-j.left-j.right,D=l-j.top-j.bottom;n=d3.select(this),a.utils.initSVG(n),w&&(b=d3.layout.stack().offset("zero").values(function(a){return a.values}).y(r)(b)),b.forEach(function(a,b){a.values.forEach(function(c){c.series=b,c.key=a.key})}),w&&b[0].values.map(function(a,c){var d=0,e=0;b.map(function(a){var b=a.values[c];b.size=Math.abs(b.y),b.y<0?(b.y1=e-b.size,e-=b.size):(b.y1=d,d+=b.size)})});var G=d&&e?[]:b.map(function(a){return a.values.map(function(a,b){return{x:q(a,b),y:r(a,b),y0:a.y0,y1:a.y1}})});o.domain(d||d3.merge(G).map(function(a){return a.x})).rangeBands(f||[0,D],A),p.domain(e||d3.extent(d3.merge(G).map(function(a){return w?a.y>0?a.y1+a.y:a.y1:a.y}).concat(t))),x&&!w?p.range(g||[p.domain()[0]<0?z:0,m-(p.domain()[1]>0?z:0)]):p.range(g||[0,m]),h=h||o,i=i||d3.scale.linear().domain(p.domain()).range([p(0),p(0)]);var H=d3.select(this).selectAll("g.nv-wrap.nv-multibarHorizontal").data([b]),I=H.enter().append("g").attr("class","nvd3 nv-wrap nv-multibarHorizontal"),J=(I.append("defs"),I.append("g"));H.select("g");J.append("g").attr("class","nv-groups"),H.attr("transform","translate("+j.left+","+j.top+")");var K=H.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a,b){return b});K.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),K.exit().watchTransition(F,"multibarhorizontal: exit groups").style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),K.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return u(a,b)}).style("stroke",function(a,b){return u(a,b)}),K.watchTransition(F,"multibarhorizontal: groups").style("stroke-opacity",1).style("fill-opacity",B);var L=K.selectAll("g.nv-bar").data(function(a){return a.values});L.exit().remove();var M=L.enter().append("g").attr("transform",function(a,c,d){return"translate("+i(w?a.y0:0)+","+(w?0:d*o.rangeBand()/b.length+o(q(a,c)))+")"});M.append("rect").attr("width",0).attr("height",o.rangeBand()/(w?1:b.length)),L.on("mouseover",function(a,b){d3.select(this).classed("hover",!0),E.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),E.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){E.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mousemove",function(a,b){E.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){var c=this;E.elementClick({data:a,index:b,color:d3.select(this).style("fill"),event:d3.event,element:c}),d3.event.stopPropagation()}).on("dblclick",function(a,b){E.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}),s(b[0],0)&&(M.append("polyline"),L.select("polyline").attr("fill","none").attr("points",function(a,c){var d=s(a,c),e=.8*o.rangeBand()/(2*(w?1:b.length));d=d.length?d:[-Math.abs(d),Math.abs(d)],d=d.map(function(a){return p(a)-p(0)});var f=[[d[0],-e],[d[0],e],[d[0],0],[d[1],0],[d[1],-e],[d[1],e]];return f.map(function(a){return a.join(",")}).join(" ")}).attr("transform",function(a,c){var d=o.rangeBand()/(2*(w?1:b.length));return"translate("+(r(a,c)<0?0:p(r(a,c))-p(0))+", "+d+")"})),M.append("text"),x&&!w?(L.select("text").attr("text-anchor",function(a,b){return r(a,b)<0?"end":"start"}).attr("y",o.rangeBand()/(2*b.length)).attr("dy",".32em").text(function(a,b){var c=C(r(a,b)),d=s(a,b);return void 0===d?c:d.length?c+"+"+C(Math.abs(d[1]))+"-"+C(Math.abs(d[0])):c+"±"+C(Math.abs(d))}),L.watchTransition(F,"multibarhorizontal: bars").select("text").attr("x",function(a,b){return r(a,b)<0?-4:p(r(a,b))-p(0)+4})):L.selectAll("text").text(""),y&&!w?(M.append("text").classed("nv-bar-label",!0),L.select("text.nv-bar-label").attr("text-anchor",function(a,b){return r(a,b)<0?"start":"end"}).attr("y",o.rangeBand()/(2*b.length)).attr("dy",".32em").text(function(a,b){return q(a,b)}),L.watchTransition(F,"multibarhorizontal: bars").select("text.nv-bar-label").attr("x",function(a,b){return r(a,b)<0?p(0)-p(r(a,b))+4:-4})):L.selectAll("text.nv-bar-label").text(""),L.attr("class",function(a,b){return r(a,b)<0?"nv-bar negative":"nv-bar positive"}),v&&(c||(c=b.map(function(){return!0})),L.style("fill",function(a,b,d){return d3.rgb(v(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()}).style("stroke",function(a,b,d){return d3.rgb(v(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()})),w?L.watchTransition(F,"multibarhorizontal: bars").attr("transform",function(a,b){return"translate("+p(a.y1)+","+o(q(a,b))+")"}).select("rect").attr("width",function(a,b){return Math.abs(p(r(a,b)+a.y0)-p(a.y0))||0}).attr("height",o.rangeBand()):L.watchTransition(F,"multibarhorizontal: bars").attr("transform",function(a,c){return"translate("+p(r(a,c)<0?r(a,c):0)+","+(a.series*o.rangeBand()/b.length+o(q(a,c)))+")"}).select("rect").attr("height",o.rangeBand()/b.length).attr("width",function(a,b){return Math.max(Math.abs(p(r(a,b))-p(0)),1)||0}),h=o.copy(),i=p.copy()}),F.renderEnd("multibarHorizontal immediate"),b}var c,d,e,f,g,h,i,j={top:0,right:0,bottom:0,left:0},k=960,l=500,m=Math.floor(1e4*Math.random()),n=null,o=d3.scale.ordinal(),p=d3.scale.linear(),q=function(a){return a.x},r=function(a){return a.y},s=function(a){return a.yErr},t=[0],u=a.utils.defaultColor(),v=null,w=!1,x=!1,y=!1,z=60,A=.1,B=.75,C=d3.format(",.2f"),D=250,E=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),F=a.utils.renderWatch(E,D);return b.dispatch=E,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},x:{get:function(){return q},set:function(a){q=a}},y:{get:function(){return r},set:function(a){r=a}},yErr:{get:function(){return s},set:function(a){s=a}},xScale:{get:function(){return o},set:function(a){o=a}},yScale:{get:function(){return p},set:function(a){p=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},forceY:{get:function(){return t},set:function(a){t=a}},stacked:{get:function(){return w},set:function(a){w=a}},showValues:{get:function(){return x},set:function(a){x=a}},disabled:{get:function(){return c},set:function(a){c=a}},id:{get:function(){return m},set:function(a){m=a}},valueFormat:{get:function(){return C},set:function(a){C=a}},valuePadding:{get:function(){return z},set:function(a){z=a}},groupSpacing:{get:function(){return A},set:function(a){A=a}},fillOpacity:{get:function(){return B},set:function(a){B=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},duration:{get:function(){return D},set:function(a){D=a,F.reset(D)}},color:{get:function(){return u},set:function(b){u=a.utils.getColor(b)}},barColor:{get:function(){return v},set:function(b){v=b?a.utils.getColor(b):null}}}),a.utils.initOptions(b),b},a.models.multiBarHorizontalChart=function(){"use strict";function b(j){return D.reset(),D.models(e),s&&D.models(f),t&&D.models(g),j.each(function(j){var x=d3.select(this);a.utils.initSVG(x);var D=a.utils.availableWidth(m,x,k),E=a.utils.availableHeight(n,x,k);if(b.update=function(){x.transition().duration(A).call(b)},b.container=this,u=e.stacked(),v.setter(C(j),b.update).getter(B(j)).update(),v.disabled=j.map(function(a){return!!a.disabled}),!w){var F;w={};for(F in v)v[F]instanceof Array?w[F]=v[F].slice(0):w[F]=v[F]}if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,x),b;x.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale().clamp(!0);var G=x.selectAll("g.nv-wrap.nv-multiBarHorizontalChart").data([j]),H=G.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarHorizontalChart").append("g"),I=G.select("g");if(H.append("g").attr("class","nv-x nv-axis"),H.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),H.append("g").attr("class","nv-barsWrap"),H.append("g").attr("class","nv-legendWrap"),H.append("g").attr("class","nv-controlsWrap"),r?(h.width(D-z()),I.select(".nv-legendWrap").datum(j).call(h),l||h.height()===k.top||(k.top=h.height(),E=a.utils.availableHeight(n,x,k)),I.select(".nv-legendWrap").attr("transform","translate("+z()+","+-k.top+")")):I.select(".nv-legendWrap").selectAll("*").remove(),p){var J=[{key:q.grouped||"Grouped",disabled:e.stacked()},{key:q.stacked||"Stacked",disabled:!e.stacked()}];i.width(z()).color(["#444","#444","#444"]),I.select(".nv-controlsWrap").datum(J).attr("transform","translate(0,"+-k.top+")").call(i)}else I.select(".nv-controlsWrap").selectAll("*").remove();G.attr("transform","translate("+k.left+","+k.top+")"),e.disabled(j.map(function(a){return a.disabled})).width(D).height(E).color(j.map(function(a,b){return a.color||o(a,b)}).filter(function(a,b){return!j[b].disabled}));var K=I.select(".nv-barsWrap").datum(j.filter(function(a){return!a.disabled}));if(K.transition().call(e),s){f.scale(c)._ticks(a.utils.calcTicksY(E/24,j)).tickSize(-D,0),I.select(".nv-x.nv-axis").call(f);var L=I.select(".nv-x.nv-axis").selectAll("g");L.selectAll("line, text")}t&&(g.scale(d)._ticks(a.utils.calcTicksX(D/100,j)).tickSize(-E,0),I.select(".nv-y.nv-axis").attr("transform","translate(0,"+E+")"),I.select(".nv-y.nv-axis").call(g)),I.select(".nv-zeroLine line").attr("x1",d(0)).attr("x2",d(0)).attr("y1",0).attr("y2",-E),h.dispatch.on("stateChange",function(a){for(var c in a)v[c]=a[c];y.stateChange(v),b.update()}),i.dispatch.on("legendClick",function(a,c){if(a.disabled){switch(J=J.map(function(a){return a.disabled=!0,a}),a.disabled=!1,a.key){case"Grouped":case q.grouped:e.stacked(!1);break;case"Stacked":case q.stacked:e.stacked(!0)}v.stacked=e.stacked(),y.stateChange(v),u=e.stacked(),b.update()}}),y.on("changeState",function(a){"undefined"!=typeof a.disabled&&(j.forEach(function(b,c){b.disabled=a.disabled[c]}),v.disabled=a.disabled),"undefined"!=typeof a.stacked&&(e.stacked(a.stacked),v.stacked=a.stacked,u=a.stacked),b.update()})}),D.renderEnd("multibar horizontal chart immediate"),b}var c,d,e=a.models.multiBarHorizontal(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend().height(30),i=a.models.legend().height(30),j=a.models.tooltip(),k={top:30,right:20,bottom:50,left:60},l=null,m=null,n=null,o=a.utils.defaultColor(),p=!0,q={},r=!0,s=!0,t=!0,u=!1,v=a.utils.state(),w=null,x=null,y=d3.dispatch("stateChange","changeState","renderEnd"),z=function(){return p?180:0},A=250;v.stacked=!1,e.stacked(u),f.orient("left").tickPadding(5).showMaxMin(!1).tickFormat(function(a){return a}),g.orient("bottom").tickFormat(d3.format(",.1f")),j.duration(0).valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)}),i.updateState(!1);var B=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),stacked:u}}},C=function(a){return function(b){void 0!==b.stacked&&(u=b.stacked),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}},D=a.utils.renderWatch(y,A);return e.dispatch.on("elementMouseover.tooltip",function(a){a.value=b.x()(a.data),a.series={key:a.data.key,value:b.y()(a.data),color:a.color},j.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(a){j.hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(a){j()}),b.dispatch=y,b.multibar=e,b.legend=h,b.controls=i,b.xAxis=f,b.yAxis=g,b.state=v,b.tooltip=j,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return m},set:function(a){m=a}},height:{get:function(){return n},set:function(a){n=a}},showLegend:{get:function(){return r},set:function(a){r=a}},showControls:{get:function(){return p},set:function(a){p=a}},controlLabels:{get:function(){return q},set:function(a){q=a}},showXAxis:{get:function(){return s},set:function(a){s=a}},showYAxis:{get:function(){return t},set:function(a){t=a}},defaultState:{get:function(){return w},set:function(a){w=a}},noData:{get:function(){return x},set:function(a){x=a}},margin:{get:function(){return k},set:function(a){void 0!==a.top&&(k.top=a.top,l=a.top),k.right=void 0!==a.right?a.right:k.right,k.bottom=void 0!==a.bottom?a.bottom:k.bottom,k.left=void 0!==a.left?a.left:k.left}},duration:{get:function(){return A},set:function(a){A=a,D.reset(A),e.duration(A),f.duration(A),g.duration(A)}},color:{get:function(){return o},set:function(b){o=a.utils.getColor(b),h.color(o)}},barColor:{get:function(){return e.barColor},set:function(a){e.barColor(a),h.color(function(a,b){return d3.rgb("#ccc").darker(1.5*b).toString()})}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.multiChart=function(){"use strict";function b(k){return k.each(function(k){function o(a){var b=2===k[a.seriesIndex].yAxis?G:F;a.value=a.point.x,a.series={value:a.point.y,color:a.point.color,key:a.series.key},I.duration(0).headerFormatter(function(a,b){return E.tickFormat()(a,b)}).valueFormatter(function(a,c){return b.tickFormat()(a,c)}).data(a).hidden(!1)}function s(a){var b=2===k[a.seriesIndex].yAxis?G:F;a.value=a.point.x,a.series={value:a.point.y,color:a.point.color,key:a.series.key},I.duration(100).headerFormatter(function(a,b){return E.tickFormat()(a,b)}).valueFormatter(function(a,c){return b.tickFormat()(a,c)}).data(a).hidden(!1)}function J(a){var b=2===k[a.seriesIndex].yAxis?G:F;a.point.x=C.x()(a.point),a.point.y=C.y()(a.point),I.duration(0).headerFormatter(function(a,b){return E.tickFormat()(a,b)}).valueFormatter(function(a,c){return b.tickFormat()(a,c)}).data(a).hidden(!1)}function L(a){var b=2===k[a.data.series].yAxis?G:F;a.value=A.x()(a.data),a.series={value:A.y()(a.data),color:a.color,key:a.data.key},I.duration(0).headerFormatter(function(a,b){return E.tickFormat()(a,b)}).valueFormatter(function(a,c){return b.tickFormat()(a,c)}).data(a).hidden(!1)}function M(){for(var a=0,b=K.length;b>a;a++){var c=K[a];try{c.clearHighlights()}catch(d){}}}function N(a,b,c){for(var d=0,e=K.length;e>d;d++){var f=K[d];try{f.highlightPoint(a,b,c)}catch(g){}}}var O=d3.select(this);a.utils.initSVG(O),b.update=function(){O.transition().call(b)},b.container=this;var P=a.utils.availableWidth(h,O,e),Q=a.utils.availableHeight(i,O,e),R=k.filter(function(a){return"line"==a.type&&1==a.yAxis}),S=k.filter(function(a){return"line"==a.type&&2==a.yAxis}),T=k.filter(function(a){return"scatter"==a.type&&1==a.yAxis}),U=k.filter(function(a){return"scatter"==a.type&&2==a.yAxis}),V=k.filter(function(a){return"bar"==a.type&&1==a.yAxis}),W=k.filter(function(a){return"bar"==a.type&&2==a.yAxis}),X=k.filter(function(a){return"area"==a.type&&1==a.yAxis}),Y=k.filter(function(a){return"area"==a.type&&2==a.yAxis});if(!(k&&k.length&&k.filter(function(a){return a.values.length}).length))return a.utils.noData(b,O),b;O.selectAll(".nv-noData").remove();var Z=k.filter(function(a){return!a.disabled&&1==a.yAxis}).map(function(a){return a.values.map(function(a,b){return{x:l(a),y:m(a)}})}),$=k.filter(function(a){return!a.disabled&&2==a.yAxis}).map(function(a){return a.values.map(function(a,b){return{x:l(a),y:m(a)}})});t.domain(d3.extent(d3.merge(Z.concat($)),function(a){return a.x})).range([0,P]);var _=O.selectAll("g.wrap.multiChart").data([k]),aa=_.enter().append("g").attr("class","wrap nvd3 multiChart").append("g");aa.append("g").attr("class","nv-x nv-axis"),aa.append("g").attr("class","nv-y1 nv-axis"),aa.append("g").attr("class","nv-y2 nv-axis"),aa.append("g").attr("class","stack1Wrap"),aa.append("g").attr("class","stack2Wrap"),aa.append("g").attr("class","bars1Wrap"),aa.append("g").attr("class","bars2Wrap"),aa.append("g").attr("class","scatters1Wrap"),aa.append("g").attr("class","scatters2Wrap"),aa.append("g").attr("class","lines1Wrap"),aa.append("g").attr("class","lines2Wrap"),aa.append("g").attr("class","legendWrap"),aa.append("g").attr("class","nv-interactive");var ba=_.select("g"),ca=k.map(function(a,b){return k[b].color||g(a,b)});if(j){var da=H.align()?P/2:P,ea=H.align()?da:0;H.width(da),H.color(ca),ba.select(".legendWrap").datum(k.map(function(a){return a.originalKey=void 0===a.originalKey?a.key:a.originalKey,a.key=a.originalKey+(1==a.yAxis?"":r),a})).call(H),f||H.height()===e.top||(e.top=H.height(),Q=a.utils.availableHeight(i,O,e)),ba.select(".legendWrap").attr("transform","translate("+ea+","+-e.top+")")}else ba.select(".legendWrap").selectAll("*").remove();w.width(P).height(Q).interpolate(n).color(ca.filter(function(a,b){return!k[b].disabled&&1==k[b].yAxis&&"line"==k[b].type})),x.width(P).height(Q).interpolate(n).color(ca.filter(function(a,b){return!k[b].disabled&&2==k[b].yAxis&&"line"==k[b].type})),y.width(P).height(Q).color(ca.filter(function(a,b){return!k[b].disabled&&1==k[b].yAxis&&"scatter"==k[b].type})),z.width(P).height(Q).color(ca.filter(function(a,b){return!k[b].disabled&&2==k[b].yAxis&&"scatter"==k[b].type})),A.width(P).height(Q).color(ca.filter(function(a,b){return!k[b].disabled&&1==k[b].yAxis&&"bar"==k[b].type})),B.width(P).height(Q).color(ca.filter(function(a,b){return!k[b].disabled&&2==k[b].yAxis&&"bar"==k[b].type})),C.width(P).height(Q).interpolate(n).color(ca.filter(function(a,b){return!k[b].disabled&&1==k[b].yAxis&&"area"==k[b].type})),D.width(P).height(Q).interpolate(n).color(ca.filter(function(a,b){return!k[b].disabled&&2==k[b].yAxis&&"area"==k[b].type})),ba.attr("transform","translate("+e.left+","+e.top+")");var fa=ba.select(".lines1Wrap").datum(R.filter(function(a){return!a.disabled})),ga=ba.select(".scatters1Wrap").datum(T.filter(function(a){return!a.disabled})),ha=ba.select(".bars1Wrap").datum(V.filter(function(a){return!a.disabled})),ia=ba.select(".stack1Wrap").datum(X.filter(function(a){return!a.disabled})),ja=ba.select(".lines2Wrap").datum(S.filter(function(a){return!a.disabled})),ka=ba.select(".scatters2Wrap").datum(U.filter(function(a){return!a.disabled})),la=ba.select(".bars2Wrap").datum(W.filter(function(a){return!a.disabled})),ma=ba.select(".stack2Wrap").datum(Y.filter(function(a){return!a.disabled})),na=X.length?X.map(function(a){return a.values}).reduce(function(a,b){return a.map(function(a,c){return{x:a.x,y:a.y+b[c].y}})}).concat([{x:0,y:0}]):[],oa=Y.length?Y.map(function(a){return a.values}).reduce(function(a,b){return a.map(function(a,c){return{x:a.x,y:a.y+b[c].y}})}).concat([{x:0,y:0}]):[];u.domain(c||d3.extent(d3.merge(Z).concat(na),function(a){return a.y})).range([0,Q]),v.domain(d||d3.extent(d3.merge($).concat(oa),function(a){return a.y})).range([0,Q]),w.yDomain(u.domain()),y.yDomain(u.domain()),A.yDomain(u.domain()),C.yDomain(u.domain()),x.yDomain(v.domain()),z.yDomain(v.domain()),B.yDomain(v.domain()),D.yDomain(v.domain()),X.length&&d3.transition(ia).call(C),Y.length&&d3.transition(ma).call(D),V.length&&d3.transition(ha).call(A),W.length&&d3.transition(la).call(B),R.length&&d3.transition(fa).call(w), -S.length&&d3.transition(ja).call(x),T.length&&d3.transition(ga).call(y),U.length&&d3.transition(ka).call(z),E._ticks(a.utils.calcTicksX(P/100,k)).tickSize(-Q,0),ba.select(".nv-x.nv-axis").attr("transform","translate(0,"+Q+")"),d3.transition(ba.select(".nv-x.nv-axis")).call(E),F._ticks(a.utils.calcTicksY(Q/36,k)).tickSize(-P,0),d3.transition(ba.select(".nv-y1.nv-axis")).call(F),G._ticks(a.utils.calcTicksY(Q/36,k)).tickSize(-P,0),d3.transition(ba.select(".nv-y2.nv-axis")).call(G),ba.select(".nv-y1.nv-axis").classed("nv-disabled",Z.length?!1:!0).attr("transform","translate("+t.range()[0]+",0)"),ba.select(".nv-y2.nv-axis").classed("nv-disabled",$.length?!1:!0).attr("transform","translate("+t.range()[1]+",0)"),H.dispatch.on("stateChange",function(a){b.update()}),q&&(p.width(P).height(Q).margin({left:e.left,top:e.top}).svgContainer(O).xScale(t),_.select(".nv-interactive").call(p)),q?(p.dispatch.on("elementMousemove",function(c){M();var d,e,f,h=[];k.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(i,j){var k=t.domain(),l=i.values.filter(function(a,c){return b.x()(a,c)>=k[0]&&b.x()(a,c)<=k[1]});e=a.interactiveBisect(l,c.pointXValue,b.x());var m=l[e],n=b.y()(m,e);null!==n&&N(j,e,!0),void 0!==m&&(void 0===d&&(d=m),void 0===f&&(f=t(b.x()(m,e))),h.push({key:i.key,value:n,color:g(i,i.seriesIndex),data:m,yAxis:2==i.yAxis?G:F}))});var i=function(a,b){var c=h[b].yAxis;return null==a?"N/A":c.tickFormat()(a)};p.tooltip.headerFormatter(function(a,b){return E.tickFormat()(a,b)}).valueFormatter(p.tooltip.valueFormatter()||i).data({value:b.x()(d,e),index:e,series:h})(),p.renderGuideLine(f)}),p.dispatch.on("elementMouseout",function(a){M()})):(w.dispatch.on("elementMouseover.tooltip",o),x.dispatch.on("elementMouseover.tooltip",o),w.dispatch.on("elementMouseout.tooltip",function(a){I.hidden(!0)}),x.dispatch.on("elementMouseout.tooltip",function(a){I.hidden(!0)}),y.dispatch.on("elementMouseover.tooltip",s),z.dispatch.on("elementMouseover.tooltip",s),y.dispatch.on("elementMouseout.tooltip",function(a){I.hidden(!0)}),z.dispatch.on("elementMouseout.tooltip",function(a){I.hidden(!0)}),C.dispatch.on("elementMouseover.tooltip",J),D.dispatch.on("elementMouseover.tooltip",J),C.dispatch.on("elementMouseout.tooltip",function(a){I.hidden(!0)}),D.dispatch.on("elementMouseout.tooltip",function(a){I.hidden(!0)}),A.dispatch.on("elementMouseover.tooltip",L),B.dispatch.on("elementMouseover.tooltip",L),A.dispatch.on("elementMouseout.tooltip",function(a){I.hidden(!0)}),B.dispatch.on("elementMouseout.tooltip",function(a){I.hidden(!0)}),A.dispatch.on("elementMousemove.tooltip",function(a){I()}),B.dispatch.on("elementMousemove.tooltip",function(a){I()}))}),b}var c,d,e={top:30,right:20,bottom:50,left:60},f=null,g=a.utils.defaultColor(),h=null,i=null,j=!0,k=null,l=function(a){return a.x},m=function(a){return a.y},n="linear",o=!0,p=a.interactiveGuideline(),q=!1,r=" (right axis)",s=250,t=d3.scale.linear(),u=d3.scale.linear(),v=d3.scale.linear(),w=a.models.line().yScale(u).duration(s),x=a.models.line().yScale(v).duration(s),y=a.models.scatter().yScale(u).duration(s),z=a.models.scatter().yScale(v).duration(s),A=a.models.multiBar().stacked(!1).yScale(u).duration(s),B=a.models.multiBar().stacked(!1).yScale(v).duration(s),C=a.models.stackedArea().yScale(u).duration(s),D=a.models.stackedArea().yScale(v).duration(s),E=a.models.axis().scale(t).orient("bottom").tickPadding(5).duration(s),F=a.models.axis().scale(u).orient("left").duration(s),G=a.models.axis().scale(v).orient("right").duration(s),H=a.models.legend().height(30),I=a.models.tooltip(),J=d3.dispatch(),K=[w,x,y,z,A,B,C,D];return b.dispatch=J,b.legend=H,b.lines1=w,b.lines2=x,b.scatters1=y,b.scatters2=z,b.bars1=A,b.bars2=B,b.stack1=C,b.stack2=D,b.xAxis=E,b.yAxis1=F,b.yAxis2=G,b.tooltip=I,b.interactiveLayer=p,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},showLegend:{get:function(){return j},set:function(a){j=a}},yDomain1:{get:function(){return c},set:function(a){c=a}},yDomain2:{get:function(){return d},set:function(a){d=a}},noData:{get:function(){return k},set:function(a){k=a}},interpolate:{get:function(){return n},set:function(a){n=a}},legendRightAxisHint:{get:function(){return r},set:function(a){r=a}},margin:{get:function(){return e},set:function(a){void 0!==a.top&&(e.top=a.top,f=a.top),e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}},color:{get:function(){return g},set:function(b){g=a.utils.getColor(b)}},x:{get:function(){return l},set:function(a){l=a,w.x(a),x.x(a),y.x(a),z.x(a),A.x(a),B.x(a),C.x(a),D.x(a)}},y:{get:function(){return m},set:function(a){m=a,w.y(a),x.y(a),y.y(a),z.y(a),C.y(a),D.y(a),A.y(a),B.y(a)}},useVoronoi:{get:function(){return o},set:function(a){o=a,w.useVoronoi(a),x.useVoronoi(a),C.useVoronoi(a),D.useVoronoi(a)}},useInteractiveGuideline:{get:function(){return q},set:function(a){q=a,q&&(w.interactive(!1),w.useVoronoi(!1),x.interactive(!1),x.useVoronoi(!1),C.interactive(!1),C.useVoronoi(!1),D.interactive(!1),D.useVoronoi(!1),y.interactive(!1),z.interactive(!1))}},duration:{get:function(){return s},set:function(a){s=a,[w,x,C,D,y,z,E,F,G].forEach(function(a){a.duration(s)})}}}),a.utils.initOptions(b),b},a.models.ohlcBar=function(){"use strict";function b(y){return y.each(function(b){k=d3.select(this);var y=a.utils.availableWidth(h,k,g),A=a.utils.availableHeight(i,k,g);a.utils.initSVG(k);var B=y/b[0].values.length*.9;l.domain(c||d3.extent(b[0].values.map(n).concat(t))),v?l.range(e||[.5*y/b[0].values.length,y*(b[0].values.length-.5)/b[0].values.length]):l.range(e||[5+B/2,y-B/2-5]),m.domain(d||[d3.min(b[0].values.map(s).concat(u)),d3.max(b[0].values.map(r).concat(u))]).range(f||[A,0]),l.domain()[0]===l.domain()[1]&&(l.domain()[0]?l.domain([l.domain()[0]-.01*l.domain()[0],l.domain()[1]+.01*l.domain()[1]]):l.domain([-1,1])),m.domain()[0]===m.domain()[1]&&(m.domain()[0]?m.domain([m.domain()[0]+.01*m.domain()[0],m.domain()[1]-.01*m.domain()[1]]):m.domain([-1,1]));var C=d3.select(this).selectAll("g.nv-wrap.nv-ohlcBar").data([b[0].values]),D=C.enter().append("g").attr("class","nvd3 nv-wrap nv-ohlcBar"),E=D.append("defs"),F=D.append("g"),G=C.select("g");F.append("g").attr("class","nv-ticks"),C.attr("transform","translate("+g.left+","+g.top+")"),k.on("click",function(a,b){z.chartClick({data:a,index:b,pos:d3.event,id:j})}),E.append("clipPath").attr("id","nv-chart-clip-path-"+j).append("rect"),C.select("#nv-chart-clip-path-"+j+" rect").attr("width",y).attr("height",A),G.attr("clip-path",w?"url(#nv-chart-clip-path-"+j+")":"");var H=C.select(".nv-ticks").selectAll(".nv-tick").data(function(a){return a});H.exit().remove(),H.enter().append("path").attr("class",function(a,b,c){return(p(a,b)>q(a,b)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+c+"-"+b}).attr("d",function(a,b){return"m0,0l0,"+(m(p(a,b))-m(r(a,b)))+"l"+-B/2+",0l"+B/2+",0l0,"+(m(s(a,b))-m(p(a,b)))+"l0,"+(m(q(a,b))-m(s(a,b)))+"l"+B/2+",0l"+-B/2+",0z"}).attr("transform",function(a,b){return"translate("+l(n(a,b))+","+m(r(a,b))+")"}).attr("fill",function(a,b){return x[0]}).attr("stroke",function(a,b){return x[0]}).attr("x",0).attr("y",function(a,b){return m(Math.max(0,o(a,b)))}).attr("height",function(a,b){return Math.abs(m(o(a,b))-m(0))}),H.attr("class",function(a,b,c){return(p(a,b)>q(a,b)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+c+"-"+b}),d3.transition(H).attr("transform",function(a,b){return"translate("+l(n(a,b))+","+m(r(a,b))+")"}).attr("d",function(a,c){var d=y/b[0].values.length*.9;return"m0,0l0,"+(m(p(a,c))-m(r(a,c)))+"l"+-d/2+",0l"+d/2+",0l0,"+(m(s(a,c))-m(p(a,c)))+"l0,"+(m(q(a,c))-m(s(a,c)))+"l"+d/2+",0l"+-d/2+",0z"})}),b}var c,d,e,f,g={top:0,right:0,bottom:0,left:0},h=null,i=null,j=Math.floor(1e4*Math.random()),k=null,l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=function(a){return a.open},q=function(a){return a.close},r=function(a){return a.high},s=function(a){return a.low},t=[],u=[],v=!1,w=!0,x=a.utils.defaultColor(),y=!1,z=d3.dispatch("stateChange","changeState","renderEnd","chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove");return b.highlightPoint=function(a,c){b.clearHighlights(),k.select(".nv-ohlcBar .nv-tick-0-"+a).classed("hover",c)},b.clearHighlights=function(){k.select(".nv-ohlcBar .nv-tick.hover").classed("hover",!1)},b.dispatch=z,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},forceX:{get:function(){return t},set:function(a){t=a}},forceY:{get:function(){return u},set:function(a){u=a}},padData:{get:function(){return v},set:function(a){v=a}},clipEdge:{get:function(){return w},set:function(a){w=a}},id:{get:function(){return j},set:function(a){j=a}},interactive:{get:function(){return y},set:function(a){y=a}},x:{get:function(){return n},set:function(a){n=a}},y:{get:function(){return o},set:function(a){o=a}},open:{get:function(){return p()},set:function(a){p=a}},close:{get:function(){return q()},set:function(a){q=a}},high:{get:function(){return r},set:function(a){r=a}},low:{get:function(){return s},set:function(a){s=a}},margin:{get:function(){return g},set:function(a){g.top=void 0!=a.top?a.top:g.top,g.right=void 0!=a.right?a.right:g.right,g.bottom=void 0!=a.bottom?a.bottom:g.bottom,g.left=void 0!=a.left?a.left:g.left}},color:{get:function(){return x},set:function(b){x=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.parallelCoordinates=function(){"use strict";function b(B){return A.reset(),B.each(function(b){function A(a){return x(o.map(function(b){if(isNaN(a.values[b.key])||isNaN(parseFloat(a.values[b.key]))||O){var c=l[b.key].domain(),d=l[b.key].range(),e=c[0]-(c[1]-c[0])/9;if(v.indexOf(b.key)<0){var f=d3.scale.linear().domain([e,c[1]]).range([j-12,d[1]]);l[b.key].brush.y(f),v.push(b.key)}if(isNaN(a.values[b.key])||isNaN(parseFloat(a.values[b.key])))return[k(b.key),l[b.key](e)]}return void 0!==U&&(v.length>0||O?(U.style("display","inline"),V.style("display","inline")):(U.style("display","none"),V.style("display","none"))),[k(b.key),l[b.key](a.values[b.key])]}))}function B(a){s.forEach(function(b){var c=l[b.dimension].brush.y().domain();b.hasOnlyNaN&&(b.extent[1]=(l[b.dimension].domain()[1]-c[0])*(b.extent[1]-b.extent[0])/(N[b.dimension]-b.extent[0])+c[0]),b.hasNaN&&(b.extent[0]=c[0]),a&&l[b.dimension].brush.extent(b.extent)}),e.select(".nv-brushBackground").each(function(a){d3.select(this).call(l[a.key].brush)}).selectAll("rect").attr("x",-8).attr("width",16),F()}function C(){q===!1&&(q=!0,B(!0))}function D(){$=p.filter(function(a){return!l[a].brush.empty()}),_=$.map(function(a){return l[a].brush.extent()}),s=[],$.forEach(function(a,b){s[b]={dimension:a,extent:_[b],hasNaN:!1,hasOnlyNaN:!1}}),t=[],c.style("display",function(a){var b=$.every(function(b,c){return(isNaN(a.values[b])||isNaN(parseFloat(a.values[b])))&&_[c][0]==l[b].brush.y().domain()[0]?!0:_[c][0]<=a.values[b]&&a.values[b]<=_[c][1]&&!isNaN(parseFloat(a.values[b]))});return b&&t.push(a),b?null:"none"}),F(),z.brush({filters:s,active:t})}function E(){var a=$.length>0?!0:!1;s.forEach(function(a){a.extent[0]===l[a.dimension].brush.y().domain()[0]&&v.indexOf(a.dimension)>=0&&(a.hasNaN=!0),a.extent[1]l[a.key].domain()[0]&&(P[a.key]=[c[0].extent[1]]),c[0].extent[0]>=l[a.key].domain()[0]&&P[a.key].push(c[0].extent[0])),d3.select(this).call(y.scale(l[a.key]).tickFormat(a.format).tickValues(P[a.key]))})}function G(a){u[a.key]=this.parentNode.__origin__=k(a.key),d.attr("visibility","hidden")}function H(a){u[a.key]=Math.min(i,Math.max(0,this.parentNode.__origin__+=d3.event.x)),c.attr("d",A),o.sort(function(a,b){return J(a.key)-J(b.key)}),o.forEach(function(a,b){return a.currentPosition=b}),k.domain(o.map(function(a){return a.key})),e.attr("transform",function(a){return"translate("+J(a.key)+")"})}function I(a,b){delete this.parentNode.__origin__,delete u[a.key],d3.select(this.parentNode).attr("transform","translate("+k(a.key)+")"),c.attr("d",A),d.attr("d",A).attr("visibility",null),z.dimensionsOrder(o)}function J(a){var b=u[a];return null==b?k(a):b}var K=d3.select(this);if(i=a.utils.availableWidth(g,K,f),j=a.utils.availableHeight(h,K,f),a.utils.initSVG(K),void 0===b[0].values){var L=[];b.forEach(function(a){var b={},c=Object.keys(a);c.forEach(function(c){"name"!==c&&(b[c]=a[c])}),L.push({key:a.name,values:b})}),b=L}var M=b.map(function(a){return a.values});0===t.length&&(t=b),p=n.sort(function(a,b){return a.currentPosition-b.currentPosition}).map(function(a){return a.key}),o=n.filter(function(a){return!a.disabled}),k.rangePoints([0,i],1).domain(o.map(function(a){return a.key}));var N={},O=!1,P=[];p.forEach(function(a){var b=d3.extent(M,function(b){return+b[a]}),c=b[0],d=b[1],e=!1;(isNaN(c)||isNaN(d))&&(e=!0,c=0,d=0),c===d&&(c-=1,d+=1);var f=s.filter(function(b){return b.dimension==a});0!==f.length&&(e?(c=l[a].domain()[0],d=l[a].domain()[1]):!f[0].hasOnlyNaN&&q?(c=c>f[0].extent[0]?f[0].extent[0]:c,d=d0||!a.utils.arrayEquals(t,aa))&&z.activeChanged(t)}),b}var c,d,e,f={top:30,right:0,bottom:10,left:0},g=null,h=null,i=null,j=null,k=d3.scale.ordinal(),l={},m="undefined values",n=[],o=[],p=[],q=!0,r=a.utils.defaultColor(),s=[],t=[],u=[],v=[],w=1,x=d3.svg.line(),y=d3.svg.axis(),z=d3.dispatch("brushstart","brush","brushEnd","dimensionsOrder","stateChange","elementClick","elementMouseover","elementMouseout","elementMousemove","renderEnd","activeChanged"),A=a.utils.renderWatch(z);return b.dispatch=z,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},dimensionData:{get:function(){return n},set:function(a){n=a}},displayBrush:{get:function(){return q},set:function(a){q=a}},filters:{get:function(){return s},set:function(a){s=a}},active:{get:function(){return t},set:function(a){t=a}},lineTension:{get:function(){return w},set:function(a){w=a}},undefinedValuesLabel:{get:function(){return m},set:function(a){m=a}},dimensions:{get:function(){return n.map(function(a){return a.key})},set:function(b){a.deprecated("dimensions","use dimensionData instead"),0===n.length?b.forEach(function(a){n.push({key:a})}):b.forEach(function(a,b){n[b].key=a})}},dimensionNames:{get:function(){return n.map(function(a){return a.key})},set:function(b){a.deprecated("dimensionNames","use dimensionData instead"),p=[],0===n.length?b.forEach(function(a){n.push({key:a})}):b.forEach(function(a,b){n[b].key=a})}},dimensionFormats:{get:function(){return n.map(function(a){return a.format})},set:function(b){a.deprecated("dimensionFormats","use dimensionData instead"),0===n.length?b.forEach(function(a){n.push({format:a})}):b.forEach(function(a,b){n[b].format=a})}},margin:{get:function(){return f},set:function(a){f.top=void 0!==a.top?a.top:f.top,f.right=void 0!==a.right?a.right:f.right,f.bottom=void 0!==a.bottom?a.bottom:f.bottom,f.left=void 0!==a.left?a.left:f.left}},color:{get:function(){return r},set:function(b){r=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.parallelCoordinatesChart=function(){"use strict";function b(e){return s.reset(),s.models(c),e.each(function(e){var k=d3.select(this);a.utils.initSVG(k);var p=a.utils.availableWidth(h,k,f),q=a.utils.availableHeight(i,k,f);if(b.update=function(){k.call(b)},b.container=this,l.setter(u(m),b.update).getter(t(m)).update(),l.disabled=m.map(function(a){return!!a.disabled}),m=m.map(function(a){return a.disabled=!!a.disabled,a}),m.forEach(function(a,b){a.originalPosition=isNaN(a.originalPosition)?b:a.originalPosition,a.currentPosition=isNaN(a.currentPosition)?b:a.currentPosition}),!o){var s;o={};for(s in l)l[s]instanceof Array?o[s]=l[s].slice(0):o[s]=l[s]}if(!e||!e.length)return a.utils.noData(b,k),b;k.selectAll(".nv-noData").remove();var v=k.selectAll("g.nv-wrap.nv-parallelCoordinatesChart").data([e]),w=v.enter().append("g").attr("class","nvd3 nv-wrap nv-parallelCoordinatesChart").append("g"),x=v.select("g");w.append("g").attr("class","nv-parallelCoordinatesWrap"),w.append("g").attr("class","nv-legendWrap"),x.select("rect").attr("width",p).attr("height",q>0?q:0),j?(d.width(p).color(function(a){return"rgb(188,190,192)"}),x.select(".nv-legendWrap").datum(m.sort(function(a,b){return a.originalPosition-b.originalPosition})).call(d),g||d.height()===f.top||(f.top=d.height(),q=a.utils.availableHeight(i,k,f)),v.select(".nv-legendWrap").attr("transform","translate( 0 ,"+-f.top+")")):x.select(".nv-legendWrap").selectAll("*").remove(),v.attr("transform","translate("+f.left+","+f.top+")"),c.width(p).height(q).dimensionData(m).displayBrush(n);var y=x.select(".nv-parallelCoordinatesWrap ").datum(e);y.transition().call(c),c.dispatch.on("brushEnd",function(a,b){b?(n=!0,r.brushEnd(a)):n=!1}),d.dispatch.on("stateChange",function(a){for(var c in a)l[c]=a[c];r.stateChange(l),b.update()}),c.dispatch.on("dimensionsOrder",function(a){m.sort(function(a,b){return a.currentPosition-b.currentPosition});var b=!1;m.forEach(function(a,c){a.currentPosition=c,a.currentPosition!==a.originalPosition&&(b=!0)}),r.dimensionsOrder(m,b)}),r.on("changeState",function(a){"undefined"!=typeof a.disabled&&(m.forEach(function(b,c){b.disabled=a.disabled[c]}),l.disabled=a.disabled),b.update()})}),s.renderEnd("parraleleCoordinateChart immediate"),b}var c=a.models.parallelCoordinates(),d=a.models.legend(),e=a.models.tooltip(),f=(a.models.tooltip(),{top:0,right:0,bottom:0,left:0}),g=null,h=null,i=null,j=!0,k=a.utils.defaultColor(),l=a.utils.state(),m=[],n=!0,o=null,p=null,q="undefined",r=d3.dispatch("dimensionsOrder","brushEnd","stateChange","changeState","renderEnd"),s=a.utils.renderWatch(r),t=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},u=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return e.contentGenerator(function(a){var b='";return 0!==a.series.length&&(b+='',a.series.forEach(function(a){b=b+'"}),b+=""),b+="
'+a.key+"
'+a.key+''+a.value+"
"}),c.dispatch.on("elementMouseover.tooltip",function(a){var b={key:a.label,color:a.color,series:[]};a.values&&(Object.keys(a.values).forEach(function(c){var d=a.dimensions.filter(function(a){return a.key===c})[0];if(d){var e;e=isNaN(a.values[c])||isNaN(parseFloat(a.values[c]))?q:d.format(a.values[c]),b.series.push({idx:d.currentPosition,key:c,value:e,color:d.color})}}),b.series.sort(function(a,b){return a.idx-b.idx})),e.data(b).hidden(!1)}),c.dispatch.on("elementMouseout.tooltip",function(a){e.hidden(!0)}),c.dispatch.on("elementMousemove.tooltip",function(){e()}),b.dispatch=r,b.parallelCoordinates=c,b.legend=d,b.tooltip=e,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},showLegend:{get:function(){return j},set:function(a){j=a}},defaultState:{get:function(){return o},set:function(a){o=a}},dimensionData:{get:function(){return m},set:function(a){m=a}},displayBrush:{get:function(){return n},set:function(a){n=a}},noData:{get:function(){return p},set:function(a){p=a}},nanValue:{get:function(){return q},set:function(a){q=a}},margin:{get:function(){return f},set:function(a){void 0!==a.top&&(f.top=a.top,g=a.top),f.right=void 0!==a.right?a.right:f.right,f.bottom=void 0!==a.bottom?a.bottom:f.bottom,f.left=void 0!==a.left?a.left:f.left}},color:{get:function(){return k},set:function(b){k=a.utils.getColor(b),d.color(k),c.color(k)}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.pie=function(){"use strict";function b(F){return E.reset(),F.each(function(b){function F(a,b){a.endAngle=isNaN(a.endAngle)?0:a.endAngle,a.startAngle=isNaN(a.startAngle)?0:a.startAngle,p||(a.innerRadius=0);var c=d3.interpolate(this._current,a);return this._current=c(0),function(a){return C[b](c(a))}}var G=d-c.left-c.right,H=e-c.top-c.bottom,I=Math.min(G,H)/2,J=[],K=[];if(i=d3.select(this),0===A.length)for(var L=I-I/5,M=y*I,N=0;N=o){var f=ba(d);$[f]&&(d[1]-=_),$[ba(d)]=!0}return"translate("+d+")"}),X.select(".nv-label text").style("text-anchor",function(a,b){return t?(a.startAngle+a.endAngle)/2c)return"";if("function"==typeof n)d=n(a,b,{key:f(a.data),value:g(a.data),percent:k(c)});else switch(n){case"key":d=f(a.data);break;case"value":d=k(g(a.data));break;case"percent":d=d3.format("%")(c)}return d})}}),E.renderEnd("pie immediate"),b}var c={top:0,right:0,bottom:0,left:0},d=500,e=500,f=function(a){return a.x},g=function(a){return a.y},h=Math.floor(1e4*Math.random()),i=null,j=a.utils.defaultColor(),k=d3.format(",.2f"),l=!0,m=!1,n="key",o=.02,p=!1,q=!1,r=!0,s=0,t=!1,u=!1,v=!1,w=!1,x=0,y=.5,z=250,A=[],B=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),C=[],D=[],E=a.utils.renderWatch(B);return b.dispatch=B,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{arcsRadius:{get:function(){return A},set:function(a){A=a}},width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},showLabels:{get:function(){return l},set:function(a){l=a}},title:{get:function(){return q},set:function(a){q=a}},titleOffset:{get:function(){return s},set:function(a){s=a}},labelThreshold:{get:function(){return o},set:function(a){o=a}},valueFormat:{get:function(){return k},set:function(a){k=a}},x:{get:function(){return f},set:function(a){f=a}},id:{get:function(){return h},set:function(a){h=a}},endAngle:{get:function(){return w},set:function(a){w=a}},startAngle:{get:function(){return u},set:function(a){u=a}},padAngle:{get:function(){return v},set:function(a){v=a}},cornerRadius:{get:function(){return x},set:function(a){x=a}},donutRatio:{get:function(){return y},set:function(a){y=a}},labelsOutside:{get:function(){return m},set:function(a){m=a}},labelSunbeamLayout:{get:function(){return t},set:function(a){t=a}},donut:{get:function(){return p},set:function(a){p=a}},growOnHover:{get:function(){return r},set:function(a){r=a}},pieLabelsOutside:{get:function(){return m},set:function(b){m=b,a.deprecated("pieLabelsOutside","use labelsOutside instead")}},donutLabelsOutside:{get:function(){return m},set:function(b){m=b,a.deprecated("donutLabelsOutside","use labelsOutside instead")}},labelFormat:{get:function(){return k},set:function(b){k=b,a.deprecated("labelFormat","use valueFormat instead")}},margin:{get:function(){return c},set:function(a){c.top="undefined"!=typeof a.top?a.top:c.top,c.right="undefined"!=typeof a.right?a.right:c.right,c.bottom="undefined"!=typeof a.bottom?a.bottom:c.bottom,c.left="undefined"!=typeof a.left?a.left:c.left}},duration:{get:function(){return z},set:function(a){z=a,E.reset(z)}},y:{get:function(){return g},set:function(a){g=d3.functor(a)}},color:{get:function(){return j},set:function(b){j=a.utils.getColor(b)}},labelType:{get:function(){return n},set:function(a){n=a||"key"}}}),a.utils.initOptions(b),b},a.models.pieChart=function(){"use strict";function b(e){return s.reset(),s.models(c),e.each(function(e){var j=d3.select(this);a.utils.initSVG(j);var m=a.utils.availableWidth(h,j,f),p=a.utils.availableHeight(i,j,f);if(b.update=function(){j.transition().call(b)},b.container=this,n.setter(u(e),b.update).getter(t(e)).update(),n.disabled=e.map(function(a){return!!a.disabled}),!o){var q;o={};for(q in n)n[q]instanceof Array?o[q]=n[q].slice(0):o[q]=n[q]}if(!e||!e.length)return a.utils.noData(b,j),b;j.selectAll(".nv-noData").remove();var s=j.selectAll("g.nv-wrap.nv-pieChart").data([e]),v=s.enter().append("g").attr("class","nvd3 nv-wrap nv-pieChart").append("g"),w=s.select("g"); -if(v.append("g").attr("class","nv-pieWrap"),v.append("g").attr("class","nv-legendWrap"),k){if("top"===l)d.width(m).key(c.x()),s.select(".nv-legendWrap").datum(e).call(d),g||d.height()===f.top||(f.top=d.height(),p=a.utils.availableHeight(i,j,f)),s.select(".nv-legendWrap").attr("transform","translate(0,"+-f.top+")");else if("right"===l){var x=a.models.legend().width();x>m/2&&(x=m/2),d.height(p).key(c.x()),d.width(x),m-=d.width(),s.select(".nv-legendWrap").datum(e).call(d).attr("transform","translate("+m+",0)")}}else w.select(".nv-legendWrap").selectAll("*").remove();s.attr("transform","translate("+f.left+","+f.top+")"),c.width(m).height(p);var y=w.select(".nv-pieWrap").datum([e]);d3.transition(y).call(c),d.dispatch.on("stateChange",function(a){for(var c in a)n[c]=a[c];r.stateChange(n),b.update()}),r.on("changeState",function(a){"undefined"!=typeof a.disabled&&(e.forEach(function(b,c){b.disabled=a.disabled[c]}),n.disabled=a.disabled),b.update()})}),s.renderEnd("pieChart immediate"),b}var c=a.models.pie(),d=a.models.legend(),e=a.models.tooltip(),f={top:30,right:20,bottom:20,left:20},g=null,h=null,i=null,j=!1,k=!0,l="top",m=a.utils.defaultColor(),n=a.utils.state(),o=null,p=null,q=250,r=d3.dispatch("stateChange","changeState","renderEnd");e.duration(0).headerEnabled(!1).valueFormatter(function(a,b){return c.valueFormat()(a,b)});var s=a.utils.renderWatch(r),t=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},u=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return c.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:b.x()(a.data),value:b.y()(a.data),color:a.color,percent:a.percent},j||(delete a.percent,delete a.series.percent),e.data(a).hidden(!1)}),c.dispatch.on("elementMouseout.tooltip",function(a){e.hidden(!0)}),c.dispatch.on("elementMousemove.tooltip",function(a){e()}),b.legend=d,b.dispatch=r,b.pie=c,b.tooltip=e,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},noData:{get:function(){return p},set:function(a){p=a}},showTooltipPercent:{get:function(){return j},set:function(a){j=a}},showLegend:{get:function(){return k},set:function(a){k=a}},legendPosition:{get:function(){return l},set:function(a){l=a}},defaultState:{get:function(){return o},set:function(a){o=a}},color:{get:function(){return m},set:function(a){m=a,d.color(m),c.color(m)}},duration:{get:function(){return q},set:function(a){q=a,s.reset(q),c.duration(q)}},margin:{get:function(){return f},set:function(a){void 0!==a.top&&(f.top=a.top,g=a.top),f.right=void 0!==a.right?a.right:f.right,f.bottom=void 0!==a.bottom?a.bottom:f.bottom,f.left=void 0!==a.left?a.left:f.left}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.sankey=function(){"use strict";function b(){n.forEach(function(a){a.sourceLinks=[],a.targetLinks=[]}),o.forEach(function(a){var b=a.source,c=a.target;"number"==typeof b&&(b=a.source=n[a.source]),"number"==typeof c&&(c=a.target=n[a.target]),b.sourceLinks.push(a),c.targetLinks.push(a)})}function c(){n.forEach(function(a){a.value=Math.max(d3.sum(a.sourceLinks,i),d3.sum(a.targetLinks,i))})}function d(){for(var a,b=n,c=0;b.length&&cd;++d)b=a[d],c=e-b.y,c>0&&(b.y+=c),e=b.y+b.dy+l;if(c=e-l-m[1],c>0)for(e=b.y-=c,d=g-2;d>=0;--d)b=a[d],c=b.y+b.dy+l-e,c>0&&(b.y-=c),e=b.y})}function f(a,b){return a.y-b.y}var g=d3.nest().key(function(a){return a.x}).sortKeys(d3.ascending).entries(n).map(function(a){return a.values});b(),e(),h();for(var j=1;a>0;--a)d(j*=.99),e(),h(),c(j),e(),h()}function h(){function a(a,b){return a.source.y-b.source.y}function b(a,b){return a.target.y-b.target.y}n.forEach(function(c){c.sourceLinks.sort(b),c.targetLinks.sort(a)}),n.forEach(function(a){var b=0,c=0;a.sourceLinks.forEach(function(a){a.sy=b,b+=a.dy}),a.targetLinks.forEach(function(a){a.ty=c,c+=a.dy})})}function i(a){return a.value}var j={},k=24,l=8,m=[1,1],n=[],o=[],p=!0,q=function(a){b(),c(),d(),g(a)},r=function(){h()},s=function(){function a(a){var c=a.source.x+a.source.dx,d=a.target.x,e=d3.interpolateNumber(c,d),f=e(b),g=e(1-b),h=a.source.y+a.sy+a.dy/2,i=a.target.y+a.ty+a.dy/2,j="M"+c+","+h+"C"+f+","+h+" "+g+","+i+" "+d+","+i;return j}var b=.5;return a.curvature=function(c){return arguments.length?(b=+c,a):b},a},t=function(a){return a.y+a.dy/2};return j.options=a.utils.optionsFunc.bind(j),j._options=Object.create({},{nodeWidth:{get:function(){return k},set:function(a){k=+a}},nodePadding:{get:function(){return l},set:function(a){l=a}},nodes:{get:function(){return n},set:function(a){n=a}},links:{get:function(){return o},set:function(a){o=a}},size:{get:function(){return m},set:function(a){m=a}},sinksRight:{get:function(){return p},set:function(a){p=a}},layout:{get:function(){q(32)},set:function(a){q(a)}},relayout:{get:function(){r()},set:function(a){}},center:{get:function(){return t()},set:function(a){"function"==typeof a&&(t=a)}},link:{get:function(){return s()},set:function(a){return"function"==typeof a&&(s=a),s()}}}),a.utils.initOptions(j),j},a.models.sankeyChart=function(){"use strict";function b(a){return a.each(function(b){function c(a){d3.select(this).attr("transform","translate("+a.x+","+(a.y=Math.max(0,Math.min(f-a.dy,d3.event.y)))+")"),d.relayout(),t.attr("d",s)}var i={nodes:[{node:1,name:"Test 1"},{node:2,name:"Test 2"},{node:3,name:"Test 3"},{node:4,name:"Test 4"},{node:5,name:"Test 5"},{node:6,name:"Test 6"}],links:[{source:0,target:1,value:2295},{source:0,target:5,value:1199},{source:1,target:2,value:1119},{source:1,target:5,value:1176},{source:2,target:3,value:487},{source:2,target:5,value:632},{source:3,target:4,value:301},{source:3,target:5,value:186}]},k=!1,l=!1;if(("object"==typeof b.nodes&&b.nodes.length)>=0&&("object"==typeof b.links&&b.links.length)>=0&&(k=!0),b.nodes&&b.nodes.length>0&&b.links&&b.links.length>0&&(l=!0),!k)return console.error("NVD3 Sankey chart error:","invalid data format for",b),console.info("Valid data format is: ",i,JSON.stringify(i)),r(a,"Error loading chart, data is invalid"),!1;if(!l)return r(a,"No data available"),!1;var m=a.append("svg").attr("width",e).attr("height",f).append("g").attr("class","nvd3 nv-wrap nv-sankeyChart");d.nodeWidth(g).nodePadding(h).size([e,f]);var s=d.link();d.nodes(b.nodes).links(b.links).layout(32).center(j);var t=m.append("g").selectAll(".link").data(b.links).enter().append("path").attr("class","link").attr("d",s).style("stroke-width",function(a){return Math.max(1,a.dy)}).sort(function(a,b){return b.dy-a.dy});t.append("title").text(n);var u=m.append("g").selectAll(".node").data(b.nodes).enter().append("g").attr("class","node").attr("transform",function(a){return"translate("+a.x+","+a.y+")"}).call(d3.behavior.drag().origin(function(a){return a}).on("dragstart",function(){this.parentNode.appendChild(this)}).on("drag",c));u.append("rect").attr("height",function(a){return a.dy}).attr("width",d.nodeWidth()).style("fill",o).style("stroke",p).append("title").text(q),u.append("text").attr("x",-6).attr("y",function(a){return a.dy/2}).attr("dy",".35em").attr("text-anchor","end").attr("transform",null).text(function(a){return a.name}).filter(function(a){return a.x0?$+20:0),ia.attr("clip-path",G?"url(#nv-edge-clip-"+q+")":""),W=!0;var ja=ea.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});ja.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),ja.exit().remove(),ja.attr("class",function(a,b){return(a.classed||"")+" nv-group nv-series-"+b}).classed("nv-noninteractive",!C).classed("hover",function(a){return a.hover}),ja.watchTransition(X,"scatter: groups").style("fill",function(a,b){return o(a,b)}).style("stroke",function(a,b){return a.pointBorderColor||p||o(a,b)}).style("stroke-opacity",1).style("fill-opacity",.5);var ka=ja.selectAll("path.nv-point").data(function(a){return a.values.map(function(a,b){return[a,b]}).filter(function(a,b){return D(a[0],b)})});if(ka.enter().append("path").attr("class",function(a){return"nv-point nv-point-"+a[1]}).style("fill",function(a){return a.color}).style("stroke",function(a){return a.color}).attr("transform",function(b){return"translate("+a.utils.NaNtoZero(f(v(b[0],b[1])))+","+a.utils.NaNtoZero(g(w(b[0],b[1])))+")"}).attr("d",a.utils.symbol().type(function(a){return y(a[0])}).size(function(a){return u(x(a[0],a[1]))})),ka.exit().each(c).remove(),ja.exit().selectAll("path.nv-point").watchTransition(X,"scatter exit").attr("transform",function(b){return"translate("+a.utils.NaNtoZero(s(v(b[0],b[1])))+","+a.utils.NaNtoZero(t(w(b[0],b[1])))+")"}).remove(),ka.filter(function(a){return ca||da||d(a,"x",v,"y",w)}).watchTransition(X,"scatter points").attr("transform",function(b){return"translate("+a.utils.NaNtoZero(s(v(b[0],b[1])))+","+a.utils.NaNtoZero(t(w(b[0],b[1])))+")"}),ka.filter(function(a){return ca||da||d(a,"shape",y,"size",x)}).watchTransition(X,"scatter points").attr("d",a.utils.symbol().type(function(a){return y(a[0])}).size(function(a){return u(x(a[0],a[1]))})),V){var la=ja.selectAll(".nv-label").data(function(a){return a.values.map(function(a,b){return[a,b]}).filter(function(a,b){return D(a[0],b)})});la.enter().append("text").style("fill",function(a,b){return a.color}).style("stroke-opacity",0).style("fill-opacity",1).attr("transform",function(b){var c=a.utils.NaNtoZero(f(v(b[0],b[1])))+Math.sqrt(u(x(b[0],b[1]))/Math.PI)+2;return"translate("+c+","+a.utils.NaNtoZero(g(w(b[0],b[1])))+")"}).text(function(a,b){return a[0].label}),la.exit().remove(),ja.exit().selectAll("path.nv-label").watchTransition(X,"scatter exit").attr("transform",function(b){var c=a.utils.NaNtoZero(s(v(b[0],b[1])))+Math.sqrt(u(x(b[0],b[1]))/Math.PI)+2;return"translate("+c+","+a.utils.NaNtoZero(t(w(b[0],b[1])))+")"}).remove(),la.each(function(a){d3.select(this).classed("nv-label",!0).classed("nv-label-"+a[1],!1).classed("hover",!1)}),la.watchTransition(X,"scatter labels").attr("transform",function(b){var c=a.utils.NaNtoZero(s(v(b[0],b[1])))+Math.sqrt(u(x(b[0],b[1]))/Math.PI)+2;return"translate("+c+","+a.utils.NaNtoZero(t(w(b[0],b[1])))+")"})}U?(clearTimeout(k),k=setTimeout(T,U)):T(),f=s.copy(),g=t.copy(),h=u.copy(),i=m,j=n}),X.renderEnd("scatter immediate"),e}var f,g,h,i,j,k,l={top:0,right:0,bottom:0,left:0},m=null,n=null,o=a.utils.defaultColor(),p=null,q=Math.floor(1e5*Math.random()),r=null,s=d3.scale.linear(),t=d3.scale.linear(),u=d3.scale.linear(),v=function(a){return a.x},w=function(a){return a.y},x=function(a){return a.size||1},y=function(a){return a.shape||"circle"},z=[],A=[],B=[],C=!0,D=function(a){return!a.notActive},E=!1,F=.1,G=!1,H=!0,I=!1,J=function(){return 25},K=null,L=null,M=null,N=null,O=null,P=null,Q=!1,R=d3.dispatch("elementClick","elementDblClick","elementMouseover","elementMouseout","renderEnd"),S=!0,T=250,U=300,V=!1,W=!1,X=a.utils.renderWatch(R,T),Y=[16,256],Z={};return e.dispatch=R,e.options=a.utils.optionsFunc.bind(e),e._calls=new function(){this.clearHighlights=function(){return a.dom.write(function(){r.selectAll(".nv-point.hover").classed("hover",!1)}),null},this.highlightPoint=function(b,c,d){a.dom.write(function(){r.select(".nv-groups").selectAll(".nv-series-"+b).selectAll(".nv-point-"+c).classed("hover",d)})}},R.on("elementMouseover.point",function(a){C&&e._calls.highlightPoint(a.seriesIndex,a.pointIndex,!0)}),R.on("elementMouseout.point",function(a){C&&e._calls.highlightPoint(a.seriesIndex,a.pointIndex,!1)}),e._options=Object.create({},{width:{get:function(){return m},set:function(a){m=a}},height:{get:function(){return n},set:function(a){n=a}},xScale:{get:function(){return s},set:function(a){s=a}},yScale:{get:function(){return t},set:function(a){t=a}},pointScale:{get:function(){return u},set:function(a){u=a}},xDomain:{get:function(){return K},set:function(a){K=a}},yDomain:{get:function(){return L},set:function(a){L=a}},pointDomain:{get:function(){return O},set:function(a){O=a}},xRange:{get:function(){return M},set:function(a){M=a}},yRange:{get:function(){return N},set:function(a){N=a}},pointRange:{get:function(){return P},set:function(a){P=a}},forceX:{get:function(){return z},set:function(a){z=a}},forceY:{get:function(){return A},set:function(a){A=a}},forcePoint:{get:function(){return B},set:function(a){B=a}},interactive:{get:function(){return C},set:function(a){C=a}},pointActive:{get:function(){return D},set:function(a){D=a}},padDataOuter:{get:function(){return F},set:function(a){F=a}},padData:{get:function(){return E},set:function(a){E=a}},clipEdge:{get:function(){return G},set:function(a){G=a}},clipVoronoi:{get:function(){return H},set:function(a){H=a}},clipRadius:{get:function(){return J},set:function(a){J=a}},showVoronoi:{get:function(){return I},set:function(a){I=a}},id:{get:function(){return q},set:function(a){q=a}},interactiveUpdateDelay:{get:function(){return U},set:function(a){U=a}},showLabels:{get:function(){return V},set:function(a){V=a}},pointBorderColor:{get:function(){return p},set:function(a){p=a}},x:{get:function(){return v},set:function(a){v=d3.functor(a)}},y:{get:function(){return w},set:function(a){w=d3.functor(a)}},pointSize:{get:function(){return x},set:function(a){x=d3.functor(a)}},pointShape:{get:function(){return y},set:function(a){y=d3.functor(a)}},margin:{get:function(){return l},set:function(a){l.top=void 0!==a.top?a.top:l.top,l.right=void 0!==a.right?a.right:l.right,l.bottom=void 0!==a.bottom?a.bottom:l.bottom,l.left=void 0!==a.left?a.left:l.left}},duration:{get:function(){return T},set:function(a){T=a,X.reset(T)}},color:{get:function(){return o},set:function(b){o=a.utils.getColor(b)}},useVoronoi:{get:function(){return S},set:function(a){S=a,S===!1&&(H=!1)}}}),a.utils.initOptions(e),e},a.models.scatterChart=function(){"use strict";function b(A){return F.reset(),F.models(c),u&&F.models(d),v&&F.models(e),r&&F.models(g),s&&F.models(h),A.each(function(A){n=d3.select(this),a.utils.initSVG(n);var I=a.utils.availableWidth(l,n,j),J=a.utils.availableHeight(m,n,j);if(b.update=function(){0===B?n.call(b):n.transition().duration(B).call(b)},b.container=this,x.setter(H(A),b.update).getter(G(A)).update(),x.disabled=A.map(function(a){return!!a.disabled}),!y){var K;y={};for(K in x)x[K]instanceof Array?y[K]=x[K].slice(0):y[K]=x[K]}if(!(A&&A.length&&A.filter(function(a){return a.values.length}).length))return a.utils.noData(b,n),F.renderEnd("scatter immediate"),b;n.selectAll(".nv-noData").remove(),p=c.xScale(),q=c.yScale();var L=n.selectAll("g.nv-wrap.nv-scatterChart").data([A]),M=L.enter().append("g").attr("class","nvd3 nv-wrap nv-scatterChart nv-chart-"+c.id()),N=M.append("g"),O=L.select("g");if(N.append("rect").attr("class","nvd3 nv-background").style("pointer-events","none"),N.append("g").attr("class","nv-x nv-axis"),N.append("g").attr("class","nv-y nv-axis"),N.append("g").attr("class","nv-scatterWrap"),N.append("g").attr("class","nv-regressionLinesWrap"),N.append("g").attr("class","nv-distWrap"),N.append("g").attr("class","nv-legendWrap"),w&&O.select(".nv-y.nv-axis").attr("transform","translate("+I+",0)"),t){var P=I;f.width(P),L.select(".nv-legendWrap").datum(A).call(f),k||f.height()===j.top||(j.top=f.height(),J=a.utils.availableHeight(m,n,j)),L.select(".nv-legendWrap").attr("transform","translate(0,"+-j.top+")")}else O.select(".nv-legendWrap").selectAll("*").remove();L.attr("transform","translate("+j.left+","+j.top+")"),c.width(I).height(J).color(A.map(function(a,b){return a.color=a.color||o(a,b),a.color}).filter(function(a,b){return!A[b].disabled})).showLabels(C),L.select(".nv-scatterWrap").datum(A.filter(function(a){return!a.disabled})).call(c),L.select(".nv-regressionLinesWrap").attr("clip-path","url(#nv-edge-clip-"+c.id()+")");var Q=L.select(".nv-regressionLinesWrap").selectAll(".nv-regLines").data(function(a){return a});Q.enter().append("g").attr("class","nv-regLines");var R=Q.selectAll(".nv-regLine").data(function(a){return[a]});R.enter().append("line").attr("class","nv-regLine").style("stroke-opacity",0),R.filter(function(a){return a.intercept&&a.slope}).watchTransition(F,"scatterPlusLineChart: regline").attr("x1",p.range()[0]).attr("x2",p.range()[1]).attr("y1",function(a,b){return q(p.domain()[0]*a.slope+a.intercept)}).attr("y2",function(a,b){return q(p.domain()[1]*a.slope+a.intercept)}).style("stroke",function(a,b,c){return o(a,c)}).style("stroke-opacity",function(a,b){return a.disabled||"undefined"==typeof a.slope||"undefined"==typeof a.intercept?0:1}),u&&(d.scale(p)._ticks(a.utils.calcTicksX(I/100,A)).tickSize(-J,0),O.select(".nv-x.nv-axis").attr("transform","translate(0,"+q.range()[0]+")").call(d)),v&&(e.scale(q)._ticks(a.utils.calcTicksY(J/36,A)).tickSize(-I,0),O.select(".nv-y.nv-axis").call(e)),r&&(g.getData(c.x()).scale(p).width(I).color(A.map(function(a,b){return a.color||o(a,b)}).filter(function(a,b){return!A[b].disabled})),N.select(".nv-distWrap").append("g").attr("class","nv-distributionX"),O.select(".nv-distributionX").attr("transform","translate(0,"+q.range()[0]+")").datum(A.filter(function(a){return!a.disabled})).call(g)),s&&(h.getData(c.y()).scale(q).width(J).color(A.map(function(a,b){return a.color||o(a,b)}).filter(function(a,b){return!A[b].disabled})),N.select(".nv-distWrap").append("g").attr("class","nv-distributionY"),O.select(".nv-distributionY").attr("transform","translate("+(w?I:-h.size())+",0)").datum(A.filter(function(a){return!a.disabled})).call(h)),f.dispatch.on("stateChange",function(a){for(var c in a)x[c]=a[c];z.stateChange(x),b.update()}),z.on("changeState",function(a){"undefined"!=typeof a.disabled&&(A.forEach(function(b,c){b.disabled=a.disabled[c]}),x.disabled=a.disabled),b.update()}),c.dispatch.on("elementMouseout.tooltip",function(a){i.hidden(!0),n.select(".nv-chart-"+c.id()+" .nv-series-"+a.seriesIndex+" .nv-distx-"+a.pointIndex).attr("y1",0),n.select(".nv-chart-"+c.id()+" .nv-series-"+a.seriesIndex+" .nv-disty-"+a.pointIndex).attr("x2",h.size())}),c.dispatch.on("elementMouseover.tooltip",function(a){n.select(".nv-series-"+a.seriesIndex+" .nv-distx-"+a.pointIndex).attr("y1",a.relativePos[1]-J),n.select(".nv-series-"+a.seriesIndex+" .nv-disty-"+a.pointIndex).attr("x2",a.relativePos[0]+g.size()),i.data(a).hidden(!1)}),D=p.copy(),E=q.copy()}),F.renderEnd("scatter with line immediate"),b}var c=a.models.scatter(),d=a.models.axis(),e=a.models.axis(),f=a.models.legend(),g=a.models.distribution(),h=a.models.distribution(),i=a.models.tooltip(),j={top:30,right:20,bottom:50,left:75},k=null,l=null,m=null,n=null,o=a.utils.defaultColor(),p=c.xScale(),q=c.yScale(),r=!1,s=!1,t=!0,u=!0,v=!0,w=!1,x=a.utils.state(),y=null,z=d3.dispatch("stateChange","changeState","renderEnd"),A=null,B=250,C=!1;c.xScale(p).yScale(q),d.orient("bottom").tickPadding(10),e.orient(w?"right":"left").tickPadding(10),g.axis("x"),h.axis("y"),i.headerFormatter(function(a,b){return d.tickFormat()(a,b)}).valueFormatter(function(a,b){return e.tickFormat()(a,b)});var D,E,F=a.utils.renderWatch(z,B),G=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},H=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return b.dispatch=z,b.scatter=c,b.legend=f,b.xAxis=d,b.yAxis=e,b.distX=g,b.distY=h,b.tooltip=i,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return l},set:function(a){l=a}},height:{get:function(){return m},set:function(a){m=a}},container:{get:function(){return n},set:function(a){n=a}},showDistX:{get:function(){return r},set:function(a){r=a}},showDistY:{get:function(){return s},set:function(a){s=a}},showLegend:{get:function(){return t},set:function(a){t=a}},showXAxis:{get:function(){return u},set:function(a){u=a}},showYAxis:{get:function(){return v},set:function(a){v=a}},defaultState:{get:function(){return y},set:function(a){y=a}},noData:{get:function(){return A},set:function(a){A=a}},duration:{get:function(){return B},set:function(a){B=a}},showLabels:{get:function(){return C},set:function(a){C=a}},margin:{get:function(){return j},set:function(a){void 0!==a.top&&(j.top=a.top,k=a.top),j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},rightAlignYAxis:{get:function(){return w},set:function(a){w=a,e.orient(a?"right":"left")}},color:{get:function(){return o},set:function(b){o=a.utils.getColor(b),f.color(o),g.color(o),h.color(o)}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.sparkline=function(){"use strict";function b(k){return t.reset(),k.each(function(b){var k=h-g.left-g.right,s=i-g.top-g.bottom;j=d3.select(this),a.utils.initSVG(j),l.domain(c||d3.extent(b,n)).range(e||[0,k]),m.domain(d||d3.extent(b,o)).range(f||[s,0]);var t=j.selectAll("g.nv-wrap.nv-sparkline").data([b]),u=t.enter().append("g").attr("class","nvd3 nv-wrap nv-sparkline");u.append("g"),t.select("g");t.attr("transform","translate("+g.left+","+g.top+")");var v=t.selectAll("path").data(function(a){return[a]});v.enter().append("path"),v.exit().remove(),v.style("stroke",function(a,b){return a.color||p(a,b)}).attr("d",d3.svg.line().x(function(a,b){return l(n(a,b))}).y(function(a,b){return m(o(a,b))}));var w=t.selectAll("circle.nv-point").data(function(a){function b(b){if(-1!=b){var c=a[b];return c.pointIndex=b,c}return null}var c=a.map(function(a,b){return o(a,b)}),d=b(c.lastIndexOf(m.domain()[1])),e=b(c.indexOf(m.domain()[0])),f=b(c.length-1);return[q?e:null,q?d:null,r?f:null].filter(function(a){return null!=a})});w.enter().append("circle"),w.exit().remove(),w.attr("cx",function(a,b){return l(n(a,a.pointIndex))}).attr("cy",function(a,b){return m(o(a,a.pointIndex))}).attr("r",2).attr("class",function(a,b){return n(a,a.pointIndex)==l.domain()[1]?"nv-point nv-currentValue":o(a,a.pointIndex)==m.domain()[0]?"nv-point nv-minValue":"nv-point nv-maxValue"})}),t.renderEnd("sparkline immediate"),b}var c,d,e,f,g={top:2,right:0,bottom:2,left:0},h=400,i=32,j=null,k=!0,l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=a.utils.getColor(["#000"]),q=!0,r=!0,s=d3.dispatch("renderEnd"),t=a.utils.renderWatch(s);return b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},animate:{get:function(){return k},set:function(a){k=a}},showMinMaxPoints:{get:function(){return q},set:function(a){q=a}},showCurrentPoint:{get:function(){return r},set:function(a){r=a}},x:{get:function(){return n},set:function(a){n=d3.functor(a)}},y:{get:function(){return o},set:function(a){o=d3.functor(a)}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},color:{get:function(){return p},set:function(b){p=a.utils.getColor(b)}}}),b.dispatch=s,a.utils.initOptions(b),b},a.models.sparklinePlus=function(){"use strict";function b(p){return r.reset(),r.models(e),p.each(function(p){function q(){if(!j){var a=z.selectAll(".nv-hoverValue").data(i),b=a.enter().append("g").attr("class","nv-hoverValue").style("stroke-opacity",0).style("fill-opacity",0);a.exit().transition().duration(250).style("stroke-opacity",0).style("fill-opacity",0).remove(),a.attr("transform",function(a){return"translate("+c(e.x()(p[a],a))+",0)"}).transition().duration(250).style("stroke-opacity",1).style("fill-opacity",1),i.length&&(b.append("line").attr("x1",0).attr("y1",-f.top).attr("x2",0).attr("y2",u), -b.append("text").attr("class","nv-xValue").attr("x",-6).attr("y",-f.top).attr("text-anchor","end").attr("dy",".9em"),z.select(".nv-hoverValue .nv-xValue").text(k(e.x()(p[i[0]],i[0]))),b.append("text").attr("class","nv-yValue").attr("x",6).attr("y",-f.top).attr("text-anchor","start").attr("dy",".9em"),z.select(".nv-hoverValue .nv-yValue").text(l(e.y()(p[i[0]],i[0]))))}}function r(){function a(a,b){for(var c=Math.abs(e.x()(a[0],0)-b),d=0,f=0;fc;++c){for(b=0,d=0;bb;b++)a[b][c][1]/=d;else for(b=0;e>b;b++)a[b][c][1]=0}for(c=0;f>c;++c)g[c]=0;return g}}),v.renderEnd("stackedArea immediate"),b}var c,d,e={top:0,right:0,bottom:0,left:0},f=960,g=500,h=a.utils.defaultColor(),i=Math.floor(1e5*Math.random()),j=null,k=function(a){return a.x},l=function(a){return a.y},m=function(a,b){return!isNaN(l(a,b))&&null!==l(a,b)},n="stack",o="zero",p="default",q="linear",r=!1,s=a.models.scatter(),t=250,u=d3.dispatch("areaClick","areaMouseover","areaMouseout","renderEnd","elementClick","elementMouseover","elementMouseout");s.pointSize(2.2).pointDomain([2.2,2.2]);var v=a.utils.renderWatch(u,t);return b.dispatch=u,b.scatter=s,s.dispatch.on("elementClick",function(){u.elementClick.apply(this,arguments)}),s.dispatch.on("elementMouseover",function(){u.elementMouseover.apply(this,arguments)}),s.dispatch.on("elementMouseout",function(){u.elementMouseout.apply(this,arguments)}),b.interpolate=function(a){return arguments.length?(q=a,b):q},b.duration=function(a){return arguments.length?(t=a,v.reset(t),s.duration(t),b):t},b.dispatch=u,b.scatter=s,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return f},set:function(a){f=a}},height:{get:function(){return g},set:function(a){g=a}},defined:{get:function(){return m},set:function(a){m=a}},clipEdge:{get:function(){return r},set:function(a){r=a}},offset:{get:function(){return o},set:function(a){o=a}},order:{get:function(){return p},set:function(a){p=a}},interpolate:{get:function(){return q},set:function(a){q=a}},x:{get:function(){return k},set:function(a){k=d3.functor(a)}},y:{get:function(){return l},set:function(a){l=d3.functor(a)}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}},color:{get:function(){return h},set:function(b){h=a.utils.getColor(b)}},style:{get:function(){return n},set:function(a){switch(n=a){case"stack":b.offset("zero"),b.order("default");break;case"stream":b.offset("wiggle"),b.order("inside-out");break;case"stream-center":b.offset("silhouette"),b.order("inside-out");break;case"expand":b.offset("expand"),b.order("default");break;case"stack_percent":b.offset(b.d3_stackedOffset_stackPercent),b.order("default")}}},duration:{get:function(){return t},set:function(a){t=a,v.reset(t),s.duration(t)}}}),a.utils.inheritOptions(b,s),a.utils.initOptions(b),b},a.models.stackedAreaChart=function(){"use strict";function b(k){return L.reset(),L.models(e),u&&L.models(f),v&&L.models(g),k.each(function(k){function D(){u&&X.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+T+")").transition().duration(I).call(f)}function L(){if(v){if("expand"===e.style()||"stack_percent"===e.style()){var a=g.tickFormat();J&&a===P||(J=a),g.tickFormat(P)}else J&&(g.tickFormat(J),J=null);X.select(".nv-focus .nv-y.nv-axis").transition().duration(0).call(g)}}function Q(a){var b=X.select(".nv-focus .nv-stackedWrap").datum(k.filter(function(a){return!a.disabled}).map(function(b,c){return{key:b.key,area:b.area,classed:b.classed,values:b.values.filter(function(b,c){return e.x()(b,c)>=a[0]&&e.x()(b,c)<=a[1]}),disableTooltip:b.disableTooltip}}));b.transition().duration(I).call(e),D(),L()}var R=d3.select(this);a.utils.initSVG(R);var S=a.utils.availableWidth(o,R,m),T=a.utils.availableHeight(p,R,m)-(x?l.height():0);if(b.update=function(){R.transition().duration(I).call(b)},b.container=this,B.setter(O(k),b.update).getter(N(k)).update(),B.disabled=k.map(function(a){return!!a.disabled}),!C){var U;C={};for(U in B)B[U]instanceof Array?C[U]=B[U].slice(0):C[U]=B[U]}if(!(k&&k.length&&k.filter(function(a){return a.values.length}).length))return a.utils.noData(b,R),b;R.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var V=R.selectAll("g.nv-wrap.nv-stackedAreaChart").data([k]),W=V.enter().append("g").attr("class","nvd3 nv-wrap nv-stackedAreaChart").append("g"),X=V.select("g");W.append("g").attr("class","nv-legendWrap"),W.append("g").attr("class","nv-controlsWrap");var Y=W.append("g").attr("class","nv-focus");Y.append("g").attr("class","nv-background").append("rect"),Y.append("g").attr("class","nv-x nv-axis"),Y.append("g").attr("class","nv-y nv-axis"),Y.append("g").attr("class","nv-stackedWrap"),Y.append("g").attr("class","nv-interactive");W.append("g").attr("class","nv-focusWrap");if(s){var Z=r&&"top"===t?S-F:S;if(h.width(Z),X.select(".nv-legendWrap").datum(k).call(h),"bottom"===t){var $=(u?12:0)+10;m.bottom=Math.max(h.height()+$,m.bottom),T=a.utils.availableHeight(p,R,m)-(x?l.height():0);var _=T+$;X.select(".nv-legendWrap").attr("transform","translate(0,"+_+")")}else"top"===t&&(n||m.top==h.height()||(m.top=h.height(),T=a.utils.availableHeight(p,R,m)-(x?l.height():0)),X.select(".nv-legendWrap").attr("transform","translate("+(S-Z)+","+-m.top+")"))}else X.select(".nv-legendWrap").selectAll("*").remove();if(r){var aa=[{key:H.stacked||"Stacked",metaKey:"Stacked",disabled:"stack"!=e.style(),style:"stack"},{key:H.stream||"Stream",metaKey:"Stream",disabled:"stream"!=e.style(),style:"stream"},{key:H.expanded||"Expanded",metaKey:"Expanded",disabled:"expand"!=e.style(),style:"expand"},{key:H.stack_percent||"Stack %",metaKey:"Stack_Percent",disabled:"stack_percent"!=e.style(),style:"stack_percent"}];F=G.length/3*260,aa=aa.filter(function(a){return-1!==G.indexOf(a.metaKey)}),i.width(F).color(["#444","#444","#444"]),X.select(".nv-controlsWrap").datum(aa).call(i);var ba=Math.max(i.height(),s&&"top"===t?h.height():0);m.top!=ba&&(m.top=ba,T=a.utils.availableHeight(p,R,m)-(x?l.height():0)),X.select(".nv-controlsWrap").attr("transform","translate(0,"+-m.top+")")}else X.select(".nv-controlsWrap").selectAll("*").remove();V.attr("transform","translate("+m.left+","+m.top+")"),w&&X.select(".nv-y.nv-axis").attr("transform","translate("+S+",0)"),y&&(j.width(S).height(T).margin({left:m.left,top:m.top}).svgContainer(R).xScale(c),V.select(".nv-interactive").call(j)),X.select(".nv-focus .nv-background rect").attr("width",S).attr("height",T),e.width(S).height(T).color(k.map(function(a,b){return a.color||q(a,b)}).filter(function(a,b){return!k[b].disabled}));var ca=X.select(".nv-focus .nv-stackedWrap").datum(k.filter(function(a){return!a.disabled}));if(u&&f.scale(c)._ticks(a.utils.calcTicksX(S/100,k)).tickSize(-T,0),v){var da;da="wiggle"===e.offset()?0:a.utils.calcTicksY(T/36,k),g.scale(d)._ticks(da).tickSize(-S,0)}if(x){l.width(S),X.select(".nv-focusWrap").attr("transform","translate(0,"+(T+m.bottom+l.margin().top)+")").datum(k.filter(function(a){return!a.disabled})).call(l);var ea=l.brush.empty()?l.xDomain():l.brush.extent();null!==ea&&Q(ea)}else ca.transition().call(e),D(),L();e.dispatch.on("areaClick.toggle",function(a){1===k.filter(function(a){return!a.disabled}).length?k.forEach(function(a){a.disabled=!1}):k.forEach(function(b,c){b.disabled=c!=a.seriesIndex}),B.disabled=k.map(function(a){return!!a.disabled}),E.stateChange(B),b.update()}),h.dispatch.on("stateChange",function(a){for(var c in a)B[c]=a[c];E.stateChange(B),b.update()}),i.dispatch.on("legendClick",function(a,c){a.disabled&&(aa=aa.map(function(a){return a.disabled=!0,a}),a.disabled=!1,e.style(a.style),B.style=e.style(),E.stateChange(B),b.update())}),j.dispatch.on("elementMousemove",function(c){e.clearHighlights();var d,f,g,h=[],i=0,l=!0;if(k.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(j,k){f=a.interactiveBisect(j.values,c.pointXValue,b.x());var m=j.values[f],n=b.y()(m,f);if(null!=n&&e.highlightPoint(k,f,!0),"undefined"!=typeof m){"undefined"==typeof d&&(d=m),"undefined"==typeof g&&(g=b.xScale()(b.x()(m,f)));var o="expand"==e.style()?m.display.y:b.y()(m,f);h.push({key:j.key,value:o,color:q(j,j.seriesIndex),point:m}),z&&"expand"!=e.style()&&null!=o&&(i+=o,l=!1)}}),h.reverse(),h.length>2){var m=b.yScale().invert(c.mouseY),n=null;h.forEach(function(a,b){m=Math.abs(m);var c=Math.abs(a.point.display.y0),d=Math.abs(a.point.display.y);return m>=c&&d+c>=m?void(n=b):void 0}),null!=n&&(h[n].highlight=!0)}z&&"expand"!=e.style()&&h.length>=2&&!l&&h.push({key:A,value:i,total:!0});var o=b.x()(d,f),p=j.tooltip.valueFormatter();"expand"===e.style()||"stack_percent"===e.style()?(K||(K=p),p=d3.format(".1%")):K&&(p=K,K=null),j.tooltip.valueFormatter(p).data({value:o,series:h})(),j.renderGuideLine(g)}),j.dispatch.on("elementMouseout",function(a){e.clearHighlights()}),l.dispatch.on("onBrush",function(a){Q(a)}),E.on("changeState",function(a){"undefined"!=typeof a.disabled&&k.length===a.disabled.length&&(k.forEach(function(b,c){b.disabled=a.disabled[c]}),B.disabled=a.disabled),"undefined"!=typeof a.style&&(e.style(a.style),M=a.style),b.update()})}),L.renderEnd("stacked Area chart immediate"),b}var c,d,e=a.models.stackedArea(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.models.legend(),j=a.interactiveGuideline(),k=a.models.tooltip(),l=a.models.focus(a.models.stackedArea()),m={top:10,right:25,bottom:50,left:60},n=null,o=null,p=null,q=a.utils.defaultColor(),r=!0,s=!0,t="top",u=!0,v=!0,w=!1,x=!1,y=!1,z=!0,A="TOTAL",B=a.utils.state(),C=null,D=null,E=d3.dispatch("stateChange","changeState","renderEnd"),F=250,G=["Stacked","Stream","Expanded"],H={},I=250;B.style=e.style(),f.orient("bottom").tickPadding(7),g.orient(w?"right":"left"),k.headerFormatter(function(a,b){return f.tickFormat()(a,b)}).valueFormatter(function(a,b){return g.tickFormat()(a,b)}),j.tooltip.headerFormatter(function(a,b){return f.tickFormat()(a,b)}).valueFormatter(function(a,b){return null==a?"N/A":g.tickFormat()(a,b)});var J=null,K=null;i.updateState(!1);var L=a.utils.renderWatch(E),M=e.style(),N=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),style:e.style()}}},O=function(a){return function(b){void 0!==b.style&&(M=b.style),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}},P=d3.format("%");return e.dispatch.on("elementMouseover.tooltip",function(a){a.point.x=e.x()(a.point),a.point.y=e.y()(a.point),k.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(a){k.hidden(!0)}),b.dispatch=E,b.stacked=e,b.legend=h,b.controls=i,b.xAxis=f,b.x2Axis=l.xAxis,b.yAxis=g,b.y2Axis=l.yAxis,b.interactiveLayer=j,b.tooltip=k,b.focus=l,b.dispatch=E,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return o},set:function(a){o=a}},height:{get:function(){return p},set:function(a){p=a}},showLegend:{get:function(){return s},set:function(a){s=a}},legendPosition:{get:function(){return t},set:function(a){t=a}},showXAxis:{get:function(){return u},set:function(a){u=a}},showYAxis:{get:function(){return v},set:function(a){v=a}},defaultState:{get:function(){return C},set:function(a){C=a}},noData:{get:function(){return D},set:function(a){D=a}},showControls:{get:function(){return r},set:function(a){r=a}},controlLabels:{get:function(){return H},set:function(a){H=a}},controlOptions:{get:function(){return G},set:function(a){G=a}},showTotalInTooltip:{get:function(){return z},set:function(a){z=a}},totalLabel:{get:function(){return A},set:function(a){A=a}},focusEnable:{get:function(){return x},set:function(a){x=a}},focusHeight:{get:function(){return l.height()},set:function(a){l.height(a)}},brushExtent:{get:function(){return l.brushExtent()},set:function(a){l.brushExtent(a)}},margin:{get:function(){return m},set:function(a){void 0!==a.top&&(m.top=a.top,n=a.top),m.right=void 0!==a.right?a.right:m.right,m.bottom=void 0!==a.bottom?a.bottom:m.bottom,m.left=void 0!==a.left?a.left:m.left}},focusMargin:{get:function(){return l.margin},set:function(a){l.margin.top=void 0!==a.top?a.top:l.margin.top,l.margin.right=void 0!==a.right?a.right:l.margin.right,l.margin.bottom=void 0!==a.bottom?a.bottom:l.margin.bottom,l.margin.left=void 0!==a.left?a.left:l.margin.left}},duration:{get:function(){return I},set:function(a){I=a,L.reset(I),e.duration(I),f.duration(I),g.duration(I)}},color:{get:function(){return q},set:function(b){q=a.utils.getColor(b),h.color(q),e.color(q),l.color(q)}},x:{get:function(){return e.x()},set:function(a){e.x(a),l.x(a)}},y:{get:function(){return e.y()},set:function(a){e.y(a),l.y(a)}},rightAlignYAxis:{get:function(){return w},set:function(a){w=a,g.orient(w?"right":"left")}},useInteractiveGuideline:{get:function(){return y},set:function(a){y=!!a,b.interactive(!a),b.useVoronoi(!a),e.scatter.interactive(!a)}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.stackedAreaWithFocusChart=function(){return a.models.stackedAreaChart().margin({bottom:30}).focusEnable(!0)},a.models.sunburst=function(){"use strict";function b(a){var b=c(a);return b>90?180:0}function c(a){var b=Math.max(0,Math.min(2*Math.PI,F(a.x))),c=Math.max(0,Math.min(2*Math.PI,F(a.x+a.dx))),d=(b+c)/2*(180/Math.PI)-90;return d}function d(a){var b=Math.max(0,Math.min(2*Math.PI,F(a.x))),c=Math.max(0,Math.min(2*Math.PI,F(a.x+a.dx)));return(c-b)/(2*Math.PI)}function e(a){var b=Math.max(0,Math.min(2*Math.PI,F(a.x))),c=Math.max(0,Math.min(2*Math.PI,F(a.x+a.dx))),d=c-b;return d>z}function f(a,b){var c=d3.interpolate(F.domain(),[l.x,l.x+l.dx]),d=d3.interpolate(G.domain(),[l.y,1]),e=d3.interpolate(G.range(),[l.y?20:0,o]);return 0===b?function(){return J(a)}:function(b){return F.domain(c(b)),G.domain(d(b)).range(e(b)),J(a)}}function g(a){var b=d3.interpolate({x:a.x0,dx:a.dx0,y:a.y0,dy:a.dy0},a);return function(c){var d=b(c);return a.x0=d.x,a.dx0=d.dx,a.y0=d.y,a.dy0=d.dy,J(d)}}function h(a){var b=B(a);I[b]||(I[b]={});var c=I[b];c.dx=a.dx,c.x=a.x,c.dy=a.dy,c.y=a.y}function i(a){a.forEach(function(a){var b=B(a),c=I[b];c?(a.dx0=c.dx,a.x0=c.x,a.dy0=c.dy,a.y0=c.y):(a.dx0=a.dx,a.x0=a.x,a.dy0=a.dy,a.y0=a.y),h(a)})}function j(a){var d=v.selectAll("text"),g=v.selectAll("path");d.transition().attr("opacity",0),l=a,g.transition().duration(D).attrTween("d",f).each("end",function(d){if(d.x>=a.x&&d.x=a.depth){var f=d3.select(this.parentNode),g=f.select("text");g.transition().duration(D).text(function(a){return y(a)}).attr("opacity",function(a){return e(a)?1:0}).attr("transform",function(){var e=this.getBBox().width;if(0===d.depth)return"translate("+e/2*-1+",0)";if(d.depth===a.depth)return"translate("+(G(d.y)+5)+",0)";var f=c(d),g=b(d);return 0===g?"rotate("+f+")translate("+(G(d.y)+5)+",0)":"rotate("+f+")translate("+(G(d.y)+e+5)+",0)rotate("+g+")"})}})}function k(f){return K.reset(),f.each(function(f){v=d3.select(this),m=a.utils.availableWidth(q,v,p),n=a.utils.availableHeight(r,v,p),o=Math.min(m,n)/2,G.range([0,o]);var h=v.select("g.nvd3.nv-wrap.nv-sunburst");h[0][0]?h.attr("transform","translate("+(m/2+p.left+p.right)+","+(n/2+p.top+p.bottom)+")"):h=v.append("g").attr("class","nvd3 nv-wrap nv-sunburst nv-chart-"+u).attr("transform","translate("+(m/2+p.left+p.right)+","+(n/2+p.top+p.bottom)+")"),v.on("click",function(a,b){E.chartClick({data:a,index:b,pos:d3.event,id:u})}),H.value(t[s]||t.count);var k=H.nodes(f[0]).reverse();i(k);var l=h.selectAll(".arc-container").data(k,B),z=l.enter().append("g").attr("class","arc-container");z.append("path").attr("d",J).style("fill",function(a){return a.color?a.color:w(C?(a.children?a:a.parent).name:a.name)}).style("stroke","#FFF").on("click",function(a,b){j(a),E.elementClick({data:a,index:b})}).on("mouseover",function(a,b){d3.select(this).classed("hover",!0).style("opacity",.8),E.elementMouseover({data:a,color:d3.select(this).style("fill"),percent:d(a)})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1).style("opacity",1),E.elementMouseout({data:a})}).on("mousemove",function(a,b){E.elementMousemove({data:a})}),l.each(function(a){d3.select(this).select("path").transition().duration(D).attrTween("d",g)}),x&&(l.selectAll("text").remove(),l.append("text").text(function(a){return y(a)}).transition().duration(D).attr("opacity",function(a){return e(a)?1:0}).attr("transform",function(a){var d=this.getBBox().width;if(0===a.depth)return"rotate(0)translate("+d/2*-1+",0)";var e=c(a),f=b(a);return 0===f?"rotate("+e+")translate("+(G(a.y)+5)+",0)":"rotate("+e+")translate("+(G(a.y)+d+5)+",0)rotate("+f+")"})),j(k[k.length-1]),l.exit().transition().duration(D).attr("opacity",0).each("end",function(a){var b=B(a);I[b]=void 0}).remove()}),K.renderEnd("sunburst immediate"),k}var l,m,n,o,p={top:0,right:0,bottom:0,left:0},q=600,r=600,s="count",t={count:function(a){return 1},value:function(a){return a.value||a.size},size:function(a){return a.value||a.size}},u=Math.floor(1e4*Math.random()),v=null,w=a.utils.defaultColor(),x=!1,y=function(a){return"count"===s?a.name+" #"+a.value:a.name+" "+(a.value||a.size)},z=.02,A=function(a,b){return a.name>b.name},B=function(a,b){return a.name},C=!0,D=500,E=d3.dispatch("chartClick","elementClick","elementDblClick","elementMousemove","elementMouseover","elementMouseout","renderEnd"),F=d3.scale.linear().range([0,2*Math.PI]),G=d3.scale.sqrt(),H=d3.layout.partition().sort(A),I={},J=d3.svg.arc().startAngle(function(a){return Math.max(0,Math.min(2*Math.PI,F(a.x)))}).endAngle(function(a){return Math.max(0,Math.min(2*Math.PI,F(a.x+a.dx)))}).innerRadius(function(a){return Math.max(0,G(a.y))}).outerRadius(function(a){return Math.max(0,G(a.y+a.dy))}),K=a.utils.renderWatch(E);return k.dispatch=E,k.options=a.utils.optionsFunc.bind(k),k._options=Object.create({},{width:{get:function(){return q},set:function(a){q=a}},height:{get:function(){return r},set:function(a){r=a}},mode:{get:function(){return s},set:function(a){s=a}},id:{get:function(){return u},set:function(a){u=a}},duration:{get:function(){return D},set:function(a){D=a}},groupColorByParent:{get:function(){return C},set:function(a){C=!!a}},showLabels:{get:function(){return x},set:function(a){x=!!a}},labelFormat:{get:function(){return y},set:function(a){y=a}},labelThreshold:{get:function(){return z},set:function(a){z=a}},sort:{get:function(){return A},set:function(a){A=a}},key:{get:function(){return B},set:function(a){B=a}},margin:{get:function(){return p},set:function(a){p.top=void 0!=a.top?a.top:p.top,p.right=void 0!=a.right?a.right:p.right,p.bottom=void 0!=a.bottom?a.bottom:p.bottom,p.left=void 0!=a.left?a.left:p.left}},color:{get:function(){return w},set:function(b){w=a.utils.getColor(b)}}}),a.utils.initOptions(k),k},a.models.sunburstChart=function(){"use strict";function b(d){return n.reset(),n.models(c),d.each(function(d){var h=d3.select(this);a.utils.initSVG(h);var i=a.utils.availableWidth(f,h,e),j=a.utils.availableHeight(g,h,e);return b.update=function(){0===l?h.call(b):h.transition().duration(l).call(b)},b.container=h,d&&d.length?(h.selectAll(".nv-noData").remove(),c.width(i).height(j).margin(e),void h.call(c)):(a.utils.noData(b,h),b)}),n.renderEnd("sunburstChart immediate"),b}var c=a.models.sunburst(),d=a.models.tooltip(),e={top:30,right:20,bottom:20,left:20},f=null,g=null,h=a.utils.defaultColor(),i=!1,j=(Math.round(1e5*Math.random()),null),k=null,l=250,m=d3.dispatch("stateChange","changeState","renderEnd"),n=a.utils.renderWatch(m);return d.duration(0).headerEnabled(!1).valueFormatter(function(a){return a}),c.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:a.data.name,value:a.data.value||a.data.size,color:a.color,percent:a.percent},i||(delete a.percent,delete a.series.percent),d.data(a).hidden(!1)}),c.dispatch.on("elementMouseout.tooltip",function(a){d.hidden(!0)}),c.dispatch.on("elementMousemove.tooltip",function(a){d()}),b.dispatch=m,b.sunburst=c,b.tooltip=d,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{noData:{get:function(){return k},set:function(a){k=a}},defaultState:{get:function(){return j},set:function(a){j=a}},showTooltipPercent:{get:function(){return i},set:function(a){i=a}},color:{get:function(){return h},set:function(a){h=a,c.color(h)}},duration:{get:function(){return l},set:function(a){l=a,n.reset(l),c.duration(l)}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left,c.margin(e)}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.version="1.8.5"}(); -//# sourceMappingURL=nv.d3.min.js.map \ No newline at end of file diff --git a/hadoop-hdds/framework/src/main/resources/webapps/static/nvd3-1.8.5.min.js.map b/hadoop-hdds/framework/src/main/resources/webapps/static/nvd3-1.8.5.min.js.map deleted file mode 100644 index 594da5a35c8..00000000000 --- a/hadoop-hdds/framework/src/main/resources/webapps/static/nvd3-1.8.5.min.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"nv.d3.min.js","sources":["../src/core.js","../src/dom.js","../src/interactiveLayer.js","../src/tooltip.js","../src/utils.js","../src/models/axis.js","../src/models/boxPlot.js","../src/models/boxPlotChart.js","../src/models/bullet.js","../src/models/bulletChart.js","../src/models/candlestickBar.js","../src/models/cumulativeLineChart.js","../src/models/discreteBar.js","../src/models/discreteBarChart.js","../src/models/distribution.js","../src/models/focus.js","../src/models/forceDirectedGraph.js","../src/models/furiousLegend.js","../src/models/historicalBar.js","../src/models/historicalBarChart.js","../src/models/legend.js","../src/models/line.js","../src/models/lineChart.js","../src/models/linePlusBarChart.js","../src/models/multiBar.js","../src/models/multiBarChart.js","../src/models/multiBarHorizontal.js","../src/models/multiBarHorizontalChart.js","../src/models/multiChart.js","../src/models/ohlcBar.js","../src/models/parallelCoordinates.js","../src/models/parallelCoordinatesChart.js","../src/models/pie.js","../src/models/pieChart.js","../src/models/sankey.js","../src/models/sankeyChart.js","../src/models/scatter.js","../src/models/scatterChart.js","../src/models/sparkline.js","../src/models/sparklinePlus.js","../src/models/stackedArea.js","../src/models/stackedAreaChart.js","../src/models/sunburst.js","../src/models/sunburstChart.js"],"names":["nv","dev","tooltip","utils","models","charts","logs","dom","d3","require","dispatch","Function","prototype","bind","oThis","this","TypeError","aArgs","Array","slice","call","arguments","fToBind","fNOP","fBound","apply","concat","on","e","startTime","Date","endTime","totalTime","log","window","console","length","deprecated","name","info","warn","render","step","active","render_start","renderLoop","chart","graph","i","queue","generate","callback","splice","setTimeout","render_end","addGraph","obj","push","module","exports","write","undefined","fastdom","mutate","read","measure","interactiveGuideline","layer","selection","each","data","mouseHandler","d3mouse","mouse","mouseX","mouseY","subtractMargin","mouseOutAnyReason","isMSIE","event","offsetX","offsetY","target","tagName","className","baseVal","match","margin","left","top","type","availableWidth","availableHeight","relatedTarget","ownerSVGElement","nvPointerEventsClass","elementMouseout","renderGuideLine","hidden","scaleIsOrdinal","xScale","rangeBands","pointXValue","elementIndex","bisect","range","rangeBand","domain","invert","elementMousemove","elementDblclick","elementClick","elementMouseDown","elementMouseUp","container","select","width","height","wrap","selectAll","wrapEnter","enter","append","attr","svgContainer","guideLine","x","showGuideLine","line","NaNtoZero","String","d","exit","remove","scale","linear","ActiveXObject","duration","hideDelay","_","interactiveBisect","values","searchVal","xAccessor","_xAccessor","_cmp","v","bisector","index","max","currentValue","nextIndex","min","nextValue","Math","abs","nearestValueIndex","threshold","yDistMax","Infinity","indexToHighlight","forEach","delta","initTooltip","node","document","body","id","classes","style","classed","nvtooltip","enabled","dataSeriesExists","newContent","contentGenerator","innerHTML","positionTooltip","floor","random","gravity","distance","snapDistance","lastPosition","headerEnabled","valueFormatter","headerFormatter","keyFormatter","table","createElement","theadEnter","html","value","tbodyEnter","trowEnter","p","series","highlight","color","total","key","filter","percent","format","opacityScale","opacity","outerHTML","footer","position","pos","clientX","clientY","getComputedStyle","transform","client","getBoundingClientRect","isArray","isObject","calcGravityOffset","tmp","offsetHeight","offsetWidth","clientWidth","documentElement","clientHeight","gravityOffset","interrupt","transition","delay","old_translate","new_translate","round","translateInterpolator","interpolateString","is_hidden","styleTween","options","optionsFunc","_options","Object","create","get","set","chartContainer","fixedTop","offset","point","y","initOptions","windowSize","size","innerWidth","innerHeight","compatMode","a","isFunction","isDate","toString","isNumber","isNaN","windowResize","handler","addEventListener","clear","removeEventListener","getColor","defaultColor","color_scale","ordinal","category20","customTheme","dictionary","getKey","defaultColors","defIndex","pjax","links","content","load","href","fragment","parentNode","replaceChild","history","pushState","textContent","preventDefault","state","calcApproxTextWidth","svgTextElem","text","fontSize","parseInt","replace","textLength","n","watchTransition","renderWatch","args","_duration","renderStack","self","model","__rendered","m","arg","renderEnd","indexOf","reset","pop","every","deepExtend","dst","sources","source","srcObj","_setState","_getState","init","changed","getter","fn","setter","update","_set","settings","JSON","stringify","change","map","calcTicksX","numTicks","numValues","stream_len","calcTicksY","initOption","_calls","_overrides","ops","getOwnPropertyNames","calls","inheritOptionsD3","d3_source","oplist","_d3options","unshift","rebind","arrayUnique","sort","item","symbolMap","symbol","t","s","svg","symbolTypes","functor","inheritOptions","inherited","_inherited","d3ops","initSVG","nvd3-svg","sanitizeHeight","sanitizeWidth","bottom","right","noData","opt","noDataText","wrapTicks","word","words","split","reverse","lineNumber","lineHeight","dy","parseFloat","tspan","join","getComputedTextLength","arrayEquals","array1","array2","l","axis","g","ticks","orient","scale0","fmt","tickFormat","axisLabel","axisLabelText","xLabelMargin","axisMaxMin","w","isOrdinal","showMaxMin","tickPadding","axisLabelDistance","maxTextWidth","textHeight","xTicks","rotateLabelsRule","rotateLabels","box","sin","PI","staggerLabels","rotateYLabel","maxMinRange","err","copy","boxPlot","xDomain","getX","xRange","yData","yDomain","yMin","yMax","q1","getQ1","q3","getQ3","wl","getWl","wh","getWh","olItems","getOlItems","getOlValue","yScale","yRange","xScale0","yScale0","boxplots","boxEnter","j","hover","f","box_width","maxBoxWidth","box_left","box_right","endpoint","elementMouseover","getQ2","outliers","getOlColor","getOlLabel","label","Q1","Q2","Q3","whisker_low","whisker_high","q2","itemColor","outlierValue","outlierLabel","outlierColor","boxPlotChart","boxplot","showXAxis","xAxis","showYAxis","yAxis","beforeUpdate","clamp","gEnter","defsEnter","rightAlignYAxis","barsWrap","datum","disabled","tickSize","evt","tooltipContent","bullet","sortLabels","labels","lz","b","iA","iB","descending","rangez","ranges","markerz","markers","markerLinez","markerLines","measurez","measures","rangeLabelz","rangeLabels","markerLabelz","markerLabels","markerLineLabelz","markerLineLabels","measureLabelz","measureLabels","x1","extent","merge","forceX","__chart__","il","rangeClassNames","legacyRangeClassNames","w1","xp1","h3","markerData","marker","markerLinesData","defaultRangeLabels","bulletChart","x0","title","subtitle","bulletWrap","tick","tickEnter","tickUpdate","timer","flush","candlestickBar","barWidth","padData","getLow","forceY","getHigh","chartClick","clipEdge","tickGroups","getOpen","getClose","getY","open","close","high","low","interactive","highlightPoint","pointIndex","isHoverOver","clearHighlights","cumulativeLineChart","lines","dragStart","dragMove","dx","updateZero","dragEnd","stateChange","indexLine","oldDuration","stateSetter","stateGetter","defaultState","indexDrag","behavior","drag","rescaleY","seriesDomains","initialDomain","completeDomain","indexify","interactivePointerEvents","showLegend","legend","marginTop","showControls","controlsData","controls","rightAlign","tempDisabled","useInteractiveGuideline","interactiveLayer","display","linesWrap","seriesIndex","avgLineData","average","avgLines","getAvgLineY","yVal","_ticks","newState","singlePoint","pointXLocation","allData","yValue","domainExtent","xValue","idx","indexifyYGetter","indexValue","noErrorCheck","updateState","useVoronoi","discreteBar","seriesData","y0","showValues","groups","bars","barsEnter","element","stopPropagation","elementDblClick","valueFormat","rectClass","discreteBarChart","discretebar","wrapLabels","distribution","naxis","distWrap","dist","getData","focus","resizePath","updateBrushBG","brush","empty","brushExtent","brushBG","leftWidth","rightWidth","onBrush","shouldDispatch","contentWrap","syncBrushing","brushBGenter","gBrush","pointActive","interpolate","xTickFormat","yTickFormat","forceDirectedGraph","nodes","nodeFieldSet","Set","keys","add","force","layout","linkStrength","friction","linkDistance","linkDist","charge","theta","alpha","start","link","sqrt","radius","py","px","nodeColor","field","linkExtras","nodeExtras","furiousLegend","setTextColor","vers","expanded","disengaged","setBGColor","seriesShape","seriesEnter","property","seriesCheckbox","seriesText","legendMouseover","legendMouseout","legendClick","radioButtonMode","userDisabled","engaged","legendDblclick","versPadding","align","seriesWidths","legendText","maxKeyLength","trimmedKey","substring","nodeTextLength","Error","padding","seriesPerRow","legendWidth","columnWidths","k","reduce","prev","cur","array","xPositions","curX","ceil","xpos","ypos","newxpos","maxwidth","historicalBar","rval","historicalBarChart","bar_model","transitionDuration","tooltipHide","ohlcBarChart","ohlcBar","candlestickBarChart","setBGOpacity","insert","seriesBG","scatter","scatterWrap","strokeWidth","fillOpacity","areaPaths","isArea","area","defined","y1","linePaths","pointSize","pointDomain","lineChart","updateXAxis","updateYAxis","focusLinesWrap","disableTooltip","focusEnable","focusEnter","legendPosition","currentValues","pointYValue","defaultValueFormatter","yPos","x2Axis","y2Axis","focusHeight","focusShowAxisX","focusShowAxisY","focusMargin","lineWithFocusChart","linePlusBarChart","availableHeight2","x2","availableHeight1","bar","focusBarsWrap","dataBars","allDisabled","dataLines","dataLine","switchYAxisOrder","y1Axis","y2","barsOpacity","linesOpacity","y1Opacity","y2Opacity","margin2","y3","lines2","bars2","y4","series1","series2","contextEnter","legendXPosition","originalKey","legendRightAxisHint","legendLeftAxisHint","bars2Wrap","lines2Wrap","y3Axis","y4Axis","getBarsAxis","main","getLinesAxis","multiBar","nonStackableCount","hideable","stacked","parsed","stack","stackOffset","nonStackable","nonStackableSeries","posBase","negBase","groupSpacing","exitTransition","last_datalength","barColor","rgb","darker","barSelection","multiBarChart","multibar","controlWidth","controlLabels","grouped","getTranslate","staggerUp","staggerDown","totalInBetweenTicks","reduceXTicks","multiBarHorizontal","valuePadding","getYerr","xerr","mid","path","yerr","showBarLabels","yErr","multiBarHorizontalChart","multiChart","mouseover_line","yaxis","yAxis2","yAxis1","mouseover_scatter","mouseover_stack","stack1","mouseover_bar","bars1","serieIndex","dataLines1","dataLines2","dataScatters1","dataScatters2","dataBars1","dataBars2","dataStack1","dataStack2","color_array","lines1","scatters1","scatters2","stack2","lines1Wrap","scatters1Wrap","bars1Wrap","stack1Wrap","scatters2Wrap","stack2Wrap","extraValue1","aVal","extraValue2","yScale1","yDomain1","yScale2","yDomain2","stackedArea","parallelCoordinates","enabledDimensions","displayMissingValuesline","axisWithUndefinedValues","newscale","missingValuesline","missingValueslineText","restoreBrush","visible","filters","brushDomain","dimension","hasOnlyNaN","oldDomainMaxValue","hasNaN","dimensions","updateTicks","brushstart","displayBrush","actives","dimensionNames","extents","foreground","isActive","brushend","hasActiveBrush","brushEnd","currentTicks","tickValues","dragging","__origin__","background","dimensionPosition","currentPosition","dimensionsOrder","newData","val","dataValues","dimensionData","rangePoints","onlyUndefinedValues","tension","lineTension","axisDrag","lineData","undefinedValuesLabel","dimensionsEnter","formerActive","activeChanged","dimensionFormats","parallelCoordinatesChart","originalPosition","parallelCoordinatesWrap","isSorted","nanValue","str","tp","dim","dd","pie","arcTween","endAngle","startAngle","donut","innerRadius","_current","arcs","arcsRadiusOuter","arcsRadiusInner","arcsRadius","outer","inner","donutRatio","growOnHover","g_pie","arcsOver","arc","outerRadius","arcOver","cornerRadius","padAngle","titleOffset","slices","pieLabels","ae","attrTween","showLabels","labelsArc","labelsOutside","group","labelSunbeamLayout","rotateAngle","centroid","labelLocationHash","avgHeight","avgWidth","createHashKey","coordinates","getSlicePercentage","center","labelThreshold","hashKey","labelType","pieLabelsOutside","donutLabelsOutside","labelFormat","pieChart","pieWrap","showTooltipPercent","sankey","computeNodeLinks","sourceLinks","targetLinks","computeNodeValues","sum","computeNodeBreadths","nextNodes","remainingNodes","nodeWidth","sinksRight","moveSinksRight","scaleNodeBreadths","kx","computeNodeDepths","iterations","initializeNodeDepth","ky","nodesByBreadth","nodePadding","relaxLeftToRight","weightedSource","sy","breadth","relaxRightToLeft","weightedTarget","ty","resolveCollisions","ascendingDepth","nest","sortKeys","ascending","entries","computeLinkDepths","ascendingSourceDepth","ascendingTargetDepth","relayout","xi","interpolateNumber","curvature","x3","linkPath","sankeyChart","dragmove","testData","isDataValid","dataAvailable","error","showError","linkTitle","origin","appendChild","nodeFillColor","nodeStrokeColor","nodeTitle","units","formatNumber","message","nodeStyle","fillColor","strokeColor","getCache","_cache","delCache","getDiffs","cache","diffs","hasOwnProperty","updateInteractiveLayer","needsUpdate","vertices","groupIndex","pX","pY","pointArray","bounds","geom","polygon","voronoi","clip","pointPaths","vPointPaths","showVoronoi","clipVoronoi","pointClips","clipRadius","mouseEventCallback","el","mDispatch","scrollTop","pageYOffset","scrollLeft","pageXOffset","relativePos","logScale","sizeDomain","getSize","padDataOuter","z","forceSize","sizeRange","_sizeRange_def","z0","scaleDiff","width0","height0","sizeDiff","pointBorderColor","points","getShape","titles","interactiveUpdateDelay","clearTimeout","timeoutID","shape","notActive","pointScale","pointRange","forcePoint","pointShape","scatterChart","showDistX","distX","showDistY","distY","regWrap","regLine","intercept","slope","sparkline","paths","result","yValues","maxPoint","lastIndexOf","minPoint","currentPoint","showMinMaxPoints","showCurrentPoint","animate","sparklinePlus","updateValueLine","paused","hoverValue","hoverEnter","sparklineHover","getClosestIndex","closestIndex","sparklineWrap","showLastValue","valueWrap","rightAlignValue","alignValue","dataRaw","aseries","dataFiltered","order","out","zeroArea","areaMouseover","pageX","pageY","areaMouseout","areaClick","d3_stackedOffset_stackPercent","stackData","o","stackedAreaChart","currentFormat","oldYTickFormat","percentFormatter","stackedWrap","xAxisHeight","legendTop","metaKey","stream","stack_percent","controlOptions","requiredTop","valueSum","allNullValues","tooltipValue","showTotalInTooltip","stackedY0","stackedY","totalLabel","oldValueFormatter","stackedAreaWithFocusChart","sunburst","rotationToAvoidUpsideDown","centerAngle","computeCenterAngle","computeNodePercentage","labelThresholdMatched","arcTweenZoom","xd","yd","yr","arcTweenUpdate","ipo","dx0","dy0","updatePrevPosition","prevPositions","pP","storeRetrievePrevPositions","zoomClick","depth","arcText","getBBox","rotation","partition","modes","mode","cG","cGE","groupColorByParent","children","parent","count","d1","d2","sunburstChart"],"mappings":"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","sourcesContent":["\n// set up main nv object\nvar nv = {};\n\n// the major global objects under the nv namespace\nnv.dev = false; //set false when in production\nnv.tooltip = nv.tooltip || {}; // For the tooltip system\nnv.utils = nv.utils || {}; // Utility subsystem\nnv.models = nv.models || {}; //stores all the possible models/components\nnv.charts = {}; //stores all the ready to use charts\nnv.logs = {}; //stores some statistics and potential error messages\nnv.dom = {}; //DOM manipulation functions\n\n// Node/CommonJS - require D3\nif (typeof(module) !== 'undefined' && typeof(exports) !== 'undefined' && typeof(d3) == 'undefined') {\n d3 = require('d3');\n}\n\nnv.dispatch = d3.dispatch('render_start', 'render_end');\n\n// Function bind polyfill\n// Needed ONLY for phantomJS as it's missing until version 2.0 which is unreleased as of this comment\n// https://github.com/ariya/phantomjs/issues/10522\n// http://kangax.github.io/compat-table/es5/#Function.prototype.bind\n// phantomJS is used for running the test suite\nif (!Function.prototype.bind) {\n Function.prototype.bind = function (oThis) {\n if (typeof this !== \"function\") {\n // closest thing possible to the ECMAScript 5 internal IsCallable function\n throw new TypeError(\"Function.prototype.bind - what is trying to be bound is not callable\");\n }\n\n var aArgs = Array.prototype.slice.call(arguments, 1),\n fToBind = this,\n fNOP = function () {},\n fBound = function () {\n return fToBind.apply(this instanceof fNOP && oThis\n ? this\n : oThis,\n aArgs.concat(Array.prototype.slice.call(arguments)));\n };\n\n fNOP.prototype = this.prototype;\n fBound.prototype = new fNOP();\n return fBound;\n };\n}\n\n// Development render timers - disabled if dev = false\nif (nv.dev) {\n nv.dispatch.on('render_start', function(e) {\n nv.logs.startTime = +new Date();\n });\n\n nv.dispatch.on('render_end', function(e) {\n nv.logs.endTime = +new Date();\n nv.logs.totalTime = nv.logs.endTime - nv.logs.startTime;\n nv.log('total', nv.logs.totalTime); // used for development, to keep track of graph generation times\n });\n}\n\n// Logs all arguments, and returns the last so you can test things in place\n// Note: in IE8 console.log is an object not a function, and if modernizr is used\n// then calling Function.prototype.bind with with anything other than a function\n// causes a TypeError to be thrown.\nnv.log = function() {\n if (nv.dev && window.console && console.log && console.log.apply)\n console.log.apply(console, arguments);\n else if (nv.dev && window.console && typeof console.log == \"function\" && Function.prototype.bind) {\n var log = Function.prototype.bind.call(console.log, console);\n log.apply(console, arguments);\n }\n return arguments[arguments.length - 1];\n};\n\n// print console warning, should be used by deprecated functions\nnv.deprecated = function(name, info) {\n if (console && console.warn) {\n console.warn('nvd3 warning: `' + name + '` has been deprecated. ', info || '');\n }\n};\n\n// The nv.render function is used to queue up chart rendering\n// in non-blocking async functions.\n// When all queued charts are done rendering, nv.dispatch.render_end is invoked.\nnv.render = function render(step) {\n // number of graphs to generate in each timeout loop\n step = step || 1;\n\n nv.render.active = true;\n nv.dispatch.render_start();\n\n var renderLoop = function() {\n var chart, graph;\n\n for (var i = 0; i < step && (graph = nv.render.queue[i]); i++) {\n chart = graph.generate();\n if (typeof graph.callback == typeof(Function)) graph.callback(chart);\n }\n\n nv.render.queue.splice(0, i);\n\n if (nv.render.queue.length) {\n setTimeout(renderLoop);\n }\n else {\n nv.dispatch.render_end();\n nv.render.active = false;\n }\n };\n\n setTimeout(renderLoop);\n};\n\nnv.render.active = false;\nnv.render.queue = [];\n\n/*\nAdds a chart to the async rendering queue. This method can take arguments in two forms:\nnv.addGraph({\n generate: \n callback: \n})\n\nor\n\nnv.addGraph(, )\n\nThe generate function should contain code that creates the NVD3 model, sets options\non it, adds data to an SVG element, and invokes the chart model. The generate function\nshould return the chart model. See examples/lineChart.html for a usage example.\n\nThe callback function is optional, and it is called when the generate function completes.\n*/\nnv.addGraph = function(obj) {\n if (typeof arguments[0] === typeof(Function)) {\n obj = {generate: arguments[0], callback: arguments[1]};\n }\n\n nv.render.queue.push(obj);\n\n if (!nv.render.active) {\n nv.render();\n }\n};\n\n// Node/CommonJS exports\nif (typeof(module) !== 'undefined' && typeof(exports) !== 'undefined') {\n module.exports = nv;\n}\n\nif (typeof(window) !== 'undefined') {\n window.nv = nv;\n}\n","/* Facade for queueing DOM write operations\r\n * with Fastdom (https://github.com/wilsonpage/fastdom)\r\n * if available.\r\n * This could easily be extended to support alternate\r\n * implementations in the future.\r\n */\r\nnv.dom.write = function(callback) {\r\n\tif (window.fastdom !== undefined) {\r\n\t\treturn fastdom.mutate(callback);\r\n\t}\r\n\treturn callback();\r\n};\r\n\r\n/* Facade for queueing DOM read operations\r\n * with Fastdom (https://github.com/wilsonpage/fastdom)\r\n * if available.\r\n * This could easily be extended to support alternate\r\n * implementations in the future.\r\n */\r\nnv.dom.read = function(callback) {\r\n\tif (window.fastdom !== undefined) {\r\n\t\treturn fastdom.measure(callback);\r\n\t}\r\n\treturn callback();\r\n};\r\n","/* Utility class to handle creation of an interactive layer.\n This places a rectangle on top of the chart. When you mouse move over it, it sends a dispatch\n containing the X-coordinate. It can also render a vertical line where the mouse is located.\n\n dispatch.elementMousemove is the important event to latch onto. It is fired whenever the mouse moves over\n the rectangle. The dispatch is given one object which contains the mouseX/Y location.\n It also has 'pointXValue', which is the conversion of mouseX to the x-axis scale.\n */\nnv.interactiveGuideline = function() {\n \"use strict\";\n\n var margin = { left: 0, top: 0 } //Pass the chart's top and left magins. Used to calculate the mouseX/Y.\n , width = null\n , height = null\n , xScale = d3.scale.linear()\n , dispatch = d3.dispatch('elementMousemove', 'elementMouseout', 'elementClick', 'elementDblclick', 'elementMouseDown', 'elementMouseUp')\n , showGuideLine = true\n , svgContainer = null // Must pass the chart's svg, we'll use its mousemove event.\n , tooltip = nv.models.tooltip()\n , isMSIE = window.ActiveXObject// Checkt if IE by looking for activeX. (excludes IE11)\n ;\n\n tooltip\n .duration(0)\n .hideDelay(0)\n .hidden(false);\n\n function layer(selection) {\n selection.each(function(data) {\n var container = d3.select(this);\n var availableWidth = (width || 960), availableHeight = (height || 400);\n var wrap = container.selectAll(\"g.nv-wrap.nv-interactiveLineLayer\")\n .data([data]);\n var wrapEnter = wrap.enter()\n .append(\"g\").attr(\"class\", \" nv-wrap nv-interactiveLineLayer\");\n wrapEnter.append(\"g\").attr(\"class\",\"nv-interactiveGuideLine\");\n\n if (!svgContainer) {\n return;\n }\n\n function mouseHandler() {\n var d3mouse = d3.mouse(this);\n var mouseX = d3mouse[0];\n var mouseY = d3mouse[1];\n var subtractMargin = true;\n var mouseOutAnyReason = false;\n if (isMSIE) {\n /*\n D3.js (or maybe SVG.getScreenCTM) has a nasty bug in Internet Explorer 10.\n d3.mouse() returns incorrect X,Y mouse coordinates when mouse moving\n over a rect in IE 10.\n However, d3.event.offsetX/Y also returns the mouse coordinates\n relative to the triggering . So we use offsetX/Y on IE.\n */\n mouseX = d3.event.offsetX;\n mouseY = d3.event.offsetY;\n\n /*\n On IE, if you attach a mouse event listener to the container,\n it will actually trigger it for all the child elements (like , , etc).\n When this happens on IE, the offsetX/Y is set to where ever the child element\n is located.\n As a result, we do NOT need to subtract margins to figure out the mouse X/Y\n position under this scenario. Removing the line below *will* cause\n the interactive layer to not work right on IE.\n */\n if(d3.event.target.tagName !== \"svg\") {\n subtractMargin = false;\n }\n\n if (d3.event.target.className.baseVal.match(\"nv-legend\")) {\n mouseOutAnyReason = true;\n }\n\n }\n\n if(subtractMargin) {\n mouseX -= margin.left;\n mouseY -= margin.top;\n }\n\n /* If mouseX/Y is outside of the chart's bounds,\n trigger a mouseOut event.\n */\n if (d3.event.type === 'mouseout'\n || mouseX < 0 || mouseY < 0\n || mouseX > availableWidth || mouseY > availableHeight\n || (d3.event.relatedTarget && d3.event.relatedTarget.ownerSVGElement === undefined)\n || mouseOutAnyReason\n ) {\n\n if (isMSIE) {\n if (d3.event.relatedTarget\n && d3.event.relatedTarget.ownerSVGElement === undefined\n && (d3.event.relatedTarget.className === undefined\n || d3.event.relatedTarget.className.match(tooltip.nvPointerEventsClass))) {\n\n return;\n }\n }\n dispatch.elementMouseout({\n mouseX: mouseX,\n mouseY: mouseY\n });\n layer.renderGuideLine(null); //hide the guideline\n tooltip.hidden(true);\n return;\n } else {\n tooltip.hidden(false);\n }\n\n\n var scaleIsOrdinal = typeof xScale.rangeBands === 'function';\n var pointXValue = undefined;\n\n // Ordinal scale has no invert method\n if (scaleIsOrdinal) {\n var elementIndex = d3.bisect(xScale.range(), mouseX) - 1;\n // Check if mouseX is in the range band\n if (xScale.range()[elementIndex] + xScale.rangeBand() >= mouseX) {\n pointXValue = xScale.domain()[d3.bisect(xScale.range(), mouseX) - 1];\n }\n else {\n dispatch.elementMouseout({\n mouseX: mouseX,\n mouseY: mouseY\n });\n layer.renderGuideLine(null); //hide the guideline\n tooltip.hidden(true);\n return;\n }\n }\n else {\n pointXValue = xScale.invert(mouseX);\n }\n\n dispatch.elementMousemove({\n mouseX: mouseX,\n mouseY: mouseY,\n pointXValue: pointXValue\n });\n\n //If user double clicks the layer, fire a elementDblclick\n if (d3.event.type === \"dblclick\") {\n dispatch.elementDblclick({\n mouseX: mouseX,\n mouseY: mouseY,\n pointXValue: pointXValue\n });\n }\n\n // if user single clicks the layer, fire elementClick\n if (d3.event.type === 'click') {\n dispatch.elementClick({\n mouseX: mouseX,\n mouseY: mouseY,\n pointXValue: pointXValue\n });\n }\n\n // if user presses mouse down the layer, fire elementMouseDown\n if (d3.event.type === 'mousedown') {\n \tdispatch.elementMouseDown({\n \t\tmouseX: mouseX,\n \t\tmouseY: mouseY,\n \t\tpointXValue: pointXValue\n \t});\n }\n\n // if user presses mouse down the layer, fire elementMouseUp\n if (d3.event.type === 'mouseup') {\n \tdispatch.elementMouseUp({\n \t\tmouseX: mouseX,\n \t\tmouseY: mouseY,\n \t\tpointXValue: pointXValue\n \t});\n }\n }\n\n svgContainer\n .on(\"touchmove\",mouseHandler)\n .on(\"mousemove\",mouseHandler, true)\n .on(\"mouseout\" ,mouseHandler,true)\n .on(\"mousedown\" ,mouseHandler,true)\n .on(\"mouseup\" ,mouseHandler,true)\n .on(\"dblclick\" ,mouseHandler)\n .on(\"click\", mouseHandler)\n ;\n\n layer.guideLine = null;\n //Draws a vertical guideline at the given X postion.\n layer.renderGuideLine = function(x) {\n if (!showGuideLine) return;\n if (layer.guideLine && layer.guideLine.attr(\"x1\") === x) return;\n nv.dom.write(function() {\n var line = wrap.select(\".nv-interactiveGuideLine\")\n .selectAll(\"line\")\n .data((x != null) ? [nv.utils.NaNtoZero(x)] : [], String);\n line.enter()\n .append(\"line\")\n .attr(\"class\", \"nv-guideline\")\n .attr(\"x1\", function(d) { return d;})\n .attr(\"x2\", function(d) { return d;})\n .attr(\"y1\", availableHeight)\n .attr(\"y2\",0);\n line.exit().remove();\n });\n }\n });\n }\n\n layer.dispatch = dispatch;\n layer.tooltip = tooltip;\n\n layer.margin = function(_) {\n if (!arguments.length) return margin;\n margin.top = typeof _.top != 'undefined' ? _.top : margin.top;\n margin.left = typeof _.left != 'undefined' ? _.left : margin.left;\n return layer;\n };\n\n layer.width = function(_) {\n if (!arguments.length) return width;\n width = _;\n return layer;\n };\n\n layer.height = function(_) {\n if (!arguments.length) return height;\n height = _;\n return layer;\n };\n\n layer.xScale = function(_) {\n if (!arguments.length) return xScale;\n xScale = _;\n return layer;\n };\n\n layer.showGuideLine = function(_) {\n if (!arguments.length) return showGuideLine;\n showGuideLine = _;\n return layer;\n };\n\n layer.svgContainer = function(_) {\n if (!arguments.length) return svgContainer;\n svgContainer = _;\n return layer;\n };\n\n return layer;\n};\n\n/* Utility class that uses d3.bisect to find the index in a given array, where a search value can be inserted.\n This is different from normal bisectLeft; this function finds the nearest index to insert the search value.\n\n For instance, lets say your array is [1,2,3,5,10,30], and you search for 28.\n Normal d3.bisectLeft will return 4, because 28 is inserted after the number 10. But interactiveBisect will return 5\n because 28 is closer to 30 than 10.\n\n Unit tests can be found in: interactiveBisectTest.html\n\n Has the following known issues:\n * Will not work if the data points move backwards (ie, 10,9,8,7, etc) or if the data points are in random order.\n * Won't work if there are duplicate x coordinate values.\n */\nnv.interactiveBisect = function (values, searchVal, xAccessor) {\n \"use strict\";\n if (! (values instanceof Array)) {\n return null;\n }\n var _xAccessor;\n if (typeof xAccessor !== 'function') {\n _xAccessor = function(d) {\n return d.x;\n }\n } else {\n _xAccessor = xAccessor;\n }\n var _cmp = function(d, v) {\n // Accessors are no longer passed the index of the element along with\n // the element itself when invoked by d3.bisector.\n //\n // Starting at D3 v3.4.4, d3.bisector() started inspecting the\n // function passed to determine if it should consider it an accessor\n // or a comparator. This meant that accessors that take two arguments\n // (expecting an index as the second parameter) are treated as\n // comparators where the second argument is the search value against\n // which the first argument is compared.\n return _xAccessor(d) - v;\n };\n\n var bisect = d3.bisector(_cmp).left;\n var index = d3.max([0, bisect(values,searchVal) - 1]);\n var currentValue = _xAccessor(values[index]);\n\n if (typeof currentValue === 'undefined') {\n currentValue = index;\n }\n\n if (currentValue === searchVal) {\n return index; //found exact match\n }\n\n var nextIndex = d3.min([index+1, values.length - 1]);\n var nextValue = _xAccessor(values[nextIndex]);\n\n if (typeof nextValue === 'undefined') {\n nextValue = nextIndex;\n }\n\n if (Math.abs(nextValue - searchVal) >= Math.abs(currentValue - searchVal)) {\n return index;\n } else {\n return nextIndex\n }\n};\n\n/*\n Returns the index in the array \"values\" that is closest to searchVal.\n Only returns an index if searchVal is within some \"threshold\".\n Otherwise, returns null.\n */\nnv.nearestValueIndex = function (values, searchVal, threshold) {\n \"use strict\";\n var yDistMax = Infinity, indexToHighlight = null;\n values.forEach(function(d,i) {\n var delta = Math.abs(searchVal - d);\n if ( d != null && delta <= yDistMax && delta < threshold) {\n yDistMax = delta;\n indexToHighlight = i;\n }\n });\n return indexToHighlight;\n};\n","\n/* Model which can be instantiated to handle tooltip rendering.\n Example usage:\n var tip = nv.models.tooltip().gravity('w').distance(23)\n .data(myDataObject);\n\n tip(); //just invoke the returned function to render tooltip.\n */\nnv.models.tooltip = function() {\n \"use strict\";\n\n /*\n Tooltip data. If data is given in the proper format, a consistent tooltip is generated.\n Example Format of data:\n {\n key: \"Date\",\n value: \"August 2009\",\n series: [\n {key: \"Series 1\", value: \"Value 1\", color: \"#000\"},\n {key: \"Series 2\", value: \"Value 2\", color: \"#00f\"}\n ]\n }\n */\n var id = \"nvtooltip-\" + Math.floor(Math.random() * 100000) // Generates a unique id when you create a new tooltip() object.\n , data = null\n , gravity = 'w' // Can be 'n','s','e','w'. Determines how tooltip is positioned.\n , distance = 25 // Distance to offset tooltip from the mouse location.\n , snapDistance = 0 // Tolerance allowed before tooltip is moved from its current position (creates 'snapping' effect)\n , classes = null // Attaches additional CSS classes to the tooltip DIV that is created.\n , hidden = true // Start off hidden, toggle with hide/show functions below.\n , hideDelay = 200 // Delay (in ms) before the tooltip hides after calling hide().\n , tooltip = null // d3 select of the tooltip div.\n , lastPosition = { left: null, top: null } // Last position the tooltip was in.\n , enabled = true // True -> tooltips are rendered. False -> don't render tooltips.\n , duration = 100 // Tooltip movement duration, in ms.\n , headerEnabled = true // If is to show the tooltip header.\n , nvPointerEventsClass = \"nv-pointer-events-none\" // CSS class to specify whether element should not have mouse events.\n ;\n\n // Format function for the tooltip values column.\n var valueFormatter = function(d, i) {\n return d;\n };\n\n // Format function for the tooltip header value.\n var headerFormatter = function(d) {\n return d;\n };\n\n var keyFormatter = function(d, i) {\n return d;\n };\n\n // By default, the tooltip model renders a beautiful table inside a DIV.\n // You can override this function if a custom tooltip is desired.\n var contentGenerator = function(d) {\n if (d === null) {\n return '';\n }\n\n var table = d3.select(document.createElement(\"table\"));\n if (headerEnabled) {\n var theadEnter = table.selectAll(\"thead\")\n .data([d])\n .enter().append(\"thead\");\n\n theadEnter.append(\"tr\")\n .append(\"td\")\n .attr(\"colspan\", 3)\n .append(\"strong\")\n .classed(\"x-value\", true)\n .html(headerFormatter(d.value));\n }\n\n var tbodyEnter = table.selectAll(\"tbody\")\n .data([d])\n .enter().append(\"tbody\");\n\n var trowEnter = tbodyEnter.selectAll(\"tr\")\n .data(function(p) { return p.series})\n .enter()\n .append(\"tr\")\n .classed(\"highlight\", function(p) { return p.highlight});\n\n trowEnter.append(\"td\")\n .classed(\"legend-color-guide\",true)\n .append(\"div\")\n .style(\"background-color\", function(p) { return p.color});\n\n trowEnter.append(\"td\")\n .classed(\"key\",true)\n .classed(\"total\",function(p) { return !!p.total})\n .html(function(p, i) { return keyFormatter(p.key, i)});\n\n trowEnter.append(\"td\")\n .classed(\"value\",true)\n .html(function(p, i) { return valueFormatter(p.value, i) });\n\n trowEnter.filter(function (p,i) { return p.percent !== undefined }).append(\"td\")\n .classed(\"percent\", true)\n .html(function(p, i) { return \"(\" + d3.format('%')(p.percent) + \")\" });\n\n trowEnter.selectAll(\"td\").each(function(p) {\n if (p.highlight) {\n var opacityScale = d3.scale.linear().domain([0,1]).range([\"#fff\",p.color]);\n var opacity = 0.6;\n d3.select(this)\n .style(\"border-bottom-color\", opacityScale(opacity))\n .style(\"border-top-color\", opacityScale(opacity))\n ;\n }\n });\n\n var html = table.node().outerHTML;\n if (d.footer !== undefined)\n html += \"\";\n return html;\n\n };\n\n /*\n Function that returns the position (relative to the viewport/document.body)\n the tooltip should be placed in.\n Should return: {\n left: ,\n top: \n }\n */\n var position = function() {\n var pos = {\n left: d3.event !== null ? d3.event.clientX : 0,\n top: d3.event !== null ? d3.event.clientY : 0\n };\n\n if(getComputedStyle(document.body).transform != 'none') {\n // Take the offset into account, as now the tooltip is relative\n // to document.body.\n var client = document.body.getBoundingClientRect();\n pos.left -= client.left;\n pos.top -= client.top;\n }\n\n return pos;\n };\n\n var dataSeriesExists = function(d) {\n if (d && d.series) {\n if (nv.utils.isArray(d.series)) {\n return true;\n }\n // if object, it's okay just convert to array of the object\n if (nv.utils.isObject(d.series)) {\n d.series = [d.series];\n return true;\n }\n }\n return false;\n };\n\n // Calculates the gravity offset of the tooltip. Parameter is position of tooltip\n // relative to the viewport.\n var calcGravityOffset = function(pos) {\n var height = tooltip.node().offsetHeight,\n width = tooltip.node().offsetWidth,\n clientWidth = document.documentElement.clientWidth, // Don't want scrollbars.\n clientHeight = document.documentElement.clientHeight, // Don't want scrollbars.\n left, top, tmp;\n\n // calculate position based on gravity\n switch (gravity) {\n case 'e':\n left = - width - distance;\n top = - (height / 2);\n if(pos.left + left < 0) left = distance;\n if((tmp = pos.top + top) < 0) top -= tmp;\n if((tmp = pos.top + top + height) > clientHeight) top -= tmp - clientHeight;\n break;\n case 'w':\n left = distance;\n top = - (height / 2);\n if (pos.left + left + width > clientWidth) left = - width - distance;\n if ((tmp = pos.top + top) < 0) top -= tmp;\n if ((tmp = pos.top + top + height) > clientHeight) top -= tmp - clientHeight;\n break;\n case 'n':\n left = - (width / 2) - 5; // - 5 is an approximation of the mouse's height.\n top = distance;\n if (pos.top + top + height > clientHeight) top = - height - distance;\n if ((tmp = pos.left + left) < 0) left -= tmp;\n if ((tmp = pos.left + left + width) > clientWidth) left -= tmp - clientWidth;\n break;\n case 's':\n left = - (width / 2);\n top = - height - distance;\n if (pos.top + top < 0) top = distance;\n if ((tmp = pos.left + left) < 0) left -= tmp;\n if ((tmp = pos.left + left + width) > clientWidth) left -= tmp - clientWidth;\n break;\n case 'center':\n left = - (width / 2);\n top = - (height / 2);\n break;\n default:\n left = 0;\n top = 0;\n break;\n }\n\n return { 'left': left, 'top': top };\n };\n\n /*\n Positions the tooltip in the correct place, as given by the position() function.\n */\n var positionTooltip = function() {\n nv.dom.read(function() {\n var pos = position(),\n gravityOffset = calcGravityOffset(pos),\n left = pos.left + gravityOffset.left,\n top = pos.top + gravityOffset.top;\n\n // delay hiding a bit to avoid flickering\n if (hidden) {\n tooltip\n .interrupt()\n .transition()\n .delay(hideDelay)\n .duration(0)\n .style('opacity', 0);\n } else {\n // using tooltip.style('transform') returns values un-usable for tween\n var old_translate = 'translate(' + lastPosition.left + 'px, ' + lastPosition.top + 'px)';\n var new_translate = 'translate(' + Math.round(left) + 'px, ' + Math.round(top) + 'px)';\n var translateInterpolator = d3.interpolateString(old_translate, new_translate);\n var is_hidden = tooltip.style('opacity') < 0.1;\n\n tooltip\n .interrupt() // cancel running transitions\n .transition()\n .duration(is_hidden ? 0 : duration)\n // using tween since some versions of d3 can't auto-tween a translate on a div\n .styleTween('transform', function (d) {\n return translateInterpolator;\n }, 'important')\n // Safari has its own `-webkit-transform` and does not support `transform`\n .styleTween('-webkit-transform', function (d) {\n return translateInterpolator;\n })\n .style('-ms-transform', new_translate)\n .style('opacity', 1);\n }\n\n lastPosition.left = left;\n lastPosition.top = top;\n });\n };\n\n // Creates new tooltip container, or uses existing one on DOM.\n function initTooltip() {\n if (!tooltip || !tooltip.node()) {\n // Create new tooltip div if it doesn't exist on DOM.\n\n var data = [1];\n tooltip = d3.select(document.body).select('#'+id).data(data);\n\n tooltip.enter().append('div')\n .attr(\"class\", \"nvtooltip \" + (classes ? classes : \"xy-tooltip\"))\n .attr(\"id\", id)\n .style(\"top\", 0).style(\"left\", 0)\n .style('opacity', 0)\n .style('position', 'fixed')\n .selectAll(\"div, table, td, tr\").classed(nvPointerEventsClass, true)\n .classed(nvPointerEventsClass, true);\n\n tooltip.exit().remove()\n }\n }\n\n // Draw the tooltip onto the DOM.\n function nvtooltip() {\n if (!enabled) return;\n if (!dataSeriesExists(data)) return;\n\n nv.dom.write(function () {\n initTooltip();\n // Generate data and set it into tooltip.\n // Bonus - If you override contentGenerator and return falsey you can use something like\n // React or Knockout to bind the data for your tooltip.\n var newContent = contentGenerator(data);\n if (newContent) {\n tooltip.node().innerHTML = newContent;\n }\n\n positionTooltip();\n });\n\n return nvtooltip;\n }\n\n nvtooltip.nvPointerEventsClass = nvPointerEventsClass;\n nvtooltip.options = nv.utils.optionsFunc.bind(nvtooltip);\n\n nvtooltip._options = Object.create({}, {\n // simple read/write options\n duration: {get: function(){return duration;}, set: function(_){duration=_;}},\n gravity: {get: function(){return gravity;}, set: function(_){gravity=_;}},\n distance: {get: function(){return distance;}, set: function(_){distance=_;}},\n snapDistance: {get: function(){return snapDistance;}, set: function(_){snapDistance=_;}},\n classes: {get: function(){return classes;}, set: function(_){classes=_;}},\n enabled: {get: function(){return enabled;}, set: function(_){enabled=_;}},\n hideDelay: {get: function(){return hideDelay;}, set: function(_){hideDelay=_;}},\n contentGenerator: {get: function(){return contentGenerator;}, set: function(_){contentGenerator=_;}},\n valueFormatter: {get: function(){return valueFormatter;}, set: function(_){valueFormatter=_;}},\n headerFormatter: {get: function(){return headerFormatter;}, set: function(_){headerFormatter=_;}},\n keyFormatter: {get: function(){return keyFormatter;}, set: function(_){keyFormatter=_;}},\n headerEnabled: {get: function(){return headerEnabled;}, set: function(_){headerEnabled=_;}},\n position: {get: function(){return position;}, set: function(_){position=_;}},\n\n // Deprecated options\n chartContainer: {get: function(){return document.body;}, set: function(_){\n // deprecated after 1.8.3\n nv.deprecated('chartContainer', 'feature removed after 1.8.3');\n }},\n fixedTop: {get: function(){return null;}, set: function(_){\n // deprecated after 1.8.1\n nv.deprecated('fixedTop', 'feature removed after 1.8.1');\n }},\n offset: {get: function(){return {left: 0, top: 0};}, set: function(_){\n // deprecated after 1.8.1\n nv.deprecated('offset', 'use chart.tooltip.distance() instead');\n }},\n\n // options with extra logic\n hidden: {get: function(){return hidden;}, set: function(_){\n if (hidden != _) {\n hidden = !!_;\n nvtooltip();\n }\n }},\n data: {get: function(){return data;}, set: function(_){\n // if showing a single data point, adjust data format with that\n if (_.point) {\n _.value = _.point.x;\n _.series = _.series || {};\n _.series.value = _.point.y;\n _.series.color = _.point.color || _.series.color;\n }\n data = _;\n }},\n\n // read only properties\n node: {get: function(){return tooltip.node();}, set: function(_){}},\n id: {get: function(){return id;}, set: function(_){}}\n });\n\n nv.utils.initOptions(nvtooltip);\n return nvtooltip;\n};\n","\n\n/*\nGets the browser window size\n\nReturns object with height and width properties\n */\nnv.utils.windowSize = function() {\n // Sane defaults\n var size = {width: 640, height: 480};\n\n // Most recent browsers use\n if (window.innerWidth && window.innerHeight) {\n size.width = window.innerWidth;\n size.height = window.innerHeight;\n return (size);\n }\n\n // IE can use depending on mode it is in\n if (document.compatMode=='CSS1Compat' &&\n document.documentElement &&\n document.documentElement.offsetWidth ) {\n\n size.width = document.documentElement.offsetWidth;\n size.height = document.documentElement.offsetHeight;\n return (size);\n }\n\n // Earlier IE uses Doc.body\n if (document.body && document.body.offsetWidth) {\n size.width = document.body.offsetWidth;\n size.height = document.body.offsetHeight;\n return (size);\n }\n\n return (size);\n};\n\n\n/* handle dumb browser quirks... isinstance breaks if you use frames\ntypeof returns 'object' for null, NaN is a number, etc.\n */\nnv.utils.isArray = Array.isArray;\nnv.utils.isObject = function(a) {\n return a !== null && typeof a === 'object';\n};\nnv.utils.isFunction = function(a) {\n return typeof a === 'function';\n};\nnv.utils.isDate = function(a) {\n return toString.call(a) === '[object Date]';\n};\nnv.utils.isNumber = function(a) {\n return !isNaN(a) && typeof a === 'number';\n};\n\n\n/*\nBinds callback function to run when window is resized\n */\nnv.utils.windowResize = function(handler) {\n if (window.addEventListener) {\n window.addEventListener('resize', handler);\n } else {\n nv.log(\"ERROR: Failed to bind to window.resize with: \", handler);\n }\n // return object with clear function to remove the single added callback.\n return {\n callback: handler,\n clear: function() {\n window.removeEventListener('resize', handler);\n }\n }\n};\n\n\n/*\nBackwards compatible way to implement more d3-like coloring of graphs.\nCan take in nothing, an array, or a function/scale\nTo use a normal scale, get the range and pass that because we must be able\nto take two arguments and use the index to keep backward compatibility\n*/\nnv.utils.getColor = function(color) {\n //if you pass in nothing, get default colors back\n if (color === undefined) {\n return nv.utils.defaultColor();\n\n //if passed an array, turn it into a color scale\n } else if(nv.utils.isArray(color)) {\n var color_scale = d3.scale.ordinal().range(color);\n return function(d, i) {\n var key = i === undefined ? d : i;\n return d.color || color_scale(key);\n };\n\n //if passed a function or scale, return it, or whatever it may be\n //external libs, such as angularjs-nvd3-directives use this\n } else {\n //can't really help it if someone passes rubbish as color\n return color;\n }\n};\n\n\n/*\nDefault color chooser uses a color scale of 20 colors from D3\n https://github.com/mbostock/d3/wiki/Ordinal-Scales#categorical-colors\n */\nnv.utils.defaultColor = function() {\n // get range of the scale so we'll turn it into our own function.\n return nv.utils.getColor(d3.scale.category20().range());\n};\n\n\n/*\nReturns a color function that takes the result of 'getKey' for each series and\nlooks for a corresponding color from the dictionary\n*/\nnv.utils.customTheme = function(dictionary, getKey, defaultColors) {\n // use default series.key if getKey is undefined\n getKey = getKey || function(series) { return series.key };\n defaultColors = defaultColors || d3.scale.category20().range();\n\n // start at end of default color list and walk back to index 0\n var defIndex = defaultColors.length;\n\n return function(series, index) {\n var key = getKey(series);\n if (nv.utils.isFunction(dictionary[key])) {\n return dictionary[key]();\n } else if (dictionary[key] !== undefined) {\n return dictionary[key];\n } else {\n // no match in dictionary, use a default color\n if (!defIndex) {\n // used all the default colors, start over\n defIndex = defaultColors.length;\n }\n defIndex = defIndex - 1;\n return defaultColors[defIndex];\n }\n };\n};\n\n\n/*\nFrom the PJAX example on d3js.org, while this is not really directly needed\nit's a very cool method for doing pjax, I may expand upon it a little bit,\nopen to suggestions on anything that may be useful\n*/\nnv.utils.pjax = function(links, content) {\n\n var load = function(href) {\n d3.html(href, function(fragment) {\n var target = d3.select(content).node();\n target.parentNode.replaceChild(\n d3.select(fragment).select(content).node(),\n target);\n nv.utils.pjax(links, content);\n });\n };\n\n d3.selectAll(links).on(\"click\", function() {\n history.pushState(this.href, this.textContent, this.href);\n load(this.href);\n d3.event.preventDefault();\n });\n\n d3.select(window).on(\"popstate\", function() {\n if (d3.event.state) {\n load(d3.event.state);\n }\n });\n};\n\n\n/*\nFor when we want to approximate the width in pixels for an SVG:text element.\nMost common instance is when the element is in a display:none; container.\nForumla is : text.length * font-size * constant_factor\n*/\nnv.utils.calcApproxTextWidth = function (svgTextElem) {\n if (nv.utils.isFunction(svgTextElem.style) && nv.utils.isFunction(svgTextElem.text)) {\n var fontSize = parseInt(svgTextElem.style(\"font-size\").replace(\"px\",\"\"), 10);\n var textLength = svgTextElem.text().length;\n return nv.utils.NaNtoZero(textLength * fontSize * 0.5);\n }\n return 0;\n};\n\n\n/*\nNumbers that are undefined, null or NaN, convert them to zeros.\n*/\nnv.utils.NaNtoZero = function(n) {\n if (!nv.utils.isNumber(n)\n || isNaN(n)\n || n === null\n || n === Infinity\n || n === -Infinity) {\n\n return 0;\n }\n return n;\n};\n\n/*\nAdd a way to watch for d3 transition ends to d3\n*/\nd3.selection.prototype.watchTransition = function(renderWatch){\n var args = [this].concat([].slice.call(arguments, 1));\n return renderWatch.transition.apply(renderWatch, args);\n};\n\n\n/*\nHelper object to watch when d3 has rendered something\n*/\nnv.utils.renderWatch = function(dispatch, duration) {\n if (!(this instanceof nv.utils.renderWatch)) {\n return new nv.utils.renderWatch(dispatch, duration);\n }\n\n var _duration = duration !== undefined ? duration : 250;\n var renderStack = [];\n var self = this;\n\n this.models = function(models) {\n models = [].slice.call(arguments, 0);\n models.forEach(function(model){\n model.__rendered = false;\n (function(m){\n m.dispatch.on('renderEnd', function(arg){\n m.__rendered = true;\n self.renderEnd('model');\n });\n })(model);\n\n if (renderStack.indexOf(model) < 0) {\n renderStack.push(model);\n }\n });\n return this;\n };\n\n this.reset = function(duration) {\n if (duration !== undefined) {\n _duration = duration;\n }\n renderStack = [];\n };\n\n this.transition = function(selection, args, duration) {\n args = arguments.length > 1 ? [].slice.call(arguments, 1) : [];\n\n if (args.length > 1) {\n duration = args.pop();\n } else {\n duration = _duration !== undefined ? _duration : 250;\n }\n selection.__rendered = false;\n\n if (renderStack.indexOf(selection) < 0) {\n renderStack.push(selection);\n }\n\n if (duration === 0) {\n selection.__rendered = true;\n selection.delay = function() { return this; };\n selection.duration = function() { return this; };\n return selection;\n } else {\n if (selection.length === 0) {\n selection.__rendered = true;\n } else if (selection.every( function(d){ return !d.length; } )) {\n selection.__rendered = true;\n } else {\n selection.__rendered = false;\n }\n\n var n = 0;\n return selection\n .transition()\n .duration(duration)\n .each(function(){ ++n; })\n .each('end', function(d, i) {\n if (--n === 0) {\n selection.__rendered = true;\n self.renderEnd.apply(this, args);\n }\n });\n }\n };\n\n this.renderEnd = function() {\n if (renderStack.every( function(d){ return d.__rendered; } )) {\n renderStack.forEach( function(d){ d.__rendered = false; });\n dispatch.renderEnd.apply(this, arguments);\n }\n }\n\n};\n\n\n/*\nTakes multiple objects and combines them into the first one (dst)\nexample: nv.utils.deepExtend({a: 1}, {a: 2, b: 3}, {c: 4});\ngives: {a: 2, b: 3, c: 4}\n*/\nnv.utils.deepExtend = function(dst){\n var sources = arguments.length > 1 ? [].slice.call(arguments, 1) : [];\n sources.forEach(function(source) {\n for (var key in source) {\n var isArray = nv.utils.isArray(dst[key]);\n var isObject = nv.utils.isObject(dst[key]);\n var srcObj = nv.utils.isObject(source[key]);\n\n if (isObject && !isArray && srcObj) {\n nv.utils.deepExtend(dst[key], source[key]);\n } else {\n dst[key] = source[key];\n }\n }\n });\n};\n\n\n/*\nstate utility object, used to track d3 states in the models\n*/\nnv.utils.state = function(){\n if (!(this instanceof nv.utils.state)) {\n return new nv.utils.state();\n }\n var state = {};\n var _self = this;\n var _setState = function(){};\n var _getState = function(){ return {}; };\n var init = null;\n var changed = null;\n\n this.dispatch = d3.dispatch('change', 'set');\n\n this.dispatch.on('set', function(state){\n _setState(state, true);\n });\n\n this.getter = function(fn){\n _getState = fn;\n return this;\n };\n\n this.setter = function(fn, callback) {\n if (!callback) {\n callback = function(){};\n }\n _setState = function(state, update){\n fn(state);\n if (update) {\n callback();\n }\n };\n return this;\n };\n\n this.init = function(state){\n init = init || {};\n nv.utils.deepExtend(init, state);\n };\n\n var _set = function(){\n var settings = _getState();\n\n if (JSON.stringify(settings) === JSON.stringify(state)) {\n return false;\n }\n\n for (var key in settings) {\n if (state[key] === undefined) {\n state[key] = {};\n }\n state[key] = settings[key];\n changed = true;\n }\n return true;\n };\n\n this.update = function(){\n if (init) {\n _setState(init, false);\n init = null;\n }\n if (_set.call(this)) {\n this.dispatch.change(state);\n }\n };\n\n};\n\n\n/*\nSnippet of code you can insert into each nv.models.* to give you the ability to\ndo things like:\nchart.options({\n showXAxis: true,\n tooltips: true\n});\n\nTo enable in the chart:\nchart.options = nv.utils.optionsFunc.bind(chart);\n*/\nnv.utils.optionsFunc = function(args) {\n if (args) {\n d3.map(args).forEach((function(key,value) {\n if (nv.utils.isFunction(this[key])) {\n this[key](value);\n }\n }).bind(this));\n }\n return this;\n};\n\n\n/*\nnumTicks: requested number of ticks\ndata: the chart data\n\nreturns the number of ticks to actually use on X axis, based on chart data\nto avoid duplicate ticks with the same value\n*/\nnv.utils.calcTicksX = function(numTicks, data) {\n // find max number of values from all data streams\n var numValues = 1;\n var i = 0;\n for (i; i < data.length; i += 1) {\n var stream_len = data[i] && data[i].values ? data[i].values.length : 0;\n numValues = stream_len > numValues ? stream_len : numValues;\n }\n nv.log(\"Requested number of ticks: \", numTicks);\n nv.log(\"Calculated max values to be: \", numValues);\n // make sure we don't have more ticks than values to avoid duplicates\n numTicks = numTicks > numValues ? numTicks = numValues - 1 : numTicks;\n // make sure we have at least one tick\n numTicks = numTicks < 1 ? 1 : numTicks;\n // make sure it's an integer\n numTicks = Math.floor(numTicks);\n nv.log(\"Calculating tick count as: \", numTicks);\n return numTicks;\n};\n\n\n/*\nreturns number of ticks to actually use on Y axis, based on chart data\n*/\nnv.utils.calcTicksY = function(numTicks, data) {\n // currently uses the same logic but we can adjust here if needed later\n return nv.utils.calcTicksX(numTicks, data);\n};\n\n\n/*\nAdd a particular option from an options object onto chart\nOptions exposed on a chart are a getter/setter function that returns chart\non set to mimic typical d3 option chaining, e.g. svg.option1('a').option2('b');\n\noption objects should be generated via Object.create() to provide\nthe option of manipulating data via get/set functions.\n*/\nnv.utils.initOption = function(chart, name) {\n // if it's a call option, just call it directly, otherwise do get/set\n if (chart._calls && chart._calls[name]) {\n chart[name] = chart._calls[name];\n } else {\n chart[name] = function (_) {\n if (!arguments.length) return chart._options[name];\n chart._overrides[name] = true;\n chart._options[name] = _;\n return chart;\n };\n // calling the option as _option will ignore if set by option already\n // so nvd3 can set options internally but the stop if set manually\n chart['_' + name] = function(_) {\n if (!arguments.length) return chart._options[name];\n if (!chart._overrides[name]) {\n chart._options[name] = _;\n }\n return chart;\n }\n }\n};\n\n\n/*\nAdd all options in an options object to the chart\n*/\nnv.utils.initOptions = function(chart) {\n chart._overrides = chart._overrides || {};\n var ops = Object.getOwnPropertyNames(chart._options || {});\n var calls = Object.getOwnPropertyNames(chart._calls || {});\n ops = ops.concat(calls);\n for (var i in ops) {\n nv.utils.initOption(chart, ops[i]);\n }\n};\n\n\n/*\nInherit options from a D3 object\nd3.rebind makes calling the function on target actually call it on source\nAlso use _d3options so we can track what we inherit for documentation and chained inheritance\n*/\nnv.utils.inheritOptionsD3 = function(target, d3_source, oplist) {\n target._d3options = oplist.concat(target._d3options || []);\n oplist.unshift(d3_source);\n oplist.unshift(target);\n d3.rebind.apply(this, oplist);\n};\n\n\n/*\nRemove duplicates from an array\n*/\nnv.utils.arrayUnique = function(a) {\n return a.sort().filter(function(item, pos) {\n return !pos || item != a[pos - 1];\n });\n};\n\n\n/*\nKeeps a list of custom symbols to draw from in addition to d3.svg.symbol\nNecessary since d3 doesn't let you extend its list -_-\nAdd new symbols by doing nv.utils.symbols.set('name', function(size){...});\n*/\nnv.utils.symbolMap = d3.map();\n\n\n/*\nReplaces d3.svg.symbol so that we can look both there and our own map\n */\nnv.utils.symbol = function() {\n var type,\n size = 64;\n function symbol(d,i) {\n var t = type.call(this,d,i);\n var s = size.call(this,d,i);\n if (d3.svg.symbolTypes.indexOf(t) !== -1) {\n return d3.svg.symbol().type(t).size(s)();\n } else {\n return nv.utils.symbolMap.get(t)(s);\n }\n }\n symbol.type = function(_) {\n if (!arguments.length) return type;\n type = d3.functor(_);\n return symbol;\n };\n symbol.size = function(_) {\n if (!arguments.length) return size;\n size = d3.functor(_);\n return symbol;\n };\n return symbol;\n};\n\n\n/*\nInherit option getter/setter functions from source to target\nd3.rebind makes calling the function on target actually call it on source\nAlso track via _inherited and _d3options so we can track what we inherit\nfor documentation generation purposes and chained inheritance\n*/\nnv.utils.inheritOptions = function(target, source) {\n // inherit all the things\n var ops = Object.getOwnPropertyNames(source._options || {});\n var calls = Object.getOwnPropertyNames(source._calls || {});\n var inherited = source._inherited || [];\n var d3ops = source._d3options || [];\n var args = ops.concat(calls).concat(inherited).concat(d3ops);\n args.unshift(source);\n args.unshift(target);\n d3.rebind.apply(this, args);\n // pass along the lists to keep track of them, don't allow duplicates\n target._inherited = nv.utils.arrayUnique(ops.concat(calls).concat(inherited).concat(ops).concat(target._inherited || []));\n target._d3options = nv.utils.arrayUnique(d3ops.concat(target._d3options || []));\n};\n\n\n/*\nRuns common initialize code on the svg before the chart builds\n*/\nnv.utils.initSVG = function(svg) {\n svg.classed({'nvd3-svg':true});\n};\n\n\n/*\nSanitize and provide default for the container height.\n*/\nnv.utils.sanitizeHeight = function(height, container) {\n return (height || parseInt(container.style('height'), 10) || 400);\n};\n\n\n/*\nSanitize and provide default for the container width.\n*/\nnv.utils.sanitizeWidth = function(width, container) {\n return (width || parseInt(container.style('width'), 10) || 960);\n};\n\n\n/*\nCalculate the available height for a chart.\n*/\nnv.utils.availableHeight = function(height, container, margin) {\n return Math.max(0,nv.utils.sanitizeHeight(height, container) - margin.top - margin.bottom);\n};\n\n/*\nCalculate the available width for a chart.\n*/\nnv.utils.availableWidth = function(width, container, margin) {\n return Math.max(0,nv.utils.sanitizeWidth(width, container) - margin.left - margin.right);\n};\n\n/*\nClear any rendered chart components and display a chart's 'noData' message\n*/\nnv.utils.noData = function(chart, container) {\n var opt = chart.options(),\n margin = opt.margin(),\n noData = opt.noData(),\n data = (noData == null) ? [\"No Data Available.\"] : [noData],\n height = nv.utils.availableHeight(null, container, margin),\n width = nv.utils.availableWidth(null, container, margin),\n x = margin.left + width/2,\n y = margin.top + height/2;\n\n //Remove any previously created chart components\n container.selectAll('g').remove();\n\n var noDataText = container.selectAll('.nv-noData').data(data);\n\n noDataText.enter().append('text')\n .attr('class', 'nvd3 nv-noData')\n .attr('dy', '-.7em')\n .style('text-anchor', 'middle');\n\n noDataText\n .attr('x', x)\n .attr('y', y)\n .text(function(t){ return t; });\n};\n\n/*\n Wrap long labels.\n */\nnv.utils.wrapTicks = function (text, width) {\n text.each(function() {\n var text = d3.select(this),\n words = text.text().split(/\\s+/).reverse(),\n word,\n line = [],\n lineNumber = 0,\n lineHeight = 1.1,\n y = text.attr(\"y\"),\n dy = parseFloat(text.attr(\"dy\")),\n tspan = text.text(null).append(\"tspan\").attr(\"x\", 0).attr(\"y\", y).attr(\"dy\", dy + \"em\");\n while (word = words.pop()) {\n line.push(word);\n tspan.text(line.join(\" \"));\n if (tspan.node().getComputedTextLength() > width) {\n line.pop();\n tspan.text(line.join(\" \"));\n line = [word];\n tspan = text.append(\"tspan\").attr(\"x\", 0).attr(\"y\", y).attr(\"dy\", ++lineNumber * lineHeight + dy + \"em\").text(word);\n }\n }\n });\n};\n\n/*\nCheck equality of 2 array\n*/\nnv.utils.arrayEquals = function (array1, array2) {\n if (array1 === array2)\n return true;\n\n if (!array1 || !array2)\n return false;\n\n // compare lengths - can save a lot of time\n if (array1.length != array2.length)\n return false;\n\n for (var i = 0,\n l = array1.length; i < l; i++) {\n // Check if we have nested arrays\n if (array1[i] instanceof Array && array2[i] instanceof Array) {\n // recurse into the nested arrays\n if (!nv.arrayEquals(array1[i], array2[i]))\n return false;\n } else if (array1[i] != array2[i]) {\n // Warning - two different object instances will never be equal: {x:20} != {x:20}\n return false;\n }\n }\n return true;\n};\n","nv.models.axis = function() {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var axis = d3.svg.axis();\n var scale = d3.scale.linear();\n\n var margin = {top: 0, right: 0, bottom: 0, left: 0}\n , width = 75 //only used for tickLabel currently\n , height = 60 //only used for tickLabel currently\n , axisLabelText = null\n , showMaxMin = true //TODO: showMaxMin should be disabled on all ordinal scaled axes\n , rotateLabels = 0\n , rotateYLabel = true\n , staggerLabels = false\n , isOrdinal = false\n , ticks = null\n , axisLabelDistance = 0\n , fontSize = undefined\n , duration = 250\n , dispatch = d3.dispatch('renderEnd')\n ;\n axis\n .scale(scale)\n .orient('bottom')\n .tickFormat(function(d) { return d })\n ;\n\n //============================================================\n // Private Variables\n //------------------------------------------------------------\n\n var scale0;\n var renderWatch = nv.utils.renderWatch(dispatch, duration);\n\n function chart(selection) {\n renderWatch.reset();\n selection.each(function(data) {\n var container = d3.select(this);\n nv.utils.initSVG(container);\n\n // Setup containers and skeleton of chart\n var wrap = container.selectAll('g.nv-wrap.nv-axis').data([data]);\n var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-axis');\n var gEnter = wrapEnter.append('g');\n var g = wrap.select('g');\n\n if (ticks !== null)\n axis.ticks(ticks);\n else if (axis.orient() == 'top' || axis.orient() == 'bottom')\n axis.ticks(Math.abs(scale.range()[1] - scale.range()[0]) / 100);\n\n //TODO: consider calculating width/height based on whether or not label is added, for reference in charts using this component\n g.watchTransition(renderWatch, 'axis').call(axis);\n\n scale0 = scale0 || axis.scale();\n\n var fmt = axis.tickFormat();\n if (fmt == null) {\n fmt = scale0.tickFormat();\n }\n\n var axisLabel = g.selectAll('text.nv-axislabel')\n .data([axisLabelText || null]);\n axisLabel.exit().remove();\n\n //only skip when fontSize is undefined so it can be cleared with a null or blank string\n if (fontSize !== undefined) {\n g.selectAll('g').select(\"text\").style('font-size', fontSize);\n }\n\n var xLabelMargin;\n var axisMaxMin;\n var w;\n switch (axis.orient()) {\n case 'top':\n axisLabel.enter().append('text').attr('class', 'nv-axislabel');\n w = 0;\n if (scale.range().length === 1) {\n w = isOrdinal ? scale.range()[0] * 2 + scale.rangeBand() : 0;\n } else if (scale.range().length === 2) {\n w = isOrdinal ? scale.range()[0] + scale.range()[1] + scale.rangeBand() : scale.range()[1];\n } else if ( scale.range().length > 2){\n w = scale.range()[scale.range().length-1]+(scale.range()[1]-scale.range()[0]);\n };\n axisLabel\n .attr('text-anchor', 'middle')\n .attr('y', 0)\n .attr('x', w/2);\n if (showMaxMin) {\n axisMaxMin = wrap.selectAll('g.nv-axisMaxMin')\n .data(scale.domain());\n axisMaxMin.enter().append('g').attr('class',function(d,i){\n return ['nv-axisMaxMin','nv-axisMaxMin-x',(i == 0 ? 'nv-axisMin-x':'nv-axisMax-x')].join(' ')\n }).append('text');\n axisMaxMin.exit().remove();\n axisMaxMin\n .attr('transform', function(d,i) {\n return 'translate(' + nv.utils.NaNtoZero(scale(d)) + ',0)'\n })\n .select('text')\n .attr('dy', '-0.5em')\n .attr('y', -axis.tickPadding())\n .attr('text-anchor', 'middle')\n .text(function(d,i) {\n var v = fmt(d);\n return ('' + v).match('NaN') ? '' : v;\n });\n axisMaxMin.watchTransition(renderWatch, 'min-max top')\n .attr('transform', function(d,i) {\n return 'translate(' + nv.utils.NaNtoZero(scale.range()[i]) + ',0)'\n });\n }\n break;\n case 'bottom':\n xLabelMargin = axisLabelDistance + 36;\n var maxTextWidth = 30;\n var textHeight = 0;\n var xTicks = g.selectAll('g').select(\"text\");\n var rotateLabelsRule = '';\n if (rotateLabels%360) {\n //Reset transform on ticks so textHeight can be calculated correctly\n xTicks.attr('transform', ''); \n //Calculate the longest xTick width\n xTicks.each(function(d,i){\n var box = this.getBoundingClientRect();\n var width = box.width;\n textHeight = box.height;\n if(width > maxTextWidth) maxTextWidth = width;\n });\n rotateLabelsRule = 'rotate(' + rotateLabels + ' 0,' + (textHeight/2 + axis.tickPadding()) + ')';\n //Convert to radians before calculating sin. Add 30 to margin for healthy padding.\n var sin = Math.abs(Math.sin(rotateLabels*Math.PI/180));\n xLabelMargin = (sin ? sin*maxTextWidth : maxTextWidth)+30;\n //Rotate all xTicks\n xTicks\n .attr('transform', rotateLabelsRule)\n .style('text-anchor', rotateLabels%360 > 0 ? 'start' : 'end');\n } else {\n if (staggerLabels) {\n xTicks\n .attr('transform', function(d,i) {\n return 'translate(0,' + (i % 2 == 0 ? '0' : '12') + ')'\n });\n } else {\n xTicks.attr('transform', \"translate(0,0)\");\n }\n }\n axisLabel.enter().append('text').attr('class', 'nv-axislabel');\n w = 0;\n if (scale.range().length === 1) {\n w = isOrdinal ? scale.range()[0] * 2 + scale.rangeBand() : 0;\n } else if (scale.range().length === 2) {\n w = isOrdinal ? scale.range()[0] + scale.range()[1] + scale.rangeBand() : scale.range()[1];\n } else if ( scale.range().length > 2){\n w = scale.range()[scale.range().length-1]+(scale.range()[1]-scale.range()[0]);\n };\n axisLabel\n .attr('text-anchor', 'middle')\n .attr('y', xLabelMargin)\n .attr('x', w/2);\n if (showMaxMin) {\n //if (showMaxMin && !isOrdinal) {\n axisMaxMin = wrap.selectAll('g.nv-axisMaxMin')\n //.data(scale.domain())\n .data([scale.domain()[0], scale.domain()[scale.domain().length - 1]]);\n axisMaxMin.enter().append('g').attr('class',function(d,i){\n return ['nv-axisMaxMin','nv-axisMaxMin-x',(i == 0 ? 'nv-axisMin-x':'nv-axisMax-x')].join(' ')\n }).append('text');\n axisMaxMin.exit().remove();\n axisMaxMin\n .attr('transform', function(d,i) {\n return 'translate(' + nv.utils.NaNtoZero((scale(d) + (isOrdinal ? scale.rangeBand() / 2 : 0))) + ',0)'\n })\n .select('text')\n .attr('dy', '.71em')\n .attr('y', axis.tickPadding())\n .attr('transform', rotateLabelsRule)\n .style('text-anchor', rotateLabels ? (rotateLabels%360 > 0 ? 'start' : 'end') : 'middle')\n .text(function(d,i) {\n var v = fmt(d);\n return ('' + v).match('NaN') ? '' : v;\n });\n axisMaxMin.watchTransition(renderWatch, 'min-max bottom')\n .attr('transform', function(d,i) {\n return 'translate(' + nv.utils.NaNtoZero((scale(d) + (isOrdinal ? scale.rangeBand() / 2 : 0))) + ',0)'\n });\n }\n\n break;\n case 'right':\n axisLabel.enter().append('text').attr('class', 'nv-axislabel');\n axisLabel\n .style('text-anchor', rotateYLabel ? 'middle' : 'begin')\n .attr('transform', rotateYLabel ? 'rotate(90)' : '')\n .attr('y', rotateYLabel ? (-Math.max(margin.right, width) + 12 - (axisLabelDistance || 0)) : -10) //TODO: consider calculating this based on largest tick width... OR at least expose this on chart\n .attr('x', rotateYLabel ? (d3.max(scale.range()) / 2) : axis.tickPadding());\n if (showMaxMin) {\n axisMaxMin = wrap.selectAll('g.nv-axisMaxMin')\n .data(scale.domain());\n \taxisMaxMin.enter().append('g').attr('class',function(d,i){\n return ['nv-axisMaxMin','nv-axisMaxMin-y',(i == 0 ? 'nv-axisMin-y':'nv-axisMax-y')].join(' ')\n }).append('text')\n .style('opacity', 0);\n axisMaxMin.exit().remove();\n axisMaxMin\n .attr('transform', function(d,i) {\n return 'translate(0,' + nv.utils.NaNtoZero(scale(d)) + ')'\n })\n .select('text')\n .attr('dy', '.32em')\n .attr('y', 0)\n .attr('x', axis.tickPadding())\n .style('text-anchor', 'start')\n .text(function(d, i) {\n var v = fmt(d);\n return ('' + v).match('NaN') ? '' : v;\n });\n axisMaxMin.watchTransition(renderWatch, 'min-max right')\n .attr('transform', function(d,i) {\n return 'translate(0,' + nv.utils.NaNtoZero(scale.range()[i]) + ')'\n })\n .select('text')\n .style('opacity', 1);\n }\n break;\n case 'left':\n /*\n //For dynamically placing the label. Can be used with dynamically-sized chart axis margins\n var yTicks = g.selectAll('g').select(\"text\");\n yTicks.each(function(d,i){\n var labelPadding = this.getBoundingClientRect().width + axis.tickPadding() + 16;\n if(labelPadding > width) width = labelPadding;\n });\n */\n axisLabel.enter().append('text').attr('class', 'nv-axislabel');\n axisLabel\n .style('text-anchor', rotateYLabel ? 'middle' : 'end')\n .attr('transform', rotateYLabel ? 'rotate(-90)' : '')\n .attr('y', rotateYLabel ? (-Math.max(margin.left, width) + 25 - (axisLabelDistance || 0)) : -10)\n .attr('x', rotateYLabel ? (-d3.max(scale.range()) / 2) : -axis.tickPadding());\n if (showMaxMin) {\n axisMaxMin = wrap.selectAll('g.nv-axisMaxMin')\n .data(scale.domain());\n axisMaxMin.enter().append('g').attr('class',function(d,i){\n return ['nv-axisMaxMin','nv-axisMaxMin-y',(i == 0 ? 'nv-axisMin-y':'nv-axisMax-y')].join(' ')\n }).append('text')\n .style('opacity', 0);\n axisMaxMin.exit().remove();\n axisMaxMin\n .attr('transform', function(d,i) {\n return 'translate(0,' + nv.utils.NaNtoZero(scale0(d)) + ')'\n })\n .select('text')\n .attr('dy', '.32em')\n .attr('y', 0)\n .attr('x', -axis.tickPadding())\n .attr('text-anchor', 'end')\n .text(function(d,i) {\n var v = fmt(d);\n return ('' + v).match('NaN') ? '' : v;\n });\n axisMaxMin.watchTransition(renderWatch, 'min-max right')\n .attr('transform', function(d,i) {\n return 'translate(0,' + nv.utils.NaNtoZero(scale.range()[i]) + ')'\n })\n .select('text')\n .style('opacity', 1);\n }\n break;\n }\n axisLabel.text(function(d) { return d });\n\n if (showMaxMin && (axis.orient() === 'left' || axis.orient() === 'right')) {\n //check if max and min overlap other values, if so, hide the values that overlap\n g.selectAll('g') // the g's wrapping each tick\n .each(function(d,i) {\n d3.select(this).select('text').attr('opacity', 1);\n if (scale(d) < scale.range()[1] + 10 || scale(d) > scale.range()[0] - 10) { // 10 is assuming text height is 16... if d is 0, leave it!\n if (d > 1e-10 || d < -1e-10) // accounts for minor floating point errors... though could be problematic if the scale is EXTREMELY SMALL\n d3.select(this).attr('opacity', 0);\n\n d3.select(this).select('text').attr('opacity', 0); // Don't remove the ZERO line!!\n }\n });\n\n //if Max and Min = 0 only show min, Issue #281\n if (scale.domain()[0] == scale.domain()[1] && scale.domain()[0] == 0) {\n wrap.selectAll('g.nv-axisMaxMin').style('opacity', function (d, i) {\n return !i ? 1 : 0\n });\n }\n }\n\n if (showMaxMin && (axis.orient() === 'top' || axis.orient() === 'bottom')) {\n var maxMinRange = [];\n wrap.selectAll('g.nv-axisMaxMin')\n .each(function(d,i) {\n try {\n if (i) // i== 1, max position\n maxMinRange.push(scale(d) - this.getBoundingClientRect().width - 4); //assuming the max and min labels are as wide as the next tick (with an extra 4 pixels just in case)\n else // i==0, min position\n maxMinRange.push(scale(d) + this.getBoundingClientRect().width + 4)\n }catch (err) {\n if (i) // i== 1, max position\n maxMinRange.push(scale(d) - 4); //assuming the max and min labels are as wide as the next tick (with an extra 4 pixels just in case)\n else // i==0, min position\n maxMinRange.push(scale(d) + 4);\n }\n });\n // the g's wrapping each tick\n g.selectAll('g').each(function(d, i) {\n if (scale(d) < maxMinRange[0] || scale(d) > maxMinRange[1]) {\n if (d > 1e-10 || d < -1e-10) // accounts for minor floating point errors... though could be problematic if the scale is EXTREMELY SMALL\n d3.select(this).remove();\n else\n d3.select(this).select('text').remove(); // Don't remove the ZERO line!!\n }\n });\n }\n\n //Highlight zero tick line\n g.selectAll('.tick')\n .filter(function (d) {\n /*\n The filter needs to return only ticks at or near zero.\n Numbers like 0.00001 need to count as zero as well,\n and the arithmetic trick below solves that.\n */\n return !parseFloat(Math.round(d * 100000) / 1000000) && (d !== undefined)\n }) \n .classed('zero', true);\n \n //store old scales for use in transitions on update\n scale0 = scale.copy();\n\n });\n\n renderWatch.renderEnd('axis immediate');\n return chart;\n }\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n // expose chart's sub-components\n chart.axis = axis;\n chart.dispatch = dispatch;\n\n chart.options = nv.utils.optionsFunc.bind(chart);\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n axisLabelDistance: {get: function(){return axisLabelDistance;}, set: function(_){axisLabelDistance=_;}},\n staggerLabels: {get: function(){return staggerLabels;}, set: function(_){staggerLabels=_;}},\n rotateLabels: {get: function(){return rotateLabels;}, set: function(_){rotateLabels=_;}},\n rotateYLabel: {get: function(){return rotateYLabel;}, set: function(_){rotateYLabel=_;}},\n showMaxMin: {get: function(){return showMaxMin;}, set: function(_){showMaxMin=_;}},\n axisLabel: {get: function(){return axisLabelText;}, set: function(_){axisLabelText=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n ticks: {get: function(){return ticks;}, set: function(_){ticks=_;}},\n width: {get: function(){return width;}, set: function(_){width=_;}},\n fontSize: {get: function(){return fontSize;}, set: function(_){fontSize=_;}},\n\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n margin.top = _.top !== undefined ? _.top : margin.top;\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n }},\n duration: {get: function(){return duration;}, set: function(_){\n duration=_;\n renderWatch.reset(duration);\n }},\n scale: {get: function(){return scale;}, set: function(_){\n scale = _;\n axis.scale(scale);\n isOrdinal = typeof scale.rangeBands === 'function';\n nv.utils.inheritOptionsD3(chart, scale, ['domain', 'range', 'rangeBand', 'rangeBands']);\n }}\n });\n\n nv.utils.initOptions(chart);\n nv.utils.inheritOptionsD3(chart, axis, ['orient', 'tickValues', 'tickSubdivide', 'tickSize', 'tickPadding', 'tickFormat']);\n nv.utils.inheritOptionsD3(chart, scale, ['domain', 'range', 'rangeBand', 'rangeBands']);\n\n return chart;\n};\n","nv.models.boxPlot = function() {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var margin = {top: 0, right: 0, bottom: 0, left: 0},\n width = 960,\n height = 500,\n id = Math.floor(Math.random() * 10000), // Create semi-unique ID in case user doesn't select one\n xScale = d3.scale.ordinal(),\n yScale = d3.scale.linear(),\n getX = function(d) { return d.label }, // Default data model selectors.\n getQ1 = function(d) { return d.values.Q1 },\n getQ2 = function(d) { return d.values.Q2 },\n getQ3 = function(d) { return d.values.Q3 },\n getWl = function(d) { return d.values.whisker_low },\n getWh = function(d) { return d.values.whisker_high },\n getColor = function(d) { return d.color },\n getOlItems = function(d) { return d.values.outliers },\n getOlValue = function(d, i, j) { return d },\n getOlLabel = function(d, i, j) { return d },\n getOlColor = function(d, i, j) { return undefined },\n color = nv.utils.defaultColor(),\n container = null,\n xDomain, xRange,\n yDomain, yRange,\n dispatch = d3.dispatch('elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd'),\n duration = 250,\n maxBoxWidth = null;\n\n //============================================================\n // Private Variables\n //------------------------------------------------------------\n\n var xScale0, yScale0;\n var renderWatch = nv.utils.renderWatch(dispatch, duration);\n\n function chart(selection) {\n renderWatch.reset();\n selection.each(function(data) {\n var availableWidth = width - margin.left - margin.right,\n availableHeight = height - margin.top - margin.bottom;\n\n container = d3.select(this);\n nv.utils.initSVG(container);\n\n // Setup Scales\n xScale.domain(xDomain || data.map(function(d,i) { return getX(d,i); }))\n .rangeBands(xRange || [0, availableWidth], 0.1);\n\n // if we know yDomain, no need to calculate\n var yData = []\n if (!yDomain) {\n // (y-range is based on quartiles, whiskers and outliers)\n var values = [], yMin, yMax;\n data.forEach(function (d, i) {\n var q1 = getQ1(d), q3 = getQ3(d), wl = getWl(d), wh = getWh(d);\n var olItems = getOlItems(d);\n if (olItems) {\n olItems.forEach(function (e, i) {\n values.push(getOlValue(e, i, undefined));\n });\n }\n if (wl) { values.push(wl) }\n if (q1) { values.push(q1) }\n if (q3) { values.push(q3) }\n if (wh) { values.push(wh) }\n });\n yMin = d3.min(values);\n yMax = d3.max(values);\n yData = [ yMin, yMax ] ;\n }\n\n yScale.domain(yDomain || yData);\n yScale.range(yRange || [availableHeight, 0]);\n\n //store old scales if they exist\n xScale0 = xScale0 || xScale;\n yScale0 = yScale0 || yScale.copy().range([yScale(0),yScale(0)]);\n\n // Setup containers and skeleton of chart\n var wrap = container.selectAll('g.nv-wrap').data([data]);\n var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap');\n wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');\n\n var boxplots = wrap.selectAll('.nv-boxplot').data(function(d) { return d });\n var boxEnter = boxplots.enter().append('g').style('stroke-opacity', 1e-6).style('fill-opacity', 1e-6);\n boxplots\n .attr('class', 'nv-boxplot')\n .attr('transform', function(d,i,j) { return 'translate(' + (xScale(getX(d,i)) + xScale.rangeBand() * 0.05) + ', 0)'; })\n .classed('hover', function(d) { return d.hover });\n boxplots\n .watchTransition(renderWatch, 'nv-boxplot: boxplots')\n .style('stroke-opacity', 1)\n .style('fill-opacity', 0.75)\n .delay(function(d,i) { return i * duration / data.length })\n .attr('transform', function(d,i) {\n return 'translate(' + (xScale(getX(d,i)) + xScale.rangeBand() * 0.05) + ', 0)';\n });\n boxplots.exit().remove();\n\n // ----- add the SVG elements for each boxPlot -----\n\n // conditionally append whisker lines\n boxEnter.each(function(d,i) {\n var box = d3.select(this);\n [getWl, getWh].forEach(function (f) {\n if (f(d) !== undefined && f(d) !== null) {\n var key = (f === getWl) ? 'low' : 'high';\n box.append('line')\n .style('stroke', getColor(d) || color(d,i))\n .attr('class', 'nv-boxplot-whisker nv-boxplot-' + key);\n box.append('line')\n .style('stroke', getColor(d) || color(d,i))\n .attr('class', 'nv-boxplot-tick nv-boxplot-' + key);\n }\n });\n });\n\n var box_width = function() { return (maxBoxWidth === null ? xScale.rangeBand() * 0.9 : Math.min(75, xScale.rangeBand() * 0.9)); };\n var box_left = function() { return xScale.rangeBand() * 0.45 - box_width()/2; };\n var box_right = function() { return xScale.rangeBand() * 0.45 + box_width()/2; };\n\n // update whisker lines and ticks\n [getWl, getWh].forEach(function (f) {\n var key = (f === getWl) ? 'low' : 'high';\n var endpoint = (f === getWl) ? getQ1 : getQ3;\n boxplots.select('line.nv-boxplot-whisker.nv-boxplot-' + key)\n .watchTransition(renderWatch, 'nv-boxplot: boxplots')\n .attr('x1', xScale.rangeBand() * 0.45 )\n .attr('y1', function(d,i) { return yScale(f(d)); })\n .attr('x2', xScale.rangeBand() * 0.45 )\n .attr('y2', function(d,i) { return yScale(endpoint(d)); });\n boxplots.select('line.nv-boxplot-tick.nv-boxplot-' + key)\n .watchTransition(renderWatch, 'nv-boxplot: boxplots')\n .attr('x1', box_left )\n .attr('y1', function(d,i) { return yScale(f(d)); })\n .attr('x2', box_right )\n .attr('y2', function(d,i) { return yScale(f(d)); });\n });\n\n [getWl, getWh].forEach(function (f) {\n var key = (f === getWl) ? 'low' : 'high';\n boxEnter.selectAll('.nv-boxplot-' + key)\n .on('mouseover', function(d,i,j) {\n d3.select(this).classed('hover', true);\n dispatch.elementMouseover({\n series: { key: f(d), color: getColor(d) || color(d,j) },\n e: d3.event\n });\n })\n .on('mouseout', function(d,i,j) {\n d3.select(this).classed('hover', false);\n dispatch.elementMouseout({\n series: { key: f(d), color: getColor(d) || color(d,j) },\n e: d3.event\n });\n })\n .on('mousemove', function(d,i) {\n dispatch.elementMousemove({e: d3.event});\n });\n });\n\n // boxes\n boxEnter.append('rect')\n .attr('class', 'nv-boxplot-box')\n // tooltip events\n .on('mouseover', function(d,i) {\n d3.select(this).classed('hover', true);\n dispatch.elementMouseover({\n key: getX(d),\n value: getX(d),\n series: [\n { key: 'Q3', value: getQ3(d), color: getColor(d) || color(d,i) },\n { key: 'Q2', value: getQ2(d), color: getColor(d) || color(d,i) },\n { key: 'Q1', value: getQ1(d), color: getColor(d) || color(d,i) }\n ],\n data: d,\n index: i,\n e: d3.event\n });\n })\n .on('mouseout', function(d,i) {\n d3.select(this).classed('hover', false);\n dispatch.elementMouseout({\n key: getX(d),\n value: getX(d),\n series: [\n { key: 'Q3', value: getQ3(d), color: getColor(d) || color(d,i) },\n { key: 'Q2', value: getQ2(d), color: getColor(d) || color(d,i) },\n { key: 'Q1', value: getQ1(d), color: getColor(d) || color(d,i) }\n ],\n data: d,\n index: i,\n e: d3.event\n });\n })\n .on('mousemove', function(d,i) {\n dispatch.elementMousemove({e: d3.event});\n });\n\n // box transitions\n boxplots.select('rect.nv-boxplot-box')\n .watchTransition(renderWatch, 'nv-boxplot: boxes')\n .attr('y', function(d,i) { return yScale(getQ3(d)); })\n .attr('width', box_width)\n .attr('x', box_left )\n .attr('height', function(d,i) { return Math.abs(yScale(getQ3(d)) - yScale(getQ1(d))) || 1 })\n .style('fill', function(d,i) { return getColor(d) || color(d,i) })\n .style('stroke', function(d,i) { return getColor(d) || color(d,i) });\n\n // median line\n boxEnter.append('line').attr('class', 'nv-boxplot-median');\n\n boxplots.select('line.nv-boxplot-median')\n .watchTransition(renderWatch, 'nv-boxplot: boxplots line')\n .attr('x1', box_left)\n .attr('y1', function(d,i) { return yScale(getQ2(d)); })\n .attr('x2', box_right)\n .attr('y2', function(d,i) { return yScale(getQ2(d)); });\n\n // outliers\n var outliers = boxplots.selectAll('.nv-boxplot-outlier').data(function(d) {\n return getOlItems(d) || [];\n });\n outliers.enter().append('circle')\n .style('fill', function(d,i,j) { return getOlColor(d,i,j) || color(d,j) })\n .style('stroke', function(d,i,j) { return getOlColor(d,i,j) || color(d,j) })\n .style('z-index', 9000)\n .on('mouseover', function(d,i,j) {\n d3.select(this).classed('hover', true);\n dispatch.elementMouseover({\n series: { key: getOlLabel(d,i,j), color: getOlColor(d,i,j) || color(d,j) },\n e: d3.event\n });\n })\n .on('mouseout', function(d,i,j) {\n d3.select(this).classed('hover', false);\n dispatch.elementMouseout({\n series: { key: getOlLabel(d,i,j), color: getOlColor(d,i,j) || color(d,j) },\n e: d3.event\n });\n })\n .on('mousemove', function(d,i) {\n dispatch.elementMousemove({e: d3.event});\n });\n outliers.attr('class', 'nv-boxplot-outlier');\n outliers\n .watchTransition(renderWatch, 'nv-boxplot: nv-boxplot-outlier')\n .attr('cx', xScale.rangeBand() * 0.45)\n .attr('cy', function(d,i,j) { return yScale(getOlValue(d,i,j)); })\n .attr('r', '3');\n outliers.exit().remove();\n\n //store old scales for use in transitions on update\n xScale0 = xScale.copy();\n yScale0 = yScale.copy();\n });\n\n renderWatch.renderEnd('nv-boxplot immediate');\n return chart;\n }\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n chart.dispatch = dispatch;\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n maxBoxWidth: {get: function(){return maxBoxWidth;}, set: function(_){maxBoxWidth=_;}},\n x: {get: function(){return getX;}, set: function(_){getX=_;}},\n q1: {get: function(){return getQ1;}, set: function(_){getQ1=_;}},\n q2: {get: function(){return getQ2;}, set: function(_){getQ2=_;}},\n q3: {get: function(){return getQ3;}, set: function(_){getQ3=_;}},\n wl: {get: function(){return getWl;}, set: function(_){getWl=_;}},\n wh: {get: function(){return getWh;}, set: function(_){getWh=_;}},\n itemColor: {get: function(){return getColor;}, set: function(_){getColor=_;}},\n outliers: {get: function(){return getOlItems;}, set: function(_){getOlItems=_;}},\n outlierValue: {get: function(){return getOlValue;}, set: function(_){getOlValue=_;}},\n outlierLabel: {get: function(){return getOlLabel;}, set: function(_){getOlLabel=_;}},\n outlierColor: {get: function(){return getOlColor;}, set: function(_){getOlColor=_;}},\n xScale: {get: function(){return xScale;}, set: function(_){xScale=_;}},\n yScale: {get: function(){return yScale;}, set: function(_){yScale=_;}},\n xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}},\n yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}},\n xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}},\n yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}},\n id: {get: function(){return id;}, set: function(_){id=_;}},\n // rectClass: {get: function(){return rectClass;}, set: function(_){rectClass=_;}},\n y: {\n get: function() {\n console.warn('BoxPlot \\'y\\' chart option is deprecated. Please use model overrides instead.');\n return {};\n },\n set: function(_) {\n console.warn('BoxPlot \\'y\\' chart option is deprecated. Please use model overrides instead.');\n }\n },\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n margin.top = _.top !== undefined ? _.top : margin.top;\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n }},\n color: {get: function(){return color;}, set: function(_){\n color = nv.utils.getColor(_);\n }},\n duration: {get: function(){return duration;}, set: function(_){\n duration = _;\n renderWatch.reset(duration);\n }}\n });\n\n nv.utils.initOptions(chart);\n\n return chart;\n};\n","nv.models.boxPlotChart = function() {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var boxplot = nv.models.boxPlot(),\n xAxis = nv.models.axis(),\n yAxis = nv.models.axis();\n\n var margin = {top: 15, right: 10, bottom: 50, left: 60},\n width = null,\n height = null,\n color = nv.utils.getColor(),\n showXAxis = true,\n showYAxis = true,\n rightAlignYAxis = false,\n staggerLabels = false,\n tooltip = nv.models.tooltip(),\n x, y,\n noData = 'No Data Available.',\n dispatch = d3.dispatch('beforeUpdate', 'renderEnd'),\n duration = 250;\n\n xAxis\n .orient('bottom')\n .showMaxMin(false)\n .tickFormat(function(d) { return d })\n ;\n yAxis\n .orient((rightAlignYAxis) ? 'right' : 'left')\n .tickFormat(d3.format(',.1f'))\n ;\n\n tooltip.duration(0);\n\n //============================================================\n // Private Variables\n //------------------------------------------------------------\n\n var renderWatch = nv.utils.renderWatch(dispatch, duration);\n\n function chart(selection) {\n renderWatch.reset();\n renderWatch.models(boxplot);\n if (showXAxis) renderWatch.models(xAxis);\n if (showYAxis) renderWatch.models(yAxis);\n\n selection.each(function(data) {\n var container = d3.select(this), that = this;\n nv.utils.initSVG(container);\n var availableWidth = (width || parseInt(container.style('width')) || 960) - margin.left - margin.right;\n var availableHeight = (height || parseInt(container.style('height')) || 400) - margin.top - margin.bottom;\n\n chart.update = function() {\n dispatch.beforeUpdate();\n container.transition().duration(duration).call(chart);\n };\n chart.container = this;\n\n // TODO still need to find a way to validate quartile data presence using boxPlot callbacks.\n // Display No Data message if there's nothing to show. (quartiles required at minimum).\n if (!data || !data.length) {\n var noDataText = container.selectAll('.nv-noData').data([noData]);\n\n noDataText.enter().append('text')\n .attr('class', 'nvd3 nv-noData')\n .attr('dy', '-.7em')\n .style('text-anchor', 'middle');\n\n noDataText\n .attr('x', margin.left + availableWidth / 2)\n .attr('y', margin.top + availableHeight / 2)\n .text(function(d) { return d });\n\n return chart;\n } else {\n container.selectAll('.nv-noData').remove();\n }\n\n // Setup Scales\n x = boxplot.xScale();\n y = boxplot.yScale().clamp(true);\n\n // Setup containers and skeleton of chart\n var wrap = container.selectAll('g.nv-wrap.nv-boxPlotWithAxes').data([data]);\n var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-boxPlotWithAxes').append('g');\n var defsEnter = gEnter.append('defs');\n var g = wrap.select('g');\n\n gEnter.append('g').attr('class', 'nv-x nv-axis');\n gEnter.append('g').attr('class', 'nv-y nv-axis')\n .append('g').attr('class', 'nv-zeroLine')\n .append('line');\n\n gEnter.append('g').attr('class', 'nv-barsWrap');\n g.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');\n\n if (rightAlignYAxis) {\n g.select('.nv-y.nv-axis')\n .attr('transform', 'translate(' + availableWidth + ',0)');\n }\n\n // Main Chart Component(s)\n boxplot.width(availableWidth).height(availableHeight);\n\n var barsWrap = g.select('.nv-barsWrap')\n .datum(data.filter(function(d) { return !d.disabled }))\n\n barsWrap.transition().call(boxplot);\n\n defsEnter.append('clipPath')\n .attr('id', 'nv-x-label-clip-' + boxplot.id())\n .append('rect');\n\n g.select('#nv-x-label-clip-' + boxplot.id() + ' rect')\n .attr('width', x.rangeBand() * (staggerLabels ? 2 : 1))\n .attr('height', 16)\n .attr('x', -x.rangeBand() / (staggerLabels ? 1 : 2 ));\n\n // Setup Axes\n if (showXAxis) {\n xAxis\n .scale(x)\n .ticks( nv.utils.calcTicksX(availableWidth/100, data) )\n .tickSize(-availableHeight, 0);\n\n g.select('.nv-x.nv-axis').attr('transform', 'translate(0,' + y.range()[0] + ')');\n g.select('.nv-x.nv-axis').call(xAxis);\n\n var xTicks = g.select('.nv-x.nv-axis').selectAll('g');\n if (staggerLabels) {\n xTicks\n .selectAll('text')\n .attr('transform', function(d,i,j) { return 'translate(0,' + (j % 2 === 0 ? '5' : '17') + ')' })\n }\n }\n\n if (showYAxis) {\n yAxis\n .scale(y)\n .ticks( Math.floor(availableHeight/36) ) // can't use nv.utils.calcTicksY with Object data\n .tickSize( -availableWidth, 0);\n\n g.select('.nv-y.nv-axis').call(yAxis);\n }\n\n // Zero line\n g.select('.nv-zeroLine line')\n .attr('x1',0)\n .attr('x2',availableWidth)\n .attr('y1', y(0))\n .attr('y2', y(0))\n ;\n\n //============================================================\n // Event Handling/Dispatching (in chart's scope)\n //------------------------------------------------------------\n });\n\n renderWatch.renderEnd('nv-boxplot chart immediate');\n return chart;\n }\n\n //============================================================\n // Event Handling/Dispatching (out of chart's scope)\n //------------------------------------------------------------\n\n boxplot.dispatch.on('elementMouseover.tooltip', function(evt) {\n tooltip.data(evt).hidden(false);\n });\n\n boxplot.dispatch.on('elementMouseout.tooltip', function(evt) {\n tooltip.data(evt).hidden(true);\n });\n\n boxplot.dispatch.on('elementMousemove.tooltip', function(evt) {\n tooltip();\n });\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n chart.dispatch = dispatch;\n chart.boxplot = boxplot;\n chart.xAxis = xAxis;\n chart.yAxis = yAxis;\n chart.tooltip = tooltip;\n\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n staggerLabels: {get: function(){return staggerLabels;}, set: function(_){staggerLabels=_;}},\n showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},\n showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},\n tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}},\n noData: {get: function(){return noData;}, set: function(_){noData=_;}},\n\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n margin.top = _.top !== undefined ? _.top : margin.top;\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n }},\n duration: {get: function(){return duration;}, set: function(_){\n duration = _;\n renderWatch.reset(duration);\n boxplot.duration(duration);\n xAxis.duration(duration);\n yAxis.duration(duration);\n }},\n color: {get: function(){return color;}, set: function(_){\n color = nv.utils.getColor(_);\n boxplot.color(color);\n }},\n rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){\n rightAlignYAxis = _;\n yAxis.orient( (_) ? 'right' : 'left');\n }}\n });\n\n nv.utils.inheritOptions(chart, boxplot);\n nv.utils.initOptions(chart);\n\n return chart;\n}\n","\n// Chart design based on the recommendations of Stephen Few. Implementation\n// based on the work of Clint Ivy, Jamie Love, and Jason Davies.\n// http://projects.instantcognition.com/protovis/bulletchart/\n\nnv.models.bullet = function() {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var margin = {top: 0, right: 0, bottom: 0, left: 0}\n , orient = 'left' // TODO top & bottom\n , reverse = false\n , ranges = function(d) { return d.ranges }\n , markers = function(d) { return d.markers ? d.markers : [] }\n , markerLines = function(d) { return d.markerLines ? d.markerLines : [0] }\n , measures = function(d) { return d.measures }\n , rangeLabels = function(d) { return d.rangeLabels ? d.rangeLabels : [] }\n , markerLabels = function(d) { return d.markerLabels ? d.markerLabels : [] }\n , markerLineLabels = function(d) { return d.markerLineLabels ? d.markerLineLabels : [] }\n , measureLabels = function(d) { return d.measureLabels ? d.measureLabels : [] }\n , forceX = [0] // List of numbers to Force into the X scale (ie. 0, or a max / min, etc.)\n , width = 380\n , height = 30\n , container = null\n , tickFormat = null\n , color = nv.utils.getColor(['#1f77b4'])\n , dispatch = d3.dispatch('elementMouseover', 'elementMouseout', 'elementMousemove')\n , defaultRangeLabels = [\"Maximum\", \"Mean\", \"Minimum\"]\n , legacyRangeClassNames = [\"Max\", \"Avg\", \"Min\"]\n , duration = 1000\n ;\n\n function sortLabels(labels, values){\n var lz = labels.slice();\n labels.sort(function(a, b){\n var iA = lz.indexOf(a);\n var iB = lz.indexOf(b);\n return d3.descending(values[iA], values[iB]);\n });\n };\n\n function chart(selection) {\n selection.each(function(d, i) {\n var availableWidth = width - margin.left - margin.right,\n availableHeight = height - margin.top - margin.bottom;\n\n container = d3.select(this);\n nv.utils.initSVG(container);\n\n var rangez = ranges.call(this, d, i).slice(),\n markerz = markers.call(this, d, i).slice(),\n markerLinez = markerLines.call(this, d, i).slice(),\n measurez = measures.call(this, d, i).slice(),\n rangeLabelz = rangeLabels.call(this, d, i).slice(),\n markerLabelz = markerLabels.call(this, d, i).slice(),\n markerLineLabelz = markerLineLabels.call(this, d, i).slice(),\n measureLabelz = measureLabels.call(this, d, i).slice();\n\n // Sort labels according to their sorted values\n sortLabels(rangeLabelz, rangez);\n sortLabels(markerLabelz, markerz);\n sortLabels(markerLineLabelz, markerLinez);\n sortLabels(measureLabelz, measurez);\n\n // sort values descending\n rangez.sort(d3.descending);\n markerz.sort(d3.descending);\n markerLinez.sort(d3.descending);\n measurez.sort(d3.descending);\n\n // Setup Scales\n // Compute the new x-scale.\n var x1 = d3.scale.linear()\n .domain( d3.extent(d3.merge([forceX, rangez])) )\n .range(reverse ? [availableWidth, 0] : [0, availableWidth]);\n\n // Retrieve the old x-scale, if this is an update.\n var x0 = this.__chart__ || d3.scale.linear()\n .domain([0, Infinity])\n .range(x1.range());\n\n // Stash the new scale.\n this.__chart__ = x1;\n\n var rangeMin = d3.min(rangez), //rangez[2]\n rangeMax = d3.max(rangez), //rangez[0]\n rangeAvg = rangez[1];\n\n // Setup containers and skeleton of chart\n var wrap = container.selectAll('g.nv-wrap.nv-bullet').data([d]);\n var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-bullet');\n var gEnter = wrapEnter.append('g');\n var g = wrap.select('g');\n\n for(var i=0,il=rangez.length; i getClose(d, i) ? 'nv-tick negative' : 'nv-tick positive') + ' nv-tick-' + j + '-' + i});\n\n var lines = tickGroups.append('line')\n .attr('class', 'nv-candlestick-lines')\n .attr('transform', function(d, i) { return 'translate(' + x(getX(d, i)) + ',0)'; })\n .attr('x1', 0)\n .attr('y1', function(d, i) { return y(getHigh(d, i)); })\n .attr('x2', 0)\n .attr('y2', function(d, i) { return y(getLow(d, i)); });\n\n var rects = tickGroups.append('rect')\n .attr('class', 'nv-candlestick-rects nv-bars')\n .attr('transform', function(d, i) {\n return 'translate(' + (x(getX(d, i)) - barWidth/2) + ','\n + (y(getY(d, i)) - (getOpen(d, i) > getClose(d, i) ? (y(getClose(d, i)) - y(getOpen(d, i))) : 0))\n + ')';\n })\n .attr('x', 0)\n .attr('y', 0)\n .attr('width', barWidth)\n .attr('height', function(d, i) {\n var open = getOpen(d, i);\n var close = getClose(d, i);\n return open > close ? y(close) - y(open) : y(open) - y(close);\n });\n\n ticks.select('.nv-candlestick-lines').transition()\n .attr('transform', function(d, i) { return 'translate(' + x(getX(d, i)) + ',0)'; })\n .attr('x1', 0)\n .attr('y1', function(d, i) { return y(getHigh(d, i)); })\n .attr('x2', 0)\n .attr('y2', function(d, i) { return y(getLow(d, i)); });\n\n ticks.select('.nv-candlestick-rects').transition()\n .attr('transform', function(d, i) {\n return 'translate(' + (x(getX(d, i)) - barWidth/2) + ','\n + (y(getY(d, i)) - (getOpen(d, i) > getClose(d, i) ? (y(getClose(d, i)) - y(getOpen(d, i))) : 0))\n + ')';\n })\n .attr('x', 0)\n .attr('y', 0)\n .attr('width', barWidth)\n .attr('height', function(d, i) {\n var open = getOpen(d, i);\n var close = getClose(d, i);\n return open > close ? y(close) - y(open) : y(open) - y(close);\n });\n });\n\n return chart;\n }\n\n\n //Create methods to allow outside functions to highlight a specific bar.\n chart.highlightPoint = function(pointIndex, isHoverOver) {\n chart.clearHighlights();\n container.select(\".nv-candlestickBar .nv-tick-0-\" + pointIndex)\n .classed(\"hover\", isHoverOver)\n ;\n };\n\n chart.clearHighlights = function() {\n container.select(\".nv-candlestickBar .nv-tick.hover\")\n .classed(\"hover\", false)\n ;\n };\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n chart.dispatch = dispatch;\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n xScale: {get: function(){return x;}, set: function(_){x=_;}},\n yScale: {get: function(){return y;}, set: function(_){y=_;}},\n xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}},\n yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}},\n xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}},\n yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}},\n forceX: {get: function(){return forceX;}, set: function(_){forceX=_;}},\n forceY: {get: function(){return forceY;}, set: function(_){forceY=_;}},\n padData: {get: function(){return padData;}, set: function(_){padData=_;}},\n clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}},\n id: {get: function(){return id;}, set: function(_){id=_;}},\n interactive: {get: function(){return interactive;}, set: function(_){interactive=_;}},\n\n x: {get: function(){return getX;}, set: function(_){getX=_;}},\n y: {get: function(){return getY;}, set: function(_){getY=_;}},\n open: {get: function(){return getOpen();}, set: function(_){getOpen=_;}},\n close: {get: function(){return getClose();}, set: function(_){getClose=_;}},\n high: {get: function(){return getHigh;}, set: function(_){getHigh=_;}},\n low: {get: function(){return getLow;}, set: function(_){getLow=_;}},\n\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n margin.top = _.top != undefined ? _.top : margin.top;\n margin.right = _.right != undefined ? _.right : margin.right;\n margin.bottom = _.bottom != undefined ? _.bottom : margin.bottom;\n margin.left = _.left != undefined ? _.left : margin.left;\n }},\n color: {get: function(){return color;}, set: function(_){\n color = nv.utils.getColor(_);\n }}\n });\n\n nv.utils.initOptions(chart);\n return chart;\n};\n","\nnv.models.cumulativeLineChart = function() {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var lines = nv.models.line()\n , xAxis = nv.models.axis()\n , yAxis = nv.models.axis()\n , legend = nv.models.legend()\n , controls = nv.models.legend()\n , interactiveLayer = nv.interactiveGuideline()\n , tooltip = nv.models.tooltip()\n ;\n\n var margin = {top: 30, right: 30, bottom: 50, left: 60}\n , marginTop = null\n , color = nv.utils.defaultColor()\n , width = null\n , height = null\n , showLegend = true\n , showXAxis = true\n , showYAxis = true\n , rightAlignYAxis = false\n , showControls = true\n , useInteractiveGuideline = false\n , rescaleY = true\n , x //can be accessed via chart.xScale()\n , y //can be accessed via chart.yScale()\n , id = lines.id()\n , state = nv.utils.state()\n , defaultState = null\n , noData = null\n , average = function(d) { return d.average }\n , dispatch = d3.dispatch('stateChange', 'changeState', 'renderEnd')\n , transitionDuration = 250\n , duration = 250\n , noErrorCheck = false //if set to TRUE, will bypass an error check in the indexify function.\n ;\n\n state.index = 0;\n state.rescaleY = rescaleY;\n\n xAxis.orient('bottom').tickPadding(7);\n yAxis.orient((rightAlignYAxis) ? 'right' : 'left');\n\n tooltip.valueFormatter(function(d, i) {\n return yAxis.tickFormat()(d, i);\n }).headerFormatter(function(d, i) {\n return xAxis.tickFormat()(d, i);\n });\n\n controls.updateState(false);\n\n //============================================================\n // Private Variables\n //------------------------------------------------------------\n\n var dx = d3.scale.linear()\n , index = {i: 0, x: 0}\n , renderWatch = nv.utils.renderWatch(dispatch, duration)\n ;\n\n var stateGetter = function(data) {\n return function(){\n return {\n active: data.map(function(d) { return !d.disabled }),\n index: index.i,\n rescaleY: rescaleY\n };\n }\n };\n\n var stateSetter = function(data) {\n return function(state) {\n if (state.index !== undefined)\n index.i = state.index;\n if (state.rescaleY !== undefined)\n rescaleY = state.rescaleY;\n if (state.active !== undefined)\n data.forEach(function(series,i) {\n series.disabled = !state.active[i];\n });\n }\n };\n\n function chart(selection) {\n renderWatch.reset();\n renderWatch.models(lines);\n if (showXAxis) renderWatch.models(xAxis);\n if (showYAxis) renderWatch.models(yAxis);\n selection.each(function(data) {\n var container = d3.select(this);\n nv.utils.initSVG(container);\n container.classed('nv-chart-' + id, true);\n var that = this;\n\n var availableWidth = nv.utils.availableWidth(width, container, margin),\n availableHeight = nv.utils.availableHeight(height, container, margin);\n\n chart.update = function() {\n if (duration === 0)\n container.call(chart);\n else\n container.transition().duration(duration).call(chart)\n };\n chart.container = this;\n\n state\n .setter(stateSetter(data), chart.update)\n .getter(stateGetter(data))\n .update();\n\n // DEPRECATED set state.disableddisabled\n state.disabled = data.map(function(d) { return !!d.disabled });\n\n if (!defaultState) {\n var key;\n defaultState = {};\n for (key in state) {\n if (state[key] instanceof Array)\n defaultState[key] = state[key].slice(0);\n else\n defaultState[key] = state[key];\n }\n }\n\n var indexDrag = d3.behavior.drag()\n .on('dragstart', dragStart)\n .on('drag', dragMove)\n .on('dragend', dragEnd);\n\n\n function dragStart(d,i) {\n d3.select(chart.container)\n .style('cursor', 'ew-resize');\n }\n\n function dragMove(d,i) {\n index.x = d3.event.x;\n index.i = Math.round(dx.invert(index.x));\n updateZero();\n }\n\n function dragEnd(d,i) {\n d3.select(chart.container)\n .style('cursor', 'auto');\n\n // update state and send stateChange with new index\n state.index = index.i;\n dispatch.stateChange(state);\n }\n\n // Display No Data message if there's nothing to show.\n if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {\n nv.utils.noData(chart, container)\n return chart;\n } else {\n container.selectAll('.nv-noData').remove();\n }\n\n // Setup Scales\n x = lines.xScale();\n y = lines.yScale();\n\n if (!rescaleY) {\n var seriesDomains = data\n .filter(function(series) { return !series.disabled })\n .map(function(series,i) {\n var initialDomain = d3.extent(series.values, lines.y());\n\n //account for series being disabled when losing 95% or more\n if (initialDomain[0] < -.95) initialDomain[0] = -.95;\n\n return [\n (initialDomain[0] - initialDomain[1]) / (1 + initialDomain[1]),\n (initialDomain[1] - initialDomain[0]) / (1 + initialDomain[0])\n ];\n });\n\n var completeDomain = [\n d3.min(seriesDomains, function(d) { return d[0] }),\n d3.max(seriesDomains, function(d) { return d[1] })\n ];\n\n lines.yDomain(completeDomain);\n } else {\n lines.yDomain(null);\n }\n\n dx.domain([0, data[0].values.length - 1]) //Assumes all series have same length\n .range([0, availableWidth])\n .clamp(true);\n\n var data = indexify(index.i, data);\n\n // Setup containers and skeleton of chart\n var interactivePointerEvents = (useInteractiveGuideline) ? \"none\" : \"all\";\n var wrap = container.selectAll('g.nv-wrap.nv-cumulativeLine').data([data]);\n var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-cumulativeLine').append('g');\n var g = wrap.select('g');\n\n gEnter.append('g').attr('class', 'nv-interactive');\n gEnter.append('g').attr('class', 'nv-x nv-axis').style(\"pointer-events\",\"none\");\n gEnter.append('g').attr('class', 'nv-y nv-axis');\n gEnter.append('g').attr('class', 'nv-background');\n gEnter.append('g').attr('class', 'nv-linesWrap').style(\"pointer-events\",interactivePointerEvents);\n gEnter.append('g').attr('class', 'nv-avgLinesWrap').style(\"pointer-events\",\"none\");\n gEnter.append('g').attr('class', 'nv-legendWrap');\n gEnter.append('g').attr('class', 'nv-controlsWrap');\n\n // Legend\n if (!showLegend) {\n g.select('.nv-legendWrap').selectAll('*').remove();\n } else {\n legend.width(availableWidth);\n\n g.select('.nv-legendWrap')\n .datum(data)\n .call(legend);\n\n if (!marginTop && legend.height() !== margin.top) {\n margin.top = legend.height();\n availableHeight = nv.utils.availableHeight(height, container, margin);\n }\n\n g.select('.nv-legendWrap')\n .attr('transform', 'translate(0,' + (-margin.top) +')')\n }\n\n // Controls\n if (!showControls) {\n g.select('.nv-controlsWrap').selectAll('*').remove();\n } else {\n var controlsData = [\n { key: 'Re-scale y-axis', disabled: !rescaleY }\n ];\n\n controls\n .width(140)\n .color(['#444', '#444', '#444'])\n .rightAlign(false)\n .margin({top: 5, right: 0, bottom: 5, left: 20})\n ;\n\n g.select('.nv-controlsWrap')\n .datum(controlsData)\n .attr('transform', 'translate(0,' + (-margin.top) +')')\n .call(controls);\n }\n\n wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');\n\n if (rightAlignYAxis) {\n g.select(\".nv-y.nv-axis\")\n .attr(\"transform\", \"translate(\" + availableWidth + \",0)\");\n }\n\n // Show error if series goes below 100%\n var tempDisabled = data.filter(function(d) { return d.tempDisabled });\n\n wrap.select('.tempDisabled').remove(); //clean-up and prevent duplicates\n if (tempDisabled.length) {\n wrap.append('text').attr('class', 'tempDisabled')\n .attr('x', availableWidth / 2)\n .attr('y', '-.71em')\n .style('text-anchor', 'end')\n .text(tempDisabled.map(function(d) { return d.key }).join(', ') + ' values cannot be calculated for this time period.');\n }\n\n //Set up interactive layer\n if (useInteractiveGuideline) {\n interactiveLayer\n .width(availableWidth)\n .height(availableHeight)\n .margin({left:margin.left,top:margin.top})\n .svgContainer(container)\n .xScale(x);\n wrap.select(\".nv-interactive\").call(interactiveLayer);\n }\n\n gEnter.select('.nv-background')\n .append('rect');\n\n g.select('.nv-background rect')\n .attr('width', availableWidth)\n .attr('height', availableHeight);\n\n lines\n //.x(function(d) { return d.x })\n .y(function(d) { return d.display.y })\n .width(availableWidth)\n .height(availableHeight)\n .color(data.map(function(d,i) {\n return d.color || color(d, i);\n }).filter(function(d,i) { return !data[i].disabled && !data[i].tempDisabled; }));\n\n var linesWrap = g.select('.nv-linesWrap')\n .datum(data.filter(function(d) { return !d.disabled && !d.tempDisabled }));\n\n linesWrap.call(lines);\n\n //Store a series index number in the data array.\n data.forEach(function(d,i) {\n d.seriesIndex = i;\n });\n\n var avgLineData = data.filter(function(d) {\n return !d.disabled && !!average(d);\n });\n\n var avgLines = g.select(\".nv-avgLinesWrap\").selectAll(\"line\")\n .data(avgLineData, function(d) { return d.key; });\n\n var getAvgLineY = function(d) {\n //If average lines go off the svg element, clamp them to the svg bounds.\n var yVal = y(average(d));\n if (yVal < 0) return 0;\n if (yVal > availableHeight) return availableHeight;\n return yVal;\n };\n\n avgLines.enter()\n .append('line')\n .style('stroke-width',2)\n .style('stroke-dasharray','10,10')\n .style('stroke',function (d,i) {\n return lines.color()(d,d.seriesIndex);\n })\n .attr('x1',0)\n .attr('x2',availableWidth)\n .attr('y1', getAvgLineY)\n .attr('y2', getAvgLineY);\n\n avgLines\n .style('stroke-opacity',function(d){\n //If average lines go offscreen, make them transparent\n var yVal = y(average(d));\n if (yVal < 0 || yVal > availableHeight) return 0;\n return 1;\n })\n .attr('x1',0)\n .attr('x2',availableWidth)\n .attr('y1', getAvgLineY)\n .attr('y2', getAvgLineY);\n\n avgLines.exit().remove();\n\n //Create index line\n var indexLine = linesWrap.selectAll('.nv-indexLine')\n .data([index]);\n indexLine.enter().append('rect').attr('class', 'nv-indexLine')\n .attr('width', 3)\n .attr('x', -2)\n .attr('fill', 'red')\n .attr('fill-opacity', .5)\n .style(\"pointer-events\",\"all\")\n .call(indexDrag);\n\n indexLine\n .attr('transform', function(d) { return 'translate(' + dx(d.i) + ',0)' })\n .attr('height', availableHeight);\n\n // Setup Axes\n if (showXAxis) {\n xAxis\n .scale(x)\n ._ticks( nv.utils.calcTicksX(availableWidth/70, data) )\n .tickSize(-availableHeight, 0);\n\n g.select('.nv-x.nv-axis')\n .attr('transform', 'translate(0,' + y.range()[0] + ')');\n g.select('.nv-x.nv-axis')\n .call(xAxis);\n }\n\n if (showYAxis) {\n yAxis\n .scale(y)\n ._ticks( nv.utils.calcTicksY(availableHeight/36, data) )\n .tickSize( -availableWidth, 0);\n\n g.select('.nv-y.nv-axis')\n .call(yAxis);\n }\n\n //============================================================\n // Event Handling/Dispatching (in chart's scope)\n //------------------------------------------------------------\n\n function updateZero() {\n indexLine\n .data([index]);\n\n //When dragging the index line, turn off line transitions.\n // Then turn them back on when done dragging.\n var oldDuration = chart.duration();\n chart.duration(0);\n chart.update();\n chart.duration(oldDuration);\n }\n\n g.select('.nv-background rect')\n .on('click', function() {\n index.x = d3.mouse(this)[0];\n index.i = Math.round(dx.invert(index.x));\n\n // update state and send stateChange with new index\n state.index = index.i;\n dispatch.stateChange(state);\n\n updateZero();\n });\n\n lines.dispatch.on('elementClick', function(e) {\n index.i = e.pointIndex;\n index.x = dx(index.i);\n\n // update state and send stateChange with new index\n state.index = index.i;\n dispatch.stateChange(state);\n\n updateZero();\n });\n\n controls.dispatch.on('legendClick', function(d,i) {\n d.disabled = !d.disabled;\n rescaleY = !d.disabled;\n\n state.rescaleY = rescaleY;\n dispatch.stateChange(state);\n chart.update();\n });\n\n legend.dispatch.on('stateChange', function(newState) {\n for (var key in newState)\n state[key] = newState[key];\n dispatch.stateChange(state);\n chart.update();\n });\n\n interactiveLayer.dispatch.on('elementMousemove', function(e) {\n lines.clearHighlights();\n var singlePoint, pointIndex, pointXLocation, allData = [];\n\n data\n .filter(function(series, i) {\n series.seriesIndex = i;\n return !series.disabled;\n })\n .forEach(function(series,i) {\n pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x());\n lines.highlightPoint(i, pointIndex, true);\n var point = series.values[pointIndex];\n if (typeof point === 'undefined') return;\n if (typeof singlePoint === 'undefined') singlePoint = point;\n if (typeof pointXLocation === 'undefined') pointXLocation = chart.xScale()(chart.x()(point,pointIndex));\n allData.push({\n key: series.key,\n value: chart.y()(point, pointIndex),\n color: color(series,series.seriesIndex)\n });\n });\n\n //Highlight the tooltip entry based on which point the mouse is closest to.\n if (allData.length > 2) {\n var yValue = chart.yScale().invert(e.mouseY);\n var domainExtent = Math.abs(chart.yScale().domain()[0] - chart.yScale().domain()[1]);\n var threshold = 0.03 * domainExtent;\n var indexToHighlight = nv.nearestValueIndex(allData.map(function(d){return d.value}),yValue,threshold);\n if (indexToHighlight !== null)\n allData[indexToHighlight].highlight = true;\n }\n\n var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex), pointIndex);\n interactiveLayer.tooltip\n .valueFormatter(function(d,i) {\n return yAxis.tickFormat()(d);\n })\n .data(\n {\n value: xValue,\n series: allData\n }\n )();\n\n interactiveLayer.renderGuideLine(pointXLocation);\n });\n\n interactiveLayer.dispatch.on(\"elementMouseout\",function(e) {\n lines.clearHighlights();\n });\n\n // Update chart from a state object passed to event handler\n dispatch.on('changeState', function(e) {\n if (typeof e.disabled !== 'undefined') {\n data.forEach(function(series,i) {\n series.disabled = e.disabled[i];\n });\n\n state.disabled = e.disabled;\n }\n\n if (typeof e.index !== 'undefined') {\n index.i = e.index;\n index.x = dx(index.i);\n\n state.index = e.index;\n\n indexLine\n .data([index]);\n }\n\n if (typeof e.rescaleY !== 'undefined') {\n rescaleY = e.rescaleY;\n }\n\n chart.update();\n });\n\n });\n\n renderWatch.renderEnd('cumulativeLineChart immediate');\n\n return chart;\n }\n\n //============================================================\n // Event Handling/Dispatching (out of chart's scope)\n //------------------------------------------------------------\n\n lines.dispatch.on('elementMouseover.tooltip', function(evt) {\n var point = {\n x: chart.x()(evt.point),\n y: chart.y()(evt.point),\n color: evt.point.color\n };\n evt.point = point;\n tooltip.data(evt).hidden(false);\n });\n\n lines.dispatch.on('elementMouseout.tooltip', function(evt) {\n tooltip.hidden(true)\n });\n\n //============================================================\n // Functions\n //------------------------------------------------------------\n\n var indexifyYGetter = null;\n /* Normalize the data according to an index point. */\n function indexify(idx, data) {\n if (!indexifyYGetter) indexifyYGetter = lines.y();\n return data.map(function(line, i) {\n if (!line.values) {\n return line;\n }\n var indexValue = line.values[idx];\n if (indexValue == null) {\n return line;\n }\n var v = indexifyYGetter(indexValue, idx);\n\n //TODO: implement check below, and disable series if series loses 100% or more cause divide by 0 issue\n if (v < -.95 && !noErrorCheck) {\n //if a series loses more than 100%, calculations fail.. anything close can cause major distortion (but is mathematically correct till it hits 100)\n\n line.tempDisabled = true;\n return line;\n }\n\n line.tempDisabled = false;\n\n line.values = line.values.map(function(point, pointIndex) {\n point.display = {'y': (indexifyYGetter(point, pointIndex) - v) / (1 + v) };\n return point;\n });\n\n return line;\n })\n }\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n // expose chart's sub-components\n chart.dispatch = dispatch;\n chart.lines = lines;\n chart.legend = legend;\n chart.controls = controls;\n chart.xAxis = xAxis;\n chart.yAxis = yAxis;\n chart.interactiveLayer = interactiveLayer;\n chart.state = state;\n chart.tooltip = tooltip;\n\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n rescaleY: {get: function(){return rescaleY;}, set: function(_){rescaleY=_;}},\n showControls: {get: function(){return showControls;}, set: function(_){showControls=_;}},\n showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},\n average: {get: function(){return average;}, set: function(_){average=_;}},\n defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}},\n noData: {get: function(){return noData;}, set: function(_){noData=_;}},\n showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},\n showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},\n noErrorCheck: {get: function(){return noErrorCheck;}, set: function(_){noErrorCheck=_;}},\n\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n if (_.top !== undefined) {\n margin.top = _.top;\n marginTop = _.top;\n }\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n }},\n color: {get: function(){return color;}, set: function(_){\n color = nv.utils.getColor(_);\n legend.color(color);\n }},\n useInteractiveGuideline: {get: function(){return useInteractiveGuideline;}, set: function(_){\n useInteractiveGuideline = _;\n if (_ === true) {\n chart.interactive(false);\n chart.useVoronoi(false);\n }\n }},\n rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){\n rightAlignYAxis = _;\n yAxis.orient( (_) ? 'right' : 'left');\n }},\n duration: {get: function(){return duration;}, set: function(_){\n duration = _;\n lines.duration(duration);\n xAxis.duration(duration);\n yAxis.duration(duration);\n renderWatch.reset(duration);\n }}\n });\n\n nv.utils.inheritOptions(chart, lines);\n nv.utils.initOptions(chart);\n\n return chart;\n};\n","//TODO: consider deprecating by adding necessary features to multiBar model\nnv.models.discreteBar = function() {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var margin = {top: 0, right: 0, bottom: 0, left: 0}\n , width = 960\n , height = 500\n , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one\n , container\n , x = d3.scale.ordinal()\n , y = d3.scale.linear()\n , getX = function(d) { return d.x }\n , getY = function(d) { return d.y }\n , forceY = [0] // 0 is forced by default.. this makes sense for the majority of bar graphs... user can always do chart.forceY([]) to remove\n , color = nv.utils.defaultColor()\n , showValues = false\n , valueFormat = d3.format(',.2f')\n , xDomain\n , yDomain\n , xRange\n , yRange\n , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd')\n , rectClass = 'discreteBar'\n , duration = 250\n ;\n\n //============================================================\n // Private Variables\n //------------------------------------------------------------\n\n var x0, y0;\n var renderWatch = nv.utils.renderWatch(dispatch, duration);\n\n function chart(selection) {\n renderWatch.reset();\n selection.each(function(data) {\n var availableWidth = width - margin.left - margin.right,\n availableHeight = height - margin.top - margin.bottom;\n\n container = d3.select(this);\n nv.utils.initSVG(container);\n\n //add series index to each data point for reference\n data.forEach(function(series, i) {\n series.values.forEach(function(point) {\n point.series = i;\n });\n });\n\n // Setup Scales\n // remap and flatten the data for use in calculating the scales' domains\n var seriesData = (xDomain && yDomain) ? [] : // if we know xDomain and yDomain, no need to calculate\n data.map(function(d) {\n return d.values.map(function(d,i) {\n return { x: getX(d,i), y: getY(d,i), y0: d.y0 }\n })\n });\n\n x .domain(xDomain || d3.merge(seriesData).map(function(d) { return d.x }))\n .rangeBands(xRange || [0, availableWidth], .1);\n y .domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return d.y }).concat(forceY)));\n\n // If showValues, pad the Y axis range to account for label height\n if (showValues) y.range(yRange || [availableHeight - (y.domain()[0] < 0 ? 12 : 0), y.domain()[1] > 0 ? 12 : 0]);\n else y.range(yRange || [availableHeight, 0]);\n\n //store old scales if they exist\n x0 = x0 || x;\n y0 = y0 || y.copy().range([y(0),y(0)]);\n\n // Setup containers and skeleton of chart\n var wrap = container.selectAll('g.nv-wrap.nv-discretebar').data([data]);\n var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-discretebar');\n var gEnter = wrapEnter.append('g');\n var g = wrap.select('g');\n\n gEnter.append('g').attr('class', 'nv-groups');\n wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');\n\n //TODO: by definition, the discrete bar should not have multiple groups, will modify/remove later\n var groups = wrap.select('.nv-groups').selectAll('.nv-group')\n .data(function(d) { return d }, function(d) { return d.key });\n groups.enter().append('g')\n .style('stroke-opacity', 1e-6)\n .style('fill-opacity', 1e-6);\n groups.exit()\n .watchTransition(renderWatch, 'discreteBar: exit groups')\n .style('stroke-opacity', 1e-6)\n .style('fill-opacity', 1e-6)\n .remove();\n groups\n .attr('class', function(d,i) { return 'nv-group nv-series-' + i })\n .classed('hover', function(d) { return d.hover });\n groups\n .watchTransition(renderWatch, 'discreteBar: groups')\n .style('stroke-opacity', 1)\n .style('fill-opacity', .75);\n\n var bars = groups.selectAll('g.nv-bar')\n .data(function(d) { return d.values });\n bars.exit().remove();\n\n var barsEnter = bars.enter().append('g')\n .attr('transform', function(d,i,j) {\n return 'translate(' + (x(getX(d,i)) + x.rangeBand() * .05 ) + ', ' + y(0) + ')'\n })\n .on('mouseover', function(d,i) { //TODO: figure out why j works above, but not here\n d3.select(this).classed('hover', true);\n dispatch.elementMouseover({\n data: d,\n index: i,\n color: d3.select(this).style(\"fill\")\n });\n })\n .on('mouseout', function(d,i) {\n d3.select(this).classed('hover', false);\n dispatch.elementMouseout({\n data: d,\n index: i,\n color: d3.select(this).style(\"fill\")\n });\n })\n .on('mousemove', function(d,i) {\n dispatch.elementMousemove({\n data: d,\n index: i,\n color: d3.select(this).style(\"fill\")\n });\n })\n .on('click', function(d,i) {\n var element = this;\n dispatch.elementClick({\n data: d,\n index: i,\n color: d3.select(this).style(\"fill\"),\n event: d3.event,\n element: element\n });\n d3.event.stopPropagation();\n })\n .on('dblclick', function(d,i) {\n dispatch.elementDblClick({\n data: d,\n index: i,\n color: d3.select(this).style(\"fill\")\n });\n d3.event.stopPropagation();\n });\n\n barsEnter.append('rect')\n .attr('height', 0)\n .attr('width', x.rangeBand() * .9 / data.length )\n\n if (showValues) {\n barsEnter.append('text')\n .attr('text-anchor', 'middle')\n ;\n\n bars.select('text')\n .text(function(d,i) { return valueFormat(getY(d,i)) })\n .watchTransition(renderWatch, 'discreteBar: bars text')\n .attr('x', x.rangeBand() * .9 / 2)\n .attr('y', function(d,i) { return getY(d,i) < 0 ? y(getY(d,i)) - y(0) + 12 : -4 })\n\n ;\n } else {\n bars.selectAll('text').remove();\n }\n\n bars\n .attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive' })\n .style('fill', function(d,i) { return d.color || color(d,i) })\n .style('stroke', function(d,i) { return d.color || color(d,i) })\n .select('rect')\n .attr('class', rectClass)\n .watchTransition(renderWatch, 'discreteBar: bars rect')\n .attr('width', x.rangeBand() * .9 / data.length);\n bars.watchTransition(renderWatch, 'discreteBar: bars')\n //.delay(function(d,i) { return i * 1200 / data[0].values.length })\n .attr('transform', function(d,i) {\n var left = x(getX(d,i)) + x.rangeBand() * .05,\n top = getY(d,i) < 0 ?\n y(0) :\n y(0) - y(getY(d,i)) < 1 ?\n y(0) - 1 : //make 1 px positive bars show up above y=0\n y(getY(d,i));\n\n return 'translate(' + left + ', ' + top + ')'\n })\n .select('rect')\n .attr('height', function(d,i) {\n return Math.max(Math.abs(y(getY(d,i)) - y(0)), 1)\n });\n\n\n //store old scales for use in transitions on update\n x0 = x.copy();\n y0 = y.copy();\n\n });\n\n renderWatch.renderEnd('discreteBar immediate');\n return chart;\n }\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n chart.dispatch = dispatch;\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n forceY: {get: function(){return forceY;}, set: function(_){forceY=_;}},\n showValues: {get: function(){return showValues;}, set: function(_){showValues=_;}},\n x: {get: function(){return getX;}, set: function(_){getX=_;}},\n y: {get: function(){return getY;}, set: function(_){getY=_;}},\n xScale: {get: function(){return x;}, set: function(_){x=_;}},\n yScale: {get: function(){return y;}, set: function(_){y=_;}},\n xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}},\n yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}},\n xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}},\n yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}},\n valueFormat: {get: function(){return valueFormat;}, set: function(_){valueFormat=_;}},\n id: {get: function(){return id;}, set: function(_){id=_;}},\n rectClass: {get: function(){return rectClass;}, set: function(_){rectClass=_;}},\n\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n margin.top = _.top !== undefined ? _.top : margin.top;\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n }},\n color: {get: function(){return color;}, set: function(_){\n color = nv.utils.getColor(_);\n }},\n duration: {get: function(){return duration;}, set: function(_){\n duration = _;\n renderWatch.reset(duration);\n }}\n });\n\n nv.utils.initOptions(chart);\n\n return chart;\n};\n","\nnv.models.discreteBarChart = function() {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var discretebar = nv.models.discreteBar()\n , xAxis = nv.models.axis()\n , yAxis = nv.models.axis()\n\t, legend = nv.models.legend()\n , tooltip = nv.models.tooltip()\n ;\n\n var margin = {top: 15, right: 10, bottom: 50, left: 60}\n , marginTop = null\n , width = null\n , height = null\n , color = nv.utils.getColor()\n\t, showLegend = false\n , showXAxis = true\n , showYAxis = true\n , rightAlignYAxis = false\n , staggerLabels = false\n , wrapLabels = false\n , rotateLabels = 0\n , x\n , y\n , noData = null\n , dispatch = d3.dispatch('beforeUpdate','renderEnd')\n , duration = 250\n ;\n\n xAxis\n .orient('bottom')\n .showMaxMin(false)\n .tickFormat(function(d) { return d })\n ;\n yAxis\n .orient((rightAlignYAxis) ? 'right' : 'left')\n .tickFormat(d3.format(',.1f'))\n ;\n\n tooltip\n .duration(0)\n .headerEnabled(false)\n .valueFormatter(function(d, i) {\n return yAxis.tickFormat()(d, i);\n })\n .keyFormatter(function(d, i) {\n return xAxis.tickFormat()(d, i);\n });\n\n //============================================================\n // Private Variables\n //------------------------------------------------------------\n\n var renderWatch = nv.utils.renderWatch(dispatch, duration);\n\n function chart(selection) {\n renderWatch.reset();\n renderWatch.models(discretebar);\n if (showXAxis) renderWatch.models(xAxis);\n if (showYAxis) renderWatch.models(yAxis);\n\n selection.each(function(data) {\n var container = d3.select(this),\n that = this;\n nv.utils.initSVG(container);\n var availableWidth = nv.utils.availableWidth(width, container, margin),\n availableHeight = nv.utils.availableHeight(height, container, margin);\n\n chart.update = function() {\n dispatch.beforeUpdate();\n container.transition().duration(duration).call(chart);\n };\n chart.container = this;\n\n // Display No Data message if there's nothing to show.\n if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {\n nv.utils.noData(chart, container);\n return chart;\n } else {\n container.selectAll('.nv-noData').remove();\n }\n\n // Setup Scales\n x = discretebar.xScale();\n y = discretebar.yScale().clamp(true);\n\n // Setup containers and skeleton of chart\n var wrap = container.selectAll('g.nv-wrap.nv-discreteBarWithAxes').data([data]);\n var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-discreteBarWithAxes').append('g');\n var defsEnter = gEnter.append('defs');\n var g = wrap.select('g');\n\n gEnter.append('g').attr('class', 'nv-x nv-axis');\n gEnter.append('g').attr('class', 'nv-y nv-axis')\n .append('g').attr('class', 'nv-zeroLine')\n .append('line');\n\n gEnter.append('g').attr('class', 'nv-barsWrap');\n\t gEnter.append('g').attr('class', 'nv-legendWrap');\n\n g.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');\n\n // Legend\n if (!showLegend) {\n g.select('.nv-legendWrap').selectAll('*').remove();\n } else {\n legend.width(availableWidth);\n\n g.select('.nv-legendWrap')\n .datum(data)\n .call(legend);\n\n if (!marginTop && legend.height() !== margin.top) {\n margin.top = legend.height();\n availableHeight = nv.utils.availableHeight(height, container, margin);\n }\n\n wrap.select('.nv-legendWrap')\n .attr('transform', 'translate(0,' + (-margin.top) +')')\n }\n\n if (rightAlignYAxis) {\n g.select(\".nv-y.nv-axis\")\n .attr(\"transform\", \"translate(\" + availableWidth + \",0)\");\n }\n\n // Main Chart Component(s)\n discretebar\n .width(availableWidth)\n .height(availableHeight);\n\n var barsWrap = g.select('.nv-barsWrap')\n .datum(data.filter(function(d) { return !d.disabled }));\n\n barsWrap.transition().call(discretebar);\n\n\n defsEnter.append('clipPath')\n .attr('id', 'nv-x-label-clip-' + discretebar.id())\n .append('rect');\n\n g.select('#nv-x-label-clip-' + discretebar.id() + ' rect')\n .attr('width', x.rangeBand() * (staggerLabels ? 2 : 1))\n .attr('height', 16)\n .attr('x', -x.rangeBand() / (staggerLabels ? 1 : 2 ));\n\n // Setup Axes\n if (showXAxis) {\n xAxis\n .scale(x)\n ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )\n .tickSize(-availableHeight, 0);\n\n g.select('.nv-x.nv-axis')\n .attr('transform', 'translate(0,' + (y.range()[0] + ((discretebar.showValues() && y.domain()[0] < 0) ? 16 : 0)) + ')');\n g.select('.nv-x.nv-axis').call(xAxis);\n\n var xTicks = g.select('.nv-x.nv-axis').selectAll('g');\n if (staggerLabels) {\n xTicks\n .selectAll('text')\n .attr('transform', function(d,i,j) { return 'translate(0,' + (j % 2 == 0 ? '5' : '17') + ')' })\n }\n\n if (rotateLabels) {\n xTicks\n .selectAll('.tick text')\n .attr('transform', 'rotate(' + rotateLabels + ' 0,0)')\n .style('text-anchor', rotateLabels > 0 ? 'start' : 'end');\n }\n\n if (wrapLabels) {\n g.selectAll('.tick text')\n .call(nv.utils.wrapTicks, chart.xAxis.rangeBand())\n }\n }\n\n if (showYAxis) {\n yAxis\n .scale(y)\n ._ticks( nv.utils.calcTicksY(availableHeight/36, data) )\n .tickSize( -availableWidth, 0);\n\n g.select('.nv-y.nv-axis').call(yAxis);\n }\n\n // Zero line\n g.select(\".nv-zeroLine line\")\n .attr(\"x1\",0)\n .attr(\"x2\",(rightAlignYAxis) ? -availableWidth : availableWidth)\n .attr(\"y1\", y(0))\n .attr(\"y2\", y(0))\n ;\n });\n\n renderWatch.renderEnd('discreteBar chart immediate');\n return chart;\n }\n\n //============================================================\n // Event Handling/Dispatching (out of chart's scope)\n //------------------------------------------------------------\n\n discretebar.dispatch.on('elementMouseover.tooltip', function(evt) {\n evt['series'] = {\n key: chart.x()(evt.data),\n value: chart.y()(evt.data),\n color: evt.color\n };\n tooltip.data(evt).hidden(false);\n });\n\n discretebar.dispatch.on('elementMouseout.tooltip', function(evt) {\n tooltip.hidden(true);\n });\n\n discretebar.dispatch.on('elementMousemove.tooltip', function(evt) {\n tooltip();\n });\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n chart.dispatch = dispatch;\n chart.discretebar = discretebar;\n chart.legend = legend;\n chart.xAxis = xAxis;\n chart.yAxis = yAxis;\n chart.tooltip = tooltip;\n\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n\tshowLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},\n staggerLabels: {get: function(){return staggerLabels;}, set: function(_){staggerLabels=_;}},\n rotateLabels: {get: function(){return rotateLabels;}, set: function(_){rotateLabels=_;}},\n wrapLabels: {get: function(){return wrapLabels;}, set: function(_){wrapLabels=!!_;}},\n showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},\n showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},\n noData: {get: function(){return noData;}, set: function(_){noData=_;}},\n\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n if (_.top !== undefined) {\n margin.top = _.top;\n marginTop = _.top;\n }\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n }},\n duration: {get: function(){return duration;}, set: function(_){\n duration = _;\n renderWatch.reset(duration);\n discretebar.duration(duration);\n xAxis.duration(duration);\n yAxis.duration(duration);\n }},\n color: {get: function(){return color;}, set: function(_){\n color = nv.utils.getColor(_);\n discretebar.color(color);\n\t legend.color(color);\n }},\n rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){\n rightAlignYAxis = _;\n yAxis.orient( (_) ? 'right' : 'left');\n }}\n });\n\n nv.utils.inheritOptions(chart, discretebar);\n nv.utils.initOptions(chart);\n\n return chart;\n}\n","\nnv.models.distribution = function() {\n \"use strict\";\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var margin = {top: 0, right: 0, bottom: 0, left: 0}\n , width = 400 //technically width or height depending on x or y....\n , size = 8\n , axis = 'x' // 'x' or 'y'... horizontal or vertical\n , getData = function(d) { return d[axis] } // defaults d.x or d.y\n , color = nv.utils.defaultColor()\n , scale = d3.scale.linear()\n , domain\n , duration = 250\n , dispatch = d3.dispatch('renderEnd')\n ;\n\n //============================================================\n\n\n //============================================================\n // Private Variables\n //------------------------------------------------------------\n\n var scale0;\n var renderWatch = nv.utils.renderWatch(dispatch, duration);\n\n //============================================================\n\n\n function chart(selection) {\n renderWatch.reset();\n selection.each(function(data) {\n var availableLength = width - (axis === 'x' ? margin.left + margin.right : margin.top + margin.bottom),\n naxis = axis == 'x' ? 'y' : 'x',\n container = d3.select(this);\n nv.utils.initSVG(container);\n\n //------------------------------------------------------------\n // Setup Scales\n\n scale0 = scale0 || scale;\n\n //------------------------------------------------------------\n\n\n //------------------------------------------------------------\n // Setup containers and skeleton of chart\n\n var wrap = container.selectAll('g.nv-distribution').data([data]);\n var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-distribution');\n var gEnter = wrapEnter.append('g');\n var g = wrap.select('g');\n\n wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')\n\n //------------------------------------------------------------\n\n\n var distWrap = g.selectAll('g.nv-dist')\n .data(function(d) { return d }, function(d) { return d.key });\n\n distWrap.enter().append('g');\n distWrap\n .attr('class', function(d,i) { return 'nv-dist nv-series-' + i })\n .style('stroke', function(d,i) { return color(d, i) });\n\n var dist = distWrap.selectAll('line.nv-dist' + axis)\n .data(function(d) { return d.values })\n dist.enter().append('line')\n .attr(axis + '1', function(d,i) { return scale0(getData(d,i)) })\n .attr(axis + '2', function(d,i) { return scale0(getData(d,i)) })\n renderWatch.transition(distWrap.exit().selectAll('line.nv-dist' + axis), 'dist exit')\n // .transition()\n .attr(axis + '1', function(d,i) { return scale(getData(d,i)) })\n .attr(axis + '2', function(d,i) { return scale(getData(d,i)) })\n .style('stroke-opacity', 0)\n .remove();\n dist\n .attr('class', function(d,i) { return 'nv-dist' + axis + ' nv-dist' + axis + '-' + i })\n .attr(naxis + '1', 0)\n .attr(naxis + '2', size);\n renderWatch.transition(dist, 'dist')\n // .transition()\n .attr(axis + '1', function(d,i) { return scale(getData(d,i)) })\n .attr(axis + '2', function(d,i) { return scale(getData(d,i)) })\n\n\n scale0 = scale.copy();\n\n });\n renderWatch.renderEnd('distribution immediate');\n return chart;\n }\n\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n chart.options = nv.utils.optionsFunc.bind(chart);\n chart.dispatch = dispatch;\n\n chart.margin = function(_) {\n if (!arguments.length) return margin;\n margin.top = typeof _.top != 'undefined' ? _.top : margin.top;\n margin.right = typeof _.right != 'undefined' ? _.right : margin.right;\n margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;\n margin.left = typeof _.left != 'undefined' ? _.left : margin.left;\n return chart;\n };\n\n chart.width = function(_) {\n if (!arguments.length) return width;\n width = _;\n return chart;\n };\n\n chart.axis = function(_) {\n if (!arguments.length) return axis;\n axis = _;\n return chart;\n };\n\n chart.size = function(_) {\n if (!arguments.length) return size;\n size = _;\n return chart;\n };\n\n chart.getData = function(_) {\n if (!arguments.length) return getData;\n getData = d3.functor(_);\n return chart;\n };\n\n chart.scale = function(_) {\n if (!arguments.length) return scale;\n scale = _;\n return chart;\n };\n\n chart.color = function(_) {\n if (!arguments.length) return color;\n color = nv.utils.getColor(_);\n return chart;\n };\n\n chart.duration = function(_) {\n if (!arguments.length) return duration;\n duration = _;\n renderWatch.reset(duration);\n return chart;\n };\n //============================================================\n\n\n return chart;\n}\n","nv.models.focus = function(content) {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var content = content || nv.models.line()\n , xAxis = nv.models.axis()\n , yAxis = nv.models.axis()\n , brush = d3.svg.brush()\n ;\n\n var margin = {top: 10, right: 0, bottom: 30, left: 0}\n , color = nv.utils.defaultColor()\n , width = null\n , height = 70\n , showXAxis = true\n , showYAxis = false\n , rightAlignYAxis = false\n , ticks = null\n , x\n , y\n , brushExtent = null\n , duration = 250\n , dispatch = d3.dispatch('brush', 'onBrush', 'renderEnd')\n , syncBrushing = true\n ;\n\n content.interactive(false);\n content.pointActive(function(d) { return false; });\n\n //============================================================\n // Private Variables\n //------------------------------------------------------------\n\n var renderWatch = nv.utils.renderWatch(dispatch, duration);\n\n function chart(selection) {\n renderWatch.reset();\n renderWatch.models(content);\n if (showXAxis) renderWatch.models(xAxis);\n if (showYAxis) renderWatch.models(yAxis);\n\n selection.each(function(data) {\n var container = d3.select(this);\n nv.utils.initSVG(container);\n var availableWidth = nv.utils.availableWidth(width, container, margin),\n availableHeight = height - margin.top - margin.bottom;\n\n chart.update = function() { \n if( duration === 0 ) {\n container.call( chart );\n } else {\n container.transition().duration(duration).call(chart);\n }\n };\n chart.container = this;\n\n // Setup Scales\n x = content.xScale();\n y = content.yScale();\n\n // Setup containers and skeleton of chart\n var wrap = container.selectAll('g.nv-focus').data([data]);\n var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-focus').append('g');\n var g = wrap.select('g');\n\n wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');\n\n gEnter.append('g').attr('class', 'nv-background').append('rect');\n gEnter.append('g').attr('class', 'nv-x nv-axis');\n gEnter.append('g').attr('class', 'nv-y nv-axis');\n gEnter.append('g').attr('class', 'nv-contentWrap');\n gEnter.append('g').attr('class', 'nv-brushBackground');\n gEnter.append('g').attr('class', 'nv-x nv-brush');\n\n if (rightAlignYAxis) {\n g.select(\".nv-y.nv-axis\")\n .attr(\"transform\", \"translate(\" + availableWidth + \",0)\");\n }\n\n g.select('.nv-background rect')\n .attr('width', availableWidth)\n .attr('height', availableHeight);\n \n content\n .width(availableWidth)\n .height(availableHeight)\n .color(data.map(function(d,i) {\n return d.color || color(d, i);\n }).filter(function(d,i) { return !data[i].disabled; }));\n\n var contentWrap = g.select('.nv-contentWrap')\n .datum(data.filter(function(d) { return !d.disabled; }));\n\n d3.transition(contentWrap).call(content);\n \n // Setup Brush\n brush\n .x(x)\n .on('brush', function() {\n onBrush(syncBrushing);\n });\n\n brush.on('brushend', function () {\n if (!syncBrushing) {\n dispatch.onBrush(brush.empty() ? x.domain() : brush.extent());\n }\n });\n\n if (brushExtent) brush.extent(brushExtent);\n\n var brushBG = g.select('.nv-brushBackground').selectAll('g')\n .data([brushExtent || brush.extent()]);\n \n var brushBGenter = brushBG.enter()\n .append('g');\n\n brushBGenter.append('rect')\n .attr('class', 'left')\n .attr('x', 0)\n .attr('y', 0)\n .attr('height', availableHeight);\n\n brushBGenter.append('rect')\n .attr('class', 'right')\n .attr('x', 0)\n .attr('y', 0)\n .attr('height', availableHeight);\n\n var gBrush = g.select('.nv-x.nv-brush')\n .call(brush);\n gBrush.selectAll('rect')\n .attr('height', availableHeight);\n gBrush.selectAll('.resize').append('path').attr('d', resizePath);\n\n onBrush(true);\n\n g.select('.nv-background rect')\n .attr('width', availableWidth)\n .attr('height', availableHeight);\n\n if (showXAxis) {\n xAxis.scale(x)\n ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )\n .tickSize(-availableHeight, 0);\n \n g.select('.nv-x.nv-axis')\n .attr('transform', 'translate(0,' + y.range()[0] + ')');\n d3.transition(g.select('.nv-x.nv-axis'))\n .call(xAxis);\n }\n\n if (showYAxis) {\n yAxis\n .scale(y)\n ._ticks( nv.utils.calcTicksY(availableHeight/36, data) )\n .tickSize( -availableWidth, 0);\n\n d3.transition(g.select('.nv-y.nv-axis'))\n .call(yAxis);\n }\n \n g.select('.nv-x.nv-axis')\n .attr('transform', 'translate(0,' + y.range()[0] + ')');\n\n //============================================================\n // Event Handling/Dispatching (in chart's scope)\n //------------------------------------------------------------\n\n //============================================================\n // Functions\n //------------------------------------------------------------\n \n // Taken from crossfilter (http://square.github.com/crossfilter/)\n function resizePath(d) {\n var e = +(d == 'e'),\n x = e ? 1 : -1,\n y = availableHeight / 3;\n return 'M' + (0.5 * x) + ',' + y\n + 'A6,6 0 0 ' + e + ' ' + (6.5 * x) + ',' + (y + 6)\n + 'V' + (2 * y - 6)\n + 'A6,6 0 0 ' + e + ' ' + (0.5 * x) + ',' + (2 * y)\n + 'Z'\n + 'M' + (2.5 * x) + ',' + (y + 8)\n + 'V' + (2 * y - 8)\n + 'M' + (4.5 * x) + ',' + (y + 8)\n + 'V' + (2 * y - 8);\n }\n \n \n function updateBrushBG() {\n if (!brush.empty()) brush.extent(brushExtent);\n brushBG\n .data([brush.empty() ? x.domain() : brushExtent])\n .each(function(d,i) {\n var leftWidth = x(d[0]) - x.range()[0],\n rightWidth = availableWidth - x(d[1]);\n d3.select(this).select('.left')\n .attr('width', leftWidth < 0 ? 0 : leftWidth);\n \n d3.select(this).select('.right')\n .attr('x', x(d[1]))\n .attr('width', rightWidth < 0 ? 0 : rightWidth);\n });\n }\n\n\n function onBrush(shouldDispatch) {\n brushExtent = brush.empty() ? null : brush.extent();\n var extent = brush.empty() ? x.domain() : brush.extent();\n dispatch.brush({extent: extent, brush: brush});\n updateBrushBG();\n if (shouldDispatch) {\n dispatch.onBrush(extent);\n }\n }\n });\n\n renderWatch.renderEnd('focus immediate');\n return chart;\n }\n\n\n //============================================================\n // Event Handling/Dispatching (out of chart's scope)\n //------------------------------------------------------------\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n // expose chart's sub-components\n chart.dispatch = dispatch;\n chart.content = content;\n chart.brush = brush;\n chart.xAxis = xAxis;\n chart.yAxis = yAxis;\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},\n showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},\n brushExtent: {get: function(){return brushExtent;}, set: function(_){brushExtent=_;}},\n syncBrushing: {get: function(){return syncBrushing;}, set: function(_){syncBrushing=_;}},\n\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n margin.top = _.top !== undefined ? _.top : margin.top;\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n }},\n duration: {get: function(){return duration;}, set: function(_){\n duration = _;\n renderWatch.reset(duration);\n content.duration(duration);\n xAxis.duration(duration);\n yAxis.duration(duration);\n }},\n color: {get: function(){return color;}, set: function(_){\n color = nv.utils.getColor(_);\n content.color(color);\n }},\n interpolate: {get: function(){return content.interpolate();}, set: function(_){\n content.interpolate(_);\n }},\n xTickFormat: {get: function(){return xAxis.tickFormat();}, set: function(_){\n xAxis.tickFormat(_);\n }},\n yTickFormat: {get: function(){return yAxis.tickFormat();}, set: function(_){\n yAxis.tickFormat(_);\n }},\n x: {get: function(){return content.x();}, set: function(_){\n content.x(_);\n }},\n y: {get: function(){return content.y();}, set: function(_){\n content.y(_);\n }},\n rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){\n rightAlignYAxis = _;\n yAxis.orient( rightAlignYAxis ? 'right' : 'left');\n }}\n });\n\n nv.utils.inheritOptions(chart, content);\n nv.utils.initOptions(chart);\n\n return chart;\n};\n","nv.models.forceDirectedGraph = function() {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n var margin = {top: 2, right: 0, bottom: 2, left: 0}\n , width = 400\n , height = 32\n , container = null\n , dispatch = d3.dispatch('renderEnd')\n , color = nv.utils.getColor(['#000'])\n , tooltip = nv.models.tooltip()\n , noData = null\n // Force directed graph specific parameters [default values]\n , linkStrength = 0.1\n , friction = 0.9\n , linkDist = 30\n , charge = -120\n , gravity = 0.1\n , theta = 0.8\n , alpha = 0.1\n , radius = 5\n // These functions allow to add extra attributes to ndes and links\n ,nodeExtras = function(nodes) { /* Do nothing */ }\n ,linkExtras = function(links) { /* Do nothing */ }\n ;\n\n\n //============================================================\n // Private Variables\n //------------------------------------------------------------\n\n var renderWatch = nv.utils.renderWatch(dispatch);\n\n function chart(selection) {\n renderWatch.reset();\n\n selection.each(function(data) {\n container = d3.select(this);\n nv.utils.initSVG(container);\n\n var availableWidth = nv.utils.availableWidth(width, container, margin),\n availableHeight = nv.utils.availableHeight(height, container, margin);\n\n container\n .attr(\"width\", availableWidth)\n .attr(\"height\", availableHeight);\n\n // Display No Data message if there's nothing to show.\n if (!data || !data.links || !data.nodes) {\n nv.utils.noData(chart, container)\n return chart;\n } else {\n container.selectAll('.nv-noData').remove();\n }\n container.selectAll('*').remove();\n\n // Collect names of all fields in the nodes\n var nodeFieldSet = new Set();\n data.nodes.forEach(function(node) {\n var keys = Object.keys(node);\n keys.forEach(function(key) {\n nodeFieldSet.add(key);\n });\n });\n\n var force = d3.layout.force()\n .nodes(data.nodes)\n .links(data.links)\n .size([availableWidth, availableHeight])\n .linkStrength(linkStrength)\n .friction(friction)\n .linkDistance(linkDist)\n .charge(charge)\n .gravity(gravity)\n .theta(theta)\n .alpha(alpha)\n .start();\n\n var link = container.selectAll(\".link\")\n .data(data.links)\n .enter().append(\"line\")\n .attr(\"class\", \"nv-force-link\")\n .style(\"stroke-width\", function(d) { return Math.sqrt(d.value); });\n\n var node = container.selectAll(\".node\")\n .data(data.nodes)\n .enter()\n .append(\"g\")\n .attr(\"class\", \"nv-force-node\")\n .call(force.drag);\n\n node\n .append(\"circle\")\n .attr(\"r\", radius)\n .style(\"fill\", function(d) { return color(d) } )\n .on(\"mouseover\", function(evt) {\n container.select('.nv-series-' + evt.seriesIndex + ' .nv-distx-' + evt.pointIndex)\n .attr('y1', evt.py);\n container.select('.nv-series-' + evt.seriesIndex + ' .nv-disty-' + evt.pointIndex)\n .attr('x2', evt.px);\n\n // Add 'series' object to\n var nodeColor = color(evt);\n evt.series = [];\n nodeFieldSet.forEach(function(field) {\n evt.series.push({\n color: nodeColor,\n key: field,\n value: evt[field]\n });\n });\n tooltip.data(evt).hidden(false);\n })\n .on(\"mouseout\", function(d) {\n tooltip.hidden(true);\n });\n\n tooltip.headerFormatter(function(d) {return \"Node\";});\n\n // Apply extra attributes to nodes and links (if any)\n linkExtras(link);\n nodeExtras(node);\n\n force.on(\"tick\", function() {\n link.attr(\"x1\", function(d) { return d.source.x; })\n .attr(\"y1\", function(d) { return d.source.y; })\n .attr(\"x2\", function(d) { return d.target.x; })\n .attr(\"y2\", function(d) { return d.target.y; });\n\n node.attr(\"transform\", function(d) {\n return \"translate(\" + d.x + \", \" + d.y + \")\";\n });\n });\n });\n\n return chart;\n }\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n\n // Force directed graph specific parameters\n linkStrength:{get: function(){return linkStrength;}, set: function(_){linkStrength=_;}},\n friction: {get: function(){return friction;}, set: function(_){friction=_;}},\n linkDist: {get: function(){return linkDist;}, set: function(_){linkDist=_;}},\n charge: {get: function(){return charge;}, set: function(_){charge=_;}},\n gravity: {get: function(){return gravity;}, set: function(_){gravity=_;}},\n theta: {get: function(){return theta;}, set: function(_){theta=_;}},\n alpha: {get: function(){return alpha;}, set: function(_){alpha=_;}},\n radius: {get: function(){return radius;}, set: function(_){radius=_;}},\n\n //functor options\n x: {get: function(){return getX;}, set: function(_){getX=d3.functor(_);}},\n y: {get: function(){return getY;}, set: function(_){getY=d3.functor(_);}},\n\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n margin.top = _.top !== undefined ? _.top : margin.top;\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n }},\n color: {get: function(){return color;}, set: function(_){\n color = nv.utils.getColor(_);\n }},\n noData: {get: function(){return noData;}, set: function(_){noData=_;}},\n nodeExtras: {get: function(){return nodeExtras;}, set: function(_){\n nodeExtras = _;\n }},\n linkExtras: {get: function(){return linkExtras;}, set: function(_){\n linkExtras = _;\n }}\n });\n\n chart.dispatch = dispatch;\n chart.tooltip = tooltip;\n nv.utils.initOptions(chart);\n return chart;\n};\n","nv.models.furiousLegend = function() {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var margin = {top: 5, right: 0, bottom: 5, left: 0}\n , width = 400\n , height = 20\n , getKey = function(d) { return d.key }\n , keyFormatter = function (d) { return d }\n , color = nv.utils.getColor()\n , maxKeyLength = 20 //default value for key lengths\n , align = true\n , padding = 28 //define how much space between legend items. - recommend 32 for furious version\n , rightAlign = true\n , updateState = true //If true, legend will update data.disabled and trigger a 'stateChange' dispatch.\n , radioButtonMode = false //If true, clicking legend items will cause it to behave like a radio button. (only one can be selected at a time)\n , expanded = false\n , dispatch = d3.dispatch('legendClick', 'legendDblclick', 'legendMouseover', 'legendMouseout', 'stateChange')\n , vers = 'classic' //Options are \"classic\" and \"furious\"\n ;\n\n function chart(selection) {\n selection.each(function(data) {\n var availableWidth = width - margin.left - margin.right,\n container = d3.select(this);\n nv.utils.initSVG(container);\n\n // Setup containers and skeleton of chart\n var wrap = container.selectAll('g.nv-legend').data([data]);\n var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-legend').append('g');\n var g = wrap.select('g');\n\n wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');\n\n var series = g.selectAll('.nv-series')\n .data(function(d) {\n if(vers != 'furious') return d;\n\n return d.filter(function(n) {\n return expanded ? true : !n.disengaged;\n });\n });\n var seriesEnter = series.enter().append('g').attr('class', 'nv-series')\n\n var seriesShape;\n\n if(vers == 'classic') {\n seriesEnter.append('circle')\n .style('stroke-width', 2)\n .attr('class','nv-legend-symbol')\n .attr('r', 5);\n\n seriesShape = series.select('circle');\n } else if (vers == 'furious') {\n seriesEnter.append('rect')\n .style('stroke-width', 2)\n .attr('class','nv-legend-symbol')\n .attr('rx', 3)\n .attr('ry', 3);\n\n seriesShape = series.select('rect');\n\n seriesEnter.append('g')\n .attr('class', 'nv-check-box')\n .property('innerHTML','')\n .attr('transform', 'translate(-10,-8)scale(0.5)');\n\n var seriesCheckbox = series.select('.nv-check-box');\n\n seriesCheckbox.each(function(d,i) {\n d3.select(this).selectAll('path')\n .attr('stroke', setTextColor(d,i));\n });\n }\n\n seriesEnter.append('text')\n .attr('text-anchor', 'start')\n .attr('class','nv-legend-text')\n .attr('dy', '.32em')\n .attr('dx', '8');\n\n var seriesText = series.select('text.nv-legend-text');\n\n series\n .on('mouseover', function(d,i) {\n dispatch.legendMouseover(d,i); //TODO: Make consistent with other event objects\n })\n .on('mouseout', function(d,i) {\n dispatch.legendMouseout(d,i);\n })\n .on('click', function(d,i) {\n dispatch.legendClick(d,i);\n // make sure we re-get data in case it was modified\n var data = series.data();\n if (updateState) {\n if(vers =='classic') {\n if (radioButtonMode) {\n //Radio button mode: set every series to disabled,\n // and enable the clicked series.\n data.forEach(function(series) { series.disabled = true});\n d.disabled = false;\n }\n else {\n d.disabled = !d.disabled;\n if (data.every(function(series) { return series.disabled})) {\n //the default behavior of NVD3 legends is, if every single series\n // is disabled, turn all series' back on.\n data.forEach(function(series) { series.disabled = false});\n }\n }\n } else if(vers == 'furious') {\n if(expanded) {\n d.disengaged = !d.disengaged;\n d.userDisabled = d.userDisabled == undefined ? !!d.disabled : d.userDisabled;\n d.disabled = d.disengaged || d.userDisabled;\n } else if (!expanded) {\n d.disabled = !d.disabled;\n d.userDisabled = d.disabled;\n var engaged = data.filter(function(d) { return !d.disengaged; });\n if (engaged.every(function(series) { return series.userDisabled })) {\n //the default behavior of NVD3 legends is, if every single series\n // is disabled, turn all series' back on.\n data.forEach(function(series) {\n series.disabled = series.userDisabled = false;\n });\n }\n }\n }\n dispatch.stateChange({\n disabled: data.map(function(d) { return !!d.disabled }),\n disengaged: data.map(function(d) { return !!d.disengaged })\n });\n\n }\n })\n .on('dblclick', function(d,i) {\n if(vers == 'furious' && expanded) return;\n dispatch.legendDblclick(d,i);\n if (updateState) {\n // make sure we re-get data in case it was modified\n var data = series.data();\n //the default behavior of NVD3 legends, when double clicking one,\n // is to set all other series' to false, and make the double clicked series enabled.\n data.forEach(function(series) {\n series.disabled = true;\n if(vers == 'furious') series.userDisabled = series.disabled;\n });\n d.disabled = false;\n if(vers == 'furious') d.userDisabled = d.disabled;\n dispatch.stateChange({\n disabled: data.map(function(d) { return !!d.disabled })\n });\n }\n });\n\n series.classed('nv-disabled', function(d) { return d.userDisabled });\n series.exit().remove();\n\n seriesText\n .attr('fill', setTextColor)\n .text(function (d) { return keyFormatter(getKey(d)) });\n\n //TODO: implement fixed-width and max-width options (max-width is especially useful with the align option)\n // NEW ALIGNING CODE, TODO: clean up\n\n var versPadding;\n switch(vers) {\n case 'furious' :\n versPadding = 23;\n break;\n case 'classic' :\n versPadding = 20;\n }\n\n if (align) {\n\n var seriesWidths = [];\n series.each(function(d,i) {\n var legendText;\n if (keyFormatter(getKey(d)) && keyFormatter(getKey(d)).length > maxKeyLength) {\n var trimmedKey = keyFormatter(getKey(d)).substring(0, maxKeyLength);\n legendText = d3.select(this).select('text').text(trimmedKey + \"...\");\n d3.select(this).append(\"svg:title\").text(keyFormatter(getKey(d)));\n } else {\n legendText = d3.select(this).select('text');\n }\n var nodeTextLength;\n try {\n nodeTextLength = legendText.node().getComputedTextLength();\n // If the legendText is display:none'd (nodeTextLength == 0), simulate an error so we approximate, instead\n if(nodeTextLength <= 0) throw Error();\n }\n catch(e) {\n nodeTextLength = nv.utils.calcApproxTextWidth(legendText);\n }\n\n seriesWidths.push(nodeTextLength + padding);\n });\n\n var seriesPerRow = 0;\n var legendWidth = 0;\n var columnWidths = [];\n\n while ( legendWidth < availableWidth && seriesPerRow < seriesWidths.length) {\n columnWidths[seriesPerRow] = seriesWidths[seriesPerRow];\n legendWidth += seriesWidths[seriesPerRow++];\n }\n if (seriesPerRow === 0) seriesPerRow = 1; //minimum of one series per row\n\n while ( legendWidth > availableWidth && seriesPerRow > 1 ) {\n columnWidths = [];\n seriesPerRow--;\n\n for (var k = 0; k < seriesWidths.length; k++) {\n if (seriesWidths[k] > (columnWidths[k % seriesPerRow] || 0) )\n columnWidths[k % seriesPerRow] = seriesWidths[k];\n }\n\n legendWidth = columnWidths.reduce(function(prev, cur, index, array) {\n return prev + cur;\n });\n }\n\n var xPositions = [];\n for (var i = 0, curX = 0; i < seriesPerRow; i++) {\n xPositions[i] = curX;\n curX += columnWidths[i];\n }\n\n series\n .attr('transform', function(d, i) {\n return 'translate(' + xPositions[i % seriesPerRow] + ',' + (5 + Math.floor(i / seriesPerRow) * versPadding) + ')';\n });\n\n //position legend as far right as possible within the total width\n if (rightAlign) {\n g.attr('transform', 'translate(' + (width - margin.right - legendWidth) + ',' + margin.top + ')');\n }\n else {\n g.attr('transform', 'translate(0' + ',' + margin.top + ')');\n }\n\n height = margin.top + margin.bottom + (Math.ceil(seriesWidths.length / seriesPerRow) * versPadding);\n\n } else {\n\n var ypos = 5,\n newxpos = 5,\n maxwidth = 0,\n xpos;\n series\n .attr('transform', function(d, i) {\n var length = d3.select(this).select('text').node().getComputedTextLength() + padding;\n xpos = newxpos;\n\n if (width < margin.left + margin.right + xpos + length) {\n newxpos = xpos = 5;\n ypos += versPadding;\n }\n\n newxpos += length;\n if (newxpos > maxwidth) maxwidth = newxpos;\n\n return 'translate(' + xpos + ',' + ypos + ')';\n });\n\n //position legend as far right as possible within the total width\n g.attr('transform', 'translate(' + (width - margin.right - maxwidth) + ',' + margin.top + ')');\n\n height = margin.top + margin.bottom + ypos + 15;\n }\n\n if(vers == 'furious') {\n // Size rectangles after text is placed\n seriesShape\n .attr('width', function(d,i) {\n return seriesText[0][i].getComputedTextLength() + 27;\n })\n .attr('height', 18)\n .attr('y', -9)\n .attr('x', -15)\n }\n\n seriesShape\n .style('fill', setBGColor)\n .style('stroke', function(d,i) { return d.color || color(d, i) });\n });\n\n function setTextColor(d,i) {\n if(vers != 'furious') return '#000';\n if(expanded) {\n return d.disengaged ? color(d,i) : '#fff';\n } else if (!expanded) {\n return !!d.disabled ? color(d,i) : '#fff';\n }\n }\n\n function setBGColor(d,i) {\n if(expanded && vers == 'furious') {\n return d.disengaged ? '#fff' : color(d,i);\n } else {\n return !!d.disabled ? '#fff' : color(d,i);\n }\n }\n\n return chart;\n }\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n chart.dispatch = dispatch;\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n key: {get: function(){return getKey;}, set: function(_){getKey=_;}},\n keyFormatter: {get: function(){return keyFormatter;}, set: function(_){keyFormatter=_;}},\n align: {get: function(){return align;}, set: function(_){align=_;}},\n rightAlign: {get: function(){return rightAlign;}, set: function(_){rightAlign=_;}},\n maxKeyLength: {get: function(){return maxKeyLength;}, set: function(_){maxKeyLength=_;}},\n padding: {get: function(){return padding;}, set: function(_){padding=_;}},\n updateState: {get: function(){return updateState;}, set: function(_){updateState=_;}},\n radioButtonMode:{get: function(){return radioButtonMode;}, set: function(_){radioButtonMode=_;}},\n expanded: {get: function(){return expanded;}, set: function(_){expanded=_;}},\n vers: {get: function(){return vers;}, set: function(_){vers=_;}},\n\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n margin.top = _.top !== undefined ? _.top : margin.top;\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n }},\n color: {get: function(){return color;}, set: function(_){\n color = nv.utils.getColor(_);\n }}\n });\n\n nv.utils.initOptions(chart);\n\n return chart;\n};\n","//TODO: consider deprecating and using multibar with single series for this\nnv.models.historicalBar = function() {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var margin = {top: 0, right: 0, bottom: 0, left: 0}\n , width = null\n , height = null\n , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one\n , container = null\n , x = d3.scale.linear()\n , y = d3.scale.linear()\n , getX = function(d) { return d.x }\n , getY = function(d) { return d.y }\n , forceX = []\n , forceY = [0]\n , padData = false\n , clipEdge = true\n , color = nv.utils.defaultColor()\n , xDomain\n , yDomain\n , xRange\n , yRange\n , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd')\n , interactive = true\n ;\n\n var renderWatch = nv.utils.renderWatch(dispatch, 0);\n\n function chart(selection) {\n selection.each(function(data) {\n renderWatch.reset();\n\n container = d3.select(this);\n var availableWidth = nv.utils.availableWidth(width, container, margin),\n availableHeight = nv.utils.availableHeight(height, container, margin);\n\n nv.utils.initSVG(container);\n\n // Setup Scales\n x.domain(xDomain || d3.extent(data[0].values.map(getX).concat(forceX) ));\n\n if (padData)\n x.range(xRange || [availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5) / data[0].values.length ]);\n else\n x.range(xRange || [0, availableWidth]);\n\n y.domain(yDomain || d3.extent(data[0].values.map(getY).concat(forceY) ))\n .range(yRange || [availableHeight, 0]);\n\n // If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point\n if (x.domain()[0] === x.domain()[1])\n x.domain()[0] ?\n x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01])\n : x.domain([-1,1]);\n\n if (y.domain()[0] === y.domain()[1])\n y.domain()[0] ?\n y.domain([y.domain()[0] + y.domain()[0] * 0.01, y.domain()[1] - y.domain()[1] * 0.01])\n : y.domain([-1,1]);\n\n // Setup containers and skeleton of chart\n var wrap = container.selectAll('g.nv-wrap.nv-historicalBar-' + id).data([data[0].values]);\n var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-historicalBar-' + id);\n var defsEnter = wrapEnter.append('defs');\n var gEnter = wrapEnter.append('g');\n var g = wrap.select('g');\n\n gEnter.append('g').attr('class', 'nv-bars');\n wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');\n\n container\n .on('click', function(d,i) {\n dispatch.chartClick({\n data: d,\n index: i,\n pos: d3.event,\n id: id\n });\n });\n\n defsEnter.append('clipPath')\n .attr('id', 'nv-chart-clip-path-' + id)\n .append('rect');\n\n wrap.select('#nv-chart-clip-path-' + id + ' rect')\n .attr('width', availableWidth)\n .attr('height', availableHeight);\n\n g.attr('clip-path', clipEdge ? 'url(#nv-chart-clip-path-' + id + ')' : '');\n\n var bars = wrap.select('.nv-bars').selectAll('.nv-bar')\n .data(function(d) { return d }, function(d,i) {return getX(d,i)});\n bars.exit().remove();\n\n bars.enter().append('rect')\n .attr('x', 0 )\n .attr('y', function(d,i) { return nv.utils.NaNtoZero(y(Math.max(0, getY(d,i)))) })\n .attr('height', function(d,i) { return nv.utils.NaNtoZero(Math.abs(y(getY(d,i)) - y(0))) })\n .attr('transform', function(d,i) { return 'translate(' + (x(getX(d,i)) - availableWidth / data[0].values.length * .45) + ',0)'; })\n .on('mouseover', function(d,i) {\n if (!interactive) return;\n d3.select(this).classed('hover', true);\n dispatch.elementMouseover({\n data: d,\n index: i,\n color: d3.select(this).style(\"fill\")\n });\n\n })\n .on('mouseout', function(d,i) {\n if (!interactive) return;\n d3.select(this).classed('hover', false);\n dispatch.elementMouseout({\n data: d,\n index: i,\n color: d3.select(this).style(\"fill\")\n });\n })\n .on('mousemove', function(d,i) {\n if (!interactive) return;\n dispatch.elementMousemove({\n data: d,\n index: i,\n color: d3.select(this).style(\"fill\")\n });\n })\n .on('click', function(d,i) {\n if (!interactive) return;\n var element = this;\n dispatch.elementClick({\n data: d,\n index: i,\n color: d3.select(this).style(\"fill\"),\n event: d3.event,\n element: element\n });\n d3.event.stopPropagation();\n })\n .on('dblclick', function(d,i) {\n if (!interactive) return;\n dispatch.elementDblClick({\n data: d,\n index: i,\n color: d3.select(this).style(\"fill\")\n });\n d3.event.stopPropagation();\n });\n\n bars\n .attr('fill', function(d,i) { return color(d, i); })\n .attr('class', function(d,i,j) { return (getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive') + ' nv-bar-' + j + '-' + i })\n .watchTransition(renderWatch, 'bars')\n .attr('transform', function(d,i) { return 'translate(' + (x(getX(d,i)) - availableWidth / data[0].values.length * .45) + ',0)'; })\n //TODO: better width calculations that don't assume always uniform data spacing;w\n .attr('width', (availableWidth / data[0].values.length) * .9 );\n\n bars.watchTransition(renderWatch, 'bars')\n .attr('y', function(d,i) {\n var rval = getY(d,i) < 0 ?\n y(0) :\n y(0) - y(getY(d,i)) < 1 ?\n y(0) - 1 :\n y(getY(d,i));\n return nv.utils.NaNtoZero(rval);\n })\n .attr('height', function(d,i) { return nv.utils.NaNtoZero(Math.max(Math.abs(y(getY(d,i)) - y(0)),1)) });\n\n });\n\n renderWatch.renderEnd('historicalBar immediate');\n return chart;\n }\n\n //Create methods to allow outside functions to highlight a specific bar.\n chart.highlightPoint = function(pointIndex, isHoverOver) {\n container\n .select(\".nv-bars .nv-bar-0-\" + pointIndex)\n .classed(\"hover\", isHoverOver)\n ;\n };\n\n chart.clearHighlights = function() {\n container\n .select(\".nv-bars .nv-bar.hover\")\n .classed(\"hover\", false)\n ;\n };\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n chart.dispatch = dispatch;\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n forceX: {get: function(){return forceX;}, set: function(_){forceX=_;}},\n forceY: {get: function(){return forceY;}, set: function(_){forceY=_;}},\n padData: {get: function(){return padData;}, set: function(_){padData=_;}},\n x: {get: function(){return getX;}, set: function(_){getX=_;}},\n y: {get: function(){return getY;}, set: function(_){getY=_;}},\n xScale: {get: function(){return x;}, set: function(_){x=_;}},\n yScale: {get: function(){return y;}, set: function(_){y=_;}},\n xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}},\n yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}},\n xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}},\n yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}},\n clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}},\n id: {get: function(){return id;}, set: function(_){id=_;}},\n interactive: {get: function(){return interactive;}, set: function(_){interactive=_;}},\n\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n margin.top = _.top !== undefined ? _.top : margin.top;\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n }},\n color: {get: function(){return color;}, set: function(_){\n color = nv.utils.getColor(_);\n }}\n });\n\n nv.utils.initOptions(chart);\n\n return chart;\n};\n","\nnv.models.historicalBarChart = function(bar_model) {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var bars = bar_model || nv.models.historicalBar()\n , xAxis = nv.models.axis()\n , yAxis = nv.models.axis()\n , legend = nv.models.legend()\n , interactiveLayer = nv.interactiveGuideline()\n , tooltip = nv.models.tooltip()\n ;\n\n\n var margin = {top: 30, right: 90, bottom: 50, left: 90}\n , marginTop = null\n , color = nv.utils.defaultColor()\n , width = null\n , height = null\n , showLegend = false\n , showXAxis = true\n , showYAxis = true\n , rightAlignYAxis = false\n , useInteractiveGuideline = false\n , x\n , y\n , state = {}\n , defaultState = null\n , noData = null\n , dispatch = d3.dispatch('tooltipHide', 'stateChange', 'changeState', 'renderEnd')\n , transitionDuration = 250\n ;\n\n xAxis.orient('bottom').tickPadding(7);\n yAxis.orient( (rightAlignYAxis) ? 'right' : 'left');\n tooltip\n .duration(0)\n .headerEnabled(false)\n .valueFormatter(function(d, i) {\n return yAxis.tickFormat()(d, i);\n })\n .headerFormatter(function(d, i) {\n return xAxis.tickFormat()(d, i);\n });\n\n\n //============================================================\n // Private Variables\n //------------------------------------------------------------\n\n var renderWatch = nv.utils.renderWatch(dispatch, 0);\n\n function chart(selection) {\n selection.each(function(data) {\n renderWatch.reset();\n renderWatch.models(bars);\n if (showXAxis) renderWatch.models(xAxis);\n if (showYAxis) renderWatch.models(yAxis);\n\n var container = d3.select(this),\n that = this;\n nv.utils.initSVG(container);\n var availableWidth = nv.utils.availableWidth(width, container, margin),\n availableHeight = nv.utils.availableHeight(height, container, margin);\n\n chart.update = function() { container.transition().duration(transitionDuration).call(chart) };\n chart.container = this;\n\n //set state.disabled\n state.disabled = data.map(function(d) { return !!d.disabled });\n\n if (!defaultState) {\n var key;\n defaultState = {};\n for (key in state) {\n if (state[key] instanceof Array)\n defaultState[key] = state[key].slice(0);\n else\n defaultState[key] = state[key];\n }\n }\n\n // Display noData message if there's nothing to show.\n if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {\n nv.utils.noData(chart, container)\n return chart;\n } else {\n container.selectAll('.nv-noData').remove();\n }\n\n // Setup Scales\n x = bars.xScale();\n y = bars.yScale();\n\n // Setup containers and skeleton of chart\n var wrap = container.selectAll('g.nv-wrap.nv-historicalBarChart').data([data]);\n var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-historicalBarChart').append('g');\n var g = wrap.select('g');\n\n gEnter.append('g').attr('class', 'nv-x nv-axis');\n gEnter.append('g').attr('class', 'nv-y nv-axis');\n gEnter.append('g').attr('class', 'nv-barsWrap');\n gEnter.append('g').attr('class', 'nv-legendWrap');\n gEnter.append('g').attr('class', 'nv-interactive');\n\n // Legend\n if (!showLegend) {\n g.select('.nv-legendWrap').selectAll('*').remove();\n } else {\n legend.width(availableWidth);\n\n g.select('.nv-legendWrap')\n .datum(data)\n .call(legend);\n\n if (!marginTop && legend.height() !== margin.top) {\n margin.top = legend.height();\n availableHeight = nv.utils.availableHeight(height, container, margin);\n }\n\n wrap.select('.nv-legendWrap')\n .attr('transform', 'translate(0,' + (-margin.top) +')')\n }\n wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');\n\n if (rightAlignYAxis) {\n g.select(\".nv-y.nv-axis\")\n .attr(\"transform\", \"translate(\" + availableWidth + \",0)\");\n }\n\n //Set up interactive layer\n if (useInteractiveGuideline) {\n interactiveLayer\n .width(availableWidth)\n .height(availableHeight)\n .margin({left:margin.left, top:margin.top})\n .svgContainer(container)\n .xScale(x);\n wrap.select(\".nv-interactive\").call(interactiveLayer);\n }\n bars\n .width(availableWidth)\n .height(availableHeight)\n .color(data.map(function(d,i) {\n return d.color || color(d, i);\n }).filter(function(d,i) { return !data[i].disabled }));\n\n var barsWrap = g.select('.nv-barsWrap')\n .datum(data.filter(function(d) { return !d.disabled }));\n barsWrap.transition().call(bars);\n\n // Setup Axes\n if (showXAxis) {\n xAxis\n .scale(x)\n ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )\n .tickSize(-availableHeight, 0);\n\n g.select('.nv-x.nv-axis')\n .attr('transform', 'translate(0,' + y.range()[0] + ')');\n g.select('.nv-x.nv-axis')\n .transition()\n .call(xAxis);\n }\n\n if (showYAxis) {\n yAxis\n .scale(y)\n ._ticks( nv.utils.calcTicksY(availableHeight/36, data) )\n .tickSize( -availableWidth, 0);\n\n g.select('.nv-y.nv-axis')\n .transition()\n .call(yAxis);\n }\n\n //============================================================\n // Event Handling/Dispatching (in chart's scope)\n //------------------------------------------------------------\n\n interactiveLayer.dispatch.on('elementMousemove', function(e) {\n bars.clearHighlights();\n\n var singlePoint, pointIndex, pointXLocation, allData = [];\n data\n .filter(function(series, i) {\n series.seriesIndex = i;\n return !series.disabled;\n })\n .forEach(function(series,i) {\n pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x());\n bars.highlightPoint(pointIndex,true);\n var point = series.values[pointIndex];\n if (point === undefined) return;\n if (singlePoint === undefined) singlePoint = point;\n if (pointXLocation === undefined) pointXLocation = chart.xScale()(chart.x()(point,pointIndex));\n allData.push({\n key: series.key,\n value: chart.y()(point, pointIndex),\n color: color(series,series.seriesIndex),\n data: series.values[pointIndex]\n });\n });\n\n var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex));\n interactiveLayer.tooltip\n .valueFormatter(function(d,i) {\n return yAxis.tickFormat()(d);\n })\n .data({\n value: xValue,\n index: pointIndex,\n series: allData\n })();\n\n interactiveLayer.renderGuideLine(pointXLocation);\n\n });\n\n interactiveLayer.dispatch.on(\"elementMouseout\",function(e) {\n dispatch.tooltipHide();\n bars.clearHighlights();\n });\n\n legend.dispatch.on('legendClick', function(d,i) {\n d.disabled = !d.disabled;\n\n if (!data.filter(function(d) { return !d.disabled }).length) {\n data.map(function(d) {\n d.disabled = false;\n wrap.selectAll('.nv-series').classed('disabled', false);\n return d;\n });\n }\n\n state.disabled = data.map(function(d) { return !!d.disabled });\n dispatch.stateChange(state);\n\n selection.transition().call(chart);\n });\n\n legend.dispatch.on('legendDblclick', function(d) {\n //Double clicking should always enable current series, and disabled all others.\n data.forEach(function(d) {\n d.disabled = true;\n });\n d.disabled = false;\n\n state.disabled = data.map(function(d) { return !!d.disabled });\n dispatch.stateChange(state);\n chart.update();\n });\n\n dispatch.on('changeState', function(e) {\n if (typeof e.disabled !== 'undefined') {\n data.forEach(function(series,i) {\n series.disabled = e.disabled[i];\n });\n\n state.disabled = e.disabled;\n }\n\n chart.update();\n });\n });\n\n renderWatch.renderEnd('historicalBarChart immediate');\n return chart;\n }\n\n //============================================================\n // Event Handling/Dispatching (out of chart's scope)\n //------------------------------------------------------------\n\n bars.dispatch.on('elementMouseover.tooltip', function(evt) {\n evt['series'] = {\n key: chart.x()(evt.data),\n value: chart.y()(evt.data),\n color: evt.color\n };\n tooltip.data(evt).hidden(false);\n });\n\n bars.dispatch.on('elementMouseout.tooltip', function(evt) {\n tooltip.hidden(true);\n });\n\n bars.dispatch.on('elementMousemove.tooltip', function(evt) {\n tooltip();\n });\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n // expose chart's sub-components\n chart.dispatch = dispatch;\n chart.bars = bars;\n chart.legend = legend;\n chart.xAxis = xAxis;\n chart.yAxis = yAxis;\n chart.interactiveLayer = interactiveLayer;\n chart.tooltip = tooltip;\n\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},\n showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},\n showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},\n defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}},\n noData: {get: function(){return noData;}, set: function(_){noData=_;}},\n\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n if (_.top !== undefined) {\n margin.top = _.top;\n marginTop = _.top;\n }\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n }},\n color: {get: function(){return color;}, set: function(_){\n color = nv.utils.getColor(_);\n legend.color(color);\n bars.color(color);\n }},\n duration: {get: function(){return transitionDuration;}, set: function(_){\n transitionDuration=_;\n renderWatch.reset(transitionDuration);\n yAxis.duration(transitionDuration);\n xAxis.duration(transitionDuration);\n }},\n rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){\n rightAlignYAxis = _;\n yAxis.orient( (_) ? 'right' : 'left');\n }},\n useInteractiveGuideline: {get: function(){return useInteractiveGuideline;}, set: function(_){\n useInteractiveGuideline = _;\n if (_ === true) {\n chart.interactive(false);\n }\n }}\n });\n\n nv.utils.inheritOptions(chart, bars);\n nv.utils.initOptions(chart);\n\n return chart;\n};\n\n\n// ohlcChart is just a historical chart with ohlc bars and some tweaks\nnv.models.ohlcBarChart = function() {\n var chart = nv.models.historicalBarChart(nv.models.ohlcBar());\n\n // special default tooltip since we show multiple values per x\n chart.useInteractiveGuideline(true);\n chart.interactiveLayer.tooltip.contentGenerator(function(data) {\n // we assume only one series exists for this chart\n var d = data.series[0].data;\n // match line colors as defined in nv.d3.css\n var color = d.open < d.close ? \"2ca02c\" : \"d62728\";\n return '' +\n '

' + data.value + '

' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '
open:' + chart.yAxis.tickFormat()(d.open) + '
close:' + chart.yAxis.tickFormat()(d.close) + '
high' + chart.yAxis.tickFormat()(d.high) + '
low:' + chart.yAxis.tickFormat()(d.low) + '
';\n });\n return chart;\n};\n\n// candlestickChart is just a historical chart with candlestick bars and some tweaks\nnv.models.candlestickBarChart = function() {\n var chart = nv.models.historicalBarChart(nv.models.candlestickBar());\n\n // special default tooltip since we show multiple values per x\n chart.useInteractiveGuideline(true);\n chart.interactiveLayer.tooltip.contentGenerator(function(data) {\n // we assume only one series exists for this chart\n var d = data.series[0].data;\n // match line colors as defined in nv.d3.css\n var color = d.open < d.close ? \"2ca02c\" : \"d62728\";\n return '' +\n '

' + data.value + '

' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '
open:' + chart.yAxis.tickFormat()(d.open) + '
close:' + chart.yAxis.tickFormat()(d.close) + '
high' + chart.yAxis.tickFormat()(d.high) + '
low:' + chart.yAxis.tickFormat()(d.low) + '
';\n });\n return chart;\n};\n","nv.models.legend = function() {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var margin = {top: 5, right: 0, bottom: 5, left: 0}\n , width = 400\n , height = 20\n , getKey = function(d) { return d.key }\n , keyFormatter = function (d) { return d }\n , color = nv.utils.getColor()\n , maxKeyLength = 20 //default value for key lengths\n , align = true\n , padding = 32 //define how much space between legend items. - recommend 32 for furious version\n , rightAlign = true\n , updateState = true //If true, legend will update data.disabled and trigger a 'stateChange' dispatch.\n , radioButtonMode = false //If true, clicking legend items will cause it to behave like a radio button. (only one can be selected at a time)\n , expanded = false\n , dispatch = d3.dispatch('legendClick', 'legendDblclick', 'legendMouseover', 'legendMouseout', 'stateChange')\n , vers = 'classic' //Options are \"classic\" and \"furious\"\n ;\n\n function chart(selection) {\n selection.each(function(data) {\n var availableWidth = width - margin.left - margin.right,\n container = d3.select(this);\n nv.utils.initSVG(container);\n\n // Setup containers and skeleton of chart\n var wrap = container.selectAll('g.nv-legend').data([data]);\n var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-legend').append('g');\n var g = wrap.select('g');\n\n if (rightAlign)\n wrap.attr('transform', 'translate(' + (- margin.right) + ',' + margin.top + ')');\n else\n wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');\n\n var series = g.selectAll('.nv-series')\n .data(function(d) {\n if(vers != 'furious') return d;\n\n return d.filter(function(n) {\n return expanded ? true : !n.disengaged;\n });\n });\n\n var seriesEnter = series.enter().append('g').attr('class', 'nv-series');\n var seriesShape;\n\n var versPadding;\n switch(vers) {\n case 'furious' :\n versPadding = 23;\n break;\n case 'classic' :\n versPadding = 20;\n }\n\n if(vers == 'classic') {\n seriesEnter.append('circle')\n .style('stroke-width', 2)\n .attr('class','nv-legend-symbol')\n .attr('r', 5);\n\n seriesShape = series.select('.nv-legend-symbol');\n } else if (vers == 'furious') {\n seriesEnter.append('rect')\n .style('stroke-width', 2)\n .attr('class','nv-legend-symbol')\n .attr('rx', 3)\n .attr('ry', 3);\n seriesShape = series.select('.nv-legend-symbol');\n\n seriesEnter.append('g')\n .attr('class', 'nv-check-box')\n .property('innerHTML','')\n .attr('transform', 'translate(-10,-8)scale(0.5)');\n\n var seriesCheckbox = series.select('.nv-check-box');\n\n seriesCheckbox.each(function(d,i) {\n d3.select(this).selectAll('path')\n .attr('stroke', setTextColor(d,i));\n });\n }\n\n seriesEnter.append('text')\n .attr('text-anchor', 'start')\n .attr('class','nv-legend-text')\n .attr('dy', '.32em')\n .attr('dx', '8');\n\n var seriesText = series.select('text.nv-legend-text');\n\n series\n .on('mouseover', function(d,i) {\n dispatch.legendMouseover(d,i); //TODO: Make consistent with other event objects\n })\n .on('mouseout', function(d,i) {\n dispatch.legendMouseout(d,i);\n })\n .on('click', function(d,i) {\n dispatch.legendClick(d,i);\n // make sure we re-get data in case it was modified\n var data = series.data();\n if (updateState) {\n if(vers =='classic') {\n if (radioButtonMode) {\n //Radio button mode: set every series to disabled,\n // and enable the clicked series.\n data.forEach(function(series) { series.disabled = true});\n d.disabled = false;\n }\n else {\n d.disabled = !d.disabled;\n if (data.every(function(series) { return series.disabled})) {\n //the default behavior of NVD3 legends is, if every single series\n // is disabled, turn all series' back on.\n data.forEach(function(series) { series.disabled = false});\n }\n }\n } else if(vers == 'furious') {\n if(expanded) {\n d.disengaged = !d.disengaged;\n d.userDisabled = d.userDisabled == undefined ? !!d.disabled : d.userDisabled;\n d.disabled = d.disengaged || d.userDisabled;\n } else if (!expanded) {\n d.disabled = !d.disabled;\n d.userDisabled = d.disabled;\n var engaged = data.filter(function(d) { return !d.disengaged; });\n if (engaged.every(function(series) { return series.userDisabled })) {\n //the default behavior of NVD3 legends is, if every single series\n // is disabled, turn all series' back on.\n data.forEach(function(series) {\n series.disabled = series.userDisabled = false;\n });\n }\n }\n }\n dispatch.stateChange({\n disabled: data.map(function(d) { return !!d.disabled }),\n disengaged: data.map(function(d) { return !!d.disengaged })\n });\n\n }\n })\n .on('dblclick', function(d,i) {\n if(vers == 'furious' && expanded) return;\n dispatch.legendDblclick(d,i);\n if (updateState) {\n // make sure we re-get data in case it was modified\n var data = series.data();\n //the default behavior of NVD3 legends, when double clicking one,\n // is to set all other series' to false, and make the double clicked series enabled.\n data.forEach(function(series) {\n series.disabled = true;\n if(vers == 'furious') series.userDisabled = series.disabled;\n });\n d.disabled = false;\n if(vers == 'furious') d.userDisabled = d.disabled;\n dispatch.stateChange({\n disabled: data.map(function(d) { return !!d.disabled })\n });\n }\n });\n\n series.classed('nv-disabled', function(d) { return d.userDisabled });\n series.exit().remove();\n\n seriesText\n .attr('fill', setTextColor)\n .text(function (d) { return keyFormatter(getKey(d)) });\n\n //TODO: implement fixed-width and max-width options (max-width is especially useful with the align option)\n // NEW ALIGNING CODE, TODO: clean up\n var legendWidth = 0;\n if (align) {\n\n var seriesWidths = [];\n series.each(function(d,i) {\n var legendText;\n if (keyFormatter(getKey(d)) && keyFormatter(getKey(d)).length > maxKeyLength) {\n var trimmedKey = keyFormatter(getKey(d)).substring(0, maxKeyLength);\n legendText = d3.select(this).select('text').text(trimmedKey + \"...\");\n d3.select(this).append(\"svg:title\").text(keyFormatter(getKey(d)));\n } else {\n legendText = d3.select(this).select('text');\n }\n var nodeTextLength;\n try {\n nodeTextLength = legendText.node().getComputedTextLength();\n // If the legendText is display:none'd (nodeTextLength == 0), simulate an error so we approximate, instead\n if(nodeTextLength <= 0) throw Error();\n }\n catch(e) {\n nodeTextLength = nv.utils.calcApproxTextWidth(legendText);\n }\n\n seriesWidths.push(nodeTextLength + padding);\n });\n\n var seriesPerRow = 0;\n var columnWidths = [];\n legendWidth = 0;\n\n while ( legendWidth < availableWidth && seriesPerRow < seriesWidths.length) {\n columnWidths[seriesPerRow] = seriesWidths[seriesPerRow];\n legendWidth += seriesWidths[seriesPerRow++];\n }\n if (seriesPerRow === 0) seriesPerRow = 1; //minimum of one series per row\n\n while ( legendWidth > availableWidth && seriesPerRow > 1 ) {\n columnWidths = [];\n seriesPerRow--;\n\n for (var k = 0; k < seriesWidths.length; k++) {\n if (seriesWidths[k] > (columnWidths[k % seriesPerRow] || 0) )\n columnWidths[k % seriesPerRow] = seriesWidths[k];\n }\n\n legendWidth = columnWidths.reduce(function(prev, cur, index, array) {\n return prev + cur;\n });\n }\n\n var xPositions = [];\n for (var i = 0, curX = 0; i < seriesPerRow; i++) {\n xPositions[i] = curX;\n curX += columnWidths[i];\n }\n\n series\n .attr('transform', function(d, i) {\n return 'translate(' + xPositions[i % seriesPerRow] + ',' + (5 + Math.floor(i / seriesPerRow) * versPadding) + ')';\n });\n\n //position legend as far right as possible within the total width\n if (rightAlign) {\n g.attr('transform', 'translate(' + (width - margin.right - legendWidth) + ',' + margin.top + ')');\n }\n else {\n g.attr('transform', 'translate(0' + ',' + margin.top + ')');\n }\n\n height = margin.top + margin.bottom + (Math.ceil(seriesWidths.length / seriesPerRow) * versPadding);\n\n } else {\n\n var ypos = 5,\n newxpos = 5,\n maxwidth = 0,\n xpos;\n series\n .attr('transform', function(d, i) {\n var length = d3.select(this).select('text').node().getComputedTextLength() + padding;\n xpos = newxpos;\n\n if (width < margin.left + margin.right + xpos + length) {\n newxpos = xpos = 5;\n ypos += versPadding;\n }\n\n newxpos += length;\n if (newxpos > maxwidth) maxwidth = newxpos;\n\n if(legendWidth < xpos + maxwidth) {\n legendWidth = xpos + maxwidth;\n }\n return 'translate(' + xpos + ',' + ypos + ')';\n });\n\n //position legend as far right as possible within the total width\n g.attr('transform', 'translate(' + (width - margin.right - maxwidth) + ',' + margin.top + ')');\n\n height = margin.top + margin.bottom + ypos + 15;\n }\n\n if(vers == 'furious') {\n // Size rectangles after text is placed\n seriesShape\n .attr('width', function(d,i) {\n return seriesText[0][i].getComputedTextLength() + 27;\n })\n .attr('height', 18)\n .attr('y', -9)\n .attr('x', -15);\n\n // The background for the expanded legend (UI)\n gEnter.insert('rect',':first-child')\n .attr('class', 'nv-legend-bg')\n .attr('fill', '#eee')\n // .attr('stroke', '#444')\n .attr('opacity',0);\n\n var seriesBG = g.select('.nv-legend-bg');\n\n seriesBG\n .transition().duration(300)\n .attr('x', -versPadding )\n .attr('width', legendWidth + versPadding - 12)\n .attr('height', height + 10)\n .attr('y', -margin.top - 10)\n .attr('opacity', expanded ? 1 : 0);\n\n\n }\n\n seriesShape\n .style('fill', setBGColor)\n .style('fill-opacity', setBGOpacity)\n .style('stroke', setBGColor);\n });\n\n function setTextColor(d,i) {\n if(vers != 'furious') return '#000';\n if(expanded) {\n return d.disengaged ? '#000' : '#fff';\n } else if (!expanded) {\n if(!d.color) d.color = color(d,i);\n return !!d.disabled ? d.color : '#fff';\n }\n }\n\n function setBGColor(d,i) {\n if(expanded && vers == 'furious') {\n return d.disengaged ? '#eee' : d.color || color(d,i);\n } else {\n return d.color || color(d,i);\n }\n }\n\n\n function setBGOpacity(d,i) {\n if(expanded && vers == 'furious') {\n return 1;\n } else {\n return !!d.disabled ? 0 : 1;\n }\n }\n\n return chart;\n }\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n chart.dispatch = dispatch;\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n key: {get: function(){return getKey;}, set: function(_){getKey=_;}},\n keyFormatter: {get: function(){return keyFormatter;}, set: function(_){keyFormatter=_;}},\n align: {get: function(){return align;}, set: function(_){align=_;}},\n maxKeyLength: {get: function(){return maxKeyLength;}, set: function(_){maxKeyLength=_;}},\n rightAlign: {get: function(){return rightAlign;}, set: function(_){rightAlign=_;}},\n padding: {get: function(){return padding;}, set: function(_){padding=_;}},\n updateState: {get: function(){return updateState;}, set: function(_){updateState=_;}},\n radioButtonMode:{get: function(){return radioButtonMode;}, set: function(_){radioButtonMode=_;}},\n expanded: {get: function(){return expanded;}, set: function(_){expanded=_;}},\n vers: {get: function(){return vers;}, set: function(_){vers=_;}},\n\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n margin.top = _.top !== undefined ? _.top : margin.top;\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n }},\n color: {get: function(){return color;}, set: function(_){\n color = nv.utils.getColor(_);\n }}\n });\n\n nv.utils.initOptions(chart);\n\n return chart;\n};\n","\nnv.models.line = function() {\n \"use strict\";\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var scatter = nv.models.scatter()\n ;\n\n var margin = {top: 0, right: 0, bottom: 0, left: 0}\n , width = 960\n , height = 500\n , container = null\n , strokeWidth = 1.5\n , color = nv.utils.defaultColor() // a function that returns a color\n , getX = function(d) { return d.x } // accessor to get the x value from a data point\n , getY = function(d) { return d.y } // accessor to get the y value from a data point\n , defined = function(d,i) { return !isNaN(getY(d,i)) && getY(d,i) !== null } // allows a line to be not continuous when it is not defined\n , isArea = function(d) { return d.area } // decides if a line is an area or just a line\n , clipEdge = false // if true, masks lines within x and y scale\n , x //can be accessed via chart.xScale()\n , y //can be accessed via chart.yScale()\n , interpolate = \"linear\" // controls the line interpolation\n , duration = 250\n , dispatch = d3.dispatch('elementClick', 'elementMouseover', 'elementMouseout', 'renderEnd')\n ;\n\n scatter\n .pointSize(16) // default size\n .pointDomain([16,256]) //set to speed up calculation, needs to be unset if there is a custom size accessor\n ;\n\n //============================================================\n\n\n //============================================================\n // Private Variables\n //------------------------------------------------------------\n\n var x0, y0 //used to store previous scales\n , renderWatch = nv.utils.renderWatch(dispatch, duration)\n ;\n\n //============================================================\n\n\n function chart(selection) {\n renderWatch.reset();\n renderWatch.models(scatter);\n selection.each(function(data) {\n container = d3.select(this);\n var availableWidth = nv.utils.availableWidth(width, container, margin),\n availableHeight = nv.utils.availableHeight(height, container, margin);\n nv.utils.initSVG(container);\n\n // Setup Scales\n x = scatter.xScale();\n y = scatter.yScale();\n\n x0 = x0 || x;\n y0 = y0 || y;\n\n // Setup containers and skeleton of chart\n var wrap = container.selectAll('g.nv-wrap.nv-line').data([data]);\n var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-line');\n var defsEnter = wrapEnter.append('defs');\n var gEnter = wrapEnter.append('g');\n var g = wrap.select('g');\n\n gEnter.append('g').attr('class', 'nv-groups');\n gEnter.append('g').attr('class', 'nv-scatterWrap');\n\n wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');\n\n scatter\n .width(availableWidth)\n .height(availableHeight);\n\n var scatterWrap = wrap.select('.nv-scatterWrap');\n scatterWrap.call(scatter);\n\n defsEnter.append('clipPath')\n .attr('id', 'nv-edge-clip-' + scatter.id())\n .append('rect');\n\n wrap.select('#nv-edge-clip-' + scatter.id() + ' rect')\n .attr('width', availableWidth)\n .attr('height', (availableHeight > 0) ? availableHeight : 0);\n\n g .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + scatter.id() + ')' : '');\n scatterWrap\n .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + scatter.id() + ')' : '');\n\n var groups = wrap.select('.nv-groups').selectAll('.nv-group')\n .data(function(d) { return d }, function(d) { return d.key });\n groups.enter().append('g')\n .style('stroke-opacity', 1e-6)\n .style('stroke-width', function(d) { return d.strokeWidth || strokeWidth })\n .style('fill-opacity', 1e-6);\n\n groups.exit().remove();\n\n groups\n .attr('class', function(d,i) {\n return (d.classed || '') + ' nv-group nv-series-' + i;\n })\n .classed('hover', function(d) { return d.hover })\n .style('fill', function(d,i){ return color(d, i) })\n .style('stroke', function(d,i){ return color(d, i)});\n groups.watchTransition(renderWatch, 'line: groups')\n .style('stroke-opacity', 1)\n .style('fill-opacity', function(d) { return d.fillOpacity || .5});\n\n var areaPaths = groups.selectAll('path.nv-area')\n .data(function(d) { return isArea(d) ? [d] : [] }); // this is done differently than lines because I need to check if series is an area\n areaPaths.enter().append('path')\n .attr('class', 'nv-area')\n .attr('d', function(d) {\n return d3.svg.area()\n .interpolate(interpolate)\n .defined(defined)\n .x(function(d,i) { return nv.utils.NaNtoZero(x0(getX(d,i))) })\n .y0(function(d,i) { return nv.utils.NaNtoZero(y0(getY(d,i))) })\n .y1(function(d,i) { return y0( y.domain()[0] <= 0 ? y.domain()[1] >= 0 ? 0 : y.domain()[1] : y.domain()[0] ) })\n //.y1(function(d,i) { return y0(0) }) //assuming 0 is within y domain.. may need to tweak this\n .apply(this, [d.values])\n });\n groups.exit().selectAll('path.nv-area')\n .remove();\n\n areaPaths.watchTransition(renderWatch, 'line: areaPaths')\n .attr('d', function(d) {\n return d3.svg.area()\n .interpolate(interpolate)\n .defined(defined)\n .x(function(d,i) { return nv.utils.NaNtoZero(x(getX(d,i))) })\n .y0(function(d,i) { return nv.utils.NaNtoZero(y(getY(d,i))) })\n .y1(function(d,i) { return y( y.domain()[0] <= 0 ? y.domain()[1] >= 0 ? 0 : y.domain()[1] : y.domain()[0] ) })\n //.y1(function(d,i) { return y0(0) }) //assuming 0 is within y domain.. may need to tweak this\n .apply(this, [d.values])\n });\n\n var linePaths = groups.selectAll('path.nv-line')\n .data(function(d) { return [d.values] });\n\n linePaths.enter().append('path')\n .attr('class', 'nv-line')\n .attr('d',\n d3.svg.line()\n .interpolate(interpolate)\n .defined(defined)\n .x(function(d,i) { return nv.utils.NaNtoZero(x0(getX(d,i))) })\n .y(function(d,i) { return nv.utils.NaNtoZero(y0(getY(d,i))) })\n );\n\n linePaths.watchTransition(renderWatch, 'line: linePaths')\n .attr('d',\n d3.svg.line()\n .interpolate(interpolate)\n .defined(defined)\n .x(function(d,i) { return nv.utils.NaNtoZero(x(getX(d,i))) })\n .y(function(d,i) { return nv.utils.NaNtoZero(y(getY(d,i))) })\n );\n\n //store old scales for use in transitions on update\n x0 = x.copy();\n y0 = y.copy();\n });\n renderWatch.renderEnd('line immediate');\n return chart;\n }\n\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n chart.dispatch = dispatch;\n chart.scatter = scatter;\n // Pass through events\n scatter.dispatch.on('elementClick', function(){ dispatch.elementClick.apply(this, arguments); });\n scatter.dispatch.on('elementMouseover', function(){ dispatch.elementMouseover.apply(this, arguments); });\n scatter.dispatch.on('elementMouseout', function(){ dispatch.elementMouseout.apply(this, arguments); });\n\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n defined: {get: function(){return defined;}, set: function(_){defined=_;}},\n interpolate: {get: function(){return interpolate;}, set: function(_){interpolate=_;}},\n clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}},\n\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n margin.top = _.top !== undefined ? _.top : margin.top;\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n }},\n duration: {get: function(){return duration;}, set: function(_){\n duration = _;\n renderWatch.reset(duration);\n scatter.duration(duration);\n }},\n isArea: {get: function(){return isArea;}, set: function(_){\n isArea = d3.functor(_);\n }},\n x: {get: function(){return getX;}, set: function(_){\n getX = _;\n scatter.x(_);\n }},\n y: {get: function(){return getY;}, set: function(_){\n getY = _;\n scatter.y(_);\n }},\n color: {get: function(){return color;}, set: function(_){\n color = nv.utils.getColor(_);\n scatter.color(color);\n }}\n });\n\n nv.utils.inheritOptions(chart, scatter);\n nv.utils.initOptions(chart);\n\n return chart;\n};\n","nv.models.lineChart = function() {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var lines = nv.models.line()\n , xAxis = nv.models.axis()\n , yAxis = nv.models.axis()\n , legend = nv.models.legend()\n , interactiveLayer = nv.interactiveGuideline()\n , tooltip = nv.models.tooltip()\n , focus = nv.models.focus(nv.models.line())\n ;\n\n var margin = {top: 30, right: 20, bottom: 50, left: 60}\n , marginTop = null\n , color = nv.utils.defaultColor()\n , width = null\n , height = null\n , showLegend = true\n , legendPosition = 'top'\n , showXAxis = true\n , showYAxis = true\n , rightAlignYAxis = false\n , useInteractiveGuideline = false\n , x\n , y\n , focusEnable = false\n , state = nv.utils.state()\n , defaultState = null\n , noData = null\n , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState', 'renderEnd')\n , duration = 250\n ;\n\n // set options on sub-objects for this chart\n xAxis.orient('bottom').tickPadding(7);\n yAxis.orient(rightAlignYAxis ? 'right' : 'left');\n\n lines.clipEdge(true).duration(0);\n\n tooltip.valueFormatter(function(d, i) {\n return yAxis.tickFormat()(d, i);\n }).headerFormatter(function(d, i) {\n return xAxis.tickFormat()(d, i);\n });\n\n interactiveLayer.tooltip.valueFormatter(function(d, i) {\n return yAxis.tickFormat()(d, i);\n }).headerFormatter(function(d, i) {\n return xAxis.tickFormat()(d, i);\n });\n\n\n //============================================================\n // Private Variables\n //------------------------------------------------------------\n\n var renderWatch = nv.utils.renderWatch(dispatch, duration);\n\n var stateGetter = function(data) {\n return function(){\n return {\n active: data.map(function(d) { return !d.disabled; })\n };\n };\n };\n\n var stateSetter = function(data) {\n return function(state) {\n if (state.active !== undefined)\n data.forEach(function(series,i) {\n series.disabled = !state.active[i];\n });\n };\n };\n\n function chart(selection) {\n renderWatch.reset();\n renderWatch.models(lines);\n if (showXAxis) renderWatch.models(xAxis);\n if (showYAxis) renderWatch.models(yAxis);\n\n selection.each(function(data) {\n var container = d3.select(this);\n nv.utils.initSVG(container);\n var availableWidth = nv.utils.availableWidth(width, container, margin),\n availableHeight = nv.utils.availableHeight(height, container, margin) - (focusEnable ? focus.height() : 0);\n chart.update = function() {\n if( duration === 0 ) {\n container.call( chart );\n } else {\n container.transition().duration(duration).call(chart);\n }\n };\n chart.container = this;\n\n state\n .setter(stateSetter(data), chart.update)\n .getter(stateGetter(data))\n .update();\n\n // DEPRECATED set state.disabled\n state.disabled = data.map(function(d) { return !!d.disabled; });\n\n if (!defaultState) {\n var key;\n defaultState = {};\n for (key in state) {\n if (state[key] instanceof Array)\n defaultState[key] = state[key].slice(0);\n else\n defaultState[key] = state[key];\n }\n }\n\n // Display noData message if there's nothing to show.\n if (!data || !data.length || !data.filter(function(d) { return d.values.length; }).length) {\n nv.utils.noData(chart, container);\n return chart;\n } else {\n container.selectAll('.nv-noData').remove();\n }\n\n /* Update `main' graph on brush update. */\n focus.dispatch.on(\"onBrush\", function(extent) {\n onBrush(extent);\n });\n\n // Setup Scales\n x = lines.xScale();\n y = lines.yScale();\n\n // Setup containers and skeleton of chart\n var wrap = container.selectAll('g.nv-wrap.nv-lineChart').data([data]);\n var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-lineChart').append('g');\n var g = wrap.select('g');\n\n gEnter.append('g').attr('class', 'nv-legendWrap');\n\n var focusEnter = gEnter.append('g').attr('class', 'nv-focus');\n focusEnter.append('g').attr('class', 'nv-background').append('rect');\n focusEnter.append('g').attr('class', 'nv-x nv-axis');\n focusEnter.append('g').attr('class', 'nv-y nv-axis');\n focusEnter.append('g').attr('class', 'nv-linesWrap');\n focusEnter.append('g').attr('class', 'nv-interactive');\n\n var contextEnter = gEnter.append('g').attr('class', 'nv-focusWrap');\n\n // Legend\n if (!showLegend) {\n g.select('.nv-legendWrap').selectAll('*').remove();\n } else {\n legend.width(availableWidth);\n\n g.select('.nv-legendWrap')\n .datum(data)\n .call(legend);\n\n if (legendPosition === 'bottom') {\n wrap.select('.nv-legendWrap')\n .attr('transform', 'translate(0,' + availableHeight +')');\n } else if (legendPosition === 'top') {\n if (!marginTop && legend.height() !== margin.top) {\n margin.top = legend.height();\n availableHeight = nv.utils.availableHeight(height, container, margin) - (focusEnable ? focus.height() : 0);\n }\n\n wrap.select('.nv-legendWrap')\n .attr('transform', 'translate(0,' + (-margin.top) +')');\n }\n }\n\n wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');\n\n if (rightAlignYAxis) {\n g.select(\".nv-y.nv-axis\")\n .attr(\"transform\", \"translate(\" + availableWidth + \",0)\");\n }\n\n //Set up interactive layer\n if (useInteractiveGuideline) {\n interactiveLayer\n .width(availableWidth)\n .height(availableHeight)\n .margin({left:margin.left, top:margin.top})\n .svgContainer(container)\n .xScale(x);\n wrap.select(\".nv-interactive\").call(interactiveLayer);\n }\n\n g.select('.nv-focus .nv-background rect')\n .attr('width', availableWidth)\n .attr('height', availableHeight);\n\n lines\n .width(availableWidth)\n .height(availableHeight)\n .color(data.map(function(d,i) {\n return d.color || color(d, i);\n }).filter(function(d,i) { return !data[i].disabled; }));\n\n var linesWrap = g.select('.nv-linesWrap')\n .datum(data.filter(function(d) { return !d.disabled; }));\n\n\n // Setup Main (Focus) Axes\n if (showXAxis) {\n xAxis\n .scale(x)\n ._ticks(nv.utils.calcTicksX(availableWidth/100, data) )\n .tickSize(-availableHeight, 0);\n }\n\n if (showYAxis) {\n yAxis\n .scale(y)\n ._ticks( nv.utils.calcTicksY(availableHeight/36, data) )\n .tickSize( -availableWidth, 0);\n }\n\n //============================================================\n // Update Axes\n //============================================================\n function updateXAxis() {\n if(showXAxis) {\n g.select('.nv-focus .nv-x.nv-axis')\n .transition()\n .duration(duration)\n .call(xAxis)\n ;\n }\n }\n\n function updateYAxis() {\n if(showYAxis) {\n g.select('.nv-focus .nv-y.nv-axis')\n .transition()\n .duration(duration)\n .call(yAxis)\n ;\n }\n }\n\n g.select('.nv-focus .nv-x.nv-axis')\n .attr('transform', 'translate(0,' + availableHeight + ')');\n\n //============================================================\n // Update Focus\n //============================================================\n if(!focusEnable) {\n linesWrap.call(lines);\n updateXAxis();\n updateYAxis();\n } else {\n focus.width(availableWidth);\n g.select('.nv-focusWrap')\n .attr('transform', 'translate(0,' + ( availableHeight + margin.bottom + focus.margin().top) + ')')\n .datum(data.filter(function(d) { return !d.disabled; }))\n .call(focus);\n var extent = focus.brush.empty() ? focus.xDomain() : focus.brush.extent();\n if(extent !== null){\n onBrush(extent);\n }\n }\n //============================================================\n // Event Handling/Dispatching (in chart's scope)\n //------------------------------------------------------------\n\n legend.dispatch.on('stateChange', function(newState) {\n for (var key in newState)\n state[key] = newState[key];\n dispatch.stateChange(state);\n chart.update();\n });\n\n interactiveLayer.dispatch.on('elementMousemove', function(e) {\n lines.clearHighlights();\n var singlePoint, pointIndex, pointXLocation, allData = [];\n data\n .filter(function(series, i) {\n series.seriesIndex = i;\n return !series.disabled && !series.disableTooltip;\n })\n .forEach(function(series,i) {\n var extent = focusEnable ? (focus.brush.empty() ? focus.xScale().domain() : focus.brush.extent()) : x.domain();\n var currentValues = series.values.filter(function(d,i) {\n // Checks if the x point is between the extents, handling case where extent[0] is greater than extent[1]\n // (e.g. x domain is manually set to reverse the x-axis)\n if(extent[0] <= extent[1]) {\n return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1];\n } else {\n return lines.x()(d,i) >= extent[1] && lines.x()(d,i) <= extent[0];\n }\n });\n\n pointIndex = nv.interactiveBisect(currentValues, e.pointXValue, lines.x());\n var point = currentValues[pointIndex];\n var pointYValue = chart.y()(point, pointIndex);\n if (pointYValue !== null) {\n lines.highlightPoint(i, pointIndex, true);\n }\n if (point === undefined) return;\n if (singlePoint === undefined) singlePoint = point;\n if (pointXLocation === undefined) pointXLocation = chart.xScale()(chart.x()(point,pointIndex));\n allData.push({\n key: series.key,\n value: pointYValue,\n color: color(series,series.seriesIndex),\n data: point\n });\n });\n //Highlight the tooltip entry based on which point the mouse is closest to.\n if (allData.length > 2) {\n var yValue = chart.yScale().invert(e.mouseY);\n var domainExtent = Math.abs(chart.yScale().domain()[0] - chart.yScale().domain()[1]);\n var threshold = 0.03 * domainExtent;\n var indexToHighlight = nv.nearestValueIndex(allData.map(function(d){return d.value;}),yValue,threshold);\n if (indexToHighlight !== null)\n allData[indexToHighlight].highlight = true;\n }\n\n var defaultValueFormatter = function(d,i) {\n return d == null ? \"N/A\" : yAxis.tickFormat()(d);\n };\n\n interactiveLayer.tooltip\n .valueFormatter(interactiveLayer.tooltip.valueFormatter() || defaultValueFormatter)\n .data({\n value: chart.x()( singlePoint,pointIndex ),\n index: pointIndex,\n series: allData\n })();\n\n interactiveLayer.renderGuideLine(pointXLocation);\n\n });\n\n interactiveLayer.dispatch.on('elementClick', function(e) {\n var pointXLocation, allData = [];\n\n data.filter(function(series, i) {\n series.seriesIndex = i;\n return !series.disabled;\n }).forEach(function(series) {\n var pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x());\n var point = series.values[pointIndex];\n if (typeof point === 'undefined') return;\n if (typeof pointXLocation === 'undefined') pointXLocation = chart.xScale()(chart.x()(point,pointIndex));\n var yPos = chart.yScale()(chart.y()(point,pointIndex));\n allData.push({\n point: point,\n pointIndex: pointIndex,\n pos: [pointXLocation, yPos],\n seriesIndex: series.seriesIndex,\n series: series\n });\n });\n\n lines.dispatch.elementClick(allData);\n });\n\n interactiveLayer.dispatch.on(\"elementMouseout\",function(e) {\n lines.clearHighlights();\n });\n\n dispatch.on('changeState', function(e) {\n if (typeof e.disabled !== 'undefined' && data.length === e.disabled.length) {\n data.forEach(function(series,i) {\n series.disabled = e.disabled[i];\n });\n\n state.disabled = e.disabled;\n }\n chart.update();\n });\n\n //============================================================\n // Functions\n //------------------------------------------------------------\n\n // Taken from crossfilter (http://square.github.com/crossfilter/)\n function resizePath(d) {\n var e = +(d == 'e'),\n x = e ? 1 : -1,\n y = availableHeight / 3;\n return 'M' + (0.5 * x) + ',' + y\n + 'A6,6 0 0 ' + e + ' ' + (6.5 * x) + ',' + (y + 6)\n + 'V' + (2 * y - 6)\n + 'A6,6 0 0 ' + e + ' ' + (0.5 * x) + ',' + (2 * y)\n + 'Z'\n + 'M' + (2.5 * x) + ',' + (y + 8)\n + 'V' + (2 * y - 8)\n + 'M' + (4.5 * x) + ',' + (y + 8)\n + 'V' + (2 * y - 8);\n }\n\n function onBrush(extent) {\n // Update Main (Focus)\n var focusLinesWrap = g.select('.nv-focus .nv-linesWrap')\n .datum(\n data.filter(function(d) { return !d.disabled; })\n .map(function(d,i) {\n return {\n key: d.key,\n area: d.area,\n classed: d.classed,\n values: d.values.filter(function(d,i) {\n return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1];\n }),\n disableTooltip: d.disableTooltip\n };\n })\n );\n focusLinesWrap.transition().duration(duration).call(lines);\n\n // Update Main (Focus) Axes\n updateXAxis();\n updateYAxis();\n }\n });\n\n renderWatch.renderEnd('lineChart immediate');\n return chart;\n }\n\n\n //============================================================\n // Event Handling/Dispatching (out of chart's scope)\n //------------------------------------------------------------\n\n lines.dispatch.on('elementMouseover.tooltip', function(evt) {\n if(!evt.series.disableTooltip){\n tooltip.data(evt).hidden(false);\n }\n });\n\n lines.dispatch.on('elementMouseout.tooltip', function(evt) {\n tooltip.hidden(true);\n });\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n // expose chart's sub-components\n chart.dispatch = dispatch;\n chart.lines = lines;\n chart.legend = legend;\n chart.focus = focus;\n chart.xAxis = xAxis;\n chart.x2Axis = focus.xAxis\n chart.yAxis = yAxis;\n chart.y2Axis = focus.yAxis\n chart.interactiveLayer = interactiveLayer;\n chart.tooltip = tooltip;\n chart.state = state;\n chart.dispatch = dispatch;\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},\n legendPosition: {get: function(){return legendPosition;}, set: function(_){legendPosition=_;}},\n showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},\n showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},\n defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}},\n noData: {get: function(){return noData;}, set: function(_){noData=_;}},\n // Focus options, mostly passed onto focus model.\n focusEnable: {get: function(){return focusEnable;}, set: function(_){focusEnable=_;}},\n focusHeight: {get: function(){return focus.height();}, set: function(_){focus.height(_);}},\n focusShowAxisX: {get: function(){return focus.showXAxis();}, set: function(_){focus.showXAxis(_);}},\n focusShowAxisY: {get: function(){return focus.showYAxis();}, set: function(_){focus.showYAxis(_);}},\n brushExtent: {get: function(){return focus.brushExtent();}, set: function(_){focus.brushExtent(_);}},\n\n // options that require extra logic in the setter\n focusMargin: {get: function(){return focus.margin}, set: function(_){\n if (_.top !== undefined) {\n margin.top = _.top;\n marginTop = _.top;\n }\n focus.margin.right = _.right !== undefined ? _.right : focus.margin.right;\n focus.margin.bottom = _.bottom !== undefined ? _.bottom : focus.margin.bottom;\n focus.margin.left = _.left !== undefined ? _.left : focus.margin.left;\n }},\n margin: {get: function(){return margin;}, set: function(_){\n margin.top = _.top !== undefined ? _.top : margin.top;\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n }},\n duration: {get: function(){return duration;}, set: function(_){\n duration = _;\n renderWatch.reset(duration);\n lines.duration(duration);\n focus.duration(duration);\n xAxis.duration(duration);\n yAxis.duration(duration);\n }},\n color: {get: function(){return color;}, set: function(_){\n color = nv.utils.getColor(_);\n legend.color(color);\n lines.color(color);\n focus.color(color);\n }},\n interpolate: {get: function(){return lines.interpolate();}, set: function(_){\n lines.interpolate(_);\n focus.interpolate(_);\n }},\n xTickFormat: {get: function(){return xAxis.tickFormat();}, set: function(_){\n xAxis.tickFormat(_);\n focus.xTickFormat(_);\n }},\n yTickFormat: {get: function(){return yAxis.tickFormat();}, set: function(_){\n yAxis.tickFormat(_);\n focus.yTickFormat(_);\n }},\n x: {get: function(){return lines.x();}, set: function(_){\n lines.x(_);\n focus.x(_);\n }},\n y: {get: function(){return lines.y();}, set: function(_){\n lines.y(_);\n focus.y(_);\n }},\n rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){\n rightAlignYAxis = _;\n yAxis.orient( rightAlignYAxis ? 'right' : 'left');\n }},\n useInteractiveGuideline: {get: function(){return useInteractiveGuideline;}, set: function(_){\n useInteractiveGuideline = _;\n if (useInteractiveGuideline) {\n lines.interactive(false);\n lines.useVoronoi(false);\n }\n }}\n });\n\n nv.utils.inheritOptions(chart, lines);\n nv.utils.initOptions(chart);\n\n return chart;\n};\n\nnv.models.lineWithFocusChart = function() {\n return nv.models.lineChart()\n .margin({ bottom: 30 })\n .focusEnable( true );\n};\n","nv.models.linePlusBarChart = function() {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var lines = nv.models.line()\n , lines2 = nv.models.line()\n , bars = nv.models.historicalBar()\n , bars2 = nv.models.historicalBar()\n , xAxis = nv.models.axis()\n , x2Axis = nv.models.axis()\n , y1Axis = nv.models.axis()\n , y2Axis = nv.models.axis()\n , y3Axis = nv.models.axis()\n , y4Axis = nv.models.axis()\n , legend = nv.models.legend()\n , brush = d3.svg.brush()\n , tooltip = nv.models.tooltip()\n ;\n\n var margin = {top: 30, right: 30, bottom: 30, left: 60}\n , marginTop = null\n , margin2 = {top: 0, right: 30, bottom: 20, left: 60}\n , width = null\n , height = null\n , getX = function(d) { return d.x }\n , getY = function(d) { return d.y }\n , color = nv.utils.defaultColor()\n , showLegend = true\n , focusEnable = true\n , focusShowAxisY = false\n , focusShowAxisX = true\n , focusHeight = 50\n , extent\n , brushExtent = null\n , x\n , x2\n , y1\n , y2\n , y3\n , y4\n , noData = null\n , dispatch = d3.dispatch('brush', 'stateChange', 'changeState')\n , transitionDuration = 0\n , state = nv.utils.state()\n , defaultState = null\n , legendLeftAxisHint = ' (left axis)'\n , legendRightAxisHint = ' (right axis)'\n , switchYAxisOrder = false\n ;\n\n lines.clipEdge(true);\n lines2.interactive(false);\n // We don't want any points emitted for the focus chart's scatter graph.\n lines2.pointActive(function(d) { return false });\n xAxis.orient('bottom').tickPadding(5);\n y1Axis.orient('left');\n y2Axis.orient('right');\n x2Axis.orient('bottom').tickPadding(5);\n y3Axis.orient('left');\n y4Axis.orient('right');\n\n tooltip.headerEnabled(true).headerFormatter(function(d, i) {\n return xAxis.tickFormat()(d, i);\n });\n\n //============================================================\n // Private Variables\n //------------------------------------------------------------\n\n var getBarsAxis = function() {\n return switchYAxisOrder\n ? { main: y2Axis, focus: y4Axis }\n : { main: y1Axis, focus: y3Axis }\n }\n\n var getLinesAxis = function() {\n return switchYAxisOrder\n ? { main: y1Axis, focus: y3Axis }\n : { main: y2Axis, focus: y4Axis }\n }\n\n var stateGetter = function(data) {\n return function(){\n return {\n active: data.map(function(d) { return !d.disabled })\n };\n }\n };\n\n var stateSetter = function(data) {\n return function(state) {\n if (state.active !== undefined)\n data.forEach(function(series,i) {\n series.disabled = !state.active[i];\n });\n }\n };\n\n var allDisabled = function(data) {\n return data.every(function(series) {\n return series.disabled;\n });\n }\n\n function chart(selection) {\n selection.each(function(data) {\n var container = d3.select(this),\n that = this;\n nv.utils.initSVG(container);\n var availableWidth = nv.utils.availableWidth(width, container, margin),\n availableHeight1 = nv.utils.availableHeight(height, container, margin)\n - (focusEnable ? focusHeight : 0),\n availableHeight2 = focusHeight - margin2.top - margin2.bottom;\n\n chart.update = function() { container.transition().duration(transitionDuration).call(chart); };\n chart.container = this;\n\n state\n .setter(stateSetter(data), chart.update)\n .getter(stateGetter(data))\n .update();\n\n // DEPRECATED set state.disableddisabled\n state.disabled = data.map(function(d) { return !!d.disabled });\n\n if (!defaultState) {\n var key;\n defaultState = {};\n for (key in state) {\n if (state[key] instanceof Array)\n defaultState[key] = state[key].slice(0);\n else\n defaultState[key] = state[key];\n }\n }\n\n // Display No Data message if there's nothing to show.\n if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {\n nv.utils.noData(chart, container)\n return chart;\n } else {\n container.selectAll('.nv-noData').remove();\n }\n\n // Setup Scales\n var dataBars = data.filter(function(d) { return !d.disabled && d.bar });\n var dataLines = data.filter(function(d) { return !d.bar }); // removed the !d.disabled clause here to fix Issue #240\n\n if (dataBars.length && !switchYAxisOrder) {\n x = bars.xScale();\n } else {\n x = lines.xScale();\n }\n\n x2 = x2Axis.scale();\n\n // select the scales and series based on the position of the yAxis\n y1 = switchYAxisOrder ? lines.yScale() : bars.yScale();\n y2 = switchYAxisOrder ? bars.yScale() : lines.yScale();\n y3 = switchYAxisOrder ? lines2.yScale() : bars2.yScale();\n y4 = switchYAxisOrder ? bars2.yScale() : lines2.yScale();\n\n var series1 = data\n .filter(function(d) { return !d.disabled && (switchYAxisOrder ? !d.bar : d.bar) })\n .map(function(d) {\n return d.values.map(function(d,i) {\n return { x: getX(d,i), y: getY(d,i) }\n })\n });\n\n var series2 = data\n .filter(function(d) { return !d.disabled && (switchYAxisOrder ? d.bar : !d.bar) })\n .map(function(d) {\n return d.values.map(function(d,i) {\n return { x: getX(d,i), y: getY(d,i) }\n })\n });\n\n x.range([0, availableWidth]);\n\n x2 .domain(d3.extent(d3.merge(series1.concat(series2)), function(d) { return d.x } ))\n .range([0, availableWidth]);\n\n // Setup containers and skeleton of chart\n var wrap = container.selectAll('g.nv-wrap.nv-linePlusBar').data([data]);\n var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-linePlusBar').append('g');\n var g = wrap.select('g');\n\n gEnter.append('g').attr('class', 'nv-legendWrap');\n\n // this is the main chart\n var focusEnter = gEnter.append('g').attr('class', 'nv-focus');\n focusEnter.append('g').attr('class', 'nv-x nv-axis');\n focusEnter.append('g').attr('class', 'nv-y1 nv-axis');\n focusEnter.append('g').attr('class', 'nv-y2 nv-axis');\n focusEnter.append('g').attr('class', 'nv-barsWrap');\n focusEnter.append('g').attr('class', 'nv-linesWrap');\n\n // context chart is where you can focus in\n var contextEnter = gEnter.append('g').attr('class', 'nv-context');\n contextEnter.append('g').attr('class', 'nv-x nv-axis');\n contextEnter.append('g').attr('class', 'nv-y1 nv-axis');\n contextEnter.append('g').attr('class', 'nv-y2 nv-axis');\n contextEnter.append('g').attr('class', 'nv-barsWrap');\n contextEnter.append('g').attr('class', 'nv-linesWrap');\n contextEnter.append('g').attr('class', 'nv-brushBackground');\n contextEnter.append('g').attr('class', 'nv-x nv-brush');\n\n //============================================================\n // Legend\n //------------------------------------------------------------\n\n if (!showLegend) {\n g.select('.nv-legendWrap').selectAll('*').remove();\n } else {\n var legendWidth = legend.align() ? availableWidth / 2 : availableWidth;\n var legendXPosition = legend.align() ? legendWidth : 0;\n\n legend.width(legendWidth);\n\n g.select('.nv-legendWrap')\n .datum(data.map(function(series) {\n series.originalKey = series.originalKey === undefined ? series.key : series.originalKey;\n if(switchYAxisOrder) {\n series.key = series.originalKey + (series.bar ? legendRightAxisHint : legendLeftAxisHint);\n } else {\n series.key = series.originalKey + (series.bar ? legendLeftAxisHint : legendRightAxisHint);\n }\n return series;\n }))\n .call(legend);\n\n if (!marginTop && legend.height() !== margin.top) {\n margin.top = legend.height();\n // FIXME: shouldn't this be \"- (focusEnabled ? focusHeight : 0)\"?\n availableHeight1 = nv.utils.availableHeight(height, container, margin) - focusHeight;\n }\n\n g.select('.nv-legendWrap')\n .attr('transform', 'translate(' + legendXPosition + ',' + (-margin.top) +')');\n }\n\n wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');\n\n //============================================================\n // Context chart (focus chart) components\n //------------------------------------------------------------\n\n // hide or show the focus context chart\n g.select('.nv-context').style('display', focusEnable ? 'initial' : 'none');\n\n bars2\n .width(availableWidth)\n .height(availableHeight2)\n .color(data.map(function (d, i) {\n return d.color || color(d, i);\n }).filter(function (d, i) {\n return !data[i].disabled && data[i].bar\n }));\n lines2\n .width(availableWidth)\n .height(availableHeight2)\n .color(data.map(function (d, i) {\n return d.color || color(d, i);\n }).filter(function (d, i) {\n return !data[i].disabled && !data[i].bar\n }));\n\n var bars2Wrap = g.select('.nv-context .nv-barsWrap')\n .datum(dataBars.length ? dataBars : [\n {values: []}\n ]);\n var lines2Wrap = g.select('.nv-context .nv-linesWrap')\n .datum(allDisabled(dataLines) ?\n [{values: []}] :\n dataLines.filter(function(dataLine) {\n return !dataLine.disabled;\n }));\n\n g.select('.nv-context')\n .attr('transform', 'translate(0,' + ( availableHeight1 + margin.bottom + margin2.top) + ')');\n\n bars2Wrap.transition().call(bars2);\n lines2Wrap.transition().call(lines2);\n\n // context (focus chart) axis controls\n if (focusShowAxisX) {\n x2Axis\n ._ticks( nv.utils.calcTicksX(availableWidth / 100, data))\n .tickSize(-availableHeight2, 0);\n g.select('.nv-context .nv-x.nv-axis')\n .attr('transform', 'translate(0,' + y3.range()[0] + ')');\n g.select('.nv-context .nv-x.nv-axis').transition()\n .call(x2Axis);\n }\n\n if (focusShowAxisY) {\n y3Axis\n .scale(y3)\n ._ticks( availableHeight2 / 36 )\n .tickSize( -availableWidth, 0);\n y4Axis\n .scale(y4)\n ._ticks( availableHeight2 / 36 )\n .tickSize(dataBars.length ? 0 : -availableWidth, 0); // Show the y2 rules only if y1 has none\n\n g.select('.nv-context .nv-y3.nv-axis')\n .style('opacity', dataBars.length ? 1 : 0)\n .attr('transform', 'translate(0,' + x2.range()[0] + ')');\n g.select('.nv-context .nv-y2.nv-axis')\n .style('opacity', dataLines.length ? 1 : 0)\n .attr('transform', 'translate(' + x2.range()[1] + ',0)');\n\n g.select('.nv-context .nv-y1.nv-axis').transition()\n .call(y3Axis);\n g.select('.nv-context .nv-y2.nv-axis').transition()\n .call(y4Axis);\n }\n\n // Setup Brush\n brush.x(x2).on('brush', onBrush);\n\n if (brushExtent) brush.extent(brushExtent);\n\n var brushBG = g.select('.nv-brushBackground').selectAll('g')\n .data([brushExtent || brush.extent()]);\n\n var brushBGenter = brushBG.enter()\n .append('g');\n\n brushBGenter.append('rect')\n .attr('class', 'left')\n .attr('x', 0)\n .attr('y', 0)\n .attr('height', availableHeight2);\n\n brushBGenter.append('rect')\n .attr('class', 'right')\n .attr('x', 0)\n .attr('y', 0)\n .attr('height', availableHeight2);\n\n var gBrush = g.select('.nv-x.nv-brush')\n .call(brush);\n gBrush.selectAll('rect')\n //.attr('y', -5)\n .attr('height', availableHeight2);\n gBrush.selectAll('.resize').append('path').attr('d', resizePath);\n\n //============================================================\n // Event Handling/Dispatching (in chart's scope)\n //------------------------------------------------------------\n\n legend.dispatch.on('stateChange', function(newState) {\n for (var key in newState)\n state[key] = newState[key];\n dispatch.stateChange(state);\n chart.update();\n });\n\n // Update chart from a state object passed to event handler\n dispatch.on('changeState', function(e) {\n if (typeof e.disabled !== 'undefined') {\n data.forEach(function(series,i) {\n series.disabled = e.disabled[i];\n });\n state.disabled = e.disabled;\n }\n chart.update();\n });\n\n //============================================================\n // Functions\n //------------------------------------------------------------\n\n // Taken from crossfilter (http://square.github.com/crossfilter/)\n function resizePath(d) {\n var e = +(d == 'e'),\n x = e ? 1 : -1,\n y = availableHeight2 / 3;\n return 'M' + (.5 * x) + ',' + y\n + 'A6,6 0 0 ' + e + ' ' + (6.5 * x) + ',' + (y + 6)\n + 'V' + (2 * y - 6)\n + 'A6,6 0 0 ' + e + ' ' + (.5 * x) + ',' + (2 * y)\n + 'Z'\n + 'M' + (2.5 * x) + ',' + (y + 8)\n + 'V' + (2 * y - 8)\n + 'M' + (4.5 * x) + ',' + (y + 8)\n + 'V' + (2 * y - 8);\n }\n\n\n function updateBrushBG() {\n if (!brush.empty()) brush.extent(brushExtent);\n brushBG\n .data([brush.empty() ? x2.domain() : brushExtent])\n .each(function(d,i) {\n var leftWidth = x2(d[0]) - x2.range()[0],\n rightWidth = x2.range()[1] - x2(d[1]);\n d3.select(this).select('.left')\n .attr('width', leftWidth < 0 ? 0 : leftWidth);\n\n d3.select(this).select('.right')\n .attr('x', x2(d[1]))\n .attr('width', rightWidth < 0 ? 0 : rightWidth);\n });\n }\n\n function onBrush() {\n brushExtent = brush.empty() ? null : brush.extent();\n extent = brush.empty() ? x2.domain() : brush.extent();\n dispatch.brush({extent: extent, brush: brush});\n updateBrushBG();\n\n // Prepare Main (Focus) Bars and Lines\n bars\n .width(availableWidth)\n .height(availableHeight1)\n .color(data.map(function(d,i) {\n return d.color || color(d, i);\n }).filter(function(d,i) { return !data[i].disabled && data[i].bar }));\n\n lines\n .width(availableWidth)\n .height(availableHeight1)\n .color(data.map(function(d,i) {\n return d.color || color(d, i);\n }).filter(function(d,i) { return !data[i].disabled && !data[i].bar }));\n\n var focusBarsWrap = g.select('.nv-focus .nv-barsWrap')\n .datum(!dataBars.length ? [{values:[]}] :\n dataBars\n .map(function(d,i) {\n return {\n key: d.key,\n values: d.values.filter(function(d,i) {\n return bars.x()(d,i) >= extent[0] && bars.x()(d,i) <= extent[1];\n })\n }\n })\n );\n\n var focusLinesWrap = g.select('.nv-focus .nv-linesWrap')\n .datum(allDisabled(dataLines) ? [{values:[]}] :\n dataLines\n .filter(function(dataLine) { return !dataLine.disabled; })\n .map(function(d,i) {\n return {\n area: d.area,\n fillOpacity: d.fillOpacity,\n strokeWidth: d.strokeWidth,\n key: d.key,\n values: d.values.filter(function(d,i) {\n return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1];\n })\n }\n })\n );\n\n // Update Main (Focus) X Axis\n if (dataBars.length && !switchYAxisOrder) {\n x = bars.xScale();\n } else {\n x = lines.xScale();\n }\n\n xAxis\n .scale(x)\n ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )\n .tickSize(-availableHeight1, 0);\n\n xAxis.domain([Math.ceil(extent[0]), Math.floor(extent[1])]);\n\n g.select('.nv-x.nv-axis').transition().duration(transitionDuration)\n .call(xAxis);\n\n // Update Main (Focus) Bars and Lines\n focusBarsWrap.transition().duration(transitionDuration).call(bars);\n focusLinesWrap.transition().duration(transitionDuration).call(lines);\n\n // Setup and Update Main (Focus) Y Axes\n g.select('.nv-focus .nv-x.nv-axis')\n .attr('transform', 'translate(0,' + y1.range()[0] + ')');\n\n y1Axis\n .scale(y1)\n ._ticks( nv.utils.calcTicksY(availableHeight1/36, data) )\n .tickSize(-availableWidth, 0);\n y2Axis\n .scale(y2)\n ._ticks( nv.utils.calcTicksY(availableHeight1/36, data) );\n\n // Show the y2 rules only if y1 has none\n if(!switchYAxisOrder) {\n y2Axis.tickSize(dataBars.length ? 0 : -availableWidth, 0);\n } else {\n y2Axis.tickSize(dataLines.length ? 0 : -availableWidth, 0);\n }\n\n // Calculate opacity of the axis\n var barsOpacity = dataBars.length ? 1 : 0;\n var linesOpacity = dataLines.length && !allDisabled(dataLines) ? 1 : 0;\n\n var y1Opacity = switchYAxisOrder ? linesOpacity : barsOpacity;\n var y2Opacity = switchYAxisOrder ? barsOpacity : linesOpacity;\n\n g.select('.nv-focus .nv-y1.nv-axis')\n .style('opacity', y1Opacity);\n g.select('.nv-focus .nv-y2.nv-axis')\n .style('opacity', y2Opacity)\n .attr('transform', 'translate(' + x.range()[1] + ',0)');\n\n g.select('.nv-focus .nv-y1.nv-axis').transition().duration(transitionDuration)\n .call(y1Axis);\n g.select('.nv-focus .nv-y2.nv-axis').transition().duration(transitionDuration)\n .call(y2Axis);\n }\n\n onBrush();\n\n });\n\n return chart;\n }\n\n //============================================================\n // Event Handling/Dispatching (out of chart's scope)\n //------------------------------------------------------------\n\n lines.dispatch.on('elementMouseover.tooltip', function(evt) {\n tooltip\n .duration(100)\n .valueFormatter(function(d, i) {\n return getLinesAxis().main.tickFormat()(d, i);\n })\n .data(evt)\n .hidden(false);\n });\n\n lines.dispatch.on('elementMouseout.tooltip', function(evt) {\n tooltip.hidden(true)\n });\n\n bars.dispatch.on('elementMouseover.tooltip', function(evt) {\n evt.value = chart.x()(evt.data);\n evt['series'] = {\n value: chart.y()(evt.data),\n color: evt.color\n };\n tooltip\n .duration(0)\n .valueFormatter(function(d, i) {\n return getBarsAxis().main.tickFormat()(d, i);\n })\n .data(evt)\n .hidden(false);\n });\n\n bars.dispatch.on('elementMouseout.tooltip', function(evt) {\n tooltip.hidden(true);\n });\n\n bars.dispatch.on('elementMousemove.tooltip', function(evt) {\n tooltip();\n });\n\n //============================================================\n\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n // expose chart's sub-components\n chart.dispatch = dispatch;\n chart.legend = legend;\n chart.lines = lines;\n chart.lines2 = lines2;\n chart.bars = bars;\n chart.bars2 = bars2;\n chart.xAxis = xAxis;\n chart.x2Axis = x2Axis;\n chart.y1Axis = y1Axis;\n chart.y2Axis = y2Axis;\n chart.y3Axis = y3Axis;\n chart.y4Axis = y4Axis;\n chart.tooltip = tooltip;\n\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},\n brushExtent: {get: function(){return brushExtent;}, set: function(_){brushExtent=_;}},\n noData: {get: function(){return noData;}, set: function(_){noData=_;}},\n focusEnable: {get: function(){return focusEnable;}, set: function(_){focusEnable=_;}},\n focusHeight: {get: function(){return focusHeight;}, set: function(_){focusHeight=_;}},\n focusShowAxisX: {get: function(){return focusShowAxisX;}, set: function(_){focusShowAxisX=_;}},\n focusShowAxisY: {get: function(){return focusShowAxisY;}, set: function(_){focusShowAxisY=_;}},\n legendLeftAxisHint: {get: function(){return legendLeftAxisHint;}, set: function(_){legendLeftAxisHint=_;}},\n legendRightAxisHint: {get: function(){return legendRightAxisHint;}, set: function(_){legendRightAxisHint=_;}},\n\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n if (_.top !== undefined) {\n margin.top = _.top;\n marginTop = _.top;\n }\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n }},\n focusMargin: {get: function(){return margin2;}, set: function(_){\n margin2.top = _.top !== undefined ? _.top : margin2.top;\n margin2.right = _.right !== undefined ? _.right : margin2.right;\n margin2.bottom = _.bottom !== undefined ? _.bottom : margin2.bottom;\n margin2.left = _.left !== undefined ? _.left : margin2.left;\n }},\n duration: {get: function(){return transitionDuration;}, set: function(_){\n transitionDuration = _;\n }},\n color: {get: function(){return color;}, set: function(_){\n color = nv.utils.getColor(_);\n legend.color(color);\n }},\n x: {get: function(){return getX;}, set: function(_){\n getX = _;\n lines.x(_);\n lines2.x(_);\n bars.x(_);\n bars2.x(_);\n }},\n y: {get: function(){return getY;}, set: function(_){\n getY = _;\n lines.y(_);\n lines2.y(_);\n bars.y(_);\n bars2.y(_);\n }},\n switchYAxisOrder: {get: function(){return switchYAxisOrder;}, set: function(_){\n // Switch the tick format for the yAxis\n if(switchYAxisOrder !== _) {\n var y1 = y1Axis;\n y1Axis = y2Axis;\n y2Axis = y1;\n\n var y3 = y3Axis;\n y3Axis = y4Axis;\n y4Axis = y3;\n }\n switchYAxisOrder=_;\n\n y1Axis.orient('left');\n y2Axis.orient('right');\n y3Axis.orient('left');\n y4Axis.orient('right');\n }}\n });\n\n nv.utils.inheritOptions(chart, lines);\n nv.utils.initOptions(chart);\n\n return chart;\n};\n","\nnv.models.multiBar = function() {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var margin = {top: 0, right: 0, bottom: 0, left: 0}\n , width = 960\n , height = 500\n , x = d3.scale.ordinal()\n , y = d3.scale.linear()\n , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one\n , container = null\n , getX = function(d) { return d.x }\n , getY = function(d) { return d.y }\n , forceY = [0] // 0 is forced by default.. this makes sense for the majority of bar graphs... user can always do chart.forceY([]) to remove\n , clipEdge = true\n , stacked = false\n , stackOffset = 'zero' // options include 'silhouette', 'wiggle', 'expand', 'zero', or a custom function\n , color = nv.utils.defaultColor()\n , hideable = false\n , barColor = null // adding the ability to set the color for each rather than the whole group\n , disabled // used in conjunction with barColor to communicate from multiBarHorizontalChart what series are disabled\n , duration = 500\n , xDomain\n , yDomain\n , xRange\n , yRange\n , groupSpacing = 0.1\n , fillOpacity = 0.75\n , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd')\n ;\n\n //============================================================\n // Private Variables\n //------------------------------------------------------------\n\n var x0, y0 //used to store previous scales\n , renderWatch = nv.utils.renderWatch(dispatch, duration)\n ;\n\n var last_datalength = 0;\n\n function chart(selection) {\n renderWatch.reset();\n selection.each(function(data) {\n var availableWidth = width - margin.left - margin.right,\n availableHeight = height - margin.top - margin.bottom;\n\n container = d3.select(this);\n nv.utils.initSVG(container);\n var nonStackableCount = 0;\n // This function defines the requirements for render complete\n var endFn = function(d, i) {\n if (d.series === data.length - 1 && i === data[0].values.length - 1)\n return true;\n return false;\n };\n\n if(hideable && data.length) hideable = [{\n values: data[0].values.map(function(d) {\n return {\n x: d.x,\n y: 0,\n series: d.series,\n size: 0.01\n };}\n )}];\n\n if (stacked) {\n var parsed = d3.layout.stack()\n .offset(stackOffset)\n .values(function(d){ return d.values })\n .y(getY)\n (!data.length && hideable ? hideable : data);\n\n parsed.forEach(function(series, i){\n // if series is non-stackable, use un-parsed data\n if (series.nonStackable) {\n data[i].nonStackableSeries = nonStackableCount++;\n parsed[i] = data[i];\n } else {\n // don't stack this seires on top of the nonStackable seriees\n if (i > 0 && parsed[i - 1].nonStackable){\n parsed[i].values.map(function(d,j){\n d.y0 -= parsed[i - 1].values[j].y;\n d.y1 = d.y0 + d.y;\n });\n }\n }\n });\n data = parsed;\n }\n //add series index and key to each data point for reference\n data.forEach(function(series, i) {\n series.values.forEach(function(point) {\n point.series = i;\n point.key = series.key;\n });\n });\n\n // HACK for negative value stacking\n if (stacked && data.length > 0) {\n data[0].values.map(function(d,i) {\n var posBase = 0, negBase = 0;\n data.map(function(d, idx) {\n if (!data[idx].nonStackable) {\n var f = d.values[i]\n f.size = Math.abs(f.y);\n if (f.y<0) {\n f.y1 = negBase;\n negBase = negBase - f.size;\n } else\n {\n f.y1 = f.size + posBase;\n posBase = posBase + f.size;\n }\n }\n\n });\n });\n }\n // Setup Scales\n // remap and flatten the data for use in calculating the scales' domains\n var seriesData = (xDomain && yDomain) ? [] : // if we know xDomain and yDomain, no need to calculate\n data.map(function(d, idx) {\n return d.values.map(function(d,i) {\n return { x: getX(d,i), y: getY(d,i), y0: d.y0, y1: d.y1, idx:idx }\n })\n });\n\n x.domain(xDomain || d3.merge(seriesData).map(function(d) { return d.x }))\n .rangeBands(xRange || [0, availableWidth], groupSpacing);\n\n y.domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) {\n var domain = d.y;\n // increase the domain range if this series is stackable\n if (stacked && !data[d.idx].nonStackable) {\n if (d.y > 0){\n domain = d.y1\n } else {\n domain = d.y1 + d.y\n }\n }\n return domain;\n }).concat(forceY)))\n .range(yRange || [availableHeight, 0]);\n\n // If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point\n if (x.domain()[0] === x.domain()[1])\n x.domain()[0] ?\n x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01])\n : x.domain([-1,1]);\n\n if (y.domain()[0] === y.domain()[1])\n y.domain()[0] ?\n y.domain([y.domain()[0] + y.domain()[0] * 0.01, y.domain()[1] - y.domain()[1] * 0.01])\n : y.domain([-1,1]);\n\n x0 = x0 || x;\n y0 = y0 || y;\n\n // Setup containers and skeleton of chart\n var wrap = container.selectAll('g.nv-wrap.nv-multibar').data([data]);\n var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-multibar');\n var defsEnter = wrapEnter.append('defs');\n var gEnter = wrapEnter.append('g');\n var g = wrap.select('g');\n\n gEnter.append('g').attr('class', 'nv-groups');\n wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');\n\n defsEnter.append('clipPath')\n .attr('id', 'nv-edge-clip-' + id)\n .append('rect');\n wrap.select('#nv-edge-clip-' + id + ' rect')\n .attr('width', availableWidth)\n .attr('height', availableHeight);\n\n g.attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : '');\n\n var groups = wrap.select('.nv-groups').selectAll('.nv-group')\n .data(function(d) { return d }, function(d,i) { return i });\n groups.enter().append('g')\n .style('stroke-opacity', 1e-6)\n .style('fill-opacity', 1e-6);\n\n var exitTransition = renderWatch\n .transition(groups.exit().selectAll('rect.nv-bar'), 'multibarExit', Math.min(100, duration))\n .attr('y', function(d, i, j) {\n var yVal = y0(0) || 0;\n if (stacked) {\n if (data[d.series] && !data[d.series].nonStackable) {\n yVal = y0(d.y0);\n }\n }\n return yVal;\n })\n .attr('height', 0)\n .remove();\n if (exitTransition.delay)\n exitTransition.delay(function(d,i) {\n var delay = i * (duration / (last_datalength + 1)) - i;\n return delay;\n });\n groups\n .attr('class', function(d,i) { return 'nv-group nv-series-' + i })\n .classed('hover', function(d) { return d.hover })\n .style('fill', function(d,i){ return color(d, i) })\n .style('stroke', function(d,i){ return color(d, i) });\n groups\n .style('stroke-opacity', 1)\n .style('fill-opacity', fillOpacity);\n\n var bars = groups.selectAll('rect.nv-bar')\n .data(function(d) { return (hideable && !data.length) ? hideable.values : d.values });\n bars.exit().remove();\n\n var barsEnter = bars.enter().append('rect')\n .attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive'})\n .attr('x', function(d,i,j) {\n return stacked && !data[j].nonStackable ? 0 : (j * x.rangeBand() / data.length )\n })\n .attr('y', function(d,i,j) { return y0(stacked && !data[j].nonStackable ? d.y0 : 0) || 0 })\n .attr('height', 0)\n .attr('width', function(d,i,j) { return x.rangeBand() / (stacked && !data[j].nonStackable ? 1 : data.length) })\n .attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',0)'; })\n ;\n bars\n .style('fill', function(d,i,j){ return color(d, j, i); })\n .style('stroke', function(d,i,j){ return color(d, j, i); })\n .on('mouseover', function(d,i) { //TODO: figure out why j works above, but not here\n d3.select(this).classed('hover', true);\n dispatch.elementMouseover({\n data: d,\n index: i,\n color: d3.select(this).style(\"fill\")\n });\n })\n .on('mouseout', function(d,i) {\n d3.select(this).classed('hover', false);\n dispatch.elementMouseout({\n data: d,\n index: i,\n color: d3.select(this).style(\"fill\")\n });\n })\n .on('mousemove', function(d,i) {\n dispatch.elementMousemove({\n data: d,\n index: i,\n color: d3.select(this).style(\"fill\")\n });\n })\n .on('click', function(d,i) {\n var element = this;\n dispatch.elementClick({\n data: d,\n index: i,\n color: d3.select(this).style(\"fill\"),\n event: d3.event,\n element: element\n });\n d3.event.stopPropagation();\n })\n .on('dblclick', function(d,i) {\n dispatch.elementDblClick({\n data: d,\n index: i,\n color: d3.select(this).style(\"fill\")\n });\n d3.event.stopPropagation();\n });\n bars\n .attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive'})\n .attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',0)'; })\n\n if (barColor) {\n if (!disabled) disabled = data.map(function() { return true });\n bars\n .style('fill', function(d,i,j) { return d3.rgb(barColor(d,i)).darker( disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i] })[j] ).toString(); })\n .style('stroke', function(d,i,j) { return d3.rgb(barColor(d,i)).darker( disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i] })[j] ).toString(); });\n }\n\n var barSelection =\n bars.watchTransition(renderWatch, 'multibar', Math.min(250, duration))\n .delay(function(d,i) {\n return i * duration / data[0].values.length;\n });\n if (stacked){\n barSelection\n .attr('y', function(d,i,j) {\n var yVal = 0;\n // if stackable, stack it on top of the previous series\n if (!data[j].nonStackable) {\n yVal = y(d.y1);\n } else {\n if (getY(d,i) < 0){\n yVal = y(0);\n } else {\n if (y(0) - y(getY(d,i)) < -1){\n yVal = y(0) - 1;\n } else {\n yVal = y(getY(d, i)) || 0;\n }\n }\n }\n return yVal;\n })\n .attr('height', function(d,i,j) {\n if (!data[j].nonStackable) {\n return Math.max(Math.abs(y(d.y+d.y0) - y(d.y0)), 0);\n } else {\n return Math.max(Math.abs(y(getY(d,i)) - y(0)), 0) || 0;\n }\n })\n .attr('x', function(d,i,j) {\n var width = 0;\n if (data[j].nonStackable) {\n width = d.series * x.rangeBand() / data.length;\n if (data.length !== nonStackableCount){\n width = data[j].nonStackableSeries * x.rangeBand()/(nonStackableCount*2);\n }\n }\n return width;\n })\n .attr('width', function(d,i,j){\n if (!data[j].nonStackable) {\n return x.rangeBand();\n } else {\n // if all series are nonStacable, take the full width\n var width = (x.rangeBand() / nonStackableCount);\n // otherwise, nonStackable graph will be only taking the half-width\n // of the x rangeBand\n if (data.length !== nonStackableCount) {\n width = x.rangeBand()/(nonStackableCount*2);\n }\n return width;\n }\n });\n }\n else {\n barSelection\n .attr('x', function(d,i) {\n return d.series * x.rangeBand() / data.length;\n })\n .attr('width', x.rangeBand() / data.length)\n .attr('y', function(d,i) {\n return getY(d,i) < 0 ?\n y(0) :\n y(0) - y(getY(d,i)) < 1 ?\n y(0) - 1 :\n y(getY(d,i)) || 0;\n })\n .attr('height', function(d,i) {\n return Math.max(Math.abs(y(getY(d,i)) - y(0)),1) || 0;\n });\n }\n\n //store old scales for use in transitions on update\n x0 = x.copy();\n y0 = y.copy();\n\n // keep track of the last data value length for transition calculations\n if (data[0] && data[0].values) {\n last_datalength = data[0].values.length;\n }\n\n });\n\n renderWatch.renderEnd('multibar immediate');\n\n return chart;\n }\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n chart.dispatch = dispatch;\n\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n x: {get: function(){return getX;}, set: function(_){getX=_;}},\n y: {get: function(){return getY;}, set: function(_){getY=_;}},\n xScale: {get: function(){return x;}, set: function(_){x=_;}},\n yScale: {get: function(){return y;}, set: function(_){y=_;}},\n xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}},\n yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}},\n xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}},\n yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}},\n forceY: {get: function(){return forceY;}, set: function(_){forceY=_;}},\n stacked: {get: function(){return stacked;}, set: function(_){stacked=_;}},\n stackOffset: {get: function(){return stackOffset;}, set: function(_){stackOffset=_;}},\n clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}},\n disabled: {get: function(){return disabled;}, set: function(_){disabled=_;}},\n id: {get: function(){return id;}, set: function(_){id=_;}},\n hideable: {get: function(){return hideable;}, set: function(_){hideable=_;}},\n groupSpacing:{get: function(){return groupSpacing;}, set: function(_){groupSpacing=_;}},\n fillOpacity: {get: function(){return fillOpacity;}, set: function(_){fillOpacity=_;}},\n\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n margin.top = _.top !== undefined ? _.top : margin.top;\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n }},\n duration: {get: function(){return duration;}, set: function(_){\n duration = _;\n renderWatch.reset(duration);\n }},\n color: {get: function(){return color;}, set: function(_){\n color = nv.utils.getColor(_);\n }},\n barColor: {get: function(){return barColor;}, set: function(_){\n barColor = _ ? nv.utils.getColor(_) : null;\n }}\n });\n\n nv.utils.initOptions(chart);\n\n return chart;\n};\n","nv.models.multiBarChart = function() {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var multibar = nv.models.multiBar()\n , xAxis = nv.models.axis()\n , yAxis = nv.models.axis()\n , interactiveLayer = nv.interactiveGuideline()\n , legend = nv.models.legend()\n , controls = nv.models.legend()\n , tooltip = nv.models.tooltip()\n ;\n\n var margin = {top: 30, right: 20, bottom: 50, left: 60}\n , marginTop = null\n , width = null\n , height = null\n , color = nv.utils.defaultColor()\n , showControls = true\n , controlLabels = {}\n , showLegend = true\n , showXAxis = true\n , showYAxis = true\n , rightAlignYAxis = false\n , reduceXTicks = true // if false a tick will show for every data point\n , staggerLabels = false\n , wrapLabels = false\n , rotateLabels = 0\n , x //can be accessed via chart.xScale()\n , y //can be accessed via chart.yScale()\n , state = nv.utils.state()\n , defaultState = null\n , noData = null\n , dispatch = d3.dispatch('stateChange', 'changeState', 'renderEnd')\n , controlWidth = function() { return showControls ? 180 : 0 }\n , duration = 250\n , useInteractiveGuideline = false\n ;\n\n state.stacked = false // DEPRECATED Maintained for backward compatibility\n\n multibar.stacked(false);\n xAxis\n .orient('bottom')\n .tickPadding(7)\n .showMaxMin(false)\n .tickFormat(function(d) { return d })\n ;\n yAxis\n .orient((rightAlignYAxis) ? 'right' : 'left')\n .tickFormat(d3.format(',.1f'))\n ;\n\n tooltip\n .duration(0)\n .valueFormatter(function(d, i) {\n return yAxis.tickFormat()(d, i);\n })\n .headerFormatter(function(d, i) {\n return xAxis.tickFormat()(d, i);\n });\n\n interactiveLayer.tooltip\n .valueFormatter(function(d, i) {\n return d == null ? \"N/A\" : yAxis.tickFormat()(d, i);\n })\n .headerFormatter(function(d, i) {\n return xAxis.tickFormat()(d, i);\n });\n\n interactiveLayer.tooltip\n .valueFormatter(function (d, i) {\n return d == null ? \"N/A\" : yAxis.tickFormat()(d, i);\n })\n .headerFormatter(function (d, i) {\n return xAxis.tickFormat()(d, i);\n });\n\n interactiveLayer.tooltip\n .duration(0)\n .valueFormatter(function(d, i) {\n return yAxis.tickFormat()(d, i);\n })\n .headerFormatter(function(d, i) {\n return xAxis.tickFormat()(d, i);\n });\n\n controls.updateState(false);\n\n //============================================================\n // Private Variables\n //------------------------------------------------------------\n\n var renderWatch = nv.utils.renderWatch(dispatch);\n var stacked = false;\n\n var stateGetter = function(data) {\n return function(){\n return {\n active: data.map(function(d) { return !d.disabled }),\n stacked: stacked\n };\n }\n };\n\n var stateSetter = function(data) {\n return function(state) {\n if (state.stacked !== undefined)\n stacked = state.stacked;\n if (state.active !== undefined)\n data.forEach(function(series,i) {\n series.disabled = !state.active[i];\n });\n }\n };\n\n function chart(selection) {\n renderWatch.reset();\n renderWatch.models(multibar);\n if (showXAxis) renderWatch.models(xAxis);\n if (showYAxis) renderWatch.models(yAxis);\n\n selection.each(function(data) {\n var container = d3.select(this),\n that = this;\n nv.utils.initSVG(container);\n var availableWidth = nv.utils.availableWidth(width, container, margin),\n availableHeight = nv.utils.availableHeight(height, container, margin);\n\n chart.update = function() {\n if (duration === 0)\n container.call(chart);\n else\n container.transition()\n .duration(duration)\n .call(chart);\n };\n chart.container = this;\n\n state\n .setter(stateSetter(data), chart.update)\n .getter(stateGetter(data))\n .update();\n\n // DEPRECATED set state.disableddisabled\n state.disabled = data.map(function(d) { return !!d.disabled });\n\n if (!defaultState) {\n var key;\n defaultState = {};\n for (key in state) {\n if (state[key] instanceof Array)\n defaultState[key] = state[key].slice(0);\n else\n defaultState[key] = state[key];\n }\n }\n\n // Display noData message if there's nothing to show.\n if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {\n nv.utils.noData(chart, container)\n return chart;\n } else {\n container.selectAll('.nv-noData').remove();\n }\n\n // Setup Scales\n x = multibar.xScale();\n y = multibar.yScale();\n\n // Setup containers and skeleton of chart\n var wrap = container.selectAll('g.nv-wrap.nv-multiBarWithLegend').data([data]);\n var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-multiBarWithLegend').append('g');\n var g = wrap.select('g');\n\n gEnter.append('g').attr('class', 'nv-x nv-axis');\n gEnter.append('g').attr('class', 'nv-y nv-axis');\n gEnter.append('g').attr('class', 'nv-barsWrap');\n gEnter.append('g').attr('class', 'nv-legendWrap');\n gEnter.append('g').attr('class', 'nv-controlsWrap');\n gEnter.append('g').attr('class', 'nv-interactive');\n\n // Legend\n if (!showLegend) {\n g.select('.nv-legendWrap').selectAll('*').remove();\n } else {\n legend.width(availableWidth - controlWidth());\n\n g.select('.nv-legendWrap')\n .datum(data)\n .call(legend);\n\n if (!marginTop && legend.height() !== margin.top) {\n margin.top = legend.height();\n availableHeight = nv.utils.availableHeight(height, container, margin);\n }\n\n g.select('.nv-legendWrap')\n .attr('transform', 'translate(' + controlWidth() + ',' + (-margin.top) +')');\n }\n\n // Controls\n if (!showControls) {\n g.select('.nv-controlsWrap').selectAll('*').remove();\n } else {\n var controlsData = [\n { key: controlLabels.grouped || 'Grouped', disabled: multibar.stacked() },\n { key: controlLabels.stacked || 'Stacked', disabled: !multibar.stacked() }\n ];\n\n controls.width(controlWidth()).color(['#444', '#444', '#444']);\n g.select('.nv-controlsWrap')\n .datum(controlsData)\n .attr('transform', 'translate(0,' + (-margin.top) +')')\n .call(controls);\n }\n\n wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');\n if (rightAlignYAxis) {\n g.select(\".nv-y.nv-axis\")\n .attr(\"transform\", \"translate(\" + availableWidth + \",0)\");\n }\n\n // Main Chart Component(s)\n multibar\n .disabled(data.map(function(series) { return series.disabled }))\n .width(availableWidth)\n .height(availableHeight)\n .color(data.map(function(d,i) {\n return d.color || color(d, i);\n }).filter(function(d,i) { return !data[i].disabled }));\n\n\n var barsWrap = g.select('.nv-barsWrap')\n .datum(data.filter(function(d) { return !d.disabled }));\n\n barsWrap.call(multibar);\n\n // Setup Axes\n if (showXAxis) {\n xAxis\n .scale(x)\n ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )\n .tickSize(-availableHeight, 0);\n\n g.select('.nv-x.nv-axis')\n .attr('transform', 'translate(0,' + y.range()[0] + ')');\n g.select('.nv-x.nv-axis')\n .call(xAxis);\n\n var xTicks = g.select('.nv-x.nv-axis > g').selectAll('g');\n\n xTicks\n .selectAll('line, text')\n .style('opacity', 1)\n\n if (staggerLabels) {\n var getTranslate = function(x,y) {\n return \"translate(\" + x + \",\" + y + \")\";\n };\n\n var staggerUp = 5, staggerDown = 17; //pixels to stagger by\n // Issue #140\n xTicks\n .selectAll(\"text\")\n .attr('transform', function(d,i,j) {\n return getTranslate(0, (j % 2 == 0 ? staggerUp : staggerDown));\n });\n\n var totalInBetweenTicks = d3.selectAll(\".nv-x.nv-axis .nv-wrap g g text\")[0].length;\n g.selectAll(\".nv-x.nv-axis .nv-axisMaxMin text\")\n .attr(\"transform\", function(d,i) {\n return getTranslate(0, (i === 0 || totalInBetweenTicks % 2 !== 0) ? staggerDown : staggerUp);\n });\n }\n\n if (wrapLabels) {\n g.selectAll('.tick text')\n .call(nv.utils.wrapTicks, chart.xAxis.rangeBand())\n }\n\n if (reduceXTicks)\n xTicks\n .filter(function(d,i) {\n return i % Math.ceil(data[0].values.length / (availableWidth / 100)) !== 0;\n })\n .selectAll('text, line')\n .style('opacity', 0);\n\n if(rotateLabels)\n xTicks\n .selectAll('.tick text')\n .attr('transform', 'rotate(' + rotateLabels + ' 0,0)')\n .style('text-anchor', rotateLabels > 0 ? 'start' : 'end');\n\n g.select('.nv-x.nv-axis').selectAll('g.nv-axisMaxMin text')\n .style('opacity', 1);\n }\n\n if (showYAxis) {\n yAxis\n .scale(y)\n ._ticks( nv.utils.calcTicksY(availableHeight/36, data) )\n .tickSize( -availableWidth, 0);\n\n g.select('.nv-y.nv-axis')\n .call(yAxis);\n }\n\n //Set up interactive layer\n if (useInteractiveGuideline) {\n interactiveLayer\n .width(availableWidth)\n .height(availableHeight)\n .margin({left:margin.left, top:margin.top})\n .svgContainer(container)\n .xScale(x);\n wrap.select(\".nv-interactive\").call(interactiveLayer);\n }\n\n //============================================================\n // Event Handling/Dispatching (in chart's scope)\n //------------------------------------------------------------\n\n legend.dispatch.on('stateChange', function(newState) {\n for (var key in newState)\n state[key] = newState[key];\n dispatch.stateChange(state);\n chart.update();\n });\n\n controls.dispatch.on('legendClick', function(d,i) {\n if (!d.disabled) return;\n controlsData = controlsData.map(function(s) {\n s.disabled = true;\n return s;\n });\n d.disabled = false;\n\n switch (d.key) {\n case 'Grouped':\n case controlLabels.grouped:\n multibar.stacked(false);\n break;\n case 'Stacked':\n case controlLabels.stacked:\n multibar.stacked(true);\n break;\n }\n\n state.stacked = multibar.stacked();\n dispatch.stateChange(state);\n chart.update();\n });\n\n // Update chart from a state object passed to event handler\n dispatch.on('changeState', function(e) {\n if (typeof e.disabled !== 'undefined') {\n data.forEach(function(series,i) {\n series.disabled = e.disabled[i];\n });\n state.disabled = e.disabled;\n }\n if (typeof e.stacked !== 'undefined') {\n multibar.stacked(e.stacked);\n state.stacked = e.stacked;\n stacked = e.stacked;\n }\n chart.update();\n });\n\n if (useInteractiveGuideline) {\n interactiveLayer.dispatch.on('elementMousemove', function(e) {\n if (e.pointXValue == undefined) return;\n\n var singlePoint, pointIndex, pointXLocation, xValue, allData = [];\n data\n .filter(function(series, i) {\n series.seriesIndex = i;\n return !series.disabled;\n })\n .forEach(function(series,i) {\n pointIndex = x.domain().indexOf(e.pointXValue)\n\n var point = series.values[pointIndex];\n if (point === undefined) return;\n\n xValue = point.x;\n if (singlePoint === undefined) singlePoint = point;\n if (pointXLocation === undefined) pointXLocation = e.mouseX\n allData.push({\n key: series.key,\n value: chart.y()(point, pointIndex),\n color: color(series,series.seriesIndex),\n data: series.values[pointIndex]\n });\n });\n\n interactiveLayer.tooltip\n .data({\n value: xValue,\n index: pointIndex,\n series: allData\n })();\n\n interactiveLayer.renderGuideLine(pointXLocation);\n });\n\n interactiveLayer.dispatch.on(\"elementMouseout\",function(e) {\n interactiveLayer.tooltip.hidden(true);\n });\n }\n else {\n multibar.dispatch.on('elementMouseover.tooltip', function(evt) {\n evt.value = chart.x()(evt.data);\n evt['series'] = {\n key: evt.data.key,\n value: chart.y()(evt.data),\n color: evt.color\n };\n tooltip.data(evt).hidden(false);\n });\n\n multibar.dispatch.on('elementMouseout.tooltip', function(evt) {\n tooltip.hidden(true);\n });\n\n multibar.dispatch.on('elementMousemove.tooltip', function(evt) {\n tooltip();\n });\n }\n });\n\n renderWatch.renderEnd('multibarchart immediate');\n return chart;\n }\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n // expose chart's sub-components\n chart.dispatch = dispatch;\n chart.multibar = multibar;\n chart.legend = legend;\n chart.controls = controls;\n chart.xAxis = xAxis;\n chart.yAxis = yAxis;\n chart.state = state;\n chart.tooltip = tooltip;\n chart.interactiveLayer = interactiveLayer;\n\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},\n showControls: {get: function(){return showControls;}, set: function(_){showControls=_;}},\n controlLabels: {get: function(){return controlLabels;}, set: function(_){controlLabels=_;}},\n showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},\n showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},\n defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}},\n noData: {get: function(){return noData;}, set: function(_){noData=_;}},\n reduceXTicks: {get: function(){return reduceXTicks;}, set: function(_){reduceXTicks=_;}},\n rotateLabels: {get: function(){return rotateLabels;}, set: function(_){rotateLabels=_;}},\n staggerLabels: {get: function(){return staggerLabels;}, set: function(_){staggerLabels=_;}},\n wrapLabels: {get: function(){return wrapLabels;}, set: function(_){wrapLabels=!!_;}},\n\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n if (_.top !== undefined) {\n margin.top = _.top;\n marginTop = _.top;\n }\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n }},\n duration: {get: function(){return duration;}, set: function(_){\n duration = _;\n multibar.duration(duration);\n xAxis.duration(duration);\n yAxis.duration(duration);\n renderWatch.reset(duration);\n }},\n color: {get: function(){return color;}, set: function(_){\n color = nv.utils.getColor(_);\n legend.color(color);\n }},\n rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){\n rightAlignYAxis = _;\n yAxis.orient( rightAlignYAxis ? 'right' : 'left');\n }},\n useInteractiveGuideline: {get: function(){return useInteractiveGuideline;}, set: function(_){\n useInteractiveGuideline = _;\n }},\n barColor: {get: function(){return multibar.barColor;}, set: function(_){\n multibar.barColor(_);\n legend.color(function(d,i) {return d3.rgb('#ccc').darker(i * 1.5).toString();})\n }}\n });\n\n nv.utils.inheritOptions(chart, multibar);\n nv.utils.initOptions(chart);\n\n return chart;\n};\n","\nnv.models.multiBarHorizontal = function() {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var margin = {top: 0, right: 0, bottom: 0, left: 0}\n , width = 960\n , height = 500\n , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one\n , container = null\n , x = d3.scale.ordinal()\n , y = d3.scale.linear()\n , getX = function(d) { return d.x }\n , getY = function(d) { return d.y }\n , getYerr = function(d) { return d.yErr }\n , forceY = [0] // 0 is forced by default.. this makes sense for the majority of bar graphs... user can always do chart.forceY([]) to remove\n , color = nv.utils.defaultColor()\n , barColor = null // adding the ability to set the color for each rather than the whole group\n , disabled // used in conjunction with barColor to communicate from multiBarHorizontalChart what series are disabled\n , stacked = false\n , showValues = false\n , showBarLabels = false\n , valuePadding = 60\n , groupSpacing = 0.1\n , fillOpacity = 0.75\n , valueFormat = d3.format(',.2f')\n , delay = 1200\n , xDomain\n , yDomain\n , xRange\n , yRange\n , duration = 250\n , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd')\n ;\n\n //============================================================\n // Private Variables\n //------------------------------------------------------------\n\n var x0, y0; //used to store previous scales\n var renderWatch = nv.utils.renderWatch(dispatch, duration);\n\n function chart(selection) {\n renderWatch.reset();\n selection.each(function(data) {\n var availableWidth = width - margin.left - margin.right,\n availableHeight = height - margin.top - margin.bottom;\n\n container = d3.select(this);\n nv.utils.initSVG(container);\n\n if (stacked)\n data = d3.layout.stack()\n .offset('zero')\n .values(function(d){ return d.values })\n .y(getY)\n (data);\n\n //add series index and key to each data point for reference\n data.forEach(function(series, i) {\n series.values.forEach(function(point) {\n point.series = i;\n point.key = series.key;\n });\n });\n\n // HACK for negative value stacking\n if (stacked)\n data[0].values.map(function(d,i) {\n var posBase = 0, negBase = 0;\n data.map(function(d) {\n var f = d.values[i]\n f.size = Math.abs(f.y);\n if (f.y<0) {\n f.y1 = negBase - f.size;\n negBase = negBase - f.size;\n } else\n {\n f.y1 = posBase;\n posBase = posBase + f.size;\n }\n });\n });\n\n // Setup Scales\n // remap and flatten the data for use in calculating the scales' domains\n var seriesData = (xDomain && yDomain) ? [] : // if we know xDomain and yDomain, no need to calculate\n data.map(function(d) {\n return d.values.map(function(d,i) {\n return { x: getX(d,i), y: getY(d,i), y0: d.y0, y1: d.y1 }\n })\n });\n\n x.domain(xDomain || d3.merge(seriesData).map(function(d) { return d.x }))\n .rangeBands(xRange || [0, availableHeight], groupSpacing);\n\n y.domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return stacked ? (d.y > 0 ? d.y1 + d.y : d.y1 ) : d.y }).concat(forceY)))\n\n if (showValues && !stacked)\n y.range(yRange || [(y.domain()[0] < 0 ? valuePadding : 0), availableWidth - (y.domain()[1] > 0 ? valuePadding : 0) ]);\n else\n y.range(yRange || [0, availableWidth]);\n\n x0 = x0 || x;\n y0 = y0 || d3.scale.linear().domain(y.domain()).range([y(0),y(0)]);\n\n // Setup containers and skeleton of chart\n var wrap = d3.select(this).selectAll('g.nv-wrap.nv-multibarHorizontal').data([data]);\n var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-multibarHorizontal');\n var defsEnter = wrapEnter.append('defs');\n var gEnter = wrapEnter.append('g');\n var g = wrap.select('g');\n\n gEnter.append('g').attr('class', 'nv-groups');\n wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');\n\n var groups = wrap.select('.nv-groups').selectAll('.nv-group')\n .data(function(d) { return d }, function(d,i) { return i });\n groups.enter().append('g')\n .style('stroke-opacity', 1e-6)\n .style('fill-opacity', 1e-6);\n groups.exit().watchTransition(renderWatch, 'multibarhorizontal: exit groups')\n .style('stroke-opacity', 1e-6)\n .style('fill-opacity', 1e-6)\n .remove();\n groups\n .attr('class', function(d,i) { return 'nv-group nv-series-' + i })\n .classed('hover', function(d) { return d.hover })\n .style('fill', function(d,i){ return color(d, i) })\n .style('stroke', function(d,i){ return color(d, i) });\n groups.watchTransition(renderWatch, 'multibarhorizontal: groups')\n .style('stroke-opacity', 1)\n .style('fill-opacity', fillOpacity);\n\n var bars = groups.selectAll('g.nv-bar')\n .data(function(d) { return d.values });\n bars.exit().remove();\n\n var barsEnter = bars.enter().append('g')\n .attr('transform', function(d,i,j) {\n return 'translate(' + y0(stacked ? d.y0 : 0) + ',' + (stacked ? 0 : (j * x.rangeBand() / data.length ) + x(getX(d,i))) + ')'\n });\n\n barsEnter.append('rect')\n .attr('width', 0)\n .attr('height', x.rangeBand() / (stacked ? 1 : data.length) )\n\n bars\n .on('mouseover', function(d,i) { //TODO: figure out why j works above, but not here\n d3.select(this).classed('hover', true);\n dispatch.elementMouseover({\n data: d,\n index: i,\n color: d3.select(this).style(\"fill\")\n });\n })\n .on('mouseout', function(d,i) {\n d3.select(this).classed('hover', false);\n dispatch.elementMouseout({\n data: d,\n index: i,\n color: d3.select(this).style(\"fill\")\n });\n })\n .on('mouseout', function(d,i) {\n dispatch.elementMouseout({\n data: d,\n index: i,\n color: d3.select(this).style(\"fill\")\n });\n })\n .on('mousemove', function(d,i) {\n dispatch.elementMousemove({\n data: d,\n index: i,\n color: d3.select(this).style(\"fill\")\n });\n })\n .on('click', function(d,i) {\n var element = this;\n dispatch.elementClick({\n data: d,\n index: i,\n color: d3.select(this).style(\"fill\"),\n event: d3.event,\n element: element\n });\n d3.event.stopPropagation();\n })\n .on('dblclick', function(d,i) {\n dispatch.elementDblClick({\n data: d,\n index: i,\n color: d3.select(this).style(\"fill\")\n });\n d3.event.stopPropagation();\n });\n\n if (getYerr(data[0],0)) {\n barsEnter.append('polyline');\n\n bars.select('polyline')\n .attr('fill', 'none')\n .attr('points', function(d,i) {\n var xerr = getYerr(d,i)\n , mid = 0.8 * x.rangeBand() / ((stacked ? 1 : data.length) * 2);\n xerr = xerr.length ? xerr : [-Math.abs(xerr), Math.abs(xerr)];\n xerr = xerr.map(function(e) { return y(e) - y(0); });\n var a = [[xerr[0],-mid], [xerr[0],mid], [xerr[0],0], [xerr[1],0], [xerr[1],-mid], [xerr[1],mid]];\n return a.map(function (path) { return path.join(',') }).join(' ');\n })\n .attr('transform', function(d,i) {\n var mid = x.rangeBand() / ((stacked ? 1 : data.length) * 2);\n return 'translate(' + (getY(d,i) < 0 ? 0 : y(getY(d,i)) - y(0)) + ', ' + mid + ')'\n });\n }\n\n barsEnter.append('text');\n\n if (showValues && !stacked) {\n bars.select('text')\n .attr('text-anchor', function(d,i) { return getY(d,i) < 0 ? 'end' : 'start' })\n .attr('y', x.rangeBand() / (data.length * 2))\n .attr('dy', '.32em')\n .text(function(d,i) {\n var t = valueFormat(getY(d,i))\n , yerr = getYerr(d,i);\n if (yerr === undefined)\n return t;\n if (!yerr.length)\n return t + '±' + valueFormat(Math.abs(yerr));\n return t + '+' + valueFormat(Math.abs(yerr[1])) + '-' + valueFormat(Math.abs(yerr[0]));\n });\n bars.watchTransition(renderWatch, 'multibarhorizontal: bars')\n .select('text')\n .attr('x', function(d,i) { return getY(d,i) < 0 ? -4 : y(getY(d,i)) - y(0) + 4 })\n } else {\n bars.selectAll('text').text('');\n }\n\n if (showBarLabels && !stacked) {\n barsEnter.append('text').classed('nv-bar-label',true);\n bars.select('text.nv-bar-label')\n .attr('text-anchor', function(d,i) { return getY(d,i) < 0 ? 'start' : 'end' })\n .attr('y', x.rangeBand() / (data.length * 2))\n .attr('dy', '.32em')\n .text(function(d,i) { return getX(d,i) });\n bars.watchTransition(renderWatch, 'multibarhorizontal: bars')\n .select('text.nv-bar-label')\n .attr('x', function(d,i) { return getY(d,i) < 0 ? y(0) - y(getY(d,i)) + 4 : -4 });\n }\n else {\n bars.selectAll('text.nv-bar-label').text('');\n }\n\n bars\n .attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive'})\n\n if (barColor) {\n if (!disabled) disabled = data.map(function() { return true });\n bars\n .style('fill', function(d,i,j) { return d3.rgb(barColor(d,i)).darker( disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i] })[j] ).toString(); })\n .style('stroke', function(d,i,j) { return d3.rgb(barColor(d,i)).darker( disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i] })[j] ).toString(); });\n }\n\n if (stacked)\n bars.watchTransition(renderWatch, 'multibarhorizontal: bars')\n .attr('transform', function(d,i) {\n return 'translate(' + y(d.y1) + ',' + x(getX(d,i)) + ')'\n })\n .select('rect')\n .attr('width', function(d,i) {\n return Math.abs(y(getY(d,i) + d.y0) - y(d.y0)) || 0\n })\n .attr('height', x.rangeBand() );\n else\n bars.watchTransition(renderWatch, 'multibarhorizontal: bars')\n .attr('transform', function(d,i) {\n //TODO: stacked must be all positive or all negative, not both?\n return 'translate(' +\n (getY(d,i) < 0 ? y(getY(d,i)) : y(0))\n + ',' +\n (d.series * x.rangeBand() / data.length\n +\n x(getX(d,i)) )\n + ')'\n })\n .select('rect')\n .attr('height', x.rangeBand() / data.length )\n .attr('width', function(d,i) {\n return Math.max(Math.abs(y(getY(d,i)) - y(0)),1) || 0\n });\n\n //store old scales for use in transitions on update\n x0 = x.copy();\n y0 = y.copy();\n\n });\n\n renderWatch.renderEnd('multibarHorizontal immediate');\n return chart;\n }\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n chart.dispatch = dispatch;\n\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n x: {get: function(){return getX;}, set: function(_){getX=_;}},\n y: {get: function(){return getY;}, set: function(_){getY=_;}},\n yErr: {get: function(){return getYerr;}, set: function(_){getYerr=_;}},\n xScale: {get: function(){return x;}, set: function(_){x=_;}},\n yScale: {get: function(){return y;}, set: function(_){y=_;}},\n xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}},\n yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}},\n xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}},\n yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}},\n forceY: {get: function(){return forceY;}, set: function(_){forceY=_;}},\n stacked: {get: function(){return stacked;}, set: function(_){stacked=_;}},\n showValues: {get: function(){return showValues;}, set: function(_){showValues=_;}},\n // this shows the group name, seems pointless?\n //showBarLabels: {get: function(){return showBarLabels;}, set: function(_){showBarLabels=_;}},\n disabled: {get: function(){return disabled;}, set: function(_){disabled=_;}},\n id: {get: function(){return id;}, set: function(_){id=_;}},\n valueFormat: {get: function(){return valueFormat;}, set: function(_){valueFormat=_;}},\n valuePadding: {get: function(){return valuePadding;}, set: function(_){valuePadding=_;}},\n groupSpacing: {get: function(){return groupSpacing;}, set: function(_){groupSpacing=_;}},\n fillOpacity: {get: function(){return fillOpacity;}, set: function(_){fillOpacity=_;}},\n\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n margin.top = _.top !== undefined ? _.top : margin.top;\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n }},\n duration: {get: function(){return duration;}, set: function(_){\n duration = _;\n renderWatch.reset(duration);\n }},\n color: {get: function(){return color;}, set: function(_){\n color = nv.utils.getColor(_);\n }},\n barColor: {get: function(){return barColor;}, set: function(_){\n barColor = _ ? nv.utils.getColor(_) : null;\n }}\n });\n\n nv.utils.initOptions(chart);\n\n return chart;\n};\n","\nnv.models.multiBarHorizontalChart = function() {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var multibar = nv.models.multiBarHorizontal()\n , xAxis = nv.models.axis()\n , yAxis = nv.models.axis()\n , legend = nv.models.legend().height(30)\n , controls = nv.models.legend().height(30)\n , tooltip = nv.models.tooltip()\n ;\n\n var margin = {top: 30, right: 20, bottom: 50, left: 60}\n , marginTop = null\n , width = null\n , height = null\n , color = nv.utils.defaultColor()\n , showControls = true\n , controlLabels = {}\n , showLegend = true\n , showXAxis = true\n , showYAxis = true\n , stacked = false\n , x //can be accessed via chart.xScale()\n , y //can be accessed via chart.yScale()\n , state = nv.utils.state()\n , defaultState = null\n , noData = null\n , dispatch = d3.dispatch('stateChange', 'changeState','renderEnd')\n , controlWidth = function() { return showControls ? 180 : 0 }\n , duration = 250\n ;\n\n state.stacked = false; // DEPRECATED Maintained for backward compatibility\n\n multibar.stacked(stacked);\n\n xAxis\n .orient('left')\n .tickPadding(5)\n .showMaxMin(false)\n .tickFormat(function(d) { return d })\n ;\n yAxis\n .orient('bottom')\n .tickFormat(d3.format(',.1f'))\n ;\n\n tooltip\n .duration(0)\n .valueFormatter(function(d, i) {\n return yAxis.tickFormat()(d, i);\n })\n .headerFormatter(function(d, i) {\n return xAxis.tickFormat()(d, i);\n });\n\n controls.updateState(false);\n\n //============================================================\n // Private Variables\n //------------------------------------------------------------\n\n var stateGetter = function(data) {\n return function(){\n return {\n active: data.map(function(d) { return !d.disabled }),\n stacked: stacked\n };\n }\n };\n\n var stateSetter = function(data) {\n return function(state) {\n if (state.stacked !== undefined)\n stacked = state.stacked;\n if (state.active !== undefined)\n data.forEach(function(series,i) {\n series.disabled = !state.active[i];\n });\n }\n };\n\n var renderWatch = nv.utils.renderWatch(dispatch, duration);\n\n function chart(selection) {\n renderWatch.reset();\n renderWatch.models(multibar);\n if (showXAxis) renderWatch.models(xAxis);\n if (showYAxis) renderWatch.models(yAxis);\n\n selection.each(function(data) {\n var container = d3.select(this),\n that = this;\n nv.utils.initSVG(container);\n var availableWidth = nv.utils.availableWidth(width, container, margin),\n availableHeight = nv.utils.availableHeight(height, container, margin);\n\n chart.update = function() { container.transition().duration(duration).call(chart) };\n chart.container = this;\n\n stacked = multibar.stacked();\n\n state\n .setter(stateSetter(data), chart.update)\n .getter(stateGetter(data))\n .update();\n\n // DEPRECATED set state.disableddisabled\n state.disabled = data.map(function(d) { return !!d.disabled });\n\n if (!defaultState) {\n var key;\n defaultState = {};\n for (key in state) {\n if (state[key] instanceof Array)\n defaultState[key] = state[key].slice(0);\n else\n defaultState[key] = state[key];\n }\n }\n\n // Display No Data message if there's nothing to show.\n if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {\n nv.utils.noData(chart, container)\n return chart;\n } else {\n container.selectAll('.nv-noData').remove();\n }\n\n // Setup Scales\n x = multibar.xScale();\n y = multibar.yScale().clamp(true);\n\n // Setup containers and skeleton of chart\n var wrap = container.selectAll('g.nv-wrap.nv-multiBarHorizontalChart').data([data]);\n var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-multiBarHorizontalChart').append('g');\n var g = wrap.select('g');\n\n gEnter.append('g').attr('class', 'nv-x nv-axis');\n gEnter.append('g').attr('class', 'nv-y nv-axis')\n .append('g').attr('class', 'nv-zeroLine')\n .append('line');\n gEnter.append('g').attr('class', 'nv-barsWrap');\n gEnter.append('g').attr('class', 'nv-legendWrap');\n gEnter.append('g').attr('class', 'nv-controlsWrap');\n\n // Legend\n if (!showLegend) {\n g.select('.nv-legendWrap').selectAll('*').remove();\n } else {\n legend.width(availableWidth - controlWidth());\n\n g.select('.nv-legendWrap')\n .datum(data)\n .call(legend);\n\n if (!marginTop && legend.height() !== margin.top) {\n margin.top = legend.height();\n availableHeight = nv.utils.availableHeight(height, container, margin);\n }\n\n g.select('.nv-legendWrap')\n .attr('transform', 'translate(' + controlWidth() + ',' + (-margin.top) +')');\n }\n\n // Controls\n if (!showControls) {\n g.select('.nv-controlsWrap').selectAll('*').remove();\n } else {\n var controlsData = [\n { key: controlLabels.grouped || 'Grouped', disabled: multibar.stacked() },\n { key: controlLabels.stacked || 'Stacked', disabled: !multibar.stacked() }\n ];\n\n controls.width(controlWidth()).color(['#444', '#444', '#444']);\n g.select('.nv-controlsWrap')\n .datum(controlsData)\n .attr('transform', 'translate(0,' + (-margin.top) +')')\n .call(controls);\n }\n\n wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');\n\n // Main Chart Component(s)\n multibar\n .disabled(data.map(function(series) { return series.disabled }))\n .width(availableWidth)\n .height(availableHeight)\n .color(data.map(function(d,i) {\n return d.color || color(d, i);\n }).filter(function(d,i) { return !data[i].disabled }));\n\n var barsWrap = g.select('.nv-barsWrap')\n .datum(data.filter(function(d) { return !d.disabled }));\n\n barsWrap.transition().call(multibar);\n\n // Setup Axes\n if (showXAxis) {\n xAxis\n .scale(x)\n ._ticks( nv.utils.calcTicksY(availableHeight/24, data) )\n .tickSize(-availableWidth, 0);\n\n g.select('.nv-x.nv-axis').call(xAxis);\n\n var xTicks = g.select('.nv-x.nv-axis').selectAll('g');\n\n xTicks\n .selectAll('line, text');\n }\n\n if (showYAxis) {\n yAxis\n .scale(y)\n ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )\n .tickSize( -availableHeight, 0);\n\n g.select('.nv-y.nv-axis')\n .attr('transform', 'translate(0,' + availableHeight + ')');\n g.select('.nv-y.nv-axis').call(yAxis);\n }\n\n // Zero line\n g.select(\".nv-zeroLine line\")\n .attr(\"x1\", y(0))\n .attr(\"x2\", y(0))\n .attr(\"y1\", 0)\n .attr(\"y2\", -availableHeight)\n ;\n\n //============================================================\n // Event Handling/Dispatching (in chart's scope)\n //------------------------------------------------------------\n\n legend.dispatch.on('stateChange', function(newState) {\n for (var key in newState)\n state[key] = newState[key];\n dispatch.stateChange(state);\n chart.update();\n });\n\n controls.dispatch.on('legendClick', function(d,i) {\n if (!d.disabled) return;\n controlsData = controlsData.map(function(s) {\n s.disabled = true;\n return s;\n });\n d.disabled = false;\n\n switch (d.key) {\n case 'Grouped':\n case controlLabels.grouped:\n multibar.stacked(false);\n break;\n case 'Stacked':\n case controlLabels.stacked:\n multibar.stacked(true);\n break;\n }\n\n state.stacked = multibar.stacked();\n dispatch.stateChange(state);\n stacked = multibar.stacked();\n\n chart.update();\n });\n\n // Update chart from a state object passed to event handler\n dispatch.on('changeState', function(e) {\n\n if (typeof e.disabled !== 'undefined') {\n data.forEach(function(series,i) {\n series.disabled = e.disabled[i];\n });\n\n state.disabled = e.disabled;\n }\n\n if (typeof e.stacked !== 'undefined') {\n multibar.stacked(e.stacked);\n state.stacked = e.stacked;\n stacked = e.stacked;\n }\n\n chart.update();\n });\n });\n renderWatch.renderEnd('multibar horizontal chart immediate');\n return chart;\n }\n\n //============================================================\n // Event Handling/Dispatching (out of chart's scope)\n //------------------------------------------------------------\n\n multibar.dispatch.on('elementMouseover.tooltip', function(evt) {\n evt.value = chart.x()(evt.data);\n evt['series'] = {\n key: evt.data.key,\n value: chart.y()(evt.data),\n color: evt.color\n };\n tooltip.data(evt).hidden(false);\n });\n\n multibar.dispatch.on('elementMouseout.tooltip', function(evt) {\n tooltip.hidden(true);\n });\n\n multibar.dispatch.on('elementMousemove.tooltip', function(evt) {\n tooltip();\n });\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n // expose chart's sub-components\n chart.dispatch = dispatch;\n chart.multibar = multibar;\n chart.legend = legend;\n chart.controls = controls;\n chart.xAxis = xAxis;\n chart.yAxis = yAxis;\n chart.state = state;\n chart.tooltip = tooltip;\n\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},\n showControls: {get: function(){return showControls;}, set: function(_){showControls=_;}},\n controlLabels: {get: function(){return controlLabels;}, set: function(_){controlLabels=_;}},\n showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},\n showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},\n defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}},\n noData: {get: function(){return noData;}, set: function(_){noData=_;}},\n\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n if (_.top !== undefined) {\n margin.top = _.top;\n marginTop = _.top;\n }\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n }},\n duration: {get: function(){return duration;}, set: function(_){\n duration = _;\n renderWatch.reset(duration);\n multibar.duration(duration);\n xAxis.duration(duration);\n yAxis.duration(duration);\n }},\n color: {get: function(){return color;}, set: function(_){\n color = nv.utils.getColor(_);\n legend.color(color);\n }},\n barColor: {get: function(){return multibar.barColor;}, set: function(_){\n multibar.barColor(_);\n legend.color(function(d,i) {return d3.rgb('#ccc').darker(i * 1.5).toString();})\n }}\n });\n\n nv.utils.inheritOptions(chart, multibar);\n nv.utils.initOptions(chart);\n\n return chart;\n};\n","nv.models.multiChart = function() {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var margin = {top: 30, right: 20, bottom: 50, left: 60},\n marginTop = null,\n color = nv.utils.defaultColor(),\n width = null,\n height = null,\n showLegend = true,\n noData = null,\n yDomain1,\n yDomain2,\n getX = function(d) { return d.x },\n getY = function(d) { return d.y},\n interpolate = 'linear',\n useVoronoi = true,\n interactiveLayer = nv.interactiveGuideline(),\n useInteractiveGuideline = false,\n legendRightAxisHint = ' (right axis)',\n duration = 250\n ;\n\n //============================================================\n // Private Variables\n //------------------------------------------------------------\n\n var x = d3.scale.linear(),\n yScale1 = d3.scale.linear(),\n yScale2 = d3.scale.linear(),\n\n lines1 = nv.models.line().yScale(yScale1).duration(duration),\n lines2 = nv.models.line().yScale(yScale2).duration(duration),\n\n scatters1 = nv.models.scatter().yScale(yScale1).duration(duration),\n scatters2 = nv.models.scatter().yScale(yScale2).duration(duration),\n\n bars1 = nv.models.multiBar().stacked(false).yScale(yScale1).duration(duration),\n bars2 = nv.models.multiBar().stacked(false).yScale(yScale2).duration(duration),\n\n stack1 = nv.models.stackedArea().yScale(yScale1).duration(duration),\n stack2 = nv.models.stackedArea().yScale(yScale2).duration(duration),\n\n xAxis = nv.models.axis().scale(x).orient('bottom').tickPadding(5).duration(duration),\n yAxis1 = nv.models.axis().scale(yScale1).orient('left').duration(duration),\n yAxis2 = nv.models.axis().scale(yScale2).orient('right').duration(duration),\n\n legend = nv.models.legend().height(30),\n tooltip = nv.models.tooltip(),\n dispatch = d3.dispatch();\n\n var charts = [lines1, lines2, scatters1, scatters2, bars1, bars2, stack1, stack2];\n\n function chart(selection) {\n selection.each(function(data) {\n var container = d3.select(this),\n that = this;\n nv.utils.initSVG(container);\n\n chart.update = function() { container.transition().call(chart); };\n chart.container = this;\n\n var availableWidth = nv.utils.availableWidth(width, container, margin),\n availableHeight = nv.utils.availableHeight(height, container, margin);\n\n var dataLines1 = data.filter(function(d) {return d.type == 'line' && d.yAxis == 1});\n var dataLines2 = data.filter(function(d) {return d.type == 'line' && d.yAxis == 2});\n var dataScatters1 = data.filter(function(d) {return d.type == 'scatter' && d.yAxis == 1});\n var dataScatters2 = data.filter(function(d) {return d.type == 'scatter' && d.yAxis == 2});\n var dataBars1 = data.filter(function(d) {return d.type == 'bar' && d.yAxis == 1});\n var dataBars2 = data.filter(function(d) {return d.type == 'bar' && d.yAxis == 2});\n var dataStack1 = data.filter(function(d) {return d.type == 'area' && d.yAxis == 1});\n var dataStack2 = data.filter(function(d) {return d.type == 'area' && d.yAxis == 2});\n\n // Display noData message if there's nothing to show.\n if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {\n nv.utils.noData(chart, container);\n return chart;\n } else {\n container.selectAll('.nv-noData').remove();\n }\n\n var series1 = data.filter(function(d) {return !d.disabled && d.yAxis == 1})\n .map(function(d) {\n return d.values.map(function(d,i) {\n return { x: getX(d), y: getY(d) }\n })\n });\n\n var series2 = data.filter(function(d) {return !d.disabled && d.yAxis == 2})\n .map(function(d) {\n return d.values.map(function(d,i) {\n return { x: getX(d), y: getY(d) }\n })\n });\n\n x .domain(d3.extent(d3.merge(series1.concat(series2)), function(d) { return d.x }))\n .range([0, availableWidth]);\n\n var wrap = container.selectAll('g.wrap.multiChart').data([data]);\n var gEnter = wrap.enter().append('g').attr('class', 'wrap nvd3 multiChart').append('g');\n\n gEnter.append('g').attr('class', 'nv-x nv-axis');\n gEnter.append('g').attr('class', 'nv-y1 nv-axis');\n gEnter.append('g').attr('class', 'nv-y2 nv-axis');\n gEnter.append('g').attr('class', 'stack1Wrap');\n gEnter.append('g').attr('class', 'stack2Wrap');\n gEnter.append('g').attr('class', 'bars1Wrap');\n gEnter.append('g').attr('class', 'bars2Wrap');\n gEnter.append('g').attr('class', 'scatters1Wrap');\n gEnter.append('g').attr('class', 'scatters2Wrap');\n gEnter.append('g').attr('class', 'lines1Wrap');\n gEnter.append('g').attr('class', 'lines2Wrap');\n gEnter.append('g').attr('class', 'legendWrap');\n gEnter.append('g').attr('class', 'nv-interactive');\n\n var g = wrap.select('g');\n\n var color_array = data.map(function(d,i) {\n return data[i].color || color(d, i);\n });\n\n // Legend\n if (!showLegend) {\n g.select('.legendWrap').selectAll('*').remove();\n } else {\n var legendWidth = legend.align() ? availableWidth / 2 : availableWidth;\n var legendXPosition = legend.align() ? legendWidth : 0;\n\n legend.width(legendWidth);\n legend.color(color_array);\n\n g.select('.legendWrap')\n .datum(data.map(function(series) {\n series.originalKey = series.originalKey === undefined ? series.key : series.originalKey;\n series.key = series.originalKey + (series.yAxis == 1 ? '' : legendRightAxisHint);\n return series;\n }))\n .call(legend);\n\n if (!marginTop && legend.height() !== margin.top) {\n margin.top = legend.height();\n availableHeight = nv.utils.availableHeight(height, container, margin);\n }\n\n g.select('.legendWrap')\n .attr('transform', 'translate(' + legendXPosition + ',' + (-margin.top) +')');\n }\n\n lines1\n .width(availableWidth)\n .height(availableHeight)\n .interpolate(interpolate)\n .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 1 && data[i].type == 'line'}));\n lines2\n .width(availableWidth)\n .height(availableHeight)\n .interpolate(interpolate)\n .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 2 && data[i].type == 'line'}));\n scatters1\n .width(availableWidth)\n .height(availableHeight)\n .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 1 && data[i].type == 'scatter'}));\n scatters2\n .width(availableWidth)\n .height(availableHeight)\n .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 2 && data[i].type == 'scatter'}));\n bars1\n .width(availableWidth)\n .height(availableHeight)\n .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 1 && data[i].type == 'bar'}));\n bars2\n .width(availableWidth)\n .height(availableHeight)\n .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 2 && data[i].type == 'bar'}));\n stack1\n .width(availableWidth)\n .height(availableHeight)\n .interpolate(interpolate)\n .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 1 && data[i].type == 'area'}));\n stack2\n .width(availableWidth)\n .height(availableHeight)\n .interpolate(interpolate)\n .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 2 && data[i].type == 'area'}));\n\n g.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');\n\n var lines1Wrap = g.select('.lines1Wrap')\n .datum(dataLines1.filter(function(d){return !d.disabled}));\n var scatters1Wrap = g.select('.scatters1Wrap')\n .datum(dataScatters1.filter(function(d){return !d.disabled}));\n var bars1Wrap = g.select('.bars1Wrap')\n .datum(dataBars1.filter(function(d){return !d.disabled}));\n var stack1Wrap = g.select('.stack1Wrap')\n .datum(dataStack1.filter(function(d){return !d.disabled}));\n var lines2Wrap = g.select('.lines2Wrap')\n .datum(dataLines2.filter(function(d){return !d.disabled}));\n var scatters2Wrap = g.select('.scatters2Wrap')\n .datum(dataScatters2.filter(function(d){return !d.disabled}));\n var bars2Wrap = g.select('.bars2Wrap')\n .datum(dataBars2.filter(function(d){return !d.disabled}));\n var stack2Wrap = g.select('.stack2Wrap')\n .datum(dataStack2.filter(function(d){return !d.disabled}));\n\n var extraValue1 = dataStack1.length ? dataStack1.map(function(a){return a.values}).reduce(function(a,b){\n return a.map(function(aVal,i){return {x: aVal.x, y: aVal.y + b[i].y}})\n }).concat([{x:0, y:0}]) : [];\n var extraValue2 = dataStack2.length ? dataStack2.map(function(a){return a.values}).reduce(function(a,b){\n return a.map(function(aVal,i){return {x: aVal.x, y: aVal.y + b[i].y}})\n }).concat([{x:0, y:0}]) : [];\n\n yScale1 .domain(yDomain1 || d3.extent(d3.merge(series1).concat(extraValue1), function(d) { return d.y } ))\n .range([0, availableHeight]);\n\n yScale2 .domain(yDomain2 || d3.extent(d3.merge(series2).concat(extraValue2), function(d) { return d.y } ))\n .range([0, availableHeight]);\n\n lines1.yDomain(yScale1.domain());\n scatters1.yDomain(yScale1.domain());\n bars1.yDomain(yScale1.domain());\n stack1.yDomain(yScale1.domain());\n\n lines2.yDomain(yScale2.domain());\n scatters2.yDomain(yScale2.domain());\n bars2.yDomain(yScale2.domain());\n stack2.yDomain(yScale2.domain());\n\n if(dataStack1.length){d3.transition(stack1Wrap).call(stack1);}\n if(dataStack2.length){d3.transition(stack2Wrap).call(stack2);}\n\n if(dataBars1.length){d3.transition(bars1Wrap).call(bars1);}\n if(dataBars2.length){d3.transition(bars2Wrap).call(bars2);}\n\n if(dataLines1.length){d3.transition(lines1Wrap).call(lines1);}\n if(dataLines2.length){d3.transition(lines2Wrap).call(lines2);}\n\n if(dataScatters1.length){d3.transition(scatters1Wrap).call(scatters1);}\n if(dataScatters2.length){d3.transition(scatters2Wrap).call(scatters2);}\n\n xAxis\n ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )\n .tickSize(-availableHeight, 0);\n\n g.select('.nv-x.nv-axis')\n .attr('transform', 'translate(0,' + availableHeight + ')');\n d3.transition(g.select('.nv-x.nv-axis'))\n .call(xAxis);\n\n yAxis1\n ._ticks( nv.utils.calcTicksY(availableHeight/36, data) )\n .tickSize( -availableWidth, 0);\n\n\n d3.transition(g.select('.nv-y1.nv-axis'))\n .call(yAxis1);\n\n yAxis2\n ._ticks( nv.utils.calcTicksY(availableHeight/36, data) )\n .tickSize( -availableWidth, 0);\n\n d3.transition(g.select('.nv-y2.nv-axis'))\n .call(yAxis2);\n\n g.select('.nv-y1.nv-axis')\n .classed('nv-disabled', series1.length ? false : true)\n .attr('transform', 'translate(' + x.range()[0] + ',0)');\n\n g.select('.nv-y2.nv-axis')\n .classed('nv-disabled', series2.length ? false : true)\n .attr('transform', 'translate(' + x.range()[1] + ',0)');\n\n legend.dispatch.on('stateChange', function(newState) {\n chart.update();\n });\n\n if(useInteractiveGuideline){\n interactiveLayer\n .width(availableWidth)\n .height(availableHeight)\n .margin({left:margin.left, top:margin.top})\n .svgContainer(container)\n .xScale(x);\n wrap.select(\".nv-interactive\").call(interactiveLayer);\n }\n\n //============================================================\n // Event Handling/Dispatching\n //------------------------------------------------------------\n\n function mouseover_line(evt) {\n var yaxis = data[evt.seriesIndex].yAxis === 2 ? yAxis2 : yAxis1;\n evt.value = evt.point.x;\n evt.series = {\n value: evt.point.y,\n color: evt.point.color,\n key: evt.series.key\n };\n tooltip\n .duration(0)\n .headerFormatter(function(d, i) {\n \treturn xAxis.tickFormat()(d, i);\n })\n .valueFormatter(function(d, i) {\n return yaxis.tickFormat()(d, i);\n })\n .data(evt)\n .hidden(false);\n }\n\n function mouseover_scatter(evt) {\n var yaxis = data[evt.seriesIndex].yAxis === 2 ? yAxis2 : yAxis1;\n evt.value = evt.point.x;\n evt.series = {\n value: evt.point.y,\n color: evt.point.color,\n key: evt.series.key\n };\n tooltip\n .duration(100)\n .headerFormatter(function(d, i) {\n \treturn xAxis.tickFormat()(d, i);\n })\n .valueFormatter(function(d, i) {\n return yaxis.tickFormat()(d, i);\n })\n .data(evt)\n .hidden(false);\n }\n\n function mouseover_stack(evt) {\n var yaxis = data[evt.seriesIndex].yAxis === 2 ? yAxis2 : yAxis1;\n evt.point['x'] = stack1.x()(evt.point);\n evt.point['y'] = stack1.y()(evt.point);\n tooltip\n .duration(0)\n .headerFormatter(function(d, i) {\n \treturn xAxis.tickFormat()(d, i);\n })\n .valueFormatter(function(d, i) {\n return yaxis.tickFormat()(d, i);\n })\n .data(evt)\n .hidden(false);\n }\n\n function mouseover_bar(evt) {\n var yaxis = data[evt.data.series].yAxis === 2 ? yAxis2 : yAxis1;\n\n evt.value = bars1.x()(evt.data);\n evt['series'] = {\n value: bars1.y()(evt.data),\n color: evt.color,\n key: evt.data.key\n };\n tooltip\n .duration(0)\n .headerFormatter(function(d, i) {\n \treturn xAxis.tickFormat()(d, i);\n })\n .valueFormatter(function(d, i) {\n return yaxis.tickFormat()(d, i);\n })\n .data(evt)\n .hidden(false);\n }\n\n\n\n function clearHighlights() {\n for(var i=0, il=charts.length; i < il; i++){\n var chart = charts[i];\n try {\n chart.clearHighlights();\n } catch(e){}\n }\n }\n\n function highlightPoint(serieIndex, pointIndex, b){\n for(var i=0, il=charts.length; i < il; i++){\n var chart = charts[i];\n try {\n chart.highlightPoint(serieIndex, pointIndex, b);\n } catch(e){}\n }\n }\n\n if(useInteractiveGuideline){\n interactiveLayer.dispatch.on('elementMousemove', function(e) {\n clearHighlights();\n var singlePoint, pointIndex, pointXLocation, allData = [];\n data\n .filter(function(series, i) {\n series.seriesIndex = i;\n return !series.disabled;\n })\n .forEach(function(series,i) {\n var extent = x.domain();\n var currentValues = series.values.filter(function(d,i) {\n return chart.x()(d,i) >= extent[0] && chart.x()(d,i) <= extent[1];\n });\n\n pointIndex = nv.interactiveBisect(currentValues, e.pointXValue, chart.x());\n var point = currentValues[pointIndex];\n var pointYValue = chart.y()(point, pointIndex);\n if (pointYValue !== null) {\n highlightPoint(i, pointIndex, true);\n }\n if (point === undefined) return;\n if (singlePoint === undefined) singlePoint = point;\n if (pointXLocation === undefined) pointXLocation = x(chart.x()(point,pointIndex));\n allData.push({\n key: series.key,\n value: pointYValue,\n color: color(series,series.seriesIndex),\n data: point,\n yAxis: series.yAxis == 2 ? yAxis2 : yAxis1\n });\n });\n\n var defaultValueFormatter = function(d,i) {\n var yAxis = allData[i].yAxis;\n return d == null ? \"N/A\" : yAxis.tickFormat()(d);\n };\n\n interactiveLayer.tooltip\n .headerFormatter(function(d, i) {\n return xAxis.tickFormat()(d, i);\n })\n .valueFormatter(interactiveLayer.tooltip.valueFormatter() || defaultValueFormatter)\n .data({\n value: chart.x()( singlePoint,pointIndex ),\n index: pointIndex,\n series: allData\n })();\n\n interactiveLayer.renderGuideLine(pointXLocation);\n });\n\n interactiveLayer.dispatch.on(\"elementMouseout\",function(e) {\n clearHighlights();\n });\n } else {\n lines1.dispatch.on('elementMouseover.tooltip', mouseover_line);\n lines2.dispatch.on('elementMouseover.tooltip', mouseover_line);\n lines1.dispatch.on('elementMouseout.tooltip', function(evt) {\n tooltip.hidden(true)\n });\n lines2.dispatch.on('elementMouseout.tooltip', function(evt) {\n tooltip.hidden(true)\n });\n\n scatters1.dispatch.on('elementMouseover.tooltip', mouseover_scatter);\n scatters2.dispatch.on('elementMouseover.tooltip', mouseover_scatter);\n scatters1.dispatch.on('elementMouseout.tooltip', function(evt) {\n tooltip.hidden(true)\n });\n scatters2.dispatch.on('elementMouseout.tooltip', function(evt) {\n tooltip.hidden(true)\n });\n\n stack1.dispatch.on('elementMouseover.tooltip', mouseover_stack);\n stack2.dispatch.on('elementMouseover.tooltip', mouseover_stack);\n stack1.dispatch.on('elementMouseout.tooltip', function(evt) {\n tooltip.hidden(true)\n });\n stack2.dispatch.on('elementMouseout.tooltip', function(evt) {\n tooltip.hidden(true)\n });\n\n bars1.dispatch.on('elementMouseover.tooltip', mouseover_bar);\n bars2.dispatch.on('elementMouseover.tooltip', mouseover_bar);\n\n bars1.dispatch.on('elementMouseout.tooltip', function(evt) {\n tooltip.hidden(true);\n });\n bars2.dispatch.on('elementMouseout.tooltip', function(evt) {\n tooltip.hidden(true);\n });\n bars1.dispatch.on('elementMousemove.tooltip', function(evt) {\n tooltip();\n });\n bars2.dispatch.on('elementMousemove.tooltip', function(evt) {\n tooltip();\n });\n }\n });\n\n return chart;\n }\n\n //============================================================\n // Global getters and setters\n //------------------------------------------------------------\n\n chart.dispatch = dispatch;\n chart.legend = legend;\n chart.lines1 = lines1;\n chart.lines2 = lines2;\n chart.scatters1 = scatters1;\n chart.scatters2 = scatters2;\n chart.bars1 = bars1;\n chart.bars2 = bars2;\n chart.stack1 = stack1;\n chart.stack2 = stack2;\n chart.xAxis = xAxis;\n chart.yAxis1 = yAxis1;\n chart.yAxis2 = yAxis2;\n chart.tooltip = tooltip;\n chart.interactiveLayer = interactiveLayer;\n\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},\n yDomain1: {get: function(){return yDomain1;}, set: function(_){yDomain1=_;}},\n yDomain2: {get: function(){return yDomain2;}, set: function(_){yDomain2=_;}},\n noData: {get: function(){return noData;}, set: function(_){noData=_;}},\n interpolate: {get: function(){return interpolate;}, set: function(_){interpolate=_;}},\n legendRightAxisHint: {get: function(){return legendRightAxisHint;}, set: function(_){legendRightAxisHint=_;}},\n\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n if (_.top !== undefined) {\n margin.top = _.top;\n marginTop = _.top;\n }\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n }},\n color: {get: function(){return color;}, set: function(_){\n color = nv.utils.getColor(_);\n }},\n x: {get: function(){return getX;}, set: function(_){\n getX = _;\n lines1.x(_);\n lines2.x(_);\n scatters1.x(_);\n scatters2.x(_);\n bars1.x(_);\n bars2.x(_);\n stack1.x(_);\n stack2.x(_);\n }},\n y: {get: function(){return getY;}, set: function(_){\n getY = _;\n lines1.y(_);\n lines2.y(_);\n scatters1.y(_);\n scatters2.y(_);\n stack1.y(_);\n stack2.y(_);\n bars1.y(_);\n bars2.y(_);\n }},\n useVoronoi: {get: function(){return useVoronoi;}, set: function(_){\n useVoronoi=_;\n lines1.useVoronoi(_);\n lines2.useVoronoi(_);\n stack1.useVoronoi(_);\n stack2.useVoronoi(_);\n }},\n\n useInteractiveGuideline: {get: function(){return useInteractiveGuideline;}, set: function(_){\n useInteractiveGuideline = _;\n if (useInteractiveGuideline) {\n lines1.interactive(false);\n lines1.useVoronoi(false);\n lines2.interactive(false);\n lines2.useVoronoi(false);\n stack1.interactive(false);\n stack1.useVoronoi(false);\n stack2.interactive(false);\n stack2.useVoronoi(false);\n scatters1.interactive(false);\n scatters2.interactive(false);\n }\n }},\n\n duration: {get: function(){return duration;}, set: function(_) {\n duration = _;\n [lines1, lines2, stack1, stack2, scatters1, scatters2, xAxis, yAxis1, yAxis2].forEach(function(model){\n model.duration(duration);\n });\n }}\n });\n\n nv.utils.initOptions(chart);\n\n return chart;\n};\n","\nnv.models.ohlcBar = function() {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var margin = {top: 0, right: 0, bottom: 0, left: 0}\n , width = null\n , height = null\n , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one\n , container = null\n , x = d3.scale.linear()\n , y = d3.scale.linear()\n , getX = function(d) { return d.x }\n , getY = function(d) { return d.y }\n , getOpen = function(d) { return d.open }\n , getClose = function(d) { return d.close }\n , getHigh = function(d) { return d.high }\n , getLow = function(d) { return d.low }\n , forceX = []\n , forceY = []\n , padData = false // If true, adds half a data points width to front and back, for lining up a line chart with a bar chart\n , clipEdge = true\n , color = nv.utils.defaultColor()\n , interactive = false\n , xDomain\n , yDomain\n , xRange\n , yRange\n , dispatch = d3.dispatch('stateChange', 'changeState', 'renderEnd', 'chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove')\n ;\n\n //============================================================\n // Private Variables\n //------------------------------------------------------------\n\n function chart(selection) {\n selection.each(function(data) {\n container = d3.select(this);\n var availableWidth = nv.utils.availableWidth(width, container, margin),\n availableHeight = nv.utils.availableHeight(height, container, margin);\n\n nv.utils.initSVG(container);\n\n // ohlc bar width.\n var w = (availableWidth / data[0].values.length) * .9;\n\n // Setup Scales\n x.domain(xDomain || d3.extent(data[0].values.map(getX).concat(forceX) ));\n\n if (padData)\n x.range(xRange || [availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5) / data[0].values.length ]);\n else\n x.range(xRange || [5 + w/2, availableWidth - w/2 - 5]);\n\n y.domain(yDomain || [\n d3.min(data[0].values.map(getLow).concat(forceY)),\n d3.max(data[0].values.map(getHigh).concat(forceY))\n ]\n ).range(yRange || [availableHeight, 0]);\n\n // If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point\n if (x.domain()[0] === x.domain()[1])\n x.domain()[0] ?\n x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01])\n : x.domain([-1,1]);\n\n if (y.domain()[0] === y.domain()[1])\n y.domain()[0] ?\n y.domain([y.domain()[0] + y.domain()[0] * 0.01, y.domain()[1] - y.domain()[1] * 0.01])\n : y.domain([-1,1]);\n\n // Setup containers and skeleton of chart\n var wrap = d3.select(this).selectAll('g.nv-wrap.nv-ohlcBar').data([data[0].values]);\n var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-ohlcBar');\n var defsEnter = wrapEnter.append('defs');\n var gEnter = wrapEnter.append('g');\n var g = wrap.select('g');\n\n gEnter.append('g').attr('class', 'nv-ticks');\n\n wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');\n\n container\n .on('click', function(d,i) {\n dispatch.chartClick({\n data: d,\n index: i,\n pos: d3.event,\n id: id\n });\n });\n\n defsEnter.append('clipPath')\n .attr('id', 'nv-chart-clip-path-' + id)\n .append('rect');\n\n wrap.select('#nv-chart-clip-path-' + id + ' rect')\n .attr('width', availableWidth)\n .attr('height', availableHeight);\n\n g .attr('clip-path', clipEdge ? 'url(#nv-chart-clip-path-' + id + ')' : '');\n\n var ticks = wrap.select('.nv-ticks').selectAll('.nv-tick')\n .data(function(d) { return d });\n ticks.exit().remove();\n\n ticks.enter().append('path')\n .attr('class', function(d,i,j) { return (getOpen(d,i) > getClose(d,i) ? 'nv-tick negative' : 'nv-tick positive') + ' nv-tick-' + j + '-' + i })\n .attr('d', function(d,i) {\n return 'm0,0l0,'\n + (y(getOpen(d,i))\n - y(getHigh(d,i)))\n + 'l'\n + (-w/2)\n + ',0l'\n + (w/2)\n + ',0l0,'\n + (y(getLow(d,i)) - y(getOpen(d,i)))\n + 'l0,'\n + (y(getClose(d,i))\n - y(getLow(d,i)))\n + 'l'\n + (w/2)\n + ',0l'\n + (-w/2)\n + ',0z';\n })\n .attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',' + y(getHigh(d,i)) + ')'; })\n .attr('fill', function(d,i) { return color[0]; })\n .attr('stroke', function(d,i) { return color[0]; })\n .attr('x', 0 )\n .attr('y', function(d,i) { return y(Math.max(0, getY(d,i))) })\n .attr('height', function(d,i) { return Math.abs(y(getY(d,i)) - y(0)) });\n\n // the bar colors are controlled by CSS currently\n ticks.attr('class', function(d,i,j) {\n return (getOpen(d,i) > getClose(d,i) ? 'nv-tick negative' : 'nv-tick positive') + ' nv-tick-' + j + '-' + i;\n });\n\n d3.transition(ticks)\n .attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',' + y(getHigh(d,i)) + ')'; })\n .attr('d', function(d,i) {\n var w = (availableWidth / data[0].values.length) * .9;\n return 'm0,0l0,'\n + (y(getOpen(d,i))\n - y(getHigh(d,i)))\n + 'l'\n + (-w/2)\n + ',0l'\n + (w/2)\n + ',0l0,'\n + (y(getLow(d,i))\n - y(getOpen(d,i)))\n + 'l0,'\n + (y(getClose(d,i))\n - y(getLow(d,i)))\n + 'l'\n + (w/2)\n + ',0l'\n + (-w/2)\n + ',0z';\n });\n });\n\n return chart;\n }\n\n\n //Create methods to allow outside functions to highlight a specific bar.\n chart.highlightPoint = function(pointIndex, isHoverOver) {\n chart.clearHighlights();\n container.select(\".nv-ohlcBar .nv-tick-0-\" + pointIndex)\n .classed(\"hover\", isHoverOver)\n ;\n };\n\n chart.clearHighlights = function() {\n container.select(\".nv-ohlcBar .nv-tick.hover\")\n .classed(\"hover\", false)\n ;\n };\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n chart.dispatch = dispatch;\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n xScale: {get: function(){return x;}, set: function(_){x=_;}},\n yScale: {get: function(){return y;}, set: function(_){y=_;}},\n xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}},\n yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}},\n xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}},\n yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}},\n forceX: {get: function(){return forceX;}, set: function(_){forceX=_;}},\n forceY: {get: function(){return forceY;}, set: function(_){forceY=_;}},\n padData: {get: function(){return padData;}, set: function(_){padData=_;}},\n clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}},\n id: {get: function(){return id;}, set: function(_){id=_;}},\n interactive: {get: function(){return interactive;}, set: function(_){interactive=_;}},\n\n x: {get: function(){return getX;}, set: function(_){getX=_;}},\n y: {get: function(){return getY;}, set: function(_){getY=_;}},\n open: {get: function(){return getOpen();}, set: function(_){getOpen=_;}},\n close: {get: function(){return getClose();}, set: function(_){getClose=_;}},\n high: {get: function(){return getHigh;}, set: function(_){getHigh=_;}},\n low: {get: function(){return getLow;}, set: function(_){getLow=_;}},\n\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n margin.top = _.top != undefined ? _.top : margin.top;\n margin.right = _.right != undefined ? _.right : margin.right;\n margin.bottom = _.bottom != undefined ? _.bottom : margin.bottom;\n margin.left = _.left != undefined ? _.left : margin.left;\n }},\n color: {get: function(){return color;}, set: function(_){\n color = nv.utils.getColor(_);\n }}\n });\n\n nv.utils.initOptions(chart);\n return chart;\n};\n","// Code adapted from Jason Davies' \"Parallel Coordinates\"\n// http://bl.ocks.org/jasondavies/1341281\nnv.models.parallelCoordinates = function() {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var margin = {top: 30, right: 0, bottom: 10, left: 0}\n , width = null\n , height = null\n , availableWidth = null\n , availableHeight = null\n , x = d3.scale.ordinal()\n , y = {}\n , undefinedValuesLabel = \"undefined values\"\n , dimensionData = []\n , enabledDimensions = []\n , dimensionNames = []\n , displayBrush = true\n , color = nv.utils.defaultColor()\n , filters = []\n , active = []\n , dragging = []\n , axisWithUndefinedValues = []\n , lineTension = 1\n , foreground\n , background\n , dimensions\n , line = d3.svg.line()\n , axis = d3.svg.axis()\n , dispatch = d3.dispatch('brushstart', 'brush', 'brushEnd', 'dimensionsOrder', \"stateChange\", 'elementClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd', 'activeChanged')\n ;\n\n //============================================================\n // Private Variables\n //------------------------------------------------------------\n\n var renderWatch = nv.utils.renderWatch(dispatch);\n\n function chart(selection) {\n renderWatch.reset();\n selection.each(function(data) {\n var container = d3.select(this);\n availableWidth = nv.utils.availableWidth(width, container, margin);\n availableHeight = nv.utils.availableHeight(height, container, margin);\n\n nv.utils.initSVG(container);\n\n //Convert old data to new format (name, values)\n if (data[0].values === undefined) {\n var newData = [];\n data.forEach(function (d) {\n var val = {};\n var key = Object.keys(d);\n key.forEach(function (k) { if (k !== \"name\") val[k] = d[k] });\n newData.push({ key: d.name, values: val });\n });\n data = newData;\n }\n\n var dataValues = data.map(function (d) {return d.values});\n if (active.length === 0) {\n active = data;\n }; //set all active before first brush call\n \n dimensionNames = dimensionData.sort(function (a, b) { return a.currentPosition - b.currentPosition; }).map(function (d) { return d.key });\n enabledDimensions = dimensionData.filter(function (d) { return !d.disabled; });\n \n // Setup Scales\n x.rangePoints([0, availableWidth], 1).domain(enabledDimensions.map(function (d) { return d.key; }));\n\n //Set as true if all values on an axis are missing.\n // Extract the list of dimensions and create a scale for each.\n var oldDomainMaxValue = {};\n var displayMissingValuesline = false;\n var currentTicks = [];\n \n dimensionNames.forEach(function(d) {\n var extent = d3.extent(dataValues, function (p) { return +p[d]; });\n var min = extent[0];\n var max = extent[1];\n var onlyUndefinedValues = false;\n //If there is no values to display on an axis, set the extent to 0\n if (isNaN(min) || isNaN(max)) {\n onlyUndefinedValues = true;\n min = 0;\n max = 0;\n }\n //Scale axis if there is only one value\n if (min === max) {\n min = min - 1;\n max = max + 1;\n }\n var f = filters.filter(function (k) { return k.dimension == d; });\n if (f.length !== 0) {\n //If there is only NaN values, keep the existing domain.\n if (onlyUndefinedValues) {\n min = y[d].domain()[0];\n max = y[d].domain()[1];\n }\n //If the brush extent is > max (< min), keep the extent value.\n else if (!f[0].hasOnlyNaN && displayBrush) {\n min = min > f[0].extent[0] ? f[0].extent[0] : min;\n max = max < f[0].extent[1] ? f[0].extent[1] : max;\n }\n //If there is NaN values brushed be sure the brush extent is on the domain.\n else if (f[0].hasNaN) {\n max = max < f[0].extent[1] ? f[0].extent[1] : max;\n oldDomainMaxValue[d] = y[d].domain()[1];\n displayMissingValuesline = true;\n }\n }\n //Use 90% of (availableHeight - 12) for the axis range, 12 reprensenting the space necessary to display \"undefined values\" text.\n //The remaining 10% are used to display the missingValue line.\n y[d] = d3.scale.linear()\n .domain([min, max])\n .range([(availableHeight - 12) * 0.9, 0]);\n\n axisWithUndefinedValues = [];\n y[d].brush = d3.svg.brush().y(y[d]).on('brushstart', brushstart).on('brush', brush).on('brushend', brushend);\n });\n\n // Setup containers and skeleton of chart\n var wrap = container.selectAll('g.nv-wrap.nv-parallelCoordinates').data([data]);\n var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-parallelCoordinates');\n var gEnter = wrapEnter.append('g');\n var g = wrap.select('g');\n\n gEnter.append('g').attr('class', 'nv-parallelCoordinates background');\n gEnter.append('g').attr('class', 'nv-parallelCoordinates foreground');\n gEnter.append('g').attr('class', 'nv-parallelCoordinates missingValuesline');\n\n wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');\n\n line.interpolate('cardinal').tension(lineTension);\n axis.orient('left');\n var axisDrag = d3.behavior.drag()\n .on('dragstart', dragStart)\n .on('drag', dragMove)\n .on('dragend', dragEnd);\n\n //Add missing value line at the bottom of the chart\n var missingValuesline, missingValueslineText;\n var step = x.range()[1] - x.range()[0];\n step = isNaN(step) ? x.range()[0] : step;\n if (!isNaN(step)) {\n var lineData = [0 + step / 2, availableHeight - 12, availableWidth - step / 2, availableHeight - 12];\n missingValuesline = wrap.select('.missingValuesline').selectAll('line').data([lineData]);\n missingValuesline.enter().append('line');\n missingValuesline.exit().remove();\n missingValuesline.attr(\"x1\", function(d) { return d[0]; })\n .attr(\"y1\", function(d) { return d[1]; })\n .attr(\"x2\", function(d) { return d[2]; })\n .attr(\"y2\", function(d) { return d[3]; });\n \n //Add the text \"undefined values\" under the missing value line\n missingValueslineText = wrap.select('.missingValuesline').selectAll('text').data([undefinedValuesLabel]);\n missingValueslineText.append('text').data([undefinedValuesLabel]);\n missingValueslineText.enter().append('text');\n missingValueslineText.exit().remove();\n missingValueslineText.attr(\"y\", availableHeight)\n //To have the text right align with the missingValues line, substract 92 representing the text size.\n .attr(\"x\", availableWidth - 92 - step / 2)\n .text(function(d) { return d; });\n }\n // Add grey background lines for context.\n background = wrap.select('.background').selectAll('path').data(data);\n background.enter().append('path');\n background.exit().remove();\n background.attr('d', path);\n\n // Add blue foreground lines for focus.\n foreground = wrap.select('.foreground').selectAll('path').data(data);\n foreground.enter().append('path')\n foreground.exit().remove();\n foreground.attr('d', path)\n .style(\"stroke-width\", function (d, i) {\n if (isNaN(d.strokeWidth)) { d.strokeWidth = 1;} return d.strokeWidth;})\n .attr('stroke', function (d, i) { return d.color || color(d, i); });\n foreground.on(\"mouseover\", function (d, i) {\n d3.select(this).classed('hover', true).style(\"stroke-width\", d.strokeWidth + 2 + \"px\").style(\"stroke-opacity\", 1);\n dispatch.elementMouseover({\n label: d.name,\n color: d.color || color(d, i),\n values: d.values,\n dimensions: enabledDimensions\n });\n\n });\n foreground.on(\"mouseout\", function (d, i) {\n d3.select(this).classed('hover', false).style(\"stroke-width\", d.strokeWidth + \"px\").style(\"stroke-opacity\", 0.7);\n dispatch.elementMouseout({\n label: d.name,\n index: i\n });\n });\n foreground.on('mousemove', function (d, i) {\n dispatch.elementMousemove();\n });\n foreground.on('click', function (d) {\n dispatch.elementClick({\n id: d.id\n });\n });\n // Add a group element for each dimension.\n dimensions = g.selectAll('.dimension').data(enabledDimensions);\n var dimensionsEnter = dimensions.enter().append('g').attr('class', 'nv-parallelCoordinates dimension');\n\n dimensions.attr('transform', function(d) { return 'translate(' + x(d.key) + ',0)'; });\n dimensionsEnter.append('g').attr('class', 'nv-axis');\n\n // Add an axis and title.\n dimensionsEnter.append('text')\n .attr('class', 'nv-label')\n .style(\"cursor\", \"move\")\n .attr('dy', '-1em')\n .attr('text-anchor', 'middle')\n .on(\"mouseover\", function(d, i) {\n dispatch.elementMouseover({\n label: d.tooltip || d.key,\n color: d.color \n });\n })\n .on(\"mouseout\", function(d, i) {\n dispatch.elementMouseout({\n label: d.tooltip\n });\n })\n .on('mousemove', function (d, i) {\n dispatch.elementMousemove();\n })\n .call(axisDrag);\n\n dimensionsEnter.append('g').attr('class', 'nv-brushBackground');\n dimensions.exit().remove();\n dimensions.select('.nv-label').text(function (d) { return d.key });\n\n // Add and store a brush for each axis.\n restoreBrush(displayBrush);\n\n var actives = dimensionNames.filter(function (p) { return !y[p].brush.empty(); }),\n extents = actives.map(function (p) { return y[p].brush.extent(); });\n var formerActive = active.slice(0);\n\n //Restore active values\n active = [];\n foreground.style(\"display\", function (d) {\n var isActive = actives.every(function (p, i) {\n if ((isNaN(d.values[p]) || isNaN(parseFloat(d.values[p]))) && extents[i][0] == y[p].brush.y().domain()[0]) {\n return true;\n }\n return (extents[i][0] <= d.values[p] && d.values[p] <= extents[i][1]) && !isNaN(parseFloat(d.values[p]));\n });\n if (isActive)\n active.push(d);\n return !isActive ? \"none\" : null;\n\n });\n\n if (filters.length > 0 || !nv.utils.arrayEquals(active, formerActive)) {\n dispatch.activeChanged(active);\n }\n\n // Returns the path for a given data point.\n function path(d) {\n return line(enabledDimensions.map(function (p) {\n //If value if missing, put the value on the missing value line\n if (isNaN(d.values[p.key]) || isNaN(parseFloat(d.values[p.key])) || displayMissingValuesline) {\n var domain = y[p.key].domain();\n var range = y[p.key].range();\n var min = domain[0] - (domain[1] - domain[0]) / 9;\n\n //If it's not already the case, allow brush to select undefined values\n if (axisWithUndefinedValues.indexOf(p.key) < 0) {\n\n var newscale = d3.scale.linear().domain([min, domain[1]]).range([availableHeight - 12, range[1]]);\n y[p.key].brush.y(newscale);\n axisWithUndefinedValues.push(p.key);\n }\n if (isNaN(d.values[p.key]) || isNaN(parseFloat(d.values[p.key]))) {\n return [x(p.key), y[p.key](min)];\n }\n }\n\n //If parallelCoordinate contain missing values show the missing values line otherwise, hide it.\n if (missingValuesline !== undefined) {\n if (axisWithUndefinedValues.length > 0 || displayMissingValuesline) {\n missingValuesline.style(\"display\", \"inline\");\n missingValueslineText.style(\"display\", \"inline\");\n } else {\n missingValuesline.style(\"display\", \"none\");\n missingValueslineText.style(\"display\", \"none\");\n }\n }\n return [x(p.key), y[p.key](d.values[p.key])];\n }));\n }\n\n function restoreBrush(visible) {\n filters.forEach(function (f) {\n //If filter brushed NaN values, keep the brush on the bottom of the axis.\n var brushDomain = y[f.dimension].brush.y().domain();\n if (f.hasOnlyNaN) {\n f.extent[1] = (y[f.dimension].domain()[1] - brushDomain[0]) * (f.extent[1] - f.extent[0]) / (oldDomainMaxValue[f.dimension] - f.extent[0]) + brushDomain[0];\n }\n if (f.hasNaN) {\n f.extent[0] = brushDomain[0];\n }\n if (visible)\n y[f.dimension].brush.extent(f.extent);\n });\n \n dimensions.select('.nv-brushBackground')\n .each(function (d) {\n d3.select(this).call(y[d.key].brush);\n\n })\n .selectAll('rect')\n .attr('x', -8)\n .attr('width', 16);\n \n updateTicks();\n }\n \n // Handles a brush event, toggling the display of foreground lines.\n function brushstart() {\n //If brush aren't visible, show it before brushing again.\n if (displayBrush === false) {\n displayBrush = true;\n restoreBrush(true);\n }\n }\n \n // Handles a brush event, toggling the display of foreground lines.\n function brush() {\n actives = dimensionNames.filter(function (p) { return !y[p].brush.empty(); });\n extents = actives.map(function(p) { return y[p].brush.extent(); });\n\n filters = []; //erase current filters\n actives.forEach(function(d,i) {\n filters[i] = {\n dimension: d,\n extent: extents[i],\n hasNaN: false,\n hasOnlyNaN: false\n }\n });\n\n active = []; //erase current active list\n foreground.style('display', function(d) {\n var isActive = actives.every(function(p, i) {\n if ((isNaN(d.values[p]) || isNaN(parseFloat(d.values[p]))) && extents[i][0] == y[p].brush.y().domain()[0]) return true;\n return (extents[i][0] <= d.values[p] && d.values[p] <= extents[i][1]) && !isNaN(parseFloat(d.values[p]));\n });\n if (isActive) active.push(d);\n return isActive ? null : 'none';\n });\n \n updateTicks();\n \n dispatch.brush({\n filters: filters,\n active: active\n });\n }\n function brushend() {\n var hasActiveBrush = actives.length > 0 ? true : false;\n filters.forEach(function (f) {\n if (f.extent[0] === y[f.dimension].brush.y().domain()[0] && axisWithUndefinedValues.indexOf(f.dimension) >= 0)\n f.hasNaN = true;\n if (f.extent[1] < y[f.dimension].domain()[0])\n f.hasOnlyNaN = true;\n });\n dispatch.brushEnd(active, hasActiveBrush);\n } \n function updateTicks() {\n dimensions.select('.nv-axis')\n .each(function (d, i) {\n var f = filters.filter(function (k) { return k.dimension == d.key; });\n currentTicks[d.key] = y[d.key].domain();\n \n //If brush are available, display brush extent\n if (f.length != 0 && displayBrush)\n {\n currentTicks[d.key] = [];\n if (f[0].extent[1] > y[d.key].domain()[0]) \n currentTicks[d.key] = [f[0].extent[1]];\n if (f[0].extent[0] >= y[d.key].domain()[0])\n currentTicks[d.key].push(f[0].extent[0]); \n }\n \n d3.select(this).call(axis.scale(y[d.key]).tickFormat(d.format).tickValues(currentTicks[d.key]));\n });\n }\n function dragStart(d) {\n dragging[d.key] = this.parentNode.__origin__ = x(d.key);\n background.attr(\"visibility\", \"hidden\");\n }\n function dragMove(d) {\n dragging[d.key] = Math.min(availableWidth, Math.max(0, this.parentNode.__origin__ += d3.event.x));\n foreground.attr(\"d\", path);\n enabledDimensions.sort(function (a, b) { return dimensionPosition(a.key) - dimensionPosition(b.key); });\n enabledDimensions.forEach(function (d, i) { return d.currentPosition = i; });\n x.domain(enabledDimensions.map(function (d) { return d.key; }));\n dimensions.attr(\"transform\", function(d) { return \"translate(\" + dimensionPosition(d.key) + \")\"; });\n }\n function dragEnd(d, i) {\n delete this.parentNode.__origin__;\n delete dragging[d.key];\n d3.select(this.parentNode).attr(\"transform\", \"translate(\" + x(d.key) + \")\");\n foreground\n .attr(\"d\", path);\n background\n .attr(\"d\", path)\n .attr(\"visibility\", null);\n\n dispatch.dimensionsOrder(enabledDimensions);\n }\n function dimensionPosition(d) {\n var v = dragging[d];\n return v == null ? x(d) : v;\n }\n });\n return chart;\n }\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n chart.dispatch = dispatch;\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: {get: function(){return width;}, set: function(_){width= _;}},\n height: {get: function(){return height;}, set: function(_){height= _;}},\n dimensionData: { get: function () { return dimensionData; }, set: function (_) { dimensionData = _; } },\n displayBrush: { get: function () { return displayBrush; }, set: function (_) { displayBrush = _; } },\n filters: { get: function () { return filters; }, set: function (_) { filters = _; } },\n active: { get: function () { return active; }, set: function (_) { active = _; } },\n lineTension: {get: function(){return lineTension;}, set: function(_){lineTension = _;}},\n undefinedValuesLabel : {get: function(){return undefinedValuesLabel;}, set: function(_){undefinedValuesLabel=_;}},\n \n // deprecated options\n dimensions: {get: function () { return dimensionData.map(function (d){return d.key}); }, set: function (_) {\n // deprecated after 1.8.1\n nv.deprecated('dimensions', 'use dimensionData instead');\n if (dimensionData.length === 0) {\n _.forEach(function (k) { dimensionData.push({ key: k }) })\n } else {\n _.forEach(function (k, i) { dimensionData[i].key= k })\n }\n }},\n dimensionNames: {get: function () { return dimensionData.map(function (d){return d.key}); }, set: function (_) {\n // deprecated after 1.8.1\n nv.deprecated('dimensionNames', 'use dimensionData instead');\n dimensionNames = [];\n if (dimensionData.length === 0) {\n _.forEach(function (k) { dimensionData.push({ key: k }) })\n } else {\n _.forEach(function (k, i) { dimensionData[i].key = k })\n }\n \n }},\n dimensionFormats: {get: function () { return dimensionData.map(function (d) { return d.format }); }, set: function (_) {\n // deprecated after 1.8.1\n nv.deprecated('dimensionFormats', 'use dimensionData instead');\n if (dimensionData.length === 0) {\n _.forEach(function (f) { dimensionData.push({ format: f }) })\n } else {\n _.forEach(function (f, i) { dimensionData[i].format = f })\n }\n\n }},\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n margin.top = _.top !== undefined ? _.top : margin.top;\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n }},\n color: {get: function(){return color;}, set: function(_){\n color = nv.utils.getColor(_);\n }}\n });\n nv.utils.initOptions(chart);\n return chart;\n};\n","nv.models.parallelCoordinatesChart = function () {\n \"use strict\";\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var parallelCoordinates = nv.models.parallelCoordinates()\n var legend = nv.models.legend()\n var tooltip = nv.models.tooltip();\n var dimensionTooltip = nv.models.tooltip();\n\n var margin = { top: 0, right: 0, bottom: 0, left: 0 }\n , marginTop = null\n , width = null\n , height = null\n , showLegend = true\n , color = nv.utils.defaultColor()\n , state = nv.utils.state()\n , dimensionData = []\n , displayBrush = true\n , defaultState = null\n , noData = null\n , nanValue = \"undefined\"\n , dispatch = d3.dispatch('dimensionsOrder', 'brushEnd', 'stateChange', 'changeState', 'renderEnd')\n , controlWidth = function () { return showControls ? 180 : 0 }\n ;\n\n\t //============================================================\n\n\t\t//============================================================\n // Private Variables\n //------------------------------------------------------------\n\n var renderWatch = nv.utils.renderWatch(dispatch);\n\n var stateGetter = function(data) {\n return function() {\n return {\n active: data.map(function(d) { return !d.disabled })\n };\n }\n };\n\n var stateSetter = function(data) {\n return function(state) {\n if(state.active !== undefined) {\n data.forEach(function(series, i) {\n series.disabled = !state.active[i];\n });\n }\n }\n };\n\n tooltip.contentGenerator(function(data) {\n var str = '';\n if(data.series.length !== 0)\n {\n str = str + '';\n data.series.forEach(function(d){\n str = str + '';\n });\n str = str + '';\n }\n str = str + '
' + data.key + '
' + d.key + '' + d.value + '
';\n return str;\n });\n\n //============================================================\n // Chart function\n //------------------------------------------------------------\n\n function chart(selection) {\n renderWatch.reset();\n renderWatch.models(parallelCoordinates);\n\n selection.each(function(data) {\n var container = d3.select(this);\n nv.utils.initSVG(container);\n\n var that = this;\n\n var availableWidth = nv.utils.availableWidth(width, container, margin),\n availableHeight = nv.utils.availableHeight(height, container, margin);\n\n chart.update = function() { container.call(chart); };\n chart.container = this;\n\n state.setter(stateSetter(dimensionData), chart.update)\n .getter(stateGetter(dimensionData))\n .update();\n\n //set state.disabled\n state.disabled = dimensionData.map(function (d) { return !!d.disabled });\n\n //Keep dimensions position in memory\n dimensionData = dimensionData.map(function (d) {d.disabled = !!d.disabled; return d});\n dimensionData.forEach(function (d, i) {\n d.originalPosition = isNaN(d.originalPosition) ? i : d.originalPosition;\n d.currentPosition = isNaN(d.currentPosition) ? i : d.currentPosition;\n });\n\n if (!defaultState) {\n var key;\n defaultState = {};\n for(key in state) {\n if(state[key] instanceof Array)\n defaultState[key] = state[key].slice(0);\n else\n defaultState[key] = state[key];\n }\n }\n\n // Display No Data message if there's nothing to show.\n if(!data || !data.length) {\n nv.utils.noData(chart, container);\n return chart;\n } else {\n container.selectAll('.nv-noData').remove();\n }\n\n //------------------------------------------------------------\n // Setup containers and skeleton of chart\n\n var wrap = container.selectAll('g.nv-wrap.nv-parallelCoordinatesChart').data([data]);\n var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-parallelCoordinatesChart').append('g');\n\n var g = wrap.select('g');\n\n gEnter.append('g').attr('class', 'nv-parallelCoordinatesWrap');\n gEnter.append('g').attr('class', 'nv-legendWrap');\n\n g.select(\"rect\")\n .attr(\"width\", availableWidth)\n .attr(\"height\", (availableHeight > 0) ? availableHeight : 0);\n\n // Legend\n if (!showLegend) {\n g.select('.nv-legendWrap').selectAll('*').remove();\n } else {\n legend.width(availableWidth)\n .color(function (d) { return \"rgb(188,190,192)\"; });\n\n g.select('.nv-legendWrap')\n .datum(dimensionData.sort(function (a, b) { return a.originalPosition - b.originalPosition; }))\n .call(legend);\n\n if (!marginTop && legend.height() !== margin.top) {\n margin.top = legend.height();\n availableHeight = nv.utils.availableHeight(height, container, margin);\n }\n wrap.select('.nv-legendWrap')\n .attr('transform', 'translate( 0 ,' + (-margin.top) + ')');\n }\n wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');\n\n // Main Chart Component(s)\n parallelCoordinates\n .width(availableWidth)\n .height(availableHeight)\n .dimensionData(dimensionData)\n .displayBrush(displayBrush);\n\n\t\t var parallelCoordinatesWrap = g.select('.nv-parallelCoordinatesWrap ')\n .datum(data);\n\n\t\t parallelCoordinatesWrap.transition().call(parallelCoordinates);\n\n\t\t\t\t//============================================================\n // Event Handling/Dispatching (in chart's scope)\n //------------------------------------------------------------\n //Display reset brush button\n\t\t parallelCoordinates.dispatch.on('brushEnd', function (active, hasActiveBrush) {\n\t\t if (hasActiveBrush) {\n\t\t displayBrush = true;\n\t\t dispatch.brushEnd(active);\n\t\t } else {\n\n\t\t displayBrush = false;\n\t\t }\n\t\t });\n\n\t\t legend.dispatch.on('stateChange', function(newState) {\n\t\t for(var key in newState) {\n\t\t state[key] = newState[key];\n\t\t }\n\t\t dispatch.stateChange(state);\n\t\t chart.update();\n\t\t });\n\n //Update dimensions order and display reset sorting button\n\t\t parallelCoordinates.dispatch.on('dimensionsOrder', function (e) {\n\t\t dimensionData.sort(function (a, b) { return a.currentPosition - b.currentPosition; });\n\t\t var isSorted = false;\n\t\t dimensionData.forEach(function (d, i) {\n\t\t d.currentPosition = i;\n\t\t if (d.currentPosition !== d.originalPosition)\n\t\t isSorted = true;\n\t\t });\n\t\t dispatch.dimensionsOrder(dimensionData, isSorted);\n\t\t });\n\n\t\t\t\t// Update chart from a state object passed to event handler\n dispatch.on('changeState', function (e) {\n\n if (typeof e.disabled !== 'undefined') {\n dimensionData.forEach(function (series, i) {\n series.disabled = e.disabled[i];\n });\n state.disabled = e.disabled;\n }\n chart.update();\n });\n });\n\n renderWatch.renderEnd('parraleleCoordinateChart immediate');\n return chart;\n }\n\n\t\t//============================================================\n // Event Handling/Dispatching (out of chart's scope)\n //------------------------------------------------------------\n\n parallelCoordinates.dispatch.on('elementMouseover.tooltip', function (evt) {\n var tp = {\n key: evt.label,\n color: evt.color,\n series: []\n }\n if(evt.values){\n Object.keys(evt.values).forEach(function (d) {\n var dim = evt.dimensions.filter(function (dd) {return dd.key === d;})[0];\n if(dim){\n var v;\n if (isNaN(evt.values[d]) || isNaN(parseFloat(evt.values[d]))) {\n v = nanValue;\n } else {\n v = dim.format(evt.values[d]);\n }\n tp.series.push({ idx: dim.currentPosition, key: d, value: v, color: dim.color });\n }\n });\n tp.series.sort(function(a,b) {return a.idx - b.idx});\n }\n tooltip.data(tp).hidden(false);\n });\n\n parallelCoordinates.dispatch.on('elementMouseout.tooltip', function(evt) {\n tooltip.hidden(true)\n });\n\n parallelCoordinates.dispatch.on('elementMousemove.tooltip', function () {\n tooltip();\n });\n\t\t //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n\t\t// expose chart's sub-components\n chart.dispatch = dispatch;\n chart.parallelCoordinates = parallelCoordinates;\n chart.legend = legend;\n chart.tooltip = tooltip;\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: { get: function () { return width; }, set: function (_) { width = _; } },\n height: { get: function () { return height; }, set: function (_) { height = _; } },\n showLegend: { get: function () { return showLegend; }, set: function (_) { showLegend = _; } },\n defaultState: { get: function () { return defaultState; }, set: function (_) { defaultState = _; } },\n dimensionData: { get: function () { return dimensionData; }, set: function (_) { dimensionData = _; } },\n displayBrush: { get: function () { return displayBrush; }, set: function (_) { displayBrush = _; } },\n noData: { get: function () { return noData; }, set: function (_) { noData = _; } },\n nanValue: { get: function () { return nanValue; }, set: function (_) { nanValue = _; } },\n\n // options that require extra logic in the setter\n margin: {\n get: function () { return margin; },\n set: function (_) {\n if (_.top !== undefined) {\n margin.top = _.top;\n marginTop = _.top;\n }\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n }\n },\n color: {get: function(){return color;}, set: function(_){\n color = nv.utils.getColor(_);\n legend.color(color);\n parallelCoordinates.color(color);\n }}\n });\n\n nv.utils.inheritOptions(chart, parallelCoordinates);\n nv.utils.initOptions(chart);\n\n return chart;\n };\n","nv.models.pie = function() {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var margin = {top: 0, right: 0, bottom: 0, left: 0}\n , width = 500\n , height = 500\n , getX = function(d) { return d.x }\n , getY = function(d) { return d.y }\n , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one\n , container = null\n , color = nv.utils.defaultColor()\n , valueFormat = d3.format(',.2f')\n , showLabels = true\n , labelsOutside = false\n , labelType = \"key\"\n , labelThreshold = .02 //if slice percentage is under this, don't show label\n , donut = false\n , title = false\n , growOnHover = true\n , titleOffset = 0\n , labelSunbeamLayout = false\n , startAngle = false\n , padAngle = false\n , endAngle = false\n , cornerRadius = 0\n , donutRatio = 0.5\n , duration = 250\n , arcsRadius = []\n , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd')\n ;\n\n var arcs = [];\n var arcsOver = [];\n\n //============================================================\n // chart function\n //------------------------------------------------------------\n\n var renderWatch = nv.utils.renderWatch(dispatch);\n\n function chart(selection) {\n renderWatch.reset();\n selection.each(function(data) {\n var availableWidth = width - margin.left - margin.right\n , availableHeight = height - margin.top - margin.bottom\n , radius = Math.min(availableWidth, availableHeight) / 2\n , arcsRadiusOuter = []\n , arcsRadiusInner = []\n ;\n\n container = d3.select(this)\n if (arcsRadius.length === 0) {\n var outer = radius - radius / 5;\n var inner = donutRatio * radius;\n for (var i = 0; i < data[0].length; i++) {\n arcsRadiusOuter.push(outer);\n arcsRadiusInner.push(inner);\n }\n } else {\n if(growOnHover){\n arcsRadiusOuter = arcsRadius.map(function (d) { return (d.outer - d.outer / 5) * radius; });\n arcsRadiusInner = arcsRadius.map(function (d) { return (d.inner - d.inner / 5) * radius; });\n donutRatio = d3.min(arcsRadius.map(function (d) { return (d.inner - d.inner / 5); }));\n } else {\n arcsRadiusOuter = arcsRadius.map(function (d) { return d.outer * radius; });\n arcsRadiusInner = arcsRadius.map(function (d) { return d.inner * radius; });\n donutRatio = d3.min(arcsRadius.map(function (d) { return d.inner; }));\n }\n }\n nv.utils.initSVG(container);\n\n // Setup containers and skeleton of chart\n var wrap = container.selectAll('.nv-wrap.nv-pie').data(data);\n var wrapEnter = wrap.enter().append('g').attr('class','nvd3 nv-wrap nv-pie nv-chart-' + id);\n var gEnter = wrapEnter.append('g');\n var g = wrap.select('g');\n var g_pie = gEnter.append('g').attr('class', 'nv-pie');\n gEnter.append('g').attr('class', 'nv-pieLabels');\n\n wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');\n g.select('.nv-pie').attr('transform', 'translate(' + availableWidth / 2 + ',' + availableHeight / 2 + ')');\n g.select('.nv-pieLabels').attr('transform', 'translate(' + availableWidth / 2 + ',' + availableHeight / 2 + ')');\n\n //\n container.on('click', function(d,i) {\n dispatch.chartClick({\n data: d,\n index: i,\n pos: d3.event,\n id: id\n });\n });\n\n arcs = [];\n arcsOver = [];\n for (var i = 0; i < data[0].length; i++) {\n\n var arc = d3.svg.arc().outerRadius(arcsRadiusOuter[i]);\n var arcOver = d3.svg.arc().outerRadius(arcsRadiusOuter[i] + 5);\n\n if (startAngle !== false) {\n arc.startAngle(startAngle);\n arcOver.startAngle(startAngle);\n }\n if (endAngle !== false) {\n arc.endAngle(endAngle);\n arcOver.endAngle(endAngle);\n }\n if (donut) {\n arc.innerRadius(arcsRadiusInner[i]);\n arcOver.innerRadius(arcsRadiusInner[i]);\n }\n\n if (arc.cornerRadius && cornerRadius) {\n arc.cornerRadius(cornerRadius);\n arcOver.cornerRadius(cornerRadius);\n }\n\n arcs.push(arc);\n arcsOver.push(arcOver);\n }\n\n // Setup the Pie chart and choose the data element\n var pie = d3.layout.pie()\n .sort(null)\n .value(function(d) { return d.disabled ? 0 : getY(d) });\n\n // padAngle added in d3 3.5\n if (pie.padAngle && padAngle) {\n pie.padAngle(padAngle);\n }\n\n // if title is specified and donut, put it in the middle\n if (donut && title) {\n g_pie.append(\"text\").attr('class', 'nv-pie-title');\n\n wrap.select('.nv-pie-title')\n .style(\"text-anchor\", \"middle\")\n .text(function (d) {\n return title;\n })\n .style(\"font-size\", (Math.min(availableWidth, availableHeight)) * donutRatio * 2 / (title.length + 2) + \"px\")\n .attr(\"dy\", \"0.35em\") // trick to vertically center text\n .attr('transform', function(d, i) {\n return 'translate(0, '+ titleOffset + ')';\n });\n }\n\n var slices = wrap.select('.nv-pie').selectAll('.nv-slice').data(pie);\n var pieLabels = wrap.select('.nv-pieLabels').selectAll('.nv-label').data(pie);\n\n slices.exit().remove();\n pieLabels.exit().remove();\n\n var ae = slices.enter().append('g');\n ae.attr('class', 'nv-slice');\n ae.on('mouseover', function(d, i) {\n d3.select(this).classed('hover', true);\n if (growOnHover) {\n d3.select(this).select(\"path\").transition()\n .duration(70)\n .attr(\"d\", arcsOver[i]);\n }\n dispatch.elementMouseover({\n data: d.data,\n index: i,\n color: d3.select(this).style(\"fill\"),\n percent: (d.endAngle - d.startAngle) / (2 * Math.PI)\n });\n });\n ae.on('mouseout', function(d, i) {\n d3.select(this).classed('hover', false);\n if (growOnHover) {\n d3.select(this).select(\"path\").transition()\n .duration(50)\n .attr(\"d\", arcs[i]);\n }\n dispatch.elementMouseout({data: d.data, index: i});\n });\n ae.on('mousemove', function(d, i) {\n dispatch.elementMousemove({data: d.data, index: i});\n });\n ae.on('click', function(d, i) {\n var element = this;\n dispatch.elementClick({\n data: d.data,\n index: i,\n color: d3.select(this).style(\"fill\"),\n event: d3.event,\n element: element\n });\n });\n ae.on('dblclick', function(d, i) {\n dispatch.elementDblClick({\n data: d.data,\n index: i,\n color: d3.select(this).style(\"fill\")\n });\n });\n\n slices.attr('fill', function(d,i) { return color(d.data, i); });\n slices.attr('stroke', function(d,i) { return color(d.data, i); });\n\n var paths = ae.append('path').each(function(d) {\n this._current = d;\n });\n\n slices.select('path')\n .transition()\n .duration(duration)\n .attr('d', function (d, i) { return arcs[i](d); })\n .attrTween('d', arcTween);\n\n if (showLabels) {\n // This does the normal label\n var labelsArc = [];\n for (var i = 0; i < data[0].length; i++) {\n labelsArc.push(arcs[i]);\n\n if (labelsOutside) {\n if (donut) {\n labelsArc[i] = d3.svg.arc().outerRadius(arcs[i].outerRadius());\n if (startAngle !== false) labelsArc[i].startAngle(startAngle);\n if (endAngle !== false) labelsArc[i].endAngle(endAngle);\n }\n } else if (!donut) {\n labelsArc[i].innerRadius(0);\n }\n }\n\n pieLabels.enter().append(\"g\").classed(\"nv-label\",true).each(function(d,i) {\n var group = d3.select(this);\n\n group.attr('transform', function (d, i) {\n if (labelSunbeamLayout) {\n d.outerRadius = arcsRadiusOuter[i] + 10; // Set Outer Coordinate\n d.innerRadius = arcsRadiusOuter[i] + 15; // Set Inner Coordinate\n var rotateAngle = (d.startAngle + d.endAngle) / 2 * (180 / Math.PI);\n if ((d.startAngle + d.endAngle) / 2 < Math.PI) {\n rotateAngle -= 90;\n } else {\n rotateAngle += 90;\n }\n return 'translate(' + labelsArc[i].centroid(d) + ') rotate(' + rotateAngle + ')';\n } else {\n d.outerRadius = radius + 10; // Set Outer Coordinate\n d.innerRadius = radius + 15; // Set Inner Coordinate\n return 'translate(' + labelsArc[i].centroid(d) + ')'\n }\n });\n\n group.append('rect')\n .style('stroke', '#fff')\n .style('fill', '#fff')\n .attr(\"rx\", 3)\n .attr(\"ry\", 3);\n\n group.append('text')\n .style('text-anchor', labelSunbeamLayout ? ((d.startAngle + d.endAngle) / 2 < Math.PI ? 'start' : 'end') : 'middle') //center the text on it's origin or begin/end if orthogonal aligned\n .style('fill', '#000')\n });\n\n var labelLocationHash = {};\n var avgHeight = 14;\n var avgWidth = 140;\n var createHashKey = function(coordinates) {\n return Math.floor(coordinates[0]/avgWidth) * avgWidth + ',' + Math.floor(coordinates[1]/avgHeight) * avgHeight;\n };\n var getSlicePercentage = function(d) {\n return (d.endAngle - d.startAngle) / (2 * Math.PI);\n };\n\n pieLabels.watchTransition(renderWatch, 'pie labels').attr('transform', function (d, i) {\n if (labelSunbeamLayout) {\n d.outerRadius = arcsRadiusOuter[i] + 10; // Set Outer Coordinate\n d.innerRadius = arcsRadiusOuter[i] + 15; // Set Inner Coordinate\n var rotateAngle = (d.startAngle + d.endAngle) / 2 * (180 / Math.PI);\n if ((d.startAngle + d.endAngle) / 2 < Math.PI) {\n rotateAngle -= 90;\n } else {\n rotateAngle += 90;\n }\n return 'translate(' + labelsArc[i].centroid(d) + ') rotate(' + rotateAngle + ')';\n } else {\n d.outerRadius = radius + 10; // Set Outer Coordinate\n d.innerRadius = radius + 15; // Set Inner Coordinate\n\n /*\n Overlapping pie labels are not good. What this attempts to do is, prevent overlapping.\n Each label location is hashed, and if a hash collision occurs, we assume an overlap.\n Adjust the label's y-position to remove the overlap.\n */\n var center = labelsArc[i].centroid(d);\n var percent = getSlicePercentage(d);\n if (d.value && percent >= labelThreshold) {\n var hashKey = createHashKey(center);\n if (labelLocationHash[hashKey]) {\n center[1] -= avgHeight;\n }\n labelLocationHash[createHashKey(center)] = true;\n }\n return 'translate(' + center + ')'\n }\n });\n\n pieLabels.select(\".nv-label text\")\n .style('text-anchor', function(d,i) {\n //center the text on it's origin or begin/end if orthogonal aligned\n return labelSunbeamLayout ? ((d.startAngle + d.endAngle) / 2 < Math.PI ? 'start' : 'end') : 'middle';\n })\n .text(function(d, i) {\n var percent = getSlicePercentage(d);\n var label = '';\n if (!d.value || percent < labelThreshold) return '';\n\n if(typeof labelType === 'function') {\n label = labelType(d, i, {\n 'key': getX(d.data),\n 'value': getY(d.data),\n 'percent': valueFormat(percent)\n });\n } else {\n switch (labelType) {\n case 'key':\n label = getX(d.data);\n break;\n case 'value':\n label = valueFormat(getY(d.data));\n break;\n case 'percent':\n label = d3.format('%')(percent);\n break;\n }\n }\n return label;\n })\n ;\n }\n\n\n // Computes the angle of an arc, converting from radians to degrees.\n function angle(d) {\n var a = (d.startAngle + d.endAngle) * 90 / Math.PI - 90;\n return a > 90 ? a - 180 : a;\n }\n\n function arcTween(a, idx) {\n a.endAngle = isNaN(a.endAngle) ? 0 : a.endAngle;\n a.startAngle = isNaN(a.startAngle) ? 0 : a.startAngle;\n if (!donut) a.innerRadius = 0;\n var i = d3.interpolate(this._current, a);\n this._current = i(0);\n return function (t) {\n return arcs[idx](i(t));\n };\n }\n });\n\n renderWatch.renderEnd('pie immediate');\n return chart;\n }\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n chart.dispatch = dispatch;\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n arcsRadius: { get: function () { return arcsRadius; }, set: function (_) { arcsRadius = _; } },\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n showLabels: {get: function(){return showLabels;}, set: function(_){showLabels=_;}},\n title: {get: function(){return title;}, set: function(_){title=_;}},\n titleOffset: {get: function(){return titleOffset;}, set: function(_){titleOffset=_;}},\n labelThreshold: {get: function(){return labelThreshold;}, set: function(_){labelThreshold=_;}},\n valueFormat: {get: function(){return valueFormat;}, set: function(_){valueFormat=_;}},\n x: {get: function(){return getX;}, set: function(_){getX=_;}},\n id: {get: function(){return id;}, set: function(_){id=_;}},\n endAngle: {get: function(){return endAngle;}, set: function(_){endAngle=_;}},\n startAngle: {get: function(){return startAngle;}, set: function(_){startAngle=_;}},\n padAngle: {get: function(){return padAngle;}, set: function(_){padAngle=_;}},\n cornerRadius: {get: function(){return cornerRadius;}, set: function(_){cornerRadius=_;}},\n donutRatio: {get: function(){return donutRatio;}, set: function(_){donutRatio=_;}},\n labelsOutside: {get: function(){return labelsOutside;}, set: function(_){labelsOutside=_;}},\n labelSunbeamLayout: {get: function(){return labelSunbeamLayout;}, set: function(_){labelSunbeamLayout=_;}},\n donut: {get: function(){return donut;}, set: function(_){donut=_;}},\n growOnHover: {get: function(){return growOnHover;}, set: function(_){growOnHover=_;}},\n\n // depreciated after 1.7.1\n pieLabelsOutside: {get: function(){return labelsOutside;}, set: function(_){\n labelsOutside=_;\n nv.deprecated('pieLabelsOutside', 'use labelsOutside instead');\n }},\n // depreciated after 1.7.1\n donutLabelsOutside: {get: function(){return labelsOutside;}, set: function(_){\n labelsOutside=_;\n nv.deprecated('donutLabelsOutside', 'use labelsOutside instead');\n }},\n // deprecated after 1.7.1\n labelFormat: {get: function(){ return valueFormat;}, set: function(_) {\n valueFormat=_;\n nv.deprecated('labelFormat','use valueFormat instead');\n }},\n\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n margin.top = typeof _.top != 'undefined' ? _.top : margin.top;\n margin.right = typeof _.right != 'undefined' ? _.right : margin.right;\n margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;\n margin.left = typeof _.left != 'undefined' ? _.left : margin.left;\n }},\n duration: {get: function(){return duration;}, set: function(_){\n duration = _;\n renderWatch.reset(duration);\n }},\n y: {get: function(){return getY;}, set: function(_){\n getY=d3.functor(_);\n }},\n color: {get: function(){return color;}, set: function(_){\n color=nv.utils.getColor(_);\n }},\n labelType: {get: function(){return labelType;}, set: function(_){\n labelType= _ || 'key';\n }}\n });\n\n nv.utils.initOptions(chart);\n return chart;\n};\n","nv.models.pieChart = function() {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var pie = nv.models.pie();\n var legend = nv.models.legend();\n var tooltip = nv.models.tooltip();\n\n var margin = {top: 30, right: 20, bottom: 20, left: 20}\n , marginTop = null\n , width = null\n , height = null\n , showTooltipPercent = false\n , showLegend = true\n , legendPosition = \"top\"\n , color = nv.utils.defaultColor()\n , state = nv.utils.state()\n , defaultState = null\n , noData = null\n , duration = 250\n , dispatch = d3.dispatch('stateChange', 'changeState','renderEnd')\n ;\n\n tooltip\n .duration(0)\n .headerEnabled(false)\n .valueFormatter(function(d, i) {\n return pie.valueFormat()(d, i);\n });\n\n //============================================================\n // Private Variables\n //------------------------------------------------------------\n\n var renderWatch = nv.utils.renderWatch(dispatch);\n\n var stateGetter = function(data) {\n return function(){\n return {\n active: data.map(function(d) { return !d.disabled })\n };\n }\n };\n\n var stateSetter = function(data) {\n return function(state) {\n if (state.active !== undefined) {\n data.forEach(function (series, i) {\n series.disabled = !state.active[i];\n });\n }\n }\n };\n\n //============================================================\n // Chart function\n //------------------------------------------------------------\n\n function chart(selection) {\n renderWatch.reset();\n renderWatch.models(pie);\n\n selection.each(function(data) {\n var container = d3.select(this);\n nv.utils.initSVG(container);\n\n var that = this;\n var availableWidth = nv.utils.availableWidth(width, container, margin),\n availableHeight = nv.utils.availableHeight(height, container, margin);\n\n chart.update = function() { container.transition().call(chart); };\n chart.container = this;\n\n state.setter(stateSetter(data), chart.update)\n .getter(stateGetter(data))\n .update();\n\n //set state.disabled\n state.disabled = data.map(function(d) { return !!d.disabled });\n\n if (!defaultState) {\n var key;\n defaultState = {};\n for (key in state) {\n if (state[key] instanceof Array)\n defaultState[key] = state[key].slice(0);\n else\n defaultState[key] = state[key];\n }\n }\n\n // Display No Data message if there's nothing to show.\n if (!data || !data.length) {\n nv.utils.noData(chart, container);\n return chart;\n } else {\n container.selectAll('.nv-noData').remove();\n }\n\n // Setup containers and skeleton of chart\n var wrap = container.selectAll('g.nv-wrap.nv-pieChart').data([data]);\n var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-pieChart').append('g');\n var g = wrap.select('g');\n\n gEnter.append('g').attr('class', 'nv-pieWrap');\n gEnter.append('g').attr('class', 'nv-legendWrap');\n\n // Legend\n if (!showLegend) {\n g.select('.nv-legendWrap').selectAll('*').remove();\n } else {\n if (legendPosition === \"top\") {\n legend.width( availableWidth ).key(pie.x());\n\n wrap.select('.nv-legendWrap')\n .datum(data)\n .call(legend);\n\n if (!marginTop && legend.height() !== margin.top) {\n margin.top = legend.height();\n availableHeight = nv.utils.availableHeight(height, container, margin);\n }\n\n wrap.select('.nv-legendWrap')\n .attr('transform', 'translate(0,' + (-margin.top) +')');\n } else if (legendPosition === \"right\") {\n var legendWidth = nv.models.legend().width();\n if (availableWidth / 2 < legendWidth) {\n legendWidth = (availableWidth / 2)\n }\n legend.height(availableHeight).key(pie.x());\n legend.width(legendWidth);\n availableWidth -= legend.width();\n\n wrap.select('.nv-legendWrap')\n .datum(data)\n .call(legend)\n .attr('transform', 'translate(' + (availableWidth) +',0)');\n }\n }\n wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');\n\n // Main Chart Component(s)\n pie.width(availableWidth).height(availableHeight);\n var pieWrap = g.select('.nv-pieWrap').datum([data]);\n d3.transition(pieWrap).call(pie);\n\n //============================================================\n // Event Handling/Dispatching (in chart's scope)\n //------------------------------------------------------------\n\n legend.dispatch.on('stateChange', function(newState) {\n for (var key in newState) {\n state[key] = newState[key];\n }\n dispatch.stateChange(state);\n chart.update();\n });\n\n // Update chart from a state object passed to event handler\n dispatch.on('changeState', function(e) {\n if (typeof e.disabled !== 'undefined') {\n data.forEach(function(series,i) {\n series.disabled = e.disabled[i];\n });\n state.disabled = e.disabled;\n }\n chart.update();\n });\n });\n\n renderWatch.renderEnd('pieChart immediate');\n return chart;\n }\n\n //============================================================\n // Event Handling/Dispatching (out of chart's scope)\n //------------------------------------------------------------\n\n pie.dispatch.on('elementMouseover.tooltip', function(evt) {\n evt['series'] = {\n key: chart.x()(evt.data),\n value: chart.y()(evt.data),\n color: evt.color,\n percent: evt.percent\n };\n if (!showTooltipPercent) {\n delete evt.percent;\n delete evt.series.percent;\n }\n tooltip.data(evt).hidden(false);\n });\n\n pie.dispatch.on('elementMouseout.tooltip', function(evt) {\n tooltip.hidden(true);\n });\n\n pie.dispatch.on('elementMousemove.tooltip', function(evt) {\n tooltip();\n });\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n // expose chart's sub-components\n chart.legend = legend;\n chart.dispatch = dispatch;\n chart.pie = pie;\n chart.tooltip = tooltip;\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n // use Object get/set functionality to map between vars and chart functions\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n noData: {get: function(){return noData;}, set: function(_){noData=_;}},\n showTooltipPercent: {get: function(){return showTooltipPercent;}, set: function(_){showTooltipPercent=_;}},\n showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},\n legendPosition: {get: function(){return legendPosition;}, set: function(_){legendPosition=_;}},\n defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}},\n\n // options that require extra logic in the setter\n color: {get: function(){return color;}, set: function(_){\n color = _;\n legend.color(color);\n pie.color(color);\n }},\n duration: {get: function(){return duration;}, set: function(_){\n duration = _;\n renderWatch.reset(duration);\n pie.duration(duration);\n }},\n margin: {get: function(){return margin;}, set: function(_){\n if (_.top !== undefined) {\n margin.top = _.top;\n marginTop = _.top;\n }\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n }}\n });\n nv.utils.inheritOptions(chart, pie);\n nv.utils.initOptions(chart);\n return chart;\n};\n","nv.models.sankey = function() {\n 'use strict';\n\n // Sources:\n // - https://bost.ocks.org/mike/sankey/\n // - https://github.com/soxofaan/d3-plugin-captain-sankey\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var sankey = {},\n nodeWidth = 24,\n nodePadding = 8,\n size = [1, 1],\n nodes = [],\n links = [],\n sinksRight = true;\n\n var layout = function(iterations) {\n computeNodeLinks();\n computeNodeValues();\n computeNodeBreadths();\n computeNodeDepths(iterations);\n };\n\n var relayout = function() {\n computeLinkDepths();\n };\n\n // SVG path data generator, to be used as 'd' attribute on 'path' element selection.\n var link = function() {\n var curvature = .5;\n\n function link(d) {\n\n var x0 = d.source.x + d.source.dx,\n x1 = d.target.x,\n xi = d3.interpolateNumber(x0, x1),\n x2 = xi(curvature),\n x3 = xi(1 - curvature),\n y0 = d.source.y + d.sy + d.dy / 2,\n y1 = d.target.y + d.ty + d.dy / 2;\n var linkPath = 'M' + x0 + ',' + y0\n + 'C' + x2 + ',' + y0\n + ' ' + x3 + ',' + y1\n + ' ' + x1 + ',' + y1;\n return linkPath;\n }\n\n link.curvature = function(_) {\n if (!arguments.length) return curvature;\n curvature = +_;\n return link;\n };\n\n return link;\n };\n\n // Y-position of the middle of a node.\n var center = function(node) {\n return node.y + node.dy / 2;\n };\n\n //============================================================\n // Private Variables\n //------------------------------------------------------------\n\n // Populate the sourceLinks and targetLinks for each node.\n // Also, if the source and target are not objects, assume they are indices.\n function computeNodeLinks() {\n nodes.forEach(function(node) {\n // Links that have this node as source.\n node.sourceLinks = [];\n // Links that have this node as target.\n node.targetLinks = [];\n });\n links.forEach(function(link) {\n var source = link.source,\n target = link.target;\n if (typeof source === 'number') source = link.source = nodes[link.source];\n if (typeof target === 'number') target = link.target = nodes[link.target];\n source.sourceLinks.push(link);\n target.targetLinks.push(link);\n });\n }\n\n // Compute the value (size) of each node by summing the associated links.\n function computeNodeValues() {\n nodes.forEach(function(node) {\n node.value = Math.max(\n d3.sum(node.sourceLinks, value),\n d3.sum(node.targetLinks, value)\n );\n });\n }\n\n // Iteratively assign the breadth (x-position) for each node.\n // Nodes are assigned the maximum breadth of incoming neighbors plus one;\n // nodes with no incoming links are assigned breadth zero, while\n // nodes with no outgoing links are assigned the maximum breadth.\n function computeNodeBreadths() {\n //\n var remainingNodes = nodes,\n nextNodes,\n x = 0;\n\n // Work from left to right.\n // Keep updating the breath (x-position) of nodes that are target of recently updated nodes.\n //\n while (remainingNodes.length && x < nodes.length) {\n nextNodes = [];\n remainingNodes.forEach(function(node) {\n node.x = x;\n node.dx = nodeWidth;\n node.sourceLinks.forEach(function(link) {\n if (nextNodes.indexOf(link.target) < 0) {\n nextNodes.push(link.target);\n }\n });\n });\n remainingNodes = nextNodes;\n ++x;\n //\n }\n\n // Optionally move pure sinks always to the right.\n if (sinksRight) {\n moveSinksRight(x);\n }\n\n scaleNodeBreadths((size[0] - nodeWidth) / (x - 1));\n }\n\n function moveSourcesRight() {\n nodes.forEach(function(node) {\n if (!node.targetLinks.length) {\n node.x = d3.min(node.sourceLinks, function(d) { return d.target.x; }) - 1;\n }\n });\n }\n\n function moveSinksRight(x) {\n nodes.forEach(function(node) {\n if (!node.sourceLinks.length) {\n node.x = x - 1;\n }\n });\n }\n\n function scaleNodeBreadths(kx) {\n nodes.forEach(function(node) {\n node.x *= kx;\n });\n }\n\n // Compute the depth (y-position) for each node.\n function computeNodeDepths(iterations) {\n // Group nodes by breath.\n var nodesByBreadth = d3.nest()\n .key(function(d) { return d.x; })\n .sortKeys(d3.ascending)\n .entries(nodes)\n .map(function(d) { return d.values; });\n\n //\n initializeNodeDepth();\n resolveCollisions();\n computeLinkDepths();\n for (var alpha = 1; iterations > 0; --iterations) {\n relaxRightToLeft(alpha *= .99);\n resolveCollisions();\n computeLinkDepths();\n relaxLeftToRight(alpha);\n resolveCollisions();\n computeLinkDepths();\n }\n\n function initializeNodeDepth() {\n // Calculate vertical scaling factor.\n var ky = d3.min(nodesByBreadth, function(nodes) {\n return (size[1] - (nodes.length - 1) * nodePadding) / d3.sum(nodes, value);\n });\n\n nodesByBreadth.forEach(function(nodes) {\n nodes.forEach(function(node, i) {\n node.y = i;\n node.dy = node.value * ky;\n });\n });\n\n links.forEach(function(link) {\n link.dy = link.value * ky;\n });\n }\n\n function relaxLeftToRight(alpha) {\n nodesByBreadth.forEach(function(nodes, breadth) {\n nodes.forEach(function(node) {\n if (node.targetLinks.length) {\n // Value-weighted average of the y-position of source node centers linked to this node.\n var y = d3.sum(node.targetLinks, weightedSource) / d3.sum(node.targetLinks, value);\n node.y += (y - center(node)) * alpha;\n }\n });\n });\n\n function weightedSource(link) {\n return (link.source.y + link.sy + link.dy / 2) * link.value;\n }\n }\n\n function relaxRightToLeft(alpha) {\n nodesByBreadth.slice().reverse().forEach(function(nodes) {\n nodes.forEach(function(node) {\n if (node.sourceLinks.length) {\n // Value-weighted average of the y-positions of target nodes linked to this node.\n var y = d3.sum(node.sourceLinks, weightedTarget) / d3.sum(node.sourceLinks, value);\n node.y += (y - center(node)) * alpha;\n }\n });\n });\n\n function weightedTarget(link) {\n return (link.target.y + link.ty + link.dy / 2) * link.value;\n }\n }\n\n function resolveCollisions() {\n nodesByBreadth.forEach(function(nodes) {\n var node,\n dy,\n y0 = 0,\n n = nodes.length,\n i;\n\n // Push any overlapping nodes down.\n nodes.sort(ascendingDepth);\n for (i = 0; i < n; ++i) {\n node = nodes[i];\n dy = y0 - node.y;\n if (dy > 0) node.y += dy;\n y0 = node.y + node.dy + nodePadding;\n }\n\n // If the bottommost node goes outside the bounds, push it back up.\n dy = y0 - nodePadding - size[1];\n if (dy > 0) {\n y0 = node.y -= dy;\n\n // Push any overlapping nodes back up.\n for (i = n - 2; i >= 0; --i) {\n node = nodes[i];\n dy = node.y + node.dy + nodePadding - y0;\n if (dy > 0) node.y -= dy;\n y0 = node.y;\n }\n }\n });\n }\n\n function ascendingDepth(a, b) {\n return a.y - b.y;\n }\n }\n\n // Compute y-offset of the source endpoint (sy) and target endpoints (ty) of links,\n // relative to the source/target node's y-position.\n function computeLinkDepths() {\n nodes.forEach(function(node) {\n node.sourceLinks.sort(ascendingTargetDepth);\n node.targetLinks.sort(ascendingSourceDepth);\n });\n nodes.forEach(function(node) {\n var sy = 0, ty = 0;\n node.sourceLinks.forEach(function(link) {\n link.sy = sy;\n sy += link.dy;\n });\n node.targetLinks.forEach(function(link) {\n link.ty = ty;\n ty += link.dy;\n });\n });\n\n function ascendingSourceDepth(a, b) {\n return a.source.y - b.source.y;\n }\n\n function ascendingTargetDepth(a, b) {\n return a.target.y - b.target.y;\n }\n }\n\n // Value property accessor.\n function value(x) {\n return x.value;\n }\n\n sankey.options = nv.utils.optionsFunc.bind(sankey);\n sankey._options = Object.create({}, {\n nodeWidth: {get: function(){return nodeWidth;}, set: function(_){nodeWidth=+_;}},\n nodePadding: {get: function(){return nodePadding;}, set: function(_){nodePadding=_;}},\n nodes: {get: function(){return nodes;}, set: function(_){nodes=_;}},\n links: {get: function(){return links ;}, set: function(_){links=_;}},\n size: {get: function(){return size;}, set: function(_){size=_;}},\n sinksRight: {get: function(){return sinksRight;}, set: function(_){sinksRight=_;}},\n\n layout: {get: function(){layout(32);}, set: function(_){layout(_);}},\n relayout: {get: function(){relayout();}, set: function(_){}},\n center: {get: function(){return center();}, set: function(_){\n if(typeof _ === 'function'){\n center=_;\n }\n }},\n link: {get: function(){return link();}, set: function(_){\n if(typeof _ === 'function'){\n link=_;\n }\n return link();\n }}\n });\n\n nv.utils.initOptions(sankey);\n\n return sankey;\n};\n","nv.models.sankeyChart = function() {\n \"use strict\";\n\n // Sources:\n // - https://bost.ocks.org/mike/sankey/\n // - https://github.com/soxofaan/d3-plugin-captain-sankey\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var margin = {top: 5, right: 0, bottom: 5, left: 0}\n , sankey = nv.models.sankey()\n , width = 600\n , height = 400\n , nodeWidth = 36\n , nodePadding = 40\n , units = 'units'\n , center = undefined\n ;\n\n //============================================================\n // Private Variables\n //------------------------------------------------------------\n\n var formatNumber = d3.format(',.0f'); // zero decimal places\n var format = function(d) {\n return formatNumber(d) + ' ' + units;\n };\n var color = d3.scale.category20();\n var linkTitle = function(d){\n return d.source.name + ' → ' + d.target.name + '\\n' + format(d.value);\n };\n var nodeFillColor = function(d){\n return d.color = color(d.name.replace(/ .*/, ''));\n };\n var nodeStrokeColor = function(d){\n return d3.rgb(d.color).darker(2);\n };\n var nodeTitle = function(d){\n return d.name + '\\n' + format(d.value);\n };\n\n var showError = function(element, message) {\n element.append('text')\n .attr('x', 0)\n .attr('y', 0)\n .attr('class', 'nvd3-sankey-chart-error')\n .attr('text-anchor', 'middle')\n .text(message);\n };\n\n function chart(selection) {\n selection.each(function(data) {\n\n var testData = {\n nodes:\n [\n {'node': 1, 'name': 'Test 1'},\n {'node': 2, 'name': 'Test 2'},\n {'node': 3, 'name': 'Test 3'},\n {'node': 4, 'name': 'Test 4'},\n {'node': 5, 'name': 'Test 5'},\n {'node': 6, 'name': 'Test 6'}\n ],\n links:\n [\n {'source': 0, 'target': 1, 'value': 2295},\n {'source': 0, 'target': 5, 'value': 1199},\n {'source': 1, 'target': 2, 'value': 1119},\n {'source': 1, 'target': 5, 'value': 1176},\n {'source': 2, 'target': 3, 'value': 487},\n {'source': 2, 'target': 5, 'value': 632},\n {'source': 3, 'target': 4, 'value': 301},\n {'source': 3, 'target': 5, 'value': 186}\n ]\n };\n\n // Error handling\n var isDataValid = false;\n var dataAvailable = false;\n\n // check if data is valid\n if(\n (typeof data['nodes'] === 'object' && data['nodes'].length) >= 0 &&\n (typeof data['links'] === 'object' && data['links'].length) >= 0\n ){\n isDataValid = true;\n }\n\n // check if data is available\n if(\n data['nodes'] && data['nodes'].length > 0 &&\n data['links'] && data['links'].length > 0\n ) {\n dataAvailable = true;\n }\n\n // show error\n if(!isDataValid) {\n console.error('NVD3 Sankey chart error:', 'invalid data format for', data);\n console.info('Valid data format is: ', testData, JSON.stringify(testData));\n showError(selection, 'Error loading chart, data is invalid');\n return false;\n }\n\n // TODO use nv.utils.noData\n if(!dataAvailable) {\n showError(selection, 'No data available');\n return false;\n }\n\n // No errors, continue\n\n // append the svg canvas to the page\n var svg = selection.append('svg')\n .attr('width', width)\n .attr('height', height)\n .append('g')\n .attr('class', 'nvd3 nv-wrap nv-sankeyChart');\n\n // Set the sankey diagram properties\n sankey\n .nodeWidth(nodeWidth)\n .nodePadding(nodePadding)\n .size([width, height]);\n\n var path = sankey.link();\n\n sankey\n .nodes(data.nodes)\n .links(data.links)\n .layout(32)\n .center(center);\n\n // add in the links\n var link = svg.append('g').selectAll('.link')\n .data(data.links)\n .enter().append('path')\n .attr('class', 'link')\n .attr('d', path)\n .style('stroke-width', function(d) { return Math.max(1, d.dy); })\n .sort(function(a,b) { return b.dy - a.dy; });\n\n // add the link titles\n link.append('title')\n .text(linkTitle);\n\n // add in the nodes\n var node = svg.append('g').selectAll('.node')\n .data(data.nodes)\n .enter().append('g')\n .attr('class', 'node')\n .attr('transform', function(d) { return 'translate(' + d.x + ',' + d.y + ')'; })\n .call(\n d3.behavior\n .drag()\n .origin(function(d) { return d; })\n .on('dragstart', function() {\n this.parentNode.appendChild(this);\n })\n .on('drag', dragmove)\n );\n\n // add the rectangles for the nodes\n node.append('rect')\n .attr('height', function(d) { return d.dy; })\n .attr('width', sankey.nodeWidth())\n .style('fill', nodeFillColor)\n .style('stroke', nodeStrokeColor)\n .append('title')\n .text(nodeTitle);\n\n // add in the title for the nodes\n node.append('text')\n .attr('x', -6)\n .attr('y', function(d) { return d.dy / 2; })\n .attr('dy', '.35em')\n .attr('text-anchor', 'end')\n .attr('transform', null)\n .text(function(d) { return d.name; })\n .filter(function(d) { return d.x < width / 2; })\n .attr('x', 6 + sankey.nodeWidth())\n .attr('text-anchor', 'start');\n\n // the function for moving the nodes\n function dragmove(d) {\n d3.select(this).attr('transform',\n 'translate(' + d.x + ',' + (\n d.y = Math.max(0, Math.min(height - d.dy, d3.event.y))\n ) + ')');\n sankey.relayout();\n link.attr('d', path);\n }\n });\n\n return chart;\n }\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n units: {get: function(){return units;}, set: function(_){units=_;}},\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n format: {get: function(){return format;}, set: function(_){format=_;}},\n linkTitle: {get: function(){return linkTitle;}, set: function(_){linkTitle=_;}},\n nodeWidth: {get: function(){return nodeWidth;}, set: function(_){nodeWidth=_;}},\n nodePadding: {get: function(){return nodePadding;}, set: function(_){nodePadding=_;}},\n center: {get: function(){return center}, set: function(_){center=_}},\n\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n margin.top = _.top !== undefined ? _.top : margin.top;\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n }},\n nodeStyle: {get: function(){return {};}, set: function(_){\n nodeFillColor = _.fillColor !== undefined ? _.fillColor : nodeFillColor;\n nodeStrokeColor = _.strokeColor !== undefined ? _.strokeColor : nodeStrokeColor;\n nodeTitle = _.title !== undefined ? _.title : nodeTitle;\n }}\n\n });\n\n nv.utils.initOptions(chart);\n\n return chart;\n};\n","\nnv.models.scatter = function() {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var margin = {top: 0, right: 0, bottom: 0, left: 0}\n , width = null\n , height = null\n , color = nv.utils.defaultColor() // chooses color\n , pointBorderColor = null\n , id = Math.floor(Math.random() * 100000) //Create semi-unique ID incase user doesn't select one\n , container = null\n , x = d3.scale.linear()\n , y = d3.scale.linear()\n , z = d3.scale.linear() //linear because d3.svg.shape.size is treated as area\n , getX = function(d) { return d.x } // accessor to get the x value\n , getY = function(d) { return d.y } // accessor to get the y value\n , getSize = function(d) { return d.size || 1} // accessor to get the point size\n , getShape = function(d) { return d.shape || 'circle' } // accessor to get point shape\n , forceX = [] // List of numbers to Force into the X scale (ie. 0, or a max / min, etc.)\n , forceY = [] // List of numbers to Force into the Y scale\n , forceSize = [] // List of numbers to Force into the Size scale\n , interactive = true // If true, plots a voronoi overlay for advanced point intersection\n , pointActive = function(d) { return !d.notActive } // any points that return false will be filtered out\n , padData = false // If true, adds half a data points width to front and back, for lining up a line chart with a bar chart\n , padDataOuter = .1 //outerPadding to imitate ordinal scale outer padding\n , clipEdge = false // if true, masks points within x and y scale\n , clipVoronoi = true // if true, masks each point with a circle... can turn off to slightly increase performance\n , showVoronoi = false // display the voronoi areas\n , clipRadius = function() { return 25 } // function to get the radius for voronoi point clips\n , xDomain = null // Override x domain (skips the calculation from data)\n , yDomain = null // Override y domain\n , xRange = null // Override x range\n , yRange = null // Override y range\n , sizeDomain = null // Override point size domain\n , sizeRange = null\n , singlePoint = false\n , dispatch = d3.dispatch('elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'renderEnd')\n , useVoronoi = true\n , duration = 250\n , interactiveUpdateDelay = 300\n , showLabels = false\n ;\n\n\n //============================================================\n // Private Variables\n //------------------------------------------------------------\n\n var x0, y0, z0 // used to store previous scales\n , width0\n , height0\n , timeoutID\n , needsUpdate = false // Flag for when the points are visually updating, but the interactive layer is behind, to disable tooltips\n , renderWatch = nv.utils.renderWatch(dispatch, duration)\n , _sizeRange_def = [16, 256]\n , _cache = {}\n ;\n\n function getCache(d) {\n var key, val;\n key = d[0].series + ':' + d[1];\n val = _cache[key] = _cache[key] || {};\n return val;\n }\n\n function delCache(d) {\n var key, val;\n key = d[0].series + ':' + d[1];\n delete _cache[key];\n }\n\n function getDiffs(d) {\n var i, key, val,\n cache = getCache(d),\n diffs = false;\n for (i = 1; i < arguments.length; i += 2) {\n key = arguments[i];\n val = arguments[i + 1](d[0], d[1]);\n if (cache[key] !== val || !cache.hasOwnProperty(key)) {\n cache[key] = val;\n diffs = true;\n }\n }\n return diffs;\n }\n\n function chart(selection) {\n renderWatch.reset();\n selection.each(function(data) {\n container = d3.select(this);\n var availableWidth = nv.utils.availableWidth(width, container, margin),\n availableHeight = nv.utils.availableHeight(height, container, margin);\n\n nv.utils.initSVG(container);\n\n //add series index to each data point for reference\n data.forEach(function(series, i) {\n series.values.forEach(function(point) {\n point.series = i;\n });\n });\n\n // Setup Scales\n var logScale = chart.yScale().name === d3.scale.log().name ? true : false;\n // remap and flatten the data for use in calculating the scales' domains\n var seriesData = (xDomain && yDomain && sizeDomain) ? [] : // if we know xDomain and yDomain and sizeDomain, no need to calculate.... if Size is constant remember to set sizeDomain to speed up performance\n d3.merge(\n data.map(function(d) {\n return d.values.map(function(d,i) {\n return { x: getX(d,i), y: getY(d,i), size: getSize(d,i) }\n })\n })\n );\n\n x .domain(xDomain || d3.extent(seriesData.map(function(d) { return d.x; }).concat(forceX)))\n\n if (padData && data[0])\n x.range(xRange || [(availableWidth * padDataOuter + availableWidth) / (2 *data[0].values.length), availableWidth - availableWidth * (1 + padDataOuter) / (2 * data[0].values.length) ]);\n //x.range([availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5) / data[0].values.length ]);\n else\n x.range(xRange || [0, availableWidth]);\n\n if (logScale) {\n var min = d3.min(seriesData.map(function(d) { if (d.y !== 0) return d.y; }));\n y.clamp(true)\n .domain(yDomain || d3.extent(seriesData.map(function(d) {\n if (d.y !== 0) return d.y;\n else return min * 0.1;\n }).concat(forceY)))\n .range(yRange || [availableHeight, 0]);\n } else {\n y.domain(yDomain || d3.extent(seriesData.map(function (d) { return d.y;}).concat(forceY)))\n .range(yRange || [availableHeight, 0]);\n }\n\n z .domain(sizeDomain || d3.extent(seriesData.map(function(d) { return d.size }).concat(forceSize)))\n .range(sizeRange || _sizeRange_def);\n\n // If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point\n singlePoint = x.domain()[0] === x.domain()[1] || y.domain()[0] === y.domain()[1];\n\n if (x.domain()[0] === x.domain()[1])\n x.domain()[0] ?\n x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01])\n : x.domain([-1,1]);\n\n if (y.domain()[0] === y.domain()[1])\n y.domain()[0] ?\n y.domain([y.domain()[0] - y.domain()[0] * 0.01, y.domain()[1] + y.domain()[1] * 0.01])\n : y.domain([-1,1]);\n\n if ( isNaN(x.domain()[0])) {\n x.domain([-1,1]);\n }\n\n if ( isNaN(y.domain()[0])) {\n y.domain([-1,1]);\n }\n\n x0 = x0 || x;\n y0 = y0 || y;\n z0 = z0 || z;\n\n var scaleDiff = x(1) !== x0(1) || y(1) !== y0(1) || z(1) !== z0(1);\n\n width0 = width0 || width;\n height0 = height0 || height;\n\n var sizeDiff = width0 !== width || height0 !== height;\n\n // Setup containers and skeleton of chart\n var wrap = container.selectAll('g.nv-wrap.nv-scatter').data([data]);\n var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-scatter nv-chart-' + id);\n var defsEnter = wrapEnter.append('defs');\n var gEnter = wrapEnter.append('g');\n var g = wrap.select('g');\n\n wrap.classed('nv-single-point', singlePoint);\n gEnter.append('g').attr('class', 'nv-groups');\n gEnter.append('g').attr('class', 'nv-point-paths');\n wrapEnter.append('g').attr('class', 'nv-point-clips');\n\n wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');\n\n defsEnter.append('clipPath')\n .attr('id', 'nv-edge-clip-' + id)\n .append('rect')\n .attr('transform', 'translate( -10, -10)');\n \n wrap.select('#nv-edge-clip-' + id + ' rect')\n .attr('width', availableWidth + 20)\n .attr('height', (availableHeight > 0) ? availableHeight + 20 : 0);\n\n g.attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : '');\n\n function updateInteractiveLayer() {\n // Always clear needs-update flag regardless of whether or not\n // we will actually do anything (avoids needless invocations).\n needsUpdate = false;\n\n if (!interactive) return false;\n\n // inject series and point index for reference into voronoi\n if (useVoronoi === true) {\n var vertices = d3.merge(data.map(function(group, groupIndex) {\n return group.values\n .map(function(point, pointIndex) {\n // *Adding noise to make duplicates very unlikely\n // *Injecting series and point index for reference\n /* *Adding a 'jitter' to the points, because there's an issue in d3.geom.voronoi.\n */\n var pX = getX(point,pointIndex);\n var pY = getY(point,pointIndex);\n\n return [nv.utils.NaNtoZero(x(pX))+ Math.random() * 1e-4,\n nv.utils.NaNtoZero(y(pY))+ Math.random() * 1e-4,\n groupIndex,\n pointIndex, point]; //temp hack to add noise until I think of a better way so there are no duplicates\n })\n .filter(function(pointArray, pointIndex) {\n return pointActive(pointArray[4], pointIndex); // Issue #237.. move filter to after map, so pointIndex is correct!\n })\n })\n );\n\n if (vertices.length == 0) return false; // No active points, we're done\n if (vertices.length < 3) {\n // Issue #283 - Adding 2 dummy points to the voronoi b/c voronoi requires min 3 points to work\n vertices.push([x.range()[0] - 20, y.range()[0] - 20, null, null]);\n vertices.push([x.range()[1] + 20, y.range()[1] + 20, null, null]);\n vertices.push([x.range()[0] - 20, y.range()[0] + 20, null, null]);\n vertices.push([x.range()[1] + 20, y.range()[1] - 20, null, null]);\n }\n\n // keep voronoi sections from going more than 10 outside of graph\n // to avoid overlap with other things like legend etc\n var bounds = d3.geom.polygon([\n [-10,-10],\n [-10,height + 10],\n [width + 10,height + 10],\n [width + 10,-10]\n ]);\n\n var voronoi = d3.geom.voronoi(vertices).map(function(d, i) {\n return {\n 'data': bounds.clip(d),\n 'series': vertices[i][2],\n 'point': vertices[i][3]\n }\n });\n\n // nuke all voronoi paths on reload and recreate them\n wrap.select('.nv-point-paths').selectAll('path').remove();\n var pointPaths = wrap.select('.nv-point-paths').selectAll('path').data(voronoi);\n var vPointPaths = pointPaths\n .enter().append(\"svg:path\")\n .attr(\"d\", function(d) {\n if (!d || !d.data || d.data.length === 0)\n return 'M 0 0';\n else\n return \"M\" + d.data.join(\",\") + \"Z\";\n })\n .attr(\"id\", function(d,i) {\n return \"nv-path-\"+i; })\n .attr(\"clip-path\", function(d,i) { return \"url(#nv-clip-\"+id+\"-\"+i+\")\"; })\n ;\n\n // good for debugging point hover issues\n if (showVoronoi) {\n vPointPaths.style(\"fill\", d3.rgb(230, 230, 230))\n .style('fill-opacity', 0.4)\n .style('stroke-opacity', 1)\n .style(\"stroke\", d3.rgb(200,200,200));\n }\n\n if (clipVoronoi) {\n // voronoi sections are already set to clip,\n // just create the circles with the IDs they expect\n wrap.select('.nv-point-clips').selectAll('*').remove(); // must do * since it has sub-dom\n var pointClips = wrap.select('.nv-point-clips').selectAll('clipPath').data(vertices);\n var vPointClips = pointClips\n .enter().append(\"svg:clipPath\")\n .attr(\"id\", function(d, i) { return \"nv-clip-\"+id+\"-\"+i;})\n .append(\"svg:circle\")\n .attr('cx', function(d) { return d[0]; })\n .attr('cy', function(d) { return d[1]; })\n .attr('r', clipRadius);\n }\n\n var mouseEventCallback = function(el, d, mDispatch) {\n if (needsUpdate) return 0;\n var series = data[d.series];\n if (series === undefined) return;\n var point = series.values[d.point];\n point['color'] = color(series, d.series);\n\n // standardize attributes for tooltip.\n point['x'] = getX(point);\n point['y'] = getY(point);\n\n // can't just get box of event node since it's actually a voronoi polygon\n var box = container.node().getBoundingClientRect();\n var scrollTop = window.pageYOffset || document.documentElement.scrollTop;\n var scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;\n\n var pos = {\n left: x(getX(point, d.point)) + box.left + scrollLeft + margin.left + 10,\n top: y(getY(point, d.point)) + box.top + scrollTop + margin.top + 10\n };\n\n mDispatch({\n point: point,\n series: series,\n pos: pos,\n relativePos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top],\n seriesIndex: d.series,\n pointIndex: d.point,\n event: d3.event,\n element: el\n });\n };\n\n pointPaths\n .on('click', function(d) {\n mouseEventCallback(this, d, dispatch.elementClick);\n })\n .on('dblclick', function(d) {\n mouseEventCallback(this, d, dispatch.elementDblClick);\n })\n .on('mouseover', function(d) {\n mouseEventCallback(this, d, dispatch.elementMouseover);\n })\n .on('mouseout', function(d, i) {\n mouseEventCallback(this, d, dispatch.elementMouseout);\n });\n\n } else {\n // add event handlers to points instead voronoi paths\n wrap.select('.nv-groups').selectAll('.nv-group')\n .selectAll('.nv-point')\n //.data(dataWithPoints)\n //.style('pointer-events', 'auto') // recativate events, disabled by css\n .on('click', function(d,i) {\n //nv.log('test', d, i);\n if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point\n var series = data[d.series],\n point = series.values[i];\n var element = this;\n dispatch.elementClick({\n point: point,\n series: series,\n pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top], //TODO: make this pos base on the page\n relativePos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],\n seriesIndex: d.series,\n pointIndex: i,\n event: d3.event,\n element: element\n });\n })\n .on('dblclick', function(d,i) {\n if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point\n var series = data[d.series],\n point = series.values[i];\n\n dispatch.elementDblClick({\n point: point,\n series: series,\n pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],//TODO: make this pos base on the page\n relativePos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],\n seriesIndex: d.series,\n pointIndex: i\n });\n })\n .on('mouseover', function(d,i) {\n if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point\n var series = data[d.series],\n point = series.values[i];\n\n dispatch.elementMouseover({\n point: point,\n series: series,\n pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],//TODO: make this pos base on the page\n relativePos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],\n seriesIndex: d.series,\n pointIndex: i,\n color: color(d, i)\n });\n })\n .on('mouseout', function(d,i) {\n if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point\n var series = data[d.series],\n point = series.values[i];\n\n dispatch.elementMouseout({\n point: point,\n series: series,\n pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],//TODO: make this pos base on the page\n relativePos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],\n seriesIndex: d.series,\n pointIndex: i,\n color: color(d, i)\n });\n });\n }\n }\n\n needsUpdate = true;\n var groups = wrap.select('.nv-groups').selectAll('.nv-group')\n .data(function(d) { return d }, function(d) { return d.key });\n groups.enter().append('g')\n .style('stroke-opacity', 1e-6)\n .style('fill-opacity', 1e-6);\n groups.exit()\n .remove();\n groups\n .attr('class', function(d,i) {\n return (d.classed || '') + ' nv-group nv-series-' + i;\n })\n .classed('nv-noninteractive', !interactive)\n .classed('hover', function(d) { return d.hover });\n groups.watchTransition(renderWatch, 'scatter: groups')\n .style('fill', function(d,i) { return color(d, i) })\n .style('stroke', function(d,i) { return d.pointBorderColor || pointBorderColor || color(d, i) })\n .style('stroke-opacity', 1)\n .style('fill-opacity', .5);\n\n // create the points, maintaining their IDs from the original data set\n var points = groups.selectAll('path.nv-point')\n .data(function(d) {\n return d.values.map(\n function (point, pointIndex) {\n return [point, pointIndex]\n }).filter(\n function(pointArray, pointIndex) {\n return pointActive(pointArray[0], pointIndex)\n })\n });\n points.enter().append('path')\n .attr('class', function (d) {\n return 'nv-point nv-point-' + d[1];\n })\n .style('fill', function (d) { return d.color })\n .style('stroke', function (d) { return d.color })\n .attr('transform', function(d) {\n return 'translate(' + nv.utils.NaNtoZero(x0(getX(d[0],d[1]))) + ',' + nv.utils.NaNtoZero(y0(getY(d[0],d[1]))) + ')'\n })\n .attr('d',\n nv.utils.symbol()\n .type(function(d) { return getShape(d[0]); })\n .size(function(d) { return z(getSize(d[0],d[1])) })\n );\n points.exit().each(delCache).remove();\n groups.exit().selectAll('path.nv-point')\n .watchTransition(renderWatch, 'scatter exit')\n .attr('transform', function(d) {\n return 'translate(' + nv.utils.NaNtoZero(x(getX(d[0],d[1]))) + ',' + nv.utils.NaNtoZero(y(getY(d[0],d[1]))) + ')'\n })\n .remove();\n // Update points position only if \"x\" or \"y\" have changed\n points.filter(function (d) { return scaleDiff || sizeDiff || getDiffs(d, 'x', getX, 'y', getY); })\n .watchTransition(renderWatch, 'scatter points')\n .attr('transform', function(d) {\n //nv.log(d, getX(d[0],d[1]), x(getX(d[0],d[1])));\n return 'translate(' + nv.utils.NaNtoZero(x(getX(d[0],d[1]))) + ',' + nv.utils.NaNtoZero(y(getY(d[0],d[1]))) + ')'\n });\n // Update points appearance only if \"shape\" or \"size\" have changed\n points.filter(function (d) { return scaleDiff || sizeDiff || getDiffs(d, 'shape', getShape, 'size', getSize); })\n .watchTransition(renderWatch, 'scatter points')\n .attr('d',\n nv.utils.symbol()\n .type(function(d) { return getShape(d[0]); })\n .size(function(d) { return z(getSize(d[0],d[1])) })\n );\n\n // add label a label to scatter chart\n if(showLabels)\n {\n var titles = groups.selectAll('.nv-label')\n .data(function(d) {\n return d.values.map(\n function (point, pointIndex) {\n return [point, pointIndex]\n }).filter(\n function(pointArray, pointIndex) {\n return pointActive(pointArray[0], pointIndex)\n })\n });\n\n titles.enter().append('text')\n .style('fill', function (d,i) {\n return d.color })\n .style('stroke-opacity', 0)\n .style('fill-opacity', 1)\n .attr('transform', function(d) {\n var dx = nv.utils.NaNtoZero(x0(getX(d[0],d[1]))) + Math.sqrt(z(getSize(d[0],d[1]))/Math.PI) + 2;\n return 'translate(' + dx + ',' + nv.utils.NaNtoZero(y0(getY(d[0],d[1]))) + ')';\n })\n .text(function(d,i){\n return d[0].label;});\n\n titles.exit().remove();\n groups.exit().selectAll('path.nv-label')\n .watchTransition(renderWatch, 'scatter exit')\n .attr('transform', function(d) {\n var dx = nv.utils.NaNtoZero(x(getX(d[0],d[1])))+ Math.sqrt(z(getSize(d[0],d[1]))/Math.PI)+2;\n return 'translate(' + dx + ',' + nv.utils.NaNtoZero(y(getY(d[0],d[1]))) + ')';\n })\n .remove();\n titles.each(function(d) {\n d3.select(this)\n .classed('nv-label', true)\n .classed('nv-label-' + d[1], false)\n .classed('hover',false);\n });\n titles.watchTransition(renderWatch, 'scatter labels')\n .attr('transform', function(d) {\n var dx = nv.utils.NaNtoZero(x(getX(d[0],d[1])))+ Math.sqrt(z(getSize(d[0],d[1]))/Math.PI)+2;\n return 'translate(' + dx + ',' + nv.utils.NaNtoZero(y(getY(d[0],d[1]))) + ')'\n });\n }\n\n // Delay updating the invisible interactive layer for smoother animation\n if( interactiveUpdateDelay )\n {\n clearTimeout(timeoutID); // stop repeat calls to updateInteractiveLayer\n timeoutID = setTimeout(updateInteractiveLayer, interactiveUpdateDelay );\n }\n else\n {\n updateInteractiveLayer();\n }\n\n //store old scales for use in transitions on update\n x0 = x.copy();\n y0 = y.copy();\n z0 = z.copy();\n\n width0 = width;\n height0 = height;\n\n });\n renderWatch.renderEnd('scatter immediate');\n return chart;\n }\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n chart.dispatch = dispatch;\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n // utility function calls provided by this chart\n chart._calls = new function() {\n this.clearHighlights = function () {\n nv.dom.write(function() {\n container.selectAll(\".nv-point.hover\").classed(\"hover\", false);\n });\n return null;\n };\n this.highlightPoint = function (seriesIndex, pointIndex, isHoverOver) {\n nv.dom.write(function() {\n container.select('.nv-groups')\n .selectAll(\".nv-series-\" + seriesIndex)\n .selectAll(\".nv-point-\" + pointIndex)\n .classed(\"hover\", isHoverOver);\n });\n };\n };\n\n // trigger calls from events too\n dispatch.on('elementMouseover.point', function(d) {\n if (interactive) chart._calls.highlightPoint(d.seriesIndex,d.pointIndex,true);\n });\n\n dispatch.on('elementMouseout.point', function(d) {\n if (interactive) chart._calls.highlightPoint(d.seriesIndex,d.pointIndex,false);\n });\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n xScale: {get: function(){return x;}, set: function(_){x=_;}},\n yScale: {get: function(){return y;}, set: function(_){y=_;}},\n pointScale: {get: function(){return z;}, set: function(_){z=_;}},\n xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}},\n yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}},\n pointDomain: {get: function(){return sizeDomain;}, set: function(_){sizeDomain=_;}},\n xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}},\n yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}},\n pointRange: {get: function(){return sizeRange;}, set: function(_){sizeRange=_;}},\n forceX: {get: function(){return forceX;}, set: function(_){forceX=_;}},\n forceY: {get: function(){return forceY;}, set: function(_){forceY=_;}},\n forcePoint: {get: function(){return forceSize;}, set: function(_){forceSize=_;}},\n interactive: {get: function(){return interactive;}, set: function(_){interactive=_;}},\n pointActive: {get: function(){return pointActive;}, set: function(_){pointActive=_;}},\n padDataOuter: {get: function(){return padDataOuter;}, set: function(_){padDataOuter=_;}},\n padData: {get: function(){return padData;}, set: function(_){padData=_;}},\n clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}},\n clipVoronoi: {get: function(){return clipVoronoi;}, set: function(_){clipVoronoi=_;}},\n clipRadius: {get: function(){return clipRadius;}, set: function(_){clipRadius=_;}},\n showVoronoi: {get: function(){return showVoronoi;}, set: function(_){showVoronoi=_;}},\n id: {get: function(){return id;}, set: function(_){id=_;}},\n interactiveUpdateDelay: {get:function(){return interactiveUpdateDelay;}, set: function(_){interactiveUpdateDelay=_;}},\n showLabels: {get: function(){return showLabels;}, set: function(_){ showLabels = _;}},\n pointBorderColor: {get: function(){return pointBorderColor;}, set: function(_){pointBorderColor=_;}},\n\n // simple functor options\n x: {get: function(){return getX;}, set: function(_){getX = d3.functor(_);}},\n y: {get: function(){return getY;}, set: function(_){getY = d3.functor(_);}},\n pointSize: {get: function(){return getSize;}, set: function(_){getSize = d3.functor(_);}},\n pointShape: {get: function(){return getShape;}, set: function(_){getShape = d3.functor(_);}},\n\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n margin.top = _.top !== undefined ? _.top : margin.top;\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n }},\n duration: {get: function(){return duration;}, set: function(_){\n duration = _;\n renderWatch.reset(duration);\n }},\n color: {get: function(){return color;}, set: function(_){\n color = nv.utils.getColor(_);\n }},\n useVoronoi: {get: function(){return useVoronoi;}, set: function(_){\n useVoronoi = _;\n if (useVoronoi === false) {\n clipVoronoi = false;\n }\n }}\n });\n\n nv.utils.initOptions(chart);\n return chart;\n};\n","\nnv.models.scatterChart = function() {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var scatter = nv.models.scatter()\n , xAxis = nv.models.axis()\n , yAxis = nv.models.axis()\n , legend = nv.models.legend()\n , distX = nv.models.distribution()\n , distY = nv.models.distribution()\n , tooltip = nv.models.tooltip()\n ;\n\n var margin = {top: 30, right: 20, bottom: 50, left: 75}\n , marginTop = null\n , width = null\n , height = null\n , container = null\n , color = nv.utils.defaultColor()\n , x = scatter.xScale()\n , y = scatter.yScale()\n , showDistX = false\n , showDistY = false\n , showLegend = true\n , showXAxis = true\n , showYAxis = true\n , rightAlignYAxis = false\n , state = nv.utils.state()\n , defaultState = null\n , dispatch = d3.dispatch('stateChange', 'changeState', 'renderEnd')\n , noData = null\n , duration = 250\n , showLabels = false\n ;\n\n scatter.xScale(x).yScale(y);\n xAxis.orient('bottom').tickPadding(10);\n yAxis\n .orient((rightAlignYAxis) ? 'right' : 'left')\n .tickPadding(10)\n ;\n distX.axis('x');\n distY.axis('y');\n tooltip\n .headerFormatter(function(d, i) {\n return xAxis.tickFormat()(d, i);\n })\n .valueFormatter(function(d, i) {\n return yAxis.tickFormat()(d, i);\n });\n\n //============================================================\n // Private Variables\n //------------------------------------------------------------\n\n var x0, y0\n , renderWatch = nv.utils.renderWatch(dispatch, duration);\n\n var stateGetter = function(data) {\n return function(){\n return {\n active: data.map(function(d) { return !d.disabled })\n };\n }\n };\n\n var stateSetter = function(data) {\n return function(state) {\n if (state.active !== undefined)\n data.forEach(function(series,i) {\n series.disabled = !state.active[i];\n });\n }\n };\n\n function chart(selection) {\n renderWatch.reset();\n renderWatch.models(scatter);\n if (showXAxis) renderWatch.models(xAxis);\n if (showYAxis) renderWatch.models(yAxis);\n if (showDistX) renderWatch.models(distX);\n if (showDistY) renderWatch.models(distY);\n\n selection.each(function(data) {\n var that = this;\n\n container = d3.select(this);\n nv.utils.initSVG(container);\n\n var availableWidth = nv.utils.availableWidth(width, container, margin),\n availableHeight = nv.utils.availableHeight(height, container, margin);\n\n chart.update = function() {\n if (duration === 0)\n container.call(chart);\n else\n container.transition().duration(duration).call(chart);\n };\n chart.container = this;\n\n state\n .setter(stateSetter(data), chart.update)\n .getter(stateGetter(data))\n .update();\n\n // DEPRECATED set state.disableddisabled\n state.disabled = data.map(function(d) { return !!d.disabled });\n\n if (!defaultState) {\n var key;\n defaultState = {};\n for (key in state) {\n if (state[key] instanceof Array)\n defaultState[key] = state[key].slice(0);\n else\n defaultState[key] = state[key];\n }\n }\n\n // Display noData message if there's nothing to show.\n if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {\n nv.utils.noData(chart, container);\n renderWatch.renderEnd('scatter immediate');\n return chart;\n } else {\n container.selectAll('.nv-noData').remove();\n }\n\n // Setup Scales\n x = scatter.xScale();\n y = scatter.yScale();\n\n // Setup containers and skeleton of chart\n var wrap = container.selectAll('g.nv-wrap.nv-scatterChart').data([data]);\n var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-scatterChart nv-chart-' + scatter.id());\n var gEnter = wrapEnter.append('g');\n var g = wrap.select('g');\n\n // background for pointer events\n gEnter.append('rect').attr('class', 'nvd3 nv-background').style(\"pointer-events\",\"none\");\n\n gEnter.append('g').attr('class', 'nv-x nv-axis');\n gEnter.append('g').attr('class', 'nv-y nv-axis');\n gEnter.append('g').attr('class', 'nv-scatterWrap');\n gEnter.append('g').attr('class', 'nv-regressionLinesWrap');\n gEnter.append('g').attr('class', 'nv-distWrap');\n gEnter.append('g').attr('class', 'nv-legendWrap');\n\n if (rightAlignYAxis) {\n g.select(\".nv-y.nv-axis\")\n .attr(\"transform\", \"translate(\" + availableWidth + \",0)\");\n }\n\n // Legend\n if (!showLegend) {\n g.select('.nv-legendWrap').selectAll('*').remove();\n } else {\n var legendWidth = availableWidth;\n legend.width(legendWidth);\n\n wrap.select('.nv-legendWrap')\n .datum(data)\n .call(legend);\n\n if (!marginTop && legend.height() !== margin.top) {\n margin.top = legend.height();\n availableHeight = nv.utils.availableHeight(height, container, margin);\n }\n\n wrap.select('.nv-legendWrap')\n .attr('transform', 'translate(0' + ',' + (-margin.top) +')');\n }\n\n wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');\n\n // Main Chart Component(s)\n scatter\n .width(availableWidth)\n .height(availableHeight)\n .color(data.map(function(d,i) {\n d.color = d.color || color(d, i);\n return d.color;\n }).filter(function(d,i) { return !data[i].disabled }))\n .showLabels(showLabels);\n\n wrap.select('.nv-scatterWrap')\n .datum(data.filter(function(d) { return !d.disabled }))\n .call(scatter);\n\n\n wrap.select('.nv-regressionLinesWrap')\n .attr('clip-path', 'url(#nv-edge-clip-' + scatter.id() + ')');\n\n var regWrap = wrap.select('.nv-regressionLinesWrap').selectAll('.nv-regLines')\n .data(function (d) {\n return d;\n });\n\n regWrap.enter().append('g').attr('class', 'nv-regLines');\n\n var regLine = regWrap.selectAll('.nv-regLine')\n .data(function (d) {\n return [d]\n });\n\n regLine.enter()\n .append('line').attr('class', 'nv-regLine')\n .style('stroke-opacity', 0);\n\n // don't add lines unless we have slope and intercept to use\n regLine.filter(function(d) {\n return d.intercept && d.slope;\n })\n .watchTransition(renderWatch, 'scatterPlusLineChart: regline')\n .attr('x1', x.range()[0])\n .attr('x2', x.range()[1])\n .attr('y1', function (d, i) {\n return y(x.domain()[0] * d.slope + d.intercept)\n })\n .attr('y2', function (d, i) {\n return y(x.domain()[1] * d.slope + d.intercept)\n })\n .style('stroke', function (d, i, j) {\n return color(d, j)\n })\n .style('stroke-opacity', function (d, i) {\n return (d.disabled || typeof d.slope === 'undefined' || typeof d.intercept === 'undefined') ? 0 : 1\n });\n\n // Setup Axes\n if (showXAxis) {\n xAxis\n .scale(x)\n ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )\n .tickSize( -availableHeight , 0);\n\n g.select('.nv-x.nv-axis')\n .attr('transform', 'translate(0,' + y.range()[0] + ')')\n .call(xAxis);\n }\n\n if (showYAxis) {\n yAxis\n .scale(y)\n ._ticks( nv.utils.calcTicksY(availableHeight/36, data) )\n .tickSize( -availableWidth, 0);\n\n g.select('.nv-y.nv-axis')\n .call(yAxis);\n }\n\n // Setup Distribution\n if (showDistX) {\n distX\n .getData(scatter.x())\n .scale(x)\n .width(availableWidth)\n .color(data.map(function(d,i) {\n return d.color || color(d, i);\n }).filter(function(d,i) { return !data[i].disabled }));\n gEnter.select('.nv-distWrap').append('g')\n .attr('class', 'nv-distributionX');\n g.select('.nv-distributionX')\n .attr('transform', 'translate(0,' + y.range()[0] + ')')\n .datum(data.filter(function(d) { return !d.disabled }))\n .call(distX);\n }\n\n if (showDistY) {\n distY\n .getData(scatter.y())\n .scale(y)\n .width(availableHeight)\n .color(data.map(function(d,i) {\n return d.color || color(d, i);\n }).filter(function(d,i) { return !data[i].disabled }));\n gEnter.select('.nv-distWrap').append('g')\n .attr('class', 'nv-distributionY');\n g.select('.nv-distributionY')\n .attr('transform', 'translate(' + (rightAlignYAxis ? availableWidth : -distY.size() ) + ',0)')\n .datum(data.filter(function(d) { return !d.disabled }))\n .call(distY);\n }\n\n //============================================================\n // Event Handling/Dispatching (in chart's scope)\n //------------------------------------------------------------\n\n legend.dispatch.on('stateChange', function(newState) {\n for (var key in newState)\n state[key] = newState[key];\n dispatch.stateChange(state);\n chart.update();\n });\n\n // Update chart from a state object passed to event handler\n dispatch.on('changeState', function(e) {\n if (typeof e.disabled !== 'undefined') {\n data.forEach(function(series,i) {\n series.disabled = e.disabled[i];\n });\n state.disabled = e.disabled;\n }\n chart.update();\n });\n\n // mouseover needs availableHeight so we just keep scatter mouse events inside the chart block\n scatter.dispatch.on('elementMouseout.tooltip', function(evt) {\n tooltip.hidden(true);\n container.select('.nv-chart-' + scatter.id() + ' .nv-series-' + evt.seriesIndex + ' .nv-distx-' + evt.pointIndex)\n .attr('y1', 0);\n container.select('.nv-chart-' + scatter.id() + ' .nv-series-' + evt.seriesIndex + ' .nv-disty-' + evt.pointIndex)\n .attr('x2', distY.size());\n });\n\n scatter.dispatch.on('elementMouseover.tooltip', function(evt) {\n container.select('.nv-series-' + evt.seriesIndex + ' .nv-distx-' + evt.pointIndex)\n .attr('y1', evt.relativePos[1] - availableHeight);\n container.select('.nv-series-' + evt.seriesIndex + ' .nv-disty-' + evt.pointIndex)\n .attr('x2', evt.relativePos[0] + distX.size());\n tooltip.data(evt).hidden(false);\n });\n\n //store old scales for use in transitions on update\n x0 = x.copy();\n y0 = y.copy();\n\n });\n\n renderWatch.renderEnd('scatter with line immediate');\n return chart;\n }\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n // expose chart's sub-components\n chart.dispatch = dispatch;\n chart.scatter = scatter;\n chart.legend = legend;\n chart.xAxis = xAxis;\n chart.yAxis = yAxis;\n chart.distX = distX;\n chart.distY = distY;\n chart.tooltip = tooltip;\n\n chart.options = nv.utils.optionsFunc.bind(chart);\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n container: {get: function(){return container;}, set: function(_){container=_;}},\n showDistX: {get: function(){return showDistX;}, set: function(_){showDistX=_;}},\n showDistY: {get: function(){return showDistY;}, set: function(_){showDistY=_;}},\n showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},\n showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},\n showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},\n defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}},\n noData: {get: function(){return noData;}, set: function(_){noData=_;}},\n duration: {get: function(){return duration;}, set: function(_){duration=_;}},\n showLabels: {get: function(){return showLabels;}, set: function(_){showLabels=_;}},\n\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n if (_.top !== undefined) {\n margin.top = _.top;\n marginTop = _.top;\n }\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n }},\n rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){\n rightAlignYAxis = _;\n yAxis.orient( (_) ? 'right' : 'left');\n }},\n color: {get: function(){return color;}, set: function(_){\n color = nv.utils.getColor(_);\n legend.color(color);\n distX.color(color);\n distY.color(color);\n }}\n });\n\n nv.utils.inheritOptions(chart, scatter);\n nv.utils.initOptions(chart);\n return chart;\n};\n","\nnv.models.sparkline = function() {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var margin = {top: 2, right: 0, bottom: 2, left: 0}\n , width = 400\n , height = 32\n , container = null\n , animate = true\n , x = d3.scale.linear()\n , y = d3.scale.linear()\n , getX = function(d) { return d.x }\n , getY = function(d) { return d.y }\n , color = nv.utils.getColor(['#000'])\n , xDomain\n , yDomain\n , xRange\n , yRange\n , showMinMaxPoints = true\n , showCurrentPoint = true\n , dispatch = d3.dispatch('renderEnd')\n ;\n\n //============================================================\n // Private Variables\n //------------------------------------------------------------\n\n var renderWatch = nv.utils.renderWatch(dispatch);\n \n function chart(selection) {\n renderWatch.reset();\n selection.each(function(data) {\n var availableWidth = width - margin.left - margin.right,\n availableHeight = height - margin.top - margin.bottom;\n\n container = d3.select(this);\n nv.utils.initSVG(container);\n\n // Setup Scales\n x .domain(xDomain || d3.extent(data, getX ))\n .range(xRange || [0, availableWidth]);\n\n y .domain(yDomain || d3.extent(data, getY ))\n .range(yRange || [availableHeight, 0]);\n\n // Setup containers and skeleton of chart\n var wrap = container.selectAll('g.nv-wrap.nv-sparkline').data([data]);\n var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-sparkline');\n var gEnter = wrapEnter.append('g');\n var g = wrap.select('g');\n\n wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')\n\n var paths = wrap.selectAll('path')\n .data(function(d) { return [d] });\n paths.enter().append('path');\n paths.exit().remove();\n paths\n .style('stroke', function(d,i) { return d.color || color(d, i) })\n .attr('d', d3.svg.line()\n .x(function(d,i) { return x(getX(d,i)) })\n .y(function(d,i) { return y(getY(d,i)) })\n );\n\n // TODO: Add CURRENT data point (Need Min, Mac, Current / Most recent)\n var points = wrap.selectAll('circle.nv-point')\n .data(function(data) {\n var yValues = data.map(function(d, i) { return getY(d,i); });\n function pointIndex(index) {\n if (index != -1) {\n var result = data[index];\n result.pointIndex = index;\n return result;\n } else {\n return null;\n }\n }\n var maxPoint = pointIndex(yValues.lastIndexOf(y.domain()[1])),\n minPoint = pointIndex(yValues.indexOf(y.domain()[0])),\n currentPoint = pointIndex(yValues.length - 1);\n return [(showMinMaxPoints ? minPoint : null), (showMinMaxPoints ? maxPoint : null), (showCurrentPoint ? currentPoint : null)].filter(function (d) {return d != null;});\n });\n points.enter().append('circle');\n points.exit().remove();\n points\n .attr('cx', function(d,i) { return x(getX(d,d.pointIndex)) })\n .attr('cy', function(d,i) { return y(getY(d,d.pointIndex)) })\n .attr('r', 2)\n .attr('class', function(d,i) {\n return getX(d, d.pointIndex) == x.domain()[1] ? 'nv-point nv-currentValue' :\n getY(d, d.pointIndex) == y.domain()[0] ? 'nv-point nv-minValue' : 'nv-point nv-maxValue'\n });\n });\n \n renderWatch.renderEnd('sparkline immediate');\n return chart;\n }\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}},\n yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}},\n xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}},\n yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}},\n xScale: {get: function(){return x;}, set: function(_){x=_;}},\n yScale: {get: function(){return y;}, set: function(_){y=_;}},\n animate: {get: function(){return animate;}, set: function(_){animate=_;}},\n showMinMaxPoints: {get: function(){return showMinMaxPoints;}, set: function(_){showMinMaxPoints=_;}},\n showCurrentPoint: {get: function(){return showCurrentPoint;}, set: function(_){showCurrentPoint=_;}},\n\n //functor options\n x: {get: function(){return getX;}, set: function(_){getX=d3.functor(_);}},\n y: {get: function(){return getY;}, set: function(_){getY=d3.functor(_);}},\n\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n margin.top = _.top !== undefined ? _.top : margin.top;\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n }},\n color: {get: function(){return color;}, set: function(_){\n color = nv.utils.getColor(_);\n }}\n });\n\n chart.dispatch = dispatch;\n nv.utils.initOptions(chart);\n return chart;\n};\n","\nnv.models.sparklinePlus = function() {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var sparkline = nv.models.sparkline();\n\n var margin = {top: 15, right: 100, bottom: 10, left: 50}\n , width = null\n , height = null\n , x\n , y\n , index = []\n , paused = false\n , xTickFormat = d3.format(',r')\n , yTickFormat = d3.format(',.2f')\n , showLastValue = true\n , alignValue = true\n , rightAlignValue = false\n , noData = null\n , dispatch = d3.dispatch('renderEnd')\n ;\n \n //============================================================\n // Private Variables\n //------------------------------------------------------------\n\n var renderWatch = nv.utils.renderWatch(dispatch);\n\n function chart(selection) {\n renderWatch.reset();\n renderWatch.models(sparkline);\n selection.each(function(data) {\n var container = d3.select(this);\n nv.utils.initSVG(container);\n\n var availableWidth = nv.utils.availableWidth(width, container, margin),\n availableHeight = nv.utils.availableHeight(height, container, margin);\n\n chart.update = function() { container.call(chart); };\n chart.container = this;\n\n // Display No Data message if there's nothing to show.\n if (!data || !data.length) {\n nv.utils.noData(chart, container)\n return chart;\n } else {\n container.selectAll('.nv-noData').remove();\n }\n\n var currentValue = sparkline.y()(data[data.length-1], data.length-1);\n\n // Setup Scales\n x = sparkline.xScale();\n y = sparkline.yScale();\n\n // Setup containers and skeleton of chart\n var wrap = container.selectAll('g.nv-wrap.nv-sparklineplus').data([data]);\n var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-sparklineplus');\n var gEnter = wrapEnter.append('g');\n var g = wrap.select('g');\n\n gEnter.append('g').attr('class', 'nv-sparklineWrap');\n gEnter.append('g').attr('class', 'nv-valueWrap');\n gEnter.append('g').attr('class', 'nv-hoverArea');\n\n wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');\n\n // Main Chart Component(s)\n var sparklineWrap = g.select('.nv-sparklineWrap');\n\n sparkline.width(availableWidth).height(availableHeight);\n sparklineWrap.call(sparkline);\n\n if (showLastValue) {\n var valueWrap = g.select('.nv-valueWrap');\n var value = valueWrap.selectAll('.nv-currentValue')\n .data([currentValue]);\n\n value.enter().append('text').attr('class', 'nv-currentValue')\n .attr('dx', rightAlignValue ? -8 : 8)\n .attr('dy', '.9em')\n .style('text-anchor', rightAlignValue ? 'end' : 'start');\n\n value\n .attr('x', availableWidth + (rightAlignValue ? margin.right : 0))\n .attr('y', alignValue ? function (d) {\n return y(d)\n } : 0)\n .style('fill', sparkline.color()(data[data.length - 1], data.length - 1))\n .text(yTickFormat(currentValue));\n }\n\n gEnter.select('.nv-hoverArea').append('rect')\n .on('mousemove', sparklineHover)\n .on('click', function() { paused = !paused })\n .on('mouseout', function() { index = []; updateValueLine(); });\n\n g.select('.nv-hoverArea rect')\n .attr('transform', function(d) { return 'translate(' + -margin.left + ',' + -margin.top + ')' })\n .attr('width', availableWidth + margin.left + margin.right)\n .attr('height', availableHeight + margin.top);\n\n //index is currently global (within the chart), may or may not keep it that way\n function updateValueLine() {\n if (paused) return;\n\n var hoverValue = g.selectAll('.nv-hoverValue').data(index);\n\n var hoverEnter = hoverValue.enter()\n .append('g').attr('class', 'nv-hoverValue')\n .style('stroke-opacity', 0)\n .style('fill-opacity', 0);\n\n hoverValue.exit()\n .transition().duration(250)\n .style('stroke-opacity', 0)\n .style('fill-opacity', 0)\n .remove();\n\n hoverValue\n .attr('transform', function(d) { return 'translate(' + x(sparkline.x()(data[d],d)) + ',0)' })\n .transition().duration(250)\n .style('stroke-opacity', 1)\n .style('fill-opacity', 1);\n\n if (!index.length) return;\n\n hoverEnter.append('line')\n .attr('x1', 0)\n .attr('y1', -margin.top)\n .attr('x2', 0)\n .attr('y2', availableHeight);\n\n hoverEnter.append('text').attr('class', 'nv-xValue')\n .attr('x', -6)\n .attr('y', -margin.top)\n .attr('text-anchor', 'end')\n .attr('dy', '.9em');\n\n g.select('.nv-hoverValue .nv-xValue')\n .text(xTickFormat(sparkline.x()(data[index[0]], index[0])));\n\n hoverEnter.append('text').attr('class', 'nv-yValue')\n .attr('x', 6)\n .attr('y', -margin.top)\n .attr('text-anchor', 'start')\n .attr('dy', '.9em');\n\n g.select('.nv-hoverValue .nv-yValue')\n .text(yTickFormat(sparkline.y()(data[index[0]], index[0])));\n }\n\n function sparklineHover() {\n if (paused) return;\n\n var pos = d3.mouse(this)[0] - margin.left;\n\n function getClosestIndex(data, x) {\n var distance = Math.abs(sparkline.x()(data[0], 0) - x);\n var closestIndex = 0;\n for (var i = 0; i < data.length; i++){\n if (Math.abs(sparkline.x()(data[i], i) - x) < distance) {\n distance = Math.abs(sparkline.x()(data[i], i) - x);\n closestIndex = i;\n }\n }\n return closestIndex;\n }\n\n index = [getClosestIndex(data, Math.round(x.invert(pos)))];\n updateValueLine();\n }\n\n });\n renderWatch.renderEnd('sparklinePlus immediate');\n return chart;\n }\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n // expose chart's sub-components\n chart.dispatch = dispatch;\n chart.sparkline = sparkline;\n\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n xTickFormat: {get: function(){return xTickFormat;}, set: function(_){xTickFormat=_;}},\n yTickFormat: {get: function(){return yTickFormat;}, set: function(_){yTickFormat=_;}},\n showLastValue: {get: function(){return showLastValue;}, set: function(_){showLastValue=_;}},\n alignValue: {get: function(){return alignValue;}, set: function(_){alignValue=_;}},\n rightAlignValue: {get: function(){return rightAlignValue;}, set: function(_){rightAlignValue=_;}},\n noData: {get: function(){return noData;}, set: function(_){noData=_;}},\n\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n margin.top = _.top !== undefined ? _.top : margin.top;\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n }}\n });\n\n nv.utils.inheritOptions(chart, sparkline);\n nv.utils.initOptions(chart);\n\n return chart;\n};\n","\nnv.models.stackedArea = function() {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var margin = {top: 0, right: 0, bottom: 0, left: 0}\n , width = 960\n , height = 500\n , color = nv.utils.defaultColor() // a function that computes the color\n , id = Math.floor(Math.random() * 100000) //Create semi-unique ID incase user doesn't selet one\n , container = null\n , getX = function(d) { return d.x } // accessor to get the x value from a data point\n , getY = function(d) { return d.y } // accessor to get the y value from a data point\n , defined = function(d,i) { return !isNaN(getY(d,i)) && getY(d,i) !== null } // allows a line to be not continuous when it is not defined\n , style = 'stack'\n , offset = 'zero'\n , order = 'default'\n , interpolate = 'linear' // controls the line interpolation\n , clipEdge = false // if true, masks lines within x and y scale\n , x //can be accessed via chart.xScale()\n , y //can be accessed via chart.yScale()\n , scatter = nv.models.scatter()\n , duration = 250\n , dispatch = d3.dispatch('areaClick', 'areaMouseover', 'areaMouseout','renderEnd', 'elementClick', 'elementMouseover', 'elementMouseout')\n ;\n\n scatter\n .pointSize(2.2) // default size\n .pointDomain([2.2, 2.2]) // all the same size by default\n ;\n\n /************************************\n * offset:\n * 'wiggle' (stream)\n * 'zero' (stacked)\n * 'expand' (normalize to 100%)\n * 'silhouette' (simple centered)\n *\n * order:\n * 'inside-out' (stream)\n * 'default' (input order)\n ************************************/\n\n var renderWatch = nv.utils.renderWatch(dispatch, duration);\n\n function chart(selection) {\n renderWatch.reset();\n renderWatch.models(scatter);\n selection.each(function(data) {\n var availableWidth = width - margin.left - margin.right,\n availableHeight = height - margin.top - margin.bottom;\n\n container = d3.select(this);\n nv.utils.initSVG(container);\n\n // Setup Scales\n x = scatter.xScale();\n y = scatter.yScale();\n\n var dataRaw = data;\n // Injecting point index into each point because d3.layout.stack().out does not give index\n data.forEach(function(aseries, i) {\n aseries.seriesIndex = i;\n aseries.values = aseries.values.map(function(d, j) {\n d.index = j;\n d.seriesIndex = i;\n return d;\n });\n });\n\n var dataFiltered = data.filter(function(series) {\n return !series.disabled;\n });\n\n data = d3.layout.stack()\n .order(order)\n .offset(offset)\n .values(function(d) { return d.values }) //TODO: make values customizeable in EVERY model in this fashion\n .x(getX)\n .y(getY)\n .out(function(d, y0, y) {\n d.display = {\n y: y,\n y0: y0\n };\n })\n (dataFiltered);\n\n // Setup containers and skeleton of chart\n var wrap = container.selectAll('g.nv-wrap.nv-stackedarea').data([data]);\n var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-stackedarea');\n var defsEnter = wrapEnter.append('defs');\n var gEnter = wrapEnter.append('g');\n var g = wrap.select('g');\n\n gEnter.append('g').attr('class', 'nv-areaWrap');\n gEnter.append('g').attr('class', 'nv-scatterWrap');\n\n wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');\n \n // If the user has not specified forceY, make sure 0 is included in the domain\n // Otherwise, use user-specified values for forceY\n if (scatter.forceY().length == 0) {\n scatter.forceY().push(0);\n }\n \n scatter\n .width(availableWidth)\n .height(availableHeight)\n .x(getX)\n .y(function(d) {\n if (d.display !== undefined) { return d.display.y + d.display.y0; }\n })\n .color(data.map(function(d,i) {\n d.color = d.color || color(d, d.seriesIndex);\n return d.color;\n }));\n\n var scatterWrap = g.select('.nv-scatterWrap')\n .datum(data);\n\n scatterWrap.call(scatter);\n\n defsEnter.append('clipPath')\n .attr('id', 'nv-edge-clip-' + id)\n .append('rect');\n\n wrap.select('#nv-edge-clip-' + id + ' rect')\n .attr('width', availableWidth)\n .attr('height', availableHeight);\n\n g.attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : '');\n\n var area = d3.svg.area()\n .defined(defined)\n .x(function(d,i) { return x(getX(d,i)) })\n .y0(function(d) {\n return y(d.display.y0)\n })\n .y1(function(d) {\n return y(d.display.y + d.display.y0)\n })\n .interpolate(interpolate);\n\n var zeroArea = d3.svg.area()\n .defined(defined)\n .x(function(d,i) { return x(getX(d,i)) })\n .y0(function(d) { return y(d.display.y0) })\n .y1(function(d) { return y(d.display.y0) });\n\n var path = g.select('.nv-areaWrap').selectAll('path.nv-area')\n .data(function(d) { return d });\n\n path.enter().append('path').attr('class', function(d,i) { return 'nv-area nv-area-' + i })\n .attr('d', function(d,i){\n return zeroArea(d.values, d.seriesIndex);\n })\n .on('mouseover', function(d,i) {\n d3.select(this).classed('hover', true);\n dispatch.areaMouseover({\n point: d,\n series: d.key,\n pos: [d3.event.pageX, d3.event.pageY],\n seriesIndex: d.seriesIndex\n });\n })\n .on('mouseout', function(d,i) {\n d3.select(this).classed('hover', false);\n dispatch.areaMouseout({\n point: d,\n series: d.key,\n pos: [d3.event.pageX, d3.event.pageY],\n seriesIndex: d.seriesIndex\n });\n })\n .on('click', function(d,i) {\n d3.select(this).classed('hover', false);\n dispatch.areaClick({\n point: d,\n series: d.key,\n pos: [d3.event.pageX, d3.event.pageY],\n seriesIndex: d.seriesIndex\n });\n });\n\n path.exit().remove();\n path.style('fill', function(d,i){\n return d.color || color(d, d.seriesIndex)\n })\n .style('stroke', function(d,i){ return d.color || color(d, d.seriesIndex) });\n path.watchTransition(renderWatch,'stackedArea path')\n .attr('d', function(d,i) {\n return area(d.values,i)\n });\n\n //============================================================\n // Event Handling/Dispatching (in chart's scope)\n //------------------------------------------------------------\n\n scatter.dispatch.on('elementMouseover.area', function(e) {\n g.select('.nv-chart-' + id + ' .nv-area-' + e.seriesIndex).classed('hover', true);\n });\n scatter.dispatch.on('elementMouseout.area', function(e) {\n g.select('.nv-chart-' + id + ' .nv-area-' + e.seriesIndex).classed('hover', false);\n });\n\n //Special offset functions\n chart.d3_stackedOffset_stackPercent = function(stackData) {\n var n = stackData.length, //How many series\n m = stackData[0].length, //how many points per series\n i,\n j,\n o,\n y0 = [];\n\n for (j = 0; j < m; ++j) { //Looping through all points\n for (i = 0, o = 0; i < dataRaw.length; i++) { //looping through all series\n o += getY(dataRaw[i].values[j]); //total y value of all series at a certian point in time.\n }\n\n if (o) for (i = 0; i < n; i++) { //(total y value of all series at point in time i) != 0\n stackData[i][j][1] /= o;\n } else { //(total y value of all series at point in time i) == 0\n for (i = 0; i < n; i++) {\n stackData[i][j][1] = 0;\n }\n }\n }\n for (j = 0; j < m; ++j) y0[j] = 0;\n return y0;\n };\n\n });\n\n renderWatch.renderEnd('stackedArea immediate');\n return chart;\n }\n\n //============================================================\n // Global getters and setters\n //------------------------------------------------------------\n\n chart.dispatch = dispatch;\n chart.scatter = scatter;\n\n scatter.dispatch.on('elementClick', function(){ dispatch.elementClick.apply(this, arguments); });\n scatter.dispatch.on('elementMouseover', function(){ dispatch.elementMouseover.apply(this, arguments); });\n scatter.dispatch.on('elementMouseout', function(){ dispatch.elementMouseout.apply(this, arguments); });\n\n chart.interpolate = function(_) {\n if (!arguments.length) return interpolate;\n interpolate = _;\n return chart;\n };\n\n chart.duration = function(_) {\n if (!arguments.length) return duration;\n duration = _;\n renderWatch.reset(duration);\n scatter.duration(duration);\n return chart;\n };\n\n chart.dispatch = dispatch;\n chart.scatter = scatter;\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n defined: {get: function(){return defined;}, set: function(_){defined=_;}},\n clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}},\n offset: {get: function(){return offset;}, set: function(_){offset=_;}},\n order: {get: function(){return order;}, set: function(_){order=_;}},\n interpolate: {get: function(){return interpolate;}, set: function(_){interpolate=_;}},\n\n // simple functor options\n x: {get: function(){return getX;}, set: function(_){getX = d3.functor(_);}},\n y: {get: function(){return getY;}, set: function(_){getY = d3.functor(_);}},\n\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n margin.top = _.top !== undefined ? _.top : margin.top;\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n }},\n color: {get: function(){return color;}, set: function(_){\n color = nv.utils.getColor(_);\n }},\n style: {get: function(){return style;}, set: function(_){\n style = _;\n switch (style) {\n case 'stack':\n chart.offset('zero');\n chart.order('default');\n break;\n case 'stream':\n chart.offset('wiggle');\n chart.order('inside-out');\n break;\n case 'stream-center':\n chart.offset('silhouette');\n chart.order('inside-out');\n break;\n case 'expand':\n chart.offset('expand');\n chart.order('default');\n break;\n case 'stack_percent':\n chart.offset(chart.d3_stackedOffset_stackPercent);\n chart.order('default');\n break;\n }\n }},\n duration: {get: function(){return duration;}, set: function(_){\n duration = _;\n renderWatch.reset(duration);\n scatter.duration(duration);\n }}\n });\n\n nv.utils.inheritOptions(chart, scatter);\n nv.utils.initOptions(chart);\n\n return chart;\n};\n","\nnv.models.stackedAreaChart = function() {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var stacked = nv.models.stackedArea()\n , xAxis = nv.models.axis()\n , yAxis = nv.models.axis()\n , legend = nv.models.legend()\n , controls = nv.models.legend()\n , interactiveLayer = nv.interactiveGuideline()\n , tooltip = nv.models.tooltip()\n , focus = nv.models.focus(nv.models.stackedArea())\n ;\n\n var margin = {top: 10, right: 25, bottom: 50, left: 60}\n , marginTop = null\n , width = null\n , height = null\n , color = nv.utils.defaultColor()\n , showControls = true\n , showLegend = true\n , legendPosition = 'top'\n , showXAxis = true\n , showYAxis = true\n , rightAlignYAxis = false\n , focusEnable = false\n , useInteractiveGuideline = false\n , showTotalInTooltip = true\n , totalLabel = 'TOTAL'\n , x //can be accessed via chart.xScale()\n , y //can be accessed via chart.yScale()\n , state = nv.utils.state()\n , defaultState = null\n , noData = null\n , dispatch = d3.dispatch('stateChange', 'changeState','renderEnd')\n , controlWidth = 250\n , controlOptions = ['Stacked','Stream','Expanded']\n , controlLabels = {}\n , duration = 250\n ;\n\n state.style = stacked.style();\n xAxis.orient('bottom').tickPadding(7);\n yAxis.orient((rightAlignYAxis) ? 'right' : 'left');\n\n tooltip\n .headerFormatter(function(d, i) {\n return xAxis.tickFormat()(d, i);\n })\n .valueFormatter(function(d, i) {\n return yAxis.tickFormat()(d, i);\n });\n\n interactiveLayer.tooltip\n .headerFormatter(function(d, i) {\n return xAxis.tickFormat()(d, i);\n })\n .valueFormatter(function(d, i) {\n return d == null ? \"N/A\" : yAxis.tickFormat()(d, i);\n });\n\n var oldYTickFormat = null,\n oldValueFormatter = null;\n\n controls.updateState(false);\n\n //============================================================\n // Private Variables\n //------------------------------------------------------------\n\n var renderWatch = nv.utils.renderWatch(dispatch);\n var style = stacked.style();\n\n var stateGetter = function(data) {\n return function(){\n return {\n active: data.map(function(d) { return !d.disabled }),\n style: stacked.style()\n };\n }\n };\n\n var stateSetter = function(data) {\n return function(state) {\n if (state.style !== undefined)\n style = state.style;\n if (state.active !== undefined)\n data.forEach(function(series,i) {\n series.disabled = !state.active[i];\n });\n }\n };\n\n var percentFormatter = d3.format('%');\n\n function chart(selection) {\n renderWatch.reset();\n renderWatch.models(stacked);\n if (showXAxis) renderWatch.models(xAxis);\n if (showYAxis) renderWatch.models(yAxis);\n\n selection.each(function(data) {\n var container = d3.select(this),\n that = this;\n nv.utils.initSVG(container);\n\n var availableWidth = nv.utils.availableWidth(width, container, margin),\n availableHeight = nv.utils.availableHeight(height, container, margin) - (focusEnable ? focus.height() : 0);\n\n chart.update = function() { container.transition().duration(duration).call(chart); };\n chart.container = this;\n\n state\n .setter(stateSetter(data), chart.update)\n .getter(stateGetter(data))\n .update();\n\n // DEPRECATED set state.disabled\n state.disabled = data.map(function(d) { return !!d.disabled });\n\n if (!defaultState) {\n var key;\n defaultState = {};\n for (key in state) {\n if (state[key] instanceof Array)\n defaultState[key] = state[key].slice(0);\n else\n defaultState[key] = state[key];\n }\n }\n\n // Display No Data message if there's nothing to show.\n if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {\n nv.utils.noData(chart, container)\n return chart;\n } else {\n container.selectAll('.nv-noData').remove();\n }\n // Setup Scales\n x = stacked.xScale();\n y = stacked.yScale();\n\n // Setup containers and skeleton of chart\n var wrap = container.selectAll('g.nv-wrap.nv-stackedAreaChart').data([data]);\n var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-stackedAreaChart').append('g');\n var g = wrap.select('g');\n\n gEnter.append('g').attr('class', 'nv-legendWrap');\n gEnter.append('g').attr('class', 'nv-controlsWrap');\n\n var focusEnter = gEnter.append('g').attr('class', 'nv-focus');\n focusEnter.append('g').attr('class', 'nv-background').append('rect');\n focusEnter.append('g').attr('class', 'nv-x nv-axis');\n focusEnter.append('g').attr('class', 'nv-y nv-axis');\n focusEnter.append('g').attr('class', 'nv-stackedWrap');\n focusEnter.append('g').attr('class', 'nv-interactive');\n\n // g.select(\"rect\").attr(\"width\",availableWidth).attr(\"height\",availableHeight);\n\n var contextEnter = gEnter.append('g').attr('class', 'nv-focusWrap');\n\n // Legend\n if (!showLegend) {\n g.select('.nv-legendWrap').selectAll('*').remove();\n } else {\n var legendWidth = (showControls && legendPosition === 'top') ? availableWidth - controlWidth : availableWidth;\n\n legend.width(legendWidth);\n g.select('.nv-legendWrap').datum(data).call(legend);\n\n if (legendPosition === 'bottom') {\n \t// constant from axis.js, plus some margin for better layout\n \tvar xAxisHeight = (showXAxis ? 12 : 0) + 10;\n \tmargin.bottom = Math.max(legend.height() + xAxisHeight, margin.bottom);\n \tavailableHeight = nv.utils.availableHeight(height, container, margin) - (focusEnable ? focus.height() : 0);\n \tvar legendTop = availableHeight + xAxisHeight;\n g.select('.nv-legendWrap')\n .attr('transform', 'translate(0,' + legendTop +')');\n } else if (legendPosition === 'top') {\n if (!marginTop && margin.top != legend.height()) {\n margin.top = legend.height();\n availableHeight = nv.utils.availableHeight(height, container, margin) - (focusEnable ? focus.height() : 0);\n }\n\n g.select('.nv-legendWrap')\n \t.attr('transform', 'translate(' + (availableWidth-legendWidth) + ',' + (-margin.top) +')');\n }\n }\n\n // Controls\n if (!showControls) {\n g.select('.nv-controlsWrap').selectAll('*').remove();\n } else {\n var controlsData = [\n {\n key: controlLabels.stacked || 'Stacked',\n metaKey: 'Stacked',\n disabled: stacked.style() != 'stack',\n style: 'stack'\n },\n {\n key: controlLabels.stream || 'Stream',\n metaKey: 'Stream',\n disabled: stacked.style() != 'stream',\n style: 'stream'\n },\n {\n key: controlLabels.expanded || 'Expanded',\n metaKey: 'Expanded',\n disabled: stacked.style() != 'expand',\n style: 'expand'\n },\n {\n key: controlLabels.stack_percent || 'Stack %',\n metaKey: 'Stack_Percent',\n disabled: stacked.style() != 'stack_percent',\n style: 'stack_percent'\n }\n ];\n\n controlWidth = (controlOptions.length/3) * 260;\n controlsData = controlsData.filter(function(d) {\n return controlOptions.indexOf(d.metaKey) !== -1;\n });\n\n controls\n .width( controlWidth )\n .color(['#444', '#444', '#444']);\n\n g.select('.nv-controlsWrap')\n .datum(controlsData)\n .call(controls);\n\n var requiredTop = Math.max(controls.height(), showLegend && (legendPosition === 'top') ? legend.height() : 0);\n\n if ( margin.top != requiredTop ) {\n margin.top = requiredTop;\n availableHeight = nv.utils.availableHeight(height, container, margin) - (focusEnable ? focus.height() : 0);\n }\n\n g.select('.nv-controlsWrap')\n .attr('transform', 'translate(0,' + (-margin.top) +')');\n }\n\n wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');\n\n if (rightAlignYAxis) {\n g.select(\".nv-y.nv-axis\")\n .attr(\"transform\", \"translate(\" + availableWidth + \",0)\");\n }\n\n //Set up interactive layer\n if (useInteractiveGuideline) {\n interactiveLayer\n .width(availableWidth)\n .height(availableHeight)\n .margin({left: margin.left, top: margin.top})\n .svgContainer(container)\n .xScale(x);\n wrap.select(\".nv-interactive\").call(interactiveLayer);\n }\n\n g.select('.nv-focus .nv-background rect')\n .attr('width', availableWidth)\n .attr('height', availableHeight);\n\n stacked\n .width(availableWidth)\n .height(availableHeight)\n .color(data.map(function(d,i) {\n return d.color || color(d, i);\n }).filter(function(d,i) { return !data[i].disabled; }));\n\n var stackedWrap = g.select('.nv-focus .nv-stackedWrap')\n .datum(data.filter(function(d) { return !d.disabled; }));\n\n // Setup Axes\n if (showXAxis) {\n xAxis.scale(x)\n ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )\n .tickSize( -availableHeight, 0);\n }\n\n if (showYAxis) {\n var ticks;\n if (stacked.offset() === 'wiggle') {\n ticks = 0;\n }\n else {\n ticks = nv.utils.calcTicksY(availableHeight/36, data);\n }\n yAxis.scale(y)\n ._ticks(ticks)\n .tickSize(-availableWidth, 0);\n }\n\n //============================================================\n // Update Axes\n //============================================================\n function updateXAxis() {\n if(showXAxis) {\n g.select('.nv-focus .nv-x.nv-axis')\n .attr('transform', 'translate(0,' + availableHeight + ')')\n .transition()\n .duration(duration)\n .call(xAxis)\n ;\n }\n }\n\n function updateYAxis() {\n if(showYAxis) {\n if (stacked.style() === 'expand' || stacked.style() === 'stack_percent') {\n var currentFormat = yAxis.tickFormat();\n\n if ( !oldYTickFormat || currentFormat !== percentFormatter )\n oldYTickFormat = currentFormat;\n\n //Forces the yAxis to use percentage in 'expand' mode.\n yAxis.tickFormat(percentFormatter);\n }\n else {\n if (oldYTickFormat) {\n yAxis.tickFormat(oldYTickFormat);\n oldYTickFormat = null;\n }\n }\n\n g.select('.nv-focus .nv-y.nv-axis')\n .transition().duration(0)\n .call(yAxis);\n }\n }\n\n //============================================================\n // Update Focus\n //============================================================\n if(!focusEnable) {\n stackedWrap.transition().call(stacked);\n updateXAxis();\n updateYAxis();\n } else {\n focus.width(availableWidth);\n g.select('.nv-focusWrap')\n .attr('transform', 'translate(0,' + ( availableHeight + margin.bottom + focus.margin().top) + ')')\n .datum(data.filter(function(d) { return !d.disabled; }))\n .call(focus);\n var extent = focus.brush.empty() ? focus.xDomain() : focus.brush.extent();\n if(extent !== null){\n onBrush(extent);\n }\n }\n\n //============================================================\n // Event Handling/Dispatching (in chart's scope)\n //------------------------------------------------------------\n\n stacked.dispatch.on('areaClick.toggle', function(e) {\n if (data.filter(function(d) { return !d.disabled }).length === 1)\n data.forEach(function(d) {\n d.disabled = false;\n });\n else\n data.forEach(function(d,i) {\n d.disabled = (i != e.seriesIndex);\n });\n\n state.disabled = data.map(function(d) { return !!d.disabled });\n dispatch.stateChange(state);\n\n chart.update();\n });\n\n legend.dispatch.on('stateChange', function(newState) {\n for (var key in newState)\n state[key] = newState[key];\n dispatch.stateChange(state);\n chart.update();\n });\n\n controls.dispatch.on('legendClick', function(d,i) {\n if (!d.disabled) return;\n\n controlsData = controlsData.map(function(s) {\n s.disabled = true;\n return s;\n });\n d.disabled = false;\n\n stacked.style(d.style);\n\n\n state.style = stacked.style();\n dispatch.stateChange(state);\n\n chart.update();\n });\n\n interactiveLayer.dispatch.on('elementMousemove', function(e) {\n stacked.clearHighlights();\n var singlePoint, pointIndex, pointXLocation, allData = [], valueSum = 0, allNullValues = true;\n data\n .filter(function(series, i) {\n series.seriesIndex = i;\n return !series.disabled;\n })\n .forEach(function(series,i) {\n pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x());\n var point = series.values[pointIndex];\n var pointYValue = chart.y()(point, pointIndex);\n if (pointYValue != null) {\n stacked.highlightPoint(i, pointIndex, true);\n }\n if (typeof point === 'undefined') return;\n if (typeof singlePoint === 'undefined') singlePoint = point;\n if (typeof pointXLocation === 'undefined') pointXLocation = chart.xScale()(chart.x()(point,pointIndex));\n\n //If we are in 'expand' mode, use the stacked percent value instead of raw value.\n var tooltipValue = (stacked.style() == 'expand') ? point.display.y : chart.y()(point,pointIndex);\n allData.push({\n key: series.key,\n value: tooltipValue,\n color: color(series,series.seriesIndex),\n point: point\n });\n\n if (showTotalInTooltip && stacked.style() != 'expand' && tooltipValue != null) {\n valueSum += tooltipValue;\n allNullValues = false;\n };\n });\n\n allData.reverse();\n\n //Highlight the tooltip entry based on which stack the mouse is closest to.\n if (allData.length > 2) {\n var yValue = chart.yScale().invert(e.mouseY);\n var yDistMax = Infinity, indexToHighlight = null;\n allData.forEach(function(series,i) {\n\n //To handle situation where the stacked area chart is negative, we need to use absolute values\n //when checking if the mouse Y value is within the stack area.\n yValue = Math.abs(yValue);\n var stackedY0 = Math.abs(series.point.display.y0);\n var stackedY = Math.abs(series.point.display.y);\n if ( yValue >= stackedY0 && yValue <= (stackedY + stackedY0))\n {\n indexToHighlight = i;\n return;\n }\n });\n if (indexToHighlight != null)\n allData[indexToHighlight].highlight = true;\n }\n\n //If we are not in 'expand' mode, add a 'Total' row to the tooltip.\n if (showTotalInTooltip && stacked.style() != 'expand' && allData.length >= 2 && !allNullValues) {\n allData.push({\n key: totalLabel,\n value: valueSum,\n total: true\n });\n }\n\n var xValue = chart.x()(singlePoint,pointIndex);\n\n var valueFormatter = interactiveLayer.tooltip.valueFormatter();\n // Keeps track of the tooltip valueFormatter if the chart changes to expanded view\n if (stacked.style() === 'expand' || stacked.style() === 'stack_percent') {\n if ( !oldValueFormatter ) {\n oldValueFormatter = valueFormatter;\n }\n //Forces the tooltip to use percentage in 'expand' mode.\n valueFormatter = d3.format(\".1%\");\n }\n else {\n if (oldValueFormatter) {\n valueFormatter = oldValueFormatter;\n oldValueFormatter = null;\n }\n }\n\n interactiveLayer.tooltip\n .valueFormatter(valueFormatter)\n .data(\n {\n value: xValue,\n series: allData\n }\n )();\n\n interactiveLayer.renderGuideLine(pointXLocation);\n\n });\n\n interactiveLayer.dispatch.on(\"elementMouseout\",function(e) {\n stacked.clearHighlights();\n });\n\n /* Update `main' graph on brush update. */\n focus.dispatch.on(\"onBrush\", function(extent) {\n onBrush(extent);\n });\n\n // Update chart from a state object passed to event handler\n dispatch.on('changeState', function(e) {\n\n if (typeof e.disabled !== 'undefined' && data.length === e.disabled.length) {\n data.forEach(function(series,i) {\n series.disabled = e.disabled[i];\n });\n\n state.disabled = e.disabled;\n }\n\n if (typeof e.style !== 'undefined') {\n stacked.style(e.style);\n style = e.style;\n }\n\n chart.update();\n });\n\n //============================================================\n // Functions\n //------------------------------------------------------------\n\n function onBrush(extent) {\n // Update Main (Focus)\n var stackedWrap = g.select('.nv-focus .nv-stackedWrap')\n .datum(\n data.filter(function(d) { return !d.disabled; })\n .map(function(d,i) {\n return {\n key: d.key,\n area: d.area,\n classed: d.classed,\n values: d.values.filter(function(d,i) {\n return stacked.x()(d,i) >= extent[0] && stacked.x()(d,i) <= extent[1];\n }),\n disableTooltip: d.disableTooltip\n };\n })\n );\n stackedWrap.transition().duration(duration).call(stacked);\n\n // Update Main (Focus) Axes\n updateXAxis();\n updateYAxis();\n }\n\n });\n\n renderWatch.renderEnd('stacked Area chart immediate');\n return chart;\n }\n\n //============================================================\n // Event Handling/Dispatching (out of chart's scope)\n //------------------------------------------------------------\n\n stacked.dispatch.on('elementMouseover.tooltip', function(evt) {\n evt.point['x'] = stacked.x()(evt.point);\n evt.point['y'] = stacked.y()(evt.point);\n tooltip.data(evt).hidden(false);\n });\n\n stacked.dispatch.on('elementMouseout.tooltip', function(evt) {\n tooltip.hidden(true)\n });\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n // expose chart's sub-components\n chart.dispatch = dispatch;\n chart.stacked = stacked;\n chart.legend = legend;\n chart.controls = controls;\n chart.xAxis = xAxis;\n chart.x2Axis = focus.xAxis;\n chart.yAxis = yAxis;\n chart.y2Axis = focus.yAxis;\n chart.interactiveLayer = interactiveLayer;\n chart.tooltip = tooltip;\n chart.focus = focus;\n\n chart.dispatch = dispatch;\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},\n legendPosition: {get: function(){return legendPosition;}, set: function(_){legendPosition=_;}},\n showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},\n showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},\n defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}},\n noData: {get: function(){return noData;}, set: function(_){noData=_;}},\n showControls: {get: function(){return showControls;}, set: function(_){showControls=_;}},\n controlLabels: {get: function(){return controlLabels;}, set: function(_){controlLabels=_;}},\n controlOptions: {get: function(){return controlOptions;}, set: function(_){controlOptions=_;}},\n showTotalInTooltip: {get: function(){return showTotalInTooltip;}, set: function(_){showTotalInTooltip=_;}},\n totalLabel: {get: function(){return totalLabel;}, set: function(_){totalLabel=_;}},\n focusEnable: {get: function(){return focusEnable;}, set: function(_){focusEnable=_;}},\n focusHeight: {get: function(){return focus.height();}, set: function(_){focus.height(_);}},\n brushExtent: {get: function(){return focus.brushExtent();}, set: function(_){focus.brushExtent(_);}},\n\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n if (_.top !== undefined) {\n margin.top = _.top;\n marginTop = _.top;\n }\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n }},\n focusMargin: {get: function(){return focus.margin}, set: function(_){\n focus.margin.top = _.top !== undefined ? _.top : focus.margin.top;\n focus.margin.right = _.right !== undefined ? _.right : focus.margin.right;\n focus.margin.bottom = _.bottom !== undefined ? _.bottom : focus.margin.bottom;\n focus.margin.left = _.left !== undefined ? _.left : focus.margin.left;\n }},\n duration: {get: function(){return duration;}, set: function(_){\n duration = _;\n renderWatch.reset(duration);\n stacked.duration(duration);\n xAxis.duration(duration);\n yAxis.duration(duration);\n }},\n color: {get: function(){return color;}, set: function(_){\n color = nv.utils.getColor(_);\n legend.color(color);\n stacked.color(color);\n focus.color(color);\n }},\n x: {get: function(){return stacked.x();}, set: function(_){\n stacked.x(_);\n focus.x(_);\n }},\n y: {get: function(){return stacked.y();}, set: function(_){\n stacked.y(_);\n focus.y(_);\n }},\n rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){\n rightAlignYAxis = _;\n yAxis.orient( rightAlignYAxis ? 'right' : 'left');\n }},\n useInteractiveGuideline: {get: function(){return useInteractiveGuideline;}, set: function(_){\n useInteractiveGuideline = !!_;\n chart.interactive(!_);\n chart.useVoronoi(!_);\n stacked.scatter.interactive(!_);\n }}\n });\n\n nv.utils.inheritOptions(chart, stacked);\n nv.utils.initOptions(chart);\n\n return chart;\n};\n\nnv.models.stackedAreaWithFocusChart = function() {\n return nv.models.stackedAreaChart()\n .margin({ bottom: 30 })\n .focusEnable( true );\n};\n","// based on http://bl.ocks.org/kerryrodden/477c1bfb081b783f80ad\nnv.models.sunburst = function() {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var margin = {top: 0, right: 0, bottom: 0, left: 0}\n , width = 600\n , height = 600\n , mode = \"count\"\n , modes = {count: function(d) { return 1; }, value: function(d) { return d.value || d.size }, size: function(d) { return d.value || d.size }}\n , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one\n , container = null\n , color = nv.utils.defaultColor()\n , showLabels = false\n , labelFormat = function(d){if(mode === 'count'){return d.name + ' #' + d.value}else{return d.name + ' ' + (d.value || d.size)}}\n , labelThreshold = 0.02\n , sort = function(d1, d2){return d1.name > d2.name;}\n , key = function(d,i){return d.name;}\n , groupColorByParent = true\n , duration = 500\n , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMousemove', 'elementMouseover', 'elementMouseout', 'renderEnd');\n\n //============================================================\n // aux functions and setup\n //------------------------------------------------------------\n\n var x = d3.scale.linear().range([0, 2 * Math.PI]);\n var y = d3.scale.sqrt();\n\n var partition = d3.layout.partition().sort(sort);\n\n var node, availableWidth, availableHeight, radius;\n var prevPositions = {};\n\n var arc = d3.svg.arc()\n .startAngle(function(d) {return Math.max(0, Math.min(2 * Math.PI, x(d.x))) })\n .endAngle(function(d) {return Math.max(0, Math.min(2 * Math.PI, x(d.x + d.dx))) })\n .innerRadius(function(d) {return Math.max(0, y(d.y)) })\n .outerRadius(function(d) {return Math.max(0, y(d.y + d.dy)) });\n\n function rotationToAvoidUpsideDown(d) {\n var centerAngle = computeCenterAngle(d);\n if(centerAngle > 90){\n return 180;\n }\n else {\n return 0;\n }\n }\n\n function computeCenterAngle(d) {\n var startAngle = Math.max(0, Math.min(2 * Math.PI, x(d.x)));\n var endAngle = Math.max(0, Math.min(2 * Math.PI, x(d.x + d.dx)));\n var centerAngle = (((startAngle + endAngle) / 2) * (180 / Math.PI)) - 90;\n return centerAngle;\n }\n\n function computeNodePercentage(d) {\n var startAngle = Math.max(0, Math.min(2 * Math.PI, x(d.x)));\n var endAngle = Math.max(0, Math.min(2 * Math.PI, x(d.x + d.dx)));\n return (endAngle - startAngle) / (2 * Math.PI);\n }\n\n function labelThresholdMatched(d) {\n var startAngle = Math.max(0, Math.min(2 * Math.PI, x(d.x)));\n var endAngle = Math.max(0, Math.min(2 * Math.PI, x(d.x + d.dx)));\n\n var size = endAngle - startAngle;\n return size > labelThreshold;\n }\n\n // When zooming: interpolate the scales.\n function arcTweenZoom(e,i) {\n var xd = d3.interpolate(x.domain(), [node.x, node.x + node.dx]),\n yd = d3.interpolate(y.domain(), [node.y, 1]),\n yr = d3.interpolate(y.range(), [node.y ? 20 : 0, radius]);\n\n if (i === 0) {\n return function() {return arc(e);}\n }\n else {\n return function (t) {\n x.domain(xd(t));\n y.domain(yd(t)).range(yr(t));\n return arc(e);\n }\n };\n }\n\n function arcTweenUpdate(d) {\n var ipo = d3.interpolate({x: d.x0, dx: d.dx0, y: d.y0, dy: d.dy0}, d);\n\n return function (t) {\n var b = ipo(t);\n\n d.x0 = b.x;\n d.dx0 = b.dx;\n d.y0 = b.y;\n d.dy0 = b.dy;\n\n return arc(b);\n };\n }\n\n function updatePrevPosition(node) {\n var k = key(node);\n if(! prevPositions[k]) prevPositions[k] = {};\n var pP = prevPositions[k];\n pP.dx = node.dx;\n pP.x = node.x;\n pP.dy = node.dy;\n pP.y = node.y;\n }\n\n function storeRetrievePrevPositions(nodes) {\n nodes.forEach(function(n){\n var k = key(n);\n var pP = prevPositions[k];\n //console.log(k,n,pP);\n if( pP ){\n n.dx0 = pP.dx;\n n.x0 = pP.x;\n n.dy0 = pP.dy;\n n.y0 = pP.y;\n }\n else {\n n.dx0 = n.dx;\n n.x0 = n.x;\n n.dy0 = n.dy;\n n.y0 = n.y;\n }\n updatePrevPosition(n);\n });\n }\n\n function zoomClick(d) {\n var labels = container.selectAll('text')\n var path = container.selectAll('path')\n\n // fade out all text elements\n labels.transition().attr(\"opacity\",0);\n\n // to allow reference to the new center node\n node = d;\n\n path.transition()\n .duration(duration)\n .attrTween(\"d\", arcTweenZoom)\n .each('end', function(e) {\n // partially taken from here: http://bl.ocks.org/metmajer/5480307\n // check if the animated element's data e lies within the visible angle span given in d\n if(e.x >= d.x && e.x < (d.x + d.dx) ){\n if(e.depth >= d.depth){\n // get a selection of the associated text element\n var parentNode = d3.select(this.parentNode);\n var arcText = parentNode.select('text');\n\n // fade in the text element and recalculate positions\n arcText.transition().duration(duration)\n .text( function(e){return labelFormat(e) })\n .attr(\"opacity\", function(d){\n if(labelThresholdMatched(d)) {\n return 1;\n }\n else {\n return 0;\n }\n })\n .attr(\"transform\", function() {\n var width = this.getBBox().width;\n if(e.depth === 0)\n return \"translate(\" + (width / 2 * - 1) + \",0)\";\n else if(e.depth === d.depth){\n return \"translate(\" + (y(e.y) + 5) + \",0)\";\n }\n else {\n var centerAngle = computeCenterAngle(e);\n var rotation = rotationToAvoidUpsideDown(e);\n if (rotation === 0) {\n return 'rotate('+ centerAngle +')translate(' + (y(e.y) + 5) + ',0)';\n }\n else {\n return 'rotate('+ centerAngle +')translate(' + (y(e.y) + width + 5) + ',0)rotate(' + rotation + ')';\n }\n }\n });\n }\n }\n })\n }\n\n //============================================================\n // chart function\n //------------------------------------------------------------\n var renderWatch = nv.utils.renderWatch(dispatch);\n\n function chart(selection) {\n renderWatch.reset();\n\n selection.each(function(data) {\n container = d3.select(this);\n availableWidth = nv.utils.availableWidth(width, container, margin);\n availableHeight = nv.utils.availableHeight(height, container, margin);\n radius = Math.min(availableWidth, availableHeight) / 2;\n\n y.range([0, radius]);\n\n // Setup containers and skeleton of chart\n var wrap = container.select('g.nvd3.nv-wrap.nv-sunburst');\n if( !wrap[0][0] ) {\n wrap = container.append('g')\n .attr('class', 'nvd3 nv-wrap nv-sunburst nv-chart-' + id)\n .attr('transform', 'translate(' + ((availableWidth / 2) + margin.left + margin.right) + ',' + ((availableHeight / 2) + margin.top + margin.bottom) + ')');\n } else {\n wrap.attr('transform', 'translate(' + ((availableWidth / 2) + margin.left + margin.right) + ',' + ((availableHeight / 2) + margin.top + margin.bottom) + ')');\n }\n\n container.on('click', function (d, i) {\n dispatch.chartClick({\n data: d,\n index: i,\n pos: d3.event,\n id: id\n });\n });\n\n partition.value(modes[mode] || modes[\"count\"]);\n\n //reverse the drawing order so that the labels of inner\n //arcs are drawn on top of the outer arcs.\n var nodes = partition.nodes(data[0]).reverse()\n\n storeRetrievePrevPositions(nodes);\n var cG = wrap.selectAll('.arc-container').data(nodes, key)\n\n //handle new datapoints\n var cGE = cG.enter()\n .append(\"g\")\n .attr(\"class\",'arc-container')\n\n cGE.append(\"path\")\n .attr(\"d\", arc)\n .style(\"fill\", function (d) {\n if (d.color) {\n return d.color;\n }\n else if (groupColorByParent) {\n return color((d.children ? d : d.parent).name);\n }\n else {\n return color(d.name);\n }\n })\n .style(\"stroke\", \"#FFF\")\n .on(\"click\", function(d,i){\n zoomClick(d);\n dispatch.elementClick({\n data: d,\n index: i\n })\n })\n .on('mouseover', function(d,i){\n d3.select(this).classed('hover', true).style('opacity', 0.8);\n dispatch.elementMouseover({\n data: d,\n color: d3.select(this).style(\"fill\"),\n percent: computeNodePercentage(d)\n });\n })\n .on('mouseout', function(d,i){\n d3.select(this).classed('hover', false).style('opacity', 1);\n dispatch.elementMouseout({\n data: d\n });\n })\n .on('mousemove', function(d,i){\n dispatch.elementMousemove({\n data: d\n });\n });\n\n ///Iterating via each and selecting based on the this\n ///makes it work ... a cG.selectAll('path') doesn't.\n ///Without iteration the data (in the element) didn't update.\n cG.each(function(d){\n d3.select(this).select('path')\n .transition()\n .duration(duration)\n .attrTween('d', arcTweenUpdate);\n });\n\n if(showLabels){\n //remove labels first and add them back\n cG.selectAll('text').remove();\n\n //this way labels are on top of newly added arcs\n cG.append('text')\n .text( function(e){ return labelFormat(e)})\n .transition()\n .duration(duration)\n .attr(\"opacity\", function(d){\n if(labelThresholdMatched(d)) {\n return 1;\n }\n else {\n return 0;\n }\n })\n .attr(\"transform\", function(d) {\n var width = this.getBBox().width;\n if(d.depth === 0){\n return \"rotate(0)translate(\" + (width / 2 * -1) + \",0)\";\n }\n else {\n var centerAngle = computeCenterAngle(d);\n var rotation = rotationToAvoidUpsideDown(d);\n if (rotation === 0) {\n return 'rotate('+ centerAngle +')translate(' + (y(d.y) + 5) + ',0)';\n }\n else {\n return 'rotate('+ centerAngle +')translate(' + (y(d.y) + width + 5) + ',0)rotate(' + rotation + ')';\n }\n }\n });\n }\n\n //zoom out to the center when the data is updated.\n zoomClick(nodes[nodes.length - 1])\n\n\n //remove unmatched elements ...\n cG.exit()\n .transition()\n .duration(duration)\n .attr('opacity',0)\n .each('end',function(d){\n var k = key(d);\n prevPositions[k] = undefined;\n })\n .remove();\n });\n\n\n renderWatch.renderEnd('sunburst immediate');\n return chart;\n }\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n chart.dispatch = dispatch;\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n width: {get: function(){return width;}, set: function(_){width=_;}},\n height: {get: function(){return height;}, set: function(_){height=_;}},\n mode: {get: function(){return mode;}, set: function(_){mode=_;}},\n id: {get: function(){return id;}, set: function(_){id=_;}},\n duration: {get: function(){return duration;}, set: function(_){duration=_;}},\n groupColorByParent: {get: function(){return groupColorByParent;}, set: function(_){groupColorByParent=!!_;}},\n showLabels: {get: function(){return showLabels;}, set: function(_){showLabels=!!_}},\n labelFormat: {get: function(){return labelFormat;}, set: function(_){labelFormat=_}},\n labelThreshold: {get: function(){return labelThreshold;}, set: function(_){labelThreshold=_}},\n sort: {get: function(){return sort;}, set: function(_){sort=_}},\n key: {get: function(){return key;}, set: function(_){key=_}},\n // options that require extra logic in the setter\n margin: {get: function(){return margin;}, set: function(_){\n margin.top = _.top != undefined ? _.top : margin.top;\n margin.right = _.right != undefined ? _.right : margin.right;\n margin.bottom = _.bottom != undefined ? _.bottom : margin.bottom;\n margin.left = _.left != undefined ? _.left : margin.left;\n }},\n color: {get: function(){return color;}, set: function(_){\n color=nv.utils.getColor(_);\n }}\n });\n\n nv.utils.initOptions(chart);\n return chart;\n};\n","nv.models.sunburstChart = function() {\n \"use strict\";\n\n //============================================================\n // Public Variables with Default Settings\n //------------------------------------------------------------\n\n var sunburst = nv.models.sunburst();\n var tooltip = nv.models.tooltip();\n\n var margin = {top: 30, right: 20, bottom: 20, left: 20}\n , width = null\n , height = null\n , color = nv.utils.defaultColor()\n , showTooltipPercent = false\n , id = Math.round(Math.random() * 100000)\n , defaultState = null\n , noData = null\n , duration = 250\n , dispatch = d3.dispatch('stateChange', 'changeState','renderEnd');\n\n\n //============================================================\n // Private Variables\n //------------------------------------------------------------\n\n var renderWatch = nv.utils.renderWatch(dispatch);\n\n tooltip\n .duration(0)\n .headerEnabled(false)\n .valueFormatter(function(d){return d;});\n\n //============================================================\n // Chart function\n //------------------------------------------------------------\n\n function chart(selection) {\n renderWatch.reset();\n renderWatch.models(sunburst);\n\n selection.each(function(data) {\n var container = d3.select(this);\n\n nv.utils.initSVG(container);\n\n var availableWidth = nv.utils.availableWidth(width, container, margin);\n var availableHeight = nv.utils.availableHeight(height, container, margin);\n\n chart.update = function() {\n if (duration === 0) {\n container.call(chart);\n } else {\n container.transition().duration(duration).call(chart);\n }\n };\n chart.container = container;\n\n // Display No Data message if there's nothing to show.\n if (!data || !data.length) {\n nv.utils.noData(chart, container);\n return chart;\n } else {\n container.selectAll('.nv-noData').remove();\n }\n\n sunburst.width(availableWidth).height(availableHeight).margin(margin);\n container.call(sunburst);\n });\n\n renderWatch.renderEnd('sunburstChart immediate');\n return chart;\n }\n\n //============================================================\n // Event Handling/Dispatching (out of chart's scope)\n //------------------------------------------------------------\n\n sunburst.dispatch.on('elementMouseover.tooltip', function(evt) {\n evt.series = {\n key: evt.data.name,\n value: (evt.data.value || evt.data.size),\n color: evt.color,\n percent: evt.percent\n };\n if (!showTooltipPercent) {\n delete evt.percent;\n delete evt.series.percent;\n }\n tooltip.data(evt).hidden(false);\n });\n\n sunburst.dispatch.on('elementMouseout.tooltip', function(evt) {\n tooltip.hidden(true);\n });\n\n sunburst.dispatch.on('elementMousemove.tooltip', function(evt) {\n tooltip();\n });\n\n //============================================================\n // Expose Public Variables\n //------------------------------------------------------------\n\n // expose chart's sub-components\n chart.dispatch = dispatch;\n chart.sunburst = sunburst;\n chart.tooltip = tooltip;\n chart.options = nv.utils.optionsFunc.bind(chart);\n\n // use Object get/set functionality to map between vars and chart functions\n chart._options = Object.create({}, {\n // simple options, just get/set the necessary values\n noData: {get: function(){return noData;}, set: function(_){noData=_;}},\n defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}},\n showTooltipPercent: {get: function(){return showTooltipPercent;}, set: function(_){showTooltipPercent=_;}},\n\n // options that require extra logic in the setter\n color: {get: function(){return color;}, set: function(_){\n color = _;\n sunburst.color(color);\n }},\n duration: {get: function(){return duration;}, set: function(_){\n duration = _;\n renderWatch.reset(duration);\n sunburst.duration(duration);\n }},\n margin: {get: function(){return margin;}, set: function(_){\n margin.top = _.top !== undefined ? _.top : margin.top;\n margin.right = _.right !== undefined ? _.right : margin.right;\n margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;\n margin.left = _.left !== undefined ? _.left : margin.left;\n sunburst.margin(margin);\n }}\n });\n nv.utils.inheritOptions(chart, sunburst);\n nv.utils.initOptions(chart);\n return chart;\n\n};\n"]} \ No newline at end of file diff --git a/hadoop-hdds/framework/src/main/resources/webapps/static/ozone.css b/hadoop-hdds/framework/src/main/resources/webapps/static/ozone.css deleted file mode 100644 index 271ac744461..00000000000 --- a/hadoop-hdds/framework/src/main/resources/webapps/static/ozone.css +++ /dev/null @@ -1,60 +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 - * - * 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. -*/ -body { - padding: 40px; - padding-top: 60px; -} -.starter-template { - padding: 40px 15px; - text-align: center; -} - - -.btn { - border: 0 none; - font-weight: 700; - letter-spacing: 1px; - text-transform: uppercase; -} - -.btn:focus, .btn:active:focus, .btn.active:focus { - outline: 0 none; -} - -.table-striped > tbody > tr:nth-child(2n+1).selectedtag > td:hover { - background-color: #3276b1; -} -.table-striped > tbody > tr:nth-child(2n+1).selectedtag > td { - background-color: #3276b1; -} -.tagPanel tr.selectedtag td { - background-color: #3276b1; -} -.top-buffer { margin-top:4px; } - - -.sortorder:after { - content: '\25b2'; // BLACK UP-POINTING TRIANGLE -} -.sortorder.reverse:after { - content: '\25bc'; // BLACK DOWN-POINTING TRIANGLE -} - -.wrap-table{ - word-wrap: break-word; - table-layout: fixed; -} diff --git a/hadoop-hdds/framework/src/main/resources/webapps/static/ozone.js b/hadoop-hdds/framework/src/main/resources/webapps/static/ozone.js deleted file mode 100644 index c2ed2adce2f..00000000000 --- a/hadoop-hdds/framework/src/main/resources/webapps/static/ozone.js +++ /dev/null @@ -1,387 +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 - * - * 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. - */ -(function() { - "use strict"; - - var isIgnoredJmxKeys = function(key) { - return key == 'name' || key == 'modelerType' || key == "$$hashKey" || - key.match(/tag.*/); - }; - angular.module('ozone', ['nvd3', 'ngRoute']); - angular.module('ozone').config(function($routeProvider) { - $routeProvider - .when("/", { - templateUrl: "main.html" - }) - .when("/metrics/rpc", { - template: "" - }) - .when("/config", { - template: "" - }) - }); - angular.module('ozone').component('overview', { - templateUrl: 'static/templates/overview.html', - transclude: true, - controller: function($http) { - var ctrl = this; - $http.get("jmx?qry=Hadoop:service=*,name=*,component=ServerRuntime") - .then(function(result) { - ctrl.jmx = result.data.beans[0] - }) - } - }); - angular.module('ozone').component('jvmParameters', { - templateUrl: 'static/templates/jvm.html', - controller: function($http) { - var ctrl = this; - $http.get("jmx?qry=java.lang:type=Runtime") - .then(function(result) { - ctrl.jmx = result.data.beans[0]; - - //convert array to a map - var systemProperties = {}; - for (var idx in ctrl.jmx.SystemProperties) { - var item = ctrl.jmx.SystemProperties[idx]; - systemProperties[item.key.replace(/\./g, "_")] = item.value; - } - ctrl.jmx.SystemProperties = systemProperties; - }) - } - }); - - angular.module('ozone').component('rpcMetrics', { - template: '

Rpc metrics

' + - '' + - '' + - '', - controller: function($http) { - var ctrl = this; - $http.get("jmx?qry=Hadoop:service=*,name=RpcActivityForPort*") - .then(function(result) { - ctrl.metrics = result.data.beans; - }) - } - }); - angular.module('ozone').component('rpcMetric', { - bindings: { - jmxdata: '<' - }, - templateUrl: 'static/templates/rpc-metrics.html', - controller: function() { - var ctrl = this; - - - ctrl.percentileGraphOptions = { - chart: { - type: 'discreteBarChart', - height: 450, - margin: { - top: 20, - right: 20, - bottom: 50, - left: 55 - }, - x: function(d) { - return d.label; - }, - y: function(d) { - return d.value; - }, - showValues: true, - valueFormat: function(d) { - return d3.format(',.1f')(d); - }, - duration: 500, - xAxis: { - axisLabel: 'Percentage' - }, - yAxis: { - axisLabel: 'Latency (ms)', - axisLabelDistance: -10 - } - } - }; - - ctrl.$onChanges = function(data) { - var groupedMetrics = {} - - var createPercentageMetrics = function(metricName, window) { - groupedMetrics.percentiles = groupedMetrics['percentiles'] || {} - groupedMetrics.percentiles[window] = groupedMetrics.percentiles[window] || {}; - groupedMetrics.percentiles[window][metricName] = groupedMetrics.percentiles[window][metricName] || { - graphdata: [{ - key: window, - values: [] - }], - numOps: 0 - }; - - }; - var metrics = ctrl.jmxdata; - for (var key in metrics) { - var percentile = key.match(/(.*Time)(\d+s)(\d+th)PercentileLatency/); - var percentileNumOps = key.match(/(.*Time)(\d+s)NumOps/); - var successFailures = key.match(/(.*)(Success|Failures)/); - var numAverages = key.match(/(.*Time)(NumOps|AvgTime)/); - if (percentile) { - var metricName = percentile[1]; - var window = percentile[2]; - var percentage = percentile[3] - createPercentageMetrics(metricName, window); - - - groupedMetrics.percentiles[window][metricName].graphdata[0] - .values.push({ - label: percentage, - value: metrics[key] - }) - } else if (successFailures) { - var metricName = successFailures[1]; - groupedMetrics.successfailures = groupedMetrics['successfailures'] || {} - groupedMetrics.successfailures[metricName] = groupedMetrics.successfailures[metricName] || { - success: 0, - failures: 0 - }; - if (successFailures[2] == 'Success') { - groupedMetrics.successfailures[metricName].success = metrics[key]; - } else { - groupedMetrics.successfailures[metricName].failures = metrics[key]; - } - - } else if (numAverages) { - var metricName = numAverages[1]; - groupedMetrics.numavgs = groupedMetrics['numavgs'] || {} - groupedMetrics.numavgs[metricName] = groupedMetrics.numavgs[metricName] || { - numOps: 0, - avgTime: 0 - }; - if (numAverages[2] == 'NumOps') { - groupedMetrics.numavgs[metricName].numOps = metrics[key]; - } else { - groupedMetrics.numavgs[metricName].avgTime = metrics[key]; - } - - } else if (percentileNumOps) { - var metricName = percentileNumOps[1]; - var window = percentileNumOps[2]; - createPercentageMetrics(metricName, window); - groupedMetrics.percentiles[window][metricName].numOps = metrics[key]; - } else if (isIgnoredJmxKeys(key)) { - //ignore - } else { - groupedMetrics.others = groupedMetrics.others || []; - groupedMetrics.others.push({ - 'key': key, - 'value': metrics[key] - }); - } - - } - ctrl.metrics = groupedMetrics; - }; - - } - }); - angular.module('ozone') - .component('tabs', { - transclude: true, - controller: function($scope) { - var ctrl = this; - var panes = this.panes = []; - this.select = function(pane) { - angular.forEach(panes, function(pane) { - pane.selected = false; - }); - pane.selected = true; - }; - this.addPane = function(pane) { - if (panes.length === 0) { - this.select(pane); - } - panes.push(pane); - }; - this.click = function(pane) { - ctrl.select(pane); - } - }, - template: '' - }) - .component('pane', { - transclude: true, - require: { - tabsCtrl: '^tabs' - }, - bindings: { - title: '@' - }, - controller: function() { - this.$onInit = function() { - this.tabsCtrl.addPane(this); - }; - }, - template: '
' - }); - - angular.module('ozone').component('navmenu', { - bindings: { - metrics: '<' - }, - templateUrl: 'static/templates/menu.html', - controller: function($http) { - var ctrl = this; - ctrl.docs = false; - $http.head("docs/index.html") - .then(function(result) { - ctrl.docs = true; - }, function() { - ctrl.docs = false; - }); - } - }); - - angular.module('ozone').component('config', { - templateUrl: 'static/templates/config.html', - controller: function($scope, $http) { - var ctrl = this; - ctrl.selectedTags = []; - ctrl.configArray = []; - - $http.get("conf?cmd=getOzoneTags") - .then(function(response) { - ctrl.tags = response.data; - var excludedTags = ['CBLOCK', 'OM', 'SCM']; - for (var i = 0; i < excludedTags.length; i++) { - var idx = ctrl.tags.indexOf(excludedTags[i]); - // Remove CBLOCK related properties - if (idx > -1) { - ctrl.tags.splice(idx, 1); - } - } - ctrl.loadAll(); - }); - - ctrl.convertToArray = function(srcObj) { - ctrl.keyTagMap = {}; - for (var idx in srcObj) { - //console.log("Adding keys for "+idx) - for (var key in srcObj[idx]) { - - if (ctrl.keyTagMap.hasOwnProperty(key)) { - ctrl.keyTagMap[key]['tag'].push(idx); - } else { - var newProp = {}; - newProp['name'] = key; - newProp['value'] = srcObj[idx][key]; - newProp['tag'] = []; - newProp['tag'].push(idx); - ctrl.keyTagMap[key] = newProp; - } - } - } - } - - ctrl.loadAll = function() { - $http.get("conf?cmd=getPropertyByTag&tags=OM,SCM," + ctrl.tags) - .then(function(response) { - - ctrl.convertToArray(response.data); - ctrl.configs = Object.values(ctrl.keyTagMap); - ctrl.component = 'All'; - console.log("ajay -> " + JSON.stringify(ctrl.configs)); - ctrl.sortBy('name'); - }); - }; - - ctrl.filterTags = function() { - if (!ctrl.selectedTags) { - return true; - } - - if (ctrl.selectedTags.length < 1 && ctrl.component == 'All') { - return true; - } - - ctrl.configs = ctrl.configs.filter(function(item) { - - if (ctrl.component != 'All' && (item['tag'].indexOf(ctrl - .component) < 0)) { - console.log(item['name'] + " false tag " + item['tag']); - return false; - } - - if (ctrl.selectedTags.length < 1) { - return true; - } - for (var tag in item['tag']) { - tag = item['tag'][tag]; - if (ctrl.selectedTags.indexOf(tag) > -1) { - return true; - } - } - return false; - }); - - }; - ctrl.configFilter = function(config) { - return false; - }; - ctrl.selected = function(tag) { - return ctrl.selectedTags.includes(tag); - }; - - ctrl.switchto = function(tag) { - ctrl.component = tag; - ctrl.reloadConfig(); - }; - - ctrl.select = function(tag) { - var tagIdx = ctrl.selectedTags.indexOf(tag); - if (tagIdx > -1) { - ctrl.selectedTags.splice(tagIdx, 1); - } else { - ctrl.selectedTags.push(tag); - } - ctrl.reloadConfig(); - }; - - ctrl.reloadConfig = function() { - ctrl.configs = []; - ctrl.configs = Object.values(ctrl.keyTagMap); - ctrl.filterTags(); - }; - - ctrl.sortBy = function(field) { - ctrl.reverse = (ctrl.propertyName === field) ? !ctrl.reverse : false; - ctrl.propertyName = field; - }; - - ctrl.allSelected = function(comp) { - //console.log("Adding key for compo ->"+comp) - return ctrl.component == comp; - }; - - } - }); - -})(); \ No newline at end of file diff --git a/hadoop-hdds/framework/src/main/resources/webapps/static/templates/config.html b/hadoop-hdds/framework/src/main/resources/webapps/static/templates/config.html deleted file mode 100644 index b52f6533fc9..00000000000 --- a/hadoop-hdds/framework/src/main/resources/webapps/static/templates/config.html +++ /dev/null @@ -1,91 +0,0 @@ - - -
-
- -
-
-
- All - - OM - SCM -
-
-
-
-
- - - - - - - - - - - - - - - -
Tag
{{tag}}
-
-
- - - - - - - - - - - - - - - -
- Property - - - - Value - - - Description - -
{{config.name}}{{config.value}}{{config.description}}
-
-
diff --git a/hadoop-hdds/framework/src/main/resources/webapps/static/templates/jvm.html b/hadoop-hdds/framework/src/main/resources/webapps/static/templates/jvm.html deleted file mode 100644 index c1f7d16aefa..00000000000 --- a/hadoop-hdds/framework/src/main/resources/webapps/static/templates/jvm.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - -
JVM:{{$ctrl.jmx.SystemProperties.java_vm_name}} {{$ctrl.jmx.SystemProperties.java_vm_version}}
Input arguments:{{$ctrl.jmx.InputArguments}}
diff --git a/hadoop-hdds/framework/src/main/resources/webapps/static/templates/menu.html b/hadoop-hdds/framework/src/main/resources/webapps/static/templates/menu.html deleted file mode 100644 index 95f1b4842f1..00000000000 --- a/hadoop-hdds/framework/src/main/resources/webapps/static/templates/menu.html +++ /dev/null @@ -1,60 +0,0 @@ - - diff --git a/hadoop-hdds/framework/src/main/resources/webapps/static/templates/overview.html b/hadoop-hdds/framework/src/main/resources/webapps/static/templates/overview.html deleted file mode 100644 index 30e2d26f56f..00000000000 --- a/hadoop-hdds/framework/src/main/resources/webapps/static/templates/overview.html +++ /dev/null @@ -1,39 +0,0 @@ - -

Overview

- - - - - - - - - - - - - - - -
Started:{{$ctrl.jmx.StartedTimeInMillis | date : 'medium'}}
Version:{{$ctrl.jmx.Version}}
Compiled:{{$ctrl.jmx.CompileInfo}}
- -

JVM parameters

- - - -
\ No newline at end of file diff --git a/hadoop-hdds/framework/src/main/resources/webapps/static/templates/rpc-metrics.html b/hadoop-hdds/framework/src/main/resources/webapps/static/templates/rpc-metrics.html deleted file mode 100644 index facb1520304..00000000000 --- a/hadoop-hdds/framework/src/main/resources/webapps/static/templates/rpc-metrics.html +++ /dev/null @@ -1,87 +0,0 @@ - -
- Please set rpc.metrics.quantile.enable to true and define the - intervals in seconds with setting rpc.metrics.percentiles.intervals - (eg. set to 60,300) in your hdfs-site.xml - to display Hadoop RPC related graphs. -
-
-

{{window}} window

-

Quantiles based on a fixed {{window}} window. Calculated once at every - {{window}}

- -
-
-

{{metric}}

-

{{percentiles.numOps}} sample

- -
-
- -
-
-
-

Number of ops / Averages

- - - - - - - - - - - - - - -
Metric nameNumber of opsAverage time (ms)
{{key}}{{metric.numOps | number}}{{metric.avgTime | number:2}}
-
-
-

Success / Failures

- - - - - - - - - - - - - - - -
Metric nameSuccessFailures
{{key}}{{metric.success}}{{metric.failures}}
-
-
-
-

Other JMX Metrics

- - - - - - -
{{metric.key}}{{metric.value}}
-
\ No newline at end of file diff --git a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/TestBaseHttpServer.java b/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/TestBaseHttpServer.java deleted file mode 100644 index c6eae0e5fa6..00000000000 --- a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/TestBaseHttpServer.java +++ /dev/null @@ -1,98 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.server; - -import org.apache.hadoop.conf.Configuration; -import org.junit.Assert; -import org.junit.Test; - -/** - * Test Common ozone/hdds web methods. - */ -public class TestBaseHttpServer { - @Test - public void getBindAddress() throws Exception { - Configuration conf = new Configuration(); - conf.set("enabled", "false"); - - BaseHttpServer baseHttpServer = new BaseHttpServer(conf, "test") { - @Override - protected String getHttpAddressKey() { - return null; - } - - @Override - protected String getHttpsAddressKey() { - return null; - } - - @Override - protected String getHttpBindHostKey() { - return null; - } - - @Override - protected String getHttpsBindHostKey() { - return null; - } - - @Override - protected String getBindHostDefault() { - return null; - } - - @Override - protected int getHttpBindPortDefault() { - return 0; - } - - @Override - protected int getHttpsBindPortDefault() { - return 0; - } - - @Override - protected String getKeytabFile() { - return null; - } - - @Override - protected String getSpnegoPrincipal() { - return null; - } - - @Override - protected String getEnabledKey() { - return "enabled"; - } - }; - - conf.set("addresskey", "0.0.0.0:1234"); - - Assert.assertEquals("/0.0.0.0:1234", baseHttpServer - .getBindAddress("bindhostkey", "addresskey", - "default", 65).toString()); - - conf.set("bindhostkey", "1.2.3.4"); - - Assert.assertEquals("/1.2.3.4:1234", baseHttpServer - .getBindAddress("bindhostkey", "addresskey", - "default", 65).toString()); - } - -} \ No newline at end of file diff --git a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/events/EventHandlerStub.java b/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/events/EventHandlerStub.java deleted file mode 100644 index 3f34a70e6e7..00000000000 --- a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/events/EventHandlerStub.java +++ /dev/null @@ -1,38 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.server.events; - -import java.util.ArrayList; -import java.util.List; - -/** - * Dummy class for testing to collect all the received events. - */ -public class EventHandlerStub implements EventHandler { - - private List receivedEvents = new ArrayList<>(); - - @Override - public void onMessage(PAYLOAD payload, EventPublisher publisher) { - receivedEvents.add(payload); - } - - public List getReceivedEvents() { - return receivedEvents; - } -} diff --git a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/events/TestEventQueue.java b/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/events/TestEventQueue.java deleted file mode 100644 index 0c1200f6d14..00000000000 --- a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/events/TestEventQueue.java +++ /dev/null @@ -1,83 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.server.events; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem; - -/** - * Testing the basic functionality of the event queue. - */ -public class TestEventQueue { - - private static final Event EVENT1 = - new TypedEvent<>(Long.class, "SCM_EVENT1"); - private static final Event EVENT2 = - new TypedEvent<>(Long.class, "SCM_EVENT2"); - - private static final Event EVENT3 = - new TypedEvent<>(Long.class, "SCM_EVENT3"); - private static final Event EVENT4 = - new TypedEvent<>(Long.class, "SCM_EVENT4"); - - private EventQueue queue; - - @Before - public void startEventQueue() { - DefaultMetricsSystem.initialize(getClass().getSimpleName()); - queue = new EventQueue(); - } - - @After - public void stopEventQueue() { - DefaultMetricsSystem.shutdown(); - queue.close(); - } - - @Test - public void simpleEvent() { - - final long[] result = new long[2]; - - queue.addHandler(EVENT1, (payload, publisher) -> result[0] = payload); - - queue.fireEvent(EVENT1, 11L); - queue.processAll(1000); - Assert.assertEquals(11, result[0]); - - } - - @Test - public void multipleSubscriber() { - final long[] result = new long[2]; - queue.addHandler(EVENT2, (payload, publisher) -> result[0] = payload); - - queue.addHandler(EVENT2, (payload, publisher) -> result[1] = payload); - - queue.fireEvent(EVENT2, 23L); - queue.processAll(1000); - Assert.assertEquals(23, result[0]); - Assert.assertEquals(23, result[1]); - - } - -} \ No newline at end of file diff --git a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/events/TestEventQueueChain.java b/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/events/TestEventQueueChain.java deleted file mode 100644 index bb05ef453e6..00000000000 --- a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/events/TestEventQueueChain.java +++ /dev/null @@ -1,79 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.server.events; - -import org.junit.Test; - -/** - * More realistic event test with sending event from one listener. - */ -public class TestEventQueueChain { - - private static final Event DECOMMISSION = - new TypedEvent<>(FailedNode.class); - - private static final Event DECOMMISSION_START = - new TypedEvent<>(FailedNode.class); - - @Test - public void simpleEvent() { - EventQueue queue = new EventQueue(); - - queue.addHandler(DECOMMISSION, new PipelineManager()); - queue.addHandler(DECOMMISSION_START, new NodeWatcher()); - - queue.fireEvent(DECOMMISSION, new FailedNode("node1")); - - queue.processAll(5000); - } - - - static class FailedNode { - private final String nodeId; - - FailedNode(String nodeId) { - this.nodeId = nodeId; - } - - String getNodeId() { - return nodeId; - } - } - - private static class PipelineManager implements EventHandler { - - @Override - public void onMessage(FailedNode message, EventPublisher publisher) { - - System.out.println( - "Closing pipelines for all pipelines including node: " + message - .getNodeId()); - - publisher.fireEvent(DECOMMISSION_START, message); - } - - } - - private static class NodeWatcher implements EventHandler { - - @Override - public void onMessage(FailedNode message, EventPublisher publisher) { - System.out.println("Clear timer"); - } - } -} \ No newline at end of file diff --git a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/events/TestEventWatcher.java b/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/events/TestEventWatcher.java deleted file mode 100644 index b72d2ae7680..00000000000 --- a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/events/TestEventWatcher.java +++ /dev/null @@ -1,292 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.server.events; - -import java.util.List; -import java.util.Objects; -import org.apache.hadoop.hdds.HddsIdFactory; -import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem; -import org.apache.hadoop.ozone.lease.LeaseManager; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -/** - * Test the basic functionality of event watcher. - */ -public class TestEventWatcher { - - private static final TypedEvent WATCH_UNDER_REPLICATED = - new TypedEvent<>(UnderreplicatedEvent.class); - - private static final TypedEvent UNDER_REPLICATED = - new TypedEvent<>(UnderreplicatedEvent.class); - - private static final TypedEvent - REPLICATION_COMPLETED = new TypedEvent<>(ReplicationCompletedEvent.class); - - LeaseManager leaseManager; - - @Before - public void startLeaseManager() { - DefaultMetricsSystem.instance(); - leaseManager = new LeaseManager<>("Test", 2000L); - leaseManager.start(); - } - - @After - public void stopLeaseManager() { - leaseManager.shutdown(); - DefaultMetricsSystem.shutdown(); - } - - - @Test - public void testEventHandling() throws InterruptedException { - EventQueue queue = new EventQueue(); - - EventWatcher - replicationWatcher = createEventWatcher(); - - EventHandlerStub underReplicatedEvents = - new EventHandlerStub<>(); - - queue.addHandler(UNDER_REPLICATED, underReplicatedEvents); - - replicationWatcher.start(queue); - - long id1 = HddsIdFactory.getLongId(); - long id2 = HddsIdFactory.getLongId(); - - queue.fireEvent(WATCH_UNDER_REPLICATED, - new UnderreplicatedEvent(id1, "C1")); - - queue.fireEvent(WATCH_UNDER_REPLICATED, - new UnderreplicatedEvent(id2, "C2")); - - Assert.assertEquals(0, underReplicatedEvents.getReceivedEvents().size()); - - Thread.sleep(1000); - - queue.fireEvent(REPLICATION_COMPLETED, - new ReplicationCompletedEvent(id1, "C2", "D1")); - - Assert.assertEquals(0, underReplicatedEvents.getReceivedEvents().size()); - - Thread.sleep(1500); - - queue.processAll(1000L); - - Assert.assertEquals(1, underReplicatedEvents.getReceivedEvents().size()); - Assert.assertEquals(id2, - underReplicatedEvents.getReceivedEvents().get(0).id); - - } - - @Test - public void testInprogressFilter() throws InterruptedException { - - EventQueue queue = new EventQueue(); - - EventWatcher - replicationWatcher = createEventWatcher(); - - EventHandlerStub underReplicatedEvents = - new EventHandlerStub<>(); - - queue.addHandler(UNDER_REPLICATED, underReplicatedEvents); - - replicationWatcher.start(queue); - - UnderreplicatedEvent event1 = - new UnderreplicatedEvent(HddsIdFactory.getLongId(), "C1"); - - queue.fireEvent(WATCH_UNDER_REPLICATED, event1); - - queue.fireEvent(WATCH_UNDER_REPLICATED, - new UnderreplicatedEvent(HddsIdFactory.getLongId(), "C2")); - - queue.fireEvent(WATCH_UNDER_REPLICATED, - new UnderreplicatedEvent(HddsIdFactory.getLongId(), "C1")); - - queue.processAll(1000L); - Thread.sleep(1000L); - List c1todo = replicationWatcher - .getTimeoutEvents(e -> e.containerId.equalsIgnoreCase("C1")); - - Assert.assertEquals(2, c1todo.size()); - Assert.assertTrue(replicationWatcher.contains(event1)); - Thread.sleep(1500L); - - c1todo = replicationWatcher - .getTimeoutEvents(e -> e.containerId.equalsIgnoreCase("C1")); - Assert.assertEquals(0, c1todo.size()); - Assert.assertFalse(replicationWatcher.contains(event1)); - - } - - @Test - public void testMetrics() throws InterruptedException { - - DefaultMetricsSystem.initialize("test"); - - EventQueue queue = new EventQueue(); - - EventWatcher - replicationWatcher = createEventWatcher(); - - EventHandlerStub underReplicatedEvents = - new EventHandlerStub<>(); - - queue.addHandler(UNDER_REPLICATED, underReplicatedEvents); - - replicationWatcher.start(queue); - - //send 3 event to track 3 in-progress activity - UnderreplicatedEvent event1 = - new UnderreplicatedEvent(HddsIdFactory.getLongId(), "C1"); - - UnderreplicatedEvent event2 = - new UnderreplicatedEvent(HddsIdFactory.getLongId(), "C2"); - - UnderreplicatedEvent event3 = - new UnderreplicatedEvent(HddsIdFactory.getLongId(), "C1"); - - queue.fireEvent(WATCH_UNDER_REPLICATED, event1); - - queue.fireEvent(WATCH_UNDER_REPLICATED, event2); - - queue.fireEvent(WATCH_UNDER_REPLICATED, event3); - - //1st event is completed, don't need to track any more - ReplicationCompletedEvent event1Completed = - new ReplicationCompletedEvent(event1.id, "C1", "D1"); - - queue.fireEvent(REPLICATION_COMPLETED, event1Completed); - - Thread.sleep(2200l); - - //until now: 3 in-progress activities are tracked with three - // UnderreplicatedEvents. The first one is completed, the remaining two - // are timed out (as the timeout -- defined in the leasmanager -- is 2000ms. - - EventWatcherMetrics metrics = replicationWatcher.getMetrics(); - - //3 events are received - Assert.assertEquals(3, metrics.getTrackedEvents().value()); - - //one is finished. doesn't need to be resent - Assert.assertEquals(1, metrics.getCompletedEvents().value()); - - //Other two are timed out and resent - Assert.assertEquals(2, metrics.getTimedOutEvents().value()); - - DefaultMetricsSystem.shutdown(); - } - - private EventWatcher - createEventWatcher() { - return new CommandWatcherExample(WATCH_UNDER_REPLICATED, - REPLICATION_COMPLETED, leaseManager); - } - - private class CommandWatcherExample - extends EventWatcher { - - public CommandWatcherExample(Event startEvent, - Event completionEvent, - LeaseManager leaseManager) { - super("TestCommandWatcher", startEvent, completionEvent, leaseManager); - } - - @Override - protected void onTimeout(EventPublisher publisher, UnderreplicatedEvent payload) { - publisher.fireEvent(UNDER_REPLICATED, payload); - } - - @Override - protected void onFinished(EventPublisher publisher, UnderreplicatedEvent payload) { - //Good job. We did it. - } - - @Override - public EventWatcherMetrics getMetrics() { - return super.getMetrics(); - } - } - - private static class ReplicationCompletedEvent - implements IdentifiableEventPayload { - - private final long id; - - private final String containerId; - - private final String datanodeId; - - public ReplicationCompletedEvent(long id, String containerId, - String datanodeId) { - this.id = id; - this.containerId = containerId; - this.datanodeId = datanodeId; - } - - public long getId() { - return id; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - ReplicationCompletedEvent that = (ReplicationCompletedEvent) o; - return Objects.equals(containerId, that.containerId) && Objects - .equals(datanodeId, that.datanodeId); - } - - @Override - public int hashCode() { - - return Objects.hash(containerId, datanodeId); - } - } - - private static class UnderreplicatedEvent - - implements IdentifiableEventPayload { - - private final long id; - - private final String containerId; - - public UnderreplicatedEvent(long id, String containerId) { - this.containerId = containerId; - this.id = id; - } - - public long getId() { - return id; - } - } - -} diff --git a/hadoop-hdds/framework/src/test/resources/ozone-site.xml b/hadoop-hdds/framework/src/test/resources/ozone-site.xml deleted file mode 100644 index 77dd7ef9940..00000000000 --- a/hadoop-hdds/framework/src/test/resources/ozone-site.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - diff --git a/hadoop-hdds/pom.xml b/hadoop-hdds/pom.xml deleted file mode 100644 index 59dfa79fc67..00000000000 --- a/hadoop-hdds/pom.xml +++ /dev/null @@ -1,203 +0,0 @@ - - - - 4.0.0 - - org.apache.hadoop - hadoop-project-dist - 3.2.0-SNAPSHOT - ../hadoop-project-dist - - - hadoop-hdds - 0.3.0-SNAPSHOT - Apache Hadoop Distributed Data Store Project - Apache Hadoop HDDS - pom - - - client - common - framework - container-service - server-scm - tools - - - - - - org.apache.hadoop - hadoop-common - - - org.apache.hadoop - hadoop-hdfs - - - org.apache.hadoop - hadoop-hdfs-client - - - org.apache.hadoop - hadoop-common - test - test-jar - - - org.apache.hadoop - hadoop-hdfs - test - test-jar - - - info.picocli - picocli - 3.5.2 - - - com.google.protobuf - protobuf-java - compile - - - com.google.guava - guava - compile - - - junit - junit - test - - - - - - org.apache.rat - apache-rat-plugin - - - **/hs_err*.log - **/target/** - .gitattributes - .idea/** - src/main/resources/webapps/static/angular-1.6.4.min.js - src/main/resources/webapps/static/angular-nvd3-1.0.9.min.js - src/main/resources/webapps/static/angular-route-1.6.4.min.js - src/main/resources/webapps/static/d3-3.5.17.min.js - src/main/resources/webapps/static/nvd3-1.8.5.min.css.map - src/main/resources/webapps/static/nvd3-1.8.5.min.css - src/main/resources/webapps/static/nvd3-1.8.5.min.js.map - src/main/resources/webapps/static/nvd3-1.8.5.min.js - src/test/resources/additionalfields.container - src/test/resources/incorrect.checksum.container - src/test/resources/incorrect.container - src/test/resources/test.db.ini - - - - - org.codehaus.mojo - findbugs-maven-plugin - - - - - - org.apache.maven.plugins - maven-dependency-plugin - - - add-classpath-descriptor - package - - build-classpath - - - true - $HDDS_LIB_JARS_DIR - true - runtime - - - - - - org.apache.maven.plugins - maven-jar-plugin - - - - test-jar - - - - - - - - - - parallel-tests - - - - org.apache.hadoop - hadoop-maven-plugins - - - parallel-tests-createdir - - parallel-tests-createdir - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - ${testsThreadCount} - false - ${maven-surefire-plugin.argLine} -DminiClusterDedicatedDirs=true - - ${testsThreadCount} - ${test.build.data}/${surefire.forkNumber} - ${test.build.dir}/${surefire.forkNumber} - ${hadoop.tmp.dir}/${surefire.forkNumber} - - - - - - ${test.build.data} - - - - - - fork-${surefire.forkNumber} - - - - - - - - diff --git a/hadoop-hdds/server-scm/pom.xml b/hadoop-hdds/server-scm/pom.xml deleted file mode 100644 index f34e8482515..00000000000 --- a/hadoop-hdds/server-scm/pom.xml +++ /dev/null @@ -1,129 +0,0 @@ - - - - 4.0.0 - - org.apache.hadoop - hadoop-hdds - 0.3.0-SNAPSHOT - - hadoop-hdds-server-scm - 0.3.0-SNAPSHOT - Apache Hadoop Distributed Data Store Storage Container Manager Server - Apache Hadoop HDDS SCM Server - jar - - - - org.apache.hadoop - hadoop-hdds-common - - - - org.apache.hadoop - hadoop-hdds-container-service - - - - org.apache.hadoop - hadoop-hdds-client - - - - org.apache.hadoop - hadoop-hdds-server-framework - - - - org.apache.hadoop - hadoop-hdds-container-service - test - test-jar - - - - org.hamcrest - hamcrest-core - 1.3 - test - - - io.dropwizard.metrics - metrics-core - - - org.assertj - assertj-core - test - - - org.openjdk.jmh - jmh-core - test - - - org.openjdk.jmh - jmh-generator-annprocess - test - - - org.mockito - mockito-all - test - - - org.hamcrest - hamcrest-all - 1.3 - - - org.bouncycastle - bcprov-jdk16 - test - - - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-common-html - prepare-package - - unpack - - - - - org.apache.hadoop - hadoop-hdds-server-framework - ${project.build.outputDirectory} - - webapps/static/**/*.* - - - true - - - - - - - diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ScmUtils.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ScmUtils.java deleted file mode 100644 index 435f0a59322..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ScmUtils.java +++ /dev/null @@ -1,45 +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 - * - *      http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm; - -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ScmOps; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.hdds.scm.server.Precheck; - -/** - * SCM utility class. - */ -public final class ScmUtils { - - private ScmUtils() { - } - - /** - * Perform all prechecks for given scm operation. - * - * @param operation - * @param preChecks prechecks to be performed - */ - public static void preCheck(ScmOps operation, Precheck... preChecks) - throws SCMException { - for (Precheck preCheck : preChecks) { - preCheck.check(operation); - } - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/BlockManager.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/BlockManager.java deleted file mode 100644 index f9aa0cd4f72..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/BlockManager.java +++ /dev/null @@ -1,78 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.hdds.scm.block; - -import org.apache.hadoop.hdds.scm.container.common.helpers.AllocatedBlock; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.client.BlockID; - -import java.io.Closeable; -import java.io.IOException; -import java.util.List; - -/** - * - * Block APIs. - * Container is transparent to these APIs. - */ -public interface BlockManager extends Closeable { - /** - * Allocates a new block for a given size. - * @param size - Block Size - * @param type Replication Type - * @param factor - Replication Factor - * @return AllocatedBlock - * @throws IOException - */ - AllocatedBlock allocateBlock(long size, HddsProtos.ReplicationType type, - HddsProtos.ReplicationFactor factor, String owner) throws IOException; - - /** - * Deletes a list of blocks in an atomic operation. Internally, SCM - * writes these blocks into a {@link DeletedBlockLog} and deletes them - * from SCM DB. If this is successful, given blocks are entering pending - * deletion state and becomes invisible from SCM namespace. - * - * @param blockIDs block IDs. This is often the list of blocks of - * a particular object key. - * @throws IOException if exception happens, non of the blocks is deleted. - */ - void deleteBlocks(List blockIDs) throws IOException; - - /** - * @return the block deletion transaction log maintained by SCM. - */ - DeletedBlockLog getDeletedBlockLog(); - - /** - * Start block manager background services. - * @throws IOException - */ - void start() throws IOException; - - /** - * Shutdown block manager background services. - * @throws IOException - */ - void stop() throws IOException; - - /** - * @return the block deleting service executed in SCM. - */ - SCMBlockDeletingService getSCMBlockDeletingService(); -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/BlockManagerImpl.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/BlockManagerImpl.java deleted file mode 100644 index d383c687a76..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/BlockManagerImpl.java +++ /dev/null @@ -1,485 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.scm.block; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.conf.StorageUnit; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ScmOps; -import org.apache.hadoop.hdds.scm.ScmConfigKeys; -import org.apache.hadoop.hdds.scm.ScmUtils; -import org.apache.hadoop.hdds.scm.container.Mapping; -import org.apache.hadoop.hdds.scm.container.common.helpers.AllocatedBlock; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerWithPipeline; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.hdds.scm.node.NodeManager; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationFactor; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationType; -import org.apache.hadoop.hdds.scm.server.ChillModePrecheck; -import org.apache.hadoop.hdds.server.events.EventHandler; -import org.apache.hadoop.hdds.server.events.EventPublisher; -import org.apache.hadoop.metrics2.util.MBeans; -import org.apache.hadoop.hdds.client.BlockID; -import org.apache.hadoop.util.StringUtils; -import org.apache.hadoop.util.Time; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.management.ObjectName; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.concurrent.TimeUnit; - -import static org.apache.hadoop.hdds.scm.exceptions.SCMException.ResultCodes - .CHILL_MODE_EXCEPTION; -import static org.apache.hadoop.hdds.scm.exceptions.SCMException.ResultCodes - .INVALID_BLOCK_SIZE; -import static org.apache.hadoop.ozone.OzoneConfigKeys - .OZONE_BLOCK_DELETING_SERVICE_INTERVAL; -import static org.apache.hadoop.ozone.OzoneConfigKeys - .OZONE_BLOCK_DELETING_SERVICE_INTERVAL_DEFAULT; -import static org.apache.hadoop.ozone.OzoneConfigKeys - .OZONE_BLOCK_DELETING_SERVICE_TIMEOUT; -import static org.apache.hadoop.ozone.OzoneConfigKeys - .OZONE_BLOCK_DELETING_SERVICE_TIMEOUT_DEFAULT; - -/** Block Manager manages the block access for SCM. */ -public class BlockManagerImpl implements EventHandler, - BlockManager, BlockmanagerMXBean { - private static final Logger LOG = - LoggerFactory.getLogger(BlockManagerImpl.class); - // TODO : FIX ME : Hard coding the owner. - // Currently only user of the block service is Ozone, CBlock manages blocks - // by itself and does not rely on the Block service offered by SCM. - - private final NodeManager nodeManager; - private final Mapping containerManager; - - private final long containerSize; - - private final DeletedBlockLog deletedBlockLog; - private final SCMBlockDeletingService blockDeletingService; - - private final int containerProvisionBatchSize; - private final Random rand; - private ObjectName mxBean; - private ChillModePrecheck chillModePrecheck; - - /** - * Constructor. - * - * @param conf - configuration. - * @param nodeManager - node manager. - * @param containerManager - container manager. - * @param eventPublisher - event publisher. - * @throws IOException - */ - public BlockManagerImpl(final Configuration conf, - final NodeManager nodeManager, final Mapping containerManager, - EventPublisher eventPublisher) - throws IOException { - this.nodeManager = nodeManager; - this.containerManager = containerManager; - - this.containerSize = (long)conf.getStorageSize( - ScmConfigKeys.OZONE_SCM_CONTAINER_SIZE, - ScmConfigKeys.OZONE_SCM_CONTAINER_SIZE_DEFAULT, - StorageUnit.BYTES); - - this.containerProvisionBatchSize = - conf.getInt( - ScmConfigKeys.OZONE_SCM_CONTAINER_PROVISION_BATCH_SIZE, - ScmConfigKeys.OZONE_SCM_CONTAINER_PROVISION_BATCH_SIZE_DEFAULT); - rand = new Random(); - - mxBean = MBeans.register("BlockManager", "BlockManagerImpl", this); - - // SCM block deleting transaction log and deleting service. - deletedBlockLog = new DeletedBlockLogImpl(conf, containerManager); - long svcInterval = - conf.getTimeDuration(OZONE_BLOCK_DELETING_SERVICE_INTERVAL, - OZONE_BLOCK_DELETING_SERVICE_INTERVAL_DEFAULT, - TimeUnit.MILLISECONDS); - long serviceTimeout = - conf.getTimeDuration( - OZONE_BLOCK_DELETING_SERVICE_TIMEOUT, - OZONE_BLOCK_DELETING_SERVICE_TIMEOUT_DEFAULT, - TimeUnit.MILLISECONDS); - blockDeletingService = - new SCMBlockDeletingService(deletedBlockLog, containerManager, - nodeManager, eventPublisher, svcInterval, serviceTimeout, conf); - chillModePrecheck = new ChillModePrecheck(); - } - - /** - * Start block manager services. - * - * @throws IOException - */ - public void start() throws IOException { - this.blockDeletingService.start(); - } - - /** - * Shutdown block manager services. - * - * @throws IOException - */ - public void stop() throws IOException { - this.blockDeletingService.shutdown(); - this.close(); - } - - /** - * Pre allocate specified count of containers for block creation. - * - * @param count - Number of containers to allocate. - * @param type - Type of containers - * @param factor - how many copies needed for this container. - * @throws IOException - */ - private synchronized void preAllocateContainers(int count, - ReplicationType type, ReplicationFactor factor, String owner) - throws IOException { - for (int i = 0; i < count; i++) { - ContainerWithPipeline containerWithPipeline; - try { - // TODO: Fix this later when Ratis is made the Default. - containerWithPipeline = containerManager.allocateContainer( - type, factor, owner); - - if (containerWithPipeline == null) { - LOG.warn("Unable to allocate container."); - } - } catch (IOException ex) { - LOG.warn("Unable to allocate container: {}", ex); - } - } - } - - /** - * Allocates a block in a container and returns that info. - * - * @param size - Block Size - * @param type Replication Type - * @param factor - Replication Factor - * @return Allocated block - * @throws IOException on failure. - */ - @Override - public AllocatedBlock allocateBlock(final long size, - ReplicationType type, ReplicationFactor factor, String owner) - throws IOException { - LOG.trace("Size;{} , type : {}, factor : {} ", size, type, factor); - ScmUtils.preCheck(ScmOps.allocateBlock, chillModePrecheck); - if (size < 0 || size > containerSize) { - LOG.warn("Invalid block size requested : {}", size); - throw new SCMException("Unsupported block size: " + size, - INVALID_BLOCK_SIZE); - } - - /* - Here is the high level logic. - - 1. First we check if there are containers in ALLOCATED state, that is - SCM has allocated them in the SCM namespace but the corresponding - container has not been created in the Datanode yet. If we have any in - that state, we will return that to the client, which allows client to - finish creating those containers. This is a sort of greedy algorithm, - our primary purpose is to get as many containers as possible. - - 2. If there are no allocated containers -- Then we find a Open container - that matches that pattern. - - 3. If both of them fail, the we will pre-allocate a bunch of containers - in SCM and try again. - - TODO : Support random picking of two containers from the list. So we can - use different kind of policies. - */ - - ContainerWithPipeline containerWithPipeline; - - // This is to optimize performance, if the below condition is evaluated - // to false, then we can be sure that there are no containers in - // ALLOCATED state. - // This can result in false positive, but it will never be false negative. - // How can this result in false positive? We check if there are any - // containers in ALLOCATED state, this check doesn't care about the - // USER of the containers. So there might be cases where a different - // USER has few containers in ALLOCATED state, which will result in - // false positive. - if (!containerManager.getStateManager().getContainerStateMap() - .getContainerIDsByState(HddsProtos.LifeCycleState.ALLOCATED) - .isEmpty()) { - // Since the above check can result in false positive, we have to do - // the actual check and find out if there are containers in ALLOCATED - // state matching our criteria. - synchronized (this) { - // Using containers from ALLOCATED state should be done within - // synchronized block (or) write lock. Since we already hold a - // read lock, we will end up in deadlock situation if we take - // write lock here. - containerWithPipeline = containerManager - .getMatchingContainerWithPipeline(size, owner, type, factor, - HddsProtos.LifeCycleState.ALLOCATED); - if (containerWithPipeline != null) { - containerManager.updateContainerState( - containerWithPipeline.getContainerInfo().getContainerID(), - HddsProtos.LifeCycleEvent.CREATE); - return newBlock(containerWithPipeline, - HddsProtos.LifeCycleState.ALLOCATED); - } - } - } - - // Since we found no allocated containers that match our criteria, let us - // look for OPEN containers that match the criteria. - containerWithPipeline = containerManager - .getMatchingContainerWithPipeline(size, owner, type, factor, - HddsProtos.LifeCycleState.OPEN); - if (containerWithPipeline != null) { - return newBlock(containerWithPipeline, HddsProtos.LifeCycleState.OPEN); - } - - // We found neither ALLOCATED or OPEN Containers. This generally means - // that most of our containers are full or we have not allocated - // containers of the type and replication factor. So let us go and - // allocate some. - - // Even though we have already checked the containers in ALLOCATED - // state, we have to check again as we only hold a read lock. - // Some other thread might have pre-allocated container in meantime. - synchronized (this) { - if (!containerManager.getStateManager().getContainerStateMap() - .getContainerIDsByState(HddsProtos.LifeCycleState.ALLOCATED) - .isEmpty()) { - containerWithPipeline = containerManager - .getMatchingContainerWithPipeline(size, owner, type, factor, - HddsProtos.LifeCycleState.ALLOCATED); - } - if (containerWithPipeline == null) { - preAllocateContainers(containerProvisionBatchSize, - type, factor, owner); - containerWithPipeline = containerManager - .getMatchingContainerWithPipeline(size, owner, type, factor, - HddsProtos.LifeCycleState.ALLOCATED); - } - - if (containerWithPipeline != null) { - containerManager.updateContainerState( - containerWithPipeline.getContainerInfo().getContainerID(), - HddsProtos.LifeCycleEvent.CREATE); - return newBlock(containerWithPipeline, - HddsProtos.LifeCycleState.ALLOCATED); - } - } - // we have tried all strategies we know and but somehow we are not able - // to get a container for this block. Log that info and return a null. - LOG.error( - "Unable to allocate a block for the size: {}, type: {}, factor: {}", - size, type, factor); - return null; - } - - /** - * newBlock - returns a new block assigned to a container. - * - * @param containerWithPipeline - Container Info. - * @param state - Current state of the container. - * @return AllocatedBlock - */ - private AllocatedBlock newBlock(ContainerWithPipeline containerWithPipeline, - HddsProtos.LifeCycleState state) throws IOException { - ContainerInfo containerInfo = containerWithPipeline.getContainerInfo(); - if (containerWithPipeline.getPipeline().getDatanodes().size() == 0) { - LOG.error("Pipeline Machine count is zero."); - return null; - } - - // TODO : Revisit this local ID allocation when HA is added. - long localID = UniqueId.next(); - long containerID = containerInfo.getContainerID(); - - boolean createContainer = (state == HddsProtos.LifeCycleState.ALLOCATED); - - AllocatedBlock.Builder abb = - new AllocatedBlock.Builder() - .setBlockID(new BlockID(containerID, localID)) - .setPipeline(containerWithPipeline.getPipeline()) - .setShouldCreateContainer(createContainer); - LOG.trace("New block allocated : {} Container ID: {}", localID, - containerID); - return abb.build(); - } - - /** - * Deletes a list of blocks in an atomic operation. Internally, SCM writes - * these blocks into a - * {@link DeletedBlockLog} and deletes them from SCM DB. If this is - * successful, given blocks are - * entering pending deletion state and becomes invisible from SCM namespace. - * - * @param blockIDs block IDs. This is often the list of blocks of a - * particular object key. - * @throws IOException if exception happens, non of the blocks is deleted. - */ - @Override - public void deleteBlocks(List blockIDs) throws IOException { - if (!nodeManager.isOutOfChillMode()) { - throw new SCMException("Unable to delete block while in chill mode", - CHILL_MODE_EXCEPTION); - } - - LOG.info("Deleting blocks {}", StringUtils.join(",", blockIDs)); - Map> containerBlocks = new HashMap<>(); - // TODO: track the block size info so that we can reclaim the container - // TODO: used space when the block is deleted. - for (BlockID block : blockIDs) { - // Merge blocks to a container to blocks mapping, - // prepare to persist this info to the deletedBlocksLog. - long containerID = block.getContainerID(); - if (containerBlocks.containsKey(containerID)) { - containerBlocks.get(containerID).add(block.getLocalID()); - } else { - List item = new ArrayList<>(); - item.add(block.getLocalID()); - containerBlocks.put(containerID, item); - } - } - - try { - deletedBlockLog.addTransactions(containerBlocks); - } catch (IOException e) { - throw new IOException( - "Skip writing the deleted blocks info to" - + " the delLog because addTransaction fails. Batch skipped: " - + StringUtils.join(",", blockIDs), e); - } - // TODO: Container report handling of the deleted blocks: - // Remove tombstone and update open container usage. - // We will revisit this when the closed container replication is done. - } - - @Override - public DeletedBlockLog getDeletedBlockLog() { - return this.deletedBlockLog; - } - - /** - * Close the resources for BlockManager. - * - * @throws IOException - */ - @Override - public void close() throws IOException { - if (deletedBlockLog != null) { - deletedBlockLog.close(); - } - blockDeletingService.shutdown(); - if (mxBean != null) { - MBeans.unregister(mxBean); - mxBean = null; - } - } - - @Override - public int getOpenContainersNo() { - return 0; - // TODO : FIX ME : The open container being a single number does not make - // sense. - // We have to get open containers by Replication Type and Replication - // factor. Hence returning 0 for now. - // containers.get(HddsProtos.LifeCycleState.OPEN).size(); - } - - @Override - public SCMBlockDeletingService getSCMBlockDeletingService() { - return this.blockDeletingService; - } - - @Override - public void onMessage(Boolean inChillMode, EventPublisher publisher) { - this.chillModePrecheck.setInChillMode(inChillMode); - } - - /** - * Returns status of scm chill mode determined by CHILL_MODE_STATUS event. - * */ - public boolean isScmInChillMode() { - return this.chillModePrecheck.isInChillMode(); - } - - /** - * Get class logger. - * */ - public static Logger getLogger() { - return LOG; - } - - /** - * This class uses system current time milliseconds to generate unique id. - */ - public static final class UniqueId { - /* - * When we represent time in milliseconds using 'long' data type, - * the LSB bits are used. Currently we are only using 44 bits (LSB), - * 20 bits (MSB) are not used. - * We will exhaust this 44 bits only when we are in year 2525, - * until then we can safely use this 20 bits (MSB) for offset to generate - * unique id within millisecond. - * - * Year : Mon Dec 31 18:49:04 IST 2525 - * TimeInMillis: 17545641544247 - * Binary Representation: - * MSB (20 bits): 0000 0000 0000 0000 0000 - * LSB (44 bits): 1111 1111 0101 0010 1001 1011 1011 0100 1010 0011 0111 - * - * We have 20 bits to run counter, we should exclude the first bit (MSB) - * as we don't want to deal with negative values. - * To be on safer side we will use 'short' data type which is of length - * 16 bits and will give us 65,536 values for offset. - * - */ - - private static volatile short offset = 0; - - /** - * Private constructor so that no one can instantiate this class. - */ - private UniqueId() {} - - /** - * Calculate and returns next unique id based on System#currentTimeMillis. - * - * @return unique long value - */ - public static synchronized long next() { - long utcTime = Time.getUtcTime(); - if ((utcTime & 0xFFFF000000000000L) == 0) { - return utcTime << Short.SIZE | (offset++ & 0x0000FFFF); - } - throw new RuntimeException("Got invalid UTC time," + - " cannot generate unique Id. UTC Time: " + utcTime); - } - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/BlockmanagerMXBean.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/BlockmanagerMXBean.java deleted file mode 100644 index 23c6983083e..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/BlockmanagerMXBean.java +++ /dev/null @@ -1,30 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.hdds.scm.block; - - -/** - * JMX interface for the block manager. - */ -public interface BlockmanagerMXBean { - - /** - * Number of open containers manager by the block manager. - */ - int getOpenContainersNo(); -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/DatanodeDeletedBlockTransactions.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/DatanodeDeletedBlockTransactions.java deleted file mode 100644 index 8702a42d26a..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/DatanodeDeletedBlockTransactions.java +++ /dev/null @@ -1,148 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.scm.block; - -import com.google.common.collect.ArrayListMultimap; -import org.apache.hadoop.hdds.scm.container.Mapping; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.DeletedBlocksTransaction; - -import java.io.IOException; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.UUID; -import java.util.stream.Collectors; - -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerWithPipeline; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; - -/** - * A wrapper class to hold info about datanode and all deleted block - * transactions that will be sent to this datanode. - */ -public class DatanodeDeletedBlockTransactions { - private int nodeNum; - // The throttle size for each datanode. - private int maximumAllowedTXNum; - // Current counter of inserted TX. - private int currentTXNum; - private Mapping mappingService; - // A list of TXs mapped to a certain datanode ID. - private final ArrayListMultimap - transactions; - - DatanodeDeletedBlockTransactions(Mapping mappingService, - int maximumAllowedTXNum, int nodeNum) { - this.transactions = ArrayListMultimap.create(); - this.mappingService = mappingService; - this.maximumAllowedTXNum = maximumAllowedTXNum; - this.nodeNum = nodeNum; - } - - public boolean addTransaction(DeletedBlocksTransaction tx, - Set dnsWithTransactionCommitted) { - Pipeline pipeline = null; - try { - ContainerWithPipeline containerWithPipeline = - mappingService.getContainerWithPipeline(tx.getContainerID()); - if (containerWithPipeline.getContainerInfo().isContainerOpen() - || containerWithPipeline.getPipeline().isEmpty()) { - return false; - } - pipeline = containerWithPipeline.getPipeline(); - } catch (IOException e) { - SCMBlockDeletingService.LOG.warn("Got container info error.", e); - return false; - } - - boolean success = false; - for (DatanodeDetails dd : pipeline.getMachines()) { - UUID dnID = dd.getUuid(); - if (dnsWithTransactionCommitted == null || - !dnsWithTransactionCommitted.contains(dnID)) { - // Transaction need not be sent to dns which have already committed it - success = addTransactionToDN(dnID, tx); - } - } - return success; - } - - private boolean addTransactionToDN(UUID dnID, DeletedBlocksTransaction tx) { - if (transactions.containsKey(dnID)) { - List txs = transactions.get(dnID); - if (txs != null && txs.size() < maximumAllowedTXNum) { - boolean hasContained = false; - for (DeletedBlocksTransaction t : txs) { - if (t.getContainerID() == tx.getContainerID()) { - hasContained = true; - break; - } - } - - if (!hasContained) { - txs.add(tx); - currentTXNum++; - return true; - } - } - } else { - currentTXNum++; - transactions.put(dnID, tx); - return true; - } - SCMBlockDeletingService.LOG - .debug("Transaction added: {} <- TX({})", dnID, tx.getTxID()); - return false; - } - - Set getDatanodeIDs() { - return transactions.keySet(); - } - - boolean isEmpty() { - return transactions.isEmpty(); - } - - boolean hasTransactions(UUID dnId) { - return transactions.containsKey(dnId) && - !transactions.get(dnId).isEmpty(); - } - - List getDatanodeTransactions(UUID dnId) { - return transactions.get(dnId); - } - - List getTransactionIDList(UUID dnId) { - if (hasTransactions(dnId)) { - return transactions.get(dnId).stream() - .map(DeletedBlocksTransaction::getTxID).map(String::valueOf) - .collect(Collectors.toList()); - } else { - return Collections.emptyList(); - } - } - - boolean isFull() { - return currentTXNum >= maximumAllowedTXNum * nodeNum; - } - - int getTXNum() { - return currentTXNum; - } -} \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/DeletedBlockLog.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/DeletedBlockLog.java deleted file mode 100644 index db6c1c5dda2..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/DeletedBlockLog.java +++ /dev/null @@ -1,118 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.block; - -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerBlocksDeletionACKProto - .DeleteBlockTransactionResult; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.DeletedBlocksTransaction; - -import java.io.Closeable; -import java.io.IOException; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -/** - * The DeletedBlockLog is a persisted log in SCM to keep tracking - * container blocks which are under deletion. It maintains info - * about under-deletion container blocks that notified by OM, - * and the state how it is processed. - */ -public interface DeletedBlockLog extends Closeable { - - /** - * Scan entire log once and returns TXs to DatanodeDeletedBlockTransactions. - * Once DatanodeDeletedBlockTransactions is full, the scan behavior will - * stop. - * @param transactions a list of TXs will be set into. - * @return Mapping from containerId to latest transactionId for the container. - * @throws IOException - */ - Map getTransactions(DatanodeDeletedBlockTransactions transactions) - throws IOException; - - /** - * Return all failed transactions in the log. A transaction is considered - * to be failed if it has been sent more than MAX_RETRY limit and its - * count is reset to -1. - * - * @return a list of failed deleted block transactions. - * @throws IOException - */ - List getFailedTransactions() - throws IOException; - - /** - * Increments count for given list of transactions by 1. - * The log maintains a valid range of counts for each transaction - * [0, MAX_RETRY]. If exceed this range, resets it to -1 to indicate - * the transaction is no longer valid. - * - * @param txIDs - transaction ID. - */ - void incrementCount(List txIDs) - throws IOException; - - /** - * Commits a transaction means to delete all footprints of a transaction - * from the log. This method doesn't guarantee all transactions can be - * successfully deleted, it tolerate failures and tries best efforts to. - * @param transactionResults - delete block transaction results. - * @param dnID - ID of datanode which acknowledges the delete block command. - */ - void commitTransactions(List transactionResults, - UUID dnID); - - /** - * Creates a block deletion transaction and adds that into the log. - * - * @param containerID - container ID. - * @param blocks - blocks that belong to the same container. - * - * @throws IOException - */ - void addTransaction(long containerID, List blocks) - throws IOException; - - /** - * Creates block deletion transactions for a set of containers, - * add into the log and persist them atomically. An object key - * might be stored in multiple containers and multiple blocks, - * this API ensures that these updates are done in atomic manner - * so if any of them fails, the entire operation fails without - * any updates to the log. Note, this doesn't mean to create only - * one transaction, it creates multiple transactions (depends on the - * number of containers) together (on success) or non (on failure). - * - * @param containerBlocksMap a map of containerBlocks. - * @throws IOException - */ - void addTransactions(Map> containerBlocksMap) - throws IOException; - - /** - * Returns the total number of valid transactions. A transaction is - * considered to be valid as long as its count is in range [0, MAX_RETRY]. - * - * @return number of a valid transactions. - * @throws IOException - */ - int getNumOfValidTransactions() throws IOException; -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/DeletedBlockLogImpl.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/DeletedBlockLogImpl.java deleted file mode 100644 index 68435d1c6a2..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/DeletedBlockLogImpl.java +++ /dev/null @@ -1,428 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.block; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.Lists; -import com.google.common.primitives.Longs; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerBlocksDeletionACKProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerBlocksDeletionACKProto - .DeleteBlockTransactionResult; -import org.apache.hadoop.hdds.scm.command - .CommandStatusReportHandler.DeleteBlockStatus; -import org.apache.hadoop.hdds.scm.container.Mapping; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.server.events.EventHandler; -import org.apache.hadoop.hdds.server.events.EventPublisher; -import org.apache.hadoop.hdfs.DFSUtil; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.DeletedBlocksTransaction; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.utils.BatchOperation; -import org.apache.hadoop.utils.MetadataStore; -import org.apache.hadoop.utils.MetadataStoreBuilder; -import org.eclipse.jetty.util.ConcurrentHashSet; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; -import java.util.stream.Collectors; - -import static java.lang.Math.min; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_BLOCK_DELETION_MAX_RETRY; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_BLOCK_DELETION_MAX_RETRY_DEFAULT; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_DB_CACHE_SIZE_DEFAULT; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_DB_CACHE_SIZE_MB; -import static org.apache.hadoop.hdds.server.ServerUtils.getOzoneMetaDirPath; -import static org.apache.hadoop.ozone.OzoneConsts.DELETED_BLOCK_DB; - -/** - * A implement class of {@link DeletedBlockLog}, and it uses - * K/V db to maintain block deletion transactions between scm and datanode. - * This is a very basic implementation, it simply scans the log and - * memorize the position that scanned by last time, and uses this to - * determine where the next scan starts. It has no notion about weight - * of each transaction so as long as transaction is still valid, they get - * equally same chance to be retrieved which only depends on the nature - * order of the transaction ID. - */ -public class DeletedBlockLogImpl - implements DeletedBlockLog, EventHandler { - - public static final Logger LOG = - LoggerFactory.getLogger(DeletedBlockLogImpl.class); - - private static final byte[] LATEST_TXID = - DFSUtil.string2Bytes("#LATEST_TXID#"); - - private final int maxRetry; - private final MetadataStore deletedStore; - private final Mapping containerManager; - private final Lock lock; - // The latest id of deleted blocks in the db. - private long lastTxID; - // Maps txId to set of DNs which are successful in committing the transaction - private Map> transactionToDNsCommitMap; - - public DeletedBlockLogImpl(Configuration conf, Mapping containerManager) - throws IOException { - maxRetry = conf.getInt(OZONE_SCM_BLOCK_DELETION_MAX_RETRY, - OZONE_SCM_BLOCK_DELETION_MAX_RETRY_DEFAULT); - - File metaDir = getOzoneMetaDirPath(conf); - String scmMetaDataDir = metaDir.getPath(); - File deletedLogDbPath = new File(scmMetaDataDir, DELETED_BLOCK_DB); - int cacheSize = conf.getInt(OZONE_SCM_DB_CACHE_SIZE_MB, - OZONE_SCM_DB_CACHE_SIZE_DEFAULT); - // Load store of all transactions. - deletedStore = MetadataStoreBuilder.newBuilder() - .setCreateIfMissing(true) - .setConf(conf) - .setDbFile(deletedLogDbPath) - .setCacheSize(cacheSize * OzoneConsts.MB) - .build(); - this.containerManager = containerManager; - - this.lock = new ReentrantLock(); - // start from the head of deleted store. - lastTxID = findLatestTxIDInStore(); - - // transactionToDNsCommitMap is updated only when - // transaction is added to the log and when it is removed. - - // maps transaction to dns which have committed it. - transactionToDNsCommitMap = new ConcurrentHashMap<>(); - } - - @VisibleForTesting - public MetadataStore getDeletedStore() { - return deletedStore; - } - - /** - * There is no need to lock before reading because - * it's only used in construct method. - * - * @return latest txid. - * @throws IOException - */ - private long findLatestTxIDInStore() throws IOException { - long txid = 0; - byte[] value = deletedStore.get(LATEST_TXID); - if (value != null) { - txid = Longs.fromByteArray(value); - } - return txid; - } - - @Override - public List getFailedTransactions() - throws IOException { - lock.lock(); - try { - final List failedTXs = Lists.newArrayList(); - deletedStore.iterate(null, (key, value) -> { - if (!Arrays.equals(LATEST_TXID, key)) { - DeletedBlocksTransaction delTX = - DeletedBlocksTransaction.parseFrom(value); - if (delTX.getCount() == -1) { - failedTXs.add(delTX); - } - } - return true; - }); - return failedTXs; - } finally { - lock.unlock(); - } - } - - /** - * {@inheritDoc} - * - * @param txIDs - transaction ID. - * @throws IOException - */ - @Override - public void incrementCount(List txIDs) throws IOException { - BatchOperation batch = new BatchOperation(); - lock.lock(); - try { - for(Long txID : txIDs) { - try { - byte[] deleteBlockBytes = - deletedStore.get(Longs.toByteArray(txID)); - if (deleteBlockBytes == null) { - LOG.warn("Delete txID {} not found", txID); - continue; - } - DeletedBlocksTransaction block = DeletedBlocksTransaction - .parseFrom(deleteBlockBytes); - DeletedBlocksTransaction.Builder builder = block.toBuilder(); - int currentCount = block.getCount(); - if (currentCount > -1) { - builder.setCount(++currentCount); - } - // if the retry time exceeds the maxRetry value - // then set the retry value to -1, stop retrying, admins can - // analyze those blocks and purge them manually by SCMCli. - if (currentCount > maxRetry) { - builder.setCount(-1); - } - deletedStore.put(Longs.toByteArray(txID), - builder.build().toByteArray()); - } catch (IOException ex) { - LOG.warn("Cannot increase count for txID " + txID, ex); - } - } - deletedStore.writeBatch(batch); - } finally { - lock.unlock(); - } - } - - private DeletedBlocksTransaction constructNewTransaction(long txID, - long containerID, List blocks) { - return DeletedBlocksTransaction.newBuilder() - .setTxID(txID) - .setContainerID(containerID) - .addAllLocalID(blocks) - .setCount(0) - .build(); - } - - /** - * {@inheritDoc} - * - * @param transactionResults - transaction IDs. - * @param dnID - Id of Datanode which has acknowledged a delete block command. - * @throws IOException - */ - @Override - public void commitTransactions( - List transactionResults, UUID dnID) { - lock.lock(); - try { - Set dnsWithCommittedTxn; - for (DeleteBlockTransactionResult transactionResult : - transactionResults) { - if (isTransactionFailed(transactionResult)) { - continue; - } - try { - long txID = transactionResult.getTxID(); - // set of dns which have successfully committed transaction txId. - dnsWithCommittedTxn = transactionToDNsCommitMap.get(txID); - Long containerId = transactionResult.getContainerID(); - if (dnsWithCommittedTxn == null) { - LOG.warn("Transaction txId={} commit by dnId={} for containerID={} " - + "failed. Corresponding entry not found.", txID, dnID, - containerId); - return; - } - - dnsWithCommittedTxn.add(dnID); - Pipeline pipeline = - containerManager.getContainerWithPipeline(containerId) - .getPipeline(); - Collection containerDnsDetails = - pipeline.getDatanodes().values(); - // The delete entry can be safely removed from the log if all the - // corresponding nodes commit the txn. It is required to check that - // the nodes returned in the pipeline match the replication factor. - if (min(containerDnsDetails.size(), dnsWithCommittedTxn.size()) - >= pipeline.getFactor().getNumber()) { - List containerDns = containerDnsDetails.stream() - .map(DatanodeDetails::getUuid) - .collect(Collectors.toList()); - if (dnsWithCommittedTxn.containsAll(containerDns)) { - transactionToDNsCommitMap.remove(txID); - LOG.debug("Purging txId={} from block deletion log", txID); - deletedStore.delete(Longs.toByteArray(txID)); - } - } - LOG.debug("Datanode txId={} containerId={} committed by dnId={}", - txID, containerId, dnID); - } catch (IOException e) { - LOG.warn("Could not commit delete block transaction: " + - transactionResult.getTxID(), e); - } - } - } finally { - lock.unlock(); - } - } - - private boolean isTransactionFailed(DeleteBlockTransactionResult result) { - if (LOG.isDebugEnabled()) { - LOG.debug( - "Got block deletion ACK from datanode, TXIDs={}, " + "success={}", - result.getTxID(), result.getSuccess()); - } - if (!result.getSuccess()) { - LOG.warn("Got failed ACK for TXID={}, prepare to resend the " - + "TX in next interval", result.getTxID()); - return true; - } - return false; - } - - /** - * {@inheritDoc} - * - * @param containerID - container ID. - * @param blocks - blocks that belong to the same container. - * @throws IOException - */ - @Override - public void addTransaction(long containerID, List blocks) - throws IOException { - BatchOperation batch = new BatchOperation(); - lock.lock(); - try { - DeletedBlocksTransaction tx = constructNewTransaction(lastTxID + 1, - containerID, blocks); - byte[] key = Longs.toByteArray(lastTxID + 1); - - batch.put(key, tx.toByteArray()); - batch.put(LATEST_TXID, Longs.toByteArray(lastTxID + 1)); - - deletedStore.writeBatch(batch); - lastTxID += 1; - } finally { - lock.unlock(); - } - } - - @Override - public int getNumOfValidTransactions() throws IOException { - lock.lock(); - try { - final AtomicInteger num = new AtomicInteger(0); - deletedStore.iterate(null, (key, value) -> { - // Exclude latest txid record - if (!Arrays.equals(LATEST_TXID, key)) { - DeletedBlocksTransaction delTX = - DeletedBlocksTransaction.parseFrom(value); - if (delTX.getCount() > -1) { - num.incrementAndGet(); - } - } - return true; - }); - return num.get(); - } finally { - lock.unlock(); - } - } - - /** - * {@inheritDoc} - * - * @param containerBlocksMap a map of containerBlocks. - * @throws IOException - */ - @Override - public void addTransactions( - Map> containerBlocksMap) - throws IOException { - BatchOperation batch = new BatchOperation(); - lock.lock(); - try { - long currentLatestID = lastTxID; - for (Map.Entry> entry : - containerBlocksMap.entrySet()) { - currentLatestID += 1; - byte[] key = Longs.toByteArray(currentLatestID); - DeletedBlocksTransaction tx = constructNewTransaction(currentLatestID, - entry.getKey(), entry.getValue()); - batch.put(key, tx.toByteArray()); - } - lastTxID = currentLatestID; - batch.put(LATEST_TXID, Longs.toByteArray(lastTxID)); - deletedStore.writeBatch(batch); - } finally { - lock.unlock(); - } - } - - @Override - public void close() throws IOException { - if (deletedStore != null) { - deletedStore.close(); - } - } - - @Override - public Map getTransactions( - DatanodeDeletedBlockTransactions transactions) throws IOException { - lock.lock(); - try { - Map deleteTransactionMap = new HashMap<>(); - deletedStore.iterate(null, (key, value) -> { - if (!Arrays.equals(LATEST_TXID, key)) { - DeletedBlocksTransaction block = DeletedBlocksTransaction - .parseFrom(value); - - if (block.getCount() > -1 && block.getCount() <= maxRetry) { - if (transactions.addTransaction(block, - transactionToDNsCommitMap.get(block.getTxID()))) { - deleteTransactionMap.put(block.getContainerID(), block.getTxID()); - transactionToDNsCommitMap - .putIfAbsent(block.getTxID(), new ConcurrentHashSet<>()); - } - } - return !transactions.isFull(); - } - return true; - }); - return deleteTransactionMap; - } finally { - lock.unlock(); - } - } - - @Override - public void onMessage(DeleteBlockStatus deleteBlockStatus, - EventPublisher publisher) { - ContainerBlocksDeletionACKProto ackProto = - deleteBlockStatus.getCmdStatus().getBlockDeletionAck(); - commitTransactions(ackProto.getResultsList(), - UUID.fromString(ackProto.getDnId())); - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/PendingDeleteHandler.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/PendingDeleteHandler.java deleted file mode 100644 index 736daac54c2..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/PendingDeleteHandler.java +++ /dev/null @@ -1,38 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.block; - -import org.apache.hadoop.hdds.server.events.EventHandler; -import org.apache.hadoop.hdds.server.events.EventPublisher; - -public class PendingDeleteHandler implements - EventHandler { - - private SCMBlockDeletingService scmBlockDeletingService; - - public PendingDeleteHandler( - SCMBlockDeletingService scmBlockDeletingService) { - this.scmBlockDeletingService = scmBlockDeletingService; - } - - @Override - public void onMessage(PendingDeleteStatusList pendingDeleteStatusList, - EventPublisher publisher) { - scmBlockDeletingService.handlePendingDeletes(pendingDeleteStatusList); - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/PendingDeleteStatusList.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/PendingDeleteStatusList.java deleted file mode 100644 index 904762db596..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/PendingDeleteStatusList.java +++ /dev/null @@ -1,79 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.block; - -import org.apache.hadoop.hdds.protocol.DatanodeDetails; - -import java.util.LinkedList; -import java.util.List; - -public class PendingDeleteStatusList { - - private List pendingDeleteStatuses; - private DatanodeDetails datanodeDetails; - - public PendingDeleteStatusList(DatanodeDetails datanodeDetails) { - this.datanodeDetails = datanodeDetails; - pendingDeleteStatuses = new LinkedList<>(); - } - - public void addPendingDeleteStatus(long dnDeleteTransactionId, - long scmDeleteTransactionId, long containerId) { - pendingDeleteStatuses.add( - new PendingDeleteStatus(dnDeleteTransactionId, scmDeleteTransactionId, - containerId)); - } - - public static class PendingDeleteStatus { - private long dnDeleteTransactionId; - private long scmDeleteTransactionId; - private long containerId; - - public PendingDeleteStatus(long dnDeleteTransactionId, - long scmDeleteTransactionId, long containerId) { - this.dnDeleteTransactionId = dnDeleteTransactionId; - this.scmDeleteTransactionId = scmDeleteTransactionId; - this.containerId = containerId; - } - - public long getDnDeleteTransactionId() { - return dnDeleteTransactionId; - } - - public long getScmDeleteTransactionId() { - return scmDeleteTransactionId; - } - - public long getContainerId() { - return containerId; - } - - } - - public List getPendingDeleteStatuses() { - return pendingDeleteStatuses; - } - - public int getNumPendingDeletes() { - return pendingDeleteStatuses.size(); - } - - public DatanodeDetails getDatanodeDetails() { - return datanodeDetails; - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/SCMBlockDeletingService.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/SCMBlockDeletingService.java deleted file mode 100644 index b85d77f0841..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/SCMBlockDeletingService.java +++ /dev/null @@ -1,196 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.scm.block; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.scm.container.Mapping; -import org.apache.hadoop.hdds.scm.events.SCMEvents; -import org.apache.hadoop.hdds.scm.node.NodeManager; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.DeletedBlocksTransaction; -import org.apache.hadoop.hdds.server.events.EventPublisher; -import org.apache.hadoop.ozone.protocol.commands.CommandForDatanode; -import org.apache.hadoop.ozone.protocol.commands.DeleteBlocksCommand; -import org.apache.hadoop.util.Time; -import org.apache.hadoop.utils.BackgroundService; -import org.apache.hadoop.utils.BackgroundTask; -import org.apache.hadoop.utils.BackgroundTaskQueue; -import org.apache.hadoop.utils.BackgroundTaskResult.EmptyTaskResult; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.TimeUnit; - -import static org.apache.hadoop.ozone.OzoneConfigKeys - .OZONE_BLOCK_DELETING_CONTAINER_LIMIT_PER_INTERVAL; -import static org.apache.hadoop.ozone.OzoneConfigKeys - .OZONE_BLOCK_DELETING_CONTAINER_LIMIT_PER_INTERVAL_DEFAULT; - -/** - * A background service running in SCM to delete blocks. This service scans - * block deletion log in certain interval and caches block deletion commands - * in {@link org.apache.hadoop.hdds.scm.node.CommandQueue}, asynchronously - * SCM HB thread polls cached commands and sends them to datanode for physical - * processing. - */ -public class SCMBlockDeletingService extends BackgroundService { - - public static final Logger LOG = - LoggerFactory.getLogger(SCMBlockDeletingService.class); - - // ThreadPoolSize=2, 1 for scheduler and the other for the scanner. - private final static int BLOCK_DELETING_SERVICE_CORE_POOL_SIZE = 2; - private final DeletedBlockLog deletedBlockLog; - private final Mapping mappingService; - private final NodeManager nodeManager; - private final EventPublisher eventPublisher; - - // Block delete limit size is dynamically calculated based on container - // delete limit size (ozone.block.deleting.container.limit.per.interval) - // that configured for datanode. To ensure DN not wait for - // delete commands, we use this value multiply by a factor 2 as the final - // limit TX size for each node. - // Currently we implement a throttle algorithm that throttling delete blocks - // for each datanode. Each node is limited by the calculation size. Firstly - // current node info is fetched from nodemanager, then scan entire delLog - // from the beginning to end. If one node reaches maximum value, its records - // will be skipped. If not, keep scanning until it reaches maximum value. - // Once all node are full, the scan behavior will stop. - private int blockDeleteLimitSize; - - public SCMBlockDeletingService(DeletedBlockLog deletedBlockLog, - Mapping mapper, NodeManager nodeManager, EventPublisher eventPublisher, - long interval, long serviceTimeout, Configuration conf) { - super("SCMBlockDeletingService", interval, TimeUnit.MILLISECONDS, - BLOCK_DELETING_SERVICE_CORE_POOL_SIZE, serviceTimeout); - this.deletedBlockLog = deletedBlockLog; - this.mappingService = mapper; - this.nodeManager = nodeManager; - this.eventPublisher = eventPublisher; - - int containerLimit = conf.getInt( - OZONE_BLOCK_DELETING_CONTAINER_LIMIT_PER_INTERVAL, - OZONE_BLOCK_DELETING_CONTAINER_LIMIT_PER_INTERVAL_DEFAULT); - Preconditions.checkArgument(containerLimit > 0, - "Container limit size should be " + "positive."); - // Use container limit value multiply by a factor 2 to ensure DN - // not wait for orders. - this.blockDeleteLimitSize = containerLimit * 2; - } - - @Override - public BackgroundTaskQueue getTasks() { - BackgroundTaskQueue queue = new BackgroundTaskQueue(); - queue.add(new DeletedBlockTransactionScanner()); - return queue; - } - - public void handlePendingDeletes(PendingDeleteStatusList deletionStatusList) { - DatanodeDetails dnDetails = deletionStatusList.getDatanodeDetails(); - for (PendingDeleteStatusList.PendingDeleteStatus deletionStatus : - deletionStatusList.getPendingDeleteStatuses()) { - LOG.info( - "Block deletion txnID mismatch in datanode {} for containerID {}." - + " Datanode delete txnID: {}, SCM txnID: {}", - dnDetails.getUuid(), deletionStatus.getContainerId(), - deletionStatus.getDnDeleteTransactionId(), - deletionStatus.getScmDeleteTransactionId()); - } - } - - private class DeletedBlockTransactionScanner - implements BackgroundTask { - - @Override - public int getPriority() { - return 1; - } - - @Override - public EmptyTaskResult call() throws Exception { - int dnTxCount = 0; - long startTime = Time.monotonicNow(); - // Scan SCM DB in HB interval and collect a throttled list of - // to delete blocks. - LOG.debug("Running DeletedBlockTransactionScanner"); - DatanodeDeletedBlockTransactions transactions = null; - List datanodes = nodeManager.getNodes(NodeState.HEALTHY); - Map transactionMap = null; - if (datanodes != null) { - transactions = new DatanodeDeletedBlockTransactions(mappingService, - blockDeleteLimitSize, datanodes.size()); - try { - transactionMap = deletedBlockLog.getTransactions(transactions); - } catch (IOException e) { - // We may tolerant a number of failures for sometime - // but if it continues to fail, at some point we need to raise - // an exception and probably fail the SCM ? At present, it simply - // continues to retry the scanning. - LOG.error("Failed to get block deletion transactions from delTX log", - e); - } - LOG.debug("Scanned deleted blocks log and got {} delTX to process.", - transactions.getTXNum()); - } - - if (transactions != null && !transactions.isEmpty()) { - for (UUID dnId : transactions.getDatanodeIDs()) { - List dnTXs = transactions - .getDatanodeTransactions(dnId); - if (dnTXs != null && !dnTXs.isEmpty()) { - dnTxCount += dnTXs.size(); - // TODO commandQueue needs a cap. - // We should stop caching new commands if num of un-processed - // command is bigger than a limit, e.g 50. In case datanode goes - // offline for sometime, the cached commands be flooded. - eventPublisher.fireEvent(SCMEvents.RETRIABLE_DATANODE_COMMAND, - new CommandForDatanode<>(dnId, new DeleteBlocksCommand(dnTXs))); - LOG.debug( - "Added delete block command for datanode {} in the queue," - + " number of delete block transactions: {}, TxID list: {}", - dnId, dnTXs.size(), String.join(",", - transactions.getTransactionIDList(dnId))); - } - } - mappingService.updateDeleteTransactionId(transactionMap); - } - - if (dnTxCount > 0) { - LOG.info( - "Totally added {} delete blocks command for" - + " {} datanodes, task elapsed time: {}ms", - dnTxCount, transactions.getDatanodeIDs().size(), - Time.monotonicNow() - startTime); - } - - return EmptyTaskResult.newResult(); - } - } - - @VisibleForTesting - public void setBlockDeleteTXNum(int numTXs) { - blockDeleteLimitSize = numTXs; - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/package-info.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/package-info.java deleted file mode 100644 index e1bfdff5063..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/package-info.java +++ /dev/null @@ -1,22 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.hdds.scm.block; -/** - * This package contains routines to manage the block location and - * mapping inside SCM - */ diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/command/CommandStatusReportHandler.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/command/CommandStatusReportHandler.java deleted file mode 100644 index c0de3820bf2..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/command/CommandStatusReportHandler.java +++ /dev/null @@ -1,131 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.hdds.scm.command; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.CommandStatus; -import org.apache.hadoop.hdds.scm.events.SCMEvents; -import org.apache.hadoop.hdds.scm.server.SCMDatanodeHeartbeatDispatcher - .CommandStatusReportFromDatanode; -import org.apache.hadoop.hdds.server.events.EventPublisher; -import org.apache.hadoop.hdds.server.events.EventHandler; -import org.apache.hadoop.hdds.server.events.IdentifiableEventPayload; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.List; - -/** - * Handles CommandStatusReports from datanode. - */ -public class CommandStatusReportHandler implements - EventHandler { - - private static final Logger LOGGER = LoggerFactory - .getLogger(CommandStatusReportHandler.class); - - @Override - public void onMessage(CommandStatusReportFromDatanode report, - EventPublisher publisher) { - Preconditions.checkNotNull(report); - List cmdStatusList = report.getReport().getCmdStatusList(); - Preconditions.checkNotNull(cmdStatusList); - LOGGER.trace("Processing command status report for dn: {}", report - .getDatanodeDetails()); - - // Route command status to its watchers. - cmdStatusList.forEach(cmdStatus -> { - LOGGER.trace("Emitting command status for id:{} type: {}", cmdStatus - .getCmdId(), cmdStatus.getType()); - switch (cmdStatus.getType()) { - case replicateContainerCommand: - publisher.fireEvent(SCMEvents.REPLICATION_STATUS, new - ReplicationStatus(cmdStatus)); - break; - case closeContainerCommand: - publisher.fireEvent(SCMEvents.CLOSE_CONTAINER_STATUS, new - CloseContainerStatus(cmdStatus)); - break; - case deleteBlocksCommand: - if (cmdStatus.getStatus() == CommandStatus.Status.EXECUTED) { - publisher.fireEvent(SCMEvents.DELETE_BLOCK_STATUS, - new DeleteBlockStatus(cmdStatus)); - } - break; - default: - LOGGER.debug("CommandStatus of type:{} not handled in " + - "CommandStatusReportHandler.", cmdStatus.getType()); - break; - } - }); - } - - /** - * Wrapper event for CommandStatus. - */ - public static class CommandStatusEvent implements IdentifiableEventPayload { - private CommandStatus cmdStatus; - - CommandStatusEvent(CommandStatus cmdStatus) { - this.cmdStatus = cmdStatus; - } - - public CommandStatus getCmdStatus() { - return cmdStatus; - } - - @Override - public String toString() { - return "CommandStatusEvent:" + cmdStatus.toString(); - } - - @Override - public long getId() { - return cmdStatus.getCmdId(); - } - } - - /** - * Wrapper event for Replicate Command. - */ - public static class ReplicationStatus extends CommandStatusEvent { - public ReplicationStatus(CommandStatus cmdStatus) { - super(cmdStatus); - } - } - - /** - * Wrapper event for CloseContainer Command. - */ - public static class CloseContainerStatus extends CommandStatusEvent { - public CloseContainerStatus(CommandStatus cmdStatus) { - super(cmdStatus); - } - } - - /** - * Wrapper event for DeleteBlock Command. - */ - public static class DeleteBlockStatus extends CommandStatusEvent { - public DeleteBlockStatus(CommandStatus cmdStatus) { - super(cmdStatus); - } - } - -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/command/package-info.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/command/package-info.java deleted file mode 100644 index ba17fb9eeaa..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/command/package-info.java +++ /dev/null @@ -1,26 +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 - *

- * 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. - *

- * This package contains HDDS protocol related classes. - */ - -/** - * This package contains HDDS protocol related classes. - */ -package org.apache.hadoop.hdds.scm.command; -/* - * Classes related to commands issued from SCM to DataNode. - * */ \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/CloseContainerEventHandler.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/CloseContainerEventHandler.java deleted file mode 100644 index 7baecc4b1f8..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/CloseContainerEventHandler.java +++ /dev/null @@ -1,160 +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 - *

- *

http://www.apache.org/licenses/LICENSE-2.0 - *

- *

Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.scm.container; - -import java.io.IOException; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerWithPipeline; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.server.events.EventHandler; -import org.apache.hadoop.hdds.server.events.EventPublisher; -import org.apache.hadoop.hdds.server.events.IdentifiableEventPayload; -import org.apache.hadoop.ozone.protocol.commands.CloseContainerCommand; -import org.apache.hadoop.ozone.protocol.commands.CommandForDatanode; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static org.apache.hadoop.hdds.scm.events.SCMEvents.DATANODE_COMMAND; -import static org.apache.hadoop.hdds.scm.events.SCMEvents.CLOSE_CONTAINER_RETRYABLE_REQ; - -/** - * In case of a node failure, volume failure, volume out of spapce, node - * out of space etc, CLOSE_CONTAINER will be triggered. - * CloseContainerEventHandler is the handler for CLOSE_CONTAINER. - * When a close container event is fired, a close command for the container - * should be sent to all the datanodes in the pipeline and containerStateManager - * needs to update the container state to Closing. - */ -public class CloseContainerEventHandler implements EventHandler { - - public static final Logger LOG = - LoggerFactory.getLogger(CloseContainerEventHandler.class); - - - private final Mapping containerManager; - - public CloseContainerEventHandler(Mapping containerManager) { - this.containerManager = containerManager; - } - - @Override - public void onMessage(ContainerID containerID, EventPublisher publisher) { - - LOG.info("Close container Event triggered for container : {}", - containerID.getId()); - ContainerWithPipeline containerWithPipeline; - ContainerInfo info; - try { - containerWithPipeline = - containerManager.getContainerWithPipeline(containerID.getId()); - info = containerWithPipeline.getContainerInfo(); - if (info == null) { - LOG.error("Failed to update the container state. Container with id : {}" - + " does not exist", containerID.getId()); - return; - } - } catch (IOException e) { - LOG.error("Failed to update the container state. Container with id : {} " - + "does not exist", containerID.getId(), e); - return; - } - - HddsProtos.LifeCycleState state = info.getState(); - try { - switch (state) { - case ALLOCATED: - // We cannot close a container in ALLOCATED state, moving the - // container to CREATING state, this should eventually - // timeout and the container will be moved to DELETING state. - LOG.debug("Closing container {} in {} state", containerID, state); - containerManager.updateContainerState(containerID.getId(), - HddsProtos.LifeCycleEvent.CREATE); - break; - case CREATING: - // We cannot close a container in CREATING state, it will eventually - // timeout and moved to DELETING state. - LOG.debug("Closing container {} in {} state", containerID, state); - break; - case OPEN: - containerManager.updateContainerState(containerID.getId(), - HddsProtos.LifeCycleEvent.FINALIZE); - fireCloseContainerEvents(containerWithPipeline, info, publisher); - break; - case CLOSING: - fireCloseContainerEvents(containerWithPipeline, info, publisher); - break; - case CLOSED: - case DELETING: - case DELETED: - LOG.info( - "container with id : {} is in {} state and need not be closed.", - containerID.getId(), info.getState()); - break; - default: - throw new IOException( - "Invalid container state for container " + containerID); - } - } catch (IOException ex) { - LOG.error("Failed to update the container state for" + "container : {}" - + containerID, ex); - } - } - - private void fireCloseContainerEvents( - ContainerWithPipeline containerWithPipeline, ContainerInfo info, - EventPublisher publisher) { - ContainerID containerID = info.containerID(); - // fire events. - CloseContainerCommand closeContainerCommand = - new CloseContainerCommand(containerID.getId(), - info.getReplicationType(), info.getPipelineID()); - - Pipeline pipeline = containerWithPipeline.getPipeline(); - pipeline.getMachines().stream().map( - datanode -> new CommandForDatanode<>(datanode.getUuid(), - closeContainerCommand)).forEach((command) -> { - publisher.fireEvent(DATANODE_COMMAND, command); - }); - publisher.fireEvent(CLOSE_CONTAINER_RETRYABLE_REQ, - new CloseContainerRetryableReq(containerID)); - LOG.trace("Issuing {} on Pipeline {} for container", closeContainerCommand, - pipeline, containerID); - } - - /** - * Class to create retryable event. Prevents redundant requests for same - * container Id. - */ - public static class CloseContainerRetryableReq implements - IdentifiableEventPayload { - - private ContainerID containerID; - public CloseContainerRetryableReq(ContainerID containerID) { - this.containerID = containerID; - } - - public ContainerID getContainerID() { - return containerID; - } - - @Override - public long getId() { - return containerID.getId(); - } - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/CloseContainerWatcher.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/CloseContainerWatcher.java deleted file mode 100644 index 8e277b9f369..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/CloseContainerWatcher.java +++ /dev/null @@ -1,100 +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 - *

- *

http://www.apache.org/licenses/LICENSE-2.0 - *

- *

Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.scm.container; - -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.CommandStatus.Status; -import org.apache.hadoop.hdds.scm.command.CommandStatusReportHandler - .CloseContainerStatus; - -import org.apache.hadoop.hdds.scm.events.SCMEvents; -import org.apache.hadoop.hdds.server.events.Event; -import org.apache.hadoop.hdds.server.events.EventPublisher; -import org.apache.hadoop.hdds.server.events.EventWatcher; -import org.apache.hadoop.hdds.scm.container.CloseContainerEventHandler - .CloseContainerRetryableReq; -import org.apache.hadoop.ozone.lease.LeaseManager; -import org.apache.hadoop.ozone.lease.LeaseNotFoundException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; - -/** - * This watcher will watch for CLOSE_CONTAINER_STATUS events fired from - * CommandStatusReport. If required it will re-trigger CloseContainer command - * for DataNodes to CloseContainerEventHandler. - */ -public class CloseContainerWatcher extends - EventWatcher { - - public static final Logger LOG = - LoggerFactory.getLogger(CloseContainerWatcher.class); - private final Mapping containerManager; - - public CloseContainerWatcher(Event startEvent, - Event completionEvent, - LeaseManager leaseManager, Mapping containerManager) { - super(startEvent, completionEvent, leaseManager); - this.containerManager = containerManager; - } - - @Override - protected void onTimeout(EventPublisher publisher, - CloseContainerRetryableReq payload) { - // Let CloseContainerEventHandler handle this message. - this.resendEventToHandler(payload.getId(), publisher); - } - - @Override - protected void onFinished(EventPublisher publisher, - CloseContainerRetryableReq payload) { - LOG.trace("CloseContainerCommand for containerId: {} executed ", payload - .getContainerID().getId()); - } - - @Override - protected synchronized void handleCompletion(CloseContainerStatus status, - EventPublisher publisher) throws LeaseNotFoundException { - // If status is PENDING then return without doing anything. - if(status.getCmdStatus().getStatus().equals(Status.PENDING)){ - return; - } - - CloseContainerRetryableReq closeCont = getTrackedEventbyId(status.getId()); - super.handleCompletion(status, publisher); - // If status is FAILED then send a msg to Handler to resend the command. - if (status.getCmdStatus().getStatus().equals(Status.FAILED) && closeCont - != null) { - this.resendEventToHandler(closeCont.getId(), publisher); - } - } - - private void resendEventToHandler(long containerID, EventPublisher - publisher) { - try { - // Check if container is still open - if (containerManager.getContainer(containerID).isContainerOpen()) { - publisher.fireEvent(SCMEvents.CLOSE_CONTAINER, - ContainerID.valueof(containerID)); - } - } catch (IOException e) { - LOG.warn("Error in CloseContainerWatcher while processing event " + - "for containerId {} ExceptionMsg: ", containerID, e.getMessage()); - } - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerActionsHandler.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerActionsHandler.java deleted file mode 100644 index ce399eb89b8..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerActionsHandler.java +++ /dev/null @@ -1,60 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.container; - -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerAction; -import org.apache.hadoop.hdds.scm.events.SCMEvents; -import org.apache.hadoop.hdds.scm.server.SCMDatanodeHeartbeatDispatcher - .ContainerActionsFromDatanode; -import org.apache.hadoop.hdds.server.events.EventHandler; -import org.apache.hadoop.hdds.server.events.EventPublisher; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Handles container reports from datanode. - */ -public class ContainerActionsHandler implements - EventHandler { - - private static final Logger LOG = LoggerFactory.getLogger( - ContainerActionsHandler.class); - - @Override - public void onMessage( - ContainerActionsFromDatanode containerReportFromDatanode, - EventPublisher publisher) { - DatanodeDetails dd = containerReportFromDatanode.getDatanodeDetails(); - for (ContainerAction action : containerReportFromDatanode.getReport() - .getContainerActionsList()) { - ContainerID containerId = ContainerID.valueof(action.getContainerID()); - switch (action.getAction()) { - case CLOSE: - LOG.debug("Closing container {} in datanode {} because the" + - " container is {}.", containerId, dd, action.getReason()); - publisher.fireEvent(SCMEvents.CLOSE_CONTAINER, containerId); - break; - default: - LOG.warn("Invalid action {} with reason {}, from datanode {}. ", - action.getAction(), action.getReason(), dd); } - } - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerMapping.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerMapping.java deleted file mode 100644 index 71e17e9982d..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerMapping.java +++ /dev/null @@ -1,699 +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 - *

- *

http://www.apache.org/licenses/LICENSE-2.0 - *

- *

Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.scm.container; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import com.google.common.primitives.Longs; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.conf.StorageUnit; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.LifeCycleEvent; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.LifeCycleState; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.SCMContainerInfo; -import org.apache.hadoop.hdds.scm.block.PendingDeleteStatusList; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerWithPipeline; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.scm.ScmConfigKeys; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo; -import org.apache.hadoop.hdds.scm.container.common.helpers.PipelineID; -import org.apache.hadoop.hdds.scm.events.SCMEvents; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.hdds.scm.node.NodeManager; -import org.apache.hadoop.hdds.scm.pipelines.PipelineSelector; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationFactor; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationType; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerReportsProto; -import org.apache.hadoop.hdds.server.events.EventPublisher; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.lease.Lease; -import org.apache.hadoop.ozone.lease.LeaseException; -import org.apache.hadoop.ozone.lease.LeaseManager; -import org.apache.hadoop.utils.BatchOperation; -import org.apache.hadoop.utils.MetadataStore; -import org.apache.hadoop.utils.MetadataStoreBuilder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_CONTAINER_SIZE_DEFAULT; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_CONTAINER_SIZE; -import static org.apache.hadoop.hdds.scm.exceptions.SCMException.ResultCodes - .FAILED_TO_CHANGE_CONTAINER_STATE; -import static org.apache.hadoop.hdds.server.ServerUtils.getOzoneMetaDirPath; -import static org.apache.hadoop.ozone.OzoneConsts.SCM_CONTAINER_DB; - -/** - * Mapping class contains the mapping from a name to a pipeline mapping. This - * is used by SCM when - * allocating new locations and when looking up a key. - */ -public class ContainerMapping implements Mapping { - private static final Logger LOG = LoggerFactory.getLogger(ContainerMapping - .class); - - private final NodeManager nodeManager; - private final long cacheSize; - private final Lock lock; - private final Charset encoding = Charset.forName("UTF-8"); - private final MetadataStore containerStore; - private final PipelineSelector pipelineSelector; - private final ContainerStateManager containerStateManager; - private final LeaseManager containerLeaseManager; - private final EventPublisher eventPublisher; - private final long size; - - /** - * Constructs a mapping class that creates mapping between container names - * and pipelines. - * - * @param nodeManager - NodeManager so that we can get the nodes that are - * healthy to place new - * containers. - * @param cacheSizeMB - Amount of memory reserved for the LSM tree to cache - * its nodes. This is - * passed to LevelDB and this memory is allocated in Native code space. - * CacheSize is specified - * in MB. - * @throws IOException on Failure. - */ - @SuppressWarnings("unchecked") - public ContainerMapping( - final Configuration conf, final NodeManager nodeManager, final int - cacheSizeMB, EventPublisher eventPublisher) throws IOException { - this.nodeManager = nodeManager; - this.cacheSize = cacheSizeMB; - - File metaDir = getOzoneMetaDirPath(conf); - - // Write the container name to pipeline mapping. - File containerDBPath = new File(metaDir, SCM_CONTAINER_DB); - containerStore = - MetadataStoreBuilder.newBuilder() - .setConf(conf) - .setDbFile(containerDBPath) - .setCacheSize(this.cacheSize * OzoneConsts.MB) - .build(); - - this.lock = new ReentrantLock(); - - size = (long)conf.getStorageSize(OZONE_SCM_CONTAINER_SIZE, - OZONE_SCM_CONTAINER_SIZE_DEFAULT, StorageUnit.BYTES); - - this.pipelineSelector = new PipelineSelector(nodeManager, - conf, eventPublisher, cacheSizeMB); - - this.containerStateManager = - new ContainerStateManager(conf, this, pipelineSelector); - LOG.trace("Container State Manager created."); - - this.eventPublisher = eventPublisher; - - long containerCreationLeaseTimeout = conf.getTimeDuration( - ScmConfigKeys.OZONE_SCM_CONTAINER_CREATION_LEASE_TIMEOUT, - ScmConfigKeys.OZONE_SCM_CONTAINER_CREATION_LEASE_TIMEOUT_DEFAULT, - TimeUnit.MILLISECONDS); - containerLeaseManager = new LeaseManager<>("ContainerCreation", - containerCreationLeaseTimeout); - containerLeaseManager.start(); - } - - /** - * {@inheritDoc} - */ - @Override - public ContainerInfo getContainer(final long containerID) throws - IOException { - ContainerInfo containerInfo; - lock.lock(); - try { - byte[] containerBytes = containerStore.get( - Longs.toByteArray(containerID)); - if (containerBytes == null) { - throw new SCMException( - "Specified key does not exist. key : " + containerID, - SCMException.ResultCodes.FAILED_TO_FIND_CONTAINER); - } - - HddsProtos.SCMContainerInfo temp = HddsProtos.SCMContainerInfo.PARSER - .parseFrom(containerBytes); - containerInfo = ContainerInfo.fromProtobuf(temp); - return containerInfo; - } finally { - lock.unlock(); - } - } - - /** - * Returns the ContainerInfo and pipeline from the containerID. If container - * has no available replicas in datanodes it returns pipeline with no - * datanodes and empty leaderID . Pipeline#isEmpty can be used to check for - * an empty pipeline. - * - * @param containerID - ID of container. - * @return - ContainerWithPipeline such as creation state and the pipeline. - * @throws IOException - */ - @Override - public ContainerWithPipeline getContainerWithPipeline(long containerID) - throws IOException { - ContainerInfo contInfo; - lock.lock(); - try { - byte[] containerBytes = containerStore.get( - Longs.toByteArray(containerID)); - if (containerBytes == null) { - throw new SCMException( - "Specified key does not exist. key : " + containerID, - SCMException.ResultCodes.FAILED_TO_FIND_CONTAINER); - } - HddsProtos.SCMContainerInfo temp = HddsProtos.SCMContainerInfo.PARSER - .parseFrom(containerBytes); - contInfo = ContainerInfo.fromProtobuf(temp); - - Pipeline pipeline; - String leaderId = ""; - if (contInfo.isContainerOpen()) { - // If pipeline with given pipeline Id already exist return it - pipeline = pipelineSelector.getPipeline(contInfo.getPipelineID()); - } else { - // For close containers create pipeline from datanodes with replicas - Set dnWithReplicas = containerStateManager - .getContainerReplicas(contInfo.containerID()); - if (!dnWithReplicas.isEmpty()) { - leaderId = dnWithReplicas.iterator().next().getUuidString(); - } - pipeline = new Pipeline(leaderId, contInfo.getState(), - ReplicationType.STAND_ALONE, contInfo.getReplicationFactor(), - PipelineID.randomId()); - dnWithReplicas.forEach(pipeline::addMember); - } - return new ContainerWithPipeline(contInfo, pipeline); - } finally { - lock.unlock(); - } - } - - /** - * {@inheritDoc} - */ - @Override - public List listContainer(long startContainerID, - int count) throws IOException { - List containerList = new ArrayList<>(); - lock.lock(); - try { - if (containerStore.isEmpty()) { - throw new IOException("No container exists in current db"); - } - byte[] startKey = startContainerID <= 0 ? null : - Longs.toByteArray(startContainerID); - List> range = - containerStore.getSequentialRangeKVs(startKey, count, null); - - // Transform the values into the pipelines. - // TODO: filter by container state - for (Map.Entry entry : range) { - ContainerInfo containerInfo = - ContainerInfo.fromProtobuf( - HddsProtos.SCMContainerInfo.PARSER.parseFrom( - entry.getValue())); - Preconditions.checkNotNull(containerInfo); - containerList.add(containerInfo); - } - } finally { - lock.unlock(); - } - return containerList; - } - - /** - * Allocates a new container. - * - * @param replicationFactor - replication factor of the container. - * @param owner - The string name of the Service that owns this container. - * @return - Pipeline that makes up this container. - * @throws IOException - Exception - */ - @Override - public ContainerWithPipeline allocateContainer( - ReplicationType type, - ReplicationFactor replicationFactor, - String owner) - throws IOException { - - ContainerInfo containerInfo; - ContainerWithPipeline containerWithPipeline; - - lock.lock(); - try { - containerWithPipeline = containerStateManager.allocateContainer( - pipelineSelector, type, replicationFactor, owner); - containerInfo = containerWithPipeline.getContainerInfo(); - - byte[] containerIDBytes = Longs.toByteArray( - containerInfo.getContainerID()); - containerStore.put(containerIDBytes, containerInfo.getProtobuf() - .toByteArray()); - } finally { - lock.unlock(); - } - return containerWithPipeline; - } - - /** - * Deletes a container from SCM. - * - * @param containerID - Container ID - * @throws IOException if container doesn't exist or container store failed - * to delete the - * specified key. - */ - @Override - public void deleteContainer(long containerID) throws IOException { - lock.lock(); - try { - byte[] dbKey = Longs.toByteArray(containerID); - byte[] containerBytes = containerStore.get(dbKey); - if (containerBytes == null) { - throw new SCMException( - "Failed to delete container " + containerID + ", reason : " + - "container doesn't exist.", - SCMException.ResultCodes.FAILED_TO_FIND_CONTAINER); - } - containerStore.delete(dbKey); - } finally { - lock.unlock(); - } - } - - /** - * {@inheritDoc} Used by client to update container state on SCM. - */ - @Override - public HddsProtos.LifeCycleState updateContainerState( - long containerID, HddsProtos.LifeCycleEvent event) throws - IOException { - ContainerInfo containerInfo; - lock.lock(); - try { - byte[] dbKey = Longs.toByteArray(containerID); - byte[] containerBytes = containerStore.get(dbKey); - if (containerBytes == null) { - throw new SCMException( - "Failed to update container state" - + containerID - + ", reason : container doesn't exist.", - SCMException.ResultCodes.FAILED_TO_FIND_CONTAINER); - } - containerInfo = - ContainerInfo.fromProtobuf(HddsProtos.SCMContainerInfo.PARSER - .parseFrom(containerBytes)); - - Preconditions.checkNotNull(containerInfo); - switch (event) { - case CREATE: - // Acquire lease on container - Lease containerLease = - containerLeaseManager.acquire(containerInfo); - // Register callback to be executed in case of timeout - containerLease.registerCallBack(() -> { - updateContainerState(containerID, - HddsProtos.LifeCycleEvent.TIMEOUT); - return null; - }); - break; - case CREATED: - // Release the lease on container - containerLeaseManager.release(containerInfo); - break; - case FINALIZE: - // TODO: we don't need a lease manager here for closing as the - // container report will include the container state after HDFS-13008 - // If a client failed to update the container close state, DN container - // report from 3 DNs will be used to close the container eventually. - break; - case CLOSE: - break; - case UPDATE: - break; - case DELETE: - break; - case TIMEOUT: - break; - case CLEANUP: - break; - default: - throw new SCMException("Unsupported container LifeCycleEvent.", - FAILED_TO_CHANGE_CONTAINER_STATE); - } - // If the below updateContainerState call fails, we should revert the - // changes made in switch case. - // Like releasing the lease in case of BEGIN_CREATE. - ContainerInfo updatedContainer = containerStateManager - .updateContainerState(containerInfo, event); - if (!updatedContainer.isContainerOpen()) { - pipelineSelector.removeContainerFromPipeline( - containerInfo.getPipelineID(), containerID); - } - containerStore.put(dbKey, updatedContainer.getProtobuf().toByteArray()); - return updatedContainer.getState(); - } catch (LeaseException e) { - throw new IOException("Lease Exception.", e); - } finally { - lock.unlock(); - } - } - - /** - * Update deleteTransactionId according to deleteTransactionMap. - * - * @param deleteTransactionMap Maps the containerId to latest delete - * transaction id for the container. - * @throws IOException - */ - public void updateDeleteTransactionId(Map deleteTransactionMap) - throws IOException { - if (deleteTransactionMap == null) { - return; - } - - lock.lock(); - try { - BatchOperation batch = new BatchOperation(); - for (Map.Entry entry : deleteTransactionMap.entrySet()) { - long containerID = entry.getKey(); - byte[] dbKey = Longs.toByteArray(containerID); - byte[] containerBytes = containerStore.get(dbKey); - if (containerBytes == null) { - throw new SCMException( - "Failed to increment number of deleted blocks for container " - + containerID + ", reason : " + "container doesn't exist.", - SCMException.ResultCodes.FAILED_TO_FIND_CONTAINER); - } - ContainerInfo containerInfo = ContainerInfo.fromProtobuf( - HddsProtos.SCMContainerInfo.parseFrom(containerBytes)); - containerInfo.updateDeleteTransactionId(entry.getValue()); - batch.put(dbKey, containerInfo.getProtobuf().toByteArray()); - } - containerStore.writeBatch(batch); - containerStateManager - .updateDeleteTransactionId(deleteTransactionMap); - } finally { - lock.unlock(); - } - } - - /** - * Returns the container State Manager. - * - * @return ContainerStateManager - */ - @Override - public ContainerStateManager getStateManager() { - return containerStateManager; - } - - /** - * Return a container matching the attributes specified. - * - * @param sizeRequired - Space needed in the Container. - * @param owner - Owner of the container - A specific nameservice. - * @param type - Replication Type {StandAlone, Ratis} - * @param factor - Replication Factor {ONE, THREE} - * @param state - State of the Container-- {Open, Allocated etc.} - * @return ContainerInfo, null if there is no match found. - */ - public ContainerWithPipeline getMatchingContainerWithPipeline( - final long sizeRequired, String owner, ReplicationType type, - ReplicationFactor factor, LifeCycleState state) throws IOException { - ContainerInfo containerInfo = getStateManager() - .getMatchingContainer(sizeRequired, owner, type, factor, state); - if (containerInfo == null) { - return null; - } - Pipeline pipeline = pipelineSelector - .getPipeline(containerInfo.getPipelineID()); - return new ContainerWithPipeline(containerInfo, pipeline); - } - - /** - * Process container report from Datanode. - *

- * Processing follows a very simple logic for time being. - *

- * 1. Datanodes report the current State -- denoted by the datanodeState - *

- * 2. We are the older SCM state from the Database -- denoted by - * the knownState. - *

- * 3. We copy the usage etc. from currentState to newState and log that - * newState to the DB. This allows us SCM to bootup again and read the - * state of the world from the DB, and then reconcile the state from - * container reports, when they arrive. - * - * @param reports Container report - */ - @Override - public void processContainerReports(DatanodeDetails datanodeDetails, - ContainerReportsProto reports, boolean isRegisterCall) - throws IOException { - List - containerInfos = reports.getReportsList(); - PendingDeleteStatusList pendingDeleteStatusList = - new PendingDeleteStatusList(datanodeDetails); - for (StorageContainerDatanodeProtocolProtos.ContainerInfo contInfo : - containerInfos) { - // Update replica info during registration process. - if (isRegisterCall) { - try { - getStateManager().addContainerReplica(ContainerID. - valueof(contInfo.getContainerID()), datanodeDetails); - } catch (Exception ex) { - // Continue to next one after logging the error. - LOG.error("Error while adding replica for containerId {}.", - contInfo.getContainerID(), ex); - } - } - byte[] dbKey = Longs.toByteArray(contInfo.getContainerID()); - lock.lock(); - try { - byte[] containerBytes = containerStore.get(dbKey); - if (containerBytes != null) { - HddsProtos.SCMContainerInfo knownState = - HddsProtos.SCMContainerInfo.PARSER.parseFrom(containerBytes); - - if (knownState.getState() == LifeCycleState.CLOSING - && contInfo.getState() == LifeCycleState.CLOSED) { - - updateContainerState(contInfo.getContainerID(), - LifeCycleEvent.CLOSE); - - //reread the container - knownState = - HddsProtos.SCMContainerInfo.PARSER - .parseFrom(containerStore.get(dbKey)); - } - - HddsProtos.SCMContainerInfo newState = - reconcileState(contInfo, knownState, datanodeDetails); - - if (knownState.getDeleteTransactionId() > contInfo - .getDeleteTransactionId()) { - pendingDeleteStatusList - .addPendingDeleteStatus(contInfo.getDeleteTransactionId(), - knownState.getDeleteTransactionId(), - knownState.getContainerID()); - } - - // FIX ME: This can be optimized, we write twice to memory, where a - // single write would work well. - // - // We need to write this to DB again since the closed only write - // the updated State. - containerStore.put(dbKey, newState.toByteArray()); - - } else { - // Container not found in our container db. - LOG.error("Error while processing container report from datanode :" + - " {}, for container: {}, reason: container doesn't exist in" + - "container database.", datanodeDetails, - contInfo.getContainerID()); - } - } finally { - lock.unlock(); - } - } - if (pendingDeleteStatusList.getNumPendingDeletes() > 0) { - eventPublisher.fireEvent(SCMEvents.PENDING_DELETE_STATUS, - pendingDeleteStatusList); - } - - } - - /** - * Reconciles the state from Datanode with the state in SCM. - * - * @param datanodeState - State from the Datanode. - * @param knownState - State inside SCM. - * @param dnDetails - * @return new SCM State for this container. - */ - private HddsProtos.SCMContainerInfo reconcileState( - StorageContainerDatanodeProtocolProtos.ContainerInfo datanodeState, - SCMContainerInfo knownState, DatanodeDetails dnDetails) { - HddsProtos.SCMContainerInfo.Builder builder = - HddsProtos.SCMContainerInfo.newBuilder(); - builder.setContainerID(knownState.getContainerID()) - .setPipelineID(knownState.getPipelineID()) - .setReplicationType(knownState.getReplicationType()) - .setReplicationFactor(knownState.getReplicationFactor()); - - // TODO: If current state doesn't have this DN in list of DataNodes with - // replica then add it in list of replicas. - - // If used size is greater than allocated size, we will be updating - // allocated size with used size. This update is done as a fallback - // mechanism in case SCM crashes without properly updating allocated - // size. Correct allocated value will be updated by - // ContainerStateManager during SCM shutdown. - long usedSize = datanodeState.getUsed(); - long allocated = knownState.getAllocatedBytes() > usedSize ? - knownState.getAllocatedBytes() : usedSize; - builder.setAllocatedBytes(allocated) - .setUsedBytes(usedSize) - .setNumberOfKeys(datanodeState.getKeyCount()) - .setState(knownState.getState()) - .setStateEnterTime(knownState.getStateEnterTime()) - .setContainerID(knownState.getContainerID()) - .setDeleteTransactionId(knownState.getDeleteTransactionId()); - if (knownState.getOwner() != null) { - builder.setOwner(knownState.getOwner()); - } - return builder.build(); - } - - - /** - * In Container is in closed state, if it is in closed, Deleting or Deleted - * State. - * - * @param info - ContainerInfo. - * @return true if is in open state, false otherwise - */ - private boolean shouldClose(ContainerInfo info) { - return info.getState() == HddsProtos.LifeCycleState.OPEN; - } - - private boolean isClosed(ContainerInfo info) { - return info.getState() == HddsProtos.LifeCycleState.CLOSED; - } - - /** - * Closes this stream and releases any system resources associated with it. - * If the stream is - * already closed then invoking this method has no effect. - *

- *

As noted in {@link AutoCloseable#close()}, cases where the close may - * fail require careful - * attention. It is strongly advised to relinquish the underlying resources - * and to internally - * mark the {@code Closeable} as closed, prior to throwing the - * {@code IOException}. - * - * @throws IOException if an I/O error occurs - */ - @Override - public void close() throws IOException { - if (containerLeaseManager != null) { - containerLeaseManager.shutdown(); - } - if (containerStateManager != null) { - flushContainerInfo(); - containerStateManager.close(); - } - if (containerStore != null) { - containerStore.close(); - } - - if (pipelineSelector != null) { - pipelineSelector.shutdown(); - } - } - - /** - * Since allocatedBytes of a container is only in memory, stored in - * containerStateManager, when closing ContainerMapping, we need to update - * this in the container store. - * - * @throws IOException on failure. - */ - @VisibleForTesting - public void flushContainerInfo() throws IOException { - List containers = containerStateManager.getAllContainers(); - List failedContainers = new ArrayList<>(); - for (ContainerInfo info : containers) { - // even if some container updated failed, others can still proceed - try { - byte[] dbKey = Longs.toByteArray(info.getContainerID()); - byte[] containerBytes = containerStore.get(dbKey); - // TODO : looks like when a container is deleted, the container is - // removed from containerStore but not containerStateManager, so it can - // return info of a deleted container. may revisit this in the future, - // for now, just skip a not-found container - if (containerBytes != null) { - containerStore.put(dbKey, info.getProtobuf().toByteArray()); - } else { - LOG.debug("Container state manager has container {} but not found " + - "in container store, a deleted container?", - info.getContainerID()); - } - } catch (IOException ioe) { - failedContainers.add(info.getContainerID()); - } - } - if (!failedContainers.isEmpty()) { - throw new IOException("Error in flushing container info from container " + - "state manager: " + failedContainers); - } - } - - @VisibleForTesting - public MetadataStore getContainerStore() { - return containerStore; - } - - public PipelineSelector getPipelineSelector() { - return pipelineSelector; - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerReportHandler.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerReportHandler.java deleted file mode 100644 index 71935f0aa25..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerReportHandler.java +++ /dev/null @@ -1,150 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.container; - -import java.io.IOException; -import java.util.Set; -import java.util.stream.Collectors; - -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos; -import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.ContainerReportsProto; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo; -import org.apache.hadoop.hdds.scm.container.replication.ReplicationActivityStatus; -import org.apache.hadoop.hdds.scm.container.replication.ReplicationRequest; -import org.apache.hadoop.hdds.scm.events.SCMEvents; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.hdds.scm.node.NodeManager; -import org.apache.hadoop.hdds.scm.node.states.ReportResult; -import org.apache.hadoop.hdds.scm.server.SCMDatanodeHeartbeatDispatcher.ContainerReportFromDatanode; -import org.apache.hadoop.hdds.server.events.EventHandler; -import org.apache.hadoop.hdds.server.events.EventPublisher; - -import com.google.common.base.Preconditions; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Handles container reports from datanode. - */ -public class ContainerReportHandler implements - EventHandler { - - private static final Logger LOG = - LoggerFactory.getLogger(ContainerReportHandler.class); - - private final NodeManager nodeManager; - - private final Mapping containerMapping; - - private ContainerStateManager containerStateManager; - - private ReplicationActivityStatus replicationStatus; - - public ContainerReportHandler(Mapping containerMapping, - NodeManager nodeManager, - ReplicationActivityStatus replicationActivityStatus) { - Preconditions.checkNotNull(containerMapping); - Preconditions.checkNotNull(nodeManager); - Preconditions.checkNotNull(replicationActivityStatus); - this.containerStateManager = containerMapping.getStateManager(); - this.nodeManager = nodeManager; - this.containerMapping = containerMapping; - this.replicationStatus = replicationActivityStatus; - } - - @Override - public void onMessage(ContainerReportFromDatanode containerReportFromDatanode, - EventPublisher publisher) { - - DatanodeDetails datanodeOrigin = - containerReportFromDatanode.getDatanodeDetails(); - - ContainerReportsProto containerReport = - containerReportFromDatanode.getReport(); - try { - - //update state in container db and trigger close container events - containerMapping - .processContainerReports(datanodeOrigin, containerReport, false); - - Set containerIds = containerReport.getReportsList().stream() - .map(StorageContainerDatanodeProtocolProtos - .ContainerInfo::getContainerID) - .map(ContainerID::new) - .collect(Collectors.toSet()); - - ReportResult reportResult = nodeManager - .processContainerReport(datanodeOrigin.getUuid(), containerIds); - - //we have the report, so we can update the states for the next iteration. - nodeManager - .setContainersForDatanode(datanodeOrigin.getUuid(), containerIds); - - for (ContainerID containerID : reportResult.getMissingEntries()) { - containerStateManager - .removeContainerReplica(containerID, datanodeOrigin); - checkReplicationState(containerID, publisher); - } - - for (ContainerID containerID : reportResult.getNewEntries()) { - containerStateManager.addContainerReplica(containerID, datanodeOrigin); - checkReplicationState(containerID, publisher); - } - - } catch (IOException e) { - //TODO: stop all the replication? - LOG.error("Error on processing container report from datanode {}", - datanodeOrigin, e); - } - - } - - private void checkReplicationState(ContainerID containerID, - EventPublisher publisher) - throws SCMException { - ContainerInfo container = containerStateManager.getContainer(containerID); - - if (container == null) { - //warning unknown container - LOG.warn( - "Container is missing from containerStateManager. Can't request " - + "replication. {}", - containerID); - return; - } - if (container.isContainerOpen()) { - return; - } - - ReplicationRequest replicationState = - containerStateManager.checkReplicationState(containerID); - if (replicationState != null) { - if (replicationStatus.isReplicationEnabled()) { - publisher.fireEvent(SCMEvents.REPLICATE_CONTAINER, - replicationState); - } else { - LOG.warn( - "Over/under replicated container but the replication is not " - + "(yet) enabled: " - + replicationState.toString()); - } - } - - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerStateManager.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerStateManager.java deleted file mode 100644 index 930c098f0f5..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerStateManager.java +++ /dev/null @@ -1,570 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.hdds.scm.container; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.conf.StorageUnit; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.scm.ScmConfigKeys; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerWithPipeline; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.scm.container.replication.ReplicationRequest; -import org.apache.hadoop.hdds.scm.container.states.ContainerState; -import org.apache.hadoop.hdds.scm.container.states.ContainerStateMap; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.hdds.scm.pipelines.PipelineSelector; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.LifeCycleEvent; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.LifeCycleState; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationFactor; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationType; -import org.apache.hadoop.ozone.common.statemachine - .InvalidStateTransitionException; -import org.apache.hadoop.ozone.common.statemachine.StateMachine; -import org.apache.hadoop.util.Time; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.Closeable; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.NavigableSet; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicLong; - -import static org.apache.hadoop.hdds.scm.exceptions.SCMException.ResultCodes - .FAILED_TO_CHANGE_CONTAINER_STATE; - -/** - * A container state manager keeps track of container states and returns - * containers that match various queries. - *

- * This state machine is driven by a combination of server and client actions. - *

- * This is how a create container happens: 1. When a container is created, the - * Server(or SCM) marks that Container as ALLOCATED state. In this state, SCM - * has chosen a pipeline for container to live on. However, the container is not - * created yet. This container along with the pipeline is returned to the - * client. - *

- * 2. The client when it sees the Container state as ALLOCATED understands that - * container needs to be created on the specified pipeline. The client lets the - * SCM know that saw this flag and is initiating the on the data nodes. - *

- * This is done by calling into notifyObjectCreation(ContainerName, - * BEGIN_CREATE) flag. When SCM gets this call, SCM puts the container state - * into CREATING. All this state means is that SCM told Client to create a - * container and client saw that request. - *

- * 3. Then client makes calls to datanodes directly, asking the datanodes to - * create the container. This is done with the help of pipeline that supports - * this container. - *

- * 4. Once the creation of the container is complete, the client will make - * another call to the SCM, this time specifying the containerName and the - * COMPLETE_CREATE as the Event. - *

- * 5. With COMPLETE_CREATE event, the container moves to an Open State. This is - * the state when clients can write to a container. - *

- * 6. If the client does not respond with the COMPLETE_CREATE event with a - * certain time, the state machine times out and triggers a delete operation of - * the container. - *

- * Please see the function initializeStateMachine below to see how this looks in - * code. - *

- * Reusing existing container : - *

- * The create container call is not made all the time, the system tries to use - * open containers as much as possible. So in those cases, it looks thru the - * list of open containers and will return containers that match the specific - * signature. - *

- * Please note : Logically there are 3 separate state machines in the case of - * containers. - *

- * The Create State Machine -- Commented extensively above. - *

- * Open/Close State Machine - Once the container is in the Open State, - * eventually it will be closed, once sufficient data has been written to it. - *

- * TimeOut Delete Container State Machine - if the container creating times out, - * then Container State manager decides to delete the container. - */ -public class ContainerStateManager implements Closeable { - private static final Logger LOG = - LoggerFactory.getLogger(ContainerStateManager.class); - - private final StateMachine stateMachine; - - private final long containerSize; - private final ConcurrentHashMap lastUsedMap; - private final ContainerStateMap containers; - private final AtomicLong containerCount; - - /** - * Constructs a Container State Manager that tracks all containers owned by - * SCM for the purpose of allocation of blocks. - *

- * TODO : Add Container Tags so we know which containers are owned by SCM. - */ - @SuppressWarnings("unchecked") - public ContainerStateManager(Configuration configuration, - Mapping containerMapping, PipelineSelector pipelineSelector) { - - // Initialize the container state machine. - Set finalStates = new HashSet(); - - // These are the steady states of a container. - finalStates.add(LifeCycleState.OPEN); - finalStates.add(LifeCycleState.CLOSED); - finalStates.add(LifeCycleState.DELETED); - - this.stateMachine = new StateMachine<>(LifeCycleState.ALLOCATED, - finalStates); - initializeStateMachine(); - - this.containerSize = (long) configuration.getStorageSize( - ScmConfigKeys.OZONE_SCM_CONTAINER_SIZE, - ScmConfigKeys.OZONE_SCM_CONTAINER_SIZE_DEFAULT, - StorageUnit.BYTES); - - lastUsedMap = new ConcurrentHashMap<>(); - containerCount = new AtomicLong(0); - containers = new ContainerStateMap(); - loadExistingContainers(containerMapping, pipelineSelector); - } - - private void loadExistingContainers(Mapping containerMapping, - PipelineSelector pipelineSelector) { - - List containerList; - try { - containerList = containerMapping.listContainer(0, Integer.MAX_VALUE); - - // if there are no container to load, let us return. - if (containerList == null || containerList.size() == 0) { - LOG.info("No containers to load for this cluster."); - return; - } - } catch (IOException e) { - if (!e.getMessage().equals("No container exists in current db")) { - LOG.error("Could not list the containers", e); - } - return; - } - - try { - long maxID = 0; - for (ContainerInfo container : containerList) { - containers.addContainer(container); - pipelineSelector.addContainerToPipeline( - container.getPipelineID(), container.getContainerID()); - - if (maxID < container.getContainerID()) { - maxID = container.getContainerID(); - } - - containerCount.set(maxID); - } - } catch (SCMException ex) { - LOG.error("Unable to create a container information. ", ex); - // Fix me, what is the proper shutdown procedure for SCM ?? - // System.exit(1) // Should we exit here? - } - } - - /** - * Return the info of all the containers kept by the in-memory mapping. - * - * @return the list of all container info. - */ - public List getAllContainers() { - List list = new ArrayList<>(); - - //No Locking needed since the return value is an immutable map. - containers.getContainerMap().forEach((key, value) -> list.add(value)); - return list; - } - - /* - * - * Event and State Transition Mapping: - * - * State: ALLOCATED ---------------> CREATING - * Event: CREATE - * - * State: CREATING ---------------> OPEN - * Event: CREATED - * - * State: OPEN ---------------> CLOSING - * Event: FINALIZE - * - * State: CLOSING ---------------> CLOSED - * Event: CLOSE - * - * State: CLOSED ----------------> DELETING - * Event: DELETE - * - * State: DELETING ----------------> DELETED - * Event: CLEANUP - * - * State: CREATING ---------------> DELETING - * Event: TIMEOUT - * - * - * Container State Flow: - * - * [ALLOCATED]---->[CREATING]------>[OPEN]-------->[CLOSING]------->[CLOSED] - * (CREATE) | (CREATED) (FINALIZE) (CLOSE) | - * | | - * | | - * |(TIMEOUT) (DELETE)| - * | | - * +-------------> [DELETING] <-------------------+ - * | - * | - * (CLEANUP)| - * | - * [DELETED] - */ - private void initializeStateMachine() { - stateMachine.addTransition(LifeCycleState.ALLOCATED, - LifeCycleState.CREATING, - LifeCycleEvent.CREATE); - - stateMachine.addTransition(LifeCycleState.CREATING, - LifeCycleState.OPEN, - LifeCycleEvent.CREATED); - - stateMachine.addTransition(LifeCycleState.OPEN, - LifeCycleState.CLOSING, - LifeCycleEvent.FINALIZE); - - stateMachine.addTransition(LifeCycleState.CLOSING, - LifeCycleState.CLOSED, - LifeCycleEvent.CLOSE); - - stateMachine.addTransition(LifeCycleState.CLOSED, - LifeCycleState.DELETING, - LifeCycleEvent.DELETE); - - stateMachine.addTransition(LifeCycleState.CREATING, - LifeCycleState.DELETING, - LifeCycleEvent.TIMEOUT); - - stateMachine.addTransition(LifeCycleState.DELETING, - LifeCycleState.DELETED, - LifeCycleEvent.CLEANUP); - } - - /** - * allocates a new container based on the type, replication etc. - * - * @param selector -- Pipeline selector class. - * @param type -- Replication type. - * @param replicationFactor - Replication replicationFactor. - * @return ContainerWithPipeline - * @throws IOException on Failure. - */ - public ContainerWithPipeline allocateContainer(PipelineSelector selector, - HddsProtos.ReplicationType type, - HddsProtos.ReplicationFactor replicationFactor, String owner) - throws IOException { - - Pipeline pipeline = selector.getReplicationPipeline(type, - replicationFactor); - - Preconditions.checkNotNull(pipeline, "Pipeline type=%s/" - + "replication=%s couldn't be found for the new container. " - + "Do you have enough nodes?", type, replicationFactor); - - long containerID = containerCount.incrementAndGet(); - ContainerInfo containerInfo = new ContainerInfo.Builder() - .setState(HddsProtos.LifeCycleState.ALLOCATED) - .setPipelineID(pipeline.getId()) - // This is bytes allocated for blocks inside container, not the - // container size - .setAllocatedBytes(0) - .setUsedBytes(0) - .setNumberOfKeys(0) - .setStateEnterTime(Time.monotonicNow()) - .setOwner(owner) - .setContainerID(containerID) - .setDeleteTransactionId(0) - .setReplicationFactor(replicationFactor) - .setReplicationType(pipeline.getType()) - .build(); - selector.addContainerToPipeline(pipeline.getId(), containerID); - Preconditions.checkNotNull(containerInfo); - containers.addContainer(containerInfo); - LOG.trace("New container allocated: {}", containerInfo); - return new ContainerWithPipeline(containerInfo, pipeline); - } - - /** - * Update the Container State to the next state. - * - * @param info - ContainerInfo - * @param event - LifeCycle Event - * @return Updated ContainerInfo. - * @throws SCMException on Failure. - */ - public ContainerInfo updateContainerState(ContainerInfo - info, HddsProtos.LifeCycleEvent event) throws SCMException { - LifeCycleState newState; - try { - newState = this.stateMachine.getNextState(info.getState(), event); - } catch (InvalidStateTransitionException ex) { - String error = String.format("Failed to update container state %s, " + - "reason: invalid state transition from state: %s upon " + - "event: %s.", - info.getContainerID(), info.getState(), event); - LOG.error(error); - throw new SCMException(error, FAILED_TO_CHANGE_CONTAINER_STATE); - } - - // This is a post condition after executing getNextState. - Preconditions.checkNotNull(newState); - containers.updateState(info, info.getState(), newState); - return containers.getContainerInfo(info); - } - - /** - * Update the container State. - * @param info - Container Info - * @return ContainerInfo - * @throws SCMException - on Error. - */ - public ContainerInfo updateContainerInfo(ContainerInfo info) - throws SCMException { - containers.updateContainerInfo(info); - return containers.getContainerInfo(info); - } - - /** - * Update deleteTransactionId for a container. - * - * @param deleteTransactionMap maps containerId to its new - * deleteTransactionID - */ - public void updateDeleteTransactionId(Map deleteTransactionMap) { - for (Map.Entry entry : deleteTransactionMap.entrySet()) { - containers.getContainerMap().get(ContainerID.valueof(entry.getKey())) - .updateDeleteTransactionId(entry.getValue()); - } - } - - /** - * Return a container matching the attributes specified. - * - * @param size - Space needed in the Container. - * @param owner - Owner of the container - A specific nameservice. - * @param type - Replication Type {StandAlone, Ratis} - * @param factor - Replication Factor {ONE, THREE} - * @param state - State of the Container-- {Open, Allocated etc.} - * @return ContainerInfo, null if there is no match found. - */ - public ContainerInfo getMatchingContainer(final long size, - String owner, ReplicationType type, ReplicationFactor factor, - LifeCycleState state) { - - // Find containers that match the query spec, if no match return null. - NavigableSet matchingSet = - containers.getMatchingContainerIDs(state, owner, factor, type); - if (matchingSet == null || matchingSet.size() == 0) { - return null; - } - - // Get the last used container and find container above the last used - // container ID. - ContainerState key = new ContainerState(owner, type, factor); - ContainerID lastID = lastUsedMap.get(key); - if (lastID == null) { - lastID = matchingSet.first(); - } - - // There is a small issue here. The first time, we will skip the first - // container. But in most cases it will not matter. - NavigableSet resultSet = matchingSet.tailSet(lastID, false); - if (resultSet.size() == 0) { - resultSet = matchingSet; - } - - ContainerInfo selectedContainer = - findContainerWithSpace(size, resultSet, owner); - if (selectedContainer == null) { - - // If we did not find any space in the tailSet, we need to look for - // space in the headset, we need to pass true to deal with the - // situation that we have a lone container that has space. That is we - // ignored the last used container under the assumption we can find - // other containers with space, but if have a single container that is - // not true. Hence we need to include the last used container as the - // last element in the sorted set. - - resultSet = matchingSet.headSet(lastID, true); - selectedContainer = findContainerWithSpace(size, resultSet, owner); - } - // Update the allocated Bytes on this container. - if (selectedContainer != null) { - selectedContainer.updateAllocatedBytes(size); - } - return selectedContainer; - - } - - private ContainerInfo findContainerWithSpace(long size, - NavigableSet searchSet, String owner) { - // Get the container with space to meet our request. - for (ContainerID id : searchSet) { - ContainerInfo containerInfo = containers.getContainerInfo(id); - if (containerInfo.getAllocatedBytes() + size <= this.containerSize) { - containerInfo.updateLastUsedTime(); - - ContainerState key = new ContainerState(owner, - containerInfo.getReplicationType(), - containerInfo.getReplicationFactor()); - lastUsedMap.put(key, containerInfo.containerID()); - return containerInfo; - } - } - return null; - } - - /** - * Returns a set of ContainerIDs that match the Container. - * - * @param owner Owner of the Containers. - * @param type - Replication Type of the containers - * @param factor - Replication factor of the containers. - * @param state - Current State, like Open, Close etc. - * @return Set of containers that match the specific query parameters. - */ - public NavigableSet getMatchingContainerIDs( - String owner, ReplicationType type, ReplicationFactor factor, - LifeCycleState state) { - return containers.getMatchingContainerIDs(state, owner, - factor, type); - } - - /** - * Returns the containerInfo with pipeline for the given container id. - * @param selector -- Pipeline selector class. - * @param containerID id of the container - * @return ContainerInfo containerInfo - * @throws IOException - */ - public ContainerWithPipeline getContainer(PipelineSelector selector, - ContainerID containerID) { - ContainerInfo info = containers.getContainerInfo(containerID.getId()); - Pipeline pipeline = selector.getPipeline(info.getPipelineID()); - return new ContainerWithPipeline(info, pipeline); - } - - /** - * Returns the containerInfo for the given container id. - * @param containerID id of the container - * @return ContainerInfo containerInfo - * @throws IOException - */ - public ContainerInfo getContainer(ContainerID containerID) { - return containers.getContainerInfo(containerID); - } - - @Override - public void close() throws IOException { - } - - /** - * Returns the latest list of DataNodes where replica for given containerId - * exist. Throws an SCMException if no entry is found for given containerId. - * - * @param containerID - * @return Set - */ - public Set getContainerReplicas(ContainerID containerID) - throws SCMException { - return containers.getContainerReplicas(containerID); - } - - /** - * Add a container Replica for given DataNode. - * - * @param containerID - * @param dn - */ - public void addContainerReplica(ContainerID containerID, DatanodeDetails dn) { - containers.addContainerReplica(containerID, dn); - } - - /** - * Remove a container Replica for given DataNode. - * - * @param containerID - * @param dn - * @return True of dataNode is removed successfully else false. - */ - public boolean removeContainerReplica(ContainerID containerID, - DatanodeDetails dn) throws SCMException { - return containers.removeContainerReplica(containerID, dn); - } - - /** - * Compare the existing replication number with the expected one. - */ - public ReplicationRequest checkReplicationState(ContainerID containerID) - throws SCMException { - int existingReplicas = getContainerReplicas(containerID).size(); - int expectedReplicas = getContainer(containerID) - .getReplicationFactor().getNumber(); - if (existingReplicas != expectedReplicas) { - return new ReplicationRequest(containerID.getId(), existingReplicas, - expectedReplicas); - } - return null; - } - - /** - * Checks if the container is open. - */ - public boolean isOpen(ContainerID containerID) { - Preconditions.checkNotNull(containerID); - ContainerInfo container = Preconditions - .checkNotNull(getContainer(containerID), - "Container can't be found " + containerID); - return container.isContainerOpen(); - } - - @VisibleForTesting - public ContainerStateMap getContainerStateMap() { - return containers; - } - -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/Mapping.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/Mapping.java deleted file mode 100644 index 5ed80cb47f3..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/Mapping.java +++ /dev/null @@ -1,141 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.scm.container; - -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.LifeCycleState; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationFactor; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationType; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerWithPipeline; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerReportsProto; -import org.apache.hadoop.hdds.scm.pipelines.PipelineSelector; - -import java.io.Closeable; -import java.io.IOException; -import java.util.List; -import java.util.Map; - -/** - * Mapping class contains the mapping from a name to a pipeline mapping. This is - * used by SCM when allocating new locations and when looking up a key. - */ -public interface Mapping extends Closeable { - /** - * Returns the ContainerInfo from the container ID. - * - * @param containerID - ID of container. - * @return - ContainerInfo such as creation state and the pipeline. - * @throws IOException - */ - ContainerInfo getContainer(long containerID) throws IOException; - - /** - * Returns the ContainerInfo from the container ID. - * - * @param containerID - ID of container. - * @return - ContainerWithPipeline such as creation state and the pipeline. - * @throws IOException - */ - ContainerWithPipeline getContainerWithPipeline(long containerID) - throws IOException; - - /** - * Returns containers under certain conditions. - * Search container IDs from start ID(exclusive), - * The max size of the searching range cannot exceed the - * value of count. - * - * @param startContainerID start containerID, >=0, - * start searching at the head if 0. - * @param count count must be >= 0 - * Usually the count will be replace with a very big - * value instead of being unlimited in case the db is very big. - * - * @return a list of container. - * @throws IOException - */ - List listContainer(long startContainerID, int count) - throws IOException; - - /** - * Allocates a new container for a given keyName and replication factor. - * - * @param replicationFactor - replication factor of the container. - * @param owner - * @return - ContainerWithPipeline. - * @throws IOException - */ - ContainerWithPipeline allocateContainer(HddsProtos.ReplicationType type, - HddsProtos.ReplicationFactor replicationFactor, String owner) - throws IOException; - - /** - * Deletes a container from SCM. - * - * @param containerID - Container ID - * @throws IOException - */ - void deleteContainer(long containerID) throws IOException; - - /** - * Update container state. - * @param containerID - Container ID - * @param event - container life cycle event - * @return - new container state - * @throws IOException - */ - HddsProtos.LifeCycleState updateContainerState(long containerID, - HddsProtos.LifeCycleEvent event) throws IOException; - - /** - * Returns the container State Manager. - * @return ContainerStateManager - */ - ContainerStateManager getStateManager(); - - /** - * Process container report from Datanode. - * - * @param reports Container report - */ - void processContainerReports(DatanodeDetails datanodeDetails, - ContainerReportsProto reports, boolean isRegisterCall) - throws IOException; - - /** - * Update deleteTransactionId according to deleteTransactionMap. - * - * @param deleteTransactionMap Maps the containerId to latest delete - * transaction id for the container. - * @throws IOException - */ - void updateDeleteTransactionId(Map deleteTransactionMap) - throws IOException; - - /** - * Returns the ContainerWithPipeline. - * @return NodeManager - */ - ContainerWithPipeline getMatchingContainerWithPipeline(long size, - String owner, ReplicationType type, ReplicationFactor factor, - LifeCycleState state) throws IOException; - - PipelineSelector getPipelineSelector(); -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/closer/package-info.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/closer/package-info.java deleted file mode 100644 index ee02bbd88f2..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/closer/package-info.java +++ /dev/null @@ -1,23 +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 - * - * 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. - * - */ - -/** - * This package has class that close a container. That is move a container from - * open state to close state. - */ -package org.apache.hadoop.hdds.scm.container.closer; \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/package-info.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/package-info.java deleted file mode 100644 index 3f8d05681bd..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/package-info.java +++ /dev/null @@ -1,22 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.hdds.scm.container; -/** - * This package contains routines to manage the container location and - * mapping inside SCM - */ \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/algorithms/ContainerPlacementPolicy.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/algorithms/ContainerPlacementPolicy.java deleted file mode 100644 index 3336c8e80e7..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/algorithms/ContainerPlacementPolicy.java +++ /dev/null @@ -1,44 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.hdds.scm.container.placement.algorithms; - -import org.apache.hadoop.hdds.protocol.DatanodeDetails; - -import java.io.IOException; -import java.util.List; - -/** - * A ContainerPlacementPolicy support choosing datanodes to build replication - * pipeline with specified constraints. - */ -public interface ContainerPlacementPolicy { - - /** - * Given the replication factor and size required, return set of datanodes - * that satisfy the nodes and size requirement. - * - * @param excludedNodes - list of nodes to be excluded. - * @param nodesRequired - number of datanodes required. - * @param sizeRequired - size required for the container or block. - * @return list of datanodes chosen. - * @throws IOException - */ - List chooseDatanodes(List excludedNodes, - int nodesRequired, long sizeRequired) - throws IOException; -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/algorithms/SCMCommonPolicy.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/algorithms/SCMCommonPolicy.java deleted file mode 100644 index 60861b770c8..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/algorithms/SCMCommonPolicy.java +++ /dev/null @@ -1,201 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.hdds.scm.container.placement.algorithms; - -import com.google.common.annotations.VisibleForTesting; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.scm.container.placement.metrics.SCMNodeMetric; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.hdds.scm.node.NodeManager; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.LinkedList; -import java.util.List; -import java.util.Random; -import java.util.stream.Collectors; - -/** - * SCM CommonPolicy implements a set of invariants which are common - * for all container placement policies, acts as the repository of helper - * functions which are common to placement policies. - */ -public abstract class SCMCommonPolicy implements ContainerPlacementPolicy { - @VisibleForTesting - static final Logger LOG = - LoggerFactory.getLogger(SCMCommonPolicy.class); - private final NodeManager nodeManager; - private final Random rand; - private final Configuration conf; - - /** - * Constructs SCM Common Policy Class. - * - * @param nodeManager NodeManager - * @param conf Configuration class. - */ - public SCMCommonPolicy(NodeManager nodeManager, Configuration conf) { - this.nodeManager = nodeManager; - this.rand = new Random(); - this.conf = conf; - } - - /** - * Return node manager. - * - * @return node manager - */ - public NodeManager getNodeManager() { - return nodeManager; - } - - /** - * Returns the Random Object. - * - * @return rand - */ - public Random getRand() { - return rand; - } - - /** - * Get Config. - * - * @return Configuration - */ - public Configuration getConf() { - return conf; - } - - /** - * Given the replication factor and size required, return set of datanodes - * that satisfy the nodes and size requirement. - *

- * Here are some invariants of container placement. - *

- * 1. We place containers only on healthy nodes. - * 2. We place containers on nodes with enough space for that container. - * 3. if a set of containers are requested, we either meet the required - * number of nodes or we fail that request. - * - * - * @param excludedNodes - datanodes with existing replicas - * @param nodesRequired - number of datanodes required. - * @param sizeRequired - size required for the container or block. - * @return list of datanodes chosen. - * @throws SCMException SCM exception. - */ - - public List chooseDatanodes( - List excludedNodes, - int nodesRequired, final long sizeRequired) throws SCMException { - List healthyNodes = - nodeManager.getNodes(HddsProtos.NodeState.HEALTHY); - healthyNodes.removeAll(excludedNodes); - String msg; - if (healthyNodes.size() == 0) { - msg = "No healthy node found to allocate container."; - LOG.error(msg); - throw new SCMException(msg, SCMException.ResultCodes - .FAILED_TO_FIND_HEALTHY_NODES); - } - - if (healthyNodes.size() < nodesRequired) { - msg = String.format("Not enough healthy nodes to allocate container. %d " - + " datanodes required. Found %d", - nodesRequired, healthyNodes.size()); - LOG.error(msg); - throw new SCMException(msg, - SCMException.ResultCodes.FAILED_TO_FIND_SUITABLE_NODE); - } - List healthyList = healthyNodes.stream().filter(d -> - hasEnoughSpace(d, sizeRequired)).collect(Collectors.toList()); - - if (healthyList.size() < nodesRequired) { - msg = String.format("Unable to find enough nodes that meet the space " + - "requirement of %d bytes in healthy node set." + - " Nodes required: %d Found: %d", - sizeRequired, nodesRequired, healthyList.size()); - LOG.error(msg); - throw new SCMException(msg, - SCMException.ResultCodes.FAILED_TO_FIND_NODES_WITH_SPACE); - } - - return healthyList; - } - - /** - * Returns true if this node has enough space to meet our requirement. - * - * @param datanodeDetails DatanodeDetails - * @return true if we have enough space. - */ - private boolean hasEnoughSpace(DatanodeDetails datanodeDetails, - long sizeRequired) { - SCMNodeMetric nodeMetric = nodeManager.getNodeStat(datanodeDetails); - return (nodeMetric != null) && (nodeMetric.get() != null) - && nodeMetric.get().getRemaining().hasResources(sizeRequired); - } - - /** - * This function invokes the derived classes chooseNode Function to build a - * list of nodes. Then it verifies that invoked policy was able to return - * expected number of nodes. - * - * @param nodesRequired - Nodes Required - * @param healthyNodes - List of Nodes in the result set. - * @return List of Datanodes that can be used for placement. - * @throws SCMException - */ - public List getResultSet( - int nodesRequired, List healthyNodes) - throws SCMException { - List results = new LinkedList<>(); - for (int x = 0; x < nodesRequired; x++) { - // invoke the choose function defined in the derived classes. - DatanodeDetails nodeId = chooseNode(healthyNodes); - if (nodeId != null) { - results.add(nodeId); - } - } - - if (results.size() < nodesRequired) { - LOG.error("Unable to find the required number of healthy nodes that " + - "meet the criteria. Required nodes: {}, Found nodes: {}", - nodesRequired, results.size()); - throw new SCMException("Unable to find required number of nodes.", - SCMException.ResultCodes.FAILED_TO_FIND_SUITABLE_NODE); - } - return results; - } - - /** - * Choose a datanode according to the policy, this function is implemented - * by the actual policy class. For example, PlacementCapacity or - * PlacementRandom. - * - * @param healthyNodes - Set of healthy nodes we can choose from. - * @return DatanodeDetails - */ - public abstract DatanodeDetails chooseNode( - List healthyNodes); - - -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/algorithms/SCMContainerPlacementCapacity.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/algorithms/SCMContainerPlacementCapacity.java deleted file mode 100644 index 8df8f6e034d..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/algorithms/SCMContainerPlacementCapacity.java +++ /dev/null @@ -1,137 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.hdds.scm.container.placement.algorithms; - -import java.util.List; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.scm.container.placement.metrics.SCMNodeMetric; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.hdds.scm.node.NodeManager; - -import com.google.common.annotations.VisibleForTesting; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Container placement policy that randomly choose datanodes with remaining - * space to satisfy the size constraints. - *

- * The Algorithm is as follows, Pick 2 random nodes from a given pool of nodes - * and then pick the node which lower utilization. This leads to a higher - * probability of nodes with lower utilization to be picked. - *

- * For those wondering why we choose two nodes randomly and choose the node - * with lower utilization. There are links to this original papers in - * HDFS-11564. - *

- * A brief summary -- We treat the nodes from a scale of lowest utilized to - * highest utilized, there are (s * ( s + 1)) / 2 possibilities to build - * distinct pairs of nodes. There are s - k pairs of nodes in which the rank - * k node is less than the couple. So probability of a picking a node is - * (2 * (s -k)) / (s * (s - 1)). - *

- * In English, There is a much higher probability of picking less utilized nodes - * as compared to nodes with higher utilization since we pick 2 nodes and - * then pick the node with lower utilization. - *

- * This avoids the issue of users adding new nodes into the cluster and HDFS - * sending all traffic to those nodes if we only use a capacity based - * allocation scheme. Unless those nodes are part of the set of the first 2 - * nodes then newer nodes will not be in the running to get the container. - *

- * This leads to an I/O pattern where the lower utilized nodes are favoured - * more than higher utilized nodes, but part of the I/O will still go to the - * older higher utilized nodes. - *

- * With this algorithm in place, our hope is that balancer tool needs to do - * little or no work and the cluster will achieve a balanced distribution - * over time. - */ -public final class SCMContainerPlacementCapacity extends SCMCommonPolicy { - @VisibleForTesting - static final Logger LOG = - LoggerFactory.getLogger(SCMContainerPlacementCapacity.class); - - /** - * Constructs a Container Placement with considering only capacity. - * That is this policy tries to place containers based on node weight. - * - * @param nodeManager Node Manager - * @param conf Configuration - */ - public SCMContainerPlacementCapacity(final NodeManager nodeManager, - final Configuration conf) { - super(nodeManager, conf); - } - - /** - * Called by SCM to choose datanodes. - * - * - * @param excludedNodes - list of the datanodes to exclude. - * @param nodesRequired - number of datanodes required. - * @param sizeRequired - size required for the container or block. - * @return List of datanodes. - * @throws SCMException SCMException - */ - @Override - public List chooseDatanodes( - List excludedNodes, final int nodesRequired, - final long sizeRequired) throws SCMException { - List healthyNodes = - super.chooseDatanodes(excludedNodes, nodesRequired, sizeRequired); - if (healthyNodes.size() == nodesRequired) { - return healthyNodes; - } - return getResultSet(nodesRequired, healthyNodes); - } - - /** - * Find a node from the healthy list and return it after removing it from the - * list that we are operating on. - * - * @param healthyNodes - List of healthy nodes that meet the size - * requirement. - * @return DatanodeDetails that is chosen. - */ - @Override - public DatanodeDetails chooseNode(List healthyNodes) { - int firstNodeNdx = getRand().nextInt(healthyNodes.size()); - int secondNodeNdx = getRand().nextInt(healthyNodes.size()); - - DatanodeDetails datanodeDetails; - // There is a possibility that both numbers will be same. - // if that is so, we just return the node. - if (firstNodeNdx == secondNodeNdx) { - datanodeDetails = healthyNodes.get(firstNodeNdx); - } else { - DatanodeDetails firstNodeDetails = healthyNodes.get(firstNodeNdx); - DatanodeDetails secondNodeDetails = healthyNodes.get(secondNodeNdx); - SCMNodeMetric firstNodeMetric = - getNodeManager().getNodeStat(firstNodeDetails); - SCMNodeMetric secondNodeMetric = - getNodeManager().getNodeStat(secondNodeDetails); - datanodeDetails = firstNodeMetric.isGreater(secondNodeMetric.get()) - ? firstNodeDetails : secondNodeDetails; - } - healthyNodes.remove(datanodeDetails); - return datanodeDetails; - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/algorithms/SCMContainerPlacementRandom.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/algorithms/SCMContainerPlacementRandom.java deleted file mode 100644 index 76702d555ef..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/algorithms/SCMContainerPlacementRandom.java +++ /dev/null @@ -1,92 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.hdds.scm.container.placement.algorithms; - -import com.google.common.annotations.VisibleForTesting; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.hdds.scm.node.NodeManager; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.List; - -/** - * Container placement policy that randomly chooses healthy datanodes. - * This is very similar to current HDFS placement. That is we - * just randomly place containers without any considerations of utilization. - *

- * That means we rely on balancer to achieve even distribution of data. - * Balancer will need to support containers as a feature before this class - * can be practically used. - */ -public final class SCMContainerPlacementRandom extends SCMCommonPolicy - implements ContainerPlacementPolicy { - @VisibleForTesting - static final Logger LOG = - LoggerFactory.getLogger(SCMContainerPlacementRandom.class); - - /** - * Construct a random Block Placement policy. - * - * @param nodeManager nodeManager - * @param conf Config - */ - public SCMContainerPlacementRandom(final NodeManager nodeManager, - final Configuration conf) { - super(nodeManager, conf); - } - - /** - * Choose datanodes called by the SCM to choose the datanode. - * - * - * @param excludedNodes - list of the datanodes to exclude. - * @param nodesRequired - number of datanodes required. - * @param sizeRequired - size required for the container or block. - * @return List of Datanodes. - * @throws SCMException SCMException - */ - @Override - public List chooseDatanodes( - List excludedNodes, final int nodesRequired, - final long sizeRequired) throws SCMException { - List healthyNodes = - super.chooseDatanodes(excludedNodes, nodesRequired, sizeRequired); - - if (healthyNodes.size() == nodesRequired) { - return healthyNodes; - } - return getResultSet(nodesRequired, healthyNodes); - } - - /** - * Just chose a node randomly and remove it from the set of nodes we can - * chose from. - * - * @param healthyNodes - all healthy datanodes. - * @return one randomly chosen datanode that from two randomly chosen datanode - */ - public DatanodeDetails chooseNode(final List healthyNodes) { - DatanodeDetails selectedNode = - healthyNodes.get(getRand().nextInt(healthyNodes.size())); - healthyNodes.remove(selectedNode); - return selectedNode; - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/algorithms/package-info.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/algorithms/package-info.java deleted file mode 100644 index 1cb810dd0e5..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/algorithms/package-info.java +++ /dev/null @@ -1,18 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.scm.container.placement.algorithms; -// Various placement algorithms. \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/ContainerStat.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/ContainerStat.java deleted file mode 100644 index b8e89987638..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/ContainerStat.java +++ /dev/null @@ -1,165 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.container.placement.metrics; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.common.base.Preconditions; -import org.apache.hadoop.ozone.web.utils.JsonUtils; - -import java.io.IOException; - -/** - * This class represents the SCM container stat. - */ -public class ContainerStat { - /** - * The maximum container size. - */ - @JsonProperty("Size") - private LongMetric size; - - /** - * The number of bytes used by the container. - */ - @JsonProperty("Used") - private LongMetric used; - - /** - * The number of keys in the container. - */ - @JsonProperty("KeyCount") - private LongMetric keyCount; - - /** - * The number of bytes read from the container. - */ - @JsonProperty("ReadBytes") - private LongMetric readBytes; - - /** - * The number of bytes write into the container. - */ - @JsonProperty("WriteBytes") - private LongMetric writeBytes; - - /** - * The number of times the container is read. - */ - @JsonProperty("ReadCount") - private LongMetric readCount; - - /** - * The number of times the container is written into. - */ - @JsonProperty("WriteCount") - private LongMetric writeCount; - - public ContainerStat() { - this(0L, 0L, 0L, 0L, 0L, 0L, 0L); - } - - public ContainerStat(long size, long used, long keyCount, long readBytes, - long writeBytes, long readCount, long writeCount) { - Preconditions.checkArgument(size >= 0, - "Container size cannot be " + "negative."); - Preconditions.checkArgument(used >= 0, - "Used space cannot be " + "negative."); - Preconditions.checkArgument(keyCount >= 0, - "Key count cannot be " + "negative"); - Preconditions.checkArgument(readBytes >= 0, - "Read bytes read cannot be " + "negative."); - Preconditions.checkArgument(readBytes >= 0, - "Write bytes cannot be " + "negative."); - Preconditions.checkArgument(readCount >= 0, - "Read count cannot be " + "negative."); - Preconditions.checkArgument(writeCount >= 0, - "Write count cannot be " + "negative"); - - this.size = new LongMetric(size); - this.used = new LongMetric(used); - this.keyCount = new LongMetric(keyCount); - this.readBytes = new LongMetric(readBytes); - this.writeBytes = new LongMetric(writeBytes); - this.readCount = new LongMetric(readCount); - this.writeCount = new LongMetric(writeCount); - } - - public LongMetric getSize() { - return size; - } - - public LongMetric getUsed() { - return used; - } - - public LongMetric getKeyCount() { - return keyCount; - } - - public LongMetric getReadBytes() { - return readBytes; - } - - public LongMetric getWriteBytes() { - return writeBytes; - } - - public LongMetric getReadCount() { - return readCount; - } - - public LongMetric getWriteCount() { - return writeCount; - } - - public void add(ContainerStat stat) { - if (stat == null) { - return; - } - - this.size.add(stat.getSize().get()); - this.used.add(stat.getUsed().get()); - this.keyCount.add(stat.getKeyCount().get()); - this.readBytes.add(stat.getReadBytes().get()); - this.writeBytes.add(stat.getWriteBytes().get()); - this.readCount.add(stat.getReadCount().get()); - this.writeCount.add(stat.getWriteCount().get()); - } - - public void subtract(ContainerStat stat) { - if (stat == null) { - return; - } - - this.size.subtract(stat.getSize().get()); - this.used.subtract(stat.getUsed().get()); - this.keyCount.subtract(stat.getKeyCount().get()); - this.readBytes.subtract(stat.getReadBytes().get()); - this.writeBytes.subtract(stat.getWriteBytes().get()); - this.readCount.subtract(stat.getReadCount().get()); - this.writeCount.subtract(stat.getWriteCount().get()); - } - - public String toJsonString() { - try { - return JsonUtils.toJsonString(this); - } catch (IOException ignored) { - return null; - } - } -} \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/DatanodeMetric.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/DatanodeMetric.java deleted file mode 100644 index a6e732c7503..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/DatanodeMetric.java +++ /dev/null @@ -1,91 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.hdds.scm.container.placement.metrics; - -import org.apache.hadoop.hdds.scm.exceptions.SCMException; - -/** - * DatanodeMetric acts as the basis for all the metric that is used in - * comparing 2 datanodes. - */ -public interface DatanodeMetric extends Comparable { - - /** - * Some syntactic sugar over Comparable interface. This makes code easier to - * read. - * - * @param o - Other Object - * @return - True if *this* object is greater than argument. - */ - boolean isGreater(T o); - - /** - * Inverse of isGreater. - * - * @param o - other object. - * @return True if *this* object is Lesser than argument. - */ - boolean isLess(T o); - - /** - * Returns true if the object has same values. Because of issues with - * equals, and loss of type information this interface supports isEqual. - * - * @param o object to compare. - * @return True, if the values match. - */ - boolean isEqual(T o); - - /** - * A resourceCheck, defined by resourceNeeded. - * For example, S could be bytes required - * and DatanodeMetric can reply by saying it can be met or not. - * - * @param resourceNeeded - ResourceNeeded in its own metric. - * @return boolean, True if this resource requirement can be met. - */ - boolean hasResources(S resourceNeeded) throws SCMException; - - /** - * Returns the metric. - * - * @return T, the object that represents this metric. - */ - T get(); - - /** - * Sets the value of this metric. - * - * @param value - value of the metric. - */ - void set(T value); - - /** - * Adds a value of to the base. - * @param value - value - */ - void add(T value); - - /** - * subtract a value. - * @param value value - */ - void subtract(T value); - - -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/LongMetric.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/LongMetric.java deleted file mode 100644 index 050d26bd23c..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/LongMetric.java +++ /dev/null @@ -1,162 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.scm.container.placement.metrics; - -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; - -/** - * An helper class for all metrics based on Longs. - */ -@JsonAutoDetect(fieldVisibility = Visibility.ANY) -public class LongMetric implements DatanodeMetric { - private Long value; - - /** - * Constructs a long Metric. - * - * @param value Value for this metric. - */ - public LongMetric(Long value) { - this.value = value; - } - - /** - * Some syntactic sugar over Comparable interface. This makes code easier to - * read. - * - * @param o - Other Object - * @return - True if *this* object is greater than argument. - */ - @Override - public boolean isGreater(Long o) { - return compareTo(o) > 0; - } - - /** - * Inverse of isGreater. - * - * @param o - other object. - * @return True if *this* object is Lesser than argument. - */ - @Override - public boolean isLess(Long o) { - return compareTo(o) < 0; - } - - /** - * Returns true if the object has same values. Because of issues with - * equals, and loss of type information this interface supports isEqual. - * - * @param o object to compare. - * @return True, if the values match. - */ - @Override - public boolean isEqual(Long o) { - return compareTo(o) == 0; - } - - /** - * A resourceCheck, defined by resourceNeeded. - * For example, S could be bytes required - * and DatanodeMetric can reply by saying it can be met or not. - * - * @param resourceNeeded - ResourceNeeded in its own metric. - * @return boolean, True if this resource requirement can be met. - */ - @Override - public boolean hasResources(Long resourceNeeded) { - return isGreater(resourceNeeded); - } - - /** - * Returns the metric. - * - * @return T, the object that represents this metric. - */ - @Override - public Long get() { - return this.value; - } - - /** - * Sets the value of this metric. - * - * @param setValue - value of the metric. - */ - @Override - public void set(Long setValue) { - this.value = setValue; - - } - - /** - * Adds a value of to the base. - * - * @param addValue - value - */ - @Override - public void add(Long addValue) { - this.value += addValue; - } - - /** - * subtract a value. - * - * @param subValue value - */ - @Override - public void subtract(Long subValue) { - this.value -= subValue; - } - - /** - * Compares this object with the specified object for order. Returns a - * negative integer, zero, or a positive integer as this object is less - * than, equal to, or greater than the specified object. - * - * @param o the object to be compared. - * @return a negative integer, zero, or a positive integer as this object is - * less than, equal to, or greater than the specified object. - * @throws NullPointerException if the specified object is null - * @throws ClassCastException if the specified object's type prevents it - * from being compared to this object. - */ - @Override - public int compareTo(Long o) { - return Long.compare(this.value, o); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - LongMetric that = (LongMetric) o; - - return value != null ? value.equals(that.value) : that.value == null; - } - - @Override - public int hashCode() { - return value != null ? value.hashCode() : 0; - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/NodeStat.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/NodeStat.java deleted file mode 100644 index d6857d395cf..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/NodeStat.java +++ /dev/null @@ -1,67 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.container.placement.metrics; - -import com.google.common.annotations.VisibleForTesting; - -/** - * Interface that defines Node Stats. - */ -interface NodeStat { - /** - * Get capacity of the node. - * @return capacity of the node. - */ - LongMetric getCapacity(); - - /** - * Get the used space of the node. - * @return the used space of the node. - */ - LongMetric getScmUsed(); - - /** - * Get the remaining space of the node. - * @return the remaining space of the node. - */ - LongMetric getRemaining(); - - /** - * Set the total/used/remaining space. - * @param capacity - total space. - * @param used - used space. - * @param remain - remaining space. - */ - @VisibleForTesting - void set(long capacity, long used, long remain); - - /** - * Adding of the stat. - * @param stat - stat to be added. - * @return updated node stat. - */ - NodeStat add(NodeStat stat); - - /** - * Subtract of the stat. - * @param stat - stat to be subtracted. - * @return updated nodestat. - */ - NodeStat subtract(NodeStat stat); -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/SCMMetrics.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/SCMMetrics.java deleted file mode 100644 index e4dd9aa37ef..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/SCMMetrics.java +++ /dev/null @@ -1,154 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.container.placement.metrics; - -import org.apache.hadoop.metrics2.MetricsSystem; -import org.apache.hadoop.metrics2.annotation.Metric; -import org.apache.hadoop.metrics2.annotation.Metrics; -import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem; -import org.apache.hadoop.metrics2.lib.MutableCounterLong; -import org.apache.hadoop.metrics2.lib.MutableGaugeLong; - -/** - * This class is for maintaining StorageContainerManager statistics. - */ -@Metrics(about="Storage Container Manager Metrics", context="dfs") -public class SCMMetrics { - public static final String SOURCE_NAME = - SCMMetrics.class.getSimpleName(); - - /** - * Container stat metrics, the meaning of following metrics - * can be found in {@link ContainerStat}. - */ - @Metric private MutableGaugeLong lastContainerReportSize; - @Metric private MutableGaugeLong lastContainerReportUsed; - @Metric private MutableGaugeLong lastContainerReportKeyCount; - @Metric private MutableGaugeLong lastContainerReportReadBytes; - @Metric private MutableGaugeLong lastContainerReportWriteBytes; - @Metric private MutableGaugeLong lastContainerReportReadCount; - @Metric private MutableGaugeLong lastContainerReportWriteCount; - - @Metric private MutableCounterLong containerReportSize; - @Metric private MutableCounterLong containerReportUsed; - @Metric private MutableCounterLong containerReportKeyCount; - @Metric private MutableCounterLong containerReportReadBytes; - @Metric private MutableCounterLong containerReportWriteBytes; - @Metric private MutableCounterLong containerReportReadCount; - @Metric private MutableCounterLong containerReportWriteCount; - - public SCMMetrics() { - } - - public static SCMMetrics create() { - MetricsSystem ms = DefaultMetricsSystem.instance(); - return ms.register(SOURCE_NAME, "Storage Container Manager Metrics", - new SCMMetrics()); - } - - public void setLastContainerReportSize(long size) { - this.lastContainerReportSize.set(size); - } - - public void setLastContainerReportUsed(long used) { - this.lastContainerReportUsed.set(used); - } - - public void setLastContainerReportKeyCount(long keyCount) { - this.lastContainerReportKeyCount.set(keyCount); - } - - public void setLastContainerReportReadBytes(long readBytes) { - this.lastContainerReportReadBytes.set(readBytes); - } - - public void setLastContainerReportWriteBytes(long writeBytes) { - this.lastContainerReportWriteBytes.set(writeBytes); - } - - public void setLastContainerReportReadCount(long readCount) { - this.lastContainerReportReadCount.set(readCount); - } - - public void setLastContainerReportWriteCount(long writeCount) { - this.lastContainerReportWriteCount.set(writeCount); - } - - public void incrContainerReportSize(long size) { - this.containerReportSize.incr(size); - } - - public void incrContainerReportUsed(long used) { - this.containerReportUsed.incr(used); - } - - public void incrContainerReportKeyCount(long keyCount) { - this.containerReportKeyCount.incr(keyCount); - } - - public void incrContainerReportReadBytes(long readBytes) { - this.containerReportReadBytes.incr(readBytes); - } - - public void incrContainerReportWriteBytes(long writeBytes) { - this.containerReportWriteBytes.incr(writeBytes); - } - - public void incrContainerReportReadCount(long readCount) { - this.containerReportReadCount.incr(readCount); - } - - public void incrContainerReportWriteCount(long writeCount) { - this.containerReportWriteCount.incr(writeCount); - } - - public void setLastContainerStat(ContainerStat newStat) { - this.lastContainerReportSize.set(newStat.getSize().get()); - this.lastContainerReportUsed.set(newStat.getUsed().get()); - this.lastContainerReportKeyCount.set(newStat.getKeyCount().get()); - this.lastContainerReportReadBytes.set(newStat.getReadBytes().get()); - this.lastContainerReportWriteBytes.set(newStat.getWriteBytes().get()); - this.lastContainerReportReadCount.set(newStat.getReadCount().get()); - this.lastContainerReportWriteCount.set(newStat.getWriteCount().get()); - } - - public void incrContainerStat(ContainerStat deltaStat) { - this.containerReportSize.incr(deltaStat.getSize().get()); - this.containerReportUsed.incr(deltaStat.getUsed().get()); - this.containerReportKeyCount.incr(deltaStat.getKeyCount().get()); - this.containerReportReadBytes.incr(deltaStat.getReadBytes().get()); - this.containerReportWriteBytes.incr(deltaStat.getWriteBytes().get()); - this.containerReportReadCount.incr(deltaStat.getReadCount().get()); - this.containerReportWriteCount.incr(deltaStat.getWriteCount().get()); - } - - public void decrContainerStat(ContainerStat deltaStat) { - this.containerReportSize.incr(-1 * deltaStat.getSize().get()); - this.containerReportUsed.incr(-1 * deltaStat.getUsed().get()); - this.containerReportKeyCount.incr(-1 * deltaStat.getKeyCount().get()); - this.containerReportReadBytes.incr(-1 * deltaStat.getReadBytes().get()); - this.containerReportWriteBytes.incr(-1 * deltaStat.getWriteBytes().get()); - this.containerReportReadCount.incr(-1 * deltaStat.getReadCount().get()); - this.containerReportWriteCount.incr(-1 * deltaStat.getWriteCount().get()); - } - - public void unRegister() { - MetricsSystem ms = DefaultMetricsSystem.instance(); - ms.unregisterSource(SOURCE_NAME); - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/SCMNodeMetric.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/SCMNodeMetric.java deleted file mode 100644 index efd5fd60ab1..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/SCMNodeMetric.java +++ /dev/null @@ -1,224 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.hdds.scm.container.placement.metrics; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; - -/** - * SCM Node Metric that is used in the placement classes. - */ -public class SCMNodeMetric implements DatanodeMetric { - private SCMNodeStat stat; - - /** - * Constructs an SCMNode Metric. - * - * @param stat - SCMNodeStat. - */ - public SCMNodeMetric(SCMNodeStat stat) { - this.stat = stat; - } - - /** - * Set the capacity, used and remaining space on a datanode. - * - * @param capacity in bytes - * @param used in bytes - * @param remaining in bytes - */ - @VisibleForTesting - public SCMNodeMetric(long capacity, long used, long remaining) { - this.stat = new SCMNodeStat(); - this.stat.set(capacity, used, remaining); - } - - /** - * - * @param o - Other Object - * @return - True if *this* object is greater than argument. - */ - @Override - public boolean isGreater(SCMNodeStat o) { - Preconditions.checkNotNull(this.stat, "Argument cannot be null"); - Preconditions.checkNotNull(o, "Argument cannot be null"); - - // if zero, replace with 1 for the division to work. - long thisDenominator = (this.stat.getCapacity().get() == 0) - ? 1 : this.stat.getCapacity().get(); - long otherDenominator = (o.getCapacity().get() == 0) - ? 1 : o.getCapacity().get(); - - float thisNodeWeight = - stat.getScmUsed().get() / (float) thisDenominator; - - float oNodeWeight = - o.getScmUsed().get() / (float) otherDenominator; - - if (Math.abs(thisNodeWeight - oNodeWeight) > 0.000001) { - return thisNodeWeight > oNodeWeight; - } - // if these nodes are have similar weight then return the node with more - // free space as the greater node. - return stat.getRemaining().isGreater(o.getRemaining().get()); - } - - /** - * Inverse of isGreater. - * - * @param o - other object. - * @return True if *this* object is Lesser than argument. - */ - @Override - public boolean isLess(SCMNodeStat o) { - Preconditions.checkNotNull(o, "Argument cannot be null"); - - // if zero, replace with 1 for the division to work. - long thisDenominator = (this.stat.getCapacity().get() == 0) - ? 1 : this.stat.getCapacity().get(); - long otherDenominator = (o.getCapacity().get() == 0) - ? 1 : o.getCapacity().get(); - - float thisNodeWeight = - stat.getScmUsed().get() / (float) thisDenominator; - - float oNodeWeight = - o.getScmUsed().get() / (float) otherDenominator; - - if (Math.abs(thisNodeWeight - oNodeWeight) > 0.000001) { - return thisNodeWeight < oNodeWeight; - } - - // if these nodes are have similar weight then return the node with less - // free space as the lesser node. - return stat.getRemaining().isLess(o.getRemaining().get()); - } - - /** - * Returns true if the object has same values. Because of issues with - * equals, and loss of type information this interface supports isEqual. - * - * @param o object to compare. - * @return True, if the values match. - * TODO : Consider if it makes sense to add remaining to this equation. - */ - @Override - public boolean isEqual(SCMNodeStat o) { - float thisNodeWeight = stat.getScmUsed().get() / (float) - stat.getCapacity().get(); - float oNodeWeight = o.getScmUsed().get() / (float) o.getCapacity().get(); - return Math.abs(thisNodeWeight - oNodeWeight) < 0.000001; - } - - /** - * A resourceCheck, defined by resourceNeeded. - * For example, S could be bytes required - * and DatanodeMetric can reply by saying it can be met or not. - * - * @param resourceNeeded - ResourceNeeded in its own metric. - * @return boolean, True if this resource requirement can be met. - */ - @Override - public boolean hasResources(Long resourceNeeded) { - return false; - } - - /** - * Returns the metric. - * - * @return T, the object that represents this metric. - */ - @Override - public SCMNodeStat get() { - return stat; - } - - /** - * Sets the value of this metric. - * - * @param value - value of the metric. - */ - @Override - public void set(SCMNodeStat value) { - stat.set(value.getCapacity().get(), value.getScmUsed().get(), - value.getRemaining().get()); - } - - /** - * Adds a value of to the base. - * - * @param value - value - */ - @Override - public void add(SCMNodeStat value) { - stat.add(value); - } - - /** - * subtract a value. - * - * @param value value - */ - @Override - public void subtract(SCMNodeStat value) { - stat.subtract(value); - } - - /** - * Compares this object with the specified object for order. Returns a - * negative integer, zero, or a positive integer as this object is less - * than, equal to, or greater than the specified object. - * - * @param o the object to be compared. - * @return a negative integer, zero, or a positive integer as this object is - * less than, equal to, or greater than the specified object. - * @throws NullPointerException if the specified object is null - * @throws ClassCastException if the specified object's type prevents it - * from being compared to this object. - */ - @Override - public int compareTo(SCMNodeStat o) { - if (isEqual(o)) { - return 0; - } - if (isGreater(o)) { - return 1; - } else { - return -1; - } - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - SCMNodeMetric that = (SCMNodeMetric) o; - - return stat != null ? stat.equals(that.stat) : that.stat == null; - } - - @Override - public int hashCode() { - return stat != null ? stat.hashCode() : 0; - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/SCMNodeStat.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/SCMNodeStat.java deleted file mode 100644 index 3c871d3ef50..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/SCMNodeStat.java +++ /dev/null @@ -1,139 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.container.placement.metrics; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; - -/** - * This class represents the SCM node stat. - */ -public class SCMNodeStat implements NodeStat { - private LongMetric capacity; - private LongMetric scmUsed; - private LongMetric remaining; - - public SCMNodeStat() { - this(0L, 0L, 0L); - } - - public SCMNodeStat(SCMNodeStat other) { - this(other.capacity.get(), other.scmUsed.get(), other.remaining.get()); - } - - public SCMNodeStat(long capacity, long used, long remaining) { - Preconditions.checkArgument(capacity >= 0, "Capacity cannot be " + - "negative."); - Preconditions.checkArgument(used >= 0, "used space cannot be " + - "negative."); - Preconditions.checkArgument(remaining >= 0, "remaining cannot be " + - "negative"); - this.capacity = new LongMetric(capacity); - this.scmUsed = new LongMetric(used); - this.remaining = new LongMetric(remaining); - } - - /** - * @return the total configured capacity of the node. - */ - public LongMetric getCapacity() { - return capacity; - } - - /** - * @return the total SCM used space on the node. - */ - public LongMetric getScmUsed() { - return scmUsed; - } - - /** - * @return the total remaining space available on the node. - */ - public LongMetric getRemaining() { - return remaining; - } - - /** - * Set the capacity, used and remaining space on a datanode. - * - * @param newCapacity in bytes - * @param newUsed in bytes - * @param newRemaining in bytes - */ - @VisibleForTesting - public void set(long newCapacity, long newUsed, long newRemaining) { - Preconditions.checkNotNull(newCapacity, "Capacity cannot be null"); - Preconditions.checkNotNull(newUsed, "used cannot be null"); - Preconditions.checkNotNull(newRemaining, "remaining cannot be null"); - - Preconditions.checkArgument(newCapacity >= 0, "Capacity cannot be " + - "negative."); - Preconditions.checkArgument(newUsed >= 0, "used space cannot be " + - "negative."); - Preconditions.checkArgument(newRemaining >= 0, "remaining cannot be " + - "negative"); - - this.capacity = new LongMetric(newCapacity); - this.scmUsed = new LongMetric(newUsed); - this.remaining = new LongMetric(newRemaining); - } - - /** - * Adds a new nodestat to existing values of the node. - * - * @param stat Nodestat. - * @return SCMNodeStat - */ - public SCMNodeStat add(NodeStat stat) { - this.capacity.set(this.getCapacity().get() + stat.getCapacity().get()); - this.scmUsed.set(this.getScmUsed().get() + stat.getScmUsed().get()); - this.remaining.set(this.getRemaining().get() + stat.getRemaining().get()); - return this; - } - - /** - * Subtracts the stat values from the existing NodeStat. - * - * @param stat SCMNodeStat. - * @return Modified SCMNodeStat - */ - public SCMNodeStat subtract(NodeStat stat) { - this.capacity.set(this.getCapacity().get() - stat.getCapacity().get()); - this.scmUsed.set(this.getScmUsed().get() - stat.getScmUsed().get()); - this.remaining.set(this.getRemaining().get() - stat.getRemaining().get()); - return this; - } - - @Override - public boolean equals(Object to) { - if (to instanceof SCMNodeStat) { - SCMNodeStat tempStat = (SCMNodeStat) to; - return capacity.isEqual(tempStat.getCapacity().get()) && - scmUsed.isEqual(tempStat.getScmUsed().get()) && - remaining.isEqual(tempStat.getRemaining().get()); - } - return false; - } - - @Override - public int hashCode() { - return Long.hashCode(capacity.get() ^ scmUsed.get() ^ remaining.get()); - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/package-info.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/package-info.java deleted file mode 100644 index 4a81d692168..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/metrics/package-info.java +++ /dev/null @@ -1,20 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.scm.container.placement.metrics; - -// Various metrics supported by Datanode and used by SCM in the placement -// strategy. \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/package-info.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/package-info.java deleted file mode 100644 index dc54d9bd912..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/placement/package-info.java +++ /dev/null @@ -1,19 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.hdds.scm.container.placement; -// Classes related to container placement. \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/replication/ReplicationActivityStatus.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/replication/ReplicationActivityStatus.java deleted file mode 100644 index 993a9860244..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/replication/ReplicationActivityStatus.java +++ /dev/null @@ -1,117 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.container.replication; - -import javax.management.ObjectName; -import java.io.Closeable; -import java.io.IOException; -import java.util.concurrent.atomic.AtomicBoolean; -import org.apache.hadoop.hdds.server.events.EventHandler; -import org.apache.hadoop.hdds.server.events.EventPublisher; -import org.apache.hadoop.metrics2.util.MBeans; - -import com.google.common.annotations.VisibleForTesting; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Event listener to track the current state of replication. - */ -public class ReplicationActivityStatus implements - ReplicationActivityStatusMXBean, Closeable { - - private static final Logger LOG = - LoggerFactory.getLogger(ReplicationActivityStatus.class); - - private AtomicBoolean replicationEnabled = new AtomicBoolean(); - private AtomicBoolean replicationStatusSetExternally = new AtomicBoolean(); - private ObjectName jmxObjectName; - private ReplicationStatusListener replicationStatusListener; - private ChillModeStatusListener chillModeStatusListener; - - public ReplicationActivityStatus(){ - replicationStatusListener = new ReplicationStatusListener(); - chillModeStatusListener = new ChillModeStatusListener(); - } - - public boolean isReplicationEnabled() { - return replicationEnabled.get(); - } - - @VisibleForTesting - public void setReplicationEnabled(boolean enabled) { - replicationEnabled.set(enabled); - } - - @VisibleForTesting - public void enableReplication() { - replicationEnabled.set(true); - } - - - public void start() { - try { - this.jmxObjectName = - MBeans.register( - "StorageContainerManager", "ReplicationActivityStatus", this); - } catch (Exception ex) { - LOG.error("JMX bean for ReplicationActivityStatus can't be registered", - ex); - } - } - - @Override - public void close() throws IOException { - if (this.jmxObjectName != null) { - MBeans.unregister(jmxObjectName); - } - } - - /** - * Replication status listener. - */ - class ReplicationStatusListener implements EventHandler { - @Override - public void onMessage(Boolean status, EventPublisher publisher) { - replicationStatusSetExternally.set(true); - replicationEnabled.set(status); - } - } - - /** - * Replication status is influenced by Chill mode status as well. - */ - class ChillModeStatusListener implements EventHandler { - - @Override - public void onMessage(Boolean inChillMode, EventPublisher publisher) { - if (!replicationStatusSetExternally.get()) { - replicationEnabled.set(!inChillMode); - } - } - } - - public ReplicationStatusListener getReplicationStatusListener() { - return replicationStatusListener; - } - - public ChillModeStatusListener getChillModeStatusListener() { - return chillModeStatusListener; - } - -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/replication/ReplicationActivityStatusMXBean.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/replication/ReplicationActivityStatusMXBean.java deleted file mode 100644 index 164bd247efb..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/replication/ReplicationActivityStatusMXBean.java +++ /dev/null @@ -1,28 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.container.replication; - -/** - * JMX interface to monitor replication status. - */ -public interface ReplicationActivityStatusMXBean { - - boolean isReplicationEnabled(); - - void setReplicationEnabled(boolean enabled); -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/replication/ReplicationCommandWatcher.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/replication/ReplicationCommandWatcher.java deleted file mode 100644 index 03a81a7db86..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/replication/ReplicationCommandWatcher.java +++ /dev/null @@ -1,56 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.scm.container.replication; - -import org.apache.hadoop.hdds.scm.container.replication.ReplicationManager - .ReplicationCompleted; -import org.apache.hadoop.hdds.scm.container.replication.ReplicationManager - .ReplicationRequestToRepeat; -import org.apache.hadoop.hdds.scm.events.SCMEvents; -import org.apache.hadoop.hdds.server.events.Event; -import org.apache.hadoop.hdds.server.events.EventPublisher; -import org.apache.hadoop.hdds.server.events.EventWatcher; -import org.apache.hadoop.ozone.lease.LeaseManager; - -/** - * Command watcher to track the replication commands. - */ -public class ReplicationCommandWatcher - extends - EventWatcher { - - public ReplicationCommandWatcher(Event startEvent, - Event completionEvent, - LeaseManager leaseManager) { - super(startEvent, completionEvent, leaseManager); - } - - @Override - protected void onTimeout(EventPublisher publisher, - ReplicationRequestToRepeat payload) { - //put back to the original queue - publisher.fireEvent(SCMEvents.REPLICATE_CONTAINER, - payload.getRequest()); - } - - @Override - protected void onFinished(EventPublisher publisher, - ReplicationRequestToRepeat payload) { - - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/replication/ReplicationManager.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/replication/ReplicationManager.java deleted file mode 100644 index ddecdbcfa5c..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/replication/ReplicationManager.java +++ /dev/null @@ -1,250 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.scm.container.replication; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.ThreadFactory; - -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.LifeCycleState; -import org.apache.hadoop.hdds.scm.container.ContainerID; -import org.apache.hadoop.hdds.scm.container.ContainerStateManager; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo; -import org.apache.hadoop.hdds.scm.container.placement.algorithms - .ContainerPlacementPolicy; -import org.apache.hadoop.hdds.scm.events.SCMEvents; -import org.apache.hadoop.hdds.server.events.EventPublisher; -import org.apache.hadoop.hdds.server.events.EventQueue; -import org.apache.hadoop.hdds.server.events.IdentifiableEventPayload; -import org.apache.hadoop.ozone.lease.LeaseManager; -import org.apache.hadoop.ozone.protocol.commands.CommandForDatanode; -import org.apache.hadoop.ozone.protocol.commands.ReplicateContainerCommand; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import static org.apache.hadoop.hdds.scm.events.SCMEvents - .TRACK_REPLICATE_COMMAND; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Replication Manager manages the replication of the closed container. - */ -public class ReplicationManager implements Runnable { - - private static final Logger LOG = - LoggerFactory.getLogger(ReplicationManager.class); - - private ReplicationQueue replicationQueue; - - private ContainerPlacementPolicy containerPlacement; - - private EventPublisher eventPublisher; - - private ReplicationCommandWatcher replicationCommandWatcher; - - private boolean running = true; - - private ContainerStateManager containerStateManager; - - public ReplicationManager(ContainerPlacementPolicy containerPlacement, - ContainerStateManager containerStateManager, EventQueue eventQueue, - LeaseManager commandWatcherLeaseManager) { - - this.containerPlacement = containerPlacement; - this.containerStateManager = containerStateManager; - this.eventPublisher = eventQueue; - - this.replicationCommandWatcher = - new ReplicationCommandWatcher(TRACK_REPLICATE_COMMAND, - SCMEvents.REPLICATION_COMPLETE, commandWatcherLeaseManager); - - this.replicationQueue = new ReplicationQueue(); - - eventQueue.addHandler(SCMEvents.REPLICATE_CONTAINER, - (replicationRequest, publisher) -> replicationQueue - .add(replicationRequest)); - - this.replicationCommandWatcher.start(eventQueue); - - } - - public void start() { - - ThreadFactory threadFactory = new ThreadFactoryBuilder().setDaemon(true) - .setNameFormat("Replication Manager").build(); - - threadFactory.newThread(this).start(); - } - - public void run() { - - while (running) { - ReplicationRequest request = null; - try { - //TODO: add throttling here - request = replicationQueue.take(); - - ContainerID containerID = new ContainerID(request.getContainerId()); - ContainerInfo containerInfo = - containerStateManager.getContainer(containerID); - - Preconditions.checkNotNull(containerInfo, - "No information about the container " + request.getContainerId()); - - Preconditions - .checkState(containerInfo.getState() == LifeCycleState.CLOSED, - "Container should be in closed state"); - - //check the current replication - List datanodesWithReplicas = - new ArrayList<>(getCurrentReplicas(request)); - - if (datanodesWithReplicas.size() == 0) { - LOG.warn( - "Container {} should be replicated but can't find any existing " - + "replicas", - containerID); - return; - } - - ReplicationRequest finalRequest = request; - - int inFlightReplications = replicationCommandWatcher.getTimeoutEvents( - e -> e.request.getContainerId() == finalRequest.getContainerId()) - .size(); - - int deficit = - request.getExpecReplicationCount() - datanodesWithReplicas.size() - - inFlightReplications; - - if (deficit > 0) { - - List selectedDatanodes = containerPlacement - .chooseDatanodes(datanodesWithReplicas, deficit, - containerInfo.getUsedBytes()); - - //send the command - for (DatanodeDetails datanode : selectedDatanodes) { - - ReplicateContainerCommand replicateCommand = - new ReplicateContainerCommand(containerID.getId(), - datanodesWithReplicas); - - eventPublisher.fireEvent(SCMEvents.DATANODE_COMMAND, - new CommandForDatanode<>( - datanode.getUuid(), replicateCommand)); - - ReplicationRequestToRepeat timeoutEvent = - new ReplicationRequestToRepeat(replicateCommand.getId(), - request); - - eventPublisher.fireEvent(TRACK_REPLICATE_COMMAND, timeoutEvent); - - } - - } else if (deficit < 0) { - //TODO: too many replicas. Not handled yet. - } - - } catch (Exception e) { - LOG.error("Can't replicate container {}", request, e); - } - } - - } - - @VisibleForTesting - protected Set getCurrentReplicas(ReplicationRequest request) - throws IOException { - return containerStateManager - .getContainerReplicas(new ContainerID(request.getContainerId())); - } - - @VisibleForTesting - public ReplicationQueue getReplicationQueue() { - return replicationQueue; - } - - public void stop() { - running = false; - } - - /** - * Event for the ReplicationCommandWatcher to repeate the embedded request. - * in case fof timeout. - */ - public static class ReplicationRequestToRepeat - implements IdentifiableEventPayload { - - private final long commandId; - - private final ReplicationRequest request; - - public ReplicationRequestToRepeat(long commandId, - ReplicationRequest request) { - this.commandId = commandId; - this.request = request; - } - - public ReplicationRequest getRequest() { - return request; - } - - @Override - public long getId() { - return commandId; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - ReplicationRequestToRepeat that = (ReplicationRequestToRepeat) o; - return Objects.equals(request, that.request); - } - - @Override - public int hashCode() { - - return Objects.hash(request); - } - } - - public static class ReplicationCompleted implements IdentifiableEventPayload { - - private final long uuid; - - public ReplicationCompleted(long uuid) { - this.uuid = uuid; - } - - @Override - public long getId() { - return uuid; - } - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/replication/ReplicationQueue.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/replication/ReplicationQueue.java deleted file mode 100644 index 4ca67be4e11..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/replication/ReplicationQueue.java +++ /dev/null @@ -1,73 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.container.replication; - -import java.util.List; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.PriorityBlockingQueue; - -/** - * Priority queue to handle under-replicated and over replicated containers - * in ozone. ReplicationManager will consume these messages and decide - * accordingly. - */ -public class ReplicationQueue { - - private final BlockingQueue queue; - - public ReplicationQueue() { - queue = new PriorityBlockingQueue<>(); - } - - public boolean add(ReplicationRequest repObj) { - if (this.queue.contains(repObj)) { - // Remove the earlier message and insert this one - this.queue.remove(repObj); - } - return this.queue.add(repObj); - } - - public boolean remove(ReplicationRequest repObj) { - return queue.remove(repObj); - } - - /** - * Retrieves, but does not remove, the head of this queue, - * or returns {@code null} if this queue is empty. - * - * @return the head of this queue, or {@code null} if this queue is empty - */ - public ReplicationRequest peek() { - return queue.peek(); - } - - /** - * Retrieves and removes the head of this queue (blocking queue). - */ - public ReplicationRequest take() throws InterruptedException { - return queue.take(); - } - - public boolean removeAll(List repObjs) { - return queue.removeAll(repObjs); - } - - public int size() { - return queue.size(); - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/replication/ReplicationRequest.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/replication/ReplicationRequest.java deleted file mode 100644 index d40cd9cd17d..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/replication/ReplicationRequest.java +++ /dev/null @@ -1,123 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.container.replication; - -import java.io.Serializable; - -import org.apache.commons.lang3.builder.EqualsBuilder; -import org.apache.commons.lang3.builder.HashCodeBuilder; - -/** - * Wrapper class for hdds replication queue. Implements its natural - * ordering for priority queue. - */ -public class ReplicationRequest implements Comparable, - Serializable { - private final long containerId; - private final int replicationCount; - private final int expecReplicationCount; - private final long timestamp; - - public ReplicationRequest(long containerId, int replicationCount, - long timestamp, int expecReplicationCount) { - this.containerId = containerId; - this.replicationCount = replicationCount; - this.timestamp = timestamp; - this.expecReplicationCount = expecReplicationCount; - } - - public ReplicationRequest(long containerId, int replicationCount, - int expecReplicationCount) { - this(containerId, replicationCount, System.currentTimeMillis(), - expecReplicationCount); - } - - /** - * Compares this object with the specified object for order. Returns a - * negative integer, zero, or a positive integer as this object is less - * than, equal to, or greater than the specified object. - * @param o the object to be compared. - * @return a negative integer, zero, or a positive integer as this object - * is less than, equal to, or greater than the specified object. - * @throws NullPointerException if the specified object is null - * @throws ClassCastException if the specified object's type prevents it - * from being compared to this object. - */ - @Override - public int compareTo(ReplicationRequest o) { - if (o == null) { - return 1; - } - if (this == o) { - return 0; - } - int retVal = Integer - .compare(getReplicationCount() - getExpecReplicationCount(), - o.getReplicationCount() - o.getExpecReplicationCount()); - if (retVal != 0) { - return retVal; - } - return Long.compare(getTimestamp(), o.getTimestamp()); - } - - @Override - public int hashCode() { - return new HashCodeBuilder(91, 1011) - .append(getContainerId()) - .toHashCode(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - ReplicationRequest that = (ReplicationRequest) o; - return new EqualsBuilder().append(getContainerId(), that.getContainerId()) - .isEquals(); - } - - public long getContainerId() { - return containerId; - } - - public int getReplicationCount() { - return replicationCount; - } - - public long getTimestamp() { - return timestamp; - } - - public int getExpecReplicationCount() { - return expecReplicationCount; - } - - @Override - public String toString() { - return "ReplicationRequest{" + - "containerId=" + containerId + - ", replicationCount=" + replicationCount + - ", expecReplicationCount=" + expecReplicationCount + - ", timestamp=" + timestamp + - '}'; - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/replication/package-info.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/replication/package-info.java deleted file mode 100644 index 934b01e6231..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/replication/package-info.java +++ /dev/null @@ -1,23 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.container.replication; - -/** - * HDDS (Closed) Container replicaton related classes. - */ \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/states/ContainerAttribute.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/states/ContainerAttribute.java deleted file mode 100644 index 288fa2deb14..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/states/ContainerAttribute.java +++ /dev/null @@ -1,245 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ -package org.apache.hadoop.hdds.scm.container.states; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdds.scm.container.ContainerID; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.NavigableSet; -import java.util.TreeSet; - -import static org.apache.hadoop.hdds.scm.exceptions.SCMException.ResultCodes - .FAILED_TO_CHANGE_CONTAINER_STATE; - -/** - * Each Attribute that we manage for a container is maintained as a map. - *

- * Currently we manage the following attributes for a container. - *

- * 1. StateMap - LifeCycleState -> Set of ContainerIDs - * 2. TypeMap - ReplicationType -> Set of ContainerIDs - * 3. OwnerMap - OwnerNames -> Set of ContainerIDs - * 4. FactorMap - ReplicationFactor -> Set of ContainerIDs - *

- * This means that for a cluster size of 750 PB -- we will have around 150 - * Million containers, if we assume 5GB average container size. - *

- * That implies that these maps will take around 2/3 GB of RAM which will be - * pinned down in the SCM. This is deemed acceptable since we can tune the - * container size --say we make it 10GB average size, then we can deal with a - * cluster size of 1.5 exa bytes with the same metadata in SCMs memory. - *

- * Please note: **This class is not thread safe**. This used to be thread safe, - * while bench marking we found that ContainerStateMap would be taking 5 - * locks for a single container insert. If we remove locks in this class, - * then we are able to perform about 540K operations per second, with the - * locks in this class it goes down to 246K operations per second. Hence we - * are going to rely on ContainerStateMap locks to maintain consistency of - * data in these classes too, since ContainerAttribute is only used by - * ContainerStateMap class. - */ -public class ContainerAttribute { - private static final Logger LOG = - LoggerFactory.getLogger(ContainerAttribute.class); - - private final Map> attributeMap; - private static final NavigableSet EMPTY_SET = Collections - .unmodifiableNavigableSet(new TreeSet<>()); - - /** - * Creates a Container Attribute map from an existing Map. - * - * @param attributeMap - AttributeMap - */ - public ContainerAttribute(Map> attributeMap) { - this.attributeMap = attributeMap; - } - - /** - * Create an empty Container Attribute map. - */ - public ContainerAttribute() { - this.attributeMap = new HashMap<>(); - } - - /** - * Insert or update the value in the Attribute map. - * - * @param key - The key to the set where the ContainerID should exist. - * @param value - Actual Container ID. - * @throws SCMException - on Error - */ - public boolean insert(T key, ContainerID value) throws SCMException { - Preconditions.checkNotNull(key); - Preconditions.checkNotNull(value); - - if (attributeMap.containsKey(key)) { - if (attributeMap.get(key).add(value)) { - return true; //we inserted the value as it doesn’t exist in the set. - } else { // Failure indicates that this ContainerID exists in the Set - if (!attributeMap.get(key).remove(value)) { - LOG.error("Failure to remove the object from the Map.Key:{}, " + - "ContainerID: {}", key, value); - throw new SCMException("Failure to remove the object from the Map", - FAILED_TO_CHANGE_CONTAINER_STATE); - } - attributeMap.get(key).add(value); - return true; - } - } else { - // This key does not exist, we need to allocate this key in the map. - // TODO: Replace TreeSet with FoldedTreeSet from HDFS Utils. - // Skipping for now, since FoldedTreeSet does not have implementations - // for headSet and TailSet. We need those calls. - this.attributeMap.put(key, new TreeSet<>()); - // This should not fail, we just allocated this object. - attributeMap.get(key).add(value); - return true; - } - } - - /** - * Returns true if have this bucket in the attribute map. - * - * @param key - Key to lookup - * @return true if we have the key - */ - public boolean hasKey(T key) { - Preconditions.checkNotNull(key); - return this.attributeMap.containsKey(key); - } - - /** - * Returns true if we have the key and the containerID in the bucket. - * - * @param key - Key to the bucket - * @param id - container ID that we want to lookup - * @return true or false - */ - public boolean hasContainerID(T key, ContainerID id) { - Preconditions.checkNotNull(key); - Preconditions.checkNotNull(id); - - return this.attributeMap.containsKey(key) && - this.attributeMap.get(key).contains(id); - } - - /** - * Returns true if we have the key and the containerID in the bucket. - * - * @param key - Key to the bucket - * @param id - container ID that we want to lookup - * @return true or false - */ - public boolean hasContainerID(T key, int id) { - return hasContainerID(key, ContainerID.valueof(id)); - } - - /** - * Clears all entries for this key type. - * - * @param key - Key that identifies the Set. - */ - public void clearSet(T key) { - Preconditions.checkNotNull(key); - - if (attributeMap.containsKey(key)) { - attributeMap.get(key).clear(); - } else { - LOG.debug("key: {} does not exist in the attributeMap", key); - } - } - - /** - * Removes a container ID from the set pointed by the key. - * - * @param key - key to identify the set. - * @param value - Container ID - */ - public boolean remove(T key, ContainerID value) { - Preconditions.checkNotNull(key); - Preconditions.checkNotNull(value); - - if (attributeMap.containsKey(key)) { - if (!attributeMap.get(key).remove(value)) { - LOG.debug("ContainerID: {} does not exist in the set pointed by " + - "key:{}", value, key); - return false; - } - return true; - } else { - LOG.debug("key: {} does not exist in the attributeMap", key); - return false; - } - } - - /** - * Returns the collection that maps to the given key. - * - * @param key - Key to the bucket. - * @return Underlying Set in immutable form. - */ - public NavigableSet getCollection(T key) { - Preconditions.checkNotNull(key); - - if (this.attributeMap.containsKey(key)) { - return Collections.unmodifiableNavigableSet(this.attributeMap.get(key)); - } - LOG.debug("No such Key. Key {}", key); - return EMPTY_SET; - } - - /** - * Moves a ContainerID from one bucket to another. - * - * @param currentKey - Current Key - * @param newKey - newKey - * @param value - ContainerID - * @throws SCMException on Error - */ - public void update(T currentKey, T newKey, ContainerID value) - throws SCMException { - Preconditions.checkNotNull(currentKey); - Preconditions.checkNotNull(newKey); - - boolean removed = false; - try { - removed = remove(currentKey, value); - if (!removed) { - throw new SCMException("Unable to find key in the current key bucket", - FAILED_TO_CHANGE_CONTAINER_STATE); - } - insert(newKey, value); - } catch (SCMException ex) { - // if we removed the key, insert it back to original bucket, since the - // next insert failed. - LOG.error("error in update.", ex); - if (removed) { - insert(currentKey, value); - LOG.trace("reinserted the removed key. {}", currentKey); - } - throw ex; - } - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/states/ContainerQueryKey.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/states/ContainerQueryKey.java deleted file mode 100644 index cd491154291..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/states/ContainerQueryKey.java +++ /dev/null @@ -1,110 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ - -package org.apache.hadoop.hdds.scm.container.states; - -import org.apache.commons.lang3.builder.EqualsBuilder; -import org.apache.commons.lang3.builder.HashCodeBuilder; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; - -/** - * Key for the Caching layer for Container Query. - */ -public class ContainerQueryKey { - private final HddsProtos.LifeCycleState state; - private final String owner; - private final HddsProtos.ReplicationFactor factor; - private final HddsProtos.ReplicationType type; - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (o == null || getClass() != o.getClass()) { - return false; - } - - ContainerQueryKey that = (ContainerQueryKey) o; - - return new EqualsBuilder() - .append(getState(), that.getState()) - .append(getOwner(), that.getOwner()) - .append(getFactor(), that.getFactor()) - .append(getType(), that.getType()) - .isEquals(); - } - - @Override - public int hashCode() { - return new HashCodeBuilder(61, 71) - .append(getState()) - .append(getOwner()) - .append(getFactor()) - .append(getType()) - .toHashCode(); - } - - /** - * Constructor for ContainerQueryKey. - * @param state LifeCycleState - * @param owner - Name of the Owner. - * @param factor Replication Factor. - * @param type - Replication Type. - */ - public ContainerQueryKey(HddsProtos.LifeCycleState state, String owner, - HddsProtos.ReplicationFactor factor, HddsProtos.ReplicationType type) { - this.state = state; - this.owner = owner; - this.factor = factor; - this.type = type; - } - - /** - * Returns the state of containers which this key represents. - * @return LifeCycleState - */ - public HddsProtos.LifeCycleState getState() { - return state; - } - - /** - * Returns the owner of containers which this key represents. - * @return Owner - */ - public String getOwner() { - return owner; - } - - /** - * Returns the replication factor of containers which this key represents. - * @return ReplicationFactor - */ - public HddsProtos.ReplicationFactor getFactor() { - return factor; - } - - /** - * Returns the replication type of containers which this key represents. - * @return ReplicationType - */ - public HddsProtos.ReplicationType getType() { - return type; - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/states/ContainerState.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/states/ContainerState.java deleted file mode 100644 index 1dac36ef771..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/states/ContainerState.java +++ /dev/null @@ -1,96 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ - -package org.apache.hadoop.hdds.scm.container.states; - -import org.apache.commons.lang3.builder.EqualsBuilder; -import org.apache.commons.lang3.builder.HashCodeBuilder; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; - -/** - * Class that acts as the container state. - */ -public class ContainerState { - private final HddsProtos.ReplicationType type; - private final String owner; - private final HddsProtos.ReplicationFactor replicationFactor; - - /** - * Constructs a Container Key. - * - * @param owner - Container Owners - * @param type - Replication Type. - * @param factor - Replication Factors - */ - public ContainerState(String owner, HddsProtos.ReplicationType type, - HddsProtos.ReplicationFactor factor) { - this.type = type; - this.owner = owner; - this.replicationFactor = factor; - } - - - public HddsProtos.ReplicationType getType() { - return type; - } - - public String getOwner() { - return owner; - } - - public HddsProtos.ReplicationFactor getFactor() { - return replicationFactor; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (o == null || getClass() != o.getClass()) { - return false; - } - - ContainerState that = (ContainerState) o; - - return new EqualsBuilder() - .append(type, that.type) - .append(owner, that.owner) - .append(replicationFactor, that.replicationFactor) - .isEquals(); - } - - @Override - public int hashCode() { - return new HashCodeBuilder(137, 757) - .append(type) - .append(owner) - .append(replicationFactor) - .toHashCode(); - } - - @Override - public String toString() { - return "ContainerKey{" + - ", type=" + type + - ", owner=" + owner + - ", replicationFactor=" + replicationFactor + - '}'; - } -} \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/states/ContainerStateMap.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/states/ContainerStateMap.java deleted file mode 100644 index 880a715f6bc..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/states/ContainerStateMap.java +++ /dev/null @@ -1,569 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ - -package org.apache.hadoop.hdds.scm.container.states; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import java.util.HashSet; -import java.util.Set; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.scm.container.ContainerID; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.LifeCycleState; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationFactor; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationType; -import org.apache.hadoop.hdds.scm.exceptions.SCMException.ResultCodes; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.NavigableSet; -import java.util.TreeSet; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.concurrent.ConcurrentHashMap; - -import static org.apache.hadoop.hdds.scm.exceptions.SCMException.ResultCodes - .CONTAINER_EXISTS; -import static org.apache.hadoop.hdds.scm.exceptions.SCMException.ResultCodes - .FAILED_TO_CHANGE_CONTAINER_STATE; -import static org.apache.hadoop.hdds.scm.exceptions.SCMException.ResultCodes - .FAILED_TO_FIND_CONTAINER; - -/** - * Container State Map acts like a unified map for various attributes that are - * used to select containers when we need allocated blocks. - *

- * This class provides the ability to query 5 classes of attributes. They are - *

- * 1. LifeCycleStates - LifeCycle States of container describe in which state - * a container is. For example, a container needs to be in Open State for a - * client to able to write to it. - *

- * 2. Owners - Each instance of Name service, for example, Namenode of HDFS or - * Ozone Manager (OM) of Ozone or CBlockServer -- is an owner. It is - * possible to have many OMs for a Ozone cluster and only one SCM. But SCM - * keeps the data from each OM in separate bucket, never mixing them. To - * write data, often we have to find all open containers for a specific owner. - *

- * 3. ReplicationType - The clients are allowed to specify what kind of - * replication pipeline they want to use. Each Container exists on top of a - * pipeline, so we need to get ReplicationType that is specified by the user. - *

- * 4. ReplicationFactor - The replication factor represents how many copies - * of data should be made, right now we support 2 different types, ONE - * Replica and THREE Replica. User can specify how many copies should be made - * for a ozone key. - *

- * The most common access pattern of this class is to select a container based - * on all these parameters, for example, when allocating a block we will - * select a container that belongs to user1, with Ratis replication which can - * make 3 copies of data. The fact that we will look for open containers by - * default and if we cannot find them we will add new containers. - */ -public class ContainerStateMap { - private static final Logger LOG = - LoggerFactory.getLogger(ContainerStateMap.class); - - private final ContainerAttribute lifeCycleStateMap; - private final ContainerAttribute ownerMap; - private final ContainerAttribute factorMap; - private final ContainerAttribute typeMap; - - private final Map containerMap; - // Map to hold replicas of given container. - private final Map> contReplicaMap; - private final static NavigableSet EMPTY_SET = - Collections.unmodifiableNavigableSet(new TreeSet<>()); - private final Map> resultCache; - - // Container State Map lock should be held before calling into - // Update ContainerAttributes. The consistency of ContainerAttributes is - // protected by this lock. - private final ReadWriteLock lock; - - /** - * Create a ContainerStateMap. - */ - public ContainerStateMap() { - lifeCycleStateMap = new ContainerAttribute<>(); - ownerMap = new ContainerAttribute<>(); - factorMap = new ContainerAttribute<>(); - typeMap = new ContainerAttribute<>(); - containerMap = new HashMap<>(); - lock = new ReentrantReadWriteLock(); - contReplicaMap = new HashMap<>(); -// new InstrumentedLock(getClass().getName(), LOG, -// new ReentrantLock(), -// 1000, -// 300)); - resultCache = new ConcurrentHashMap<>(); - } - - /** - * Adds a ContainerInfo Entry in the ContainerStateMap. - * - * @param info - container info - * @throws SCMException - throws if create failed. - */ - public void addContainer(ContainerInfo info) - throws SCMException { - Preconditions.checkNotNull(info, "Container Info cannot be null"); - Preconditions.checkArgument(info.getReplicationFactor().getNumber() > 0, - "ExpectedReplicaCount should be greater than 0"); - - lock.writeLock().lock(); - try { - ContainerID id = ContainerID.valueof(info.getContainerID()); - if (containerMap.putIfAbsent(id, info) != null) { - LOG.debug("Duplicate container ID detected. {}", id); - throw new - SCMException("Duplicate container ID detected.", - CONTAINER_EXISTS); - } - - lifeCycleStateMap.insert(info.getState(), id); - ownerMap.insert(info.getOwner(), id); - factorMap.insert(info.getReplicationFactor(), id); - typeMap.insert(info.getReplicationType(), id); - - // Flush the cache of this container type, will be added later when - // get container queries are executed. - flushCache(info); - LOG.trace("Created container with {} successfully.", id); - } finally { - lock.writeLock().unlock(); - } - } - - /** - * Returns the latest state of Container from SCM's Container State Map. - * - * @param info - ContainerInfo - * @return ContainerInfo - */ - public ContainerInfo getContainerInfo(ContainerInfo info) { - return getContainerInfo(info.getContainerID()); - } - - /** - * Returns the latest state of Container from SCM's Container State Map. - * - * @param containerID - int - * @return container info, if found. - */ - public ContainerInfo getContainerInfo(long containerID) { - return getContainerInfo(ContainerID.valueof(containerID)); - } - - /** - * Returns the latest state of Container from SCM's Container State Map. - * - * @param containerID - ContainerID - * @return container info, if found. - */ - public ContainerInfo getContainerInfo(ContainerID containerID) { - lock.readLock().lock(); - try { - return containerMap.get(containerID); - } finally { - lock.readLock().unlock(); - } - } - - /** - * Returns the latest list of DataNodes where replica for given containerId - * exist. Throws an SCMException if no entry is found for given containerId. - * - * @param containerID - * @return Set - */ - public Set getContainerReplicas(ContainerID containerID) - throws SCMException { - Preconditions.checkNotNull(containerID); - lock.readLock().lock(); - try { - if (contReplicaMap.containsKey(containerID)) { - return Collections - .unmodifiableSet(contReplicaMap.get(containerID)); - } - } finally { - lock.readLock().unlock(); - } - throw new SCMException( - "No entry exist for containerId: " + containerID + " in replica map.", - ResultCodes.NO_REPLICA_FOUND); - } - - /** - * Adds given datanodes as nodes where replica for given containerId exist. - * Logs a debug entry if a datanode is already added as replica for given - * ContainerId. - * - * @param containerID - * @param dnList - */ - public void addContainerReplica(ContainerID containerID, - DatanodeDetails... dnList) { - Preconditions.checkNotNull(containerID); - lock.writeLock().lock(); - try { - for (DatanodeDetails dn : dnList) { - Preconditions.checkNotNull(dn); - if (contReplicaMap.containsKey(containerID)) { - if(!contReplicaMap.get(containerID).add(dn)) { - LOG.debug("ReplicaMap already contains entry for container Id: " - + "{},DataNode: {}", containerID, dn); - } - } else { - Set dnSet = new HashSet<>(); - dnSet.add(dn); - contReplicaMap.put(containerID, dnSet); - } - } - } finally { - lock.writeLock().unlock(); - } - } - - /** - * Remove a container Replica for given DataNode. - * - * @param containerID - * @param dn - * @return True of dataNode is removed successfully else false. - */ - public boolean removeContainerReplica(ContainerID containerID, - DatanodeDetails dn) throws SCMException { - Preconditions.checkNotNull(containerID); - Preconditions.checkNotNull(dn); - - lock.writeLock().lock(); - try { - if (contReplicaMap.containsKey(containerID)) { - return contReplicaMap.get(containerID).remove(dn); - } - } finally { - lock.writeLock().unlock(); - } - throw new SCMException( - "No entry exist for containerId: " + containerID + " in replica map.", - ResultCodes.FAILED_TO_FIND_CONTAINER); - } - - @VisibleForTesting - public static Logger getLOG() { - return LOG; - } - - /** - * Returns the full container Map. - * - * @return - Map - */ - public Map getContainerMap() { - lock.readLock().lock(); - try { - return Collections.unmodifiableMap(containerMap); - } finally { - lock.readLock().unlock(); - } - } - - /** - * Just update the container State. - * @param info ContainerInfo. - */ - public void updateContainerInfo(ContainerInfo info) throws SCMException { - Preconditions.checkNotNull(info); - ContainerInfo currentInfo = null; - lock.writeLock().lock(); - try { - currentInfo = containerMap.get( - ContainerID.valueof(info.getContainerID())); - - if (currentInfo == null) { - throw new SCMException("No such container.", FAILED_TO_FIND_CONTAINER); - } - flushCache(info, currentInfo); - containerMap.put(info.containerID(), info); - } finally { - lock.writeLock().unlock(); - } - } - - /** - * Update the State of a container. - * - * @param info - ContainerInfo - * @param currentState - CurrentState - * @param newState - NewState. - * @throws SCMException - in case of failure. - */ - public void updateState(ContainerInfo info, LifeCycleState currentState, - LifeCycleState newState) throws SCMException { - Preconditions.checkNotNull(currentState); - Preconditions.checkNotNull(newState); - - ContainerID id = new ContainerID(info.getContainerID()); - ContainerInfo currentInfo = null; - - lock.writeLock().lock(); - try { - try { - // Just flush both old and new data sets from the result cache. - ContainerInfo newInfo = new ContainerInfo(info); - newInfo.setState(newState); - flushCache(newInfo, info); - - currentInfo = containerMap.get(id); - - if (currentInfo == null) { - throw new - SCMException("No such container.", FAILED_TO_FIND_CONTAINER); - } - // We are updating two places before this update is done, these can - // fail independently, since the code needs to handle it. - - // We update the attribute map, if that fails it will throw an - // exception, so no issues, if we are successful, we keep track of the - // fact that we have updated the lifecycle state in the map, and update - // the container state. If this second update fails, we will attempt to - // roll back the earlier change we did. If the rollback fails, we can - // be in an inconsistent state, - - info.setState(newState); - containerMap.put(id, info); - lifeCycleStateMap.update(currentState, newState, id); - LOG.trace("Updated the container {} to new state. Old = {}, new = " + - "{}", id, currentState, newState); - } catch (SCMException ex) { - LOG.error("Unable to update the container state. {}", ex); - // we need to revert the change in this attribute since we are not - // able to update the hash table. - LOG.info("Reverting the update to lifecycle state. Moving back to " + - "old state. Old = {}, Attempted state = {}", currentState, - newState); - - containerMap.put(id, currentInfo); - - // if this line throws, the state map can be in an inconsistent - // state, since we will have modified the attribute by the - // container state will not in sync since we were not able to put - // that into the hash table. - lifeCycleStateMap.update(newState, currentState, id); - - throw new SCMException("Updating the container map failed.", ex, - FAILED_TO_CHANGE_CONTAINER_STATE); - } - } finally { - lock.writeLock().unlock(); - } - } - - /** - * Returns A list of containers owned by a name service. - * - * @param ownerName - Name of the NameService. - * @return - NavigableSet of ContainerIDs. - */ - NavigableSet getContainerIDsByOwner(String ownerName) { - Preconditions.checkNotNull(ownerName); - lock.readLock().lock(); - try { - return ownerMap.getCollection(ownerName); - } finally { - lock.readLock().unlock(); - } - } - - /** - * Returns Containers in the System by the Type. - * - * @param type - Replication type -- StandAlone, Ratis etc. - * @return NavigableSet - */ - NavigableSet getContainerIDsByType(ReplicationType type) { - Preconditions.checkNotNull(type); - lock.readLock().lock(); - try { - return typeMap.getCollection(type); - } finally { - lock.readLock().unlock(); - } - } - - /** - * Returns Containers by replication factor. - * - * @param factor - Replication Factor. - * @return NavigableSet. - */ - NavigableSet getContainerIDsByFactor(ReplicationFactor factor) { - Preconditions.checkNotNull(factor); - lock.readLock().lock(); - try { - return factorMap.getCollection(factor); - } finally { - lock.readLock().unlock(); - } - } - - /** - * Returns Containers by State. - * - * @param state - State - Open, Closed etc. - * @return List of containers by state. - */ - public NavigableSet getContainerIDsByState( - LifeCycleState state) { - Preconditions.checkNotNull(state); - lock.readLock().lock(); - try { - return lifeCycleStateMap.getCollection(state); - } finally { - lock.readLock().unlock(); - } - } - - /** - * Gets the containers that matches the following filters. - * - * @param state - LifeCycleState - * @param owner - Owner - * @param factor - Replication Factor - * @param type - Replication Type - * @return ContainerInfo or Null if not container satisfies the criteria. - */ - public NavigableSet getMatchingContainerIDs( - LifeCycleState state, String owner, - ReplicationFactor factor, ReplicationType type) { - - Preconditions.checkNotNull(state, "State cannot be null"); - Preconditions.checkNotNull(owner, "Owner cannot be null"); - Preconditions.checkNotNull(factor, "Factor cannot be null"); - Preconditions.checkNotNull(type, "Type cannot be null"); - - lock.readLock().lock(); - try { - ContainerQueryKey queryKey = - new ContainerQueryKey(state, owner, factor, type); - if(resultCache.containsKey(queryKey)){ - return resultCache.get(queryKey); - } - - // If we cannot meet any one condition we return EMPTY_SET immediately. - // Since when we intersect these sets, the result will be empty if any - // one is empty. - NavigableSet stateSet = - lifeCycleStateMap.getCollection(state); - if (stateSet.size() == 0) { - return EMPTY_SET; - } - - NavigableSet ownerSet = ownerMap.getCollection(owner); - if (ownerSet.size() == 0) { - return EMPTY_SET; - } - - NavigableSet factorSet = factorMap.getCollection(factor); - if (factorSet.size() == 0) { - return EMPTY_SET; - } - - NavigableSet typeSet = typeMap.getCollection(type); - if (typeSet.size() == 0) { - return EMPTY_SET; - } - - - // if we add more constraints we will just add those sets here.. - NavigableSet[] sets = sortBySize(stateSet, - ownerSet, factorSet, typeSet); - - NavigableSet currentSet = sets[0]; - // We take the smallest set and intersect against the larger sets. This - // allows us to reduce the lookups to the least possible number. - for (int x = 1; x < sets.length; x++) { - currentSet = intersectSets(currentSet, sets[x]); - } - resultCache.put(queryKey, currentSet); - return currentSet; - } finally { - lock.readLock().unlock(); - } - } - - /** - * Calculates the intersection between sets and returns a new set. - * - * @param smaller - First Set - * @param bigger - Second Set - * @return resultSet which is the intersection of these two sets. - */ - private NavigableSet intersectSets( - NavigableSet smaller, - NavigableSet bigger) { - Preconditions.checkState(smaller.size() <= bigger.size(), - "This function assumes the first set is lesser or equal to second " + - "set"); - NavigableSet resultSet = new TreeSet<>(); - for (ContainerID id : smaller) { - if (bigger.contains(id)) { - resultSet.add(id); - } - } - return resultSet; - } - - /** - * Sorts a list of Sets based on Size. This is useful when we are - * intersecting the sets. - * - * @param sets - varagrs of sets - * @return Returns a sorted array of sets based on the size of the set. - */ - @SuppressWarnings("unchecked") - private NavigableSet[] sortBySize( - NavigableSet... sets) { - for (int x = 0; x < sets.length - 1; x++) { - for (int y = 0; y < sets.length - x - 1; y++) { - if (sets[y].size() > sets[y + 1].size()) { - NavigableSet temp = sets[y]; - sets[y] = sets[y + 1]; - sets[y + 1] = temp; - } - } - } - return sets; - } - - private void flushCache(ContainerInfo... containerInfos) { - for (ContainerInfo containerInfo : containerInfos) { - ContainerQueryKey key = new ContainerQueryKey(containerInfo.getState(), - containerInfo.getOwner(), containerInfo.getReplicationFactor(), - containerInfo.getReplicationType()); - resultCache.remove(key); - } - } - -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/states/package-info.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/states/package-info.java deleted file mode 100644 index 8ad1c8b842f..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/states/package-info.java +++ /dev/null @@ -1,22 +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 - * - * 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. - * - */ - -/** - * Container States package. - */ -package org.apache.hadoop.hdds.scm.container.states; \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/events/SCMEvents.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/events/SCMEvents.java deleted file mode 100644 index 77b87132a4a..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/events/SCMEvents.java +++ /dev/null @@ -1,255 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.hadoop.hdds.scm.events; - -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.scm.block.PendingDeleteStatusList; -import org.apache.hadoop.hdds.scm.command.CommandStatusReportHandler - .CloseContainerStatus; -import org.apache.hadoop.hdds.scm.command.CommandStatusReportHandler; -import org.apache.hadoop.hdds.scm.command.CommandStatusReportHandler - .ReplicationStatus; -import org.apache.hadoop.hdds.scm.container.CloseContainerEventHandler - .CloseContainerRetryableReq; -import org.apache.hadoop.hdds.scm.container.ContainerID; -import org.apache.hadoop.hdds.scm.container.common.helpers.PipelineID; -import org.apache.hadoop.hdds.scm.server.SCMDatanodeHeartbeatDispatcher - .PipelineReportFromDatanode; -import org.apache.hadoop.hdds.scm.server.SCMDatanodeHeartbeatDispatcher - .PipelineActionsFromDatanode; -import org.apache.hadoop.hdds.scm.server.SCMDatanodeHeartbeatDispatcher - .ContainerActionsFromDatanode; -import org.apache.hadoop.hdds.scm.server.SCMDatanodeHeartbeatDispatcher - .CommandStatusReportFromDatanode; -import org.apache.hadoop.hdds.scm.server.SCMDatanodeHeartbeatDispatcher - .ContainerReportFromDatanode; -import org.apache.hadoop.hdds.scm.server.SCMDatanodeHeartbeatDispatcher - .NodeReportFromDatanode; -import org.apache.hadoop.hdds.scm.container.replication.ReplicationManager; -import org.apache.hadoop.hdds.scm.container.replication.ReplicationManager - .ReplicationCompleted; -import org.apache.hadoop.hdds.scm.container.replication.ReplicationRequest; - -import org.apache.hadoop.hdds.scm.server.SCMDatanodeProtocolServer.NodeRegistrationContainerReport; -import org.apache.hadoop.hdds.server.events.Event; -import org.apache.hadoop.hdds.server.events.TypedEvent; -import org.apache.hadoop.ozone.protocol.commands.CommandForDatanode; - -/** - * Class that acts as the namespace for all SCM Events. - */ -public final class SCMEvents { - - /** - * NodeReports are sent out by Datanodes. This report is received by - * SCMDatanodeHeartbeatDispatcher and NodeReport Event is generated. - */ - public static final TypedEvent NODE_REPORT = - new TypedEvent<>(NodeReportFromDatanode.class, "Node_Report"); - - /** - * Event generated on DataNode registration. - */ - public static final TypedEvent - NODE_REGISTRATION_CONT_REPORT = new TypedEvent<>( - NodeRegistrationContainerReport.class, - "Node_Registration_Container_Report"); - - /** - * ContainerReports are send out by Datanodes. This report is received by - * SCMDatanodeHeartbeatDispatcher and Container_Report Event is generated. - */ - public static final TypedEvent CONTAINER_REPORT = - new TypedEvent<>(ContainerReportFromDatanode.class, "Container_Report"); - - /** - * ContainerActions are sent by Datanode. This event is received by - * SCMDatanodeHeartbeatDispatcher and CONTAINER_ACTIONS event is generated. - */ - public static final TypedEvent - CONTAINER_ACTIONS = new TypedEvent<>(ContainerActionsFromDatanode.class, - "Container_Actions"); - - /** - * PipelineReports are send out by Datanodes. This report is received by - * SCMDatanodeHeartbeatDispatcher and Pipeline_Report Event is generated. - */ - public static final TypedEvent PIPELINE_REPORT = - new TypedEvent<>(PipelineReportFromDatanode.class, "Pipeline_Report"); - - /** - * PipelineActions are sent by Datanode. This event is received by - * SCMDatanodeHeartbeatDispatcher and PIPELINE_ACTIONS event is generated. - */ - public static final TypedEvent - PIPELINE_ACTIONS = new TypedEvent<>(PipelineActionsFromDatanode.class, - "Pipeline_Actions"); - - /** - * Pipeline close event are triggered to close pipeline because of failure, - * stale node, decommissioning etc. - */ - public static final TypedEvent - PIPELINE_CLOSE = new TypedEvent<>(PipelineID.class, - "Pipeline_Close"); - - /** - * A Command status report will be sent by datanodes. This repoort is received - * by SCMDatanodeHeartbeatDispatcher and CommandReport event is generated. - */ - public static final TypedEvent - CMD_STATUS_REPORT = - new TypedEvent<>(CommandStatusReportFromDatanode.class, - "Cmd_Status_Report"); - - /** - * When ever a command for the Datanode needs to be issued by any component - * inside SCM, a Datanode_Command event is generated. NodeManager listens to - * these events and dispatches them to Datanode for further processing. - */ - public static final Event DATANODE_COMMAND = - new TypedEvent<>(CommandForDatanode.class, "Datanode_Command"); - - public static final TypedEvent - RETRIABLE_DATANODE_COMMAND = - new TypedEvent<>(CommandForDatanode.class, "Retriable_Datanode_Command"); - - /** - * A Close Container Event can be triggered under many condition. Some of them - * are: 1. A Container is full, then we stop writing further information to - * that container. DN's let SCM know that current state and sends a - * informational message that allows SCM to close the container. - *

- * 2. If a pipeline is open; for example Ratis; if a single node fails, we - * will proactively close these containers. - *

- * Once a command is dispatched to DN, we will also listen to updates from the - * datanode which lets us know that this command completed or timed out. - */ - public static final TypedEvent CLOSE_CONTAINER = - new TypedEvent<>(ContainerID.class, "Close_Container"); - - /** - * A CLOSE_CONTAINER_RETRYABLE_REQ will be triggered by - * CloseContainerEventHandler after sending a SCMCommand to DataNode. - * CloseContainerWatcher will track this event. Watcher will be responsible - * for retrying it in event of failure or timeout. - */ - public static final TypedEvent - CLOSE_CONTAINER_RETRYABLE_REQ = new TypedEvent<>( - CloseContainerRetryableReq.class, "Close_Container_Retryable"); - - /** - * This event will be triggered whenever a new datanode is registered with - * SCM. - */ - public static final TypedEvent NEW_NODE = - new TypedEvent<>(DatanodeDetails.class, "New_Node"); - - /** - * This event will be triggered whenever a datanode is moved from healthy to - * stale state. - */ - public static final TypedEvent STALE_NODE = - new TypedEvent<>(DatanodeDetails.class, "Stale_Node"); - - /** - * This event will be triggered whenever a datanode is moved from stale to - * dead state. - */ - public static final TypedEvent DEAD_NODE = - new TypedEvent<>(DatanodeDetails.class, "Dead_Node"); - - /** - * This event will be triggered by CommandStatusReportHandler whenever a - * status for Replication SCMCommand is received. - */ - public static final Event REPLICATION_STATUS = new - TypedEvent<>(ReplicationStatus.class, "Replicate_Command_Status"); - /** - * This event will be triggered by CommandStatusReportHandler whenever a - * status for CloseContainer SCMCommand is received. - */ - public static final Event - CLOSE_CONTAINER_STATUS = - new TypedEvent<>(CloseContainerStatus.class, - "Close_Container_Command_Status"); - /** - * This event will be triggered by CommandStatusReportHandler whenever a - * status for DeleteBlock SCMCommand is received. - */ - public static final TypedEvent - DELETE_BLOCK_STATUS = - new TypedEvent<>(CommandStatusReportHandler.DeleteBlockStatus.class, - "Delete_Block_Status"); - - /** - * This event will be triggered while processing container reports from DN - * when deleteTransactionID of container in report mismatches with the - * deleteTransactionID on SCM. - */ - public static final Event PENDING_DELETE_STATUS = - new TypedEvent<>(PendingDeleteStatusList.class, "Pending_Delete_Status"); - - /** - * This is the command for ReplicationManager to handle under/over - * replication. Sent by the ContainerReportHandler after processing the - * heartbeat. - */ - public static final TypedEvent REPLICATE_CONTAINER = - new TypedEvent<>(ReplicationRequest.class); - - /** - * This event is sent by the ReplicaManager to the - * ReplicationCommandWatcher to track the in-progress replication. - */ - public static final TypedEvent - TRACK_REPLICATE_COMMAND = - new TypedEvent<>(ReplicationManager.ReplicationRequestToRepeat.class); - /** - * This event comes from the Heartbeat dispatcher (in fact from the - * datanode) to notify the scm that the replication is done. This is - * received by the replicate command watcher to mark in-progress task as - * finished. -

- * TODO: Temporary event, should be replaced by specific Heartbeat - * ActionRequred event. - */ - public static final TypedEvent REPLICATION_COMPLETE = - new TypedEvent<>(ReplicationCompleted.class); - - /** - * Signal for all the components (but especially for the replication - * manager and container report handler) that the replication could be - * started. Should be send only if (almost) all the container state are - * available from the datanodes. - */ - public static final TypedEvent START_REPLICATION = - new TypedEvent<>(Boolean.class); - public static final TypedEvent CHILL_MODE_STATUS = - new TypedEvent<>(Boolean.class); - - /** - * Private Ctor. Never Constructed. - */ - private SCMEvents() { - } - -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/events/package-info.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/events/package-info.java deleted file mode 100644 index 46181a3eb5f..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/events/package-info.java +++ /dev/null @@ -1,23 +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 - * - * 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. - * - */ -/** - * Events Package contains all the Events used by SCM internally to - * communicate between different sub-systems that make up SCM. - */ -package org.apache.hadoop.hdds.scm.events; \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/exceptions/SCMException.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/exceptions/SCMException.java deleted file mode 100644 index dae0b065055..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/exceptions/SCMException.java +++ /dev/null @@ -1,124 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.exceptions; - -import java.io.IOException; - -/** - * Exception thrown by SCM. - */ -public class SCMException extends IOException { - private final ResultCodes result; - - /** - * Constructs an {@code IOException} with {@code null} - * as its error detail message. - */ - public SCMException(ResultCodes result) { - this.result = result; - } - - /** - * Constructs an {@code IOException} with the specified detail message. - * - * @param message The detail message (which is saved for later retrieval by - * the - * {@link #getMessage()} method) - */ - public SCMException(String message, ResultCodes result) { - super(message); - this.result = result; - } - - /** - * Constructs an {@code IOException} with the specified detail message - * and cause. - *

- *

Note that the detail message associated with {@code cause} is - * not automatically incorporated into this exception's detail - * message. - * - * @param message The detail message (which is saved for later retrieval by - * the - * {@link #getMessage()} method) - * @param cause The cause (which is saved for later retrieval by the {@link - * #getCause()} method). (A null value is permitted, and indicates that the - * cause is nonexistent or unknown.) - * @since 1.6 - */ - public SCMException(String message, Throwable cause, ResultCodes result) { - super(message, cause); - this.result = result; - } - - /** - * Constructs an {@code IOException} with the specified cause and a - * detail message of {@code (cause==null ? null : cause.toString())} - * (which typically contains the class and detail message of {@code cause}). - * This constructor is useful for IO exceptions that are little more - * than wrappers for other throwables. - * - * @param cause The cause (which is saved for later retrieval by the {@link - * #getCause()} method). (A null value is permitted, and indicates that the - * cause is nonexistent or unknown.) - * @since 1.6 - */ - public SCMException(Throwable cause, ResultCodes result) { - super(cause); - this.result = result; - } - - /** - * Returns resultCode. - * @return ResultCode - */ - public ResultCodes getResult() { - return result; - } - - /** - * Error codes to make it easy to decode these exceptions. - */ - public enum ResultCodes { - SUCCEESS, - FAILED_TO_LOAD_NODEPOOL, - FAILED_TO_FIND_NODE_IN_POOL, - FAILED_TO_FIND_HEALTHY_NODES, - FAILED_TO_FIND_NODES_WITH_SPACE, - FAILED_TO_FIND_SUITABLE_NODE, - INVALID_CAPACITY, - INVALID_BLOCK_SIZE, - CHILL_MODE_EXCEPTION, - FAILED_TO_LOAD_OPEN_CONTAINER, - FAILED_TO_ALLOCATE_CONTAINER, - FAILED_TO_CHANGE_CONTAINER_STATE, - FAILED_TO_CHANGE_PIPELINE_STATE, - CONTAINER_EXISTS, - FAILED_TO_FIND_CONTAINER, - FAILED_TO_FIND_CONTAINER_WITH_SPACE, - BLOCK_EXISTS, - FAILED_TO_FIND_BLOCK, - IO_EXCEPTION, - UNEXPECTED_CONTAINER_STATE, - SCM_NOT_INITIALIZED, - DUPLICATE_DATANODE, - NO_SUCH_DATANODE, - NO_REPLICA_FOUND, - FAILED_TO_FIND_ACTIVE_PIPELINE - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/exceptions/package-info.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/exceptions/package-info.java deleted file mode 100644 index 7b69310c239..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/exceptions/package-info.java +++ /dev/null @@ -1,18 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.scm.exceptions; -// Exceptions thrown by SCM. \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/CommandQueue.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/CommandQueue.java deleted file mode 100644 index 996478caaaf..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/CommandQueue.java +++ /dev/null @@ -1,190 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.node; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import org.apache.hadoop.ozone.protocol.commands.SCMCommand; -import org.apache.hadoop.util.Time; - -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -/** - * Command Queue is queue of commands for the datanode. - *

- * Node manager, container Manager and Ozone managers can queue commands for - * datanodes into this queue. These commands will be send in the order in which - * there where queued. - */ -public class CommandQueue { - // This list is used as default return value. - private static final List DEFAULT_LIST = new LinkedList<>(); - private final Map commandMap; - private final Lock lock; - private long commandsInQueue; - - /** - * Returns number of commands in queue. - * @return Command Count. - */ - public long getCommandsInQueue() { - return commandsInQueue; - } - - /** - * Constructs a Command Queue. - * TODO : Add a flusher thread that throws away commands older than a certain - * time period. - */ - public CommandQueue() { - commandMap = new HashMap<>(); - lock = new ReentrantLock(); - commandsInQueue = 0; - } - - /** - * This function is used only for test purposes. - */ - @VisibleForTesting - public void clear() { - lock.lock(); - try { - commandMap.clear(); - commandsInQueue = 0; - } finally { - lock.unlock(); - } - } - - /** - * Returns a list of Commands for the datanode to execute, if we have no - * commands returns a empty list otherwise the current set of - * commands are returned and command map set to empty list again. - * - * @param datanodeUuid Datanode UUID - * @return List of SCM Commands. - */ - @SuppressWarnings("unchecked") - List getCommand(final UUID datanodeUuid) { - lock.lock(); - try { - Commands cmds = commandMap.remove(datanodeUuid); - List cmdList = null; - if(cmds != null) { - cmdList = cmds.getCommands(); - commandsInQueue -= cmdList.size() > 0 ? cmdList.size() : 0; - // A post condition really. - Preconditions.checkState(commandsInQueue >= 0); - } - return cmds == null ? DEFAULT_LIST : cmdList; - } finally { - lock.unlock(); - } - } - - /** - * Adds a Command to the SCM Queue to send the command to container. - * - * @param datanodeUuid DatanodeDetails.Uuid - * @param command - Command - */ - public void addCommand(final UUID datanodeUuid, final SCMCommand - command) { - lock.lock(); - try { - if (commandMap.containsKey(datanodeUuid)) { - commandMap.get(datanodeUuid).add(command); - } else { - commandMap.put(datanodeUuid, new Commands(command)); - } - commandsInQueue++; - } finally { - lock.unlock(); - } - } - - /** - * Class that stores commands for a datanode. - */ - private static class Commands { - private long updateTime; - private long readTime; - private List commands; - - /** - * Constructs a Commands class. - */ - Commands() { - commands = new LinkedList<>(); - updateTime = 0; - readTime = 0; - } - - /** - * Creates the object and populates with the command. - * @param command command to add to queue. - */ - Commands(SCMCommand command) { - this(); - this.add(command); - } - - /** - * Gets the last time the commands for this node was updated. - * @return Time stamp - */ - public long getUpdateTime() { - return updateTime; - } - - /** - * Gets the last read time. - * @return last time when these commands were read from this queue. - */ - public long getReadTime() { - return readTime; - } - - /** - * Adds a command to the list. - * - * @param command SCMCommand - */ - public void add(SCMCommand command) { - this.commands.add(command); - updateTime = Time.monotonicNow(); - } - - /** - * Returns the commands for this datanode. - * @return command list. - */ - public List getCommands() { - List temp = this.commands; - this.commands = new LinkedList<>(); - readTime = Time.monotonicNow(); - return temp; - } - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/DatanodeInfo.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/DatanodeInfo.java deleted file mode 100644 index 26b8b95b040..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/DatanodeInfo.java +++ /dev/null @@ -1,128 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.node; - -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.StorageReportProto; -import org.apache.hadoop.util.Time; - -import java.util.List; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -/** - * This class extends the primary identifier of a Datanode with ephemeral - * state, eg last reported time, usage information etc. - */ -public class DatanodeInfo extends DatanodeDetails { - - private final ReadWriteLock lock; - - private volatile long lastHeartbeatTime; - private long lastStatsUpdatedTime; - - // If required we can dissect StorageReportProto and store the raw data - private List storageReports; - - /** - * Constructs DatanodeInfo from DatanodeDetails. - * - * @param datanodeDetails Details about the datanode - */ - public DatanodeInfo(DatanodeDetails datanodeDetails) { - super(datanodeDetails); - lock = new ReentrantReadWriteLock(); - lastHeartbeatTime = Time.monotonicNow(); - } - - /** - * Updates the last heartbeat time with current time. - */ - public void updateLastHeartbeatTime() { - try { - lock.writeLock().lock(); - lastHeartbeatTime = Time.monotonicNow(); - } finally { - lock.writeLock().unlock(); - } - } - - /** - * Returns the last heartbeat time. - * - * @return last heartbeat time. - */ - public long getLastHeartbeatTime() { - try { - lock.readLock().lock(); - return lastHeartbeatTime; - } finally { - lock.readLock().unlock(); - } - } - - /** - * Updates the datanode storage reports. - * - * @param reports list of storage report - */ - public void updateStorageReports(List reports) { - try { - lock.writeLock().lock(); - lastStatsUpdatedTime = Time.monotonicNow(); - storageReports = reports; - } finally { - lock.writeLock().unlock(); - } - } - - /** - * Returns the storage reports associated with this datanode. - * - * @return list of storage report - */ - public List getStorageReports() { - try { - lock.readLock().lock(); - return storageReports; - } finally { - lock.readLock().unlock(); - } - } - - /** - * Returns the last updated time of datanode info. - * @return the last updated time of datanode info. - */ - public long getLastStatsUpdatedTime() { - return lastStatsUpdatedTime; - } - - @Override - public int hashCode() { - return super.hashCode(); - } - - @Override - public boolean equals(Object obj) { - return super.equals(obj); - } - -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/DeadNodeHandler.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/DeadNodeHandler.java deleted file mode 100644 index 17edf9ea17a..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/DeadNodeHandler.java +++ /dev/null @@ -1,100 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.node; - -import java.util.Set; - -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.scm.container.ContainerID; -import org.apache.hadoop.hdds.scm.container.ContainerStateManager; -import org.apache.hadoop.hdds.scm.container.replication.ReplicationRequest; -import org.apache.hadoop.hdds.scm.events.SCMEvents; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.hdds.server.events.EventHandler; -import org.apache.hadoop.hdds.server.events.EventPublisher; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Handles Dead Node event. - */ -public class DeadNodeHandler implements EventHandler { - - private final ContainerStateManager containerStateManager; - - private final NodeManager nodeManager; - - private static final Logger LOG = - LoggerFactory.getLogger(DeadNodeHandler.class); - - public DeadNodeHandler(NodeManager nodeManager, - ContainerStateManager containerStateManager) { - this.containerStateManager = containerStateManager; - this.nodeManager = nodeManager; - } - - @Override - public void onMessage(DatanodeDetails datanodeDetails, - EventPublisher publisher) { - nodeManager.processDeadNode(datanodeDetails.getUuid()); - - Set containers = - nodeManager.getContainers(datanodeDetails.getUuid()); - if (containers == null) { - LOG.info("There's no containers in dead datanode {}, no replica will be" - + " removed from the in-memory state.", datanodeDetails.getUuid()); - return; - } - LOG.info( - "Datanode {} is dead. Removing replications from the in-memory state.", - datanodeDetails.getUuid()); - for (ContainerID container : containers) { - try { - try { - containerStateManager.removeContainerReplica(container, - datanodeDetails); - } catch (SCMException ex) { - LOG.info("DataNode {} doesn't have replica for container {}.", - datanodeDetails.getUuid(), container.getId()); - } - - if (!containerStateManager.isOpen(container)) { - ReplicationRequest replicationRequest = - containerStateManager.checkReplicationState(container); - - if (replicationRequest != null) { - publisher.fireEvent(SCMEvents.REPLICATE_CONTAINER, - replicationRequest); - } - } - } catch (SCMException e) { - LOG.error("Can't remove container from containerStateMap {}", container - .getId(), e); - } - } - } - - /** - * Returns logger. - * */ - public static Logger getLogger() { - return LOG; - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/NewNodeHandler.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/NewNodeHandler.java deleted file mode 100644 index 780aa2b9e7e..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/NewNodeHandler.java +++ /dev/null @@ -1,49 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.node; - -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.hdds.server.events.EventHandler; -import org.apache.hadoop.hdds.server.events.EventPublisher; - -import java.util.Collections; - -/** - * Handles New Node event. - */ -public class NewNodeHandler implements EventHandler { - - private final NodeManager nodeManager; - - public NewNodeHandler(NodeManager nodeManager) { - this.nodeManager = nodeManager; - } - - @Override - public void onMessage(DatanodeDetails datanodeDetails, - EventPublisher publisher) { - try { - nodeManager.addDatanodeInContainerMap(datanodeDetails.getUuid(), - Collections.emptySet()); - } catch (SCMException e) { - // TODO: log exception message. - } - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/NodeManager.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/NodeManager.java deleted file mode 100644 index 0dc1a0c5d6c..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/NodeManager.java +++ /dev/null @@ -1,219 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.node; - -import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.NodeReportProto; -import org.apache.hadoop.hdds.scm.container.ContainerID; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.scm.container.common.helpers.PipelineID; -import org.apache.hadoop.hdds.scm.container.placement.metrics.SCMNodeMetric; -import org.apache.hadoop.hdds.scm.container.placement.metrics.SCMNodeStat; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.hdds.scm.node.states.NodeNotFoundException; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState; -import org.apache.hadoop.hdds.scm.node.states.ReportResult; -import org.apache.hadoop.hdds.server.events.EventHandler; -import org.apache.hadoop.ozone.protocol.StorageContainerNodeProtocol; -import org.apache.hadoop.ozone.protocol.commands.CommandForDatanode; -import org.apache.hadoop.ozone.protocol.commands.SCMCommand; - -import java.io.Closeable; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - -/** - * A node manager supports a simple interface for managing a datanode. - *

- * 1. A datanode registers with the NodeManager. - *

- * 2. If the node is allowed to register, we add that to the nodes that we need - * to keep track of. - *

- * 3. A heartbeat is made by the node at a fixed frequency. - *

- * 4. A node can be in any of these 4 states: {HEALTHY, STALE, DEAD, - * DECOMMISSIONED} - *

- * HEALTHY - It is a datanode that is regularly heartbeating us. - * - * STALE - A datanode for which we have missed few heart beats. - * - * DEAD - A datanode that we have not heard from for a while. - * - * DECOMMISSIONED - Someone told us to remove this node from the tracking - * list, by calling removeNode. We will throw away this nodes info soon. - */ -public interface NodeManager extends StorageContainerNodeProtocol, - EventHandler, NodeManagerMXBean, Closeable { - /** - * Removes a data node from the management of this Node Manager. - * - * @param node - DataNode. - * @throws NodeNotFoundException - */ - void removeNode(DatanodeDetails node) throws NodeNotFoundException; - - /** - * Gets all Live Datanodes that is currently communicating with SCM. - * @param nodeState - State of the node - * @return List of Datanodes that are Heartbeating SCM. - */ - List getNodes(NodeState nodeState); - - /** - * Returns the Number of Datanodes that are communicating with SCM. - * @param nodeState - State of the node - * @return int -- count - */ - int getNodeCount(NodeState nodeState); - - /** - * Get all datanodes known to SCM. - * - * @return List of DatanodeDetails known to SCM. - */ - List getAllNodes(); - - /** - * Chill mode is the period when node manager waits for a minimum - * configured number of datanodes to report in. This is called chill mode - * to indicate the period before node manager gets into action. - * - * Forcefully exits the chill mode, even if we have not met the minimum - * criteria of the nodes reporting in. - */ - void forceExitChillMode(); - - /** - * Puts the node manager into manual chill mode. - */ - void enterChillMode(); - - /** - * Brings node manager out of manual chill mode. - */ - void exitChillMode(); - - /** - * Returns the aggregated node stats. - * @return the aggregated node stats. - */ - SCMNodeStat getStats(); - - /** - * Return a map of node stats. - * @return a map of individual node stats (live/stale but not dead). - */ - Map getNodeStats(); - - /** - * Return the node stat of the specified datanode. - * @param datanodeDetails DatanodeDetails. - * @return node stat if it is live/stale, null if it is decommissioned or - * doesn't exist. - */ - SCMNodeMetric getNodeStat(DatanodeDetails datanodeDetails); - - /** - * Returns the node state of a specific node. - * @param datanodeDetails DatanodeDetails - * @return Healthy/Stale/Dead. - */ - NodeState getNodeState(DatanodeDetails datanodeDetails); - - /** - * Get set of pipelines a datanode is part of. - * @param dnId - datanodeID - * @return Set of PipelineID - */ - Set getPipelineByDnID(UUID dnId); - - /** - * Add pipeline information in the NodeManager. - * @param pipeline - Pipeline to be added - */ - void addPipeline(Pipeline pipeline); - - /** - * Remove a pipeline information from the NodeManager. - * @param pipeline - Pipeline to be removed - */ - void removePipeline(Pipeline pipeline); - - /** - * Update set of containers available on a datanode. - * @param uuid - DatanodeID - * @param containerIds - Set of containerIDs - * @throws SCMException - if datanode is not known. For new datanode use - * addDatanodeInContainerMap call. - */ - void setContainersForDatanode(UUID uuid, Set containerIds) - throws SCMException; - - /** - * Process containerReport received from datanode. - * @param uuid - DataonodeID - * @param containerIds - Set of containerIDs - * @return The result after processing containerReport - */ - ReportResult processContainerReport(UUID uuid, - Set containerIds); - - /** - * Return set of containerIDs available on a datanode. - * @param uuid - DatanodeID - * @return - set of containerIDs - */ - Set getContainers(UUID uuid); - - /** - * Insert a new datanode with set of containerIDs for containers available - * on it. - * @param uuid - DatanodeID - * @param containerIDs - Set of ContainerIDs - * @throws SCMException - if datanode already exists - */ - void addDatanodeInContainerMap(UUID uuid, Set containerIDs) - throws SCMException; - - /** - * Add a {@link SCMCommand} to the command queue, which are - * handled by HB thread asynchronously. - * @param dnId datanode uuid - * @param command - */ - void addDatanodeCommand(UUID dnId, SCMCommand command); - - /** - * Process node report. - * - * @param dnUuid - * @param nodeReport - */ - void processNodeReport(UUID dnUuid, NodeReportProto nodeReport); - - /** - * Process a dead node event in this Node Manager. - * - * @param dnUuid datanode uuid. - */ - void processDeadNode(UUID dnUuid); -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/NodeManagerMXBean.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/NodeManagerMXBean.java deleted file mode 100644 index 3ac993b77d9..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/NodeManagerMXBean.java +++ /dev/null @@ -1,57 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.node; - -import org.apache.hadoop.classification.InterfaceAudience; - -import java.util.Map; - -/** - * - * This is the JMX management interface for node manager information. - */ -@InterfaceAudience.Private -public interface NodeManagerMXBean { - /** - * Get the minimum number of nodes to get out of chill mode. - * - * @return int - */ - int getMinimumChillModeNodes(); - - /** - * Returns a chill mode status string. - * @return String - */ - String getChillModeStatus(); - - - /** - * Returns true if node manager is out of chill mode, else false. - * @return true if out of chill mode, else false - */ - boolean isOutOfChillMode(); - - /** - * Get the number of data nodes that in all states. - * - * @return A state to number of nodes that in this state mapping - */ - Map getNodeCount(); -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/NodeReportHandler.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/NodeReportHandler.java deleted file mode 100644 index 331bfed1ab3..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/NodeReportHandler.java +++ /dev/null @@ -1,55 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.node; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.scm.server.SCMDatanodeHeartbeatDispatcher - .NodeReportFromDatanode; -import org.apache.hadoop.hdds.server.events.EventHandler; -import org.apache.hadoop.hdds.server.events.EventPublisher; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Handles Node Reports from datanode. - */ -public class NodeReportHandler implements EventHandler { - - private static final Logger LOGGER = LoggerFactory - .getLogger(NodeReportHandler.class); - private final NodeManager nodeManager; - - public NodeReportHandler(NodeManager nodeManager) { - Preconditions.checkNotNull(nodeManager); - this.nodeManager = nodeManager; - } - - @Override - public void onMessage(NodeReportFromDatanode nodeReportFromDatanode, - EventPublisher publisher) { - Preconditions.checkNotNull(nodeReportFromDatanode); - DatanodeDetails dn = nodeReportFromDatanode.getDatanodeDetails(); - Preconditions.checkNotNull(dn, "NodeReport is " - + "missing DatanodeDetails."); - LOGGER.trace("Processing node report for dn: {}", dn); - nodeManager - .processNodeReport(dn.getUuid(), nodeReportFromDatanode.getReport()); - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/NodeStateManager.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/NodeStateManager.java deleted file mode 100644 index 88f984b6736..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/NodeStateManager.java +++ /dev/null @@ -1,725 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.node; - -import com.google.common.base.Preconditions; -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState; -import org.apache.hadoop.hdds.scm.HddsServerUtil; -import org.apache.hadoop.hdds.scm.container.ContainerID; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.scm.container.common.helpers.PipelineID; -import org.apache.hadoop.hdds.scm.container.placement.metrics.SCMNodeStat; -import org.apache.hadoop.hdds.scm.events.SCMEvents; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.hdds.scm.node.states.*; -import org.apache.hadoop.hdds.scm.node.states.Node2PipelineMap; -import org.apache.hadoop.hdds.server.events.Event; -import org.apache.hadoop.hdds.server.events.EventPublisher; -import org.apache.hadoop.ozone.common.statemachine - .InvalidStateTransitionException; -import org.apache.hadoop.ozone.common.statemachine.StateMachine; -import org.apache.hadoop.util.Time; -import org.apache.hadoop.util.concurrent.HadoopExecutors; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.Closeable; -import java.util.*; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.function.Predicate; - -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_DEADNODE_INTERVAL; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_HEARTBEAT_PROCESS_INTERVAL; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_STALENODE_INTERVAL; - -/** - * NodeStateManager maintains the state of all the datanodes in the cluster. All - * the node state change should happen only via NodeStateManager. It also - * runs a heartbeat thread which periodically updates the node state. - *

- * The getNode(byState) functions make copy of node maps and then creates a list - * based on that. It should be assumed that these get functions always report - * *stale* information. For example, getting the deadNodeCount followed by - * getNodes(DEAD) could very well produce totally different count. Also - * getNodeCount(HEALTHY) + getNodeCount(DEAD) + getNodeCode(STALE), is not - * guaranteed to add up to the total nodes that we know off. Please treat all - * get functions in this file as a snap-shot of information that is inconsistent - * as soon as you read it. - */ -public class NodeStateManager implements Runnable, Closeable { - - /** - * Node's life cycle events. - */ - private enum NodeLifeCycleEvent { - TIMEOUT, RESTORE, RESURRECT, DECOMMISSION, DECOMMISSIONED - } - - private static final Logger LOG = LoggerFactory - .getLogger(NodeStateManager.class); - - /** - * StateMachine for node lifecycle. - */ - private final StateMachine stateMachine; - /** - * This is the map which maintains the current state of all datanodes. - */ - private final NodeStateMap nodeStateMap; - /** - * Maintains the mapping from node to pipelines a node is part of. - */ - private final Node2PipelineMap node2PipelineMap; - /** - * Maintains the map from node to ContainerIDs for the containers - * available on the node. - */ - private final Node2ContainerMap node2ContainerMap; - /** - * Used for publishing node state change events. - */ - private final EventPublisher eventPublisher; - /** - * Maps the event to be triggered when a node state us updated. - */ - private final Map> state2EventMap; - /** - * ExecutorService used for scheduling heartbeat processing thread. - */ - private final ScheduledExecutorService executorService; - /** - * The frequency in which we have run the heartbeat processing thread. - */ - private final long heartbeatCheckerIntervalMs; - /** - * The timeout value which will be used for marking a datanode as stale. - */ - private final long staleNodeIntervalMs; - /** - * The timeout value which will be used for marking a datanode as dead. - */ - private final long deadNodeIntervalMs; - - /** - * Constructs a NodeStateManager instance with the given configuration. - * - * @param conf Configuration - */ - public NodeStateManager(Configuration conf, EventPublisher eventPublisher) { - this.nodeStateMap = new NodeStateMap(); - this.node2PipelineMap = new Node2PipelineMap(); - this.node2ContainerMap = new Node2ContainerMap(); - this.eventPublisher = eventPublisher; - this.state2EventMap = new HashMap<>(); - initialiseState2EventMap(); - Set finalStates = new HashSet<>(); - finalStates.add(NodeState.DECOMMISSIONED); - this.stateMachine = new StateMachine<>(NodeState.HEALTHY, finalStates); - initializeStateMachine(); - heartbeatCheckerIntervalMs = HddsServerUtil - .getScmheartbeatCheckerInterval(conf); - staleNodeIntervalMs = HddsServerUtil.getStaleNodeInterval(conf); - deadNodeIntervalMs = HddsServerUtil.getDeadNodeInterval(conf); - Preconditions.checkState(heartbeatCheckerIntervalMs > 0, - OZONE_SCM_HEARTBEAT_PROCESS_INTERVAL + " should be greater than 0."); - Preconditions.checkState(staleNodeIntervalMs < deadNodeIntervalMs, - OZONE_SCM_STALENODE_INTERVAL + " should be less than" + - OZONE_SCM_DEADNODE_INTERVAL); - executorService = HadoopExecutors.newScheduledThreadPool(1, - new ThreadFactoryBuilder().setDaemon(true) - .setNameFormat("SCM Heartbeat Processing Thread - %d").build()); - executorService.schedule(this, heartbeatCheckerIntervalMs, - TimeUnit.MILLISECONDS); - } - - /** - * Populates state2event map. - */ - private void initialiseState2EventMap() { - state2EventMap.put(NodeState.STALE, SCMEvents.STALE_NODE); - state2EventMap.put(NodeState.DEAD, SCMEvents.DEAD_NODE); - } - - /* - * - * Node and State Transition Mapping: - * - * State: HEALTHY -------------------> STALE - * Event: TIMEOUT - * - * State: STALE -------------------> DEAD - * Event: TIMEOUT - * - * State: STALE -------------------> HEALTHY - * Event: RESTORE - * - * State: DEAD -------------------> HEALTHY - * Event: RESURRECT - * - * State: HEALTHY -------------------> DECOMMISSIONING - * Event: DECOMMISSION - * - * State: STALE -------------------> DECOMMISSIONING - * Event: DECOMMISSION - * - * State: DEAD -------------------> DECOMMISSIONING - * Event: DECOMMISSION - * - * State: DECOMMISSIONING -------------------> DECOMMISSIONED - * Event: DECOMMISSIONED - * - * Node State Flow - * - * +--------------------------------------------------------+ - * | (RESURRECT) | - * | +--------------------------+ | - * | | (RESTORE) | | - * | | | | - * V V | | - * [HEALTHY]------------------->[STALE]------------------->[DEAD] - * | (TIMEOUT) | (TIMEOUT) | - * | | | - * | | | - * | | | - * | | | - * | (DECOMMISSION) | (DECOMMISSION) | (DECOMMISSION) - * | V | - * +------------------->[DECOMMISSIONING]<----------------+ - * | - * | (DECOMMISSIONED) - * | - * V - * [DECOMMISSIONED] - * - */ - - /** - * Initializes the lifecycle of node state machine. - */ - private void initializeStateMachine() { - stateMachine.addTransition( - NodeState.HEALTHY, NodeState.STALE, NodeLifeCycleEvent.TIMEOUT); - stateMachine.addTransition( - NodeState.STALE, NodeState.DEAD, NodeLifeCycleEvent.TIMEOUT); - stateMachine.addTransition( - NodeState.STALE, NodeState.HEALTHY, NodeLifeCycleEvent.RESTORE); - stateMachine.addTransition( - NodeState.DEAD, NodeState.HEALTHY, NodeLifeCycleEvent.RESURRECT); - stateMachine.addTransition( - NodeState.HEALTHY, NodeState.DECOMMISSIONING, - NodeLifeCycleEvent.DECOMMISSION); - stateMachine.addTransition( - NodeState.STALE, NodeState.DECOMMISSIONING, - NodeLifeCycleEvent.DECOMMISSION); - stateMachine.addTransition( - NodeState.DEAD, NodeState.DECOMMISSIONING, - NodeLifeCycleEvent.DECOMMISSION); - stateMachine.addTransition( - NodeState.DECOMMISSIONING, NodeState.DECOMMISSIONED, - NodeLifeCycleEvent.DECOMMISSIONED); - - } - - /** - * Adds a new node to the state manager. - * - * @param datanodeDetails DatanodeDetails - * - * @throws NodeAlreadyExistsException if the node is already present - */ - public void addNode(DatanodeDetails datanodeDetails) - throws NodeAlreadyExistsException { - nodeStateMap.addNode(datanodeDetails, stateMachine.getInitialState()); - eventPublisher.fireEvent(SCMEvents.NEW_NODE, datanodeDetails); - } - - /** - * Adds a pipeline in the node2PipelineMap. - * @param pipeline - Pipeline to be added - */ - public void addPipeline(Pipeline pipeline) { - node2PipelineMap.addPipeline(pipeline); - } - - /** - * Get information about the node. - * - * @param datanodeDetails DatanodeDetails - * - * @return DatanodeInfo - * - * @throws NodeNotFoundException if the node is not present - */ - public DatanodeInfo getNode(DatanodeDetails datanodeDetails) - throws NodeNotFoundException { - return nodeStateMap.getNodeInfo(datanodeDetails.getUuid()); - } - - /** - * Updates the last heartbeat time of the node. - * - * @throws NodeNotFoundException if the node is not present - */ - public void updateLastHeartbeatTime(DatanodeDetails datanodeDetails) - throws NodeNotFoundException { - nodeStateMap.getNodeInfo(datanodeDetails.getUuid()) - .updateLastHeartbeatTime(); - } - - /** - * Returns the current state of the node. - * - * @param datanodeDetails DatanodeDetails - * - * @return NodeState - * - * @throws NodeNotFoundException if the node is not present - */ - public NodeState getNodeState(DatanodeDetails datanodeDetails) - throws NodeNotFoundException { - return nodeStateMap.getNodeState(datanodeDetails.getUuid()); - } - - /** - * Returns all the node which are in healthy state. - * - * @return list of healthy nodes - */ - public List getHealthyNodes() { - return getNodes(NodeState.HEALTHY); - } - - /** - * Returns all the node which are in stale state. - * - * @return list of stale nodes - */ - public List getStaleNodes() { - return getNodes(NodeState.STALE); - } - - /** - * Returns all the node which are in dead state. - * - * @return list of dead nodes - */ - public List getDeadNodes() { - return getNodes(NodeState.DEAD); - } - - /** - * Returns all the node which are in the specified state. - * - * @param state NodeState - * - * @return list of nodes - */ - public List getNodes(NodeState state) { - List nodes = new LinkedList<>(); - nodeStateMap.getNodes(state).forEach( - uuid -> { - try { - nodes.add(nodeStateMap.getNodeDetails(uuid)); - } catch (NodeNotFoundException e) { - // This should not happen unless someone else other than - // NodeStateManager is directly modifying NodeStateMap and removed - // the node entry after we got the list of UUIDs. - LOG.error("Inconsistent NodeStateMap! " + nodeStateMap); - } - }); - return nodes; - } - - /** - * Returns all the nodes which have registered to NodeStateManager. - * - * @return all the managed nodes - */ - public List getAllNodes() { - List nodes = new LinkedList<>(); - nodeStateMap.getAllNodes().forEach( - uuid -> { - try { - nodes.add(nodeStateMap.getNodeDetails(uuid)); - } catch (NodeNotFoundException e) { - // This should not happen unless someone else other than - // NodeStateManager is directly modifying NodeStateMap and removed - // the node entry after we got the list of UUIDs. - LOG.error("Inconsistent NodeStateMap! " + nodeStateMap); - } - }); - return nodes; - } - - /** - * Gets set of pipelineID a datanode belongs to. - * @param dnId - Datanode ID - * @return Set of PipelineID - */ - public Set getPipelineByDnID(UUID dnId) { - return node2PipelineMap.getPipelines(dnId); - } - - /** - * Returns the count of healthy nodes. - * - * @return healthy node count - */ - public int getHealthyNodeCount() { - return getNodeCount(NodeState.HEALTHY); - } - - /** - * Returns the count of stale nodes. - * - * @return stale node count - */ - public int getStaleNodeCount() { - return getNodeCount(NodeState.STALE); - } - - /** - * Returns the count of dead nodes. - * - * @return dead node count - */ - public int getDeadNodeCount() { - return getNodeCount(NodeState.DEAD); - } - - /** - * Returns the count of nodes in specified state. - * - * @param state NodeState - * - * @return node count - */ - public int getNodeCount(NodeState state) { - return nodeStateMap.getNodeCount(state); - } - - /** - * Returns the count of all nodes managed by NodeStateManager. - * - * @return node count - */ - public int getTotalNodeCount() { - return nodeStateMap.getTotalNodeCount(); - } - - /** - * Removes a node from NodeStateManager. - * - * @param datanodeDetails DatanodeDetails - * - * @throws NodeNotFoundException if the node is not present - */ - public void removeNode(DatanodeDetails datanodeDetails) - throws NodeNotFoundException { - nodeStateMap.removeNode(datanodeDetails.getUuid()); - } - - /** - * Returns the current stats of the node. - * - * @param uuid node id - * - * @return SCMNodeStat - * - * @throws NodeNotFoundException if the node is not present - */ - public SCMNodeStat getNodeStat(UUID uuid) throws NodeNotFoundException { - return nodeStateMap.getNodeStat(uuid); - } - - /** - * Returns a unmodifiable copy of nodeStats. - * @return map with node stats. - */ - public Map getNodeStatsMap() { - return nodeStateMap.getNodeStats(); - } - - /** - * Set the stat for the node. - * - * @param uuid node id. - * - * @param newstat new stat that will set to the specify node. - */ - public void setNodeStat(UUID uuid, SCMNodeStat newstat) { - nodeStateMap.setNodeStat(uuid, newstat); - } - - /** - * Remove the current stats of the specify node. - * - * @param uuid node id - * - * @return SCMNodeStat the stat removed from the node. - * - * @throws NodeNotFoundException if the node is not present. - */ - public SCMNodeStat removeNodeStat(UUID uuid) throws NodeNotFoundException { - return nodeStateMap.removeNodeStat(uuid); - } - - /** - * Removes a pipeline from the node2PipelineMap. - * @param pipeline - Pipeline to be removed - */ - public void removePipeline(Pipeline pipeline) { - node2PipelineMap.removePipeline(pipeline); - } - /** - * Update set of containers available on a datanode. - * @param uuid - DatanodeID - * @param containerIds - Set of containerIDs - * @throws SCMException - if datanode is not known. For new datanode use - * addDatanodeInContainerMap call. - */ - public void setContainersForDatanode(UUID uuid, Set containerIds) - throws SCMException { - node2ContainerMap.setContainersForDatanode(uuid, containerIds); - } - - /** - * Process containerReport received from datanode. - * @param uuid - DataonodeID - * @param containerIds - Set of containerIDs - * @return The result after processing containerReport - */ - public ReportResult processContainerReport(UUID uuid, - Set containerIds) { - return node2ContainerMap.processReport(uuid, containerIds); - } - - /** - * Return set of containerIDs available on a datanode. - * @param uuid - DatanodeID - * @return - set of containerIDs - */ - public Set getContainers(UUID uuid) { - return node2ContainerMap.getContainers(uuid); - } - - /** - * Insert a new datanode with set of containerIDs for containers available - * on it. - * @param uuid - DatanodeID - * @param containerIDs - Set of ContainerIDs - * @throws SCMException - if datanode already exists - */ - public void addDatanodeInContainerMap(UUID uuid, - Set containerIDs) throws SCMException { - node2ContainerMap.insertNewDatanode(uuid, containerIDs); - } - - /** - * Move Stale or Dead node to healthy if we got a heartbeat from them. - * Move healthy nodes to stale nodes if it is needed. - * Move Stales node to dead if needed. - * - * @see Thread#run() - */ - @Override - public void run() { - - /* - * - * staleNodeDeadline healthyNodeDeadline - * | | - * Dead | Stale | Healthy - * Node | Node | Node - * Window | Window | Window - * ----------------+----------------------------------+-------------------> - * >>-->> time-line >>-->> - * - * Here is the logic of computing the health of a node. -     * -     * 1. We get the current time and look back that the time -     *  when we got a heartbeat from a node. -     *  -     * 2. If the last heartbeat was within the window of healthy node we mark -     *  it as healthy. -     *  -     * 3. If the last HB Time stamp is longer and falls within the window of -     *  Stale Node time, we will mark it as Stale. -     *  -     * 4. If the last HB time is older than the Stale Window, then the node is -     * marked as dead. - * - * The Processing starts from current time and looks backwards in time. - */ - long processingStartTime = Time.monotonicNow(); - // After this time node is considered to be stale. - long healthyNodeDeadline = processingStartTime - staleNodeIntervalMs; - // After this time node is considered to be dead. - long staleNodeDeadline = processingStartTime - deadNodeIntervalMs; - - Predicate healthyNodeCondition = - (lastHbTime) -> lastHbTime >= healthyNodeDeadline; - // staleNodeCondition is superset of stale and dead node - Predicate staleNodeCondition = - (lastHbTime) -> lastHbTime < healthyNodeDeadline; - Predicate deadNodeCondition = - (lastHbTime) -> lastHbTime < staleNodeDeadline; - try { - for (NodeState state : NodeState.values()) { - List nodes = nodeStateMap.getNodes(state); - for (UUID id : nodes) { - DatanodeInfo node = nodeStateMap.getNodeInfo(id); - switch (state) { - case HEALTHY: - // Move the node to STALE if the last heartbeat time is less than - // configured stale-node interval. - updateNodeState(node, staleNodeCondition, state, - NodeLifeCycleEvent.TIMEOUT); - break; - case STALE: - // Move the node to DEAD if the last heartbeat time is less than - // configured dead-node interval. - updateNodeState(node, deadNodeCondition, state, - NodeLifeCycleEvent.TIMEOUT); - // Restore the node if we have received heartbeat before configured - // stale-node interval. - updateNodeState(node, healthyNodeCondition, state, - NodeLifeCycleEvent.RESTORE); - break; - case DEAD: - // Resurrect the node if we have received heartbeat before - // configured stale-node interval. - updateNodeState(node, healthyNodeCondition, state, - NodeLifeCycleEvent.RESURRECT); - break; - // We don't do anything for DECOMMISSIONING and DECOMMISSIONED in - // heartbeat processing. - case DECOMMISSIONING: - case DECOMMISSIONED: - default: - } - } - } - } catch (NodeNotFoundException e) { - // This should not happen unless someone else other than - // NodeStateManager is directly modifying NodeStateMap and removed - // the node entry after we got the list of UUIDs. - LOG.error("Inconsistent NodeStateMap! " + nodeStateMap); - } - long processingEndTime = Time.monotonicNow(); - //If we have taken too much time for HB processing, log that information. - if ((processingEndTime - processingStartTime) > - heartbeatCheckerIntervalMs) { - LOG.error("Total time spend processing datanode HB's is greater than " + - "configured values for datanode heartbeats. Please adjust the" + - " heartbeat configs. Time Spend on HB processing: {} seconds " + - "Datanode heartbeat Interval: {} seconds.", - TimeUnit.MILLISECONDS - .toSeconds(processingEndTime - processingStartTime), - heartbeatCheckerIntervalMs); - } - - // we purposefully make this non-deterministic. Instead of using a - // scheduleAtFixedFrequency we will just go to sleep - // and wake up at the next rendezvous point, which is currentTime + - // heartbeatCheckerIntervalMs. This leads to the issue that we are now - // heart beating not at a fixed cadence, but clock tick + time taken to - // work. - // - // This time taken to work can skew the heartbeat processor thread. - // The reason why we don't care is because of the following reasons. - // - // 1. checkerInterval is general many magnitudes faster than datanode HB - // frequency. - // - // 2. if we have too much nodes, the SCM would be doing only HB - // processing, this could lead to SCM's CPU starvation. With this - // approach we always guarantee that HB thread sleeps for a little while. - // - // 3. It is possible that we will never finish processing the HB's in the - // thread. But that means we have a mis-configured system. We will warn - // the users by logging that information. - // - // 4. And the most important reason, heartbeats are not blocked even if - // this thread does not run, they will go into the processing queue. - - if (!Thread.currentThread().isInterrupted() && - !executorService.isShutdown()) { - executorService.schedule(this, heartbeatCheckerIntervalMs, - TimeUnit.MILLISECONDS); - } else { - LOG.info("Current Thread is interrupted, shutting down HB processing " + - "thread for Node Manager."); - } - - } - - /** - * Updates the node state if the condition satisfies. - * - * @param node DatanodeInfo - * @param condition condition to check - * @param state current state of node - * @param lifeCycleEvent NodeLifeCycleEvent to be applied if condition - * matches - * - * @throws NodeNotFoundException if the node is not present - */ - private void updateNodeState(DatanodeInfo node, Predicate condition, - NodeState state, NodeLifeCycleEvent lifeCycleEvent) - throws NodeNotFoundException { - try { - if (condition.test(node.getLastHeartbeatTime())) { - NodeState newState = stateMachine.getNextState(state, lifeCycleEvent); - nodeStateMap.updateNodeState(node.getUuid(), state, newState); - if (state2EventMap.containsKey(newState)) { - eventPublisher.fireEvent(state2EventMap.get(newState), node); - } - } - } catch (InvalidStateTransitionException e) { - LOG.warn("Invalid state transition of node {}." + - " Current state: {}, life cycle event: {}", - node, state, lifeCycleEvent); - } - } - - @Override - public void close() { - executorService.shutdown(); - try { - if (!executorService.awaitTermination(5, TimeUnit.SECONDS)) { - executorService.shutdownNow(); - } - - if (!executorService.awaitTermination(5, TimeUnit.SECONDS)) { - LOG.error("Unable to shutdown NodeStateManager properly."); - } - } catch (InterruptedException e) { - executorService.shutdownNow(); - Thread.currentThread().interrupt(); - } - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/SCMNodeManager.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/SCMNodeManager.java deleted file mode 100644 index 36a6f154ad5..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/SCMNodeManager.java +++ /dev/null @@ -1,599 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.node; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.PipelineReportsProto; -import org.apache.hadoop.hdds.scm.container.ContainerID; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.scm.container.common.helpers.PipelineID; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.hdds.scm.node.states.NodeAlreadyExistsException; -import org.apache.hadoop.hdds.scm.node.states.NodeNotFoundException; -import org.apache.hadoop.hdds.scm.node.states.ReportResult; -import org.apache.hadoop.hdds.scm.server.StorageContainerManager; -import org.apache.hadoop.hdds.scm.VersionInfo; -import org.apache.hadoop.hdds.scm.container.placement.metrics.SCMNodeMetric; -import org.apache.hadoop.hdds.scm.container.placement.metrics.SCMNodeStat; -import org.apache.hadoop.hdds.server.events.EventPublisher; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.NodeReportProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMRegisteredResponseProto - .ErrorCode; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.StorageReportProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMVersionRequestProto; -import org.apache.hadoop.ipc.Server; -import org.apache.hadoop.metrics2.util.MBeans; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.protocol.StorageContainerNodeProtocol; -import org.apache.hadoop.ozone.protocol.VersionResponse; -import org.apache.hadoop.ozone.protocol.commands.CommandForDatanode; -import org.apache.hadoop.ozone.protocol.commands.RegisteredCommand; -import org.apache.hadoop.ozone.protocol.commands.ReregisterCommand; -import org.apache.hadoop.ozone.protocol.commands.SCMCommand; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.management.ObjectName; -import java.io.IOException; -import java.net.InetAddress; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * Maintains information about the Datanodes on SCM side. - *

- * Heartbeats under SCM is very simple compared to HDFS heartbeatManager. - *

- * The getNode(byState) functions make copy of node maps and then creates a list - * based on that. It should be assumed that these get functions always report - * *stale* information. For example, getting the deadNodeCount followed by - * getNodes(DEAD) could very well produce totally different count. Also - * getNodeCount(HEALTHY) + getNodeCount(DEAD) + getNodeCode(STALE), is not - * guaranteed to add up to the total nodes that we know off. Please treat all - * get functions in this file as a snap-shot of information that is inconsistent - * as soon as you read it. - */ -public class SCMNodeManager - implements NodeManager, StorageContainerNodeProtocol { - - @VisibleForTesting - static final Logger LOG = - LoggerFactory.getLogger(SCMNodeManager.class); - - private final NodeStateManager nodeStateManager; - // Should we maintain aggregated stats? If this is not frequently used, we - // can always calculate it from nodeStats whenever required. - // Aggregated node stats - private SCMNodeStat scmStat; - // Should we create ChillModeManager and extract all the chill mode logic - // to a new class? - private int chillModeNodeCount; - private final String clusterID; - private final VersionInfo version; - /** - * During start up of SCM, it will enter into chill mode and will be there - * until number of Datanodes registered reaches {@code chillModeNodeCount}. - * This flag is for tracking startup chill mode. - */ - private AtomicBoolean inStartupChillMode; - /** - * Administrator can put SCM into chill mode manually. - * This flag is for tracking manual chill mode. - */ - private AtomicBoolean inManualChillMode; - private final CommandQueue commandQueue; - // Node manager MXBean - private ObjectName nmInfoBean; - - // Node pool manager. - private final StorageContainerManager scmManager; - - /** - * Constructs SCM machine Manager. - */ - public SCMNodeManager(OzoneConfiguration conf, String clusterID, - StorageContainerManager scmManager, EventPublisher eventPublisher) - throws IOException { - this.nodeStateManager = new NodeStateManager(conf, eventPublisher); - this.scmStat = new SCMNodeStat(); - this.clusterID = clusterID; - this.version = VersionInfo.getLatestVersion(); - this.commandQueue = new CommandQueue(); - // TODO: Support this value as a Percentage of known machines. - this.chillModeNodeCount = 1; - this.inStartupChillMode = new AtomicBoolean(true); - this.inManualChillMode = new AtomicBoolean(false); - this.scmManager = scmManager; - LOG.info("Entering startup chill mode."); - registerMXBean(); - } - - private void registerMXBean() { - this.nmInfoBean = MBeans.register("SCMNodeManager", - "SCMNodeManagerInfo", this); - } - - private void unregisterMXBean() { - if(this.nmInfoBean != null) { - MBeans.unregister(this.nmInfoBean); - this.nmInfoBean = null; - } - } - - /** - * Removes a data node from the management of this Node Manager. - * - * @param node - DataNode. - * @throws NodeNotFoundException - */ - @Override - public void removeNode(DatanodeDetails node) throws NodeNotFoundException { - nodeStateManager.removeNode(node); - } - - /** - * Gets all datanodes that are in a certain state. This function works by - * taking a snapshot of the current collection and then returning the list - * from that collection. This means that real map might have changed by the - * time we return this list. - * - * @return List of Datanodes that are known to SCM in the requested state. - */ - @Override - public List getNodes(NodeState nodestate) { - return nodeStateManager.getNodes(nodestate); - } - - /** - * Returns all datanodes that are known to SCM. - * - * @return List of DatanodeDetails - */ - @Override - public List getAllNodes() { - return nodeStateManager.getAllNodes(); - } - - /** - * Get the minimum number of nodes to get out of Chill mode. - * - * @return int - */ - @Override - public int getMinimumChillModeNodes() { - return chillModeNodeCount; - } - - /** - * Sets the Minimum chill mode nodes count, used only in testing. - * - * @param count - Number of nodes. - */ - @VisibleForTesting - public void setMinimumChillModeNodes(int count) { - chillModeNodeCount = count; - } - - /** - * Returns chill mode Status string. - * @return String - */ - @Override - public String getChillModeStatus() { - if (inStartupChillMode.get()) { - return "Still in chill mode, waiting on nodes to report in." + - String.format(" %d nodes reported, minimal %d nodes required.", - nodeStateManager.getTotalNodeCount(), getMinimumChillModeNodes()); - } - if (inManualChillMode.get()) { - return "Out of startup chill mode, but in manual chill mode." + - String.format(" %d nodes have reported in.", - nodeStateManager.getTotalNodeCount()); - } - return "Out of chill mode." + - String.format(" %d nodes have reported in.", - nodeStateManager.getTotalNodeCount()); - } - - /** - * Forcefully exits the chill mode even if we have not met the minimum - * criteria of exiting the chill mode. This will exit from both startup - * and manual chill mode. - */ - @Override - public void forceExitChillMode() { - if(inStartupChillMode.get()) { - LOG.info("Leaving startup chill mode."); - inStartupChillMode.set(false); - } - if(inManualChillMode.get()) { - LOG.info("Leaving manual chill mode."); - inManualChillMode.set(false); - } - } - - /** - * Puts the node manager into manual chill mode. - */ - @Override - public void enterChillMode() { - LOG.info("Entering manual chill mode."); - inManualChillMode.set(true); - } - - /** - * Brings node manager out of manual chill mode. - */ - @Override - public void exitChillMode() { - LOG.info("Leaving manual chill mode."); - inManualChillMode.set(false); - } - - /** - * Returns true if node manager is out of chill mode, else false. - * @return true if out of chill mode, else false - */ - @Override - public boolean isOutOfChillMode() { - return !(inStartupChillMode.get() || inManualChillMode.get()); - } - - /** - * Returns the Number of Datanodes by State they are in. - * - * @return int -- count - */ - @Override - public int getNodeCount(NodeState nodestate) { - return nodeStateManager.getNodeCount(nodestate); - } - - /** - * Returns the node state of a specific node. - * - * @param datanodeDetails - Datanode Details - * @return Healthy/Stale/Dead/Unknown. - */ - @Override - public NodeState getNodeState(DatanodeDetails datanodeDetails) { - try { - return nodeStateManager.getNodeState(datanodeDetails); - } catch (NodeNotFoundException e) { - // TODO: should we throw NodeNotFoundException? - return null; - } - } - - - private void updateNodeStat(UUID dnId, NodeReportProto nodeReport) { - SCMNodeStat stat; - try { - stat = nodeStateManager.getNodeStat(dnId); - } catch (NodeNotFoundException e) { - LOG.debug("SCM updateNodeStat based on heartbeat from previous" + - "dead datanode {}", dnId); - stat = new SCMNodeStat(); - } - - if (nodeReport != null && nodeReport.getStorageReportCount() > 0) { - long totalCapacity = 0; - long totalRemaining = 0; - long totalScmUsed = 0; - List storageReports = nodeReport - .getStorageReportList(); - for (StorageReportProto report : storageReports) { - totalCapacity += report.getCapacity(); - totalRemaining += report.getRemaining(); - totalScmUsed+= report.getScmUsed(); - } - scmStat.subtract(stat); - stat.set(totalCapacity, totalScmUsed, totalRemaining); - scmStat.add(stat); - } - nodeStateManager.setNodeStat(dnId, stat); - } - - /** - * Closes this stream and releases any system resources associated with it. If - * the stream is already closed then invoking this method has no effect. - * - * @throws IOException if an I/O error occurs - */ - @Override - public void close() throws IOException { - unregisterMXBean(); - } - - /** - * Gets the version info from SCM. - * - * @param versionRequest - version Request. - * @return - returns SCM version info and other required information needed by - * datanode. - */ - @Override - public VersionResponse getVersion(SCMVersionRequestProto versionRequest) { - return VersionResponse.newBuilder() - .setVersion(this.version.getVersion()) - .addValue(OzoneConsts.SCM_ID, - this.scmManager.getScmStorage().getScmId()) - .addValue(OzoneConsts.CLUSTER_ID, this.scmManager.getScmStorage() - .getClusterID()) - .build(); - } - - /** - * Register the node if the node finds that it is not registered with any - * SCM. - * - * @param datanodeDetails - Send datanodeDetails with Node info. - * This function generates and assigns new datanode ID - * for the datanode. This allows SCM to be run independent - * of Namenode if required. - * @param nodeReport NodeReport. - * - * @return SCMHeartbeatResponseProto - */ - @Override - public RegisteredCommand register( - DatanodeDetails datanodeDetails, NodeReportProto nodeReport, - PipelineReportsProto pipelineReportsProto) { - - InetAddress dnAddress = Server.getRemoteIp(); - if (dnAddress != null) { - // Mostly called inside an RPC, update ip and peer hostname - datanodeDetails.setHostName(dnAddress.getHostName()); - datanodeDetails.setIpAddress(dnAddress.getHostAddress()); - } - UUID dnId = datanodeDetails.getUuid(); - try { - nodeStateManager.addNode(datanodeDetails); - nodeStateManager.setNodeStat(dnId, new SCMNodeStat()); - if(inStartupChillMode.get() && - nodeStateManager.getTotalNodeCount() >= getMinimumChillModeNodes()) { - inStartupChillMode.getAndSet(false); - LOG.info("Leaving startup chill mode."); - } - // Updating Node Report, as registration is successful - updateNodeStat(datanodeDetails.getUuid(), nodeReport); - LOG.info("Data node with ID: {} Registered.", datanodeDetails.getUuid()); - } catch (NodeAlreadyExistsException e) { - LOG.trace("Datanode is already registered. Datanode: {}", - datanodeDetails.toString()); - } - return RegisteredCommand.newBuilder().setErrorCode(ErrorCode.success) - .setDatanodeUUID(datanodeDetails.getUuidString()) - .setClusterID(this.clusterID) - .setHostname(datanodeDetails.getHostName()) - .setIpAddress(datanodeDetails.getIpAddress()) - .build(); - } - - /** - * Send heartbeat to indicate the datanode is alive and doing well. - * - * @param datanodeDetails - DatanodeDetailsProto. - * @return SCMheartbeat response. - * @throws IOException - */ - @Override - public List processHeartbeat(DatanodeDetails datanodeDetails) { - Preconditions.checkNotNull(datanodeDetails, "Heartbeat is missing " + - "DatanodeDetails."); - try { - nodeStateManager.updateLastHeartbeatTime(datanodeDetails); - } catch (NodeNotFoundException e) { - LOG.warn("SCM receive heartbeat from unregistered datanode {}", - datanodeDetails); - commandQueue.addCommand(datanodeDetails.getUuid(), - new ReregisterCommand()); - } - return commandQueue.getCommand(datanodeDetails.getUuid()); - } - - /** - * Process node report. - * - * @param dnUuid - * @param nodeReport - */ - @Override - public void processNodeReport(UUID dnUuid, NodeReportProto nodeReport) { - this.updateNodeStat(dnUuid, nodeReport); - } - - /** - * Returns the aggregated node stats. - * @return the aggregated node stats. - */ - @Override - public SCMNodeStat getStats() { - return new SCMNodeStat(this.scmStat); - } - - /** - * Return a map of node stats. - * @return a map of individual node stats (live/stale but not dead). - */ - @Override - public Map getNodeStats() { - return nodeStateManager.getNodeStatsMap(); - } - - /** - * Return the node stat of the specified datanode. - * @param datanodeDetails - datanode ID. - * @return node stat if it is live/stale, null if it is decommissioned or - * doesn't exist. - */ - @Override - public SCMNodeMetric getNodeStat(DatanodeDetails datanodeDetails) { - try { - return new SCMNodeMetric( - nodeStateManager.getNodeStat(datanodeDetails.getUuid())); - } catch (NodeNotFoundException e) { - LOG.info("SCM getNodeStat from a decommissioned or removed datanode {}", - datanodeDetails.getUuid()); - return null; - } - } - - @Override - public Map getNodeCount() { - Map nodeCountMap = new HashMap(); - for(NodeState state : NodeState.values()) { - nodeCountMap.put(state.toString(), getNodeCount(state)); - } - return nodeCountMap; - } - - /** - * Get set of pipelines a datanode is part of. - * @param dnId - datanodeID - * @return Set of PipelineID - */ - @Override - public Set getPipelineByDnID(UUID dnId) { - return nodeStateManager.getPipelineByDnID(dnId); - } - - - /** - * Add pipeline information in the NodeManager. - * @param pipeline - Pipeline to be added - */ - @Override - public void addPipeline(Pipeline pipeline) { - nodeStateManager.addPipeline(pipeline); - } - - /** - * Remove a pipeline information from the NodeManager. - * @param pipeline - Pipeline to be removed - */ - @Override - public void removePipeline(Pipeline pipeline) { - nodeStateManager.removePipeline(pipeline); - } - - /** - * Update set of containers available on a datanode. - * @param uuid - DatanodeID - * @param containerIds - Set of containerIDs - * @throws SCMException - if datanode is not known. For new datanode use - * addDatanodeInContainerMap call. - */ - @Override - public void setContainersForDatanode(UUID uuid, - Set containerIds) throws SCMException { - nodeStateManager.setContainersForDatanode(uuid, containerIds); - } - - /** - * Process containerReport received from datanode. - * @param uuid - DataonodeID - * @param containerIds - Set of containerIDs - * @return The result after processing containerReport - */ - @Override - public ReportResult processContainerReport(UUID uuid, - Set containerIds) { - return nodeStateManager.processContainerReport(uuid, containerIds); - } - - /** - * Return set of containerIDs available on a datanode. - * @param uuid - DatanodeID - * @return - set of containerIDs - */ - @Override - public Set getContainers(UUID uuid) { - return nodeStateManager.getContainers(uuid); - } - - /** - * Insert a new datanode with set of containerIDs for containers available - * on it. - * @param uuid - DatanodeID - * @param containerIDs - Set of ContainerIDs - * @throws SCMException - if datanode already exists - */ - @Override - public void addDatanodeInContainerMap(UUID uuid, - Set containerIDs) throws SCMException { - nodeStateManager.addDatanodeInContainerMap(uuid, containerIDs); - } - - // TODO: - // Since datanode commands are added through event queue, onMessage method - // should take care of adding commands to command queue. - // Refactor and remove all the usage of this method and delete this method. - @Override - public void addDatanodeCommand(UUID dnId, SCMCommand command) { - this.commandQueue.addCommand(dnId, command); - } - - /** - * This method is called by EventQueue whenever someone adds a new - * DATANODE_COMMAND to the Queue. - * - * @param commandForDatanode DatanodeCommand - * @param ignored publisher - */ - @Override - public void onMessage(CommandForDatanode commandForDatanode, - EventPublisher ignored) { - addDatanodeCommand(commandForDatanode.getDatanodeId(), - commandForDatanode.getCommand()); - } - - /** - * Update the node stats and cluster storage stats in this SCM Node Manager. - * - * @param dnUuid datanode uuid. - */ - @Override - public void processDeadNode(UUID dnUuid) { - try { - SCMNodeStat stat = nodeStateManager.getNodeStat(dnUuid); - if (stat != null) { - LOG.trace("Update stat values as Datanode {} is dead.", dnUuid); - scmStat.subtract(stat); - stat.set(0, 0, 0); - } - } catch (NodeNotFoundException e) { - LOG.warn("Can't update stats based on message of dead Datanode {}, it" - + " doesn't exist or decommissioned already.", dnUuid); - } - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/SCMNodeStorageStatMXBean.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/SCMNodeStorageStatMXBean.java deleted file mode 100644 index 32ecbad50ab..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/SCMNodeStorageStatMXBean.java +++ /dev/null @@ -1,77 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.node; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.ozone.container.common.impl.StorageLocationReport; - -import java.util.Set; -import java.util.UUID; - -/** - * - * This is the JMX management interface for node manager information. - */ -@InterfaceAudience.Private -public interface SCMNodeStorageStatMXBean { - /** - * Get the capacity of the dataNode. - * @param datanodeID Datanode Id - * @return long - */ - long getCapacity(UUID datanodeID); - - /** - * Returns the remaining space of a Datanode. - * @param datanodeId Datanode Id - * @return long - */ - long getRemainingSpace(UUID datanodeId); - - - /** - * Returns used space in bytes of a Datanode. - * @return long - */ - long getUsedSpace(UUID datanodeId); - - /** - * Returns the total capacity of all dataNodes. - * @return long - */ - long getTotalCapacity(); - - /** - * Returns the total Used Space in all Datanodes. - * @return long - */ - long getTotalSpaceUsed(); - - /** - * Returns the total Remaining Space in all Datanodes. - * @return long - */ - long getTotalFreeSpace(); - - /** - * Returns the set of disks for a given Datanode. - * @return set of storage volumes - */ - Set getStorageVolumes(UUID datanodeId); -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/SCMNodeStorageStatMap.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/SCMNodeStorageStatMap.java deleted file mode 100644 index 1b0e5b56e77..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/SCMNodeStorageStatMap.java +++ /dev/null @@ -1,368 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ - -package org.apache.hadoop.hdds.scm.node; - - -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos; -import org.apache.hadoop.hdds.protocol.proto. - StorageContainerDatanodeProtocolProtos.StorageReportProto; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.metrics2.util.MBeans; -import org.apache.hadoop.ozone.OzoneConfigKeys; -import org.apache.hadoop.ozone.container.common.impl.StorageLocationReport; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.management.ObjectName; -import java.io.IOException; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; - -import static org.apache.hadoop.hdds.scm.exceptions.SCMException.ResultCodes.DUPLICATE_DATANODE; -import static org.apache.hadoop.hdds.scm.exceptions.SCMException.ResultCodes.NO_SUCH_DATANODE; - -/** - * This data structure maintains the disk space capacity, disk usage and free - * space availability per Datanode. - * This information is built from the DN node reports. - */ -public class SCMNodeStorageStatMap implements SCMNodeStorageStatMXBean { - static final Logger LOG = - LoggerFactory.getLogger(SCMNodeStorageStatMap.class); - - private final double warningUtilizationThreshold; - private final double criticalUtilizationThreshold; - - private final Map> scmNodeStorageReportMap; - // NodeStorageInfo MXBean - private ObjectName scmNodeStorageInfoBean; - /** - * constructs the scmNodeStorageReportMap object. - */ - public SCMNodeStorageStatMap(OzoneConfiguration conf) { - // scmNodeStorageReportMap = new ConcurrentHashMap<>(); - scmNodeStorageReportMap = new ConcurrentHashMap<>(); - warningUtilizationThreshold = conf.getDouble( - OzoneConfigKeys. - HDDS_DATANODE_STORAGE_UTILIZATION_WARNING_THRESHOLD, - OzoneConfigKeys. - HDDS_DATANODE_STORAGE_UTILIZATION_WARNING_THRESHOLD_DEFAULT); - criticalUtilizationThreshold = conf.getDouble( - OzoneConfigKeys. - HDDS_DATANODE_STORAGE_UTILIZATION_CRITICAL_THRESHOLD, - OzoneConfigKeys. - HDDS_DATANODE_STORAGE_UTILIZATION_CRITICAL_THRESHOLD_DEFAULT); - } - - /** - * Enum that Describes what we should do at various thresholds. - */ - public enum UtilizationThreshold { - NORMAL, WARN, CRITICAL; - } - - /** - * Returns true if this a datanode that is already tracked by - * scmNodeStorageReportMap. - * - * @param datanodeID - UUID of the Datanode. - * @return True if this is tracked, false if this map does not know about it. - */ - public boolean isKnownDatanode(UUID datanodeID) { - Preconditions.checkNotNull(datanodeID); - return scmNodeStorageReportMap.containsKey(datanodeID); - } - - public List getDatanodeList( - UtilizationThreshold threshold) { - return scmNodeStorageReportMap.entrySet().stream().filter( - entry -> (isThresholdReached(threshold, - getScmUsedratio(getUsedSpace(entry.getKey()), - getCapacity(entry.getKey()))))) - .map(Map.Entry::getKey) - .collect(Collectors.toList()); - } - - - - /** - * Insert a new datanode into Node2Container Map. - * - * @param datanodeID -- Datanode UUID - * @param report - set if StorageReports. - */ - public void insertNewDatanode(UUID datanodeID, - Set report) throws SCMException { - Preconditions.checkNotNull(report); - Preconditions.checkState(report.size() != 0); - Preconditions.checkNotNull(datanodeID); - synchronized (scmNodeStorageReportMap) { - if (isKnownDatanode(datanodeID)) { - throw new SCMException("Node already exists in the map", - DUPLICATE_DATANODE); - } - scmNodeStorageReportMap.putIfAbsent(datanodeID, report); - } - } - - //TODO: This should be called once SCMNodeManager gets Started. - private void registerMXBean() { - this.scmNodeStorageInfoBean = MBeans.register("StorageContainerManager", - "scmNodeStorageInfo", this); - } - - //TODO: Unregister call should happen as a part of SCMNodeManager shutdown. - private void unregisterMXBean() { - if(this.scmNodeStorageInfoBean != null) { - MBeans.unregister(this.scmNodeStorageInfoBean); - this.scmNodeStorageInfoBean = null; - } - } - /** - * Updates the Container list of an existing DN. - * - * @param datanodeID - UUID of DN. - * @param report - set of Storage Reports for the Datanode. - * @throws SCMException - if we don't know about this datanode, for new DN - * use addDatanodeInContainerMap. - */ - public void updateDatanodeMap(UUID datanodeID, - Set report) throws SCMException { - Preconditions.checkNotNull(datanodeID); - Preconditions.checkNotNull(report); - Preconditions.checkState(report.size() != 0); - synchronized (scmNodeStorageReportMap) { - if (!scmNodeStorageReportMap.containsKey(datanodeID)) { - throw new SCMException("No such datanode", NO_SUCH_DATANODE); - } - scmNodeStorageReportMap.put(datanodeID, report); - } - } - - public StorageReportResult processNodeReport(UUID datanodeID, - StorageContainerDatanodeProtocolProtos.NodeReportProto nodeReport) - throws IOException { - Preconditions.checkNotNull(datanodeID); - Preconditions.checkNotNull(nodeReport); - - long totalCapacity = 0; - long totalRemaining = 0; - long totalScmUsed = 0; - Set storagReportSet = new HashSet<>(); - Set fullVolumeSet = new HashSet<>(); - Set failedVolumeSet = new HashSet<>(); - List - storageReports = nodeReport.getStorageReportList(); - for (StorageReportProto report : storageReports) { - StorageLocationReport storageReport = - StorageLocationReport.getFromProtobuf(report); - storagReportSet.add(storageReport); - if (report.hasFailed() && report.getFailed()) { - failedVolumeSet.add(storageReport); - } else if (isThresholdReached(UtilizationThreshold.CRITICAL, - getScmUsedratio(report.getScmUsed(), report.getCapacity()))) { - fullVolumeSet.add(storageReport); - } - totalCapacity += report.getCapacity(); - totalRemaining += report.getRemaining(); - totalScmUsed += report.getScmUsed(); - } - - if (!isKnownDatanode(datanodeID)) { - insertNewDatanode(datanodeID, storagReportSet); - } else { - updateDatanodeMap(datanodeID, storagReportSet); - } - if (isThresholdReached(UtilizationThreshold.CRITICAL, - getScmUsedratio(totalScmUsed, totalCapacity))) { - LOG.warn("Datanode {} is out of storage space. Capacity: {}, Used: {}", - datanodeID, totalCapacity, totalScmUsed); - return StorageReportResult.ReportResultBuilder.newBuilder() - .setStatus(ReportStatus.DATANODE_OUT_OF_SPACE) - .setFullVolumeSet(fullVolumeSet).setFailedVolumeSet(failedVolumeSet) - .build(); - } - if (isThresholdReached(UtilizationThreshold.WARN, - getScmUsedratio(totalScmUsed, totalCapacity))) { - LOG.warn("Datanode {} is low on storage space. Capacity: {}, Used: {}", - datanodeID, totalCapacity, totalScmUsed); - } - - if (failedVolumeSet.isEmpty() && !fullVolumeSet.isEmpty()) { - return StorageReportResult.ReportResultBuilder.newBuilder() - .setStatus(ReportStatus.STORAGE_OUT_OF_SPACE) - .setFullVolumeSet(fullVolumeSet).build(); - } - - if (!failedVolumeSet.isEmpty() && fullVolumeSet.isEmpty()) { - return StorageReportResult.ReportResultBuilder.newBuilder() - .setStatus(ReportStatus.FAILED_STORAGE) - .setFailedVolumeSet(failedVolumeSet).build(); - } - if (!failedVolumeSet.isEmpty() && !fullVolumeSet.isEmpty()) { - return StorageReportResult.ReportResultBuilder.newBuilder() - .setStatus(ReportStatus.FAILED_AND_OUT_OF_SPACE_STORAGE) - .setFailedVolumeSet(failedVolumeSet).setFullVolumeSet(fullVolumeSet) - .build(); - } - return StorageReportResult.ReportResultBuilder.newBuilder() - .setStatus(ReportStatus.ALL_IS_WELL).build(); - } - - private boolean isThresholdReached(UtilizationThreshold threshold, - double scmUsedratio) { - switch (threshold) { - case NORMAL: - return scmUsedratio < warningUtilizationThreshold; - case WARN: - return scmUsedratio >= warningUtilizationThreshold - && scmUsedratio < criticalUtilizationThreshold; - case CRITICAL: - return scmUsedratio >= criticalUtilizationThreshold; - default: - throw new RuntimeException("Unknown UtilizationThreshold value"); - } - } - - @Override - public long getCapacity(UUID dnId) { - long capacity = 0; - Set reportSet = scmNodeStorageReportMap.get(dnId); - for (StorageLocationReport report : reportSet) { - capacity += report.getCapacity(); - } - return capacity; - } - - @Override - public long getRemainingSpace(UUID dnId) { - long remaining = 0; - Set reportSet = scmNodeStorageReportMap.get(dnId); - for (StorageLocationReport report : reportSet) { - remaining += report.getRemaining(); - } - return remaining; - } - - @Override - public long getUsedSpace(UUID dnId) { - long scmUsed = 0; - Set reportSet = scmNodeStorageReportMap.get(dnId); - for (StorageLocationReport report : reportSet) { - scmUsed += report.getScmUsed(); - } - return scmUsed; - } - - @Override - public long getTotalCapacity() { - long capacity = 0; - Set dnIdSet = scmNodeStorageReportMap.keySet(); - for (UUID id : dnIdSet) { - capacity += getCapacity(id); - } - return capacity; - } - - @Override - public long getTotalSpaceUsed() { - long scmUsed = 0; - Set dnIdSet = scmNodeStorageReportMap.keySet(); - for (UUID id : dnIdSet) { - scmUsed += getUsedSpace(id); - } - return scmUsed; - } - - @Override - public long getTotalFreeSpace() { - long remaining = 0; - Set dnIdSet = scmNodeStorageReportMap.keySet(); - for (UUID id : dnIdSet) { - remaining += getRemainingSpace(id); - } - return remaining; - } - - /** - * removes the dataNode from scmNodeStorageReportMap. - * @param datanodeID - * @throws SCMException in case the dataNode is not found in the map. - */ - public void removeDatanode(UUID datanodeID) throws SCMException { - Preconditions.checkNotNull(datanodeID); - synchronized (scmNodeStorageReportMap) { - if (!scmNodeStorageReportMap.containsKey(datanodeID)) { - throw new SCMException("No such datanode", NO_SUCH_DATANODE); - } - scmNodeStorageReportMap.remove(datanodeID); - } - } - - /** - * Returns the set of storage volumes for a Datanode. - * @param datanodeID - * @return set of storage volumes. - */ - - @Override - public Set getStorageVolumes(UUID datanodeID) { - return scmNodeStorageReportMap.get(datanodeID); - } - - - /** - * Truncate to 4 digits since uncontrolled precision is some times - * counter intuitive to what users expect. - * @param value - double. - * @return double. - */ - private double truncateDecimals(double value) { - final int multiplier = 10000; - return (double) ((long) (value * multiplier)) / multiplier; - } - - /** - * get the scmUsed ratio. - */ - public double getScmUsedratio(long scmUsed, long capacity) { - double scmUsedRatio = - truncateDecimals(scmUsed / (double) capacity); - return scmUsedRatio; - } - /** - * Results possible from processing a Node report by - * Node2ContainerMapper. - */ - public enum ReportStatus { - ALL_IS_WELL, - DATANODE_OUT_OF_SPACE, - STORAGE_OUT_OF_SPACE, - FAILED_STORAGE, - FAILED_AND_OUT_OF_SPACE_STORAGE - } - -} \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/StaleNodeHandler.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/StaleNodeHandler.java deleted file mode 100644 index 48939f1bae1..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/StaleNodeHandler.java +++ /dev/null @@ -1,42 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.node; - -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.scm.pipelines.PipelineSelector; -import org.apache.hadoop.hdds.server.events.EventHandler; -import org.apache.hadoop.hdds.server.events.EventPublisher; - -/** - * Handles Stale node event. - */ -public class StaleNodeHandler implements EventHandler { - - private final PipelineSelector pipelineSelector; - - public StaleNodeHandler(PipelineSelector pipelineSelector) { - this.pipelineSelector = pipelineSelector; - } - - @Override - public void onMessage(DatanodeDetails datanodeDetails, - EventPublisher publisher) { - pipelineSelector.handleStaleNode(datanodeDetails); - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/StorageReportResult.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/StorageReportResult.java deleted file mode 100644 index 0b63ceb5783..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/StorageReportResult.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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.hadoop.hdds.scm.node; - -import org.apache.hadoop.ozone.container.common.impl.StorageLocationReport; - -import java.util.Set; - -/** - * A Container Report gets processsed by the Node2Container and returns the - * Report Result class. - */ -public class StorageReportResult { - private SCMNodeStorageStatMap.ReportStatus status; - private Set fullVolumes; - private Set failedVolumes; - - StorageReportResult(SCMNodeStorageStatMap.ReportStatus status, - Set fullVolumes, - Set failedVolumes) { - this.status = status; - this.fullVolumes = fullVolumes; - this.failedVolumes = failedVolumes; - } - - public SCMNodeStorageStatMap.ReportStatus getStatus() { - return status; - } - - public Set getFullVolumes() { - return fullVolumes; - } - - public Set getFailedVolumes() { - return failedVolumes; - } - - static class ReportResultBuilder { - private SCMNodeStorageStatMap.ReportStatus status; - private Set fullVolumes; - private Set failedVolumes; - - static ReportResultBuilder newBuilder() { - return new ReportResultBuilder(); - } - - public ReportResultBuilder setStatus( - SCMNodeStorageStatMap.ReportStatus newstatus) { - this.status = newstatus; - return this; - } - - public ReportResultBuilder setFullVolumeSet( - Set fullVolumesSet) { - this.fullVolumes = fullVolumesSet; - return this; - } - - public ReportResultBuilder setFailedVolumeSet( - Set failedVolumesSet) { - this.failedVolumes = failedVolumesSet; - return this; - } - - StorageReportResult build() { - return new StorageReportResult(status, fullVolumes, failedVolumes); - } - } -} \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/package-info.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/package-info.java deleted file mode 100644 index d6a8ad0394e..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/package-info.java +++ /dev/null @@ -1,31 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.scm.node; - -/** - * The node package deals with node management. - *

- * The node manager takes care of node registrations, removal of node and - * handling of heartbeats. - *

- * The node manager maintains statistics that gets send as part of - * heartbeats. - *

- * The container manager polls the node manager to learn the state of - * datanodes that it is interested in. - *

- */ \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/Node2ContainerMap.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/Node2ContainerMap.java deleted file mode 100644 index 9625f819087..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/Node2ContainerMap.java +++ /dev/null @@ -1,90 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ - -package org.apache.hadoop.hdds.scm.node.states; - -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; - -import org.apache.hadoop.hdds.scm.container.ContainerID; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import static org.apache.hadoop.hdds.scm.exceptions.SCMException.ResultCodes - .NO_SUCH_DATANODE; - -/** - * This data structure maintains the list of containers that is on a datanode. - * This information is built from the DN container reports. - */ -public class Node2ContainerMap extends Node2ObjectsMap { - - /** - * Constructs a Node2ContainerMap Object. - */ - public Node2ContainerMap() { - super(); - } - - /** - * Returns null if there no containers associated with this datanode ID. - * - * @param datanode - UUID - * @return Set of containers or Null. - */ - public Set getContainers(UUID datanode) { - return getObjects(datanode); - } - - /** - * Insert a new datanode into Node2Container Map. - * - * @param datanodeID -- Datanode UUID - * @param containerIDs - List of ContainerIDs. - */ - public void insertNewDatanode(UUID datanodeID, Set containerIDs) - throws SCMException { - super.insertNewDatanode(datanodeID, containerIDs); - } - - /** - * Updates the Container list of an existing DN. - * - * @param datanodeID - UUID of DN. - * @param containers - Set of Containers tht is present on DN. - * @throws SCMException - if we don't know about this datanode, for new DN - * use addDatanodeInContainerMap. - */ - public void setContainersForDatanode(UUID datanodeID, - Set containers) throws SCMException { - Preconditions.checkNotNull(datanodeID); - Preconditions.checkNotNull(containers); - if (dn2ObjectMap - .computeIfPresent(datanodeID, (k, v) -> new HashSet<>(containers)) - == null) { - throw new SCMException("No such datanode", NO_SUCH_DATANODE); - } - } - - @VisibleForTesting - public int size() { - return dn2ObjectMap.size(); - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/Node2ObjectsMap.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/Node2ObjectsMap.java deleted file mode 100644 index e49a79c64f6..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/Node2ObjectsMap.java +++ /dev/null @@ -1,162 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ - -package org.apache.hadoop.hdds.scm.node.states; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; - -import java.util.UUID; -import java.util.Set; -import java.util.Map; -import java.util.TreeSet; -import java.util.HashSet; -import java.util.Collections; - -import java.util.concurrent.ConcurrentHashMap; - -import static org.apache.hadoop.hdds.scm.exceptions.SCMException.ResultCodes.DUPLICATE_DATANODE; - -/** - * This data structure maintains the list of containers that is on a datanode. - * This information is built from the DN container reports. - */ -public class Node2ObjectsMap { - protected final Map> dn2ObjectMap; - - /** - * Constructs a Node2ContainerMap Object. - */ - public Node2ObjectsMap() { - dn2ObjectMap = new ConcurrentHashMap<>(); - } - - /** - * Returns true if this a datanode that is already tracked by - * Node2ContainerMap. - * - * @param datanodeID - UUID of the Datanode. - * @return True if this is tracked, false if this map does not know about it. - */ - public boolean isKnownDatanode(UUID datanodeID) { - Preconditions.checkNotNull(datanodeID); - return dn2ObjectMap.containsKey(datanodeID); - } - - /** - * Insert a new datanode into Node2Container Map. - * - * @param datanodeID -- Datanode UUID - * @param containerIDs - List of ContainerIDs. - */ - public void insertNewDatanode(UUID datanodeID, Set containerIDs) - throws SCMException { - Preconditions.checkNotNull(containerIDs); - Preconditions.checkNotNull(datanodeID); - if (dn2ObjectMap.putIfAbsent(datanodeID, new HashSet<>(containerIDs)) - != null) { - throw new SCMException("Node already exists in the map", - DUPLICATE_DATANODE); - } - } - - /** - * Removes datanode Entry from the map. - * - * @param datanodeID - Datanode ID. - */ - void removeDatanode(UUID datanodeID) { - Preconditions.checkNotNull(datanodeID); - dn2ObjectMap.computeIfPresent(datanodeID, (k, v) -> null); - } - - /** - * Returns null if there no containers associated with this datanode ID. - * - * @param datanode - UUID - * @return Set of containers or Null. - */ - Set getObjects(UUID datanode) { - Preconditions.checkNotNull(datanode); - final Set s = dn2ObjectMap.get(datanode); - return s != null? Collections.unmodifiableSet(s): Collections.emptySet(); - } - - public ReportResult.ReportResultBuilder newBuilder() { - return new ReportResult.ReportResultBuilder<>(); - } - - public ReportResult processReport(UUID datanodeID, Set objects) { - Preconditions.checkNotNull(datanodeID); - Preconditions.checkNotNull(objects); - - if (!isKnownDatanode(datanodeID)) { - return newBuilder() - .setStatus(ReportResult.ReportStatus.NEW_DATANODE_FOUND) - .setNewEntries(objects) - .build(); - } - - // Conditions like Zero length containers should be handled by removeAll. - Set currentSet = dn2ObjectMap.get(datanodeID); - TreeSet newObjects = new TreeSet<>(objects); - newObjects.removeAll(currentSet); - - TreeSet missingObjects = new TreeSet<>(currentSet); - missingObjects.removeAll(objects); - - if (newObjects.isEmpty() && missingObjects.isEmpty()) { - return newBuilder() - .setStatus(ReportResult.ReportStatus.ALL_IS_WELL) - .build(); - } - - if (newObjects.isEmpty() && !missingObjects.isEmpty()) { - return newBuilder() - .setStatus(ReportResult.ReportStatus.MISSING_ENTRIES) - .setMissingEntries(missingObjects) - .build(); - } - - if (!newObjects.isEmpty() && missingObjects.isEmpty()) { - return newBuilder() - .setStatus(ReportResult.ReportStatus.NEW_ENTRIES_FOUND) - .setNewEntries(newObjects) - .build(); - } - - if (!newObjects.isEmpty() && !missingObjects.isEmpty()) { - return newBuilder() - .setStatus(ReportResult.ReportStatus.MISSING_AND_NEW_ENTRIES_FOUND) - .setNewEntries(newObjects) - .setMissingEntries(missingObjects) - .build(); - } - - // default status & Make compiler happy - return newBuilder() - .setStatus(ReportResult.ReportStatus.ALL_IS_WELL) - .build(); - } - - @VisibleForTesting - public int size() { - return dn2ObjectMap.size(); - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/Node2PipelineMap.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/Node2PipelineMap.java deleted file mode 100644 index 87f2222b5ff..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/Node2PipelineMap.java +++ /dev/null @@ -1,75 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ - -package org.apache.hadoop.hdds.scm.node.states; - -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.scm.container.common.helpers.PipelineID; - -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; - -/** - * This data structure maintains the list of pipelines which the given datanode is a part of. This - * information will be added whenever a new pipeline allocation happens. - * - *

TODO: this information needs to be regenerated from pipeline reports on SCM restart - */ -public class Node2PipelineMap extends Node2ObjectsMap { - - /** Constructs a Node2PipelineMap Object. */ - public Node2PipelineMap() { - super(); - } - - /** - * Returns null if there no pipelines associated with this datanode ID. - * - * @param datanode - UUID - * @return Set of pipelines or Null. - */ - public Set getPipelines(UUID datanode) { - return getObjects(datanode); - } - - /** - * Adds a pipeline entry to a given dataNode in the map. - * - * @param pipeline Pipeline to be added - */ - public synchronized void addPipeline(Pipeline pipeline) { - for (DatanodeDetails details : pipeline.getDatanodes().values()) { - UUID dnId = details.getUuid(); - dn2ObjectMap.computeIfAbsent(dnId, k -> new HashSet<>()) - .add(pipeline.getId()); - } - } - - public synchronized void removePipeline(Pipeline pipeline) { - for (DatanodeDetails details : pipeline.getDatanodes().values()) { - UUID dnId = details.getUuid(); - dn2ObjectMap.computeIfPresent(dnId, - (k, v) -> { - v.remove(pipeline.getId()); - return v; - }); - } - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/NodeAlreadyExistsException.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/NodeAlreadyExistsException.java deleted file mode 100644 index aa5c382f426..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/NodeAlreadyExistsException.java +++ /dev/null @@ -1,45 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.hdds.scm.node.states; - -/** - * This exception represents that there is already a node added to NodeStateMap - * with same UUID. - */ -public class NodeAlreadyExistsException extends NodeException { - - /** - * Constructs an {@code NodeAlreadyExistsException} with {@code null} - * as its error detail message. - */ - public NodeAlreadyExistsException() { - super(); - } - - /** - * Constructs an {@code NodeAlreadyExistsException} with the specified - * detail message. - * - * @param message - * The detail message (which is saved for later retrieval - * by the {@link #getMessage()} method) - */ - public NodeAlreadyExistsException(String message) { - super(message); - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/NodeException.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/NodeException.java deleted file mode 100644 index c67b55d9531..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/NodeException.java +++ /dev/null @@ -1,44 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.hdds.scm.node.states; - -/** - * This exception represents all node related exceptions in NodeStateMap. - */ -public class NodeException extends Exception { - - /** - * Constructs an {@code NodeException} with {@code null} - * as its error detail message. - */ - public NodeException() { - super(); - } - - /** - * Constructs an {@code NodeException} with the specified - * detail message. - * - * @param message - * The detail message (which is saved for later retrieval - * by the {@link #getMessage()} method) - */ - public NodeException(String message) { - super(message); - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/NodeNotFoundException.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/NodeNotFoundException.java deleted file mode 100644 index c44a08cf51e..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/NodeNotFoundException.java +++ /dev/null @@ -1,47 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.hdds.scm.node.states; - -/** - * This exception represents that the node that is being accessed does not - * exist in NodeStateMap. - */ -public class NodeNotFoundException extends NodeException { - - - /** - * Constructs an {@code NodeNotFoundException} with {@code null} - * as its error detail message. - */ - public NodeNotFoundException() { - super(); - } - - /** - * Constructs an {@code NodeNotFoundException} with the specified - * detail message. - * - * @param message - * The detail message (which is saved for later retrieval - * by the {@link #getMessage()} method) - */ - public NodeNotFoundException(String message) { - super(message); - } - -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/NodeStateMap.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/NodeStateMap.java deleted file mode 100644 index 774ced18b0a..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/NodeStateMap.java +++ /dev/null @@ -1,337 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.node.states; - -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState; -import org.apache.hadoop.hdds.scm.container.placement.metrics.SCMNodeStat; -import org.apache.hadoop.hdds.scm.node.DatanodeInfo; - -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -/** - * Maintains the state of datanodes in SCM. This class should only be used by - * NodeStateManager to maintain the state. If anyone wants to change the - * state of a node they should call NodeStateManager, do not directly use - * this class. - */ -public class NodeStateMap { - - /** - * Node id to node info map. - */ - private final ConcurrentHashMap nodeMap; - /** - * Represents the current state of node. - */ - private final ConcurrentHashMap> stateMap; - /** - * Represents the current stats of node. - */ - private final ConcurrentHashMap nodeStats; - - private final ReadWriteLock lock; - - /** - * Creates a new instance of NodeStateMap with no nodes. - */ - public NodeStateMap() { - lock = new ReentrantReadWriteLock(); - nodeMap = new ConcurrentHashMap<>(); - stateMap = new ConcurrentHashMap<>(); - nodeStats = new ConcurrentHashMap<>(); - initStateMap(); - } - - /** - * Initializes the state map with available states. - */ - private void initStateMap() { - for (NodeState state : NodeState.values()) { - stateMap.put(state, new HashSet<>()); - } - } - - /** - * Adds a node to NodeStateMap. - * - * @param datanodeDetails DatanodeDetails - * @param nodeState initial NodeState - * - * @throws NodeAlreadyExistsException if the node already exist - */ - public void addNode(DatanodeDetails datanodeDetails, NodeState nodeState) - throws NodeAlreadyExistsException { - lock.writeLock().lock(); - try { - UUID id = datanodeDetails.getUuid(); - if (nodeMap.containsKey(id)) { - throw new NodeAlreadyExistsException("Node UUID: " + id); - } - nodeMap.put(id, new DatanodeInfo(datanodeDetails)); - stateMap.get(nodeState).add(id); - } finally { - lock.writeLock().unlock(); - } - } - - /** - * Updates the node state. - * - * @param nodeId Node Id - * @param currentState current state - * @param newState new state - * - * @throws NodeNotFoundException if the node is not present - */ - public void updateNodeState(UUID nodeId, NodeState currentState, - NodeState newState)throws NodeNotFoundException { - lock.writeLock().lock(); - try { - if (stateMap.get(currentState).remove(nodeId)) { - stateMap.get(newState).add(nodeId); - } else { - throw new NodeNotFoundException("Node UUID: " + nodeId + - ", not found in state: " + currentState); - } - } finally { - lock.writeLock().unlock(); - } - } - - /** - * Returns DatanodeDetails for the given node id. - * - * @param uuid Node Id - * - * @return DatanodeDetails of the node - * - * @throws NodeNotFoundException if the node is not present - */ - public DatanodeDetails getNodeDetails(UUID uuid) - throws NodeNotFoundException { - return getNodeInfo(uuid); - } - - /** - * Returns DatanodeInfo for the given node id. - * - * @param uuid Node Id - * - * @return DatanodeInfo of the node - * - * @throws NodeNotFoundException if the node is not present - */ - public DatanodeInfo getNodeInfo(UUID uuid) throws NodeNotFoundException { - lock.readLock().lock(); - try { - if (nodeMap.containsKey(uuid)) { - return nodeMap.get(uuid); - } - throw new NodeNotFoundException("Node UUID: " + uuid); - } finally { - lock.readLock().unlock(); - } - } - - - /** - * Returns the list of node ids which are in the specified state. - * - * @param state NodeState - * - * @return list of node ids - */ - public List getNodes(NodeState state) { - lock.readLock().lock(); - try { - return new LinkedList<>(stateMap.get(state)); - } finally { - lock.readLock().unlock(); - } - } - - /** - * Returns the list of all the node ids. - * - * @return list of all the node ids - */ - public List getAllNodes() { - lock.readLock().lock(); - try { - return new LinkedList<>(nodeMap.keySet()); - } finally { - lock.readLock().unlock(); - } - } - - /** - * Returns the count of nodes in the specified state. - * - * @param state NodeState - * - * @return Number of nodes in the specified state - */ - public int getNodeCount(NodeState state) { - lock.readLock().lock(); - try { - return stateMap.get(state).size(); - } finally { - lock.readLock().unlock(); - } - } - - /** - * Returns the total node count. - * - * @return node count - */ - public int getTotalNodeCount() { - lock.readLock().lock(); - try { - return nodeMap.size(); - } finally { - lock.readLock().unlock(); - } - } - - /** - * Returns the current state of the node. - * - * @param uuid node id - * - * @return NodeState - * - * @throws NodeNotFoundException if the node is not found - */ - public NodeState getNodeState(UUID uuid) throws NodeNotFoundException { - lock.readLock().lock(); - try { - for (Map.Entry> entry : stateMap.entrySet()) { - if (entry.getValue().contains(uuid)) { - return entry.getKey(); - } - } - throw new NodeNotFoundException("Node UUID: " + uuid); - } finally { - lock.readLock().unlock(); - } - } - - /** - * Removes the node from NodeStateMap. - * - * @param uuid node id - * - * @throws NodeNotFoundException if the node is not found - */ - public void removeNode(UUID uuid) throws NodeNotFoundException { - lock.writeLock().lock(); - try { - if (nodeMap.containsKey(uuid)) { - for (Map.Entry> entry : stateMap.entrySet()) { - if(entry.getValue().remove(uuid)) { - break; - } - nodeMap.remove(uuid); - } - throw new NodeNotFoundException("Node UUID: " + uuid); - } - } finally { - lock.writeLock().unlock(); - } - } - - /** - * Returns the current stats of the node. - * - * @param uuid node id - * - * @return SCMNodeStat of the specify node. - * - * @throws NodeNotFoundException if the node is not found - */ - public SCMNodeStat getNodeStat(UUID uuid) throws NodeNotFoundException { - SCMNodeStat stat = nodeStats.get(uuid); - if (stat == null) { - throw new NodeNotFoundException("Node UUID: " + uuid); - } - return stat; - } - - /** - * Returns a unmodifiable copy of nodeStats. - * - * @return map with node stats. - */ - public Map getNodeStats() { - return Collections.unmodifiableMap(nodeStats); - } - - /** - * Set the current stats of the node. - * - * @param uuid node id - * - * @param newstat stat that will set to the specify node. - */ - public void setNodeStat(UUID uuid, SCMNodeStat newstat) { - nodeStats.put(uuid, newstat); - } - - /** - * Remove the current stats of the specify node. - * - * @param uuid node id - * - * @return SCMNodeStat the stat removed from the node. - * - * @throws NodeNotFoundException if the node is not found - */ - public SCMNodeStat removeNodeStat(UUID uuid) throws NodeNotFoundException { - SCMNodeStat stat = nodeStats.remove(uuid); - if (stat == null) { - throw new NodeNotFoundException("Node UUID: " + uuid); - } - return stat; - } - - /** - * Since we don't hold a global lock while constructing this string, - * the result might be inconsistent. If someone has changed the state of node - * while we are constructing the string, the result will be inconsistent. - * This should only be used for logging. We should not parse this string and - * use it for any critical calculations. - * - * @return current state of NodeStateMap - */ - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("Total number of nodes: ").append(getTotalNodeCount()); - for (NodeState state : NodeState.values()) { - builder.append("Number of nodes in ").append(state).append(" state: ") - .append(getNodeCount(state)); - } - return builder.toString(); - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/ReportResult.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/ReportResult.java deleted file mode 100644 index 0c7610fc7bd..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/ReportResult.java +++ /dev/null @@ -1,110 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.hadoop.hdds.scm.node.states; - -import java.util.Collections; -import java.util.Set; - -import com.google.common.base.Preconditions; - -/** - * A Container/Pipeline Report gets processed by the - * Node2Container/Node2Pipeline and returns Report Result class. - */ -public final class ReportResult { - private ReportStatus status; - private Set missingEntries; - private Set newEntries; - - private ReportResult(ReportStatus status, - Set missingEntries, - Set newEntries) { - this.status = status; - Preconditions.checkNotNull(missingEntries); - Preconditions.checkNotNull(newEntries); - this.missingEntries = missingEntries; - this.newEntries = newEntries; - } - - public ReportStatus getStatus() { - return status; - } - - public Set getMissingEntries() { - return missingEntries; - } - - public Set getNewEntries() { - return newEntries; - } - - /** - * Result after processing report for node2Object map. - * @param - */ - public static class ReportResultBuilder { - private ReportStatus status; - private Set missingEntries; - private Set newEntries; - - public ReportResultBuilder setStatus( - ReportStatus newStatus) { - this.status = newStatus; - return this; - } - - public ReportResultBuilder setMissingEntries( - Set missingEntriesList) { - this.missingEntries = missingEntriesList; - return this; - } - - public ReportResultBuilder setNewEntries( - Set newEntriesList) { - this.newEntries = newEntriesList; - return this; - } - - public ReportResult build() { - - Set nullSafeMissingEntries = this.missingEntries; - Set nullSafeNewEntries = this.newEntries; - if (nullSafeNewEntries == null) { - nullSafeNewEntries = Collections.emptySet(); - } - if (nullSafeMissingEntries == null) { - nullSafeMissingEntries = Collections.emptySet(); - } - return new ReportResult(status, nullSafeMissingEntries, - nullSafeNewEntries); - } - } - - /** - * Results possible from processing a report. - */ - public enum ReportStatus { - ALL_IS_WELL, - MISSING_ENTRIES, - NEW_ENTRIES_FOUND, - MISSING_AND_NEW_ENTRIES_FOUND, - NEW_DATANODE_FOUND, - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/package-info.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/package-info.java deleted file mode 100644 index c429c5c3e13..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/states/package-info.java +++ /dev/null @@ -1,22 +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 - * - * 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. - * - */ - -/** - * Node States package. - */ -package org.apache.hadoop.hdds.scm.node.states; \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/package-info.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/package-info.java deleted file mode 100644 index 4669e741ef0..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/package-info.java +++ /dev/null @@ -1,22 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.hdds.scm; - -/* - * This package contains StorageContainerManager classes. - */ diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/PipelineActionEventHandler.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/PipelineActionEventHandler.java deleted file mode 100644 index 1053149bba8..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/PipelineActionEventHandler.java +++ /dev/null @@ -1,62 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.hdds.scm.pipelines; - -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.PipelineAction; -import org.apache.hadoop.hdds.scm.container.common.helpers.PipelineID; -import org.apache.hadoop.hdds.scm.events.SCMEvents; -import org.apache.hadoop.hdds.scm.server.SCMDatanodeHeartbeatDispatcher - .PipelineActionsFromDatanode; - -import org.apache.hadoop.hdds.server.events.EventHandler; -import org.apache.hadoop.hdds.server.events.EventPublisher; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Handles pipeline actions from datanode. - */ -public class PipelineActionEventHandler implements - EventHandler { - - public static final Logger LOG = LoggerFactory.getLogger( - PipelineActionEventHandler.class); - - public PipelineActionEventHandler() { - - } - - @Override - public void onMessage(PipelineActionsFromDatanode report, - EventPublisher publisher) { - for (PipelineAction action : report.getReport().getPipelineActionsList()) { - switch (action.getAction()) { - case CLOSE: - PipelineID pipelineID = PipelineID. - getFromProtobuf(action.getClosePipeline().getPipelineID()); - LOG.info("Closing pipeline " + pipelineID + " for reason:" + action - .getClosePipeline().getDetailedReason()); - publisher.fireEvent(SCMEvents.PIPELINE_CLOSE, pipelineID); - break; - default: - LOG.error("unknown pipeline action:{}" + action.getAction()); - } - } - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/PipelineCloseHandler.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/PipelineCloseHandler.java deleted file mode 100644 index e49678fee81..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/PipelineCloseHandler.java +++ /dev/null @@ -1,52 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.hdds.scm.pipelines; - -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.scm.container.common.helpers.PipelineID; -import org.apache.hadoop.hdds.server.events.EventHandler; -import org.apache.hadoop.hdds.server.events.EventPublisher; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Handles pipeline close event. - */ -public class PipelineCloseHandler implements EventHandler { - private static final Logger LOG = LoggerFactory - .getLogger(PipelineCloseHandler.class); - - private final PipelineSelector pipelineSelector; - public PipelineCloseHandler(PipelineSelector pipelineSelector) { - this.pipelineSelector = pipelineSelector; - } - - @Override - public void onMessage(PipelineID pipelineID, EventPublisher publisher) { - Pipeline pipeline = pipelineSelector.getPipeline(pipelineID); - try { - if (pipeline != null) { - pipelineSelector.finalizePipeline(pipeline); - } else { - LOG.debug("pipeline:{} not found", pipelineID); - } - } catch (Exception e) { - LOG.info("failed to close pipeline:{}", pipelineID, e); - } - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/PipelineManager.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/PipelineManager.java deleted file mode 100644 index ca2e8786370..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/PipelineManager.java +++ /dev/null @@ -1,171 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.scm.pipelines; - -import java.util.ArrayList; -import java.util.LinkedList; - -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationFactor; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationType; -import org.apache.hadoop.hdds.scm.container.common.helpers.PipelineID; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * Manage Ozone pipelines. - */ -public abstract class PipelineManager { - private static final Logger LOG = - LoggerFactory.getLogger(PipelineManager.class); - protected final ArrayList activePipelines; - - public PipelineManager() { - activePipelines = new ArrayList<>(); - for (ReplicationFactor factor : ReplicationFactor.values()) { - activePipelines.add(factor.ordinal(), new ActivePipelines()); - } - } - - /** - * List of active pipelines. - */ - public static class ActivePipelines { - private final List activePipelines; - private final AtomicInteger pipelineIndex; - - ActivePipelines() { - activePipelines = new LinkedList<>(); - pipelineIndex = new AtomicInteger(0); - } - - void addPipeline(PipelineID pipelineID) { - if (!activePipelines.contains(pipelineID)) { - activePipelines.add(pipelineID); - } - } - - public void removePipeline(PipelineID pipelineID) { - activePipelines.remove(pipelineID); - } - - /** - * Find a Pipeline that is operational. - * - * @return - Pipeline or null - */ - PipelineID findOpenPipeline() { - if (activePipelines.size() == 0) { - LOG.error("No Operational pipelines found. Returning null."); - return null; - } - return activePipelines.get(getNextIndex()); - } - - /** - * gets the next index of the Pipeline to get. - * - * @return index in the link list to get. - */ - private int getNextIndex() { - return pipelineIndex.incrementAndGet() % activePipelines.size(); - } - } - - /** - * This function is called by the Container Manager while allocating a new - * container. The client specifies what kind of replication pipeline is - * needed and based on the replication type in the request appropriate - * Interface is invoked. - * - * @param replicationFactor - Replication Factor - * @return a Pipeline. - */ - public synchronized final PipelineID getPipeline( - ReplicationFactor replicationFactor, ReplicationType replicationType) { - PipelineID id = - activePipelines.get(replicationFactor.ordinal()).findOpenPipeline(); - if (id != null) { - LOG.debug("re-used pipeline:{} for container with " + - "replicationType:{} replicationFactor:{}", - id, replicationType, replicationFactor); - } - if (id == null) { - LOG.error("Get pipeline call failed. We are not able to find" + - " operational pipeline."); - return null; - } else { - return id; - } - } - - void addOpenPipeline(Pipeline pipeline) { - activePipelines.get(pipeline.getFactor().ordinal()) - .addPipeline(pipeline.getId()); - } - - public abstract Pipeline allocatePipeline( - ReplicationFactor replicationFactor); - - /** - * Initialize the pipeline. - * TODO: move the initialization to Ozone Client later - */ - public abstract void initializePipeline(Pipeline pipeline) throws IOException; - - public void processPipelineReport(Pipeline pipeline, DatanodeDetails dn) { - if (pipeline.addMember(dn) - &&(pipeline.getDatanodes().size() == pipeline.getFactor().getNumber()) - && pipeline.getLifeCycleState() == HddsProtos.LifeCycleState.OPEN) { - addOpenPipeline(pipeline); - } - } - - /** - * Creates a pipeline with a specified replication factor and type. - * @param replicationFactor - Replication Factor. - * @param replicationType - Replication Type. - */ - public Pipeline createPipeline(ReplicationFactor replicationFactor, - ReplicationType replicationType) throws IOException { - Pipeline pipeline = allocatePipeline(replicationFactor); - if (pipeline != null) { - LOG.debug("created new pipeline:{} for container with " - + "replicationType:{} replicationFactor:{}", - pipeline.getId(), replicationType, replicationFactor); - } - return pipeline; - } - - /** - * Remove the pipeline from active allocation. - * @param pipeline pipeline to be finalized - */ - public abstract boolean finalizePipeline(Pipeline pipeline); - - /** - * - * @param pipeline - */ - public abstract void closePipeline(Pipeline pipeline) throws IOException; -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/PipelineReportHandler.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/PipelineReportHandler.java deleted file mode 100644 index 933792bee34..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/PipelineReportHandler.java +++ /dev/null @@ -1,59 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.pipelines; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.PipelineReportsProto; -import org.apache.hadoop.hdds.scm.server - .SCMDatanodeHeartbeatDispatcher.PipelineReportFromDatanode; -import org.apache.hadoop.hdds.server.events.EventHandler; -import org.apache.hadoop.hdds.server.events.EventPublisher; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Handles Node Reports from datanode. - */ -public class PipelineReportHandler implements - EventHandler { - - private static final Logger LOGGER = LoggerFactory - .getLogger(PipelineReportHandler.class); - private final PipelineSelector pipelineSelector; - - public PipelineReportHandler(PipelineSelector pipelineSelector) { - Preconditions.checkNotNull(pipelineSelector); - this.pipelineSelector = pipelineSelector; - } - - @Override - public void onMessage(PipelineReportFromDatanode pipelineReportFromDatanode, - EventPublisher publisher) { - Preconditions.checkNotNull(pipelineReportFromDatanode); - DatanodeDetails dn = pipelineReportFromDatanode.getDatanodeDetails(); - PipelineReportsProto pipelineReport = - pipelineReportFromDatanode.getReport(); - Preconditions.checkNotNull(dn, "Pipeline Report is " - + "missing DatanodeDetails."); - LOGGER.trace("Processing pipeline report for dn: {}", dn); - pipelineSelector.processPipelineReport(dn, pipelineReport); - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/PipelineSelector.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/PipelineSelector.java deleted file mode 100644 index c8d22ff6450..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/PipelineSelector.java +++ /dev/null @@ -1,481 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.scm.pipelines; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.conf.StorageUnit; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.PipelineReportsProto; -import org.apache.hadoop.hdds.scm.ScmConfigKeys; -import org.apache.hadoop.hdds.scm.container.ContainerID; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.scm.container.common.helpers.PipelineID; -import org.apache.hadoop.hdds.scm.container.placement.algorithms - .ContainerPlacementPolicy; -import org.apache.hadoop.hdds.scm.container.placement.algorithms - .SCMContainerPlacementRandom; -import org.apache.hadoop.hdds.scm.events.SCMEvents; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.hdds.scm.node.NodeManager; -import org.apache.hadoop.hdds.scm.pipelines.ratis.RatisManagerImpl; -import org.apache.hadoop.hdds.scm.pipelines.standalone.StandaloneManagerImpl; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.LifeCycleState; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationFactor; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationType; -import org.apache.hadoop.hdds.server.events.EventPublisher; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.lease.Lease; -import org.apache.hadoop.ozone.lease.LeaseException; -import org.apache.hadoop.ozone.lease.LeaseManager; -import org.apache.hadoop.utils.MetadataStore; -import org.apache.hadoop.utils.MetadataStoreBuilder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.HashSet; -import java.util.List; -import java.util.HashMap; -import java.util.Set; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; - -import static org.apache.hadoop.hdds.scm.exceptions.SCMException.ResultCodes - .FAILED_TO_CHANGE_PIPELINE_STATE; -import static org.apache.hadoop.hdds.scm.exceptions.SCMException.ResultCodes.FAILED_TO_FIND_ACTIVE_PIPELINE; -import static org.apache.hadoop.hdds.server - .ServerUtils.getOzoneMetaDirPath; -import static org.apache.hadoop.ozone - .OzoneConsts.SCM_PIPELINE_DB; - -/** - * Sends the request to the right pipeline manager. - */ -public class PipelineSelector { - private static final Logger LOG = - LoggerFactory.getLogger(PipelineSelector.class); - private final ContainerPlacementPolicy placementPolicy; - private final Map pipelineManagerMap; - private final Configuration conf; - private final EventPublisher eventPublisher; - private final long containerSize; - private final MetadataStore pipelineStore; - private final PipelineStateManager stateManager; - private final NodeManager nodeManager; - private final Map> pipeline2ContainerMap; - private final Map pipelineMap; - private final LeaseManager pipelineLeaseManager; - - /** - * Constructs a pipeline Selector. - * - * @param nodeManager - node manager - * @param conf - Ozone Config - */ - public PipelineSelector(NodeManager nodeManager, Configuration conf, - EventPublisher eventPublisher, int cacheSizeMB) throws IOException { - this.conf = conf; - this.eventPublisher = eventPublisher; - this.placementPolicy = createContainerPlacementPolicy(nodeManager, conf); - this.containerSize = (long)this.conf.getStorageSize( - ScmConfigKeys.OZONE_SCM_CONTAINER_SIZE, - ScmConfigKeys.OZONE_SCM_CONTAINER_SIZE_DEFAULT, - StorageUnit.BYTES); - pipelineMap = new ConcurrentHashMap<>(); - pipelineManagerMap = new HashMap<>(); - - pipelineManagerMap.put(ReplicationType.STAND_ALONE, - new StandaloneManagerImpl(nodeManager, placementPolicy, - containerSize)); - pipelineManagerMap.put(ReplicationType.RATIS, - new RatisManagerImpl(nodeManager, placementPolicy, - containerSize, conf)); - long pipelineCreationLeaseTimeout = conf.getTimeDuration( - ScmConfigKeys.OZONE_SCM_PIPELINE_CREATION_LEASE_TIMEOUT, - ScmConfigKeys.OZONE_SCM_PIPELINE_CREATION_LEASE_TIMEOUT_DEFAULT, - TimeUnit.MILLISECONDS); - pipelineLeaseManager = new LeaseManager<>("PipelineCreation", - pipelineCreationLeaseTimeout); - pipelineLeaseManager.start(); - - stateManager = new PipelineStateManager(); - this.nodeManager = nodeManager; - pipeline2ContainerMap = new HashMap<>(); - - // Write the container name to pipeline mapping. - File metaDir = getOzoneMetaDirPath(conf); - File containerDBPath = new File(metaDir, SCM_PIPELINE_DB); - pipelineStore = MetadataStoreBuilder.newBuilder() - .setConf(conf) - .setDbFile(containerDBPath) - .setCacheSize(cacheSizeMB * OzoneConsts.MB) - .build(); - - reloadExistingPipelines(); - } - - private void reloadExistingPipelines() throws IOException { - if (pipelineStore.isEmpty()) { - // Nothing to do just return - return; - } - - List> range = - pipelineStore.getSequentialRangeKVs(null, Integer.MAX_VALUE, null); - - // Transform the values into the pipelines. - // TODO: filter by pipeline state - for (Map.Entry entry : range) { - Pipeline pipeline = Pipeline.getFromProtoBuf( - HddsProtos.Pipeline.PARSER.parseFrom(entry.getValue())); - Preconditions.checkNotNull(pipeline); - addExistingPipeline(pipeline); - } - } - - @VisibleForTesting - public Set getOpenContainerIDsByPipeline(PipelineID pipelineID) { - return pipeline2ContainerMap.get(pipelineID); - } - - public void addContainerToPipeline(PipelineID pipelineID, long containerID) { - pipeline2ContainerMap.get(pipelineID) - .add(ContainerID.valueof(containerID)); - } - - public void removeContainerFromPipeline(PipelineID pipelineID, - long containerID) throws IOException { - pipeline2ContainerMap.get(pipelineID) - .remove(ContainerID.valueof(containerID)); - closePipelineIfNoOpenContainers(pipelineMap.get(pipelineID)); - } - - /** - * Translates a list of nodes, ordered such that the first is the leader, into - * a corresponding {@link Pipeline} object. - * - * @param nodes - list of datanodes on which we will allocate the container. - * The first of the list will be the leader node. - * @return pipeline corresponding to nodes - */ - public static Pipeline newPipelineFromNodes( - List nodes, ReplicationType replicationType, - ReplicationFactor replicationFactor, PipelineID id) { - Preconditions.checkNotNull(nodes); - Preconditions.checkArgument(nodes.size() > 0); - String leaderId = nodes.get(0).getUuidString(); - // A new pipeline always starts in allocated state - Pipeline pipeline = new Pipeline(leaderId, LifeCycleState.ALLOCATED, - replicationType, replicationFactor, id); - for (DatanodeDetails node : nodes) { - pipeline.addMember(node); - } - return pipeline; - } - - /** - * Create pluggable container placement policy implementation instance. - * - * @param nodeManager - SCM node manager. - * @param conf - configuration. - * @return SCM container placement policy implementation instance. - */ - @SuppressWarnings("unchecked") - private static ContainerPlacementPolicy createContainerPlacementPolicy( - final NodeManager nodeManager, final Configuration conf) { - Class implClass = - (Class) conf.getClass( - ScmConfigKeys.OZONE_SCM_CONTAINER_PLACEMENT_IMPL_KEY, - SCMContainerPlacementRandom.class); - - try { - Constructor ctor = - implClass.getDeclaredConstructor(NodeManager.class, - Configuration.class); - return ctor.newInstance(nodeManager, conf); - } catch (RuntimeException e) { - throw e; - } catch (InvocationTargetException e) { - throw new RuntimeException(implClass.getName() - + " could not be constructed.", e.getCause()); - } catch (Exception e) { - LOG.error("Unhandled exception occurred, Placement policy will not be " + - "functional."); - throw new IllegalArgumentException("Unable to load " + - "ContainerPlacementPolicy", e); - } - } - - /** - * This function is called by the Container Manager while allocating a new - * container. The client specifies what kind of replication pipeline is needed - * and based on the replication type in the request appropriate Interface is - * invoked. - */ - - public Pipeline getReplicationPipeline(ReplicationType replicationType, - HddsProtos.ReplicationFactor replicationFactor) - throws IOException { - PipelineManager manager = pipelineManagerMap.get(replicationType); - Preconditions.checkNotNull(manager, "Found invalid pipeline manager"); - LOG.debug("Getting replication pipeline forReplicationType {} :" + - " ReplicationFactor {}", replicationType.toString(), - replicationFactor.toString()); - - /** - * In the Ozone world, we have a very simple policy. - * - * 1. Try to create a pipeline if there are enough free nodes. - * - * 2. This allows all nodes to part of a pipeline quickly. - * - * 3. if there are not enough free nodes, return already allocated pipeline - * in a round-robin fashion. - * - * TODO: Might have to come up with a better algorithm than this. - * Create a new placement policy that returns pipelines in round robin - * fashion. - */ - Pipeline pipeline = - manager.createPipeline(replicationFactor, replicationType); - if (pipeline == null) { - // try to return a pipeline from already allocated pipelines - PipelineID pipelineId = - manager.getPipeline(replicationFactor, replicationType); - if (pipelineId == null) { - throw new SCMException(FAILED_TO_FIND_ACTIVE_PIPELINE); - } - pipeline = pipelineMap.get(pipelineId); - Preconditions.checkArgument(pipeline.getLifeCycleState() == - LifeCycleState.OPEN); - } else { - pipelineStore.put(pipeline.getId().getProtobuf().toByteArray(), - pipeline.getProtobufMessage().toByteArray()); - // if a new pipeline is created, initialize its state machine - updatePipelineState(pipeline, HddsProtos.LifeCycleEvent.CREATE); - - //TODO: move the initialization of pipeline to Ozone Client - manager.initializePipeline(pipeline); - updatePipelineState(pipeline, HddsProtos.LifeCycleEvent.CREATED); - } - return pipeline; - } - - /** - * This function to return pipeline for given pipeline id. - */ - public Pipeline getPipeline(PipelineID pipelineID) { - return pipelineMap.get(pipelineID); - } - - /** - * Finalize a given pipeline. - */ - public void finalizePipeline(Pipeline pipeline) throws IOException { - PipelineManager manager = pipelineManagerMap.get(pipeline.getType()); - Preconditions.checkNotNull(manager, "Found invalid pipeline manager"); - if (pipeline.getLifeCycleState() == LifeCycleState.CLOSING || - pipeline.getLifeCycleState() == LifeCycleState.CLOSED) { - LOG.debug("pipeline:{} already in closing state, skipping", - pipeline.getId()); - // already in closing/closed state - return; - } - - // Remove the pipeline from active allocation - if (manager.finalizePipeline(pipeline)) { - LOG.info("Finalizing pipeline. pipelineID: {}", pipeline.getId()); - updatePipelineState(pipeline, HddsProtos.LifeCycleEvent.FINALIZE); - closePipelineIfNoOpenContainers(pipeline); - } - } - - /** - * Close a given pipeline. - */ - private void closePipelineIfNoOpenContainers(Pipeline pipeline) - throws IOException { - if (pipeline.getLifeCycleState() != LifeCycleState.CLOSING) { - return; - } - HashSet containerIDS = - pipeline2ContainerMap.get(pipeline.getId()); - if (containerIDS.size() == 0) { - updatePipelineState(pipeline, HddsProtos.LifeCycleEvent.CLOSE); - LOG.info("Closing pipeline. pipelineID: {}", pipeline.getId()); - } - } - - /** - * Close a given pipeline. - */ - private void closePipeline(Pipeline pipeline) throws IOException { - PipelineManager manager = pipelineManagerMap.get(pipeline.getType()); - Preconditions.checkNotNull(manager, "Found invalid pipeline manager"); - LOG.debug("Closing pipeline. pipelineID: {}", pipeline.getId()); - HashSet containers = - pipeline2ContainerMap.get(pipeline.getId()); - Preconditions.checkArgument(containers.size() == 0); - manager.closePipeline(pipeline); - } - - /** - * Add to a given pipeline. - */ - private void addOpenPipeline(Pipeline pipeline) { - PipelineManager manager = pipelineManagerMap.get(pipeline.getType()); - Preconditions.checkNotNull(manager, "Found invalid pipeline manager"); - LOG.debug("Adding Open pipeline. pipelineID: {}", pipeline.getId()); - manager.addOpenPipeline(pipeline); - } - - private void closeContainersByPipeline(Pipeline pipeline) { - HashSet containers = - pipeline2ContainerMap.get(pipeline.getId()); - for (ContainerID id : containers) { - eventPublisher.fireEvent(SCMEvents.CLOSE_CONTAINER, id); - } - } - - private void addExistingPipeline(Pipeline pipeline) throws IOException { - LifeCycleState state = pipeline.getLifeCycleState(); - switch (state) { - case ALLOCATED: - // a pipeline in allocated state is only present in SCM and does not exist - // on datanode, on SCM restart, this pipeline can be ignored. - break; - case CREATING: - case OPEN: - case CLOSING: - //TODO: process pipeline report and move pipeline to active queue - // when all the nodes have reported. - pipelineMap.put(pipeline.getId(), pipeline); - pipeline2ContainerMap.put(pipeline.getId(), new HashSet<>()); - nodeManager.addPipeline(pipeline); - // reset the datanodes in the pipeline - // they will be reset on - pipeline.resetPipeline(); - break; - case CLOSED: - // if the pipeline is in closed state, nothing to do. - break; - default: - throw new IOException("invalid pipeline state:" + state); - } - } - - public void handleStaleNode(DatanodeDetails dn) { - Set pipelineIDs = nodeManager.getPipelineByDnID(dn.getUuid()); - for (PipelineID id : pipelineIDs) { - LOG.info("closing pipeline {}.", id); - eventPublisher.fireEvent(SCMEvents.PIPELINE_CLOSE, id); - } - } - - void processPipelineReport(DatanodeDetails dn, - PipelineReportsProto pipelineReport) { - Set reportedPipelines = new HashSet<>(); - pipelineReport.getPipelineReportList(). - forEach(p -> - reportedPipelines.add( - processPipelineReport(p.getPipelineID(), dn))); - - //TODO: handle missing pipelines and new pipelines later - } - - private PipelineID processPipelineReport( - HddsProtos.PipelineID id, DatanodeDetails dn) { - PipelineID pipelineID = PipelineID.getFromProtobuf(id); - Pipeline pipeline = pipelineMap.get(pipelineID); - if (pipeline != null) { - pipelineManagerMap.get(pipeline.getType()) - .processPipelineReport(pipeline, dn); - } - return pipelineID; - } - - /** - * Update the Pipeline State to the next state. - * - * @param pipeline - Pipeline - * @param event - LifeCycle Event - * @throws SCMException on Failure. - */ - public void updatePipelineState(Pipeline pipeline, - HddsProtos.LifeCycleEvent event) throws IOException { - try { - switch (event) { - case CREATE: - pipelineMap.put(pipeline.getId(), pipeline); - pipeline2ContainerMap.put(pipeline.getId(), new HashSet<>()); - nodeManager.addPipeline(pipeline); - // Acquire lease on pipeline - Lease pipelineLease = pipelineLeaseManager.acquire(pipeline); - // Register callback to be executed in case of timeout - pipelineLease.registerCallBack(() -> { - updatePipelineState(pipeline, HddsProtos.LifeCycleEvent.TIMEOUT); - return null; - }); - break; - case CREATED: - // Release the lease on pipeline - pipelineLeaseManager.release(pipeline); - addOpenPipeline(pipeline); - break; - - case FINALIZE: - closeContainersByPipeline(pipeline); - break; - - case CLOSE: - case TIMEOUT: - closePipeline(pipeline); - pipeline2ContainerMap.remove(pipeline.getId()); - nodeManager.removePipeline(pipeline); - pipelineMap.remove(pipeline.getId()); - break; - default: - throw new SCMException("Unsupported pipeline LifeCycleEvent.", - FAILED_TO_CHANGE_PIPELINE_STATE); - } - - stateManager.updatePipelineState(pipeline, event); - pipelineStore.put(pipeline.getId().getProtobuf().toByteArray(), - pipeline.getProtobufMessage().toByteArray()); - } catch (LeaseException e) { - throw new IOException("Lease Exception.", e); - } - } - - public void shutdown() throws IOException { - if (pipelineLeaseManager != null) { - pipelineLeaseManager.shutdown(); - } - - if (pipelineStore != null) { - pipelineStore.close(); - } - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/PipelineStateManager.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/PipelineStateManager.java deleted file mode 100644 index 6054f165444..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/PipelineStateManager.java +++ /dev/null @@ -1,136 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.scm.pipelines; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.ozone.common.statemachine - .InvalidStateTransitionException; -import org.apache.hadoop.ozone.common.statemachine.StateMachine; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.HashSet; -import java.util.Set; - -import static org.apache.hadoop.hdds.scm.exceptions.SCMException.ResultCodes - .FAILED_TO_CHANGE_PIPELINE_STATE; - -/** - * Manages Pipeline states. - */ -public class PipelineStateManager { - private static final Logger LOG = - LoggerFactory.getLogger(PipelineStateManager.class); - - private final StateMachine stateMachine; - - PipelineStateManager() { - // Initialize the container state machine. - Set finalStates = new HashSet<>(); - // These are the steady states of a container. - finalStates.add(HddsProtos.LifeCycleState.OPEN); - finalStates.add(HddsProtos.LifeCycleState.CLOSED); - - this.stateMachine = new StateMachine<>(HddsProtos.LifeCycleState.ALLOCATED, - finalStates); - initializeStateMachine(); - } - - /** - * Event and State Transition Mapping. - * - * State: ALLOCATED ---------------> CREATING - * Event: CREATE - * - * State: CREATING ---------------> OPEN - * Event: CREATED - * - * State: OPEN ---------------> CLOSING - * Event: FINALIZE - * - * State: CLOSING ---------------> CLOSED - * Event: CLOSE - * - * State: CREATING ---------------> CLOSED - * Event: TIMEOUT - * - * - * Container State Flow: - * - * [ALLOCATED]---->[CREATING]------>[OPEN]-------->[CLOSING] - * (CREATE) | (CREATED) (FINALIZE) | - * | | - * | | - * |(TIMEOUT) |(CLOSE) - * | | - * +--------> [CLOSED] <--------+ - */ - private void initializeStateMachine() { - stateMachine.addTransition(HddsProtos.LifeCycleState.ALLOCATED, - HddsProtos.LifeCycleState.CREATING, - HddsProtos.LifeCycleEvent.CREATE); - - stateMachine.addTransition(HddsProtos.LifeCycleState.CREATING, - HddsProtos.LifeCycleState.OPEN, - HddsProtos.LifeCycleEvent.CREATED); - - stateMachine.addTransition(HddsProtos.LifeCycleState.OPEN, - HddsProtos.LifeCycleState.CLOSING, - HddsProtos.LifeCycleEvent.FINALIZE); - - stateMachine.addTransition(HddsProtos.LifeCycleState.CLOSING, - HddsProtos.LifeCycleState.CLOSED, - HddsProtos.LifeCycleEvent.CLOSE); - - stateMachine.addTransition(HddsProtos.LifeCycleState.CREATING, - HddsProtos.LifeCycleState.CLOSED, - HddsProtos.LifeCycleEvent.TIMEOUT); - } - - - /** - * Update the Pipeline State to the next state. - * - * @param pipeline - Pipeline - * @param event - LifeCycle Event - * @throws SCMException on Failure. - */ - public void updatePipelineState(Pipeline pipeline, - HddsProtos.LifeCycleEvent event) throws IOException { - HddsProtos.LifeCycleState newState; - try { - newState = stateMachine.getNextState(pipeline.getLifeCycleState(), event); - } catch (InvalidStateTransitionException ex) { - String error = String.format("Failed to update pipeline state %s, " + - "reason: invalid state transition from state: %s upon " + - "event: %s.", - pipeline.getId(), pipeline.getLifeCycleState(), event); - LOG.error(error); - throw new SCMException(error, FAILED_TO_CHANGE_PIPELINE_STATE); - } - - // This is a post condition after executing getNextState. - Preconditions.checkNotNull(newState); - Preconditions.checkNotNull(pipeline); - pipeline.setLifeCycleState(newState); - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/package-info.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/package-info.java deleted file mode 100644 index ea24c581a8c..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/package-info.java +++ /dev/null @@ -1,38 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.pipelines; -/** - Ozone supports the notion of different kind of pipelines. - That means that we can have a replication pipeline build on - Ratis, Standalone or some other protocol. All Pipeline managers - the entities in charge of pipelines reside in the package. - - Here is the high level Arch. - - 1. A pipeline selector class is instantiated in the Container manager class. - - 2. A client when creating a container -- will specify what kind of - replication type it wants to use. We support 2 types now, Ratis and StandAlone. - - 3. Based on the replication type, the pipeline selector class asks the - corresponding pipeline manager for a pipeline. - - 4. We have supported the ability for clients to specify a set of nodes in - the pipeline or rely in the pipeline manager to select the datanodes if they - are not specified. - */ \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/ratis/RatisManagerImpl.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/ratis/RatisManagerImpl.java deleted file mode 100644 index 905a5b553b7..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/ratis/RatisManagerImpl.java +++ /dev/null @@ -1,129 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.scm.pipelines.ratis; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.scm.XceiverClientRatis; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.scm.container.common.helpers.PipelineID; -import org.apache.hadoop.hdds.scm.container.placement.algorithms - .ContainerPlacementPolicy; -import org.apache.hadoop.hdds.scm.node.NodeManager; -import org.apache.hadoop.hdds.scm.pipelines.PipelineManager; -import org.apache.hadoop.hdds.scm.pipelines.PipelineSelector; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationFactor; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; - -/** - * Implementation of {@link PipelineManager}. - * - * TODO : Introduce a state machine. - */ -public class RatisManagerImpl extends PipelineManager { - private static final Logger LOG = - LoggerFactory.getLogger(RatisManagerImpl.class); - private final Configuration conf; - private final NodeManager nodeManager; - private final Set ratisMembers; - - /** - * Constructs a Ratis Pipeline Manager. - * - * @param nodeManager - */ - public RatisManagerImpl(NodeManager nodeManager, - ContainerPlacementPolicy placementPolicy, long size, Configuration conf) { - super(); - this.conf = conf; - this.nodeManager = nodeManager; - ratisMembers = new HashSet<>(); - } - - /** - * Allocates a new ratis Pipeline from the free nodes. - * - * @param factor - One or Three - * @return Pipeline. - */ - public Pipeline allocatePipeline(ReplicationFactor factor) { - List newNodesList = new LinkedList<>(); - List datanodes = nodeManager.getNodes(NodeState.HEALTHY); - //TODO: Add Raft State to the Nodes, so we can query and skip nodes from - // data from datanode instead of maintaining a set. - for (DatanodeDetails datanode : datanodes) { - Preconditions.checkNotNull(datanode); - if (!ratisMembers.contains(datanode)) { - newNodesList.add(datanode); - if (newNodesList.size() == factor.getNumber()) { - // once a datanode has been added to a pipeline, exclude it from - // further allocations - ratisMembers.addAll(newNodesList); - PipelineID pipelineID = PipelineID.randomId(); - LOG.info("Allocating a new ratis pipeline of size: {} id: {}", - factor.getNumber(), pipelineID); - return PipelineSelector.newPipelineFromNodes(newNodesList, - ReplicationType.RATIS, factor, pipelineID); - } - } - } - return null; - } - - public void initializePipeline(Pipeline pipeline) throws IOException { - //TODO:move the initialization from SCM to client - try (XceiverClientRatis client = - XceiverClientRatis.newXceiverClientRatis(pipeline, conf)) { - client.createPipeline(); - } - } - - public void processPipelineReport(Pipeline pipeline, DatanodeDetails dn) { - super.processPipelineReport(pipeline, dn); - ratisMembers.add(dn); - } - - public synchronized boolean finalizePipeline(Pipeline pipeline) { - activePipelines.get(pipeline.getFactor().ordinal()) - .removePipeline(pipeline.getId()); - return true; - } - - /** - * Close the pipeline. - */ - public void closePipeline(Pipeline pipeline) throws IOException { - try (XceiverClientRatis client = - XceiverClientRatis.newXceiverClientRatis(pipeline, conf)) { - client.destroyPipeline(); - } - for (DatanodeDetails node : pipeline.getMachines()) { - // A node should always be the in ratis members list. - Preconditions.checkArgument(ratisMembers.remove(node)); - } - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/ratis/package-info.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/ratis/package-info.java deleted file mode 100644 index 2970fb354bf..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/ratis/package-info.java +++ /dev/null @@ -1,18 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.pipelines.ratis; \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/standalone/StandaloneManagerImpl.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/standalone/StandaloneManagerImpl.java deleted file mode 100644 index 045afb6ceb9..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/standalone/StandaloneManagerImpl.java +++ /dev/null @@ -1,122 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.scm.pipelines.standalone; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.scm.container.common.helpers.PipelineID; -import org.apache.hadoop.hdds.scm.container.placement.algorithms - .ContainerPlacementPolicy; -import org.apache.hadoop.hdds.scm.node.NodeManager; -import org.apache.hadoop.hdds.scm.pipelines.PipelineManager; -import org.apache.hadoop.hdds.scm.pipelines.PipelineSelector; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationFactor; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; - -/** - * Standalone Manager Impl to prove that pluggable interface - * works with current tests. - */ -public class StandaloneManagerImpl extends PipelineManager { - private static final Logger LOG = - LoggerFactory.getLogger(StandaloneManagerImpl.class); - private final NodeManager nodeManager; - private final ContainerPlacementPolicy placementPolicy; - private final long containerSize; - private final Set standAloneMembers; - - /** - * Constructor for Standalone Node Manager Impl. - * @param nodeManager - Node Manager. - * @param placementPolicy - Placement Policy - * @param containerSize - Container Size. - */ - public StandaloneManagerImpl(NodeManager nodeManager, - ContainerPlacementPolicy placementPolicy, long containerSize) { - super(); - this.nodeManager = nodeManager; - this.placementPolicy = placementPolicy; - this.containerSize = containerSize; - this.standAloneMembers = new HashSet<>(); - } - - - /** - * Allocates a new standalone Pipeline from the free nodes. - * - * @param factor - One - * @return Pipeline. - */ - public Pipeline allocatePipeline(ReplicationFactor factor) { - List newNodesList = new LinkedList<>(); - List datanodes = nodeManager.getNodes(NodeState.HEALTHY); - for (DatanodeDetails datanode : datanodes) { - Preconditions.checkNotNull(datanode); - if (!standAloneMembers.contains(datanode)) { - newNodesList.add(datanode); - if (newNodesList.size() == factor.getNumber()) { - // once a datanode has been added to a pipeline, exclude it from - // further allocations - standAloneMembers.addAll(newNodesList); - // Standalone pipeline use node id as pipeline - PipelineID pipelineID = - PipelineID.valueOf(newNodesList.get(0).getUuid()); - LOG.info("Allocating a new standalone pipeline of size: {} id: {}", - factor.getNumber(), pipelineID); - return PipelineSelector.newPipelineFromNodes(newNodesList, - ReplicationType.STAND_ALONE, ReplicationFactor.ONE, pipelineID); - } - } - } - return null; - } - - public void initializePipeline(Pipeline pipeline) { - // Nothing to be done for standalone pipeline - } - - public void processPipelineReport(Pipeline pipeline, DatanodeDetails dn) { - super.processPipelineReport(pipeline, dn); - standAloneMembers.add(dn); - } - - public synchronized boolean finalizePipeline(Pipeline pipeline) { - activePipelines.get(pipeline.getFactor().ordinal()) - .removePipeline(pipeline.getId()); - return false; - } - - /** - * Close the pipeline. - */ - public void closePipeline(Pipeline pipeline) throws IOException { - for (DatanodeDetails node : pipeline.getMachines()) { - // A node should always be the in standalone members list. - Preconditions.checkArgument(standAloneMembers.remove(node)); - } - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/standalone/package-info.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/standalone/package-info.java deleted file mode 100644 index b2c3ca40e50..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipelines/standalone/package-info.java +++ /dev/null @@ -1,18 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.pipelines.standalone; \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ratis/package-info.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ratis/package-info.java deleted file mode 100644 index 49440175932..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ratis/package-info.java +++ /dev/null @@ -1,22 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.ratis; - -/** - * This package contains classes related to Apache Ratis for SCM. - */ diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/ChillModePrecheck.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/ChillModePrecheck.java deleted file mode 100644 index b92413e80ca..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/ChillModePrecheck.java +++ /dev/null @@ -1,56 +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 - * - *      http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.server; - -import java.util.concurrent.atomic.AtomicBoolean; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ScmOps; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.hdds.scm.exceptions.SCMException.ResultCodes; -import org.apache.hadoop.hdds.scm.server.SCMChillModeManager.ChillModeRestrictedOps; - -/** - * Chill mode pre-check for SCM operations. - * */ -public class ChillModePrecheck implements Precheck { - - private AtomicBoolean inChillMode = new AtomicBoolean(true); - public static final String PRECHECK_TYPE = "ChillModePrecheck"; - - public boolean check(ScmOps op) throws SCMException { - if (inChillMode.get() && ChillModeRestrictedOps - .isRestrictedInChillMode(op)) { - throw new SCMException("ChillModePrecheck failed for " + op, - ResultCodes.CHILL_MODE_EXCEPTION); - } - return inChillMode.get(); - } - - @Override - public String type() { - return PRECHECK_TYPE; - } - - public boolean isInChillMode() { - return inChillMode.get(); - } - - public void setInChillMode(boolean inChillMode) { - this.inChillMode.set(inChillMode); - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/Precheck.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/Precheck.java deleted file mode 100644 index 16549908309..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/Precheck.java +++ /dev/null @@ -1,29 +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 - * - *      http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.server; - -import org.apache.hadoop.hdds.scm.exceptions.SCMException; - -/** - * Precheck for SCM operations. - * */ -public interface Precheck { - boolean check(T t) throws SCMException; - String type(); -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMBlockProtocolServer.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMBlockProtocolServer.java deleted file mode 100644 index 3bb284e8d02..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMBlockProtocolServer.java +++ /dev/null @@ -1,206 +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 - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software - * distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.server; - -import com.google.protobuf.BlockingService; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.protocol.proto.ScmBlockLocationProtocolProtos; -import org.apache.hadoop.hdds.scm.HddsServerUtil; -import org.apache.hadoop.hdds.scm.ScmInfo; -import org.apache.hadoop.hdds.scm.container.common.helpers.AllocatedBlock; -import org.apache.hadoop.hdds.scm.container.common.helpers.DeleteBlockResult; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.hdds.scm.protocol.ScmBlockLocationProtocol; -import org.apache.hadoop.hdds.scm.protocolPB.ScmBlockLocationProtocolPB; -import org.apache.hadoop.io.IOUtils; -import org.apache.hadoop.ipc.ProtobufRpcEngine; -import org.apache.hadoop.ipc.RPC; -import org.apache.hadoop.ozone.common.BlockGroup; -import org.apache.hadoop.hdds.client.BlockID; -import org.apache.hadoop.ozone.common.DeleteBlockGroupResult; -import org.apache.hadoop.ozone.protocolPB - .ScmBlockLocationProtocolServerSideTranslatorPB; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.List; - -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_BLOCK_CLIENT_ADDRESS_KEY; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_HANDLER_COUNT_DEFAULT; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_HANDLER_COUNT_KEY; -import static org.apache.hadoop.hdds.server.ServerUtils.updateRPCListenAddress; -import static org.apache.hadoop.hdds.scm.server.StorageContainerManager - .startRpcServer; - -/** - * SCM block protocol is the protocol used by Namenode and OzoneManager to get - * blocks from the SCM. - */ -public class SCMBlockProtocolServer implements ScmBlockLocationProtocol { - private static final Logger LOG = - LoggerFactory.getLogger(SCMBlockProtocolServer.class); - - private final StorageContainerManager scm; - private final OzoneConfiguration conf; - private final RPC.Server blockRpcServer; - private final InetSocketAddress blockRpcAddress; - - /** - * The RPC server that listens to requests from block service clients. - */ - public SCMBlockProtocolServer(OzoneConfiguration conf, - StorageContainerManager scm) throws IOException { - this.scm = scm; - this.conf = conf; - final int handlerCount = - conf.getInt(OZONE_SCM_HANDLER_COUNT_KEY, - OZONE_SCM_HANDLER_COUNT_DEFAULT); - - RPC.setProtocolEngine(conf, ScmBlockLocationProtocolPB.class, - ProtobufRpcEngine.class); - // SCM Block Service RPC - BlockingService blockProtoPbService = - ScmBlockLocationProtocolProtos.ScmBlockLocationProtocolService - .newReflectiveBlockingService( - new ScmBlockLocationProtocolServerSideTranslatorPB(this)); - - final InetSocketAddress scmBlockAddress = HddsServerUtil - .getScmBlockClientBindAddress(conf); - blockRpcServer = - startRpcServer( - conf, - scmBlockAddress, - ScmBlockLocationProtocolPB.class, - blockProtoPbService, - handlerCount); - blockRpcAddress = - updateRPCListenAddress( - conf, OZONE_SCM_BLOCK_CLIENT_ADDRESS_KEY, scmBlockAddress, - blockRpcServer); - - } - - public RPC.Server getBlockRpcServer() { - return blockRpcServer; - } - - public InetSocketAddress getBlockRpcAddress() { - return blockRpcAddress; - } - - public void start() { - LOG.info( - StorageContainerManager.buildRpcServerStartMessage( - "RPC server for Block Protocol", getBlockRpcAddress())); - getBlockRpcServer().start(); - } - - public void stop() { - try { - LOG.info("Stopping the RPC server for Block Protocol"); - getBlockRpcServer().stop(); - } catch (Exception ex) { - LOG.error("Block Protocol RPC stop failed.", ex); - } - IOUtils.cleanupWithLogger(LOG, scm.getScmNodeManager()); - } - - public void join() throws InterruptedException { - LOG.trace("Join RPC server for Block Protocol"); - getBlockRpcServer().join(); - } - - @Override - public AllocatedBlock allocateBlock(long size, HddsProtos.ReplicationType - type, HddsProtos.ReplicationFactor factor, String owner) throws - IOException { - return scm.getScmBlockManager().allocateBlock(size, type, factor, owner); - } - - /** - * Delete blocks for a set of object keys. - * - * @param keyBlocksInfoList list of block keys with object keys to delete. - * @return deletion results. - */ - @Override - public List deleteKeyBlocks( - List keyBlocksInfoList) throws IOException { - LOG.info("SCM is informed by OM to delete {} blocks", keyBlocksInfoList - .size()); - List results = new ArrayList<>(); - for (BlockGroup keyBlocks : keyBlocksInfoList) { - ScmBlockLocationProtocolProtos.DeleteScmBlockResult.Result resultCode; - try { - // We delete blocks in an atomic operation to prevent getting - // into state like only a partial of blocks are deleted, - // which will leave key in an inconsistent state. - scm.getScmBlockManager().deleteBlocks(keyBlocks.getBlockIDList()); - resultCode = ScmBlockLocationProtocolProtos.DeleteScmBlockResult - .Result.success; - } catch (SCMException scmEx) { - LOG.warn("Fail to delete block: {}", keyBlocks.getGroupID(), scmEx); - switch (scmEx.getResult()) { - case CHILL_MODE_EXCEPTION: - resultCode = ScmBlockLocationProtocolProtos.DeleteScmBlockResult - .Result.chillMode; - break; - case FAILED_TO_FIND_BLOCK: - resultCode = ScmBlockLocationProtocolProtos.DeleteScmBlockResult - .Result.errorNotFound; - break; - default: - resultCode = ScmBlockLocationProtocolProtos.DeleteScmBlockResult - .Result.unknownFailure; - } - } catch (IOException ex) { - LOG.warn("Fail to delete blocks for object key: {}", keyBlocks - .getGroupID(), ex); - resultCode = ScmBlockLocationProtocolProtos.DeleteScmBlockResult - .Result.unknownFailure; - } - List blockResultList = new ArrayList<>(); - for (BlockID blockKey : keyBlocks.getBlockIDList()) { - blockResultList.add(new DeleteBlockResult(blockKey, resultCode)); - } - results.add(new DeleteBlockGroupResult(keyBlocks.getGroupID(), - blockResultList)); - } - return results; - } - - @Override - public ScmInfo getScmInfo() throws IOException { - ScmInfo.Builder builder = - new ScmInfo.Builder() - .setClusterId(scm.getScmStorage().getClusterID()) - .setScmId(scm.getScmStorage().getScmId()); - return builder.build(); - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMChillModeManager.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMChillModeManager.java deleted file mode 100644 index 3c1cc8ff3db..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMChillModeManager.java +++ /dev/null @@ -1,247 +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 - * - *      http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.server; - -import com.google.common.annotations.VisibleForTesting; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicLong; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.HddsConfigKeys; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ScmOps; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo; -import org.apache.hadoop.hdds.scm.events.SCMEvents; -import org.apache.hadoop.hdds.scm.server.SCMDatanodeProtocolServer - .NodeRegistrationContainerReport; -import org.apache.hadoop.hdds.server.events.EventHandler; -import org.apache.hadoop.hdds.server.events.EventPublisher; -import org.apache.hadoop.hdds.server.events.EventQueue; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * StorageContainerManager enters chill mode on startup to allow system to - * reach a stable state before becoming fully functional. SCM will wait - * for certain resources to be reported before coming out of chill mode. - * - * ChillModeExitRule defines format to define new rules which must be satisfied - * to exit Chill mode. - * ContainerChillModeRule defines the only exit criteria right now. - * On every new datanode registration event this class adds replicas - * for reported containers and validates if cutoff threshold for - * containers is meet. - */ -public class SCMChillModeManager implements - EventHandler { - - private static final Logger LOG = - LoggerFactory.getLogger(SCMChillModeManager.class); - private AtomicBoolean inChillMode = new AtomicBoolean(true); - private AtomicLong containerWithMinReplicas = new AtomicLong(0); - private Map exitRules = new HashMap(1); - private Configuration config; - private static final String CONT_EXIT_RULE = "ContainerChillModeRule"; - private final EventQueue eventPublisher; - - SCMChillModeManager(Configuration conf, List allContainers, - EventQueue eventQueue) { - this.config = conf; - this.eventPublisher = eventQueue; - exitRules - .put(CONT_EXIT_RULE, new ContainerChillModeRule(config, allContainers)); - if (!conf.getBoolean(HddsConfigKeys.HDDS_SCM_CHILLMODE_ENABLED, - HddsConfigKeys.HDDS_SCM_CHILLMODE_ENABLED_DEFAULT)) { - exitChillMode(eventQueue); - } - emitChillModeStatus(); - } - - /** - * Emit Chill mode status. - */ - @VisibleForTesting - public void emitChillModeStatus() { - eventPublisher.fireEvent(SCMEvents.CHILL_MODE_STATUS, inChillMode.get()); - } - - private void validateChillModeExitRules(EventPublisher eventQueue) { - for (ChillModeExitRule exitRule : exitRules.values()) { - if (!exitRule.validate()) { - return; - } - } - exitChillMode(eventQueue); - } - - /** - * Exit chill mode. It does following actions: - * 1. Set chill mode status to fale. - * 2. Emits START_REPLICATION for ReplicationManager. - * 3. Cleanup resources. - * 4. Emit chill mode status. - * @param eventQueue - */ - @VisibleForTesting - public void exitChillMode(EventPublisher eventQueue) { - LOG.info("SCM exiting chill mode."); - setInChillMode(false); - - // TODO: Remove handler registration as there is no need to listen to - // register events anymore. - - for (ChillModeExitRule e : exitRules.values()) { - e.cleanup(); - } - emitChillModeStatus(); - } - - @Override - public void onMessage( - NodeRegistrationContainerReport nodeRegistrationContainerReport, - EventPublisher publisher) { - if (getInChillMode()) { - exitRules.get(CONT_EXIT_RULE).process(nodeRegistrationContainerReport); - validateChillModeExitRules(publisher); - } - } - - public boolean getInChillMode() { - return inChillMode.get(); - } - - /** - * Set chill mode status. - */ - public void setInChillMode(boolean inChillMode) { - this.inChillMode.set(inChillMode); - } - - /** - * Interface for defining chill mode exit rules. - * - * @param - */ - public interface ChillModeExitRule { - - boolean validate(); - - void process(T report); - - void cleanup(); - } - - /** - * Class defining Chill mode exit criteria for Containers. - */ - public class ContainerChillModeRule implements - ChillModeExitRule { - - // Required cutoff % for containers with at least 1 reported replica. - private double chillModeCutoff; - // Containers read from scm db. - private Map containerMap; - private double maxContainer; - - public ContainerChillModeRule(Configuration conf, - List containers) { - chillModeCutoff = conf - .getDouble(HddsConfigKeys.HDDS_SCM_CHILLMODE_THRESHOLD_PCT, - HddsConfigKeys.HDDS_SCM_CHILLMODE_THRESHOLD_PCT_DEFAULT); - containerMap = new ConcurrentHashMap<>(); - if(containers != null) { - containers.forEach(c -> { - if (c != null) { - containerMap.put(c.getContainerID(), c); - } - }); - maxContainer = containers.size(); - } - } - - @Override - public boolean validate() { - if (maxContainer == 0) { - return true; - } - return getCurrentContainerThreshold() >= chillModeCutoff; - } - - @VisibleForTesting - public double getCurrentContainerThreshold() { - return (containerWithMinReplicas.doubleValue() / maxContainer); - } - - @Override - public void process(NodeRegistrationContainerReport reportsProto) { - if (maxContainer == 0) { - // No container to check. - return; - } - - reportsProto.getReport().getReportsList().forEach(c -> { - if (containerMap.containsKey(c.getContainerID())) { - if(containerMap.remove(c.getContainerID()) != null) { - containerWithMinReplicas.getAndAdd(1); - } - } - }); - if(inChillMode.get()) { - LOG.info("SCM in chill mode. {} % containers have at least one" - + " reported replica.", - (containerWithMinReplicas.get() / maxContainer) * 100); - } - } - - @Override - public void cleanup() { - containerMap.clear(); - } - } - - @VisibleForTesting - public static Logger getLogger() { - return LOG; - } - - @VisibleForTesting - public double getCurrentContainerThreshold() { - return ((ContainerChillModeRule) exitRules.get(CONT_EXIT_RULE)) - .getCurrentContainerThreshold(); - } - - /** - * Operations restricted in SCM chill mode. - */ - public static class ChillModeRestrictedOps { - private static EnumSet restrictedOps = EnumSet.noneOf(ScmOps.class); - - static { - restrictedOps.add(ScmOps.allocateBlock); - restrictedOps.add(ScmOps.allocateContainer); - } - - public static boolean isRestrictedInChillMode(ScmOps opName) { - return restrictedOps.contains(opName); - } - } - -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java deleted file mode 100644 index 66136f17250..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java +++ /dev/null @@ -1,380 +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 - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software - * distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.server; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import com.google.protobuf.BlockingService; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ScmOps; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos; -import org.apache.hadoop.hdds.scm.HddsServerUtil; -import org.apache.hadoop.hdds.scm.ScmInfo; -import org.apache.hadoop.hdds.scm.ScmUtils; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerWithPipeline; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.hdds.scm.exceptions.SCMException.ResultCodes; -import org.apache.hadoop.hdds.scm.protocol.StorageContainerLocationProtocol; -import org.apache.hadoop.hdds.scm.protocolPB.StorageContainerLocationProtocolPB; -import org.apache.hadoop.hdds.server.events.EventHandler; -import org.apache.hadoop.hdds.server.events.EventPublisher; -import org.apache.hadoop.io.IOUtils; -import org.apache.hadoop.ipc.ProtobufRpcEngine; -import org.apache.hadoop.ipc.RPC; -import org.apache.hadoop.ozone.protocolPB - .StorageContainerLocationProtocolServerSideTranslatorPB; -import org.apache.hadoop.security.UserGroupInformation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; -import java.util.TreeSet; - -import static org.apache.hadoop.hdds.protocol.proto - .StorageContainerLocationProtocolProtos - .StorageContainerLocationProtocolService.newReflectiveBlockingService; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_CLIENT_ADDRESS_KEY; - -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_HANDLER_COUNT_DEFAULT; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_HANDLER_COUNT_KEY; -import static org.apache.hadoop.hdds.server.ServerUtils.updateRPCListenAddress; -import static org.apache.hadoop.hdds.scm.server.StorageContainerManager - .startRpcServer; - -/** - * The RPC server that listens to requests from clients. - */ -public class SCMClientProtocolServer implements - StorageContainerLocationProtocol, EventHandler { - private static final Logger LOG = - LoggerFactory.getLogger(SCMClientProtocolServer.class); - private final RPC.Server clientRpcServer; - private final InetSocketAddress clientRpcAddress; - private final StorageContainerManager scm; - private final OzoneConfiguration conf; - private ChillModePrecheck chillModePrecheck = new ChillModePrecheck(); - - public SCMClientProtocolServer(OzoneConfiguration conf, - StorageContainerManager scm) throws IOException { - this.scm = scm; - this.conf = conf; - final int handlerCount = - conf.getInt(OZONE_SCM_HANDLER_COUNT_KEY, - OZONE_SCM_HANDLER_COUNT_DEFAULT); - RPC.setProtocolEngine(conf, StorageContainerLocationProtocolPB.class, - ProtobufRpcEngine.class); - - // SCM Container Service RPC - BlockingService storageProtoPbService = - newReflectiveBlockingService( - new StorageContainerLocationProtocolServerSideTranslatorPB(this)); - - final InetSocketAddress scmAddress = HddsServerUtil - .getScmClientBindAddress(conf); - clientRpcServer = - startRpcServer( - conf, - scmAddress, - StorageContainerLocationProtocolPB.class, - storageProtoPbService, - handlerCount); - clientRpcAddress = - updateRPCListenAddress(conf, OZONE_SCM_CLIENT_ADDRESS_KEY, - scmAddress, clientRpcServer); - - } - - public RPC.Server getClientRpcServer() { - return clientRpcServer; - } - - public InetSocketAddress getClientRpcAddress() { - return clientRpcAddress; - } - - public void start() { - LOG.info( - StorageContainerManager.buildRpcServerStartMessage( - "RPC server for Client ", getClientRpcAddress())); - getClientRpcServer().start(); - } - - public void stop() { - try { - LOG.info("Stopping the RPC server for Client Protocol"); - getClientRpcServer().stop(); - } catch (Exception ex) { - LOG.error("Client Protocol RPC stop failed.", ex); - } - IOUtils.cleanupWithLogger(LOG, scm.getScmNodeManager()); - } - - public void join() throws InterruptedException { - LOG.trace("Join RPC server for Client Protocol"); - getClientRpcServer().join(); - } - - @VisibleForTesting - public String getRpcRemoteUsername() { - UserGroupInformation user = ProtobufRpcEngine.Server.getRemoteUser(); - return user == null ? null : user.getUserName(); - } - - @Override - public ContainerWithPipeline allocateContainer(HddsProtos.ReplicationType - replicationType, HddsProtos.ReplicationFactor factor, - String owner) throws IOException { - ScmUtils.preCheck(ScmOps.allocateContainer, chillModePrecheck); - String remoteUser = getRpcRemoteUsername(); - getScm().checkAdminAccess(remoteUser); - - return scm.getScmContainerManager() - .allocateContainer(replicationType, factor, owner); - } - - @Override - public ContainerInfo getContainer(long containerID) throws IOException { - String remoteUser = getRpcRemoteUsername(); - getScm().checkAdminAccess(remoteUser); - return scm.getScmContainerManager() - .getContainer(containerID); - } - - @Override - public ContainerWithPipeline getContainerWithPipeline(long containerID) - throws IOException { - if (chillModePrecheck.isInChillMode()) { - ContainerInfo contInfo = scm.getScmContainerManager() - .getContainer(containerID); - if (contInfo.isContainerOpen()) { - if (!hasRequiredReplicas(contInfo)) { - throw new SCMException("Open container " + containerID + " doesn't" - + " have enough replicas to service this operation in " - + "Chill mode.", ResultCodes.CHILL_MODE_EXCEPTION); - } - } - } - String remoteUser = getRpcRemoteUsername(); - getScm().checkAdminAccess(remoteUser); - return scm.getScmContainerManager() - .getContainerWithPipeline(containerID); - } - - /** - * Check if container reported replicas are equal or greater than required - * replication factor. - */ - private boolean hasRequiredReplicas(ContainerInfo contInfo) { - try{ - return getScm().getScmContainerManager().getStateManager() - .getContainerReplicas(contInfo.containerID()) - .size() >= contInfo.getReplicationFactor().getNumber(); - } catch (SCMException ex) { - // getContainerReplicas throws exception if no replica's exist for given - // container. - return false; - } - } - - @Override - public List listContainer(long startContainerID, - int count) throws IOException { - return scm.getScmContainerManager(). - listContainer(startContainerID, count); - } - - @Override - public void deleteContainer(long containerID) throws IOException { - String remoteUser = getRpcRemoteUsername(); - getScm().checkAdminAccess(remoteUser); - scm.getScmContainerManager().deleteContainer(containerID); - - } - - @Override - public List queryNode(HddsProtos.NodeState state, - HddsProtos.QueryScope queryScope, String poolName) throws - IOException { - - if (queryScope == HddsProtos.QueryScope.POOL) { - throw new IllegalArgumentException("Not Supported yet"); - } - - List result = new ArrayList<>(); - queryNode(state).forEach(node -> result.add(HddsProtos.Node.newBuilder() - .setNodeID(node.getProtoBufMessage()) - .addNodeStates(state) - .build())); - - return result; - - } - - @Override - public void notifyObjectStageChange(StorageContainerLocationProtocolProtos - .ObjectStageChangeRequestProto.Type type, long id, - StorageContainerLocationProtocolProtos.ObjectStageChangeRequestProto.Op - op, StorageContainerLocationProtocolProtos - .ObjectStageChangeRequestProto.Stage stage) throws IOException { - - LOG.info("Object type {} id {} op {} new stage {}", type, id, op, - stage); - if (type == StorageContainerLocationProtocolProtos - .ObjectStageChangeRequestProto.Type.container) { - if (op == StorageContainerLocationProtocolProtos - .ObjectStageChangeRequestProto.Op.create) { - if (stage == StorageContainerLocationProtocolProtos - .ObjectStageChangeRequestProto.Stage.begin) { - scm.getScmContainerManager().updateContainerState(id, HddsProtos - .LifeCycleEvent.CREATE); - } else { - scm.getScmContainerManager().updateContainerState(id, HddsProtos - .LifeCycleEvent.CREATED); - } - } else { - if (op == StorageContainerLocationProtocolProtos - .ObjectStageChangeRequestProto.Op.close) { - if (stage == StorageContainerLocationProtocolProtos - .ObjectStageChangeRequestProto.Stage.begin) { - scm.getScmContainerManager().updateContainerState(id, HddsProtos - .LifeCycleEvent.FINALIZE); - } else { - scm.getScmContainerManager().updateContainerState(id, HddsProtos - .LifeCycleEvent.CLOSE); - } - } - } - } // else if (type == ObjectStageChangeRequestProto.Type.pipeline) { - // TODO: pipeline state update will be addressed in future patch. - // } - - } - - @Override - public Pipeline createReplicationPipeline(HddsProtos.ReplicationType type, - HddsProtos.ReplicationFactor factor, HddsProtos.NodePool nodePool) - throws IOException { - // TODO: will be addressed in future patch. - // This is needed only for debugging purposes to make sure cluster is - // working correctly. - return null; - } - - @Override - public ScmInfo getScmInfo() throws IOException { - ScmInfo.Builder builder = - new ScmInfo.Builder() - .setClusterId(scm.getScmStorage().getClusterID()) - .setScmId(scm.getScmStorage().getScmId()); - return builder.build(); - } - - /** - * Check if SCM is in chill mode. - * - * @return Returns true if SCM is in chill mode else returns false. - * @throws IOException - */ - @Override - public boolean inChillMode() throws IOException { - return scm.isInChillMode(); - } - - /** - * Force SCM out of Chill mode. - * - * @return returns true if operation is successful. - * @throws IOException - */ - @Override - public boolean forceExitChillMode() throws IOException { - return scm.exitChillMode(); - } - - /** - * Queries a list of Node that match a set of statuses. - * - *

For example, if the nodeStatuses is HEALTHY and RAFT_MEMBER, then - * this call will return all - * healthy nodes which members in Raft pipeline. - * - *

Right now we don't support operations, so we assume it is an AND - * operation between the - * operators. - * - * @param state - NodeStates. - * @return List of Datanodes. - */ - public List queryNode(HddsProtos.NodeState state) { - Preconditions.checkNotNull(state, "Node Query set cannot be null"); - return new LinkedList<>(queryNodeState(state)); - } - - @VisibleForTesting - public StorageContainerManager getScm() { - return scm; - } - - /** - * Set chill mode status based on SCMEvents.CHILL_MODE_STATUS event. - */ - @Override - public void onMessage(Boolean inChillMOde, EventPublisher publisher) { - chillModePrecheck.setInChillMode(inChillMOde); - } - - /** - * Set chill mode status based on . - */ - public boolean getChillModeStatus() { - return chillModePrecheck.isInChillMode(); - } - - - /** - * Query the System for Nodes. - * - * @param nodeState - NodeState that we are interested in matching. - * @return Set of Datanodes that match the NodeState. - */ - private Set queryNodeState(HddsProtos.NodeState nodeState) { - Set returnSet = new TreeSet<>(); - List tmp = scm.getScmNodeManager().getNodes(nodeState); - if ((tmp != null) && (tmp.size() > 0)) { - returnSet.addAll(tmp); - } - return returnSet; - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMDatanodeHeartbeatDispatcher.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMDatanodeHeartbeatDispatcher.java deleted file mode 100644 index d9a0875385b..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMDatanodeHeartbeatDispatcher.java +++ /dev/null @@ -1,231 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.hdds.scm.server; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.PipelineReportsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.PipelineActionsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerActionsProto; -import org.apache.hadoop.hdds.protocol.proto. - StorageContainerDatanodeProtocolProtos.CommandStatusReportsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerReportsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.NodeReportProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMHeartbeatRequestProto; -import org.apache.hadoop.hdds.scm.node.NodeManager; -import org.apache.hadoop.hdds.server.events.EventPublisher; - -import com.google.protobuf.GeneratedMessage; -import org.apache.hadoop.ozone.protocol.commands.SCMCommand; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.List; - -import static org.apache.hadoop.hdds.scm.events.SCMEvents.CONTAINER_ACTIONS; -import static org.apache.hadoop.hdds.scm.events.SCMEvents.CONTAINER_REPORT; -import static org.apache.hadoop.hdds.scm.events.SCMEvents.NODE_REPORT; -import static org.apache.hadoop.hdds.scm.events.SCMEvents.CMD_STATUS_REPORT; -import static org.apache.hadoop.hdds.scm.events.SCMEvents.PIPELINE_ACTIONS; -import static org.apache.hadoop.hdds.scm.events.SCMEvents.PIPELINE_REPORT; - -/** - * This class is responsible for dispatching heartbeat from datanode to - * appropriate EventHandler at SCM. - */ -public final class SCMDatanodeHeartbeatDispatcher { - - private static final Logger LOG = - LoggerFactory.getLogger(SCMDatanodeHeartbeatDispatcher.class); - - private final NodeManager nodeManager; - private final EventPublisher eventPublisher; - - - public SCMDatanodeHeartbeatDispatcher(NodeManager nodeManager, - EventPublisher eventPublisher) { - Preconditions.checkNotNull(nodeManager); - Preconditions.checkNotNull(eventPublisher); - this.nodeManager = nodeManager; - this.eventPublisher = eventPublisher; - } - - - /** - * Dispatches heartbeat to registered event handlers. - * - * @param heartbeat heartbeat to be dispatched. - * - * @return list of SCMCommand - */ - public List dispatch(SCMHeartbeatRequestProto heartbeat) { - DatanodeDetails datanodeDetails = - DatanodeDetails.getFromProtoBuf(heartbeat.getDatanodeDetails()); - // should we dispatch heartbeat through eventPublisher? - List commands = nodeManager.processHeartbeat(datanodeDetails); - if (heartbeat.hasNodeReport()) { - LOG.debug("Dispatching Node Report."); - eventPublisher.fireEvent(NODE_REPORT, - new NodeReportFromDatanode(datanodeDetails, - heartbeat.getNodeReport())); - } - - if (heartbeat.hasContainerReport()) { - LOG.debug("Dispatching Container Report."); - eventPublisher.fireEvent(CONTAINER_REPORT, - new ContainerReportFromDatanode(datanodeDetails, - heartbeat.getContainerReport())); - - } - - if (heartbeat.hasContainerActions()) { - LOG.debug("Dispatching Container Actions."); - eventPublisher.fireEvent(CONTAINER_ACTIONS, - new ContainerActionsFromDatanode(datanodeDetails, - heartbeat.getContainerActions())); - } - - if (heartbeat.hasPipelineReports()) { - LOG.debug("Dispatching Pipeline Report."); - eventPublisher.fireEvent(PIPELINE_REPORT, - new PipelineReportFromDatanode(datanodeDetails, - heartbeat.getPipelineReports())); - - } - - if (heartbeat.hasPipelineActions()) { - LOG.debug("Dispatching Pipeline Actions."); - eventPublisher.fireEvent(PIPELINE_ACTIONS, - new PipelineActionsFromDatanode(datanodeDetails, - heartbeat.getPipelineActions())); - } - - if (heartbeat.getCommandStatusReportsCount() != 0) { - for (CommandStatusReportsProto commandStatusReport : heartbeat - .getCommandStatusReportsList()) { - eventPublisher.fireEvent(CMD_STATUS_REPORT, - new CommandStatusReportFromDatanode(datanodeDetails, - commandStatusReport)); - } - } - - return commands; - } - - /** - * Wrapper class for events with the datanode origin. - */ - public static class ReportFromDatanode { - - private final DatanodeDetails datanodeDetails; - - private final T report; - - public ReportFromDatanode(DatanodeDetails datanodeDetails, T report) { - this.datanodeDetails = datanodeDetails; - this.report = report; - } - - public DatanodeDetails getDatanodeDetails() { - return datanodeDetails; - } - - public T getReport() { - return report; - } - } - - /** - * Node report event payload with origin. - */ - public static class NodeReportFromDatanode - extends ReportFromDatanode { - - public NodeReportFromDatanode(DatanodeDetails datanodeDetails, - NodeReportProto report) { - super(datanodeDetails, report); - } - } - - /** - * Container report event payload with origin. - */ - public static class ContainerReportFromDatanode - extends ReportFromDatanode { - - public ContainerReportFromDatanode(DatanodeDetails datanodeDetails, - ContainerReportsProto report) { - super(datanodeDetails, report); - } - } - - /** - * Container action event payload with origin. - */ - public static class ContainerActionsFromDatanode - extends ReportFromDatanode { - - public ContainerActionsFromDatanode(DatanodeDetails datanodeDetails, - ContainerActionsProto actions) { - super(datanodeDetails, actions); - } - } - - /** - * Pipeline report event payload with origin. - */ - public static class PipelineReportFromDatanode - extends ReportFromDatanode { - - public PipelineReportFromDatanode(DatanodeDetails datanodeDetails, - PipelineReportsProto report) { - super(datanodeDetails, report); - } - } - - /** - * Pipeline action event payload with origin. - */ - public static class PipelineActionsFromDatanode - extends ReportFromDatanode { - - public PipelineActionsFromDatanode(DatanodeDetails datanodeDetails, - PipelineActionsProto actions) { - super(datanodeDetails, actions); - } - } - - /** - * Container report event payload with origin. - */ - public static class CommandStatusReportFromDatanode - extends ReportFromDatanode { - - public CommandStatusReportFromDatanode(DatanodeDetails datanodeDetails, - CommandStatusReportsProto report) { - super(datanodeDetails, report); - } - } - -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMDatanodeProtocolServer.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMDatanodeProtocolServer.java deleted file mode 100644 index 9c6fa88e0ce..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMDatanodeProtocolServer.java +++ /dev/null @@ -1,315 +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 - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software - * distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.server; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import com.google.protobuf.BlockingService; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos; - -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMHeartbeatRequestProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerReportsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.PipelineReportsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMHeartbeatResponseProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMVersionRequestProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMVersionResponseProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMRegisteredResponseProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ReregisterCommandProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMCommandProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.NodeReportProto; - -import static org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMCommandProto - .Type.closeContainerCommand; -import static org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMCommandProto - .Type.deleteBlocksCommand; -import static org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMCommandProto.Type - .replicateContainerCommand; -import static org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMCommandProto - .Type.reregisterCommand; - - - -import org.apache.hadoop.hdds.scm.HddsServerUtil; -import org.apache.hadoop.hdds.scm.events.SCMEvents; -import org.apache.hadoop.hdds.scm.server.SCMDatanodeHeartbeatDispatcher - .ReportFromDatanode; -import org.apache.hadoop.hdds.scm.server.SCMDatanodeHeartbeatDispatcher - .PipelineReportFromDatanode; -import org.apache.hadoop.hdds.server.events.EventPublisher; -import org.apache.hadoop.io.IOUtils; -import org.apache.hadoop.ipc.ProtobufRpcEngine; -import org.apache.hadoop.ipc.RPC; -import org.apache.hadoop.ozone.protocol.StorageContainerDatanodeProtocol; -import org.apache.hadoop.ozone.protocol.commands.CloseContainerCommand; -import org.apache.hadoop.ozone.protocol.commands.DeleteBlocksCommand; -import org.apache.hadoop.ozone.protocol.commands.RegisteredCommand; -import org.apache.hadoop.ozone.protocol.commands.ReplicateContainerCommand; -import org.apache.hadoop.ozone.protocol.commands.SCMCommand; -import org.apache.hadoop.ozone.protocolPB.StorageContainerDatanodeProtocolPB; -import org.apache.hadoop.ozone.protocolPB - .StorageContainerDatanodeProtocolServerSideTranslatorPB; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.util.LinkedList; -import java.util.List; -import java.util.stream.Collectors; - -import static org.apache.hadoop.hdds.scm.ScmConfigKeys.OZONE_SCM_DATANODE_ADDRESS_KEY; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys.OZONE_SCM_HANDLER_COUNT_DEFAULT; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys.OZONE_SCM_HANDLER_COUNT_KEY; - -import static org.apache.hadoop.hdds.scm.events.SCMEvents.PIPELINE_REPORT; -import static org.apache.hadoop.hdds.scm.server.StorageContainerManager.startRpcServer; -import static org.apache.hadoop.hdds.server.ServerUtils.updateRPCListenAddress; - -/** - * Protocol Handler for Datanode Protocol. - */ -public class SCMDatanodeProtocolServer implements - StorageContainerDatanodeProtocol { - - private static final Logger LOG = LoggerFactory.getLogger( - SCMDatanodeProtocolServer.class); - - /** - * The RPC server that listens to requests from DataNodes. - */ - private final RPC.Server datanodeRpcServer; - - private final StorageContainerManager scm; - private final InetSocketAddress datanodeRpcAddress; - private final SCMDatanodeHeartbeatDispatcher heartbeatDispatcher; - private final EventPublisher eventPublisher; - - public SCMDatanodeProtocolServer(final OzoneConfiguration conf, - StorageContainerManager scm, EventPublisher eventPublisher) - throws IOException { - - Preconditions.checkNotNull(scm, "SCM cannot be null"); - Preconditions.checkNotNull(eventPublisher, "EventPublisher cannot be null"); - - this.scm = scm; - this.eventPublisher = eventPublisher; - final int handlerCount = - conf.getInt(OZONE_SCM_HANDLER_COUNT_KEY, - OZONE_SCM_HANDLER_COUNT_DEFAULT); - - heartbeatDispatcher = new SCMDatanodeHeartbeatDispatcher( - scm.getScmNodeManager(), eventPublisher); - - RPC.setProtocolEngine(conf, StorageContainerDatanodeProtocolPB.class, - ProtobufRpcEngine.class); - BlockingService dnProtoPbService = - StorageContainerDatanodeProtocolProtos - .StorageContainerDatanodeProtocolService - .newReflectiveBlockingService( - new StorageContainerDatanodeProtocolServerSideTranslatorPB( - this)); - - InetSocketAddress datanodeRpcAddr = - HddsServerUtil.getScmDataNodeBindAddress(conf); - - datanodeRpcServer = - startRpcServer( - conf, - datanodeRpcAddr, - StorageContainerDatanodeProtocolPB.class, - dnProtoPbService, - handlerCount); - - datanodeRpcAddress = - updateRPCListenAddress( - conf, OZONE_SCM_DATANODE_ADDRESS_KEY, datanodeRpcAddr, - datanodeRpcServer); - - } - - public void start() { - LOG.info( - StorageContainerManager.buildRpcServerStartMessage( - "RPC server for DataNodes", datanodeRpcAddress)); - datanodeRpcServer.start(); - } - - public InetSocketAddress getDatanodeRpcAddress() { - return datanodeRpcAddress; - } - - @Override - public SCMVersionResponseProto getVersion(SCMVersionRequestProto - versionRequest) - throws IOException { - return scm.getScmNodeManager().getVersion(versionRequest) - .getProtobufMessage(); - } - - @Override - public SCMRegisteredResponseProto register( - HddsProtos.DatanodeDetailsProto datanodeDetailsProto, - NodeReportProto nodeReport, - ContainerReportsProto containerReportsProto, - PipelineReportsProto pipelineReportsProto) - throws IOException { - DatanodeDetails datanodeDetails = DatanodeDetails - .getFromProtoBuf(datanodeDetailsProto); - // TODO : Return the list of Nodes that forms the SCM HA. - RegisteredCommand registeredCommand = scm.getScmNodeManager() - .register(datanodeDetails, nodeReport, pipelineReportsProto); - if (registeredCommand.getError() - == SCMRegisteredResponseProto.ErrorCode.success) { - scm.getScmContainerManager().processContainerReports(datanodeDetails, - containerReportsProto, true); - eventPublisher.fireEvent(SCMEvents.NODE_REGISTRATION_CONT_REPORT, - new NodeRegistrationContainerReport(datanodeDetails, - containerReportsProto)); - eventPublisher.fireEvent(PIPELINE_REPORT, - new PipelineReportFromDatanode(datanodeDetails, - pipelineReportsProto)); - } - return getRegisteredResponse(registeredCommand); - } - - @VisibleForTesting - public static SCMRegisteredResponseProto getRegisteredResponse( - RegisteredCommand cmd) { - return SCMRegisteredResponseProto.newBuilder() - // TODO : Fix this later when we have multiple SCM support. - // .setAddressList(addressList) - .setErrorCode(cmd.getError()) - .setClusterID(cmd.getClusterID()) - .setDatanodeUUID(cmd.getDatanodeUUID()) - .build(); - } - - @Override - public SCMHeartbeatResponseProto sendHeartbeat( - SCMHeartbeatRequestProto heartbeat) throws IOException { - List cmdResponses = new LinkedList<>(); - for (SCMCommand cmd : heartbeatDispatcher.dispatch(heartbeat)) { - cmdResponses.add(getCommandResponse(cmd)); - } - return SCMHeartbeatResponseProto.newBuilder() - .setDatanodeUUID(heartbeat.getDatanodeDetails().getUuid()) - .addAllCommands(cmdResponses).build(); - } - - /** - * Returns a SCMCommandRepose from the SCM Command. - * - * @param cmd - Cmd - * @return SCMCommandResponseProto - * @throws IOException - */ - @VisibleForTesting - public SCMCommandProto getCommandResponse(SCMCommand cmd) - throws IOException { - SCMCommandProto.Builder builder = - SCMCommandProto.newBuilder(); - switch (cmd.getType()) { - case reregisterCommand: - return builder - .setCommandType(reregisterCommand) - .setReregisterCommandProto(ReregisterCommandProto - .getDefaultInstance()) - .build(); - case deleteBlocksCommand: - // Once SCM sends out the deletion message, increment the count. - // this is done here instead of when SCM receives the ACK, because - // DN might not be able to response the ACK for sometime. In case - // it times out, SCM needs to re-send the message some more times. - List txs = - ((DeleteBlocksCommand) cmd) - .blocksTobeDeleted() - .stream() - .map(tx -> tx.getTxID()) - .collect(Collectors.toList()); - scm.getScmBlockManager().getDeletedBlockLog().incrementCount(txs); - return builder - .setCommandType(deleteBlocksCommand) - .setDeleteBlocksCommandProto(((DeleteBlocksCommand) cmd).getProto()) - .build(); - case closeContainerCommand: - return builder - .setCommandType(closeContainerCommand) - .setCloseContainerCommandProto( - ((CloseContainerCommand) cmd).getProto()) - .build(); - case replicateContainerCommand: - return builder - .setCommandType(replicateContainerCommand) - .setReplicateContainerCommandProto( - ((ReplicateContainerCommand)cmd).getProto()) - .build(); - default: - throw new IllegalArgumentException("Not implemented"); - } - } - - - public void join() throws InterruptedException { - LOG.trace("Join RPC server for DataNodes"); - datanodeRpcServer.join(); - } - - public void stop() { - try { - LOG.info("Stopping the RPC server for DataNodes"); - datanodeRpcServer.stop(); - } catch (Exception ex) { - LOG.error(" datanodeRpcServer stop failed.", ex); - } - IOUtils.cleanupWithLogger(LOG, scm.getScmNodeManager()); - } - - /** - * Wrapper class for events with the datanode origin. - */ - public static class NodeRegistrationContainerReport extends - ReportFromDatanode { - - public NodeRegistrationContainerReport(DatanodeDetails datanodeDetails, - ContainerReportsProto report) { - super(datanodeDetails, report); - } - } - -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMMXBean.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMMXBean.java deleted file mode 100644 index 22d4d560dd5..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMMXBean.java +++ /dev/null @@ -1,50 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.server; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.hdds.server.ServiceRuntimeInfo; - -import java.util.Map; - -/** - * - * This is the JMX management interface for scm information. - */ -@InterfaceAudience.Private -public interface SCMMXBean extends ServiceRuntimeInfo { - - /** - * Get the SCM RPC server port that used to listen to datanode requests. - * @return SCM datanode RPC server port - */ - String getDatanodeRpcPort(); - - /** - * Get the SCM RPC server port that used to listen to client requests. - * @return SCM client RPC server port - */ - String getClientRpcPort(); - - /** - * Get container report info that includes container IO stats of nodes. - * @return The datanodeUUid to report json string mapping - */ - Map getContainerReport(); -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMStorage.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMStorage.java deleted file mode 100644 index be6c1af1868..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMStorage.java +++ /dev/null @@ -1,73 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.server; - -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeType; -import org.apache.hadoop.ozone.common.Storage; - -import java.io.IOException; -import java.util.Properties; -import java.util.UUID; - -import static org.apache.hadoop.hdds.server.ServerUtils.getOzoneMetaDirPath; -import static org.apache.hadoop.ozone.OzoneConsts.SCM_ID; -import static org.apache.hadoop.ozone.OzoneConsts.STORAGE_DIR; - -/** - * SCMStorage is responsible for management of the StorageDirectories used by - * the SCM. - */ -public class SCMStorage extends Storage { - - /** - * Construct SCMStorage. - * @throws IOException if any directories are inaccessible. - */ - public SCMStorage(OzoneConfiguration conf) throws IOException { - super(NodeType.SCM, getOzoneMetaDirPath(conf), STORAGE_DIR); - } - - public void setScmId(String scmId) throws IOException { - if (getState() == StorageState.INITIALIZED) { - throw new IOException("SCM is already initialized."); - } else { - getStorageInfo().setProperty(SCM_ID, scmId); - } - } - - /** - * Retrieves the SCM ID from the version file. - * @return SCM_ID - */ - public String getScmId() { - return getStorageInfo().getProperty(SCM_ID); - } - - @Override - protected Properties getNodeProperties() { - String scmId = getScmId(); - if (scmId == null) { - scmId = UUID.randomUUID().toString(); - } - Properties scmProperties = new Properties(); - scmProperties.setProperty(SCM_ID, scmId); - return scmProperties; - } - -} \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/StorageContainerManager.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/StorageContainerManager.java deleted file mode 100644 index a6a967c3764..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/StorageContainerManager.java +++ /dev/null @@ -1,942 +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 - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software - * distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.server; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.RemovalListener; -import com.google.common.cache.RemovalNotification; -import com.google.protobuf.BlockingService; -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.hdds.HddsUtils; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState; -import org.apache.hadoop.hdds.scm.ScmConfigKeys; -import org.apache.hadoop.hdds.scm.block.BlockManager; -import org.apache.hadoop.hdds.scm.block.BlockManagerImpl; -import org.apache.hadoop.hdds.scm.block.DeletedBlockLogImpl; -import org.apache.hadoop.hdds.scm.block.PendingDeleteHandler; -import org.apache.hadoop.hdds.scm.command.CommandStatusReportHandler; -import org.apache.hadoop.hdds.scm.container.CloseContainerEventHandler; -import org.apache.hadoop.hdds.scm.container.CloseContainerWatcher; -import org.apache.hadoop.hdds.scm.container.ContainerActionsHandler; -import org.apache.hadoop.hdds.scm.container.ContainerMapping; -import org.apache.hadoop.hdds.scm.container.ContainerReportHandler; -import org.apache.hadoop.hdds.scm.container.Mapping; -import org.apache.hadoop.hdds.scm.container.replication - .ReplicationActivityStatus; -import org.apache.hadoop.hdds.scm.container.replication.ReplicationManager; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo; -import org.apache.hadoop.hdds.scm.container.placement.algorithms - .ContainerPlacementPolicy; -import org.apache.hadoop.hdds.scm.container.placement.algorithms - .SCMContainerPlacementCapacity; -import org.apache.hadoop.hdds.scm.container.placement.metrics.ContainerStat; -import org.apache.hadoop.hdds.scm.container.placement.metrics.SCMMetrics; -import org.apache.hadoop.hdds.scm.events.SCMEvents; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.hdds.scm.exceptions.SCMException.ResultCodes; -import org.apache.hadoop.hdds.scm.node.DeadNodeHandler; -import org.apache.hadoop.hdds.scm.node.NewNodeHandler; -import org.apache.hadoop.hdds.scm.node.NodeManager; -import org.apache.hadoop.hdds.scm.node.NodeReportHandler; -import org.apache.hadoop.hdds.scm.node.SCMNodeManager; -import org.apache.hadoop.hdds.scm.node.StaleNodeHandler; -import org.apache.hadoop.hdds.scm.pipelines.PipelineCloseHandler; -import org.apache.hadoop.hdds.scm.pipelines.PipelineActionEventHandler; -import org.apache.hadoop.hdds.scm.pipelines.PipelineReportHandler; -import org.apache.hadoop.hdds.server.ServiceRuntimeInfoImpl; -import org.apache.hadoop.hdds.server.events.EventPublisher; -import org.apache.hadoop.hdds.server.events.EventQueue; -import org.apache.hadoop.ozone.protocol.commands.RetriableDatanodeEventWatcher; -import org.apache.hadoop.hdfs.DFSUtil; -import org.apache.hadoop.io.IOUtils; -import org.apache.hadoop.ipc.RPC; -import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem; -import org.apache.hadoop.metrics2.util.MBeans; -import org.apache.hadoop.ozone.OzoneConfigKeys; -import org.apache.hadoop.ozone.common.Storage.StorageState; -import org.apache.hadoop.ozone.common.StorageInfo; -import org.apache.hadoop.ozone.lease.LeaseManager; -import org.apache.hadoop.security.UserGroupInformation; -import org.apache.hadoop.util.GenericOptionsParser; -import org.apache.hadoop.util.StringUtils; - -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .HDDS_SCM_WATCHER_TIMEOUT_DEFAULT; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.management.ObjectName; -import java.io.IOException; -import java.io.PrintStream; -import java.net.InetSocketAddress; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.TimeUnit; - -import static org.apache.hadoop.hdds.scm.ScmConfigKeys.OZONE_SCM_DB_CACHE_SIZE_DEFAULT; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys.OZONE_SCM_DB_CACHE_SIZE_MB; - -import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ENABLED; -import static org.apache.hadoop.util.ExitUtil.terminate; - -/** - * StorageContainerManager is the main entry point for the service that - * provides information about - * which SCM nodes host containers. - * - *

DataNodes report to StorageContainerManager using heartbeat messages. - * SCM allocates containers - * and returns a pipeline. - * - *

A client once it gets a pipeline (a list of datanodes) will connect to - * the datanodes and - * create a container, which then can be used to store data. - */ -@InterfaceAudience.LimitedPrivate({"HDFS", "CBLOCK", "OZONE", "HBASE"}) -public final class StorageContainerManager extends ServiceRuntimeInfoImpl - implements SCMMXBean { - - private static final Logger LOG = LoggerFactory - .getLogger(StorageContainerManager.class); - private static final String USAGE = - "Usage: \n ozone scm [genericOptions] " - + "[ " - + StartupOption.INIT.getName() - + " [ " - + StartupOption.CLUSTERID.getName() - + " ] ]\n " - + "ozone scm [genericOptions] [ " - + StartupOption.GENCLUSTERID.getName() - + " ]\n " - + "ozone scm [ " - + StartupOption.HELP.getName() - + " ]\n"; - /** - * SCM metrics. - */ - private static SCMMetrics metrics; - - /* - * RPC Endpoints exposed by SCM. - */ - private final SCMDatanodeProtocolServer datanodeProtocolServer; - private final SCMBlockProtocolServer blockProtocolServer; - private final SCMClientProtocolServer clientProtocolServer; - - /* - * State Managers of SCM. - */ - private final NodeManager scmNodeManager; - private final Mapping scmContainerManager; - private final BlockManager scmBlockManager; - private final SCMStorage scmStorage; - - private final EventQueue eventQueue; - /* - * HTTP endpoint for JMX access. - */ - private final StorageContainerManagerHttpServer httpServer; - /** - * SCM super user. - */ - private final String scmUsername; - private final Collection scmAdminUsernames; - /** - * SCM mxbean. - */ - private ObjectName scmInfoBeanName; - /** - * Key = DatanodeUuid, value = ContainerStat. - */ - private Cache containerReportCache; - - private final ReplicationManager replicationManager; - - private final LeaseManager commandWatcherLeaseManager; - - private final ReplicationActivityStatus replicationStatus; - private final SCMChillModeManager scmChillModeManager; - - /** - * Creates a new StorageContainerManager. Configuration will be updated - * with information on the - * actual listening addresses used for RPC servers. - * - * @param conf configuration - */ - private StorageContainerManager(OzoneConfiguration conf) throws IOException { - - final int cacheSize = conf.getInt(OZONE_SCM_DB_CACHE_SIZE_MB, - OZONE_SCM_DB_CACHE_SIZE_DEFAULT); - - StorageContainerManager.initMetrics(); - initContainerReportCache(conf); - - scmStorage = new SCMStorage(conf); - if (scmStorage.getState() != StorageState.INITIALIZED) { - throw new SCMException("SCM not initialized.", ResultCodes - .SCM_NOT_INITIALIZED); - } - - eventQueue = new EventQueue(); - - scmNodeManager = new SCMNodeManager( - conf, scmStorage.getClusterID(), this, eventQueue); - scmContainerManager = new ContainerMapping( - conf, getScmNodeManager(), cacheSize, eventQueue); - scmBlockManager = new BlockManagerImpl( - conf, getScmNodeManager(), scmContainerManager, eventQueue); - - replicationStatus = new ReplicationActivityStatus(); - - CloseContainerEventHandler closeContainerHandler = - new CloseContainerEventHandler(scmContainerManager); - NodeReportHandler nodeReportHandler = - new NodeReportHandler(scmNodeManager); - PipelineReportHandler pipelineReportHandler = - new PipelineReportHandler( - scmContainerManager.getPipelineSelector()); - CommandStatusReportHandler cmdStatusReportHandler = - new CommandStatusReportHandler(); - - NewNodeHandler newNodeHandler = new NewNodeHandler(scmNodeManager); - StaleNodeHandler staleNodeHandler = - new StaleNodeHandler(scmContainerManager.getPipelineSelector()); - DeadNodeHandler deadNodeHandler = new DeadNodeHandler(scmNodeManager, - getScmContainerManager().getStateManager()); - ContainerActionsHandler actionsHandler = new ContainerActionsHandler(); - PendingDeleteHandler pendingDeleteHandler = - new PendingDeleteHandler(scmBlockManager.getSCMBlockDeletingService()); - - ContainerReportHandler containerReportHandler = - new ContainerReportHandler(scmContainerManager, scmNodeManager, - replicationStatus); - scmChillModeManager = new SCMChillModeManager(conf, - getScmContainerManager().getStateManager().getAllContainers(), - eventQueue); - PipelineActionEventHandler pipelineActionEventHandler = - new PipelineActionEventHandler(); - - PipelineCloseHandler pipelineCloseHandler = - new PipelineCloseHandler(scmContainerManager.getPipelineSelector()); - - long watcherTimeout = - conf.getTimeDuration(ScmConfigKeys.HDDS_SCM_WATCHER_TIMEOUT, - HDDS_SCM_WATCHER_TIMEOUT_DEFAULT, TimeUnit.MILLISECONDS); - - commandWatcherLeaseManager = new LeaseManager<>("CommandWatcher", - watcherTimeout); - - RetriableDatanodeEventWatcher retriableDatanodeEventWatcher = - new RetriableDatanodeEventWatcher<>( - SCMEvents.RETRIABLE_DATANODE_COMMAND, - SCMEvents.DELETE_BLOCK_STATUS, - commandWatcherLeaseManager); - retriableDatanodeEventWatcher.start(eventQueue); - - //TODO: support configurable containerPlacement policy - ContainerPlacementPolicy containerPlacementPolicy = - new SCMContainerPlacementCapacity(scmNodeManager, conf); - - replicationManager = new ReplicationManager(containerPlacementPolicy, - scmContainerManager.getStateManager(), eventQueue, - commandWatcherLeaseManager); - - // setup CloseContainer watcher - CloseContainerWatcher closeContainerWatcher = - new CloseContainerWatcher(SCMEvents.CLOSE_CONTAINER_RETRYABLE_REQ, - SCMEvents.CLOSE_CONTAINER_STATUS, commandWatcherLeaseManager, - scmContainerManager); - closeContainerWatcher.start(eventQueue); - - scmAdminUsernames = conf.getTrimmedStringCollection(OzoneConfigKeys - .OZONE_ADMINISTRATORS); - scmUsername = UserGroupInformation.getCurrentUser().getUserName(); - if (!scmAdminUsernames.contains(scmUsername)) { - scmAdminUsernames.add(scmUsername); - } - - datanodeProtocolServer = new SCMDatanodeProtocolServer(conf, this, - eventQueue); - blockProtocolServer = new SCMBlockProtocolServer(conf, this); - clientProtocolServer = new SCMClientProtocolServer(conf, this); - httpServer = new StorageContainerManagerHttpServer(conf); - - eventQueue.addHandler(SCMEvents.DATANODE_COMMAND, scmNodeManager); - eventQueue.addHandler(SCMEvents.RETRIABLE_DATANODE_COMMAND, scmNodeManager); - eventQueue.addHandler(SCMEvents.NODE_REPORT, nodeReportHandler); - eventQueue.addHandler(SCMEvents.CONTAINER_REPORT, containerReportHandler); - eventQueue.addHandler(SCMEvents.CONTAINER_ACTIONS, actionsHandler); - eventQueue.addHandler(SCMEvents.CLOSE_CONTAINER, closeContainerHandler); - eventQueue.addHandler(SCMEvents.NEW_NODE, newNodeHandler); - eventQueue.addHandler(SCMEvents.STALE_NODE, staleNodeHandler); - eventQueue.addHandler(SCMEvents.DEAD_NODE, deadNodeHandler); - eventQueue.addHandler(SCMEvents.CMD_STATUS_REPORT, cmdStatusReportHandler); - eventQueue.addHandler(SCMEvents.START_REPLICATION, - replicationStatus.getReplicationStatusListener()); - eventQueue.addHandler(SCMEvents.CHILL_MODE_STATUS, - replicationStatus.getChillModeStatusListener()); - eventQueue - .addHandler(SCMEvents.PENDING_DELETE_STATUS, pendingDeleteHandler); - eventQueue.addHandler(SCMEvents.DELETE_BLOCK_STATUS, - (DeletedBlockLogImpl) scmBlockManager.getDeletedBlockLog()); - eventQueue.addHandler(SCMEvents.PIPELINE_ACTIONS, - pipelineActionEventHandler); - eventQueue.addHandler(SCMEvents.PIPELINE_CLOSE, pipelineCloseHandler); - eventQueue.addHandler(SCMEvents.NODE_REGISTRATION_CONT_REPORT, - scmChillModeManager); - eventQueue.addHandler(SCMEvents.CHILL_MODE_STATUS, - (BlockManagerImpl) scmBlockManager); - eventQueue.addHandler(SCMEvents.CHILL_MODE_STATUS, clientProtocolServer); - eventQueue.addHandler(SCMEvents.PIPELINE_REPORT, pipelineReportHandler); - - registerMXBean(); - } - - /** - * Builds a message for logging startup information about an RPC server. - * - * @param description RPC server description - * @param addr RPC server listening address - * @return server startup message - */ - public static String buildRpcServerStartMessage(String description, - InetSocketAddress addr) { - return addr != null - ? String.format("%s is listening at %s", description, addr.toString()) - : String.format("%s not started", description); - } - - /** - * Starts an RPC server, if configured. - * - * @param conf configuration - * @param addr configured address of RPC server - * @param protocol RPC protocol provided by RPC server - * @param instance RPC protocol implementation instance - * @param handlerCount RPC server handler count - * @return RPC server - * @throws IOException if there is an I/O error while creating RPC server - */ - public static RPC.Server startRpcServer( - OzoneConfiguration conf, - InetSocketAddress addr, - Class protocol, - BlockingService instance, - int handlerCount) - throws IOException { - RPC.Server rpcServer = - new RPC.Builder(conf) - .setProtocol(protocol) - .setInstance(instance) - .setBindAddress(addr.getHostString()) - .setPort(addr.getPort()) - .setNumHandlers(handlerCount) - .setVerbose(false) - .setSecretManager(null) - .build(); - - DFSUtil.addPBProtocol(conf, protocol, instance, rpcServer); - return rpcServer; - } - - /** - * Main entry point for starting StorageContainerManager. - * - * @param argv arguments - * @throws IOException if startup fails due to I/O error - */ - public static void main(String[] argv) throws IOException { - if (DFSUtil.parseHelpArgument(argv, USAGE, System.out, true)) { - System.exit(0); - } - try { - OzoneConfiguration conf = new OzoneConfiguration(); - GenericOptionsParser hParser = new GenericOptionsParser(conf, argv); - if (!hParser.isParseSuccessful()) { - System.err.println("USAGE: " + USAGE + "\n"); - hParser.printGenericCommandUsage(System.err); - System.exit(1); - } - StorageContainerManager scm = createSCM( - hParser.getRemainingArgs(), conf, true); - if (scm != null) { - scm.start(); - scm.join(); - } - } catch (Throwable t) { - LOG.error("Failed to start the StorageContainerManager.", t); - terminate(1, t); - } - } - - private static void printUsage(PrintStream out) { - out.println(USAGE + "\n"); - } - - /** - * Create an SCM instance based on the supplied command-line arguments. - * - * This method is intended for unit tests only. It suppresses the - * startup/shutdown message and skips registering Unix signal - * handlers. - * - * @param args command line arguments. - * @param conf HDDS configuration - * @return SCM instance - * @throws IOException - */ - @VisibleForTesting - public static StorageContainerManager createSCM( - String[] args, OzoneConfiguration conf) throws IOException { - return createSCM(args, conf, false); - } - - /** - * Create an SCM instance based on the supplied command-line arguments. - * - * @param args command-line arguments. - * @param conf HDDS configuration - * @param printBanner if true, then log a verbose startup message. - * @return SCM instance - * @throws IOException - */ - private static StorageContainerManager createSCM( - String[] args, - OzoneConfiguration conf, - boolean printBanner) throws IOException { - String[] argv = (args == null) ? new String[0] : args; - if (!HddsUtils.isHddsEnabled(conf)) { - System.err.println( - "SCM cannot be started in secure mode or when " + OZONE_ENABLED + "" + - " is set to false"); - System.exit(1); - } - StartupOption startOpt = parseArguments(argv); - if (startOpt == null) { - printUsage(System.err); - terminate(1); - return null; - } - switch (startOpt) { - case INIT: - if (printBanner) { - StringUtils.startupShutdownMessage(StorageContainerManager.class, argv, - LOG); - } - terminate(scmInit(conf) ? 0 : 1); - return null; - case GENCLUSTERID: - if (printBanner) { - StringUtils.startupShutdownMessage(StorageContainerManager.class, argv, - LOG); - } - System.out.println("Generating new cluster id:"); - System.out.println(StorageInfo.newClusterID()); - terminate(0); - return null; - case HELP: - printUsage(System.err); - terminate(0); - return null; - default: - if (printBanner) { - StringUtils.startupShutdownMessage(StorageContainerManager.class, argv, - LOG); - } - return new StorageContainerManager(conf); - } - } - - /** - * Routine to set up the Version info for StorageContainerManager. - * - * @param conf OzoneConfiguration - * @return true if SCM initialization is successful, false otherwise. - * @throws IOException if init fails due to I/O error - */ - public static boolean scmInit(OzoneConfiguration conf) throws IOException { - SCMStorage scmStorage = new SCMStorage(conf); - StorageState state = scmStorage.getState(); - if (state != StorageState.INITIALIZED) { - try { - String clusterId = StartupOption.INIT.getClusterId(); - if (clusterId != null && !clusterId.isEmpty()) { - scmStorage.setClusterId(clusterId); - } - scmStorage.initialize(); - System.out.println( - "SCM initialization succeeded." - + "Current cluster id for sd=" - + scmStorage.getStorageDir() - + ";cid=" - + scmStorage.getClusterID()); - return true; - } catch (IOException ioe) { - LOG.error("Could not initialize SCM version file", ioe); - return false; - } - } else { - System.out.println( - "SCM already initialized. Reusing existing" - + " cluster id for sd=" - + scmStorage.getStorageDir() - + ";cid=" - + scmStorage.getClusterID()); - return true; - } - } - - private static StartupOption parseArguments(String[] args) { - int argsLen = (args == null) ? 0 : args.length; - StartupOption startOpt = StartupOption.HELP; - if (argsLen == 0) { - startOpt = StartupOption.REGULAR; - } - for (int i = 0; i < argsLen; i++) { - String cmd = args[i]; - if (StartupOption.INIT.getName().equalsIgnoreCase(cmd)) { - startOpt = StartupOption.INIT; - if (argsLen > 3) { - return null; - } - for (i = i + 1; i < argsLen; i++) { - if (args[i].equalsIgnoreCase(StartupOption.CLUSTERID.getName())) { - i++; - if (i < argsLen && !args[i].isEmpty()) { - startOpt.setClusterId(args[i]); - } else { - // if no cluster id specified or is empty string, return null - LOG.error( - "Must specify a valid cluster ID after the " - + StartupOption.CLUSTERID.getName() - + " flag"); - return null; - } - } else { - return null; - } - } - } else { - if (StartupOption.GENCLUSTERID.getName().equalsIgnoreCase(cmd)) { - if (argsLen > 1) { - return null; - } - startOpt = StartupOption.GENCLUSTERID; - } - } - } - return startOpt; - } - - /** - * Initialize SCM metrics. - */ - public static void initMetrics() { - metrics = SCMMetrics.create(); - } - - /** - * Return SCM metrics instance. - */ - public static SCMMetrics getMetrics() { - return metrics == null ? SCMMetrics.create() : metrics; - } - - public SCMStorage getScmStorage() { - return scmStorage; - } - - public SCMDatanodeProtocolServer getDatanodeProtocolServer() { - return datanodeProtocolServer; - } - - public SCMBlockProtocolServer getBlockProtocolServer() { - return blockProtocolServer; - } - - public SCMClientProtocolServer getClientProtocolServer() { - return clientProtocolServer; - } - - /** - * Initialize container reports cache that sent from datanodes. - * - * @param conf - */ - private void initContainerReportCache(OzoneConfiguration conf) { - containerReportCache = - CacheBuilder.newBuilder() - .expireAfterAccess(Long.MAX_VALUE, TimeUnit.MILLISECONDS) - .maximumSize(Integer.MAX_VALUE) - .removalListener( - new RemovalListener() { - @Override - public void onRemoval( - RemovalNotification - removalNotification) { - synchronized (containerReportCache) { - ContainerStat stat = removalNotification.getValue(); - // remove invalid container report - metrics.decrContainerStat(stat); - LOG.debug( - "Remove expired container stat entry for datanode: " + - "{}.", - removalNotification.getKey()); - } - } - }) - .build(); - } - - private void registerMXBean() { - Map jmxProperties = new HashMap<>(); - jmxProperties.put("component", "ServerRuntime"); - this.scmInfoBeanName = - MBeans.register( - "StorageContainerManager", "StorageContainerManagerInfo", - jmxProperties, this); - } - - private void unregisterMXBean() { - if (this.scmInfoBeanName != null) { - MBeans.unregister(this.scmInfoBeanName); - this.scmInfoBeanName = null; - } - } - - @VisibleForTesting - public ContainerInfo getContainerInfo(long containerID) throws - IOException { - return scmContainerManager.getContainer(containerID); - } - - /** - * Returns listening address of StorageLocation Protocol RPC server. - * - * @return listen address of StorageLocation RPC server - */ - @VisibleForTesting - public InetSocketAddress getClientRpcAddress() { - return getClientProtocolServer().getClientRpcAddress(); - } - - @Override - public String getClientRpcPort() { - InetSocketAddress addr = getClientRpcAddress(); - return addr == null ? "0" : Integer.toString(addr.getPort()); - } - - /** - * Returns listening address of StorageDatanode Protocol RPC server. - * - * @return Address where datanode are communicating. - */ - public InetSocketAddress getDatanodeRpcAddress() { - return getDatanodeProtocolServer().getDatanodeRpcAddress(); - } - - @Override - public String getDatanodeRpcPort() { - InetSocketAddress addr = getDatanodeRpcAddress(); - return addr == null ? "0" : Integer.toString(addr.getPort()); - } - - /** - * Start service. - */ - public void start() throws IOException { - LOG.info( - buildRpcServerStartMessage( - "StorageContainerLocationProtocol RPC server", - getClientRpcAddress())); - DefaultMetricsSystem.initialize("StorageContainerManager"); - - commandWatcherLeaseManager.start(); - getClientProtocolServer().start(); - - LOG.info(buildRpcServerStartMessage("ScmBlockLocationProtocol RPC " + - "server", getBlockProtocolServer().getBlockRpcAddress())); - getBlockProtocolServer().start(); - - LOG.info(buildRpcServerStartMessage("ScmDatanodeProtocl RPC " + - "server", getDatanodeProtocolServer().getDatanodeRpcAddress())); - getDatanodeProtocolServer().start(); - - httpServer.start(); - scmBlockManager.start(); - replicationStatus.start(); - replicationManager.start(); - setStartTime(); - } - - /** - * Stop service. - */ - public void stop() { - - try { - LOG.info("Stopping Replication Activity Status tracker."); - replicationStatus.close(); - } catch (Exception ex) { - LOG.error("Replication Activity Status tracker stop failed.", ex); - } - - - try { - LOG.info("Stopping Replication Manager Service."); - replicationManager.stop(); - } catch (Exception ex) { - LOG.error("Replication manager service stop failed.", ex); - } - - try { - LOG.info("Stopping Lease Manager of the command watchers"); - commandWatcherLeaseManager.shutdown(); - } catch (Exception ex) { - LOG.error("Lease Manager of the command watchers stop failed"); - } - - try { - LOG.info("Stopping datanode service RPC server"); - getDatanodeProtocolServer().stop(); - - } catch (Exception ex) { - LOG.error("Storage Container Manager datanode RPC stop failed.", ex); - } - - try { - LOG.info("Stopping block service RPC server"); - getBlockProtocolServer().stop(); - } catch (Exception ex) { - LOG.error("Storage Container Manager blockRpcServer stop failed.", ex); - } - - try { - LOG.info("Stopping the StorageContainerLocationProtocol RPC server"); - getClientProtocolServer().stop(); - } catch (Exception ex) { - LOG.error("Storage Container Manager clientRpcServer stop failed.", ex); - } - - try { - LOG.info("Stopping Storage Container Manager HTTP server."); - httpServer.stop(); - } catch (Exception ex) { - LOG.error("Storage Container Manager HTTP server stop failed.", ex); - } - - try { - LOG.info("Stopping Block Manager Service."); - scmBlockManager.stop(); - } catch (Exception ex) { - LOG.error("SCM block manager service stop failed.", ex); - } - - if (containerReportCache != null) { - containerReportCache.invalidateAll(); - containerReportCache.cleanUp(); - } - - if (metrics != null) { - metrics.unRegister(); - } - - unregisterMXBean(); - // Event queue must be stopped before the DB store is closed at the end. - try { - LOG.info("Stopping SCM Event Queue."); - eventQueue.close(); - } catch (Exception ex) { - LOG.error("SCM Event Queue stop failed", ex); - } - IOUtils.cleanupWithLogger(LOG, scmContainerManager); - } - - /** - * Wait until service has completed shutdown. - */ - public void join() { - try { - getBlockProtocolServer().join(); - getClientProtocolServer().join(); - getDatanodeProtocolServer().join(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - LOG.info("Interrupted during StorageContainerManager join."); - } - } - - /** - * Returns the Number of Datanodes that are communicating with SCM. - * - * @param nodestate Healthy, Dead etc. - * @return int -- count - */ - public int getNodeCount(NodeState nodestate) { - return scmNodeManager.getNodeCount(nodestate); - } - - /** - * Returns SCM container manager. - */ - @VisibleForTesting - public Mapping getScmContainerManager() { - return scmContainerManager; - } - - /** - * Returns node manager. - * - * @return - Node Manager - */ - @VisibleForTesting - public NodeManager getScmNodeManager() { - return scmNodeManager; - } - - @VisibleForTesting - public BlockManager getScmBlockManager() { - return scmBlockManager; - } - - public void checkAdminAccess(String remoteUser) throws IOException { - if (remoteUser != null) { - if (!scmAdminUsernames.contains(remoteUser)) { - throw new IOException( - "Access denied for user " + remoteUser + ". Superuser privilege " + - "is required."); - } - } - } - - /** - * Invalidate container stat entry for given datanode. - * - * @param datanodeUuid - */ - public void removeContainerReport(String datanodeUuid) { - synchronized (containerReportCache) { - containerReportCache.invalidate(datanodeUuid); - } - } - - /** - * Get container stat of specified datanode. - * - * @param datanodeUuid - * @return - */ - public ContainerStat getContainerReport(String datanodeUuid) { - ContainerStat stat = null; - synchronized (containerReportCache) { - stat = containerReportCache.getIfPresent(datanodeUuid); - } - - return stat; - } - - /** - * Returns a view of the container stat entries. Modifications made to the - * map will directly - * affect the cache. - * - * @return - */ - public ConcurrentMap getContainerReportCache() { - return containerReportCache.asMap(); - } - - @Override - public Map getContainerReport() { - Map id2StatMap = new HashMap<>(); - synchronized (containerReportCache) { - ConcurrentMap map = containerReportCache.asMap(); - for (Map.Entry entry : map.entrySet()) { - id2StatMap.put(entry.getKey(), entry.getValue().toJsonString()); - } - } - - return id2StatMap; - } - - public boolean isInChillMode() { - return scmChillModeManager.getInChillMode(); - } - - /** - * Returns EventPublisher. - */ - public EventPublisher getEventQueue(){ - return eventQueue; - } - - /** - * Force SCM out of chill mode. - */ - public boolean exitChillMode() { - scmChillModeManager.exitChillMode(eventQueue); - return true; - } - - @VisibleForTesting - public double getCurrentContainerThreshold() { - return scmChillModeManager.getCurrentContainerThreshold(); - } - - /** - * Startup options. - */ - public enum StartupOption { - INIT("-init"), - CLUSTERID("-clusterid"), - GENCLUSTERID("-genclusterid"), - REGULAR("-regular"), - HELP("-help"); - - private final String name; - private String clusterId = null; - - StartupOption(String arg) { - this.name = arg; - } - - public String getClusterId() { - return clusterId; - } - - public void setClusterId(String cid) { - if (cid != null && !cid.isEmpty()) { - clusterId = cid; - } - } - - public String getName() { - return name; - } - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/StorageContainerManagerHttpServer.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/StorageContainerManagerHttpServer.java deleted file mode 100644 index 75b203647a6..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/StorageContainerManagerHttpServer.java +++ /dev/null @@ -1,77 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.hdds.scm.server; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.scm.ScmConfigKeys; -import org.apache.hadoop.hdds.server.BaseHttpServer; -import org.apache.hadoop.ozone.OzoneConfigKeys; - -import java.io.IOException; - -/** - * HttpServer2 wrapper for the Ozone Storage Container Manager. - */ -public class StorageContainerManagerHttpServer extends BaseHttpServer { - - public StorageContainerManagerHttpServer(Configuration conf) - throws IOException { - super(conf, "scm"); - } - - @Override protected String getHttpAddressKey() { - return ScmConfigKeys.OZONE_SCM_HTTP_ADDRESS_KEY; - } - - @Override protected String getHttpBindHostKey() { - return ScmConfigKeys.OZONE_SCM_HTTP_BIND_HOST_KEY; - } - - @Override protected String getHttpsAddressKey() { - return ScmConfigKeys.OZONE_SCM_HTTPS_ADDRESS_KEY; - } - - @Override protected String getHttpsBindHostKey() { - return ScmConfigKeys.OZONE_SCM_HTTPS_BIND_HOST_KEY; - } - - @Override protected String getBindHostDefault() { - return ScmConfigKeys.OZONE_SCM_HTTP_BIND_HOST_DEFAULT; - } - - @Override protected int getHttpBindPortDefault() { - return ScmConfigKeys.OZONE_SCM_HTTP_BIND_PORT_DEFAULT; - } - - @Override protected int getHttpsBindPortDefault() { - return ScmConfigKeys.OZONE_SCM_HTTPS_BIND_PORT_DEFAULT; - } - - @Override protected String getKeytabFile() { - return ScmConfigKeys.OZONE_SCM_KEYTAB_FILE; - } - - @Override protected String getSpnegoPrincipal() { - return OzoneConfigKeys.OZONE_SCM_WEB_AUTHENTICATION_KERBEROS_PRINCIPAL; - } - - @Override protected String getEnabledKey() { - return ScmConfigKeys.OZONE_SCM_HTTP_ENABLED_KEY; - } - -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/package-info.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/package-info.java deleted file mode 100644 index fe07272bb6c..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/package-info.java +++ /dev/null @@ -1,22 +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 - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software - * distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.server; \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/ozone/protocol/commands/RetriableDatanodeEventWatcher.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/ozone/protocol/commands/RetriableDatanodeEventWatcher.java deleted file mode 100644 index 2a50bca9dc8..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/ozone/protocol/commands/RetriableDatanodeEventWatcher.java +++ /dev/null @@ -1,58 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.protocol.commands; - -import org.apache.hadoop.hdds.scm.command.CommandStatusReportHandler.CommandStatusEvent; -import org.apache.hadoop.hdds.scm.events.SCMEvents; -import org.apache.hadoop.hdds.server.events.Event; -import org.apache.hadoop.hdds.server.events.EventPublisher; -import org.apache.hadoop.hdds.server.events.EventWatcher; -import org.apache.hadoop.ozone.lease.LeaseManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * EventWatcher for start events and completion events with payload of type - * RetriablePayload and RetriableCompletionPayload respectively. - */ -public class RetriableDatanodeEventWatcher - extends EventWatcher { - - public static final Logger LOG = - LoggerFactory.getLogger(RetriableDatanodeEventWatcher.class); - - public RetriableDatanodeEventWatcher(Event startEvent, - Event completionEvent, LeaseManager leaseManager) { - super(startEvent, completionEvent, leaseManager); - } - - @Override - protected void onTimeout(EventPublisher publisher, - CommandForDatanode payload) { - LOG.info("RetriableDatanodeCommand type={} with id={} timed out. Retrying.", - payload.getCommand().getType(), payload.getId()); - //put back to the original queue - publisher.fireEvent(SCMEvents.RETRIABLE_DATANODE_COMMAND, payload); - } - - @Override - protected void onFinished(EventPublisher publisher, - CommandForDatanode payload) { - - } -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/ozone/protocol/commands/package-info.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/ozone/protocol/commands/package-info.java deleted file mode 100644 index b1d28386a4f..00000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/ozone/protocol/commands/package-info.java +++ /dev/null @@ -1,18 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.protocol.commands; diff --git a/hadoop-hdds/server-scm/src/main/resources/webapps/scm/index.html b/hadoop-hdds/server-scm/src/main/resources/webapps/scm/index.html deleted file mode 100644 index 2c943b626ff..00000000000 --- a/hadoop-hdds/server-scm/src/main/resources/webapps/scm/index.html +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - HDFS Storage Container Manager - - - - - - - - - - - -

- -
- - - -
- - - - - - - - - - - - diff --git a/hadoop-hdds/server-scm/src/main/resources/webapps/scm/main.html b/hadoop-hdds/server-scm/src/main/resources/webapps/scm/main.html deleted file mode 100644 index 2666f81b5ff..00000000000 --- a/hadoop-hdds/server-scm/src/main/resources/webapps/scm/main.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - - diff --git a/hadoop-hdds/server-scm/src/main/resources/webapps/scm/scm-overview.html b/hadoop-hdds/server-scm/src/main/resources/webapps/scm/scm-overview.html deleted file mode 100644 index fca23baa043..00000000000 --- a/hadoop-hdds/server-scm/src/main/resources/webapps/scm/scm-overview.html +++ /dev/null @@ -1,60 +0,0 @@ - -

Node counts

- - - - - - - - -
{{typestat.key}}{{typestat.value}}
- -

Status

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Client Rpc port{{$ctrl.overview.jmx.ClientRpcPort}}
Datanode Rpc port{{$ctrl.overview.jmx.DatanodeRpcPort}}
Block Manager: Open containers{{$ctrl.blockmanagermetrics.OpenContainersNo}}
Node Manager: Minimum chill mode nodes{{$ctrl.nodemanagermetrics.MinimumChillModeNodes}}
Node Manager: Out-of-node chill mode{{$ctrl.nodemanagermetrics.OutOfNodeChillMode}}
Node Manager: Chill mode status{{$ctrl.nodemanagermetrics.ChillModeStatus}}
Node Manager: Manual chill mode{{$ctrl.nodemanagermetrics.InManualChillMode}}
\ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/main/resources/webapps/scm/scm.js b/hadoop-hdds/server-scm/src/main/resources/webapps/scm/scm.js deleted file mode 100644 index bcfa8b7b7b7..00000000000 --- a/hadoop-hdds/server-scm/src/main/resources/webapps/scm/scm.js +++ /dev/null @@ -1,54 +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 - * - * 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. - */ -(function () { - "use strict"; - angular.module('scm', ['ozone', 'nvd3']); - - angular.module('scm').component('scmOverview', { - templateUrl: 'scm-overview.html', - require: { - overview: "^overview" - }, - controller: function ($http) { - var ctrl = this; - $http.get("jmx?qry=Hadoop:service=BlockManager,name=*") - .then(function (result) { - ctrl.blockmanagermetrics = result.data.beans[0]; - }); - $http.get("jmx?qry=Hadoop:service=SCMNodeManager,name=SCMNodeManagerInfo") - .then(function (result) { - ctrl.nodemanagermetrics = result.data.beans[0]; - }); - - var statusSortOrder = { - "HEALTHY": "a", - "STALE": "b", - "DEAD": "c", - "UNKNOWN": "z", - "DECOMMISSIONING": "x", - "DECOMMISSIONED": "y" - }; - ctrl.nodeOrder = function (v1, v2) { - //status with non defined sort order will be "undefined" - return ("" + statusSortOrder[v1.value]).localeCompare("" + statusSortOrder[v2.value]) - } - - } - }); - -})(); diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/HddsServerUtilTest.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/HddsServerUtilTest.java deleted file mode 100644 index 6e01e5354b6..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/HddsServerUtilTest.java +++ /dev/null @@ -1,308 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package org.apache.hadoop.hdds.scm; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.rules.Timeout; - -import java.net.InetSocketAddress; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; - -import static org.apache.hadoop.hdds.HddsUtils.getSCMAddresses; -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -/** - * Test the HDDS server side utilities. - */ -public class HddsServerUtilTest { - - @Rule - public Timeout timeout = new Timeout(300000); - - @Rule - public ExpectedException thrown= ExpectedException.none(); - - /** - * Verify DataNode endpoint lookup failure if neither the client nor - * datanode endpoint are configured. - */ - @Test - public void testMissingScmDataNodeAddress() { - final Configuration conf = new OzoneConfiguration(); - thrown.expect(IllegalArgumentException.class); - HddsServerUtil.getScmAddressForDataNodes(conf); - } - - /** - * Verify that the datanode endpoint is parsed correctly. - * This tests the logic used by the DataNodes to determine which address - * to connect to. - */ - @Test - public void testGetScmDataNodeAddress() { - final Configuration conf = new OzoneConfiguration(); - - // First try a client address with just a host name. Verify it falls - // back to the default port. - conf.set(ScmConfigKeys.OZONE_SCM_CLIENT_ADDRESS_KEY, "1.2.3.4"); - InetSocketAddress addr = HddsServerUtil.getScmAddressForDataNodes(conf); - assertThat(addr.getHostString(), is("1.2.3.4")); - assertThat(addr.getPort(), is( - ScmConfigKeys.OZONE_SCM_DATANODE_PORT_DEFAULT)); - - // Next try a client address with just a host name and port. - // Verify the port is ignored and the default DataNode port is used. - conf.set(ScmConfigKeys.OZONE_SCM_CLIENT_ADDRESS_KEY, "1.2.3.4:100"); - addr = HddsServerUtil.getScmAddressForDataNodes(conf); - assertThat(addr.getHostString(), is("1.2.3.4")); - assertThat(addr.getPort(), is( - ScmConfigKeys.OZONE_SCM_DATANODE_PORT_DEFAULT)); - - // Set both OZONE_SCM_CLIENT_ADDRESS_KEY and - // OZONE_SCM_DATANODE_ADDRESS_KEY. - // Verify that the latter overrides and the port number is still the - // default. - conf.set(ScmConfigKeys.OZONE_SCM_CLIENT_ADDRESS_KEY, "1.2.3.4:100"); - conf.set(ScmConfigKeys.OZONE_SCM_DATANODE_ADDRESS_KEY, "5.6.7.8"); - addr = - HddsServerUtil.getScmAddressForDataNodes(conf); - assertThat(addr.getHostString(), is("5.6.7.8")); - assertThat(addr.getPort(), is( - ScmConfigKeys.OZONE_SCM_DATANODE_PORT_DEFAULT)); - - // Set both OZONE_SCM_CLIENT_ADDRESS_KEY and - // OZONE_SCM_DATANODE_ADDRESS_KEY. - // Verify that the latter overrides and the port number from the latter is - // used. - conf.set(ScmConfigKeys.OZONE_SCM_CLIENT_ADDRESS_KEY, "1.2.3.4:100"); - conf.set(ScmConfigKeys.OZONE_SCM_DATANODE_ADDRESS_KEY, "5.6.7.8:200"); - addr = HddsServerUtil.getScmAddressForDataNodes(conf); - assertThat(addr.getHostString(), is("5.6.7.8")); - assertThat(addr.getPort(), is(200)); - } - - - /** - * Verify that the client endpoint bind address is computed correctly. - * This tests the logic used by the SCM to determine its own bind address. - */ - @Test - public void testScmClientBindHostDefault() { - final Configuration conf = new OzoneConfiguration(); - - // The bind host should be 0.0.0.0 unless OZONE_SCM_CLIENT_BIND_HOST_KEY - // is set differently. - conf.set(ScmConfigKeys.OZONE_SCM_CLIENT_ADDRESS_KEY, "1.2.3.4"); - InetSocketAddress addr = HddsServerUtil.getScmClientBindAddress(conf); - assertThat(addr.getHostString(), is("0.0.0.0")); - assertThat(addr.getPort(), is(ScmConfigKeys.OZONE_SCM_CLIENT_PORT_DEFAULT)); - - // The bind host should be 0.0.0.0 unless OZONE_SCM_CLIENT_BIND_HOST_KEY - // is set differently. The port number from OZONE_SCM_CLIENT_ADDRESS_KEY - // should be respected. - conf.set(ScmConfigKeys.OZONE_SCM_CLIENT_ADDRESS_KEY, "1.2.3.4:100"); - conf.set(ScmConfigKeys.OZONE_SCM_DATANODE_ADDRESS_KEY, "1.2.3.4:200"); - addr = HddsServerUtil.getScmClientBindAddress(conf); - assertThat(addr.getHostString(), is("0.0.0.0")); - assertThat(addr.getPort(), is(100)); - - // OZONE_SCM_CLIENT_BIND_HOST_KEY should be respected. - // Port number should be default if none is specified via - // OZONE_SCM_DATANODE_ADDRESS_KEY. - conf.set(ScmConfigKeys.OZONE_SCM_CLIENT_ADDRESS_KEY, "1.2.3.4"); - conf.set(ScmConfigKeys.OZONE_SCM_DATANODE_ADDRESS_KEY, "1.2.3.4"); - conf.set(ScmConfigKeys.OZONE_SCM_CLIENT_BIND_HOST_KEY, "5.6.7.8"); - addr = HddsServerUtil.getScmClientBindAddress(conf); - assertThat(addr.getHostString(), is("5.6.7.8")); - assertThat(addr.getPort(), is( - ScmConfigKeys.OZONE_SCM_CLIENT_PORT_DEFAULT)); - - // OZONE_SCM_CLIENT_BIND_HOST_KEY should be respected. - // Port number from OZONE_SCM_CLIENT_ADDRESS_KEY should be - // respected. - conf.set(ScmConfigKeys.OZONE_SCM_CLIENT_ADDRESS_KEY, "1.2.3.4:100"); - conf.set(ScmConfigKeys.OZONE_SCM_DATANODE_ADDRESS_KEY, "1.2.3.4:200"); - conf.set(ScmConfigKeys.OZONE_SCM_CLIENT_BIND_HOST_KEY, "5.6.7.8"); - addr = HddsServerUtil.getScmClientBindAddress(conf); - assertThat(addr.getHostString(), is("5.6.7.8")); - assertThat(addr.getPort(), is(100)); - } - - /** - * Verify that the DataNode endpoint bind address is computed correctly. - * This tests the logic used by the SCM to determine its own bind address. - */ - @Test - public void testScmDataNodeBindHostDefault() { - final Configuration conf = new OzoneConfiguration(); - - // The bind host should be 0.0.0.0 unless OZONE_SCM_DATANODE_BIND_HOST_KEY - // is set differently. - conf.set(ScmConfigKeys.OZONE_SCM_CLIENT_ADDRESS_KEY, "1.2.3.4"); - InetSocketAddress addr = HddsServerUtil.getScmDataNodeBindAddress(conf); - assertThat(addr.getHostString(), is("0.0.0.0")); - assertThat(addr.getPort(), is( - ScmConfigKeys.OZONE_SCM_DATANODE_PORT_DEFAULT)); - - // The bind host should be 0.0.0.0 unless OZONE_SCM_DATANODE_BIND_HOST_KEY - // is set differently. The port number from OZONE_SCM_DATANODE_ADDRESS_KEY - // should be respected. - conf.set(ScmConfigKeys.OZONE_SCM_CLIENT_ADDRESS_KEY, "1.2.3.4:100"); - conf.set(ScmConfigKeys.OZONE_SCM_DATANODE_ADDRESS_KEY, "1.2.3.4:200"); - addr = HddsServerUtil.getScmDataNodeBindAddress(conf); - assertThat(addr.getHostString(), is("0.0.0.0")); - assertThat(addr.getPort(), is(200)); - - // OZONE_SCM_DATANODE_BIND_HOST_KEY should be respected. - // Port number should be default if none is specified via - // OZONE_SCM_DATANODE_ADDRESS_KEY. - conf.set(ScmConfigKeys.OZONE_SCM_CLIENT_ADDRESS_KEY, "1.2.3.4:100"); - conf.set(ScmConfigKeys.OZONE_SCM_DATANODE_ADDRESS_KEY, "1.2.3.4"); - conf.set(ScmConfigKeys.OZONE_SCM_DATANODE_BIND_HOST_KEY, "5.6.7.8"); - addr = HddsServerUtil.getScmDataNodeBindAddress(conf); - assertThat(addr.getHostString(), is("5.6.7.8")); - assertThat(addr.getPort(), is( - ScmConfigKeys.OZONE_SCM_DATANODE_PORT_DEFAULT)); - - // OZONE_SCM_DATANODE_BIND_HOST_KEY should be respected. - // Port number from OZONE_SCM_DATANODE_ADDRESS_KEY should be - // respected. - conf.set(ScmConfigKeys.OZONE_SCM_CLIENT_ADDRESS_KEY, "1.2.3.4:100"); - conf.set(ScmConfigKeys.OZONE_SCM_DATANODE_ADDRESS_KEY, "1.2.3.4:200"); - conf.set(ScmConfigKeys.OZONE_SCM_DATANODE_BIND_HOST_KEY, "5.6.7.8"); - addr = HddsServerUtil.getScmDataNodeBindAddress(conf); - assertThat(addr.getHostString(), is("5.6.7.8")); - assertThat(addr.getPort(), is(200)); - } - - - - @Test - public void testGetSCMAddresses() { - final Configuration conf = new OzoneConfiguration(); - Collection addresses = null; - InetSocketAddress addr = null; - Iterator it = null; - - // Verify valid IP address setup - conf.setStrings(ScmConfigKeys.OZONE_SCM_NAMES, "1.2.3.4"); - addresses = getSCMAddresses(conf); - assertThat(addresses.size(), is(1)); - addr = addresses.iterator().next(); - assertThat(addr.getHostName(), is("1.2.3.4")); - assertThat(addr.getPort(), is(ScmConfigKeys.OZONE_SCM_DEFAULT_PORT)); - - // Verify valid hostname setup - conf.setStrings(ScmConfigKeys.OZONE_SCM_NAMES, "scm1"); - addresses = getSCMAddresses(conf); - assertThat(addresses.size(), is(1)); - addr = addresses.iterator().next(); - assertThat(addr.getHostName(), is("scm1")); - assertThat(addr.getPort(), is(ScmConfigKeys.OZONE_SCM_DEFAULT_PORT)); - - // Verify valid hostname and port - conf.setStrings(ScmConfigKeys.OZONE_SCM_NAMES, "scm1:1234"); - addresses = getSCMAddresses(conf); - assertThat(addresses.size(), is(1)); - addr = addresses.iterator().next(); - assertThat(addr.getHostName(), is("scm1")); - assertThat(addr.getPort(), is(1234)); - - final HashMap hostsAndPorts = - new HashMap(); - hostsAndPorts.put("scm1", 1234); - hostsAndPorts.put("scm2", 2345); - hostsAndPorts.put("scm3", 3456); - - // Verify multiple hosts and port - conf.setStrings( - ScmConfigKeys.OZONE_SCM_NAMES, "scm1:1234,scm2:2345,scm3:3456"); - addresses = getSCMAddresses(conf); - assertThat(addresses.size(), is(3)); - it = addresses.iterator(); - HashMap expected1 = new HashMap<>(hostsAndPorts); - while(it.hasNext()) { - InetSocketAddress current = it.next(); - assertTrue(expected1.remove(current.getHostName(), - current.getPort())); - } - assertTrue(expected1.isEmpty()); - - // Verify names with spaces - conf.setStrings( - ScmConfigKeys.OZONE_SCM_NAMES, " scm1:1234, scm2:2345 , scm3:3456 "); - addresses = getSCMAddresses(conf); - assertThat(addresses.size(), is(3)); - it = addresses.iterator(); - HashMap expected2 = new HashMap<>(hostsAndPorts); - while(it.hasNext()) { - InetSocketAddress current = it.next(); - assertTrue(expected2.remove(current.getHostName(), - current.getPort())); - } - assertTrue(expected2.isEmpty()); - - // Verify empty value - conf.setStrings(ScmConfigKeys.OZONE_SCM_NAMES, ""); - try { - addresses = getSCMAddresses(conf); - fail("Empty value should cause an IllegalArgumentException"); - } catch (Exception e) { - assertTrue(e instanceof IllegalArgumentException); - } - - // Verify invalid hostname - conf.setStrings(ScmConfigKeys.OZONE_SCM_NAMES, "s..x..:1234"); - try { - addresses = getSCMAddresses(conf); - fail("An invalid hostname should cause an IllegalArgumentException"); - } catch (Exception e) { - assertTrue(e instanceof IllegalArgumentException); - } - - // Verify invalid port - conf.setStrings(ScmConfigKeys.OZONE_SCM_NAMES, "scm:xyz"); - try { - addresses = getSCMAddresses(conf); - fail("An invalid port should cause an IllegalArgumentException"); - } catch (Exception e) { - assertTrue(e instanceof IllegalArgumentException); - } - - // Verify a mixed case (valid and invalid value both appears) - conf.setStrings(ScmConfigKeys.OZONE_SCM_NAMES, "scm1:1234, scm:xyz"); - try { - addresses = getSCMAddresses(conf); - fail("An invalid value should cause an IllegalArgumentException"); - } catch (Exception e) { - assertTrue(e instanceof IllegalArgumentException); - } - } - -} \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/HddsTestUtils.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/HddsTestUtils.java deleted file mode 100644 index 50d1eedbbe7..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/HddsTestUtils.java +++ /dev/null @@ -1,85 +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 - * - *      http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm; - -import java.util.ArrayList; -import java.util.List; -import org.apache.commons.lang3.RandomUtils; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo; -import org.apache.hadoop.hdds.scm.server.SCMDatanodeProtocolServer - .NodeRegistrationContainerReport; - -/** - * Stateless helper functions for Hdds tests. - */ -public final class HddsTestUtils { - - private HddsTestUtils() { - } - - /** - * Create Command Status report object. - * - * @param numOfContainers number of containers to be included in report. - * @return CommandStatusReportsProto - */ - public static NodeRegistrationContainerReport - createNodeRegistrationContainerReport(int numOfContainers) { - return new NodeRegistrationContainerReport( - TestUtils.randomDatanodeDetails(), - TestUtils.getRandomContainerReports(numOfContainers)); - } - - /** - * Create NodeRegistrationContainerReport object. - * - * @param dnContainers List of containers to be included in report - * @return NodeRegistrationContainerReport - */ - public static NodeRegistrationContainerReport - createNodeRegistrationContainerReport(List dnContainers) { - List - containers = new ArrayList<>(); - dnContainers.forEach(c -> { - containers.add(TestUtils.getRandomContainerInfo(c.getContainerID())); - }); - return new NodeRegistrationContainerReport( - TestUtils.randomDatanodeDetails(), - TestUtils.getContainerReports(containers)); - } - - /** - * Creates list of ContainerInfo. - * - * @param numContainers number of ContainerInfo to be included in list. - * @return List - */ - public static List getContainerInfo(int numContainers) { - List containerInfoList = new ArrayList<>(); - for (int i = 0; i < numContainers; i++) { - ContainerInfo.Builder builder = new ContainerInfo.Builder(); - containerInfoList.add(builder - .setContainerID(RandomUtils.nextLong()) - .build()); - } - return containerInfoList; - } - -} diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/TestStorageContainerManagerHttpServer.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/TestStorageContainerManagerHttpServer.java deleted file mode 100644 index d9e14255172..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/TestStorageContainerManagerHttpServer.java +++ /dev/null @@ -1,142 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.FileUtil; -import org.apache.hadoop.hdds.scm.server.StorageContainerManagerHttpServer; -import org.apache.hadoop.hdfs.DFSConfigKeys; -import org.apache.hadoop.hdfs.web.URLConnectionFactory; -import org.apache.hadoop.http.HttpConfig; -import org.apache.hadoop.http.HttpConfig.Policy; -import org.apache.hadoop.net.NetUtils; -import org.apache.hadoop.security.ssl.KeyStoreTestUtil; -import org.apache.hadoop.test.GenericTestUtils; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; - -import java.io.File; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.URL; -import java.net.URLConnection; -import java.util.Arrays; -import java.util.Collection; - -/** - * Test http server os SCM with various HTTP option. - */ -@RunWith(value = Parameterized.class) -public class TestStorageContainerManagerHttpServer { - private static final String BASEDIR = GenericTestUtils - .getTempPath(TestStorageContainerManagerHttpServer.class.getSimpleName()); - private static String keystoresDir; - private static String sslConfDir; - private static Configuration conf; - private static URLConnectionFactory connectionFactory; - - @Parameters public static Collection policy() { - Object[][] params = new Object[][] { - {HttpConfig.Policy.HTTP_ONLY}, - {HttpConfig.Policy.HTTPS_ONLY}, - {HttpConfig.Policy.HTTP_AND_HTTPS} }; - return Arrays.asList(params); - } - - private final HttpConfig.Policy policy; - - public TestStorageContainerManagerHttpServer(Policy policy) { - super(); - this.policy = policy; - } - - @BeforeClass public static void setUp() throws Exception { - File base = new File(BASEDIR); - FileUtil.fullyDelete(base); - base.mkdirs(); - conf = new Configuration(); - keystoresDir = new File(BASEDIR).getAbsolutePath(); - sslConfDir = KeyStoreTestUtil.getClasspathDir( - TestStorageContainerManagerHttpServer.class); - KeyStoreTestUtil.setupSSLConfig(keystoresDir, sslConfDir, conf, false); - connectionFactory = - URLConnectionFactory.newDefaultURLConnectionFactory(conf); - conf.set(DFSConfigKeys.DFS_CLIENT_HTTPS_KEYSTORE_RESOURCE_KEY, - KeyStoreTestUtil.getClientSSLConfigFileName()); - conf.set(DFSConfigKeys.DFS_SERVER_HTTPS_KEYSTORE_RESOURCE_KEY, - KeyStoreTestUtil.getServerSSLConfigFileName()); - } - - @AfterClass public static void tearDown() throws Exception { - FileUtil.fullyDelete(new File(BASEDIR)); - KeyStoreTestUtil.cleanupSSLConfig(keystoresDir, sslConfDir); - } - - @Test public void testHttpPolicy() throws Exception { - conf.set(DFSConfigKeys.DFS_HTTP_POLICY_KEY, policy.name()); - conf.set(ScmConfigKeys.OZONE_SCM_HTTPS_ADDRESS_KEY, "localhost:0"); - - InetSocketAddress.createUnresolved("localhost", 0); - StorageContainerManagerHttpServer server = null; - try { - server = new StorageContainerManagerHttpServer(conf); - server.start(); - - Assert.assertTrue(implies(policy.isHttpEnabled(), - canAccess("http", server.getHttpAddress()))); - Assert.assertTrue( - implies(!policy.isHttpEnabled(), server.getHttpAddress() == null)); - - Assert.assertTrue(implies(policy.isHttpsEnabled(), - canAccess("https", server.getHttpsAddress()))); - Assert.assertTrue( - implies(!policy.isHttpsEnabled(), server.getHttpsAddress() == null)); - - } finally { - if (server != null) { - server.stop(); - } - } - } - - private static boolean canAccess(String scheme, InetSocketAddress addr) { - if (addr == null) { - return false; - } - try { - URL url = - new URL(scheme + "://" + NetUtils.getHostPortString(addr) + "/jmx"); - URLConnection conn = connectionFactory.openConnection(url); - conn.connect(); - conn.getContent(); - } catch (IOException e) { - return false; - } - return true; - } - - private static boolean implies(boolean a, boolean b) { - return !a || b; - } -} diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/TestUtils.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/TestUtils.java deleted file mode 100644 index 24a16c77bb1..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/TestUtils.java +++ /dev/null @@ -1,433 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.scm; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.PipelineReportsProto; -import org.mockito.Mockito; -import static org.mockito.Mockito.when; - -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.LifeCycleState; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerInfo; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerReportsProto; -import org.apache.hadoop.hdds.protocol - .proto.StorageContainerDatanodeProtocolProtos.NodeReportProto; -import org.apache.hadoop.hdds.protocol - .proto.StorageContainerDatanodeProtocolProtos.CommandStatus; -import org.apache.hadoop.hdds.protocol - .proto.StorageContainerDatanodeProtocolProtos.CommandStatusReportsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.StorageReportProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.StorageTypeProto; -import org.apache.hadoop.hdds.scm.container.ContainerStateManager; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.scm.container.common.helpers.PipelineID; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.hdds.scm.node.SCMNodeManager; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.scm.pipelines.PipelineSelector; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.protocol.commands.RegisteredCommand; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.ThreadLocalRandom; - -/** - * Stateless helper functions to handler scm/datanode connection. - */ -public final class TestUtils { - - private static ThreadLocalRandom random = ThreadLocalRandom.current(); - - private TestUtils() { - } - - /** - * Creates DatanodeDetails with random UUID. - * - * @return DatanodeDetails - */ - public static DatanodeDetails randomDatanodeDetails() { - return createDatanodeDetails(UUID.randomUUID()); - } - - /** - * Creates DatanodeDetails using the given UUID. - * - * @param uuid Datanode's UUID - * - * @return DatanodeDetails - */ - private static DatanodeDetails createDatanodeDetails(UUID uuid) { - String ipAddress = random.nextInt(256) - + "." + random.nextInt(256) - + "." + random.nextInt(256) - + "." + random.nextInt(256); - return createDatanodeDetails(uuid.toString(), "localhost", ipAddress); - } - - /** - * Generates DatanodeDetails from RegisteredCommand. - * - * @param registeredCommand registration response from SCM - * - * @return DatanodeDetails - */ - public static DatanodeDetails getDatanodeDetails( - RegisteredCommand registeredCommand) { - return createDatanodeDetails(registeredCommand.getDatanodeUUID(), - registeredCommand.getHostName(), registeredCommand.getIpAddress()); - } - - /** - * Creates DatanodeDetails with the given information. - * - * @param uuid Datanode's UUID - * @param hostname hostname of Datanode - * @param ipAddress ip address of Datanode - * - * @return DatanodeDetails - */ - private static DatanodeDetails createDatanodeDetails(String uuid, - String hostname, String ipAddress) { - DatanodeDetails.Port containerPort = DatanodeDetails.newPort( - DatanodeDetails.Port.Name.STANDALONE, 0); - DatanodeDetails.Port ratisPort = DatanodeDetails.newPort( - DatanodeDetails.Port.Name.RATIS, 0); - DatanodeDetails.Port restPort = DatanodeDetails.newPort( - DatanodeDetails.Port.Name.REST, 0); - DatanodeDetails.Builder builder = DatanodeDetails.newBuilder(); - builder.setUuid(uuid) - .setHostName(hostname) - .setIpAddress(ipAddress) - .addPort(containerPort) - .addPort(ratisPort) - .addPort(restPort); - return builder.build(); - } - - /** - * Creates a random DatanodeDetails and register it with the given - * NodeManager. - * - * @param nodeManager NodeManager - * - * @return DatanodeDetails - */ - public static DatanodeDetails createRandomDatanodeAndRegister( - SCMNodeManager nodeManager) { - return getDatanodeDetails( - nodeManager.register(randomDatanodeDetails(), null, - getRandomPipelineReports())); - } - - /** - * Get specified number of DatanodeDetails and register them with node - * manager. - * - * @param nodeManager node manager to register the datanode ids. - * @param count number of DatanodeDetails needed. - * - * @return list of DatanodeDetails - */ - public static List getListOfRegisteredDatanodeDetails( - SCMNodeManager nodeManager, int count) { - ArrayList datanodes = new ArrayList<>(); - for (int i = 0; i < count; i++) { - datanodes.add(createRandomDatanodeAndRegister(nodeManager)); - } - return datanodes; - } - - /** - * Generates a random NodeReport. - * - * @return NodeReportProto - */ - public static NodeReportProto getRandomNodeReport() { - return getRandomNodeReport(1); - } - - /** - * Generates random NodeReport with the given number of storage report in it. - * - * @param numberOfStorageReport number of storage report this node report - * should have - * @return NodeReportProto - */ - public static NodeReportProto getRandomNodeReport(int numberOfStorageReport) { - UUID nodeId = UUID.randomUUID(); - return getRandomNodeReport(nodeId, File.separator + nodeId, - numberOfStorageReport); - } - - /** - * Generates random NodeReport for the given nodeId with the given - * base path and number of storage report in it. - * - * @param nodeId datanode id - * @param basePath base path of storage directory - * @param numberOfStorageReport number of storage report - * - * @return NodeReportProto - */ - public static NodeReportProto getRandomNodeReport(UUID nodeId, - String basePath, int numberOfStorageReport) { - List storageReports = new ArrayList<>(); - for (int i = 0; i < numberOfStorageReport; i++) { - storageReports.add(getRandomStorageReport(nodeId, - basePath + File.separator + i)); - } - return createNodeReport(storageReports); - } - - /** - * Creates NodeReport with the given storage reports. - * - * @param reports one or more storage report - * - * @return NodeReportProto - */ - public static NodeReportProto createNodeReport( - StorageReportProto... reports) { - return createNodeReport(Arrays.asList(reports)); - } - - /** - * Creates NodeReport with the given storage reports. - * - * @param reports storage reports to be included in the node report. - * - * @return NodeReportProto - */ - public static NodeReportProto createNodeReport( - List reports) { - NodeReportProto.Builder nodeReport = NodeReportProto.newBuilder(); - nodeReport.addAllStorageReport(reports); - return nodeReport.build(); - } - - /** - * Generates random storage report. - * - * @param nodeId datanode id for which the storage report belongs to - * @param path path of the storage - * - * @return StorageReportProto - */ - public static StorageReportProto getRandomStorageReport(UUID nodeId, - String path) { - return createStorageReport(nodeId, path, - random.nextInt(1000), - random.nextInt(500), - random.nextInt(500), - StorageTypeProto.DISK); - } - - /** - * Creates storage report with the given information. - * - * @param nodeId datanode id - * @param path storage dir - * @param capacity storage size - * @param used space used - * @param remaining space remaining - * @param type type of storage - * - * @return StorageReportProto - */ - public static StorageReportProto createStorageReport(UUID nodeId, String path, - long capacity, long used, long remaining, StorageTypeProto type) { - Preconditions.checkNotNull(nodeId); - Preconditions.checkNotNull(path); - StorageReportProto.Builder srb = StorageReportProto.newBuilder(); - srb.setStorageUuid(nodeId.toString()) - .setStorageLocation(path) - .setCapacity(capacity) - .setScmUsed(used) - .setRemaining(remaining); - StorageTypeProto storageTypeProto = - type == null ? StorageTypeProto.DISK : type; - srb.setStorageType(storageTypeProto); - return srb.build(); - } - - - /** - * Generates random container reports. - * - * @return ContainerReportsProto - */ - public static ContainerReportsProto getRandomContainerReports() { - return getRandomContainerReports(1); - } - - /** - * Generates random container report with the given number of containers. - * - * @param numberOfContainers number of containers to be in container report - * - * @return ContainerReportsProto - */ - public static ContainerReportsProto getRandomContainerReports( - int numberOfContainers) { - List containerInfos = new ArrayList<>(); - for (int i = 0; i < numberOfContainers; i++) { - containerInfos.add(getRandomContainerInfo(i)); - } - return getContainerReports(containerInfos); - } - - - public static PipelineReportsProto getRandomPipelineReports() { - return PipelineReportsProto.newBuilder().build(); - } - - /** - * Creates container report with the given ContainerInfo(s). - * - * @param containerInfos one or more ContainerInfo - * - * @return ContainerReportsProto - */ - public static ContainerReportsProto getContainerReports( - ContainerInfo... containerInfos) { - return getContainerReports(Arrays.asList(containerInfos)); - } - - /** - * Creates container report with the given ContainerInfo(s). - * - * @param containerInfos list of ContainerInfo - * - * @return ContainerReportsProto - */ - public static ContainerReportsProto getContainerReports( - List containerInfos) { - ContainerReportsProto.Builder - reportsBuilder = ContainerReportsProto.newBuilder(); - for (ContainerInfo containerInfo : containerInfos) { - reportsBuilder.addReports(containerInfo); - } - return reportsBuilder.build(); - } - - /** - * Generates random ContainerInfo. - * - * @param containerId container id of the ContainerInfo - * - * @return ContainerInfo - */ - public static ContainerInfo getRandomContainerInfo(long containerId) { - return createContainerInfo(containerId, - OzoneConsts.GB * 5, - random.nextLong(1000), - OzoneConsts.GB * random.nextInt(5), - random.nextLong(1000), - OzoneConsts.GB * random.nextInt(2), - random.nextLong(1000), - OzoneConsts.GB * random.nextInt(5)); - } - - /** - * Creates ContainerInfo with the given details. - * - * @param containerId id of the container - * @param size size of container - * @param keyCount number of keys - * @param bytesUsed bytes used by the container - * @param readCount number of reads - * @param readBytes bytes read - * @param writeCount number of writes - * @param writeBytes bytes written - * - * @return ContainerInfo - */ - public static ContainerInfo createContainerInfo( - long containerId, long size, long keyCount, long bytesUsed, - long readCount, long readBytes, long writeCount, long writeBytes) { - return ContainerInfo.newBuilder() - .setContainerID(containerId) - .setSize(size) - .setKeyCount(keyCount) - .setUsed(bytesUsed) - .setReadCount(readCount) - .setReadBytes(readBytes) - .setWriteCount(writeCount) - .setWriteBytes(writeBytes) - .build(); - } - - /** - * Create Command Status report object. - * @return CommandStatusReportsProto - */ - public static CommandStatusReportsProto createCommandStatusReport( - List reports) { - CommandStatusReportsProto.Builder report = CommandStatusReportsProto - .newBuilder(); - report.addAllCmdStatus(reports); - return report.build(); - } - - public static - org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo - allocateContainer(ContainerStateManager containerStateManager) - throws IOException { - - PipelineSelector pipelineSelector = Mockito.mock(PipelineSelector.class); - - Pipeline pipeline = new Pipeline("leader", HddsProtos.LifeCycleState.CLOSED, - HddsProtos.ReplicationType.STAND_ALONE, - HddsProtos.ReplicationFactor.THREE, - PipelineID.randomId()); - - when(pipelineSelector - .getReplicationPipeline(HddsProtos.ReplicationType.STAND_ALONE, - HddsProtos.ReplicationFactor.THREE)).thenReturn(pipeline); - - return containerStateManager - .allocateContainer(pipelineSelector, - HddsProtos.ReplicationType.STAND_ALONE, - HddsProtos.ReplicationFactor.THREE, "root").getContainerInfo(); - - } - - public static void closeContainer(ContainerStateManager containerStateManager, - org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo - container) - throws SCMException { - - containerStateManager.getContainerStateMap() - .updateState(container, container.getState(), LifeCycleState.CLOSING); - - containerStateManager.getContainerStateMap() - .updateState(container, container.getState(), LifeCycleState.CLOSED); - - } -} diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/block/TestBlockManager.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/block/TestBlockManager.java deleted file mode 100644 index e70e44405d2..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/block/TestBlockManager.java +++ /dev/null @@ -1,175 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.hdds.scm.block; - -import java.util.UUID; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.FileUtil; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.scm.ScmConfigKeys; -import org.apache.hadoop.hdds.scm.container.ContainerMapping; -import org.apache.hadoop.hdds.scm.container.MockNodeManager; -import org.apache.hadoop.hdds.scm.container.common.helpers.AllocatedBlock; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.scm.events.SCMEvents; -import org.apache.hadoop.hdds.scm.server.SCMStorage; -import org.apache.hadoop.hdds.scm.server.StorageContainerManager; -import org.apache.hadoop.hdds.server.events.EventHandler; -import org.apache.hadoop.hdds.server.events.EventPublisher; -import org.apache.hadoop.hdds.server.events.EventQueue; -import org.apache.hadoop.ozone.OzoneConfigKeys; -import org.apache.hadoop.ozone.common.Storage.StorageState; -import org.apache.hadoop.ozone.container.common.SCMTestUtils; -import org.apache.hadoop.test.GenericTestUtils; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Paths; - -import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ENABLED; -import static org.apache.hadoop.ozone.OzoneConsts.GB; -import static org.apache.hadoop.ozone.OzoneConsts.MB; - - -/** - * Tests for SCM Block Manager. - */ -public class TestBlockManager implements EventHandler { - private static ContainerMapping mapping; - private static MockNodeManager nodeManager; - private static BlockManagerImpl blockManager; - private static File testDir; - private final static long DEFAULT_BLOCK_SIZE = 128 * MB; - private static HddsProtos.ReplicationFactor factor; - private static HddsProtos.ReplicationType type; - private static String containerOwner = "OZONE"; - private static EventQueue eventQueue; - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - @Before - public void setUp() throws Exception { - Configuration conf = SCMTestUtils.getConf(); - - String path = GenericTestUtils - .getTempPath(TestBlockManager.class.getSimpleName()); - testDir = Paths.get(path).toFile(); - conf.set(OzoneConfigKeys.OZONE_METADATA_DIRS, path); - eventQueue = new EventQueue(); - boolean folderExisted = testDir.exists() || testDir.mkdirs(); - if (!folderExisted) { - throw new IOException("Unable to create test directory path"); - } - nodeManager = new MockNodeManager(true, 10); - mapping = new ContainerMapping(conf, nodeManager, 128, eventQueue); - blockManager = new BlockManagerImpl(conf, - nodeManager, mapping, eventQueue); - eventQueue.addHandler(SCMEvents.CHILL_MODE_STATUS, blockManager); - eventQueue.addHandler(SCMEvents.START_REPLICATION, this); - if(conf.getBoolean(ScmConfigKeys.DFS_CONTAINER_RATIS_ENABLED_KEY, - ScmConfigKeys.DFS_CONTAINER_RATIS_ENABLED_DEFAULT)){ - factor = HddsProtos.ReplicationFactor.THREE; - type = HddsProtos.ReplicationType.RATIS; - } else { - factor = HddsProtos.ReplicationFactor.ONE; - type = HddsProtos.ReplicationType.STAND_ALONE; - } - } - - @After - public void cleanup() throws IOException { - blockManager.close(); - mapping.close(); - FileUtil.fullyDelete(testDir); - } - - private static StorageContainerManager getScm(OzoneConfiguration conf) - throws IOException { - conf.setBoolean(OZONE_ENABLED, true); - SCMStorage scmStore = new SCMStorage(conf); - if(scmStore.getState() != StorageState.INITIALIZED) { - String clusterId = UUID.randomUUID().toString(); - String scmId = UUID.randomUUID().toString(); - scmStore.setClusterId(clusterId); - scmStore.setScmId(scmId); - // writes the version file properties - scmStore.initialize(); - } - return StorageContainerManager.createSCM(null, conf); - } - - @Test - public void testAllocateBlock() throws Exception { - eventQueue.fireEvent(SCMEvents.CHILL_MODE_STATUS, false); - GenericTestUtils.waitFor(() -> { - return !blockManager.isScmInChillMode(); - }, 10, 1000 * 5); - AllocatedBlock block = blockManager.allocateBlock(DEFAULT_BLOCK_SIZE, - type, factor, containerOwner); - Assert.assertNotNull(block); - } - - @Test - public void testAllocateOversizedBlock() throws Exception { - eventQueue.fireEvent(SCMEvents.CHILL_MODE_STATUS, false); - GenericTestUtils.waitFor(() -> { - return !blockManager.isScmInChillMode(); - }, 10, 1000 * 5); - long size = 6 * GB; - thrown.expectMessage("Unsupported block size"); - AllocatedBlock block = blockManager.allocateBlock(size, - type, factor, containerOwner); - } - - - @Test - public void testAllocateBlockFailureInChillMode() throws Exception { - eventQueue.fireEvent(SCMEvents.CHILL_MODE_STATUS, true); - GenericTestUtils.waitFor(() -> { - return blockManager.isScmInChillMode(); - }, 10, 1000 * 5); - // Test1: In chill mode expect an SCMException. - thrown.expectMessage("ChillModePrecheck failed for " - + "allocateBlock"); - blockManager.allocateBlock(DEFAULT_BLOCK_SIZE, - type, factor, containerOwner); - } - - @Test - public void testAllocateBlockSucInChillMode() throws Exception { - // Test2: Exit chill mode and then try allocateBock again. - eventQueue.fireEvent(SCMEvents.CHILL_MODE_STATUS, false); - GenericTestUtils.waitFor(() -> { - return !blockManager.isScmInChillMode(); - }, 10, 1000 * 5); - Assert.assertNotNull(blockManager.allocateBlock(DEFAULT_BLOCK_SIZE, - type, factor, containerOwner)); - } - - @Override - public void onMessage(Boolean aBoolean, EventPublisher publisher) { - System.out.println("test"); - } -} diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/block/TestDeletedBlockLog.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/block/TestDeletedBlockLog.java deleted file mode 100644 index 9f0e336df1f..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/block/TestDeletedBlockLog.java +++ /dev/null @@ -1,403 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.block; - -import org.apache.commons.io.FileUtils; -import org.apache.commons.lang3.RandomUtils; -import org.apache.hadoop.hdds.scm.container.ContainerMapping; -import org.apache.hadoop.hdds.scm.container.Mapping; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerWithPipeline; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.scm.container.common.helpers.PipelineID; -import org.apache.hadoop.hdfs.DFSUtil; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.LifeCycleState; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationFactor; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationType; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.DeletedBlocksTransaction; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerBlocksDeletionACKProto - .DeleteBlockTransactionResult; -import org.apache.hadoop.test.GenericTestUtils; -import org.apache.hadoop.utils.MetadataKeyFilters; -import org.apache.hadoop.utils.MetadataStore; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.UUID; -import java.util.stream.Collectors; - -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_BLOCK_DELETION_MAX_RETRY; -import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_METADATA_DIRS; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Mockito.when; - -/** - * Tests for DeletedBlockLog. - */ -public class TestDeletedBlockLog { - - private static DeletedBlockLogImpl deletedBlockLog; - private OzoneConfiguration conf; - private File testDir; - private Mapping containerManager; - private List dnList; - - @Before - public void setup() throws Exception { - testDir = GenericTestUtils.getTestDir( - TestDeletedBlockLog.class.getSimpleName()); - conf = new OzoneConfiguration(); - conf.setInt(OZONE_SCM_BLOCK_DELETION_MAX_RETRY, 20); - conf.set(OZONE_METADATA_DIRS, testDir.getAbsolutePath()); - containerManager = Mockito.mock(ContainerMapping.class); - deletedBlockLog = new DeletedBlockLogImpl(conf, containerManager); - dnList = new ArrayList<>(3); - setupContainerManager(); - } - - private void setupContainerManager() throws IOException { - dnList.add( - DatanodeDetails.newBuilder().setUuid(UUID.randomUUID().toString()) - .build()); - dnList.add( - DatanodeDetails.newBuilder().setUuid(UUID.randomUUID().toString()) - .build()); - dnList.add( - DatanodeDetails.newBuilder().setUuid(UUID.randomUUID().toString()) - .build()); - - ContainerInfo containerInfo = - new ContainerInfo.Builder().setContainerID(1).build(); - Pipeline pipeline = - new Pipeline(null, LifeCycleState.CLOSED, - ReplicationType.RATIS, ReplicationFactor.THREE, null); - pipeline.addMember(dnList.get(0)); - pipeline.addMember(dnList.get(1)); - pipeline.addMember(dnList.get(2)); - ContainerWithPipeline containerWithPipeline = - new ContainerWithPipeline(containerInfo, pipeline); - when(containerManager.getContainerWithPipeline(anyLong())) - .thenReturn(containerWithPipeline); - when(containerManager.getContainer(anyLong())).thenReturn(containerInfo); - } - - @After - public void tearDown() throws Exception { - deletedBlockLog.close(); - FileUtils.deleteDirectory(testDir); - } - - private Map> generateData(int dataSize) { - Map> blockMap = new HashMap<>(); - Random random = new Random(1); - int continerIDBase = random.nextInt(100); - int localIDBase = random.nextInt(1000); - for (int i = 0; i < dataSize; i++) { - long containerID = continerIDBase + i; - List blocks = new ArrayList<>(); - int blockSize = random.nextInt(30) + 1; - for (int j = 0; j < blockSize; j++) { - long localID = localIDBase + j; - blocks.add(localID); - } - blockMap.put(containerID, blocks); - } - return blockMap; - } - - private void commitTransactions( - List transactionResults, - DatanodeDetails... dns) { - for (DatanodeDetails dnDetails : dns) { - deletedBlockLog - .commitTransactions(transactionResults, dnDetails.getUuid()); - } - } - - private void commitTransactions( - List transactionResults) { - commitTransactions(transactionResults, - dnList.toArray(new DatanodeDetails[3])); - } - - private void commitTransactions( - Collection deletedBlocksTransactions, - DatanodeDetails... dns) { - commitTransactions(deletedBlocksTransactions.stream() - .map(this::createDeleteBlockTransactionResult) - .collect(Collectors.toList()), dns); - } - - private void commitTransactions( - Collection deletedBlocksTransactions) { - commitTransactions(deletedBlocksTransactions.stream() - .map(this::createDeleteBlockTransactionResult) - .collect(Collectors.toList())); - } - - private DeleteBlockTransactionResult createDeleteBlockTransactionResult( - DeletedBlocksTransaction transaction) { - return DeleteBlockTransactionResult.newBuilder() - .setContainerID(transaction.getContainerID()).setSuccess(true) - .setTxID(transaction.getTxID()).build(); - } - - private List getTransactions( - int maximumAllowedTXNum) throws IOException { - DatanodeDeletedBlockTransactions transactions = - new DatanodeDeletedBlockTransactions(containerManager, - maximumAllowedTXNum, 3); - deletedBlockLog.getTransactions(transactions); - return transactions.getDatanodeTransactions(dnList.get(0).getUuid()); - } - - @Test - public void testIncrementCount() throws Exception { - int maxRetry = conf.getInt(OZONE_SCM_BLOCK_DELETION_MAX_RETRY, 20); - - // Create 30 TXs in the log. - for (Map.Entry> entry : generateData(30).entrySet()){ - deletedBlockLog.addTransaction(entry.getKey(), entry.getValue()); - } - - // This will return all TXs, total num 30. - List blocks = - getTransactions(40); - List txIDs = blocks.stream().map(DeletedBlocksTransaction::getTxID) - .collect(Collectors.toList()); - - for (int i = 0; i < maxRetry; i++) { - deletedBlockLog.incrementCount(txIDs); - } - - // Increment another time so it exceed the maxRetry. - // On this call, count will be set to -1 which means TX eventually fails. - deletedBlockLog.incrementCount(txIDs); - blocks = getTransactions(40); - for (DeletedBlocksTransaction block : blocks) { - Assert.assertEquals(-1, block.getCount()); - } - - // If all TXs are failed, getTransactions call will always return nothing. - blocks = getTransactions(40); - Assert.assertEquals(blocks.size(), 0); - } - - @Test - public void testCommitTransactions() throws Exception { - for (Map.Entry> entry : generateData(50).entrySet()){ - deletedBlockLog.addTransaction(entry.getKey(), entry.getValue()); - } - List blocks = - getTransactions(20); - // Add an invalid txn. - blocks.add( - DeletedBlocksTransaction.newBuilder().setContainerID(1).setTxID(70) - .setCount(0).addLocalID(0).build()); - commitTransactions(blocks); - blocks.remove(blocks.size() - 1); - - blocks = getTransactions(50); - Assert.assertEquals(30, blocks.size()); - commitTransactions(blocks, dnList.get(1), dnList.get(2), - DatanodeDetails.newBuilder().setUuid(UUID.randomUUID().toString()) - .build()); - - blocks = getTransactions(50); - Assert.assertEquals(30, blocks.size()); - commitTransactions(blocks, dnList.get(0)); - - blocks = getTransactions(50); - Assert.assertEquals(0, blocks.size()); - } - - @Test - public void testRandomOperateTransactions() throws Exception { - Random random = new Random(); - int added = 0, committed = 0; - List blocks = new ArrayList<>(); - List txIDs = new ArrayList<>(); - byte[] latestTxid = DFSUtil.string2Bytes("#LATEST_TXID#"); - MetadataKeyFilters.MetadataKeyFilter avoidLatestTxid = - (preKey, currentKey, nextKey) -> - !Arrays.equals(latestTxid, currentKey); - MetadataStore store = deletedBlockLog.getDeletedStore(); - // Randomly add/get/commit/increase transactions. - for (int i = 0; i < 100; i++) { - int state = random.nextInt(4); - if (state == 0) { - for (Map.Entry> entry : - generateData(10).entrySet()){ - deletedBlockLog.addTransaction(entry.getKey(), entry.getValue()); - } - added += 10; - } else if (state == 1) { - blocks = getTransactions(20); - txIDs = new ArrayList<>(); - for (DeletedBlocksTransaction block : blocks) { - txIDs.add(block.getTxID()); - } - deletedBlockLog.incrementCount(txIDs); - } else if (state == 2) { - commitTransactions(blocks); - committed += blocks.size(); - blocks = new ArrayList<>(); - } else { - // verify the number of added and committed. - List> result = - store.getRangeKVs(null, added, avoidLatestTxid); - Assert.assertEquals(added, result.size() + committed); - } - } - blocks = getTransactions(1000); - commitTransactions(blocks); - } - - @Test - public void testPersistence() throws Exception { - for (Map.Entry> entry : generateData(50).entrySet()){ - deletedBlockLog.addTransaction(entry.getKey(), entry.getValue()); - } - // close db and reopen it again to make sure - // transactions are stored persistently. - deletedBlockLog.close(); - deletedBlockLog = new DeletedBlockLogImpl(conf, containerManager); - List blocks = - getTransactions(10); - commitTransactions(blocks); - blocks = getTransactions(100); - Assert.assertEquals(40, blocks.size()); - commitTransactions(blocks); - } - - @Test - public void testDeletedBlockTransactions() throws IOException { - int txNum = 10; - int maximumAllowedTXNum = 5; - List blocks = null; - List containerIDs = new LinkedList<>(); - DatanodeDetails dnId1 = dnList.get(0), dnId2 = dnList.get(1); - - int count = 0; - long containerID = 0L; - - // Creates {TXNum} TX in the log. - for (Map.Entry> entry : generateData(txNum) - .entrySet()) { - count++; - containerID = entry.getKey(); - containerIDs.add(containerID); - deletedBlockLog.addTransaction(containerID, entry.getValue()); - - // make TX[1-6] for datanode1; TX[7-10] for datanode2 - if (count <= (maximumAllowedTXNum + 1)) { - mockContainerInfo(containerID, dnId1); - } else { - mockContainerInfo(containerID, dnId2); - } - } - - DatanodeDeletedBlockTransactions transactions = - new DatanodeDeletedBlockTransactions(containerManager, - maximumAllowedTXNum, 2); - deletedBlockLog.getTransactions(transactions); - - for (UUID id : transactions.getDatanodeIDs()) { - List txs = transactions - .getDatanodeTransactions(id); - // delete TX ID - commitTransactions(txs); - } - - blocks = getTransactions(txNum); - // There should be one block remained since dnID1 reaches - // the maximum value (5). - Assert.assertEquals(1, blocks.size()); - - Assert.assertFalse(transactions.isFull()); - // The number of TX in dnID1 won't more than maximum value. - Assert.assertEquals(maximumAllowedTXNum, - transactions.getDatanodeTransactions(dnId1.getUuid()).size()); - - int size = transactions.getDatanodeTransactions(dnId2.getUuid()).size(); - // add duplicated container in dnID2, this should be failed. - DeletedBlocksTransaction.Builder builder = - DeletedBlocksTransaction.newBuilder(); - builder.setTxID(11); - builder.setContainerID(containerID); - builder.setCount(0); - transactions.addTransaction(builder.build(), - null); - - // The number of TX in dnID2 should not be changed. - Assert.assertEquals(size, - transactions.getDatanodeTransactions(dnId2.getUuid()).size()); - - // Add new TX in dnID2, then dnID2 will reach maximum value. - containerID = RandomUtils.nextLong(); - builder = DeletedBlocksTransaction.newBuilder(); - builder.setTxID(12); - builder.setContainerID(containerID); - builder.setCount(0); - mockContainerInfo(containerID, dnId2); - transactions.addTransaction(builder.build(), - null); - // Since all node are full, then transactions is full. - Assert.assertTrue(transactions.isFull()); - } - - private void mockContainerInfo(long containerID, DatanodeDetails dd) - throws IOException { - Pipeline pipeline = - new Pipeline("fake", LifeCycleState.OPEN, - ReplicationType.STAND_ALONE, ReplicationFactor.ONE, - PipelineID.randomId()); - pipeline.addMember(dd); - - ContainerInfo.Builder builder = new ContainerInfo.Builder(); - builder.setPipelineID(pipeline.getId()) - .setReplicationType(pipeline.getType()) - .setReplicationFactor(pipeline.getFactor()); - - ContainerInfo containerInfo = builder.build(); - ContainerWithPipeline containerWithPipeline = new ContainerWithPipeline( - containerInfo, pipeline); - Mockito.doReturn(containerInfo).when(containerManager) - .getContainer(containerID); - Mockito.doReturn(containerWithPipeline).when(containerManager) - .getContainerWithPipeline(containerID); - } -} diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/block/package-info.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/block/package-info.java deleted file mode 100644 index a67df6982aa..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/block/package-info.java +++ /dev/null @@ -1,23 +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 - * - * 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. - * - */ - -/** - * Make checkstyle happy. - * */ -package org.apache.hadoop.hdds.scm.block; \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/command/TestCommandStatusReportHandler.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/command/TestCommandStatusReportHandler.java deleted file mode 100644 index afa25e2af7b..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/command/TestCommandStatusReportHandler.java +++ /dev/null @@ -1,135 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.command; - -import org.apache.hadoop.hdds.HddsIdFactory; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.CommandStatus; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.CommandStatusReportsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMCommandProto.Type; -import org.apache.hadoop.hdds.scm.TestUtils; -import org.apache.hadoop.hdds.scm.server.SCMDatanodeHeartbeatDispatcher; -import org.apache.hadoop.hdds.scm.server.SCMDatanodeHeartbeatDispatcher - .CommandStatusReportFromDatanode; - -import org.apache.hadoop.hdds.server.events.Event; -import org.apache.hadoop.hdds.server.events.EventPublisher; -import org.apache.hadoop.test.GenericTestUtils; -import org.junit.Before; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.UUID; - -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.assertFalse; - -public class TestCommandStatusReportHandler implements EventPublisher { - - private static final Logger LOG = LoggerFactory - .getLogger(TestCommandStatusReportHandler.class); - private CommandStatusReportHandler cmdStatusReportHandler; - private String storagePath = GenericTestUtils.getRandomizedTempPath() - .concat("/" + UUID.randomUUID().toString()); - - @Before - public void setup() { - cmdStatusReportHandler = new CommandStatusReportHandler(); - } - - @Test - public void testCommandStatusReport() { - GenericTestUtils.LogCapturer logCapturer = GenericTestUtils.LogCapturer - .captureLogs(LOG); - - CommandStatusReportFromDatanode report = this.getStatusReport(Collections - .emptyList()); - cmdStatusReportHandler.onMessage(report, this); - assertFalse(logCapturer.getOutput().contains("Delete_Block_Status")); - assertFalse(logCapturer.getOutput().contains( - "Close_Container_Command_Status")); - assertFalse(logCapturer.getOutput().contains("Replicate_Command_Status")); - - - report = this.getStatusReport(this.getCommandStatusList()); - cmdStatusReportHandler.onMessage(report, this); - assertTrue(logCapturer.getOutput().contains("firing event of type " + - "Delete_Block_Status")); - assertTrue(logCapturer.getOutput().contains("firing event of type " + - "Close_Container_Command_Status")); - assertTrue(logCapturer.getOutput().contains("firing event of type " + - "Replicate_Command_Status")); - - assertTrue(logCapturer.getOutput().contains("type: " + - "closeContainerCommand")); - assertTrue(logCapturer.getOutput().contains("type: " + - "deleteBlocksCommand")); - assertTrue(logCapturer.getOutput().contains("type: " + - "replicateContainerCommand")); - - } - - private CommandStatusReportFromDatanode getStatusReport( - List reports) { - CommandStatusReportsProto report = TestUtils.createCommandStatusReport( - reports); - DatanodeDetails dn = TestUtils.randomDatanodeDetails(); - return new SCMDatanodeHeartbeatDispatcher.CommandStatusReportFromDatanode( - dn, report); - } - - @Override - public > void fireEvent - (EVENT_TYPE event, PAYLOAD payload) { - LOG.info("firing event of type {}, payload {}", event.getName(), payload - .toString()); - } - - private List getCommandStatusList() { - List reports = new ArrayList<>(3); - - // Add status message for replication, close container and delete block - // command. - CommandStatus.Builder builder = CommandStatus.newBuilder(); - - builder.setCmdId(HddsIdFactory.getLongId()) - .setStatus(CommandStatus.Status.EXECUTED) - .setType(Type.deleteBlocksCommand); - reports.add(builder.build()); - - builder.setCmdId(HddsIdFactory.getLongId()) - .setStatus(CommandStatus.Status.EXECUTED) - .setType(Type.closeContainerCommand); - reports.add(builder.build()); - - builder.setMsg("Not enough space") - .setCmdId(HddsIdFactory.getLongId()) - .setStatus(CommandStatus.Status.FAILED) - .setType(Type.replicateContainerCommand); - reports.add(builder.build()); - return reports; - } - -} diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/command/package-info.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/command/package-info.java deleted file mode 100644 index f529c20e74e..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/command/package-info.java +++ /dev/null @@ -1,22 +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 - * - * 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. - * - */ -/** - * Make CheckStyle Happy. - */ -package org.apache.hadoop.hdds.scm.command; \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/MockNodeManager.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/MockNodeManager.java deleted file mode 100644 index 32210535730..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/MockNodeManager.java +++ /dev/null @@ -1,592 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.scm.container; - -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.PipelineReportsProto; -import org.apache.hadoop.hdds.scm.TestUtils; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.scm.container.common.helpers.PipelineID; -import org.apache.hadoop.hdds.scm.container.placement.metrics.SCMNodeMetric; -import org.apache.hadoop.hdds.scm.container.placement.metrics.SCMNodeStat; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.hdds.scm.node.NodeManager; -import org.apache.hadoop.hdds.scm.node.states.Node2ContainerMap; -import org.apache.hadoop.hdds.scm.node.states.Node2PipelineMap; -import org.apache.hadoop.hdds.scm.node.states.NodeNotFoundException; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.NodeReportProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMVersionRequestProto; -import org.apache.hadoop.hdds.scm.node.states.ReportResult; -import org.apache.hadoop.hdds.server.events.EventPublisher; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.protocol.VersionResponse; -import org.apache.hadoop.ozone.protocol.commands.CommandForDatanode; -import org.apache.hadoop.ozone.protocol.commands.RegisteredCommand; -import org.apache.hadoop.ozone.protocol.commands.SCMCommand; -import org.assertj.core.util.Preconditions; - -import java.io.IOException; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - -import static org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState.DEAD; -import static org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState - .HEALTHY; -import static org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState.STALE; - -/** - * Test Helper for testing container Mapping. - */ -public class MockNodeManager implements NodeManager { - private final static NodeData[] NODES = { - new NodeData(10L * OzoneConsts.TB, OzoneConsts.GB), - new NodeData(64L * OzoneConsts.TB, 100 * OzoneConsts.GB), - new NodeData(128L * OzoneConsts.TB, 256 * OzoneConsts.GB), - new NodeData(40L * OzoneConsts.TB, OzoneConsts.TB), - new NodeData(256L * OzoneConsts.TB, 200 * OzoneConsts.TB), - new NodeData(20L * OzoneConsts.TB, 10 * OzoneConsts.GB), - new NodeData(32L * OzoneConsts.TB, 16 * OzoneConsts.TB), - new NodeData(OzoneConsts.TB, 900 * OzoneConsts.GB), - new NodeData(OzoneConsts.TB, 900 * OzoneConsts.GB, NodeData.STALE), - new NodeData(OzoneConsts.TB, 200L * OzoneConsts.GB, NodeData.STALE), - new NodeData(OzoneConsts.TB, 200L * OzoneConsts.GB, NodeData.DEAD) - }; - private final List healthyNodes; - private final List staleNodes; - private final List deadNodes; - private final Map nodeMetricMap; - private final SCMNodeStat aggregateStat; - private boolean chillmode; - private final Map> commandMap; - private final Node2PipelineMap node2PipelineMap; - private final Node2ContainerMap node2ContainerMap; - - public MockNodeManager(boolean initializeFakeNodes, int nodeCount) { - this.healthyNodes = new LinkedList<>(); - this.staleNodes = new LinkedList<>(); - this.deadNodes = new LinkedList<>(); - this.nodeMetricMap = new HashMap<>(); - this.node2PipelineMap = new Node2PipelineMap(); - this.node2ContainerMap = new Node2ContainerMap(); - aggregateStat = new SCMNodeStat(); - if (initializeFakeNodes) { - for (int x = 0; x < nodeCount; x++) { - DatanodeDetails dd = TestUtils.randomDatanodeDetails(); - populateNodeMetric(dd, x); - } - } - chillmode = false; - this.commandMap = new HashMap<>(); - } - - /** - * Invoked from ctor to create some node Metrics. - * - * @param datanodeDetails - Datanode details - */ - private void populateNodeMetric(DatanodeDetails datanodeDetails, int x) { - SCMNodeStat newStat = new SCMNodeStat(); - long remaining = - NODES[x % NODES.length].capacity - NODES[x % NODES.length].used; - newStat.set( - (NODES[x % NODES.length].capacity), - (NODES[x % NODES.length].used), remaining); - this.nodeMetricMap.put(datanodeDetails.getUuid(), newStat); - aggregateStat.add(newStat); - - if (NODES[x % NODES.length].getCurrentState() == NodeData.HEALTHY) { - healthyNodes.add(datanodeDetails); - } - - if (NODES[x % NODES.length].getCurrentState() == NodeData.STALE) { - staleNodes.add(datanodeDetails); - } - - if (NODES[x % NODES.length].getCurrentState() == NodeData.DEAD) { - deadNodes.add(datanodeDetails); - } - - } - - /** - * Sets the chill mode value. - * @param chillmode boolean - */ - public void setChillmode(boolean chillmode) { - this.chillmode = chillmode; - } - - /** - * Removes a data node from the management of this Node Manager. - * - * @param node - DataNode. - * @throws NodeNotFoundException - */ - @Override - public void removeNode(DatanodeDetails node) - throws NodeNotFoundException { - - } - - /** - * Gets all Live Datanodes that is currently communicating with SCM. - * - * @param nodestate - State of the node - * @return List of Datanodes that are Heartbeating SCM. - */ - @Override - public List getNodes(HddsProtos.NodeState nodestate) { - if (nodestate == HEALTHY) { - return healthyNodes; - } - - if (nodestate == STALE) { - return staleNodes; - } - - if (nodestate == DEAD) { - return deadNodes; - } - - return null; - } - - /** - * Returns the Number of Datanodes that are communicating with SCM. - * - * @param nodestate - State of the node - * @return int -- count - */ - @Override - public int getNodeCount(HddsProtos.NodeState nodestate) { - List nodes = getNodes(nodestate); - if (nodes != null) { - return nodes.size(); - } - return 0; - } - - /** - * Get all datanodes known to SCM. - * - * @return List of DatanodeDetails known to SCM. - */ - @Override - public List getAllNodes() { - return null; - } - - /** - * Get the minimum number of nodes to get out of chill mode. - * - * @return int - */ - @Override - public int getMinimumChillModeNodes() { - return 0; - } - - /** - * Chill mode is the period when node manager waits for a minimum configured - * number of datanodes to report in. This is called chill mode to indicate the - * period before node manager gets into action. - *

- * Forcefully exits the chill mode, even if we have not met the minimum - * criteria of the nodes reporting in. - */ - @Override - public void forceExitChillMode() { - - } - - /** - * Puts the node manager into manual chill mode. - */ - @Override - public void enterChillMode() { - - } - - /** - * Brings node manager out of manual chill mode. - */ - @Override - public void exitChillMode() { - - } - - /** - * Returns true if node manager is out of chill mode, else false. - * @return true if out of chill mode, else false - */ - @Override - public boolean isOutOfChillMode() { - return !chillmode; - } - - /** - * Returns a chill mode status string. - * - * @return String - */ - @Override - public String getChillModeStatus() { - return null; - } - - /** - * Returns the aggregated node stats. - * @return the aggregated node stats. - */ - @Override - public SCMNodeStat getStats() { - return aggregateStat; - } - - /** - * Return a map of nodes to their stats. - * @return a list of individual node stats (live/stale but not dead). - */ - @Override - public Map getNodeStats() { - return nodeMetricMap; - } - - /** - * Return the node stat of the specified datanode. - * @param datanodeDetails - datanode details. - * @return node stat if it is live/stale, null if it is decommissioned or - * doesn't exist. - */ - @Override - public SCMNodeMetric getNodeStat(DatanodeDetails datanodeDetails) { - SCMNodeStat stat = nodeMetricMap.get(datanodeDetails.getUuid()); - if (stat == null) { - return null; - } - return new SCMNodeMetric(stat); - } - - /** - * Returns the node state of a specific node. - * - * @param dd - DatanodeDetails - * @return Healthy/Stale/Dead. - */ - @Override - public HddsProtos.NodeState getNodeState(DatanodeDetails dd) { - return null; - } - - /** - * Get set of pipelines a datanode is part of. - * @param dnId - datanodeID - * @return Set of PipelineID - */ - @Override - public Set getPipelineByDnID(UUID dnId) { - return node2PipelineMap.getPipelines(dnId); - } - - /** - * Add pipeline information in the NodeManager. - * @param pipeline - Pipeline to be added - */ - @Override - public void addPipeline(Pipeline pipeline) { - node2PipelineMap.addPipeline(pipeline); - } - - /** - * Remove a pipeline information from the NodeManager. - * @param pipeline - Pipeline to be removed - */ - @Override - public void removePipeline(Pipeline pipeline) { - node2PipelineMap.removePipeline(pipeline); - } - - @Override - public void addDatanodeCommand(UUID dnId, SCMCommand command) { - if(commandMap.containsKey(dnId)) { - List commandList = commandMap.get(dnId); - Preconditions.checkNotNull(commandList); - commandList.add(command); - } else { - List commandList = new LinkedList<>(); - commandList.add(command); - commandMap.put(dnId, commandList); - } - } - - /** - * Empty implementation for processNodeReport. - * - * @param dnUuid - * @param nodeReport - */ - @Override - public void processNodeReport(UUID dnUuid, NodeReportProto nodeReport) { - // do nothing - } - - /** - * Update set of containers available on a datanode. - * @param uuid - DatanodeID - * @param containerIds - Set of containerIDs - * @throws SCMException - if datanode is not known. For new datanode use - * addDatanodeInContainerMap call. - */ - @Override - public void setContainersForDatanode(UUID uuid, Set containerIds) - throws SCMException { - node2ContainerMap.setContainersForDatanode(uuid, containerIds); - } - - /** - * Process containerReport received from datanode. - * @param uuid - DataonodeID - * @param containerIds - Set of containerIDs - * @return The result after processing containerReport - */ - @Override - public ReportResult processContainerReport(UUID uuid, - Set containerIds) { - return node2ContainerMap.processReport(uuid, containerIds); - } - - /** - * Return set of containerIDs available on a datanode. - * @param uuid - DatanodeID - * @return - set of containerIDs - */ - @Override - public Set getContainers(UUID uuid) { - return node2ContainerMap.getContainers(uuid); - } - - /** - * Insert a new datanode with set of containerIDs for containers available - * on it. - * @param uuid - DatanodeID - * @param containerIDs - Set of ContainerIDs - * @throws SCMException - if datanode already exists - */ - @Override - public void addDatanodeInContainerMap(UUID uuid, - Set containerIDs) throws SCMException { - node2ContainerMap.insertNewDatanode(uuid, containerIDs); - } - - // Returns the number of commands that is queued to this node manager. - public int getCommandCount(DatanodeDetails dd) { - List list = commandMap.get(dd.getUuid()); - return (list == null) ? 0 : list.size(); - } - - public void clearCommandQueue(UUID dnId) { - if(commandMap.containsKey(dnId)) { - commandMap.put(dnId, new LinkedList<>()); - } - } - - /** - * Closes this stream and releases any system resources associated with it. If - * the stream is already closed then invoking this method has no effect. - *

- *

As noted in {@link AutoCloseable#close()}, cases where the close may - * fail require careful attention. It is strongly advised to relinquish the - * underlying resources and to internally mark the {@code Closeable} - * as closed, prior to throwing the {@code IOException}. - * - * @throws IOException if an I/O error occurs - */ - @Override - public void close() throws IOException { - - } - - /** - * Gets the version info from SCM. - * - * @param versionRequest - version Request. - * @return - returns SCM version info and other required information needed by - * datanode. - */ - @Override - public VersionResponse getVersion(SCMVersionRequestProto versionRequest) { - return null; - } - - /** - * Register the node if the node finds that it is not registered with any - * SCM. - * - * @param datanodeDetails DatanodeDetails - * @param nodeReport NodeReportProto - * @return SCMHeartbeatResponseProto - */ - @Override - public RegisteredCommand register(DatanodeDetails datanodeDetails, - NodeReportProto nodeReport, PipelineReportsProto pipelineReportsProto) { - return null; - } - - /** - * Send heartbeat to indicate the datanode is alive and doing well. - * - * @param datanodeDetails - Datanode ID. - * @return SCMheartbeat response list - */ - @Override - public List processHeartbeat(DatanodeDetails datanodeDetails) { - return null; - } - - @Override - public Map getNodeCount() { - Map nodeCountMap = new HashMap(); - for (HddsProtos.NodeState state : HddsProtos.NodeState.values()) { - nodeCountMap.put(state.toString(), getNodeCount(state)); - } - return nodeCountMap; - } - - /** - * Makes it easy to add a container. - * - * @param datanodeDetails datanode details - * @param size number of bytes. - */ - public void addContainer(DatanodeDetails datanodeDetails, long size) { - SCMNodeStat stat = this.nodeMetricMap.get(datanodeDetails.getUuid()); - if (stat != null) { - aggregateStat.subtract(stat); - stat.getCapacity().add(size); - aggregateStat.add(stat); - nodeMetricMap.put(datanodeDetails.getUuid(), stat); - } - } - - /** - * Makes it easy to simulate a delete of a container. - * - * @param datanodeDetails datanode Details - * @param size number of bytes. - */ - public void delContainer(DatanodeDetails datanodeDetails, long size) { - SCMNodeStat stat = this.nodeMetricMap.get(datanodeDetails.getUuid()); - if (stat != null) { - aggregateStat.subtract(stat); - stat.getCapacity().subtract(size); - aggregateStat.add(stat); - nodeMetricMap.put(datanodeDetails.getUuid(), stat); - } - } - - @Override - public void onMessage(CommandForDatanode commandForDatanode, - EventPublisher publisher) { - addDatanodeCommand(commandForDatanode.getDatanodeId(), - commandForDatanode.getCommand()); - } - - /** - * Remove the node stats and update the storage stats - * in this Node Manager. - * - * @param dnUuid UUID of the datanode. - */ - @Override - public void processDeadNode(UUID dnUuid) { - SCMNodeStat stat = this.nodeMetricMap.get(dnUuid); - if (stat != null) { - aggregateStat.subtract(stat); - stat.set(0, 0, 0); - } - } - - /** - * A class to declare some values for the nodes so that our tests - * won't fail. - */ - private static class NodeData { - public static final long HEALTHY = 1; - public static final long STALE = 2; - public static final long DEAD = 3; - - private long capacity; - private long used; - - private long currentState; - - /** - * By default nodes are healthy. - * @param capacity - * @param used - */ - NodeData(long capacity, long used) { - this(capacity, used, HEALTHY); - } - - /** - * Constructs a nodeDefinition. - * - * @param capacity capacity. - * @param used used. - * @param currentState - Healthy, Stale and DEAD nodes. - */ - NodeData(long capacity, long used, long currentState) { - this.capacity = capacity; - this.used = used; - this.currentState = currentState; - } - - public long getCapacity() { - return capacity; - } - - public void setCapacity(long capacity) { - this.capacity = capacity; - } - - public long getUsed() { - return used; - } - - public void setUsed(long used) { - this.used = used; - } - - public long getCurrentState() { - return currentState; - } - - public void setCurrentState(long currentState) { - this.currentState = currentState; - } - - } -} diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/TestCloseContainerEventHandler.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/TestCloseContainerEventHandler.java deleted file mode 100644 index 38050c9d037..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/TestCloseContainerEventHandler.java +++ /dev/null @@ -1,177 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.hdds.scm.container; - -import org.apache.commons.lang3.RandomUtils; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.conf.StorageUnit; -import org.apache.hadoop.fs.FileUtil; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.scm.container.common.helpers - .ContainerWithPipeline; -import org.apache.hadoop.hdds.server.events.EventQueue; -import org.apache.hadoop.ozone.OzoneConfigKeys; -import org.apache.hadoop.ozone.container.common.SCMTestUtils; -import org.apache.hadoop.test.GenericTestUtils; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; - -import java.io.File; -import java.io.IOException; - -import static org.apache.hadoop.hdds.protocol.proto.HddsProtos.LifeCycleEvent.CREATED; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys.OZONE_SCM_CONTAINER_SIZE_DEFAULT; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys.OZONE_SCM_CONTAINER_SIZE; -import static org.apache.hadoop.hdds.scm.events.SCMEvents.CLOSE_CONTAINER; -import static org.apache.hadoop.hdds.scm.events.SCMEvents.DATANODE_COMMAND; - -/** - * Tests the closeContainerEventHandler class. - */ -public class TestCloseContainerEventHandler { - - private static Configuration configuration; - private static MockNodeManager nodeManager; - private static ContainerMapping mapping; - private static long size; - private static File testDir; - private static EventQueue eventQueue; - - @BeforeClass - public static void setUp() throws Exception { - configuration = SCMTestUtils.getConf(); - size = (long)configuration.getStorageSize(OZONE_SCM_CONTAINER_SIZE, - OZONE_SCM_CONTAINER_SIZE_DEFAULT, StorageUnit.BYTES); - testDir = GenericTestUtils - .getTestDir(TestCloseContainerEventHandler.class.getSimpleName()); - configuration - .set(OzoneConfigKeys.OZONE_METADATA_DIRS, testDir.getAbsolutePath()); - nodeManager = new MockNodeManager(true, 10); - mapping = new ContainerMapping(configuration, nodeManager, 128, - new EventQueue()); - eventQueue = new EventQueue(); - eventQueue.addHandler(CLOSE_CONTAINER, - new CloseContainerEventHandler(mapping)); - eventQueue.addHandler(DATANODE_COMMAND, nodeManager); - } - - @AfterClass - public static void tearDown() throws Exception { - if (mapping != null) { - mapping.close(); - } - FileUtil.fullyDelete(testDir); - } - - @Test - public void testIfCloseContainerEventHadnlerInvoked() { - GenericTestUtils.LogCapturer logCapturer = GenericTestUtils.LogCapturer - .captureLogs(CloseContainerEventHandler.LOG); - eventQueue.fireEvent(CLOSE_CONTAINER, - new ContainerID(Math.abs(RandomUtils.nextInt()))); - eventQueue.processAll(1000); - Assert.assertTrue(logCapturer.getOutput() - .contains("Close container Event triggered for container")); - } - - @Test - public void testCloseContainerEventWithInvalidContainer() { - long id = Math.abs(RandomUtils.nextInt()); - GenericTestUtils.LogCapturer logCapturer = GenericTestUtils.LogCapturer - .captureLogs(CloseContainerEventHandler.LOG); - eventQueue.fireEvent(CLOSE_CONTAINER, - new ContainerID(id)); - eventQueue.processAll(1000); - Assert.assertTrue(logCapturer.getOutput() - .contains("Failed to update the container state")); - } - - @Test - public void testCloseContainerEventWithValidContainers() throws IOException { - - GenericTestUtils.LogCapturer logCapturer = GenericTestUtils.LogCapturer - .captureLogs(CloseContainerEventHandler.LOG); - ContainerWithPipeline containerWithPipeline = mapping - .allocateContainer(HddsProtos.ReplicationType.STAND_ALONE, - HddsProtos.ReplicationFactor.ONE, "ozone"); - ContainerID id = new ContainerID( - containerWithPipeline.getContainerInfo().getContainerID()); - DatanodeDetails datanode = containerWithPipeline.getPipeline().getLeader(); - int closeCount = nodeManager.getCommandCount(datanode); - eventQueue.fireEvent(CLOSE_CONTAINER, id); - eventQueue.processAll(1000); - // At this point of time, the allocated container is not in open - // state, so firing close container event should not queue CLOSE - // command in the Datanode - Assert.assertEquals(0, nodeManager.getCommandCount(datanode)); - //Execute these state transitions so that we can close the container. - mapping.updateContainerState(id.getId(), CREATED); - eventQueue.fireEvent(CLOSE_CONTAINER, - new ContainerID( - containerWithPipeline.getContainerInfo().getContainerID())); - eventQueue.processAll(1000); - Assert.assertEquals(closeCount + 1, - nodeManager.getCommandCount(datanode)); - Assert.assertEquals(HddsProtos.LifeCycleState.CLOSING, - mapping.getStateManager().getContainer(id).getState()); - } - - @Test - public void testCloseContainerEventWithRatis() throws IOException { - - GenericTestUtils.LogCapturer logCapturer = GenericTestUtils.LogCapturer - .captureLogs(CloseContainerEventHandler.LOG); - ContainerWithPipeline containerWithPipeline = mapping - .allocateContainer(HddsProtos.ReplicationType.RATIS, - HddsProtos.ReplicationFactor.THREE, "ozone"); - ContainerID id = new ContainerID( - containerWithPipeline.getContainerInfo().getContainerID()); - int[] closeCount = new int[3]; - eventQueue.fireEvent(CLOSE_CONTAINER, id); - eventQueue.processAll(1000); - int i = 0; - for (DatanodeDetails details : containerWithPipeline.getPipeline() - .getMachines()) { - closeCount[i] = nodeManager.getCommandCount(details); - i++; - } - i = 0; - for (DatanodeDetails details : containerWithPipeline.getPipeline() - .getMachines()) { - Assert.assertEquals(closeCount[i], nodeManager.getCommandCount(details)); - i++; - } - //Execute these state transitions so that we can close the container. - mapping.updateContainerState(id.getId(), CREATED); - eventQueue.fireEvent(CLOSE_CONTAINER, id); - eventQueue.processAll(1000); - i = 0; - // Make sure close is queued for each datanode on the pipeline - for (DatanodeDetails details : containerWithPipeline.getPipeline() - .getMachines()) { - Assert.assertEquals(closeCount[i] + 1, - nodeManager.getCommandCount(details)); - Assert.assertEquals(HddsProtos.LifeCycleState.CLOSING, - mapping.getStateManager().getContainer(id).getState()); - i++; - } - } -} diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/TestContainerActionsHandler.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/TestContainerActionsHandler.java deleted file mode 100644 index 0997e1f5bc9..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/TestContainerActionsHandler.java +++ /dev/null @@ -1,68 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.container; - -import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.ContainerActionsProto; -import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.ContainerAction; -import org.apache.hadoop.hdds.scm.TestUtils; -import org.apache.hadoop.hdds.scm.events.SCMEvents; -import org.apache.hadoop.hdds.scm.server.SCMDatanodeHeartbeatDispatcher.ContainerActionsFromDatanode; -import org.apache.hadoop.hdds.server.events.EventQueue; -import org.junit.Test; -import org.mockito.Mockito; - -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -/** - * Tests ContainerActionsHandler. - */ -public class TestContainerActionsHandler { - - @Test - public void testCloseContainerAction() { - EventQueue queue = new EventQueue(); - ContainerActionsHandler actionsHandler = new ContainerActionsHandler(); - CloseContainerEventHandler closeContainerEventHandler = Mockito.mock( - CloseContainerEventHandler.class); - queue.addHandler(SCMEvents.CLOSE_CONTAINER, closeContainerEventHandler); - queue.addHandler(SCMEvents.CONTAINER_ACTIONS, actionsHandler); - - ContainerAction action = ContainerAction.newBuilder() - .setContainerID(1L) - .setAction(ContainerAction.Action.CLOSE) - .setReason(ContainerAction.Reason.CONTAINER_FULL) - .build(); - - ContainerActionsProto cap = ContainerActionsProto.newBuilder() - .addContainerActions(action) - .build(); - - ContainerActionsFromDatanode containerActions = - new ContainerActionsFromDatanode( - TestUtils.randomDatanodeDetails(), cap); - - queue.fireEvent(SCMEvents.CONTAINER_ACTIONS, containerActions); - - verify(closeContainerEventHandler, times(1)) - .onMessage(ContainerID.valueof(1L), queue); - - } - -} \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/TestContainerMapping.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/TestContainerMapping.java deleted file mode 100644 index f9a881e27d8..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/TestContainerMapping.java +++ /dev/null @@ -1,380 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.scm.container; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.FileUtil; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.LifeCycleEvent; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.LifeCycleState; -import org.apache.hadoop.hdds.scm.ScmConfigKeys; -import org.apache.hadoop.hdds.scm.TestUtils; -import org.apache.hadoop.hdds.scm.XceiverClientManager; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerWithPipeline; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerReportsProto; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.hdds.server.events.EventQueue; -import org.apache.hadoop.ozone.OzoneConfigKeys; -import org.apache.hadoop.ozone.container.common.SCMTestUtils; -import org.apache.hadoop.test.GenericTestUtils; -import org.apache.hadoop.test.LambdaTestUtils; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.NavigableSet; -import java.util.Random; -import java.util.Set; -import java.util.TreeSet; -import java.util.UUID; -import java.util.concurrent.TimeUnit; - -/** - * Tests for Container Mapping. - */ -public class TestContainerMapping { - private static ContainerMapping mapping; - private static MockNodeManager nodeManager; - private static File testDir; - private static XceiverClientManager xceiverClientManager; - private static String containerOwner = "OZONE"; - private static Random random; - - private static final long TIMEOUT = 10000; - - @Rule - public ExpectedException thrown = ExpectedException.none(); - @BeforeClass - public static void setUp() throws Exception { - Configuration conf = SCMTestUtils.getConf(); - - testDir = GenericTestUtils - .getTestDir(TestContainerMapping.class.getSimpleName()); - conf.set(OzoneConfigKeys.OZONE_METADATA_DIRS, - testDir.getAbsolutePath()); - conf.setTimeDuration( - ScmConfigKeys.OZONE_SCM_CONTAINER_CREATION_LEASE_TIMEOUT, - TIMEOUT, - TimeUnit.MILLISECONDS); - boolean folderExisted = testDir.exists() || testDir.mkdirs(); - if (!folderExisted) { - throw new IOException("Unable to create test directory path"); - } - nodeManager = new MockNodeManager(true, 10); - mapping = new ContainerMapping(conf, nodeManager, 128, - new EventQueue()); - xceiverClientManager = new XceiverClientManager(conf); - random = new Random(); - } - - @AfterClass - public static void cleanup() throws IOException { - if(mapping != null) { - mapping.close(); - } - FileUtil.fullyDelete(testDir); - } - - @Before - public void clearChillMode() { - nodeManager.setChillmode(false); - } - - @Test - public void testallocateContainer() throws Exception { - ContainerWithPipeline containerInfo = mapping.allocateContainer( - xceiverClientManager.getType(), - xceiverClientManager.getFactor(), - containerOwner); - Assert.assertNotNull(containerInfo); - } - - @Test - public void testallocateContainerDistributesAllocation() throws Exception { - /* This is a lame test, we should really be testing something like - z-score or make sure that we don't have 3sigma kind of events. Too lazy - to write all that code. This test very lamely tests if we have more than - 5 separate nodes from the list of 10 datanodes that got allocated a - container. - */ - Set pipelineList = new TreeSet<>(); - for (int x = 0; x < 30; x++) { - ContainerWithPipeline containerInfo = mapping.allocateContainer( - xceiverClientManager.getType(), - xceiverClientManager.getFactor(), - containerOwner); - - Assert.assertNotNull(containerInfo); - Assert.assertNotNull(containerInfo.getPipeline()); - pipelineList.add(containerInfo.getPipeline().getLeader() - .getUuid()); - } - Assert.assertTrue(pipelineList.size() > 5); - } - - @Test - public void testGetContainer() throws IOException { - ContainerWithPipeline containerInfo = mapping.allocateContainer( - xceiverClientManager.getType(), - xceiverClientManager.getFactor(), - containerOwner); - Pipeline pipeline = containerInfo.getPipeline(); - Assert.assertNotNull(pipeline); - Pipeline newPipeline = containerInfo.getPipeline(); - Assert.assertEquals(pipeline.getLeader().getUuid(), - newPipeline.getLeader().getUuid()); - } - - @Test - public void testGetContainerWithPipeline() throws Exception { - ContainerWithPipeline containerWithPipeline = mapping.allocateContainer( - xceiverClientManager.getType(), - xceiverClientManager.getFactor(), - containerOwner); - ContainerInfo contInfo = containerWithPipeline.getContainerInfo(); - // Add dummy replicas for container. - DatanodeDetails dn1 = DatanodeDetails.newBuilder() - .setHostName("host1") - .setIpAddress("1.1.1.1") - .setUuid(UUID.randomUUID().toString()).build(); - DatanodeDetails dn2 = DatanodeDetails.newBuilder() - .setHostName("host2") - .setIpAddress("2.2.2.2") - .setUuid(UUID.randomUUID().toString()).build(); - mapping - .updateContainerState(contInfo.getContainerID(), LifeCycleEvent.CREATE); - mapping.updateContainerState(contInfo.getContainerID(), - LifeCycleEvent.CREATED); - mapping.updateContainerState(contInfo.getContainerID(), - LifeCycleEvent.FINALIZE); - mapping - .updateContainerState(contInfo.getContainerID(), LifeCycleEvent.CLOSE); - ContainerInfo finalContInfo = contInfo; - LambdaTestUtils.intercept(SCMException.class, "No entry exist for " - + "containerId:", () -> mapping.getContainerWithPipeline( - finalContInfo.getContainerID())); - - mapping.getStateManager().getContainerStateMap() - .addContainerReplica(contInfo.containerID(), dn1, dn2); - - contInfo = mapping.getContainer(contInfo.getContainerID()); - Assert.assertEquals(contInfo.getState(), LifeCycleState.CLOSED); - Pipeline pipeline = containerWithPipeline.getPipeline(); - mapping.getPipelineSelector().finalizePipeline(pipeline); - - ContainerWithPipeline containerWithPipeline2 = mapping - .getContainerWithPipeline(contInfo.getContainerID()); - pipeline = containerWithPipeline2.getPipeline(); - Assert.assertNotEquals(containerWithPipeline, containerWithPipeline2); - Assert.assertNotNull("Pipeline should not be null", pipeline); - Assert.assertTrue(pipeline.getDatanodeHosts().contains(dn1.getHostName())); - Assert.assertTrue(pipeline.getDatanodeHosts().contains(dn2.getHostName())); - } - - @Test - public void testgetNoneExistentContainer() throws IOException { - thrown.expectMessage("Specified key does not exist."); - mapping.getContainer(random.nextLong()); - } - - @Test - public void testContainerCreationLeaseTimeout() throws IOException, - InterruptedException { - nodeManager.setChillmode(false); - ContainerWithPipeline containerInfo = mapping.allocateContainer( - xceiverClientManager.getType(), - xceiverClientManager.getFactor(), - containerOwner); - mapping.updateContainerState(containerInfo.getContainerInfo() - .getContainerID(), HddsProtos.LifeCycleEvent.CREATE); - Thread.sleep(TIMEOUT + 1000); - - NavigableSet deleteContainers = mapping.getStateManager() - .getMatchingContainerIDs( - "OZONE", - xceiverClientManager.getType(), - xceiverClientManager.getFactor(), - HddsProtos.LifeCycleState.DELETING); - Assert.assertTrue(deleteContainers - .contains(containerInfo.getContainerInfo().containerID())); - - thrown.expect(IOException.class); - thrown.expectMessage("Lease Exception"); - mapping - .updateContainerState(containerInfo.getContainerInfo().getContainerID(), - HddsProtos.LifeCycleEvent.CREATED); - } - - @Test - public void testFullContainerReport() throws Exception { - ContainerInfo info = createContainer(); - DatanodeDetails datanodeDetails = TestUtils.randomDatanodeDetails(); - List reports = - new ArrayList<>(); - StorageContainerDatanodeProtocolProtos.ContainerInfo.Builder ciBuilder = - StorageContainerDatanodeProtocolProtos.ContainerInfo.newBuilder(); - ciBuilder.setFinalhash("e16cc9d6024365750ed8dbd194ea46d2") - .setSize(5368709120L) - .setUsed(2000000000L) - .setKeyCount(100000000L) - .setReadCount(100000000L) - .setWriteCount(100000000L) - .setReadBytes(2000000000L) - .setWriteBytes(2000000000L) - .setContainerID(info.getContainerID()) - .setDeleteTransactionId(0); - - reports.add(ciBuilder.build()); - - ContainerReportsProto.Builder crBuilder = ContainerReportsProto - .newBuilder(); - crBuilder.addAllReports(reports); - - mapping.processContainerReports(datanodeDetails, crBuilder.build(), false); - - ContainerInfo updatedContainer = - mapping.getContainer(info.getContainerID()); - Assert.assertEquals(100000000L, - updatedContainer.getNumberOfKeys()); - Assert.assertEquals(2000000000L, updatedContainer.getUsedBytes()); - - for (StorageContainerDatanodeProtocolProtos.ContainerInfo c : reports) { - LambdaTestUtils.intercept(SCMException.class, "No entry " - + "exist for containerId:", () -> mapping.getStateManager() - .getContainerReplicas(ContainerID.valueof(c.getContainerID()))); - } - - mapping.processContainerReports(TestUtils.randomDatanodeDetails(), - crBuilder.build(), true); - for (StorageContainerDatanodeProtocolProtos.ContainerInfo c : reports) { - Assert.assertTrue(mapping.getStateManager().getContainerReplicas( - ContainerID.valueof(c.getContainerID())).size() > 0); - } - } - - @Test - public void testListContainerAfterReport() throws Exception { - ContainerInfo info1 = createContainer(); - ContainerInfo info2 = createContainer(); - DatanodeDetails datanodeDetails = TestUtils.randomDatanodeDetails(); - List reports = - new ArrayList<>(); - StorageContainerDatanodeProtocolProtos.ContainerInfo.Builder ciBuilder = - StorageContainerDatanodeProtocolProtos.ContainerInfo.newBuilder(); - long cID1 = info1.getContainerID(); - long cID2 = info2.getContainerID(); - ciBuilder.setFinalhash("e16cc9d6024365750ed8dbd194ea46d2") - .setSize(1000000000L) - .setUsed(987654321L) - .setKeyCount(100000000L) - .setReadBytes(1000000000L) - .setWriteBytes(1000000000L) - .setContainerID(cID1); - reports.add(ciBuilder.build()); - - ciBuilder.setFinalhash("e16cc9d6024365750ed8dbd194ea54a9") - .setSize(1000000000L) - .setUsed(123456789L) - .setKeyCount(200000000L) - .setReadBytes(3000000000L) - .setWriteBytes(4000000000L) - .setContainerID(cID2); - reports.add(ciBuilder.build()); - - ContainerReportsProto.Builder crBuilder = ContainerReportsProto - .newBuilder(); - crBuilder.addAllReports(reports); - - mapping.processContainerReports(datanodeDetails, crBuilder.build(), false); - - List list = mapping.listContainer(0, 50); - Assert.assertEquals(2, list.stream().filter( - x -> x.getContainerID() == cID1 || x.getContainerID() == cID2).count()); - Assert.assertEquals(300000000L, list.stream().filter( - x -> x.getContainerID() == cID1 || x.getContainerID() == cID2) - .mapToLong(x -> x.getNumberOfKeys()).sum()); - Assert.assertEquals(1111111110L, list.stream().filter( - x -> x.getContainerID() == cID1 || x.getContainerID() == cID2) - .mapToLong(x -> x.getUsedBytes()).sum()); - } - - @Test - public void testCloseContainer() throws IOException { - ContainerInfo info = createContainer(); - mapping.updateContainerState(info.getContainerID(), - HddsProtos.LifeCycleEvent.FINALIZE); - NavigableSet pendingCloseContainers = mapping.getStateManager() - .getMatchingContainerIDs( - containerOwner, - xceiverClientManager.getType(), - xceiverClientManager.getFactor(), - HddsProtos.LifeCycleState.CLOSING); - Assert.assertTrue(pendingCloseContainers.contains(info.containerID())); - mapping.updateContainerState(info.getContainerID(), - HddsProtos.LifeCycleEvent.CLOSE); - NavigableSet closeContainers = mapping.getStateManager() - .getMatchingContainerIDs( - containerOwner, - xceiverClientManager.getType(), - xceiverClientManager.getFactor(), - HddsProtos.LifeCycleState.CLOSED); - Assert.assertTrue(closeContainers.contains(info.containerID())); - } - - /** - * Creates a container with the given name in ContainerMapping. - * @throws IOException - */ - private ContainerInfo createContainer() - throws IOException { - nodeManager.setChillmode(false); - ContainerWithPipeline containerWithPipeline = mapping.allocateContainer( - xceiverClientManager.getType(), - xceiverClientManager.getFactor(), - containerOwner); - ContainerInfo containerInfo = containerWithPipeline.getContainerInfo(); - mapping.updateContainerState(containerInfo.getContainerID(), - HddsProtos.LifeCycleEvent.CREATE); - mapping.updateContainerState(containerInfo.getContainerID(), - HddsProtos.LifeCycleEvent.CREATED); - return containerInfo; - } - - @Test - public void testFlushAllContainers() throws IOException { - ContainerInfo info = createContainer(); - List containers = mapping.getStateManager() - .getAllContainers(); - Assert.assertTrue(containers.size() > 0); - mapping.flushContainerInfo(); - } - -} diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/TestContainerReportHandler.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/TestContainerReportHandler.java deleted file mode 100644 index f79ae1e32d9..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/TestContainerReportHandler.java +++ /dev/null @@ -1,239 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.scm.container; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; - -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.LifeCycleState; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationFactor; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationType; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerReportsProto; -import org.apache.hadoop.hdds.scm.TestUtils; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo - .Builder; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.scm.container.common.helpers.PipelineID; -import org.apache.hadoop.hdds.scm.container.replication - .ReplicationActivityStatus; -import org.apache.hadoop.hdds.scm.container.replication.ReplicationRequest; -import org.apache.hadoop.hdds.scm.node.NodeManager; -import org.apache.hadoop.hdds.scm.pipelines.PipelineSelector; -import org.apache.hadoop.hdds.scm.server.SCMDatanodeHeartbeatDispatcher - .ContainerReportFromDatanode; -import org.apache.hadoop.hdds.server.events.Event; -import org.apache.hadoop.hdds.server.events.EventPublisher; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import static org.mockito.Matchers.anyLong; -import org.mockito.Mockito; -import static org.mockito.Mockito.when; -import org.mockito.stubbing.Answer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Test the behaviour of the ContainerReportHandler. - */ -public class TestContainerReportHandler implements EventPublisher { - - private List publishedEvents = new ArrayList<>(); - private final NodeManager nodeManager = new MockNodeManager(true, 1); - - private static final Logger LOG = - LoggerFactory.getLogger(TestContainerReportHandler.class); - - @Before - public void resetEventCollector() { - publishedEvents.clear(); - } - - @Test - public void test() throws IOException { - //GIVEN - OzoneConfiguration conf = new OzoneConfiguration(); - Mapping mapping = Mockito.mock(Mapping.class); - PipelineSelector selector = Mockito.mock(PipelineSelector.class); - - when(mapping.getContainer(anyLong())) - .thenAnswer( - (Answer) invocation -> - new Builder() - .setReplicationFactor(ReplicationFactor.THREE) - .setContainerID((Long) invocation.getArguments()[0]) - .setState(LifeCycleState.CLOSED) - .build() - ); - - ContainerStateManager containerStateManager = - new ContainerStateManager(conf, mapping, selector); - - when(mapping.getStateManager()).thenReturn(containerStateManager); - - ReplicationActivityStatus replicationActivityStatus = - new ReplicationActivityStatus(); - - ContainerReportHandler reportHandler = - new ContainerReportHandler(mapping, nodeManager, - replicationActivityStatus); - - DatanodeDetails dn1 = TestUtils.randomDatanodeDetails(); - DatanodeDetails dn2 = TestUtils.randomDatanodeDetails(); - DatanodeDetails dn3 = TestUtils.randomDatanodeDetails(); - DatanodeDetails dn4 = TestUtils.randomDatanodeDetails(); - nodeManager.addDatanodeInContainerMap(dn1.getUuid(), new HashSet<>()); - nodeManager.addDatanodeInContainerMap(dn2.getUuid(), new HashSet<>()); - nodeManager.addDatanodeInContainerMap(dn3.getUuid(), new HashSet<>()); - nodeManager.addDatanodeInContainerMap(dn4.getUuid(), new HashSet<>()); - PipelineSelector pipelineSelector = Mockito.mock(PipelineSelector.class); - - Pipeline pipeline = new Pipeline("leader", LifeCycleState.CLOSED, - ReplicationType.STAND_ALONE, ReplicationFactor.THREE, - PipelineID.randomId()); - - when(pipelineSelector.getReplicationPipeline(ReplicationType.STAND_ALONE, - ReplicationFactor.THREE)).thenReturn(pipeline); - - ContainerInfo cont1 = containerStateManager - .allocateContainer(pipelineSelector, ReplicationType.STAND_ALONE, - ReplicationFactor.THREE, "root").getContainerInfo(); - ContainerInfo cont2 = containerStateManager - .allocateContainer(pipelineSelector, ReplicationType.STAND_ALONE, - ReplicationFactor.THREE, "root").getContainerInfo(); - // Open Container - ContainerInfo cont3 = containerStateManager - .allocateContainer(pipelineSelector, ReplicationType.STAND_ALONE, - ReplicationFactor.THREE, "root").getContainerInfo(); - - long c1 = cont1.getContainerID(); - long c2 = cont2.getContainerID(); - long c3 = cont3.getContainerID(); - - // Close remaining containers - TestUtils.closeContainer(containerStateManager, cont1); - TestUtils.closeContainer(containerStateManager, cont2); - - //when - - //initial reports before replication is enabled. 2 containers w 3 replicas. - reportHandler.onMessage( - new ContainerReportFromDatanode(dn1, - createContainerReport(new long[] {c1, c2, c3})), this); - - reportHandler.onMessage( - new ContainerReportFromDatanode(dn2, - createContainerReport(new long[] {c1, c2, c3})), this); - - reportHandler.onMessage( - new ContainerReportFromDatanode(dn3, - createContainerReport(new long[] {c1, c2})), this); - - reportHandler.onMessage( - new ContainerReportFromDatanode(dn4, - createContainerReport(new long[] {})), this); - - Assert.assertEquals(0, publishedEvents.size()); - - replicationActivityStatus.enableReplication(); - - //no problem here - reportHandler.onMessage( - new ContainerReportFromDatanode(dn1, - createContainerReport(new long[] {c1, c2})), this); - - Assert.assertEquals(0, publishedEvents.size()); - - //container is missing from d2 - reportHandler.onMessage( - new ContainerReportFromDatanode(dn2, - createContainerReport(new long[] {c1})), this); - - Assert.assertEquals(1, publishedEvents.size()); - ReplicationRequest replicationRequest = - (ReplicationRequest) publishedEvents.get(0); - - Assert.assertEquals(c2, replicationRequest.getContainerId()); - Assert.assertEquals(3, replicationRequest.getExpecReplicationCount()); - Assert.assertEquals(2, replicationRequest.getReplicationCount()); - - //container was replicated to dn4 - reportHandler.onMessage( - new ContainerReportFromDatanode(dn4, - createContainerReport(new long[] {c2})), this); - - //no more event, everything is perfect - Assert.assertEquals(1, publishedEvents.size()); - - //c2 was found at dn2 (it was missing before, magic) - reportHandler.onMessage( - new ContainerReportFromDatanode(dn2, - createContainerReport(new long[] {c1, c2})), this); - - //c2 is over replicated (dn1,dn2,dn3,dn4) - Assert.assertEquals(2, publishedEvents.size()); - - replicationRequest = - (ReplicationRequest) publishedEvents.get(1); - - Assert.assertEquals(c2, replicationRequest.getContainerId()); - Assert.assertEquals(3, replicationRequest.getExpecReplicationCount()); - Assert.assertEquals(4, replicationRequest.getReplicationCount()); - - } - - private ContainerReportsProto createContainerReport(long[] containerIds) { - - ContainerReportsProto.Builder crBuilder = - ContainerReportsProto.newBuilder(); - - for (long containerId : containerIds) { - org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerInfo.Builder - ciBuilder = org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerInfo.newBuilder(); - ciBuilder.setFinalhash("e16cc9d6024365750ed8dbd194ea46d2") - .setSize(5368709120L) - .setUsed(2000000000L) - .setKeyCount(100000000L) - .setReadCount(100000000L) - .setWriteCount(100000000L) - .setReadBytes(2000000000L) - .setWriteBytes(2000000000L) - .setContainerID(containerId) - .setDeleteTransactionId(0); - - crBuilder.addReports(ciBuilder.build()); - } - - return crBuilder.build(); - } - - @Override - public > void fireEvent( - EVENT_TYPE event, PAYLOAD payload) { - LOG.info("Event is published: {}", payload); - publishedEvents.add(payload); - } -} \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/TestContainerStateManager.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/TestContainerStateManager.java deleted file mode 100644 index b857740a5fd..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/TestContainerStateManager.java +++ /dev/null @@ -1,98 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.hdds.scm.container; - -import java.io.IOException; - -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.scm.TestUtils; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo; -import org.apache.hadoop.hdds.scm.container.replication.ReplicationRequest; - -import org.apache.hadoop.hdds.scm.pipelines.PipelineSelector; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -/** - * Testing ContainerStatemanager. - */ -public class TestContainerStateManager { - - private ContainerStateManager containerStateManager; - - @Before - public void init() throws IOException { - OzoneConfiguration conf = new OzoneConfiguration(); - Mapping mapping = Mockito.mock(Mapping.class); - PipelineSelector selector = Mockito.mock(PipelineSelector.class); - containerStateManager = new ContainerStateManager(conf, mapping, selector); - - } - - @Test - public void checkReplicationStateOK() throws IOException { - //GIVEN - ContainerInfo c1 = TestUtils.allocateContainer(containerStateManager); - - DatanodeDetails d1 = TestUtils.randomDatanodeDetails(); - DatanodeDetails d2 = TestUtils.randomDatanodeDetails(); - DatanodeDetails d3 = TestUtils.randomDatanodeDetails(); - - addReplica(c1, d1); - addReplica(c1, d2); - addReplica(c1, d3); - - //WHEN - ReplicationRequest replicationRequest = containerStateManager - .checkReplicationState(new ContainerID(c1.getContainerID())); - - //THEN - Assert.assertNull(replicationRequest); - } - - @Test - public void checkReplicationStateMissingReplica() throws IOException { - //GIVEN - - ContainerInfo c1 = TestUtils.allocateContainer(containerStateManager); - - DatanodeDetails d1 = TestUtils.randomDatanodeDetails(); - DatanodeDetails d2 = TestUtils.randomDatanodeDetails(); - - addReplica(c1, d1); - addReplica(c1, d2); - - //WHEN - ReplicationRequest replicationRequest = containerStateManager - .checkReplicationState(new ContainerID(c1.getContainerID())); - - Assert - .assertEquals(c1.getContainerID(), replicationRequest.getContainerId()); - Assert.assertEquals(2, replicationRequest.getReplicationCount()); - Assert.assertEquals(3, replicationRequest.getExpecReplicationCount()); - } - - private void addReplica(ContainerInfo c1, DatanodeDetails d1) { - containerStateManager - .addContainerReplica(new ContainerID(c1.getContainerID()), d1); - } - -} \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/closer/package-info.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/closer/package-info.java deleted file mode 100644 index 2f35719816f..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/closer/package-info.java +++ /dev/null @@ -1,22 +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 - * - * 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. - * - */ -/** - * Make CheckStyle happy. - */ -package org.apache.hadoop.hdds.scm.container.closer; \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/package-info.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/package-info.java deleted file mode 100644 index f93aea66e7b..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/package-info.java +++ /dev/null @@ -1,22 +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 - * - * 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. - * - */ -/** - * Make CheckStyle Happy. - */ -package org.apache.hadoop.hdds.scm.container; \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/placement/algorithms/TestSCMContainerPlacementCapacity.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/placement/algorithms/TestSCMContainerPlacementCapacity.java deleted file mode 100644 index 764daff7758..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/placement/algorithms/TestSCMContainerPlacementCapacity.java +++ /dev/null @@ -1,106 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.scm.container.placement.algorithms; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState; -import org.apache.hadoop.hdds.scm.TestUtils; -import org.apache.hadoop.hdds.scm.container.placement.metrics.SCMNodeMetric; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.hdds.scm.node.NodeManager; - -import org.junit.Assert; -import org.junit.Test; -import static org.mockito.Matchers.anyObject; -import org.mockito.Mockito; -import static org.mockito.Mockito.when; - -public class TestSCMContainerPlacementCapacity { - @Test - public void chooseDatanodes() throws SCMException { - //given - Configuration conf = new OzoneConfiguration(); - - List datanodes = new ArrayList<>(); - for (int i = 0; i < 7; i++) { - datanodes.add(TestUtils.randomDatanodeDetails()); - } - - NodeManager mockNodeManager = Mockito.mock(NodeManager.class); - when(mockNodeManager.getNodes(NodeState.HEALTHY)) - .thenReturn(new ArrayList<>(datanodes)); - - when(mockNodeManager.getNodeStat(anyObject())) - .thenReturn(new SCMNodeMetric(100L, 0L, 100L)); - when(mockNodeManager.getNodeStat(datanodes.get(2))) - .thenReturn(new SCMNodeMetric(100L, 90L, 10L)); - when(mockNodeManager.getNodeStat(datanodes.get(3))) - .thenReturn(new SCMNodeMetric(100L, 80L, 20L)); - when(mockNodeManager.getNodeStat(datanodes.get(4))) - .thenReturn(new SCMNodeMetric(100L, 70L, 30L)); - - SCMContainerPlacementCapacity scmContainerPlacementRandom = - new SCMContainerPlacementCapacity(mockNodeManager, conf); - - List existingNodes = new ArrayList<>(); - existingNodes.add(datanodes.get(0)); - existingNodes.add(datanodes.get(1)); - - Map selectedCount = new HashMap<>(); - for (DatanodeDetails datanode : datanodes) { - selectedCount.put(datanode, 0); - } - - for (int i = 0; i < 1000; i++) { - - //when - List datanodeDetails = - scmContainerPlacementRandom.chooseDatanodes(existingNodes, 1, 15); - - //then - Assert.assertEquals(1, datanodeDetails.size()); - DatanodeDetails datanode0Details = datanodeDetails.get(0); - - Assert.assertNotEquals( - "Datanode 0 should not been selected: excluded by parameter", - datanodes.get(0), datanode0Details); - Assert.assertNotEquals( - "Datanode 1 should not been selected: excluded by parameter", - datanodes.get(1), datanode0Details); - Assert.assertNotEquals( - "Datanode 2 should not been selected: not enough space there", - datanodes.get(2), datanode0Details); - - selectedCount - .put(datanode0Details, selectedCount.get(datanode0Details) + 1); - - } - - //datanode 4 has less space. Should be selected less times. - Assert.assertTrue(selectedCount.get(datanodes.get(3)) > selectedCount - .get(datanodes.get(6))); - Assert.assertTrue(selectedCount.get(datanodes.get(4)) > selectedCount - .get(datanodes.get(6))); - } -} \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/placement/algorithms/TestSCMContainerPlacementRandom.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/placement/algorithms/TestSCMContainerPlacementRandom.java deleted file mode 100644 index b652b6b76b5..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/placement/algorithms/TestSCMContainerPlacementRandom.java +++ /dev/null @@ -1,86 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.scm.container.placement.algorithms; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState; -import org.apache.hadoop.hdds.scm.TestUtils; -import org.apache.hadoop.hdds.scm.container.placement.metrics.SCMNodeMetric; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.hdds.scm.node.NodeManager; - -import org.junit.Assert; -import org.junit.Test; -import static org.mockito.Matchers.anyObject; -import org.mockito.Mockito; -import static org.mockito.Mockito.when; - -public class TestSCMContainerPlacementRandom { - - @Test - public void chooseDatanodes() throws SCMException { - //given - Configuration conf = new OzoneConfiguration(); - - List datanodes = new ArrayList<>(); - for (int i = 0; i < 5; i++) { - datanodes.add(TestUtils.randomDatanodeDetails()); - } - - NodeManager mockNodeManager = Mockito.mock(NodeManager.class); - when(mockNodeManager.getNodes(NodeState.HEALTHY)) - .thenReturn(new ArrayList<>(datanodes)); - - when(mockNodeManager.getNodeStat(anyObject())) - .thenReturn(new SCMNodeMetric(100L, 0L, 100L)); - when(mockNodeManager.getNodeStat(datanodes.get(2))) - .thenReturn(new SCMNodeMetric(100L, 90L, 10L)); - - SCMContainerPlacementRandom scmContainerPlacementRandom = - new SCMContainerPlacementRandom(mockNodeManager, conf); - - List existingNodes = new ArrayList<>(); - existingNodes.add(datanodes.get(0)); - existingNodes.add(datanodes.get(1)); - - for (int i = 0; i < 100; i++) { - //when - List datanodeDetails = - scmContainerPlacementRandom.chooseDatanodes(existingNodes, 1, 15); - - //then - Assert.assertEquals(1, datanodeDetails.size()); - DatanodeDetails datanode0Details = datanodeDetails.get(0); - - Assert.assertNotEquals( - "Datanode 0 should not been selected: excluded by parameter", - datanodes.get(0), datanode0Details); - Assert.assertNotEquals( - "Datanode 1 should not been selected: excluded by parameter", - datanodes.get(1), datanode0Details); - Assert.assertNotEquals( - "Datanode 2 should not been selected: not enough space there", - datanodes.get(2), datanode0Details); - - } - } -} \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/replication/TestReplicationActivityStatus.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/replication/TestReplicationActivityStatus.java deleted file mode 100644 index a4615fc1a7b..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/replication/TestReplicationActivityStatus.java +++ /dev/null @@ -1,63 +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 - * - *      http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.container.replication; - -import static org.junit.Assert.*; - -import java.util.concurrent.TimeoutException; -import org.apache.hadoop.hdds.scm.events.SCMEvents; -import org.apache.hadoop.hdds.server.events.EventQueue; -import org.apache.hadoop.test.GenericTestUtils; -import org.junit.BeforeClass; -import org.junit.Test; - -/** - * Tests for ReplicationActivityStatus. - */ -public class TestReplicationActivityStatus { - - private static EventQueue eventQueue; - private static ReplicationActivityStatus replicationActivityStatus; - - @BeforeClass - public static void setup() { - eventQueue = new EventQueue(); - replicationActivityStatus = new ReplicationActivityStatus(); - eventQueue.addHandler(SCMEvents.START_REPLICATION, - replicationActivityStatus.getReplicationStatusListener()); - eventQueue.addHandler(SCMEvents.CHILL_MODE_STATUS, - replicationActivityStatus.getChillModeStatusListener()); - } - - @Test - public void testReplicationStatusForChillMode() - throws TimeoutException, InterruptedException { - assertFalse(replicationActivityStatus.isReplicationEnabled()); - // In chill mode replication process should be stopped. - eventQueue.fireEvent(SCMEvents.CHILL_MODE_STATUS, true); - assertFalse(replicationActivityStatus.isReplicationEnabled()); - - // Replication should be enabled when chill mode if off. - eventQueue.fireEvent(SCMEvents.CHILL_MODE_STATUS, false); - GenericTestUtils.waitFor(() -> { - return replicationActivityStatus.isReplicationEnabled(); - }, 10, 1000*5); - assertTrue(replicationActivityStatus.isReplicationEnabled()); - } -} \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/replication/TestReplicationManager.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/replication/TestReplicationManager.java deleted file mode 100644 index 06beb7c1742..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/replication/TestReplicationManager.java +++ /dev/null @@ -1,238 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.scm.container.replication; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Objects; - -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.LifeCycleState; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationFactor; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationType; -import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.ReplicateContainerCommandProto; -import org.apache.hadoop.hdds.scm.TestUtils; -import org.apache.hadoop.hdds.scm.container.ContainerID; -import org.apache.hadoop.hdds.scm.container.ContainerStateManager; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.scm.container.common.helpers.PipelineID; -import org.apache.hadoop.hdds.scm.container.placement.algorithms.ContainerPlacementPolicy; -import org.apache.hadoop.hdds.scm.container.replication.ReplicationManager.ReplicationRequestToRepeat; -import org.apache.hadoop.hdds.scm.events.SCMEvents; -import org.apache.hadoop.hdds.server.events.EventQueue; -import org.apache.hadoop.ozone.lease.LeaseManager; -import org.apache.hadoop.ozone.protocol.commands.CommandForDatanode; - -import com.google.common.base.Preconditions; -import static org.apache.hadoop.hdds.scm.events.SCMEvents.TRACK_REPLICATE_COMMAND; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import static org.mockito.Matchers.anyObject; -import org.mockito.Mockito; -import static org.mockito.Mockito.when; - -/** - * Test behaviour of the TestReplication. - */ -public class TestReplicationManager { - - private EventQueue queue; - - private List trackReplicationEvents; - - private List> copyEvents; - - private ContainerStateManager containerStateManager; - - private ContainerPlacementPolicy containerPlacementPolicy; - private List listOfDatanodeDetails; - private LeaseManager leaseManager; - private ReplicationManager replicationManager; - - @Before - public void initReplicationManager() throws IOException { - - listOfDatanodeDetails = new ArrayList<>(); - listOfDatanodeDetails.add(TestUtils.randomDatanodeDetails()); - listOfDatanodeDetails.add(TestUtils.randomDatanodeDetails()); - listOfDatanodeDetails.add(TestUtils.randomDatanodeDetails()); - listOfDatanodeDetails.add(TestUtils.randomDatanodeDetails()); - listOfDatanodeDetails.add(TestUtils.randomDatanodeDetails()); - - containerPlacementPolicy = - (excludedNodes, nodesRequired, sizeRequired) -> listOfDatanodeDetails - .subList(2, 2 + nodesRequired); - - containerStateManager = Mockito.mock(ContainerStateManager.class); - - ContainerInfo containerInfo = new ContainerInfo.Builder() - .setState(LifeCycleState.CLOSED) - .build(); - - when(containerStateManager.getContainer(anyObject())) - .thenReturn(containerInfo); - - when(containerStateManager.getContainerReplicas(new ContainerID(1L))) - .thenReturn(new HashSet<>(Arrays.asList( - listOfDatanodeDetails.get(0), - listOfDatanodeDetails.get(1) - ))); - - - when(containerStateManager.getContainerReplicas(new ContainerID(3L))) - .thenReturn(new HashSet<>()); - - queue = new EventQueue(); - - trackReplicationEvents = new ArrayList<>(); - queue.addHandler(TRACK_REPLICATE_COMMAND, - (event, publisher) -> trackReplicationEvents.add(event)); - - copyEvents = new ArrayList<>(); - queue.addHandler(SCMEvents.DATANODE_COMMAND, - (event, publisher) -> copyEvents.add(event)); - - leaseManager = new LeaseManager<>("Test", 100000L); - - replicationManager = new ReplicationManager(containerPlacementPolicy, - containerStateManager, queue, leaseManager); - - - - } - - /** - * Container should be replicated but no source replicas. - */ - @Test() - public void testNoExistingReplicas() throws InterruptedException { - try { - leaseManager.start(); - replicationManager.start(); - - //WHEN - queue.fireEvent(SCMEvents.REPLICATE_CONTAINER, - new ReplicationRequest(3L, (short) 2, System.currentTimeMillis(), - (short) 3)); - - Thread.sleep(500L); - queue.processAll(1000L); - - //THEN - Assert.assertEquals(0, trackReplicationEvents.size()); - Assert.assertEquals(0, copyEvents.size()); - - } finally { - if (leaseManager != null) { - leaseManager.shutdown(); - } - } - } - - @Test - public void testEventSending() throws InterruptedException, IOException { - - //GIVEN - try { - leaseManager.start(); - - replicationManager.start(); - - //WHEN - queue.fireEvent(SCMEvents.REPLICATE_CONTAINER, - new ReplicationRequest(1L, (short) 2, System.currentTimeMillis(), - (short) 3)); - - Thread.sleep(500L); - queue.processAll(1000L); - - //THEN - Assert.assertEquals(1, trackReplicationEvents.size()); - Assert.assertEquals(1, copyEvents.size()); - } finally { - if (leaseManager != null) { - leaseManager.shutdown(); - } - } - } - - @Test - public void testCommandWatcher() throws InterruptedException, IOException { - LeaseManager rapidLeaseManager = - new LeaseManager<>("Test", 1000L); - - replicationManager = new ReplicationManager(containerPlacementPolicy, - containerStateManager, queue, rapidLeaseManager); - - try { - rapidLeaseManager.start(); - replicationManager.start(); - - queue.fireEvent(SCMEvents.REPLICATE_CONTAINER, - new ReplicationRequest(1L, (short) 2, System.currentTimeMillis(), - (short) 3)); - - Thread.sleep(500L); - - queue.processAll(1000L); - - Assert.assertEquals(1, trackReplicationEvents.size()); - Assert.assertEquals(1, copyEvents.size()); - - Assert.assertEquals(trackReplicationEvents.get(0).getId(), - copyEvents.get(0).getCommand().getId()); - - //event is timed out - Thread.sleep(1500); - - queue.processAll(1000L); - - //original copy command + retry - Assert.assertEquals(2, trackReplicationEvents.size()); - Assert.assertEquals(2, copyEvents.size()); - - } finally { - if (rapidLeaseManager != null) { - rapidLeaseManager.shutdown(); - } - } - } - - public static Pipeline createPipeline(Iterable ids) - throws IOException { - Objects.requireNonNull(ids, "ids == null"); - final Iterator i = ids.iterator(); - Preconditions.checkArgument(i.hasNext()); - final DatanodeDetails leader = i.next(); - final Pipeline pipeline = - new Pipeline(leader.getUuidString(), LifeCycleState.OPEN, - ReplicationType.STAND_ALONE, ReplicationFactor.ONE, - PipelineID.randomId()); - pipeline.addMember(leader); - while (i.hasNext()) { - pipeline.addMember(i.next()); - } - return pipeline; - } - -} \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/replication/TestReplicationQueue.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/replication/TestReplicationQueue.java deleted file mode 100644 index 9dd4fe31c50..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/replication/TestReplicationQueue.java +++ /dev/null @@ -1,134 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.container.replication; - -import java.util.Random; -import java.util.UUID; -import org.apache.hadoop.util.Time; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -/** - * Test class for ReplicationQueue. - */ -public class TestReplicationQueue { - - private ReplicationQueue replicationQueue; - private Random random; - - @Before - public void setUp() { - replicationQueue = new ReplicationQueue(); - random = new Random(); - } - - @Test - public void testDuplicateAddOp() throws InterruptedException { - long contId = random.nextLong(); - String nodeId = UUID.randomUUID().toString(); - ReplicationRequest obj1, obj2, obj3; - long time = Time.monotonicNow(); - obj1 = new ReplicationRequest(contId, (short) 2, time, (short) 3); - obj2 = new ReplicationRequest(contId, (short) 2, time + 1, (short) 3); - obj3 = new ReplicationRequest(contId, (short) 1, time+2, (short) 3); - - replicationQueue.add(obj1); - replicationQueue.add(obj2); - replicationQueue.add(obj3); - Assert.assertEquals("Should add only 1 msg as second one is duplicate", - 1, replicationQueue.size()); - ReplicationRequest temp = replicationQueue.take(); - Assert.assertEquals(temp, obj3); - } - - @Test - public void testPollOp() throws InterruptedException { - long contId = random.nextLong(); - String nodeId = UUID.randomUUID().toString(); - ReplicationRequest msg1, msg2, msg3, msg4, msg5; - msg1 = new ReplicationRequest(contId, (short) 1, Time.monotonicNow(), - (short) 3); - long time = Time.monotonicNow(); - msg2 = new ReplicationRequest(contId + 1, (short) 4, time, (short) 3); - msg3 = new ReplicationRequest(contId + 2, (short) 0, time, (short) 3); - msg4 = new ReplicationRequest(contId, (short) 2, time, (short) 3); - // Replication message for same container but different nodeId - msg5 = new ReplicationRequest(contId + 1, (short) 2, time, (short) 3); - - replicationQueue.add(msg1); - replicationQueue.add(msg2); - replicationQueue.add(msg3); - replicationQueue.add(msg4); - replicationQueue.add(msg5); - Assert.assertEquals("Should have 3 objects", - 3, replicationQueue.size()); - - // Since Priority queue orders messages according to replication count, - // message with lowest replication should be first - ReplicationRequest temp; - temp = replicationQueue.take(); - Assert.assertEquals("Should have 2 objects", - 2, replicationQueue.size()); - Assert.assertEquals(temp, msg3); - - temp = replicationQueue.take(); - Assert.assertEquals("Should have 1 objects", - 1, replicationQueue.size()); - Assert.assertEquals(temp, msg5); - - // Message 2 should be ordered before message 5 as both have same - // replication number but message 2 has earlier timestamp. - temp = replicationQueue.take(); - Assert.assertEquals("Should have 0 objects", - replicationQueue.size(), 0); - Assert.assertEquals(temp, msg4); - } - - @Test - public void testRemoveOp() { - long contId = random.nextLong(); - String nodeId = UUID.randomUUID().toString(); - ReplicationRequest obj1, obj2, obj3; - obj1 = new ReplicationRequest(contId, (short) 1, Time.monotonicNow(), - (short) 3); - obj2 = new ReplicationRequest(contId + 1, (short) 2, Time.monotonicNow(), - (short) 3); - obj3 = new ReplicationRequest(contId + 2, (short) 3, Time.monotonicNow(), - (short) 3); - - replicationQueue.add(obj1); - replicationQueue.add(obj2); - replicationQueue.add(obj3); - Assert.assertEquals("Should have 3 objects", - 3, replicationQueue.size()); - - replicationQueue.remove(obj3); - Assert.assertEquals("Should have 2 objects", - 2, replicationQueue.size()); - - replicationQueue.remove(obj2); - Assert.assertEquals("Should have 1 objects", - 1, replicationQueue.size()); - - replicationQueue.remove(obj1); - Assert.assertEquals("Should have 0 objects", - 0, replicationQueue.size()); - } - -} diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/replication/package-info.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/replication/package-info.java deleted file mode 100644 index 1423c999381..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/replication/package-info.java +++ /dev/null @@ -1,23 +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 - * - * 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. - * - */ -/** - * SCM Testing and Mocking Utils. - */ -package org.apache.hadoop.hdds.scm.container.replication; -// Test classes for Replication functionality. \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/states/TestContainerAttribute.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/states/TestContainerAttribute.java deleted file mode 100644 index 63cc9bfd789..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/states/TestContainerAttribute.java +++ /dev/null @@ -1,143 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ - -package org.apache.hadoop.hdds.scm.container.states; - -import org.apache.hadoop.hdds.scm.container.ContainerID; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import java.util.Arrays; -import java.util.List; - -/** - * Test ContainerAttribute management. - */ -public class TestContainerAttribute { - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - @Test - public void testInsert() throws SCMException { - ContainerAttribute containerAttribute = new ContainerAttribute<>(); - ContainerID id = new ContainerID(42); - containerAttribute.insert(1, id); - Assert.assertEquals(1, - containerAttribute.getCollection(1).size()); - Assert.assertTrue(containerAttribute.getCollection(1).contains(id)); - - // Insert again and verify that it overwrites an existing value. - ContainerID newId = - new ContainerID(42); - containerAttribute.insert(1, newId); - Assert.assertEquals(1, - containerAttribute.getCollection(1).size()); - Assert.assertTrue(containerAttribute.getCollection(1).contains(newId)); - } - - @Test - public void testHasKey() throws SCMException { - ContainerAttribute containerAttribute = new ContainerAttribute<>(); - - for (int x = 1; x < 42; x++) { - containerAttribute.insert(1, new ContainerID(x)); - } - Assert.assertTrue(containerAttribute.hasKey(1)); - for (int x = 1; x < 42; x++) { - Assert.assertTrue(containerAttribute.hasContainerID(1, x)); - } - - Assert.assertFalse(containerAttribute.hasContainerID(1, - new ContainerID(42))); - } - - @Test - public void testClearSet() throws SCMException { - List keyslist = Arrays.asList("Key1", "Key2", "Key3"); - ContainerAttribute containerAttribute = new ContainerAttribute<>(); - for (String k : keyslist) { - for (int x = 1; x < 101; x++) { - containerAttribute.insert(k, new ContainerID(x)); - } - } - for (String k : keyslist) { - Assert.assertEquals(100, - containerAttribute.getCollection(k).size()); - } - containerAttribute.clearSet("Key1"); - Assert.assertEquals(0, - containerAttribute.getCollection("Key1").size()); - } - - @Test - public void testRemove() throws SCMException { - - List keyslist = Arrays.asList("Key1", "Key2", "Key3"); - ContainerAttribute containerAttribute = new ContainerAttribute<>(); - - for (String k : keyslist) { - for (int x = 1; x < 101; x++) { - containerAttribute.insert(k, new ContainerID(x)); - } - } - for (int x = 1; x < 101; x += 2) { - containerAttribute.remove("Key1", new ContainerID(x)); - } - - for (int x = 1; x < 101; x += 2) { - Assert.assertFalse(containerAttribute.hasContainerID("Key1", - new ContainerID(x))); - } - - Assert.assertEquals(100, - containerAttribute.getCollection("Key2").size()); - - Assert.assertEquals(100, - containerAttribute.getCollection("Key3").size()); - - Assert.assertEquals(50, - containerAttribute.getCollection("Key1").size()); - } - - @Test - public void tesUpdate() throws SCMException { - String key1 = "Key1"; - String key2 = "Key2"; - String key3 = "Key3"; - - ContainerAttribute containerAttribute = new ContainerAttribute<>(); - ContainerID id = new ContainerID(42); - - containerAttribute.insert(key1, id); - Assert.assertTrue(containerAttribute.hasContainerID(key1, id)); - Assert.assertFalse(containerAttribute.hasContainerID(key2, id)); - - // This should move the id from key1 bucket to key2 bucket. - containerAttribute.update(key1, key2, id); - Assert.assertFalse(containerAttribute.hasContainerID(key1, id)); - Assert.assertTrue(containerAttribute.hasContainerID(key2, id)); - - // This should fail since we cannot find this id in the key3 bucket. - thrown.expect(SCMException.class); - containerAttribute.update(key3, key1, id); - } -} \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/states/package-info.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/states/package-info.java deleted file mode 100644 index 795dfc1e1b9..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/states/package-info.java +++ /dev/null @@ -1,22 +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 - * - * 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. - * - */ -/** - * Make CheckStyle Happy. - */ -package org.apache.hadoop.hdds.scm.container.states; \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestContainerPlacement.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestContainerPlacement.java deleted file mode 100644 index 6f8534d9be2..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestContainerPlacement.java +++ /dev/null @@ -1,171 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.node; - -import org.apache.commons.io.IOUtils; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.FileUtil; -import org.apache.hadoop.hdds.scm.ScmConfigKeys; -import org.apache.hadoop.hdds.scm.TestUtils; -import org.apache.hadoop.hdds.scm.XceiverClientManager; -import org.apache.hadoop.hdds.scm.container.ContainerMapping; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerWithPipeline; -import org.apache.hadoop.hdds.scm.container.placement.algorithms - .ContainerPlacementPolicy; -import org.apache.hadoop.hdds.scm.container.placement.algorithms - .SCMContainerPlacementCapacity; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.scm.events.SCMEvents; -import org.apache.hadoop.hdds.server.events.EventQueue; -import org.apache.hadoop.ozone.OzoneConfigKeys; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.test.PathUtils; -import org.junit.Ignore; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.Mockito; - -import java.io.File; -import java.io.IOException; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.TimeoutException; - -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_DB_CACHE_SIZE_DEFAULT; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_DB_CACHE_SIZE_MB; -import static org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState - .HEALTHY; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -/** - * Test for different container placement policy. - */ -public class TestContainerPlacement { - @Rule - public ExpectedException thrown = ExpectedException.none(); - private static XceiverClientManager xceiverClientManager = - new XceiverClientManager(new OzoneConfiguration()); - - /** - * Returns a new copy of Configuration. - * - * @return Config - */ - OzoneConfiguration getConf() { - return new OzoneConfiguration(); - } - - /** - * Creates a NodeManager. - * - * @param config - Config for the node manager. - * @return SCNNodeManager - * @throws IOException - */ - - SCMNodeManager createNodeManager(OzoneConfiguration config) - throws IOException { - EventQueue eventQueue = new EventQueue(); - eventQueue.addHandler(SCMEvents.NEW_NODE, - Mockito.mock(NewNodeHandler.class)); - eventQueue.addHandler(SCMEvents.STALE_NODE, - Mockito.mock(StaleNodeHandler.class)); - eventQueue.addHandler(SCMEvents.DEAD_NODE, - Mockito.mock(DeadNodeHandler.class)); - SCMNodeManager nodeManager = new SCMNodeManager(config, - UUID.randomUUID().toString(), null, eventQueue); - assertFalse("Node manager should be in chill mode", - nodeManager.isOutOfChillMode()); - return nodeManager; - } - - ContainerMapping createContainerManager(Configuration config, - NodeManager scmNodeManager) throws IOException { - EventQueue eventQueue = new EventQueue(); - final int cacheSize = config.getInt(OZONE_SCM_DB_CACHE_SIZE_MB, - OZONE_SCM_DB_CACHE_SIZE_DEFAULT); - return new ContainerMapping(config, scmNodeManager, cacheSize, eventQueue); - - } - - /** - * Test capacity based container placement policy with node reports. - * - * @throws IOException - * @throws InterruptedException - * @throws TimeoutException - */ - @Test - @Ignore - public void testContainerPlacementCapacity() throws IOException, - InterruptedException, TimeoutException { - OzoneConfiguration conf = getConf(); - final int nodeCount = 4; - final long capacity = 10L * OzoneConsts.GB; - final long used = 2L * OzoneConsts.GB; - final long remaining = capacity - used; - - final File testDir = PathUtils.getTestDir( - TestContainerPlacement.class); - conf.set(OzoneConfigKeys.OZONE_METADATA_DIRS, - testDir.getAbsolutePath()); - conf.setClass(ScmConfigKeys.OZONE_SCM_CONTAINER_PLACEMENT_IMPL_KEY, - SCMContainerPlacementCapacity.class, ContainerPlacementPolicy.class); - - SCMNodeManager nodeManager = createNodeManager(conf); - ContainerMapping containerManager = - createContainerManager(conf, nodeManager); - List datanodes = - TestUtils.getListOfRegisteredDatanodeDetails(nodeManager, nodeCount); - try { - for (DatanodeDetails datanodeDetails : datanodes) { - nodeManager.processHeartbeat(datanodeDetails); - } - - //TODO: wait for heartbeat to be processed - Thread.sleep(4 * 1000); - assertEquals(nodeCount, nodeManager.getNodeCount(HEALTHY)); - assertEquals(capacity * nodeCount, - (long) nodeManager.getStats().getCapacity().get()); - assertEquals(used * nodeCount, - (long) nodeManager.getStats().getScmUsed().get()); - assertEquals(remaining * nodeCount, - (long) nodeManager.getStats().getRemaining().get()); - - assertTrue(nodeManager.isOutOfChillMode()); - - ContainerWithPipeline containerWithPipeline = containerManager - .allocateContainer( - xceiverClientManager.getType(), - xceiverClientManager.getFactor(), "OZONE"); - assertEquals(xceiverClientManager.getFactor().getNumber(), - containerWithPipeline.getPipeline().getMachines().size()); - } finally { - IOUtils.closeQuietly(containerManager); - IOUtils.closeQuietly(nodeManager); - FileUtil.fullyDelete(testDir); - } - } -} diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestDeadNodeHandler.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestDeadNodeHandler.java deleted file mode 100644 index 7bba032145d..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestDeadNodeHandler.java +++ /dev/null @@ -1,236 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.node; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.NodeReportProto; -import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.StorageReportProto; -import org.apache.hadoop.hdds.scm.TestUtils; -import org.apache.hadoop.hdds.scm.container.ContainerID; -import org.apache.hadoop.hdds.scm.container.ContainerStateManager; -import org.apache.hadoop.hdds.scm.container.Mapping; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo; -import org.apache.hadoop.hdds.scm.container.placement.metrics.SCMNodeMetric; -import org.apache.hadoop.hdds.scm.container.replication.ReplicationRequest; -import org.apache.hadoop.hdds.scm.events.SCMEvents; -import org.apache.hadoop.hdds.scm.container.placement.metrics.SCMNodeStat; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.hdds.scm.pipelines.PipelineSelector; -import org.apache.hadoop.hdds.scm.server.SCMDatanodeHeartbeatDispatcher.NodeReportFromDatanode; -import org.apache.hadoop.hdds.server.events.EventPublisher; - -import org.apache.hadoop.hdds.server.events.EventQueue; -import org.apache.hadoop.test.GenericTestUtils; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import static org.mockito.Matchers.eq; -import org.mockito.Mockito; - -/** - * Test DeadNodeHandler. - */ -public class TestDeadNodeHandler { - - private List sentEvents = new ArrayList<>(); - private SCMNodeManager nodeManager; - private ContainerStateManager containerStateManager; - private NodeReportHandler nodeReportHandler; - private DeadNodeHandler deadNodeHandler; - private EventPublisher publisher; - private EventQueue eventQueue; - - @Before - public void setup() throws IOException { - OzoneConfiguration conf = new OzoneConfiguration(); - containerStateManager = new ContainerStateManager(conf, - Mockito.mock(Mapping.class), - Mockito.mock(PipelineSelector.class)); - eventQueue = new EventQueue(); - nodeManager = new SCMNodeManager(conf, "cluster1", null, eventQueue); - deadNodeHandler = new DeadNodeHandler(nodeManager, - containerStateManager); - eventQueue.addHandler(SCMEvents.DEAD_NODE, deadNodeHandler); - publisher = Mockito.mock(EventPublisher.class); - nodeReportHandler = new NodeReportHandler(nodeManager); - } - - @Test - public void testOnMessage() throws IOException { - //GIVEN - DatanodeDetails datanode1 = TestUtils.randomDatanodeDetails(); - DatanodeDetails datanode2 = TestUtils.randomDatanodeDetails(); - - ContainerInfo container1 = - TestUtils.allocateContainer(containerStateManager); - ContainerInfo container2 = - TestUtils.allocateContainer(containerStateManager); - ContainerInfo container3 = - TestUtils.allocateContainer(containerStateManager); - - registerReplicas(datanode1, container1, container2); - registerReplicas(datanode2, container1, container3); - - registerReplicas(containerStateManager, container1, datanode1, datanode2); - registerReplicas(containerStateManager, container2, datanode1); - registerReplicas(containerStateManager, container3, datanode2); - - TestUtils.closeContainer(containerStateManager, container1); - - deadNodeHandler.onMessage(datanode1, publisher); - - Set container1Replicas = - containerStateManager.getContainerStateMap() - .getContainerReplicas(new ContainerID(container1.getContainerID())); - Assert.assertEquals(1, container1Replicas.size()); - Assert.assertEquals(datanode2, container1Replicas.iterator().next()); - - Set container2Replicas = - containerStateManager.getContainerStateMap() - .getContainerReplicas(new ContainerID(container2.getContainerID())); - Assert.assertEquals(0, container2Replicas.size()); - - Set container3Replicas = - containerStateManager.getContainerStateMap() - .getContainerReplicas(new ContainerID(container3.getContainerID())); - Assert.assertEquals(1, container3Replicas.size()); - Assert.assertEquals(datanode2, container3Replicas.iterator().next()); - - ArgumentCaptor replicationRequestParameter = - ArgumentCaptor.forClass(ReplicationRequest.class); - - Mockito.verify(publisher) - .fireEvent(eq(SCMEvents.REPLICATE_CONTAINER), - replicationRequestParameter.capture()); - - Assert - .assertEquals(container1.getContainerID(), - replicationRequestParameter.getValue().getContainerId()); - Assert - .assertEquals(1, - replicationRequestParameter.getValue().getReplicationCount()); - Assert - .assertEquals(3, - replicationRequestParameter.getValue().getExpecReplicationCount()); - } - - @Test - public void testStatisticsUpdate() throws Exception { - //GIVEN - DatanodeDetails datanode1 = TestUtils.randomDatanodeDetails(); - DatanodeDetails datanode2 = TestUtils.randomDatanodeDetails(); - String storagePath1 = GenericTestUtils.getRandomizedTempPath() - .concat("/" + datanode1.getUuidString()); - String storagePath2 = GenericTestUtils.getRandomizedTempPath() - .concat("/" + datanode2.getUuidString()); - - StorageReportProto storageOne = TestUtils.createStorageReport( - datanode1.getUuid(), storagePath1, 100, 10, 90, null); - StorageReportProto storageTwo = TestUtils.createStorageReport( - datanode2.getUuid(), storagePath2, 200, 20, 180, null); - nodeReportHandler.onMessage(getNodeReport(datanode1, storageOne), - Mockito.mock(EventPublisher.class)); - nodeReportHandler.onMessage(getNodeReport(datanode2, storageTwo), - Mockito.mock(EventPublisher.class)); - - ContainerInfo container1 = - TestUtils.allocateContainer(containerStateManager); - registerReplicas(datanode1, container1); - - SCMNodeStat stat = nodeManager.getStats(); - Assert.assertTrue(stat.getCapacity().get() == 300); - Assert.assertTrue(stat.getRemaining().get() == 270); - Assert.assertTrue(stat.getScmUsed().get() == 30); - - SCMNodeMetric nodeStat = nodeManager.getNodeStat(datanode1); - Assert.assertTrue(nodeStat.get().getCapacity().get() == 100); - Assert.assertTrue(nodeStat.get().getRemaining().get() == 90); - Assert.assertTrue(nodeStat.get().getScmUsed().get() == 10); - - //WHEN datanode1 is dead. - eventQueue.fireEvent(SCMEvents.DEAD_NODE, datanode1); - Thread.sleep(100); - - //THEN statistics in SCM should changed. - stat = nodeManager.getStats(); - Assert.assertTrue(stat.getCapacity().get() == 200); - Assert.assertTrue(stat.getRemaining().get() == 180); - Assert.assertTrue(stat.getScmUsed().get() == 20); - - nodeStat = nodeManager.getNodeStat(datanode1); - Assert.assertTrue(nodeStat.get().getCapacity().get() == 0); - Assert.assertTrue(nodeStat.get().getRemaining().get() == 0); - Assert.assertTrue(nodeStat.get().getScmUsed().get() == 0); - } - - @Test - public void testOnMessageReplicaFailure() throws Exception { - DatanodeDetails dn1 = TestUtils.randomDatanodeDetails(); - GenericTestUtils.LogCapturer logCapturer = GenericTestUtils.LogCapturer - .captureLogs(DeadNodeHandler.getLogger()); - String storagePath1 = GenericTestUtils.getRandomizedTempPath() - .concat("/" + dn1.getUuidString()); - - StorageReportProto storageOne = TestUtils.createStorageReport( - dn1.getUuid(), storagePath1, 100, 10, 90, null); - nodeReportHandler.onMessage(getNodeReport(dn1, storageOne), - Mockito.mock(EventPublisher.class)); - - ContainerInfo container1 = - TestUtils.allocateContainer(containerStateManager); - registerReplicas(dn1, container1); - - deadNodeHandler.onMessage(dn1, eventQueue); - Assert.assertTrue(logCapturer.getOutput().contains( - "DataNode " + dn1.getUuid() + " doesn't have replica for container " - + container1.getContainerID())); - } - - private void registerReplicas(ContainerStateManager csm, - ContainerInfo container, DatanodeDetails... datanodes) { - csm.getContainerStateMap() - .addContainerReplica(new ContainerID(container.getContainerID()), - datanodes); - } - - private void registerReplicas(DatanodeDetails datanode, - ContainerInfo... containers) - throws SCMException { - nodeManager - .addDatanodeInContainerMap(datanode.getUuid(), - Arrays.stream(containers) - .map(container -> new ContainerID(container.getContainerID())) - .collect(Collectors.toSet())); - } - - private NodeReportFromDatanode getNodeReport(DatanodeDetails dn, - StorageReportProto... reports) { - NodeReportProto nodeReportProto = TestUtils.createNodeReport(reports); - return new NodeReportFromDatanode(dn, nodeReportProto); - } -} diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestNodeManager.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestNodeManager.java deleted file mode 100644 index cbe96eee843..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestNodeManager.java +++ /dev/null @@ -1,1144 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.node; - -import com.google.common.base.Supplier; -import org.apache.hadoop.fs.FileUtil; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationType; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMCommandProto; -import org.apache.hadoop.hdds.scm.ScmConfigKeys; -import org.apache.hadoop.hdds.scm.TestUtils; -import org.apache.hadoop.hdds.scm.container.common.helpers.PipelineID; -import org.apache.hadoop.hdds.scm.container.placement.metrics.SCMNodeStat; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.StorageReportProto; -import org.apache.hadoop.hdds.scm.events.SCMEvents; -import org.apache.hadoop.hdds.server.events.EventQueue; -import org.apache.hadoop.ozone.OzoneConfigKeys; -import org.apache.hadoop.ozone.protocol.commands.CloseContainerCommand; -import org.apache.hadoop.ozone.protocol.commands.CommandForDatanode; -import org.apache.hadoop.ozone.protocol.commands.SCMCommand; -import org.apache.hadoop.test.GenericTestUtils; -import org.apache.hadoop.test.PathUtils; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Ignore; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.Mockito; - -import java.io.File; -import java.io.IOException; -import java.util.LinkedList; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_HEARTBEAT_INTERVAL; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_DEADNODE_INTERVAL; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_HEARTBEAT_PROCESS_INTERVAL; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_STALENODE_INTERVAL; -import static org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState.DEAD; -import static org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState - .HEALTHY; -import static org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState.STALE; -import static org.apache.hadoop.hdds.scm.events.SCMEvents.DATANODE_COMMAND; -import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.core.StringStartsWith.startsWith; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -/** - * Test the Node Manager class. - */ -public class TestNodeManager { - - private File testDir; - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - @BeforeClass - public static void init() throws IOException { - } - - @Before - public void setup() { - testDir = PathUtils.getTestDir( - TestNodeManager.class); - } - - @After - public void cleanup() { - FileUtil.fullyDelete(testDir); - } - - /** - * Returns a new copy of Configuration. - * - * @return Config - */ - OzoneConfiguration getConf() { - OzoneConfiguration conf = new OzoneConfiguration(); - conf.set(OzoneConfigKeys.OZONE_METADATA_DIRS, - testDir.getAbsolutePath()); - conf.setTimeDuration(OZONE_SCM_HEARTBEAT_PROCESS_INTERVAL, 100, - TimeUnit.MILLISECONDS); - return conf; - } - - /** - * Creates a NodeManager. - * - * @param config - Config for the node manager. - * @return SCNNodeManager - * @throws IOException - */ - - SCMNodeManager createNodeManager(OzoneConfiguration config) - throws IOException { - EventQueue eventQueue = new EventQueue(); - eventQueue.addHandler(SCMEvents.NEW_NODE, - Mockito.mock(NewNodeHandler.class)); - eventQueue.addHandler(SCMEvents.STALE_NODE, - Mockito.mock(StaleNodeHandler.class)); - eventQueue.addHandler(SCMEvents.DEAD_NODE, - Mockito.mock(DeadNodeHandler.class)); - SCMNodeManager nodeManager = new SCMNodeManager(config, - UUID.randomUUID().toString(), null, eventQueue); - assertFalse("Node manager should be in chill mode", - nodeManager.isOutOfChillMode()); - return nodeManager; - } - - /** - * Tests that Node manager handles heartbeats correctly, and comes out of - * chill Mode. - * - * @throws IOException - * @throws InterruptedException - * @throws TimeoutException - */ - @Test - public void testScmHeartbeat() throws IOException, - InterruptedException, TimeoutException { - - try (SCMNodeManager nodeManager = createNodeManager(getConf())) { - // Send some heartbeats from different nodes. - for (int x = 0; x < nodeManager.getMinimumChillModeNodes(); x++) { - DatanodeDetails datanodeDetails = TestUtils - .createRandomDatanodeAndRegister(nodeManager); - nodeManager.processHeartbeat(datanodeDetails); - } - - //TODO: wait for heartbeat to be processed - Thread.sleep(4 * 1000); - assertTrue("Heartbeat thread should have picked up the" + - "scheduled heartbeats and transitioned out of chill mode.", - nodeManager.isOutOfChillMode()); - } - } - - /** - * asserts that if we send no heartbeats node manager stays in chillmode. - * - * @throws IOException - * @throws InterruptedException - * @throws TimeoutException - */ - @Test - public void testScmNoHeartbeats() throws IOException, - InterruptedException, TimeoutException { - - try (SCMNodeManager nodeManager = createNodeManager(getConf())) { - //TODO: wait for heartbeat to be processed - Thread.sleep(4 * 1000); - assertFalse("No heartbeats, Node manager should have been in" + - " chill mode.", nodeManager.isOutOfChillMode()); - } - } - - /** - * Asserts that if we don't get enough unique nodes we stay in chillmode. - * - * @throws IOException - * @throws InterruptedException - * @throws TimeoutException - */ - @Test - public void testScmNotEnoughHeartbeats() throws IOException, - InterruptedException, TimeoutException { - try (SCMNodeManager nodeManager = createNodeManager(getConf())) { - - // Need 100 nodes to come out of chill mode, only one node is sending HB. - nodeManager.setMinimumChillModeNodes(100); - nodeManager.processHeartbeat(TestUtils - .createRandomDatanodeAndRegister(nodeManager)); - //TODO: wait for heartbeat to be processed - Thread.sleep(4 * 1000); - assertFalse("Not enough heartbeat, Node manager should have" + - "been in chillmode.", nodeManager.isOutOfChillMode()); - } - } - - /** - * Asserts that many heartbeat from the same node is counted as a single - * node. - * - * @throws IOException - * @throws InterruptedException - * @throws TimeoutException - */ - @Test - public void testScmSameNodeHeartbeats() throws IOException, - InterruptedException, TimeoutException { - - try (SCMNodeManager nodeManager = createNodeManager(getConf())) { - nodeManager.setMinimumChillModeNodes(3); - DatanodeDetails datanodeDetails = TestUtils - .createRandomDatanodeAndRegister(nodeManager); - - // Send 10 heartbeat from same node, and assert we never leave chill mode. - for (int x = 0; x < 10; x++) { - nodeManager.processHeartbeat(datanodeDetails); - } - - //TODO: wait for heartbeat to be processed - Thread.sleep(4 * 1000); - assertFalse("Not enough nodes have send heartbeat to node" + - "manager.", nodeManager.isOutOfChillMode()); - } - } - - /** - * Asserts that adding heartbeats after shutdown does not work. This implies - * that heartbeat thread has been shutdown safely by closing the node - * manager. - * - * @throws IOException - * @throws InterruptedException - * @throws TimeoutException - */ - @Test - public void testScmShutdown() throws IOException, InterruptedException, - TimeoutException { - OzoneConfiguration conf = getConf(); - conf.getTimeDuration(ScmConfigKeys.OZONE_SCM_HEARTBEAT_PROCESS_INTERVAL, - 100, TimeUnit.MILLISECONDS); - SCMNodeManager nodeManager = createNodeManager(conf); - DatanodeDetails datanodeDetails = TestUtils - .createRandomDatanodeAndRegister(nodeManager); - nodeManager.close(); - - // These should never be processed. - nodeManager.processHeartbeat(datanodeDetails); - - // Let us just wait for 2 seconds to prove that HBs are not processed. - Thread.sleep(2 * 1000); - - //TODO: add assertion - } - - /** - * Asserts scm informs datanodes to re-register with the nodemanager - * on a restart. - * - * @throws Exception - */ - @Test - public void testScmHeartbeatAfterRestart() throws Exception { - OzoneConfiguration conf = getConf(); - conf.getTimeDuration(ScmConfigKeys.OZONE_SCM_HEARTBEAT_PROCESS_INTERVAL, - 100, TimeUnit.MILLISECONDS); - DatanodeDetails datanodeDetails = TestUtils.randomDatanodeDetails(); - UUID dnId = datanodeDetails.getUuid(); - String storagePath = testDir.getAbsolutePath() + "/" + dnId; - StorageReportProto report = - TestUtils.createStorageReport(dnId, storagePath, 100, 10, 90, null); - try (SCMNodeManager nodemanager = createNodeManager(conf)) { - nodemanager.register(datanodeDetails, - TestUtils.createNodeReport(report), - TestUtils.getRandomPipelineReports()); - List command = nodemanager.processHeartbeat(datanodeDetails); - Assert.assertTrue(nodemanager.getAllNodes().contains(datanodeDetails)); - Assert.assertTrue("On regular HB calls, SCM responses a " - + "datanode with an empty command list", command.isEmpty()); - } - - // Sends heartbeat without registering to SCM. - // This happens when SCM restarts. - try (SCMNodeManager nodemanager = createNodeManager(conf)) { - Assert.assertFalse(nodemanager - .getAllNodes().contains(datanodeDetails)); - try { - // SCM handles heartbeat asynchronously. - // It may need more than one heartbeat processing to - // send the notification. - GenericTestUtils.waitFor(new Supplier() { - @Override public Boolean get() { - List command = - nodemanager.processHeartbeat(datanodeDetails); - return command.size() == 1 && command.get(0).getType() - .equals(SCMCommandProto.Type.reregisterCommand); - } - }, 100, 3 * 1000); - } catch (TimeoutException e) { - Assert.fail("Times out to verify that scm informs " - + "datanode to re-register itself."); - } - } - } - - /** - * Asserts that we detect as many healthy nodes as we have generated heartbeat - * for. - * - * @throws IOException - * @throws InterruptedException - * @throws TimeoutException - */ - @Test - public void testScmHealthyNodeCount() throws IOException, - InterruptedException, TimeoutException { - OzoneConfiguration conf = getConf(); - final int count = 10; - - try (SCMNodeManager nodeManager = createNodeManager(conf)) { - - for (int x = 0; x < count; x++) { - DatanodeDetails datanodeDetails = TestUtils - .createRandomDatanodeAndRegister(nodeManager); - nodeManager.processHeartbeat(datanodeDetails); - } - //TODO: wait for heartbeat to be processed - Thread.sleep(4 * 1000); - assertEquals(count, nodeManager.getNodeCount(HEALTHY)); - } - } - - /** - * Asserts that if user provides a value less than 5 times the heartbeat - * interval as the StaleNode Value, we throw since that is a QoS that we - * cannot maintain. - * - * @throws IOException - * @throws InterruptedException - * @throws TimeoutException - */ - - @Test - public void testScmSanityOfUserConfig1() throws IOException, - InterruptedException, TimeoutException { - OzoneConfiguration conf = getConf(); - final int interval = 100; - conf.setTimeDuration(OZONE_SCM_HEARTBEAT_PROCESS_INTERVAL, interval, - MILLISECONDS); - conf.setTimeDuration(HDDS_HEARTBEAT_INTERVAL, 1, SECONDS); - - // This should be 5 times more than OZONE_SCM_HEARTBEAT_PROCESS_INTERVAL - // and 3 times more than OZONE_SCM_HEARTBEAT_INTERVAL - conf.setTimeDuration(OZONE_SCM_STALENODE_INTERVAL, interval, MILLISECONDS); - - thrown.expect(IllegalArgumentException.class); - - // This string is a multiple of the interval value - thrown.expectMessage( - startsWith("100 is not within min = 500 or max = 100000")); - createNodeManager(conf); - } - - /** - * Asserts that if Stale Interval value is more than 5 times the value of HB - * processing thread it is a sane value. - * - * @throws IOException - * @throws InterruptedException - * @throws TimeoutException - */ - @Test - public void testScmSanityOfUserConfig2() throws IOException, - InterruptedException, TimeoutException { - OzoneConfiguration conf = getConf(); - final int interval = 100; - conf.setTimeDuration(OZONE_SCM_HEARTBEAT_PROCESS_INTERVAL, interval, - TimeUnit.MILLISECONDS); - conf.setTimeDuration(HDDS_HEARTBEAT_INTERVAL, 1, TimeUnit.SECONDS); - - // This should be 5 times more than OZONE_SCM_HEARTBEAT_PROCESS_INTERVAL - // and 3 times more than OZONE_SCM_HEARTBEAT_INTERVAL - conf.setTimeDuration(OZONE_SCM_STALENODE_INTERVAL, 3 * 1000, MILLISECONDS); - createNodeManager(conf).close(); - } - - /** - * Asserts that a single node moves from Healthy to stale node, then from - * stale node to dead node if it misses enough heartbeats. - * - * @throws IOException - * @throws InterruptedException - * @throws TimeoutException - */ - @Test - public void testScmDetectStaleAndDeadNode() throws IOException, - InterruptedException, TimeoutException { - final int interval = 100; - final int nodeCount = 10; - - OzoneConfiguration conf = getConf(); - conf.setTimeDuration(OZONE_SCM_HEARTBEAT_PROCESS_INTERVAL, interval, - MILLISECONDS); - conf.setTimeDuration(HDDS_HEARTBEAT_INTERVAL, 1, SECONDS); - conf.setTimeDuration(OZONE_SCM_STALENODE_INTERVAL, 3, SECONDS); - conf.setTimeDuration(OZONE_SCM_DEADNODE_INTERVAL, 6, SECONDS); - - - try (SCMNodeManager nodeManager = createNodeManager(conf)) { - List nodeList = createNodeSet(nodeManager, nodeCount); - - - DatanodeDetails staleNode = TestUtils.createRandomDatanodeAndRegister( - nodeManager); - - // Heartbeat once - nodeManager.processHeartbeat(staleNode); - - // Heartbeat all other nodes. - for (DatanodeDetails dn : nodeList) { - nodeManager.processHeartbeat(dn); - } - - // Wait for 2 seconds .. and heartbeat good nodes again. - Thread.sleep(2 * 1000); - - for (DatanodeDetails dn : nodeList) { - nodeManager.processHeartbeat(dn); - } - - // Wait for 2 seconds, wait a total of 4 seconds to make sure that the - // node moves into stale state. - Thread.sleep(2 * 1000); - List staleNodeList = nodeManager.getNodes(STALE); - assertEquals("Expected to find 1 stale node", - 1, nodeManager.getNodeCount(STALE)); - assertEquals("Expected to find 1 stale node", - 1, staleNodeList.size()); - assertEquals("Stale node is not the expected ID", staleNode - .getUuid(), staleNodeList.get(0).getUuid()); - Thread.sleep(1000); - - // heartbeat good nodes again. - for (DatanodeDetails dn : nodeList) { - nodeManager.processHeartbeat(dn); - } - - // 6 seconds is the dead window for this test , so we wait a total of - // 7 seconds to make sure that the node moves into dead state. - Thread.sleep(2 * 1000); - - // the stale node has been removed - staleNodeList = nodeManager.getNodes(STALE); - assertEquals("Expected to find 1 stale node", - 0, nodeManager.getNodeCount(STALE)); - assertEquals("Expected to find 1 stale node", - 0, staleNodeList.size()); - - // Check for the dead node now. - List deadNodeList = nodeManager.getNodes(DEAD); - assertEquals("Expected to find 1 dead node", 1, - nodeManager.getNodeCount(DEAD)); - assertEquals("Expected to find 1 dead node", - 1, deadNodeList.size()); - assertEquals("Dead node is not the expected ID", staleNode - .getUuid(), deadNodeList.get(0).getUuid()); - } - } - - /** - * Check for NPE when datanodeDetails is passed null for sendHeartbeat. - * - * @throws IOException - * @throws InterruptedException - * @throws TimeoutException - */ - @Test - public void testScmCheckForErrorOnNullDatanodeDetails() throws IOException, - InterruptedException, TimeoutException { - try (SCMNodeManager nodeManager = createNodeManager(getConf())) { - nodeManager.processHeartbeat(null); - } catch (NullPointerException npe) { - GenericTestUtils.assertExceptionContains("Heartbeat is missing " + - "DatanodeDetails.", npe); - } - } - - /** - * Asserts that a dead node, stale node and healthy nodes co-exist. The counts - * , lists and node ID match the expected node state. - *

- * This test is pretty complicated because it explores all states of Node - * manager in a single test. Please read thru the comments to get an idea of - * the current state of the node Manager. - *

- * This test is written like a state machine to avoid threads and concurrency - * issues. This test is replicated below with the use of threads. Avoiding - * threads make it easy to debug the state machine. - * - * @throws IOException - * @throws InterruptedException - * @throws TimeoutException - */ - /** - * These values are very important. Here is what it means so you don't - * have to look it up while reading this code. - * - * OZONE_SCM_HEARTBEAT_PROCESS_INTERVAL - This the frequency of the - * HB processing thread that is running in the SCM. This thread must run - * for the SCM to process the Heartbeats. - * - * OZONE_SCM_HEARTBEAT_INTERVAL - This is the frequency at which - * datanodes will send heartbeats to SCM. Please note: This is the only - * config value for node manager that is specified in seconds. We don't - * want SCM heartbeat resolution to be more than in seconds. - * In this test it is not used, but we are forced to set it because we - * have validation code that checks Stale Node interval and Dead Node - * interval is larger than the value of - * OZONE_SCM_HEARTBEAT_INTERVAL. - * - * OZONE_SCM_STALENODE_INTERVAL - This is the time that must elapse - * from the last heartbeat for us to mark a node as stale. In this test - * we set that to 3. That is if a node has not heartbeat SCM for last 3 - * seconds we will mark it as stale. - * - * OZONE_SCM_DEADNODE_INTERVAL - This is the time that must elapse - * from the last heartbeat for a node to be marked dead. We have an - * additional constraint that this must be at least 2 times bigger than - * Stale node Interval. - * - * With these we are trying to explore the state of this cluster with - * various timeouts. Each section is commented so that you can keep - * track of the state of the cluster nodes. - * - */ - - @Test - public void testScmClusterIsInExpectedState1() throws IOException, - InterruptedException, TimeoutException { - OzoneConfiguration conf = getConf(); - conf.setTimeDuration(OZONE_SCM_HEARTBEAT_PROCESS_INTERVAL, 100, - MILLISECONDS); - conf.setTimeDuration(HDDS_HEARTBEAT_INTERVAL, 1, SECONDS); - conf.setTimeDuration(OZONE_SCM_STALENODE_INTERVAL, 3, SECONDS); - conf.setTimeDuration(OZONE_SCM_DEADNODE_INTERVAL, 6, SECONDS); - - - /** - * Cluster state: Healthy: All nodes are heartbeat-ing like normal. - */ - try (SCMNodeManager nodeManager = createNodeManager(conf)) { - DatanodeDetails healthyNode = - TestUtils.createRandomDatanodeAndRegister(nodeManager); - DatanodeDetails staleNode = - TestUtils.createRandomDatanodeAndRegister(nodeManager); - DatanodeDetails deadNode = - TestUtils.createRandomDatanodeAndRegister(nodeManager); - nodeManager.processHeartbeat(healthyNode); - nodeManager.processHeartbeat(staleNode); - nodeManager.processHeartbeat(deadNode); - - // Sleep so that heartbeat processing thread gets to run. - Thread.sleep(500); - - //Assert all nodes are healthy. - assertEquals(3, nodeManager.getAllNodes().size()); - assertEquals(3, nodeManager.getNodeCount(HEALTHY)); - - /** - * Cluster state: Quiesced: We are going to sleep for 3 seconds. Which - * means that no node is heartbeating. All nodes should move to Stale. - */ - Thread.sleep(3 * 1000); - assertEquals(3, nodeManager.getAllNodes().size()); - assertEquals(3, nodeManager.getNodeCount(STALE)); - - - /** - * Cluster State : Move healthy node back to healthy state, move other 2 - * nodes to Stale State. - * - * We heartbeat healthy node after 1 second and let other 2 nodes elapse - * the 3 second windows. - */ - - nodeManager.processHeartbeat(healthyNode); - nodeManager.processHeartbeat(staleNode); - nodeManager.processHeartbeat(deadNode); - - Thread.sleep(1500); - nodeManager.processHeartbeat(healthyNode); - Thread.sleep(2 * 1000); - assertEquals(1, nodeManager.getNodeCount(HEALTHY)); - - - // 3.5 seconds from last heartbeat for the stale and deadNode. So those - // 2 nodes must move to Stale state and the healthy node must - // remain in the healthy State. - List healthyList = nodeManager.getNodes(HEALTHY); - assertEquals("Expected one healthy node", 1, healthyList.size()); - assertEquals("Healthy node is not the expected ID", healthyNode - .getUuid(), healthyList.get(0).getUuid()); - - assertEquals(2, nodeManager.getNodeCount(STALE)); - - /** - * Cluster State: Allow healthyNode to remain in healthy state and - * staleNode to move to stale state and deadNode to move to dead state. - */ - - nodeManager.processHeartbeat(healthyNode); - nodeManager.processHeartbeat(staleNode); - Thread.sleep(1500); - nodeManager.processHeartbeat(healthyNode); - Thread.sleep(2 * 1000); - - // 3.5 seconds have elapsed for stale node, so it moves into Stale. - // 7 seconds have elapsed for dead node, so it moves into dead. - // 2 Seconds have elapsed for healthy node, so it stays in healhty state. - healthyList = nodeManager.getNodes(HEALTHY); - List staleList = nodeManager.getNodes(STALE); - List deadList = nodeManager.getNodes(DEAD); - - assertEquals(3, nodeManager.getAllNodes().size()); - assertEquals(1, nodeManager.getNodeCount(HEALTHY)); - assertEquals(1, nodeManager.getNodeCount(STALE)); - assertEquals(1, nodeManager.getNodeCount(DEAD)); - - assertEquals("Expected one healthy node", - 1, healthyList.size()); - assertEquals("Healthy node is not the expected ID", healthyNode - .getUuid(), healthyList.get(0).getUuid()); - - assertEquals("Expected one stale node", - 1, staleList.size()); - assertEquals("Stale node is not the expected ID", staleNode - .getUuid(), staleList.get(0).getUuid()); - - assertEquals("Expected one dead node", - 1, deadList.size()); - assertEquals("Dead node is not the expected ID", deadNode - .getUuid(), deadList.get(0).getUuid()); - /** - * Cluster State : let us heartbeat all the nodes and verify that we get - * back all the nodes in healthy state. - */ - nodeManager.processHeartbeat(healthyNode); - nodeManager.processHeartbeat(staleNode); - nodeManager.processHeartbeat(deadNode); - Thread.sleep(500); - //Assert all nodes are healthy. - assertEquals(3, nodeManager.getAllNodes().size()); - assertEquals(3, nodeManager.getNodeCount(HEALTHY)); - } - } - - /** - * Heartbeat a given set of nodes at a specified frequency. - * - * @param manager - Node Manager - * @param list - List of datanodeIDs - * @param sleepDuration - Duration to sleep between heartbeats. - * @throws InterruptedException - */ - private void heartbeatNodeSet(SCMNodeManager manager, - List list, - int sleepDuration) throws InterruptedException { - while (!Thread.currentThread().isInterrupted()) { - for (DatanodeDetails dn : list) { - manager.processHeartbeat(dn); - } - Thread.sleep(sleepDuration); - } - } - - /** - * Create a set of Nodes with a given prefix. - * - * @param count - number of nodes. - * @return List of Nodes. - */ - private List createNodeSet(SCMNodeManager nodeManager, int - count) { - List list = new LinkedList<>(); - for (int x = 0; x < count; x++) { - DatanodeDetails datanodeDetails = TestUtils - .createRandomDatanodeAndRegister(nodeManager); - list.add(datanodeDetails); - } - return list; - } - - /** - * Function that tells us if we found the right number of stale nodes. - * - * @param nodeManager - node manager - * @param count - number of stale nodes to look for. - * @return true if we found the expected number. - */ - private boolean findNodes(NodeManager nodeManager, int count, - HddsProtos.NodeState state) { - return count == nodeManager.getNodeCount(state); - } - - /** - * Asserts that we can create a set of nodes that send its heartbeats from - * different threads and NodeManager behaves as expected. - * - * @throws IOException - * @throws InterruptedException - */ - @Test - public void testScmClusterIsInExpectedState2() throws IOException, - InterruptedException, TimeoutException { - final int healthyCount = 5000; - final int staleCount = 100; - final int deadCount = 10; - - OzoneConfiguration conf = getConf(); - conf.setTimeDuration(OZONE_SCM_HEARTBEAT_PROCESS_INTERVAL, 100, - MILLISECONDS); - conf.setTimeDuration(HDDS_HEARTBEAT_INTERVAL, 1, SECONDS); - conf.setTimeDuration(OZONE_SCM_STALENODE_INTERVAL, 3, SECONDS); - conf.setTimeDuration(OZONE_SCM_DEADNODE_INTERVAL, 6, SECONDS); - - - try (SCMNodeManager nodeManager = createNodeManager(conf)) { - List healthyNodeList = createNodeSet(nodeManager, - healthyCount); - List staleNodeList = createNodeSet(nodeManager, - staleCount); - List deadNodeList = createNodeSet(nodeManager, - deadCount); - - Runnable healthyNodeTask = () -> { - try { - // 2 second heartbeat makes these nodes stay healthy. - heartbeatNodeSet(nodeManager, healthyNodeList, 2 * 1000); - } catch (InterruptedException ignored) { - } - }; - - Runnable staleNodeTask = () -> { - try { - // 4 second heartbeat makes these nodes go to stale and back to - // healthy again. - heartbeatNodeSet(nodeManager, staleNodeList, 4 * 1000); - } catch (InterruptedException ignored) { - } - }; - - - // No Thread just one time HBs the node manager, so that these will be - // marked as dead nodes eventually. - for (DatanodeDetails dn : deadNodeList) { - nodeManager.processHeartbeat(dn); - } - - - Thread thread1 = new Thread(healthyNodeTask); - thread1.setDaemon(true); - thread1.start(); - - - Thread thread2 = new Thread(staleNodeTask); - thread2.setDaemon(true); - thread2.start(); - - Thread.sleep(10 * 1000); - - // Assert all healthy nodes are healthy now, this has to be a greater - // than check since Stale nodes can be healthy when we check the state. - - assertTrue(nodeManager.getNodeCount(HEALTHY) >= healthyCount); - - assertEquals(deadCount, nodeManager.getNodeCount(DEAD)); - - List deadList = nodeManager.getNodes(DEAD); - - for (DatanodeDetails node : deadList) { - assertTrue(deadNodeList.contains(node)); - } - - - - // Checking stale nodes is tricky since they have to move between - // healthy and stale to avoid becoming dead nodes. So we search for - // that state for a while, if we don't find that state waitfor will - // throw. - GenericTestUtils.waitFor(() -> findNodes(nodeManager, staleCount, STALE), - 500, 4 * 1000); - - thread1.interrupt(); - thread2.interrupt(); - } - } - - /** - * Asserts that we can handle 6000+ nodes heartbeating SCM. - * - * @throws IOException - * @throws InterruptedException - * @throws TimeoutException - */ - @Test - public void testScmCanHandleScale() throws IOException, - InterruptedException, TimeoutException { - final int healthyCount = 3000; - final int staleCount = 3000; - OzoneConfiguration conf = getConf(); - conf.setTimeDuration(OZONE_SCM_HEARTBEAT_PROCESS_INTERVAL, 100, - MILLISECONDS); - conf.setTimeDuration(HDDS_HEARTBEAT_INTERVAL, 1, - SECONDS); - conf.setTimeDuration(OZONE_SCM_STALENODE_INTERVAL, 3 * 1000, - MILLISECONDS); - conf.setTimeDuration(OZONE_SCM_DEADNODE_INTERVAL, 6 * 1000, - MILLISECONDS); - - try (SCMNodeManager nodeManager = createNodeManager(conf)) { - List healthyList = createNodeSet(nodeManager, - healthyCount); - List staleList = createNodeSet(nodeManager, - staleCount); - - Runnable healthyNodeTask = () -> { - try { - heartbeatNodeSet(nodeManager, healthyList, 2 * 1000); - } catch (InterruptedException ignored) { - - } - }; - - Runnable staleNodeTask = () -> { - try { - heartbeatNodeSet(nodeManager, staleList, 4 * 1000); - } catch (InterruptedException ignored) { - } - }; - - Thread thread1 = new Thread(healthyNodeTask); - thread1.setDaemon(true); - thread1.start(); - - Thread thread2 = new Thread(staleNodeTask); - thread2.setDaemon(true); - thread2.start(); - Thread.sleep(3 * 1000); - - GenericTestUtils.waitFor(() -> findNodes(nodeManager, staleCount, STALE), - 500, 20 * 1000); - assertEquals("Node count mismatch", - healthyCount + staleCount, nodeManager.getAllNodes().size()); - - thread1.interrupt(); - thread2.interrupt(); - } - } - - - @Test - public void testScmEnterAndExitChillMode() throws IOException, - InterruptedException { - OzoneConfiguration conf = getConf(); - conf.setTimeDuration(OZONE_SCM_HEARTBEAT_PROCESS_INTERVAL, 100, - MILLISECONDS); - - try (SCMNodeManager nodeManager = createNodeManager(conf)) { - nodeManager.setMinimumChillModeNodes(10); - DatanodeDetails datanodeDetails = TestUtils - .createRandomDatanodeAndRegister(nodeManager); - nodeManager.processHeartbeat(datanodeDetails); - String status = nodeManager.getChillModeStatus(); - Assert.assertThat(status, containsString("Still in chill " + - "mode, waiting on nodes to report in.")); - - // Should not exit chill mode since 10 nodes have not heartbeat yet. - assertFalse(nodeManager.isOutOfChillMode()); - - // Force exit chill mode. - nodeManager.forceExitChillMode(); - assertTrue(nodeManager.isOutOfChillMode()); - status = nodeManager.getChillModeStatus(); - Assert.assertThat(status, - containsString("Out of chill mode.")); - - - // Enter back to into chill mode. - nodeManager.enterChillMode(); - assertFalse(nodeManager.isOutOfChillMode()); - status = nodeManager.getChillModeStatus(); - Assert.assertThat(status, - containsString("Out of startup chill mode," + - " but in manual chill mode.")); - - // Assert that node manager force enter cannot be overridden by nodes HBs. - for (int x = 0; x < 20; x++) { - DatanodeDetails datanode = TestUtils - .createRandomDatanodeAndRegister(nodeManager); - nodeManager.processHeartbeat(datanode); - } - - Thread.sleep(500); - assertFalse(nodeManager.isOutOfChillMode()); - - // Make sure that once we exit out of manual chill mode, we fall back - // to the number of nodes to get out chill mode. - nodeManager.exitChillMode(); - assertTrue(nodeManager.isOutOfChillMode()); - status = nodeManager.getChillModeStatus(); - Assert.assertThat(status, - containsString("Out of chill mode.")); - } - } - - /** - * Test multiple nodes sending initial heartbeat with their node report. - * - * @throws IOException - * @throws InterruptedException - * @throws TimeoutException - */ - @Test - @Ignore - // TODO: Enable this after we implement NodeReportEvent handler. - public void testScmStatsFromNodeReport() throws IOException, - InterruptedException, TimeoutException { - OzoneConfiguration conf = getConf(); - conf.setTimeDuration(OZONE_SCM_HEARTBEAT_PROCESS_INTERVAL, 1000, - MILLISECONDS); - final int nodeCount = 10; - final long capacity = 2000; - final long used = 100; - final long remaining = capacity - used; - - try (SCMNodeManager nodeManager = createNodeManager(conf)) { - for (int x = 0; x < nodeCount; x++) { - DatanodeDetails datanodeDetails = TestUtils - .createRandomDatanodeAndRegister(nodeManager); - UUID dnId = datanodeDetails.getUuid(); - long free = capacity - used; - String storagePath = testDir.getAbsolutePath() + "/" + dnId; - StorageReportProto report = TestUtils - .createStorageReport(dnId, storagePath, capacity, used, free, null); - nodeManager.processHeartbeat(datanodeDetails); - } - //TODO: wait for heartbeat to be processed - Thread.sleep(4 * 1000); - assertEquals(nodeCount, nodeManager.getNodeCount(HEALTHY)); - assertEquals(capacity * nodeCount, (long) nodeManager.getStats() - .getCapacity().get()); - assertEquals(used * nodeCount, (long) nodeManager.getStats() - .getScmUsed().get()); - assertEquals(remaining * nodeCount, (long) nodeManager.getStats() - .getRemaining().get()); - } - } - - /** - * Test single node stat update based on nodereport from different heartbeat - * status (healthy, stale and dead). - * @throws IOException - * @throws InterruptedException - * @throws TimeoutException - */ - @Test - @Ignore - // TODO: Enable this after we implement NodeReportEvent handler. - public void testScmNodeReportUpdate() throws IOException, - InterruptedException, TimeoutException { - OzoneConfiguration conf = getConf(); - final int heartbeatCount = 5; - final int nodeCount = 1; - final int interval = 100; - - conf.setTimeDuration(OZONE_SCM_HEARTBEAT_PROCESS_INTERVAL, interval, - MILLISECONDS); - conf.setTimeDuration(HDDS_HEARTBEAT_INTERVAL, 1, SECONDS); - conf.setTimeDuration(OZONE_SCM_STALENODE_INTERVAL, 3, SECONDS); - conf.setTimeDuration(OZONE_SCM_DEADNODE_INTERVAL, 6, SECONDS); - - try (SCMNodeManager nodeManager = createNodeManager(conf)) { - DatanodeDetails datanodeDetails = - TestUtils.createRandomDatanodeAndRegister(nodeManager); - final long capacity = 2000; - final long usedPerHeartbeat = 100; - UUID dnId = datanodeDetails.getUuid(); - for (int x = 0; x < heartbeatCount; x++) { - long scmUsed = x * usedPerHeartbeat; - long remaining = capacity - scmUsed; - String storagePath = testDir.getAbsolutePath() + "/" + dnId; - StorageReportProto report = TestUtils - .createStorageReport(dnId, storagePath, capacity, scmUsed, - remaining, null); - - nodeManager.processHeartbeat(datanodeDetails); - Thread.sleep(100); - } - - final long expectedScmUsed = usedPerHeartbeat * (heartbeatCount - 1); - final long expectedRemaining = capacity - expectedScmUsed; - - GenericTestUtils.waitFor( - () -> nodeManager.getStats().getScmUsed().get() == expectedScmUsed, - 100, 4 * 1000); - - long foundCapacity = nodeManager.getStats().getCapacity().get(); - assertEquals(capacity, foundCapacity); - - long foundScmUsed = nodeManager.getStats().getScmUsed().get(); - assertEquals(expectedScmUsed, foundScmUsed); - - long foundRemaining = nodeManager.getStats().getRemaining().get(); - assertEquals(expectedRemaining, foundRemaining); - - // Test NodeManager#getNodeStats - assertEquals(nodeCount, nodeManager.getNodeStats().size()); - long nodeCapacity = nodeManager.getNodeStat(datanodeDetails).get() - .getCapacity().get(); - assertEquals(capacity, nodeCapacity); - - foundScmUsed = nodeManager.getNodeStat(datanodeDetails).get().getScmUsed() - .get(); - assertEquals(expectedScmUsed, foundScmUsed); - - foundRemaining = nodeManager.getNodeStat(datanodeDetails).get() - .getRemaining().get(); - assertEquals(expectedRemaining, foundRemaining); - - // Compare the result from - // NodeManager#getNodeStats and NodeManager#getNodeStat - SCMNodeStat stat1 = nodeManager.getNodeStats(). - get(datanodeDetails.getUuid()); - SCMNodeStat stat2 = nodeManager.getNodeStat(datanodeDetails).get(); - assertEquals(stat1, stat2); - - // Wait up to 4s so that the node becomes stale - // Verify the usage info should be unchanged. - GenericTestUtils.waitFor( - () -> nodeManager.getNodeCount(STALE) == 1, 100, - 4 * 1000); - assertEquals(nodeCount, nodeManager.getNodeStats().size()); - - foundCapacity = nodeManager.getNodeStat(datanodeDetails).get() - .getCapacity().get(); - assertEquals(capacity, foundCapacity); - foundScmUsed = nodeManager.getNodeStat(datanodeDetails).get() - .getScmUsed().get(); - assertEquals(expectedScmUsed, foundScmUsed); - - foundRemaining = nodeManager.getNodeStat(datanodeDetails).get(). - getRemaining().get(); - assertEquals(expectedRemaining, foundRemaining); - - // Wait up to 4 more seconds so the node becomes dead - // Verify usage info should be updated. - GenericTestUtils.waitFor( - () -> nodeManager.getNodeCount(DEAD) == 1, 100, - 4 * 1000); - - assertEquals(0, nodeManager.getNodeStats().size()); - foundCapacity = nodeManager.getStats().getCapacity().get(); - assertEquals(0, foundCapacity); - - foundScmUsed = nodeManager.getStats().getScmUsed().get(); - assertEquals(0, foundScmUsed); - - foundRemaining = nodeManager.getStats().getRemaining().get(); - assertEquals(0, foundRemaining); - - nodeManager.processHeartbeat(datanodeDetails); - - // Wait up to 5 seconds so that the dead node becomes healthy - // Verify usage info should be updated. - GenericTestUtils.waitFor( - () -> nodeManager.getNodeCount(HEALTHY) == 1, - 100, 5 * 1000); - GenericTestUtils.waitFor( - () -> nodeManager.getStats().getScmUsed().get() == expectedScmUsed, - 100, 4 * 1000); - assertEquals(nodeCount, nodeManager.getNodeStats().size()); - foundCapacity = nodeManager.getNodeStat(datanodeDetails).get() - .getCapacity().get(); - assertEquals(capacity, foundCapacity); - foundScmUsed = nodeManager.getNodeStat(datanodeDetails).get().getScmUsed() - .get(); - assertEquals(expectedScmUsed, foundScmUsed); - foundRemaining = nodeManager.getNodeStat(datanodeDetails).get() - .getRemaining().get(); - assertEquals(expectedRemaining, foundRemaining); - } - } - - @Test - public void testHandlingSCMCommandEvent() { - OzoneConfiguration conf = getConf(); - conf.getTimeDuration(ScmConfigKeys.OZONE_SCM_HEARTBEAT_PROCESS_INTERVAL, - 100, TimeUnit.MILLISECONDS); - - DatanodeDetails datanodeDetails = TestUtils.randomDatanodeDetails(); - UUID dnId = datanodeDetails.getUuid(); - String storagePath = testDir.getAbsolutePath() + "/" + dnId; - StorageReportProto report = - TestUtils.createStorageReport(dnId, storagePath, 100, 10, 90, null); - - EventQueue eq = new EventQueue(); - try (SCMNodeManager nodemanager = createNodeManager(conf)) { - eq.addHandler(DATANODE_COMMAND, nodemanager); - - nodemanager - .register(datanodeDetails, TestUtils.createNodeReport(report), - TestUtils.getRandomPipelineReports()); - eq.fireEvent(DATANODE_COMMAND, - new CommandForDatanode<>(datanodeDetails.getUuid(), - new CloseContainerCommand(1L, ReplicationType.STAND_ALONE, - PipelineID.randomId()))); - - eq.processAll(1000L); - List command = - nodemanager.processHeartbeat(datanodeDetails); - Assert.assertEquals(1, command.size()); - Assert - .assertEquals(command.get(0).getClass(), CloseContainerCommand.class); - } catch (IOException e) { - e.printStackTrace(); - } - } - -} diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestNodeReportHandler.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestNodeReportHandler.java deleted file mode 100644 index f9b139294f7..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestNodeReportHandler.java +++ /dev/null @@ -1,94 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.hdds.scm.node; - -import java.io.IOException; -import java.util.UUID; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.NodeReportProto; -import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.StorageReportProto; -import org.apache.hadoop.hdds.scm.TestUtils; -import org.apache.hadoop.hdds.scm.container.placement.metrics.SCMNodeMetric; -import org.apache.hadoop.hdds.scm.server.SCMDatanodeHeartbeatDispatcher.NodeReportFromDatanode; -import org.apache.hadoop.hdds.server.events.Event; -import org.apache.hadoop.hdds.server.events.EventPublisher; -import org.apache.hadoop.hdds.server.events.EventQueue; -import org.apache.hadoop.test.GenericTestUtils; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class TestNodeReportHandler implements EventPublisher { - - private static final Logger LOG = LoggerFactory - .getLogger(TestNodeReportHandler.class); - private NodeReportHandler nodeReportHandler; - private SCMNodeManager nodeManager; - private String storagePath = GenericTestUtils.getRandomizedTempPath() - .concat("/" + UUID.randomUUID().toString()); - - @Before - public void resetEventCollector() throws IOException { - OzoneConfiguration conf = new OzoneConfiguration(); - nodeManager = new SCMNodeManager(conf, "cluster1", null, new EventQueue()); - nodeReportHandler = new NodeReportHandler(nodeManager); - } - - @Test - public void testNodeReport() throws IOException { - DatanodeDetails dn = TestUtils.randomDatanodeDetails(); - StorageReportProto storageOne = TestUtils - .createStorageReport(dn.getUuid(), storagePath, 100, 10, 90, null); - - SCMNodeMetric nodeMetric = nodeManager.getNodeStat(dn); - Assert.assertNull(nodeMetric); - - nodeReportHandler.onMessage( - getNodeReport(dn, storageOne), this); - nodeMetric = nodeManager.getNodeStat(dn); - - Assert.assertTrue(nodeMetric.get().getCapacity().get() == 100); - Assert.assertTrue(nodeMetric.get().getRemaining().get() == 90); - Assert.assertTrue(nodeMetric.get().getScmUsed().get() == 10); - - StorageReportProto storageTwo = TestUtils - .createStorageReport(dn.getUuid(), storagePath, 100, 10, 90, null); - nodeReportHandler.onMessage( - getNodeReport(dn, storageOne, storageTwo), this); - nodeMetric = nodeManager.getNodeStat(dn); - - Assert.assertTrue(nodeMetric.get().getCapacity().get() == 200); - Assert.assertTrue(nodeMetric.get().getRemaining().get() == 180); - Assert.assertTrue(nodeMetric.get().getScmUsed().get() == 20); - - } - - private NodeReportFromDatanode getNodeReport(DatanodeDetails dn, - StorageReportProto... reports) { - NodeReportProto nodeReportProto = TestUtils.createNodeReport(reports); - return new NodeReportFromDatanode(dn, nodeReportProto); - } - - @Override - public > void fireEvent( - EVENT_TYPE event, PAYLOAD payload) { - LOG.info("Event is published: {}", payload); - } -} diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestSCMNodeStorageStatMap.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestSCMNodeStorageStatMap.java deleted file mode 100644 index 623fc16a924..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestSCMNodeStorageStatMap.java +++ /dev/null @@ -1,262 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.node; - -import org.apache.hadoop.fs.StorageType; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos; -import org.apache.hadoop.hdds.protocol.proto. - StorageContainerDatanodeProtocolProtos.NodeReportProto; -import org.apache.hadoop.hdds.protocol.proto. - StorageContainerDatanodeProtocolProtos.StorageReportProto; -import org.apache.hadoop.hdds.scm.TestUtils; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.container.common.impl.StorageLocationReport; -import org.apache.hadoop.test.GenericTestUtils; -import org.junit.*; -import org.junit.Rule; -import org.junit.rules.ExpectedException; - -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.Set; -import java.util.ArrayList; -import java.util.HashSet; -import java.io.IOException; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Test Node Storage Map. - */ -public class TestSCMNodeStorageStatMap { - private final static int DATANODE_COUNT = 100; - private final long capacity = 10L * OzoneConsts.GB; - private final long used = 2L * OzoneConsts.GB; - private final long remaining = capacity - used; - private static OzoneConfiguration conf = new OzoneConfiguration(); - private final Map> testData = - new ConcurrentHashMap<>(); - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - private void generateData() { - for (int dnIndex = 1; dnIndex <= DATANODE_COUNT; dnIndex++) { - UUID dnId = UUID.randomUUID(); - Set reportSet = new HashSet<>(); - String path = GenericTestUtils.getTempPath( - TestSCMNodeStorageStatMap.class.getSimpleName() + "-" + - Integer.toString(dnIndex)); - StorageLocationReport.Builder builder = - StorageLocationReport.newBuilder(); - builder.setStorageType(StorageType.DISK).setId(dnId.toString()) - .setStorageLocation(path).setScmUsed(used).setRemaining(remaining) - .setCapacity(capacity).setFailed(false); - reportSet.add(builder.build()); - testData.put(UUID.randomUUID(), reportSet); - } - } - - private UUID getFirstKey() { - return testData.keySet().iterator().next(); - } - - @Before - public void setUp() throws Exception { - generateData(); - } - - @After - public void tearDown() throws Exception { - } - - @Test - public void testIsKnownDatanode() throws SCMException { - SCMNodeStorageStatMap map = new SCMNodeStorageStatMap(conf); - UUID knownNode = getFirstKey(); - UUID unknownNode = UUID.randomUUID(); - Set report = testData.get(knownNode); - map.insertNewDatanode(knownNode, report); - Assert.assertTrue("Not able to detect a known node", - map.isKnownDatanode(knownNode)); - Assert.assertFalse("Unknown node detected", - map.isKnownDatanode(unknownNode)); - } - - @Test - public void testInsertNewDatanode() throws SCMException { - SCMNodeStorageStatMap map = new SCMNodeStorageStatMap(conf); - UUID knownNode = getFirstKey(); - Set report = testData.get(knownNode); - map.insertNewDatanode(knownNode, report); - Assert.assertEquals(map.getStorageVolumes(knownNode), - testData.get(knownNode)); - thrown.expect(SCMException.class); - thrown.expectMessage("already exists"); - map.insertNewDatanode(knownNode, report); - } - - @Test - public void testUpdateUnknownDatanode() throws SCMException { - SCMNodeStorageStatMap map = new SCMNodeStorageStatMap(conf); - UUID unknownNode = UUID.randomUUID(); - String path = GenericTestUtils.getTempPath( - TestSCMNodeStorageStatMap.class.getSimpleName() + "-" + unknownNode - .toString()); - Set reportSet = new HashSet<>(); - StorageLocationReport.Builder builder = StorageLocationReport.newBuilder(); - builder.setStorageType(StorageType.DISK).setId(unknownNode.toString()) - .setStorageLocation(path).setScmUsed(used).setRemaining(remaining) - .setCapacity(capacity).setFailed(false); - reportSet.add(builder.build()); - thrown.expect(SCMException.class); - thrown.expectMessage("No such datanode"); - map.updateDatanodeMap(unknownNode, reportSet); - } - - @Test - public void testProcessNodeReportCheckOneNode() throws IOException { - UUID key = getFirstKey(); - List reportList = new ArrayList<>(); - Set reportSet = testData.get(key); - SCMNodeStorageStatMap map = new SCMNodeStorageStatMap(conf); - map.insertNewDatanode(key, reportSet); - Assert.assertTrue(map.isKnownDatanode(key)); - UUID storageId = UUID.randomUUID(); - String path = - GenericTestUtils.getRandomizedTempPath().concat("/" + storageId); - StorageLocationReport report = reportSet.iterator().next(); - long reportCapacity = report.getCapacity(); - long reportScmUsed = report.getScmUsed(); - long reportRemaining = report.getRemaining(); - StorageReportProto storageReport = TestUtils.createStorageReport(storageId, - path, reportCapacity, reportScmUsed, reportRemaining, null); - StorageReportResult result = - map.processNodeReport(key, TestUtils.createNodeReport(storageReport)); - Assert.assertEquals(result.getStatus(), - SCMNodeStorageStatMap.ReportStatus.ALL_IS_WELL); - StorageContainerDatanodeProtocolProtos.NodeReportProto.Builder nrb = - NodeReportProto.newBuilder(); - StorageReportProto srb = reportSet.iterator().next().getProtoBufMessage(); - reportList.add(srb); - result = map.processNodeReport(key, TestUtils.createNodeReport(reportList)); - Assert.assertEquals(result.getStatus(), - SCMNodeStorageStatMap.ReportStatus.ALL_IS_WELL); - - reportList.add(TestUtils - .createStorageReport(UUID.randomUUID(), path, reportCapacity, - reportCapacity, 0, null)); - result = map.processNodeReport(key, TestUtils.createNodeReport(reportList)); - Assert.assertEquals(result.getStatus(), - SCMNodeStorageStatMap.ReportStatus.STORAGE_OUT_OF_SPACE); - // Mark a disk failed - StorageReportProto srb2 = StorageReportProto.newBuilder() - .setStorageUuid(UUID.randomUUID().toString()) - .setStorageLocation(srb.getStorageLocation()).setScmUsed(reportCapacity) - .setCapacity(reportCapacity).setRemaining(0).setFailed(true).build(); - reportList.add(srb2); - nrb.addAllStorageReport(reportList); - result = map.processNodeReport(key, nrb.addStorageReport(srb).build()); - Assert.assertEquals(result.getStatus(), - SCMNodeStorageStatMap.ReportStatus.FAILED_AND_OUT_OF_SPACE_STORAGE); - - } - - @Test - public void testProcessMultipleNodeReports() throws SCMException { - SCMNodeStorageStatMap map = new SCMNodeStorageStatMap(conf); - int counter = 1; - // Insert all testData into the SCMNodeStorageStatMap Map. - for (Map.Entry> keyEntry : testData - .entrySet()) { - map.insertNewDatanode(keyEntry.getKey(), keyEntry.getValue()); - } - Assert.assertEquals(DATANODE_COUNT * capacity, map.getTotalCapacity()); - Assert.assertEquals(DATANODE_COUNT * remaining, map.getTotalFreeSpace()); - Assert.assertEquals(DATANODE_COUNT * used, map.getTotalSpaceUsed()); - - // upadate 1/4th of the datanode to be full - for (Map.Entry> keyEntry : testData - .entrySet()) { - Set reportSet = new HashSet<>(); - String path = GenericTestUtils.getTempPath( - TestSCMNodeStorageStatMap.class.getSimpleName() + "-" + keyEntry - .getKey().toString()); - StorageLocationReport.Builder builder = - StorageLocationReport.newBuilder(); - builder.setStorageType(StorageType.DISK) - .setId(keyEntry.getKey().toString()).setStorageLocation(path) - .setScmUsed(capacity).setRemaining(0).setCapacity(capacity) - .setFailed(false); - reportSet.add(builder.build()); - - map.updateDatanodeMap(keyEntry.getKey(), reportSet); - counter++; - if (counter > DATANODE_COUNT / 4) { - break; - } - } - Assert.assertEquals(DATANODE_COUNT / 4, - map.getDatanodeList(SCMNodeStorageStatMap.UtilizationThreshold.CRITICAL) - .size()); - Assert.assertEquals(0, - map.getDatanodeList(SCMNodeStorageStatMap.UtilizationThreshold.WARN) - .size()); - Assert.assertEquals(0.75 * DATANODE_COUNT, - map.getDatanodeList(SCMNodeStorageStatMap.UtilizationThreshold.NORMAL) - .size(), 0); - - Assert.assertEquals(DATANODE_COUNT * capacity, map.getTotalCapacity(), 0); - Assert.assertEquals(0.75 * DATANODE_COUNT * remaining, - map.getTotalFreeSpace(), 0); - Assert.assertEquals( - 0.75 * DATANODE_COUNT * used + (0.25 * DATANODE_COUNT * capacity), - map.getTotalSpaceUsed(), 0); - counter = 1; - // Remove 1/4 of the DataNodes from the Map - for (Map.Entry> keyEntry : testData - .entrySet()) { - map.removeDatanode(keyEntry.getKey()); - counter++; - if (counter > DATANODE_COUNT / 4) { - break; - } - } - - Assert.assertEquals(0, - map.getDatanodeList(SCMNodeStorageStatMap.UtilizationThreshold.CRITICAL) - .size()); - Assert.assertEquals(0, - map.getDatanodeList(SCMNodeStorageStatMap.UtilizationThreshold.WARN) - .size()); - Assert.assertEquals(0.75 * DATANODE_COUNT, - map.getDatanodeList(SCMNodeStorageStatMap.UtilizationThreshold.NORMAL) - .size(), 0); - - Assert - .assertEquals(0.75 * DATANODE_COUNT * capacity, map.getTotalCapacity(), - 0); - Assert.assertEquals(0.75 * DATANODE_COUNT * remaining, - map.getTotalFreeSpace(), 0); - Assert - .assertEquals(0.75 * DATANODE_COUNT * used, map.getTotalSpaceUsed(), 0); - - } -} diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/package-info.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/package-info.java deleted file mode 100644 index dfd83977712..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/package-info.java +++ /dev/null @@ -1,22 +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 - * - * 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. - * - */ -/** - * Make CheckStyle Happy. - */ -package org.apache.hadoop.hdds.scm.node; \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/states/TestNode2ContainerMap.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/states/TestNode2ContainerMap.java deleted file mode 100644 index ec1d5279d09..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/states/TestNode2ContainerMap.java +++ /dev/null @@ -1,327 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.hadoop.hdds.scm.node.states; - -import org.apache.hadoop.hdds.scm.container.ContainerID; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.TreeSet; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Test classes for Node2ContainerMap. - */ -public class TestNode2ContainerMap { - private final static int DATANODE_COUNT = 300; - private final static int CONTAINER_COUNT = 1000; - private final Map> testData = new - ConcurrentHashMap<>(); - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - private void generateData() { - for (int dnIndex = 1; dnIndex <= DATANODE_COUNT; dnIndex++) { - TreeSet currentSet = new TreeSet<>(); - for (int cnIndex = 1; cnIndex <= CONTAINER_COUNT; cnIndex++) { - long currentCnIndex = (dnIndex * CONTAINER_COUNT) + cnIndex; - currentSet.add(new ContainerID(currentCnIndex)); - } - testData.put(UUID.randomUUID(), currentSet); - } - } - - private UUID getFirstKey() { - return testData.keySet().iterator().next(); - } - - @Before - public void setUp() throws Exception { - generateData(); - } - - @After - public void tearDown() throws Exception { - } - - @Test - public void testIsKnownDatanode() throws SCMException { - Node2ContainerMap map = new Node2ContainerMap(); - UUID knownNode = getFirstKey(); - UUID unknownNode = UUID.randomUUID(); - Set containerIDs = testData.get(knownNode); - map.insertNewDatanode(knownNode, containerIDs); - Assert.assertTrue("Not able to detect a known node", - map.isKnownDatanode(knownNode)); - Assert.assertFalse("Unknown node detected", - map.isKnownDatanode(unknownNode)); - } - - @Test - public void testInsertNewDatanode() throws SCMException { - Node2ContainerMap map = new Node2ContainerMap(); - UUID knownNode = getFirstKey(); - Set containerIDs = testData.get(knownNode); - map.insertNewDatanode(knownNode, containerIDs); - Set readSet = map.getContainers(knownNode); - - // Assert that all elements are present in the set that we read back from - // node map. - Set newSet = new TreeSet((readSet)); - Assert.assertTrue(newSet.removeAll(containerIDs)); - Assert.assertTrue(newSet.size() == 0); - - thrown.expect(SCMException.class); - thrown.expectMessage("already exists"); - map.insertNewDatanode(knownNode, containerIDs); - - map.removeDatanode(knownNode); - map.insertNewDatanode(knownNode, containerIDs); - - } - - @Test - public void testProcessReportCheckOneNode() throws SCMException { - UUID key = getFirstKey(); - Set values = testData.get(key); - Node2ContainerMap map = new Node2ContainerMap(); - map.insertNewDatanode(key, values); - Assert.assertTrue(map.isKnownDatanode(key)); - ReportResult result = map.processReport(key, values); - Assert.assertEquals(result.getStatus(), - ReportResult.ReportStatus.ALL_IS_WELL); - } - - @Test - public void testUpdateDatanodeMap() throws SCMException { - UUID datanodeId = getFirstKey(); - Set values = testData.get(datanodeId); - Node2ContainerMap map = new Node2ContainerMap(); - map.insertNewDatanode(datanodeId, values); - Assert.assertTrue(map.isKnownDatanode(datanodeId)); - Assert.assertEquals(CONTAINER_COUNT, map.getContainers(datanodeId).size()); - - //remove one container - values.remove(values.iterator().next()); - Assert.assertEquals(CONTAINER_COUNT - 1, values.size()); - Assert.assertEquals(CONTAINER_COUNT, map.getContainers(datanodeId).size()); - - map.setContainersForDatanode(datanodeId, values); - - Assert.assertEquals(values.size(), map.getContainers(datanodeId).size()); - Assert.assertEquals(values, map.getContainers(datanodeId)); - } - - @Test - public void testProcessReportInsertAll() throws SCMException { - Node2ContainerMap map = new Node2ContainerMap(); - - for (Map.Entry> keyEntry : testData.entrySet()) { - map.insertNewDatanode(keyEntry.getKey(), keyEntry.getValue()); - } - // Assert all Keys are known datanodes. - for (UUID key : testData.keySet()) { - Assert.assertTrue(map.isKnownDatanode(key)); - } - } - - /* - For ProcessReport we have to test the following scenarios. - - 1. New Datanode - A new datanode appears and we have to add that to the - SCM's Node2Container Map. - - 2. New Container - A Datanode exists, but a new container is added to that - DN. We need to detect that and return a list of added containers. - - 3. Missing Container - A Datanode exists, but one of the expected container - on that datanode is missing. We need to detect that. - - 4. We get a container report that has both the missing and new containers. - We need to return separate lists for these. - */ - - /** - * Assert that we are able to detect the addition of a new datanode. - * - * @throws SCMException - */ - @Test - public void testProcessReportDetectNewDataNode() throws SCMException { - Node2ContainerMap map = new Node2ContainerMap(); - // If we attempt to process a node that is not present in the map, - // we get a result back that says, NEW_NODE_FOUND. - UUID key = getFirstKey(); - TreeSet values = testData.get(key); - ReportResult result = map.processReport(key, values); - Assert.assertEquals(ReportResult.ReportStatus.NEW_DATANODE_FOUND, - result.getStatus()); - Assert.assertEquals(result.getNewEntries().size(), values.size()); - } - - /** - * This test asserts that processReport is able to detect new containers - * when it is added to a datanode. For that we populate the DN with a list - * of containerIDs and then add few more containers and make sure that we - * are able to detect them. - * - * @throws SCMException - */ - @Test - public void testProcessReportDetectNewContainers() throws SCMException { - Node2ContainerMap map = new Node2ContainerMap(); - UUID key = getFirstKey(); - TreeSet values = testData.get(key); - map.insertNewDatanode(key, values); - - final int newCount = 100; - ContainerID last = values.last(); - TreeSet addedContainers = new TreeSet<>(); - for (int x = 1; x <= newCount; x++) { - long cTemp = last.getId() + x; - addedContainers.add(new ContainerID(cTemp)); - } - - // This set is the super set of existing containers and new containers. - TreeSet newContainersSet = new TreeSet<>(values); - newContainersSet.addAll(addedContainers); - - ReportResult result = map.processReport(key, newContainersSet); - - //Assert that expected size of missing container is same as addedContainers - Assert.assertEquals(ReportResult.ReportStatus.NEW_ENTRIES_FOUND, - result.getStatus()); - - Assert.assertEquals(addedContainers.size(), - result.getNewEntries().size()); - - // Assert that the Container IDs are the same as we added new. - Assert.assertTrue("All objects are not removed.", - result.getNewEntries().removeAll(addedContainers)); - } - - /** - * This test asserts that processReport is able to detect missing containers - * if they are misssing from a list. - * - * @throws SCMException - */ - @Test - public void testProcessReportDetectMissingContainers() throws SCMException { - Node2ContainerMap map = new Node2ContainerMap(); - UUID key = getFirstKey(); - TreeSet values = testData.get(key); - map.insertNewDatanode(key, values); - - final int removeCount = 100; - Random r = new Random(); - - ContainerID first = values.first(); - TreeSet removedContainers = new TreeSet<>(); - - // Pick a random container to remove it is ok to collide no issues. - for (int x = 0; x < removeCount; x++) { - int startBase = (int) first.getId(); - long cTemp = r.nextInt(values.size()); - removedContainers.add(new ContainerID(cTemp + startBase)); - } - - // This set is a new set with some containers removed. - TreeSet newContainersSet = new TreeSet<>(values); - newContainersSet.removeAll(removedContainers); - - ReportResult result = map.processReport(key, newContainersSet); - - - //Assert that expected size of missing container is same as addedContainers - Assert.assertEquals(ReportResult.ReportStatus.MISSING_ENTRIES, - result.getStatus()); - Assert.assertEquals(removedContainers.size(), - result.getMissingEntries().size()); - - // Assert that the Container IDs are the same as we added new. - Assert.assertTrue("All missing containers not found.", - result.getMissingEntries().removeAll(removedContainers)); - } - - @Test - public void testProcessReportDetectNewAndMissingContainers() throws - SCMException { - Node2ContainerMap map = new Node2ContainerMap(); - UUID key = getFirstKey(); - TreeSet values = testData.get(key); - map.insertNewDatanode(key, values); - - Set insertedSet = new TreeSet<>(); - // Insert nodes from 1..30 - for (int x = 1; x <= 30; x++) { - insertedSet.add(new ContainerID(x)); - } - - - final int removeCount = 100; - Random r = new Random(); - - ContainerID first = values.first(); - TreeSet removedContainers = new TreeSet<>(); - - // Pick a random container to remove it is ok to collide no issues. - for (int x = 0; x < removeCount; x++) { - int startBase = (int) first.getId(); - long cTemp = r.nextInt(values.size()); - removedContainers.add(new ContainerID(cTemp + startBase)); - } - - Set newSet = new TreeSet<>(values); - newSet.addAll(insertedSet); - newSet.removeAll(removedContainers); - - ReportResult result = map.processReport(key, newSet); - - - Assert.assertEquals( - ReportResult.ReportStatus.MISSING_AND_NEW_ENTRIES_FOUND, - result.getStatus()); - Assert.assertEquals(removedContainers.size(), - result.getMissingEntries().size()); - - - // Assert that the Container IDs are the same as we added new. - Assert.assertTrue("All missing containers not found.", - result.getMissingEntries().removeAll(removedContainers)); - - Assert.assertEquals(insertedSet.size(), - result.getNewEntries().size()); - - // Assert that the Container IDs are the same as we added new. - Assert.assertTrue("All inserted containers are not found.", - result.getNewEntries().removeAll(insertedSet)); - } -} \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/states/package-info.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/states/package-info.java deleted file mode 100644 index 6610fcd7106..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/states/package-info.java +++ /dev/null @@ -1,23 +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 - * - * 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. - * - */ - -/** - * Test Node2Container Map. - */ -package org.apache.hadoop.hdds.scm.node.states; \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/package-info.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/package-info.java deleted file mode 100644 index da05c59acfc..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/package-info.java +++ /dev/null @@ -1,21 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm; -/** - * SCM tests - */ diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMChillModeManager.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMChillModeManager.java deleted file mode 100644 index 486c604cd06..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMChillModeManager.java +++ /dev/null @@ -1,125 +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 - * - *      http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.server; - -import java.util.ArrayList; -import java.util.List; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.HddsConfigKeys; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.scm.HddsTestUtils; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo; -import org.apache.hadoop.hdds.scm.events.SCMEvents; -import org.apache.hadoop.hdds.server.events.EventQueue; -import org.apache.hadoop.test.GenericTestUtils; -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.Timeout; - -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.assertFalse; - -/** Test class for SCMChillModeManager. - */ -public class TestSCMChillModeManager { - - private static EventQueue queue; - private SCMChillModeManager scmChillModeManager; - private static Configuration config; - private List containers; - - @Rule - public Timeout timeout = new Timeout(1000 * 20); - - @BeforeClass - public static void setUp() { - queue = new EventQueue(); - config = new OzoneConfiguration(); - } - - @Test - public void testChillModeState() throws Exception { - // Test 1: test for 0 containers - testChillMode(0); - - // Test 2: test for 20 containers - testChillMode(20); - } - - @Test - public void testChillModeStateWithNullContainers() { - new SCMChillModeManager(config, null, queue); - } - - private void testChillMode(int numContainers) throws Exception { - containers = new ArrayList<>(); - containers.addAll(HddsTestUtils.getContainerInfo(numContainers)); - scmChillModeManager = new SCMChillModeManager(config, containers, queue); - queue.addHandler(SCMEvents.NODE_REGISTRATION_CONT_REPORT, - scmChillModeManager); - assertTrue(scmChillModeManager.getInChillMode()); - queue.fireEvent(SCMEvents.NODE_REGISTRATION_CONT_REPORT, - HddsTestUtils.createNodeRegistrationContainerReport(containers)); - GenericTestUtils.waitFor(() -> { - return !scmChillModeManager.getInChillMode(); - }, 100, 1000 * 5); - } - - @Test - public void testChillModeExitRule() throws Exception { - containers = new ArrayList<>(); - containers.addAll(HddsTestUtils.getContainerInfo(25 * 4)); - scmChillModeManager = new SCMChillModeManager(config, containers, queue); - queue.addHandler(SCMEvents.NODE_REGISTRATION_CONT_REPORT, - scmChillModeManager); - assertTrue(scmChillModeManager.getInChillMode()); - - testContainerThreshold(containers.subList(0, 25), 0.25); - assertTrue(scmChillModeManager.getInChillMode()); - testContainerThreshold(containers.subList(25, 50), 0.50); - assertTrue(scmChillModeManager.getInChillMode()); - testContainerThreshold(containers.subList(50, 75), 0.75); - assertTrue(scmChillModeManager.getInChillMode()); - testContainerThreshold(containers.subList(75, 100), 1.0); - - GenericTestUtils.waitFor(() -> { - return !scmChillModeManager.getInChillMode(); - }, 100, 1000 * 5); - } - - @Test - public void testDisableChillMode() { - OzoneConfiguration conf = new OzoneConfiguration(config); - conf.setBoolean(HddsConfigKeys.HDDS_SCM_CHILLMODE_ENABLED, false); - scmChillModeManager = new SCMChillModeManager(conf, containers, queue); - assertFalse(scmChillModeManager.getInChillMode()); - } - - private void testContainerThreshold(List dnContainers, - double expectedThreshold) - throws Exception { - queue.fireEvent(SCMEvents.NODE_REGISTRATION_CONT_REPORT, - HddsTestUtils.createNodeRegistrationContainerReport(dnContainers)); - GenericTestUtils.waitFor(() -> { - double threshold = scmChillModeManager.getCurrentContainerThreshold(); - return threshold == expectedThreshold; - }, 100, 2000 * 9); - } - -} \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMClientProtocolServer.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMClientProtocolServer.java deleted file mode 100644 index 4b2001848b1..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMClientProtocolServer.java +++ /dev/null @@ -1,60 +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 - * - *      http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.server; - -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationFactor; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationType; -import org.apache.hadoop.hdds.scm.events.SCMEvents; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.hdds.server.events.EventQueue; -import org.apache.hadoop.test.LambdaTestUtils; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -/** - * Test class for @{@link SCMClientProtocolServer}. - * */ -public class TestSCMClientProtocolServer { - private SCMClientProtocolServer scmClientProtocolServer; - private OzoneConfiguration config; - private EventQueue eventQueue; - - @Before - public void setUp() throws Exception { - config = new OzoneConfiguration(); - eventQueue = new EventQueue(); - scmClientProtocolServer = new SCMClientProtocolServer(config, null); - eventQueue.addHandler(SCMEvents.CHILL_MODE_STATUS, scmClientProtocolServer); - } - - @After - public void tearDown() throws Exception { - } - - @Test - public void testAllocateContainerFailureInChillMode() throws Exception { - LambdaTestUtils.intercept(SCMException.class, - "hillModePrecheck failed for allocateContainer", () -> { - scmClientProtocolServer.allocateContainer( - ReplicationType.STAND_ALONE, ReplicationFactor.ONE, ""); - }); - } -} \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMDatanodeHeartbeatDispatcher.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMDatanodeHeartbeatDispatcher.java deleted file mode 100644 index f3cd4eaabad..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMDatanodeHeartbeatDispatcher.java +++ /dev/null @@ -1,138 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.hdds.scm.server; - -import java.io.IOException; -import java.util.concurrent.atomic.AtomicInteger; - -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto. - StorageContainerDatanodeProtocolProtos.CommandStatusReportsProto; -import org.apache.hadoop.hdds.scm.server. - SCMDatanodeHeartbeatDispatcher.CommandStatusReportFromDatanode; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.ContainerReportsProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.NodeReportProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMHeartbeatRequestProto; -import org.apache.hadoop.hdds.scm.TestUtils; -import org.apache.hadoop.hdds.scm.node.NodeManager; -import org.apache.hadoop.hdds.scm.server.SCMDatanodeHeartbeatDispatcher - .ContainerReportFromDatanode; -import org.apache.hadoop.hdds.scm.server.SCMDatanodeHeartbeatDispatcher - .NodeReportFromDatanode; -import org.apache.hadoop.hdds.server.events.Event; -import org.apache.hadoop.hdds.server.events.EventPublisher; - -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import static org.apache.hadoop.hdds.scm.events.SCMEvents.CONTAINER_REPORT; -import static org.apache.hadoop.hdds.scm.events.SCMEvents.NODE_REPORT; -import static org.apache.hadoop.hdds.scm.events.SCMEvents.CMD_STATUS_REPORT; - -/** - * This class tests the behavior of SCMDatanodeHeartbeatDispatcher. - */ -public class TestSCMDatanodeHeartbeatDispatcher { - - - @Test - public void testNodeReportDispatcher() throws IOException { - - AtomicInteger eventReceived = new AtomicInteger(); - - NodeReportProto nodeReport = NodeReportProto.getDefaultInstance(); - - SCMDatanodeHeartbeatDispatcher dispatcher = - new SCMDatanodeHeartbeatDispatcher(Mockito.mock(NodeManager.class), - new EventPublisher() { - @Override - public > void fireEvent( - EVENT_TYPE event, PAYLOAD payload) { - Assert.assertEquals(event, NODE_REPORT); - eventReceived.incrementAndGet(); - Assert.assertEquals(nodeReport, - ((NodeReportFromDatanode)payload).getReport()); - - } - }); - - DatanodeDetails datanodeDetails = TestUtils.randomDatanodeDetails(); - - SCMHeartbeatRequestProto heartbeat = - SCMHeartbeatRequestProto.newBuilder() - .setDatanodeDetails(datanodeDetails.getProtoBufMessage()) - .setNodeReport(nodeReport) - .build(); - dispatcher.dispatch(heartbeat); - Assert.assertEquals(1, eventReceived.get()); - - - } - - @Test - public void testContainerReportDispatcher() throws IOException { - - - AtomicInteger eventReceived = new AtomicInteger(); - - ContainerReportsProto containerReport = - ContainerReportsProto.getDefaultInstance(); - CommandStatusReportsProto commandStatusReport = - CommandStatusReportsProto.getDefaultInstance(); - - SCMDatanodeHeartbeatDispatcher dispatcher = - new SCMDatanodeHeartbeatDispatcher(Mockito.mock(NodeManager.class), - new EventPublisher() { - @Override - public > void fireEvent( - EVENT_TYPE event, PAYLOAD payload) { - Assert.assertTrue( - event.equals(CONTAINER_REPORT) - || event.equals(CMD_STATUS_REPORT)); - - if (payload instanceof ContainerReportFromDatanode) { - Assert.assertEquals(containerReport, - ((ContainerReportFromDatanode) payload).getReport()); - } - if (payload instanceof CommandStatusReportFromDatanode) { - Assert.assertEquals(commandStatusReport, - ((CommandStatusReportFromDatanode) payload).getReport()); - } - eventReceived.incrementAndGet(); - } - }); - - DatanodeDetails datanodeDetails = TestUtils.randomDatanodeDetails(); - - SCMHeartbeatRequestProto heartbeat = - SCMHeartbeatRequestProto.newBuilder() - .setDatanodeDetails(datanodeDetails.getProtoBufMessage()) - .setContainerReport(containerReport) - .addCommandStatusReports(commandStatusReport) - .build(); - dispatcher.dispatch(heartbeat); - Assert.assertEquals(2, eventReceived.get()); - - - } - -} diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/TestCloseContainerWatcher.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/TestCloseContainerWatcher.java deleted file mode 100644 index 56c3830c9b8..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/TestCloseContainerWatcher.java +++ /dev/null @@ -1,287 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.container; - -import org.apache.hadoop.hdds.HddsIdFactory; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.CommandStatus; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMCommandProto.Type; -import org.apache.hadoop.hdds.scm.command.CommandStatusReportHandler - .CloseContainerStatus; -import org.apache.hadoop.hdds.scm.container.CloseContainerEventHandler - .CloseContainerRetryableReq; -import org.apache.hadoop.hdds.scm.container.CloseContainerWatcher; -import org.apache.hadoop.hdds.scm.container.ContainerID; -import org.apache.hadoop.hdds.scm.container.ContainerMapping; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo; -import org.apache.hadoop.hdds.scm.events.SCMEvents; -import org.apache.hadoop.hdds.server.events.EventHandler; -import org.apache.hadoop.hdds.server.events.EventPublisher; -import org.apache.hadoop.hdds.server.events.EventQueue; -import org.apache.hadoop.hdds.server.events.EventWatcher; -import org.apache.hadoop.ozone.lease.LeaseManager; -import org.apache.hadoop.test.GenericTestUtils; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.Timeout; -import org.mockito.Mockito; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.event.Level; - -import java.io.IOException; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.when; - -/** - * Test class for {@link CloseContainerWatcher}. - * */ -public class TestCloseContainerWatcher implements EventHandler { - - private static final Logger LOG = LoggerFactory - .getLogger(TestCloseContainerWatcher.class); - private static EventWatcher - watcher; - private static LeaseManager leaseManager; - private static ContainerMapping containerMapping = Mockito - .mock(ContainerMapping.class); - private static EventQueue queue; - @Rule - public Timeout timeout = new Timeout(1000*15); - - @After - public void stop() { - leaseManager.shutdown(); - queue.close(); - } - - /* - * This test will test watcher for Failure status event. - * */ - @Test - public void testWatcherForFailureStatusEvent() throws - InterruptedException, IOException { - setupWatcher(90000L); - long id1 = HddsIdFactory.getLongId(); - long id2 = HddsIdFactory.getLongId(); - queue.addHandler(SCMEvents.CLOSE_CONTAINER, this); - setupMock(id1, id2, true); - GenericTestUtils.LogCapturer testLogger = GenericTestUtils.LogCapturer - .captureLogs(LOG); - GenericTestUtils.LogCapturer watcherLogger = GenericTestUtils.LogCapturer - .captureLogs(CloseContainerWatcher.LOG); - GenericTestUtils.setLogLevel(CloseContainerWatcher.LOG, Level.TRACE); - testLogger.clearOutput(); - watcherLogger.clearOutput(); - - CommandStatus cmdStatus1 = CommandStatus.newBuilder() - .setCmdId(id1) - .setStatus(CommandStatus.Status.FAILED) - .setType(Type.closeContainerCommand).build(); - CommandStatus cmdStatus2 = CommandStatus.newBuilder() - .setCmdId(id2) - .setStatus(CommandStatus.Status.FAILED) - .setType(Type.closeContainerCommand).build(); - - // File events to watcher - queue.fireEvent(SCMEvents.CLOSE_CONTAINER_RETRYABLE_REQ, - new CloseContainerRetryableReq(ContainerID.valueof(id1))); - queue.fireEvent(SCMEvents.CLOSE_CONTAINER_RETRYABLE_REQ, - new CloseContainerRetryableReq(ContainerID.valueof(id2))); - Thread.sleep(10L); - queue.fireEvent(SCMEvents.CLOSE_CONTAINER_STATUS, new - CloseContainerStatus(cmdStatus1)); - queue.fireEvent(SCMEvents.CLOSE_CONTAINER_STATUS, new - CloseContainerStatus(cmdStatus2)); - - Thread.sleep(1000*4L); - // validation - assertTrue(watcherLogger.getOutput().contains("CloseContainerCommand for " + - "containerId: " + id1 + " executed")); - assertTrue(watcherLogger.getOutput().contains("CloseContainerCommand for " + - "containerId: " + id2 + " executed")); - assertTrue( - testLogger.getOutput().contains("Handling closeContainerEvent " + - "for containerId: id=" + id1)); - assertTrue(testLogger.getOutput().contains("Handling closeContainerEvent " + - "for containerId: id=" + id2)); - - } - - @Test - public void testWatcherForPendingStatusEvent() throws - InterruptedException, IOException { - setupWatcher(90000L); - long id1 = HddsIdFactory.getLongId(); - long id2 = HddsIdFactory.getLongId(); - queue.addHandler(SCMEvents.CLOSE_CONTAINER, this); - setupMock(id1, id2, true); - GenericTestUtils.LogCapturer testLogger = GenericTestUtils.LogCapturer - .captureLogs(LOG); - GenericTestUtils.LogCapturer watcherLogger = GenericTestUtils.LogCapturer - .captureLogs(CloseContainerWatcher.LOG); - GenericTestUtils.setLogLevel(CloseContainerWatcher.LOG, Level.TRACE); - testLogger.clearOutput(); - watcherLogger.clearOutput(); - - CommandStatus cmdStatus1 = CommandStatus.newBuilder() - .setCmdId(id1) - .setStatus(CommandStatus.Status.PENDING) - .setType(Type.closeContainerCommand).build(); - CommandStatus cmdStatus2 = CommandStatus.newBuilder() - .setCmdId(id2) - .setStatus(CommandStatus.Status.PENDING) - .setType(Type.closeContainerCommand).build(); - - // File events to watcher - queue.fireEvent(SCMEvents.CLOSE_CONTAINER_RETRYABLE_REQ, - new CloseContainerRetryableReq(ContainerID.valueof(id1))); - queue.fireEvent(SCMEvents.CLOSE_CONTAINER_RETRYABLE_REQ, - new CloseContainerRetryableReq(ContainerID.valueof(id2))); - Thread.sleep(10L); - queue.fireEvent(SCMEvents.CLOSE_CONTAINER_STATUS, new - CloseContainerStatus(cmdStatus1)); - queue.fireEvent(SCMEvents.CLOSE_CONTAINER_STATUS, new - CloseContainerStatus(cmdStatus2)); - - Thread.sleep(1000*2L); - // validation - assertFalse(watcherLogger.getOutput().contains("CloseContainerCommand " - + "for containerId: " + id1 + " executed")); - assertFalse(watcherLogger.getOutput().contains("CloseContainerCommand " - + "for containerId: " + id2 + " executed")); - assertFalse(testLogger.getOutput().contains("Handling " - + "closeContainerEvent for containerId: id=" + id1)); - assertFalse(testLogger.getOutput().contains("Handling " - + "closeContainerEvent for containerId: id=" + id2)); - - } - - @Test - public void testWatcherForExecutedStatusEvent() - throws IOException, InterruptedException { - setupWatcher(90000L); - long id1 = HddsIdFactory.getLongId(); - long id2 = HddsIdFactory.getLongId(); - queue.addHandler(SCMEvents.CLOSE_CONTAINER, this); - setupMock(id1, id2, true); - GenericTestUtils.LogCapturer testLogger = GenericTestUtils.LogCapturer - .captureLogs(LOG); - GenericTestUtils.LogCapturer watcherLogger = GenericTestUtils.LogCapturer - .captureLogs(CloseContainerWatcher.LOG); - GenericTestUtils.setLogLevel(CloseContainerWatcher.LOG, Level.TRACE); - testLogger.clearOutput(); - watcherLogger.clearOutput(); - - // When both of the pending event are executed successfully by DataNode - CommandStatus cmdStatus1 = CommandStatus.newBuilder() - .setCmdId(id1) - .setStatus(CommandStatus.Status.EXECUTED) - .setType(Type.closeContainerCommand).build(); - CommandStatus cmdStatus2 = CommandStatus.newBuilder() - .setCmdId(id2) - .setStatus(CommandStatus.Status.EXECUTED) - .setType(Type.closeContainerCommand).build(); - // File events to watcher - testLogger.clearOutput(); - watcherLogger.clearOutput(); - queue.fireEvent(SCMEvents.CLOSE_CONTAINER_RETRYABLE_REQ, - new CloseContainerRetryableReq(ContainerID.valueof(id1))); - queue.fireEvent(SCMEvents.CLOSE_CONTAINER_RETRYABLE_REQ, - new CloseContainerRetryableReq(ContainerID.valueof(id2))); - Thread.sleep(10L); - queue.fireEvent(SCMEvents.CLOSE_CONTAINER_STATUS, - new CloseContainerStatus(cmdStatus1)); - queue.fireEvent(SCMEvents.CLOSE_CONTAINER_STATUS, - new CloseContainerStatus(cmdStatus2)); - - Thread.sleep(1000*3L); - // validation - assertTrue(watcherLogger.getOutput().contains("CloseContainerCommand " - + "for containerId: " + id1 + " executed")); - assertTrue(watcherLogger.getOutput().contains("CloseContainerCommand " - + "for containerId: " + id2 + " executed")); - assertFalse(testLogger.getOutput().contains("Handling " - + "closeContainerEvent for containerId: id=" + id1)); - assertFalse(testLogger.getOutput().contains("Handling " - + "closeContainerEvent for containerId: id=" + id2)); - } - - private void setupWatcher(long time) { - leaseManager = new LeaseManager<>("TestCloseContainerWatcher#LeaseManager", - time); - leaseManager.start(); - watcher = new CloseContainerWatcher(SCMEvents.CLOSE_CONTAINER_RETRYABLE_REQ, - SCMEvents.CLOSE_CONTAINER_STATUS, leaseManager, containerMapping); - queue = new EventQueue(); - watcher.start(queue); - } - - /* - * This test will fire two retryable closeContainer events. Both will timeout. - * First event container will be open at time of handling so it should be - * sent back to appropriate handler. Second event container will be closed, - * so it should not be retried. - * */ - @Test - public void testWatcherRetryableTimeoutHandling() throws InterruptedException, - IOException { - - long id1 = HddsIdFactory.getLongId(); - long id2 = HddsIdFactory.getLongId(); - setupWatcher(1000L); - queue.addHandler(SCMEvents.CLOSE_CONTAINER, this); - setupMock(id1, id2, false); - GenericTestUtils.LogCapturer testLogger = GenericTestUtils.LogCapturer - .captureLogs(LOG); - testLogger.clearOutput(); - - // File events to watcher - queue.fireEvent(SCMEvents.CLOSE_CONTAINER_RETRYABLE_REQ, - new CloseContainerRetryableReq(ContainerID.valueof(id1))); - queue.fireEvent(SCMEvents.CLOSE_CONTAINER_RETRYABLE_REQ, - new CloseContainerRetryableReq(ContainerID.valueof(id2))); - - Thread.sleep(1000L + 10); - - // validation - assertTrue(testLogger.getOutput().contains("Handling " - + "closeContainerEvent for containerId: id=" + id1)); - assertFalse(testLogger.getOutput().contains("Handling " - + "closeContainerEvent for containerId: id=" + id2)); - } - - - private void setupMock(long id1, long id2, boolean isOpen) - throws IOException { - ContainerInfo containerInfo = Mockito.mock(ContainerInfo.class); - ContainerInfo containerInfo2 = Mockito.mock(ContainerInfo.class); - when(containerMapping.getContainer(id1)).thenReturn(containerInfo); - when(containerMapping.getContainer(id2)).thenReturn(containerInfo2); - when(containerInfo.isContainerOpen()).thenReturn(true); - when(containerInfo2.isContainerOpen()).thenReturn(isOpen); - } - - @Override - public void onMessage(ContainerID containerID, EventPublisher publisher) { - LOG.info("Handling closeContainerEvent for containerId: {}", containerID); - } -} diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/common/TestEndPoint.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/common/TestEndPoint.java deleted file mode 100644 index 390746f4dce..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/common/TestEndPoint.java +++ /dev/null @@ -1,530 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.container.common; - -import java.util.List; -import java.util.Map; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.FileUtil; -import org.apache.hadoop.hdds.HddsConfigKeys; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationType; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.protocol.proto. - StorageContainerDatanodeProtocolProtos.CloseContainerCommandProto; -import org.apache.hadoop.hdds.protocol.proto. - StorageContainerDatanodeProtocolProtos.CommandStatus.Status; -import org.apache.hadoop.hdds.protocol.proto. - StorageContainerDatanodeProtocolProtos.DeleteBlocksCommandProto; -import org.apache.hadoop.hdds.protocol.proto. - StorageContainerDatanodeProtocolProtos.DeletedBlocksTransaction; -import org.apache.hadoop.hdds.protocol.proto. - StorageContainerDatanodeProtocolProtos.ReplicateContainerCommandProto; -import org.apache.hadoop.hdds.protocol.proto. - StorageContainerDatanodeProtocolProtos.SCMCommandProto; -import org.apache.hadoop.hdds.protocol.proto. - StorageContainerDatanodeProtocolProtos.SCMCommandProto.Type; -import org.apache.hadoop.hdds.scm.TestUtils; -import org.apache.hadoop.hdds.scm.VersionInfo; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMHeartbeatRequestProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMHeartbeatResponseProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMRegisteredResponseProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.StorageReportProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMVersionResponseProto; -import org.apache.hadoop.hdds.scm.container.common.helpers.PipelineID; -import org.apache.hadoop.ipc.RPC; -import org.apache.hadoop.ozone.OzoneConfigKeys; -import org.apache.hadoop.ozone.container.common.statemachine - .DatanodeStateMachine; -import org.apache.hadoop.ozone.container.common.statemachine - .EndpointStateMachine; -import org.apache.hadoop.ozone.container.common.statemachine.StateContext; -import org.apache.hadoop.ozone.container.common.states.endpoint - .HeartbeatEndpointTask; -import org.apache.hadoop.ozone.container.common.states.endpoint - .RegisterEndpointTask; -import org.apache.hadoop.ozone.container.common.states.endpoint - .VersionEndpointTask; -import org.apache.hadoop.ozone.container.common.volume.HddsVolume; -import org.apache.hadoop.ozone.container.ozoneimpl.OzoneContainer; -import org.apache.hadoop.ozone.protocol.commands.CommandStatus; -import org.apache.hadoop.test.GenericTestUtils; -import org.apache.hadoop.test.PathUtils; -import org.apache.hadoop.util.Time; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import static org.mockito.Mockito.mock; - -import java.io.File; -import java.net.InetSocketAddress; -import java.util.UUID; - -import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_DATANODE_DATA_DIR_KEY; -import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_METADATA_DIRS; -import static org.apache.hadoop.ozone.container.common.ContainerTestUtils - .createEndpoint; -import static org.hamcrest.Matchers.lessThanOrEqualTo; -import static org.mockito.Mockito.when; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * Tests the endpoints. - */ -public class TestEndPoint { - private static InetSocketAddress serverAddress; - private static RPC.Server scmServer; - private static ScmTestMock scmServerImpl; - private static File testDir; - private static Configuration config; - - @AfterClass - public static void tearDown() throws Exception { - if (scmServer != null) { - scmServer.stop(); - } - FileUtil.fullyDelete(testDir); - } - - @BeforeClass - public static void setUp() throws Exception { - serverAddress = SCMTestUtils.getReuseableAddress(); - scmServerImpl = new ScmTestMock(); - scmServer = SCMTestUtils.startScmRpcServer(SCMTestUtils.getConf(), - scmServerImpl, serverAddress, 10); - testDir = PathUtils.getTestDir(TestEndPoint.class); - config = SCMTestUtils.getConf(); - config.set(DFS_DATANODE_DATA_DIR_KEY, testDir.getAbsolutePath()); - config.set(OZONE_METADATA_DIRS, testDir.getAbsolutePath()); - config - .setBoolean(OzoneConfigKeys.DFS_CONTAINER_RATIS_IPC_RANDOM_PORT, true); - config.set(HddsConfigKeys.HDDS_COMMAND_STATUS_REPORT_INTERVAL, "1s"); - } - - @Test - /** - * This test asserts that we are able to make a version call to SCM server - * and gets back the expected values. - */ - public void testGetVersion() throws Exception { - try (EndpointStateMachine rpcEndPoint = - createEndpoint(SCMTestUtils.getConf(), - serverAddress, 1000)) { - SCMVersionResponseProto responseProto = rpcEndPoint.getEndPoint() - .getVersion(null); - Assert.assertNotNull(responseProto); - Assert.assertEquals(VersionInfo.DESCRIPTION_KEY, - responseProto.getKeys(0).getKey()); - Assert.assertEquals(VersionInfo.getLatestVersion().getDescription(), - responseProto.getKeys(0).getValue()); - } - } - - @Test - /** - * We make getVersion RPC call, but via the VersionEndpointTask which is - * how the state machine would make the call. - */ - public void testGetVersionTask() throws Exception { - OzoneConfiguration conf = SCMTestUtils.getConf(); - try (EndpointStateMachine rpcEndPoint = createEndpoint(conf, - serverAddress, 1000)) { - OzoneContainer ozoneContainer = new OzoneContainer( - TestUtils.randomDatanodeDetails(), conf, null); - rpcEndPoint.setState(EndpointStateMachine.EndPointStates.GETVERSION); - VersionEndpointTask versionTask = new VersionEndpointTask(rpcEndPoint, - conf, ozoneContainer); - EndpointStateMachine.EndPointStates newState = versionTask.call(); - - // if version call worked the endpoint should automatically move to the - // next state. - Assert.assertEquals(EndpointStateMachine.EndPointStates.REGISTER, - newState); - - // Now rpcEndpoint should remember the version it got from SCM - Assert.assertNotNull(rpcEndPoint.getVersion()); - } - } - - @Test - public void testCheckVersionResponse() throws Exception { - OzoneConfiguration conf = SCMTestUtils.getConf(); - try (EndpointStateMachine rpcEndPoint = createEndpoint(conf, - serverAddress, 1000)) { - GenericTestUtils.LogCapturer logCapturer = GenericTestUtils.LogCapturer - .captureLogs(VersionEndpointTask.LOG); - OzoneContainer ozoneContainer = new OzoneContainer(TestUtils - .randomDatanodeDetails(), conf, null); - rpcEndPoint.setState(EndpointStateMachine.EndPointStates.GETVERSION); - VersionEndpointTask versionTask = new VersionEndpointTask(rpcEndPoint, - conf, ozoneContainer); - EndpointStateMachine.EndPointStates newState = versionTask.call(); - - // if version call worked the endpoint should automatically move to the - // next state. - Assert.assertEquals(EndpointStateMachine.EndPointStates.REGISTER, - newState); - - // Now rpcEndpoint should remember the version it got from SCM - Assert.assertNotNull(rpcEndPoint.getVersion()); - - // Now change server scmId, so datanode scmId will be - // different from SCM server response scmId - String newScmId = UUID.randomUUID().toString(); - scmServerImpl.setScmId(newScmId); - newState = versionTask.call(); - Assert.assertEquals(EndpointStateMachine.EndPointStates.SHUTDOWN, - newState); - List volumesList = ozoneContainer.getVolumeSet() - .getFailedVolumesList(); - Assert.assertTrue(volumesList.size() == 1); - File expectedScmDir = new File(volumesList.get(0).getHddsRootDir(), - scmServerImpl.getScmId()); - Assert.assertTrue(logCapturer.getOutput().contains("expected scm " + - "directory " + expectedScmDir.getAbsolutePath() + " does not " + - "exist")); - Assert.assertTrue(ozoneContainer.getVolumeSet().getVolumesList().size() - == 0); - Assert.assertTrue(ozoneContainer.getVolumeSet().getFailedVolumesList() - .size() == 1); - - } - } - - - - @Test - /** - * This test makes a call to end point where there is no SCM server. We - * expect that versionTask should be able to handle it. - */ - public void testGetVersionToInvalidEndpoint() throws Exception { - OzoneConfiguration conf = SCMTestUtils.getConf(); - InetSocketAddress nonExistentServerAddress = SCMTestUtils - .getReuseableAddress(); - try (EndpointStateMachine rpcEndPoint = createEndpoint(conf, - nonExistentServerAddress, 1000)) { - rpcEndPoint.setState(EndpointStateMachine.EndPointStates.GETVERSION); - OzoneContainer ozoneContainer = new OzoneContainer( - TestUtils.randomDatanodeDetails(), conf, null); - VersionEndpointTask versionTask = new VersionEndpointTask(rpcEndPoint, - conf, ozoneContainer); - EndpointStateMachine.EndPointStates newState = versionTask.call(); - - // This version call did NOT work, so endpoint should remain in the same - // state. - Assert.assertEquals(EndpointStateMachine.EndPointStates.GETVERSION, - newState); - } - } - - @Test - /** - * This test makes a getVersionRPC call, but the DummyStorageServer is - * going to respond little slowly. We will assert that we are still in the - * GETVERSION state after the timeout. - */ - public void testGetVersionAssertRpcTimeOut() throws Exception { - final long rpcTimeout = 1000; - final long tolerance = 100; - OzoneConfiguration conf = SCMTestUtils.getConf(); - - try (EndpointStateMachine rpcEndPoint = createEndpoint(conf, - serverAddress, (int) rpcTimeout)) { - rpcEndPoint.setState(EndpointStateMachine.EndPointStates.GETVERSION); - OzoneContainer ozoneContainer = new OzoneContainer( - TestUtils.randomDatanodeDetails(), conf, null); - VersionEndpointTask versionTask = new VersionEndpointTask(rpcEndPoint, - conf, ozoneContainer); - - scmServerImpl.setRpcResponseDelay(1500); - long start = Time.monotonicNow(); - EndpointStateMachine.EndPointStates newState = versionTask.call(); - long end = Time.monotonicNow(); - scmServerImpl.setRpcResponseDelay(0); - Assert.assertThat(end - start, lessThanOrEqualTo(rpcTimeout + tolerance)); - Assert.assertEquals(EndpointStateMachine.EndPointStates.GETVERSION, - newState); - } - } - - @Test - public void testRegister() throws Exception { - DatanodeDetails nodeToRegister = TestUtils.randomDatanodeDetails(); - try (EndpointStateMachine rpcEndPoint = createEndpoint( - SCMTestUtils.getConf(), serverAddress, 1000)) { - SCMRegisteredResponseProto responseProto = rpcEndPoint.getEndPoint() - .register(nodeToRegister.getProtoBufMessage(), TestUtils - .createNodeReport( - getStorageReports(nodeToRegister.getUuid())), - TestUtils.getRandomContainerReports(10), - TestUtils.getRandomPipelineReports()); - Assert.assertNotNull(responseProto); - Assert.assertEquals(nodeToRegister.getUuidString(), - responseProto.getDatanodeUUID()); - Assert.assertNotNull(responseProto.getClusterID()); - Assert.assertEquals(10, scmServerImpl. - getContainerCountsForDatanode(nodeToRegister)); - Assert.assertEquals(1, scmServerImpl.getNodeReportsCount(nodeToRegister)); - } - } - - private StorageReportProto getStorageReports(UUID id) { - String storagePath = testDir.getAbsolutePath() + "/" + id; - return TestUtils.createStorageReport(id, storagePath, 100, 10, 90, null); - } - - private EndpointStateMachine registerTaskHelper(InetSocketAddress scmAddress, - int rpcTimeout, boolean clearDatanodeDetails) throws Exception { - Configuration conf = SCMTestUtils.getConf(); - EndpointStateMachine rpcEndPoint = - createEndpoint(conf, - scmAddress, rpcTimeout); - rpcEndPoint.setState(EndpointStateMachine.EndPointStates.REGISTER); - OzoneContainer ozoneContainer = mock(OzoneContainer.class); - when(ozoneContainer.getNodeReport()).thenReturn(TestUtils - .createNodeReport(getStorageReports(UUID.randomUUID()))); - when(ozoneContainer.getContainerReport()).thenReturn( - TestUtils.getRandomContainerReports(10)); - when(ozoneContainer.getPipelineReport()).thenReturn( - TestUtils.getRandomPipelineReports()); - RegisterEndpointTask endpointTask = - new RegisterEndpointTask(rpcEndPoint, conf, ozoneContainer, - mock(StateContext.class)); - if (!clearDatanodeDetails) { - DatanodeDetails datanodeDetails = TestUtils.randomDatanodeDetails(); - endpointTask.setDatanodeDetails(datanodeDetails); - } - endpointTask.call(); - return rpcEndPoint; - } - - @Test - public void testRegisterTask() throws Exception { - try (EndpointStateMachine rpcEndpoint = - registerTaskHelper(serverAddress, 1000, false)) { - // Successful register should move us to Heartbeat state. - Assert.assertEquals(EndpointStateMachine.EndPointStates.HEARTBEAT, - rpcEndpoint.getState()); - } - } - - @Test - public void testRegisterToInvalidEndpoint() throws Exception { - InetSocketAddress address = SCMTestUtils.getReuseableAddress(); - try (EndpointStateMachine rpcEndpoint = - registerTaskHelper(address, 1000, false)) { - Assert.assertEquals(EndpointStateMachine.EndPointStates.REGISTER, - rpcEndpoint.getState()); - } - } - - @Test - public void testRegisterNoContainerID() throws Exception { - InetSocketAddress address = SCMTestUtils.getReuseableAddress(); - try (EndpointStateMachine rpcEndpoint = - registerTaskHelper(address, 1000, true)) { - // No Container ID, therefore we tell the datanode that we would like to - // shutdown. - Assert.assertEquals(EndpointStateMachine.EndPointStates.SHUTDOWN, - rpcEndpoint.getState()); - } - } - - @Test - public void testRegisterRpcTimeout() throws Exception { - final long rpcTimeout = 1000; - final long tolerance = 200; - scmServerImpl.setRpcResponseDelay(1500); - long start = Time.monotonicNow(); - registerTaskHelper(serverAddress, 1000, false).close(); - long end = Time.monotonicNow(); - scmServerImpl.setRpcResponseDelay(0); - Assert.assertThat(end - start, lessThanOrEqualTo(rpcTimeout + tolerance)); - } - - @Test - public void testHeartbeat() throws Exception { - DatanodeDetails dataNode = TestUtils.randomDatanodeDetails(); - try (EndpointStateMachine rpcEndPoint = - createEndpoint(SCMTestUtils.getConf(), - serverAddress, 1000)) { - SCMHeartbeatRequestProto request = SCMHeartbeatRequestProto.newBuilder() - .setDatanodeDetails(dataNode.getProtoBufMessage()) - .setNodeReport(TestUtils.createNodeReport( - getStorageReports(UUID.randomUUID()))) - .build(); - - SCMHeartbeatResponseProto responseProto = rpcEndPoint.getEndPoint() - .sendHeartbeat(request); - Assert.assertNotNull(responseProto); - Assert.assertEquals(0, responseProto.getCommandsCount()); - } - } - - @Test - public void testHeartbeatWithCommandStatusReport() throws Exception { - DatanodeDetails dataNode = TestUtils.randomDatanodeDetails(); - try (EndpointStateMachine rpcEndPoint = - createEndpoint(SCMTestUtils.getConf(), - serverAddress, 1000)) { - // Add some scmCommands for heartbeat response - addScmCommands(); - - - SCMHeartbeatRequestProto request = SCMHeartbeatRequestProto.newBuilder() - .setDatanodeDetails(dataNode.getProtoBufMessage()) - .setNodeReport(TestUtils.createNodeReport( - getStorageReports(UUID.randomUUID()))) - .build(); - - SCMHeartbeatResponseProto responseProto = rpcEndPoint.getEndPoint() - .sendHeartbeat(request); - assertNotNull(responseProto); - assertEquals(3, responseProto.getCommandsCount()); - assertEquals(0, scmServerImpl.getCommandStatusReportCount()); - - // Send heartbeat again from heartbeat endpoint task - final StateContext stateContext = heartbeatTaskHelper( - serverAddress, 3000); - Map map = stateContext.getCommandStatusMap(); - assertNotNull(map); - assertEquals("Should have 3 objects", 3, map.size()); - assertTrue(map.containsKey(Long.valueOf(1))); - assertTrue(map.containsKey(Long.valueOf(2))); - assertTrue(map.containsKey(Long.valueOf(3))); - assertTrue(map.get(Long.valueOf(1)).getType() - .equals(Type.closeContainerCommand)); - assertTrue(map.get(Long.valueOf(2)).getType() - .equals(Type.replicateContainerCommand)); - assertTrue( - map.get(Long.valueOf(3)).getType().equals(Type.deleteBlocksCommand)); - assertTrue(map.get(Long.valueOf(1)).getStatus().equals(Status.PENDING)); - assertTrue(map.get(Long.valueOf(2)).getStatus().equals(Status.PENDING)); - assertTrue(map.get(Long.valueOf(3)).getStatus().equals(Status.PENDING)); - - scmServerImpl.clearScmCommandRequests(); - } - } - - private void addScmCommands() { - SCMCommandProto closeCommand = SCMCommandProto.newBuilder() - .setCloseContainerCommandProto( - CloseContainerCommandProto.newBuilder().setCmdId(1) - .setContainerID(1) - .setReplicationType(ReplicationType.RATIS) - .setPipelineID(PipelineID.randomId().getProtobuf()) - .build()) - .setCommandType(Type.closeContainerCommand) - .build(); - SCMCommandProto replicationCommand = SCMCommandProto.newBuilder() - .setReplicateContainerCommandProto( - ReplicateContainerCommandProto.newBuilder() - .setCmdId(2) - .setContainerID(2) - .build()) - .setCommandType(Type.replicateContainerCommand) - .build(); - SCMCommandProto deleteBlockCommand = SCMCommandProto.newBuilder() - .setDeleteBlocksCommandProto( - DeleteBlocksCommandProto.newBuilder() - .setCmdId(3) - .addDeletedBlocksTransactions( - DeletedBlocksTransaction.newBuilder() - .setContainerID(45) - .setCount(1) - .setTxID(23) - .build()) - .build()) - .setCommandType(Type.deleteBlocksCommand) - .build(); - scmServerImpl.addScmCommandRequest(closeCommand); - scmServerImpl.addScmCommandRequest(deleteBlockCommand); - scmServerImpl.addScmCommandRequest(replicationCommand); - } - - private StateContext heartbeatTaskHelper(InetSocketAddress scmAddress, - int rpcTimeout) throws Exception { - Configuration conf = SCMTestUtils.getConf(); - conf.set(DFS_DATANODE_DATA_DIR_KEY, testDir.getAbsolutePath()); - conf.set(OZONE_METADATA_DIRS, testDir.getAbsolutePath()); - // Mini Ozone cluster will not come up if the port is not true, since - // Ratis will exit if the server port cannot be bound. We can remove this - // hard coding once we fix the Ratis default behaviour. - conf.setBoolean(OzoneConfigKeys.DFS_CONTAINER_RATIS_IPC_RANDOM_PORT, true); - - - // Create a datanode state machine for stateConext used by endpoint task - try (DatanodeStateMachine stateMachine = new DatanodeStateMachine( - TestUtils.randomDatanodeDetails(), conf); - EndpointStateMachine rpcEndPoint = - createEndpoint(conf, scmAddress, rpcTimeout)) { - HddsProtos.DatanodeDetailsProto datanodeDetailsProto = - TestUtils.randomDatanodeDetails().getProtoBufMessage(); - rpcEndPoint.setState(EndpointStateMachine.EndPointStates.HEARTBEAT); - - final StateContext stateContext = - new StateContext(conf, DatanodeStateMachine.DatanodeStates.RUNNING, - stateMachine); - - HeartbeatEndpointTask endpointTask = - new HeartbeatEndpointTask(rpcEndPoint, conf, stateContext); - endpointTask.setDatanodeDetailsProto(datanodeDetailsProto); - endpointTask.call(); - Assert.assertNotNull(endpointTask.getDatanodeDetailsProto()); - - Assert.assertEquals(EndpointStateMachine.EndPointStates.HEARTBEAT, - rpcEndPoint.getState()); - return stateContext; - } - } - - @Test - public void testHeartbeatTask() throws Exception { - heartbeatTaskHelper(serverAddress, 1000); - } - - @Test - public void testHeartbeatTaskToInvalidNode() throws Exception { - InetSocketAddress invalidAddress = SCMTestUtils.getReuseableAddress(); - heartbeatTaskHelper(invalidAddress, 1000); - } - - @Test - public void testHeartbeatTaskRpcTimeOut() throws Exception { - final long rpcTimeout = 1000; - final long tolerance = 200; - scmServerImpl.setRpcResponseDelay(1500); - long start = Time.monotonicNow(); - InetSocketAddress invalidAddress = SCMTestUtils.getReuseableAddress(); - heartbeatTaskHelper(invalidAddress, 1000); - long end = Time.monotonicNow(); - scmServerImpl.setRpcResponseDelay(0); - Assert.assertThat(end - start, - lessThanOrEqualTo(rpcTimeout + tolerance)); - } - -} diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/common/package-info.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/common/package-info.java deleted file mode 100644 index da2ae843e11..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/common/package-info.java +++ /dev/null @@ -1,22 +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 - * - * 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. - * - */ -/** - * Make CheckStyle Happy. - */ -package org.apache.hadoop.ozone.container.common; \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/placement/TestContainerPlacement.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/placement/TestContainerPlacement.java deleted file mode 100644 index 1c80880d01d..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/placement/TestContainerPlacement.java +++ /dev/null @@ -1,137 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.container.placement; - -import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.scm.container.MockNodeManager; -import org.apache.hadoop.hdds.scm.container.placement.algorithms - .SCMContainerPlacementCapacity; -import org.apache.hadoop.hdds.scm.container.placement.algorithms - .SCMContainerPlacementRandom; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.hdds.scm.node.NodeManager; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.ozone.OzoneConsts; -import org.junit.Assert; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - -import static org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState - .HEALTHY; -import static org.junit.Assert.assertEquals; - -/** - * Asserts that allocation strategy works as expected. - */ -public class TestContainerPlacement { - - private DescriptiveStatistics computeStatistics(NodeManager nodeManager) { - DescriptiveStatistics descriptiveStatistics = new DescriptiveStatistics(); - for (DatanodeDetails dd : nodeManager.getNodes(HEALTHY)) { - float weightedValue = - nodeManager.getNodeStat(dd).get().getScmUsed().get() / (float) - nodeManager.getNodeStat(dd).get().getCapacity().get(); - descriptiveStatistics.addValue(weightedValue); - } - return descriptiveStatistics; - } - - /** - * This test simulates lots of Cluster I/O and updates the metadata in SCM. - * We simulate adding and removing containers from the cluster. It asserts - * that our placement algorithm has taken the capacity of nodes into - * consideration by asserting that standard deviation of used space on these - * has improved. - */ - @Test - public void testCapacityPlacementYieldsBetterDataDistribution() throws - SCMException { - final int opsCount = 200 * 1000; - final int nodesRequired = 3; - Random random = new Random(); - - // The nature of init code in MockNodeManager yields similar clusters. - MockNodeManager nodeManagerCapacity = new MockNodeManager(true, 100); - MockNodeManager nodeManagerRandom = new MockNodeManager(true, 100); - DescriptiveStatistics beforeCapacity = - computeStatistics(nodeManagerCapacity); - DescriptiveStatistics beforeRandom = computeStatistics(nodeManagerRandom); - - //Assert that our initial layout of clusters are similar. - assertEquals(beforeCapacity.getStandardDeviation(), beforeRandom - .getStandardDeviation(), 0.001); - - SCMContainerPlacementCapacity capacityPlacer = new - SCMContainerPlacementCapacity(nodeManagerCapacity, new Configuration()); - SCMContainerPlacementRandom randomPlacer = new - SCMContainerPlacementRandom(nodeManagerRandom, new Configuration()); - - for (int x = 0; x < opsCount; x++) { - long containerSize = random.nextInt(100) * OzoneConsts.GB; - List nodesCapacity = - capacityPlacer.chooseDatanodes(new ArrayList<>(), nodesRequired, - containerSize); - assertEquals(nodesRequired, nodesCapacity.size()); - - List nodesRandom = - randomPlacer.chooseDatanodes(nodesCapacity, nodesRequired, - containerSize); - - // One fifth of all calls are delete - if (x % 5 == 0) { - deleteContainer(nodeManagerCapacity, nodesCapacity, containerSize); - deleteContainer(nodeManagerRandom, nodesRandom, containerSize); - } else { - createContainer(nodeManagerCapacity, nodesCapacity, containerSize); - createContainer(nodeManagerRandom, nodesRandom, containerSize); - } - } - DescriptiveStatistics postCapacity = computeStatistics(nodeManagerCapacity); - DescriptiveStatistics postRandom = computeStatistics(nodeManagerRandom); - - // This is a very bold claim, and needs large number of I/O operations. - // The claim in this assertion is that we improved the data distribution - // of this cluster in relation to the start state of the cluster. - Assert.assertTrue(beforeCapacity.getStandardDeviation() > - postCapacity.getStandardDeviation()); - - // This asserts that Capacity placement yields a better placement - // algorithm than random placement, since both cluster started at an - // identical state. - - Assert.assertTrue(postRandom.getStandardDeviation() > - postCapacity.getStandardDeviation()); - } - - private void deleteContainer(MockNodeManager nodeManager, - List nodes, long containerSize) { - for (DatanodeDetails dd : nodes) { - nodeManager.delContainer(dd, containerSize); - } - } - - private void createContainer(MockNodeManager nodeManager, - List nodes, long containerSize) { - for (DatanodeDetails dd : nodes) { - nodeManager.addContainer(dd, containerSize); - } - } -} diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/placement/TestDatanodeMetrics.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/placement/TestDatanodeMetrics.java deleted file mode 100644 index 7150d1b94f4..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/placement/TestDatanodeMetrics.java +++ /dev/null @@ -1,59 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.container.placement; - -import org.apache.hadoop.hdds.scm.container.placement.metrics.SCMNodeMetric; -import org.apache.hadoop.hdds.scm.container.placement.metrics.SCMNodeStat; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * Tests that test Metrics that support placement. - */ -public class TestDatanodeMetrics { - @Rule - public ExpectedException exception = ExpectedException.none(); - @Test - public void testSCMNodeMetric() { - SCMNodeStat stat = new SCMNodeStat(100L, 10L, 90L); - assertEquals((long) stat.getCapacity().get(), 100L); - assertEquals((long) stat.getScmUsed().get(), 10L); - assertEquals((long) stat.getRemaining().get(), 90L); - SCMNodeMetric metric = new SCMNodeMetric(stat); - - SCMNodeStat newStat = new SCMNodeStat(100L, 10L, 90L); - assertEquals((long) stat.getCapacity().get(), 100L); - assertEquals((long) stat.getScmUsed().get(), 10L); - assertEquals((long) stat.getRemaining().get(), 90L); - - SCMNodeMetric newMetric = new SCMNodeMetric(newStat); - assertTrue(metric.isEqual(newMetric.get())); - - newMetric.add(stat); - assertTrue(newMetric.isGreater(metric.get())); - - SCMNodeMetric zeroMetric = new SCMNodeMetric(new SCMNodeStat()); - // Assert we can handle zero capacity. - assertTrue(metric.isGreater(zeroMetric.get())); - - } -} diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/placement/package-info.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/placement/package-info.java deleted file mode 100644 index ddd751c3795..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/placement/package-info.java +++ /dev/null @@ -1,22 +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 - * - * 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. - * - */ -/** - * Make CheckStyle Happy. - */ -package org.apache.hadoop.ozone.container.placement; \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/replication/package-info.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/replication/package-info.java deleted file mode 100644 index 318c54d9585..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/replication/package-info.java +++ /dev/null @@ -1,18 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.container.replication; -// Test classes for replication. \ No newline at end of file diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/testutils/ReplicationNodeManagerMock.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/testutils/ReplicationNodeManagerMock.java deleted file mode 100644 index 74c3932eba0..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/testutils/ReplicationNodeManagerMock.java +++ /dev/null @@ -1,402 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.container.testutils; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.PipelineReportsProto; -import org.apache.hadoop.hdds.scm.container.ContainerID; -import org.apache.hadoop.hdds.scm.container.common.helpers.Pipeline; -import org.apache.hadoop.hdds.scm.container.common.helpers.PipelineID; -import org.apache.hadoop.hdds.scm.container.placement.metrics.SCMNodeMetric; -import org.apache.hadoop.hdds.scm.container.placement.metrics.SCMNodeStat; -import org.apache.hadoop.hdds.scm.exceptions.SCMException; -import org.apache.hadoop.hdds.scm.node.CommandQueue; -import org.apache.hadoop.hdds.scm.node.NodeManager; -import org.apache.hadoop.hdds.scm.node.states.NodeNotFoundException; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.NodeReportProto; -import org.apache.hadoop.hdds.protocol.proto - .StorageContainerDatanodeProtocolProtos.SCMVersionRequestProto; -import org.apache.hadoop.hdds.scm.node.states.ReportResult; -import org.apache.hadoop.hdds.server.events.EventPublisher; -import org.apache.hadoop.ozone.protocol.VersionResponse; -import org.apache.hadoop.ozone.protocol.commands.CommandForDatanode; -import org.apache.hadoop.ozone.protocol.commands.RegisteredCommand; -import org.apache.hadoop.ozone.protocol.commands.SCMCommand; - -import java.io.IOException; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - -/** - * A Node Manager to test replication. - */ -public class ReplicationNodeManagerMock implements NodeManager { - private final Map nodeStateMap; - private final CommandQueue commandQueue; - - /** - * A list of Datanodes and current states. - * @param nodeState A node state map. - */ - public ReplicationNodeManagerMock(Map nodeState, - CommandQueue commandQueue) { - Preconditions.checkNotNull(nodeState); - this.nodeStateMap = nodeState; - this.commandQueue = commandQueue; - } - - /** - * Get the minimum number of nodes to get out of chill mode. - * - * @return int - */ - @Override - public int getMinimumChillModeNodes() { - return 0; - } - - /** - * Returns a chill mode status string. - * - * @return String - */ - @Override - public String getChillModeStatus() { - return null; - } - - /** - * Get the number of data nodes that in all states. - * - * @return A state to number of nodes that in this state mapping - */ - @Override - public Map getNodeCount() { - return null; - } - - /** - * Removes a data node from the management of this Node Manager. - * - * @param node - DataNode. - * @throws NodeNotFoundException - */ - @Override - public void removeNode(DatanodeDetails node) - throws NodeNotFoundException { - nodeStateMap.remove(node); - - } - - /** - * Gets all Live Datanodes that is currently communicating with SCM. - * - * @param nodestate - State of the node - * @return List of Datanodes that are Heartbeating SCM. - */ - @Override - public List getNodes(NodeState nodestate) { - return null; - } - - /** - * Returns the Number of Datanodes that are communicating with SCM. - * - * @param nodestate - State of the node - * @return int -- count - */ - @Override - public int getNodeCount(NodeState nodestate) { - return 0; - } - - /** - * Get all datanodes known to SCM. - * - * @return List of DatanodeDetails known to SCM. - */ - @Override - public List getAllNodes() { - return null; - } - - /** - * Chill mode is the period when node manager waits for a minimum - * configured number of datanodes to report in. This is called chill mode - * to indicate the period before node manager gets into action. - *

- * Forcefully exits the chill mode, even if we have not met the minimum - * criteria of the nodes reporting in. - */ - @Override - public void forceExitChillMode() { - - } - - /** - * Puts the node manager into manual chill mode. - */ - @Override - public void enterChillMode() { - - } - - /** - * Brings node manager out of manual chill mode. - */ - @Override - public void exitChillMode() { - - } - - /** - * Returns true if node manager is out of chill mode, else false. - * @return true if out of chill mode, else false - */ - @Override - public boolean isOutOfChillMode() { - return !nodeStateMap.isEmpty(); - } - - /** - * Returns the aggregated node stats. - * - * @return the aggregated node stats. - */ - @Override - public SCMNodeStat getStats() { - return null; - } - - /** - * Return a map of node stats. - * - * @return a map of individual node stats (live/stale but not dead). - */ - @Override - public Map getNodeStats() { - return null; - } - - /** - * Return the node stat of the specified datanode. - * - * @param dd - datanode details. - * @return node stat if it is live/stale, null if it is decommissioned or - * doesn't exist. - */ - @Override - public SCMNodeMetric getNodeStat(DatanodeDetails dd) { - return null; - } - - - /** - * Returns the node state of a specific node. - * - * @param dd - DatanodeDetails - * @return Healthy/Stale/Dead. - */ - @Override - public NodeState getNodeState(DatanodeDetails dd) { - return nodeStateMap.get(dd); - } - - /** - * Get set of pipelines a datanode is part of. - * @param dnId - datanodeID - * @return Set of PipelineID - */ - @Override - public Set getPipelineByDnID(UUID dnId) { - throw new UnsupportedOperationException("Not yet implemented"); - } - - /** - * Add pipeline information in the NodeManager. - * @param pipeline - Pipeline to be added - */ - @Override - public void addPipeline(Pipeline pipeline) { - throw new UnsupportedOperationException("Not yet implemented"); - } - - /** - * Remove a pipeline information from the NodeManager. - * @param pipeline - Pipeline to be removed - */ - @Override - public void removePipeline(Pipeline pipeline) { - throw new UnsupportedOperationException("Not yet implemented"); - } - - /** - * Update set of containers available on a datanode. - * @param uuid - DatanodeID - * @param containerIds - Set of containerIDs - * @throws SCMException - if datanode is not known. For new datanode use - * addDatanodeInContainerMap call. - */ - @Override - public void setContainersForDatanode(UUID uuid, Set containerIds) - throws SCMException { - throw new UnsupportedOperationException("Not yet implemented"); - } - - /** - * Process containerReport received from datanode. - * @param uuid - DataonodeID - * @param containerIds - Set of containerIDs - * @return The result after processing containerReport - */ - @Override - public ReportResult processContainerReport(UUID uuid, - Set containerIds) { - throw new UnsupportedOperationException("Not yet implemented"); - } - - /** - * Return set of containerIDs available on a datanode. - * @param uuid - DatanodeID - * @return - set of containerIDs - */ - @Override - public Set getContainers(UUID uuid) { - throw new UnsupportedOperationException("Not yet implemented"); - } - - /** - * Insert a new datanode with set of containerIDs for containers available - * on it. - * @param uuid - DatanodeID - * @param containerIDs - Set of ContainerIDs - * @throws SCMException - if datanode already exists - */ - @Override - public void addDatanodeInContainerMap(UUID uuid, - Set containerIDs) throws SCMException { - throw new UnsupportedOperationException("Not yet implemented"); - } - - /** - * Closes this stream and releases any system resources associated - * with it. If the stream is already closed then invoking this - * method has no effect. - *

- *

As noted in {@link AutoCloseable#close()}, cases where the - * close may fail require careful attention. It is strongly advised - * to relinquish the underlying resources and to internally - * mark the {@code Closeable} as closed, prior to throwing - * the {@code IOException}. - * - * @throws IOException if an I/O error occurs - */ - @Override - public void close() throws IOException { - - } - - /** - * Gets the version info from SCM. - * - * @param versionRequest - version Request. - * @return - returns SCM version info and other required information needed by - * datanode. - */ - @Override - public VersionResponse getVersion(SCMVersionRequestProto versionRequest) { - return null; - } - - /** - * Register the node if the node finds that it is not registered with any SCM. - * - * @param dd DatanodeDetailsProto - * @param nodeReport NodeReportProto - * @return SCMHeartbeatResponseProto - */ - @Override - public RegisteredCommand register(DatanodeDetails dd, - NodeReportProto nodeReport, - PipelineReportsProto pipelineReportsProto) { - return null; - } - - /** - * Send heartbeat to indicate the datanode is alive and doing well. - * - * @param dd - Datanode Details. - * @return SCMheartbeat response list - */ - @Override - public List processHeartbeat(DatanodeDetails dd) { - return null; - } - - /** - * Clears all nodes from the node Manager. - */ - public void clearMap() { - this.nodeStateMap.clear(); - } - - /** - * Adds a node to the existing Node manager. This is used only for test - * purposes. - * @param id DatanodeDetails - * @param state State you want to put that node to. - */ - public void addNode(DatanodeDetails id, NodeState state) { - nodeStateMap.put(id, state); - } - - @Override - public void addDatanodeCommand(UUID dnId, SCMCommand command) { - this.commandQueue.addCommand(dnId, command); - } - - /** - * Empty implementation for processNodeReport. - * @param dnUuid - * @param nodeReport - */ - @Override - public void processNodeReport(UUID dnUuid, NodeReportProto nodeReport) { - // do nothing. - } - - @Override - public void onMessage(CommandForDatanode commandForDatanode, - EventPublisher publisher) { - // do nothing. - } - - /** - * Empty implementation for processDeadNode. - * @param dnUuid - */ - @Override - public void processDeadNode(UUID dnUuid) { - // do nothing. - } -} diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/testutils/package-info.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/testutils/package-info.java deleted file mode 100644 index 4e8a90bf1d4..00000000000 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/testutils/package-info.java +++ /dev/null @@ -1,18 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.container.testutils; -// Helper classes for ozone and container tests. \ No newline at end of file diff --git a/hadoop-hdds/tools/pom.xml b/hadoop-hdds/tools/pom.xml deleted file mode 100644 index 37c7d9d74ee..00000000000 --- a/hadoop-hdds/tools/pom.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - 4.0.0 - - org.apache.hadoop - hadoop-hdds - 0.3.0-SNAPSHOT - - - hadoop-hdds-tools - 0.3.0-SNAPSHOT - Apache Hadoop Distributed Data Store Tools - Apache Hadoop HDDS Tools - jar - - - - org.apache.hadoop - hadoop-hdds-common - - - org.apache.hadoop - hadoop-hdds-client - - - org.apache.hadoop - hadoop-common - - - commons-cli - commons-cli - - - org.xerial - sqlite-jdbc - 3.8.7 - - - - - diff --git a/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/SCMCLI.java b/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/SCMCLI.java deleted file mode 100644 index 59cd0ba9a46..00000000000 --- a/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/SCMCLI.java +++ /dev/null @@ -1,150 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.cli; - -import java.io.IOException; -import java.net.InetSocketAddress; - -import org.apache.hadoop.conf.StorageUnit; -import org.apache.hadoop.hdds.HddsUtils; -import org.apache.hadoop.hdds.cli.GenericCli; -import org.apache.hadoop.hdds.cli.HddsVersionProvider; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.scm.ScmConfigKeys; -import org.apache.hadoop.hdds.scm.XceiverClientManager; -import org.apache.hadoop.hdds.scm.cli.container.CloseSubcommand; -import org.apache.hadoop.hdds.scm.cli.container.CreateSubcommand; -import org.apache.hadoop.hdds.scm.cli.container.DeleteSubcommand; -import org.apache.hadoop.hdds.scm.cli.container.InfoSubcommand; -import org.apache.hadoop.hdds.scm.cli.container.ListSubcommand; -import org.apache.hadoop.hdds.scm.client.ContainerOperationClient; -import org.apache.hadoop.hdds.scm.client.ScmClient; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo; -import org.apache.hadoop.hdds.scm.protocolPB - .StorageContainerLocationProtocolClientSideTranslatorPB; -import org.apache.hadoop.hdds.scm.protocolPB.StorageContainerLocationProtocolPB; -import org.apache.hadoop.ipc.Client; -import org.apache.hadoop.ipc.ProtobufRpcEngine; -import org.apache.hadoop.ipc.RPC; -import org.apache.hadoop.net.NetUtils; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.security.UserGroupInformation; -import org.apache.hadoop.util.NativeCodeLoader; - -import org.apache.commons.lang3.StringUtils; -import static org.apache.hadoop.hdds.HddsUtils.getScmAddressForClients; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_CLIENT_ADDRESS_KEY; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys.OZONE_SCM_CONTAINER_SIZE; -import static org.apache.hadoop.hdds.scm.ScmConfigKeys - .OZONE_SCM_CONTAINER_SIZE_DEFAULT; -import org.apache.log4j.ConsoleAppender; -import org.apache.log4j.Level; -import org.apache.log4j.LogManager; -import org.apache.log4j.Logger; -import org.apache.log4j.PatternLayout; -import picocli.CommandLine.Command; -import picocli.CommandLine.Option; - -/** - * This class is the CLI of SCM. - */ - -/** - * Container subcommand. - */ -@Command(name = "ozone scmcli", hidden = true, description = - "Developer tools to handle SCM specific " - + "operations.", - versionProvider = HddsVersionProvider.class, - subcommands = { - ListSubcommand.class, - InfoSubcommand.class, - DeleteSubcommand.class, - CreateSubcommand.class, - CloseSubcommand.class - }, - mixinStandardHelpOptions = true) -public class SCMCLI extends GenericCli { - - @Option(names = {"--scm"}, description = "The destination scm (host:port)") - private String scm = ""; - - /** - * Main for the scm shell Command handling. - * - * @param argv - System Args Strings[] - * @throws Exception - */ - public static void main(String[] argv) throws Exception { - - LogManager.resetConfiguration(); - Logger.getRootLogger().setLevel(Level.INFO); - Logger.getRootLogger() - .addAppender(new ConsoleAppender(new PatternLayout("%m%n"))); - Logger.getLogger(NativeCodeLoader.class).setLevel(Level.ERROR); - - new SCMCLI().run(argv); - } - - public ScmClient createScmClient() - throws IOException { - - OzoneConfiguration ozoneConf = createOzoneConfiguration(); - if (StringUtils.isNotEmpty(scm)) { - ozoneConf.set(OZONE_SCM_CLIENT_ADDRESS_KEY, scm); - } - if (!HddsUtils.getHostNameFromConfigKeys(ozoneConf, - ScmConfigKeys.OZONE_SCM_CLIENT_ADDRESS_KEY).isPresent()) { - - throw new IllegalArgumentException( - ScmConfigKeys.OZONE_SCM_CLIENT_ADDRESS_KEY - + " should be set in ozone-site.xml or with the --scm option"); - } - - long version = RPC.getProtocolVersion( - StorageContainerLocationProtocolPB.class); - InetSocketAddress scmAddress = - getScmAddressForClients(ozoneConf); - int containerSizeGB = (int) ozoneConf.getStorageSize( - OZONE_SCM_CONTAINER_SIZE, OZONE_SCM_CONTAINER_SIZE_DEFAULT, - StorageUnit.GB); - ContainerOperationClient - .setContainerSizeB(containerSizeGB * OzoneConsts.GB); - - RPC.setProtocolEngine(ozoneConf, StorageContainerLocationProtocolPB.class, - ProtobufRpcEngine.class); - StorageContainerLocationProtocolClientSideTranslatorPB client = - new StorageContainerLocationProtocolClientSideTranslatorPB( - RPC.getProxy(StorageContainerLocationProtocolPB.class, version, - scmAddress, UserGroupInformation.getCurrentUser(), ozoneConf, - NetUtils.getDefaultSocketFactory(ozoneConf), - Client.getRpcTimeout(ozoneConf))); - return new ContainerOperationClient( - client, new XceiverClientManager(ozoneConf)); - } - - public void checkContainerExists(ScmClient scmClient, long containerId) - throws IOException { - ContainerInfo container = scmClient.getContainer(containerId); - if (container == null) { - throw new IllegalArgumentException("No such container " + containerId); - } - } - -} diff --git a/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/container/CloseSubcommand.java b/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/container/CloseSubcommand.java deleted file mode 100644 index 173d0ce0231..00000000000 --- a/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/container/CloseSubcommand.java +++ /dev/null @@ -1,54 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.cli.container; - -import java.util.concurrent.Callable; - -import org.apache.hadoop.hdds.cli.HddsVersionProvider; -import org.apache.hadoop.hdds.scm.cli.SCMCLI; -import org.apache.hadoop.hdds.scm.client.ScmClient; - -import picocli.CommandLine.Command; -import picocli.CommandLine.Parameters; -import picocli.CommandLine.ParentCommand; - -/** - * The handler of close container command. - */ -@Command( - name = "close", - description = "close container", - mixinStandardHelpOptions = true, - versionProvider = HddsVersionProvider.class) -public class CloseSubcommand implements Callable { - - @ParentCommand - private SCMCLI parent; - - @Parameters(description = "Id of the container to close") - private long containerId; - - @Override - public Void call() throws Exception { - try (ScmClient scmClient = parent.createScmClient()) { - parent.checkContainerExists(scmClient, containerId); - scmClient.closeContainer(containerId); - return null; - } - } -} diff --git a/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/container/CreateSubcommand.java b/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/container/CreateSubcommand.java deleted file mode 100644 index 1dda9c485ed..00000000000 --- a/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/container/CreateSubcommand.java +++ /dev/null @@ -1,65 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.cli.container; - -import java.util.concurrent.Callable; - -import org.apache.hadoop.hdds.cli.HddsVersionProvider; -import org.apache.hadoop.hdds.scm.cli.SCMCLI; -import org.apache.hadoop.hdds.scm.client.ScmClient; -import org.apache.hadoop.hdds.scm.container.common.helpers - .ContainerWithPipeline; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import picocli.CommandLine.Command; -import picocli.CommandLine.Option; -import picocli.CommandLine.ParentCommand; - -/** - * This is the handler that process container creation command. - */ -@Command( - name = "create", - description = "Create container", - mixinStandardHelpOptions = true, - versionProvider = HddsVersionProvider.class) -public class CreateSubcommand implements Callable { - - private static final Logger LOG = - LoggerFactory.getLogger(CreateSubcommand.class); - - @ParentCommand - private SCMCLI parent; - - @Option(description = "Owner of the new container", defaultValue = "OZONE", - required = false, names = { - "-o", "--owner"}) - - private String owner; - - @Override - public Void call() throws Exception { - try (ScmClient scmClient = parent.createScmClient()) { - ContainerWithPipeline container = scmClient.createContainer(owner); - LOG.info("Container {} is created.", - container.getContainerInfo().getContainerID()); - return null; - } - } -} diff --git a/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/container/DeleteSubcommand.java b/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/container/DeleteSubcommand.java deleted file mode 100644 index c163a3a9a53..00000000000 --- a/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/container/DeleteSubcommand.java +++ /dev/null @@ -1,60 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.cli.container; - -import java.util.concurrent.Callable; - -import org.apache.hadoop.hdds.cli.HddsVersionProvider; -import org.apache.hadoop.hdds.scm.cli.SCMCLI; -import org.apache.hadoop.hdds.scm.client.ScmClient; - -import picocli.CommandLine.Command; -import picocli.CommandLine.Option; -import picocli.CommandLine.Parameters; -import picocli.CommandLine.ParentCommand; - -/** - * This is the handler that process delete container command. - */ -@Command( - name = "delete", - description = "Delete container", - mixinStandardHelpOptions = true, - versionProvider = HddsVersionProvider.class) -public class DeleteSubcommand implements Callable { - - @Parameters(description = "Id of the container to close") - private long containerId; - - @Option(names = {"-f", - "--force"}, description = "forcibly delete the container") - private boolean force; - - @ParentCommand - private SCMCLI parent; - - @Override - public Void call() throws Exception { - try (ScmClient scmClient = parent.createScmClient()) { - parent.checkContainerExists(scmClient, containerId); - scmClient.deleteContainer(containerId, force); - return null; - } - } -} diff --git a/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/container/InfoSubcommand.java b/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/container/InfoSubcommand.java deleted file mode 100644 index 0135df38407..00000000000 --- a/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/container/InfoSubcommand.java +++ /dev/null @@ -1,94 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.cli.container; - -import java.util.concurrent.Callable; -import java.util.stream.Collectors; - -import org.apache.hadoop.hdds.cli.HddsVersionProvider; -import org.apache.hadoop.hdds.protocol.DatanodeDetails; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerData; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos - .ContainerLifeCycleState; -import org.apache.hadoop.hdds.scm.cli.SCMCLI; -import org.apache.hadoop.hdds.scm.client.ScmClient; -import org.apache.hadoop.hdds.scm.container.common.helpers - .ContainerWithPipeline; - -import com.google.common.base.Preconditions; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import picocli.CommandLine.Command; -import picocli.CommandLine.Parameters; -import picocli.CommandLine.ParentCommand; - -/** - * This is the handler that process container info command. - */ -@Command( - name = "info", - description = "Show information about a specific container", - mixinStandardHelpOptions = true, - versionProvider = HddsVersionProvider.class) -public class InfoSubcommand implements Callable { - - private static final Logger LOG = - LoggerFactory.getLogger(InfoSubcommand.class); - - @ParentCommand - private SCMCLI parent; - - @Parameters(description = "Decimal id of the container.") - private long containerID; - - @Override - public Void call() throws Exception { - try (ScmClient scmClient = parent.createScmClient()) { - ContainerWithPipeline container = scmClient. - getContainerWithPipeline(containerID); - Preconditions.checkNotNull(container, "Container cannot be null"); - - ContainerData containerData = scmClient.readContainer(container - .getContainerInfo().getContainerID(), container.getPipeline()); - - // Print container report info. - LOG.info("Container id: {}", containerID); - String openStatus = - containerData.getState() == ContainerLifeCycleState.OPEN ? "OPEN" : - "CLOSED"; - LOG.info("Container State: {}", openStatus); - LOG.info("Container Path: {}", containerData.getContainerPath()); - - // Output meta data. - String metadataStr = containerData.getMetadataList().stream().map( - p -> p.getKey() + ":" + p.getValue()) - .collect(Collectors.joining(", ")); - LOG.info("Container Metadata: {}", metadataStr); - - // Print pipeline of an existing container. - LOG.info("LeaderID: {}", container.getPipeline() - .getLeader().getHostName()); - String machinesStr = container.getPipeline() - .getMachines().stream().map( - DatanodeDetails::getHostName).collect(Collectors.joining(",")); - LOG.info("Datanodes: [{}]", machinesStr); - return null; - } - } -} diff --git a/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/container/ListSubcommand.java b/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/container/ListSubcommand.java deleted file mode 100644 index 0f520fd1b74..00000000000 --- a/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/container/ListSubcommand.java +++ /dev/null @@ -1,83 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hdds.scm.cli.container; - -import java.io.IOException; -import java.util.List; -import java.util.concurrent.Callable; - -import org.apache.hadoop.hdds.cli.HddsVersionProvider; -import org.apache.hadoop.hdds.scm.cli.SCMCLI; -import org.apache.hadoop.hdds.scm.client.ScmClient; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo; -import org.apache.hadoop.ozone.web.utils.JsonUtils; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import picocli.CommandLine.Command; -import picocli.CommandLine.Help.Visibility; -import picocli.CommandLine.Option; -import picocli.CommandLine.ParentCommand; - -/** - * This is the handler that process container list command. - */ -@Command( - name = "list", - description = "List containers", - mixinStandardHelpOptions = true, - versionProvider = HddsVersionProvider.class) -public class ListSubcommand implements Callable { - - private static final Logger LOG = - LoggerFactory.getLogger(ListSubcommand.class); - - @ParentCommand - private SCMCLI parent; - - @Option(names = {"-s", "--start"}, - description = "Container id to start the iteration", required = true) - private long startId; - - @Option(names = {"-c", "--count"}, - description = "Maximum number of containers to list", - defaultValue = "20", showDefaultValue = Visibility.ALWAYS) - private int count = 20; - - private void outputContainerInfo(ContainerInfo containerInfo) - throws IOException { - // Print container report info. - LOG.info("{}", JsonUtils.toJsonStringWithDefaultPrettyPrinter( - containerInfo.toJsonString())); - } - - @Override - public Void call() throws Exception { - try (ScmClient scmClient = parent.createScmClient()) { - - List containerList = - scmClient.listContainer(startId, count); - - // Output data list - for (ContainerInfo container : containerList) { - outputContainerInfo(container); - } - return null; - } - } -} diff --git a/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/container/package-info.java b/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/container/package-info.java deleted file mode 100644 index ff8adbc56f1..00000000000 --- a/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/container/package-info.java +++ /dev/null @@ -1,22 +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 - * - * 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. - */ - -/** - * Contains all of the container related scm commands. - */ -package org.apache.hadoop.hdds.scm.cli.container; \ No newline at end of file diff --git a/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/package-info.java b/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/package-info.java deleted file mode 100644 index d358b3cf6a5..00000000000 --- a/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/package-info.java +++ /dev/null @@ -1,23 +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 - *

- * 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. - *

- * SCM related cli tools. - */ -/** - * SCM related cli tools. - */ -package org.apache.hadoop.hdds.scm.cli; \ No newline at end of file diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/datanode/datanode.html b/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/datanode/datanode.html index 0fdf552e083..174a9dc1b65 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/datanode/datanode.html +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/datanode/datanode.html @@ -98,52 +98,6 @@ {/dn.BPServiceActorInfo} -{#ozone.enabled} -

- - - - - - - - - - - {#ozone.SCMServers} - - - - - - - - {/ozone.SCMServers} -
SCM AddressStatusVersionMissed countLast heartbeat
{addressString}{state}{versionNumber}{missedCount}s{lastSuccessfulHeartbeat|elapsed|fmt_time}
- - - - - - - - - - - - - {#ozone.LocationReport} - - - - - - - - {/ozone.LocationReport} -
IDCapacityRemainingSCM usedfailed
{id}{capacity|fmt_bytes}{remaining|fmt_bytes}{scmUsed|fmt_bytes}{failed}
-{/ozone.enabled} - @@ -179,4 +133,4 @@ - \ No newline at end of file + diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/resources/log4j.properties b/hadoop-hdfs-project/hadoop-hdfs/src/test/resources/log4j.properties index 2d1c98bb180..bd5a4dda413 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/test/resources/log4j.properties +++ b/hadoop-hdfs-project/hadoop-hdfs/src/test/resources/log4j.properties @@ -48,26 +48,3 @@ log4j.appender.DNMETRICSRFA.layout.ConversionPattern=%d{ISO8601} %m%n log4j.appender.DNMETRICSRFA.MaxBackupIndex=1 log4j.appender.DNMETRICSRFA.MaxFileSize=64MB -# -# Add a logger for ozone that is separate from the Datanode. -# -log4j.logger.org.apache.hadoop.ozone=INFO,OZONE,FILE - -# Do not log into datanode logs. Remove this line to have single log. -log4j.additivity.org.apache.hadoop.ozone=false - -# For development purposes, log both to console and log file. -log4j.appender.OZONE=org.apache.log4j.ConsoleAppender -log4j.appender.OZONE.Threshold=ALL -log4j.appender.OZONE.layout=org.apache.log4j.PatternLayout -log4j.appender.OZONE.layout.ConversionPattern=%d{ISO8601} [%t] %-5p %c{2} (%F:%M(%L)) \ - %X{component} %X{function} %X{resource} %X{user} %X{request} - %m%n - -# Real ozone logger that writes to ozone.log -log4j.appender.FILE=org.apache.log4j.DailyRollingFileAppender -log4j.appender.FILE.File=${hadoop.log.dir}/ozone.log -log4j.appender.FILE.Threshold=debug -log4j.appender.FILE.layout=org.apache.log4j.PatternLayout -log4j.appender.FILE.layout.ConversionPattern=%d{ISO8601} [%t] %-5p \ - (%F:%L) %X{function} %X{resource} %X{user} %X{request} - \ - %m%n diff --git a/hadoop-ozone/client/pom.xml b/hadoop-ozone/client/pom.xml deleted file mode 100644 index e471710c293..00000000000 --- a/hadoop-ozone/client/pom.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - 4.0.0 - - org.apache.hadoop - hadoop-ozone - 0.3.0-SNAPSHOT - - hadoop-ozone-client - 0.3.0-SNAPSHOT - Apache Hadoop Ozone Client - Apache Hadoop Ozone Client - jar - - - - org.apache.hadoop - hadoop-ozone-common - - - \ No newline at end of file diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/BucketArgs.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/BucketArgs.java deleted file mode 100644 index 0da52dc0339..00000000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/BucketArgs.java +++ /dev/null @@ -1,123 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client; - -import org.apache.hadoop.fs.StorageType; -import org.apache.hadoop.ozone.OzoneAcl; - -import java.util.List; - -/** - * This class encapsulates the arguments that are - * required for creating a bucket. - */ -public final class BucketArgs { - - /** - * ACL Information. - */ - private List acls; - /** - * Bucket Version flag. - */ - private Boolean versioning; - /** - * Type of storage to be used for this bucket. - * [RAM_DISK, SSD, DISK, ARCHIVE] - */ - private StorageType storageType; - - /** - * Private constructor, constructed via builder. - * @param versioning Bucket version flag. - * @param storageType Storage type to be used. - * @param acls list of ACLs. - */ - private BucketArgs(Boolean versioning, StorageType storageType, - List acls) { - this.acls = acls; - this.versioning = versioning; - this.storageType = storageType; - } - - /** - * Returns true if bucket version is enabled, else false. - * @return isVersionEnabled - */ - public Boolean getVersioning() { - return versioning; - } - - /** - * Returns the type of storage to be used. - * @return StorageType - */ - public StorageType getStorageType() { - return storageType; - } - - /** - * Returns the ACL's associated with this bucket. - * @return List - */ - public List getAcls() { - return acls; - } - - /** - * Returns new builder class that builds a OmBucketInfo. - * - * @return Builder - */ - public static BucketArgs.Builder newBuilder() { - return new BucketArgs.Builder(); - } - - /** - * Builder for OmBucketInfo. - */ - public static class Builder { - private Boolean versioning; - private StorageType storageType; - private List acls; - - public BucketArgs.Builder setVersioning(Boolean versionFlag) { - this.versioning = versionFlag; - return this; - } - - public BucketArgs.Builder setStorageType(StorageType storage) { - this.storageType = storage; - return this; - } - - public BucketArgs.Builder setAcls(List listOfAcls) { - this.acls = listOfAcls; - return this; - } - - /** - * Constructs the BucketArgs. - * @return instance of BucketArgs. - */ - public BucketArgs build() { - return new BucketArgs(versioning, storageType, acls); - } - } -} diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/ObjectStore.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/ObjectStore.java deleted file mode 100644 index 17d19389e01..00000000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/ObjectStore.java +++ /dev/null @@ -1,216 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Strings; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.scm.client.HddsClientUtils; -import org.apache.hadoop.ozone.client.protocol.ClientProtocol; -import org.apache.hadoop.security.UserGroupInformation; - -import java.io.IOException; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; - -/** - * ObjectStore class is responsible for the client operations that can be - * performed on Ozone Object Store. - */ -public class ObjectStore { - - /** - * The proxy used for connecting to the cluster and perform - * client operations. - */ - private final ClientProtocol proxy; - - /** - * Cache size to be used for listVolume calls. - */ - private int listCacheSize; - - /** - * Creates an instance of ObjectStore. - * @param conf Configuration object. - * @param proxy ClientProtocol proxy. - */ - public ObjectStore(Configuration conf, ClientProtocol proxy) { - this.proxy = proxy; - this.listCacheSize = HddsClientUtils.getListCacheSize(conf); - } - - @VisibleForTesting - protected ObjectStore() { - proxy = null; - } - - /** - * Creates the volume with default values. - * @param volumeName Name of the volume to be created. - * @throws IOException - */ - public void createVolume(String volumeName) throws IOException { - proxy.createVolume(volumeName); - } - - /** - * Creates the volume. - * @param volumeName Name of the volume to be created. - * @param volumeArgs Volume properties. - * @throws IOException - */ - public void createVolume(String volumeName, VolumeArgs volumeArgs) - throws IOException { - proxy.createVolume(volumeName, volumeArgs); - } - - /** - * Returns the volume information. - * @param volumeName Name of the volume. - * @return OzoneVolume - * @throws IOException - */ - public OzoneVolume getVolume(String volumeName) throws IOException { - OzoneVolume volume = proxy.getVolumeDetails(volumeName); - return volume; - } - - - /** - * Returns Iterator to iterate over all the volumes in object store. - * The result can be restricted using volume prefix, will return all - * volumes if volume prefix is null. - * - * @param volumePrefix Volume prefix to match - * @return {@code Iterator} - */ - public Iterator listVolumes(String volumePrefix) - throws IOException { - return listVolumes(volumePrefix, null); - } - - /** - * Returns Iterator to iterate over all the volumes after prevVolume in object - * store. If prevVolume is null it iterates from the first volume. - * The result can be restricted using volume prefix, will return all - * volumes if volume prefix is null. - * - * @param volumePrefix Volume prefix to match - * @param prevVolume Volumes will be listed after this volume name - * @return {@code Iterator} - */ - public Iterator listVolumes(String volumePrefix, - String prevVolume) throws IOException { - return new VolumeIterator(null, volumePrefix, prevVolume); - } - - /** - * Returns Iterator to iterate over the list of volumes after prevVolume owned - * by a specific user. The result can be restricted using volume prefix, will - * return all volumes if volume prefix is null. If user is not null, returns - * the volume of current user. - * - * @param user User Name - * @param volumePrefix Volume prefix to match - * @param prevVolume Volumes will be listed after this volume name - * @return {@code Iterator} - */ - public Iterator listVolumesByUser(String user, - String volumePrefix, String prevVolume) - throws IOException { - if(Strings.isNullOrEmpty(user)) { - user = UserGroupInformation.getCurrentUser().getShortUserName(); - } - return new VolumeIterator(user, volumePrefix, prevVolume); - } - - /** - * Deletes the volume. - * @param volumeName Name of the volume. - * @throws IOException - */ - public void deleteVolume(String volumeName) throws IOException { - proxy.deleteVolume(volumeName); - } - - /** - * An Iterator to iterate over {@link OzoneVolume} list. - */ - private class VolumeIterator implements Iterator { - - private String user = null; - private String volPrefix = null; - - private Iterator currentIterator; - private OzoneVolume currentValue; - - /** - * Creates an Iterator to iterate over all volumes after - * prevVolume of the user. If prevVolume is null it iterates from the - * first volume. The returned volumes match volume prefix. - * @param user user name - * @param volPrefix volume prefix to match - */ - VolumeIterator(String user, String volPrefix, String prevVolume) { - this.user = user; - this.volPrefix = volPrefix; - this.currentValue = null; - this.currentIterator = getNextListOfVolumes(prevVolume).iterator(); - } - - @Override - public boolean hasNext() { - if(!currentIterator.hasNext()) { - currentIterator = getNextListOfVolumes( - currentValue != null ? currentValue.getName() : null) - .iterator(); - } - return currentIterator.hasNext(); - } - - @Override - public OzoneVolume next() { - if(hasNext()) { - currentValue = currentIterator.next(); - return currentValue; - } - throw new NoSuchElementException(); - } - - /** - * Returns the next set of volume list using proxy. - * @param prevVolume previous volume, this will be excluded from the result - * @return {@code List} - */ - private List getNextListOfVolumes(String prevVolume) { - try { - //if user is null, we do list of all volumes. - if(user != null) { - return proxy.listVolumes(user, volPrefix, prevVolume, listCacheSize); - } - return proxy.listVolumes(volPrefix, prevVolume, listCacheSize); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - } - -} diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneBucket.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneBucket.java deleted file mode 100644 index 751992ed6d7..00000000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneBucket.java +++ /dev/null @@ -1,382 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.StorageType; -import org.apache.hadoop.hdds.client.ReplicationFactor; -import org.apache.hadoop.hdds.client.ReplicationType; -import org.apache.hadoop.hdds.scm.client.HddsClientUtils; -import org.apache.hadoop.ozone.OzoneConfigKeys; -import org.apache.hadoop.ozone.client.io.OzoneInputStream; -import org.apache.hadoop.ozone.client.io.OzoneOutputStream; -import org.apache.hadoop.ozone.client.protocol.ClientProtocol; -import org.apache.hadoop.ozone.OzoneAcl; - -import java.io.IOException; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; - -/** - * A class that encapsulates OzoneBucket. - */ -public class OzoneBucket { - - /** - * The proxy used for connecting to the cluster and perform - * client operations. - */ - private final ClientProtocol proxy; - /** - * Name of the volume in which the bucket belongs to. - */ - private final String volumeName; - /** - * Name of the bucket. - */ - private final String name; - /** - * Default replication factor to be used while creating keys. - */ - private final ReplicationFactor defaultReplication; - - /** - * Default replication type to be used while creating keys. - */ - private final ReplicationType defaultReplicationType; - /** - * Bucket ACLs. - */ - private List acls; - - /** - * Type of storage to be used for this bucket. - * [RAM_DISK, SSD, DISK, ARCHIVE] - */ - private StorageType storageType; - - /** - * Bucket Version flag. - */ - private Boolean versioning; - - /** - * Cache size to be used for listKey calls. - */ - private int listCacheSize; - - /** - * Creation time of the bucket. - */ - private long creationTime; - - /** - * Constructs OzoneBucket instance. - * @param conf Configuration object. - * @param proxy ClientProtocol proxy. - * @param volumeName Name of the volume the bucket belongs to. - * @param bucketName Name of the bucket. - * @param acls ACLs associated with the bucket. - * @param storageType StorageType of the bucket. - * @param versioning versioning status of the bucket. - * @param creationTime creation time of the bucket. - */ - public OzoneBucket(Configuration conf, ClientProtocol proxy, - String volumeName, String bucketName, - List acls, StorageType storageType, - Boolean versioning, long creationTime) { - Preconditions.checkNotNull(proxy, "Client proxy is not set."); - this.proxy = proxy; - this.volumeName = volumeName; - this.name = bucketName; - this.acls = acls; - this.storageType = storageType; - this.versioning = versioning; - this.listCacheSize = HddsClientUtils.getListCacheSize(conf); - this.creationTime = creationTime; - this.defaultReplication = ReplicationFactor.valueOf(conf.getInt( - OzoneConfigKeys.OZONE_REPLICATION, - OzoneConfigKeys.OZONE_REPLICATION_DEFAULT)); - this.defaultReplicationType = ReplicationType.valueOf(conf.get( - OzoneConfigKeys.OZONE_REPLICATION_TYPE, - OzoneConfigKeys.OZONE_REPLICATION_TYPE_DEFAULT)); - } - - @VisibleForTesting - OzoneBucket(String volumeName, String name, - ReplicationFactor defaultReplication, - ReplicationType defaultReplicationType, - List acls, StorageType storageType, Boolean versioning, - long creationTime) { - this.proxy = null; - this.volumeName = volumeName; - this.name = name; - this.defaultReplication = defaultReplication; - this.defaultReplicationType = defaultReplicationType; - this.acls = acls; - this.storageType = storageType; - this.versioning = versioning; - this.creationTime = creationTime; - } - - /** - * Returns Volume Name. - * - * @return volumeName - */ - public String getVolumeName() { - return volumeName; - } - - /** - * Returns Bucket Name. - * - * @return bucketName - */ - public String getName() { - return name; - } - - /** - * Returns ACL's associated with the Bucket. - * - * @return acls - */ - public List getAcls() { - return acls; - } - - /** - * Returns StorageType of the Bucket. - * - * @return storageType - */ - public StorageType getStorageType() { - return storageType; - } - - /** - * Returns Versioning associated with the Bucket. - * - * @return versioning - */ - public Boolean getVersioning() { - return versioning; - } - - /** - * Returns creation time of the Bucket. - * - * @return creation time of the bucket - */ - public long getCreationTime() { - return creationTime; - } - - /** - * Adds ACLs to the Bucket. - * @param addAcls ACLs to be added - * @throws IOException - */ - public void addAcls(List addAcls) throws IOException { - proxy.addBucketAcls(volumeName, name, addAcls); - addAcls.stream().filter(acl -> !acls.contains(acl)).forEach( - acls::add); - } - - /** - * Removes ACLs from the bucket. - * @param removeAcls ACLs to be removed - * @throws IOException - */ - public void removeAcls(List removeAcls) throws IOException { - proxy.removeBucketAcls(volumeName, name, removeAcls); - acls.removeAll(removeAcls); - } - - /** - * Sets/Changes the storage type of the bucket. - * @param newStorageType Storage type to be set - * @throws IOException - */ - public void setStorageType(StorageType newStorageType) throws IOException { - proxy.setBucketStorageType(volumeName, name, newStorageType); - storageType = newStorageType; - } - - /** - * Enable/Disable versioning of the bucket. - * @param newVersioning - * @throws IOException - */ - public void setVersioning(Boolean newVersioning) throws IOException { - proxy.setBucketVersioning(volumeName, name, newVersioning); - versioning = newVersioning; - } - - /** - * Creates a new key in the bucket, with default replication type RATIS and - * with replication factor THREE. - * @param key Name of the key to be created. - * @param size Size of the data the key will point to. - * @return OzoneOutputStream to which the data has to be written. - * @throws IOException - */ - public OzoneOutputStream createKey(String key, long size) - throws IOException { - return createKey(key, size, defaultReplicationType, defaultReplication); - } - - /** - * Creates a new key in the bucket. - * @param key Name of the key to be created. - * @param size Size of the data the key will point to. - * @param type Replication type to be used. - * @param factor Replication factor of the key. - * @return OzoneOutputStream to which the data has to be written. - * @throws IOException - */ - public OzoneOutputStream createKey(String key, long size, - ReplicationType type, - ReplicationFactor factor) - throws IOException { - return proxy.createKey(volumeName, name, key, size, type, factor); - } - - /** - * Reads an existing key from the bucket. - * @param key Name of the key to be read. - * @return OzoneInputStream the stream using which the data can be read. - * @throws IOException - */ - public OzoneInputStream readKey(String key) throws IOException { - return proxy.getKey(volumeName, name, key); - } - - /** - * Returns information about the key. - * @param key Name of the key. - * @return OzoneKeyDetails Information about the key. - * @throws IOException - */ - public OzoneKeyDetails getKey(String key) throws IOException { - return proxy.getKeyDetails(volumeName, name, key); - } - - /** - * Returns Iterator to iterate over all keys in the bucket. - * The result can be restricted using key prefix, will return all - * keys if key prefix is null. - * - * @param keyPrefix Bucket prefix to match - * @return {@code Iterator} - */ - public Iterator listKeys(String keyPrefix) { - return listKeys(keyPrefix, null); - } - - /** - * Returns Iterator to iterate over all keys after prevKey in the bucket. - * If prevKey is null it iterates from the first key in the bucket. - * The result can be restricted using key prefix, will return all - * keys if key prefix is null. - * - * @param keyPrefix Bucket prefix to match - * @param prevKey Keys will be listed after this key name - * @return {@code Iterator} - */ - public Iterator listKeys(String keyPrefix, - String prevKey) { - return new KeyIterator(keyPrefix, prevKey); - } - - /** - * Deletes key from the bucket. - * @param key Name of the key to be deleted. - * @throws IOException - */ - public void deleteKey(String key) throws IOException { - proxy.deleteKey(volumeName, name, key); - } - - public void renameKey(String fromKeyName, String toKeyName) - throws IOException { - proxy.renameKey(volumeName, name, fromKeyName, toKeyName); - } - - /** - * An Iterator to iterate over {@link OzoneKey} list. - */ - private class KeyIterator implements Iterator { - - private String keyPrefix = null; - - private Iterator currentIterator; - private OzoneKey currentValue; - - - /** - * Creates an Iterator to iterate over all keys after prevKey in the bucket. - * If prevKey is null it iterates from the first key in the bucket. - * The returned keys match key prefix. - * @param keyPrefix - */ - KeyIterator(String keyPrefix, String prevKey) { - this.keyPrefix = keyPrefix; - this.currentValue = null; - this.currentIterator = getNextListOfKeys(prevKey).iterator(); - } - - @Override - public boolean hasNext() { - if(!currentIterator.hasNext()) { - currentIterator = getNextListOfKeys( - currentValue != null ? currentValue.getName() : null) - .iterator(); - } - return currentIterator.hasNext(); - } - - @Override - public OzoneKey next() { - if(hasNext()) { - currentValue = currentIterator.next(); - return currentValue; - } - throw new NoSuchElementException(); - } - - /** - * Gets the next set of key list using proxy. - * @param prevKey - * @return {@code List} - */ - private List getNextListOfKeys(String prevKey) { - try { - return proxy.listKeys(volumeName, name, keyPrefix, prevKey, - listCacheSize); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - } -} diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneClient.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneClient.java deleted file mode 100644 index 0d65d73fc3b..00000000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneClient.java +++ /dev/null @@ -1,110 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.ozone.client.protocol.ClientProtocol; - -import java.io.Closeable; -import java.io.IOException; - -import com.google.common.annotations.VisibleForTesting; - -/** - * OzoneClient connects to Ozone Cluster and - * perform basic operations. - */ -public class OzoneClient implements Closeable { - - /* - * OzoneClient connects to Ozone Cluster and - * perform basic operations. - * - * +-------------+ +---+ +-------------------------------------+ - * | OzoneClient | --> | C | | Object Store | - * |_____________| | l | | +-------------------------------+ | - * | i | | | Volume(s) | | - * | e | | | +------------------------+ | | - * | n | | | | Bucket(s) | | | - * | t | | | | +------------------+ | | | - * | | | | | | Key -> Value (s) | | | | - * | P |-->| | | | | | | | - * | r | | | | |__________________| | | | - * | o | | | | | | | - * | t | | | |________________________| | | - * | o | | | | | - * | c | | |_______________________________| | - * | o | | | - * | l | |_____________________________________| - * |___| - * Example: - * ObjectStore store = client.getObjectStore(); - * store.createVolume(“volume one”, VolumeArgs); - * volume.setQuota(“10 GB”); - * OzoneVolume volume = store.getVolume(“volume one”); - * volume.createBucket(“bucket one”, BucketArgs); - * bucket.setVersioning(true); - * OzoneOutputStream os = bucket.createKey(“key one”, 1024); - * os.write(byte[]); - * os.close(); - * OzoneInputStream is = bucket.readKey(“key one”); - * is.read(); - * is.close(); - * bucket.deleteKey(“key one”); - * volume.deleteBucket(“bucket one”); - * store.deleteVolume(“volume one”); - * client.close(); - */ - - private final ClientProtocol proxy; - private final ObjectStore objectStore; - - /** - * Creates a new OzoneClient object, generally constructed - * using {@link OzoneClientFactory}. - * @param conf Configuration object - * @param proxy ClientProtocol proxy instance - */ - public OzoneClient(Configuration conf, ClientProtocol proxy) { - this.proxy = proxy; - this.objectStore = new ObjectStore(conf, this.proxy); - } - - @VisibleForTesting - protected OzoneClient(ObjectStore objectStore) { - this.objectStore = objectStore; - this.proxy = null; - } - /** - * Returns the object store associated with the Ozone Cluster. - * @return ObjectStore - */ - public ObjectStore getObjectStore() { - return objectStore; - } - - /** - * Closes the client and all the underlying resources. - * @throws IOException - */ - @Override - public void close() throws IOException { - proxy.close(); - } -} diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneClientException.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneClientException.java deleted file mode 100644 index de3116a6aa8..00000000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneClientException.java +++ /dev/null @@ -1,54 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.client; - -import org.apache.hadoop.ozone.client.rest.OzoneException; - -/** - * This exception is thrown by the Ozone Clients. - */ -public class OzoneClientException extends OzoneException { - /** - * Constructor that allows the shortMessage. - * - * @param shortMessage Short Message - */ - public OzoneClientException(String shortMessage) { - super(0, shortMessage, shortMessage); - } - - /** - * Constructor that allows a shortMessage and an exception. - * - * @param shortMessage short message - * @param ex exception - */ - public OzoneClientException(String shortMessage, Exception ex) { - super(0, shortMessage, shortMessage, ex); - } - - /** - * Constructor that allows the shortMessage and a longer message. - * - * @param shortMessage Short Message - * @param message long error message - */ - public OzoneClientException(String shortMessage, String message) { - super(0, shortMessage, message); - } -} diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneClientFactory.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneClientFactory.java deleted file mode 100644 index de0d166abda..00000000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneClientFactory.java +++ /dev/null @@ -1,306 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.ozone.OmUtils; -import org.apache.hadoop.ozone.client.protocol.ClientProtocol; -import org.apache.hadoop.ozone.client.rest.RestClient; -import org.apache.hadoop.ozone.client.rpc.RpcClient; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Proxy; - -import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_CLIENT_PROTOCOL; -import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_ADDRESS_KEY; -import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_HTTP_ADDRESS_KEY; - -/** - * Factory class to create different types of OzoneClients. - * Based on ozone.client.protocol, it decides which - * protocol to use for the communication. - * Default value is - * org.apache.hadoop.ozone.client.rpc.RpcClient.
- * OzoneClientFactory constructs a proxy using - * {@link OzoneClientInvocationHandler} - * and creates OzoneClient instance with it. - * {@link OzoneClientInvocationHandler} dispatches the call to - * underlying {@link ClientProtocol} implementation. - */ -public final class OzoneClientFactory { - - private static final Logger LOG = LoggerFactory.getLogger( - OzoneClientFactory.class); - - /** - * Private constructor, class is not meant to be initialized. - */ - private OzoneClientFactory(){} - - - /** - * Constructs and return an OzoneClient with default configuration. - * - * @return OzoneClient - * - * @throws IOException - */ - public static OzoneClient getClient() throws IOException { - LOG.info("Creating OzoneClient with default configuration."); - return getClient(new OzoneConfiguration()); - } - - /** - * Constructs and return an OzoneClient based on the configuration object. - * Protocol type is decided by ozone.client.protocol. - * - * @param config - * Configuration to be used for OzoneClient creation - * - * @return OzoneClient - * - * @throws IOException - */ - public static OzoneClient getClient(Configuration config) - throws IOException { - Preconditions.checkNotNull(config); - Class clazz = (Class) - config.getClass(OZONE_CLIENT_PROTOCOL, RpcClient.class); - return getClient(getClientProtocol(clazz, config), config); - } - - /** - * Returns an OzoneClient which will use RPC protocol. - * - * @param omHost - * hostname of OzoneManager to connect. - * - * @return OzoneClient - * - * @throws IOException - */ - public static OzoneClient getRpcClient(String omHost) - throws IOException { - Configuration config = new OzoneConfiguration(); - int port = OmUtils.getOmRpcPort(config); - return getRpcClient(omHost, port, config); - } - - /** - * Returns an OzoneClient which will use RPC protocol. - * - * @param omHost - * hostname of OzoneManager to connect. - * - * @param omRpcPort - * RPC port of OzoneManager. - * - * @return OzoneClient - * - * @throws IOException - */ - public static OzoneClient getRpcClient(String omHost, Integer omRpcPort) - throws IOException { - return getRpcClient(omHost, omRpcPort, new OzoneConfiguration()); - } - - /** - * Returns an OzoneClient which will use RPC protocol. - * - * @param omHost - * hostname of OzoneManager to connect. - * - * @param omRpcPort - * RPC port of OzoneManager. - * - * @param config - * Configuration to be used for OzoneClient creation - * - * @return OzoneClient - * - * @throws IOException - */ - public static OzoneClient getRpcClient(String omHost, Integer omRpcPort, - Configuration config) - throws IOException { - Preconditions.checkNotNull(omHost); - Preconditions.checkNotNull(omRpcPort); - Preconditions.checkNotNull(config); - config.set(OZONE_OM_ADDRESS_KEY, omHost + ":" + omRpcPort); - return getRpcClient(config); - } - - /** - * Returns an OzoneClient which will use RPC protocol. - * - * @param config - * used for OzoneClient creation - * - * @return OzoneClient - * - * @throws IOException - */ - public static OzoneClient getRpcClient(Configuration config) - throws IOException { - Preconditions.checkNotNull(config); - return getClient(getClientProtocol(RpcClient.class, config), - config); - } - - /** - * Returns an OzoneClient which will use REST protocol. - * - * @param omHost - * hostname of OzoneManager to connect. - * - * @return OzoneClient - * - * @throws IOException - */ - public static OzoneClient getRestClient(String omHost) - throws IOException { - Configuration config = new OzoneConfiguration(); - int port = OmUtils.getOmRestPort(config); - return getRestClient(omHost, port, config); - } - - /** - * Returns an OzoneClient which will use REST protocol. - * - * @param omHost - * hostname of OzoneManager to connect. - * - * @param omHttpPort - * HTTP port of OzoneManager. - * - * @return OzoneClient - * - * @throws IOException - */ - public static OzoneClient getRestClient(String omHost, Integer omHttpPort) - throws IOException { - return getRestClient(omHost, omHttpPort, new OzoneConfiguration()); - } - - /** - * Returns an OzoneClient which will use REST protocol. - * - * @param omHost - * hostname of OzoneManager to connect. - * - * @param omHttpPort - * HTTP port of OzoneManager. - * - * @param config - * Configuration to be used for OzoneClient creation - * - * @return OzoneClient - * - * @throws IOException - */ - public static OzoneClient getRestClient(String omHost, Integer omHttpPort, - Configuration config) - throws IOException { - Preconditions.checkNotNull(omHost); - Preconditions.checkNotNull(omHttpPort); - Preconditions.checkNotNull(config); - config.set(OZONE_OM_HTTP_ADDRESS_KEY, omHost + ":" + omHttpPort); - return getRestClient(config); - } - - /** - * Returns an OzoneClient which will use REST protocol. - * - * @param config - * Configuration to be used for OzoneClient creation - * - * @return OzoneClient - * - * @throws IOException - */ - public static OzoneClient getRestClient(Configuration config) - throws IOException { - Preconditions.checkNotNull(config); - return getClient(getClientProtocol(RestClient.class, config), - config); - } - - /** - * Creates OzoneClient with the given ClientProtocol and Configuration. - * - * @param clientProtocol - * Protocol to be used by the OzoneClient - * - * @param config - * Configuration to be used for OzoneClient creation - */ - private static OzoneClient getClient(ClientProtocol clientProtocol, - Configuration config) { - OzoneClientInvocationHandler clientHandler = - new OzoneClientInvocationHandler(clientProtocol); - ClientProtocol proxy = (ClientProtocol) Proxy.newProxyInstance( - OzoneClientInvocationHandler.class.getClassLoader(), - new Class[]{ClientProtocol.class}, clientHandler); - return new OzoneClient(config, proxy); - } - - /** - * Returns an instance of Protocol class. - * - * @param protocolClass - * Class object of the ClientProtocol. - * - * @param config - * Configuration used to initialize ClientProtocol. - * - * @return ClientProtocol - * - * @throws IOException - */ - private static ClientProtocol getClientProtocol( - Class protocolClass, Configuration config) - throws IOException { - try { - LOG.debug("Using {} as client protocol.", - protocolClass.getCanonicalName()); - Constructor ctor = - protocolClass.getConstructor(Configuration.class); - return ctor.newInstance(config); - } catch (Exception e) { - final String message = "Couldn't create protocol " + protocolClass; - LOG.error(message + " exception: ", e); - if (e.getCause() instanceof IOException) { - throw (IOException) e.getCause(); - } else if (e instanceof InvocationTargetException) { - throw new IOException(message, - ((InvocationTargetException) e).getTargetException()); - } else { - throw new IOException(message, e); - } - } - } - -} diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneClientInvocationHandler.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneClientInvocationHandler.java deleted file mode 100644 index 3051e2dd1c8..00000000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneClientInvocationHandler.java +++ /dev/null @@ -1,62 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client; - -import org.apache.hadoop.ozone.client.protocol.ClientProtocol; -import org.apache.hadoop.util.Time; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -/** - * Invocation Handler for ozone client which dispatches the call to underlying - * ClientProtocol implementation. - */ -public class OzoneClientInvocationHandler implements InvocationHandler { - - - private static final Logger LOG = LoggerFactory.getLogger(OzoneClient.class); - private final ClientProtocol target; - - /** - * Constructs OzoneClientInvocationHandler with the proxy. - * @param target proxy to be used for method invocation. - */ - public OzoneClientInvocationHandler(ClientProtocol target) { - this.target = target; - } - - @Override - public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable { - LOG.trace("Invoking method {} on proxy {}", method, proxy); - try { - long startTime = Time.monotonicNow(); - Object result = method.invoke(target, args); - LOG.debug("Call: {} took {} ms", method, - Time.monotonicNow() - startTime); - return result; - } catch(InvocationTargetException iEx) { - throw iEx.getCause(); - } - } -} \ No newline at end of file diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneClientUtils.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneClientUtils.java deleted file mode 100644 index 40e4d83113e..00000000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneClientUtils.java +++ /dev/null @@ -1,136 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.client; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.client.OzoneQuota; -import org.apache.hadoop.hdds.scm.client.HddsClientUtils; -import org.apache.hadoop.hdds.scm.container.common.helpers.BlockNotCommittedException; -import org.apache.hadoop.io.retry.RetryPolicies; -import org.apache.hadoop.io.retry.RetryPolicy; -import org.apache.hadoop.ozone.OzoneConfigKeys; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.client.rest.response.*; - -import java.util.ArrayList; -import java.util.List; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -/** A utility class for OzoneClient. */ -public final class OzoneClientUtils { - - private OzoneClientUtils() {} - - /** - * Returns a BucketInfo object constructed using fields of the input - * OzoneBucket object. - * - * @param bucket OzoneBucket instance from which BucketInfo object needs to - * be created. - * @return BucketInfo instance - */ - public static BucketInfo asBucketInfo(OzoneBucket bucket) { - BucketInfo bucketInfo = - new BucketInfo(bucket.getVolumeName(), bucket.getName()); - bucketInfo - .setCreatedOn(HddsClientUtils.formatDateTime(bucket.getCreationTime())); - bucketInfo.setStorageType(bucket.getStorageType()); - bucketInfo.setVersioning( - OzoneConsts.Versioning.getVersioning(bucket.getVersioning())); - bucketInfo.setAcls(bucket.getAcls()); - return bucketInfo; - } - - /** - * Returns a VolumeInfo object constructed using fields of the input - * OzoneVolume object. - * - * @param volume OzoneVolume instance from which VolumeInfo object needs to - * be created. - * @return VolumeInfo instance - */ - public static VolumeInfo asVolumeInfo(OzoneVolume volume) { - VolumeInfo volumeInfo = new VolumeInfo(volume.getName(), - HddsClientUtils.formatDateTime(volume.getCreationTime()), - volume.getOwner()); - volumeInfo.setQuota(OzoneQuota.getOzoneQuota(volume.getQuota())); - volumeInfo.setOwner(new VolumeOwner(volume.getOwner())); - return volumeInfo; - } - - /** - * Returns a KeyInfo object constructed using fields of the input - * OzoneKey object. - * - * @param key OzoneKey instance from which KeyInfo object needs to - * be created. - * @return KeyInfo instance - */ - public static KeyInfo asKeyInfo(OzoneKey key) { - KeyInfo keyInfo = new KeyInfo(); - keyInfo.setKeyName(key.getName()); - keyInfo.setCreatedOn(HddsClientUtils.formatDateTime(key.getCreationTime())); - keyInfo.setModifiedOn( - HddsClientUtils.formatDateTime(key.getModificationTime())); - keyInfo.setSize(key.getDataSize()); - return keyInfo; - } - - public static RetryPolicy createRetryPolicy(Configuration conf) { - int maxRetryCount = - conf.getInt(OzoneConfigKeys.OZONE_CLIENT_MAX_RETRIES, OzoneConfigKeys. - OZONE_CLIENT_MAX_RETRIES_DEFAULT); - long retryInterval = conf.getTimeDuration(OzoneConfigKeys. - OZONE_CLIENT_RETRY_INTERVAL, OzoneConfigKeys. - OZONE_CLIENT_RETRY_INTERVAL_DEFAULT, TimeUnit.MILLISECONDS); - RetryPolicy basePolicy = RetryPolicies - .retryUpToMaximumCountWithFixedSleep(maxRetryCount, retryInterval, - TimeUnit.MILLISECONDS); - Map, RetryPolicy> exceptionToPolicyMap = - new HashMap, RetryPolicy>(); - exceptionToPolicyMap.put(BlockNotCommittedException.class, basePolicy); - RetryPolicy retryPolicy = RetryPolicies - .retryByException(RetryPolicies.TRY_ONCE_THEN_FAIL, - exceptionToPolicyMap); - return retryPolicy; - } - /** - * Returns a KeyInfoDetails object constructed using fields of the input - * OzoneKeyDetails object. - * - * @param key OzoneKeyDetails instance from which KeyInfo object needs to - * be created. - * @return KeyInfoDetails instance - */ - public static KeyInfoDetails asKeyInfoDetails(OzoneKeyDetails key) { - KeyInfoDetails keyInfo = new KeyInfoDetails(); - keyInfo.setKeyName(key.getName()); - keyInfo.setCreatedOn(HddsClientUtils.formatDateTime(key.getCreationTime())); - keyInfo.setModifiedOn( - HddsClientUtils.formatDateTime(key.getModificationTime())); - keyInfo.setSize(key.getDataSize()); - List keyLocations = new ArrayList<>(); - key.getOzoneKeyLocations().forEach((a) -> keyLocations.add(new KeyLocation( - a.getContainerID(), a.getLocalID(), a.getLength(), a.getOffset()))); - keyInfo.setKeyLocation(keyLocations); - return keyInfo; - } -} diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneKey.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneKey.java deleted file mode 100644 index 7c93146abda..00000000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneKey.java +++ /dev/null @@ -1,119 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client; - -/** - * A class that encapsulates OzoneKey. - */ -public class OzoneKey { - - /** - * Name of the Volume the Key belongs to. - */ - private final String volumeName; - /** - * Name of the Bucket the Key belongs to. - */ - private final String bucketName; - /** - * Name of the Key. - */ - private final String name; - /** - * Size of the data. - */ - private final long dataSize; - /** - * Creation time of the key. - */ - private long creationTime; - /** - * Modification time of the key. - */ - private long modificationTime; - - /** - * Constructs OzoneKey from OmKeyInfo. - * - */ - public OzoneKey(String volumeName, String bucketName, - String keyName, long size, long creationTime, - long modificationTime) { - this.volumeName = volumeName; - this.bucketName = bucketName; - this.name = keyName; - this.dataSize = size; - this.creationTime = creationTime; - this.modificationTime = modificationTime; - } - - /** - * Returns Volume Name associated with the Key. - * - * @return volumeName - */ - public String getVolumeName() { - return volumeName; - } - - /** - * Returns Bucket Name associated with the Key. - * - * @return bucketName - */ - public String getBucketName(){ - return bucketName; - } - - /** - * Returns the Key Name. - * - * @return keyName - */ - public String getName() { - return name; - } - - /** - * Returns the size of the data. - * - * @return dataSize - */ - public long getDataSize() { - return dataSize; - } - - /** - * Returns the creation time of the key. - * - * @return creation time - */ - public long getCreationTime() { - return creationTime; - } - - /** - * Returns the modification time of the key. - * - * @return modification time - */ - public long getModificationTime() { - return modificationTime; - } -} diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneKeyDetails.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneKeyDetails.java deleted file mode 100644 index e7709ddfb89..00000000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneKeyDetails.java +++ /dev/null @@ -1,58 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client; - -import java.util.List; - -/** - * A class that encapsulates OzoneKeyLocation. - */ -public class OzoneKeyDetails extends OzoneKey { - - /** - * A list of block location information to specify replica locations. - */ - private List ozoneKeyLocations; - - /** - * Constructs OzoneKeyDetails from OmKeyInfo. - */ - public OzoneKeyDetails(String volumeName, String bucketName, String keyName, - long size, long creationTime, long modificationTime, - List ozoneKeyLocations) { - super(volumeName, bucketName, keyName, size, creationTime, - modificationTime); - this.ozoneKeyLocations = ozoneKeyLocations; - } - - /** - * Returns the location detail information of the specific Key. - */ - public List getOzoneKeyLocations() { - return ozoneKeyLocations; - } - - /** - * Set details of key location. - * @param ozoneKeyLocations - details of key location - */ - public void setOzoneKeyLocations(List ozoneKeyLocations) { - this.ozoneKeyLocations = ozoneKeyLocations; - } -} diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneKeyLocation.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneKeyLocation.java deleted file mode 100644 index 0ff8ba749b6..00000000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneKeyLocation.java +++ /dev/null @@ -1,82 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client; - -/** - * One key can be stored in one or more containers as one or more blocks. - * This class represents one such block instance. - */ -public class OzoneKeyLocation { - /** - * Which container this key stored. - */ - private final long containerID; - /** - * Which block this key stored inside a container. - */ - private final long localID; - /** - * Data length of this key replica. - */ - private final long length; - /** - * Offset of this key. - */ - private final long offset; - - /** - * Constructs OzoneKeyLocation. - */ - public OzoneKeyLocation(long containerID, long localID, - long length, long offset) { - this.containerID = containerID; - this.localID = localID; - this.length = length; - this.offset = offset; - } - - /** - * Returns the containerID of this Key. - */ - public long getContainerID() { - return containerID; - } - - /** - * Returns the localID of this Key. - */ - public long getLocalID() { - return localID; - } - - /** - * Returns the length of this Key. - */ - public long getLength() { - return length; - } - - /** - * Returns the offset of this Key. - */ - public long getOffset() { - return offset; - } - -} diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneVolume.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneVolume.java deleted file mode 100644 index e451b1ac24b..00000000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneVolume.java +++ /dev/null @@ -1,311 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client; - -import java.io.IOException; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.client.OzoneQuota; -import org.apache.hadoop.hdds.scm.client.HddsClientUtils; -import org.apache.hadoop.ozone.OzoneAcl; -import org.apache.hadoop.ozone.client.protocol.ClientProtocol; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; - -/** - * A class that encapsulates OzoneVolume. - */ -public class OzoneVolume { - - /** - * The proxy used for connecting to the cluster and perform - * client operations. - */ - private final ClientProtocol proxy; - - /** - * Name of the Volume. - */ - private final String name; - - /** - * Admin Name of the Volume. - */ - private String admin; - /** - * Owner of the Volume. - */ - private String owner; - /** - * Quota allocated for the Volume. - */ - private long quotaInBytes; - /** - * Creation time of the volume. - */ - private long creationTime; - /** - * Volume ACLs. - */ - private List acls; - - private int listCacheSize; - - /** - * Constructs OzoneVolume instance. - * @param conf Configuration object. - * @param proxy ClientProtocol proxy. - * @param name Name of the volume. - * @param admin Volume admin. - * @param owner Volume owner. - * @param quotaInBytes Volume quota in bytes. - * @param creationTime creation time of the volume - * @param acls ACLs associated with the volume. - */ - public OzoneVolume(Configuration conf, ClientProtocol proxy, String name, - String admin, String owner, long quotaInBytes, - long creationTime, List acls) { - Preconditions.checkNotNull(proxy, "Client proxy is not set."); - this.proxy = proxy; - this.name = name; - this.admin = admin; - this.owner = owner; - this.quotaInBytes = quotaInBytes; - this.creationTime = creationTime; - this.acls = acls; - this.listCacheSize = HddsClientUtils.getListCacheSize(conf); - } - - @VisibleForTesting - protected OzoneVolume(String name, String admin, String owner, - long quotaInBytes, - long creationTime, List acls) { - this.proxy = null; - this.name = name; - this.admin = admin; - this.owner = owner; - this.quotaInBytes = quotaInBytes; - this.creationTime = creationTime; - this.acls = acls; - } - - /** - * Returns Volume name. - * - * @return volumeName - */ - public String getName() { - return name; - } - - /** - * Returns Volume's admin name. - * - * @return adminName - */ - public String getAdmin() { - return admin; - } - - /** - * Returns Volume's owner name. - * - * @return ownerName - */ - public String getOwner() { - return owner; - } - - /** - * Returns Quota allocated for the Volume in bytes. - * - * @return quotaInBytes - */ - public long getQuota() { - return quotaInBytes; - } - - /** - * Returns creation time of the volume. - * - * @return creation time. - */ - public long getCreationTime() { - return creationTime; - } - - /** - * Returns OzoneAcl list associated with the Volume. - * - * @return aclMap - */ - public List getAcls() { - return acls; - } - - /** - * Sets/Changes the owner of this Volume. - * @param owner new owner - * @throws IOException - */ - public void setOwner(String owner) throws IOException { - proxy.setVolumeOwner(name, owner); - this.owner = owner; - } - - /** - * Sets/Changes the quota of this Volume. - * @param quota new quota - * @throws IOException - */ - public void setQuota(OzoneQuota quota) throws IOException { - proxy.setVolumeQuota(name, quota); - this.quotaInBytes = quota.sizeInBytes(); - } - - /** - * Creates a new Bucket in this Volume, with default values. - * @param bucketName Name of the Bucket - * @throws IOException - */ - public void createBucket(String bucketName) - throws IOException { - proxy.createBucket(name, bucketName); - } - - /** - * Creates a new Bucket in this Volume, with properties set in bucketArgs. - * @param bucketName Name of the Bucket - * @param bucketArgs Properties to be set - * @throws IOException - */ - public void createBucket(String bucketName, BucketArgs bucketArgs) - throws IOException { - proxy.createBucket(name, bucketName, bucketArgs); - } - - /** - * Get the Bucket from this Volume. - * @param bucketName Name of the Bucket - * @return OzoneBucket - * @throws IOException - */ - public OzoneBucket getBucket(String bucketName) throws IOException { - OzoneBucket bucket = proxy.getBucketDetails(name, bucketName); - return bucket; - } - - /** - * Returns Iterator to iterate over all buckets in the volume. - * The result can be restricted using bucket prefix, will return all - * buckets if bucket prefix is null. - * - * @param bucketPrefix Bucket prefix to match - * @return {@code Iterator} - */ - public Iterator listBuckets(String bucketPrefix) { - return listBuckets(bucketPrefix, null); - } - - /** - * Returns Iterator to iterate over all buckets after prevBucket in the - * volume. - * If prevBucket is null it iterates from the first bucket in the volume. - * The result can be restricted using bucket prefix, will return all - * buckets if bucket prefix is null. - * - * @param bucketPrefix Bucket prefix to match - * @param prevBucket Buckets are listed after this bucket - * @return {@code Iterator} - */ - public Iterator listBuckets(String bucketPrefix, - String prevBucket) { - return new BucketIterator(bucketPrefix, prevBucket); - } - - /** - * Deletes the Bucket from this Volume. - * @param bucketName Name of the Bucket - * @throws IOException - */ - public void deleteBucket(String bucketName) throws IOException { - proxy.deleteBucket(name, bucketName); - } - - - /** - * An Iterator to iterate over {@link OzoneBucket} list. - */ - private class BucketIterator implements Iterator { - - private String bucketPrefix = null; - - private Iterator currentIterator; - private OzoneBucket currentValue; - - - /** - * Creates an Iterator to iterate over all buckets after prevBucket in the volume. - * If prevBucket is null it iterates from the first bucket in the volume. - * The returned buckets match bucket prefix. - * @param bucketPrefix - */ - public BucketIterator(String bucketPrefix, String prevBucket) { - this.bucketPrefix = bucketPrefix; - this.currentValue = null; - this.currentIterator = getNextListOfBuckets(prevBucket).iterator(); - } - - @Override - public boolean hasNext() { - if(!currentIterator.hasNext()) { - currentIterator = getNextListOfBuckets( - currentValue != null ? currentValue.getName() : null) - .iterator(); - } - return currentIterator.hasNext(); - } - - @Override - public OzoneBucket next() { - if(hasNext()) { - currentValue = currentIterator.next(); - return currentValue; - } - throw new NoSuchElementException(); - } - - /** - * Gets the next set of bucket list using proxy. - * @param prevBucket - * @return {@code List} - */ - private List getNextListOfBuckets(String prevBucket) { - try { - return proxy.listBuckets(name, bucketPrefix, prevBucket, listCacheSize); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - } -} \ No newline at end of file diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/VolumeArgs.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/VolumeArgs.java deleted file mode 100644 index ae1cfccd420..00000000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/VolumeArgs.java +++ /dev/null @@ -1,128 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client; - -import org.apache.hadoop.ozone.OzoneAcl; - -import java.io.IOException; -import java.util.List; - -/** - * This class encapsulates the arguments that are - * required for creating a volume. - */ -public final class VolumeArgs { - - private final String admin; - private final String owner; - private final String quota; - private final List acls; - - /** - * Private constructor, constructed via builder. - * @param admin Administrator's name. - * @param owner Volume owner's name - * @param quota Volume Quota. - * @param acls User to access rights map. - */ - private VolumeArgs(String admin, String owner, - String quota, List acls) { - this.admin = admin; - this.owner = owner; - this.quota = quota; - this.acls = acls; - } - - /** - * Returns the Admin Name. - * @return String. - */ - public String getAdmin() { - return admin; - } - - /** - * Returns the owner Name. - * @return String - */ - public String getOwner() { - return owner; - } - - /** - * Returns Volume Quota. - * @return Quota. - */ - public String getQuota() { - return quota; - } - - public List getAcls() { - return acls; - } - /** - * Returns new builder class that builds a OmVolumeArgs. - * - * @return Builder - */ - public static VolumeArgs.Builder newBuilder() { - return new VolumeArgs.Builder(); - } - - /** - * Builder for OmVolumeArgs. - */ - public static class Builder { - private String adminName; - private String ownerName; - private String volumeQuota; - private List listOfAcls; - - - public VolumeArgs.Builder setAdmin(String admin) { - this.adminName = admin; - return this; - } - - public VolumeArgs.Builder setOwner(String owner) { - this.ownerName = owner; - return this; - } - - public VolumeArgs.Builder setQuota(String quota) { - this.volumeQuota = quota; - return this; - } - - public VolumeArgs.Builder setAcls(List acls) - throws IOException { - this.listOfAcls = acls; - return this; - } - - /** - * Constructs a CreateVolumeArgument. - * @return CreateVolumeArgs. - */ - public VolumeArgs build() { - return new VolumeArgs(adminName, ownerName, volumeQuota, listOfAcls); - } - } - -} diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/ChunkGroupInputStream.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/ChunkGroupInputStream.java deleted file mode 100644 index 2b10578824a..00000000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/ChunkGroupInputStream.java +++ /dev/null @@ -1,318 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.client.io; - -import com.google.common.annotations.VisibleForTesting; -import org.apache.hadoop.fs.FSExceptionMessages; -import org.apache.hadoop.fs.Seekable; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdds.client.BlockID; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerWithPipeline; -import org.apache.hadoop.ozone.om.helpers.OmKeyInfo; -import org.apache.hadoop.ozone.om.helpers.OmKeyLocationInfo; -import org.apache.hadoop.hdds.scm.XceiverClientManager; -import org.apache.hadoop.hdds.scm.XceiverClientSpi; -import org.apache.hadoop.hdds.scm.protocolPB.StorageContainerLocationProtocolClientSideTranslatorPB; -import org.apache.hadoop.hdds.scm.storage.ChunkInputStream; -import org.apache.hadoop.hdds.scm.storage.ContainerProtocolCalls; -import org.apache.ratis.util.Preconditions; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * Maintaining a list of ChunkInputStream. Read based on offset. - */ -public class ChunkGroupInputStream extends InputStream implements Seekable { - - private static final Logger LOG = - LoggerFactory.getLogger(ChunkGroupInputStream.class); - - private static final int EOF = -1; - - private final ArrayList streamEntries; - // streamOffset[i] stores the offset at which chunkInputStream i stores - // data in the key - private long[] streamOffset = null; - private int currentStreamIndex; - private long length = 0; - private boolean closed = false; - private String key; - - public ChunkGroupInputStream() { - streamEntries = new ArrayList<>(); - currentStreamIndex = 0; - } - - @VisibleForTesting - public synchronized int getCurrentStreamIndex() { - return currentStreamIndex; - } - - @VisibleForTesting - public long getRemainingOfIndex(int index) throws IOException { - return streamEntries.get(index).getRemaining(); - } - - /** - * Append another stream to the end of the list. - * - * @param stream the stream instance. - * @param streamLength the max number of bytes that should be written to this - * stream. - */ - public synchronized void addStream(ChunkInputStream stream, - long streamLength) { - streamEntries.add(new ChunkInputStreamEntry(stream, streamLength)); - } - - - @Override - public synchronized int read() throws IOException { - byte[] buf = new byte[1]; - if (read(buf, 0, 1) == EOF) { - return EOF; - } - return Byte.toUnsignedInt(buf[0]); - } - - @Override - public synchronized int read(byte[] b, int off, int len) throws IOException { - checkNotClosed(); - if (b == null) { - throw new NullPointerException(); - } - if (off < 0 || len < 0 || len > b.length - off) { - throw new IndexOutOfBoundsException(); - } - if (len == 0) { - return 0; - } - int totalReadLen = 0; - while (len > 0) { - if (streamEntries.size() <= currentStreamIndex) { - return totalReadLen == 0 ? EOF : totalReadLen; - } - ChunkInputStreamEntry current = streamEntries.get(currentStreamIndex); - int numBytesToRead = Math.min(len, (int)current.getRemaining()); - int numBytesRead = current.read(b, off, numBytesToRead); - if (numBytesRead != numBytesToRead) { - // This implies that there is either data loss or corruption in the - // chunk entries. Even EOF in the current stream would be covered in - // this case. - throw new IOException(String.format( - "Inconsistent read for blockID=%s length=%d numBytesRead=%d", - current.chunkInputStream.getBlockID(), current.length, - numBytesRead)); - } - totalReadLen += numBytesRead; - off += numBytesRead; - len -= numBytesRead; - if (current.getRemaining() <= 0) { - currentStreamIndex += 1; - } - } - return totalReadLen; - } - - @Override - public void seek(long pos) throws IOException { - checkNotClosed(); - if (pos < 0 || pos >= length) { - if (pos == 0) { - // It is possible for length and pos to be zero in which case - // seek should return instead of throwing exception - return; - } - throw new EOFException( - "EOF encountered at pos: " + pos + " for key: " + key); - } - Preconditions.assertTrue(currentStreamIndex >= 0); - if (currentStreamIndex >= streamEntries.size()) { - currentStreamIndex = Arrays.binarySearch(streamOffset, pos); - } else if (pos < streamOffset[currentStreamIndex]) { - currentStreamIndex = - Arrays.binarySearch(streamOffset, 0, currentStreamIndex, pos); - } else if (pos >= streamOffset[currentStreamIndex] + streamEntries - .get(currentStreamIndex).length) { - currentStreamIndex = Arrays - .binarySearch(streamOffset, currentStreamIndex + 1, - streamEntries.size(), pos); - } - if (currentStreamIndex < 0) { - // Binary search returns -insertionPoint - 1 if element is not present - // in the array. insertionPoint is the point at which element would be - // inserted in the sorted array. We need to adjust the currentStreamIndex - // accordingly so that currentStreamIndex = insertionPoint - 1 - currentStreamIndex = -currentStreamIndex - 2; - } - // seek to the proper offset in the ChunkInputStream - streamEntries.get(currentStreamIndex) - .seek(pos - streamOffset[currentStreamIndex]); - } - - @Override - public long getPos() throws IOException { - return length == 0 ? 0 : - streamOffset[currentStreamIndex] + streamEntries.get(currentStreamIndex) - .getPos(); - } - - @Override - public boolean seekToNewSource(long targetPos) throws IOException { - return false; - } - - @Override - public int available() throws IOException { - checkNotClosed(); - long remaining = length - getPos(); - return remaining <= Integer.MAX_VALUE ? (int) remaining : Integer.MAX_VALUE; - } - - @Override - public void close() throws IOException { - closed = true; - for (int i = 0; i < streamEntries.size(); i++) { - streamEntries.get(i).close(); - } - } - - /** - * Encapsulates ChunkInputStream. - */ - public static class ChunkInputStreamEntry extends InputStream - implements Seekable { - - private final ChunkInputStream chunkInputStream; - private final long length; - - public ChunkInputStreamEntry(ChunkInputStream chunkInputStream, - long length) { - this.chunkInputStream = chunkInputStream; - this.length = length; - } - - synchronized long getRemaining() throws IOException { - return length - getPos(); - } - - @Override - public synchronized int read(byte[] b, int off, int len) - throws IOException { - int readLen = chunkInputStream.read(b, off, len); - return readLen; - } - - @Override - public synchronized int read() throws IOException { - int data = chunkInputStream.read(); - return data; - } - - @Override - public synchronized void close() throws IOException { - chunkInputStream.close(); - } - - @Override - public void seek(long pos) throws IOException { - chunkInputStream.seek(pos); - } - - @Override - public long getPos() throws IOException { - return chunkInputStream.getPos(); - } - - @Override - public boolean seekToNewSource(long targetPos) throws IOException { - return false; - } - } - - public static LengthInputStream getFromOmKeyInfo( - OmKeyInfo keyInfo, - XceiverClientManager xceiverClientManager, - StorageContainerLocationProtocolClientSideTranslatorPB - storageContainerLocationClient, - String requestId) throws IOException { - long length = 0; - long containerKey; - ChunkGroupInputStream groupInputStream = new ChunkGroupInputStream(); - groupInputStream.key = keyInfo.getKeyName(); - List keyLocationInfos = - keyInfo.getLatestVersionLocations().getBlocksLatestVersionOnly(); - groupInputStream.streamOffset = new long[keyLocationInfos.size()]; - for (int i = 0; i < keyLocationInfos.size(); i++) { - OmKeyLocationInfo omKeyLocationInfo = keyLocationInfos.get(i); - BlockID blockID = omKeyLocationInfo.getBlockID(); - long containerID = blockID.getContainerID(); - ContainerWithPipeline containerWithPipeline = - storageContainerLocationClient.getContainerWithPipeline(containerID); - XceiverClientSpi xceiverClient = xceiverClientManager - .acquireClient(containerWithPipeline.getPipeline(), containerID); - boolean success = false; - containerKey = omKeyLocationInfo.getLocalID(); - try { - LOG.debug("get key accessing {} {}", - containerID, containerKey); - groupInputStream.streamOffset[i] = length; - ContainerProtos.DatanodeBlockID datanodeBlockID = blockID - .getDatanodeBlockIDProtobuf(); - ContainerProtos.GetBlockResponseProto response = ContainerProtocolCalls - .getBlock(xceiverClient, datanodeBlockID, requestId); - List chunks = - response.getBlockData().getChunksList(); - for (ContainerProtos.ChunkInfo chunk : chunks) { - length += chunk.getLen(); - } - success = true; - ChunkInputStream inputStream = new ChunkInputStream( - omKeyLocationInfo.getBlockID(), xceiverClientManager, xceiverClient, - chunks, requestId); - groupInputStream.addStream(inputStream, - omKeyLocationInfo.getLength()); - } finally { - if (!success) { - xceiverClientManager.releaseClient(xceiverClient); - } - } - } - groupInputStream.length = length; - return new LengthInputStream(groupInputStream, length); - } - - /** - * Verify that the input stream is open. Non blocking; this gives - * the last state of the volatile {@link #closed} field. - * @throws IOException if the connection is closed. - */ - private void checkNotClosed() throws IOException { - if (closed) { - throw new IOException( - ": " + FSExceptionMessages.STREAM_IS_CLOSED + " Key: " + key); - } - } -} diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/ChunkGroupOutputStream.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/ChunkGroupOutputStream.java deleted file mode 100644 index 3742a9a5d18..00000000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/ChunkGroupOutputStream.java +++ /dev/null @@ -1,733 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.client.io; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import org.apache.hadoop.fs.FSExceptionMessages; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.Result; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerInfo; -import org.apache.hadoop.hdds.client.BlockID; -import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerWithPipeline; -import org.apache.hadoop.io.retry.RetryPolicy; -import org.apache.hadoop.ozone.om.helpers.OmKeyLocationInfoGroup; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationType; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationFactor; -import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; -import org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos.ObjectStageChangeRequestProto; -import org.apache.hadoop.ozone.om.helpers.OmKeyArgs; -import org.apache.hadoop.ozone.om.helpers.OmKeyInfo; -import org.apache.hadoop.ozone.om.helpers.OmKeyLocationInfo; -import org.apache.hadoop.ozone.om.helpers.OpenKeySession; -import org.apache.hadoop.ozone.om.protocolPB.OzoneManagerProtocolClientSideTranslatorPB; -import org.apache.hadoop.hdds.scm.XceiverClientManager; -import org.apache.hadoop.hdds.scm.XceiverClientSpi; -import org.apache.hadoop.hdds.scm.container.common.helpers - .StorageContainerException; -import org.apache.hadoop.hdds.scm.protocolPB - .StorageContainerLocationProtocolClientSideTranslatorPB; -import org.apache.hadoop.hdds.scm.storage.ChunkOutputStream; -import org.apache.hadoop.hdds.scm.storage.ContainerProtocolCalls; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.io.InterruptedIOException; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.ListIterator; - -/** - * Maintaining a list of ChunkInputStream. Write based on offset. - * - * Note that this may write to multiple containers in one write call. In case - * that first container succeeded but later ones failed, the succeeded writes - * are not rolled back. - * - * TODO : currently not support multi-thread access. - */ -public class ChunkGroupOutputStream extends OutputStream { - - public static final Logger LOG = - LoggerFactory.getLogger(ChunkGroupOutputStream.class); - - // array list's get(index) is O(1) - private final ArrayList streamEntries; - private int currentStreamIndex; - private long byteOffset; - private final OzoneManagerProtocolClientSideTranslatorPB omClient; - private final - StorageContainerLocationProtocolClientSideTranslatorPB scmClient; - private final OmKeyArgs keyArgs; - private final long openID; - private final XceiverClientManager xceiverClientManager; - private final int chunkSize; - private final String requestID; - private boolean closed; - private final RetryPolicy retryPolicy; - /** - * A constructor for testing purpose only. - */ - @VisibleForTesting - public ChunkGroupOutputStream() { - streamEntries = new ArrayList<>(); - omClient = null; - scmClient = null; - keyArgs = null; - openID = -1; - xceiverClientManager = null; - chunkSize = 0; - requestID = null; - closed = false; - retryPolicy = null; - } - - /** - * For testing purpose only. Not building output stream from blocks, but - * taking from externally. - * - * @param outputStream - * @param length - */ - @VisibleForTesting - public void addStream(OutputStream outputStream, long length) { - streamEntries.add(new ChunkOutputStreamEntry(outputStream, length)); - } - - @VisibleForTesting - public List getStreamEntries() { - return streamEntries; - } - - public List getLocationInfoList() { - List locationInfoList = new ArrayList<>(); - for (ChunkOutputStreamEntry streamEntry : streamEntries) { - OmKeyLocationInfo info = - new OmKeyLocationInfo.Builder().setBlockID(streamEntry.blockID) - .setShouldCreateContainer(false) - .setLength(streamEntry.currentPosition).setOffset(0).build(); - locationInfoList.add(info); - } - return locationInfoList; - } - - public ChunkGroupOutputStream( - OpenKeySession handler, XceiverClientManager xceiverClientManager, - StorageContainerLocationProtocolClientSideTranslatorPB scmClient, - OzoneManagerProtocolClientSideTranslatorPB omClient, - int chunkSize, String requestId, ReplicationFactor factor, - ReplicationType type, RetryPolicy retryPolicy) throws IOException { - this.streamEntries = new ArrayList<>(); - this.currentStreamIndex = 0; - this.byteOffset = 0; - this.omClient = omClient; - this.scmClient = scmClient; - OmKeyInfo info = handler.getKeyInfo(); - this.keyArgs = new OmKeyArgs.Builder() - .setVolumeName(info.getVolumeName()) - .setBucketName(info.getBucketName()) - .setKeyName(info.getKeyName()) - .setType(type) - .setFactor(factor) - .setDataSize(info.getDataSize()).build(); - this.openID = handler.getId(); - this.xceiverClientManager = xceiverClientManager; - this.chunkSize = chunkSize; - this.requestID = requestId; - this.retryPolicy = retryPolicy; - LOG.debug("Expecting open key with one block, but got" + - info.getKeyLocationVersions().size()); - } - - /** - * When a key is opened, it is possible that there are some blocks already - * allocated to it for this open session. In this case, to make use of these - * blocks, we need to add these blocks to stream entries. But, a key's version - * also includes blocks from previous versions, we need to avoid adding these - * old blocks to stream entries, because these old blocks should not be picked - * for write. To do this, the following method checks that, only those - * blocks created in this particular open version are added to stream entries. - * - * @param version the set of blocks that are pre-allocated. - * @param openVersion the version corresponding to the pre-allocation. - * @throws IOException - */ - public void addPreallocateBlocks(OmKeyLocationInfoGroup version, - long openVersion) throws IOException { - // server may return any number of blocks, (0 to any) - // only the blocks allocated in this open session (block createVersion - // equals to open session version) - for (OmKeyLocationInfo subKeyInfo : version.getLocationList()) { - if (subKeyInfo.getCreateVersion() == openVersion) { - checkKeyLocationInfo(subKeyInfo); - } - } - } - - private void checkKeyLocationInfo(OmKeyLocationInfo subKeyInfo) - throws IOException { - ContainerWithPipeline containerWithPipeline = scmClient - .getContainerWithPipeline(subKeyInfo.getContainerID()); - ContainerInfo container = containerWithPipeline.getContainerInfo(); - - XceiverClientSpi xceiverClient = - xceiverClientManager.acquireClient(containerWithPipeline.getPipeline(), - container.getContainerID()); - // create container if needed - if (subKeyInfo.getShouldCreateContainer()) { - try { - ContainerProtocolCalls.createContainer(xceiverClient, - container.getContainerID(), requestID); - scmClient.notifyObjectStageChange( - ObjectStageChangeRequestProto.Type.container, - subKeyInfo.getContainerID(), - ObjectStageChangeRequestProto.Op.create, - ObjectStageChangeRequestProto.Stage.complete); - } catch (StorageContainerException ex) { - if (ex.getResult().equals(Result.CONTAINER_EXISTS)) { - //container already exist, this should never happen - LOG.debug("Container {} already exists.", - container.getContainerID()); - } else { - LOG.error("Container creation failed for {}.", - container.getContainerID(), ex); - throw ex; - } - } - } - streamEntries.add(new ChunkOutputStreamEntry(subKeyInfo.getBlockID(), - keyArgs.getKeyName(), xceiverClientManager, xceiverClient, requestID, - chunkSize, subKeyInfo.getLength())); - } - - @VisibleForTesting - public long getByteOffset() { - return byteOffset; - } - - - @Override - public void write(int b) throws IOException { - byte[] buf = new byte[1]; - buf[0] = (byte) b; - write(buf, 0, 1); - } - - /** - * Try to write the bytes sequence b[off:off+len) to streams. - * - * NOTE: Throws exception if the data could not fit into the remaining space. - * In which case nothing will be written. - * TODO:May need to revisit this behaviour. - * - * @param b byte data - * @param off starting offset - * @param len length to write - * @throws IOException - */ - @Override - public void write(byte[] b, int off, int len) - throws IOException { - checkNotClosed(); - handleWrite(b, off, len); - } - - private void handleWrite(byte[] b, int off, int len) throws IOException { - if (b == null) { - throw new NullPointerException(); - } - if ((off < 0) || (off > b.length) || (len < 0) || - ((off + len) > b.length) || ((off + len) < 0)) { - throw new IndexOutOfBoundsException(); - } - if (len == 0) { - return; - } - int succeededAllocates = 0; - while (len > 0) { - if (streamEntries.size() <= currentStreamIndex) { - Preconditions.checkNotNull(omClient); - // allocate a new block, if a exception happens, log an error and - // throw exception to the caller directly, and the write fails. - try { - allocateNewBlock(currentStreamIndex); - succeededAllocates += 1; - } catch (IOException ioe) { - LOG.error("Try to allocate more blocks for write failed, already " + - "allocated " + succeededAllocates + " blocks for this write."); - throw ioe; - } - } - // in theory, this condition should never violate due the check above - // still do a sanity check. - Preconditions.checkArgument(currentStreamIndex < streamEntries.size()); - ChunkOutputStreamEntry current = streamEntries.get(currentStreamIndex); - int writeLen = Math.min(len, (int) current.getRemaining()); - try { - current.write(b, off, writeLen); - } catch (IOException ioe) { - if (checkIfContainerIsClosed(ioe)) { - handleCloseContainerException(current, currentStreamIndex); - continue; - } else { - throw ioe; - } - } - if (current.getRemaining() <= 0) { - // since the current block is already written close the stream. - handleFlushOrClose(true); - currentStreamIndex += 1; - } - len -= writeLen; - off += writeLen; - byteOffset += writeLen; - } - } - - private long getCommittedBlockLength(ChunkOutputStreamEntry streamEntry) - throws IOException { - long blockLength; - ContainerProtos.GetCommittedBlockLengthResponseProto responseProto; - RetryPolicy.RetryAction action; - int numRetries = 0; - while (true) { - try { - responseProto = ContainerProtocolCalls - .getCommittedBlockLength(streamEntry.xceiverClient, - streamEntry.blockID, requestID); - blockLength = responseProto.getBlockLength(); - return blockLength; - } catch (StorageContainerException sce) { - try { - action = retryPolicy.shouldRetry(sce, numRetries, 0, true); - } catch (Exception e) { - throw e instanceof IOException ? (IOException) e : new IOException(e); - } - if (action.action == RetryPolicy.RetryAction.RetryDecision.FAIL) { - if (action.reason != null) { - LOG.error( - "GetCommittedBlockLength request failed. " + action.reason, - sce); - } - throw sce; - } - - // Throw the exception if the thread is interrupted - if (Thread.currentThread().isInterrupted()) { - LOG.warn("Interrupted while trying for connection"); - throw sce; - } - Preconditions.checkArgument( - action.action == RetryPolicy.RetryAction.RetryDecision.RETRY); - try { - Thread.sleep(action.delayMillis); - } catch (InterruptedException e) { - throw (IOException) new InterruptedIOException( - "Interrupted: action=" + action + ", retry policy=" + retryPolicy) - .initCause(e); - } - numRetries++; - LOG.trace("Retrying GetCommittedBlockLength request. Already tried " - + numRetries + " time(s); retry policy is " + retryPolicy); - continue; - } - } - } - - /** - * Discards the subsequent pre allocated blocks and removes the streamEntries - * from the streamEntries list for the container which is closed. - * @param containerID id of the closed container - */ - private void discardPreallocatedBlocks(long containerID) { - // currentStreamIndex < streamEntries.size() signifies that, there are still - // pre allocated blocks available. - if (currentStreamIndex < streamEntries.size()) { - ListIterator streamEntryIterator = - streamEntries.listIterator(currentStreamIndex); - while (streamEntryIterator.hasNext()) { - if (streamEntryIterator.next().blockID.getContainerID() - == containerID) { - streamEntryIterator.remove(); - } - } - } - } - - /** - * It might be possible that the blocks pre allocated might never get written - * while the stream gets closed normally. In such cases, it would be a good - * idea to trim down the locationInfoList by removing the unused blocks if any - * so as only the used block info gets updated on OzoneManager during close. - */ - private void removeEmptyBlocks() { - if (currentStreamIndex < streamEntries.size()) { - ListIterator streamEntryIterator = - streamEntries.listIterator(currentStreamIndex); - while (streamEntryIterator.hasNext()) { - if (streamEntryIterator.next().currentPosition == 0) { - streamEntryIterator.remove(); - } - } - } - } - /** - * It performs following actions : - * a. Updates the committed length at datanode for the current stream in - * datanode. - * b. Reads the data from the underlying buffer and writes it the next stream. - * - * @param streamEntry StreamEntry - * @param streamIndex Index of the entry - * @throws IOException Throws IOexception if Write fails - */ - private void handleCloseContainerException(ChunkOutputStreamEntry streamEntry, - int streamIndex) throws IOException { - long committedLength = 0; - ByteBuffer buffer = streamEntry.getBuffer(); - if (buffer == null) { - // the buffer here will be null only when closeContainerException is - // hit while calling putKey during close on chunkOutputStream. - // Since closeContainer auto commit pending keys, no need to do - // anything here. - return; - } - - // In case where not a single chunk of data has been written to the Datanode - // yet. This block does not yet exist on the datanode but cached on the - // outputStream buffer. No need to call GetCommittedBlockLength here - // for this block associated with the stream here. - if (streamEntry.currentPosition >= chunkSize - || streamEntry.currentPosition != buffer.position()) { - committedLength = getCommittedBlockLength(streamEntry); - // update the length of the current stream - streamEntry.currentPosition = committedLength; - } - - if (buffer.position() > 0) { - // If the data is still cached in the underlying stream, we need to - // allocate new block and write this data in the datanode. The cached - // data in the buffer does not exceed chunkSize. - Preconditions.checkState(buffer.position() < chunkSize); - currentStreamIndex += 1; - // readjust the byteOffset value to the length actually been written. - byteOffset -= buffer.position(); - handleWrite(buffer.array(), 0, buffer.position()); - } - - // just clean up the current stream. Since the container is already closed, - // it will be auto committed. No need to call close again here. - streamEntry.cleanup(); - // This case will arise when while writing the first chunk itself fails. - // In such case, the current block associated with the stream has no data - // written. Remove it from the current stream list. - if (committedLength == 0) { - streamEntries.remove(streamIndex); - Preconditions.checkArgument(currentStreamIndex != 0); - currentStreamIndex -= 1; - } - // discard subsequent pre allocated blocks from the streamEntries list - // from the closed container - discardPreallocatedBlocks(streamEntry.blockID.getContainerID()); - } - - private boolean checkIfContainerIsClosed(IOException ioe) { - return Optional.of(ioe.getCause()) - .filter(e -> e instanceof StorageContainerException) - .map(e -> (StorageContainerException) e) - .filter(sce -> sce.getResult() == Result.CLOSED_CONTAINER_IO) - .isPresent(); - } - - private long getKeyLength() { - return streamEntries.parallelStream().mapToLong(e -> e.currentPosition) - .sum(); - } - - /** - * Contact OM to get a new block. Set the new block with the index (e.g. - * first block has index = 0, second has index = 1 etc.) - * - * The returned block is made to new ChunkOutputStreamEntry to write. - * - * @param index the index of the block. - * @throws IOException - */ - private void allocateNewBlock(int index) throws IOException { - OmKeyLocationInfo subKeyInfo = omClient.allocateBlock(keyArgs, openID); - checkKeyLocationInfo(subKeyInfo); - } - - @Override - public void flush() throws IOException { - checkNotClosed(); - handleFlushOrClose(false); - } - - /** - * Close or Flush the latest outputStream. - * @param close Flag which decides whether to call close or flush on the - * outputStream. - * @throws IOException In case, flush or close fails with exception. - */ - private void handleFlushOrClose(boolean close) throws IOException { - if (streamEntries.size() == 0) { - return; - } - int size = streamEntries.size(); - int streamIndex = - currentStreamIndex >= size ? size - 1 : currentStreamIndex; - ChunkOutputStreamEntry entry = streamEntries.get(streamIndex); - if (entry != null) { - try { - if (close) { - entry.close(); - } else { - entry.flush(); - } - } catch (IOException ioe) { - if (checkIfContainerIsClosed(ioe)) { - // This call will allocate a new streamEntry and write the Data. - // Close needs to be retried on the newly allocated streamEntry as - // as well. - handleCloseContainerException(entry, streamIndex); - handleFlushOrClose(close); - } else { - throw ioe; - } - } - } - } - - /** - * Commit the key to OM, this will add the blocks as the new key blocks. - * - * @throws IOException - */ - @Override - public void close() throws IOException { - if (closed) { - return; - } - closed = true; - handleFlushOrClose(true); - if (keyArgs != null) { - // in test, this could be null - removeEmptyBlocks(); - Preconditions.checkState(byteOffset == getKeyLength()); - keyArgs.setDataSize(byteOffset); - keyArgs.setLocationInfoList(getLocationInfoList()); - omClient.commitKey(keyArgs, openID); - } else { - LOG.warn("Closing ChunkGroupOutputStream, but key args is null"); - } - } - - /** - * Builder class of ChunkGroupOutputStream. - */ - public static class Builder { - private OpenKeySession openHandler; - private XceiverClientManager xceiverManager; - private StorageContainerLocationProtocolClientSideTranslatorPB scmClient; - private OzoneManagerProtocolClientSideTranslatorPB omClient; - private int chunkSize; - private String requestID; - private ReplicationType type; - private ReplicationFactor factor; - private RetryPolicy retryPolicy; - - public Builder setHandler(OpenKeySession handler) { - this.openHandler = handler; - return this; - } - - public Builder setXceiverClientManager(XceiverClientManager manager) { - this.xceiverManager = manager; - return this; - } - - public Builder setScmClient( - StorageContainerLocationProtocolClientSideTranslatorPB client) { - this.scmClient = client; - return this; - } - - public Builder setOmClient( - OzoneManagerProtocolClientSideTranslatorPB client) { - this.omClient = client; - return this; - } - - public Builder setChunkSize(int size) { - this.chunkSize = size; - return this; - } - - public Builder setRequestID(String id) { - this.requestID = id; - return this; - } - - public Builder setType(ReplicationType replicationType) { - this.type = replicationType; - return this; - } - - public Builder setFactor(ReplicationFactor replicationFactor) { - this.factor = replicationFactor; - return this; - } - - public ChunkGroupOutputStream build() throws IOException { - return new ChunkGroupOutputStream(openHandler, xceiverManager, scmClient, - omClient, chunkSize, requestID, factor, type, retryPolicy); - } - - public Builder setRetryPolicy(RetryPolicy rPolicy) { - this.retryPolicy = rPolicy; - return this; - } - - } - - private static class ChunkOutputStreamEntry extends OutputStream { - private OutputStream outputStream; - private final BlockID blockID; - private final String key; - private final XceiverClientManager xceiverClientManager; - private final XceiverClientSpi xceiverClient; - private final String requestId; - private final int chunkSize; - // total number of bytes that should be written to this stream - private final long length; - // the current position of this stream 0 <= currentPosition < length - private long currentPosition; - - ChunkOutputStreamEntry(BlockID blockID, String key, - XceiverClientManager xceiverClientManager, - XceiverClientSpi xceiverClient, String requestId, int chunkSize, - long length) { - this.outputStream = null; - this.blockID = blockID; - this.key = key; - this.xceiverClientManager = xceiverClientManager; - this.xceiverClient = xceiverClient; - this.requestId = requestId; - this.chunkSize = chunkSize; - - this.length = length; - this.currentPosition = 0; - } - - /** - * For testing purpose, taking a some random created stream instance. - * @param outputStream a existing writable output stream - * @param length the length of data to write to the stream - */ - ChunkOutputStreamEntry(OutputStream outputStream, long length) { - this.outputStream = outputStream; - this.blockID = null; - this.key = null; - this.xceiverClientManager = null; - this.xceiverClient = null; - this.requestId = null; - this.chunkSize = -1; - - this.length = length; - this.currentPosition = 0; - } - - long getLength() { - return length; - } - - long getRemaining() { - return length - currentPosition; - } - - private void checkStream() { - if (this.outputStream == null) { - this.outputStream = new ChunkOutputStream(blockID, - key, xceiverClientManager, xceiverClient, - requestId, chunkSize); - } - } - - @Override - public void write(int b) throws IOException { - checkStream(); - outputStream.write(b); - this.currentPosition += 1; - } - - @Override - public void write(byte[] b, int off, int len) throws IOException { - checkStream(); - outputStream.write(b, off, len); - this.currentPosition += len; - } - - @Override - public void flush() throws IOException { - if (this.outputStream != null) { - this.outputStream.flush(); - } - } - - @Override - public void close() throws IOException { - if (this.outputStream != null) { - this.outputStream.close(); - } - } - - ByteBuffer getBuffer() throws IOException { - if (this.outputStream instanceof ChunkOutputStream) { - ChunkOutputStream out = (ChunkOutputStream) this.outputStream; - return out.getBuffer(); - } - throw new IOException("Invalid Output Stream for Key: " + key); - } - - public void cleanup() { - checkStream(); - if (this.outputStream instanceof ChunkOutputStream) { - ChunkOutputStream out = (ChunkOutputStream) this.outputStream; - out.cleanup(); - } - } - - } - - /** - * Verify that the output stream is open. Non blocking; this gives - * the last state of the volatile {@link #closed} field. - * @throws IOException if the connection is closed. - */ - private void checkNotClosed() throws IOException { - if (closed) { - throw new IOException( - ": " + FSExceptionMessages.STREAM_IS_CLOSED + " Key: " + keyArgs - .getKeyName()); - } - } -} diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/OzoneInputStream.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/OzoneInputStream.java deleted file mode 100644 index e1f65e69a86..00000000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/OzoneInputStream.java +++ /dev/null @@ -1,65 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.client.io; - -import org.apache.hadoop.hdds.scm.storage.ChunkInputStream; - -import java.io.IOException; -import java.io.InputStream; - -/** - * OzoneInputStream is used to read data from Ozone. - * It uses SCM's {@link ChunkInputStream} for reading the data. - */ -public class OzoneInputStream extends InputStream { - - private final InputStream inputStream; - - /** - * Constructs OzoneInputStream with ChunkInputStream. - * - * @param inputStream - */ - public OzoneInputStream(InputStream inputStream) { - this.inputStream = inputStream; - } - - @Override - public int read() throws IOException { - return inputStream.read(); - } - - @Override - public int read(byte[] b, int off, int len) throws IOException { - return inputStream.read(b, off, len); - } - - @Override - public synchronized void close() throws IOException { - inputStream.close(); - } - - @Override - public int available() throws IOException { - return inputStream.available(); - } - - public InputStream getInputStream() { - return inputStream; - } -} diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/OzoneOutputStream.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/OzoneOutputStream.java deleted file mode 100644 index 5369220a433..00000000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/OzoneOutputStream.java +++ /dev/null @@ -1,64 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.client.io; - -import java.io.IOException; -import java.io.OutputStream; - -/** - * OzoneOutputStream is used to write data into Ozone. - * It uses SCM's {@link ChunkGroupOutputStream} for writing the data. - */ -public class OzoneOutputStream extends OutputStream { - - private final OutputStream outputStream; - - /** - * Constructs OzoneOutputStream with ChunkGroupOutputStream. - * - * @param outputStream - */ - public OzoneOutputStream(OutputStream outputStream) { - this.outputStream = outputStream; - } - - @Override - public void write(int b) throws IOException { - outputStream.write(b); - } - - @Override - public void write(byte[] b, int off, int len) throws IOException { - outputStream.write(b, off, len); - } - - @Override - public synchronized void flush() throws IOException { - outputStream.flush(); - } - - @Override - public synchronized void close() throws IOException { - //commitKey can be done here, if needed. - outputStream.close(); - } - - public OutputStream getOutputStream() { - return outputStream; - } -} diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/package-info.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/package-info.java deleted file mode 100644 index 493ece8074e..00000000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/package-info.java +++ /dev/null @@ -1,23 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client.io; - -/** - * This package contains Ozone I/O classes. - */ diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/package-info.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/package-info.java deleted file mode 100644 index 7e2591a20ee..00000000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/package-info.java +++ /dev/null @@ -1,23 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client; - -/** - * This package contains Ozone Client classes. - */ \ No newline at end of file diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/protocol/ClientProtocol.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/protocol/ClientProtocol.java deleted file mode 100644 index 008b69d2d16..00000000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/protocol/ClientProtocol.java +++ /dev/null @@ -1,329 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client.protocol; - -import org.apache.hadoop.fs.StorageType; -import org.apache.hadoop.ozone.OzoneAcl; -import org.apache.hadoop.ozone.client.*; -import org.apache.hadoop.hdds.client.OzoneQuota; -import org.apache.hadoop.hdds.client.ReplicationFactor; -import org.apache.hadoop.hdds.client.ReplicationType; -import org.apache.hadoop.ozone.client.io.OzoneInputStream; -import org.apache.hadoop.ozone.client.io.OzoneOutputStream; - -import java.io.IOException; -import java.util.List; - -/** - * An implementer of this interface is capable of connecting to Ozone Cluster - * and perform client operations. The protocol used for communication is - * determined by the implementation class specified by - * property ozone.client.protocol. The build-in implementation - * includes: {@link org.apache.hadoop.ozone.client.rpc.RpcClient} for RPC and - * {@link org.apache.hadoop.ozone.client.rest.RestClient} for REST. - */ -public interface ClientProtocol { - - /** - * Creates a new Volume. - * @param volumeName Name of the Volume - * @throws IOException - */ - void createVolume(String volumeName) - throws IOException; - - /** - * Creates a new Volume with properties set in VolumeArgs. - * @param volumeName Name of the Volume - * @param args Properties to be set for the Volume - * @throws IOException - */ - void createVolume(String volumeName, VolumeArgs args) - throws IOException; - - /** - * Sets the owner of volume. - * @param volumeName Name of the Volume - * @param owner to be set for the Volume - * @throws IOException - */ - void setVolumeOwner(String volumeName, String owner) throws IOException; - - /** - * Set Volume Quota. - * @param volumeName Name of the Volume - * @param quota Quota to be set for the Volume - * @throws IOException - */ - void setVolumeQuota(String volumeName, OzoneQuota quota) - throws IOException; - - /** - * Returns {@link OzoneVolume}. - * @param volumeName Name of the Volume - * @return {@link OzoneVolume} - * @throws IOException - * */ - OzoneVolume getVolumeDetails(String volumeName) - throws IOException; - - /** - * Checks if a Volume exists and the user with a role specified has access - * to the Volume. - * @param volumeName Name of the Volume - * @param acl requested acls which needs to be checked for access - * @return Boolean - True if the user with a role can access the volume. - * This is possible for owners of the volume and admin users - * @throws IOException - */ - boolean checkVolumeAccess(String volumeName, OzoneAcl acl) - throws IOException; - - /** - * Deletes an empty Volume. - * @param volumeName Name of the Volume - * @throws IOException - */ - void deleteVolume(String volumeName) throws IOException; - - /** - * Lists all volumes in the cluster that matches the volumePrefix, - * size of the returned list depends on maxListResult. If volume prefix - * is null, returns all the volumes. The caller has to make multiple calls - * to read all volumes. - * - * @param volumePrefix Volume prefix to match - * @param prevVolume Starting point of the list, this volume is excluded - * @param maxListResult Max number of volumes to return. - * @return {@code List} - * @throws IOException - */ - List listVolumes(String volumePrefix, String prevVolume, - int maxListResult) - throws IOException; - - /** - * Lists all volumes in the cluster that are owned by the specified - * user and matches the volumePrefix, size of the returned list depends on - * maxListResult. If the user is null, return volumes owned by current user. - * If volume prefix is null, returns all the volumes. The caller has to make - * multiple calls to read all volumes. - * - * @param user User Name - * @param volumePrefix Volume prefix to match - * @param prevVolume Starting point of the list, this volume is excluded - * @param maxListResult Max number of volumes to return. - * @return {@code List} - * @throws IOException - */ - List listVolumes(String user, String volumePrefix, - String prevVolume, int maxListResult) - throws IOException; - - /** - * Creates a new Bucket in the Volume. - * @param volumeName Name of the Volume - * @param bucketName Name of the Bucket - * @throws IOException - */ - void createBucket(String volumeName, String bucketName) - throws IOException; - - /** - * Creates a new Bucket in the Volume, with properties set in BucketArgs. - * @param volumeName Name of the Volume - * @param bucketName Name of the Bucket - * @param bucketArgs Bucket Arguments - * @throws IOException - */ - void createBucket(String volumeName, String bucketName, - BucketArgs bucketArgs) - throws IOException; - - /** - * Adds ACLs to the Bucket. - * @param volumeName Name of the Volume - * @param bucketName Name of the Bucket - * @param addAcls ACLs to be added - * @throws IOException - */ - void addBucketAcls(String volumeName, String bucketName, - List addAcls) - throws IOException; - - /** - * Removes ACLs from a Bucket. - * @param volumeName Name of the Volume - * @param bucketName Name of the Bucket - * @param removeAcls ACLs to be removed - * @throws IOException - */ - void removeBucketAcls(String volumeName, String bucketName, - List removeAcls) - throws IOException; - - - /** - * Enables or disables Bucket Versioning. - * @param volumeName Name of the Volume - * @param bucketName Name of the Bucket - * @param versioning True to enable Versioning, False to disable. - * @throws IOException - */ - void setBucketVersioning(String volumeName, String bucketName, - Boolean versioning) - throws IOException; - - /** - * Sets the Storage Class of a Bucket. - * @param volumeName Name of the Volume - * @param bucketName Name of the Bucket - * @param storageType StorageType to be set - * @throws IOException - */ - void setBucketStorageType(String volumeName, String bucketName, - StorageType storageType) - throws IOException; - - /** - * Deletes a bucket if it is empty. - * @param volumeName Name of the Volume - * @param bucketName Name of the Bucket - * @throws IOException - */ - void deleteBucket(String volumeName, String bucketName) - throws IOException; - - /** - * True if the bucket exists and user has read access - * to the bucket else throws Exception. - * @param volumeName Name of the Volume - * @param bucketName Name of the Bucket - * @throws IOException - */ - void checkBucketAccess(String volumeName, String bucketName) - throws IOException; - - /** - * Returns {@link OzoneBucket}. - * @param volumeName Name of the Volume - * @param bucketName Name of the Bucket - * @return {@link OzoneBucket} - * @throws IOException - */ - OzoneBucket getBucketDetails(String volumeName, String bucketName) - throws IOException; - - /** - * Returns the List of Buckets in the Volume that matches the bucketPrefix, - * size of the returned list depends on maxListResult. The caller has to make - * multiple calls to read all volumes. - * @param volumeName Name of the Volume - * @param bucketPrefix Bucket prefix to match - * @param prevBucket Starting point of the list, this bucket is excluded - * @param maxListResult Max number of buckets to return. - * @return {@code List} - * @throws IOException - */ - List listBuckets(String volumeName, String bucketPrefix, - String prevBucket, int maxListResult) - throws IOException; - - /** - * Writes a key in an existing bucket. - * @param volumeName Name of the Volume - * @param bucketName Name of the Bucket - * @param keyName Name of the Key - * @param size Size of the data - * @return {@link OzoneOutputStream} - * - */ - OzoneOutputStream createKey(String volumeName, String bucketName, - String keyName, long size, ReplicationType type, - ReplicationFactor factor) - throws IOException; - - /** - * Reads a key from an existing bucket. - * @param volumeName Name of the Volume - * @param bucketName Name of the Bucket - * @param keyName Name of the Key - * @return {@link OzoneInputStream} - * @throws IOException - */ - OzoneInputStream getKey(String volumeName, String bucketName, String keyName) - throws IOException; - - - /** - * Deletes an existing key. - * @param volumeName Name of the Volume - * @param bucketName Name of the Bucket - * @param keyName Name of the Key - * @throws IOException - */ - void deleteKey(String volumeName, String bucketName, String keyName) - throws IOException; - - /** - * Renames an existing key within a bucket. - * @param volumeName Name of the Volume - * @param bucketName Name of the Bucket - * @param fromKeyName Name of the Key to be renamed - * @param toKeyName New name to be used for the Key - * @throws IOException - */ - void renameKey(String volumeName, String bucketName, String fromKeyName, - String toKeyName) throws IOException; - - /** - * Returns list of Keys in {Volume/Bucket} that matches the keyPrefix, - * size of the returned list depends on maxListResult. The caller has - * to make multiple calls to read all keys. - * @param volumeName Name of the Volume - * @param bucketName Name of the Bucket - * @param keyPrefix Bucket prefix to match - * @param prevKey Starting point of the list, this key is excluded - * @param maxListResult Max number of buckets to return. - * @return {@code List} - * @throws IOException - */ - List listKeys(String volumeName, String bucketName, - String keyPrefix, String prevKey, int maxListResult) - throws IOException; - - - /** - * Get OzoneKey. - * @param volumeName Name of the Volume - * @param bucketName Name of the Bucket - * @param keyName Key name - * @return {@link OzoneKey} - * @throws IOException - */ - OzoneKeyDetails getKeyDetails(String volumeName, String bucketName, - String keyName) - throws IOException; - - /** - * Close and release the resources. - */ - void close() throws IOException; - -} diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/protocol/package-info.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/protocol/package-info.java deleted file mode 100644 index f4890a1e8b8..00000000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/protocol/package-info.java +++ /dev/null @@ -1,23 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client.protocol; - -/** - * This package contains Ozone client protocol library classes. - */ diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/DefaultRestServerSelector.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/DefaultRestServerSelector.java deleted file mode 100644 index abdc2fbe19a..00000000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/DefaultRestServerSelector.java +++ /dev/null @@ -1,36 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client.rest; - -import org.apache.hadoop.ozone.om.helpers.ServiceInfo; - -import java.util.List; -import java.util.Random; - -/** - * Default selector randomly picks one of the REST Server from the list. - */ -public class DefaultRestServerSelector implements RestServerSelector { - - @Override - public ServiceInfo getRestServer(List restServices) { - return restServices.get( - new Random().nextInt(restServices.size())); - } -} diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/OzoneExceptionMapper.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/OzoneExceptionMapper.java deleted file mode 100644 index 6c479f7721a..00000000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/OzoneExceptionMapper.java +++ /dev/null @@ -1,45 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client.rest; - - -import javax.ws.rs.core.Response; -import javax.ws.rs.ext.ExceptionMapper; - -import org.slf4j.MDC; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Class the represents various errors returned by the - * Object Layer. - */ -public class OzoneExceptionMapper implements ExceptionMapper { - private static final Logger LOG = - LoggerFactory.getLogger(OzoneExceptionMapper.class); - - @Override - public Response toResponse(OzoneException exception) { - LOG.debug("Returning exception. ex: {}", exception.toJsonString()); - MDC.clear(); - return Response.status((int)exception.getHttpCode()) - .entity(exception.toJsonString()).build(); - } - -} diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/RestClient.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/RestClient.java deleted file mode 100644 index fdd049a5271..00000000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/RestClient.java +++ /dev/null @@ -1,912 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client.rest; - -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.base.Preconditions; -import com.google.common.base.Strings; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.StorageType; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.hdds.scm.client.HddsClientUtils; -import org.apache.hadoop.net.NetUtils; -import org.apache.hadoop.ozone.OzoneAcl; -import org.apache.hadoop.ozone.OzoneConfigKeys; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.client.*; -import org.apache.hadoop.hdds.client.OzoneQuota; -import org.apache.hadoop.hdds.client.ReplicationFactor; -import org.apache.hadoop.hdds.client.ReplicationType; -import org.apache.hadoop.ozone.client.io.OzoneInputStream; -import org.apache.hadoop.ozone.client.io.OzoneOutputStream; -import org.apache.hadoop.ozone.client.protocol.ClientProtocol; -import org.apache.hadoop.ozone.client.rest.headers.Header; -import org.apache.hadoop.ozone.client.rest.response.BucketInfo; -import org.apache.hadoop.ozone.client.rest.response.KeyInfoDetails; -import org.apache.hadoop.ozone.client.rest.response.VolumeInfo; -import org.apache.hadoop.ozone.om.OMConfigKeys; -import org.apache.hadoop.ozone.om.helpers.ServiceInfo; -import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.ServicePort; -import org.apache.hadoop.ozone.web.response.ListBuckets; -import org.apache.hadoop.ozone.web.response.ListKeys; -import org.apache.hadoop.ozone.web.response.ListVolumes; -import org.apache.hadoop.security.UserGroupInformation; -import org.apache.hadoop.util.Time; -import org.apache.http.HttpEntity; -import org.apache.http.HttpHeaders; -import org.apache.http.HttpResponse; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.HttpDelete; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.methods.HttpPut; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.client.utils.URIBuilder; -import org.apache.http.entity.InputStreamEntity; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; -import org.apache.http.util.EntityUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PipedInputStream; -import java.io.PipedOutputStream; -import java.net.InetSocketAddress; -import java.net.URI; -import java.net.URISyntaxException; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.FutureTask; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -import static java.net.HttpURLConnection.HTTP_CREATED; -import static java.net.HttpURLConnection.HTTP_OK; - -/** - * Ozone Client REST protocol implementation. It uses REST protocol to - * connect to Ozone Handler that executes client calls. - */ -public class RestClient implements ClientProtocol { - - private static final String PATH_SEPARATOR = "/"; - private static final Logger LOG = LoggerFactory.getLogger(RestClient.class); - - private final Configuration conf; - private final URI ozoneRestUri; - private final CloseableHttpClient httpClient; - private final UserGroupInformation ugi; - private final OzoneAcl.OzoneACLRights userRights; - - /** - * Creates RestClient instance with the given configuration. - * @param conf Configuration - * @throws IOException - */ - public RestClient(Configuration conf) - throws IOException { - try { - Preconditions.checkNotNull(conf); - this.conf = conf; - - long socketTimeout = conf.getTimeDuration( - OzoneConfigKeys.OZONE_CLIENT_SOCKET_TIMEOUT, - OzoneConfigKeys.OZONE_CLIENT_SOCKET_TIMEOUT_DEFAULT, - TimeUnit.MILLISECONDS); - long connectionTimeout = conf.getTimeDuration( - OzoneConfigKeys.OZONE_CLIENT_CONNECTION_TIMEOUT, - OzoneConfigKeys.OZONE_CLIENT_CONNECTION_TIMEOUT_DEFAULT, - TimeUnit.MILLISECONDS); - int maxConnection = conf.getInt( - OzoneConfigKeys.OZONE_REST_CLIENT_HTTP_CONNECTION_MAX, - OzoneConfigKeys.OZONE_REST_CLIENT_HTTP_CONNECTION_DEFAULT); - - int maxConnectionPerRoute = conf.getInt( - OzoneConfigKeys.OZONE_REST_CLIENT_HTTP_CONNECTION_PER_ROUTE_MAX, - OzoneConfigKeys - .OZONE_REST_CLIENT_HTTP_CONNECTION_PER_ROUTE_MAX_DEFAULT - ); - - /* - To make RestClient Thread safe, creating the HttpClient with - ThreadSafeClientConnManager. - */ - PoolingHttpClientConnectionManager connManager = - new PoolingHttpClientConnectionManager(); - connManager.setMaxTotal(maxConnection); - connManager.setDefaultMaxPerRoute(maxConnectionPerRoute); - - this.httpClient = HttpClients.custom() - .setConnectionManager(connManager) - .setDefaultRequestConfig( - RequestConfig.custom() - .setSocketTimeout(Math.toIntExact(socketTimeout)) - .setConnectTimeout(Math.toIntExact(connectionTimeout)) - .build()) - .build(); - this.ugi = UserGroupInformation.getCurrentUser(); - this.userRights = conf.getEnum(OMConfigKeys.OZONE_OM_USER_RIGHTS, - OMConfigKeys.OZONE_OM_USER_RIGHTS_DEFAULT); - - // TODO: Add new configuration parameter to configure RestServerSelector. - RestServerSelector defaultSelector = new DefaultRestServerSelector(); - InetSocketAddress restServer = getOzoneRestServerAddress(defaultSelector); - URIBuilder uriBuilder = new URIBuilder() - .setScheme("http") - .setHost(restServer.getHostName()) - .setPort(restServer.getPort()); - this.ozoneRestUri = uriBuilder.build(); - - } catch (URISyntaxException e) { - throw new IOException(e); - } - } - - private InetSocketAddress getOzoneRestServerAddress( - RestServerSelector selector) throws IOException { - String httpAddress = conf.get(OMConfigKeys.OZONE_OM_HTTP_ADDRESS_KEY); - - if (httpAddress == null) { - throw new IllegalArgumentException( - OMConfigKeys.OZONE_OM_HTTP_ADDRESS_KEY + " must be defined. See" + - " https://wiki.apache.org/hadoop/Ozone#Configuration for" + - " details on configuring Ozone."); - } - - HttpGet httpGet = new HttpGet("http://" + httpAddress + "/serviceList"); - HttpEntity entity = executeHttpRequest(httpGet); - try { - String serviceListJson = EntityUtils.toString(entity); - - ObjectMapper objectMapper = new ObjectMapper(); - TypeReference> serviceInfoReference = - new TypeReference>() { - }; - List services = objectMapper.readValue( - serviceListJson, serviceInfoReference); - - List dataNodeInfos = services.stream().filter( - a -> a.getNodeType().equals(HddsProtos.NodeType.DATANODE)) - .collect(Collectors.toList()); - - ServiceInfo restServer = selector.getRestServer(dataNodeInfos); - - return NetUtils.createSocketAddr( - NetUtils.normalizeHostName(restServer.getHostname()) + ":" - + restServer.getPort(ServicePort.Type.HTTP)); - } finally { - EntityUtils.consume(entity); - } - } - - @Override - public void createVolume(String volumeName) throws IOException { - createVolume(volumeName, VolumeArgs.newBuilder().build()); - } - - @Override - public void createVolume(String volumeName, VolumeArgs volArgs) - throws IOException { - try { - HddsClientUtils.verifyResourceName(volumeName); - Preconditions.checkNotNull(volArgs); - URIBuilder builder = new URIBuilder(ozoneRestUri); - String owner = volArgs.getOwner() == null ? - ugi.getUserName() : volArgs.getOwner(); - //TODO: support for ACLs has to be done in OzoneHandler (rest server) - /** - List listOfAcls = new ArrayList<>(); - //User ACL - listOfAcls.add(new OzoneAcl(OzoneAcl.OzoneACLType.USER, - owner, userRights)); - //ACLs from VolumeArgs - if(volArgs.getAcls() != null) { - listOfAcls.addAll(volArgs.getAcls()); - } - */ - builder.setPath(PATH_SEPARATOR + volumeName); - - String quota = volArgs.getQuota(); - if(quota != null) { - builder.setParameter(Header.OZONE_QUOTA_QUERY_TAG, quota); - } - - HttpPost httpPost = new HttpPost(builder.build()); - addOzoneHeaders(httpPost); - //use admin from VolumeArgs, if it's present - if(volArgs.getAdmin() != null) { - httpPost.removeHeaders(HttpHeaders.AUTHORIZATION); - httpPost.addHeader(HttpHeaders.AUTHORIZATION, - Header.OZONE_SIMPLE_AUTHENTICATION_SCHEME + " " + - volArgs.getAdmin()); - } - httpPost.addHeader(Header.OZONE_USER, owner); - LOG.info("Creating Volume: {}, with {} as owner and quota set to {}.", - volumeName, owner, quota == null ? "default" : quota); - EntityUtils.consume(executeHttpRequest(httpPost)); - } catch (URISyntaxException e) { - throw new IOException(e); - } - } - - - @Override - public void setVolumeOwner(String volumeName, String owner) - throws IOException { - try { - HddsClientUtils.verifyResourceName(volumeName); - Preconditions.checkNotNull(owner); - URIBuilder builder = new URIBuilder(ozoneRestUri); - builder.setPath(PATH_SEPARATOR + volumeName); - HttpPut httpPut = new HttpPut(builder.build()); - addOzoneHeaders(httpPut); - httpPut.addHeader(Header.OZONE_USER, owner); - EntityUtils.consume(executeHttpRequest(httpPut)); - } catch (URISyntaxException e) { - throw new IOException(e); - } - } - - @Override - public void setVolumeQuota(String volumeName, OzoneQuota quota) - throws IOException { - try { - HddsClientUtils.verifyResourceName(volumeName); - Preconditions.checkNotNull(quota); - String quotaString = quota.toString(); - URIBuilder builder = new URIBuilder(ozoneRestUri); - builder.setPath(PATH_SEPARATOR + volumeName); - builder.setParameter(Header.OZONE_QUOTA_QUERY_TAG, quotaString); - HttpPut httpPut = new HttpPut(builder.build()); - addOzoneHeaders(httpPut); - EntityUtils.consume(executeHttpRequest(httpPut)); - } catch (URISyntaxException e) { - throw new IOException(e); - } - } - - @Override - public OzoneVolume getVolumeDetails(String volumeName) - throws IOException { - try { - HddsClientUtils.verifyResourceName(volumeName); - URIBuilder builder = new URIBuilder(ozoneRestUri); - builder.setPath(PATH_SEPARATOR + volumeName); - builder.setParameter(Header.OZONE_INFO_QUERY_TAG, - Header.OZONE_INFO_QUERY_VOLUME); - HttpGet httpGet = new HttpGet(builder.build()); - addOzoneHeaders(httpGet); - HttpEntity response = executeHttpRequest(httpGet); - VolumeInfo volInfo = - VolumeInfo.parse(EntityUtils.toString(response)); - //TODO: OzoneHandler in datanode has to be modified to send ACLs - OzoneVolume volume = new OzoneVolume(conf, - this, - volInfo.getVolumeName(), - volInfo.getCreatedBy(), - volInfo.getOwner().getName(), - volInfo.getQuota().sizeInBytes(), - HddsClientUtils.formatDateTime(volInfo.getCreatedOn()), - null); - EntityUtils.consume(response); - return volume; - } catch (URISyntaxException | ParseException e) { - throw new IOException(e); - } - } - - @Override - public boolean checkVolumeAccess(String volumeName, OzoneAcl acl) - throws IOException { - throw new UnsupportedOperationException("Not yet implemented."); - } - - @Override - public void deleteVolume(String volumeName) throws IOException { - try { - HddsClientUtils.verifyResourceName(volumeName); - URIBuilder builder = new URIBuilder(ozoneRestUri); - builder.setPath(PATH_SEPARATOR + volumeName); - HttpDelete httpDelete = new HttpDelete(builder.build()); - addOzoneHeaders(httpDelete); - EntityUtils.consume(executeHttpRequest(httpDelete)); - } catch (URISyntaxException e) { - throw new IOException(e); - } - } - - @Override - public List listVolumes(String volumePrefix, String prevKey, - int maxListResult) - throws IOException { - return listVolumes(null, volumePrefix, prevKey, maxListResult); - } - - @Override - public List listVolumes(String user, String volumePrefix, - String prevKey, int maxListResult) - throws IOException { - try { - URIBuilder builder = new URIBuilder(ozoneRestUri); - builder.setPath(PATH_SEPARATOR); - builder.addParameter(Header.OZONE_INFO_QUERY_TAG, - Header.OZONE_LIST_QUERY_SERVICE); - builder.addParameter(Header.OZONE_LIST_QUERY_MAXKEYS, - String.valueOf(maxListResult)); - addQueryParamter(Header.OZONE_LIST_QUERY_PREFIX, volumePrefix, builder); - addQueryParamter(Header.OZONE_LIST_QUERY_PREVKEY, prevKey, builder); - HttpGet httpGet = new HttpGet(builder.build()); - if (!Strings.isNullOrEmpty(user)) { - httpGet.addHeader(Header.OZONE_USER, user); - } - addOzoneHeaders(httpGet); - HttpEntity response = executeHttpRequest(httpGet); - ListVolumes volumeList = - ListVolumes.parse(EntityUtils.toString(response)); - EntityUtils.consume(response); - return volumeList.getVolumes().stream().map(volInfo -> { - long creationTime = 0; - try { - creationTime = HddsClientUtils.formatDateTime(volInfo.getCreatedOn()); - } catch (ParseException e) { - LOG.warn("Parse exception in getting creation time for volume", e); - } - return new OzoneVolume(conf, this, volInfo.getVolumeName(), - volInfo.getCreatedBy(), volInfo.getOwner().getName(), - volInfo.getQuota().sizeInBytes(), creationTime, null); - }).collect(Collectors.toList()); - } catch (URISyntaxException e) { - throw new IOException(e); - } - } - - @Override - public void createBucket(String volumeName, String bucketName) - throws IOException { - createBucket(volumeName, bucketName, BucketArgs.newBuilder().build()); - } - - @Override - public void createBucket( - String volumeName, String bucketName, BucketArgs bucketArgs) - throws IOException { - try { - HddsClientUtils.verifyResourceName(volumeName, bucketName); - Preconditions.checkNotNull(bucketArgs); - URIBuilder builder = new URIBuilder(ozoneRestUri); - OzoneConsts.Versioning versioning = OzoneConsts.Versioning.DISABLED; - if(bucketArgs.getVersioning() != null && - bucketArgs.getVersioning()) { - versioning = OzoneConsts.Versioning.ENABLED; - } - StorageType storageType = bucketArgs.getStorageType() == null ? - StorageType.DEFAULT : bucketArgs.getStorageType(); - - builder.setPath(PATH_SEPARATOR + volumeName + - PATH_SEPARATOR + bucketName); - HttpPost httpPost = new HttpPost(builder.build()); - addOzoneHeaders(httpPost); - - //ACLs from BucketArgs - if(bucketArgs.getAcls() != null) { - for (OzoneAcl acl : bucketArgs.getAcls()) { - httpPost.addHeader( - Header.OZONE_ACLS, Header.OZONE_ACL_ADD + " " + acl.toString()); - } - } - httpPost.addHeader(Header.OZONE_STORAGE_TYPE, storageType.toString()); - httpPost.addHeader(Header.OZONE_BUCKET_VERSIONING, - versioning.toString()); - LOG.info("Creating Bucket: {}/{}, with Versioning {} and Storage Type" + - " set to {}", volumeName, bucketName, versioning, - storageType); - - EntityUtils.consume(executeHttpRequest(httpPost)); - } catch (URISyntaxException e) { - throw new IOException(e); - } - } - - @Override - public void addBucketAcls( - String volumeName, String bucketName, List addAcls) - throws IOException { - try { - HddsClientUtils.verifyResourceName(volumeName, bucketName); - Preconditions.checkNotNull(addAcls); - URIBuilder builder = new URIBuilder(ozoneRestUri); - - builder.setPath(PATH_SEPARATOR + volumeName + - PATH_SEPARATOR + bucketName); - HttpPut httpPut = new HttpPut(builder.build()); - addOzoneHeaders(httpPut); - - for (OzoneAcl acl : addAcls) { - httpPut.addHeader( - Header.OZONE_ACLS, Header.OZONE_ACL_ADD + " " + acl.toString()); - } - EntityUtils.consume(executeHttpRequest(httpPut)); - } catch (URISyntaxException e) { - throw new IOException(e); - } - } - - @Override - public void removeBucketAcls( - String volumeName, String bucketName, List removeAcls) - throws IOException { - try { - HddsClientUtils.verifyResourceName(volumeName, bucketName); - Preconditions.checkNotNull(removeAcls); - URIBuilder builder = new URIBuilder(ozoneRestUri); - - builder.setPath(PATH_SEPARATOR + volumeName + - PATH_SEPARATOR + bucketName); - HttpPut httpPut = new HttpPut(builder.build()); - addOzoneHeaders(httpPut); - - for (OzoneAcl acl : removeAcls) { - httpPut.addHeader( - Header.OZONE_ACLS, Header.OZONE_ACL_REMOVE + " " + acl.toString()); - } - EntityUtils.consume(executeHttpRequest(httpPut)); - } catch (URISyntaxException e) { - throw new IOException(e); - } - } - - @Override - public void setBucketVersioning( - String volumeName, String bucketName, Boolean versioning) - throws IOException { - try { - HddsClientUtils.verifyResourceName(volumeName, bucketName); - Preconditions.checkNotNull(versioning); - URIBuilder builder = new URIBuilder(ozoneRestUri); - - builder.setPath(PATH_SEPARATOR + volumeName + - PATH_SEPARATOR + bucketName); - HttpPut httpPut = new HttpPut(builder.build()); - addOzoneHeaders(httpPut); - - httpPut.addHeader(Header.OZONE_BUCKET_VERSIONING, - getBucketVersioning(versioning).toString()); - EntityUtils.consume(executeHttpRequest(httpPut)); - } catch (URISyntaxException e) { - throw new IOException(e); - } - } - - @Override - public void setBucketStorageType( - String volumeName, String bucketName, StorageType storageType) - throws IOException { - try { - HddsClientUtils.verifyResourceName(volumeName, bucketName); - Preconditions.checkNotNull(storageType); - URIBuilder builder = new URIBuilder(ozoneRestUri); - - builder.setPath(PATH_SEPARATOR + volumeName + - PATH_SEPARATOR + bucketName); - HttpPut httpPut = new HttpPut(builder.build()); - addOzoneHeaders(httpPut); - - httpPut.addHeader(Header.OZONE_STORAGE_TYPE, storageType.toString()); - EntityUtils.consume(executeHttpRequest(httpPut)); - } catch (URISyntaxException e) { - throw new IOException(e); - } - } - - @Override - public void deleteBucket(String volumeName, String bucketName) - throws IOException { - try { - HddsClientUtils.verifyResourceName(volumeName, bucketName); - URIBuilder builder = new URIBuilder(ozoneRestUri); - builder.setPath(PATH_SEPARATOR + volumeName + - PATH_SEPARATOR + bucketName); - HttpDelete httpDelete = new HttpDelete(builder.build()); - addOzoneHeaders(httpDelete); - EntityUtils.consume(executeHttpRequest(httpDelete)); - } catch (URISyntaxException e) { - throw new IOException(e); - } - } - - @Override - public void checkBucketAccess(String volumeName, String bucketName) - throws IOException { - throw new UnsupportedOperationException("Not yet implemented."); - } - - @Override - public OzoneBucket getBucketDetails(String volumeName, String bucketName) - throws IOException { - try { - HddsClientUtils.verifyResourceName(volumeName, bucketName); - URIBuilder builder = new URIBuilder(ozoneRestUri); - builder.setPath(PATH_SEPARATOR + volumeName + - PATH_SEPARATOR + bucketName); - builder.setParameter(Header.OZONE_INFO_QUERY_TAG, - Header.OZONE_INFO_QUERY_BUCKET); - HttpGet httpGet = new HttpGet(builder.build()); - addOzoneHeaders(httpGet); - HttpEntity response = executeHttpRequest(httpGet); - BucketInfo bucketInfo = - BucketInfo.parse(EntityUtils.toString(response)); - OzoneBucket bucket = new OzoneBucket(conf, - this, - bucketInfo.getVolumeName(), - bucketInfo.getBucketName(), - bucketInfo.getAcls(), - bucketInfo.getStorageType(), - getBucketVersioningFlag(bucketInfo.getVersioning()), - HddsClientUtils.formatDateTime(bucketInfo.getCreatedOn())); - EntityUtils.consume(response); - return bucket; - } catch (URISyntaxException | ParseException e) { - throw new IOException(e); - } - } - - @Override - public List listBuckets(String volumeName, String bucketPrefix, - String prevBucket, int maxListResult) - throws IOException { - try { - HddsClientUtils.verifyResourceName(volumeName); - URIBuilder builder = new URIBuilder(ozoneRestUri); - builder.setPath(PATH_SEPARATOR + volumeName); - builder.addParameter(Header.OZONE_INFO_QUERY_TAG, - Header.OZONE_INFO_QUERY_BUCKET); - builder.addParameter(Header.OZONE_LIST_QUERY_MAXKEYS, - String.valueOf(maxListResult)); - addQueryParamter(Header.OZONE_LIST_QUERY_PREFIX, bucketPrefix, builder); - addQueryParamter(Header.OZONE_LIST_QUERY_PREVKEY, prevBucket, builder); - HttpGet httpGet = new HttpGet(builder.build()); - addOzoneHeaders(httpGet); - HttpEntity response = executeHttpRequest(httpGet); - ListBuckets bucketList = - ListBuckets.parse(EntityUtils.toString(response)); - EntityUtils.consume(response); - return bucketList.getBuckets().stream().map(bucketInfo -> { - long creationTime = 0; - try { - creationTime = - HddsClientUtils.formatDateTime(bucketInfo.getCreatedOn()); - } catch (ParseException e) { - LOG.warn("Parse exception in getting creation time for volume", e); - } - return new OzoneBucket(conf, this, volumeName, - bucketInfo.getBucketName(), bucketInfo.getAcls(), - bucketInfo.getStorageType(), - getBucketVersioningFlag(bucketInfo.getVersioning()), creationTime); - }).collect(Collectors.toList()); - } catch (URISyntaxException e) { - throw new IOException(e); - } - } - - /** - * Writes a key in an existing bucket. - * - * @param volumeName Name of the Volume - * @param bucketName Name of the Bucket - * @param keyName Name of the Key - * @param size Size of the data - * @param type - * @param factor @return {@link OzoneOutputStream} - */ - @Override - public OzoneOutputStream createKey( - String volumeName, String bucketName, String keyName, long size, - ReplicationType type, ReplicationFactor factor) - throws IOException { - // TODO: Once ReplicationType and ReplicationFactor are supported in - // OzoneHandler (in Datanode), set them in header. - try { - HddsClientUtils.verifyResourceName(volumeName, bucketName); - HddsClientUtils.checkNotNull(keyName, type, factor); - URIBuilder builder = new URIBuilder(ozoneRestUri); - builder.setPath(PATH_SEPARATOR + volumeName + - PATH_SEPARATOR + bucketName + - PATH_SEPARATOR + keyName); - HttpPut putRequest = new HttpPut(builder.build()); - addOzoneHeaders(putRequest); - PipedInputStream in = new PipedInputStream(); - OutputStream out = new PipedOutputStream(in); - putRequest.setEntity(new InputStreamEntity(in, size)); - FutureTask futureTask = - new FutureTask<>(() -> executeHttpRequest(putRequest)); - new Thread(futureTask).start(); - OzoneOutputStream outputStream = new OzoneOutputStream( - new OutputStream() { - @Override - public void write(int b) throws IOException { - out.write(b); - } - - @Override - public void close() throws IOException { - try { - out.close(); - EntityUtils.consume(futureTask.get()); - } catch (ExecutionException | InterruptedException e) { - throw new IOException(e); - } - } - }); - - return outputStream; - } catch (URISyntaxException e) { - throw new IOException(e); - } - } - - @Override - public OzoneInputStream getKey( - String volumeName, String bucketName, String keyName) - throws IOException { - try { - HddsClientUtils.verifyResourceName(volumeName, bucketName); - Preconditions.checkNotNull(keyName); - URIBuilder builder = new URIBuilder(ozoneRestUri); - builder.setPath(PATH_SEPARATOR + volumeName + - PATH_SEPARATOR + bucketName + - PATH_SEPARATOR + keyName); - HttpGet getRequest = new HttpGet(builder.build()); - addOzoneHeaders(getRequest); - HttpEntity entity = executeHttpRequest(getRequest); - PipedInputStream in = new PipedInputStream(); - OutputStream out = new PipedOutputStream(in); - FutureTask futureTask = - new FutureTask<>(() -> { - entity.writeTo(out); - out.close(); - return null; - }); - new Thread(futureTask).start(); - OzoneInputStream inputStream = new OzoneInputStream( - new InputStream() { - - @Override - public int read() throws IOException { - return in.read(); - } - - @Override - public void close() throws IOException { - in.close(); - EntityUtils.consume(entity); - } - }); - - return inputStream; - } catch (URISyntaxException e) { - throw new IOException(e); - } - } - - @Override - public void deleteKey(String volumeName, String bucketName, String keyName) - throws IOException { - try { - HddsClientUtils.verifyResourceName(volumeName, bucketName); - Preconditions.checkNotNull(keyName); - URIBuilder builder = new URIBuilder(ozoneRestUri); - builder.setPath(PATH_SEPARATOR + volumeName + - PATH_SEPARATOR + bucketName + PATH_SEPARATOR + keyName); - HttpDelete httpDelete = new HttpDelete(builder.build()); - addOzoneHeaders(httpDelete); - EntityUtils.consume(executeHttpRequest(httpDelete)); - } catch (URISyntaxException e) { - throw new IOException(e); - } - } - - @Override - public void renameKey(String volumeName, String bucketName, - String fromKeyName, String toKeyName) throws IOException { - try { - HddsClientUtils.verifyResourceName(volumeName, bucketName); - HddsClientUtils.checkNotNull(fromKeyName, toKeyName); - URIBuilder builder = new URIBuilder(ozoneRestUri); - builder.setPath(PATH_SEPARATOR + volumeName + PATH_SEPARATOR + bucketName - + PATH_SEPARATOR + fromKeyName); - builder.addParameter(Header.OZONE_RENAME_TO_KEY_PARAM_NAME, toKeyName); - HttpPost httpPost = new HttpPost(builder.build()); - addOzoneHeaders(httpPost); - EntityUtils.consume(executeHttpRequest(httpPost)); - } catch (URISyntaxException e) { - throw new IOException(e); - } - } - - @Override - public List listKeys(String volumeName, String bucketName, - String keyPrefix, String prevKey, - int maxListResult) - throws IOException { - try { - HddsClientUtils.verifyResourceName(volumeName); - URIBuilder builder = new URIBuilder(ozoneRestUri); - builder - .setPath(PATH_SEPARATOR + volumeName + PATH_SEPARATOR + bucketName); - builder.addParameter(Header.OZONE_INFO_QUERY_TAG, - Header.OZONE_INFO_QUERY_KEY); - builder.addParameter(Header.OZONE_LIST_QUERY_MAXKEYS, - String.valueOf(maxListResult)); - addQueryParamter(Header.OZONE_LIST_QUERY_PREFIX, keyPrefix, builder); - addQueryParamter(Header.OZONE_LIST_QUERY_PREVKEY, prevKey, builder); - HttpGet httpGet = new HttpGet(builder.build()); - addOzoneHeaders(httpGet); - HttpEntity response = executeHttpRequest(httpGet); - ListKeys keyList = ListKeys.parse(EntityUtils.toString(response)); - EntityUtils.consume(response); - return keyList.getKeyList().stream().map(keyInfo -> { - long creationTime = 0, modificationTime = 0; - try { - creationTime = HddsClientUtils.formatDateTime(keyInfo.getCreatedOn()); - modificationTime = - HddsClientUtils.formatDateTime(keyInfo.getModifiedOn()); - } catch (ParseException e) { - LOG.warn("Parse exception in getting creation time for volume", e); - } - return new OzoneKey(volumeName, bucketName, keyInfo.getKeyName(), - keyInfo.getSize(), creationTime, modificationTime); - }).collect(Collectors.toList()); - } catch (URISyntaxException e) { - throw new IOException(e); - } - } - - @Override - public OzoneKeyDetails getKeyDetails( - String volumeName, String bucketName, String keyName) - throws IOException { - try { - HddsClientUtils.verifyResourceName(volumeName, bucketName); - Preconditions.checkNotNull(keyName); - URIBuilder builder = new URIBuilder(ozoneRestUri); - builder.setPath(PATH_SEPARATOR + volumeName + - PATH_SEPARATOR + bucketName + PATH_SEPARATOR + keyName); - builder.setParameter(Header.OZONE_INFO_QUERY_TAG, - Header.OZONE_INFO_QUERY_KEY_DETAIL); - HttpGet httpGet = new HttpGet(builder.build()); - addOzoneHeaders(httpGet); - HttpEntity response = executeHttpRequest(httpGet); - KeyInfoDetails keyInfo = - KeyInfoDetails.parse(EntityUtils.toString(response)); - - List ozoneKeyLocations = new ArrayList<>(); - keyInfo.getKeyLocations().forEach((a) -> ozoneKeyLocations.add( - new OzoneKeyLocation(a.getContainerID(), a.getLocalID(), - a.getLength(), a.getOffset()))); - OzoneKeyDetails key = new OzoneKeyDetails(volumeName, - bucketName, - keyInfo.getKeyName(), - keyInfo.getSize(), - HddsClientUtils.formatDateTime(keyInfo.getCreatedOn()), - HddsClientUtils.formatDateTime(keyInfo.getModifiedOn()), - ozoneKeyLocations); - EntityUtils.consume(response); - return key; - } catch (URISyntaxException | ParseException e) { - throw new IOException(e); - } - } - - /** - * Adds Ozone headers to http request. - * - * @param httpRequest Http Request - */ - private void addOzoneHeaders(HttpUriRequest httpRequest) { - httpRequest.addHeader(HttpHeaders.AUTHORIZATION, - Header.OZONE_SIMPLE_AUTHENTICATION_SCHEME + " " + - ugi.getUserName()); - httpRequest.addHeader(HttpHeaders.DATE, - HddsClientUtils.formatDateTime(Time.monotonicNow())); - httpRequest.addHeader(Header.OZONE_VERSION_HEADER, - Header.OZONE_V1_VERSION_HEADER); - } - - /** - * Sends the http request to server and returns the response HttpEntity. - * It's responsibility of the caller to consume and close response HttpEntity - * by calling {@code EntityUtils.consume} - * - * @param httpUriRequest http request - * @throws IOException - */ - private HttpEntity executeHttpRequest(HttpUriRequest httpUriRequest) - throws IOException { - HttpResponse response = httpClient.execute(httpUriRequest); - int errorCode = response.getStatusLine().getStatusCode(); - HttpEntity entity = response.getEntity(); - if ((errorCode == HTTP_OK) || (errorCode == HTTP_CREATED)) { - return entity; - } - if (entity != null) { - throw new IOException( - OzoneException.parse(EntityUtils.toString(entity))); - } else { - throw new IOException("Unexpected null in http payload," + - " while processing request"); - } - } - - /** - * Converts OzoneConts.Versioning to boolean. - * - * @param version - * @return corresponding boolean value - */ - private Boolean getBucketVersioningFlag( - OzoneConsts.Versioning version) { - if(version != null) { - switch(version) { - case ENABLED: - return true; - case NOT_DEFINED: - case DISABLED: - default: - return false; - } - } - return false; - } - - /** - * Converts Bucket versioning flag into OzoneConts.Versioning. - * - * @param flag versioning flag - * @return corresponding OzoneConts.Versionin - */ - private OzoneConsts.Versioning getBucketVersioning(Boolean flag) { - if(flag != null) { - if(flag) { - return OzoneConsts.Versioning.ENABLED; - } else { - return OzoneConsts.Versioning.DISABLED; - } - } - return OzoneConsts.Versioning.NOT_DEFINED; - } - - @Override - public void close() throws IOException { - httpClient.close(); - } - - private void addQueryParamter(String param, String value, - URIBuilder builder) { - if (!Strings.isNullOrEmpty(value)) { - builder.addParameter(param, value); - } - } -} diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/RestServerSelector.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/RestServerSelector.java deleted file mode 100644 index fbd6eb8ea9a..00000000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/RestServerSelector.java +++ /dev/null @@ -1,40 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client.rest; - -import org.apache.hadoop.ozone.om.helpers.ServiceInfo; - -import java.util.List; - -/** - * The implementor of this interface should select the REST server which will - * be used by the client to connect to Ozone Cluster, given list of - * REST Servers/DataNodes (DataNodes are the ones which hosts REST Service). - */ -public interface RestServerSelector { - - /** - * Returns the REST Service which will be used by the client for connection. - * - * @param restServices list of available REST servers - * @return ServiceInfo - */ - ServiceInfo getRestServer(List restServices); - -} diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/exceptions/package-info.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/exceptions/package-info.java deleted file mode 100644 index 233e7882e2d..00000000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/exceptions/package-info.java +++ /dev/null @@ -1,22 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.client.rest.exceptions; - -/** - * This package contains ozone rest client libraries. - */ diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/headers/package-info.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/headers/package-info.java deleted file mode 100644 index 340709f492d..00000000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/headers/package-info.java +++ /dev/null @@ -1,22 +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 - * - * 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. - */ - -@InterfaceAudience.Private -package org.apache.hadoop.ozone.client.rest.headers; - -import org.apache.hadoop.classification.InterfaceAudience; diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/package-info.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/package-info.java deleted file mode 100644 index ebcc104811f..00000000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/package-info.java +++ /dev/null @@ -1,23 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client.rest; - -/** - * This package contains Ozone rest client library classes. - */ diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java deleted file mode 100644 index 330eba878bf..00000000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java +++ /dev/null @@ -1,576 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client.rpc; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.fs.StorageType; -import org.apache.hadoop.hdds.scm.client.HddsClientUtils; -import org.apache.hadoop.io.IOUtils; -import org.apache.hadoop.io.retry.RetryPolicy; -import org.apache.hadoop.ipc.Client; -import org.apache.hadoop.ipc.ProtobufRpcEngine; -import org.apache.hadoop.ipc.RPC; -import org.apache.hadoop.ozone.OmUtils; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.client.*; -import org.apache.hadoop.hdds.client.OzoneQuota; -import org.apache.hadoop.hdds.client.ReplicationFactor; -import org.apache.hadoop.hdds.client.ReplicationType; -import org.apache.hadoop.ozone.client.VolumeArgs; -import org.apache.hadoop.ozone.client.OzoneClientUtils; -import org.apache.hadoop.ozone.client.io.ChunkGroupInputStream; -import org.apache.hadoop.ozone.client.io.ChunkGroupOutputStream; -import org.apache.hadoop.ozone.client.io.LengthInputStream; -import org.apache.hadoop.ozone.client.io.OzoneInputStream; -import org.apache.hadoop.ozone.client.io.OzoneOutputStream; -import org.apache.hadoop.ozone.client.protocol.ClientProtocol; -import org.apache.hadoop.ozone.om.helpers.OmBucketArgs; -import org.apache.hadoop.ozone.om.helpers.OmBucketInfo; -import org.apache.hadoop.ozone.om.helpers.OmKeyArgs; -import org.apache.hadoop.ozone.om.helpers.OmKeyInfo; -import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs; -import org.apache.hadoop.ozone.om.helpers.OpenKeySession; -import org.apache.hadoop.ozone.om.helpers.ServiceInfo; -import org.apache.hadoop.ozone.om.protocolPB.OzoneManagerProtocolClientSideTranslatorPB; -import org.apache.hadoop.ozone.om.protocolPB.OzoneManagerProtocolPB; -import org.apache.hadoop.net.NetUtils; -import org.apache.hadoop.ozone.OzoneAcl; -import org.apache.hadoop.ozone.om.OMConfigKeys; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.ServicePort; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.ozone.protocolPB.OMPBHelper; -import org.apache.hadoop.hdds.scm.ScmConfigKeys; -import org.apache.hadoop.hdds.scm.XceiverClientManager; -import org.apache.hadoop.hdds.scm.protocolPB - .StorageContainerLocationProtocolClientSideTranslatorPB; -import org.apache.hadoop.hdds.scm.protocolPB - .StorageContainerLocationProtocolPB; -import org.apache.hadoop.security.UserGroupInformation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.util.*; -import java.util.stream.Collectors; - -/** - * Ozone RPC Client Implementation, it connects to OM, SCM and DataNode - * to execute client calls. This uses RPC protocol for communication - * with the servers. - */ -public class RpcClient implements ClientProtocol { - - private static final Logger LOG = - LoggerFactory.getLogger(RpcClient.class); - - private final OzoneConfiguration conf; - private final StorageContainerLocationProtocolClientSideTranslatorPB - storageContainerLocationClient; - private final OzoneManagerProtocolClientSideTranslatorPB - ozoneManagerClient; - private final XceiverClientManager xceiverClientManager; - private final int chunkSize; - private final UserGroupInformation ugi; - private final OzoneAcl.OzoneACLRights userRights; - private final OzoneAcl.OzoneACLRights groupRights; - private final RetryPolicy retryPolicy; - - /** - * Creates RpcClient instance with the given configuration. - * @param conf - * @throws IOException - */ - public RpcClient(Configuration conf) throws IOException { - Preconditions.checkNotNull(conf); - this.conf = new OzoneConfiguration(conf); - this.ugi = UserGroupInformation.getCurrentUser(); - this.userRights = conf.getEnum(OMConfigKeys.OZONE_OM_USER_RIGHTS, - OMConfigKeys.OZONE_OM_USER_RIGHTS_DEFAULT); - this.groupRights = conf.getEnum(OMConfigKeys.OZONE_OM_GROUP_RIGHTS, - OMConfigKeys.OZONE_OM_GROUP_RIGHTS_DEFAULT); - long omVersion = - RPC.getProtocolVersion(OzoneManagerProtocolPB.class); - InetSocketAddress omAddress = OmUtils - .getOmAddressForClients(conf); - RPC.setProtocolEngine(conf, OzoneManagerProtocolPB.class, - ProtobufRpcEngine.class); - this.ozoneManagerClient = - new OzoneManagerProtocolClientSideTranslatorPB( - RPC.getProxy(OzoneManagerProtocolPB.class, omVersion, - omAddress, UserGroupInformation.getCurrentUser(), conf, - NetUtils.getDefaultSocketFactory(conf), - Client.getRpcTimeout(conf))); - - long scmVersion = - RPC.getProtocolVersion(StorageContainerLocationProtocolPB.class); - InetSocketAddress scmAddress = getScmAddressForClient(); - RPC.setProtocolEngine(conf, StorageContainerLocationProtocolPB.class, - ProtobufRpcEngine.class); - this.storageContainerLocationClient = - new StorageContainerLocationProtocolClientSideTranslatorPB( - RPC.getProxy(StorageContainerLocationProtocolPB.class, scmVersion, - scmAddress, UserGroupInformation.getCurrentUser(), conf, - NetUtils.getDefaultSocketFactory(conf), - Client.getRpcTimeout(conf))); - - this.xceiverClientManager = new XceiverClientManager(conf); - retryPolicy = OzoneClientUtils.createRetryPolicy(conf); - - int configuredChunkSize = conf.getInt( - ScmConfigKeys.OZONE_SCM_CHUNK_SIZE_KEY, - ScmConfigKeys.OZONE_SCM_CHUNK_SIZE_DEFAULT); - if(configuredChunkSize > ScmConfigKeys.OZONE_SCM_CHUNK_MAX_SIZE) { - LOG.warn("The chunk size ({}) is not allowed to be more than" - + " the maximum size ({})," - + " resetting to the maximum size.", - configuredChunkSize, ScmConfigKeys.OZONE_SCM_CHUNK_MAX_SIZE); - chunkSize = ScmConfigKeys.OZONE_SCM_CHUNK_MAX_SIZE; - } else { - chunkSize = configuredChunkSize; - } - } - - private InetSocketAddress getScmAddressForClient() throws IOException { - List services = ozoneManagerClient.getServiceList(); - ServiceInfo scmInfo = services.stream().filter( - a -> a.getNodeType().equals(HddsProtos.NodeType.SCM)) - .collect(Collectors.toList()).get(0); - return NetUtils.createSocketAddr(scmInfo.getHostname()+ ":" + - scmInfo.getPort(ServicePort.Type.RPC)); - } - - @Override - public void createVolume(String volumeName) throws IOException { - createVolume(volumeName, VolumeArgs.newBuilder().build()); - } - - @Override - public void createVolume(String volumeName, VolumeArgs volArgs) - throws IOException { - HddsClientUtils.verifyResourceName(volumeName); - Preconditions.checkNotNull(volArgs); - - String admin = volArgs.getAdmin() == null ? - ugi.getUserName() : volArgs.getAdmin(); - String owner = volArgs.getOwner() == null ? - ugi.getUserName() : volArgs.getOwner(); - long quota = volArgs.getQuota() == null ? - OzoneConsts.MAX_QUOTA_IN_BYTES : - OzoneQuota.parseQuota(volArgs.getQuota()).sizeInBytes(); - List listOfAcls = new ArrayList<>(); - //User ACL - listOfAcls.add(new OzoneAcl(OzoneAcl.OzoneACLType.USER, - owner, userRights)); - //Group ACLs of the User - List userGroups = Arrays.asList(UserGroupInformation - .createRemoteUser(owner).getGroupNames()); - userGroups.stream().forEach((group) -> listOfAcls.add( - new OzoneAcl(OzoneAcl.OzoneACLType.GROUP, group, groupRights))); - //ACLs from VolumeArgs - if(volArgs.getAcls() != null) { - listOfAcls.addAll(volArgs.getAcls()); - } - - OmVolumeArgs.Builder builder = OmVolumeArgs.newBuilder(); - builder.setVolume(volumeName); - builder.setAdminName(admin); - builder.setOwnerName(owner); - builder.setQuotaInBytes(quota); - - //Remove duplicates and add ACLs - for (OzoneAcl ozoneAcl : - listOfAcls.stream().distinct().collect(Collectors.toList())) { - builder.addOzoneAcls(OMPBHelper.convertOzoneAcl(ozoneAcl)); - } - - LOG.info("Creating Volume: {}, with {} as owner and quota set to {} bytes.", - volumeName, owner, quota); - ozoneManagerClient.createVolume(builder.build()); - } - - @Override - public void setVolumeOwner(String volumeName, String owner) - throws IOException { - HddsClientUtils.verifyResourceName(volumeName); - Preconditions.checkNotNull(owner); - ozoneManagerClient.setOwner(volumeName, owner); - } - - @Override - public void setVolumeQuota(String volumeName, OzoneQuota quota) - throws IOException { - HddsClientUtils.verifyResourceName(volumeName); - Preconditions.checkNotNull(quota); - long quotaInBytes = quota.sizeInBytes(); - ozoneManagerClient.setQuota(volumeName, quotaInBytes); - } - - @Override - public OzoneVolume getVolumeDetails(String volumeName) - throws IOException { - HddsClientUtils.verifyResourceName(volumeName); - OmVolumeArgs volume = ozoneManagerClient.getVolumeInfo(volumeName); - return new OzoneVolume( - conf, - this, - volume.getVolume(), - volume.getAdminName(), - volume.getOwnerName(), - volume.getQuotaInBytes(), - volume.getCreationTime(), - volume.getAclMap().ozoneAclGetProtobuf().stream(). - map(OMPBHelper::convertOzoneAcl).collect(Collectors.toList())); - } - - @Override - public boolean checkVolumeAccess(String volumeName, OzoneAcl acl) - throws IOException { - throw new UnsupportedOperationException("Not yet implemented."); - } - - @Override - public void deleteVolume(String volumeName) throws IOException { - HddsClientUtils.verifyResourceName(volumeName); - ozoneManagerClient.deleteVolume(volumeName); - } - - @Override - public List listVolumes(String volumePrefix, String prevVolume, - int maxListResult) - throws IOException { - List volumes = ozoneManagerClient.listAllVolumes( - volumePrefix, prevVolume, maxListResult); - - return volumes.stream().map(volume -> new OzoneVolume( - conf, - this, - volume.getVolume(), - volume.getAdminName(), - volume.getOwnerName(), - volume.getQuotaInBytes(), - volume.getCreationTime(), - volume.getAclMap().ozoneAclGetProtobuf().stream(). - map(OMPBHelper::convertOzoneAcl).collect(Collectors.toList()))) - .collect(Collectors.toList()); - } - - @Override - public List listVolumes(String user, String volumePrefix, - String prevVolume, int maxListResult) - throws IOException { - List volumes = ozoneManagerClient.listVolumeByUser( - user, volumePrefix, prevVolume, maxListResult); - - return volumes.stream().map(volume -> new OzoneVolume( - conf, - this, - volume.getVolume(), - volume.getAdminName(), - volume.getOwnerName(), - volume.getQuotaInBytes(), - volume.getCreationTime(), - volume.getAclMap().ozoneAclGetProtobuf().stream(). - map(OMPBHelper::convertOzoneAcl).collect(Collectors.toList()))) - .collect(Collectors.toList()); - } - - @Override - public void createBucket(String volumeName, String bucketName) - throws IOException { - createBucket(volumeName, bucketName, BucketArgs.newBuilder().build()); - } - - @Override - public void createBucket( - String volumeName, String bucketName, BucketArgs bucketArgs) - throws IOException { - HddsClientUtils.verifyResourceName(volumeName, bucketName); - Preconditions.checkNotNull(bucketArgs); - - Boolean isVersionEnabled = bucketArgs.getVersioning() == null ? - Boolean.FALSE : bucketArgs.getVersioning(); - StorageType storageType = bucketArgs.getStorageType() == null ? - StorageType.DEFAULT : bucketArgs.getStorageType(); - List listOfAcls = new ArrayList<>(); - //User ACL - listOfAcls.add(new OzoneAcl(OzoneAcl.OzoneACLType.USER, - ugi.getUserName(), userRights)); - //Group ACLs of the User - List userGroups = Arrays.asList(UserGroupInformation - .createRemoteUser(ugi.getUserName()).getGroupNames()); - userGroups.stream().forEach((group) -> listOfAcls.add( - new OzoneAcl(OzoneAcl.OzoneACLType.GROUP, group, groupRights))); - //ACLs from BucketArgs - if(bucketArgs.getAcls() != null) { - listOfAcls.addAll(bucketArgs.getAcls()); - } - - OmBucketInfo.Builder builder = OmBucketInfo.newBuilder(); - builder.setVolumeName(volumeName) - .setBucketName(bucketName) - .setIsVersionEnabled(isVersionEnabled) - .setStorageType(storageType) - .setAcls(listOfAcls.stream().distinct().collect(Collectors.toList())); - - LOG.info("Creating Bucket: {}/{}, with Versioning {} and " + - "Storage Type set to {}", volumeName, bucketName, isVersionEnabled, - storageType); - ozoneManagerClient.createBucket(builder.build()); - } - - @Override - public void addBucketAcls( - String volumeName, String bucketName, List addAcls) - throws IOException { - HddsClientUtils.verifyResourceName(volumeName, bucketName); - Preconditions.checkNotNull(addAcls); - OmBucketArgs.Builder builder = OmBucketArgs.newBuilder(); - builder.setVolumeName(volumeName) - .setBucketName(bucketName) - .setAddAcls(addAcls); - ozoneManagerClient.setBucketProperty(builder.build()); - } - - @Override - public void removeBucketAcls( - String volumeName, String bucketName, List removeAcls) - throws IOException { - HddsClientUtils.verifyResourceName(volumeName, bucketName); - Preconditions.checkNotNull(removeAcls); - OmBucketArgs.Builder builder = OmBucketArgs.newBuilder(); - builder.setVolumeName(volumeName) - .setBucketName(bucketName) - .setRemoveAcls(removeAcls); - ozoneManagerClient.setBucketProperty(builder.build()); - } - - @Override - public void setBucketVersioning( - String volumeName, String bucketName, Boolean versioning) - throws IOException { - HddsClientUtils.verifyResourceName(volumeName, bucketName); - Preconditions.checkNotNull(versioning); - OmBucketArgs.Builder builder = OmBucketArgs.newBuilder(); - builder.setVolumeName(volumeName) - .setBucketName(bucketName) - .setIsVersionEnabled(versioning); - ozoneManagerClient.setBucketProperty(builder.build()); - } - - @Override - public void setBucketStorageType( - String volumeName, String bucketName, StorageType storageType) - throws IOException { - HddsClientUtils.verifyResourceName(volumeName, bucketName); - Preconditions.checkNotNull(storageType); - OmBucketArgs.Builder builder = OmBucketArgs.newBuilder(); - builder.setVolumeName(volumeName) - .setBucketName(bucketName) - .setStorageType(storageType); - ozoneManagerClient.setBucketProperty(builder.build()); - } - - @Override - public void deleteBucket( - String volumeName, String bucketName) throws IOException { - HddsClientUtils.verifyResourceName(volumeName, bucketName); - ozoneManagerClient.deleteBucket(volumeName, bucketName); - } - - @Override - public void checkBucketAccess( - String volumeName, String bucketName) throws IOException { - - } - - @Override - public OzoneBucket getBucketDetails( - String volumeName, String bucketName) throws IOException { - HddsClientUtils.verifyResourceName(volumeName, bucketName); - OmBucketInfo bucketArgs = - ozoneManagerClient.getBucketInfo(volumeName, bucketName); - return new OzoneBucket( - conf, - this, - bucketArgs.getVolumeName(), - bucketArgs.getBucketName(), - bucketArgs.getAcls(), - bucketArgs.getStorageType(), - bucketArgs.getIsVersionEnabled(), - bucketArgs.getCreationTime()); - } - - @Override - public List listBuckets(String volumeName, String bucketPrefix, - String prevBucket, int maxListResult) - throws IOException { - List buckets = ozoneManagerClient.listBuckets( - volumeName, prevBucket, bucketPrefix, maxListResult); - - return buckets.stream().map(bucket -> new OzoneBucket( - conf, - this, - bucket.getVolumeName(), - bucket.getBucketName(), - bucket.getAcls(), - bucket.getStorageType(), - bucket.getIsVersionEnabled(), - bucket.getCreationTime())) - .collect(Collectors.toList()); - } - - @Override - public OzoneOutputStream createKey( - String volumeName, String bucketName, String keyName, long size, - ReplicationType type, ReplicationFactor factor) - throws IOException { - HddsClientUtils.verifyResourceName(volumeName, bucketName); - HddsClientUtils.checkNotNull(keyName, type, factor); - String requestId = UUID.randomUUID().toString(); - OmKeyArgs keyArgs = new OmKeyArgs.Builder() - .setVolumeName(volumeName) - .setBucketName(bucketName) - .setKeyName(keyName) - .setDataSize(size) - .setType(HddsProtos.ReplicationType.valueOf(type.toString())) - .setFactor(HddsProtos.ReplicationFactor.valueOf(factor.getValue())) - .build(); - - OpenKeySession openKey = ozoneManagerClient.openKey(keyArgs); - ChunkGroupOutputStream groupOutputStream = - new ChunkGroupOutputStream.Builder() - .setHandler(openKey) - .setXceiverClientManager(xceiverClientManager) - .setScmClient(storageContainerLocationClient) - .setOmClient(ozoneManagerClient) - .setChunkSize(chunkSize) - .setRequestID(requestId) - .setType(HddsProtos.ReplicationType.valueOf(type.toString())) - .setFactor(HddsProtos.ReplicationFactor.valueOf(factor.getValue())) - .setRetryPolicy(retryPolicy) - .build(); - groupOutputStream.addPreallocateBlocks( - openKey.getKeyInfo().getLatestVersionLocations(), - openKey.getOpenVersion()); - return new OzoneOutputStream(groupOutputStream); - } - - @Override - public OzoneInputStream getKey( - String volumeName, String bucketName, String keyName) - throws IOException { - HddsClientUtils.verifyResourceName(volumeName, bucketName); - Preconditions.checkNotNull(keyName); - String requestId = UUID.randomUUID().toString(); - OmKeyArgs keyArgs = new OmKeyArgs.Builder() - .setVolumeName(volumeName) - .setBucketName(bucketName) - .setKeyName(keyName) - .build(); - OmKeyInfo keyInfo = ozoneManagerClient.lookupKey(keyArgs); - LengthInputStream lengthInputStream = - ChunkGroupInputStream.getFromOmKeyInfo( - keyInfo, xceiverClientManager, storageContainerLocationClient, - requestId); - return new OzoneInputStream(lengthInputStream.getWrappedStream()); - } - - @Override - public void deleteKey( - String volumeName, String bucketName, String keyName) - throws IOException { - HddsClientUtils.verifyResourceName(volumeName, bucketName); - Preconditions.checkNotNull(keyName); - OmKeyArgs keyArgs = new OmKeyArgs.Builder() - .setVolumeName(volumeName) - .setBucketName(bucketName) - .setKeyName(keyName) - .build(); - ozoneManagerClient.deleteKey(keyArgs); - } - - @Override - public void renameKey(String volumeName, String bucketName, - String fromKeyName, String toKeyName) throws IOException { - HddsClientUtils.verifyResourceName(volumeName, bucketName); - HddsClientUtils.checkNotNull(fromKeyName, toKeyName); - OmKeyArgs keyArgs = new OmKeyArgs.Builder() - .setVolumeName(volumeName) - .setBucketName(bucketName) - .setKeyName(fromKeyName) - .build(); - ozoneManagerClient.renameKey(keyArgs, toKeyName); - } - - @Override - public List listKeys(String volumeName, String bucketName, - String keyPrefix, String prevKey, - int maxListResult) - throws IOException { - List keys = ozoneManagerClient.listKeys( - volumeName, bucketName, prevKey, keyPrefix, maxListResult); - - return keys.stream().map(key -> new OzoneKey( - key.getVolumeName(), - key.getBucketName(), - key.getKeyName(), - key.getDataSize(), - key.getCreationTime(), - key.getModificationTime())) - .collect(Collectors.toList()); - } - - @Override - public OzoneKeyDetails getKeyDetails( - String volumeName, String bucketName, String keyName) - throws IOException { - Preconditions.checkNotNull(volumeName); - Preconditions.checkNotNull(bucketName); - Preconditions.checkNotNull(keyName); - OmKeyArgs keyArgs = new OmKeyArgs.Builder() - .setVolumeName(volumeName) - .setBucketName(bucketName) - .setKeyName(keyName) - .build(); - OmKeyInfo keyInfo = ozoneManagerClient.lookupKey(keyArgs); - - List ozoneKeyLocations = new ArrayList<>(); - keyInfo.getLatestVersionLocations().getBlocksLatestVersionOnly().forEach( - (a) -> ozoneKeyLocations.add(new OzoneKeyLocation(a.getContainerID(), - a.getLocalID(), a.getLength(), a.getOffset()))); - return new OzoneKeyDetails(keyInfo.getVolumeName(), - keyInfo.getBucketName(), - keyInfo.getKeyName(), - keyInfo.getDataSize(), - keyInfo.getCreationTime(), - keyInfo.getModificationTime(), - ozoneKeyLocations); - } - - @Override - public void close() throws IOException { - IOUtils.cleanupWithLogger(LOG, storageContainerLocationClient); - IOUtils.cleanupWithLogger(LOG, ozoneManagerClient); - IOUtils.cleanupWithLogger(LOG, xceiverClientManager); - } -} diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/package-info.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/package-info.java deleted file mode 100644 index 0fcc3fc3583..00000000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/package-info.java +++ /dev/null @@ -1,23 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client.rpc; - -/** - * This package contains Ozone rpc client library classes. - */ diff --git a/hadoop-ozone/client/src/test/java/org/apache/hadoop/ozone/client/TestHddsClientUtils.java b/hadoop-ozone/client/src/test/java/org/apache/hadoop/ozone/client/TestHddsClientUtils.java deleted file mode 100644 index 3aefe8ac238..00000000000 --- a/hadoop-ozone/client/src/test/java/org/apache/hadoop/ozone/client/TestHddsClientUtils.java +++ /dev/null @@ -1,105 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.ozone.om.OMConfigKeys; -import org.apache.hadoop.hdds.scm.ScmConfigKeys; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.rules.Timeout; - -import java.net.InetSocketAddress; - -import static org.apache.hadoop.hdds.HddsUtils.getScmAddressForClients; -import static org.apache.hadoop.ozone.OmUtils.getOmAddress; -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; - -/** - * This test class verifies the parsing of SCM endpoint config settings. The - * parsing logic is in {@link org.apache.hadoop.hdds.scm.client.HddsClientUtils}. - */ -public class TestHddsClientUtils { - @Rule - public Timeout timeout = new Timeout(300000); - - @Rule - public ExpectedException thrown= ExpectedException.none(); - - /** - * Verify client endpoint lookup failure if it is not configured. - */ - @Test - public void testMissingScmClientAddress() { - final Configuration conf = new OzoneConfiguration(); - thrown.expect(IllegalArgumentException.class); - getScmAddressForClients(conf); - } - - /** - * Verify that the client endpoint can be correctly parsed from - * configuration. - */ - @Test - public void testGetScmClientAddress() { - final Configuration conf = new OzoneConfiguration(); - - // First try a client address with just a host name. Verify it falls - // back to the default port. - conf.set(ScmConfigKeys.OZONE_SCM_CLIENT_ADDRESS_KEY, "1.2.3.4"); - InetSocketAddress addr = getScmAddressForClients(conf); - assertThat(addr.getHostString(), is("1.2.3.4")); - assertThat(addr.getPort(), is(ScmConfigKeys.OZONE_SCM_CLIENT_PORT_DEFAULT)); - - // Next try a client address with a host name and port. Verify both - // are used correctly. - conf.set(ScmConfigKeys.OZONE_SCM_CLIENT_ADDRESS_KEY, "1.2.3.4:100"); - addr = getScmAddressForClients(conf); - assertThat(addr.getHostString(), is("1.2.3.4")); - assertThat(addr.getPort(), is(100)); - } - - @Test - public void testGetOmAddress() { - final Configuration conf = new OzoneConfiguration(); - - // First try a client address with just a host name. Verify it falls - // back to the default port. - conf.set(OMConfigKeys.OZONE_OM_ADDRESS_KEY, "1.2.3.4"); - InetSocketAddress addr = getOmAddress(conf); - assertThat(addr.getHostString(), is("1.2.3.4")); - assertThat(addr.getPort(), is(OMConfigKeys.OZONE_OM_PORT_DEFAULT)); - - // Next try a client address with just a host name and port. Verify the port - // is ignored and the default OM port is used. - conf.set(OMConfigKeys.OZONE_OM_ADDRESS_KEY, "1.2.3.4:100"); - addr = getOmAddress(conf); - assertThat(addr.getHostString(), is("1.2.3.4")); - assertThat(addr.getPort(), is(100)); - - // Assert the we are able to use default configs if no value is specified. - conf.set(OMConfigKeys.OZONE_OM_ADDRESS_KEY, ""); - addr = getOmAddress(conf); - assertThat(addr.getHostString(), is("0.0.0.0")); - assertThat(addr.getPort(), is(OMConfigKeys.OZONE_OM_PORT_DEFAULT)); - } -} diff --git a/hadoop-ozone/client/src/test/java/org/apache/hadoop/ozone/client/package-info.java b/hadoop-ozone/client/src/test/java/org/apache/hadoop/ozone/client/package-info.java deleted file mode 100644 index be63eab0c7a..00000000000 --- a/hadoop-ozone/client/src/test/java/org/apache/hadoop/ozone/client/package-info.java +++ /dev/null @@ -1,23 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client; - -/** - * This package contains test classes for Ozone Client. - */ \ No newline at end of file diff --git a/hadoop-ozone/common/dev-support/findbugsExcludeFile.xml b/hadoop-ozone/common/dev-support/findbugsExcludeFile.xml deleted file mode 100644 index df58f3650a4..00000000000 --- a/hadoop-ozone/common/dev-support/findbugsExcludeFile.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - diff --git a/hadoop-ozone/common/pom.xml b/hadoop-ozone/common/pom.xml deleted file mode 100644 index 942576b610a..00000000000 --- a/hadoop-ozone/common/pom.xml +++ /dev/null @@ -1,115 +0,0 @@ - - - - 4.0.0 - - org.apache.hadoop - hadoop-ozone - 0.3.0-SNAPSHOT - - hadoop-ozone-common - 0.3.0-SNAPSHOT - Apache Hadoop Ozone Common - Apache Hadoop Ozone Common - jar - - - - - - - - - ${basedir}/src/main/resources - - ozone-version-info.properties - - false - - - ${basedir}/src/main/resources - - ozone-version-info.properties - - true - - - - - org.apache.hadoop - hadoop-maven-plugins - - - version-info - generate-resources - - version-info - - - - ${basedir}/../ - - */src/main/java/**/*.java - */src/main/proto/*.proto - - - - - - compile-protoc - - protoc - - - ${protobuf.version} - ${protoc.path} - - - ${basedir}/../../hadoop-common-project/hadoop-common/src/main/proto - - - ${basedir}/../../hadoop-hdfs-project/hadoop-hdfs-client/src/main/proto/ - - - ${basedir}/../../hadoop-hdfs-project/hadoop-hdfs/src/main/proto/ - - - ${basedir}/../../hadoop-hdds/common/src/main/proto/ - - ${basedir}/src/main/proto - - - ${basedir}/src/main/proto - - OzoneManagerProtocol.proto - - - - - - - - org.codehaus.mojo - findbugs-maven-plugin - - ${basedir}/dev-support/findbugsExcludeFile.xml - - - - - diff --git a/hadoop-ozone/common/src/main/bin/ozone b/hadoop-ozone/common/src/main/bin/ozone deleted file mode 100755 index 4b507711765..00000000000 --- a/hadoop-ozone/common/src/main/bin/ozone +++ /dev/null @@ -1,242 +0,0 @@ -#!/usr/bin/env bash - -# 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. - -# The name of the script being executed. -HADOOP_SHELL_EXECNAME="ozone" -MYNAME="${BASH_SOURCE-$0}" - -## @description build up the hdfs command's usage text. -## @audience public -## @stability stable -## @replaceable no -function hadoop_usage -{ - hadoop_add_option "--buildpaths" "attempt to add class files from build tree" - hadoop_add_option "--daemon (start|status|stop)" "operate on a daemon" - hadoop_add_option "--hostnames list[,of,host,names]" "hosts to use in worker mode" - hadoop_add_option "--hosts filename" "list of hosts to use in worker mode" - hadoop_add_option "--loglevel level" "set the log4j level for this command" - hadoop_add_option "--workers" "turn on worker mode" - - hadoop_add_subcommand "classpath" client "prints the class path needed to get the hadoop jar and the required libraries" - hadoop_add_subcommand "datanode" daemon "run a HDDS datanode" - hadoop_add_subcommand "envvars" client "display computed Hadoop environment variables" - hadoop_add_subcommand "freon" client "runs an ozone data generator" - hadoop_add_subcommand "fs" client "run a filesystem command on Ozone file system. Equivalent to 'hadoop fs'" - hadoop_add_subcommand "genconf" client "generate minimally required ozone configs and output to ozone-site.xml in specified path" - hadoop_add_subcommand "genesis" client "runs a collection of ozone benchmarks to help with tuning." - hadoop_add_subcommand "getozoneconf" client "get ozone config values from configuration" - hadoop_add_subcommand "jmxget" admin "get JMX exported values from NameNode or DataNode." - hadoop_add_subcommand "noz" client "ozone debug tool, convert ozone metadata into relational data" - hadoop_add_subcommand "om" daemon "Ozone Manager" - hadoop_add_subcommand "scm" daemon "run the Storage Container Manager service" - hadoop_add_subcommand "s3g" daemon "run the S3 compatible REST gateway" - hadoop_add_subcommand "scmcli" client "run the CLI of the Storage Container Manager" - hadoop_add_subcommand "sh" client "command line interface for object store operations" - hadoop_add_subcommand "version" client "print the version" - - hadoop_generate_usage "${HADOOP_SHELL_EXECNAME}" false -} - -## @description Default command handler for hadoop command -## @audience public -## @stability stable -## @replaceable no -## @param CLI arguments -function ozonecmd_case -{ - subcmd=$1 - shift - - case ${subcmd} in - classpath) - hadoop_do_classpath_subcommand HADOOP_CLASSNAME "$@" - ;; - datanode) - HADOOP_SUBCMD_SUPPORTDAEMONIZATION="true" - HADOOP_CLASSNAME=org.apache.hadoop.ozone.HddsDatanodeService - OZONE_RUN_ARTIFACT_NAME="hadoop-ozone-datanode" - ;; - envvars) - echo "JAVA_HOME='${JAVA_HOME}'" - echo "HADOOP_HDFS_HOME='${HADOOP_HDFS_HOME}'" - echo "HDFS_DIR='${HDFS_DIR}'" - echo "HDFS_LIB_JARS_DIR='${HDFS_LIB_JARS_DIR}'" - echo "HADOOP_CONF_DIR='${HADOOP_CONF_DIR}'" - echo "HADOOP_TOOLS_HOME='${HADOOP_TOOLS_HOME}'" - echo "HADOOP_TOOLS_DIR='${HADOOP_TOOLS_DIR}'" - echo "HADOOP_TOOLS_LIB_JARS_DIR='${HADOOP_TOOLS_LIB_JARS_DIR}'" - if [[ -n "${QATESTMODE}" ]]; then - echo "MYNAME=${MYNAME}" - echo "HADOOP_SHELL_EXECNAME=${HADOOP_SHELL_EXECNAME}" - fi - exit 0 - ;; - freon) - HADOOP_CLASSNAME=org.apache.hadoop.ozone.freon.Freon - OZONE_RUN_ARTIFACT_NAME="hadoop-ozone-tools" - ;; - genesis) - HADOOP_CLASSNAME=org.apache.hadoop.ozone.genesis.Genesis - OZONE_RUN_ARTIFACT_NAME="hadoop-ozone-tools" - ;; - getozoneconf) - HADOOP_CLASSNAME=org.apache.hadoop.ozone.freon.OzoneGetConf; - OZONE_RUN_ARTIFACT_NAME="hadoop-ozone-tools" - ;; - om) - HADOOP_SUBCMD_SUPPORTDAEMONIZATION="true" - HADOOP_CLASSNAME=org.apache.hadoop.ozone.om.OzoneManager - HDFS_OM_OPTS="${HDFS_OM_OPTS} -Dlog4j.configurationFile=${HADOOP_CONF_DIR}/om-audit-log4j2.properties" - HADOOP_OPTS="${HADOOP_OPTS} ${HDFS_OM_OPTS}" - OZONE_RUN_ARTIFACT_NAME="hadoop-ozone-ozone-manager" - ;; - sh | shell) - HADOOP_CLASSNAME=org.apache.hadoop.ozone.web.ozShell.Shell - OZONE_RUN_ARTIFACT_NAME="hadoop-ozone-ozone-manager" - ;; - scm) - HADOOP_SUBCMD_SUPPORTDAEMONIZATION="true" - HADOOP_CLASSNAME='org.apache.hadoop.hdds.scm.server.StorageContainerManager' - hadoop_debug "Appending HDFS_STORAGECONTAINERMANAGER_OPTS onto HADOOP_OPTS" - HADOOP_OPTS="${HADOOP_OPTS} ${HDFS_STORAGECONTAINERMANAGER_OPTS}" - OZONE_RUN_ARTIFACT_NAME="hadoop-hdds-server-scm" - ;; - s3g) - HADOOP_SUBCMD_SUPPORTDAEMONIZATION="true" - HADOOP_CLASSNAME='org.apache.hadoop.ozone.s3.Gateway' - OZONE_RUN_ARTIFACT_NAME="hadoop-ozone-s3gateway" - ;; - fs) - HADOOP_CLASSNAME=org.apache.hadoop.fs.FsShell - OZONE_RUN_ARTIFACT_NAME="hadoop-ozone-tools" - ;; - scmcli) - HADOOP_CLASSNAME=org.apache.hadoop.hdds.scm.cli.SCMCLI - OZONE_RUN_ARTIFACT_NAME="hadoop-hdds-tools" - ;; - version) - HADOOP_CLASSNAME=org.apache.hadoop.ozone.util.OzoneVersionInfo - OZONE_RUN_ARTIFACT_NAME="hadoop-ozone-common" - ;; - genconf) - HADOOP_CLASSNAME=org.apache.hadoop.ozone.genconf.GenerateOzoneRequiredConfigurations - OZONE_RUN_ARTIFACT_NAME="hadoop-ozone-tools" - ;; - *) - HADOOP_CLASSNAME="${subcmd}" - if ! hadoop_validate_classname "${HADOOP_CLASSNAME}"; then - hadoop_exit_with_usage 1 - fi - ;; - esac -} - -# let's locate libexec... -if [[ -n "${HADOOP_HOME}" ]]; then - HADOOP_DEFAULT_LIBEXEC_DIR="${HADOOP_HOME}/libexec" -else - bin=$(cd -P -- "$(dirname -- "${MYNAME}")" >/dev/null && pwd -P) - HADOOP_DEFAULT_LIBEXEC_DIR="${bin}/../libexec" -fi - -HADOOP_LIBEXEC_DIR="${HADOOP_LIBEXEC_DIR:-$HADOOP_DEFAULT_LIBEXEC_DIR}" -# shellcheck disable=SC2034 -HADOOP_NEW_CONFIG=true -if [[ -f "${HADOOP_LIBEXEC_DIR}/ozone-config.sh" ]]; then - # shellcheck source=./hadoop-ozone/common/src/main/bin/ozone-config.sh - . "${HADOOP_LIBEXEC_DIR}/ozone-config.sh" -else - echo "ERROR: Cannot execute ${HADOOP_LIBEXEC_DIR}/ozone-config.sh." 2>&1 - exit 1 -fi - -# now that we have support code, let's abs MYNAME so we can use it later -MYNAME=$(hadoop_abs "${MYNAME}") - -if [[ $# = 0 ]]; then - hadoop_exit_with_usage 1 -fi - -HADOOP_SUBCMD=$1 -shift - - -if hadoop_need_reexec ozone "${HADOOP_SUBCMD}"; then - hadoop_uservar_su ozone "${HADOOP_SUBCMD}" \ - "${MYNAME}" \ - "--reexec" \ - "${HADOOP_USER_PARAMS[@]}" - exit $? -fi - -hadoop_verify_user_perm "${HADOOP_SHELL_EXECNAME}" "${HADOOP_SUBCMD}" - -HADOOP_SUBCMD_ARGS=("$@") - -if declare -f ozone_subcommand_"${HADOOP_SUBCMD}" >/dev/null 2>&1; then - hadoop_debug "Calling dynamically: ozone_subcommand_${HADOOP_SUBCMD} ${HADOOP_SUBCMD_ARGS[*]}" - "ozone_subcommand_${HADOOP_SUBCMD}" "${HADOOP_SUBCMD_ARGS[@]}" -else - ozonecmd_case "${HADOOP_SUBCMD}" "${HADOOP_SUBCMD_ARGS[@]}" -fi - - -# -# Setting up classpath based on the generate classpath descriptors -# -if [ ! "$OZONE_RUN_ARTIFACT_NAME" ]; then - echo "ERROR: Ozone components require to set OZONE_RUN_ARTIFACT_NAME to set the classpath" - exit -1 -fi -export HDDS_LIB_JARS_DIR="${HADOOP_HDFS_HOME}/share/ozone/lib" -CLASSPATH_FILE="${HADOOP_HDFS_HOME}/share/ozone/classpath/${OZONE_RUN_ARTIFACT_NAME}.classpath" -if [ ! "$CLASSPATH_FILE" ]; then - echo "ERROR: Classpath file descriptor $CLASSPATH_FILE is missing" - exit -1 -fi -# shellcheck disable=SC1090,SC2086 -source $CLASSPATH_FILE -OIFS=$IFS -IFS=':' -# shellcheck disable=SC2154 -for jar in $classpath; do - hadoop_add_classpath "$jar" -done -hadoop_add_classpath "${HADOOP_HDFS_HOME}/share/ozone/web" - -#We need to add the artifact manually as it's not part the generated classpath desciptor -ARTIFACT_LIB_DIR="${HADOOP_HDFS_HOME}/share/ozone/lib" -MAIN_ARTIFACT=$(find "$ARTIFACT_LIB_DIR" -name "${OZONE_RUN_ARTIFACT_NAME}-*.jar") -if [ ! "$MAIN_ARTIFACT" ]; then - echo "ERROR: Component jar file $MAIN_ARTIFACT is missing from ${HADOOP_HDFS_HOME}/share/ozone/lib" -fi -hadoop_add_classpath "${MAIN_ARTIFACT}" -IFS=$OIFS - - -hadoop_add_client_opts - -if [[ ${HADOOP_WORKER_MODE} = true ]]; then - hadoop_common_worker_mode_execute "${HADOOP_HDFS_HOME}/bin/ozone" "${HADOOP_USER_PARAMS[@]}" - exit $? -fi - -hadoop_subcommand_opts "${HADOOP_SHELL_EXECNAME}" "${HADOOP_SUBCMD}" - -# everything is in globals at this point, so call the generic handler -hadoop_generic_java_subcmd_handler diff --git a/hadoop-ozone/common/src/main/bin/ozone-config.sh b/hadoop-ozone/common/src/main/bin/ozone-config.sh deleted file mode 100755 index d179a331ae9..00000000000 --- a/hadoop-ozone/common/src/main/bin/ozone-config.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env bash - -# 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. - -# included in all the ozone scripts with source command -# should not be executed directly - -function hadoop_subproject_init -{ - if [[ -z "${HADOOP_OZONE_ENV_PROCESSED}" ]]; then - if [[ -e "${HADOOP_CONF_DIR}/ozone-env.sh" ]]; then - . "${HADOOP_CONF_DIR}/ozone-env.sh" - export HADOOP_OZONE_ENV_PROCESSED=true - fi - fi - HADOOP_OZONE_HOME="${HADOOP_OZONE_HOME:-$HADOOP_HOME}" - -} - -if [[ -z "${HADOOP_LIBEXEC_DIR}" ]]; then - _hd_this="${BASH_SOURCE-$0}" - HADOOP_LIBEXEC_DIR=$(cd -P -- "$(dirname -- "${_hd_this}")" >/dev/null && pwd -P) -fi - -# shellcheck source=./hadoop-common-project/hadoop-common/src/main/bin/hadoop-config.sh - -if [[ -n "${HADOOP_COMMON_HOME}" ]] && - [[ -e "${HADOOP_COMMON_HOME}/libexec/hadoop-config.sh" ]]; then - . "${HADOOP_COMMON_HOME}/libexec/hadoop-config.sh" -elif [[ -e "${HADOOP_LIBEXEC_DIR}/hadoop-config.sh" ]]; then - . "${HADOOP_LIBEXEC_DIR}/hadoop-config.sh" -elif [ -e "${HADOOP_HOME}/libexec/hadoop-config.sh" ]; then - . "${HADOOP_HOME}/libexec/hadoop-config.sh" -else - echo "ERROR: Hadoop common not found." 2>&1 - exit 1 -fi - diff --git a/hadoop-ozone/common/src/main/bin/start-ozone.sh b/hadoop-ozone/common/src/main/bin/start-ozone.sh deleted file mode 100755 index cfb54e03325..00000000000 --- a/hadoop-ozone/common/src/main/bin/start-ozone.sh +++ /dev/null @@ -1,127 +0,0 @@ -#!/usr/bin/env bash - -# 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. - -# Start hadoop hdfs and ozone daemons. -# Run this on master node. -## @description usage info -## @audience private -## @stability evolving -## @replaceable no -function hadoop_usage -{ - echo "Usage: start-ozone.sh" -} - -this="${BASH_SOURCE-$0}" -bin=$(cd -P -- "$(dirname -- "${this}")" >/dev/null && pwd -P) - -# let's locate libexec... -if [[ -n "${HADOOP_HOME}" ]]; then - HADOOP_DEFAULT_LIBEXEC_DIR="${HADOOP_HOME}/libexec" -else - HADOOP_DEFAULT_LIBEXEC_DIR="${bin}/../libexec" -fi - -HADOOP_LIBEXEC_DIR="${HADOOP_LIBEXEC_DIR:-$HADOOP_DEFAULT_LIBEXEC_DIR}" -# shellcheck disable=SC2034 -HADOOP_NEW_CONFIG=true -if [[ -f "${HADOOP_LIBEXEC_DIR}/ozone-config.sh" ]]; then - # shellcheck disable=SC1090 - . "${HADOOP_LIBEXEC_DIR}/ozone-config.sh" -else - echo "ERROR: Cannot execute ${HADOOP_LIBEXEC_DIR}/ozone-config.sh." 2>&1 - exit 1 -fi - -# get arguments -if [[ $# -ge 1 ]]; then - startOpt="$1" - shift - case "$startOpt" in - -upgrade) - nameStartOpt="$startOpt" - ;; - -rollback) - dataStartOpt="$startOpt" - ;; - *) - hadoop_exit_with_usage 1 - ;; - esac -fi - -#Add other possible options -nameStartOpt="$nameStartOpt $*" - -SECURITY_ENABLED=$("${HADOOP_HDFS_HOME}/bin/ozone" getozoneconf -confKey hadoop.security.authentication | tr '[:upper:]' '[:lower:]' 2>&-) -SECURITY_AUTHORIZATION_ENABLED=$("${HADOOP_HDFS_HOME}/bin/ozone" getozoneconf -confKey hadoop.security.authorization | tr '[:upper:]' '[:lower:]' 2>&-) - -if [[ ${SECURITY_ENABLED} == "kerberos" || ${SECURITY_AUTHORIZATION_ENABLED} == "true" ]]; then - echo "Ozone is not supported in a security enabled cluster." - exit 1 -fi - -#--------------------------------------------------------- -# Check if ozone is enabled -OZONE_ENABLED=$("${HADOOP_HDFS_HOME}/bin/ozone" getozoneconf -confKey ozone.enabled | tr '[:upper:]' '[:lower:]' 2>&-) -if [[ "${OZONE_ENABLED}" != "true" ]]; then - echo "Operation is not supported because ozone is not enabled." - exit -1 -fi - -#--------------------------------------------------------- -# datanodes (using default workers file) - -echo "Starting datanodes" -hadoop_uservar_su hdfs datanode "${HADOOP_HDFS_HOME}/bin/ozone" \ - --workers \ - --config "${HADOOP_CONF_DIR}" \ - --daemon start \ - datanode ${dataStartOpt} -(( HADOOP_JUMBO_RETCOUNTER=HADOOP_JUMBO_RETCOUNTER + $? )) - -#--------------------------------------------------------- -# Ozone ozonemanager nodes -OM_NODES=$("${HADOOP_HDFS_HOME}/bin/ozone" getozoneconf -ozonemanagers 2>/dev/null) -echo "Starting Ozone Manager nodes [${OM_NODES}]" -if [[ "${OM_NODES}" == "0.0.0.0" ]]; then - OM_NODES=$(hostname) -fi - -hadoop_uservar_su hdfs om "${HADOOP_HDFS_HOME}/bin/ozone" \ - --workers \ - --config "${HADOOP_CONF_DIR}" \ - --hostnames "${OM_NODES}" \ - --daemon start \ - om - -HADOOP_JUMBO_RETCOUNTER=$? - -#--------------------------------------------------------- -# Ozone storagecontainermanager nodes -SCM_NODES=$("${HADOOP_HDFS_HOME}/bin/ozone" getozoneconf -storagecontainermanagers 2>/dev/null) -echo "Starting storage container manager nodes [${SCM_NODES}]" -hadoop_uservar_su hdfs scm "${HADOOP_HDFS_HOME}/bin/ozone" \ - --workers \ - --config "${HADOOP_CONF_DIR}" \ - --hostnames "${SCM_NODES}" \ - --daemon start \ - scm - -(( HADOOP_JUMBO_RETCOUNTER=HADOOP_JUMBO_RETCOUNTER + $? )) - -exit ${HADOOP_JUMBO_RETCOUNTER} diff --git a/hadoop-ozone/common/src/main/bin/stop-ozone.sh b/hadoop-ozone/common/src/main/bin/stop-ozone.sh deleted file mode 100755 index 97e1df4df36..00000000000 --- a/hadoop-ozone/common/src/main/bin/stop-ozone.sh +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/env bash - -# 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. - -# Stop hdfs and ozone daemons. -# Run this on master node. -## @description usage info -## @audience private -## @stability evolving -## @replaceable no -function hadoop_usage -{ - echo "Usage: stop-ozone.sh" -} - -this="${BASH_SOURCE-$0}" -bin=$(cd -P -- "$(dirname -- "${this}")" >/dev/null && pwd -P) - -# let's locate libexec... -if [[ -n "${HADOOP_HOME}" ]]; then - HADOOP_DEFAULT_LIBEXEC_DIR="${HADOOP_HOME}/libexec" -else - HADOOP_DEFAULT_LIBEXEC_DIR="${bin}/../libexec" -fi - -HADOOP_LIBEXEC_DIR="${HADOOP_LIBEXEC_DIR:-$HADOOP_DEFAULT_LIBEXEC_DIR}" -# shellcheck disable=SC2034 -HADOOP_NEW_CONFIG=true -if [[ -f "${HADOOP_LIBEXEC_DIR}/ozone-config.sh" ]]; then - # shellcheck disable=SC1090 - . "${HADOOP_LIBEXEC_DIR}/ozone-config.sh" -else - echo "ERROR: Cannot execute ${HADOOP_LIBEXEC_DIR}/ozone-config.sh." 2>&1 - exit 1 -fi - -SECURITY_ENABLED=$("${HADOOP_HDFS_HOME}/bin/ozone" getozoneconf -confKey hadoop.security.authentication | tr '[:upper:]' '[:lower:]' 2>&-) -SECURITY_AUTHORIZATION_ENABLED=$("${HADOOP_HDFS_HOME}/bin/ozone" getozoneconf -confKey hadoop.security.authorization | tr '[:upper:]' '[:lower:]' 2>&-) - -if [[ ${SECURITY_ENABLED} == "kerberos" || ${SECURITY_AUTHORIZATION_ENABLED} == "true" ]]; then - echo "Ozone is not supported in a security enabled cluster." - exit 1 -fi - -#--------------------------------------------------------- -# Check if ozone is enabled -OZONE_ENABLED=$("${HADOOP_HDFS_HOME}/bin/ozone" getozoneconf -confKey ozone.enabled | tr '[:upper:]' '[:lower:]' 2>&-) -if [[ "${OZONE_ENABLED}" != "true" ]]; then - echo "Operation is not supported because ozone is not enabled." - exit -1 -fi - -#--------------------------------------------------------- -# datanodes (using default workers file) - -echo "Stopping datanodes" - -hadoop_uservar_su ozone datanode "${HADOOP_HDFS_HOME}/bin/ozone" \ - --workers \ - --config "${HADOOP_CONF_DIR}" \ - --daemon stop \ - datanode - -#--------------------------------------------------------- -# Ozone Manager nodes -OM_NODES=$("${HADOOP_HDFS_HOME}/bin/ozone" getozoneconf -ozonemanagers 2>/dev/null) -echo "Stopping Ozone Manager nodes [${OM_NODES}]" -if [[ "${OM_NODES}" == "0.0.0.0" ]]; then - OM_NODES=$(hostname) -fi - -hadoop_uservar_su hdfs om "${HADOOP_HDFS_HOME}/bin/ozone" \ - --workers \ - --config "${HADOOP_CONF_DIR}" \ - --hostnames "${OM_NODES}" \ - --daemon stop \ - om - -#--------------------------------------------------------- -# Ozone storagecontainermanager nodes -SCM_NODES=$("${HADOOP_HDFS_HOME}/bin/ozone" getozoneconf -storagecontainermanagers 2>/dev/null) -echo "Stopping storage container manager nodes [${SCM_NODES}]" -hadoop_uservar_su hdfs scm "${HADOOP_HDFS_HOME}/bin/ozone" \ - --workers \ - --config "${HADOOP_CONF_DIR}" \ - --hostnames "${SCM_NODES}" \ - --daemon stop \ - scm \ No newline at end of file diff --git a/hadoop-ozone/common/src/main/conf/om-audit-log4j2.properties b/hadoop-ozone/common/src/main/conf/om-audit-log4j2.properties deleted file mode 100644 index 7d097a081a2..00000000000 --- a/hadoop-ozone/common/src/main/conf/om-audit-log4j2.properties +++ /dev/null @@ -1,86 +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 -#

-# 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. -# -name=PropertiesConfig - -# Checks for config change periodically and reloads -monitorInterval=30 - -filter=read,write -# filter.read.onMatch=DENY avoids logging all READ events -# filter.read.onMatch=ACCEPT permits logging all READ events -# The above two settings ignore the log levels in configuration -# filter.read.onMatch=NEUTRAL permits logging of only those READ events -# which are attempted at log level equal or greater than log level specified -# in the configuration -filter.read.type=MarkerFilter -filter.read.marker=READ -filter.read.onMatch=DENY -filter.read.onMismatch=NEUTRAL - -# filter.write.onMatch=DENY avoids logging all WRITE events -# filter.write.onMatch=ACCEPT permits logging all WRITE events -# The above two settings ignore the log levels in configuration -# filter.write.onMatch=NEUTRAL permits logging of only those WRITE events -# which are attempted at log level equal or greater than log level specified -# in the configuration -filter.write.type=MarkerFilter -filter.write.marker=WRITE -filter.write.onMatch=NEUTRAL -filter.write.onMismatch=NEUTRAL - -# Log Levels are organized from most specific to least: -# OFF (most specific, no logging) -# FATAL (most specific, little data) -# ERROR -# WARN -# INFO -# DEBUG -# TRACE (least specific, a lot of data) -# ALL (least specific, all data) - -appenders=console, rolling -appender.console.type=Console -appender.console.name=STDOUT -appender.console.layout.type=PatternLayout -appender.console.layout.pattern=%d{DEFAULT} | %-5level | %c{1} | %msg | %throwable{3} %n - -#Rolling File Appender with size & time thresholds. -#Rolling is triggered when either threshold is breached. -#The rolled over file is compressed by default -#Time interval is specified in seconds 86400s=1 day -appender.rolling.type=RollingFile -appender.rolling.name=RollingFile -appender.rolling.fileName =${sys:hadoop.log.dir}/om-audit-${hostName}.log -appender.rolling.filePattern=${sys:hadoop.log.dir}/om-audit-${hostName}-%d{yyyy-MM-dd-HH-mm-ss}-%i.log.gz -appender.rolling.layout.type=PatternLayout -appender.rolling.layout.pattern=%d{DEFAULT} | %-5level | %c{1} | %msg | %throwable{3} %n -appender.rolling.policies.type=Policies -appender.rolling.policies.time.type=TimeBasedTriggeringPolicy -appender.rolling.policies.time.interval=86400 -appender.rolling.policies.size.type=SizeBasedTriggeringPolicy -appender.rolling.policies.size.size=64MB - -loggers=audit -logger.audit.type=AsyncLogger -logger.audit.name=OMAudit -logger.audit.level=INFO -logger.audit.appenderRefs=rolling -logger.audit.appenderRef.file.ref=RollingFile - -rootLogger.level=INFO -rootLogger.appenderRefs=stdout -rootLogger.appenderRef.stdout.ref=STDOUT diff --git a/hadoop-ozone/common/src/main/conf/ozone-site.xml b/hadoop-ozone/common/src/main/conf/ozone-site.xml deleted file mode 100644 index 77dd7ef9940..00000000000 --- a/hadoop-ozone/common/src/main/conf/ozone-site.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java deleted file mode 100644 index 097410405f0..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java +++ /dev/null @@ -1,94 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone; - -import java.net.InetSocketAddress; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.net.NetUtils; - -import com.google.common.base.Optional; -import static org.apache.hadoop.hdds.HddsUtils.getHostNameFromConfigKeys; -import static org.apache.hadoop.hdds.HddsUtils.getPortNumberFromConfigKeys; -import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_ADDRESS_KEY; -import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_BIND_HOST_DEFAULT; -import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_HTTP_ADDRESS_KEY; -import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_HTTP_BIND_PORT_DEFAULT; -import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_PORT_DEFAULT; - -/** - * Stateless helper functions for the server and client side of OM - * communication. - */ -public final class OmUtils { - - private OmUtils() { - } - - /** - * Retrieve the socket address that is used by OM. - * @param conf - * @return Target InetSocketAddress for the SCM service endpoint. - */ - public static InetSocketAddress getOmAddress( - Configuration conf) { - final Optional host = getHostNameFromConfigKeys(conf, - OZONE_OM_ADDRESS_KEY); - - return NetUtils.createSocketAddr( - host.or(OZONE_OM_BIND_HOST_DEFAULT) + ":" + - getOmRpcPort(conf)); - } - - /** - * Retrieve the socket address that should be used by clients to connect - * to OM. - * @param conf - * @return Target InetSocketAddress for the OM service endpoint. - */ - public static InetSocketAddress getOmAddressForClients( - Configuration conf) { - final Optional host = getHostNameFromConfigKeys(conf, - OZONE_OM_ADDRESS_KEY); - - if (!host.isPresent()) { - throw new IllegalArgumentException( - OZONE_OM_ADDRESS_KEY + " must be defined. See" + - " https://wiki.apache.org/hadoop/Ozone#Configuration for" + - " details on configuring Ozone."); - } - - return NetUtils.createSocketAddr( - host.get() + ":" + getOmRpcPort(conf)); - } - - public static int getOmRpcPort(Configuration conf) { - // If no port number is specified then we'll just try the defaultBindPort. - final Optional port = getPortNumberFromConfigKeys(conf, - OZONE_OM_ADDRESS_KEY); - return port.or(OZONE_OM_PORT_DEFAULT); - } - - public static int getOmRestPort(Configuration conf) { - // If no port number is specified then we'll just try the default - // HTTP BindPort. - final Optional port = - getPortNumberFromConfigKeys(conf, OZONE_OM_HTTP_ADDRESS_KEY); - return port.or(OZONE_OM_HTTP_BIND_PORT_DEFAULT); - } -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/audit/OMAction.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/audit/OMAction.java deleted file mode 100644 index a0ae455303e..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/audit/OMAction.java +++ /dev/null @@ -1,61 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.audit; - -/** - * Enum to define Audit Action types for OzoneManager. - */ -public enum OMAction implements AuditAction { - - // WRITE Actions - ALLOCATE_BLOCK("ALLOCATE_BLOCK"), - ALLOCATE_KEY("ALLOCATE_KEY"), - COMMIT_KEY("COMMIT_KEY"), - CREATE_VOLUME("CREATE_VOLUME"), - CREATE_BUCKET("CREATE_BUCKET"), - CREATE_KEY("CREATE_KEY"), - DELETE_VOLUME("DELETE_VOLUME"), - DELETE_BUCKET("DELETE_BUCKET"), - DELETE_KEY("DELETE_KEY"), - RENAME_KEY("RENAME_KEY"), - SET_OWNER("SET_OWNER"), - SET_QUOTA("SET_QUOTA"), - UPDATE_VOLUME("UPDATE_VOLUME"), - UPDATE_BUCKET("UPDATE_BUCKET"), - UPDATE_KEY("UPDATE_KEY"), - // READ Actions - CHECK_VOLUME_ACCESS("CHECK_VOLUME_ACCESS"), - LIST_BUCKETS("LIST_BUCKETS"), - LIST_VOLUMES("LIST_VOLUMES"), - LIST_KEYS("LIST_KEYS"), - READ_VOLUME("READ_VOLUME"), - READ_BUCKET("READ_BUCKET"), - READ_KEY("READ_BUCKET"); - - private String action; - - OMAction(String action) { - this.action = action; - } - - @Override - public String getAction() { - return this.action; - } - -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/audit/package-info.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/audit/package-info.java deleted file mode 100644 index 0f887909d49..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/audit/package-info.java +++ /dev/null @@ -1,22 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.audit; -/** - * This package defines OMAction - an implementation of AuditAction - * OMAction defines audit action types for various actions that will be - * audited in OzoneManager. - */ diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/io/LengthInputStream.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/io/LengthInputStream.java deleted file mode 100644 index baf1887c468..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/io/LengthInputStream.java +++ /dev/null @@ -1,49 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client.io; - -import java.io.FilterInputStream; -import java.io.InputStream; - -/** - * An input stream with length. - */ -public class LengthInputStream extends FilterInputStream { - - private final long length; - - /** - * Create an stream. - * @param in the underlying input stream. - * @param length the length of the stream. - */ - public LengthInputStream(InputStream in, long length) { - super(in); - this.length = length; - } - - /** @return the length. */ - public long getLength() { - return length; - } - - public InputStream getWrappedStream() { - return in; - } -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/io/package-info.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/io/package-info.java deleted file mode 100644 index ece1ff4463c..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/io/package-info.java +++ /dev/null @@ -1,22 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.client.io; - -/** - * IO related ozone helper classes. - */ \ No newline at end of file diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/OzoneException.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/OzoneException.java deleted file mode 100644 index 953e3991f7b..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/OzoneException.java +++ /dev/null @@ -1,267 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client.rest; - - -import java.io.IOException; - -import org.apache.hadoop.classification.InterfaceAudience; - -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ObjectReader; - -/** - * Class the represents various errors returned by the - * Ozone Layer. - */ -@InterfaceAudience.Private -public class OzoneException extends Exception { - - private static final ObjectReader READER = - new ObjectMapper().readerFor(OzoneException.class); - private static final ObjectMapper MAPPER; - - static { - MAPPER = new ObjectMapper(); - MAPPER.setVisibility( - MAPPER.getSerializationConfig().getDefaultVisibilityChecker() - .withCreatorVisibility(JsonAutoDetect.Visibility.NONE) - .withFieldVisibility(JsonAutoDetect.Visibility.NONE) - .withGetterVisibility(JsonAutoDetect.Visibility.NONE) - .withIsGetterVisibility(JsonAutoDetect.Visibility.NONE) - .withSetterVisibility(JsonAutoDetect.Visibility.NONE)); - } - - @JsonProperty("httpCode") - private long httpCode; - @JsonProperty("shortMessage") - private String shortMessage; - @JsonProperty("resource") - private String resource; - @JsonProperty("message") - private String message; - @JsonProperty("requestID") - private String requestId; - @JsonProperty("hostName") - private String hostID; - - /** - * Constructs a new exception with {@code null} as its detail message. The - * cause is not initialized, and may subsequently be initialized by a call - * to {@link #initCause}. - * - * This constructor is needed by Json Serializer. - */ - public OzoneException() { - } - - - /** - * Constructor that allows a shortMessage and exception. - * - * @param httpCode Error Code - * @param shortMessage Short Message - * @param ex Exception - */ - public OzoneException(long httpCode, String shortMessage, Exception ex) { - super(ex); - this.message = ex.getMessage(); - this.shortMessage = shortMessage; - this.httpCode = httpCode; - } - - - /** - * Constructor that allows a shortMessage. - * - * @param httpCode Error Code - * @param shortMessage Short Message - */ - public OzoneException(long httpCode, String shortMessage) { - this.shortMessage = shortMessage; - this.httpCode = httpCode; - } - - /** - * Constructor that allows a shortMessage and long message. - * - * @param httpCode Error Code - * @param shortMessage Short Message - * @param message long error message - */ - public OzoneException(long httpCode, String shortMessage, String message) { - this.shortMessage = shortMessage; - this.message = message; - this.httpCode = httpCode; - } - - /** - * Constructor that allows a shortMessage, a long message and an exception. - * - * @param httpCode Error code - * @param shortMessage Short message - * @param message Long error message - * @param ex Exception - */ - public OzoneException(long httpCode, String shortMessage, - String message, Exception ex) { - super(ex); - this.shortMessage = shortMessage; - this.message = message; - this.httpCode = httpCode; - } - - /** - * Returns the Resource that was involved in the stackTraceString. - * - * @return String - */ - public String getResource() { - return resource; - } - - /** - * Sets Resource. - * - * @param resourceName - Name of the Resource - */ - public void setResource(String resourceName) { - this.resource = resourceName; - } - - /** - * Gets a detailed message for the error. - * - * @return String - */ - public String getMessage() { - return message; - } - - /** - * Sets the error message. - * - * @param longMessage - Long message - */ - public void setMessage(String longMessage) { - this.message = longMessage; - } - - /** - * Returns request Id. - * - * @return String - */ - public String getRequestId() { - return requestId; - } - - /** - * Sets request ID. - * - * @param ozoneRequestId Request ID generated by the Server - */ - public void setRequestId(String ozoneRequestId) { - this.requestId = ozoneRequestId; - } - - /** - * Returns short error string. - * - * @return String - */ - public String getShortMessage() { - return shortMessage; - } - - /** - * Sets short error string. - * - * @param shortError Short Error Code - */ - public void setShortMessage(String shortError) { - this.shortMessage = shortError; - } - - /** - * Returns hostID. - * - * @return String - */ - public String getHostID() { - return hostID; - } - - /** - * Sets host ID. - * - * @param hostName host Name - */ - public void setHostID(String hostName) { - this.hostID = hostName; - } - - /** - * Returns http error code. - * - * @return long - */ - public long getHttpCode() { - return httpCode; - } - - /** - * Sets http status. - * - * @param httpStatus http error code. - */ - public void setHttpCode(long httpStatus) { - this.httpCode = httpStatus; - } - - /** - * Returns a Json String. - * - * @return JSON representation of the Error - */ - public String toJsonString() { - try { - return MAPPER.writeValueAsString(this); - } catch (IOException ex) { - // TODO : Log this error on server side. - } - // TODO : Replace this with a JSON Object -- That represents this error. - return "500 Internal Server Error"; - } - - /** - * Parses an Exception record. - * - * @param jsonString - Exception in Json format. - * - * @return OzoneException Object - * - * @throws IOException - */ - public static OzoneException parse(String jsonString) throws IOException { - return READER.readValue(jsonString); - } -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/headers/Header.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/headers/Header.java deleted file mode 100644 index 3e404937061..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/headers/Header.java +++ /dev/null @@ -1,74 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client.rest.headers; - -import org.apache.hadoop.classification.InterfaceAudience; - -/** - * OZONE specific HTTP headers. - */ -@InterfaceAudience.Private -public final class Header { - public static final String OZONE_QUOTA_BYTES = "BYTES"; - public static final String OZONE_QUOTA_MB = "MB"; - public static final String OZONE_QUOTA_GB = "GB"; - public static final String OZONE_QUOTA_TB = "TB"; - public static final String OZONE_QUOTA_REMOVE = "remove"; - public static final String OZONE_QUOTA_UNDEFINED = "undefined"; - public static final String OZONE_EMPTY_STRING=""; - public static final String OZONE_DEFAULT_LIST_SIZE = "1000"; - - public static final String OZONE_USER = "x-ozone-user"; - public static final String OZONE_SIMPLE_AUTHENTICATION_SCHEME = "OZONE"; - public static final String OZONE_VERSION_HEADER = "x-ozone-version"; - public static final String OZONE_V1_VERSION_HEADER ="v1"; - - public static final String OZONE_LIST_QUERY_SERVICE = "service"; - - public static final String OZONE_INFO_QUERY_VOLUME = "volume"; - public static final String OZONE_INFO_QUERY_BUCKET = "bucket"; - public static final String OZONE_INFO_QUERY_KEY = "key"; - public static final String OZONE_INFO_QUERY_KEY_DETAIL = "key-detail"; - - public static final String OZONE_REQUEST_ID = "x-ozone-request-id"; - public static final String OZONE_SERVER_NAME = "x-ozone-server-name"; - - public static final String OZONE_STORAGE_TYPE = "x-ozone-storage-type"; - - public static final String OZONE_BUCKET_VERSIONING = - "x-ozone-bucket-versioning"; - - public static final String OZONE_ACLS = "x-ozone-acls"; - public static final String OZONE_ACL_ADD = "ADD"; - public static final String OZONE_ACL_REMOVE = "REMOVE"; - - public static final String OZONE_INFO_QUERY_TAG ="info"; - public static final String OZONE_QUOTA_QUERY_TAG ="quota"; - public static final String CONTENT_MD5 = "Content-MD5"; - public static final String OZONE_LIST_QUERY_PREFIX="prefix"; - public static final String OZONE_LIST_QUERY_MAXKEYS="max-keys"; - public static final String OZONE_LIST_QUERY_PREVKEY="prev-key"; - public static final String OZONE_LIST_QUERY_ROOTSCAN="root-scan"; - - public static final String OZONE_RENAME_TO_KEY_PARAM_NAME = "toKey"; - - private Header() { - // Never constructed. - } -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/headers/package-info.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/headers/package-info.java deleted file mode 100644 index 76bc206e53d..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/headers/package-info.java +++ /dev/null @@ -1,22 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.client.rest.headers; - -/** - * Ozone HTTP Header utility. - */ \ No newline at end of file diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/package-info.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/package-info.java deleted file mode 100644 index fc86dbb0576..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/package-info.java +++ /dev/null @@ -1,22 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.client.rest; - -/** - * Ozone REST interface. - */ \ No newline at end of file diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/response/BucketInfo.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/response/BucketInfo.java deleted file mode 100644 index af89b39efb2..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/response/BucketInfo.java +++ /dev/null @@ -1,231 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.client.rest.response; - -import java.io.IOException; -import java.util.LinkedList; -import java.util.List; - -import org.apache.hadoop.fs.StorageType; -import org.apache.hadoop.ozone.OzoneAcl; -import org.apache.hadoop.ozone.OzoneConsts; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ObjectReader; -import com.google.common.base.Preconditions; - -/** - * BucketInfo class is used used for parsing json response - * when BucketInfo Call is made. - */ -public class BucketInfo implements Comparable { - - private static final ObjectReader READER = - new ObjectMapper().readerFor(BucketInfo.class); - - private String volumeName; - private String bucketName; - private String createdOn; - private List acls; - private OzoneConsts.Versioning versioning; - private StorageType storageType; - - /** - * Constructor for BucketInfo. - * - * @param volumeName - * @param bucketName - */ - public BucketInfo(String volumeName, String bucketName) { - this.volumeName = volumeName; - this.bucketName = bucketName; - } - - - /** - * Default constructor for BucketInfo. - */ - public BucketInfo() { - acls = new LinkedList<>(); - } - - /** - * Parse a JSON string into BucketInfo Object. - * - * @param jsonString Json String - * @return BucketInfo - * @throws IOException - */ - public static BucketInfo parse(String jsonString) throws IOException { - return READER.readValue(jsonString); - } - - /** - * Returns a List of ACLs set on the Bucket. - * - * @return List of Acl - */ - public List getAcls() { - return acls; - } - - /** - * Sets ACls. - * - * @param acls Acl list - */ - public void setAcls(List acls) { - this.acls = acls; - } - - /** - * Returns Storage Type info. - * - * @return Storage Type of the bucket - */ - public StorageType getStorageType() { - return storageType; - } - - /** - * Sets the Storage Type. - * - * @param storageType Storage Type - */ - public void setStorageType(StorageType storageType) { - this.storageType = storageType; - } - - /** - * Returns versioning. - * - * @return versioning Enum - */ - public OzoneConsts.Versioning getVersioning() { - return versioning; - } - - /** - * Sets Versioning. - * - * @param versioning - */ - public void setVersioning(OzoneConsts.Versioning versioning) { - this.versioning = versioning; - } - - - /** - * Gets bucket Name. - * - * @return String - */ - public String getBucketName() { - return bucketName; - } - - /** - * Sets bucket Name. - * - * @param bucketName Name of the bucket - */ - public void setBucketName(String bucketName) { - this.bucketName = bucketName; - } - - /** - * Sets creation time of the bucket. - * - * @param creationTime Date String - */ - public void setCreatedOn(String creationTime) { - this.createdOn = creationTime; - } - - /** - * Returns creation time. - * - * @return creation time of bucket. - */ - public String getCreatedOn() { - return createdOn; - } - - /** - * Returns Volume Name. - * - * @return String volume name - */ - public String getVolumeName() { - return volumeName; - } - - /** - * Sets the Volume Name of bucket. - * - * @param volumeName volumeName - */ - public void setVolumeName(String volumeName) { - this.volumeName = volumeName; - } - - /** - * Compares this object with the specified object for order. Returns a - * negative integer, zero, or a positive integer as this object is less - * than, equal to, or greater than the specified object. - * - * Please note : BucketInfo compare functions are used only within the - * context of a volume, hence volume name is purposefully ignored in - * compareTo, equal and hashcode functions of this class. - */ - @Override - public int compareTo(BucketInfo o) { - Preconditions.checkState(o.getVolumeName().equals(this.getVolumeName())); - return this.bucketName.compareTo(o.getBucketName()); - } - - /** - * Checks if two bucketInfo's are equal. - * @param o Object BucketInfo - * @return True or False - */ - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof BucketInfo)) { - return false; - } - - BucketInfo that = (BucketInfo) o; - Preconditions.checkState(that.getVolumeName().equals(this.getVolumeName())); - return bucketName.equals(that.bucketName); - - } - - /** - * Hash Code for this object. - * @return int - */ - @Override - public int hashCode() { - return bucketName.hashCode(); - } - -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/response/KeyInfo.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/response/KeyInfo.java deleted file mode 100644 index 61c2abb2a82..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/response/KeyInfo.java +++ /dev/null @@ -1,216 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client.rest.response; - -import java.io.IOException; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ObjectReader; -import org.apache.commons.lang3.builder.EqualsBuilder; -import org.apache.commons.lang3.builder.HashCodeBuilder; - -/** - * KeyInfo class is used used for parsing json response - * when KeyInfo Call is made. - */ -public class KeyInfo implements Comparable { - - private static final ObjectReader READER = - new ObjectMapper().readerFor(KeyInfo.class); - - private long version; - private String md5hash; - private String createdOn; - private String modifiedOn; - private long size; - private String keyName; - - /** - * When this key was created. - * - * @return Date String - */ - public String getCreatedOn() { - return createdOn; - } - - /** - * When this key was modified. - * - * @return Date String - */ - public String getModifiedOn() { - return modifiedOn; - } - - /** - * When this key was created. - * - * @param createdOn Date String - */ - public void setCreatedOn(String createdOn) { - this.createdOn = createdOn; - } - - /** - * When this key was modified. - * - * @param modifiedOn Date String - */ - public void setModifiedOn(String modifiedOn) { - this.modifiedOn = modifiedOn; - } - - /** - * Gets the Key name of this object. - * - * @return String - */ - public String getKeyName() { - return keyName; - } - - /** - * Sets the Key name of this object. - * - * @param keyName String - */ - public void setKeyName(String keyName) { - this.keyName = keyName; - } - - /** - * Returns the MD5 Hash for the data of this key. - * - * @return String MD5 - */ - public String getMd5hash() { - return md5hash; - } - - /** - * Sets the MD5 value of this key. - * - * @param md5hash Md5 of this file - */ - public void setMd5hash(String md5hash) { - this.md5hash = md5hash; - } - - /** - * Number of bytes stored in the data part of this key. - * - * @return long size of the data file - */ - public long getSize() { - return size; - } - - /** - * Sets the size of the data part of this key. - * - * @param size Size in long - */ - public void setSize(long size) { - this.size = size; - } - - /** - * Version of this key. - * - * @return returns the version of this key. - */ - public long getVersion() { - return version; - } - - /** - * Sets the version of this key. - * - * @param version - Version String - */ - public void setVersion(long version) { - this.version = version; - } - - /** - * Compares this object with the specified object for order. Returns a - * negative integer, zero, or a positive integer as this object is less - * than, equal to, or greater than the specified object. - * - * @param o the object to be compared. - * @return a negative integer, zero, or a positive integer as this object - * is less than, equal to, or greater than the specified object. - * @throws NullPointerException if the specified object is null - * @throws ClassCastException if the specified object's type prevents it - * from being compared to this object. - */ - @Override - public int compareTo(KeyInfo o) { - if (this.keyName.compareTo(o.getKeyName()) != 0) { - return this.keyName.compareTo(o.getKeyName()); - } - - if (this.getVersion() == o.getVersion()) { - return 0; - } - if (this.getVersion() < o.getVersion()) { - return -1; - } - return 1; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (o == null || getClass() != o.getClass()) { - return false; - } - - KeyInfo keyInfo = (KeyInfo) o; - - return new EqualsBuilder() - .append(version, keyInfo.version) - .append(keyName, keyInfo.keyName) - .isEquals(); - } - - @Override - public int hashCode() { - return new HashCodeBuilder(17, 37) - .append(version) - .append(keyName) - .toHashCode(); - } - - /** - * Parse a string to return KeyInfo Object. - * - * @param jsonString Json String - * @return keyInfo - * @throws IOException - */ - public static KeyInfo parse(String jsonString) throws IOException { - return READER.readValue(jsonString); - } - -} \ No newline at end of file diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/response/KeyInfoDetails.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/response/KeyInfoDetails.java deleted file mode 100644 index 98506f06a89..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/response/KeyInfoDetails.java +++ /dev/null @@ -1,107 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client.rest.response; - -import java.io.IOException; -import java.util.List; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ObjectReader; -import org.apache.commons.lang3.builder.EqualsBuilder; -import org.apache.commons.lang3.builder.HashCodeBuilder; - -/** - * KeyInfoDetails class is used for parsing json response - * when KeyInfoDetails Call is made. - */ -public class KeyInfoDetails extends KeyInfo { - - private static final ObjectReader READER = - new ObjectMapper().readerFor(KeyInfoDetails.class); - - /** - * a list of Map which maps localID to ContainerID - * to specify replica locations. - */ - private List keyLocations; - - /** - * Constructor needed for json serialization. - */ - public KeyInfoDetails() { - } - - /** - * Set details of key location. - * - * @param locations - details of key location - */ - public void setKeyLocation(List locations) { - this.keyLocations = locations; - } - - /** - * Returns details of key location. - * - * @return volumeName - */ - public List getKeyLocations() { - return keyLocations; - } - - /** - * Parse a string to return KeyInfoDetails Object. - * - * @param jsonString Json String - * @return KeyInfoDetails - * @throws IOException - */ - public static KeyInfoDetails parse(String jsonString) throws IOException { - return READER.readValue(jsonString); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (o == null || getClass() != o.getClass()) { - return false; - } - - KeyInfoDetails that = (KeyInfoDetails) o; - - return new EqualsBuilder() - .append(getVersion(), that.getVersion()) - .append(getKeyName(), that.getKeyName()) - .append(keyLocations, that.keyLocations) - .isEquals(); - } - - @Override - public int hashCode() { - return new HashCodeBuilder(21, 33) - .append(getVersion()) - .append(getKeyName()) - .append(keyLocations) - .toHashCode(); - } -} - diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/response/KeyLocation.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/response/KeyLocation.java deleted file mode 100644 index e5f46980ab1..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/response/KeyLocation.java +++ /dev/null @@ -1,89 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client.rest.response; - -/** - * KeyLocation class is used used for parsing json response - * when KeyInfoDetails Call is made. - */ -public class KeyLocation { - /** - * Which container this key stored. - */ - private long containerID; - /** - * Which block this key stored inside a container. - */ - private long localID; - /** - * Data length of this key replica. - */ - private long length; - /** - * Offset of this key. - */ - private long offset; - - /** - * Empty constructor for Json serialization. - */ - public KeyLocation() { - - } - - /** - * Constructs KeyLocation. - */ - public KeyLocation(long containerID, long localID, - long length, long offset) { - this.containerID = containerID; - this.localID = localID; - this.length = length; - this.offset = offset; - } - - /** - * Returns the containerID of this Key. - */ - public long getContainerID() { - return containerID; - } - - /** - * Returns the localID of this Key. - */ - public long getLocalID() { - return localID; - } - - /** - * Returns the length of this Key. - */ - public long getLength() { - return length; - } - - /** - * Returns the offset of this Key. - */ - public long getOffset() { - return offset; - } - -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/response/VolumeInfo.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/response/VolumeInfo.java deleted file mode 100644 index f98b56a6d32..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/response/VolumeInfo.java +++ /dev/null @@ -1,215 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client.rest.response; - -import java.io.IOException; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.hdds.client.OzoneQuota; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ObjectReader; - -/** - * VolumeInfo Class is used for parsing json response - * when VolumeInfo Call is made. - */ -@InterfaceAudience.Private -public class VolumeInfo implements Comparable { - - - private static final ObjectReader READER = - new ObjectMapper().readerFor(VolumeInfo.class); - - private VolumeOwner owner; - private OzoneQuota quota; - private String volumeName; - private String createdOn; - private String createdBy; - - - /** - * Constructor for VolumeInfo. - * - * @param volumeName - Name of the Volume - * @param createdOn _ Date String - * @param createdBy - Person who created it - */ - public VolumeInfo(String volumeName, String createdOn, - String createdBy) { - this.volumeName = volumeName; - this.createdOn = createdOn; - this.createdBy = createdBy; - } - - /** - * Constructor for VolumeInfo. - */ - public VolumeInfo() { - } - - /** - * gets the volume name. - * - * @return Volume Name - */ - public String getVolumeName() { - return volumeName; - } - - /** - * Sets the volume name. - * - * @param volumeName Volume Name - */ - public void setVolumeName(String volumeName) { - this.volumeName = volumeName; - } - - - /** - * Returns the name of the person who created this volume. - * - * @return Name of Admin who created this - */ - public String getCreatedBy() { - return createdBy; - } - - /** - * Sets the user name of the person who created this volume. - * - * @param createdBy UserName - */ - public void setCreatedBy(String createdBy) { - this.createdBy = createdBy; - } - - /** - * Gets the date on which this volume was created. - * - * @return Date String - */ - public String getCreatedOn() { - return createdOn; - } - - /** - * Sets the date string. - * - * @param createdOn Date String - */ - public void setCreatedOn(String createdOn) { - this.createdOn = createdOn; - } - - /** - * Returns the owner info. - * - * @return OwnerInfo - */ - public VolumeOwner getOwner() { - return owner; - } - - /** - * Sets the owner. - * - * @param owner OwnerInfo - */ - public void setOwner(VolumeOwner owner) { - this.owner = owner; - } - - /** - * Returns the quota information on a volume. - * - * @return Quota - */ - public OzoneQuota getQuota() { - return quota; - } - - /** - * Sets the quota info. - * - * @param quota Quota Info - */ - public void setQuota(OzoneQuota quota) { - this.quota = quota; - } - - /** - * Comparable Interface. - * @param o VolumeInfo Object. - * @return Result of comparison - */ - @Override - public int compareTo(VolumeInfo o) { - return this.volumeName.compareTo(o.getVolumeName()); - } - - /** - * Returns VolumeInfo class from json string. - * - * @param data Json String - * - * @return VolumeInfo - * - * @throws IOException - */ - public static VolumeInfo parse(String data) throws IOException { - return READER.readValue(data); - } - - /** - * Indicates whether some other object is "equal to" this one. - * - * @param obj the reference object with which to compare. - * - * @return {@code true} if this object is the same as the obj - * argument; {@code false} otherwise. - */ - @Override - public boolean equals(Object obj) { - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - VolumeInfo otherInfo = (VolumeInfo) obj; - return otherInfo.getVolumeName().equals(this.getVolumeName()); - } - - /** - * Returns a hash code value for the object. This method is - * supported for the benefit of hash tables such as those provided by - * HashMap. - * @return a hash code value for this object. - * - * @see Object#equals(Object) - * @see System#identityHashCode - */ - @Override - public int hashCode() { - return getVolumeName().hashCode(); - } - -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/response/VolumeOwner.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/response/VolumeOwner.java deleted file mode 100644 index d4dbad4cbf6..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/response/VolumeOwner.java +++ /dev/null @@ -1,61 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.client.rest.response; - -import org.apache.hadoop.classification.InterfaceAudience; - -import com.fasterxml.jackson.annotation.JsonInclude; - -/** - * Volume Owner represents the owner of a volume. - * - * This is a class instead of a string since we might need to extend this class - * to support other forms of authentication. - */ -@InterfaceAudience.Private -public class VolumeOwner { - @JsonInclude(JsonInclude.Include.NON_NULL) - private String name; - - /** - * Constructor for VolumeOwner. - * - * @param name name of the User - */ - public VolumeOwner(String name) { - this.name = name; - } - - /** - * Constructs Volume Owner. - */ - public VolumeOwner() { - name = null; - } - - /** - * Returns the user name. - * - * @return Name - */ - public String getName() { - return name; - } - -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/response/package-info.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/response/package-info.java deleted file mode 100644 index 432b029b6fb..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/client/rest/response/package-info.java +++ /dev/null @@ -1,24 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.hadoop.ozone.client.rest.response; - -/** - * This package contains class for ozone rest client library. - */ \ No newline at end of file diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/freon/OzoneGetConf.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/freon/OzoneGetConf.java deleted file mode 100644 index ffbca6a2b5d..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/freon/OzoneGetConf.java +++ /dev/null @@ -1,269 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.freon; - -import java.io.IOException; -import java.io.PrintStream; -import java.net.InetSocketAddress; -import java.security.PrivilegedExceptionAction; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import org.apache.hadoop.HadoopIllegalArgumentException; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.conf.Configured; -import org.apache.hadoop.hdfs.DFSUtil; -import org.apache.hadoop.hdfs.HdfsConfiguration; -import org.apache.hadoop.hdds.HddsUtils; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.ozone.OmUtils; -import org.apache.hadoop.security.SecurityUtil; -import org.apache.hadoop.util.StringUtils; -import org.apache.hadoop.util.Tool; -import org.apache.hadoop.util.ToolRunner; - -/** - * CLI utility to print out ozone related configuration. - */ -public class OzoneGetConf extends Configured implements Tool { - - private static final String DESCRIPTION = "ozone getconf is utility for " - + "getting configuration information from the config file.\n"; - - enum Command { - INCLUDE_FILE("-includeFile", - "gets the include file path that defines the datanodes " + - "that can join the cluster."), - EXCLUDE_FILE("-excludeFile", - "gets the exclude file path that defines the datanodes " + - "that need to decommissioned."), - OZONEMANAGER("-ozonemanagers", - "gets list of Ozone Manager nodes in the cluster"), - STORAGECONTAINERMANAGER("-storagecontainermanagers", - "gets list of ozone storage container manager nodes in the cluster"), - CONFKEY("-confKey [key]", "gets a specific key from the configuration"); - - private static final Map HANDLERS; - - static { - HANDLERS = new HashMap(); - HANDLERS.put(StringUtils.toLowerCase(OZONEMANAGER.getName()), - new OzoneManagersCommandHandler()); - HANDLERS.put(StringUtils.toLowerCase(STORAGECONTAINERMANAGER.getName()), - new StorageContainerManagersCommandHandler()); - HANDLERS.put(StringUtils.toLowerCase(CONFKEY.getName()), - new PrintConfKeyCommandHandler()); - } - - private final String cmd; - private final String description; - - Command(String cmd, String description) { - this.cmd = cmd; - this.description = description; - } - - public String getName() { - return cmd.split(" ")[0]; - } - - public String getUsage() { - return cmd; - } - - public String getDescription() { - return description; - } - - public static OzoneGetConf.CommandHandler getHandler(String cmd) { - return HANDLERS.get(StringUtils.toLowerCase(cmd)); - } - } - - static final String USAGE; - static { - HdfsConfiguration.init(); - - /* Initialize USAGE based on Command values */ - StringBuilder usage = new StringBuilder(DESCRIPTION); - usage.append("\nozone getconf \n"); - for (OzoneGetConf.Command cmd : OzoneGetConf.Command.values()) { - usage.append("\t[" + cmd.getUsage() + "]\t\t\t" + cmd.getDescription() - + "\n"); - } - USAGE = usage.toString(); - } - - /** - * Handler to return value for key corresponding to the - * {@link OzoneGetConf.Command}. - */ - static class CommandHandler { - protected String key; // Configuration key to lookup - - CommandHandler() { - this(null); - } - - CommandHandler(String key) { - this.key = key; - } - - final int doWork(OzoneGetConf tool, String[] args) { - try { - checkArgs(args); - - return doWorkInternal(tool, args); - } catch (Exception e) { - tool.printError(e.getMessage()); - } - return -1; - } - - protected void checkArgs(String[] args) { - if (args.length > 0) { - throw new HadoopIllegalArgumentException( - "Did not expect argument: " + args[0]); - } - } - - - /** Method to be overridden by sub classes for specific behavior. */ - int doWorkInternal(OzoneGetConf tool, String[] args) throws Exception { - - String value = tool.getConf().getTrimmed(key); - if (value != null) { - tool.printOut(value); - return 0; - } - tool.printError("Configuration " + key + " is missing."); - return -1; - } - } - - static class PrintConfKeyCommandHandler extends OzoneGetConf.CommandHandler { - @Override - protected void checkArgs(String[] args) { - if (args.length != 1) { - throw new HadoopIllegalArgumentException( - "usage: " + OzoneGetConf.Command.CONFKEY.getUsage()); - } - } - - @Override - int doWorkInternal(OzoneGetConf tool, String[] args) throws Exception { - this.key = args[0]; - return super.doWorkInternal(tool, args); - } - } - - private final PrintStream out; // Stream for printing command output - private final PrintStream err; // Stream for printing error - - protected OzoneGetConf(Configuration conf) { - this(conf, System.out, System.err); - } - - protected OzoneGetConf(Configuration conf, PrintStream out, PrintStream err) { - super(conf); - this.out = out; - this.err = err; - } - - void printError(String message) { - err.println(message); - } - - void printOut(String message) { - out.println(message); - } - - private void printUsage() { - printError(USAGE); - } - - /** - * Main method that runs the tool for given arguments. - * @param args arguments - * @return return status of the command - */ - private int doWork(String[] args) { - if (args.length >= 1) { - OzoneGetConf.CommandHandler handler = - OzoneGetConf.Command.getHandler(args[0]); - if (handler != null) { - return handler.doWork(this, Arrays.copyOfRange(args, 1, args.length)); - } - } - printUsage(); - return -1; - } - - @Override - public int run(final String[] args) throws Exception { - return SecurityUtil.doAsCurrentUser( - new PrivilegedExceptionAction() { - @Override - public Integer run() throws Exception { - return doWork(args); - } - }); - } - - /** - * Handler for {@link Command#STORAGECONTAINERMANAGER}. - */ - static class StorageContainerManagersCommandHandler extends CommandHandler { - - @Override - public int doWorkInternal(OzoneGetConf tool, String[] args) - throws IOException { - Collection addresses = HddsUtils - .getSCMAddresses(tool.getConf()); - - for (InetSocketAddress addr : addresses) { - tool.printOut(addr.getHostName()); - } - return 0; - } - } - - /** - * Handler for {@link Command#OZONEMANAGER}. - */ - static class OzoneManagersCommandHandler extends CommandHandler { - @Override - public int doWorkInternal(OzoneGetConf tool, String[] args) - throws IOException { - tool.printOut(OmUtils.getOmAddress(tool.getConf()).getHostName()); - return 0; - } - } - - public static void main(String[] args) throws Exception { - if (DFSUtil.parseHelpArgument(args, USAGE, System.out, true)) { - System.exit(0); - } - - Configuration conf = new Configuration(); - conf.addResource(new OzoneConfiguration()); - int res = ToolRunner.run(new OzoneGetConf(conf), args); - System.exit(res); - } -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/freon/package-info.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/freon/package-info.java deleted file mode 100644 index 150c64e7d96..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/freon/package-info.java +++ /dev/null @@ -1,21 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.freon; -/** - * Classes related to Ozone tools. - */ diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/OMConfigKeys.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/OMConfigKeys.java deleted file mode 100644 index b9ca2966311..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/OMConfigKeys.java +++ /dev/null @@ -1,81 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.apache.hadoop.ozone.om; - -import org.apache.hadoop.ozone.OzoneAcl; -/** - * Ozone Manager Constants. - */ -public final class OMConfigKeys { - /** - * Never constructed. - */ - private OMConfigKeys() { - } - - - public static final String OZONE_OM_HANDLER_COUNT_KEY = - "ozone.om.handler.count.key"; - public static final int OZONE_OM_HANDLER_COUNT_DEFAULT = 20; - - public static final String OZONE_OM_ADDRESS_KEY = - "ozone.om.address"; - public static final String OZONE_OM_BIND_HOST_DEFAULT = - "0.0.0.0"; - public static final int OZONE_OM_PORT_DEFAULT = 9862; - - public static final String OZONE_OM_HTTP_ENABLED_KEY = - "ozone.om.http.enabled"; - public static final String OZONE_OM_HTTP_BIND_HOST_KEY = - "ozone.om.http-bind-host"; - public static final String OZONE_OM_HTTPS_BIND_HOST_KEY = - "ozone.om.https-bind-host"; - public static final String OZONE_OM_HTTP_ADDRESS_KEY = - "ozone.om.http-address"; - public static final String OZONE_OM_HTTPS_ADDRESS_KEY = - "ozone.om.https-address"; - public static final String OZONE_OM_KEYTAB_FILE = - "ozone.om.keytab.file"; - public static final String OZONE_OM_HTTP_BIND_HOST_DEFAULT = "0.0.0.0"; - public static final int OZONE_OM_HTTP_BIND_PORT_DEFAULT = 9874; - public static final int OZONE_OM_HTTPS_BIND_PORT_DEFAULT = 9875; - - // LevelDB cache file uses an off-heap cache in LevelDB of 128 MB. - public static final String OZONE_OM_DB_CACHE_SIZE_MB = - "ozone.om.db.cache.size.mb"; - public static final int OZONE_OM_DB_CACHE_SIZE_DEFAULT = 128; - - public static final String OZONE_OM_USER_MAX_VOLUME = - "ozone.om.user.max.volume"; - public static final int OZONE_OM_USER_MAX_VOLUME_DEFAULT = 1024; - - // OM Default user/group permissions - public static final String OZONE_OM_USER_RIGHTS = - "ozone.om.user.rights"; - public static final OzoneAcl.OzoneACLRights OZONE_OM_USER_RIGHTS_DEFAULT = - OzoneAcl.OzoneACLRights.READ_WRITE; - - public static final String OZONE_OM_GROUP_RIGHTS = - "ozone.om.group.rights"; - public static final OzoneAcl.OzoneACLRights OZONE_OM_GROUP_RIGHTS_DEFAULT = - OzoneAcl.OzoneACLRights.READ_WRITE; - - public static final String OZONE_KEY_DELETING_LIMIT_PER_TASK = - "ozone.key.deleting.limit.per.task"; - public static final int OZONE_KEY_DELETING_LIMIT_PER_TASK_DEFAULT = 1000; -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmBucketArgs.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmBucketArgs.java deleted file mode 100644 index 1bd258e7429..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmBucketArgs.java +++ /dev/null @@ -1,256 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.om.helpers; - -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.fs.StorageType; -import org.apache.hadoop.hdfs.protocolPB.PBHelperClient; -import org.apache.hadoop.ozone.OzoneAcl; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.audit.Auditable; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.BucketArgs; -import org.apache.hadoop.ozone.protocolPB.OMPBHelper; - -/** - * A class that encapsulates Bucket Arguments. - */ -public final class OmBucketArgs implements Auditable { - /** - * Name of the volume in which the bucket belongs to. - */ - private final String volumeName; - /** - * Name of the bucket. - */ - private final String bucketName; - /** - * ACL's that are to be added for the bucket. - */ - private List addAcls; - /** - * ACL's that are to be removed from the bucket. - */ - private List removeAcls; - /** - * Bucket Version flag. - */ - private Boolean isVersionEnabled; - /** - * Type of storage to be used for this bucket. - * [RAM_DISK, SSD, DISK, ARCHIVE] - */ - private StorageType storageType; - - /** - * Private constructor, constructed via builder. - * @param volumeName - Volume name. - * @param bucketName - Bucket name. - * @param addAcls - ACL's to be added. - * @param removeAcls - ACL's to be removed. - * @param isVersionEnabled - Bucket version flag. - * @param storageType - Storage type to be used. - */ - private OmBucketArgs(String volumeName, String bucketName, - List addAcls, List removeAcls, - Boolean isVersionEnabled, StorageType storageType) { - this.volumeName = volumeName; - this.bucketName = bucketName; - this.addAcls = addAcls; - this.removeAcls = removeAcls; - this.isVersionEnabled = isVersionEnabled; - this.storageType = storageType; - } - - /** - * Returns the Volume Name. - * @return String. - */ - public String getVolumeName() { - return volumeName; - } - - /** - * Returns the Bucket Name. - * @return String - */ - public String getBucketName() { - return bucketName; - } - - /** - * Returns the ACL's that are to be added. - * @return List - */ - public List getAddAcls() { - return addAcls; - } - - /** - * Returns the ACL's that are to be removed. - * @return List - */ - public List getRemoveAcls() { - return removeAcls; - } - - /** - * Returns true if bucket version is enabled, else false. - * @return isVersionEnabled - */ - public Boolean getIsVersionEnabled() { - return isVersionEnabled; - } - - /** - * Returns the type of storage to be used. - * @return StorageType - */ - public StorageType getStorageType() { - return storageType; - } - - /** - * Returns new builder class that builds a OmBucketArgs. - * - * @return Builder - */ - public static Builder newBuilder() { - return new Builder(); - } - - @Override - public Map toAuditMap() { - Map auditMap = new LinkedHashMap<>(); - auditMap.put(OzoneConsts.VOLUME, this.volumeName); - auditMap.put(OzoneConsts.BUCKET, this.bucketName); - if(this.addAcls != null){ - auditMap.put(OzoneConsts.ADD_ACLS, this.addAcls.toString()); - } - if(this.removeAcls != null){ - auditMap.put(OzoneConsts.REMOVE_ACLS, this.removeAcls.toString()); - } - auditMap.put(OzoneConsts.IS_VERSION_ENABLED, - String.valueOf(this.isVersionEnabled)); - if(this.storageType != null){ - auditMap.put(OzoneConsts.STORAGE_TYPE, this.storageType.name()); - } - return auditMap; - } - - /** - * Builder for OmBucketArgs. - */ - public static class Builder { - private String volumeName; - private String bucketName; - private List addAcls; - private List removeAcls; - private Boolean isVersionEnabled; - private StorageType storageType; - - public Builder setVolumeName(String volume) { - this.volumeName = volume; - return this; - } - - public Builder setBucketName(String bucket) { - this.bucketName = bucket; - return this; - } - - public Builder setAddAcls(List acls) { - this.addAcls = acls; - return this; - } - - public Builder setRemoveAcls(List acls) { - this.removeAcls = acls; - return this; - } - - public Builder setIsVersionEnabled(Boolean versionFlag) { - this.isVersionEnabled = versionFlag; - return this; - } - - public Builder setStorageType(StorageType storage) { - this.storageType = storage; - return this; - } - - /** - * Constructs the OmBucketArgs. - * @return instance of OmBucketArgs. - */ - public OmBucketArgs build() { - Preconditions.checkNotNull(volumeName); - Preconditions.checkNotNull(bucketName); - return new OmBucketArgs(volumeName, bucketName, addAcls, - removeAcls, isVersionEnabled, storageType); - } - } - - /** - * Creates BucketArgs protobuf from OmBucketArgs. - */ - public BucketArgs getProtobuf() { - BucketArgs.Builder builder = BucketArgs.newBuilder(); - builder.setVolumeName(volumeName) - .setBucketName(bucketName); - if(addAcls != null && !addAcls.isEmpty()) { - builder.addAllAddAcls(addAcls.stream().map( - OMPBHelper::convertOzoneAcl).collect(Collectors.toList())); - } - if(removeAcls != null && !removeAcls.isEmpty()) { - builder.addAllRemoveAcls(removeAcls.stream().map( - OMPBHelper::convertOzoneAcl).collect(Collectors.toList())); - } - if(isVersionEnabled != null) { - builder.setIsVersionEnabled(isVersionEnabled); - } - if(storageType != null) { - builder.setStorageType( - PBHelperClient.convertStorageType(storageType)); - } - return builder.build(); - } - - /** - * Parses BucketInfo protobuf and creates OmBucketArgs. - * @param bucketArgs - * @return instance of OmBucketArgs - */ - public static OmBucketArgs getFromProtobuf(BucketArgs bucketArgs) { - return new OmBucketArgs(bucketArgs.getVolumeName(), - bucketArgs.getBucketName(), - bucketArgs.getAddAclsList().stream().map( - OMPBHelper::convertOzoneAcl).collect(Collectors.toList()), - bucketArgs.getRemoveAclsList().stream().map( - OMPBHelper::convertOzoneAcl).collect(Collectors.toList()), - bucketArgs.hasIsVersionEnabled() ? - bucketArgs.getIsVersionEnabled() : null, - bucketArgs.hasStorageType() ? PBHelperClient.convertStorageType( - bucketArgs.getStorageType()) : null); - } -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmBucketInfo.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmBucketInfo.java deleted file mode 100644 index 5199ce3b58f..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmBucketInfo.java +++ /dev/null @@ -1,254 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.om.helpers; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.fs.StorageType; -import org.apache.hadoop.hdfs.protocolPB.PBHelperClient; -import org.apache.hadoop.ozone.OzoneAcl; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.audit.Auditable; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.BucketInfo; -import org.apache.hadoop.ozone.protocolPB.OMPBHelper; - -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * A class that encapsulates Bucket Info. - */ -public final class OmBucketInfo implements Auditable { - /** - * Name of the volume in which the bucket belongs to. - */ - private final String volumeName; - /** - * Name of the bucket. - */ - private final String bucketName; - /** - * ACL Information. - */ - private List acls; - /** - * Bucket Version flag. - */ - private Boolean isVersionEnabled; - /** - * Type of storage to be used for this bucket. - * [RAM_DISK, SSD, DISK, ARCHIVE] - */ - private StorageType storageType; - /** - * Creation time of bucket. - */ - private final long creationTime; - - /** - * Private constructor, constructed via builder. - * @param volumeName - Volume name. - * @param bucketName - Bucket name. - * @param acls - list of ACLs. - * @param isVersionEnabled - Bucket version flag. - * @param storageType - Storage type to be used. - * @param creationTime - Bucket creation time. - */ - private OmBucketInfo(String volumeName, String bucketName, - List acls, boolean isVersionEnabled, - StorageType storageType, long creationTime) { - this.volumeName = volumeName; - this.bucketName = bucketName; - this.acls = acls; - this.isVersionEnabled = isVersionEnabled; - this.storageType = storageType; - this.creationTime = creationTime; - } - - /** - * Returns the Volume Name. - * @return String. - */ - public String getVolumeName() { - return volumeName; - } - - /** - * Returns the Bucket Name. - * @return String - */ - public String getBucketName() { - return bucketName; - } - - /** - * Returns the ACL's associated with this bucket. - * @return List - */ - public List getAcls() { - return acls; - } - - /** - * Returns true if bucket version is enabled, else false. - * @return isVersionEnabled - */ - public boolean getIsVersionEnabled() { - return isVersionEnabled; - } - - /** - * Returns the type of storage to be used. - * @return StorageType - */ - public StorageType getStorageType() { - return storageType; - } - - /** - * Returns creation time. - * - * @return long - */ - public long getCreationTime() { - return creationTime; - } - - /** - * Returns new builder class that builds a OmBucketInfo. - * - * @return Builder - */ - public static Builder newBuilder() { - return new Builder(); - } - - @Override - public Map toAuditMap() { - Map auditMap = new LinkedHashMap<>(); - auditMap.put(OzoneConsts.VOLUME, this.volumeName); - auditMap.put(OzoneConsts.BUCKET, this.bucketName); - auditMap.put(OzoneConsts.ACLS, - (this.acls != null) ? this.acls.toString() : null); - auditMap.put(OzoneConsts.IS_VERSION_ENABLED, - String.valueOf(this.isVersionEnabled)); - auditMap.put(OzoneConsts.STORAGE_TYPE, - (this.storageType != null) ? this.storageType.name() : null); - auditMap.put(OzoneConsts.CREATION_TIME, String.valueOf(this.creationTime)); - return auditMap; - } - - /** - * Builder for OmBucketInfo. - */ - public static class Builder { - private String volumeName; - private String bucketName; - private List acls; - private Boolean isVersionEnabled; - private StorageType storageType; - private long creationTime; - - public Builder() { - //Default values - this.acls = new LinkedList<>(); - this.isVersionEnabled = false; - this.storageType = StorageType.DISK; - } - - public Builder setVolumeName(String volume) { - this.volumeName = volume; - return this; - } - - public Builder setBucketName(String bucket) { - this.bucketName = bucket; - return this; - } - - public Builder setAcls(List listOfAcls) { - this.acls = listOfAcls; - return this; - } - - public Builder setIsVersionEnabled(Boolean versionFlag) { - this.isVersionEnabled = versionFlag; - return this; - } - - public Builder setStorageType(StorageType storage) { - this.storageType = storage; - return this; - } - - public Builder setCreationTime(long createdOn) { - this.creationTime = createdOn; - return this; - } - - /** - * Constructs the OmBucketInfo. - * @return instance of OmBucketInfo. - */ - public OmBucketInfo build() { - Preconditions.checkNotNull(volumeName); - Preconditions.checkNotNull(bucketName); - Preconditions.checkNotNull(acls); - Preconditions.checkNotNull(isVersionEnabled); - Preconditions.checkNotNull(storageType); - - return new OmBucketInfo(volumeName, bucketName, acls, - isVersionEnabled, storageType, creationTime); - } - } - - /** - * Creates BucketInfo protobuf from OmBucketInfo. - */ - public BucketInfo getProtobuf() { - return BucketInfo.newBuilder() - .setVolumeName(volumeName) - .setBucketName(bucketName) - .addAllAcls(acls.stream().map( - OMPBHelper::convertOzoneAcl).collect(Collectors.toList())) - .setIsVersionEnabled(isVersionEnabled) - .setStorageType(PBHelperClient.convertStorageType( - storageType)) - .setCreationTime(creationTime) - .build(); - } - - /** - * Parses BucketInfo protobuf and creates OmBucketInfo. - * @param bucketInfo - * @return instance of OmBucketInfo - */ - public static OmBucketInfo getFromProtobuf(BucketInfo bucketInfo) { - return new OmBucketInfo( - bucketInfo.getVolumeName(), - bucketInfo.getBucketName(), - bucketInfo.getAclsList().stream().map( - OMPBHelper::convertOzoneAcl).collect(Collectors.toList()), - bucketInfo.getIsVersionEnabled(), - PBHelperClient.convertStorageType( - bucketInfo.getStorageType()), bucketInfo.getCreationTime()); - } -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmKeyArgs.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmKeyArgs.java deleted file mode 100644 index e56ad7f161b..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmKeyArgs.java +++ /dev/null @@ -1,167 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.om.helpers; -import com.google.common.annotations.VisibleForTesting; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationType; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationFactor; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.audit.Auditable; - -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -/** - * Args for key. Client use this to specify key's attributes on key creation - * (putKey()). - */ -public final class OmKeyArgs implements Auditable { - private final String volumeName; - private final String bucketName; - private final String keyName; - private long dataSize; - private final ReplicationType type; - private final ReplicationFactor factor; - private List locationInfoList; - - private OmKeyArgs(String volumeName, String bucketName, String keyName, - long dataSize, ReplicationType type, ReplicationFactor factor, - List locationInfoList) { - this.volumeName = volumeName; - this.bucketName = bucketName; - this.keyName = keyName; - this.dataSize = dataSize; - this.type = type; - this.factor = factor; - this.locationInfoList = locationInfoList; - } - - public ReplicationType getType() { - return type; - } - - public ReplicationFactor getFactor() { - return factor; - } - - public String getVolumeName() { - return volumeName; - } - - public String getBucketName() { - return bucketName; - } - - public String getKeyName() { - return keyName; - } - - public long getDataSize() { - return dataSize; - } - - public void setDataSize(long size) { - dataSize = size; - } - - public void setLocationInfoList(List locationInfoList) { - this.locationInfoList = locationInfoList; - } - - public List getLocationInfoList() { - return locationInfoList; - } - - @Override - public Map toAuditMap() { - Map auditMap = new LinkedHashMap<>(); - auditMap.put(OzoneConsts.VOLUME, this.volumeName); - auditMap.put(OzoneConsts.BUCKET, this.bucketName); - auditMap.put(OzoneConsts.KEY, this.keyName); - auditMap.put(OzoneConsts.DATA_SIZE, String.valueOf(this.dataSize)); - auditMap.put(OzoneConsts.REPLICATION_TYPE, - (this.type != null) ? this.type.name() : null); - auditMap.put(OzoneConsts.REPLICATION_FACTOR, - (this.factor != null) ? this.factor.name() : null); - auditMap.put(OzoneConsts.KEY_LOCATION_INFO, - (this.locationInfoList != null) ? locationInfoList.toString() : null); - return auditMap; - } - - @VisibleForTesting - public void addLocationInfo(OmKeyLocationInfo locationInfo) { - if (this.locationInfoList == null) { - locationInfoList = new ArrayList<>(); - } - locationInfoList.add(locationInfo); - } - - /** - * Builder class of OmKeyArgs. - */ - public static class Builder { - private String volumeName; - private String bucketName; - private String keyName; - private long dataSize; - private ReplicationType type; - private ReplicationFactor factor; - private List locationInfoList; - - public Builder setVolumeName(String volume) { - this.volumeName = volume; - return this; - } - - public Builder setBucketName(String bucket) { - this.bucketName = bucket; - return this; - } - - public Builder setKeyName(String key) { - this.keyName = key; - return this; - } - - public Builder setDataSize(long size) { - this.dataSize = size; - return this; - } - - public Builder setType(ReplicationType replicationType) { - this.type = replicationType; - return this; - } - - public Builder setFactor(ReplicationFactor replicationFactor) { - this.factor = replicationFactor; - return this; - } - - public Builder setLocationInfoList(List locationInfos) { - this.locationInfoList = locationInfos; - return this; - } - - public OmKeyArgs build() { - return new OmKeyArgs(volumeName, bucketName, keyName, dataSize, type, - factor, locationInfoList); - } - } -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmKeyInfo.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmKeyInfo.java deleted file mode 100644 index 50f4b17508a..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmKeyInfo.java +++ /dev/null @@ -1,303 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.om.helpers; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos; -import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.KeyInfo; -import org.apache.hadoop.util.Time; - -import java.io.IOException; -import java.util.List; -import java.util.stream.Collectors; - -/** - * Args for key block. The block instance for the key requested in putKey. - * This is returned from OM to client, and client use class to talk to - * datanode. Also, this is the metadata written to om.db on server side. - */ -public final class OmKeyInfo { - private final String volumeName; - private final String bucketName; - // name of key client specified - private String keyName; - private long dataSize; - private List keyLocationVersions; - private final long creationTime; - private long modificationTime; - private HddsProtos.ReplicationType type; - private HddsProtos.ReplicationFactor factor; - - private OmKeyInfo(String volumeName, String bucketName, String keyName, - List versions, long dataSize, - long creationTime, long modificationTime, HddsProtos.ReplicationType type, - HddsProtos.ReplicationFactor factor) { - this.volumeName = volumeName; - this.bucketName = bucketName; - this.keyName = keyName; - this.dataSize = dataSize; - // it is important that the versions are ordered from old to new. - // Do this sanity check when versions got loaded on creating OmKeyInfo. - // TODO : this is not necessary, here only because versioning is still a - // work in-progress, remove this following check when versioning is - // complete and prove correctly functioning - long currentVersion = -1; - for (OmKeyLocationInfoGroup version : versions) { - Preconditions.checkArgument( - currentVersion + 1 == version.getVersion()); - currentVersion = version.getVersion(); - } - this.keyLocationVersions = versions; - this.creationTime = creationTime; - this.modificationTime = modificationTime; - this.factor = factor; - this.type = type; - } - - public String getVolumeName() { - return volumeName; - } - - public String getBucketName() { - return bucketName; - } - - public HddsProtos.ReplicationType getType() { - return type; - } - - public HddsProtos.ReplicationFactor getFactor() { - return factor; - } - - public String getKeyName() { - return keyName; - } - - public void setKeyName(String keyName) { - this.keyName = keyName; - } - - public long getDataSize() { - return dataSize; - } - - public void setDataSize(long size) { - this.dataSize = size; - } - - public synchronized OmKeyLocationInfoGroup getLatestVersionLocations() { - return keyLocationVersions.size() == 0? null : - keyLocationVersions.get(keyLocationVersions.size() - 1); - } - - public List getKeyLocationVersions() { - return keyLocationVersions; - } - - public void updateModifcationTime() { - this.modificationTime = Time.monotonicNow(); - } - - /** - * updates the length of the each block in the list given. - * This will be called when the key is being committed to OzoneManager. - * - * @param locationInfoList list of locationInfo - * @throws IOException - */ - public void updateLocationInfoList(List locationInfoList) { - long latestVersion = getLatestVersionLocations().getVersion(); - OmKeyLocationInfoGroup keyLocationInfoGroup = getLatestVersionLocations(); - List currentList = - keyLocationInfoGroup.getLocationList(); - List latestVersionList = - keyLocationInfoGroup.getBlocksLatestVersionOnly(); - // Updates the latest locationList in the latest version only with - // given locationInfoList here. - // TODO : The original allocated list and the updated list here may vary - // as the containers on the Datanode on which the blocks were pre allocated - // might get closed. The diff of blocks between these two lists here - // need to be garbage collected in case the ozone client dies. - currentList.removeAll(latestVersionList); - // set each of the locationInfo object to the latest version - locationInfoList.stream().forEach(omKeyLocationInfo -> omKeyLocationInfo - .setCreateVersion(latestVersion)); - currentList.addAll(locationInfoList); - } - - /** - * Append a set of blocks to the latest version. Note that these blocks are - * part of the latest version, not a new version. - * - * @param newLocationList the list of new blocks to be added. - * @throws IOException - */ - public synchronized void appendNewBlocks( - List newLocationList) throws IOException { - if (keyLocationVersions.size() == 0) { - throw new IOException("Appending new block, but no version exist"); - } - OmKeyLocationInfoGroup currentLatestVersion = - keyLocationVersions.get(keyLocationVersions.size() - 1); - currentLatestVersion.appendNewBlocks(newLocationList); - setModificationTime(Time.now()); - } - - /** - * Add a new set of blocks. The new blocks will be added as appending a new - * version to the all version list. - * - * @param newLocationList the list of new blocks to be added. - * @throws IOException - */ - public synchronized long addNewVersion( - List newLocationList) throws IOException { - long latestVersionNum; - if (keyLocationVersions.size() == 0) { - // no version exist, these blocks are the very first version. - keyLocationVersions.add(new OmKeyLocationInfoGroup(0, newLocationList)); - latestVersionNum = 0; - } else { - // it is important that the new version are always at the tail of the list - OmKeyLocationInfoGroup currentLatestVersion = - keyLocationVersions.get(keyLocationVersions.size() - 1); - // the new version is created based on the current latest version - OmKeyLocationInfoGroup newVersion = - currentLatestVersion.generateNextVersion(newLocationList); - keyLocationVersions.add(newVersion); - latestVersionNum = newVersion.getVersion(); - } - setModificationTime(Time.now()); - return latestVersionNum; - } - - public long getCreationTime() { - return creationTime; - } - - public long getModificationTime() { - return modificationTime; - } - - public void setModificationTime(long modificationTime) { - this.modificationTime = modificationTime; - } - - /** - * Builder of OmKeyInfo. - */ - public static class Builder { - private String volumeName; - private String bucketName; - private String keyName; - private long dataSize; - private List omKeyLocationInfoGroups; - private long creationTime; - private long modificationTime; - private HddsProtos.ReplicationType type; - private HddsProtos.ReplicationFactor factor; - - public Builder setVolumeName(String volume) { - this.volumeName = volume; - return this; - } - - public Builder setBucketName(String bucket) { - this.bucketName = bucket; - return this; - } - - public Builder setKeyName(String key) { - this.keyName = key; - return this; - } - - public Builder setOmKeyLocationInfos( - List omKeyLocationInfoList) { - this.omKeyLocationInfoGroups = omKeyLocationInfoList; - return this; - } - - public Builder setDataSize(long size) { - this.dataSize = size; - return this; - } - - public Builder setCreationTime(long crTime) { - this.creationTime = crTime; - return this; - } - - public Builder setModificationTime(long mTime) { - this.modificationTime = mTime; - return this; - } - - public Builder setReplicationFactor(HddsProtos.ReplicationFactor factor) { - this.factor = factor; - return this; - } - - public Builder setReplicationType(HddsProtos.ReplicationType type) { - this.type = type; - return this; - } - - public OmKeyInfo build() { - return new OmKeyInfo( - volumeName, bucketName, keyName, omKeyLocationInfoGroups, - dataSize, creationTime, modificationTime, type, factor); - } - } - - public KeyInfo getProtobuf() { - long latestVersion = keyLocationVersions.size() == 0 ? -1 : - keyLocationVersions.get(keyLocationVersions.size() - 1).getVersion(); - return KeyInfo.newBuilder() - .setVolumeName(volumeName) - .setBucketName(bucketName) - .setKeyName(keyName) - .setDataSize(dataSize) - .setFactor(factor) - .setType(type) - .addAllKeyLocationList(keyLocationVersions.stream() - .map(OmKeyLocationInfoGroup::getProtobuf) - .collect(Collectors.toList())) - .setLatestVersion(latestVersion) - .setCreationTime(creationTime) - .setModificationTime(modificationTime) - .build(); - } - - public static OmKeyInfo getFromProtobuf(KeyInfo keyInfo) { - return new OmKeyInfo( - keyInfo.getVolumeName(), - keyInfo.getBucketName(), - keyInfo.getKeyName(), - keyInfo.getKeyLocationListList().stream() - .map(OmKeyLocationInfoGroup::getFromProtobuf) - .collect(Collectors.toList()), - keyInfo.getDataSize(), - keyInfo.getCreationTime(), - keyInfo.getModificationTime(), - keyInfo.getType(), - keyInfo.getFactor()); - } - -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmKeyLocationInfo.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmKeyLocationInfo.java deleted file mode 100644 index 79b3c82b2dc..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmKeyLocationInfo.java +++ /dev/null @@ -1,143 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.om.helpers; - -import org.apache.hadoop.hdds.client.BlockID; -import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.KeyLocation; - -/** - * One key can be too huge to fit in one container. In which case it gets split - * into a number of subkeys. This class represents one such subkey instance. - */ -public final class OmKeyLocationInfo { - private final BlockID blockID; - private final boolean shouldCreateContainer; - // the id of this subkey in all the subkeys. - private long length; - private final long offset; - // the version number indicating when this block was added - private long createVersion; - - private OmKeyLocationInfo(BlockID blockID, boolean shouldCreateContainer, - long length, long offset) { - this.blockID = blockID; - this.shouldCreateContainer = shouldCreateContainer; - this.length = length; - this.offset = offset; - } - - public void setCreateVersion(long version) { - createVersion = version; - } - - public long getCreateVersion() { - return createVersion; - } - - public BlockID getBlockID() { - return blockID; - } - - public long getContainerID() { - return blockID.getContainerID(); - } - - public long getLocalID() { - return blockID.getLocalID(); - } - - public boolean getShouldCreateContainer() { - return shouldCreateContainer; - } - - public long getLength() { - return length; - } - - public void setLength(long length) { - this.length = length; - } - - public long getOffset() { - return offset; - } - - /** - * Builder of OmKeyLocationInfo. - */ - public static class Builder { - private BlockID blockID; - private boolean shouldCreateContainer; - private long length; - private long offset; - - public Builder setBlockID(BlockID blockId) { - this.blockID = blockId; - return this; - } - - public Builder setShouldCreateContainer(boolean create) { - this.shouldCreateContainer = create; - return this; - } - - public Builder setLength(long len) { - this.length = len; - return this; - } - - public Builder setOffset(long off) { - this.offset = off; - return this; - } - - public OmKeyLocationInfo build() { - return new OmKeyLocationInfo(blockID, - shouldCreateContainer, length, offset); - } - } - - public KeyLocation getProtobuf() { - return KeyLocation.newBuilder() - .setBlockID(blockID.getProtobuf()) - .setShouldCreateContainer(shouldCreateContainer) - .setLength(length) - .setOffset(offset) - .setCreateVersion(createVersion) - .build(); - } - - public static OmKeyLocationInfo getFromProtobuf(KeyLocation keyLocation) { - OmKeyLocationInfo info = new OmKeyLocationInfo( - BlockID.getFromProtobuf(keyLocation.getBlockID()), - keyLocation.getShouldCreateContainer(), - keyLocation.getLength(), - keyLocation.getOffset()); - info.setCreateVersion(keyLocation.getCreateVersion()); - return info; - } - - @Override - public String toString() { - return "{blockID={containerID=" + blockID.getContainerID() + - ", localID=" + blockID.getLocalID() + "}" + - ", shouldCreateContainer=" + shouldCreateContainer + - ", length=" + length + - ", offset=" + offset + - ", createVersion=" + createVersion + '}'; - } -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmKeyLocationInfoGroup.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmKeyLocationInfoGroup.java deleted file mode 100644 index 8bdcee3803c..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmKeyLocationInfoGroup.java +++ /dev/null @@ -1,118 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS,WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.apache.hadoop.ozone.om.helpers; - -import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.KeyLocationList; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -/** - * A list of key locations. This class represents one single version of the - * blocks of a key. - */ -public class OmKeyLocationInfoGroup { - private final long version; - private final List locationList; - - public OmKeyLocationInfoGroup(long version, - List locations) { - this.version = version; - this.locationList = locations; - } - - /** - * Return only the blocks that are created in the most recent version. - * - * @return the list of blocks that are created in the latest version. - */ - public List getBlocksLatestVersionOnly() { - List list = new ArrayList<>(); - locationList.stream().filter(x -> x.getCreateVersion() == version) - .forEach(list::add); - return list; - } - - public long getVersion() { - return version; - } - - public List getLocationList() { - return locationList; - } - - public KeyLocationList getProtobuf() { - return KeyLocationList.newBuilder() - .setVersion(version) - .addAllKeyLocations( - locationList.stream().map(OmKeyLocationInfo::getProtobuf) - .collect(Collectors.toList())) - .build(); - } - - public static OmKeyLocationInfoGroup getFromProtobuf( - KeyLocationList keyLocationList) { - return new OmKeyLocationInfoGroup( - keyLocationList.getVersion(), - keyLocationList.getKeyLocationsList().stream() - .map(OmKeyLocationInfo::getFromProtobuf) - .collect(Collectors.toList())); - } - - /** - * Given a new block location, generate a new version list based upon this - * one. - * - * @param newLocationList a list of new location to be added. - * @return - */ - OmKeyLocationInfoGroup generateNextVersion( - List newLocationList) throws IOException { - // TODO : revisit if we can do this method more efficiently - // one potential inefficiency here is that later version always include - // older ones. e.g. v1 has B1, then v2, v3...will all have B1 and only add - // more - List newList = new ArrayList<>(); - newList.addAll(locationList); - for (OmKeyLocationInfo newInfo : newLocationList) { - // all these new blocks will have addVersion of current version + 1 - newInfo.setCreateVersion(version + 1); - newList.add(newInfo); - } - return new OmKeyLocationInfoGroup(version + 1, newList); - } - - void appendNewBlocks(List newLocationList) - throws IOException { - for (OmKeyLocationInfo info : newLocationList) { - info.setCreateVersion(version); - locationList.add(info); - } - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("version:").append(version).append(" "); - for (OmKeyLocationInfo kli : locationList) { - sb.append(kli.getLocalID()).append(" || "); - } - return sb.toString(); - } -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmOzoneAclMap.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmOzoneAclMap.java deleted file mode 100644 index de75a05e9d9..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmOzoneAclMap.java +++ /dev/null @@ -1,110 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.om.helpers; - -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.OzoneAclInfo; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.OzoneAclInfo.OzoneAclRights; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.OzoneAclInfo.OzoneAclType; - -import java.util.List; -import java.util.LinkedList; -import java.util.Map; -import java.util.ArrayList; -import java.util.HashMap; - -/** - * This helper class keeps a map of all user and their permissions. - */ -public class OmOzoneAclMap { - // per Acl Type user:rights map - private ArrayList> aclMaps; - - OmOzoneAclMap() { - aclMaps = new ArrayList<>(); - for (OzoneAclType aclType : OzoneAclType.values()) { - aclMaps.add(aclType.ordinal(), new HashMap<>()); - } - } - - private Map getMap(OzoneAclType type) { - return aclMaps.get(type.ordinal()); - } - - // For a given acl type and user, get the stored acl - private OzoneAclRights getAcl(OzoneAclType type, String user) { - return getMap(type).get(user); - } - - // Add a new acl to the map - public void addAcl(OzoneAclInfo acl) { - getMap(acl.getType()).put(acl.getName(), acl.getRights()); - } - - // for a given acl, check if the user has access rights - public boolean hasAccess(OzoneAclInfo acl) { - OzoneAclRights storedRights = getAcl(acl.getType(), acl.getName()); - if (storedRights != null) { - switch (acl.getRights()) { - case READ: - return (storedRights == OzoneAclRights.READ) - || (storedRights == OzoneAclRights.READ_WRITE); - case WRITE: - return (storedRights == OzoneAclRights.WRITE) - || (storedRights == OzoneAclRights.READ_WRITE); - case READ_WRITE: - return (storedRights == OzoneAclRights.READ_WRITE); - default: - return false; - } - } else { - return false; - } - } - - // Convert this map to OzoneAclInfo Protobuf List - public List ozoneAclGetProtobuf() { - List aclList = new LinkedList<>(); - for (OzoneAclType type: OzoneAclType.values()) { - for (Map.Entry entry : - aclMaps.get(type.ordinal()).entrySet()) { - OzoneAclInfo aclInfo = OzoneAclInfo.newBuilder() - .setName(entry.getKey()) - .setType(type) - .setRights(entry.getValue()) - .build(); - aclList.add(aclInfo); - } - } - - return aclList; - } - - // Create map from list of OzoneAclInfos - public static OmOzoneAclMap ozoneAclGetFromProtobuf( - List aclList) { - OmOzoneAclMap aclMap = new OmOzoneAclMap(); - for (OzoneAclInfo acl : aclList) { - aclMap.addAcl(acl); - } - return aclMap; - } -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmVolumeArgs.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmVolumeArgs.java deleted file mode 100644 index 165d9aba783..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmVolumeArgs.java +++ /dev/null @@ -1,237 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.om.helpers; - -import com.google.common.base.Preconditions; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.audit.Auditable; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.OzoneAclInfo; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.VolumeInfo; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.KeyValue; - -import java.io.IOException; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - - -/** - * A class that encapsulates the OmVolumeArgs Args. - */ -public final class OmVolumeArgs implements Auditable{ - private final String adminName; - private final String ownerName; - private final String volume; - private final long creationTime; - private final long quotaInBytes; - private final Map keyValueMap; - private final OmOzoneAclMap aclMap; - - /** - * Private constructor, constructed via builder. - * @param adminName - Administrator's name. - * @param ownerName - Volume owner's name - * @param volume - volume name - * @param quotaInBytes - Volume Quota in bytes. - * @param keyValueMap - keyValue map. - * @param aclMap - User to access rights map. - * @param creationTime - Volume creation time. - */ - private OmVolumeArgs(String adminName, String ownerName, String volume, - long quotaInBytes, Map keyValueMap, - OmOzoneAclMap aclMap, long creationTime) { - this.adminName = adminName; - this.ownerName = ownerName; - this.volume = volume; - this.quotaInBytes = quotaInBytes; - this.keyValueMap = keyValueMap; - this.aclMap = aclMap; - this.creationTime = creationTime; - } - - /** - * Returns the Admin Name. - * @return String. - */ - public String getAdminName() { - return adminName; - } - - /** - * Returns the owner Name. - * @return String - */ - public String getOwnerName() { - return ownerName; - } - - /** - * Returns the volume Name. - * @return String - */ - public String getVolume() { - return volume; - } - - /** - * Returns creation time. - * @return long - */ - public long getCreationTime() { - return creationTime; - } - - /** - * Returns Quota in Bytes. - * @return long, Quota in bytes. - */ - public long getQuotaInBytes() { - return quotaInBytes; - } - - public Map getKeyValueMap() { - return keyValueMap; - } - - public OmOzoneAclMap getAclMap() { - return aclMap; - } - /** - * Returns new builder class that builds a OmVolumeArgs. - * - * @return Builder - */ - public static Builder newBuilder() { - return new Builder(); - } - - @Override - public Map toAuditMap() { - Map auditMap = new LinkedHashMap<>(); - auditMap.put(OzoneConsts.ADMIN, this.adminName); - auditMap.put(OzoneConsts.OWNER, this.ownerName); - auditMap.put(OzoneConsts.VOLUME, this.volume); - auditMap.put(OzoneConsts.CREATION_TIME, String.valueOf(this.creationTime)); - auditMap.put(OzoneConsts.QUOTA_IN_BYTES, String.valueOf(this.quotaInBytes)); - return auditMap; - } - - /** - * Builder for OmVolumeArgs. - */ - public static class Builder { - private String adminName; - private String ownerName; - private String volume; - private long creationTime; - private long quotaInBytes; - private Map keyValueMap; - private OmOzoneAclMap aclMap; - - /** - * Constructs a builder. - */ - public Builder() { - keyValueMap = new HashMap<>(); - aclMap = new OmOzoneAclMap(); - } - - public Builder setAdminName(String admin) { - this.adminName = admin; - return this; - } - - public Builder setOwnerName(String owner) { - this.ownerName = owner; - return this; - } - - public Builder setVolume(String volumeName) { - this.volume = volumeName; - return this; - } - - public Builder setCreationTime(long createdOn) { - this.creationTime = createdOn; - return this; - } - - public Builder setQuotaInBytes(long quota) { - this.quotaInBytes = quota; - return this; - } - - public Builder addMetadata(String key, String value) { - keyValueMap.put(key, value); // overwrite if present. - return this; - } - - public Builder addOzoneAcls(OzoneAclInfo acl) throws IOException { - aclMap.addAcl(acl); - return this; - } - - /** - * Constructs a CreateVolumeArgument. - * @return CreateVolumeArgs. - */ - public OmVolumeArgs build() { - Preconditions.checkNotNull(adminName); - Preconditions.checkNotNull(ownerName); - Preconditions.checkNotNull(volume); - return new OmVolumeArgs(adminName, ownerName, volume, quotaInBytes, - keyValueMap, aclMap, creationTime); - } - } - - public VolumeInfo getProtobuf() { - List metadataList = new LinkedList<>(); - for (Map.Entry entry : keyValueMap.entrySet()) { - metadataList.add(KeyValue.newBuilder().setKey(entry.getKey()). - setValue(entry.getValue()).build()); - } - List aclList = aclMap.ozoneAclGetProtobuf(); - - return VolumeInfo.newBuilder() - .setAdminName(adminName) - .setOwnerName(ownerName) - .setVolume(volume) - .setQuotaInBytes(quotaInBytes) - .addAllMetadata(metadataList) - .addAllVolumeAcls(aclList) - .setCreationTime(creationTime) - .build(); - } - - public static OmVolumeArgs getFromProtobuf(VolumeInfo volInfo) { - Map kvMap = volInfo.getMetadataList().stream() - .collect(Collectors.toMap(KeyValue::getKey, - KeyValue::getValue)); - OmOzoneAclMap aclMap = - OmOzoneAclMap.ozoneAclGetFromProtobuf(volInfo.getVolumeAclsList()); - - return new OmVolumeArgs(volInfo.getAdminName(), volInfo.getOwnerName(), - volInfo.getVolume(), volInfo.getQuotaInBytes(), kvMap, aclMap, - volInfo.getCreationTime()); - } -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OpenKeySession.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OpenKeySession.java deleted file mode 100644 index 11ee622494d..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OpenKeySession.java +++ /dev/null @@ -1,50 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.om.helpers; - -/** - * This class represents a open key "session". A session here means a key is - * opened by a specific client, the client sends the handler to server, such - * that servers can recognize this client, and thus know how to close the key. - */ -public class OpenKeySession { - private final long id; - private final OmKeyInfo keyInfo; - // the version of the key when it is being opened in this session. - // a block that has a create version equals to open version means it will - // be committed only when this open session is closed. - private long openVersion; - - public OpenKeySession(long id, OmKeyInfo info, long version) { - this.id = id; - this.keyInfo = info; - this.openVersion = version; - } - - public long getOpenVersion() { - return this.openVersion; - } - - public OmKeyInfo getKeyInfo() { - return keyInfo; - } - - public long getId() { - return id; - } -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/ServiceInfo.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/ServiceInfo.java deleted file mode 100644 index 9b03aefe1a8..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/ServiceInfo.java +++ /dev/null @@ -1,237 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.om.helpers; - - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ObjectReader; -import com.fasterxml.jackson.databind.ObjectWriter; -import com.google.common.base.Preconditions; -import org.apache.hadoop.ozone.client.rest.response.BucketInfo; -import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos; -import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos - .ServicePort; -import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeType; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * ServiceInfo holds the config details of Ozone services. - */ -public final class ServiceInfo { - - private static final ObjectReader READER = - new ObjectMapper().readerFor(ServiceInfo.class); - private static final ObjectWriter WRITER = - new ObjectMapper().writerWithDefaultPrettyPrinter(); - - /** - * Type of node/service. - */ - private NodeType nodeType; - /** - * Hostname of the node in which the service is running. - */ - private String hostname; - - /** - * List of ports the service listens to. - */ - private Map ports; - - /** - * Default constructor for JSON deserialization. - */ - public ServiceInfo() {} - - /** - * Constructs the ServiceInfo for the {@code nodeType}. - * @param nodeType type of node/service - * @param hostname hostname of the service - * @param portList list of ports the service listens to - */ - private ServiceInfo( - NodeType nodeType, String hostname, List portList) { - Preconditions.checkNotNull(nodeType); - Preconditions.checkNotNull(hostname); - this.nodeType = nodeType; - this.hostname = hostname; - this.ports = new HashMap<>(); - for (ServicePort port : portList) { - ports.put(port.getType(), port.getValue()); - } - } - - /** - * Returns the type of node/service. - * @return node type - */ - public NodeType getNodeType() { - return nodeType; - } - - /** - * Returns the hostname of the service. - * @return hostname - */ - public String getHostname() { - return hostname; - } - - /** - * Returns ServicePort.Type to port mappings. - * @return ports - */ - public Map getPorts() { - return ports; - } - - /** - * Returns the port for given type, null if the service doesn't support - * the type. - * - * @param type the type of port. - * ex: RPC, HTTP, HTTPS, etc.. - */ - @JsonIgnore - public int getPort(ServicePort.Type type) { - return ports.get(type); - } - - /** - * Converts {@link ServiceInfo} to OzoneManagerProtocolProtos.ServiceInfo. - * - * @return OzoneManagerProtocolProtos.ServiceInfo - */ - @JsonIgnore - public OzoneManagerProtocolProtos.ServiceInfo getProtobuf() { - OzoneManagerProtocolProtos.ServiceInfo.Builder builder = - OzoneManagerProtocolProtos.ServiceInfo.newBuilder(); - builder.setNodeType(nodeType) - .setHostname(hostname) - .addAllServicePorts( - ports.entrySet().stream() - .map( - entry -> - ServicePort.newBuilder() - .setType(entry.getKey()) - .setValue(entry.getValue()).build()) - .collect(Collectors.toList())); - return builder.build(); - } - - /** - * Converts OzoneManagerProtocolProtos.ServiceInfo to {@link ServiceInfo}. - * - * @return {@link ServiceInfo} - */ - @JsonIgnore - public static ServiceInfo getFromProtobuf( - OzoneManagerProtocolProtos.ServiceInfo serviceInfo) { - return new ServiceInfo(serviceInfo.getNodeType(), - serviceInfo.getHostname(), - serviceInfo.getServicePortsList()); - } - - /** - * Returns a JSON string of this object. - * - * @return String - json string - * @throws IOException - */ - public String toJsonString() throws IOException { - return WRITER.writeValueAsString(this); - } - - /** - * Parse a JSON string into ServiceInfo Object. - * - * @param jsonString Json String - * @return BucketInfo - * @throws IOException - */ - public static BucketInfo parse(String jsonString) throws IOException { - return READER.readValue(jsonString); - } - - /** - * Creates a new builder to build {@link ServiceInfo}. - * @return {@link ServiceInfo.Builder} - */ - public static Builder newBuilder() { - return new Builder(); - } - - /** - * Builder used to build/construct {@link ServiceInfo}. - */ - public static class Builder { - - private NodeType node; - private String host; - private List portList = new ArrayList<>(); - - - /** - * Sets the node/service type. - * @param nodeType type of node - * @return the builder - */ - public Builder setNodeType(NodeType nodeType) { - node = nodeType; - return this; - } - - /** - * Sets the hostname of the service. - * @param hostname service hostname - * @return the builder - */ - public Builder setHostname(String hostname) { - host = hostname; - return this; - } - - /** - * Adds the service port to the service port list. - * @param servicePort RPC port - * @return the builder - */ - public Builder addServicePort(ServicePort servicePort) { - portList.add(servicePort); - return this; - } - - - /** - * Builds and returns {@link ServiceInfo} with the set values. - * @return {@link ServiceInfo} - */ - public ServiceInfo build() { - return new ServiceInfo(node, host, portList); - } - } - -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/VolumeArgs.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/VolumeArgs.java deleted file mode 100644 index 6fc7c8fcc53..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/VolumeArgs.java +++ /dev/null @@ -1,140 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.om.helpers; - -import com.google.common.base.Preconditions; - -import java.util.HashMap; -import java.util.Map; - -/** - * A class that encapsulates the createVolume Args. - */ -public final class VolumeArgs { - private final String adminName; - private final String ownerName; - private final String volume; - private final long quotaInBytes; - private final Map extendedAttributes; - - /** - * Private constructor, constructed via builder. - * - * @param adminName - Administrator name. - * @param ownerName - Volume owner's name - * @param volume - volume name - * @param quotaInBytes - Volume Quota in bytes. - * @param keyValueMap - keyValue map. - */ - private VolumeArgs(String adminName, String ownerName, String volume, - long quotaInBytes, Map keyValueMap) { - this.adminName = adminName; - this.ownerName = ownerName; - this.volume = volume; - this.quotaInBytes = quotaInBytes; - this.extendedAttributes = keyValueMap; - } - - /** - * Returns the Admin Name. - * - * @return String. - */ - public String getAdminName() { - return adminName; - } - - /** - * Returns the owner Name. - * - * @return String - */ - public String getOwnerName() { - return ownerName; - } - - /** - * Returns the volume Name. - * - * @return String - */ - public String getVolume() { - return volume; - } - - /** - * Returns Quota in Bytes. - * - * @return long, Quota in bytes. - */ - public long getQuotaInBytes() { - return quotaInBytes; - } - - public Map getExtendedAttributes() { - return extendedAttributes; - } - - static class Builder { - private String adminName; - private String ownerName; - private String volume; - private long quotaInBytes; - private Map extendedAttributes; - - /** - * Constructs a builder. - */ - Builder() { - extendedAttributes = new HashMap<>(); - } - - public void setAdminName(String adminName) { - this.adminName = adminName; - } - - public void setOwnerName(String ownerName) { - this.ownerName = ownerName; - } - - public void setVolume(String volume) { - this.volume = volume; - } - - public void setQuotaInBytes(long quotaInBytes) { - this.quotaInBytes = quotaInBytes; - } - - public void addMetadata(String key, String value) { - extendedAttributes.put(key, value); // overwrite if present. - } - - /** - * Constructs a CreateVolumeArgument. - * - * @return CreateVolumeArgs. - */ - public VolumeArgs build() { - Preconditions.checkNotNull(adminName); - Preconditions.checkNotNull(ownerName); - Preconditions.checkNotNull(volume); - return new VolumeArgs(adminName, ownerName, volume, quotaInBytes, - extendedAttributes); - } - } -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/package-info.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/package-info.java deleted file mode 100644 index b1211d8cb86..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/package-info.java +++ /dev/null @@ -1,18 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.om.helpers; \ No newline at end of file diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/package-info.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/package-info.java deleted file mode 100644 index 1744cffc134..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/package-info.java +++ /dev/null @@ -1,21 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.om; -/** - This package contains client side protocol library to communicate with OM. - */ \ No newline at end of file diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java deleted file mode 100644 index edb260a1084..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java +++ /dev/null @@ -1,253 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.om.protocol; - -import org.apache.hadoop.ozone.om.helpers.OmBucketArgs; -import org.apache.hadoop.ozone.om.helpers.OmBucketInfo; -import org.apache.hadoop.ozone.om.helpers.OmKeyArgs; -import org.apache.hadoop.ozone.om.helpers.OmKeyInfo; -import org.apache.hadoop.ozone.om.helpers.OmKeyLocationInfo; -import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs; -import org.apache.hadoop.ozone.om.helpers.OpenKeySession; -import org.apache.hadoop.ozone.om.helpers.ServiceInfo; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.OzoneAclInfo; -import java.io.IOException; -import java.util.List; - -/** - * Protocol to talk to OM. - */ -public interface OzoneManagerProtocol { - - /** - * Creates a volume. - * @param args - Arguments to create Volume. - * @throws IOException - */ - void createVolume(OmVolumeArgs args) throws IOException; - - /** - * Changes the owner of a volume. - * @param volume - Name of the volume. - * @param owner - Name of the owner. - * @throws IOException - */ - void setOwner(String volume, String owner) throws IOException; - - /** - * Changes the Quota on a volume. - * @param volume - Name of the volume. - * @param quota - Quota in bytes. - * @throws IOException - */ - void setQuota(String volume, long quota) throws IOException; - - /** - * Checks if the specified user can access this volume. - * @param volume - volume - * @param userAcl - user acls which needs to be checked for access - * @return true if the user has required access for the volume, - * false otherwise - * @throws IOException - */ - boolean checkVolumeAccess(String volume, OzoneAclInfo userAcl) - throws IOException; - - /** - * Gets the volume information. - * @param volume - Volume name. - * @return VolumeArgs or exception is thrown. - * @throws IOException - */ - OmVolumeArgs getVolumeInfo(String volume) throws IOException; - - /** - * Deletes an existing empty volume. - * @param volume - Name of the volume. - * @throws IOException - */ - void deleteVolume(String volume) throws IOException; - - /** - * Lists volume owned by a specific user. - * @param userName - user name - * @param prefix - Filter prefix -- Return only entries that match this. - * @param prevKey - Previous key -- List starts from the next from the prevkey - * @param maxKeys - Max number of keys to return. - * @return List of Volumes. - * @throws IOException - */ - List listVolumeByUser(String userName, String prefix, String - prevKey, int maxKeys) throws IOException; - - /** - * Lists volume all volumes in the cluster. - * @param prefix - Filter prefix -- Return only entries that match this. - * @param prevKey - Previous key -- List starts from the next from the prevkey - * @param maxKeys - Max number of keys to return. - * @return List of Volumes. - * @throws IOException - */ - List listAllVolumes(String prefix, String - prevKey, int maxKeys) throws IOException; - - /** - * Creates a bucket. - * @param bucketInfo - BucketInfo to create Bucket. - * @throws IOException - */ - void createBucket(OmBucketInfo bucketInfo) throws IOException; - - /** - * Gets the bucket information. - * @param volumeName - Volume name. - * @param bucketName - Bucket name. - * @return OmBucketInfo or exception is thrown. - * @throws IOException - */ - OmBucketInfo getBucketInfo(String volumeName, String bucketName) - throws IOException; - - /** - * Sets bucket property from args. - * @param args - BucketArgs. - * @throws IOException - */ - void setBucketProperty(OmBucketArgs args) throws IOException; - - /** - * Open the given key and return an open key session. - * - * @param args the args of the key. - * @return OpenKeySession instance that client uses to talk to container. - * @throws IOException - */ - OpenKeySession openKey(OmKeyArgs args) throws IOException; - - /** - * Commit a key. This will make the change from the client visible. The client - * is identified by the clientID. - * - * @param args the key to commit - * @param clientID the client identification - * @throws IOException - */ - void commitKey(OmKeyArgs args, long clientID) throws IOException; - - /** - * Allocate a new block, it is assumed that the client is having an open key - * session going on. This block will be appended to this open key session. - * - * @param args the key to append - * @param clientID the client identification - * @return an allocated block - * @throws IOException - */ - OmKeyLocationInfo allocateBlock(OmKeyArgs args, long clientID) - throws IOException; - - /** - * Look up for the container of an existing key. - * - * @param args the args of the key. - * @return OmKeyInfo instance that client uses to talk to container. - * @throws IOException - */ - OmKeyInfo lookupKey(OmKeyArgs args) throws IOException; - - /** - * Rename an existing key within a bucket. - * @param args the args of the key. - * @param toKeyName New name to be used for the Key - * @throws IOException - */ - void renameKey(OmKeyArgs args, String toKeyName) throws IOException; - - /** - * Deletes an existing key. - * - * @param args the args of the key. - * @throws IOException - */ - void deleteKey(OmKeyArgs args) throws IOException; - - /** - * Deletes an existing empty bucket from volume. - * @param volume - Name of the volume. - * @param bucket - Name of the bucket. - * @throws IOException - */ - void deleteBucket(String volume, String bucket) throws IOException; - - /** - * Returns a list of buckets represented by {@link OmBucketInfo} - * in the given volume. Argument volumeName is required, others - * are optional. - * - * @param volumeName - * the name of the volume. - * @param startBucketName - * the start bucket name, only the buckets whose name is - * after this value will be included in the result. - * @param bucketPrefix - * bucket name prefix, only the buckets whose name has - * this prefix will be included in the result. - * @param maxNumOfBuckets - * the maximum number of buckets to return. It ensures - * the size of the result will not exceed this limit. - * @return a list of buckets. - * @throws IOException - */ - List listBuckets(String volumeName, - String startBucketName, String bucketPrefix, int maxNumOfBuckets) - throws IOException; - - /** - * Returns a list of keys represented by {@link OmKeyInfo} - * in the given bucket. Argument volumeName, bucketName is required, - * others are optional. - * - * @param volumeName - * the name of the volume. - * @param bucketName - * the name of the bucket. - * @param startKeyName - * the start key name, only the keys whose name is - * after this value will be included in the result. - * @param keyPrefix - * key name prefix, only the keys whose name has - * this prefix will be included in the result. - * @param maxKeys - * the maximum number of keys to return. It ensures - * the size of the result will not exceed this limit. - * @return a list of keys. - * @throws IOException - */ - List listKeys(String volumeName, - String bucketName, String startKeyName, String keyPrefix, int maxKeys) - throws IOException; - - /** - * Returns list of Ozone services with its configuration details. - * - * @return list of Ozone services - * @throws IOException - */ - List getServiceList() throws IOException; -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/package-info.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/package-info.java deleted file mode 100644 index 9c7f3888d31..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/package-info.java +++ /dev/null @@ -1,19 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.om.protocol; \ No newline at end of file diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java deleted file mode 100644 index c0829fabb98..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java +++ /dev/null @@ -1,775 +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 - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.om.protocolPB; - -import com.google.common.base.Preconditions; -import com.google.common.base.Strings; -import com.google.common.collect.Lists; -import com.google.protobuf.RpcController; -import com.google.protobuf.ServiceException; -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.ipc.ProtobufHelper; -import org.apache.hadoop.ipc.ProtocolTranslator; -import org.apache.hadoop.ozone.om.helpers.OmBucketArgs; -import org.apache.hadoop.ozone.om.helpers.OmBucketInfo; -import org.apache.hadoop.ozone.om.helpers.OmKeyArgs; -import org.apache.hadoop.ozone.om.helpers.OmKeyInfo; -import org.apache.hadoop.ozone.om.helpers.OmKeyLocationInfo; -import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs; -import org.apache.hadoop.ozone.om.helpers.OpenKeySession; -import org.apache.hadoop.ozone.om.helpers.ServiceInfo; -import org.apache.hadoop.ozone.om.protocol.OzoneManagerProtocol; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.AllocateBlockRequest; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.AllocateBlockResponse; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.CommitKeyRequest; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.CommitKeyResponse; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.BucketArgs; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.BucketInfo; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.CreateBucketRequest; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.CreateBucketResponse; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.InfoBucketRequest; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.InfoBucketResponse; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.SetBucketPropertyRequest; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.SetBucketPropertyResponse; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.DeleteBucketRequest; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.DeleteBucketResponse; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.CreateVolumeRequest; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.CreateVolumeResponse; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.LocateKeyRequest; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.LocateKeyResponse; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.RenameKeyRequest; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.RenameKeyResponse; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.KeyArgs; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.SetVolumePropertyRequest; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.SetVolumePropertyResponse; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.DeleteVolumeRequest; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.DeleteVolumeResponse; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.InfoVolumeRequest; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.InfoVolumeResponse; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.CheckVolumeAccessRequest; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.CheckVolumeAccessResponse; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.ListBucketsRequest; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.ListBucketsResponse; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.ListKeysRequest; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.ListKeysResponse; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.VolumeInfo; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.Status; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.OzoneAclInfo; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.ListVolumeRequest; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.ListVolumeResponse; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.ServiceListRequest; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.ServiceListResponse; - -import java.io.Closeable; -import java.io.IOException; -import java.util.List; -import java.util.ArrayList; -import java.util.stream.Collectors; - -/** - * The client side implementation of OzoneManagerProtocol. - */ - -@InterfaceAudience.Private -public final class OzoneManagerProtocolClientSideTranslatorPB - implements OzoneManagerProtocol, ProtocolTranslator, Closeable { - - /** - * RpcController is not used and hence is set to null. - */ - private static final RpcController NULL_RPC_CONTROLLER = null; - - private final OzoneManagerProtocolPB rpcProxy; - - /** - * Constructor for KeySpaceManger Client. - * @param rpcProxy - */ - public OzoneManagerProtocolClientSideTranslatorPB( - OzoneManagerProtocolPB rpcProxy) { - this.rpcProxy = rpcProxy; - } - - /** - * Closes this stream and releases any system resources associated - * with it. If the stream is already closed then invoking this - * method has no effect. - *

- *

As noted in {@link AutoCloseable#close()}, cases where the - * close may fail require careful attention. It is strongly advised - * to relinquish the underlying resources and to internally - * mark the {@code Closeable} as closed, prior to throwing - * the {@code IOException}. - * - * @throws IOException if an I/O error occurs - */ - @Override - public void close() throws IOException { - - } - - /** - * Creates a volume. - * - * @param args - Arguments to create Volume. - * @throws IOException - */ - @Override - public void createVolume(OmVolumeArgs args) throws IOException { - CreateVolumeRequest.Builder req = - CreateVolumeRequest.newBuilder(); - VolumeInfo volumeInfo = args.getProtobuf(); - req.setVolumeInfo(volumeInfo); - - final CreateVolumeResponse resp; - try { - resp = rpcProxy.createVolume(NULL_RPC_CONTROLLER, - req.build()); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - - if (resp.getStatus() != Status.OK) { - throw new - IOException("Volume creation failed, error:" + resp.getStatus()); - } - } - - /** - * Changes the owner of a volume. - * - * @param volume - Name of the volume. - * @param owner - Name of the owner. - * @throws IOException - */ - @Override - public void setOwner(String volume, String owner) throws IOException { - SetVolumePropertyRequest.Builder req = - SetVolumePropertyRequest.newBuilder(); - req.setVolumeName(volume).setOwnerName(owner); - final SetVolumePropertyResponse resp; - try { - resp = rpcProxy.setVolumeProperty(NULL_RPC_CONTROLLER, req.build()); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - if (resp.getStatus() != Status.OK) { - throw new - IOException("Volume owner change failed, error:" + resp.getStatus()); - } - } - - /** - * Changes the Quota on a volume. - * - * @param volume - Name of the volume. - * @param quota - Quota in bytes. - * @throws IOException - */ - @Override - public void setQuota(String volume, long quota) throws IOException { - SetVolumePropertyRequest.Builder req = - SetVolumePropertyRequest.newBuilder(); - req.setVolumeName(volume).setQuotaInBytes(quota); - final SetVolumePropertyResponse resp; - try { - resp = rpcProxy.setVolumeProperty(NULL_RPC_CONTROLLER, req.build()); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - if (resp.getStatus() != Status.OK) { - throw new - IOException("Volume quota change failed, error:" + resp.getStatus()); - } - } - - /** - * Checks if the specified user can access this volume. - * - * @param volume - volume - * @param userAcl - user acls which needs to be checked for access - * @return true if the user has required access for the volume, - * false otherwise - * @throws IOException - */ - @Override - public boolean checkVolumeAccess(String volume, OzoneAclInfo userAcl) throws - IOException { - CheckVolumeAccessRequest.Builder req = - CheckVolumeAccessRequest.newBuilder(); - req.setVolumeName(volume).setUserAcl(userAcl); - final CheckVolumeAccessResponse resp; - try { - resp = rpcProxy.checkVolumeAccess(NULL_RPC_CONTROLLER, req.build()); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - - if (resp.getStatus() == Status.ACCESS_DENIED) { - return false; - } else if (resp.getStatus() == Status.OK) { - return true; - } else { - throw new - IOException("Check Volume Access failed, error:" + resp.getStatus()); - } - } - - /** - * Gets the volume information. - * - * @param volume - Volume name. - * @return OmVolumeArgs or exception is thrown. - * @throws IOException - */ - @Override - public OmVolumeArgs getVolumeInfo(String volume) throws IOException { - InfoVolumeRequest.Builder req = InfoVolumeRequest.newBuilder(); - req.setVolumeName(volume); - final InfoVolumeResponse resp; - try { - resp = rpcProxy.infoVolume(NULL_RPC_CONTROLLER, req.build()); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - if (resp.getStatus() != Status.OK) { - throw new - IOException("Info Volume failed, error:" + resp.getStatus()); - } - return OmVolumeArgs.getFromProtobuf(resp.getVolumeInfo()); - } - - /** - * Deletes an existing empty volume. - * - * @param volume - Name of the volume. - * @throws IOException - */ - @Override - public void deleteVolume(String volume) throws IOException { - DeleteVolumeRequest.Builder req = DeleteVolumeRequest.newBuilder(); - req.setVolumeName(volume); - final DeleteVolumeResponse resp; - try { - resp = rpcProxy.deleteVolume(NULL_RPC_CONTROLLER, req.build()); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - if (resp.getStatus() != Status.OK) { - throw new - IOException("Delete Volume failed, error:" + resp.getStatus()); - } - } - - /** - * Lists volume owned by a specific user. - * - * @param userName - user name - * @param prefix - Filter prefix -- Return only entries that match this. - * @param prevKey - Previous key -- List starts from the next from the - * prevkey - * @param maxKeys - Max number of keys to return. - * @return List of Volumes. - * @throws IOException - */ - @Override - public List listVolumeByUser(String userName, String prefix, - String prevKey, int maxKeys) - throws IOException { - ListVolumeRequest.Builder builder = ListVolumeRequest.newBuilder(); - if (!Strings.isNullOrEmpty(prefix)) { - builder.setPrefix(prefix); - } - if (!Strings.isNullOrEmpty(prevKey)) { - builder.setPrevKey(prevKey); - } - builder.setMaxKeys(maxKeys); - builder.setUserName(userName); - builder.setScope(ListVolumeRequest.Scope.VOLUMES_BY_USER); - return listVolume(builder.build()); - } - - /** - * Lists volume all volumes in the cluster. - * - * @param prefix - Filter prefix -- Return only entries that match this. - * @param prevKey - Previous key -- List starts from the next from the - * prevkey - * @param maxKeys - Max number of keys to return. - * @return List of Volumes. - * @throws IOException - */ - @Override - public List listAllVolumes(String prefix, String prevKey, - int maxKeys) throws IOException { - ListVolumeRequest.Builder builder = ListVolumeRequest.newBuilder(); - if (!Strings.isNullOrEmpty(prefix)) { - builder.setPrefix(prefix); - } - if (!Strings.isNullOrEmpty(prevKey)) { - builder.setPrevKey(prevKey); - } - builder.setMaxKeys(maxKeys); - builder.setScope(ListVolumeRequest.Scope.VOLUMES_BY_CLUSTER); - return listVolume(builder.build()); - } - - private List listVolume(ListVolumeRequest request) - throws IOException { - final ListVolumeResponse resp; - try { - resp = rpcProxy.listVolumes(NULL_RPC_CONTROLLER, request); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - - if (resp.getStatus() != Status.OK) { - throw new IOException("List volume failed, error: " - + resp.getStatus()); - } - - List result = Lists.newArrayList(); - for (VolumeInfo volInfo : resp.getVolumeInfoList()) { - OmVolumeArgs volArgs = OmVolumeArgs.getFromProtobuf(volInfo); - result.add(volArgs); - } - - return resp.getVolumeInfoList().stream() - .map(item -> OmVolumeArgs.getFromProtobuf(item)) - .collect(Collectors.toList()); - } - - /** - * Creates a bucket. - * - * @param bucketInfo - BucketInfo to create bucket. - * @throws IOException - */ - @Override - public void createBucket(OmBucketInfo bucketInfo) throws IOException { - CreateBucketRequest.Builder req = - CreateBucketRequest.newBuilder(); - BucketInfo bucketInfoProtobuf = bucketInfo.getProtobuf(); - req.setBucketInfo(bucketInfoProtobuf); - - final CreateBucketResponse resp; - try { - resp = rpcProxy.createBucket(NULL_RPC_CONTROLLER, - req.build()); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - if (resp.getStatus() != Status.OK) { - throw new IOException("Bucket creation failed, error: " - + resp.getStatus()); - } - } - - /** - * Gets the bucket information. - * - * @param volume - Volume name. - * @param bucket - Bucket name. - * @return OmBucketInfo or exception is thrown. - * @throws IOException - */ - @Override - public OmBucketInfo getBucketInfo(String volume, String bucket) - throws IOException { - InfoBucketRequest.Builder req = - InfoBucketRequest.newBuilder(); - req.setVolumeName(volume); - req.setBucketName(bucket); - - final InfoBucketResponse resp; - try { - resp = rpcProxy.infoBucket(NULL_RPC_CONTROLLER, - req.build()); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - if (resp.getStatus() == Status.OK) { - return OmBucketInfo.getFromProtobuf(resp.getBucketInfo()); - } else { - throw new IOException("Info Bucket failed, error: " - + resp.getStatus()); - } - } - - /** - * Sets bucket property from args. - * @param args - BucketArgs. - * @throws IOException - */ - @Override - public void setBucketProperty(OmBucketArgs args) - throws IOException { - SetBucketPropertyRequest.Builder req = - SetBucketPropertyRequest.newBuilder(); - BucketArgs bucketArgs = args.getProtobuf(); - req.setBucketArgs(bucketArgs); - final SetBucketPropertyResponse resp; - try { - resp = rpcProxy.setBucketProperty(NULL_RPC_CONTROLLER, - req.build()); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - if (resp.getStatus() != Status.OK) { - throw new IOException("Setting bucket property failed, error: " - + resp.getStatus()); - } - } - - /** - * List buckets in a volume. - * - * @param volumeName - * @param startKey - * @param prefix - * @param count - * @return - * @throws IOException - */ - @Override - public List listBuckets(String volumeName, - String startKey, String prefix, int count) throws IOException { - List buckets = new ArrayList<>(); - ListBucketsRequest.Builder reqBuilder = ListBucketsRequest.newBuilder(); - reqBuilder.setVolumeName(volumeName); - reqBuilder.setCount(count); - if (startKey != null) { - reqBuilder.setStartKey(startKey); - } - if (prefix != null) { - reqBuilder.setPrefix(prefix); - } - ListBucketsRequest request = reqBuilder.build(); - final ListBucketsResponse resp; - try { - resp = rpcProxy.listBuckets(NULL_RPC_CONTROLLER, request); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - - if (resp.getStatus() == Status.OK) { - buckets.addAll( - resp.getBucketInfoList().stream() - .map(OmBucketInfo::getFromProtobuf) - .collect(Collectors.toList())); - return buckets; - } else { - throw new IOException("List Buckets failed, error: " - + resp.getStatus()); - } - } - - /** - * Create a new open session of the key, then use the returned meta info to - * talk to data node to actually write the key. - * @param args the args for the key to be allocated - * @return a handler to the key, returned client - * @throws IOException - */ - @Override - public OpenKeySession openKey(OmKeyArgs args) throws IOException { - LocateKeyRequest.Builder req = LocateKeyRequest.newBuilder(); - KeyArgs.Builder keyArgs = KeyArgs.newBuilder() - .setVolumeName(args.getVolumeName()) - .setBucketName(args.getBucketName()) - .setFactor(args.getFactor()) - .setType(args.getType()) - .setKeyName(args.getKeyName()); - if (args.getDataSize() > 0) { - keyArgs.setDataSize(args.getDataSize()); - } - req.setKeyArgs(keyArgs.build()); - - final LocateKeyResponse resp; - try { - resp = rpcProxy.createKey(NULL_RPC_CONTROLLER, req.build()); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - if (resp.getStatus() != Status.OK) { - throw new IOException("Create key failed, error:" + resp.getStatus()); - } - return new OpenKeySession(resp.getID(), - OmKeyInfo.getFromProtobuf(resp.getKeyInfo()), resp.getOpenVersion()); - } - - @Override - public OmKeyLocationInfo allocateBlock(OmKeyArgs args, long clientID) - throws IOException { - AllocateBlockRequest.Builder req = AllocateBlockRequest.newBuilder(); - KeyArgs keyArgs = KeyArgs.newBuilder() - .setVolumeName(args.getVolumeName()) - .setBucketName(args.getBucketName()) - .setKeyName(args.getKeyName()) - .setDataSize(args.getDataSize()).build(); - req.setKeyArgs(keyArgs); - req.setClientID(clientID); - - final AllocateBlockResponse resp; - try { - resp = rpcProxy.allocateBlock(NULL_RPC_CONTROLLER, req.build()); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - if (resp.getStatus() != Status.OK) { - throw new IOException("Allocate block failed, error:" + - resp.getStatus()); - } - return OmKeyLocationInfo.getFromProtobuf(resp.getKeyLocation()); - } - - @Override - public void commitKey(OmKeyArgs args, long clientID) - throws IOException { - CommitKeyRequest.Builder req = CommitKeyRequest.newBuilder(); - List locationInfoList = args.getLocationInfoList(); - Preconditions.checkNotNull(locationInfoList); - KeyArgs keyArgs = KeyArgs.newBuilder() - .setVolumeName(args.getVolumeName()) - .setBucketName(args.getBucketName()) - .setKeyName(args.getKeyName()) - .setDataSize(args.getDataSize()) - .addAllKeyLocations( - locationInfoList.stream().map(OmKeyLocationInfo::getProtobuf) - .collect(Collectors.toList())).build(); - req.setKeyArgs(keyArgs); - req.setClientID(clientID); - - final CommitKeyResponse resp; - try { - resp = rpcProxy.commitKey(NULL_RPC_CONTROLLER, req.build()); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - if (resp.getStatus() != Status.OK) { - throw new IOException("Commit key failed, error:" + - resp.getStatus()); - } - } - - - @Override - public OmKeyInfo lookupKey(OmKeyArgs args) throws IOException { - LocateKeyRequest.Builder req = LocateKeyRequest.newBuilder(); - KeyArgs keyArgs = KeyArgs.newBuilder() - .setVolumeName(args.getVolumeName()) - .setBucketName(args.getBucketName()) - .setKeyName(args.getKeyName()) - .setDataSize(args.getDataSize()).build(); - req.setKeyArgs(keyArgs); - - final LocateKeyResponse resp; - try { - resp = rpcProxy.lookupKey(NULL_RPC_CONTROLLER, req.build()); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - if (resp.getStatus() != Status.OK) { - throw new IOException("Lookup key failed, error:" + - resp.getStatus()); - } - return OmKeyInfo.getFromProtobuf(resp.getKeyInfo()); - } - - @Override - public void renameKey(OmKeyArgs args, String toKeyName) throws IOException { - RenameKeyRequest.Builder req = RenameKeyRequest.newBuilder(); - KeyArgs keyArgs = KeyArgs.newBuilder() - .setVolumeName(args.getVolumeName()) - .setBucketName(args.getBucketName()) - .setKeyName(args.getKeyName()) - .setDataSize(args.getDataSize()).build(); - req.setKeyArgs(keyArgs); - req.setToKeyName(toKeyName); - - final RenameKeyResponse resp; - try { - resp = rpcProxy.renameKey(NULL_RPC_CONTROLLER, req.build()); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - if (resp.getStatus() != Status.OK) { - throw new IOException("Rename key failed, error:" + - resp.getStatus()); - } - } - - /** - * Deletes an existing key. - * - * @param args the args of the key. - * @throws IOException - */ - @Override - public void deleteKey(OmKeyArgs args) throws IOException { - LocateKeyRequest.Builder req = LocateKeyRequest.newBuilder(); - KeyArgs keyArgs = KeyArgs.newBuilder() - .setVolumeName(args.getVolumeName()) - .setBucketName(args.getBucketName()) - .setKeyName(args.getKeyName()).build(); - req.setKeyArgs(keyArgs); - - final LocateKeyResponse resp; - try { - resp = rpcProxy.deleteKey(NULL_RPC_CONTROLLER, req.build()); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - if (resp.getStatus() != Status.OK) { - throw new IOException("Delete key failed, error:" + - resp.getStatus()); - } - } - - /** - * Deletes an existing empty bucket from volume. - * @param volume - Name of the volume. - * @param bucket - Name of the bucket. - * @throws IOException - */ - public void deleteBucket(String volume, String bucket) throws IOException { - DeleteBucketRequest.Builder req = DeleteBucketRequest.newBuilder(); - req.setVolumeName(volume); - req.setBucketName(bucket); - final DeleteBucketResponse resp; - try { - resp = rpcProxy.deleteBucket(NULL_RPC_CONTROLLER, req.build()); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - if (resp.getStatus() != Status.OK) { - throw new - IOException("Delete Bucket failed, error:" + resp.getStatus()); - } - } - - /** - * List keys in a bucket. - */ - @Override - public List listKeys(String volumeName, String bucketName, - String startKey, String prefix, int maxKeys) throws IOException { - List keys = new ArrayList<>(); - ListKeysRequest.Builder reqBuilder = ListKeysRequest.newBuilder(); - reqBuilder.setVolumeName(volumeName); - reqBuilder.setBucketName(bucketName); - reqBuilder.setCount(maxKeys); - - if (startKey != null) { - reqBuilder.setStartKey(startKey); - } - - if (prefix != null) { - reqBuilder.setPrefix(prefix); - } - - ListKeysRequest request = reqBuilder.build(); - final ListKeysResponse resp; - try { - resp = rpcProxy.listKeys(NULL_RPC_CONTROLLER, request); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - - if (resp.getStatus() == Status.OK) { - keys.addAll( - resp.getKeyInfoList().stream() - .map(OmKeyInfo::getFromProtobuf) - .collect(Collectors.toList())); - return keys; - } else { - throw new IOException("List Keys failed, error: " - + resp.getStatus()); - } - } - - @Override - public List getServiceList() throws IOException { - ServiceListRequest request = ServiceListRequest.newBuilder().build(); - final ServiceListResponse resp; - try { - resp = rpcProxy.getServiceList(NULL_RPC_CONTROLLER, request); - } catch (ServiceException e) { - throw ProtobufHelper.getRemoteException(e); - } - - if (resp.getStatus() == Status.OK) { - return resp.getServiceInfoList().stream() - .map(ServiceInfo::getFromProtobuf) - .collect(Collectors.toList()); - } else { - throw new IOException("Getting service list failed, error: " - + resp.getStatus()); - } - } - - /** - * Return the proxy object underlying this protocol translator. - * - * @return the proxy object underlying this protocol translator. - */ - @Override - public Object getUnderlyingProxyObject() { - return null; - } -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolPB.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolPB.java deleted file mode 100644 index e0879d601ce..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolPB.java +++ /dev/null @@ -1,34 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.om.protocolPB; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.ipc.ProtocolInfo; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.OzoneManagerService; - -/** - * Protocol used to communicate with OM. - */ -@ProtocolInfo(protocolName = - "org.apache.hadoop.ozone.protocol.OzoneManagerProtocol", - protocolVersion = 1) -@InterfaceAudience.Private -public interface OzoneManagerProtocolPB - extends OzoneManagerService.BlockingInterface { -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/package-info.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/package-info.java deleted file mode 100644 index d595edf291a..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/package-info.java +++ /dev/null @@ -1,19 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.om.protocolPB; \ No newline at end of file diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/package-info.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/package-info.java deleted file mode 100644 index 69d94b60ac4..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/package-info.java +++ /dev/null @@ -1,22 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone; - -/** - * Classes related to ozone REST interface. - */ \ No newline at end of file diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/protocolPB/OMPBHelper.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/protocolPB/OMPBHelper.java deleted file mode 100644 index d57d32e0c45..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/protocolPB/OMPBHelper.java +++ /dev/null @@ -1,113 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.protocolPB; - -import org.apache.hadoop.ozone.OzoneAcl; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.OzoneAclInfo; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.OzoneAclInfo.OzoneAclType; -import org.apache.hadoop.ozone.protocol.proto - .OzoneManagerProtocolProtos.OzoneAclInfo.OzoneAclRights; - -/** - * Utilities for converting protobuf classes. - */ -public final class OMPBHelper { - - private OMPBHelper() { - /** Hidden constructor */ - } - - /** - * Converts OzoneAcl into protobuf's OzoneAclInfo. - * @return OzoneAclInfo - */ - public static OzoneAclInfo convertOzoneAcl(OzoneAcl acl) { - OzoneAclInfo.OzoneAclType aclType; - switch(acl.getType()) { - case USER: - aclType = OzoneAclType.USER; - break; - case GROUP: - aclType = OzoneAclType.GROUP; - break; - case WORLD: - aclType = OzoneAclType.WORLD; - break; - default: - throw new IllegalArgumentException("ACL type is not recognized"); - } - OzoneAclInfo.OzoneAclRights aclRights; - switch(acl.getRights()) { - case READ: - aclRights = OzoneAclRights.READ; - break; - case WRITE: - aclRights = OzoneAclRights.WRITE; - break; - case READ_WRITE: - aclRights = OzoneAclRights.READ_WRITE; - break; - default: - throw new IllegalArgumentException("ACL right is not recognized"); - } - - return OzoneAclInfo.newBuilder().setType(aclType) - .setName(acl.getName()) - .setRights(aclRights) - .build(); - } - - /** - * Converts protobuf's OzoneAclInfo into OzoneAcl. - * @return OzoneAcl - */ - public static OzoneAcl convertOzoneAcl(OzoneAclInfo aclInfo) { - OzoneAcl.OzoneACLType aclType; - switch(aclInfo.getType()) { - case USER: - aclType = OzoneAcl.OzoneACLType.USER; - break; - case GROUP: - aclType = OzoneAcl.OzoneACLType.GROUP; - break; - case WORLD: - aclType = OzoneAcl.OzoneACLType.WORLD; - break; - default: - throw new IllegalArgumentException("ACL type is not recognized"); - } - OzoneAcl.OzoneACLRights aclRights; - switch(aclInfo.getRights()) { - case READ: - aclRights = OzoneAcl.OzoneACLRights.READ; - break; - case WRITE: - aclRights = OzoneAcl.OzoneACLRights.WRITE; - break; - case READ_WRITE: - aclRights = OzoneAcl.OzoneACLRights.READ_WRITE; - break; - default: - throw new IllegalArgumentException("ACL right is not recognized"); - } - - return new OzoneAcl(aclType, aclInfo.getName(), aclRights); - } -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/protocolPB/OzonePBHelper.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/protocolPB/OzonePBHelper.java deleted file mode 100644 index 8361bac0d06..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/protocolPB/OzonePBHelper.java +++ /dev/null @@ -1,30 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.protocolPB; - -/** - * Helper class for converting protobuf objects. - */ -public final class OzonePBHelper { - - private OzonePBHelper() { - /** Hidden constructor */ - } - - -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/protocolPB/package-info.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/protocolPB/package-info.java deleted file mode 100644 index 860386d9fdc..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/protocolPB/package-info.java +++ /dev/null @@ -1,24 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.protocolPB; - -/** - * This package contains classes for the Protocol Buffers binding of Ozone - * protocols. - */ diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/util/OzoneVersionInfo.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/util/OzoneVersionInfo.java deleted file mode 100644 index d4767482084..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/util/OzoneVersionInfo.java +++ /dev/null @@ -1,213 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.util; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.classification.InterfaceStability; -import org.apache.hadoop.io.IOUtils; -import org.apache.hadoop.util.ClassUtil; -import org.apache.hadoop.util.ThreadUtil; -import org.apache.hadoop.utils.HddsVersionInfo; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Properties; - -/** - * This class returns build information about Hadoop components. - */ -@InterfaceAudience.Public -@InterfaceStability.Stable -public class OzoneVersionInfo { - private static final Logger LOG = LoggerFactory.getLogger(OzoneVersionInfo.class); - - private Properties info; - - protected OzoneVersionInfo(String component) { - info = new Properties(); - String versionInfoFile = component + "-version-info.properties"; - InputStream is = null; - try { - is = ThreadUtil.getResourceAsStream(OzoneVersionInfo.class.getClassLoader(), - versionInfoFile); - info.load(is); - } catch (IOException ex) { - LoggerFactory.getLogger(getClass()).warn("Could not read '" + - versionInfoFile + "', " + ex.toString(), ex); - } finally { - IOUtils.closeStream(is); - } - } - - protected String _getVersion() { - return info.getProperty("version", "Unknown"); - } - - protected String _getRelease() { - return info.getProperty("release", "Unknown"); - } - - protected String _getRevision() { - return info.getProperty("revision", "Unknown"); - } - - protected String _getBranch() { - return info.getProperty("branch", "Unknown"); - } - - protected String _getDate() { - return info.getProperty("date", "Unknown"); - } - - protected String _getUser() { - return info.getProperty("user", "Unknown"); - } - - protected String _getUrl() { - return info.getProperty("url", "Unknown"); - } - - protected String _getSrcChecksum() { - return info.getProperty("srcChecksum", "Unknown"); - } - - protected String _getBuildVersion(){ - return _getVersion() + - " from " + _getRevision() + - " by " + _getUser() + - " source checksum " + _getSrcChecksum(); - } - - protected String _getProtocVersion() { - return info.getProperty("protocVersion", "Unknown"); - } - - private static OzoneVersionInfo OZONE_VERSION_INFO = new OzoneVersionInfo("ozone"); - /** - * Get the Ozone version. - * @return the Ozone version string, eg. "0.6.3-dev" - */ - public static String getVersion() { - return OZONE_VERSION_INFO._getVersion(); - } - - /** - * Get the Ozone release name. - * @return the Ozone release string, eg. "Acadia" - */ - public static String getRelease() { - return OZONE_VERSION_INFO._getRelease(); - } - - /** - * Get the Git commit hash of the repository when compiled. - * @return the commit hash, eg. "18f64065d5db6208daf50b02c1b5ed4ee3ce547a" - */ - public static String getRevision() { - return OZONE_VERSION_INFO._getRevision(); - } - - /** - * Get the branch on which this originated. - * @return The branch name, e.g. "trunk" or "branches/branch-0.20" - */ - public static String getBranch() { - return OZONE_VERSION_INFO._getBranch(); - } - - /** - * The date that Ozone was compiled. - * @return the compilation date in unix date format - */ - public static String getDate() { - return OZONE_VERSION_INFO._getDate(); - } - - /** - * The user that compiled Ozone. - * @return the username of the user - */ - public static String getUser() { - return OZONE_VERSION_INFO._getUser(); - } - - /** - * Get the URL for the Ozone repository. - * @return the URL of the Ozone repository - */ - public static String getUrl() { - return OZONE_VERSION_INFO._getUrl(); - } - - /** - * Get the checksum of the source files from which Ozone was built. - * @return the checksum of the source files - */ - public static String getSrcChecksum() { - return OZONE_VERSION_INFO._getSrcChecksum(); - } - - /** - * Returns the buildVersion which includes version, - * revision, user and date. - * @return the buildVersion - */ - public static String getBuildVersion(){ - return OZONE_VERSION_INFO._getBuildVersion(); - } - - /** - * Returns the protoc version used for the build. - * @return the protoc version - */ - public static String getProtocVersion(){ - return OZONE_VERSION_INFO._getProtocVersion(); - } - - public static void main(String[] args) { - System.out.println( - " ////////////// \n" + - " //////////////////// \n" + - " //////// //////////////// \n" + - " ////// //////////////// \n" + - " ///// //////////////// / \n" + - " ///// //////// /// \n" + - " //// //////// ///// \n" + - " ///// //////////////// \n" + - " ///// //////////////// // \n" + - " //// /////////////// ///// \n" + - " ///// /////////////// //// \n" + - " ///// ////// ///// \n" + - " ////// ////// ///// \n" + - " /////////// //////// \n" + - " ////// //////////// \n" + - " /// ////////// \n" + - " / "+ getVersion() + "("+ getRelease() +")\n"); - System.out.println("Source code repository " + getUrl() + " -r " + - getRevision()); - System.out.println("Compiled by " + getUser() + " on " + getDate()); - System.out.println("Compiled with protoc " + getProtocVersion()); - System.out.println("From source with checksum " + getSrcChecksum() + "\n"); - LOG.debug("This command was run using " + - ClassUtil.findContainingJar(OzoneVersionInfo.class)); - HddsVersionInfo.main(args); - } -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/handlers/BucketArgs.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/handlers/BucketArgs.java deleted file mode 100644 index 0d5248d125e..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/handlers/BucketArgs.java +++ /dev/null @@ -1,214 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.web.handlers; - -import org.apache.hadoop.fs.StorageType; -import org.apache.hadoop.ozone.OzoneAcl; -import org.apache.hadoop.ozone.OzoneConsts; - -import java.util.LinkedList; -import java.util.List; - -/** - * BucketArgs packages all bucket related arguments to - * file system calls. - */ -public class BucketArgs extends VolumeArgs { - private final String bucketName; - private List addAcls; - private List removeAcls; - private OzoneConsts.Versioning versioning; - private StorageType storageType; - - /** - * Constructor for BucketArgs. - * - * @param volumeName - volumeName - * @param bucketName - bucket Name - * @param userArgs - userArgs - */ - public BucketArgs(String volumeName, String bucketName, UserArgs userArgs) { - super(volumeName, userArgs); - this.bucketName = bucketName; - this.versioning = OzoneConsts.Versioning.NOT_DEFINED; - this.storageType = null; - } - - - /** - * Constructor for BucketArgs. - * - * @param bucketName - bucket Name - * @param volumeArgs - volume Args - */ - public BucketArgs(String bucketName, VolumeArgs volumeArgs) { - super(volumeArgs); - this.bucketName = bucketName; - this.versioning = OzoneConsts.Versioning.NOT_DEFINED; - this.storageType = null; - } - - /** - * Constructor for BucketArgs. - * - * @param args - Bucket Args - */ - public BucketArgs(BucketArgs args) { - this(args.getBucketName(), args); - this.setAddAcls(args.getAddAcls()); - this.setRemoveAcls(args.getRemoveAcls()); - } - - /** - * Returns the Bucket Name. - * - * @return Bucket Name - */ - public String getBucketName() { - return bucketName; - } - - /** - * Returns Additive ACLs for the Bucket if specified. - * - * @return acls - */ - public List getAddAcls() { - return addAcls; - } - - /** - * Set Additive ACLs. - * - * @param acl - ACL - */ - public void setAddAcls(List acl) { - this.addAcls = acl; - } - - /** - * Returns remove ACLs for the Bucket if specified. - * - * @return acls - */ - public List getRemoveAcls() { - return removeAcls; - } - - /** - * Takes an ACL and sets the ACL object to ACL represented by the String. - * - * @param aclString - aclString - */ - public void addAcls(List aclString) throws IllegalArgumentException { - if (aclString == null) { - throw new IllegalArgumentException("ACLs cannot be null"); - } - if (this.addAcls == null) { - this.addAcls = new LinkedList<>(); - } - for (String s : aclString) { - this.addAcls.add(OzoneAcl.parseAcl(s)); - } - } - - /** - * Takes an ACL and sets the ACL object to ACL represented by the String. - * - * @param aclString - aclString - */ - public void removeAcls(List aclString) - throws IllegalArgumentException { - if (aclString == null) { - throw new IllegalArgumentException("ACLs cannot be null"); - } - if (this.removeAcls == null) { - this.removeAcls = new LinkedList<>(); - } - for (String s : aclString) { - this.removeAcls.add(OzoneAcl.parseAcl(s)); - } - } - - /** - * Set remove ACLs. - * - * @param acl - ACL - */ - public void setRemoveAcls(List acl) { - this.removeAcls = acl; - } - - - /** - * Returns Versioning Info. - * - * @return versioning - */ - public OzoneConsts.Versioning getVersioning() { - return versioning; - } - - - /** - * SetVersioning Info. - * - * @param versioning - Enum value - */ - public void setVersioning(OzoneConsts.Versioning versioning) { - this.versioning = versioning; - } - - /** - * returns the current Storage Class. - * - * @return Storage Class - */ - public StorageType getStorageType() { - return storageType; - } - - /** - * Sets the Storage Class. - * - * @param storageType Set Storage Class - */ - public void setStorageType(StorageType storageType) { - this.storageType = storageType; - } - - /** - * returns - Volume/bucketName. - * - * @return String - */ - @Override - public String getResourceName() { - return getVolumeName() + "/" + getBucketName(); - } - - /** - * Returns User/Volume name which is the parent of this - * bucket. - * - * @return String - */ - public String getParentName() { - return getUserName() + "/" + getVolumeName(); - } -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/handlers/KeyArgs.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/handlers/KeyArgs.java deleted file mode 100644 index 48a4cb45136..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/handlers/KeyArgs.java +++ /dev/null @@ -1,117 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.web.handlers; - -/** - * Class that packages all key Arguments. - */ -public class KeyArgs extends BucketArgs { - private String key; - private String hash; - private long size; - - /** - * Constructor for Key Args. - * - * @param volumeName - Volume Name - * @param bucketName - Bucket Name - * @param objectName - Key - */ - public KeyArgs(String volumeName, String bucketName, - String objectName, UserArgs args) { - super(volumeName, bucketName, args); - this.key = objectName; - } - - /** - * Constructor for Key Args. - * - * @param objectName - Key - * @param args - Bucket Args - */ - public KeyArgs(String objectName, BucketArgs args) { - super(args); - this.key = objectName; - } - - /** - * Get Key Name. - * - * @return String - */ - public String getKeyName() { - return this.key; - } - - /** - * Computed File hash. - * - * @return String - */ - public String getHash() { - return hash; - } - - /** - * Sets the hash String. - * - * @param hash String - */ - public void setHash(String hash) { - this.hash = hash; - } - - /** - * Returns the file size. - * - * @return long - file size - */ - public long getSize() { - return size; - } - - /** - * Set Size. - * - * @param size Size of the file - */ - public void setSize(long size) { - this.size = size; - } - - /** - * Returns the name of the resource. - * - * @return String - */ - @Override - public String getResourceName() { - return super.getResourceName() + "/" + getKeyName(); - } - - /** - * Parent name of this resource. - * - * @return String. - */ - @Override - public String getParentName() { - return super.getResourceName(); - } -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/handlers/ListArgs.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/handlers/ListArgs.java deleted file mode 100644 index 49ca4a4f7e3..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/handlers/ListArgs.java +++ /dev/null @@ -1,142 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.web.handlers; - -/** - * Supports listing keys with pagination. - */ -public class ListArgs { - private String prevKey; - private String prefix; - private int maxKeys; - private boolean rootScan; - private T args; - - /** - * Constructor for ListArgs. - * - * @param args - BucketArgs - * @param prefix Prefix to start Query from - * @param maxKeys Max result set - * @param prevKey - Page token - */ - public ListArgs(T args, String prefix, int maxKeys, - String prevKey) { - setArgs(args); - setPrefix(prefix); - setMaxKeys(maxKeys); - setPrevKey(prevKey); - } - - /** - * Copy Constructor for ListArgs. - * - * @param args - List Args - */ - public ListArgs(T args, ListArgs listArgs) { - this(args, listArgs.getPrefix(), listArgs.getMaxKeys(), - listArgs.getPrevKey()); - } - - /** - * Returns page token. - * - * @return String - */ - public String getPrevKey() { - return prevKey; - } - - /** - * Sets page token. - * - * @param prevKey - Page token - */ - public void setPrevKey(String prevKey) { - this.prevKey = prevKey; - } - - /** - * Gets max keys. - * - * @return int - */ - public int getMaxKeys() { - return maxKeys; - } - - /** - * Sets max keys. - * - * @param maxKeys - Maximum keys to return - */ - public void setMaxKeys(int maxKeys) { - this.maxKeys = maxKeys; - } - - /** - * Gets prefix. - * - * @return String - */ - public String getPrefix() { - return prefix; - } - - /** - * Sets prefix. - * - * @param prefix - The prefix that we are looking for - */ - public void setPrefix(String prefix) { - this.prefix = prefix; - } - - /** - * Gets args. - * @return T - */ - public T getArgs() { - return args; - } - - /** - * Sets args. - * @param args T - */ - public void setArgs(T args) { - this.args = args; - } - - /** - * Checks if we are doing a rootScan. - * @return - RootScan. - */ - public boolean isRootScan() { - return rootScan; - } - - /** - * Sets the RootScan property. - * @param rootScan - Boolean. - */ - public void setRootScan(boolean rootScan) { - this.rootScan = rootScan; - } - -} \ No newline at end of file diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/handlers/UserArgs.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/handlers/UserArgs.java deleted file mode 100644 index 8a75928a1c6..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/handlers/UserArgs.java +++ /dev/null @@ -1,172 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.web.handlers; - -import org.apache.hadoop.classification.InterfaceAudience; - -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.Request; -import javax.ws.rs.core.UriInfo; -import java.util.Arrays; - -/** - * UserArgs is used to package caller info - * and pass it down to file system. - */ -@InterfaceAudience.Private -public class UserArgs { - private String userName; - private final String requestID; - private final String hostName; - private final UriInfo uri; - private final Request request; - private final HttpHeaders headers; - private String[] groups; - - - /** - * Constructs user args. - * - * @param userName - User name - * @param requestID - Request ID - * @param hostName - Host Name - * @param req - Request - * @param info - Uri Info - * @param httpHeaders - http headers - */ - public UserArgs(String userName, String requestID, String hostName, - Request req, UriInfo info, HttpHeaders httpHeaders) { - this.hostName = hostName; - this.userName = userName; - this.requestID = requestID; - this.uri = info; - this.request = req; - this.headers = httpHeaders; - } - - /** - * Constructs user args when we don't know the user name yet. - * - * @param requestID _ Request ID - * @param hostName - Host Name - * @param req - Request - * @param info - UriInfo - * @param httpHeaders - http headers - */ - public UserArgs(String requestID, String hostName, Request req, UriInfo info, - HttpHeaders httpHeaders) { - this.hostName = hostName; - this.requestID = requestID; - this.uri = info; - this.request = req; - this.headers = httpHeaders; - } - - /** - * Returns hostname. - * - * @return String - */ - public String getHostName() { - return hostName; - } - - /** - * Returns RequestID. - * - * @return Long - */ - public String getRequestID() { - return requestID; - } - - /** - * Returns User Name. - * - * @return String - */ - public String getUserName() { - return userName; - } - - /** - * Sets the user name. - * - * @param userName Name of the user - */ - public void setUserName(String userName) { - this.userName = userName; - } - - /** - * Returns list of groups. - * - * @return String[] - */ - public String[] getGroups() { - return groups != null ? - Arrays.copyOf(groups, groups.length) : null; - } - - /** - * Sets the group list. - * - * @param groups list of groups - */ - public void setGroups(String[] groups) { - if (groups != null) { - this.groups = Arrays.copyOf(groups, groups.length); - } - } - - /** - * Returns the resource Name. - * - * @return String Resource. - */ - public String getResourceName() { - return getUserName(); - } - - /** - * Returns Http Headers for this call. - * - * @return httpHeaders - */ - public HttpHeaders getHeaders() { - return headers; - } - - /** - * Returns Request Object. - * - * @return Request - */ - public Request getRequest() { - return request; - } - - /** - * Returns UriInfo. - * - * @return UriInfo - */ - public UriInfo getUri() { - return uri; - } -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/handlers/VolumeArgs.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/handlers/VolumeArgs.java deleted file mode 100644 index 1d67c67f598..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/handlers/VolumeArgs.java +++ /dev/null @@ -1,142 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.web.handlers; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.ozone.web.request.OzoneQuota; - -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.Request; -import javax.ws.rs.core.UriInfo; - -/** - * VolumeArgs is used to package all volume - * related arguments in the call to underlying - * file system. - */ -@InterfaceAudience.Private -public class VolumeArgs extends UserArgs { - private String adminName; - private final String volumeName; - private OzoneQuota quota; - - /** - * Returns Quota Information. - * - * @return Quota - */ - public OzoneQuota getQuota() { - return quota; - } - - /** - * Returns volume name. - * - * @return String - */ - public String getVolumeName() { - return volumeName; - } - - /** - * Constructs volume Args. - * - * @param userName - User name - * @param volumeName - volume Name - * @param requestID _ Request ID - * @param hostName - Host Name - * @param request - Http Request - * @param info - URI info - * @param headers - http headers - * @param groups - list of groups allowed to access the volume - */ - public VolumeArgs(String userName, String volumeName, String requestID, - String hostName, Request request, UriInfo info, - HttpHeaders headers, String[] groups) { - super(userName, requestID, hostName, request, info, headers); - super.setGroups(groups); - this.volumeName = volumeName; - } - - /** - * Constructs volume Args. - * - * @param volumeName - volume Name - * @param userArgs - userArgs - */ - public VolumeArgs(String volumeName, UserArgs userArgs) { - this(userArgs.getUserName(), volumeName, userArgs.getRequestID(), - userArgs.getHostName(), userArgs.getRequest(), userArgs.getUri(), - userArgs.getHeaders(), userArgs.getGroups()); - } - - /** - * Creates VolumeArgs from another VolumeArgs. - */ - public VolumeArgs(VolumeArgs volArgs) { - this(volArgs.getVolumeName(), volArgs); - } - - /** - * Sets Quota information. - * - * @param quota - Quota Sting - * @throws IllegalArgumentException - */ - public void setQuota(String quota) throws IllegalArgumentException { - this.quota = OzoneQuota.parseQuota(quota); - } - - /** - * Sets quota information. - * - * @param quota - OzoneQuota - */ - public void setQuota(OzoneQuota quota) { - this.quota = quota; - } - - /** - * Gets admin Name. - * - * @return - Admin Name - */ - public String getAdminName() { - return adminName; - } - - /** - * Sets Admin Name. - * - * @param adminName - Admin Name - */ - public void setAdminName(String adminName) { - this.adminName = adminName; - } - - /** - * Returns UserName/VolumeName. - * - * @return String - */ - @Override - public String getResourceName() { - return super.getResourceName() + "/" + getVolumeName(); - } -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/handlers/package-info.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/handlers/package-info.java deleted file mode 100644 index a66a773c389..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/handlers/package-info.java +++ /dev/null @@ -1,22 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.web.handlers; - -/** - * REST handler value classes. - */ \ No newline at end of file diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/request/OzoneQuota.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/request/OzoneQuota.java deleted file mode 100644 index 9619ebdb7cd..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/request/OzoneQuota.java +++ /dev/null @@ -1,214 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.web.request; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.client.rest.headers.Header; -import com.fasterxml.jackson.annotation.JsonIgnore; - -/** - * represents an OzoneQuota Object that can be applied to - * a storage volume. - */ -@InterfaceAudience.Private -public class OzoneQuota { - - private Units unit; - private int size; - - /** Quota Units.*/ - public enum Units {UNDEFINED, BYTES, MB, GB, TB} - - /** - * Returns size. - * - * @return int - */ - public int getSize() { - return size; - } - - /** - * Returns Units. - * - * @return Unit in MB, GB or TB - */ - public Units getUnit() { - return unit; - } - - /** - * Constructs a default Quota object. - */ - public OzoneQuota() { - this.size = 0; - this.unit = Units.UNDEFINED; - } - - /** - * Constructor for Ozone Quota. - * - * @param size - Integer Size - * @param unit MB, GB or TB - */ - public OzoneQuota(int size, Units unit) { - this.size = size; - this.unit = unit; - } - - /** - * Formats a quota as a string. - * - * @param quota the quota to format - * @return string representation of quota - */ - public static String formatQuota(OzoneQuota quota) { - return String.valueOf(quota.size) + quota.unit; - } - - /** - * Parses a user provided string and returns the - * Quota Object. - * - * @param quotaString Quota String - * - * @return OzoneQuota object - * - * @throws IllegalArgumentException - */ - public static OzoneQuota parseQuota(String quotaString) - throws IllegalArgumentException { - - if ((quotaString == null) || (quotaString.isEmpty())) { - throw new IllegalArgumentException( - "Quota string cannot be null or empty."); - } - - if (isRemove(quotaString)) { - throw new IllegalArgumentException("Remove is invalid in this context."); - } - - String uppercase = quotaString.toUpperCase().replaceAll("\\s+", ""); - String size = ""; - int nSize; - Units currUnit = Units.MB; - Boolean found = false; - if (uppercase.endsWith(Header.OZONE_QUOTA_MB)) { - size = uppercase - .substring(0, uppercase.length() - Header.OZONE_QUOTA_MB.length()); - currUnit = Units.MB; - found = true; - } - - if (uppercase.endsWith(Header.OZONE_QUOTA_GB)) { - size = uppercase - .substring(0, uppercase.length() - Header.OZONE_QUOTA_GB.length()); - currUnit = Units.GB; - found = true; - } - - if (uppercase.endsWith(Header.OZONE_QUOTA_TB)) { - size = uppercase - .substring(0, uppercase.length() - Header.OZONE_QUOTA_TB.length()); - currUnit = Units.TB; - found = true; - } - - if (uppercase.endsWith(Header.OZONE_QUOTA_BYTES)) { - size = uppercase - .substring(0, uppercase.length() - Header.OZONE_QUOTA_BYTES.length()); - currUnit = Units.BYTES; - found = true; - } - - if (!found) { - throw new IllegalArgumentException( - "Quota unit not recognized. Supported values are BYTES, MB, GB and " + - "TB."); - } - - nSize = Integer.parseInt(size); - if (nSize < 0) { - throw new IllegalArgumentException("Quota cannot be negative."); - } - - return new OzoneQuota(nSize, currUnit); - } - - - /** - * Checks if Quota String is just as remove operation. - * - * @param quotaString User provided quota String - * - * @return True if it is Remove, false otherwise - */ - public static boolean isRemove(String quotaString) { - - return (quotaString != null) && - (quotaString.compareToIgnoreCase(Header.OZONE_QUOTA_REMOVE) == 0); - } - - /** - * Returns size in Bytes or -1 if there is no Quota. - */ - @JsonIgnore - public long sizeInBytes() { - switch (this.unit) { - case BYTES: - return this.getSize(); - case MB: - return this.getSize() * OzoneConsts.MB; - case GB: - return this.getSize() * OzoneConsts.GB; - case TB: - return this.getSize() * OzoneConsts.TB; - case UNDEFINED: - default: - return -1; - } - } - - /** - * Returns OzoneQuota corresponding to size in bytes. - * - * @param sizeInBytes size in bytes to be converted - * - * @return OzoneQuota object - */ - public static OzoneQuota getOzoneQuota(long sizeInBytes) { - long size; - Units unit; - if (sizeInBytes % OzoneConsts.TB == 0) { - size = sizeInBytes / OzoneConsts.TB; - unit = Units.TB; - } else if (sizeInBytes % OzoneConsts.GB == 0) { - size = sizeInBytes / OzoneConsts.GB; - unit = Units.GB; - } else if (sizeInBytes % OzoneConsts.MB == 0) { - size = sizeInBytes / OzoneConsts.MB; - unit = Units.MB; - } else { - size = sizeInBytes; - unit = Units.BYTES; - } - return new OzoneQuota((int)size, unit); - } -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/request/package-info.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/request/package-info.java deleted file mode 100644 index 4fbc18ff6e4..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/request/package-info.java +++ /dev/null @@ -1,23 +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 - * - * 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. - */ - -/** - * Netty-based HTTP server implementation for Ozone. - */ -package org.apache.hadoop.ozone.web.request; \ No newline at end of file diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/BucketInfo.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/BucketInfo.java deleted file mode 100644 index e66cd204df0..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/BucketInfo.java +++ /dev/null @@ -1,325 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.web.response; - -import java.io.IOException; -import java.util.LinkedList; -import java.util.List; - -import org.apache.hadoop.fs.StorageType; -import org.apache.hadoop.ozone.OzoneConsts; -import org.apache.hadoop.ozone.OzoneAcl; -import org.apache.hadoop.ozone.web.utils.JsonUtils; - -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.JsonFilter; -import com.fasterxml.jackson.annotation.PropertyAccessor; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ObjectReader; -import com.fasterxml.jackson.databind.ObjectWriter; -import com.fasterxml.jackson.databind.ser.FilterProvider; -import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; -import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; -import com.google.common.base.Preconditions; - -/** - * BucketInfo class, this is used as response class to send - * Json info about a bucket back to a client. - */ -public class BucketInfo implements Comparable { - static final String BUCKET_INFO = "BUCKET_INFO_FILTER"; - private static final ObjectReader READER = - new ObjectMapper().readerFor(BucketInfo.class); - private static final ObjectWriter WRITER; - - static { - ObjectMapper mapper = new ObjectMapper(); - String[] ignorableFieldNames = {"bytesUsed", "keyCount"}; - - FilterProvider filters = new SimpleFilterProvider().addFilter(BUCKET_INFO, - SimpleBeanPropertyFilter.serializeAllExcept(ignorableFieldNames)); - mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); - mapper.addMixIn(Object.class, MixIn.class); - - mapper.setFilterProvider(filters); - WRITER = mapper.writerWithDefaultPrettyPrinter(); - } - - private String volumeName; - private String bucketName; - private String createdOn; - private List acls; - private OzoneConsts.Versioning versioning; - private StorageType storageType; - private long bytesUsed; - private long keyCount; - - /** - * Constructor for BucketInfo. - * - * @param volumeName - * @param bucketName - */ - public BucketInfo(String volumeName, String bucketName) { - this.volumeName = volumeName; - this.bucketName = bucketName; - } - - - /** - * Default constructor for BucketInfo. - */ - public BucketInfo() { - acls = new LinkedList(); - } - - /** - * Parse a JSON string into BucketInfo Object. - * - * @param jsonString - Json String - * - * @return - BucketInfo - * - * @throws IOException - */ - public static BucketInfo parse(String jsonString) throws IOException { - return READER.readValue(jsonString); - } - - /** - * Returns a List of ACL on the Bucket. - * - * @return List of Acls - */ - public List getAcls() { - return acls; - } - - /** - * Sets ACls. - * - * @param acls - Acls list - */ - public void setAcls(List acls) { - this.acls = acls; - } - - /** - * Returns Storage Type info. - * - * @return Storage Type of the bucket - */ - public StorageType getStorageType() { - return storageType; - } - - /** - * Sets the Storage Type. - * - * @param storageType - Storage Type - */ - public void setStorageType(StorageType storageType) { - this.storageType = storageType; - } - - /** - * Returns versioning. - * - * @return versioning Enum - */ - public OzoneConsts.Versioning getVersioning() { - return versioning; - } - - /** - * Sets Versioning. - * - * @param versioning - */ - public void setVersioning(OzoneConsts.Versioning versioning) { - this.versioning = versioning; - } - - - /** - * Gets bucket Name. - * - * @return String - */ - public String getBucketName() { - return bucketName; - } - - /** - * Sets bucket Name. - * - * @param bucketName - Name of the bucket - */ - public void setBucketName(String bucketName) { - this.bucketName = bucketName; - } - - /** - * Sets creation time of the bucket. - * - * @param creationTime - Date String - */ - public void setCreatedOn(String creationTime) { - this.createdOn = creationTime; - } - - /** - * Returns creation time. - * - * @return creation time of bucket. - */ - public String getCreatedOn() { - return createdOn; - } - - /** - * Returns a JSON string of this object. - * After stripping out bytesUsed and keyCount - * - * @return String - */ - public String toJsonString() throws IOException { - return WRITER.writeValueAsString(this); - } - - /** - * Returns the Object as a Json String. - * - * The reason why both toJSONString exists and toDBString exists - * is because toJSONString supports an external facing contract with - * REST clients. However server internally would want to add more - * fields to this class. The distinction helps in serializing all - * fields vs. only fields that are part of REST protocol. - */ - public String toDBString() throws IOException { - return JsonUtils.toJsonString(this); - } - - /** - * Returns Volume Name. - * - * @return String volume name - */ - public String getVolumeName() { - return volumeName; - } - - /** - * Sets the Volume Name of the bucket. - * - * @param volumeName - volumeName - */ - public void setVolumeName(String volumeName) { - this.volumeName = volumeName; - } - - /** - * Compares this object with the specified object for order. Returns a - * negative integer, zero, or a positive integer as this object is less - * than, equal to, or greater than the specified object. - * - * Please note : BucketInfo compare functions are used only within the - * context of a volume, hence volume name is purposefully ignored in - * compareTo, equal and hashcode functions of this class. - */ - @Override - public int compareTo(BucketInfo o) { - Preconditions.checkState(o.getVolumeName().equals(this.getVolumeName())); - return this.bucketName.compareTo(o.getBucketName()); - } - - /** - * Checks if two bucketInfo's are equal. - * @param o Object BucketInfo - * @return True or False - */ - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof BucketInfo)) { - return false; - } - - BucketInfo that = (BucketInfo) o; - Preconditions.checkState(that.getVolumeName().equals(this.getVolumeName())); - return bucketName.equals(that.bucketName); - - } - - /** - * Hash Code for this object. - * @return int - */ - @Override - public int hashCode() { - return bucketName.hashCode(); - } - - /** - * Get the number of bytes used by this bucket. - * - * @return long - */ - public long getBytesUsed() { - return bytesUsed; - } - - /** - * Set bytes Used. - * - * @param bytesUsed - bytesUsed - */ - public void setBytesUsed(long bytesUsed) { - this.bytesUsed = bytesUsed; - } - - /** - * Get Key Count inside this bucket. - * - * @return - KeyCount - */ - public long getKeyCount() { - return keyCount; - } - - /** - * Set Key Count inside this bucket. - * - * @param keyCount - Sets the Key Count - */ - public void setKeyCount(long keyCount) { - this.keyCount = keyCount; - } - - /** - * This class allows us to create custom filters - * for the Json serialization. - */ - @JsonFilter(BUCKET_INFO) - class MixIn { - - } - -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/KeyInfo.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/KeyInfo.java deleted file mode 100644 index ba47bee7679..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/KeyInfo.java +++ /dev/null @@ -1,290 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.web.response; - -import java.io.IOException; - -import org.apache.commons.lang3.builder.EqualsBuilder; -import org.apache.commons.lang3.builder.HashCodeBuilder; -import org.apache.hadoop.ozone.web.utils.JsonUtils; - -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.JsonFilter; -import com.fasterxml.jackson.annotation.PropertyAccessor; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ObjectReader; -import com.fasterxml.jackson.databind.ObjectWriter; -import com.fasterxml.jackson.databind.ser.FilterProvider; -import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; -import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; - -/** - * Represents an Ozone key Object. - */ -public class KeyInfo implements Comparable { - static final String OBJECT_INFO = "OBJECT_INFO_FILTER"; - - private static final ObjectReader READER = - new ObjectMapper().readerFor(KeyInfo.class); - private static final ObjectWriter WRITER; - - static { - ObjectMapper mapper = new ObjectMapper(); - String[] ignorableFieldNames = {"dataFileName"}; - - FilterProvider filters = new SimpleFilterProvider() - .addFilter(OBJECT_INFO, SimpleBeanPropertyFilter - .serializeAllExcept(ignorableFieldNames)); - mapper.setVisibility(PropertyAccessor.FIELD, - JsonAutoDetect.Visibility.ANY); - mapper.addMixIn(Object.class, MixIn.class); - - mapper.setFilterProvider(filters); - WRITER = mapper.writerWithDefaultPrettyPrinter(); - } - - /** - * This class allows us to create custom filters - * for the Json serialization. - */ - @JsonFilter(OBJECT_INFO) - class MixIn { - - } - private long version; - private String md5hash; - private String createdOn; - private String modifiedOn; - private long size; - private String keyName; - - private String dataFileName; - - /** - * When this key was created. - * - * @return Date String - */ - public String getCreatedOn() { - return createdOn; - } - - /** - * When this key was modified. - * - * @return Date String - */ - public String getModifiedOn() { - return modifiedOn; - } - - /** - * When this key was created. - * - * @param createdOn - Date String - */ - public void setCreatedOn(String createdOn) { - this.createdOn = createdOn; - } - - /** - * When this key was modified. - * - * @param modifiedOn - Date String - */ - public void setModifiedOn(String modifiedOn) { - this.modifiedOn = modifiedOn; - } - - /** - * Full path to where the actual data for this key is stored. - * - * @return String - */ - public String getDataFileName() { - return dataFileName; - } - - /** - * Sets up where the file path is stored. - * - * @param dataFileName - Data File Name - */ - public void setDataFileName(String dataFileName) { - this.dataFileName = dataFileName; - } - - /** - * Gets the Keyname of this object. - * - * @return String - */ - public String getKeyName() { - return keyName; - } - - /** - * Sets the Key name of this object. - * - * @param keyName - String - */ - public void setKeyName(String keyName) { - this.keyName = keyName; - } - - /** - * Returns the MD5 Hash for the data of this key. - * - * @return String MD5 - */ - public String getMd5hash() { - return md5hash; - } - - /** - * Sets the MD5 of this file. - * - * @param md5hash - Md5 of this file - */ - public void setMd5hash(String md5hash) { - this.md5hash = md5hash; - } - - /** - * Number of bytes stored in the data part of this key. - * - * @return long size of the data file - */ - public long getSize() { - return size; - } - - /** - * Sets the size of the Data part of this key. - * - * @param size - Size in long - */ - public void setSize(long size) { - this.size = size; - } - - /** - * Version of this key. - * - * @return - returns the version of this key. - */ - public long getVersion() { - return version; - } - - /** - * Sets the version of this key. - * - * @param version - Version String - */ - public void setVersion(long version) { - this.version = version; - } - - /** - * Compares this object with the specified object for order. Returns a - * negative integer, zero, or a positive integer as this object is less - * than, equal to, or greater than the specified object. - * - * @param o the object to be compared. - * - * @return a negative integer, zero, or a positive integer as this object - * is less than, equal to, or greater than the specified object. - * - * @throws NullPointerException if the specified object is null - * @throws ClassCastException if the specified object's type prevents it - * from being compared to this object. - */ - @Override - public int compareTo(KeyInfo o) { - if (this.keyName.compareTo(o.getKeyName()) != 0) { - return this.keyName.compareTo(o.getKeyName()); - } - - if (this.getVersion() == o.getVersion()) { - return 0; - } - if (this.getVersion() < o.getVersion()) { - return -1; - } - return 1; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (o == null || getClass() != o.getClass()) { - return false; - } - - KeyInfo keyInfo = (KeyInfo) o; - - return new EqualsBuilder() - .append(version, keyInfo.version) - .append(keyName, keyInfo.keyName) - .isEquals(); - } - - @Override - public int hashCode() { - return new HashCodeBuilder(17, 37) - .append(version) - .append(keyName) - .toHashCode(); - } - - /** - - * Parse a string to retuen BucketInfo Object. - * - * @param jsonString - Json String - * - * @return - BucketInfo - * - * @throws IOException - */ - public static KeyInfo parse(String jsonString) throws IOException { - return READER.readValue(jsonString); - } - - - /** - * Returns a JSON string of this object. - * After stripping out bytesUsed and keyCount - * - * @return String - */ - public String toJsonString() throws IOException { - return WRITER.writeValueAsString(this); - } - - /** - * Returns the Object as a Json String. - */ - public String toDBString() throws IOException { - return JsonUtils.toJsonString(this); - } -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/KeyInfoDetails.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/KeyInfoDetails.java deleted file mode 100644 index 7f2ba098d79..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/KeyInfoDetails.java +++ /dev/null @@ -1,80 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.web.response; - -import org.apache.commons.lang3.builder.EqualsBuilder; -import org.apache.commons.lang3.builder.HashCodeBuilder; - -import java.util.List; - -/** - * Represents an Ozone key Object with detail information of location. - */ -public class KeyInfoDetails extends KeyInfo { - /** - * a list of Map which maps localID to ContainerID - * to specify replica locations. - */ - private List keyLocations; - - /** - * Set details of key location. - * - * @param keyLocations - details of key location - */ - public void setKeyLocations(List keyLocations) { - this.keyLocations = keyLocations; - } - - /** - * Returns details of key location. - * - * @return volumeName - */ - public List getKeyLocations() { - return keyLocations; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (o == null || getClass() != o.getClass()) { - return false; - } - - KeyInfoDetails that = (KeyInfoDetails) o; - - return new EqualsBuilder() - .append(getVersion(), that.getVersion()) - .append(getKeyName(), that.getKeyName()) - .append(keyLocations, that.getKeyLocations()) - .isEquals(); - } - - @Override - public int hashCode() { - return new HashCodeBuilder(17, 37) - .append(getVersion()) - .append(getKeyName()) - .append(keyLocations) - .toHashCode(); - } -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/KeyLocation.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/KeyLocation.java deleted file mode 100644 index d03eff74753..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/KeyLocation.java +++ /dev/null @@ -1,82 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.web.response; - -/** - * KeyLocation class is used used for parsing json response - * when KeyInfoDetails Call is made. - */ -public class KeyLocation { - /** - * Which container this key stored. - */ - private final long containerID; - /** - * Which block this key stored inside a container. - */ - private final long localID; - /** - * Data length of this key replica. - */ - private final long length; - /** - * Offset of this key. - */ - private final long offset; - - /** - * Constructs KeyLocation. - */ - public KeyLocation(long containerID, long localID, - long length, long offset) { - this.containerID = containerID; - this.localID = localID; - this.length = length; - this.offset = offset; - } - - /** - * Returns the containerID of this Key. - */ - public long getContainerID() { - return containerID; - } - - /** - * Returns the localID of this Key. - */ - public long getLocalID() { - return localID; - } - - /** - * Returns the length of this Key. - */ - public long getLength() { - return length; - } - - /** - * Returns the offset of this Key. - */ - public long getOffset() { - return offset; - } - -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/ListBuckets.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/ListBuckets.java deleted file mode 100644 index bc4e65be0df..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/ListBuckets.java +++ /dev/null @@ -1,154 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.web.response; - - -import java.io.IOException; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; - -import org.apache.hadoop.ozone.web.utils.JsonUtils; - -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.JsonFilter; -import com.fasterxml.jackson.annotation.PropertyAccessor; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ObjectReader; -import com.fasterxml.jackson.databind.ObjectWriter; -import com.fasterxml.jackson.databind.ser.FilterProvider; -import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; -import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; - -/** - * List Bucket is the response for the ListBucket Query. - */ -public class ListBuckets { - static final String BUCKET_LIST = "BUCKET_LIST_FILTER"; - private static final ObjectReader READER = - new ObjectMapper().readerFor(ListBuckets.class); - private static final ObjectWriter WRITER; - - static { - ObjectMapper mapper = new ObjectMapper(); - String[] ignorableFieldNames = {"dataFileName"}; - - FilterProvider filters = new SimpleFilterProvider() - .addFilter(BUCKET_LIST, SimpleBeanPropertyFilter - .serializeAllExcept(ignorableFieldNames)); - mapper.setVisibility(PropertyAccessor.FIELD, - JsonAutoDetect.Visibility.ANY); - mapper.addMixIn(Object.class, MixIn.class); - - mapper.setFilterProvider(filters); - WRITER = mapper.writerWithDefaultPrettyPrinter(); - } - - private List buckets; - - /** - * Constructor for ListBuckets. - * @param buckets - List of buckets owned by this user - */ - public ListBuckets(List buckets) { - this.buckets = buckets; - - } - - /** - * Constructor for ListBuckets. - */ - public ListBuckets() { - this.buckets = new LinkedList(); - } - - /** - * Parses a String to return ListBuckets object. - * - * @param data - Json String - * - * @return - ListBuckets - * - * @throws IOException - */ - public static ListBuckets parse(String data) throws IOException { - return READER.readValue(data); - } - - /** - * Returns a list of Buckets. - * - * @return Bucket list - */ - public List getBuckets() { - return buckets; - } - - /** - * Sets the list of buckets owned by this user. - * - * @param buckets - List of Buckets - */ - public void setBuckets(List buckets) { - this.buckets = buckets; - } - - - /** - * Returns a JSON string of this object. - * After stripping out bytesUsed and keyCount - * - * @return String - */ - public String toJsonString() throws IOException { - return WRITER.writeValueAsString(this); - } - - /** - * Returns the Object as a Json String. - */ - public String toDBString() throws IOException { - return JsonUtils.toJsonString(this); - } - - /** - * Sorts the buckets based on bucketName. - * This is useful when we return the list of buckets - */ - public void sort() { - Collections.sort(buckets); - } - - /** - * Add a new bucket to the list of buckets. - * @param bucketInfo - bucket Info - */ - public void addBucket(BucketInfo bucketInfo){ - this.buckets.add(bucketInfo); - } - - /** - * This class allows us to create custom filters - * for the Json serialization. - */ - @JsonFilter(BUCKET_LIST) - class MixIn { - - } - -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/ListKeys.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/ListKeys.java deleted file mode 100644 index 9dc77d2c234..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/ListKeys.java +++ /dev/null @@ -1,209 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.web.response; - -import java.io.IOException; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; - -import org.apache.hadoop.ozone.web.handlers.BucketArgs; -import org.apache.hadoop.ozone.web.handlers.ListArgs; -import org.apache.hadoop.ozone.web.utils.JsonUtils; - -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.JsonFilter; -import com.fasterxml.jackson.annotation.PropertyAccessor; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ObjectReader; -import com.fasterxml.jackson.databind.ObjectWriter; -import com.fasterxml.jackson.databind.ser.FilterProvider; -import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; -import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; -import com.google.common.base.Preconditions; - -/** - * This class the represents the list of keys (Objects) in a bucket. - */ -public class ListKeys { - static final String OBJECT_LIST = "OBJECT_LIST_FILTER"; - - private static final ObjectReader READER = - new ObjectMapper().readerFor(ListKeys.class); - private static final ObjectWriter WRITER; - - static { - ObjectMapper mapper = new ObjectMapper(); - String[] ignorableFieldNames = {"dataFileName"}; - - FilterProvider filters = new SimpleFilterProvider() - .addFilter(OBJECT_LIST, SimpleBeanPropertyFilter - .serializeAllExcept(ignorableFieldNames)); - mapper.setVisibility(PropertyAccessor.FIELD, - JsonAutoDetect.Visibility.ANY); - mapper.addMixIn(Object.class, MixIn.class); - - mapper.setFilterProvider(filters); - WRITER = mapper.writerWithDefaultPrettyPrinter(); - } - - private String name; - private String prefix; - private long maxKeys; - private boolean truncated; - private List keyList; - - /** - * Default constructor needed for json serialization. - */ - public ListKeys() { - this.keyList = new LinkedList<>(); - } - - /** - * Constructor for ListKeys. - * - * @param args ListArgs - * @param truncated is truncated - */ - public ListKeys(ListArgs args, boolean truncated) { - Preconditions.checkState(args.getArgs() instanceof BucketArgs); - this.name = ((BucketArgs) args.getArgs()).getBucketName(); - this.prefix = args.getPrefix(); - this.maxKeys = args.getMaxKeys(); - this.truncated = truncated; - } - - /** - * Converts a Json string to POJO. - * @param jsonString - json string. - * @return ListObject - * @throws IOException - Json conversion error. - */ - public static ListKeys parse(String jsonString) throws IOException { - return READER.readValue(jsonString); - } - - /** - * Returns a list of Objects. - * - * @return List of KeyInfo Objects. - */ - public List getKeyList() { - return keyList; - } - - /** - * Sets the list of Objects. - * - * @param objectList - List of Keys - */ - public void setKeyList(List objectList) { - this.keyList = objectList; - } - - /** - * Gets the Max Key Count. - * - * @return long - */ - public long getMaxKeys() { - return maxKeys; - } - - /** - * Gets bucket Name. - * - * @return String - */ - public String getName() { - return name; - } - - /** - * Gets Prefix. - * - * @return String - */ - public String getPrefix() { - return prefix; - } - - /** - * Gets truncated Status. - * - * @return Boolean - */ - public boolean isTruncated() { - return truncated; - } - - /** - * Sets the value of truncated. - * - * @param value - Boolean - */ - public void setTruncated(boolean value) { - this.truncated = value; - } - - /** - * Returns a JSON string of this object. After stripping out bytesUsed and - * keyCount. - * - * @return String - * @throws IOException - On json Errors. - */ - public String toJsonString() throws IOException { - return WRITER.writeValueAsString(this); - } - - /** - * Returns the Object as a Json String. - * - * @return String - * @throws IOException - on json errors. - */ - public String toDBString() throws IOException { - return JsonUtils.toJsonString(this); - } - - /** - * Sorts the keys based on name and version. This is useful when we return the - * list of keys. - */ - public void sort() { - Collections.sort(keyList); - } - - /** - * Add a new key to the list of keys. - * @param keyInfo - key Info - */ - public void addKey(KeyInfo keyInfo){ - this.keyList.add(keyInfo); - } - - /** - * This class allows us to create custom filters for the Json serialization. - */ - @JsonFilter(OBJECT_LIST) - class MixIn { - - } -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/ListVolumes.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/ListVolumes.java deleted file mode 100644 index b918349d493..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/ListVolumes.java +++ /dev/null @@ -1,152 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.web.response; - -import java.io.IOException; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.ozone.web.utils.JsonUtils; - -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.JsonFilter; -import com.fasterxml.jackson.annotation.PropertyAccessor; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ObjectReader; -import com.fasterxml.jackson.databind.ObjectWriter; -import com.fasterxml.jackson.databind.ser.FilterProvider; -import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; -import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; - -/** - * List Volume Class is the class that is returned in JSON format to - * users when they call ListVolumes. - */ -@InterfaceAudience.Private -public class ListVolumes { - private List volumes; - - static final String VOLUME_LIST = "VOLUME_LIST_FILTER"; - private static final ObjectReader READER = - new ObjectMapper().readerFor(ListVolumes.class); - private static final ObjectWriter WRITER; - - static { - ObjectMapper mapper = new ObjectMapper(); - String[] ignorableFieldNames = {"bytesUsed", "bucketCount"}; - - FilterProvider filters = new SimpleFilterProvider() - .addFilter(VOLUME_LIST, SimpleBeanPropertyFilter - .serializeAllExcept(ignorableFieldNames)); - mapper.setVisibility(PropertyAccessor.FIELD, - JsonAutoDetect.Visibility.ANY); - mapper.addMixIn(Object.class, MixIn.class); - - mapper.setFilterProvider(filters); - WRITER = mapper.writerWithDefaultPrettyPrinter(); - } - - /** - * Used for json filtering. - */ - @JsonFilter(VOLUME_LIST) - class MixIn { - } - - /** - * Constructs ListVolume objects. - */ - public ListVolumes() { - this.volumes = new LinkedList(); - } - - /** - * Gets the list of volumes. - * - * @return List of VolumeInfo Objects - */ - public List getVolumes() { - return volumes; - } - - - /** - * Sets volume info. - * - * @param volumes - List of Volumes - */ - public void setVolumes(List volumes) { - this.volumes = volumes; - } - - /** - * Returns a JSON string of this object. - * After stripping out bytesUsed and bucketCount - * - * @return String - */ - public String toJsonString() throws IOException { - return WRITER.writeValueAsString(this); - } - - /** - * When we serialize a volumeInfo to our database - * we will use all fields. However the toJsonString - * will strip out bytesUsed and bucketCount from the - * volume Info - * - * @return Json String - * - * @throws IOException - */ - public String toDBString() throws IOException { - return JsonUtils.toJsonString(this); - } - - /** - * Parses a String to return ListVolumes object. - * - * @param data - Json String - * - * @return - ListVolumes - * - * @throws IOException - */ - public static ListVolumes parse(String data) throws IOException { - return READER.readValue(data); - } - - /** - * Adds a new volume info to the List. - * - * @param info - VolumeInfo - */ - public void addVolume(VolumeInfo info) { - this.volumes.add(info); - } - - /** - * Sorts the volume names based on volume name. - * This is useful when we return the list of volume names - */ - public void sort() { - Collections.sort(volumes); - } -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/VolumeInfo.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/VolumeInfo.java deleted file mode 100644 index 112b27e5415..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/VolumeInfo.java +++ /dev/null @@ -1,308 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.web.response; - - -import java.io.IOException; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.ozone.web.request.OzoneQuota; -import org.apache.hadoop.ozone.web.utils.JsonUtils; - -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.JsonFilter; -import com.fasterxml.jackson.annotation.PropertyAccessor; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ObjectReader; -import com.fasterxml.jackson.databind.ObjectWriter; -import com.fasterxml.jackson.databind.ser.FilterProvider; -import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; -import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; - -/** - * VolumeInfo Class is the Java class that represents - * Json when VolumeInfo Call is made. - */ -@InterfaceAudience.Private -public class VolumeInfo implements Comparable { - - static final String VOLUME_INFO = "VOLUME_INFO_FILTER"; - private static final ObjectReader READER = - new ObjectMapper().readerFor(VolumeInfo.class); - private static final ObjectWriter WRITER; - - static { - ObjectMapper mapper = new ObjectMapper(); - String[] ignorableFieldNames = {"bytesUsed", "bucketCount"}; - - FilterProvider filters = new SimpleFilterProvider() - .addFilter(VOLUME_INFO, SimpleBeanPropertyFilter - .serializeAllExcept(ignorableFieldNames)); - mapper.setVisibility(PropertyAccessor.FIELD, - JsonAutoDetect.Visibility.ANY); - mapper.addMixIn(Object.class, MixIn.class); - - mapper.setFilterProvider(filters); - WRITER = mapper.writerWithDefaultPrettyPrinter(); - } - - /** - * Custom Json Filter Class. - */ - @JsonFilter(VOLUME_INFO) - class MixIn { - } - private VolumeOwner owner; - private OzoneQuota quota; - private String volumeName; - private String createdOn; - private String createdBy; - - private long bytesUsed; - private long bucketCount; - - - /** - * Constructor for VolumeInfo. - * - * @param volumeName - Name of the Volume - * @param createdOn _ Date String - * @param createdBy - Person who created it - */ - public VolumeInfo(String volumeName, String createdOn, String createdBy) { - this.createdOn = createdOn; - this.volumeName = volumeName; - this.createdBy = createdBy; - } - - /** - * Constructor for VolumeInfo. - */ - public VolumeInfo() { - } - - /** - * Returns the name of the person who created this volume. - * - * @return Name of Admin who created this - */ - public String getCreatedBy() { - return createdBy; - } - - /** - * Sets the user name of the person who created this volume. - * - * @param createdBy - UserName - */ - public void setCreatedBy(String createdBy) { - this.createdBy = createdBy; - } - - /** - * Gets the date on which this volume was created. - * - * @return - Date String - */ - public String getCreatedOn() { - return createdOn; - } - - /** - * Sets the date string. - * - * @param createdOn - Date String - */ - public void setCreatedOn(String createdOn) { - this.createdOn = createdOn; - } - - /** - * Returns the owner info. - * - * @return - OwnerInfo - */ - public VolumeOwner getOwner() { - return owner; - } - - /** - * Sets the owner. - * - * @param owner - OwnerInfo - */ - public void setOwner(VolumeOwner owner) { - this.owner = owner; - } - - /** - * Returns the quota information on a volume. - * - * @return Quota - */ - public OzoneQuota getQuota() { - return quota; - } - - /** - * Sets the quota info. - * - * @param quota - Quota Info - */ - public void setQuota(OzoneQuota quota) { - this.quota = quota; - } - - /** - * gets the volume name. - * - * @return - Volume Name - */ - public String getVolumeName() { - return volumeName; - } - - /** - * Sets the volume name. - * - * @param volumeName - Volume Name - */ - public void setVolumeName(String volumeName) { - this.volumeName = volumeName; - } - - /** - * Returns a JSON string of this object. - * After stripping out bytesUsed and bucketCount - * - * @return String - json string - * @throws IOException - */ - public String toJsonString() throws IOException { - return WRITER.writeValueAsString(this); - } - - /** - * When we serialize a volumeInfo to our database - * we will use all fields. However the toJsonString - * will strip out bytesUsed and bucketCount from the - * volume Info - * - * @return Json String - * - * @throws IOException - */ - public String toDBString() throws IOException { - return JsonUtils.toJsonString(this); - } - - - /** - * Comparable Interface. - * @param o VolumeInfo Object. - * @return Result of comparison - */ - @Override - public int compareTo(VolumeInfo o) { - return this.volumeName.compareTo(o.getVolumeName()); - } - - /** - * Gets the number of bytesUsed by this volume. - * - * @return long - Bytes used - */ - public long getBytesUsed() { - return bytesUsed; - } - - /** - * Sets number of bytesUsed by this volume. - * - * @param bytesUsed - Number of bytesUsed - */ - public void setBytesUsed(long bytesUsed) { - this.bytesUsed = bytesUsed; - } - - /** - * Returns VolumeInfo class from json string. - * - * @param data - Json String - * - * @return VolumeInfo - * - * @throws IOException - */ - public static VolumeInfo parse(String data) throws IOException { - return READER.readValue(data); - } - - /** - * Indicates whether some other object is "equal to" this one. - * - * @param obj the reference object with which to compare. - * - * @return {@code true} if this object is the same as the obj - * argument; {@code false} otherwise. - */ - @Override - public boolean equals(Object obj) { - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - VolumeInfo otherInfo = (VolumeInfo) obj; - return otherInfo.getVolumeName().equals(this.getVolumeName()); - } - - /** - * Returns a hash code value for the object. This method is - * supported for the benefit of hash tables such as those provided by - * HashMap. - * @return a hash code value for this object. - * - * @see Object#equals(Object) - * @see System#identityHashCode - */ - @Override - public int hashCode() { - return getVolumeName().hashCode(); - } - - /** - * Total number of buckets under this volume. - * - * @return - bucketCount - */ - public long getBucketCount() { - return bucketCount; - } - - /** - * Sets the buckets count. - * - * @param bucketCount - Bucket Count - */ - public void setBucketCount(long bucketCount) { - this.bucketCount = bucketCount; - } -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/VolumeOwner.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/VolumeOwner.java deleted file mode 100644 index afb0460538c..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/VolumeOwner.java +++ /dev/null @@ -1,60 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.web.response; - -import com.fasterxml.jackson.annotation.JsonInclude; -import org.apache.hadoop.classification.InterfaceAudience; - -/** - * Volume Owner represents the owner of a volume. - * - * This is a class instead of a string since we might need to extend this class - * to support other forms of authentication. - */ -@InterfaceAudience.Private -public class VolumeOwner { - @JsonInclude(JsonInclude.Include.NON_NULL) - private String name; - - /** - * Constructor for VolumeOwner. - * - * @param name - name of the User - */ - public VolumeOwner(String name) { - this.name = name; - } - - /** - * Constructs Volume Owner. - */ - public VolumeOwner() { - name = null; - } - - /** - * Returns the user name. - * - * @return Name - */ - public String getName() { - return name; - } - -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/package-info.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/package-info.java deleted file mode 100644 index 3bf66c861be..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/response/package-info.java +++ /dev/null @@ -1,23 +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 - * - * 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. - */ - -/** - * Netty-based HTTP server implementation for Ozone. - */ -package org.apache.hadoop.ozone.web.response; \ No newline at end of file diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/utils/OzoneUtils.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/utils/OzoneUtils.java deleted file mode 100644 index 22fff56d7d7..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/utils/OzoneUtils.java +++ /dev/null @@ -1,227 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.web.utils; - -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.nio.charset.Charset; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Locale; -import java.util.TimeZone; -import java.util.UUID; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdds.HddsUtils; -import org.apache.hadoop.ozone.OzoneConsts; - -import com.google.common.base.Preconditions; - -/** - * Set of Utility functions used in ozone. - */ -@InterfaceAudience.Private -public final class OzoneUtils { - - public static final String ENCODING_NAME = "UTF-8"; - public static final Charset ENCODING = Charset.forName(ENCODING_NAME); - - private OzoneUtils() { - // Never constructed - } - - /** - * Date format that used in ozone. Here the format is thread safe to use. - */ - private static final ThreadLocal DATE_FORMAT = - new ThreadLocal() { - @Override - protected SimpleDateFormat initialValue() { - SimpleDateFormat format = new SimpleDateFormat( - OzoneConsts.OZONE_DATE_FORMAT, Locale.US); - format.setTimeZone(TimeZone.getTimeZone(OzoneConsts.OZONE_TIME_ZONE)); - - return format; - } - }; - - /** - * Verifies that max key length is a valid value. - * - * @param length - * The max key length to be validated - * - * @throws IllegalArgumentException - */ - public static void verifyMaxKeyLength(String length) - throws IllegalArgumentException { - int maxKey = 0; - try { - maxKey = Integer.parseInt(length); - } catch (NumberFormatException nfe) { - throw new IllegalArgumentException( - "Invalid max key length, the vaule should be digital."); - } - - if (maxKey <= 0) { - throw new IllegalArgumentException( - "Invalid max key length, the vaule should be a positive number."); - } - } - - /** - * Returns a random Request ID. - * - * Request ID is returned to the client as well as flows through the system - * facilitating debugging on why a certain request failed. - * - * @return String random request ID - */ - public static String getRequestID() { - return UUID.randomUUID().toString(); - } - - /** - * Return host name if possible. - * - * @return Host Name or localhost - */ - public static String getHostName() { - String host = "localhost"; - try { - host = InetAddress.getLocalHost().getHostName(); - } catch (UnknownHostException e) { - // Ignore the error - } - return host; - } - - /** - * Get the path for datanode id file. - * - * @param conf - Configuration - * @return the path of datanode id as string - */ - public static String getDatanodeIdFilePath(Configuration conf) { - return HddsUtils.getDatanodeIdFilePath(conf); - } - - /** - * Convert time in millisecond to a human readable format required in ozone. - * @return a human readable string for the input time - */ - public static String formatTime(long millis) { - return DATE_FORMAT.get().format(millis); - } - - /** - * Convert time in ozone date format to millisecond. - * @return time in milliseconds - */ - public static long formatDate(String date) throws ParseException { - Preconditions.checkNotNull(date, "Date string should not be null."); - return DATE_FORMAT.get().parse(date).getTime(); - } - - public static boolean isOzoneEnabled(Configuration conf) { - return HddsUtils.isHddsEnabled(conf); - } - - - /** - * verifies that bucket name / volume name is a valid DNS name. - * - * @param resName Bucket or volume Name to be validated - * - * @throws IllegalArgumentException - */ - public static void verifyResourceName(String resName) - throws IllegalArgumentException { - - if (resName == null) { - throw new IllegalArgumentException("Bucket or Volume name is null"); - } - - if ((resName.length() < OzoneConsts.OZONE_MIN_BUCKET_NAME_LENGTH) || - (resName.length() > OzoneConsts.OZONE_MAX_BUCKET_NAME_LENGTH)) { - throw new IllegalArgumentException( - "Bucket or Volume length is illegal, " + - "valid length is 3-63 characters"); - } - - if ((resName.charAt(0) == '.') || (resName.charAt(0) == '-')) { - throw new IllegalArgumentException( - "Bucket or Volume name cannot start with a period or dash"); - } - - if ((resName.charAt(resName.length() - 1) == '.') || - (resName.charAt(resName.length() - 1) == '-')) { - throw new IllegalArgumentException( - "Bucket or Volume name cannot end with a period or dash"); - } - - boolean isIPv4 = true; - char prev = (char) 0; - - for (int index = 0; index < resName.length(); index++) { - char currChar = resName.charAt(index); - - if (currChar != '.') { - isIPv4 = ((currChar >= '0') && (currChar <= '9')) && isIPv4; - } - - if (currChar > 'A' && currChar < 'Z') { - throw new IllegalArgumentException( - "Bucket or Volume name does not support uppercase characters"); - } - - if ((currChar != '.') && (currChar != '-')) { - if ((currChar < '0') || (currChar > '9' && currChar < 'a') || - (currChar > 'z')) { - throw new IllegalArgumentException("Bucket or Volume name has an " + - "unsupported character : " + - currChar); - } - } - - if ((prev == '.') && (currChar == '.')) { - throw new IllegalArgumentException("Bucket or Volume name should not " + - "have two contiguous periods"); - } - - if ((prev == '-') && (currChar == '.')) { - throw new IllegalArgumentException( - "Bucket or Volume name should not have period after dash"); - } - - if ((prev == '.') && (currChar == '-')) { - throw new IllegalArgumentException( - "Bucket or Volume name should not have dash after period"); - } - prev = currChar; - } - - if (isIPv4) { - throw new IllegalArgumentException( - "Bucket or Volume name cannot be an IPv4 address or all numeric"); - } - } - -} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/utils/package-info.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/utils/package-info.java deleted file mode 100644 index 178157fcacc..00000000000 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/web/utils/package-info.java +++ /dev/null @@ -1,18 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.web.utils; diff --git a/hadoop-ozone/common/src/main/proto/OzoneManagerProtocol.proto b/hadoop-ozone/common/src/main/proto/OzoneManagerProtocol.proto deleted file mode 100644 index 975c790f784..00000000000 --- a/hadoop-ozone/common/src/main/proto/OzoneManagerProtocol.proto +++ /dev/null @@ -1,481 +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 - * - * 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. - */ - -/** - * These .proto interfaces are private and unstable. - * Please see http://wiki.apache.org/hadoop/Compatibility - * for what changes are allowed for a *unstable* .proto interface. - */ - -option java_package = "org.apache.hadoop.ozone.protocol.proto"; -option java_outer_classname = "OzoneManagerProtocolProtos"; -option java_generic_services = true; -option java_generate_equals_and_hash = true; -package hadoop.ozone; - -/** -This is file contains the protocol to communicate with -Ozone Manager. Ozone Manager manages the namespace for ozone. -This is similar to Namenode for Ozone. -*/ - -import "hdfs.proto"; -import "hdds.proto"; - -enum Status { - OK = 1; - VOLUME_NOT_UNIQUE = 2; - VOLUME_NOT_FOUND = 3; - VOLUME_NOT_EMPTY = 4; - VOLUME_ALREADY_EXISTS = 5; - USER_NOT_FOUND = 6; - USER_TOO_MANY_VOLUMES = 7; - BUCKET_NOT_FOUND = 8; - BUCKET_NOT_EMPTY = 9; - BUCKET_ALREADY_EXISTS = 10; - KEY_ALREADY_EXISTS = 11; - KEY_NOT_FOUND = 12; - INVALID_KEY_NAME = 13; - ACCESS_DENIED = 14; - INTERNAL_ERROR = 15; - KEY_ALLOCATION_ERROR = 16; - KEY_DELETION_ERROR = 17; - KEY_RENAME_ERROR = 18; - METADATA_ERROR = 19; - OM_NOT_INITIALIZED = 20; - SCM_VERSION_MISMATCH_ERROR = 21; -} - - -message VolumeInfo { - required string adminName = 1; - required string ownerName = 2; - required string volume = 3; - optional uint64 quotaInBytes = 4; - repeated hadoop.hdds.KeyValue metadata = 5; - repeated OzoneAclInfo volumeAcls = 6; - required uint64 creationTime = 7; -} - -/** - Creates a volume -*/ -message CreateVolumeRequest { - required VolumeInfo volumeInfo = 1; -} - -message CreateVolumeResponse { - - required Status status = 1; -} - -message VolumeList { - repeated string volumeNames = 1; -} - -/** - Changes the Volume Properties -- like ownership and quota for a volume. -*/ -message SetVolumePropertyRequest { - required string volumeName = 1; - optional string ownerName = 2; - optional uint64 quotaInBytes = 3; -} - -message SetVolumePropertyResponse { - required Status status = 1; -} - -/** - * Checks if the user has specified permissions for the volume - */ -message CheckVolumeAccessRequest { - required string volumeName = 1; - required OzoneAclInfo userAcl = 2; -} - -message CheckVolumeAccessResponse { - - required Status status = 1; -} - - -/** - Returns information about a volume. -*/ - -message InfoVolumeRequest { - required string volumeName = 1; -} - -message InfoVolumeResponse { - required Status status = 1; - optional VolumeInfo volumeInfo = 2; - -} - -/** - Deletes an existing volume. -*/ -message DeleteVolumeRequest { - required string volumeName = 1; -} - -message DeleteVolumeResponse { - required Status status = 1; -} - - -/** - List Volumes -- List all volumes in the cluster or by user. -*/ - -message ListVolumeRequest { - enum Scope { - USER_VOLUMES = 1; // User volumes -- called by user - VOLUMES_BY_USER = 2; // User volumes - called by Admin - VOLUMES_BY_CLUSTER = 3; // All volumes in the cluster - } - required Scope scope = 1; - optional string userName = 2; - optional string prefix = 3; - optional string prevKey = 4; - optional uint32 maxKeys = 5; -} - -message ListVolumeResponse { - required Status status = 1; - repeated VolumeInfo volumeInfo = 2; -} - -message BucketInfo { - required string volumeName = 1; - required string bucketName = 2; - repeated OzoneAclInfo acls = 3; - required bool isVersionEnabled = 4 [default = false]; - required hadoop.hdfs.StorageTypeProto storageType = 5 [default = DISK]; - required uint64 creationTime = 6; -} - -message BucketArgs { - required string volumeName = 1; - required string bucketName = 2; - repeated OzoneAclInfo addAcls = 3; - repeated OzoneAclInfo removeAcls = 4; - optional bool isVersionEnabled = 5; - optional hadoop.hdfs.StorageTypeProto storageType = 6; -} - -message OzoneAclInfo { - enum OzoneAclType { - USER = 1; - GROUP = 2; - WORLD = 3; - } - enum OzoneAclRights { - READ = 1; - WRITE = 2; - READ_WRITE = 3; - } - required OzoneAclType type = 1; - required string name = 2; - required OzoneAclRights rights = 3; -} - -message CreateBucketRequest { - required BucketInfo bucketInfo = 1; -} - -message CreateBucketResponse { - required Status status = 1; -} - -message InfoBucketRequest { - required string volumeName = 1; - required string bucketName = 2; -} - -message InfoBucketResponse { - required Status status = 1; - optional BucketInfo bucketInfo = 2; -} - -message ListBucketsRequest { - required string volumeName = 1; - optional string startKey = 2; - optional string prefix = 3; - optional int32 count = 4; -} - -message ListBucketsResponse { - required Status status = 1; - repeated BucketInfo bucketInfo = 2; -} - -message KeyArgs { - required string volumeName = 1; - required string bucketName = 2; - required string keyName = 3; - optional uint64 dataSize = 4; - optional hadoop.hdds.ReplicationType type = 5; - optional hadoop.hdds.ReplicationFactor factor = 6; - repeated KeyLocation keyLocations = 7; -} - -message KeyLocation { - required hadoop.hdds.BlockID blockID = 1; - required bool shouldCreateContainer = 2; - required uint64 offset = 3; - required uint64 length = 4; - // indicated at which version this block gets created. - optional uint64 createVersion = 5; -} - -message KeyLocationList { - optional uint64 version = 1; - repeated KeyLocation keyLocations = 2; -} - -message KeyInfo { - required string volumeName = 1; - required string bucketName = 2; - required string keyName = 3; - required uint64 dataSize = 4; - required hadoop.hdds.ReplicationType type = 5; - required hadoop.hdds.ReplicationFactor factor = 6; - repeated KeyLocationList keyLocationList = 7; - required uint64 creationTime = 8; - required uint64 modificationTime = 9; - optional uint64 latestVersion = 10; -} - -message LocateKeyRequest { - required KeyArgs keyArgs = 1; -} - -message LocateKeyResponse { - required Status status = 1; - optional KeyInfo keyInfo = 2; - // clients' followup request may carry this ID for stateful operations (similar - // to a cookie). - optional uint64 ID = 3; - // TODO : allow specifiying a particular version to read. - optional uint64 openVersion = 4; -} - -message SetBucketPropertyRequest { - required BucketArgs bucketArgs = 1; -} - -message SetBucketPropertyResponse { - required Status status = 1; -} - -message RenameKeyRequest{ - required KeyArgs keyArgs = 1; - required string toKeyName = 2; -} - -message RenameKeyResponse{ - required Status status = 1; -} - -message DeleteBucketRequest { - required string volumeName = 1; - required string bucketName = 2; -} - -message DeleteBucketResponse { - required Status status = 1; -} - -message ListKeysRequest { - required string volumeName = 1; - required string bucketName = 2; - optional string startKey = 3; - optional string prefix = 4; - optional int32 count = 5; -} - -message ListKeysResponse { - required Status status = 1; - repeated KeyInfo keyInfo = 2; -} - -message AllocateBlockRequest { - required KeyArgs keyArgs = 1; - required uint64 clientID = 2; -} - -message AllocateBlockResponse { - required Status status = 1; - optional KeyLocation keyLocation = 2; -} - -message CommitKeyRequest { - required KeyArgs keyArgs = 1; - required uint64 clientID = 2; -} - -message CommitKeyResponse { - required Status status = 1; -} - -message ServiceListRequest { -} - -message ServiceListResponse { - required Status status = 1; - repeated ServiceInfo serviceInfo = 2; -} - -message ServicePort { - enum Type { - RPC = 1; - HTTP = 2; - HTTPS = 3; - RATIS = 4; - }; - required Type type = 1; - required uint32 value = 2; -} - -message ServiceInfo { - required hadoop.hdds.NodeType nodeType = 1; - required string hostname = 2; - repeated ServicePort servicePorts = 3; -} - -/** - The OM service that takes care of Ozone namespace. -*/ -service OzoneManagerService { - - /** - Creates a Volume. - */ - rpc createVolume(CreateVolumeRequest) - returns(CreateVolumeResponse); - - /** - Allows modificiation of volume properties. - */ - rpc setVolumeProperty(SetVolumePropertyRequest) - returns (SetVolumePropertyResponse); - - /** - Checks if the specified volume is accesible by the specified user. - */ - rpc checkVolumeAccess(CheckVolumeAccessRequest) - returns (CheckVolumeAccessResponse); - - /** - Gets Volume information. - */ - rpc infoVolume(InfoVolumeRequest) - returns(InfoVolumeResponse); - /** - Deletes a volume if it is empty. - */ - rpc deleteVolume(DeleteVolumeRequest) - returns (DeleteVolumeResponse); - - /** - Lists Volumes - */ - rpc listVolumes(ListVolumeRequest) - returns (ListVolumeResponse); - - /** - Creates a Bucket. - */ - rpc createBucket(CreateBucketRequest) - returns(CreateBucketResponse); - - /** - Get Bucket information. - */ - rpc infoBucket(InfoBucketRequest) - returns(InfoBucketResponse); - - /** - Sets bucket properties. - */ - rpc setBucketProperty(SetBucketPropertyRequest) - returns(SetBucketPropertyResponse); - - /** - Get key. - */ - rpc createKey(LocateKeyRequest) - returns(LocateKeyResponse); - - /** - Look up for an existing key. - */ - rpc lookupKey(LocateKeyRequest) - returns(LocateKeyResponse); - - /** - Rename an existing key within a bucket. - */ - rpc renameKey(RenameKeyRequest) - returns(RenameKeyResponse); - - /** - Delete an existing key. - */ - rpc deleteKey(LocateKeyRequest) - returns(LocateKeyResponse); - - /** - Deletes a bucket from volume if it is empty. - */ - rpc deleteBucket(DeleteBucketRequest) - returns (DeleteBucketResponse); - - /** - List Buckets. - */ - rpc listBuckets(ListBucketsRequest) - returns(ListBucketsResponse); - - /** - List Keys. - */ - rpc listKeys(ListKeysRequest) - returns(ListKeysResponse); - - /** - Commit a key. - */ - rpc commitKey(CommitKeyRequest) - returns(CommitKeyResponse); - - /** - Allocate a new block for a key. - */ - rpc allocateBlock(AllocateBlockRequest) - returns(AllocateBlockResponse); - - /** - Returns list of Ozone services with its configuration details. - */ - rpc getServiceList(ServiceListRequest) - returns(ServiceListResponse); -} diff --git a/hadoop-ozone/common/src/main/resources/ozone-version-info.properties b/hadoop-ozone/common/src/main/resources/ozone-version-info.properties deleted file mode 100644 index 599f14d5eca..00000000000 --- a/hadoop-ozone/common/src/main/resources/ozone-version-info.properties +++ /dev/null @@ -1,27 +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 -# -# 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. -# - -version=${declared.ozone.version} -release=${ozone.release} -revision=${version-info.scm.commit} -branch=${version-info.scm.branch} -user=${user.name} -date=${version-info.build.time} -url=${version-info.scm.uri} -srcChecksum=${version-info.source.md5} -protocVersion=${protobuf.version} diff --git a/hadoop-ozone/common/src/main/shellprofile.d/hadoop-ozone.sh b/hadoop-ozone/common/src/main/shellprofile.d/hadoop-ozone.sh deleted file mode 100644 index 3fff7f5f354..00000000000 --- a/hadoop-ozone/common/src/main/shellprofile.d/hadoop-ozone.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash -# 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. - -if [[ "${HADOOP_SHELL_EXECNAME}" = ozone ]]; then - hadoop_add_profile ozone -fi - - diff --git a/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/web/TestBucketInfo.java b/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/web/TestBucketInfo.java deleted file mode 100644 index 2e699225947..00000000000 --- a/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/web/TestBucketInfo.java +++ /dev/null @@ -1,81 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.web; - - -import org.apache.hadoop.fs.StorageType; -import org.apache.hadoop.ozone.OzoneAcl; -import org.apache.hadoop.ozone.web.response.BucketInfo; -import org.apache.hadoop.ozone.OzoneConsts; -import org.junit.Test; - -import java.io.IOException; -import java.util.LinkedList; -import java.util.List; - -/** - * Test Ozone Bucket Info operation. - */ -public class TestBucketInfo { - @Test - public void testBucketInfoJson() throws IOException { - BucketInfo bucketInfo = new BucketInfo("volumeName", "bucketName"); - String bucketInfoString = bucketInfo.toJsonString(); - BucketInfo newBucketInfo = BucketInfo.parse(bucketInfoString); - assert(bucketInfo.equals(newBucketInfo)); - } - - @Test - public void testBucketInfoDBString() throws IOException { - BucketInfo bucketInfo = new BucketInfo("volumeName", "bucketName"); - String bucketInfoString = bucketInfo.toDBString(); - BucketInfo newBucketInfo = BucketInfo.parse(bucketInfoString); - assert(bucketInfo.equals(newBucketInfo)); - } - - @Test - public void testBucketInfoAddAcls() throws IOException { - BucketInfo bucketInfo = new BucketInfo("volumeName", "bucketName"); - String bucketInfoString = bucketInfo.toDBString(); - BucketInfo newBucketInfo = BucketInfo.parse(bucketInfoString); - assert(bucketInfo.equals(newBucketInfo)); - List aclList = new LinkedList<>(); - - aclList.add(OzoneAcl.parseAcl("user:bilbo:r")); - aclList.add(OzoneAcl.parseAcl("user:samwise:rw")); - newBucketInfo.setAcls(aclList); - - assert(newBucketInfo.getAcls() != null); - assert(newBucketInfo.getAcls().size() == 2); - } - - - @Test - public void testBucketInfoVersionAndType() throws IOException { - BucketInfo bucketInfo = new BucketInfo("volumeName", "bucketName"); - bucketInfo.setVersioning(OzoneConsts.Versioning.ENABLED); - bucketInfo.setStorageType(StorageType.DISK); - - String bucketInfoString = bucketInfo.toDBString(); - - BucketInfo newBucketInfo = BucketInfo.parse(bucketInfoString); - assert(bucketInfo.equals(newBucketInfo)); - } - -} diff --git a/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/web/TestQuota.java b/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/web/TestQuota.java deleted file mode 100644 index d777d0cd897..00000000000 --- a/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/web/TestQuota.java +++ /dev/null @@ -1,116 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.web; - -import org.apache.hadoop.ozone.web.request.OzoneQuota; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Set; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -/** - * Test Ozone Volume Quota. - */ -public class TestQuota { - @Test - public void testParseQuota() { - HashMap testMatrix; - testMatrix = new HashMap(); - - testMatrix.put("10TB", Boolean.TRUE); - testMatrix.put("1 TB", Boolean.TRUE); - testMatrix.put("0MB", Boolean.TRUE); - testMatrix.put("0 TB", Boolean.TRUE); - testMatrix.put(" 1000MB ", Boolean.TRUE); - - testMatrix.put(" 1000MBMB ", Boolean.FALSE); - testMatrix.put(" 1000MB00 ", Boolean.FALSE); - testMatrix.put("1000ZMB", Boolean.FALSE); - testMatrix.put("MB1000", Boolean.FALSE); - testMatrix.put("9999", Boolean.FALSE); - testMatrix.put("1", Boolean.FALSE); - testMatrix.put("remove", Boolean.FALSE); - testMatrix.put("1UNDEFINED", Boolean.FALSE); - testMatrix.put(null, Boolean.FALSE); - testMatrix.put("", Boolean.FALSE); - testMatrix.put("-1000MB", Boolean.FALSE); - testMatrix.put("1024 bytes", Boolean.TRUE); - testMatrix.put("1bytes", Boolean.TRUE); - testMatrix.put("0bytes", Boolean.TRUE); - testMatrix.put("10000 BYTES", Boolean.TRUE); - testMatrix.put("BYTESbytes", Boolean.FALSE); - testMatrix.put("bytes", Boolean.FALSE); - - Set keys = testMatrix.keySet(); - for (String key : keys) { - if (testMatrix.get(key)) { - OzoneQuota.parseQuota(key); - } else { - try { - OzoneQuota.parseQuota(key); - // should never get here since the isValid call will throw - fail(key); - fail("An exception was expected but did not happen."); - } catch (IllegalArgumentException e) { - - } - } - } - } - - @Test - public void testVerifyQuota() { - OzoneQuota qt = OzoneQuota.parseQuota("10TB"); - assertEquals(qt.getSize(), 10); - assertEquals(qt.getUnit(), OzoneQuota.Units.TB); - assertEquals(qt.sizeInBytes(), 10L * (1024L * 1024L * 1024L * 1024L)); - - qt = OzoneQuota.parseQuota("10MB"); - assertEquals(qt.getSize(), 10); - assertEquals(qt.getUnit(), OzoneQuota.Units.MB); - assertEquals(qt.sizeInBytes(), 10L * (1024L * 1024L)); - - qt = OzoneQuota.parseQuota("10GB"); - assertEquals(qt.getSize(), 10); - assertEquals(qt.getUnit(), OzoneQuota.Units.GB); - assertEquals(qt.sizeInBytes(), 10L * (1024L * 1024L * 1024L)); - - qt = OzoneQuota.parseQuota("10BYTES"); - assertEquals(qt.getSize(), 10); - assertEquals(qt.getUnit(), OzoneQuota.Units.BYTES); - assertEquals(qt.sizeInBytes(), 10L); - - OzoneQuota emptyQuota = new OzoneQuota(); - assertEquals(emptyQuota.sizeInBytes(), -1L); - assertEquals(emptyQuota.getSize(), 0); - assertEquals(emptyQuota.getUnit(), OzoneQuota.Units.UNDEFINED); - } - - @Test - public void testVerifyRemove() { - assertTrue(OzoneQuota.isRemove("remove")); - assertFalse(OzoneQuota.isRemove("not remove")); - assertFalse(OzoneQuota.isRemove(null)); - } -} diff --git a/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/web/TestUtils.java b/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/web/TestUtils.java deleted file mode 100644 index d3f8f5e659c..00000000000 --- a/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/web/TestUtils.java +++ /dev/null @@ -1,101 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.ozone.web; - -import org.junit.Test; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Set; - -import static org.apache.hadoop.ozone.web.utils.OzoneUtils.getRequestID; -import static org.apache.hadoop.ozone.web.utils.OzoneUtils.verifyResourceName; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -/** - * Test Ozone Utility operations like verifying resource name. - */ -public class TestUtils { - - /** - * Tests if the bucket name handling is correct. - */ - @Test - public void testValidBucketNames() { - HashMap testMatrix; - // Init the Table with Strings and Expected Return values - testMatrix = new HashMap(); - - testMatrix.put("bucket-.ozone.self", Boolean.FALSE); - testMatrix.put("bucket.-ozone.self", Boolean.FALSE); - testMatrix.put(".bucket.ozone.self", Boolean.FALSE); - testMatrix.put("bucket.ozone.self.", Boolean.FALSE); - testMatrix.put("bucket..ozone.self", Boolean.FALSE); - testMatrix.put("192.1.1.1", Boolean.FALSE); - testMatrix.put("ab", Boolean.FALSE); - testMatrix.put("bucket.ozone.self.this.is.a.really.long.name.that." - + "is.more.than.sixty.three.characters.long.for.sure", Boolean.FALSE); - testMatrix.put(null, Boolean.FALSE); - testMatrix.put("bucket@$", Boolean.FALSE); - testMatrix.put("BUCKET", Boolean.FALSE); - testMatrix.put("bucket .ozone.self", Boolean.FALSE); - testMatrix.put(" bucket.ozone.self", Boolean.FALSE); - testMatrix.put("bucket.ozone.self-", Boolean.FALSE); - testMatrix.put("-bucket.ozone.self", Boolean.FALSE); - - testMatrix.put("bucket", Boolean.TRUE); - testMatrix.put("bucket.ozone.self", Boolean.TRUE); - testMatrix.put("bucket.ozone.self", Boolean.TRUE); - testMatrix.put("bucket-name.ozone.self", Boolean.TRUE); - testMatrix.put("bucket.1.ozone.self", Boolean.TRUE); - - Set keys = testMatrix.keySet(); - for (String key : keys) { - if (testMatrix.get(key)) { - - // For valid names there should be no exceptions at all - verifyResourceName(key); - } else { - try { - verifyResourceName(key); - // should never get here since the isValid call will throw - fail("An exception was expected but did not happen."); - } catch (IllegalArgumentException e) { - - } - } - } - } - - /** - * Just calls Request ID many times and assert we - * got different values, ideally this should be - * run under parallel threads. Since the function under - * test has no external dependencies it is assumed - * that this test is good enough. - */ - @Test - public void testRequestIDisRandom() { - HashSet set = new HashSet<>(); - for (int i = 0; i < 1000; i++) { - assertTrue(set.add(getRequestID())); - } - } -} diff --git a/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/web/TestVolumeStructs.java b/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/web/TestVolumeStructs.java deleted file mode 100644 index b433be6fb51..00000000000 --- a/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/web/TestVolumeStructs.java +++ /dev/null @@ -1,73 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package org.apache.hadoop.ozone.web; - -import org.apache.hadoop.ozone.web.response.ListVolumes; -import org.apache.hadoop.ozone.web.response.VolumeInfo; -import org.apache.hadoop.ozone.web.response.VolumeOwner; -import org.junit.Test; - -import java.io.IOException; - -import static org.junit.Assert.assertEquals; - -/** - * Test Ozone Volume info structure. - */ -public class TestVolumeStructs { - - @Test - public void testVolumeInfoParse() throws IOException { - VolumeInfo volInfo = - new VolumeInfo("testvol", "Thu, Apr 9, 2015 10:23:45 GMT", "gandalf"); - VolumeOwner owner = new VolumeOwner("bilbo"); - volInfo.setOwner(owner); - String jString = volInfo.toJsonString(); - VolumeInfo newVollInfo = VolumeInfo.parse(jString); - String one = volInfo.toJsonString(); - String two = newVollInfo.toJsonString(); - - assertEquals(volInfo.toJsonString(), newVollInfo.toJsonString()); - } - - @Test - public void testVolumeInfoValue() throws IOException { - String createdOn = "Thu, Apr 9, 2015 10:23:45 GMT"; - String createdBy = "gandalf"; - VolumeInfo volInfo = new VolumeInfo("testvol", createdOn, createdBy); - assertEquals(volInfo.getCreatedBy(), createdBy); - assertEquals(volInfo.getCreatedOn(), createdOn); - } - - - @Test - public void testVolumeListParse() throws IOException { - ListVolumes list = new ListVolumes(); - for (int x = 0; x < 100; x++) { - VolumeInfo volInfo = new VolumeInfo("testvol" + Integer.toString(x), - "Thu, Apr 9, 2015 10:23:45 GMT", "gandalf"); - list.addVolume(volInfo); - } - list.sort(); - String listString = list.toJsonString(); - ListVolumes newList = ListVolumes.parse(listString); - assertEquals(list.toJsonString(), newList.toJsonString()); - } -} diff --git a/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/web/package-info.java b/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/web/package-info.java deleted file mode 100644 index ddbc30e09f2..00000000000 --- a/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/web/package-info.java +++ /dev/null @@ -1,21 +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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.ozone.web; -/** - * Unit tests of generic ozone web app and rest utils. - */ diff --git a/hadoop-ozone/datanode/pom.xml b/hadoop-ozone/datanode/pom.xml deleted file mode 100644 index 02995f53488..00000000000 --- a/hadoop-ozone/datanode/pom.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - 4.0.0 - - org.apache.hadoop - hadoop-ozone - 0.3.0-SNAPSHOT - - hadoop-ozone-datanode - Apache Hadoop Ozone Datanode - jar - 0.3.0-SNAPSHOT - - - - org.apache.hadoop - hadoop-common - compile - - - org.apache.hadoop - hadoop-hdfs - compile - - - org.apache.hadoop - hadoop-hdds-container-service - - - org.apache.hadoop - hadoop-ozone-objectstore-service - - - diff --git a/hadoop-ozone/dist/dev-support/bin/dist-layout-stitching b/hadoop-ozone/dist/dev-support/bin/dist-layout-stitching deleted file mode 100755 index 3f102fa01b0..00000000000 --- a/hadoop-ozone/dist/dev-support/bin/dist-layout-stitching +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/bin/env bash -# 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. - -# project.build.directory -BASEDIR=$1 - -#hdds.version -HDDS_VERSION=$2 - -## @audience private -## @stability evolving -function run() -{ - declare res - - echo "\$ ${*}" - "${@}" - res=$? - if [[ ${res} != 0 ]]; then - echo - echo "Failed!" - echo - exit "${res}" - fi -} - -## @audience private -## @stability evolving -function findfileindir() -{ - declare file="$1" - declare dir="${2:-./share}" - declare count - - count=$(find "${dir}" -iname "${file}" | wc -l) - - #shellcheck disable=SC2086 - echo ${count} -} - - -# shellcheck disable=SC2164 -ROOT=$(cd "${BASEDIR}"/../../..;pwd) -echo -echo "Current directory $(pwd)" -echo - -run rm -rf "ozone-${HDDS_VERSION}" -run mkdir "ozone-${HDDS_VERSION}" -run cd "ozone-${HDDS_VERSION}" -run cp -p "${ROOT}/LICENSE.txt" . -run cp -p "${ROOT}/NOTICE.txt" . -run cp -p "${ROOT}/README.txt" . - -run mkdir -p ./share/hadoop/mapreduce -run mkdir -p ./share/hadoop/ozone -run mkdir -p ./share/hadoop/hdds -run mkdir -p ./share/hadoop/yarn -run mkdir -p ./share/hadoop/hdfs -run mkdir -p ./share/hadoop/common -run mkdir -p ./share/ozone/web -run mkdir -p ./bin -run mkdir -p ./sbin -run mkdir -p ./etc -run mkdir -p ./libexec - -run cp -r "${ROOT}/hadoop-common-project/hadoop-common/src/main/conf" "etc/hadoop" - -run cp "${ROOT}/hadoop-common-project/hadoop-common/src/main/bin/hadoop" "bin/" -run cp "${ROOT}/hadoop-common-project/hadoop-common/src/main/bin/hadoop.cmd" "bin/" -run cp "${ROOT}/hadoop-ozone/common/src/main/bin/ozone" "bin/" - -run cp "${ROOT}/hadoop-common-project/hadoop-common/src/main/bin/hadoop-config.sh" "libexec/" -run cp "${ROOT}/hadoop-common-project/hadoop-common/src/main/bin/hadoop-config.cmd" "libexec/" -run cp "${ROOT}/hadoop-common-project/hadoop-common/src/main/bin/hadoop-functions.sh" "libexec/" -run cp "${ROOT}/hadoop-ozone/common/src/main/bin/ozone-config.sh" "libexec/" -run cp -r "${ROOT}/hadoop-ozone/common/src/main/shellprofile.d" "libexec/" - - -run cp "${ROOT}/hadoop-common-project/hadoop-common/src/main/bin/hadoop-daemons.sh" "sbin/" -run cp "${ROOT}/hadoop-common-project/hadoop-common/src/main/bin/workers.sh" "sbin/" -run cp "${ROOT}/hadoop-ozone/common/src/main/bin/start-ozone.sh" "sbin/" -run cp "${ROOT}/hadoop-ozone/common/src/main/bin/stop-ozone.sh" "sbin/" - -#shaded ozonefs -run mkdir -p "./share/hadoop/ozonefs" -run cp "${ROOT}/hadoop-ozone/ozonefs/target/hadoop-ozone-filesystem-${HDDS_VERSION}.jar" "./share/hadoop/ozonefs/hadoop-ozone-filesystem-${HDDS_VERSION}.jar" - -#shaded datanode service -run mkdir -p "./share/hadoop/ozoneplugin" -run cp "${ROOT}/hadoop-ozone/objectstore-service/target/hadoop-ozone-objectstore-service-${HDDS_VERSION}-plugin.jar" "./share/hadoop/ozoneplugin/hadoop-ozone-datanode-plugin-${HDDS_VERSION}.jar" - - -# Optional documentation, could be missing -cp -r "${ROOT}/hadoop-ozone/docs/target/classes/webapps/docs" ./share/hadoop/ozone/webapps/ozoneManager/ -cp -r "${ROOT}/hadoop-ozone/docs/target/classes/webapps/docs" ./share/hadoop/hdds/webapps/scm/ - -#Copy docker compose files -run cp -p -r "${ROOT}/hadoop-ozone/dist/src/main/compose" . -run cp -p -r "${ROOT}/hadoop-ozone/dist/src/main/smoketest" . diff --git a/hadoop-ozone/dist/dev-support/bin/dist-tar-stitching b/hadoop-ozone/dist/dev-support/bin/dist-tar-stitching deleted file mode 100755 index c94e7d0eb6e..00000000000 --- a/hadoop-ozone/dist/dev-support/bin/dist-tar-stitching +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env bash -# 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. - - -# project.version -VERSION=$1 - -# project.build.directory -BASEDIR=$2 - -## @audience private -## @stability evolving -function run() -{ - declare res - - echo "\$ ${*}" - "${@}" - res=$? - if [[ ${res} != 0 ]]; then - echo - echo "Failed!" - echo - exit "${res}" - fi -} - -run tar -c -f "ozone-${VERSION}.tar" "ozone-${VERSION}" -run gzip -f "ozone-${VERSION}.tar" -echo -echo "Ozone dist tar available at: ${BASEDIR}/ozone-${VERSION}.tar.gz" -echo diff --git a/hadoop-ozone/dist/pom.xml b/hadoop-ozone/dist/pom.xml deleted file mode 100644 index 7d1137274e2..00000000000 --- a/hadoop-ozone/dist/pom.xml +++ /dev/null @@ -1,195 +0,0 @@ - - - - 4.0.0 - - org.apache.hadoop - hadoop-ozone - 0.3.0-SNAPSHOT - - hadoop-ozone-dist - Apache Hadoop Ozone Distribution - pom - 0.3.0-SNAPSHOT - - UTF-8 - true - - - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-classpath-files - package - - copy - - - target/ozone-${ozone.version}/share/ozone/classpath - - - - org.apache.hadoop - hadoop-hdds-server-scm - ${hdds.version} - classpath - hadoop-hdds-server-scm.classpath - - - org.apache.hadoop - hadoop-hdds-tools - ${hdds.version} - classpath - hadoop-hdds-tools.classpath - - - org.apache.hadoop - hadoop-ozone-s3gateway - ${ozone.version} - classpath - hadoop-ozone-s3gateway.classpath - - - org.apache.hadoop - hadoop-ozone-ozone-manager - ${ozone.version} - classpath - hadoop-ozone-ozone-manager.classpath - - - - org.apache.hadoop - hadoop-ozone-tools - ${ozone.version} - classpath - hadoop-ozone-tools.classpath - - - org.apache.hadoop - hadoop-ozone-common - ${ozone.version} - classpath - hadoop-ozone-common.classpath - - - org.apache.hadoop - hadoop-ozone-datanode - ${ozone.version} - classpath - hadoop-ozone-datanode.classpath - - - - - - copy-jars - package - - copy-dependencies - - - target/ozone-${ozone.version}/share/ozone/lib - - runtime - - - - - - org.codehaus.mojo - exec-maven-plugin - - - dist - prepare-package - - exec - - - ${shell-executable} - ${project.build.directory} - - - ${basedir}/dev-support/bin/dist-layout-stitching - - ${project.build.directory} - ${hdds.version} - - - - - tar-ozone - package - - exec - - - ${shell-executable} - ${project.build.directory} - - - ${basedir}/dev-support/bin/dist-tar-stitching - - ${hdds.version} - ${project.build.directory} - - - - - - - - - - - org.apache.hadoop - hadoop-hdds-tools - - - org.apache.hadoop - hadoop-hdds-server-scm - - - org.apache.hadoop - hadoop-hdds-container-service - - - org.apache.hadoop - hadoop-ozone-s3gateway - - - org.apache.hadoop - hadoop-ozone-ozone-manager - - - org.apache.hadoop - hadoop-ozone-tools - - - org.apache.hadoop - hadoop-ozone-common - - - org.apache.hadoop - hadoop-ozone-datanode - - - diff --git a/hadoop-ozone/dist/src/main/compose/README.md b/hadoop-ozone/dist/src/main/compose/README.md deleted file mode 100644 index 8189d2c169a..00000000000 --- a/hadoop-ozone/dist/src/main/compose/README.md +++ /dev/null @@ -1,51 +0,0 @@ - - -# Docker cluster definitions - -This directory contains multiple docker cluster definitions to start local pseudo cluster with different configuration. - -It helps to start local (multi-node like) pseudo cluster with docker and docker-compose and obviously it's not for production. - -You may find more information in the specific subdirectories but in generic you can use the following commands: - -## Usage - -To start a cluster go to a subdirectory and start the cluster: - -``` -docker-compose up -d -``` - -You can check the logs of all the components with: - -``` -docker-compose logs -``` - -In case of a problem you can destroy the cluster an delete all the local state with: - -``` -docker-compose down -``` - -(Note: a simple docker-compose stop may not delete all the local data). - -You can scale up and down the components: - -``` -docker-compose scale datanode=5 -``` - -Usually the key webui ports are published on the docker host. diff --git a/hadoop-ozone/dist/src/main/compose/ozone-hdfs/.env b/hadoop-ozone/dist/src/main/compose/ozone-hdfs/.env deleted file mode 100644 index c437513bbd8..00000000000 --- a/hadoop-ozone/dist/src/main/compose/ozone-hdfs/.env +++ /dev/null @@ -1,17 +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 -# -# 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. - -HADOOP_VERSION=3.1.0 \ No newline at end of file diff --git a/hadoop-ozone/dist/src/main/compose/ozone-hdfs/docker-compose.yaml b/hadoop-ozone/dist/src/main/compose/ozone-hdfs/docker-compose.yaml deleted file mode 100644 index b89052dd0cc..00000000000 --- a/hadoop-ozone/dist/src/main/compose/ozone-hdfs/docker-compose.yaml +++ /dev/null @@ -1,60 +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 -# -# 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. - -version: "3" -services: - namenode: - image: flokkr/hadoop:${HADOOP_VERSION} - ports: - - 9870:9870 - env_file: - - ./docker-config - environment: - ENSURE_NAMENODE_DIR: "/tmp/hadoop-root/dfs/name" - command: ["hdfs", "namenode"] - datanode: - image: flokkr/hadoop:${HADOOP_VERSION} - ports: - - 9864 - volumes: - - ../..:/opt/ozone - command: ["hdfs","datanode"] - environment: - HADOOP_CLASSPATH: /opt/ozone/share/hadoop/ozoneplugin/*.jar - env_file: - - ./docker-config - ozoneManager: - image: apache/hadoop-runner - volumes: - - ../..:/opt/hadoop - ports: - - 9874:9874 - environment: - ENSURE_OM_INITIALIZED: /data/metadata/ozoneManager/current/VERSION - env_file: - - ./docker-config - command: ["ozone","om"] - scm: - image: apache/hadoop-runner - volumes: - - ../..:/opt/hadoop - ports: - - 9876:9876 - env_file: - - ./docker-config - environment: - ENSURE_SCM_INITIALIZED: /data/metadata/scm/current/VERSION - command: ["ozone","scm"] diff --git a/hadoop-ozone/dist/src/main/compose/ozone-hdfs/docker-config b/hadoop-ozone/dist/src/main/compose/ozone-hdfs/docker-config deleted file mode 100644 index 3b2819fbf77..00000000000 --- a/hadoop-ozone/dist/src/main/compose/ozone-hdfs/docker-config +++ /dev/null @@ -1,76 +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 -# -# 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. - -OZONE-SITE.XML_ozone.om.address=ozoneManager -OZONE-SITE.XML_ozone.om.http-address=ozoneManager:9874 -OZONE-SITE.XML_ozone.scm.names=scm -OZONE-SITE.XML_ozone.enabled=true -OZONE-SITE.XML_ozone.scm.datanode.id=/data/datanode.id -OZONE-SITE.XML_ozone.scm.block.client.address=scm -OZONE-SITE.XML_ozone.metadata.dirs=/data/metadata -OZONE-SITE.XML_ozone.scm.client.address=scm -OZONE-SITE.XML_ozone.replication=1 -OZONE-SITE.XML_hdds.datanode.plugins=org.apache.hadoop.ozone.web.OzoneHddsDatanodeService - -HDFS-SITE.XML_dfs.datanode.plugins=org.apache.hadoop.ozone.HddsDatanodeService -HDFS-SITE.XML_dfs.namenode.rpc-address=namenode:9000 -HDFS-SITE.XML_rpc.metrics.quantile.enable=true -HDFS-SITE.XML_rpc.metrics.percentiles.intervals=60,300 - -LOG4J.PROPERTIES_log4j.rootLogger=INFO, stdout -LOG4J.PROPERTIES_log4j.appender.stdout=org.apache.log4j.ConsoleAppender -LOG4J.PROPERTIES_log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -LOG4J.PROPERTIES_log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n - -#Enable this variable to print out all hadoop rpc traffic to the stdout. See http://byteman.jboss.org/ to define your own instrumentation. -#BYTEMAN_SCRIPT_URL=https://raw.githubusercontent.com/apache/hadoop/trunk/dev-support/byteman/hadooprpc.btm - -#LOG4J2.PROPERTIES_* are for Ozone Audit Logging -LOG4J2.PROPERTIES_monitorInterval=30 -LOG4J2.PROPERTIES_filter=read,write -LOG4J2.PROPERTIES_filter.read.type=MarkerFilter -LOG4J2.PROPERTIES_filter.read.marker=READ -LOG4J2.PROPERTIES_filter.read.onMatch=DENY -LOG4J2.PROPERTIES_filter.read.onMismatch=NEUTRAL -LOG4J2.PROPERTIES_filter.write.type=MarkerFilter -LOG4J2.PROPERTIES_filter.write.marker=WRITE -LOG4J2.PROPERTIES_filter.write.onMatch=NEUTRAL -LOG4J2.PROPERTIES_filter.write.onMismatch=NEUTRAL -LOG4J2.PROPERTIES_appenders=console, rolling -LOG4J2.PROPERTIES_appender.console.type=Console -LOG4J2.PROPERTIES_appender.console.name=STDOUT -LOG4J2.PROPERTIES_appender.console.layout.type=PatternLayout -LOG4J2.PROPERTIES_appender.console.layout.pattern=%d{DEFAULT} | %-5level | %c{1} | %msg | %throwable{3} %n -LOG4J2.PROPERTIES_appender.rolling.type=RollingFile -LOG4J2.PROPERTIES_appender.rolling.name=RollingFile -LOG4J2.PROPERTIES_appender.rolling.fileName =${sys:hadoop.log.dir}/om-audit-${hostName}.log -LOG4J2.PROPERTIES_appender.rolling.filePattern=${sys:hadoop.log.dir}/om-audit-${hostName}-%d{yyyy-MM-dd-HH-mm-ss}-%i.log.gz -LOG4J2.PROPERTIES_appender.rolling.layout.type=PatternLayout -LOG4J2.PROPERTIES_appender.rolling.layout.pattern=%d{DEFAULT} | %-5level | %c{1} | %msg | %throwable{3} %n -LOG4J2.PROPERTIES_appender.rolling.policies.type=Policies -LOG4J2.PROPERTIES_appender.rolling.policies.time.type=TimeBasedTriggeringPolicy -LOG4J2.PROPERTIES_appender.rolling.policies.time.interval=86400 -LOG4J2.PROPERTIES_appender.rolling.policies.size.type=SizeBasedTriggeringPolicy -LOG4J2.PROPERTIES_appender.rolling.policies.size.size=64MB -LOG4J2.PROPERTIES_loggers=audit -LOG4J2.PROPERTIES_logger.audit.type=AsyncLogger -LOG4J2.PROPERTIES_logger.audit.name=OMAudit -LOG4J2.PROPERTIES_logger.audit.level=INFO -LOG4J2.PROPERTIES_logger.audit.appenderRefs=rolling -LOG4J2.PROPERTIES_logger.audit.appenderRef.file.ref=RollingFile -LOG4J2.PROPERTIES_rootLogger.level=INFO -LOG4J2.PROPERTIES_rootLogger.appenderRefs=stdout -LOG4J2.PROPERTIES_rootLogger.appenderRef.stdout.ref=STDOUT diff --git a/hadoop-ozone/dist/src/main/compose/ozone/.env b/hadoop-ozone/dist/src/main/compose/ozone/.env deleted file mode 100644 index 67eed25884f..00000000000 --- a/hadoop-ozone/dist/src/main/compose/ozone/.env +++ /dev/null @@ -1,17 +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 -# -# 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. - -HDDS_VERSION=${hdds.version} \ No newline at end of file diff --git a/hadoop-ozone/dist/src/main/compose/ozone/docker-compose.yaml b/hadoop-ozone/dist/src/main/compose/ozone/docker-compose.yaml deleted file mode 100644 index 0a6a9d80280..00000000000 --- a/hadoop-ozone/dist/src/main/compose/ozone/docker-compose.yaml +++ /dev/null @@ -1,49 +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 -# -# 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. - -version: "3" -services: - datanode: - image: apache/hadoop-runner - volumes: - - ../..:/opt/hadoop - ports: - - 9864 - command: ["/opt/hadoop/bin/ozone","datanode"] - env_file: - - ./docker-config - ozoneManager: - image: apache/hadoop-runner - volumes: - - ../..:/opt/hadoop - ports: - - 9874:9874 - environment: - ENSURE_OM_INITIALIZED: /data/metadata/ozoneManager/current/VERSION - env_file: - - ./docker-config - command: ["/opt/hadoop/bin/ozone","om"] - scm: - image: apache/hadoop-runner - volumes: - - ../..:/opt/hadoop - ports: - - 9876:9876 - env_file: - - ./docker-config - environment: - ENSURE_SCM_INITIALIZED: /data/metadata/scm/current/VERSION - command: ["/opt/hadoop/bin/ozone","scm"] diff --git a/hadoop-ozone/dist/src/main/compose/ozone/docker-config b/hadoop-ozone/dist/src/main/compose/ozone/docker-config deleted file mode 100644 index f2c8db1f3bb..00000000000 --- a/hadoop-ozone/dist/src/main/compose/ozone/docker-config +++ /dev/null @@ -1,75 +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 -# -# 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. - -OZONE-SITE.XML_ozone.om.address=ozoneManager -OZONE-SITE.XML_ozone.om.http-address=ozoneManager:9874 -OZONE-SITE.XML_ozone.scm.names=scm -OZONE-SITE.XML_ozone.enabled=True -OZONE-SITE.XML_ozone.scm.datanode.id=/data/datanode.id -OZONE-SITE.XML_ozone.scm.block.client.address=scm -OZONE-SITE.XML_ozone.metadata.dirs=/data/metadata -OZONE-SITE.XML_ozone.handler.type=distributed -OZONE-SITE.XML_ozone.scm.client.address=scm -OZONE-SITE.XML_ozone.replication=1 -HDFS-SITE.XML_rpc.metrics.quantile.enable=true -HDFS-SITE.XML_rpc.metrics.percentiles.intervals=60,300 -LOG4J.PROPERTIES_log4j.rootLogger=INFO, stdout -LOG4J.PROPERTIES_log4j.appender.stdout=org.apache.log4j.ConsoleAppender -LOG4J.PROPERTIES_log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -LOG4J.PROPERTIES_log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n -LOG4J.PROPERTIES_log4j.logger.org.apache.hadoop.util.NativeCodeLoader=ERROR -LOG4J.PROPERTIES_log4j.logger.org.apache.ratis.conf.ConfUtils=WARN -LOG4J.PROPERTIES_log4j.logger.org.apache.hadoop.security.ShellBasedUnixGroupsMapping=ERROR - -#Enable this variable to print out all hadoop rpc traffic to the stdout. See http://byteman.jboss.org/ to define your own instrumentation. -#BYTEMAN_SCRIPT_URL=https://raw.githubusercontent.com/apache/hadoop/trunk/dev-support/byteman/hadooprpc.btm - -#LOG4J2.PROPERTIES_* are for Ozone Audit Logging -LOG4J2.PROPERTIES_monitorInterval=30 -LOG4J2.PROPERTIES_filter=read,write -LOG4J2.PROPERTIES_filter.read.type=MarkerFilter -LOG4J2.PROPERTIES_filter.read.marker=READ -LOG4J2.PROPERTIES_filter.read.onMatch=DENY -LOG4J2.PROPERTIES_filter.read.onMismatch=NEUTRAL -LOG4J2.PROPERTIES_filter.write.type=MarkerFilter -LOG4J2.PROPERTIES_filter.write.marker=WRITE -LOG4J2.PROPERTIES_filter.write.onMatch=NEUTRAL -LOG4J2.PROPERTIES_filter.write.onMismatch=NEUTRAL -LOG4J2.PROPERTIES_appenders=console, rolling -LOG4J2.PROPERTIES_appender.console.type=Console -LOG4J2.PROPERTIES_appender.console.name=STDOUT -LOG4J2.PROPERTIES_appender.console.layout.type=PatternLayout -LOG4J2.PROPERTIES_appender.console.layout.pattern=%d{DEFAULT} | %-5level | %c{1} | %msg | %throwable{3} %n -LOG4J2.PROPERTIES_appender.rolling.type=RollingFile -LOG4J2.PROPERTIES_appender.rolling.name=RollingFile -LOG4J2.PROPERTIES_appender.rolling.fileName =${sys:hadoop.log.dir}/om-audit-${hostName}.log -LOG4J2.PROPERTIES_appender.rolling.filePattern=${sys:hadoop.log.dir}/om-audit-${hostName}-%d{yyyy-MM-dd-HH-mm-ss}-%i.log.gz -LOG4J2.PROPERTIES_appender.rolling.layout.type=PatternLayout -LOG4J2.PROPERTIES_appender.rolling.layout.pattern=%d{DEFAULT} | %-5level | %c{1} | %msg | %throwable{3} %n -LOG4J2.PROPERTIES_appender.rolling.policies.type=Policies -LOG4J2.PROPERTIES_appender.rolling.policies.time.type=TimeBasedTriggeringPolicy -LOG4J2.PROPERTIES_appender.rolling.policies.time.interval=86400 -LOG4J2.PROPERTIES_appender.rolling.policies.size.type=SizeBasedTriggeringPolicy -LOG4J2.PROPERTIES_appender.rolling.policies.size.size=64MB -LOG4J2.PROPERTIES_loggers=audit -LOG4J2.PROPERTIES_logger.audit.type=AsyncLogger -LOG4J2.PROPERTIES_logger.audit.name=OMAudit -LOG4J2.PROPERTIES_logger.audit.level=INFO -LOG4J2.PROPERTIES_logger.audit.appenderRefs=rolling -LOG4J2.PROPERTIES_logger.audit.appenderRef.file.ref=RollingFile -LOG4J2.PROPERTIES_rootLogger.level=INFO -LOG4J2.PROPERTIES_rootLogger.appenderRefs=stdout -LOG4J2.PROPERTIES_rootLogger.appenderRef.stdout.ref=STDOUT diff --git a/hadoop-ozone/dist/src/main/compose/ozonefs/docker-compose.yaml b/hadoop-ozone/dist/src/main/compose/ozonefs/docker-compose.yaml deleted file mode 100644 index a1e874849ee..00000000000 --- a/hadoop-ozone/dist/src/main/compose/ozonefs/docker-compose.yaml +++ /dev/null @@ -1,59 +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 -# -# 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. - -version: "3" -services: - datanode: - image: apache/hadoop-runner - volumes: - - ../..:/opt/hadoop - ports: - - 9864 - command: ["/opt/hadoop/bin/ozone","datanode"] - env_file: - - ./docker-config - ozoneManager: - image: apache/hadoop-runner - hostname: ozoneManager - volumes: - - ../..:/opt/hadoop - ports: - - 9874 - environment: - ENSURE_OM_INITIALIZED: /data/metadata/ozoneManager/current/VERSION - env_file: - - ./docker-config - command: ["/opt/hadoop/bin/ozone","om"] - scm: - image: apache/hadoop-runner - volumes: - - ../..:/opt/hadoop - ports: - - 9876 - env_file: - - ./docker-config - environment: - ENSURE_SCM_INITIALIZED: /data/metadata/scm/current/VERSION - command: ["/opt/hadoop/bin/ozone","scm"] - hadooplast: - image: flokkr/hadoop:3.1.0 - volumes: - - ../..:/opt/ozone - env_file: - - ./docker-config - environment: - HADOOP_CLASSPATH: /opt/ozone/share/hadoop/ozonefs/*.jar - command: ["watch","-n","100000","ls"] diff --git a/hadoop-ozone/dist/src/main/compose/ozonefs/docker-config b/hadoop-ozone/dist/src/main/compose/ozonefs/docker-config deleted file mode 100644 index 3171f089e1b..00000000000 --- a/hadoop-ozone/dist/src/main/compose/ozonefs/docker-config +++ /dev/null @@ -1,35 +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 -# -# 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. - -CORE-SITE.XML_fs.o3.impl=org.apache.hadoop.fs.ozone.OzoneFileSystem -OZONE-SITE.XML_ozone.om.address=ozoneManager -OZONE-SITE.XML_ozone.om.http-address=ozoneManager:9874 -OZONE-SITE.XML_ozone.scm.names=scm -OZONE-SITE.XML_ozone.enabled=True -OZONE-SITE.XML_ozone.scm.datanode.id=/data/datanode.id -OZONE-SITE.XML_ozone.scm.block.client.address=scm -OZONE-SITE.XML_ozone.metadata.dirs=/data/metadata -OZONE-SITE.XML_ozone.handler.type=distributed -OZONE-SITE.XML_ozone.scm.client.address=scm -OZONE-SITE.XML_ozone.scm.heartbeat.interval=3s -HDFS-SITE.XML_rpc.metrics.quantile.enable=true -HDFS-SITE.XML_rpc.metrics.percentiles.intervals=60,300 -LOG4J.PROPERTIES_log4j.rootLogger=INFO, stdout -LOG4J.PROPERTIES_log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -LOG4J.PROPERTIES_log4j.appender.stdout=org.apache.log4j.ConsoleAppender -LOG4J.PROPERTIES_log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n -LOG4J.PROPERTIES_log4j.logger.org.apache.hadoop.util.NativeCodeLoader=ERROR -LOG4J.PROPERTIES_log4j.logger.org.apache.ratis.conf.ConfUtils=WARN diff --git a/hadoop-ozone/dist/src/main/compose/ozoneperf/.env b/hadoop-ozone/dist/src/main/compose/ozoneperf/.env deleted file mode 100644 index cac418ae59e..00000000000 --- a/hadoop-ozone/dist/src/main/compose/ozoneperf/.env +++ /dev/null @@ -1,17 +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 -# -# 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. - -HDDS_VERSION=${hdds.version} diff --git a/hadoop-ozone/dist/src/main/compose/ozoneperf/README.md b/hadoop-ozone/dist/src/main/compose/ozoneperf/README.md deleted file mode 100644 index 527ff418d37..00000000000 --- a/hadoop-ozone/dist/src/main/compose/ozoneperf/README.md +++ /dev/null @@ -1,73 +0,0 @@ - - -# Compose files for local performance tests - -This directory contains docker-compose definition for an ozone cluster where -all the metrics are saved to a prometheus instance. - - Prometheus follows a pull based approach where the metrics are published - on a HTTP endpoint. - - Our current approach: - - 1. A Java agent activates a prometheus metrics endpoint in every JVM instance - (use `init.sh` to download the agent) - - 2. The Java agent publishes all the jmx parameters in prometheus format AND - register the endpoint address to the consul. - - 3. Prometheus polls all the endpoints which are registered to consul. - - - -## How to use - -First of all download the required Java agent with running `./init.sh` - -After that you can start the cluster with docker-compose: - -``` -docker-compose up -d -``` - -After a while the cluster will be started. You can check the ozone web ui-s: - -https://localhost:9874 -https://localhost:9876 - -You can also scale up the datanodes: - -``` -docker-compose scale datanode=3 -``` - -Freon (Ozone test generator tool) is not part of docker-compose by default, -you can activate it using `compose-all.sh` instead of `docker-compose`: - -``` -compose-all.sh up -d -``` - -Now Freon is running. Let's try to check the metrics from the local Prometheus: - -http://localhost:9090/graph - -Example queries: - -``` -Hadoop_OzoneManager_NumKeyCommits -rate(Hadoop_OzoneManager_NumKeyCommits[10m]) -rate(Hadoop_Ozone_BYTES_WRITTEN[10m]) -``` diff --git a/hadoop-ozone/dist/src/main/compose/ozoneperf/compose-all.sh b/hadoop-ozone/dist/src/main/compose/ozoneperf/compose-all.sh deleted file mode 100755 index 82ab8b3101d..00000000000 --- a/hadoop-ozone/dist/src/main/compose/ozoneperf/compose-all.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env bash -# 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. - -docker-compose -f docker-compose.yaml -f docker-compose-freon.yaml "$@" diff --git a/hadoop-ozone/dist/src/main/compose/ozoneperf/docker-compose-freon.yaml b/hadoop-ozone/dist/src/main/compose/ozoneperf/docker-compose-freon.yaml deleted file mode 100644 index 60bdc4a503f..00000000000 --- a/hadoop-ozone/dist/src/main/compose/ozoneperf/docker-compose-freon.yaml +++ /dev/null @@ -1,26 +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 -# -# 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. - -version: "3" -services: - freon: - image: apache/hadoop-runner - volumes: - - ../../ozone:/opt/hadoop - - ./jmxpromo.jar:/opt/jmxpromo.jar - env_file: - - ./docker-config - command: ["/opt/hadoop/bin/ozone","freon"] diff --git a/hadoop-ozone/dist/src/main/compose/ozoneperf/docker-compose.yaml b/hadoop-ozone/dist/src/main/compose/ozoneperf/docker-compose.yaml deleted file mode 100644 index 12b28bbcf0d..00000000000 --- a/hadoop-ozone/dist/src/main/compose/ozoneperf/docker-compose.yaml +++ /dev/null @@ -1,64 +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 -# -# 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. - -version: "3" -services: - datanode: - image: apache/hadoop-runner - volumes: - - ../..:/opt/hadoop - - ./jmxpromo.jar:/opt/jmxpromo.jar - ports: - - 9864 - command: ["/opt/hadoop/bin/ozone","datanode"] - env_file: - - ./docker-config - ozoneManager: - image: apache/hadoop-runner - volumes: - - ../..:/opt/hadoop - - ./jmxpromo.jar:/opt/jmxpromo.jar - ports: - - 9874:9874 - environment: - ENSURE_OM_INITIALIZED: /data/metadata/ozoneManager/current/VERSION - env_file: - - ./docker-config - command: ["/opt/hadoop/bin/ozone","om"] - scm: - image: apache/hadoop-runner - volumes: - - ../..:/opt/hadoop - - ./jmxpromo.jar:/opt/jmxpromo.jar - ports: - - 9876:9876 - env_file: - - ./docker-config - environment: - ENSURE_SCM_INITIALIZED: /data/metadata/scm/current/VERSION - command: ["/opt/hadoop/bin/ozone","scm"] - consul: - image: consul - command: ["agent", "-dev", "-ui", "-client", "0.0.0.0"] - ports: - - 8500:8500 - prometheus: - image: prom/prometheus - volumes: - - "./prometheus.yml:/etc/prometheus.yml" - command: ["--config.file","/etc/prometheus.yml"] - ports: - - 9090:9090 diff --git a/hadoop-ozone/dist/src/main/compose/ozoneperf/docker-config b/hadoop-ozone/dist/src/main/compose/ozoneperf/docker-config deleted file mode 100644 index 1ed116992c2..00000000000 --- a/hadoop-ozone/dist/src/main/compose/ozoneperf/docker-config +++ /dev/null @@ -1,35 +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 -# -# 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. - -OZONE-SITE.XML_ozone.om.address=ozoneManager -OZONE-SITE.XML_ozone.om.http-address=ozoneManager:9874 -OZONE-SITE.XML_ozone.scm.names=scm -OZONE-SITE.XML_ozone.enabled=True -OZONE-SITE.XML_ozone.scm.datanode.id=/data/datanode.id -OZONE-SITE.XML_ozone.scm.block.client.address=scm -OZONE-SITE.XML_ozone.metadata.dirs=/data/metadata -OZONE-SITE.XML_ozone.handler.type=distributed -OZONE-SITE.XML_ozone.scm.client.address=scm -HDFS-SITE.XML_rpc.metrics.quantile.enable=true -HDFS-SITE.XML_rpc.metrics.percentiles.intervals=60,300 -LOG4J.PROPERTIES_log4j.rootLogger=INFO, stdout -LOG4J.PROPERTIES_log4j.appender.stdout=org.apache.log4j.ConsoleAppender -LOG4J.PROPERTIES_log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -LOG4J.PROPERTIES_log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n -HADOOP_OPTS=-javaagent:/opt/jmxpromo.jar=port=0:consulHost=consul:consulMode=node -LOG4J.PROPERTIES_log4j.logger.org.apache.hadoop.util.NativeCodeLoader=ERROR -LOG4J.PROPERTIES_log4j.logger.org.apache.ratis.conf.ConfUtils=WARN -LOG4J.PROPERTIES_log4j.logger.org.apache.hadoop.security.ShellBasedUnixGroupsMapping=ERROR diff --git a/hadoop-ozone/dist/src/main/compose/ozoneperf/init.sh b/hadoop-ozone/dist/src/main/compose/ozoneperf/init.sh deleted file mode 100755 index cf25398bc20..00000000000 --- a/hadoop-ozone/dist/src/main/compose/ozoneperf/init.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash -# 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. -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -EXPORTER_FILE="$DIR/jmxpromo.jar" -if [ ! -f "$EXPORTER_FILE" ]; then - wget https://github.com/flokkr/jmxpromo/releases/download/0.11/jmx_prometheus_javaagent-0.11.jar -O $EXPORTER_FILE -fi diff --git a/hadoop-ozone/dist/src/main/compose/ozoneperf/prometheus.yml b/hadoop-ozone/dist/src/main/compose/ozoneperf/prometheus.yml deleted file mode 100644 index 80aa5203a20..00000000000 --- a/hadoop-ozone/dist/src/main/compose/ozoneperf/prometheus.yml +++ /dev/null @@ -1,24 +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 -# -# 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. -global: - scrape_interval: 15s # By default, scrape targets every 15 seconds. - -scrape_configs: - - job_name: jmxexporter - consul_sd_configs: - - server: consul:8500 - services: - - jmxexporter diff --git a/hadoop-ozone/dist/src/main/compose/ozones3/docker-compose.yaml b/hadoop-ozone/dist/src/main/compose/ozones3/docker-compose.yaml deleted file mode 100644 index 42d7d1d1a67..00000000000 --- a/hadoop-ozone/dist/src/main/compose/ozones3/docker-compose.yaml +++ /dev/null @@ -1,58 +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 -# -# 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. - -version: "3" -services: - datanode: - image: apache/hadoop-runner - volumes: - - ../..:/opt/hadoop - ports: - - 9864 - command: ["ozone","datanode"] - env_file: - - ./docker-config - ozoneManager: - image: apache/hadoop-runner - volumes: - - ../..:/opt/hadoop - ports: - - 9874:9874 - environment: - ENSURE_OM_INITIALIZED: /data/metadata/ozoneManager/current/VERSION - env_file: - - ./docker-config - command: ["ozone","om"] - scm: - image: apache/hadoop-runner - volumes: - - ../..:/opt/hadoop - ports: - - 9876:9876 - env_file: - - ./docker-config - environment: - ENSURE_SCM_INITIALIZED: /data/metadata/scm/current/VERSION - command: ["ozone","scm"] - s3g: - image: apache/hadoop-runner - volumes: - - ../..:/opt/hadoop - ports: - - 9878:9878 - env_file: - - ./docker-config - command: ["ozone","s3g"] diff --git a/hadoop-ozone/dist/src/main/compose/ozones3/docker-config b/hadoop-ozone/dist/src/main/compose/ozones3/docker-config deleted file mode 100644 index 2b22874b021..00000000000 --- a/hadoop-ozone/dist/src/main/compose/ozones3/docker-config +++ /dev/null @@ -1,73 +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 -# -# 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. - -OZONE-SITE.XML_ozone.om.address=ozoneManager -OZONE-SITE.XML_ozone.scm.names=scm -OZONE-SITE.XML_ozone.enabled=true -OZONE-SITE.XML_ozone.scm.datanode.id=/data/datanode.id -OZONE-SITE.XML_ozone.scm.block.client.address=scm -OZONE-SITE.XML_ozone.metadata.dirs=/data/metadata -OZONE-SITE.XML_ozone.scm.client.address=scm -OZONE-SITE.XML_ozone.replication=1 -HDFS-SITE.XML_rpc.metrics.quantile.enable=true -HDFS-SITE.XML_rpc.metrics.percentiles.intervals=60,300 -LOG4J.PROPERTIES_log4j.rootLogger=INFO, stdout -LOG4J.PROPERTIES_log4j.appender.stdout=org.apache.log4j.ConsoleAppender -LOG4J.PROPERTIES_log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -LOG4J.PROPERTIES_log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n -LOG4J.PROPERTIES_log4j.logger.org.apache.hadoop.util.NativeCodeLoader=ERROR -LOG4J.PROPERTIES_log4j.logger.org.apache.ratis.conf.ConfUtils=WARN -LOG4J.PROPERTIES_log4j.logger.org.apache.hadoop.security.ShellBasedUnixGroupsMapping=ERROR - -#Enable this variable to print out all hadoop rpc traffic to the stdout. See http://byteman.jboss.org/ to define your own instrumentation. -#BYTEMAN_SCRIPT_URL=https://raw.githubusercontent.com/apache/hadoop/trunk/dev-support/byteman/hadooprpc.btm - -#LOG4J2.PROPERTIES_* are for Ozone Audit Logging -LOG4J2.PROPERTIES_monitorInterval=30 -LOG4J2.PROPERTIES_filter=read,write -LOG4J2.PROPERTIES_filter.read.type=MarkerFilter -LOG4J2.PROPERTIES_filter.read.marker=READ -LOG4J2.PROPERTIES_filter.read.onMatch=DENY -LOG4J2.PROPERTIES_filter.read.onMismatch=NEUTRAL -LOG4J2.PROPERTIES_filter.write.type=MarkerFilter -LOG4J2.PROPERTIES_filter.write.marker=WRITE -LOG4J2.PROPERTIES_filter.write.onMatch=NEUTRAL -LOG4J2.PROPERTIES_filter.write.onMismatch=NEUTRAL -LOG4J2.PROPERTIES_appenders=console, rolling -LOG4J2.PROPERTIES_appender.console.type=Console -LOG4J2.PROPERTIES_appender.console.name=STDOUT -LOG4J2.PROPERTIES_appender.console.layout.type=PatternLayout -LOG4J2.PROPERTIES_appender.console.layout.pattern=%d{DEFAULT} | %-5level | %c{1} | %msg | %throwable{3} %n -LOG4J2.PROPERTIES_appender.rolling.type=RollingFile -LOG4J2.PROPERTIES_appender.rolling.name=RollingFile -LOG4J2.PROPERTIES_appender.rolling.fileName =${sys:hadoop.log.dir}/om-audit-${hostName}.log -LOG4J2.PROPERTIES_appender.rolling.filePattern=${sys:hadoop.log.dir}/om-audit-${hostName}-%d{yyyy-MM-dd-HH-mm-ss}-%i.log.gz -LOG4J2.PROPERTIES_appender.rolling.layout.type=PatternLayout -LOG4J2.PROPERTIES_appender.rolling.layout.pattern=%d{DEFAULT} | %-5level | %c{1} | %msg | %throwable{3} %n -LOG4J2.PROPERTIES_appender.rolling.policies.type=Policies -LOG4J2.PROPERTIES_appender.rolling.policies.time.type=TimeBasedTriggeringPolicy -LOG4J2.PROPERTIES_appender.rolling.policies.time.interval=86400 -LOG4J2.PROPERTIES_appender.rolling.policies.size.type=SizeBasedTriggeringPolicy -LOG4J2.PROPERTIES_appender.rolling.policies.size.size=64MB -LOG4J2.PROPERTIES_loggers=audit -LOG4J2.PROPERTIES_logger.audit.type=AsyncLogger -LOG4J2.PROPERTIES_logger.audit.name=OMAudit -LOG4J2.PROPERTIES_logger.audit.level=INFO -LOG4J2.PROPERTIES_logger.audit.appenderRefs=rolling -LOG4J2.PROPERTIES_logger.audit.appenderRef.file.ref=RollingFile -LOG4J2.PROPERTIES_rootLogger.level=INFO -LOG4J2.PROPERTIES_rootLogger.appenderRefs=stdout -LOG4J2.PROPERTIES_rootLogger.appenderRef.stdout.ref=STDOUT diff --git a/hadoop-ozone/dist/src/main/compose/ozonescripts/.ssh/authorized_keys b/hadoop-ozone/dist/src/main/compose/ozonescripts/.ssh/authorized_keys deleted file mode 100644 index ae390529c7e..00000000000 --- a/hadoop-ozone/dist/src/main/compose/ozonescripts/.ssh/authorized_keys +++ /dev/null @@ -1,16 +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 -# -# 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. -ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDgEmLpYm4BrWtq1KG9hhZXCZgGrETntu0eNTo21U3VKc9nH9/ot7M6lAawsFcT9uXu4b58PTlnfvwH/TATlCFjC8n0Z7SOx+FU6L3Sn8URh9HaX4L0tF8u87oCAD4dBrUGhhB36eiuH9dBBWly6RKffYJvrjatbc7GxBO/e5OSUMtqk/DSVKksmBhZxutrKivCNjDish9ViGIf8b5yS/MlEGmaVKApik1fJ5iOlloM/GgpB60YV/hbqfCecbWgeiM1gK92gdOcA/Wx1C7fj8BSI5iDSE6eZeF80gM3421lvyPDWyVhFaGbka4rXBX/fb9QSRBA9RTqhRKAEmAIf49H hadoop@cdae967fa87a diff --git a/hadoop-ozone/dist/src/main/compose/ozonescripts/.ssh/config b/hadoop-ozone/dist/src/main/compose/ozonescripts/.ssh/config deleted file mode 100644 index 6506916ded0..00000000000 --- a/hadoop-ozone/dist/src/main/compose/ozonescripts/.ssh/config +++ /dev/null @@ -1,18 +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 -# -# 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. -Host * - UserKnownHostsFile /dev/null - StrictHostKeyChecking no diff --git a/hadoop-ozone/dist/src/main/compose/ozonescripts/.ssh/environment b/hadoop-ozone/dist/src/main/compose/ozonescripts/.ssh/environment deleted file mode 100644 index 5685453be12..00000000000 --- a/hadoop-ozone/dist/src/main/compose/ozonescripts/.ssh/environment +++ /dev/null @@ -1,16 +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 -# -# 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. -JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-amd64/ diff --git a/hadoop-ozone/dist/src/main/compose/ozonescripts/.ssh/id_rsa b/hadoop-ozone/dist/src/main/compose/ozonescripts/.ssh/id_rsa deleted file mode 100644 index 6632ce51c54..00000000000 --- a/hadoop-ozone/dist/src/main/compose/ozonescripts/.ssh/id_rsa +++ /dev/null @@ -1,42 +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 -# -# 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. ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEA4BJi6WJuAa1ratShvYYWVwmYBqxE57btHjU6NtVN1SnPZx/f -6LezOpQGsLBXE/bl7uG+fD05Z378B/0wE5QhYwvJ9Ge0jsfhVOi90p/FEYfR2l+C -9LRfLvO6AgA+HQa1BoYQd+norh/XQQVpcukSn32Cb642rW3OxsQTv3uTklDLapPw -0lSpLJgYWcbrayorwjYw4rIfVYhiH/G+ckvzJRBpmlSgKYpNXyeYjpZaDPxoKQet -GFf4W6nwnnG1oHojNYCvdoHTnAP1sdQu34/AUiOYg0hOnmXhfNIDN+NtZb8jw1sl -YRWhm5GuK1wV/32/UEkQQPUU6oUSgBJgCH+PRwIDAQABAoIBAQDI1TH6ZNKchkck -9XgSWsBjOqIcOQN5fCeDT8nho8WjLVpL3/Hcr+ngsxRcAXHK3xyvw33r9SQic1qJ -/pC8u6RBFivo95qJ7vU0GXcp9TG4yLd6tui1U4WMm784U+dYNM7EDh1snSaECt3v -1V3yNJ0QfnoOh2NShn0zAkOA+M4H8Nx2SudMCsjcbK9+fYxzW3hX+sJpMKdjG1HW -DUz+I7cW7t0EGaVrgVSV+eR58LiXu+14YDNMrySiejB4nD2sKrx93XgiCBECCsBN -GLQGJCztaXoAY+5Kf/aJ9EEf2wBF3GecRk+XIAd87PeDmeahLQAVkAJ/rD1vsKFs -8kWi6CrhAoGBAP7leG/dMBhlfvROpBddIfWm2i8B+oZiAlSjdYGz+/ZhUaByXk18 -pupMGiiMQR1ziPnEg0gNgR2ZkH54qrXPn5WcQa4rlSEtUsZEp5v5WblhfX2QwKzY -G/uhA+mB7wXpQkSmXo0LclfPF2teROQrG1OyfWkWbxFH4i3+em7sL95jAoGBAOEK -v+wscqkMLW7Q8ONbWMCCBlmMHr6baB3VDCYZx25lr+GIF5zmJJFTmF2rq2VSAlts -qx1AGmaUSo78kC5FuJvSNTL6a1Us5ucdthQZM3N8pAz+OAE+QEU+BsdA27yAh3tO -yKDsMFNHKtXcgy5LeB5gzENLlNyw2jgkRv2Ef77NAoGAVH8DHqoHEH9Mx3XuRWR1 -JnaqKx0PzE5fEWmiQV3Fr5XxNivTgQJKXq7dmQVtbHLpPErdbhwz6fkHAjXD+UMb -VsAWscL2y6m3n8wQd87/5EkiDWbXyDRXimGE53pQHviFJDa2bzEVNXCMBeaZFb4I -cAViN1zdcrAOlUqfkXewIpsCgYB8wsXl/DpRB+RENGfn0+OfTjaQ/IKq72NIbq1+ -jfondQ6N/TICFQEe5HZrL9okoNOXteYjoD9CsWGoZdLVJGgVUvOVYImSvgMBDFK+ -T75bfzU/0sxfvBBLkviVDJsFpUf3D5VgybB86s6Po+HCD6r3RHjZshRESXOhflMx -B3z+3QKBgE2Lwo0DuwUGkm6k8psyn3x8EiXNsiNw12cojicFTyKUYLHxMBeVbCLW -3j3pxSggJgRuBLLzixUHbHp91r2ARTy28naK7R/la8yKVqK6ojcikN2mQsCHYtwB -nuFwXr42ytn6G+9Wn4xT64tGjRCqyZn0/v0XsPjVCyrZ6G7EtNHP ------END RSA PRIVATE KEY----- diff --git a/hadoop-ozone/dist/src/main/compose/ozonescripts/.ssh/id_rsa.pub b/hadoop-ozone/dist/src/main/compose/ozonescripts/.ssh/id_rsa.pub deleted file mode 100644 index ae390529c7e..00000000000 --- a/hadoop-ozone/dist/src/main/compose/ozonescripts/.ssh/id_rsa.pub +++ /dev/null @@ -1,16 +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 -# -# 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. -ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDgEmLpYm4BrWtq1KG9hhZXCZgGrETntu0eNTo21U3VKc9nH9/ot7M6lAawsFcT9uXu4b58PTlnfvwH/TATlCFjC8n0Z7SOx+FU6L3Sn8URh9HaX4L0tF8u87oCAD4dBrUGhhB36eiuH9dBBWly6RKffYJvrjatbc7GxBO/e5OSUMtqk/DSVKksmBhZxutrKivCNjDish9ViGIf8b5yS/MlEGmaVKApik1fJ5iOlloM/GgpB60YV/hbqfCecbWgeiM1gK92gdOcA/Wx1C7fj8BSI5iDSE6eZeF80gM3421lvyPDWyVhFaGbka4rXBX/fb9QSRBA9RTqhRKAEmAIf49H hadoop@cdae967fa87a diff --git a/hadoop-ozone/dist/src/main/compose/ozonescripts/Dockerfile b/hadoop-ozone/dist/src/main/compose/ozonescripts/Dockerfile deleted file mode 100644 index 3bdcb0cc982..00000000000 --- a/hadoop-ozone/dist/src/main/compose/ozonescripts/Dockerfile +++ /dev/null @@ -1,33 +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 -# -# 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. -FROM apache/hadoop-runner -RUN sudo apt-get update && sudo apt-get install -y openssh-server - -RUN sudo mkdir -p /run/sshd -RUN sudo sed -i "s/.*UsePrivilegeSeparation.*/UsePrivilegeSeparation no/g" /etc/ssh/sshd_config -RUN sudo sed -i "s/.*PermitUserEnvironment.*/PermitUserEnvironment yes/g" /etc/ssh/sshd_config -RUN sudo sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd - -#/opt/hadoop is mounted, we can't use it as a home -RUN sudo usermod -d /opt hadoop -ADD .ssh /opt/.ssh -RUN sudo chown -R hadoop /opt/.ssh -RUN sudo chown hadoop /opt -RUN sudo chmod 600 /opt/.ssh/* -RUN sudo chmod 700 /opt/.ssh - -RUN sudo sh -c 'echo "export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-amd64/" >> /etc/profile' -CMD ["sudo","/usr/sbin/sshd","-D"] diff --git a/hadoop-ozone/dist/src/main/compose/ozonescripts/README.md b/hadoop-ozone/dist/src/main/compose/ozonescripts/README.md deleted file mode 100644 index 2531fa43660..00000000000 --- a/hadoop-ozone/dist/src/main/compose/ozonescripts/README.md +++ /dev/null @@ -1,38 +0,0 @@ - - -# start-ozone environment - -This is an example environment to use/test `./sbin/start-ozone.sh` and `./sbin/stop-ozone.sh` scripts. - -There are ssh connections between the containers and the start/stop scripts could handle the start/stop process -similar to a real cluster. - -To use it, first start the cluster: - -``` -docker-copmose up -d -``` - -After a successfull startup (which starts only the ssh daemons) you can start ozone: - -``` -./start.sh -``` - -Check it the java processes are started: - -``` -./ps.sh -``` \ No newline at end of file diff --git a/hadoop-ozone/dist/src/main/compose/ozonescripts/docker-compose.yaml b/hadoop-ozone/dist/src/main/compose/ozonescripts/docker-compose.yaml deleted file mode 100644 index 62f116368f4..00000000000 --- a/hadoop-ozone/dist/src/main/compose/ozonescripts/docker-compose.yaml +++ /dev/null @@ -1,42 +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 -# -# 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. - -version: "3" -services: - datanode: - build: . - volumes: - - ../..:/opt/hadoop - ports: - - 9864 - env_file: - - ./docker-config - om: - build: . - volumes: - - ../..:/opt/hadoop - ports: - - 9874:9874 - env_file: - - ./docker-config - scm: - build: . - volumes: - - ../..:/opt/hadoop - ports: - - 9876:9876 - env_file: - - ./docker-config diff --git a/hadoop-ozone/dist/src/main/compose/ozonescripts/docker-config b/hadoop-ozone/dist/src/main/compose/ozonescripts/docker-config deleted file mode 100644 index 1afec73e0ed..00000000000 --- a/hadoop-ozone/dist/src/main/compose/ozonescripts/docker-config +++ /dev/null @@ -1,38 +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 -# -# 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. - -JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-amd64/ -CORE-SITE.XML_fs.defaultFS=hdfs://namenode:9000 -OZONE-SITE.XML_ozone.ksm.address=ksm -OZONE-SITE.XML_ozone.scm.names=scm -OZONE-SITE.XML_ozone.enabled=true -OZONE-SITE.XML_ozone.scm.datanode.id=/data/datanode.id -OZONE-SITE.XML_ozone.om.address=om -OZONE-SITE.XML_ozone.om.http-address=om:9874 -OZONE-SITE.XML_ozone.scm.block.client.address=scm -OZONE-SITE.XML_ozone.metadata.dirs=/data/metadata -OZONE-SITE.XML_ozone.scm.client.address=scm -OZONE-SITE.XML_hdds.datanode.plugins=org.apache.hadoop.ozone.web.OzoneHddsDatanodeService -HDFS-SITE.XML_dfs.namenode.rpc-address=namenode:9000 -HDFS-SITE.XML_dfs.namenode.name.dir=/data/namenode -HDFS-SITE.XML_rpc.metrics.quantile.enable=true -HDFS-SITE.XML_rpc.metrics.percentiles.intervals=60,300 -HDFS-SITE.XML_dfs.datanode.plugins=org.apache.hadoop.ozone.HddsDatanodeService -LOG4J.PROPERTIES_log4j.rootLogger=INFO, stdout -LOG4J.PROPERTIES_log4j.logger.org.apache.hadoop.util.NativeCodeLoader=ERROR, stdout -LOG4J.PROPERTIES_log4j.appender.stdout=org.apache.log4j.ConsoleAppender -LOG4J.PROPERTIES_log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -LOG4J.PROPERTIES_log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n \ No newline at end of file diff --git a/hadoop-ozone/dist/src/main/compose/ozonescripts/ps.sh b/hadoop-ozone/dist/src/main/compose/ozonescripts/ps.sh deleted file mode 100755 index d5e2c386752..00000000000 --- a/hadoop-ozone/dist/src/main/compose/ozonescripts/ps.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash -# 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. -docker-compose ps -q | xargs -n1 -I CONTAINER docker exec CONTAINER ps xa \ No newline at end of file diff --git a/hadoop-ozone/dist/src/main/compose/ozonescripts/start.sh b/hadoop-ozone/dist/src/main/compose/ozonescripts/start.sh deleted file mode 100755 index 3358b07c4e9..00000000000 --- a/hadoop-ozone/dist/src/main/compose/ozonescripts/start.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash -# 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. -docker-compose ps | grep datanode | awk '{print $1}' | xargs -n1 docker inspect --format '{{ .Config.Hostname }}' > ../../etc/hadoop/workers -docker-compose exec scm /opt/hadoop/bin/ozone scm -init -docker-compose exec scm /opt/hadoop/sbin/start-ozone.sh -#We need a running SCM for om objectstore creation -#TODO create a utility to wait for the startup -sleep 10 -docker-compose exec om /opt/hadoop/bin/ozone om -createObjectStore -docker-compose exec scm /opt/hadoop/sbin/start-ozone.sh diff --git a/hadoop-ozone/dist/src/main/compose/ozonescripts/stop.sh b/hadoop-ozone/dist/src/main/compose/ozonescripts/stop.sh deleted file mode 100755 index a3ce08af573..00000000000 --- a/hadoop-ozone/dist/src/main/compose/ozonescripts/stop.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash -# 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. -docker-compose exec scm /opt/hadoop/sbin/stop-ozone.sh diff --git a/hadoop-ozone/dist/src/main/ozone/README.txt b/hadoop-ozone/dist/src/main/ozone/README.txt deleted file mode 100644 index 6bbd83ffd04..00000000000 --- a/hadoop-ozone/dist/src/main/ozone/README.txt +++ /dev/null @@ -1,51 +0,0 @@ - - -This is the distribution of Apache Hadoop Ozone. - -Ozone is a submodule of Hadoop with separated release cycle. For more information, check - - http://ozone.hadoop.apache.org - - and - - https://cwiki.apache.org/confluence/display/HADOOP/Ozone+Contributor+Guide - -For more information about Hadoop, check: - - http://hadoop.apache.org - -This distribution includes cryptographic software. The country in -which you currently reside may have restrictions on the import, -possession, use, and/or re-export to another country, of -encryption software. BEFORE using any encryption software, please -check your country's laws, regulations and policies concerning the -import, possession, or use, and re-export of encryption software, to -see if this is permitted. See for more -information. - -The U.S. Government Department of Commerce, Bureau of Industry and -Security (BIS), has classified this software as Export Commodity -Control Number (ECCN) 5D002.C.1, which includes information security -software using or performing cryptographic functions with asymmetric -algorithms. The form and manner of this Apache Software Foundation -distribution makes it eligible for export under the License Exception -ENC Technology Software Unrestricted (TSU) exception (see the BIS -Export Administration Regulations, Section 740.13) for both object -code and source code. - -The following provides more details on the included cryptographic -software: - Hadoop Core uses the SSL libraries from the Jetty project written -by mortbay.org. diff --git a/hadoop-ozone/dist/src/main/smoketest/README.md b/hadoop-ozone/dist/src/main/smoketest/README.md deleted file mode 100644 index c521a54beb2..00000000000 --- a/hadoop-ozone/dist/src/main/smoketest/README.md +++ /dev/null @@ -1,30 +0,0 @@ - - -## Ozone Acceptance Tests - -This directory contains a [robotframework](http://robotframework.org/) based test suite for Ozone to make it easier to check the current state of the package. - -You can run in in any environment after [installing](https://github.com/robotframework/robotframework/blob/master/INSTALL.rst) - -``` -cd $DIRECTORY_OF_OZONE -robot smoketest/basic -``` - -The argument of the `robot` could be any robot file or directory. - -The current configuration in the robot files (hostnames, ports) are adjusted for the docker-based setup but you can easily modify it for any environment. - -The `./test.sh` in this directory can start multiple type of clusters (ozone standalone or ozone + hdfs) and execute the test framework with all of the clusters. diff --git a/hadoop-ozone/dist/src/main/smoketest/basic/basic.robot b/hadoop-ozone/dist/src/main/smoketest/basic/basic.robot deleted file mode 100644 index a69450dbba8..00000000000 --- a/hadoop-ozone/dist/src/main/smoketest/basic/basic.robot +++ /dev/null @@ -1,47 +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 -# -# 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. - -*** Settings *** -Documentation Smoketest ozone cluster startup -Library OperatingSystem -Resource ../commonlib.robot - -*** Variables *** -${COMMON_REST_HEADER} -H "x-ozone-user: bilbo" -H "x-ozone-version: v1" -H "Date: Mon, 26 Jun 2017 04:23:30 GMT" -H "Authorization:OZONE root" -${DATANODE_HOST} localhost - - -*** Test Cases *** - -Test rest interface - ${result} = Execute curl -i -X POST ${COMMON_RESTHEADER} "http://${DATANODE_HOST}:9880/volume1" - Should contain ${result} 201 Created - ${result} = Execute curl -i -X POST ${COMMON_RESTHEADER} "http://${DATANODE_HOST}:9880/volume1/bucket1" - Should contain ${result} 201 Created - ${result} = Execute curl -i -X DELETE ${COMMON_RESTHEADER} "http://${DATANODE_HOST}:9880/volume1/bucket1" - Should contain ${result} 200 OK - ${result} = Execute curl -i -X DELETE ${COMMON_RESTHEADER} "http://${DATANODE_HOST}:9880/volume1" - Should contain ${result} 200 OK - -Check webui static resources - ${result} = Execute curl -s -I http://scm:9876/static/bootstrap-3.3.7/js/bootstrap.min.js - Should contain ${result} 200 - ${result} = Execute curl -s -I http://ozoneManager:9874/static/bootstrap-3.3.7/js/bootstrap.min.js - Should contain ${result} 200 - -Start freon testing - ${result} = Execute ozone freon randomkeys --numOfVolumes 5 --numOfBuckets 5 --numOfKeys 5 --numOfThreads 10 - Wait Until Keyword Succeeds 3min 10sec Should contain ${result} Number of Keys added: 125 - Should Not Contain ${result} ERROR diff --git a/hadoop-ozone/dist/src/main/smoketest/basic/ozone-shell.robot b/hadoop-ozone/dist/src/main/smoketest/basic/ozone-shell.robot deleted file mode 100644 index 14a576170d7..00000000000 --- a/hadoop-ozone/dist/src/main/smoketest/basic/ozone-shell.robot +++ /dev/null @@ -1,82 +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 -# -# 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. - -*** Settings *** -Documentation Test ozone shell CLI usage -Library OperatingSystem -Resource ../commonlib.robot -Test Timeout 2 minute - -*** Variables *** - -*** Test Cases *** -RestClient without http port - Test ozone shell http:// ozoneManager restwoport - -RestClient with http port - Test ozone shell http:// ozoneManager:9874 restwport - -RestClient without host name - Test ozone shell http:// ${EMPTY} restwohost - -RpcClient with port - Test ozone shell o3:// ozoneManager:9862 rpcwoport - -RpcClient without host - Test ozone shell o3:// ${EMPTY} rpcwport - -RpcClient without scheme - Test ozone shell ${EMPTY} ${EMPTY} rpcwoscheme - - -*** Keywords *** -Test ozone shell - [arguments] ${protocol} ${server} ${volume} - ${result} = Execute ozone sh volume create ${protocol}${server}/${volume} --user bilbo --quota 100TB --root - Should not contain ${result} Failed - Should contain ${result} Creating Volume: ${volume} - ${result} = Execute ozone sh volume list ${protocol}${server}/ --user bilbo | grep -Ev 'Removed|WARN|DEBUG|ERROR|INFO|TRACE' | jq -r '.[] | select(.volumeName=="${volume}")' - Should contain ${result} createdOn - ${result} = Execute ozone sh volume list --user bilbo | grep -Ev 'Removed|DEBUG|ERROR|INFO|TRACE|WARN' | jq -r '.[] | select(.volumeName=="${volume}")' - Should contain ${result} createdOn - Execute ozone sh volume update ${protocol}${server}/${volume} --user bill --quota 10TB - ${result} = Execute ozone sh volume info ${protocol}${server}/${volume} | grep -Ev 'Removed|WARN|DEBUG|ERROR|INFO|TRACE' | jq -r '. | select(.volumeName=="${volume}") | .owner | .name' - Should Be Equal ${result} bill - ${result} = Execute ozone sh volume info ${protocol}${server}/${volume} | grep -Ev 'Removed|WARN|DEBUG|ERROR|INFO|TRACE' | jq -r '. | select(.volumeName=="${volume}") | .quota | .size' - Should Be Equal ${result} 10 - Execute ozone sh bucket create ${protocol}${server}/${volume}/bb1 - ${result} = Execute ozone sh bucket info ${protocol}${server}/${volume}/bb1 | grep -Ev 'Removed|WARN|DEBUG|ERROR|INFO|TRACE' | jq -r '. | select(.bucketName=="bb1") | .storageType' - Should Be Equal ${result} DISK - ${result} = Execute ozone sh bucket update ${protocol}${server}/${volume}/bb1 --addAcl user:frodo:rw,group:samwise:r | grep -Ev 'Removed|WARN|DEBUG|ERROR|INFO|TRACE' | jq -r '. | select(.bucketName=="bb1") | .acls | .[] | select(.name=="samwise") | .type' - Should Be Equal ${result} GROUP - ${result} = Execute ozone sh bucket update ${protocol}${server}/${volume}/bb1 --removeAcl group:samwise:r | grep -Ev 'Removed|WARN|DEBUG|ERROR|INFO|TRACE' | jq -r '. | select(.bucketName=="bb1") | .acls | .[] | select(.name=="frodo") | .type' - Should Be Equal ${result} USER - ${result} = Execute ozone sh bucket list ${protocol}${server}/${volume}/ | grep -Ev 'Removed|WARN|DEBUG|ERROR|INFO|TRACE' | jq -r '.[] | select(.bucketName=="bb1") | .volumeName' - Should Be Equal ${result} ${volume} - Run Keyword Test key handling ${protocol} ${server} ${volume} - Execute ozone sh bucket delete ${protocol}${server}/${volume}/bb1 - Execute ozone sh volume delete ${protocol}${server}/${volume} --user bilbo - -Test key handling - [arguments] ${protocol} ${server} ${volume} - Execute ozone sh key put ${protocol}${server}/${volume}/bb1/key1 /opt/hadoop/NOTICE.txt - Execute rm -f NOTICE.txt.1 - Execute ozone sh key get ${protocol}${server}/${volume}/bb1/key1 NOTICE.txt.1 - Execute ls -l NOTICE.txt.1 - ${result} = Execute ozone sh key info ${protocol}${server}/${volume}/bb1/key1 | grep -Ev 'Removed|WARN|DEBUG|ERROR|INFO|TRACE' | jq -r '. | select(.keyName=="key1")' - Should contain ${result} createdOn - ${result} = Execute ozone sh key list ${protocol}${server}/${volume}/bb1 | grep -Ev 'Removed|WARN|DEBUG|ERROR|INFO|TRACE' | jq -r '.[] | select(.keyName=="key1") | .keyName' - Should Be Equal ${result} key1 - Execute ozone sh key delete ${protocol}${server}/${volume}/bb1/key1 diff --git a/hadoop-ozone/dist/src/main/smoketest/commonlib.robot b/hadoop-ozone/dist/src/main/smoketest/commonlib.robot deleted file mode 100644 index e2620fa4340..00000000000 --- a/hadoop-ozone/dist/src/main/smoketest/commonlib.robot +++ /dev/null @@ -1,24 +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 -# -# 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. - -*** Keywords *** - - -Execute - [arguments] ${command} - ${rc} ${output} = Run And Return Rc And Output ${command} - Log ${output} - Should Be Equal As Integers ${rc} 0 - [return] ${output} diff --git a/hadoop-ozone/dist/src/main/smoketest/ozonefs/ozonefs.robot b/hadoop-ozone/dist/src/main/smoketest/ozonefs/ozonefs.robot deleted file mode 100644 index fb7b98cec63..00000000000 --- a/hadoop-ozone/dist/src/main/smoketest/ozonefs/ozonefs.robot +++ /dev/null @@ -1,35 +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 -# -# 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. - -*** Settings *** -Documentation Ozonefs test -Library OperatingSystem -Resource ../commonlib.robot - -*** Variables *** - - -*** Test Cases *** -Create volume and bucket - Execute ozone sh volume create http://ozoneManager/fstest --user bilbo --quota 100TB --root - Execute ozone sh bucket create http://ozoneManager/fstest/bucket1 - -Check volume from ozonefs - ${result} = Execute ozone fs -ls o3://bucket1.fstest/ - -Create directory from ozonefs - Execute ozone fs -mkdir -p o3://bucket1.fstest/testdir/deep - ${result} = Execute ozone sh key list o3://ozoneManager/fstest/bucket1 | grep -v WARN | jq -r '.[].keyName' - Should contain ${result} testdir/deep diff --git a/hadoop-ozone/dist/src/main/smoketest/s3/awscli.robot b/hadoop-ozone/dist/src/main/smoketest/s3/awscli.robot deleted file mode 100644 index b26ad91d446..00000000000 --- a/hadoop-ozone/dist/src/main/smoketest/s3/awscli.robot +++ /dev/null @@ -1,63 +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 -# -# 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. - -*** Settings *** -Documentation S3 gateway test with aws cli -Library OperatingSystem -Library String -Resource ../commonlib.robot - -*** Variables *** -${ENDPOINT_URL} http://s3g:9878 - -*** Keywords *** -Execute AWSCli - [Arguments] ${command} - ${output} = Execute aws s3 --endpoint-url ${ENDPOINT_URL}/${VOLUME} ${command} - [return] ${output} - -*** Test Cases *** - -Create volume and bucket for the tests - ${postfix} = Generate Random String 5 [NUMBERS] - Set Suite Variable ${BUCKET} bucket-${postfix} - Set Suite Variable ${VOLUME} vol-${postfix} - Log Testing s3 commands in /${VOLUME}/${BUCKET} - ${result} = Execute ozone sh volume create /${VOLUME} --user hadoop - ${result} = Execute ozone sh bucket create /${VOLUME}/${BUCKET} - -Install aws s3 cli - Execute sudo apt-get install -y awscli - Set Environment Variable AWS_ACCESS_KEY_ID ANYID - Set Environment Variable AWS_SECRET_ACCESS_KEY ANYKEY - -File upload and directory list - Execute date > /tmp/testfile - ${result} = Execute AWSCli cp /tmp/testfile s3://${BUCKET} - Should contain ${result} upload - ${result} = Execute AWSCli cp /tmp/testfile s3://${BUCKET}/dir1/dir2/file - Should contain ${result} upload - ${result} = Execute AWSCli ls s3://${BUCKET} - Should contain ${result} testfile - Should contain ${result} dir1 - Should not contain ${result} dir2 - ${result} = Execute AWSCli ls s3://${BUCKET}/dir1/ - Should not contain ${result} testfile - Should not contain ${result} dir1 - Should contain ${result} dir2 - ${result} = Execute AWSCli ls s3://${BUCKET}/dir1/dir2/ - Should not contain ${result} testfile - Should not contain ${result} dir1 - Should contain ${result} file diff --git a/hadoop-ozone/dist/src/main/smoketest/test.sh b/hadoop-ozone/dist/src/main/smoketest/test.sh deleted file mode 100755 index b32955a2a52..00000000000 --- a/hadoop-ozone/dist/src/main/smoketest/test.sh +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/env bash -# 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. - -set -e -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" - -execute_tests(){ - COMPOSE_FILE=$DIR/../compose/$1/docker-compose.yaml - TESTS=$2 - echo "Executing test ${TESTS[*]} with $COMPOSE_FILE" - docker-compose -f "$COMPOSE_FILE" down - docker-compose -f "$COMPOSE_FILE" up -d - docker-compose -f "$COMPOSE_FILE" exec datanode sudo apt-get update - docker-compose -f "$COMPOSE_FILE" exec datanode sudo apt-get install -y python-pip - docker-compose -f "$COMPOSE_FILE" exec datanode sudo pip install robotframework - for TEST in "${TESTS[@]}"; do - set +e - docker-compose -f "$COMPOSE_FILE" exec datanode python -m robot "smoketest/$TEST" - set -e - done - if [ "$KEEP_RUNNING" = false ]; then - docker-compose -f "$COMPOSE_FILE" down - fi -} -RUN_ALL=true -KEEP_RUNNING=false -POSITIONAL=() -while [[ $# -gt 0 ]] -do -key="$1" - -case $key in - --env) - DOCKERENV="$2" - RUN_ALL=false - shift # past argument - shift # past value - ;; - --keep) - KEEP_RUNNING=true - shift # past argument - ;; - --help|-h|-help) - cat << EOF - - Acceptance test executor for ozone. - - This is a lightweight test executor for ozone. - - You can run it with - - ./test.sh - - Which executes all the tests in all the available environments. - - Or you can run manually one test with - - ./test.sh --keep --env ozone-hdfs basic - - --keep means that docker cluster won't be stopped after the test (optional) - --env defines the subdirectory under the compose dir - The remaining parameters define the test suites under smoketest dir. - Could be any directory or robot file relative to the smoketest dir. -EOF - exit 0 - ;; - *) - POSITIONAL+=("$1") # save it in an array for later - shift # past argument - ;; -esac -done - -if [ "$RUN_ALL" = true ]; then -# -# This is the definition of the ozone acceptance test suite -# -# We select the test suites and execute them on multiple type of clusters -# - DEFAULT_TESTS=("basic") - execute_tests ozone "${DEFAULT_TESTS[@]}" - TESTS=("ozonefs") - execute_tests ozonefs "${TESTS[@]}" - TESTS=("s3") - execute_tests ozones3 "${TESTS[@]}" -else - execute_tests "$DOCKERENV" "${POSITIONAL[@]}" -fi diff --git a/hadoop-ozone/docs/README.md b/hadoop-ozone/docs/README.md deleted file mode 100644 index 85817a79d06..00000000000 --- a/hadoop-ozone/docs/README.md +++ /dev/null @@ -1,55 +0,0 @@ - -# Hadoop Ozone/HDDS docs - -This subproject contains the inline documentation for Ozone/HDDS components. - -You can create a new page with: - -``` -hugo new content/title.md -``` - -You can check the rendering with: - -``` -hugo serve -``` - -This maven project will create the rendered HTML page during the build (ONLY if hugo is available). -And the dist project will include the documentation. - -You can adjust the menu hierarchy with adjusting the header of the markdown file: - -To show it in the main header add the menu entry: - -``` ---- -menu: main ---- -``` - -To show it as a subpage, you can set the parent. (The value could be the title of the parent page, -our you can defined an `id: ...` in the parent markdown and use that in the parent reference. - -``` ---- -menu: - main: - parent: "Getting started" ---- -``` diff --git a/hadoop-ozone/docs/archetypes/default.md b/hadoop-ozone/docs/archetypes/default.md deleted file mode 100644 index f4cc9998dc6..00000000000 --- a/hadoop-ozone/docs/archetypes/default.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: "{{ replace .Name "-" " " | title }}" -menu: main ---- - diff --git a/hadoop-ozone/docs/config.yaml b/hadoop-ozone/docs/config.yaml deleted file mode 100644 index e86b59970cd..00000000000 --- a/hadoop-ozone/docs/config.yaml +++ /dev/null @@ -1,41 +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 -# -# 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. - - -languageCode: "en-us" -DefaultContentLanguage: "en" -title: "Ozone" -theme: "ozonedoc" -pygmentsCodeFences: true -uglyurls: true -relativeURLs: true - -menu: - main: - - identifier: Starting - name: "Getting Started" - title: "Getting Started" - url: runningviadocker.html - weight: 1 - - identifier: Client - name: Client - title: Client - url: commandshell.html - weight: 2 - - identifier: Tools - name: Tools - title: Tools - url: dozone.html - weight: 3 diff --git a/hadoop-ozone/docs/content/BucketCommands.md b/hadoop-ozone/docs/content/BucketCommands.md deleted file mode 100644 index 3ab35053028..00000000000 --- a/hadoop-ozone/docs/content/BucketCommands.md +++ /dev/null @@ -1,122 +0,0 @@ ---- -title: Bucket Commands -menu: - main: - parent: Client - weight: 3 ---- - - -Ozone shell supports the following bucket commands. - - * [create](#create) - * [delete](#delete) - * [info](#info) - * [list](#list) - * [update](#update) - -### Create - -The bucket create command allows a user to create a bucket. - -***Params:*** - -| Arguments | Comment | -|--------------------------------|-----------------------------------------| -| Uri | The name of the bucket in **/volume/bucket** format. - -{{< highlight bash >}} -ozone sh bucket create /hive/jan -{{< /highlight >}} - -The above command will create a bucket called _jan_ in the _hive_ volume. -Since no scheme was specified this command defaults to O3 (RPC) protocol. - -### Delete - -The bucket delete commands allows an user to delete a volume. If the -bucket is not empty then this command will fail. - -***Params:*** - -| Arguments | Comment | -|--------------------------------|-----------------------------------------| -| Uri | The name of the bucket - -{{< highlight bash >}} -ozone sh volume delete /hive/jan -{{< /highlight >}} - -The above command will delete _jan_ bucket if it is empty. - -### Info - -The bucket info commands returns the information about the bucket. -***Params:*** - -| Arguments | Comment | -|--------------------------------|-----------------------------------------| -| Uri | The name of the bucket. - -{{< highlight bash >}} -ozone sh bucket info /hive/jan -{{< /highlight >}} - -The above command will print out the information about _jan_ bucket. - -### List - -The bucket list commands allows uset to list the buckets in a volume. - -***Params:*** - -| Arguments | Comment | -|--------------------------------|-----------------------------------------| -| -l, --length | Maximum number of results to return. Default: 100 -| -p, --prefix | Optional, Only buckets that match this prefix will be returned. -| -s, --start | The listing will start from key after the start key. -| Uri | The name of the _volume_. - -{{< highlight bash >}} -ozone sh bucket list /hive -{{< /highlight >}} - -This command will list all buckets on the volume _hive_. - - - -### Update - -The bucket update command allows changing access permissions on bucket. - -***Params:*** - -| Arguments | Comment | -|--------------------------------|-----------------------------------------| -| --addAcl | Optional, Comma separated ACLs that will added to bucket. -| --removeAcl | Optional, Comma separated list of acl to remove. -| Uri | The name of the bucket. - -{{< highlight bash >}} -ozone sh bucket update --addAcl=user:bilbo:rw /hive/jan -{{< /highlight >}} - -The above command gives user bilbo read/write permission to the bucket. - -You can try out these commands from the docker instance of the [Alpha -Cluster](runningviadocker.html). diff --git a/hadoop-ozone/docs/content/BuildingSources.md b/hadoop-ozone/docs/content/BuildingSources.md deleted file mode 100644 index 1953f47f59b..00000000000 --- a/hadoop-ozone/docs/content/BuildingSources.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: Building from Sources -weight: 1 -menu: - main: - parent: Starting - weight: 5 ---- - - -***This is a guide on how to build the ozone sources. If you are not -planning to build sources yourself, you can safely skip this page.*** - -If you are a Hadoop ninja, and wise in the ways of Apache, you already know -that a real Apache release is a source release. - -If you want to build from sources, Please untar the source tarball and run -the ozone build command. This instruction assumes that you have all the -dependencies to build Hadoop on your build machine. If you need instructions -on how to build Hadoop, please look at the Apache Hadoop Website. - -{{< highlight bash >}} -mvn clean package -DskipTests=true -Dmaven.javadoc.skip=true -Phdds -Pdist -Dtar -DskipShade -{{< /highlight >}} - - -This will build an ozone-\.tar.gz in your target directory. - -You can copy this tarball and use this instead of binary artifacts that are -provided along with the official release. - -## How to test the build -You can run the acceptance tests in the hadoop-ozone directory to make sure -that your build is functional. To launch the acceptance tests, please follow - the instructions in the **README.md** in the - ```$hadoop_src/hadoop-ozone/acceptance-test``` directory. Acceptance tests - will start a small ozone cluster and verify that ozone shell and ozone file - system is fully functional. diff --git a/hadoop-ozone/docs/content/CommandShell.md b/hadoop-ozone/docs/content/CommandShell.md deleted file mode 100644 index 74072a5218d..00000000000 --- a/hadoop-ozone/docs/content/CommandShell.md +++ /dev/null @@ -1,109 +0,0 @@ ---- -title: Ozone CLI -menu: - main: - parent: Client - weight: 1 ---- - - -Ozone has a set of command line tools that can be used to manage ozone. - -All these commands are invoked via the ```ozone``` script. - -The commands supported by ozone are: - - * **classpath** - Prints the class path needed to get the hadoop jar and the - required libraries. - * **fs** - Runs a command on ozone file system. - * **datanode** - Via daemon command, the HDDS data nodes can be started or - stopped. - * **envvars** - Display computed Hadoop environment variables. - * **freon** - Runs the ozone load generator. - * **genesis** - Developer Only, Ozone micro-benchmark application. - * **getozoneconf** - Reads ozone config values from configuration. - * **jmxget** - Get JMX exported values from NameNode or DataNode. - * **om** - Ozone Manager, via daemon command can be started or stopped. - * **sh** - Primary command line interface for ozone. - * **scm** - Storage Container Manager service, via daemon can be - stated or stopped. - * **scmcli** - Developer only, Command Line Interface for the Storage - Container Manager. - * **version** - Prints the version of Ozone and HDDS. - * **genconf** - Generate minimally required ozone configs and output to - ozone-site.xml. - -## Understanding Ozone command shell -The most used command when working with Ozone is the Ozone command shell. -Ozone command shell gives a command shell interface to work against -Ozone. - -The Ozone shell commands take the following format. - -> _ozone sh object action url_ - -**ozone** script is used to invoke all Ozone sub-commands. The ozone shell is -invoked via ```sh``` command. - -The object can be a volume, bucket or a key. The action is various verbs like - create, list, delete etc. - - -Ozone URL can point to a volume, bucket or keys in the following format: - -_\[scheme\]\[server:port\]/volume/bucket/key_ - - -Where, - -1. Scheme - Can be one of the following - * o3 - Ozone's native RPC protocol. If you specify this scheme, the - native RPC protocol is used while communicating with Ozone Manager and - data nodes. - * http/https - If an HTTP protocol is specified, then Ozone shell assumes - that you are interested in using the Ozone Rest protocol and falls back - to using the REST protocol instead of RPC. - If no protocol is specified, the Ozone shell defaults to the native RPC - protocol. - -2. Server:Port - This is the address of the Ozone Manager. This can be server - only, in that case, the default port is used. If this value is omitted -then the defaults specified in the ozone-site.xml will be used for Ozone -Manager address. - -Depending on the call, the volume/bucket/key names will be part of the URL. -Please see volume commands, bucket commands, and key commands section for more -detail. - -## Invoking help - -Ozone shell help can be invoked at _object_ level or at _action_ level. -For example: - -{{< highlight bash >}} -ozone sh volume --help -{{< /highlight >}} - -This will show all possible actions for volumes. - -or it can be invoked to explain a specific action like -{{< highlight bash >}} -ozone sh volume create --help -{{< /highlight >}} -This command will give you command line options of the create command. - diff --git a/hadoop-ozone/docs/content/Concepts.md b/hadoop-ozone/docs/content/Concepts.md deleted file mode 100644 index 7f7dd3b4899..00000000000 --- a/hadoop-ozone/docs/content/Concepts.md +++ /dev/null @@ -1,108 +0,0 @@ ---- -title: Architecture -date: "2017-10-10" -menu: main ---- - - - -Ozone is a redundant, distributed object store build by -leveraging primitives present in HDFS. The primary design point of ozone is scalability, and it aims to scale to billions of objects. - -Ozone consists of volumes, buckets, and keys. A volume is similar to a home directory in the ozone world. Only an administrator can create it. Volumes are used to store buckets. Once a volume is created users can create as many buckets as needed. Ozone stores data as keys which live inside these buckets. - -Ozone namespace is composed of many storage volumes. Storage volumes are also used as the basis for storage accounting. - -To access a key, an Ozone URL has the following format: - -``` -http://servername:port/volume/bucket/key -``` - -Where the server name is the name of a data node, the port is the data node HTTP port. The volume represents the name of the ozone volume; bucket is an ozone bucket created by the user and key represents the file. - -Please look at the [command line interface]({{< ref "CommandShell.md#shell" >}}) for more info. - -Ozone supports both REST and RPC protocols. Clients can choose either of these protocols to communicate with Ozone. Please see the [client documentation]({{< ref "JavaApi.md" >}}) for more details. - -Ozone separates namespace management and block space management; this helps -ozone to scale much better. The namespace is managed by a daemon called -[Ozone Manager ]({{< ref "OzoneManager.md" >}}) (OM), and block space is -managed by [Storage Container Manager] ({{< ref "Hdds.md" >}}) (SCM). - -The data nodes provide replication and ability to store blocks; these blocks are stored in groups to reduce the metadata pressure on SCM. This groups of blocks are called storage containers. Hence the block manager is called storage container -manager. - -Ozone Overview --------------- - -
The following diagram is a high-level overview of the core components of Ozone.

 - -![Architecture diagram](../../OzoneOverview.svg) - -The main elements of Ozone are
: - -### Ozone Manager
 - -[Ozone Manager]({{< ref "OzoneManager.md" >}}) (OM) takes care of the Ozone's namespace. -All ozone objects like volumes, buckets, and keys are managed by OM. In Short, OM is the metadata manager for Ozone. -OM talks to blockManager(SCM) to get blocks and passes it on to the Ozone -client. Ozone client writes data to these blocks. -OM will eventually be replicated via Apache Ratis for High Availability.
 - -### Storage Container Manager - -[Storage Container Manager]({{< ref "Hdds.md" >}}) (SCM) is the block and cluster manager for Ozone. -SCM along with data nodes offer a service called 'storage containers'. -A storage container is a group unrelated of blocks that are managed together as a single entity. - -SCM offers the following abstractions.

 - -![SCM Abstractions](../../SCMBlockDiagram.png) - -### Blocks -Blocks are similar to blocks in HDFS. They are replicated store of data. Client writes data to blocks. - -### Containers -A collection of blocks replicated and managed together. - -### Pipelines -SCM allows each storage container to choose its method of replication. -For example, a storage container might decide that it needs only one copy of a block -and might choose a stand-alone pipeline. Another storage container might want to have a very high level of reliability and pick a RATIS based pipeline. In other words, SCM allows different kinds of replication strategies to co-exist. The client while writing data, chooses a storage container with required properties. - -### Pools -A group of data nodes is called a pool. For scaling purposes, -we define a pool as a set of machines. This makes management of data nodes easier. - -### Nodes -The data node where data is stored. SCM monitors these nodes via heartbeat. - -### Clients -Ozone ships with a set of clients. Ozone [CLI]({{< ref "CommandShell.md#shell" >}}) is the command line interface like 'hdfs' command.
 [Freon] ({{< ref "Freon.md" >}}) is a load generation tool for Ozone.
 - -### REST Handler -Ozone provides an RPC (Remote Procedure Call) as well as a REST (Representational State Transfer) interface. This allows clients to be written in many languages quickly. Ozone strives to maintain an API compatibility between REST and RPC. -For most purposes, a client can make one line change to switch from REST to RPC or vice versa. 
 - -### Ozone File System -Ozone file system (TODO: Add documentation) is a Hadoop compatible file system. This allows Hadoop services and applications like Hive and Spark to run against -Ozone without any change. - -### Ozone Client -This is similar to DFSClient in HDFS. This is the standard client to talk to Ozone. All other components that we have discussed so far rely on Ozone client. Ozone client supports both RPC and REST protocols. diff --git a/hadoop-ozone/docs/content/Dozone.md b/hadoop-ozone/docs/content/Dozone.md deleted file mode 100644 index 7906cf3fd4e..00000000000 --- a/hadoop-ozone/docs/content/Dozone.md +++ /dev/null @@ -1,110 +0,0 @@ ---- -title: "Dozone & Dev Tools" -date: 2017-08-10 -menu: - main: - parent: Tools ---- - - - -Dozone stands for docker for ozone. Ozone supports docker to make it easy to develop and test ozone. Starting a docker based ozone container is simple. - -In the `compose/ozone` directory there are two files that define the docker and ozone settings. - -Developers can - -{{< highlight bash >}} -cd compose/ozone -{{< /highlight >}} - -and simply run - -{{< highlight bash >}} -docker-compose up -d -{{< /highlight >}} - -to run a ozone cluster on docker. - -This command will launch a Namenode, OM, SCM and a data node. - -To access the OM UI, one can run 'http://localhost:9874'. - -_Please note_: dozone does not map the data node ports to the 9864. Instead, it maps to the ephemeral port range. So many examples in the command shell will not work if you run those commands from the host machine. To find out where the data node port is listening, you can run the `docker ps` command or always ssh into a container before running ozone commands. - -To shutdown a running docker based ozone cluster, please run - -{{< highlight bash >}} -docker-compose down -{{< /highlight >}} - - -Adding more config settings ---------------------------- -The file called `docker-config` contains all ozone specific config settings. This file is processed to create the ozone-site.xml. - -Useful Docker & Ozone Commands ------------------------------- - -If you make any modifications to ozone, the simplest way to test it is to run freon and unit tests. - -Here are the instructions to run corona in a docker based cluster. - -{{< highlight bash >}} -docker-compose exec datanode bash -{{< /highlight >}} - -This will open a bash shell on the data node container. -Now we can execute corona for load generation. - -{{< highlight bash >}} -ozone freon randomkeys --numOfVolumes=10 --numOfBuckets 10 --numOfKeys 10 -{{< /highlight >}} - -Here is a set helpful commands while working with docker for ozone. -To check the status of the components: - -{{< highlight bash >}} -docker-compose ps -{{< /highlight >}} - -To get logs from a specific node/service: - -{{< highlight bash >}} -docker-compose logs scm -{{< /highlight >}} - - -As the WebUI ports are forwarded to the external machine, you can check the web UI: - -* For the Storage Container Manager: http://localhost:9876 -* For the Ozone Managerr: http://localhost:9874 -* For the Datanode: check the port with docker ps (as there could be multiple data node ports are mapped to the ephemeral port range) -* For the Namenode: http://localhost:9870 - -You can start multiple data nodes with: - -{{< highlight bash >}} -docker-compose scale datanode=3 -{{< /highlight >}} - -You can test the commands from the [Ozone CLI]({{< ref "CommandShell.md#shell" >}}) after opening a new bash shell in one of the containers: - -{{< highlight bash >}} -docker-compose exec datanode bash -{{< /highlight >}} diff --git a/hadoop-ozone/docs/content/Freon.md b/hadoop-ozone/docs/content/Freon.md deleted file mode 100644 index 6ef0280717e..00000000000 --- a/hadoop-ozone/docs/content/Freon.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: Freon -date: "2017-09-02T23:58:17-07:00" -menu: - main: - parent: Tools ---- - - -Overview --------- - -Freon is a load-generator for Ozone. This tool is used for testing the functionality of ozone. - -### Random keys - -In randomkeys mode, the data written into ozone cluster is randomly generated. -Each key will be of size 10 KB. - -The number of volumes/buckets/keys can be configured. The replication type and -factor (eg. replicate with ratis to 3 nodes) Also can be configured. - -For more information use - -`bin/ozone freon --help` - -### Example - -{{< highlight bash >}} -ozone freon randomkeys --numOfVolumes=10 --numOfBuckets 10 --numOfKeys 10 --replicationType=RATIS --factor=THREE -{{< /highlight >}} - -{{< highlight bash >}} -*************************************************** -Status: Success -Git Base Revision: 48aae081e5afacbb3240657556b26c29e61830c3 -Number of Volumes created: 10 -Number of Buckets created: 100 -Number of Keys added: 1000 -Ratis replication factor: THREE -Ratis replication type: RATIS -Average Time spent in volume creation: 00:00:00,035 -Average Time spent in bucket creation: 00:00:00,319 -Average Time spent in key creation: 00:00:03,659 -Average Time spent in key write: 00:00:10,894 -Total bytes written: 10240000 -Total Execution time: 00:00:16,898 -*********************** -{{< /highlight >}} diff --git a/hadoop-ozone/docs/content/Hdds.md b/hadoop-ozone/docs/content/Hdds.md deleted file mode 100644 index 9978c26e846..00000000000 --- a/hadoop-ozone/docs/content/Hdds.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: "Hadoop Distributed Data Store" -date: "2017-09-14" -menu: - main: - parent: Architecture -weight: 10 ---- - - -SCM Overview ------------- - -Storage Container Manager or SCM is a very important component of ozone. SCM -offers block and container-based services to Ozone Manager. A container is a -collection of unrelated blocks under ozone. SCM and data nodes work together -to maintain the replication levels needed by the cluster. - -It is easier to look at a putKey operation to understand the role that SCM plays. - -To put a key, a client makes a call to KSM with the following arguments. - --- putKey(keyName, data, pipeline type, replication count) - -1. keyName - refers to the file name. -2. data - The data that the client wants to write. -3. pipeline type - Allows the client to select the pipeline type. A pipeline - refers to the replication strategy used for replicating a block. Ozone - currently supports Stand Alone and Ratis as two different pipeline types. -4. replication count - This specifies how many copies of the block replica should be maintained. - -In most cases, the client does not specify the pipeline type and replication - count. The default pipeline type and replication count are used. - - -Ozone Manager when it receives the putKey call, makes a call to SCM asking -for a pipeline instance with the specified property. So if the client asked -for RATIS replication strategy and a replication count of three, then OM -requests SCM to return a set of data nodes that meet this capability. - -If SCM can find this a pipeline ( that is a set of data nodes) that can meet -the requirement from the client, then those nodes are returned to OM. OM will -persist this info and return a tuple consisting of {BlockID, ContainerName, and Pipeline}. - -If SCM is not able to find a pipeline, then SCM creates a logical pipeline and then returns it. - - -SCM manages blocks, containers, and pipelines. To return healthy pipelines, -SCM also needs to understand the node health. So SCM listens to heartbeats -from data nodes and acts as the node manager too. diff --git a/hadoop-ozone/docs/content/JavaApi.md b/hadoop-ozone/docs/content/JavaApi.md deleted file mode 100644 index 1d32bed1ecf..00000000000 --- a/hadoop-ozone/docs/content/JavaApi.md +++ /dev/null @@ -1,172 +0,0 @@ ---- -title: "Java API" -date: "2017-09-14" -menu: - main: - parent: "Client" ---- - - -Introduction -------------- - -Ozone ships with it own client library, that supports both RPC(Remote -Procedure call) and REST(Representational State Transfer). This library is -the primary user interface to ozone. - -It is trivial to switch from RPC to REST or vice versa, by setting the -property _ozone.client.protocol_ in the configuration or by calling the -appropriate factory method. - -## Creating an Ozone client -The Ozone client factory creates the ozone client. It allows the user to -specify the protocol of communication. For example, to get an REST client, we -can use - -{{< highlight java >}} -OzoneClient ozClient = OzoneClientFactory.getRestClient(); -{{< /highlight >}} - -And to get a a RPC client we can call - -{{< highlight java >}} -OzoneClient ozClient = OzoneClientFactory.getRpcClient(); -{{< /highlight >}} - -If the user want to create a client based on the configuration, then they can -call - -{{< highlight java >}} -OzoneClient ozClient = OzoneClientFactory.getClient(); -{{< /highlight >}} - -and an appropriate client based on configuration will be returned. - -## Writing data using Ozone Client - -The hierarchy of data inside ozone is a volume, bucket and a key. A volume -is a collection of buckets. A bucket is a collection of keys. To write data -to the ozone, you need a volume, bucket and a key. - -### Creating a Volume - -Once we have a client, we need to get a reference to the ObjectStore. This -is done via - -{{< highlight java >}} -ObjectStore objectStore = ozClient.getObjectStore(); -{{< /highlight >}} - -An object store represents an active cluster against which the client is working. - -{{< highlight java >}} -// Let us create a volume to store our game assets. -// This uses default arguments for creating that volume. -objectStore.createVolume(“assets”); - -// Let us verify that the volume got created. -OzoneVolume assets = objectStore.getVolume(“assets”); -{{< /highlight >}} - - -It is possible to pass an array of arguments to the createVolume by creating volume arguments. - -### Creating a Bucket - -Once you have a volume, you can create buckets inside the volume. - -{{< highlight bash >}} -// Let us create a bucket called videos. -assets.createBucket(“videos”); -Ozonebucket video = assets.getBucket(“videos”); -{{< /highlight >}} - -At this point we have a usable volume and a bucket. Our volume is called assets and bucket is called videos. - -Now we can create a Key. - -### Reading and Writing a Key - -With a bucket object the users can now read and write keys. The following code reads a video called intro.mp4 from the local disk and stores in the video bucket that we just created. - -{{< highlight bash >}} -// read data from the file, this is a user provided function. -byte [] vidoeData = readFile(“into.mp4”); - -// Create an output stream and write data. -OzoneOutputStream videoStream = video.createKey(“intro.mp4”, 1048576); -videoStream.write(videoData); - -// Close the stream when it is done. - videoStream.close(); - - -// We can use the same bucket to read the file that we just wrote, by creating an input Stream. -// Let us allocate a byte array to hold the video first. -byte[] data = new byte[(int)1048576]; -OzoneInputStream introStream = video.readKey(“intro.mp4”); -// read intro.mp4 into the data buffer -introStream.read(data); -introStream.close(); -{{< /highlight >}} - - -Here is a complete example of the code that we just wrote. Please note the close functions being called in this program. - -{{< highlight java >}} -// Let us create a client -OzoneClient ozClient = OzoneClientFactory.getClient(); - -// Get a reference to the ObjectStore using the client -ObjectStore objectStore = ozClient.getObjectStore(); - -// Let us create a volume to store our game assets. -// This default arguments for creating that volume. -objectStore.createVolume(“assets”); - -// Let us verify that the volume got created. -OzoneVolume assets = objectStore.getVolume(“assets”); - -// Let us create a bucket called videos. -assets.createBucket(“videos”); -Ozonebucket video = assets.getBucket(“videos”); - -// read data from the file, this is assumed to be a user provided function. -byte [] vidoeData = readFile(“into.mp4”); - -// Create an output stream and write data. -OzoneOutputStream videoStream = video.createKey(“intro.mp4”, 1048576); -videoStream.write(videoData); - -// Close the stream when it is done. - videoStream.close(); - - -// We can use the same bucket to read the file that we just wrote, by creating an input Stream. -// Let us allocate a byte array to hold the video first. - -byte[] data = new byte[(int)1048576]; -OzoneInputStream introStream = video.readKey(“into.mp4”); -introStream.read(data); - -// Close the stream when it is done. -introStream.close(); - -// Close the client. -ozClient.close(); -{{< /highlight >}} diff --git a/hadoop-ozone/docs/content/KeyCommands.md b/hadoop-ozone/docs/content/KeyCommands.md deleted file mode 100644 index 0139a288c9f..00000000000 --- a/hadoop-ozone/docs/content/KeyCommands.md +++ /dev/null @@ -1,127 +0,0 @@ ---- -title: Key Commands -menu: - main: - parent: Client - weight: 3 ---- - - -Ozone shell supports the following key commands. - - * [get](#get) - * [put](#put) - * [delete](#delete) - * [info](#info) - * [list](#list) - - -### Get - -The key get command downloads a key from Ozone cluster to local file system. - -***Params:*** - -| Arguments | Comment | -|--------------------------------|-----------------------------------------| -| Uri | The name of the key in **/volume/bucket/key** format. -| FileName | Local file to download the key to. - - -{{< highlight bash >}} -ozone sh key get /hive/jan/sales.orc sales.orc -{{< /highlight >}} -Downloads the file sales.orc from the _/hive/jan_ bucket and writes to the -local file sales.orc. - -### Put - -Uploads a file from the local file system to the specified bucket. - -***Params:*** - - -| Arguments | Comment | -|--------------------------------|-----------------------------------------| -| Uri | The name of the key in **/volume/bucket/key** format. -| FileName | Local file to upload. -| -r, --replication | Optional, Number of copies, ONE or THREE are the options. Picks up the default from cluster configuration. - -{{< highlight bash >}} -ozone sh key put /hive/jan/corrected-sales.orc sales.orc -{{< /highlight >}} -The above command will put the sales.orc as a new key into _/hive/jan/corrected-sales.orc_. - -### Delete - -The delete key command removes the key from the bucket. - -***Params:*** - -| Arguments | Comment | -|--------------------------------|-----------------------------------------| -| Uri | The name of the key. - -{{< highlight bash >}} -ozone sh key delete /hive/jan/corrected-sales.orc -{{< /highlight >}} - -The above command deletes the key _/hive/jan/corrected-sales.orc_. - - -### Info - -The key info commands returns the information about the key. -***Params:*** - -| Arguments | Comment | -|--------------------------------|-----------------------------------------| -| Uri | The name of the key. - -{{< highlight bash >}} -ozone sh key info /hive/jan/sales.orc -{{< /highlight >}} - -The above command will print out the information about _/hive/jan/sales.orc_ -key. - -### List - -The key list commands allows user to list all keys in a bucket. - -***Params:*** - -| Arguments | Comment | -|--------------------------------|-----------------------------------------| -| -l, --length | Maximum number of results to return. Default: 1000 -| -p, --prefix | Optional, Only buckets that match this prefix will be returned. -| -s, --start | The listing will start from key after the start key. -| Uri | The name of the _volume_. - -{{< highlight bash >}} -ozone sh key list /hive/jan -{{< /highlight >}} - -This command will list all key in the bucket _/hive/jan_. - - - - - -You can try out these commands from the docker instance of the [Alpha -Cluster](runningviadocker.html). diff --git a/hadoop-ozone/docs/content/OzoneFS.md b/hadoop-ozone/docs/content/OzoneFS.md deleted file mode 100644 index d0621bee6dd..00000000000 --- a/hadoop-ozone/docs/content/OzoneFS.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Ozone File System -date: 2017-09-14 -menu: main -menu: - main: - parent: Client ---- - - -There are many Hadoop compatible files systems under Hadoop. Hadoop compatible file systems ensures that storage backends like Ozone can easily be integrated into Hadoop eco-system. - -## Setting up the Ozone file system - -To create an ozone file system, we have to choose a bucket where the file system would live. This bucket will be used as the backend store for OzoneFileSystem. All the files and directories will be stored as keys in this bucket. - -Please run the following commands to create a volume and bucket, if you don't have them already. - -{{< highlight bash >}} -ozone sh volume create /volume -ozone sh bucket create /volume/bucket -{{< /highlight >}} - -Once this is created, please make sure that bucket exists via the listVolume or listBucket commands. - -Please add the following entry to the core-site.xml. - -{{< highlight xml >}} - - fs.o3.impl - org.apache.hadoop.fs.ozone.OzoneFileSystem - - - fs.default.name - o3://localhost:9864/volume/bucket - -{{< /highlight >}} - -This will make this bucket to be the default file system for HDFS dfs commands and register the o3 file system type.. - -You also need to add the ozone-filesystem.jar file to the classpath: - -{{< highlight bash >}} -export HADOOP_CLASSPATH=/opt/ozone/share/hadoop/ozonefs/hadoop-ozone-filesystem.jar:$HADOOP_CLASSPATH -{{< /highlight >}} - - - - -Once the default Filesystem has been setup, users can run commands like ls, put, mkdir, etc. -For example, - -{{< highlight bash >}} -hdfs dfs -ls / -{{< /highlight >}} - -or - -{{< highlight bash >}} -hdfs dfs -mkdir /users -{{< /highlight >}} - - -Or put command etc. In other words, all programs like Hive, Spark, and Distcp will work against this file system. -Please note that any keys created/deleted in the bucket using methods apart from OzoneFileSystem will show up as diectories and files in the Ozone File System. diff --git a/hadoop-ozone/docs/content/OzoneManager.md b/hadoop-ozone/docs/content/OzoneManager.md deleted file mode 100644 index 560f827a58d..00000000000 --- a/hadoop-ozone/docs/content/OzoneManager.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: "Ozone Manager" -date: "2017-09-14" -menu: - main: - parent: Architecture -weight: 11 ---- - - -OM Overview -------------- - -Ozone Manager or OM is the namespace manager for Ozone. The clients (RPC clients, Rest proxy, Ozone file system, etc.) communicate with OM to create and delete various ozone objects. - -Each ozone volume is the root of a namespace under OM. This is very different from HDFS which provides a single rooted file system. - -Ozone's namespace is a collection of volumes or is a forest instead of a -single rooted tree as in HDFS. This property makes it easy to deploy multiple - OMs for scaling, this feature is under development. - -OM Metadata ------------------ - -Conceptually, OM maintains a list of volumes, buckets, and keys. For each user, it maintains a list of volumes. For each volume, the list of buckets and for each bucket the list of keys. - -Right now, OM is a single instance service. Ozone already relies on Apache Ratis (A Replicated State Machine based on Raft protocol). OM will be extended to replicate all its metadata via Ratis. With that, OM will be highly available. - -OM UI ------------- - -OM supports a simple UI for the time being. The default port of OM is 9874. To access the OM UI, the user can connect to http://OM:port or for a concrete example, -``` -http://omserver:9874/ -``` -OM UI primarily tries to measure load and latency of OM. The first section of OM UI relates to the number of operations seen by the cluster broken down by the object, operation and whether the operation was successful. - -The latter part of the UI is focused on latency and number of operations that OM is performing. - -One of the hardest problems in HDFS world is discovering the numerous settings offered to tune HDFS. Ozone solves that problem by tagging the configs. To discover settings, click on "Common Tools"->Config. This will take you to the ozone config UI. - -Config UI ------------- - -The ozone config UI is a matrix with row representing the tags, and columns representing All, OM and SCM. - -Suppose a user wanted to discover the required settings for ozone. Then the user can tick the checkbox that says "Required." -This will filter out all "Required" settings along with the description of what each setting does. - -The user can combine different checkboxes and UI will combine the results. That is, If you have more than one row selected, then all keys for those chosen tags are displayed together. - -We are hopeful that this leads to a more straightforward way of discovering settings that manage ozone. - - -OM and SCM -------------------- -[Storage container manager]({{< ref "Hdds.md" >}}) or (SCM) is the block manager - for ozone. When a client requests OM for a set of data nodes to write data, OM talk to SCM and gets a block. - -A block returned by SCM contains a pipeline, which is a set of nodes that we participate in that block replication. - -So OM is dependent on SCM for reading and writing of Keys. However, OM is independent of SCM while doing metadata operations like ozone volume or bucket operations. diff --git a/hadoop-ozone/docs/content/RealCluster.md b/hadoop-ozone/docs/content/RealCluster.md deleted file mode 100644 index 9d86c8458a3..00000000000 --- a/hadoop-ozone/docs/content/RealCluster.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -title: Starting an Ozone Cluster -weight: 1 -menu: - main: - parent: Starting - weight: 3 ---- - - -Before we boot up the Ozone cluster, we need to initialize both SCM and Ozone Manager. - -{{< highlight bash >}} -ozone scm -init -{{< /highlight >}} -This allows SCM to create the cluster Identity and initialize its state. -The ```init``` command is similar to Namenode format. Init command is executed only once, that allows SCM to create all the required on-disk structures to work correctly. -{{< highlight bash >}} -ozone --daemon start scm -{{< /highlight >}} - -Once we know SCM is up and running, we can create an Object Store for our use. This is done by running the following command. - -{{< highlight bash >}} -ozone om -createObjectStore -{{< /highlight >}} - - -Once Ozone manager has created the Object Store, we are ready to run the name -services. - -{{< highlight bash >}} -ozone --daemon start om -{{< /highlight >}} - -At this point Ozone's name services, the Ozone manager, and the block service SCM is both running. -**Please note**: If SCM is not running -```createObjectStore``` command will fail. SCM start will fail if on-disk data structures are missing. So please make sure you have done both ```init``` and ```createObjectStore``` commands. - -Now we need to start the data nodes. Please run the following command on each datanode. -{{< highlight bash >}} -ozone --daemon start datanode -{{< /highlight >}} - -At this point SCM, Ozone Manager and data nodes are up and running. - -***Congratulations!, You have set up a functional ozone cluster.*** - -------- -If you want to make your life simpler, you can just run -{{< highlight bash >}} -ozone scm -init -ozone om -createObjectStore -start-ozone.sh -{{< /highlight >}} -This assumes that you have set up the slaves file correctly and ssh -configuration that allows ssh-ing to all data nodes. This is the same as the -HDFS configuration, so please refer to HDFS documentation on how to set this -up. diff --git a/hadoop-ozone/docs/content/Rest.md b/hadoop-ozone/docs/content/Rest.md deleted file mode 100644 index a25d3ab0ae6..00000000000 --- a/hadoop-ozone/docs/content/Rest.md +++ /dev/null @@ -1,544 +0,0 @@ ---- -title: REST API -menu: - main: - parent: Client ---- - - -The Ozone REST API's allows user to access ozone via REST protocol. - -## Authentication and Authorization - -For time being, The default authentication mode of REST API is insecure access -mode, which is *Simple* mode. Under this mode, ozone server trusts the user -name specified by client and it does not perform any authentication. - -User name can be specified in HTTP header by - -* `x-ozone-user: {USER_NAME}` - -for example if add following header *x-ozone-user: bilbo* in the HTTP request, -then operation will be executed as *bilbo* user. -In *Simple* mode, there is no real authorization either. Client can be -authorized to obtain administrator privilege by using HTTP header - -* `Authorization: {AUTH_METHOD} {SIGNATURE}` - -for example set following header *Authorization: OZONE root* in the HTTP request, -then ozone will authorize the client with administrator privilege. - -## Common REST Headers - -The following HTTP headers must be set for each REST call. - -| Property | Description | -|:---- |:---- -| Authorization | The authorization field determines which authentication method is used by ozone. Currently only *simple* mode is supported, the corresponding value is *OZONE*. Optionally an user name can be set as *OZONE {USER_NAME}* to authorize as a particular user. | -| Date | Standard HTTP header that represents dates. The format is - day of the week, month, day, year and time (military time format) in GMT. Any other time zone will be rejected by ozone server. Eg. *Date : Mon, Apr 4, 2016 06:22:00 GMT*. This field is required. | -| x-ozone-version | A required HTTP header to indicate which version of API this call will be communicating to. E.g *x-ozone-version: v1*. Currently ozone only publishes v1 version API. | - -## Common Reply Headers - -The common reply headers are part of all Ozone server replies. - -| Property | Description | -|:---- |:---- -| Date | This is the HTTP date header and it is set to server’s local time expressed in GMT. | -| x-ozone-request-id | This is a UUID string that represents an unique request ID. This ID is used to track the request through the ozone system and is useful for debugging purposes. | -| x-ozone-server-name | Fully qualified domain name of the sever which handled the request. | - -## Volume APIs - -### Create a Volume - -This API allows admins to create a new storage volume. - -Schema: - -- `POST /{volume}?quota=` - -Query Parameter: - -| Query Parameter | Value | Description | -|:---- |:---- |:---- -| quota | long | Optional. Quota size in BYTEs, MBs, GBs or TBs | - -Sample HTTP POST request: - - curl -i -X POST -H "x-ozone-user: bilbo" -H "x-ozone-version: v1" -H "Date: Mon, 26 Jun 2017 04:23:30 GMT" -H "Authorization:OZONE root" "http://localhost:9880/volume-to-create" - -this request creates a volume as user *bilbo*, the authorization field is set to *OZONE root* because this call requires administration privilege. The client receives a response with zero content length. - - HTTP/1.1 201 Created - x-ozone-server-name: localhost - x-ozone-request-id: 2173deb5-bbb7-4f0a-8236-f354784e3bae - Date: Tue, 27 Jun 2017 07:42:04 GMT - Content-Type: application/octet-stream - Content-Length: 0 - Connection: keep-alive - -### Update Volume - -This API allows administrators to update volume info such as ownership and quota. This API requires administration privilege. - -Schema: - -- `PUT /{volume}?quota=` - -Query Parameter: - -| Query Parameter | Value | Description | -|:---- |:---- |:---- -| quota | long \| remove | Optional. Quota size in BYTEs, MBs, GBs or TBs. Or use string value *remove* to remove an existing quota for a volume. | - -Sample HTTP PUT request: - - curl -X PUT -H "Authorization:OZONE root" -H "Date: Mon, 26 Jun 2017 04:23:30 GMT" -H "x-ozone-version: v1" -H "x-ozone-user: john" http://localhost:9880/volume-to-update - -this request modifies the owner of */volume-to-update* to *john*. - -### Delete Volume - -This API allows user to delete a volume owned by themselves if the volume is not empty. Administrators can delete volumes owned by any user. - -Schema: - -- `DELETE /{volume}` - -Sample HTTP DELETE request: - - curl -i -X DELETE -H "Authorization:OZONE root" -H "Date: Mon, 26 Jun 2017 04:23:30 GMT" -H "x-ozone-version: v1" -H "x-ozone-user: bilbo" http://localhost:9880/volume-to-delete - -this request deletes an empty volume */volume-to-delete*. The client receives a zero length content. - - HTTP/1.1 200 OK - x-ozone-server-name: localhost - x-ozone-request-id: 6af14c64-e3a9-40fe-9634-df60b7cbbc6a - Date: Tue, 27 Jun 2017 08:49:52 GMT - Content-Type: application/octet-stream - Content-Length: 0 - Connection: keep-alive - -### Info Volume - -This API allows user to read the info of a volume owned by themselves. Administrators can read volume info owned by any user. - -Schema: - -- `GET /{volume}?info=volume` - -Query Parameter: - -| Query Parameter | Value | Description | -|:---- |:---- |:---- -| info | "volume" | Required and enforced with this value. | - -Sample HTTP GET request: - - curl -i -H "x-ozone-user: bilbo" -H "x-ozone-version: v1" -H "Date: Mon, 26 Jun 2017 04:23:30 GMT" -H "Authorization:OZONE" "http://localhost:9880/volume-of-bilbo?info=volume" - -this request gets the info of volume */volume-of-bilbo*, the client receives a response with a JSON object of volume info. - - HTTP/1.1 200 OK - x-ozone-server-name: localhost - x-ozone-request-id: a2224806-beaf-42dd-a68e-533cd7508f74 - Date: Tue, 27 Jun 2017 07:55:35 GMT - Content-Type: application/octet-stream - Content-Length: 171 - Connection: keep-alive - - { - "owner" : { "name" : "bilbo" }, - "quota" : { "unit" : "TB", "size" : 1048576 }, - "volumeName" : "volume-of-bilbo", - "createdOn" : "Tue, 27 Jun 2017 07:42:04 GMT", - "createdBy" : "root" - } - -### List Volumes - -This API allows user to list all volumes owned by themselves. Administrators can list all volumes owned by any user. - -Schema: - -- `GET /?prefix=&max-keys=&prev-key=` - -Query Parameter: - -| Query Parameter | Value | Description | -|:---- |:---- |:---- -| prefix | string | Optional. Only volumes with this prefix are included in the result. | -| max-keys | int | Optional. Maximum number of volumes included in the result. Default is 1024 if not specified. | -| prev-key | string | Optional. Volume name from where listing should start, this key is excluded in the result. It must be a valid volume name. | -| root-scan | bool | Optional. List all volumes in the cluster if this is set to true. Default false. | - -Sample HTTP GET request: - - curl -i -H "x-ozone-user: bilbo" -H "x-ozone-version: v1" -H "Date: Mon, 26 Jun 2017 04:23:30 GMT" -H "Authorization:OZONE" "http://localhost:9880/?max-keys=100&prefix=Jan" - -this request gets all volumes owned by *bilbo* and each volume's name contains prefix *Jan*, the result at most contains *100* entries. The client receives a list of SON objects, each of them describes the info of a volume. - - HTTP/1.1 200 OK - x-ozone-server-name: localhost - x-ozone-request-id: 7fa0dce1-a8bd-4387-bc3c-1dac4b710bb1 - Date: Tue, 27 Jun 2017 08:07:04 GMT - Content-Type: application/octet-stream - Content-Length: 602 - Connection: keep-alive - - { - "volumes" : [ - { - "owner" : { "name" : "bilbo"}, - "quota" : { "unit" : "TB", "size" : 2 }, - "volumeName" : "Jan-vol1", - "createdOn" : "Tue, 27 Jun 2017 07:42:04 GMT", - "createdBy" : root - }, - ... - ] - } - -## Bucket APIs - -### Create Bucket - -This API allows an user to create a bucket in a volume. - -Schema: - -- `POST /{volume}/{bucket}` - -Additional HTTP Headers: - -| HTTP Header | Value | Description | -|:---- |:---- |:---- -| x-ozone-acl | ozone ACLs | Optional. Ozone acls. | -| x-ozone-storage-class | | Optional. Storage type for a volume. | -| x-ozone-bucket-versioning | enabled/disabled | Optional. Do enable bucket versioning or not. | - -Sample HTTP POST request: - - curl -i -X POST -H "x-ozone-user: bilbo" -H "x-ozone-version: v1" -H "Date: Mon, 26 Jun 2017 04:23:30 GMT" -H "Authorization:OZONE" http://localhost:9880/volume-of-bilbo/bucket-0 - -this request creates a bucket *bucket-0* under volume *volume-of-bilbo*. - - HTTP/1.1 201 Created - x-ozone-server-name: localhost - x-ozone-request-id: 49acfeec-4c85-470a-872b-2eaebd8d751e - Date: Tue, 27 Jun 2017 08:55:25 GMT - Content-Type: application/octet-stream - Content-Length: 0 - Connection: keep-alive - -### Update Bucket - -Updates bucket meta-data, like ACLs. - -Schema: - -- `PUT /{volume}/{bucket}` - -Additional HTTP Headers: - -| HTTP Header | Value | Description | -|:---- |:---- |:---- -| x-ozone-acl | ozone ACLs | Optional. Ozone acls. | -| x-ozone-bucket-versioning | enabled/disabled | Optional. Do enable bucket versioning or not. | - -Sample HTTP PUT request: - - curl -i -X PUT -H "x-ozone-user: bilbo" -H "x-ozone-version: v1" -H "Date: Mon, 26 Jun 2017 04:23:30 GMT" -H "Authorization:OZONE" -H "x-ozone-acl: ADD user:peregrin:rw" http://localhost:9880/volume-of-bilbo/bucket-to-update - -this request adds an ACL policy specified by HTTP header *x-ozone-acl* to bucket */volume-of-bilbo/bucket-to-update*, the ACL field *ADD user:peregrin:rw* gives add additional read/write permission to user *peregrin* to this bucket. - - HTTP/1.1 200 OK - x-ozone-server-name: localhost - x-ozone-request-id: b061a295-5faf-4b98-94b9-8b3e87c8eb5e - Date: Tue, 27 Jun 2017 09:02:37 GMT - Content-Type: application/octet-stream - Content-Length: 0 - Connection: keep-alive - -### Delete Bucket - -Deletes a bucket if it is empty. An user can only delete bucket owned by themselves, and administrators can delete buckets owned by any user, as long as it is empty. - -Schema: - -- `DELETE /{volume}/{bucket}` - -Sample HTTP DELETE request: - - curl -i -X DELETE -H "Authorization:OZONE root" -H "Date: Mon, 26 Jun 2017 04:23:30 GMT" -H "x-ozone-version: v1" -H "x-ozone-user:bilbo" "http://localhost:9880/volume-of-bilbo/bucket-0" - -this request deletes bucket */volume-of-bilbo/bucket-0*. The client receives a zero length content response. - - HTTP/1.1 200 OK - x-ozone-server-name: localhost - x-ozone-request-id: f57acd7a-2116-4c2f-aa2f-5a483db81c9c - Date: Tue, 27 Jun 2017 09:16:52 GMT - Content-Type: application/octet-stream - Content-Length: 0 - Connection: keep-alive - - -### Info Bucket - -This API returns information about a given bucket. - -Schema: - -- `GET /{volume}/{bucket}?info=bucket` - -Query Parameters: - -| Query Parameter | Value | Description | -|:---- |:---- |:---- -| info | "bucket" | Required and enforced with this value. | - -Sample HTTP GET request: - - curl -i -H "x-ozone-user: bilbo" -H "x-ozone-version: v1" -H "Date: Mon, 26 Jun 2017 04:23:30 GMT" -H "Authorization:OZONE" "http://localhost:9880/volume-of-bilbo/bucket-0?info=bucket" - -this request gets the info of bucket */volume-of-bilbo/bucket-0*. The client receives a response of JSON object contains bucket info. - - HTTP/1.1 200 OK - x-ozone-server-name: localhost - x-ozone-request-id: f125485b-8cae-4c7f-a2d6-5b1fefd6f193 - Date: Tue, 27 Jun 2017 09:08:31 GMT - Content-Type: application/json - Content-Length: 138 - Connection: keep-alive - - { - "volumeName" : "volume-of-bilbo", - "bucketName" : "bucket-0", - "createdOn" : "Tue, 27 Jun 2017 08:55:25 GMT", - "acls" : [ ], - "versioning" : "DISABLED", - "storageType" : "DISK" - } - -### List Buckets - -List buckets in a given volume. - -Schema: - -- `GET /{volume}?prefix=&max-keys=&prev-key=` - -Query Parameters: - -| Query Parameter | Value | Description | -|:---- |:---- |:---- -| prefix | string | Optional. Only buckets with this prefix are included in the result. | -| max-keys | int | Optional. Maximum number of buckets included in the result. Default is 1024 if not specified. | -| prev-key | string | Optional. Bucket name from where listing should start, this key is excluded in the result. It must be a valid bucket name. | - -Sample HTTP GET request: - - curl -i -H "x-ozone-user: bilbo" -H "x-ozone-version: v1" -H "Date: Mon, 26 Jun 2017 04:23:30 GMT" -H "Authorization:OZONE" "http://localhost:9880/volume-of-bilbo?max-keys=10" - -this request lists all the buckets under volume *volume-of-bilbo*, and the result at most contains 10 entries. The client receives response of a array of JSON objects, each of them represents for a bucket info. - - HTTP/1.1 200 OK - x-ozone-server-name: localhost - x-ozone-request-id: e048c3d5-169c-470f-9903-632d9f9e32d5 - Date: Tue, 27 Jun 2017 09:12:18 GMT - Content-Type: application/octet-stream - Content-Length: 207 - Connection: keep-alive - - { - "buckets" : [ { - "volumeName" : "volume-of-bilbo", - "bucketName" : "bucket-0", - "createdOn" : "Tue, 27 Jun 2017 08:55:25 GMT", - "acls" : [ ], - "versioning" : null, - "storageType" : "DISK", - "bytesUsed" : 0, - "keyCount" : 0 - }, - ... - ] - } - -## Key APIs - -### Put Key - -This API allows user to create or overwrite keys inside of a bucket. - -Schema: - -- `PUT /{volume}/{bucket}/{key}` - -Additional HTTP headers: - -| HTTP Header | Value | Description | -|:---- |:---- |:---- -| Content-MD5 | MD5 digest | Standard HTTP header, file hash. | - -Sample PUT HTTP request: - - curl -X PUT -T /path/to/localfile -H "Authorization:OZONE" -H "Date: Mon, 26 Jun 2017 04:23:30 GMT" -H "x-ozone-version: v1" -H "x-ozone-user:bilbo" "http://localhost:9880/volume-of-bilbo/bucket-0/file-0" - -this request uploads a local file */path/to/localfile* specified by option *-T* to ozone as user *bilbo*, mapped to ozone key */volume-of-bilbo/bucket-0/file-0*. The client receives a zero length content response. - -### Get Key - -This API allows user to get or download a key from an ozone bucket. - -Schema: - -- `GET /{volume}/{bucket}/{key}` - -Sample HTTP GET request: - - curl -i -H "x-ozone-user: bilbo" -H "x-ozone-version: v1" -H "Date: Mon, 26 Jun 2017 04:23:30 GMT" -H "Authorization:OZONE" "http://localhost:9880/volume-of-bilbo/bucket-0/file-0" - -this request reads the content of key */volume-of-bilbo/bucket-0/file-0*. If the content of the file is plain text, it can be directly dumped onto stdout. - - HTTP/1.1 200 OK - Content-Type: application/octet-stream - x-ozone-server-name: localhost - x-ozone-request-id: 1bcd7de7-d8e3-46bb-afee-bdc933d383b8 - Date: Tue, 27 Jun 2017 09:35:29 GMT - Content-Length: 6 - Connection: keep-alive - - Hello Ozone! - -if the file is not plain text, specify *-O* option in curl command and the file *file-0* will be downloaded into current working directory, file name will be same as the key. A sample request like following: - - curl -O -i -H "x-ozone-user: bilbo" -H "x-ozone-version: v1" -H "Date: Mon, 26 Jun 2017 04:23:30 GMT" -H "Authorization:OZONE" "http://localhost:9880/volume-of-bilbo/bucket-0/file-1" - -response looks like following: - - % Total % Received % Xferd Average Speed Time Time Time Current - Dload Upload Total Spent Left Speed - 100 6148k 100 6148k 0 0 24.0M 0 --:--:-- --:--:-- --:--:-- 24.1M - -### Delete Key - -This API allows user to delete a key from a bucket. - -Schema: - -- `DELETE /{volume}/{bucket}/{key}` - -Sample HTTP DELETE request: - - curl -i -X DELETE -H "Authorization:OZONE root" -H "Date: Mon, 26 Jun 2017 04:23:30 GMT" -H "x-ozone-version: v1" -H "x-ozone-user:bilbo" "http://localhost:9880/volume-of-bilbo/bucket-0/file-0" - -this request deletes key */volume-of-bilbo/bucket-0/file-0*. The client receives a zero length content result: - - HTTP/1.1 200 OK - x-ozone-server-name: localhost - x-ozone-request-id: f8c4a373-dd5f-4e3a-b6c4-ddf7e191fe91 - Date: Tue, 27 Jun 2017 14:19:48 GMT - Content-Type: application/octet-stream - Content-Length: 0 - Connection: keep-alive - -### Info Key - -This API returns information about a given key. - -Schema: - -- `GET /{volume}/{bucket}/{key}?info=key` - -Query Parameter: - -| Query Parameter | Value | Description | -|:---- |:---- |:---- -| info | String, "key" | Required and enforced with this value. | - -Sample HTTP DELETE request: - - curl -i -H "x-ozone-user: bilbo" -H "x-ozone-version: v1" -H "Date: Mon, 26 Jun 2017 04:23:30 GMT" -H "Authorization:OZONE" "http://localhost:9880/volume-of-bilbo/buket-0/file-0?info=key" - -this request returns information of the key */volume-of-bilbo/bucket-0/file-0*. The client receives a JSON object listed attributes of the key. - - HTTP/1.1 200 OK - x-ozone-server-name: localhost - x-ozone-request-id: c674343c-a0f2-49e4-bbd6-daa73e7dc131 - Date: Mon, 03 Jul 2017 14:28:45 GMT - Content-Type: application/octet-stream - Content-Length: 73 - Connection: keep-alive - - { - "version" : 0, - "md5hash" : null, - "createdOn" : "Mon, 26 Jun 2017 04:23:30 GMT", - "modifiedOn" : "Mon, 26 Jun 2017 04:23:30 GMT", - "size" : 0, - "keyName" : "file-0" - } - -### List Keys - -This API allows user to list keys in a bucket. - -Schema: - -- `GET /{volume}/{bucket}?prefix=&max-keys=&prev-key=` - -Query Parameters: - -| Query Parameter | Value | Description | -|:---- |:---- |:---- -| prefix | string | Optional. Only keys with this prefix are included in the result. | -| max-keys | int | Optional. Maximum number of keys included in the result. Default is 1024 if not specified. | -| prev-key | string | Optional. Key name from where listing should start, this key is excluded in the result. It must be a valid key name. | - -Sample HTTP GET request: - - curl -i -H "x-ozone-user: bilbo" -H "x-ozone-version: v1" -H "Date: Mon, 26 Jun 2017 04:23:30 GMT" -H "Authorization:OZONE" "http:/localhost:9880/volume-of-bilbo/bucket-0/?max-keys=100&prefix=file" - -this request list keys under bucket */volume-of-bilbo/bucket-0*, the listing result is filtered by prefix *file*. The client receives an array of JSON objects, each of them represents the info of a matched key. - - HTTP/1.1 200 OK - x-ozone-server-name: localhost - x-ozone-request-id: 7f9fc970-9904-4c56-b671-83a086c6f555 - Date: Tue, 27 Jun 2017 09:48:59 GMT - Content-Type: application/json - Content-Length: 209 - Connection: keep-alive - - { - "name" : null, - "prefix" : file, - "maxKeys" : 0, - "truncated" : false, - "keyList" : [ { - "version" : 0, - "md5hash" : null, - "createdOn" : "Mon, 26 Jun 2017 04:23:30 GMT", - "modifiedOn" : "Mon, 26 Jun 2017 04:23:30 GMT", - "size" : 0, - "keyName" : "file-0" - }, - ... - ] - } diff --git a/hadoop-ozone/docs/content/RunningViaDocker.md b/hadoop-ozone/docs/content/RunningViaDocker.md deleted file mode 100644 index 0b8fece5fb1..00000000000 --- a/hadoop-ozone/docs/content/RunningViaDocker.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -title: Alpha Cluster -weight: 1 -menu: - main: - parent: Starting - weight: 1 ---- - - - -***This is an alpha release of Ozone. Please don't use this release in -production.*** Please check the road map page for features under -development. - -The easiest way to run ozone is to download the release tarball and launch -ozone via Docker. Docker will create a small ozone cluster on your machine, -including the data nodes and ozone services. - -## Running Ozone via Docker - - -**This assumes that you have Docker installed on the machine.** - -* Download the Ozone tarball and untar it. - -* Go to the directory where the docker compose files exist and tell -`docker-compose` to start Ozone in the background. This will start a small -ozone instance on your machine. - -{{< highlight bash >}} -cd ozone-0.2.1-SNAPSHOT/compose/ozone/ - -docker-compose up -d -{{< /highlight >}} - - -To verify that ozone is working as expected, let us log into a data node and -run _freon_, the load generator for Ozone. The ```exec datanode bash``` command -will open a bash shell on the datanode. The ozone freon command is executed -within the datanode container. You can quit freon via CTRL-C any time. The -```rk``` profile instructs freon to generate random keys. - -{{< highlight bash >}} -docker-compose exec datanode bash -ozone freon rk -{{< /highlight >}} - -You can check out the **OzoneManager UI** at http://localhost:9874/ to see the -activity generated by freon. -While you are there, please don't forget to check out the ozone configuration explorer. - -***Congratulations, You have just run your first ozone cluster.*** - -To shutdown the cluster, please run -{{< highlight bash >}} -docker-compose down -{{< /highlight >}} \ No newline at end of file diff --git a/hadoop-ozone/docs/content/RunningWithHDFS.md b/hadoop-ozone/docs/content/RunningWithHDFS.md deleted file mode 100644 index 2fd2bd6ace2..00000000000 --- a/hadoop-ozone/docs/content/RunningWithHDFS.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: Running concurrently with HDFS -weight: 1 -menu: - main: - parent: Starting - weight: 4 ---- - - -Ozone is designed to work with HDFS. So it is easy to deploy ozone in an -existing HDFS cluster. - -Ozone does *not* support security today. It is a work in progress and tracked - in -[HDDS-4](https://issues.apache.org/jira/browse/HDDS-4). If you enable ozone -in a secure HDFS cluster, for your own protection Ozone will refuse to work. - -In other words, till Ozone security work is done, Ozone will not work in any -secure clusters. - -The container manager part of Ozone runs inside DataNodes as a pluggable module. -To activate ozone you should define the service plugin implementation class. - -

- -{{< highlight xml >}} - - dfs.datanode.plugins - org.apache.hadoop.ozone.HddsDatanodeService - -{{< /highlight >}} - -You also need to add the ozone-datanode-plugin jar file to the classpath: - -{{< highlight bash >}} -export HADOOP_CLASSPATH=/opt/ozone/share/hadoop/ozoneplugin/hadoop-ozone-datanode-plugin.jar -{{< /highlight >}} - - - -To start ozone with HDFS you should start the the following components: - - 1. HDFS Namenode (from Hadoop distribution) - 2. HDFS Datanode (from the Hadoop distribution with the plugin on the - classpath from the Ozone distribution) - 3. Ozone Manager (from the Ozone distribution) - 4. Storage Container manager (from the Ozone distribution) - -Please check the log of the datanode whether the HDDS/Ozone plugin is started or -not. Log of datanode should contain something like this: - -``` -2018-09-17 16:19:24 INFO HddsDatanodeService:158 - Started plug-in org.apache.hadoop.ozone.web.OzoneHddsDatanodeService@6f94fb9d -``` - - \ No newline at end of file diff --git a/hadoop-ozone/docs/content/SCMCLI.md b/hadoop-ozone/docs/content/SCMCLI.md deleted file mode 100644 index bd6086c796e..00000000000 --- a/hadoop-ozone/docs/content/SCMCLI.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: "SCMCLI" -date: 2017-08-10 -menu: - main: - parent: Tools ---- - - -SCM is the block service for Ozone. It is also the workhorse for ozone. But user process never talks to SCM. However, being able to read the state of SCM is useful. - -SCMCLI allows the developer to access SCM directly. Please note: Improper usage of this tool can destroy your cluster. Unless you know exactly what you are doing, Please do *not* use this tool. In other words, this is a developer only tool. We might even remove this command in future to prevent improper use. - -[^1]: This assumes that you have a working docker installation on the development machine. diff --git a/hadoop-ozone/docs/content/Settings.md b/hadoop-ozone/docs/content/Settings.md deleted file mode 100644 index 41ab04a8878..00000000000 --- a/hadoop-ozone/docs/content/Settings.md +++ /dev/null @@ -1,142 +0,0 @@ ---- -title: Configuration -weight: 1 -menu: - main: - parent: Starting - weight: 2 ---- - - - - - -If you are feeling adventurous, you can setup ozone in a real cluster. -Setting up a real cluster requires us to understand the components of Ozone. -Ozone is designed to work concurrently with HDFS. However, Ozone is also -capable of running independently. The components of ozone are the same in both approaches. - -## Ozone Components - -1. Ozone Manager - Is the server that is in charge of the namespace of Ozone. Ozone Manager is responsible for all volume, bucket and key operations. -2. Storage Container Manager - Acts as the block manager. Ozone Manager -requests blocks from SCM, to which clients can write data. -3. Datanodes - Ozone data node code runs inside the HDFS datanode or in the independent deployment case runs an ozone datanode daemon. - - - - -## Setting up an Ozone only cluster - -* Please untar the ozone-0.2.1-SNAPSHOT to the directory where you are going -to run Ozone from. We need Ozone jars on all machines in the cluster. So you -need to do this on all machines in the cluster. - -* Ozone relies on a configuration file called ```ozone-site.xml```. To -generate a template that you can replace with proper values, please run the -following command. This will generate a template called ```ozone-site.xml``` at -the specified path (directory). - -{{< highlight bash >}} -ozone genconf -{{< /highlight >}} - -Let us look at the settings inside the generated file (ozone-site.xml) and -how they control ozone. Once the right values are defined, this file -needs to be copied to ```ozone directory/etc/Hadoop```. - - -* **ozone.enabled** This is the most critical setting for ozone. -Ozone is a work in progress and users have to enable this service explicitly. -By default, Ozone is disabled. Setting this flag to `true` enables ozone in the -HDFS or Ozone cluster. - -Here is an example, - -{{< highlight xml >}} - - ozone.enabled - True - -{{< /highlight >}} - -* **ozone.metadata.dirs** Allows Administrators to specify where the - metadata must reside. Usually you pick your fastest disk (SSD if - you have them on your nodes). OzoneManager, SCM and datanode will write the - metadata to this path. This is a required setting, if this is missing Ozone - will fail to come up. - - Here is an example, - -{{< highlight xml >}} - - ozone.metadata.dirs - /data/disk1/meta - -{{< /highlight >}} - -* **ozone.scm.names** Storage container manager(SCM) is a distributed block - service which is used by ozone. This property allows data nodes to discover - SCM's address. Data nodes send heartbeat to SCM. - Until HA feature is complete, we configure ozone.scm.names to be a - single machine. - - Here is an example, - - {{< highlight xml >}} - - ozone.scm.names - scm.hadoop.apache.org - - {{< /highlight >}} - - * **ozone.scm.datanode.id** Data nodes generate a Unique ID called Datanode - ID. This identity is written to the file specified by this path. *Data nodes - will create this path if it doesn't exist already.* - -Here is an example, -{{< highlight xml >}} - - ozone.scm.datanode.id - /data/disk1/meta/node/datanode.id - -{{< /highlight >}} - -* **ozone.om.address** OM server address. This is used by OzoneClient and -Ozone File System. - -Here is an example, -{{< highlight xml >}} - - ozone.om.address - ozonemanager.hadoop.apache.org - -{{< /highlight >}} - - -### Ozone Settings Summary - -| Setting | Value | Comment | -|--------------------------------|------------------------------|------------------------------------------------------------------| -| ozone.enabled | true | This enables SCM and containers in HDFS cluster. | -| ozone.metadata.dirs | file path | The metadata will be stored here. | -| ozone.scm.names | SCM server name | Hostname:port or IP:port address of SCM. | -| ozone.scm.block.client.address | SCM server name and port | Used by services like OM | -| ozone.scm.client.address | SCM server name and port | Used by client-side | -| ozone.scm.datanode.address | SCM server name and port | Used by datanode to talk to SCM | -| ozone.om.address | OM server name | Used by Ozone handler and Ozone file system. | diff --git a/hadoop-ozone/docs/content/VolumeCommands.md b/hadoop-ozone/docs/content/VolumeCommands.md deleted file mode 100644 index 6f024ef87f4..00000000000 --- a/hadoop-ozone/docs/content/VolumeCommands.md +++ /dev/null @@ -1,116 +0,0 @@ ---- -title: Volume Commands -menu: - main: - parent: Client - weight: 2 ---- - - -Volume commands generally need administrator privileges. The ozone shell supports the following volume commands. - - * [create](#create) - * [delete](#delete) - * [info](#info) - * [list](#list) - * [update](#update) - -### Create - -The volume create command allows an administrator to create a volume and -assign it to a user. - -***Params:*** - -| Arguments | Comment | -|--------------------------------|-----------------------------------------| -| -q, --quota | Optional, This argument that specifies the maximum size this volume can use in the Ozone cluster. | -| -u, --user | Required, The name of the user who owns this volume. This user can create, buckets and keys on this volume. | -| Uri | The name of the volume. | - -{{< highlight bash >}} -ozone sh volume create --quota=1TB --user=bilbo /hive -{{< /highlight >}} - -The above command will create a volume called _hive_ on the ozone cluster. This -volume has a quota of 1TB, and the owner is _bilbo_. - -### Delete - -The volume delete commands allows an administrator to delete a volume. If the -volume is not empty then this command will fail. - -***Params:*** - -| Arguments | Comment | -|--------------------------------|-----------------------------------------| -| Uri | The name of the volume. - -{{< highlight bash >}} -ozone sh volume delete /hive -{{< /highlight >}} - -The above command will delete the volume hive, if the volume has no buckets -inside it. - -### Info - -The volume info commands returns the information about the volume including -quota and owner information. -***Params:*** - -| Arguments | Comment | -|--------------------------------|-----------------------------------------| -| Uri | The name of the volume. - -{{< highlight bash >}} -ozone sh volume info /hive -{{< /highlight >}} - -The above command will print out the information about hive volume. - -### List - -The volume list command will list the volumes owned by a user. - -{{< highlight bash >}} -ozone sh volume list --user hadoop -{{< /highlight >}} - -The above command will print out all the volumes owned by the user hadoop. - -### Update - -The volume update command allows changing of owner and quota on a given volume. - -***Params:*** - -| Arguments | Comment | -|--------------------------------|-----------------------------------------| -| -q, --quota | Optional, This argument that specifies the maximum size this volume can use in the Ozone cluster. | -| -u, --user | Optional, The name of the user who owns this volume. This user can create, buckets and keys on this volume. | -| Uri | The name of the volume. | - -{{< highlight bash >}} -ozone sh volume update --quota=10TB /hive -{{< /highlight >}} - -The above command updates the volume quota to 10TB. - -You can try out these commands from the docker instance of the [Alpha -Cluster](runningviadocker.html). diff --git a/hadoop-ozone/docs/content/_index.md b/hadoop-ozone/docs/content/_index.md deleted file mode 100644 index e297b182fd4..00000000000 --- a/hadoop-ozone/docs/content/_index.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: Ozone Overview -menu: main -weight: -10 ---- - - -# Apache Hadoop Ozone - -Ozone is a scalable, distributed object store for Hadoop. Applications like -Apache Spark, Hive and YARN, can run against Ozone without any -modifications. Ozone comes with a [Java client library]({{< ref "JavaApi.md" ->}}) and a [command line interface] ({{< ref "CommandShell.md#shell" >}}) which makes it easy to use Ozone. This client library supports both RPC and REST protocols. - -Ozone consists of volumes, buckets, and Keys. - -* Volumes are similar to user accounts. Only administrators can create or delete volumes. -* Buckets are similar to directories. A bucket can contain any number of keys, but buckets cannot contain other buckets. -* Keys are similar to files. A bucket can contain any number of keys. - - - -}}"> - diff --git a/hadoop-ozone/docs/dev-support/bin/generate-site.sh b/hadoop-ozone/docs/dev-support/bin/generate-site.sh deleted file mode 100755 index 374e74b8904..00000000000 --- a/hadoop-ozone/docs/dev-support/bin/generate-site.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env bash -# 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. - -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -DOCDIR="$DIR/../.." - -if [ ! "$(which hugo)" ]; then - echo "Hugo is not yet installed. Doc generation is skipped." - exit 0 -fi - -DESTDIR="$DOCDIR/target/classes/webapps/docs" -mkdir -p "$DESTDIR" -cd "$DOCDIR" -hugo -d "$DESTDIR" "$@" -cd - diff --git a/hadoop-ozone/docs/pom.xml b/hadoop-ozone/docs/pom.xml deleted file mode 100644 index d8edd15e992..00000000000 --- a/hadoop-ozone/docs/pom.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - 4.0.0 - - org.apache.hadoop - hadoop-ozone - 0.3.0-SNAPSHOT - - hadoop-ozone-docs - 0.3.0-SNAPSHOT - Apache Hadoop Ozone Documentation - Apache Hadoop Ozone Documentation - jar - - - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - exec - - compile - - - - dev-support/bin/generate-site.sh - - - - org.apache.rat - apache-rat-plugin - - - themes/ozonedoc/static/js/bootstrap.min.js - themes/ozonedoc/static/js/jquery.min.js - themes/ozonedoc/static/css/bootstrap-theme.min.css - themes/ozonedoc/static/css/bootstrap.min.css.map - themes/ozonedoc/static/css/bootstrap.min.css - themes/ozonedoc/static/css/bootstrap-theme.min.css.map - themes/ozonedoc/static/fonts/glyphicons-halflings-regular.svg - themes/ozonedoc/layouts/index.html - themes/ozonedoc/theme.toml - - - - - - diff --git a/hadoop-ozone/docs/static/NOTES.md b/hadoop-ozone/docs/static/NOTES.md deleted file mode 100644 index 7b7ca1290b3..00000000000 --- a/hadoop-ozone/docs/static/NOTES.md +++ /dev/null @@ -1,20 +0,0 @@ - - -The source of Ozone logo is available here: - -https://git-wip-us.apache.org/repos/asf?p=hadoop-ozonesite.git;a=tree;f=static;h=9830788c1fa36c933272cdf87342bb71974c8567;hb=refs/heads/asf-site diff --git a/hadoop-ozone/docs/static/OzoneOverview.png b/hadoop-ozone/docs/static/OzoneOverview.png deleted file mode 100644 index 7e011d5bbde9dc06d72103e4a389d848e5eac406..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41729 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 V(nkj|2?%)IQoMb$ME-u@e*i&BNTmP( diff --git a/hadoop-ozone/docs/static/OzoneOverview.svg b/hadoop-ozone/docs/static/OzoneOverview.svg deleted file mode 100644 index 9d4660db1c8..00000000000 --- a/hadoop-ozone/docs/static/OzoneOverview.svg +++ /dev/null @@ -1,238 +0,0 @@ - - - - - Desktop HD - Created with Sketch. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Ozone Client - - - - - - - - - Rest Handler - - - - - - - - - - - - - - - - - - Ratis - - - - - - - - - - - - - - - - - Ratis - - - - - - - - - - - - - - - - - Ratis - - - - - - - - - - - - - - - Container - - - - - - - - - - - Container - - - - - - - - - Ozone File System - - - - - - - - - Ozone CLI - - - - - - - - - - - Freon - - - - - - - - - - - - - - - - - - - - Ozone Manager - - - - - - - - - - - - - - - - - Storage Container Manager - - - - - - Datanodes - - - - - - - - - - Container - - - - - Hadoop Distributed Data Store - - - - \ No newline at end of file diff --git a/hadoop-ozone/docs/static/SCMBlockDiagram.png b/hadoop-ozone/docs/static/SCMBlockDiagram.png deleted file mode 100644 index 04d27adede700b387fffbfdeadef063a2586cf9b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14714 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%0D;zThR>h!|tQ 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 NObpEpp6EG;{SS&-9>)Lx diff --git a/hadoop-ozone/docs/themes/ozonedoc/layouts/_default/single.html b/hadoop-ozone/docs/themes/ozonedoc/layouts/_default/single.html deleted file mode 100644 index ca2e1c4a65e..00000000000 --- a/hadoop-ozone/docs/themes/ozonedoc/layouts/_default/single.html +++ /dev/null @@ -1,38 +0,0 @@ - -{{ partial "header.html" . }} - - - -{{ partial "navbar.html" . }} - -

- -{{ partial "footer.html" . }} - - - diff --git a/hadoop-ozone/docs/themes/ozonedoc/layouts/index.html b/hadoop-ozone/docs/themes/ozonedoc/layouts/index.html deleted file mode 100644 index 17f0246abf4..00000000000 --- a/hadoop-ozone/docs/themes/ozonedoc/layouts/index.html +++ /dev/null @@ -1,37 +0,0 @@ - -{{ partial "header.html" . }} - - - -{{ partial "navbar.html" . }} - -
-
- {{ partial "sidebar.html" . }} -
- {{ .Content }} - - -
-
-
- -{{ partial "footer.html" . }} - - - diff --git a/hadoop-ozone/docs/themes/ozonedoc/layouts/partials/footer.html b/hadoop-ozone/docs/themes/ozonedoc/layouts/partials/footer.html deleted file mode 100644 index 5aaeed9e1ed..00000000000 --- a/hadoop-ozone/docs/themes/ozonedoc/layouts/partials/footer.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - diff --git a/hadoop-ozone/docs/themes/ozonedoc/layouts/partials/header.html b/hadoop-ozone/docs/themes/ozonedoc/layouts/partials/header.html deleted file mode 100644 index 35ba4c8042f..00000000000 --- a/hadoop-ozone/docs/themes/ozonedoc/layouts/partials/header.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - Documentation for Apache Hadoop Ozone - - - - - - - - diff --git a/hadoop-ozone/docs/themes/ozonedoc/layouts/partials/navbar.html b/hadoop-ozone/docs/themes/ozonedoc/layouts/partials/navbar.html deleted file mode 100644 index 3cd86096578..00000000000 --- a/hadoop-ozone/docs/themes/ozonedoc/layouts/partials/navbar.html +++ /dev/null @@ -1,36 +0,0 @@ - -
diff --git a/hadoop-ozone/docs/themes/ozonedoc/layouts/partials/sidebar.html b/hadoop-ozone/docs/themes/ozonedoc/layouts/partials/sidebar.html deleted file mode 100644 index 7fae50d316a..00000000000 --- a/hadoop-ozone/docs/themes/ozonedoc/layouts/partials/sidebar.html +++ /dev/null @@ -1,52 +0,0 @@ - - diff --git a/hadoop-ozone/docs/themes/ozonedoc/static/css/bootstrap-theme.min.css b/hadoop-ozone/docs/themes/ozonedoc/static/css/bootstrap-theme.min.css deleted file mode 100644 index 5e39401957d..00000000000 --- a/hadoop-ozone/docs/themes/ozonedoc/static/css/bootstrap-theme.min.css +++ /dev/null @@ -1,6 +0,0 @@ -/*! - * Bootstrap v3.3.7 (http://getbootstrap.com) - * Copyright 2011-2016 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning:active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-danger.disabled,.btn-danger[disabled],.btn-default.disabled,.btn-default[disabled],.btn-info.disabled,.btn-info[disabled],.btn-primary.disabled,.btn-primary[disabled],.btn-success.disabled,.btn-success[disabled],.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-danger,fieldset[disabled] .btn-default,fieldset[disabled] .btn-info,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-success,fieldset[disabled] .btn-warning{-webkit-box-shadow:none;box-shadow:none}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-o-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#265a88));background-image:linear-gradient(to bottom,#337ab7 0,#265a88 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#245580}.btn-primary:focus,.btn-primary:hover{background-color:#265a88;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#265a88;border-color:#245580}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#265a88;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:focus,.btn-success:hover{background-color:#419641;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#419641;border-color:#3e8f3e}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:focus,.btn-danger:hover{background-color:#c12e2a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#c12e2a;border-color:#b92c28}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#c12e2a;background-image:none}.img-thumbnail,.thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-color:#2e6da4;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-o-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#286090));background-image:linear-gradient(to bottom,#337ab7 0,#286090 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #286090;background-image:-webkit-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2b669a));background-image:linear-gradient(to bottom,#337ab7 0,#2b669a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);background-repeat:repeat-x;border-color:#2b669a}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} -/*# sourceMappingURL=bootstrap-theme.min.css.map */ \ No newline at end of file diff --git a/hadoop-ozone/docs/themes/ozonedoc/static/css/bootstrap-theme.min.css.map b/hadoop-ozone/docs/themes/ozonedoc/static/css/bootstrap-theme.min.css.map deleted file mode 100644 index 94813e90060..00000000000 --- a/hadoop-ozone/docs/themes/ozonedoc/static/css/bootstrap-theme.min.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["less/theme.less","less/mixins/vendor-prefixes.less","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Bootstrap v3.3.7 (http://getbootstrap.com)\n * Copyright 2011-2016 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\n//\n// Load core variables and mixins\n// --------------------------------------------------\n\n@import \"variables.less\";\n@import \"mixins.less\";\n\n\n//\n// Buttons\n// --------------------------------------------------\n\n// Common styles\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0,0,0,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n // Reset the shadow\n &:active,\n &.active {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n .box-shadow(none);\n }\n\n .badge {\n text-shadow: none;\n }\n}\n\n// Mixin for generating new styles\n.btn-styles(@btn-color: #555) {\n #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));\n .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners; see https://github.com/twbs/bootstrap/issues/10620\n background-repeat: repeat-x;\n border-color: darken(@btn-color, 14%);\n\n &:hover,\n &:focus {\n background-color: darken(@btn-color, 12%);\n background-position: 0 -15px;\n }\n\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n border-color: darken(@btn-color, 14%);\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &,\n &:hover,\n &:focus,\n &.focus,\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n background-image: none;\n }\n }\n}\n\n// Common styles\n.btn {\n // Remove the gradient for the pressed/active state\n &:active,\n &.active {\n background-image: none;\n }\n}\n\n// Apply the mixin to the buttons\n.btn-default { .btn-styles(@btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; }\n.btn-primary { .btn-styles(@btn-primary-bg); }\n.btn-success { .btn-styles(@btn-success-bg); }\n.btn-info { .btn-styles(@btn-info-bg); }\n.btn-warning { .btn-styles(@btn-warning-bg); }\n.btn-danger { .btn-styles(@btn-danger-bg); }\n\n\n//\n// Images\n// --------------------------------------------------\n\n.thumbnail,\n.img-thumbnail {\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n\n\n//\n// Dropdowns\n// --------------------------------------------------\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));\n background-color: darken(@dropdown-link-hover-bg, 5%);\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n background-color: darken(@dropdown-link-active-bg, 5%);\n}\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n border-radius: @navbar-border-radius;\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: darken(@navbar-default-link-active-bg, 5%); @end-color: darken(@navbar-default-link-active-bg, 2%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.075));\n }\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255,255,255,.25);\n}\n\n// Inverted navbar\n.navbar-inverse {\n #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered; see https://github.com/twbs/bootstrap/issues/10257\n border-radius: @navbar-border-radius;\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: @navbar-inverse-link-active-bg; @end-color: lighten(@navbar-inverse-link-active-bg, 2.5%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.25));\n }\n\n .navbar-brand,\n .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0,0,0,.25);\n }\n}\n\n// Undo rounded corners in static and fixed navbars\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n\n// Fix active state of dropdown items in collapsed mode\n@media (max-width: @grid-float-breakpoint-max) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: #fff;\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n }\n }\n}\n\n\n//\n// Alerts\n// --------------------------------------------------\n\n// Common styles\n.alert {\n text-shadow: 0 1px 0 rgba(255,255,255,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05);\n .box-shadow(@shadow);\n}\n\n// Mixin for generating new styles\n.alert-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));\n border-color: darken(@color, 15%);\n}\n\n// Apply the mixin to the alerts\n.alert-success { .alert-styles(@alert-success-bg); }\n.alert-info { .alert-styles(@alert-info-bg); }\n.alert-warning { .alert-styles(@alert-warning-bg); }\n.alert-danger { .alert-styles(@alert-danger-bg); }\n\n\n//\n// Progress bars\n// --------------------------------------------------\n\n// Give the progress background some depth\n.progress {\n #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg)\n}\n\n// Mixin for generating new styles\n.progress-bar-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));\n}\n\n// Apply the mixin to the progress bars\n.progress-bar { .progress-bar-styles(@progress-bar-bg); }\n.progress-bar-success { .progress-bar-styles(@progress-bar-success-bg); }\n.progress-bar-info { .progress-bar-styles(@progress-bar-info-bg); }\n.progress-bar-warning { .progress-bar-styles(@progress-bar-warning-bg); }\n.progress-bar-danger { .progress-bar-styles(@progress-bar-danger-bg); }\n\n// Reset the striped class because our mixins don't do multiple gradients and\n// the above custom styles override the new `.progress-bar-striped` in v3.2.0.\n.progress-bar-striped {\n #gradient > .striped();\n}\n\n\n//\n// List groups\n// --------------------------------------------------\n\n.list-group {\n border-radius: @border-radius-base;\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%);\n #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));\n border-color: darken(@list-group-active-border, 7.5%);\n\n .badge {\n text-shadow: none;\n }\n}\n\n\n//\n// Panels\n// --------------------------------------------------\n\n// Common styles\n.panel {\n .box-shadow(0 1px 2px rgba(0,0,0,.05));\n}\n\n// Mixin for generating new styles\n.panel-heading-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));\n}\n\n// Apply the mixin to the panel headings only\n.panel-default > .panel-heading { .panel-heading-styles(@panel-default-heading-bg); }\n.panel-primary > .panel-heading { .panel-heading-styles(@panel-primary-heading-bg); }\n.panel-success > .panel-heading { .panel-heading-styles(@panel-success-heading-bg); }\n.panel-info > .panel-heading { .panel-heading-styles(@panel-info-heading-bg); }\n.panel-warning > .panel-heading { .panel-heading-styles(@panel-warning-heading-bg); }\n.panel-danger > .panel-heading { .panel-heading-styles(@panel-danger-heading-bg); }\n\n\n//\n// Wells\n// --------------------------------------------------\n\n.well {\n #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg);\n border-color: darken(@well-bg, 10%);\n @shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They have been removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility) {\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n"]} \ No newline at end of file diff --git a/hadoop-ozone/docs/themes/ozonedoc/static/css/bootstrap.min.css b/hadoop-ozone/docs/themes/ozonedoc/static/css/bootstrap.min.css deleted file mode 100644 index ed3905e0e0c..00000000000 --- a/hadoop-ozone/docs/themes/ozonedoc/static/css/bootstrap.min.css +++ /dev/null @@ -1,6 +0,0 @@ -/*! - * Bootstrap v3.3.7 (http://getbootstrap.com) - * Copyright 2011-2016 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled.focus,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled].focus,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled.focus,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled].focus,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled.focus,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled].focus,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled.focus,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled].focus,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled.focus,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled].focus,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled.focus,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled].focus,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:rgba(0,0,0,0);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.modal-header:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} -/*# sourceMappingURL=bootstrap.min.css.map */ \ No newline at end of file diff --git a/hadoop-ozone/docs/themes/ozonedoc/static/css/bootstrap.min.css.map b/hadoop-ozone/docs/themes/ozonedoc/static/css/bootstrap.min.css.map deleted file mode 100644 index 6c7fa40b98d..00000000000 --- a/hadoop-ozone/docs/themes/ozonedoc/static/css/bootstrap.min.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["less/normalize.less","less/print.less","bootstrap.css","dist/css/bootstrap.css","less/glyphicons.less","less/scaffolding.less","less/mixins/vendor-prefixes.less","less/mixins/tab-focus.less","less/mixins/image.less","less/type.less","less/mixins/text-emphasis.less","less/mixins/background-variant.less","less/mixins/text-overflow.less","less/code.less","less/grid.less","less/mixins/grid.less","less/mixins/grid-framework.less","less/tables.less","less/mixins/table-row.less","less/forms.less","less/mixins/forms.less","less/buttons.less","less/mixins/buttons.less","less/mixins/opacity.less","less/component-animations.less","less/dropdowns.less","less/mixins/nav-divider.less","less/mixins/reset-filter.less","less/button-groups.less","less/mixins/border-radius.less","less/input-groups.less","less/navs.less","less/navbar.less","less/mixins/nav-vertical-align.less","less/utilities.less","less/breadcrumbs.less","less/pagination.less","less/mixins/pagination.less","less/pager.less","less/labels.less","less/mixins/labels.less","less/badges.less","less/jumbotron.less","less/thumbnails.less","less/alerts.less","less/mixins/alerts.less","less/progress-bars.less","less/mixins/gradients.less","less/mixins/progress-bar.less","less/media.less","less/list-group.less","less/mixins/list-group.less","less/panels.less","less/mixins/panels.less","less/responsive-embed.less","less/wells.less","less/close.less","less/modals.less","less/tooltip.less","less/mixins/reset-text.less","less/popovers.less","less/carousel.less","less/mixins/clearfix.less","less/mixins/center-block.less","less/mixins/hide-text.less","less/responsive-utilities.less","less/mixins/responsive-visibility.less"],"names":[],"mappings":"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kDG,edokDH,MAAA,acpkDG,edukDH,MAAA,IcvkDG,ed0kDH,MAAA,ac1kDG,ed6kDH,MAAA,ac7kDG,edglDH,MAAA,IchlDG,edmlDH,MAAA,ac9kDG,edilDH,MAAA,YchmDG,edmmDH,MAAA,KcnmDG,gBdsmDH,KAAA,KctmDG,gBdymDH,KAAA,aczmDG,gBd4mDH,KAAA,ac5mDG,ed+mDH,KAAA,Ic/mDG,edknDH,KAAA,aclnDG,edqnDH,KAAA,acrnDG,edwnDH,KAAA,IcxnDG,ed2nDH,KAAA,ac3nDG,ed8nDH,KAAA,ac9nDG,edioDH,KAAA,IcjoDG,edooDH,KAAA,ac/nDG,edkoDH,KAAA,YcnnDG,edsnDH,KAAA,KctnDG,kBdynDH,YAAA,KcznDG,kBd4nDH,YAAA,ac5nDG,kBd+nDH,YAAA,ac/nDG,iBdkoDH,YAAA,IcloDG,iBdqoDH,YAAA,acroDG,iBdwoDH,YAAA,acxoDG,iBd2oDH,YAAA,Ic3oDG,iBd8oDH,YAAA,ac9oDG,iBdipDH,YAAA,acjpDG,iBdopDH,YAAA,IcppDG,iBdupDH,YAAA,acvpDG,iBd0pDH,YAAA,Yc5rDG,iBACE,YAAA,EAOJ,yBACE,UAAA,WAAA,WAAA,WAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,Ud0rDD,MAAA,Kc1rDC,Wd6rDD,MAAA,Kc7rDC,WdgsDD,MAAA,achsDC,WdmsDD,MAAA,acnsDC,UdssDD,MAAA,IctsDC,UdysDD,MAAA,aczsDC,Ud4sDD,MAAA,ac5sDC,Ud+sDD,MAAA,Ic/sDC,UdktDD,MAAA,acltDC,UdqtDD,MAAA,acrtDC,UdwtDD,MAAA,IcxtDC,Ud2tDD,MAAA,ac5sDC,Ud+sDD,MAAA,Yc/sDC,gBdktDD,MAAA,KcltDC,gBdqtDD,MAAA,acrtDC,gBdwtDD,MAAA,acxtDC,ed2tDD,MAAA,Ic3tDC,ed8tDD,MAAA,ac9tDC,ediuDD,MAAA,acjuDC,edouDD,MAAA,IcpuDC,eduuDD,MAAA,acvuDC,ed0uDD,MAAA,ac1uDC,ed6uDD,MAAA,Ic7uDC,edgvDD,MAAA,ac3uDC,ed8uDD,MAAA,Yc7vDC,edgwDD,MAAA,KchwDC,gBdmwDD,KAAA,KcnwDC,gBdswDD,KAAA,actwDC,gBdywDD,KAAA,aczwDC,ed4wDD,KAAA,Ic5wDC,ed+wDD,KAAA,ac/wDC,edkxDD,KAAA,aclxDC,edqxDD,KAAA,IcrxDC,edwxDD,KAAA,acxxDC,ed2xDD,KAAA,ac3xDC,ed8xDD,KAAA,Ic9xDC,ediyDD,KAAA,ac5xDC,ed+xDD,KAAA,YchxDC,edmxDD,KAAA,KcnxDC,kBdsxDD,YAAA,KctxDC,kBdyxDD,YAAA,aczxDC,kBd4xDD,YAAA,ac5xDC,iBd+xDD,YAAA,Ic/xDC,iBdkyDD,YAAA,aclyDC,iBdqyDD,YAAA,acryDC,iBdwyDD,YAAA,IcxyDC,iBd2yDD,YAAA,ac3yDC,iBd8yDD,YAAA,ac9yDC,iBdizDD,YAAA,IcjzDC,iBdozDD,YAAA,acpzDC,iBduzDD,YAAA,YY9yDD,iBE3CE,YAAA,GAQF,yBACE,UAAA,WAAA,WAAA,WAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,Udw1DD,MAAA,Kcx1DC,Wd21DD,MAAA,Kc31DC,Wd81DD,MAAA,ac91DC,Wdi2DD,MAAA,acj2DC,Udo2DD,MAAA,Icp2DC,Udu2DD,MAAA,acv2DC,Ud02DD,MAAA,ac12DC,Ud62DD,MAAA,Ic72DC,Udg3DD,MAAA,ach3DC,Udm3DD,MAAA,acn3DC,Uds3DD,MAAA,Ict3DC,Udy3DD,MAAA,ac12DC,Ud62DD,MAAA,Yc72DC,gBdg3DD,MAAA,Kch3DC,gBdm3DD,MAAA,acn3DC,gBds3DD,MAAA,act3DC,edy3DD,MAAA,Icz3DC,ed43DD,MAAA,ac53DC,ed+3DD,MAAA,ac/3DC,edk4DD,MAAA,Icl4DC,edq4DD,MAAA,acr4DC,edw4DD,MAAA,acx4DC,ed24DD,MAAA,Ic34DC,ed84DD,MAAA,acz4DC,ed44DD,MAAA,Yc35DC,ed85DD,MAAA,Kc95DC,gBdi6DD,KAAA,Kcj6DC,gBdo6DD,KAAA,acp6DC,gBdu6DD,KAAA,acv6DC,ed06DD,KAAA,Ic16DC,ed66DD,KAAA,ac76DC,edg7DD,KAAA,ach7DC,edm7DD,KAAA,Icn7DC,eds7DD,KAAA,act7DC,edy7DD,KAAA,acz7DC,ed47DD,KAAA,Ic57DC,ed+7DD,KAAA,ac17DC,ed67DD,KAAA,Yc96DC,edi7DD,KAAA,Kcj7DC,kBdo7DD,YAAA,Kcp7DC,kBdu7DD,YAAA,acv7DC,kBd07DD,YAAA,ac17DC,iBd67DD,YAAA,Ic77DC,iBdg8DD,YAAA,ach8DC,iBdm8DD,YAAA,acn8DC,iBds8DD,YAAA,Ict8DC,iBdy8DD,YAAA,acz8DC,iBd48DD,YAAA,ac58DC,iBd+8DD,YAAA,Ic/8DC,iBdk9DD,YAAA,acl9DC,iBdq9DD,YAAA,YYz8DD,iBE9CE,YAAA,GAQF,0BACE,UAAA,WAAA,WAAA,WAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,Uds/DD,MAAA,Kct/DC,Wdy/DD,MAAA,Kcz/DC,Wd4/DD,MAAA,ac5/DC,Wd+/DD,MAAA,ac//DC,UdkgED,MAAA,IclgEC,UdqgED,MAAA,acrgEC,UdwgED,MAAA,acxgEC,Ud2gED,MAAA,Ic3gEC,Ud8gED,MAAA,ac9gEC,UdihED,MAAA,acjhEC,UdohED,MAAA,IcphEC,UduhED,MAAA,acxgEC,Ud2gED,MAAA,Yc3gEC,gBd8gED,MAAA,Kc9gEC,gBdihED,MAAA,acjhEC,gBdohED,MAAA,acphEC,eduhED,MAAA,IcvhEC,ed0hED,MAAA,ac1hEC,ed6hED,MAAA,ac7hEC,edgiED,MAAA,IchiEC,edmiED,MAAA,acniEC,edsiED,MAAA,actiEC,edyiED,MAAA,IcziEC,ed4iED,MAAA,acviEC,ed0iED,MAAA,YczjEC,ed4jED,MAAA,Kc5jEC,gBd+jED,KAAA,Kc/jEC,gBdkkED,KAAA,aclkEC,gBdqkED,KAAA,acrkEC,edwkED,KAAA,IcxkEC,ed2kED,KAAA,ac3kEC,ed8kED,KAAA,ac9kEC,edilED,KAAA,IcjlEC,edolED,KAAA,acplEC,edulED,KAAA,acvlEC,ed0lED,KAAA,Ic1lEC,ed6lED,KAAA,acxlEC,ed2lED,KAAA,Yc5kEC,ed+kED,KAAA,Kc/kEC,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A,KlBq7FM,WAAY,KkBn7FhB,QAAA,IASN,eC3DE,yBACA,eAAA,KpBi+FD,aoB99FC,MAAA,KnB0+FA,iBAAkB,KmBx+FhB,aAAA,KpBk+FH,mBoBh+FO,mBAEN,MAAA,KACE,iBAAA,QACA,aAAA,QpBi+FH,mBoB99FC,MAAA,KnB0+FA,iBAAkB,QAClB,aAAc,QmBt+FR,oBADJ,oBpBi+FH,mCoB99FG,MAAA,KnB0+FF,iBAAkB,QAClB,aAAc,QmBt+FN,0BnB4+FV,0BAHA,0BmB1+FM,0BnB4+FN,0BAHA,0BDFC,yCoBx+FK,yCnB4+FN,yCmBv+FE,MAAA,KnB++FA,iBAAkB,QAClB,aAAc,QmBx+FZ,oBpBg+FH,oBoBh+FG,mCnB6+FF,iBAAkB,KmBz+FV,4BnB8+FV,4BAHA,4BDHC,6BCOD,6BAHA,6BkB39FA,sCClBM,sCnB8+FN,sCmBx+FI,iBAAA,KACA,aAAA,KDcJ,oBC9DE,MAAA,KACA,iBAAA,KpB0hGD,aoBvhGC,MAAA,KnBmiGA,iBAAkB,QmBjiGhB,aAAA,QpB2hGH,mBoBzhGO,mBAEN,MAAA,KACE,iBAAA,QACA,aAAA,QpB0hGH,mBoBvhGC,MAAA,KnBmiGA,iBAAkB,QAClB,aAAc,QmB/hGR,oBADJ,oBpB0hGH,mCoBvhGG,MAAA,KnBmiGF,iBAAkB,QAClB,aAAc,QmB/hGN,0BnBqiGV,0BAHA,0BmBniGM,0BnBqiGN,0BAHA,0BDFC,yCoBjiGK,yCnBqiGN,yCmBhiGE,MAAA,KnBwiGA,iBAAkB,QAClB,aAAc,QmBjiGZ,oBpByhGH,oBoBzhGG,mCnBsiGF,iBAAkB,KmBliGV,4BnBuiGV,4BAHA,4BDHC,6BCOD,6BAHA,6BkBjhGA,sCCrBM,sCnBuiGN,sCmBjiGI,iBAAA,QACA,aAAA,QDkBJ,oBClEE,MAAA,QACA,iBAAA,KpBmlGD,aoBhlGC,MAAA,KnB4lGA,iBAAkB,QmB1lGhB,aAAA,QpBolGH,mBoBllGO,mBAEN,MAAA,KACE,iBAAA,QACA,aAAA,QpBmlGH,mBoBhlGC,MAAA,KnB4lGA,iBAAkB,QAClB,aAAc,QmBxlGR,oBADJ,oBpBmlGH,mCoBhlGG,MAAA,KnB4lGF,iBAAkB,QAClB,aAAc,QmBxlGN,0BnB8lGV,0BAHA,0BmB5lGM,0BnB8lGN,0BAHA,0BDFC,yCoB1lGK,yCnB8lGN,yCmBzlGE,MAAA,KnBimGA,iBAAkB,QAClB,aAAc,QmB1lGZ,oBpBklGH,oBoBllGG,mCnB+lGF,iBAAkB,KmB3lGV,4BnBgmGV,4BAHA,4BDHC,6BCOD,6BAHA,6BkBtkGA,sCCzBM,sCnBgmGN,sCmB1lGI,iBAAA,QACA,aAAA,QDsBJ,oBCtEE,MAAA,QACA,iBAAA,KpB4oGD,UoBzoGC,MAAA,KnBqpGA,iBAAkB,QmBnpGhB,aAAA,QpB6oGH,gBoB3oGO,gBAEN,MAAA,KACE,iBAAA,QACA,aAAA,QpB4oGH,gBoBzoGC,MAAA,KnBqpGA,iBAAkB,QAClB,aAAc,QmBjpGR,iBADJ,iBpB4oGH,gCoBzoGG,MAAA,KnBqpGF,iBAAkB,QAClB,aAAc,QmBjpGN,uBnBupGV,uBAHA,uBmBrpGM,uBnBupGN,uBAHA,uBDFC,sCoBnpGK,sCnBupGN,sCmBlpGE,MAAA,KnB0pGA,iBAAkB,QAClB,aAAc,QmBnpGZ,iBpB2oGH,iBoB3oGG,gCnBwpGF,iBAAkB,KmBppGV,yBnBypGV,yBAHA,yBDHC,0BCOD,0BAHA,0BkB3nGA,mCC7BM,mCnBypGN,mCmBnpGI,iBAAA,QACA,aAAA,QD0BJ,iBC1EE,MAAA,QACA,iBAAA,KpBqsGD,aoBlsGC,MAAA,KnB8sGA,iBAAkB,QmB5sGhB,aAAA,QpBssGH,mBoBpsGO,mBAEN,MAAA,KACE,iBAAA,QACA,aAAA,QpBqsGH,mBoBlsGC,MAAA,KnB8sGA,iBAAkB,QAClB,aAAc,QmB1sGR,oBADJ,oBpBqsGH,mCoBlsGG,MAAA,KnB8sGF,iBAAkB,QAClB,aAAc,QmB1sGN,0BnBgtGV,0BAHA,0BmB9sGM,0BnBgtGN,0BAHA,0BDFC,yCoB5sGK,yCnBgtGN,yCmB3sGE,MAAA,KnBmtGA,iBAAkB,QAClB,aAAc,QmB5sGZ,oBpBosGH,oBoBpsGG,mCnBitGF,iBAAkB,KmB7sGV,4BnBktGV,4BAHA,4BDHC,6BCOD,6BAHA,6BkBhrGA,sCCjC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A,QkDrxKC,WAAY,IAAI,MAAM,KjDizKtB,2BAA4B,IiD9yK1B,0BAAA,IAHJ,mBAAA,mCAMM,cAAA,ElDwxKL,oCkDnxKG,oDjD+yKF,aAAc,IAAI,EiD7yKZ,cAAA,EvBtEL,4D3B61KF,4EkDjxKG,WAAA,EjD6yKF,uBAAwB,IiD3yKlB,wBAAA,IvBtEL,0D3B21KF,0EkD1yKC,cAAe,EvB1Df,2BAAA,IACC,0BAAA,IuB0FH,+EAEI,uBAAA,ElD8wKH,wBAAA,EkD1wKC,wDlD6wKD,iBAAA,EC4BD,0BACE,iBAAkB,EiDlyKpB,8BlD0wKC,ckD1wKD,gCjDuyKE,cAAe,EiDvyKjB,sCAQM,sBlDwwKL,wCC4BC,cAAe,K0Br5Kf,aAAA,KuByGF,wDlDqxKC,0BC4BC,uBAAwB,IACxB,wBAAyB,IiDlzK3B,yFAoBQ,yFlDwwKP,2DkDzwKO,2DjDqyKN,uBAAwB,IACxB,wBAAyB,IAK3B,wGiD9zKA,wGjD4zKA,wGDtBC,wGCuBD,0EiD7zKA,0EjD2zKA,0EiDnyKU,0EjD2yKR,uBAAwB,IAK1B,uGiDx0KA,uGjDs0KA,uGDtBC,uGCuBD,yEiDv0KA,yEjDq0KA,yEiDzyKU,yEvB7HR,wBAAA,IuBiGF,sDlDqzKC,yBC4BC,2BAA4B,IAC5B,0BAA2B,IiDxyKrB,qFA1CR,qFAyCQ,wDlDmxKP,wDC4BC,2BAA4B,IAC5B,0BAA2B,IAG7B,oGDtBC,oGCwBD,oGiD91KA,oGjD21KA,uEiD7yKU,uEjD+yKV,uEiD71KA,uEjDm2KE,0BAA2B,IAG7B,mGDtBC,mGCwBD,mGiDx2KA,mGjDq2KA,sEiDnzKU,sEjDqzKV,sEiDv2KA,sEjD62KE,2BAA4B,IiDlzK1B,0BlD2xKH,qCkDt1KD,0BAAA,qCA+DI,WAAA,IAAA,MAAA,KA/DJ,kDAAA,kDAmEI,WAAA,EAnEJ,uBAAA,yCjD23KE,OAAQ,EiDjzKA,+CjDqzKV,+CiD/3KA,+CjDi4KA,+CAEA,+CANA,+CDjBC,iECoBD,iEiDh4KA,iEjDk4KA,iEAEA,iEANA,iEAWE,YAAa,EiD3zKL,8CjD+zKV,8CiD74KA,8CjD+4KA,8CAEA,8CANA,8CDjBC,gECoBD,gEiD94KA,gEjDg5KA,gEAEA,gEANA,gEAWE,aAAc,EAIhB,+CiD35KA,+CjDy5KA,+CiDl0KU,+CjDq0KV,iEiD55KA,iEjD05KA,iEDtBC,iEC6BC,cAAe,EAEjB,8CiDn0KU,8CjDq0KV,8CiDr6KA,8CjDo6KA,gEDtBC,gECwBD,gEiDh0KI,gEACA,cAAA,EAUJ,yBACE,cAAA,ElDmyKD,OAAA,EkD/xKG,aACA,cAAA,KANJ,oBASM,cAAA,ElDkyKL,cAAA,IkD7xKG,2BlDgyKH,WAAA,IC4BD,4BiDxzKM,cAAA,EAKF,wDAvBJ,wDlDqzKC,WAAA,IAAA,MAAA,KkD5xKK,2BlD+xKL,WAAA,EmDlhLC,uDnDqhLD,cAAA,IAAA,MAAA,KmDlhLG,eACA,aAAA,KnDshLH,8BmDxhLC,MAAA,KAMI,iBAAA,QnDqhLL,aAAA,KmDlhLK,0DACA,iBAAA,KAGJ,qCAEI,MAAA,QnDmhLL,iBAAA,KmDpiLC,yDnDuiLD,oBAAA,KmDpiLG,eACA,aAAA,QnDwiLH,8BmD1iLC,MAAA,KAMI,iBAAA,QnDuiLL,aAAA,QmDpiLK,0DACA,iBAAA,QAGJ,qCAEI,MAAA,QnDqiLL,iBAAA,KmDtjLC,yDnDyjLD,oBAAA,QmDtjLG,eACA,aAAA,QnD0jLH,8BmD5jLC,MAAA,QAMI,iBAAA,QnDyjLL,aAAA,QmDtjLK,0DACA,iBAAA,QAGJ,qCAEI,MAAA,QnDujLL,iBAAA,QmDxkLC,yDnD2kLD,oBAAA,QmDxkLG,YACA,aAAA,QnD4kLH,2BmD9kLC,MAAA,QAMI,iBAAA,QnD2kLL,aAAA,QmDxkLK,uDACA,iBAAA,QAGJ,kCAEI,MAAA,QnDykLL,iBAAA,QmD1lLC,sDnD6lLD,oBAAA,QmD1lLG,eACA,aAAA,QnD8lLH,8BmDhmLC,MAAA,QAMI,iBAAA,QnD6lLL,aAAA,QmD1lLK,0DACA,iBAAA,QAGJ,qCAEI,MAAA,QnD2lLL,iBAAA,QmD5mLC,yDnD+mLD,oBAAA,QmD5mLG,cACA,aAAA,QnDgnLH,6BmDlnLC,MAAA,QAMI,iBAAA,QnD+mLL,aAAA,QmD5mLK,yDACA,iBAAA,QAGJ,oCAEI,MAAA,QnD6mLL,iBAAA,QoD5nLC,wDACA,oBAAA,QAEA,kBACA,SAAA,SpD+nLD,QAAA,MoDpoLC,OAAQ,EnDgqLR,QAAS,EACT,SAAU,OAEZ,yCmDtpLI,wBADA,yBAEA,yBACA,wBACA,SAAA,SACA,IAAA,EACA,OAAA,EpD+nLH,KAAA,EoD1nLC,MAAO,KACP,OAAA,KpD4nLD,OAAA,EoDvnLC,wBpD0nLD,eAAA,OqDppLC,uBACA,eAAA,IAEA,MACA,WAAA,KACA,QAAA,KjDwDA,cAAA,KACQ,iBAAA,QJgmLT,OAAA,IAAA,MAAA,QqD/pLC,cAAe,IASb,mBAAA,MAAA,EAAA,IAAA,IAAA,gBACA,WAAA,MAAA,EAAA,IAAA,IAAA,gBAKJ,iBACE,aAAA,KACA,aAAA,gBAEF,SACE,QAAA,KACA,cAAA,ICtBF,SACE,QAAA,IACA,cAAA,IAEA,OACA,MAAA,MACA,UAAA,KjCRA,YAAA,IAGA,YAAA,ErBqrLD,MAAA,KsD7qLC,YAAA,EAAA,IAAA,EAAA,KrDysLA,OAAQ,kBqDvsLN,QAAA,GjCbF,aiCeE,ajCZF,MAAA,KrB6rLD,gBAAA,KsDzqLC,OAAA,QACE,OAAA,kBACA,QAAA,GAEA,aACA,mBAAA,KtD2qLH,QAAA,EuDhsLC,OAAQ,QACR,WAAA,IvDksLD,OAAA,EuD7rLC,YACA,SAAA,OAEA,OACA,SAAA,MACA,IAAA,EACA,MAAA,EACA,OAAA,EACA,KAAA,EAIA,QAAA,KvD6rLD,QAAA,KuD1rLC,SAAA,OnD+GA,2BAAA,MACI,QAAA,EAEI,0BAkER,mBAAA,kBAAA,IAAA,SAEK,cAAA,aAAA,IAAA,SACG,WAAA,UAAA,IAAA,SJ6gLT,kBAAA,kBuDhsLC,cAAA,kBnD2GA,aAAA,kBACI,UAAA,kBAEI,wBJwlLT,kBAAA,euDpsLK,cAAe,eACnB,aAAA,eACA,UAAA,eAIF,mBACE,WAAA,OACA,WAAA,KvDqsLD,cuDhsLC,SAAU,SACV,MAAA,KACA,OAAA,KAEA,eACA,SAAA,SnDaA,iBAAA,KACQ,wBAAA,YmDZR,gBAAA,YtD4tLA,OsD5tLA,IAAA,MAAA,KAEA,OAAA,IAAA,MAAA,evDksLD,cAAA,IuD9rLC,QAAS,EACT,mBAAA,EAAA,IAAA,IAAA,eACA,WAAA,EAAA,IAAA,IAAA,eAEA,gBACA,SAAA,MACA,IAAA,EACA,MAAA,EvDgsLD,OAAA,EuD9rLC,KAAA,ElCrEA,QAAA,KAGA,iBAAA,KkCmEA,qBlCtEA,OAAA,iBAGA,QAAA,EkCwEF,mBACE,OAAA,kBACA,QAAA,GAIF,cACE,QAAA,KvDgsLD,cAAA,IAAA,MAAA,QuD3rLC,qBACA,WAAA,KAKF,aACE,OAAA,EACA,YAAA,WAIF,YACE,SAAA,SACA,QAAA,KvD0rLD,cuD5rLC,QAAS,KAQP,WAAA,MACA,WAAA,IAAA,MAAA,QATJ,wBAaI,cAAA,EvDsrLH,YAAA,IuDlrLG,mCvDqrLH,YAAA,KuD/qLC,oCACA,YAAA,EAEA,yBACA,SAAA,SvDkrLD,IAAA,QuDhqLC,MAAO,KAZP,OAAA,KACE,SAAA,OvDgrLD,yBuD7qLD,cnDvEA,MAAA,MACQ,OAAA,KAAA,KmD2ER,eAAY,mBAAA,EAAA,IAAA,KAAA,evD+qLX,WAAA,EAAA,IAAA,KAAA,euDzqLD,UAFA,MAAA,OvDirLD,yBwD/zLC,UACA,MAAA,OCNA,SAEA,SAAA,SACA,QAAA,KACA,QAAA,MACA,YAAA,iBAAA,UAAA,MAAA,WACA,UAAA,KACA,WAAA,OACA,YAAA,IACA,YAAA,WACA,WAAA,KACA,WAAA,MACA,gBAAA,KACA,YAAA,KACA,eAAA,KACA,eAAA,ODHA,WAAA,OnCVA,aAAA,OAGA,UAAA,OrBs1LD,YAAA,OwD30LC,OAAA,iBnCdA,QAAA,ErB61LD,WAAA,KwD90LY,YAAmB,OAAA,kBxDk1L/B,QAAA,GwDj1LY,aAAmB,QAAA,IAAA,ExDq1L/B,WAAA,KwDp1LY,eAAmB,QAAA,EAAA,IxDw1L/B,YAAA,IwDv1LY,gBAAmB,QAAA,IAAA,ExD21L/B,WAAA,IwDt1LC,cACA,QAAA,EAAA,IACA,YAAA,KAEA,eACA,UAAA,MxDy1LD,QAAA,IAAA,IwDr1LC,MAAO,KACP,WAAA,OACA,iBAAA,KACA,cAAA,IAEA,exDu1LD,SAAA,SwDn1LC,MAAA,EACE,OAAA,EACA,aAAA,YACA,aAAA,MAEA,4BxDq1LH,OAAA,EwDn1LC,KAAA,IACE,YAAA,KACA,aAAA,IAAA,IAAA,EACA,iBAAA,KAEA,iCxDq1LH,MAAA,IwDn1LC,OAAA,EACE,cAAA,KACA,aAAA,IAAA,IAAA,EACA,iBAAA,KAEA,kCxDq1LH,OAAA,EwDn1LC,KAAA,IACE,cAAA,KACA,aAAA,IAAA,IAAA,EACA,iBAAA,KAEA,8BxDq1LH,IAAA,IwDn1LC,KAAA,EACE,WAAA,KACA,aAAA,IAAA,IAAA,IAAA,EACA,mBAAA,KAEA,6BxDq1LH,IAAA,IwDn1LC,MAAA,EACE,WAAA,KACA,aAAA,IAAA,EAAA,IAAA,IACA,kBAAA,KAEA,+BxDq1LH,IAAA,EwDn1LC,KAAA,IACE,YAAA,KACA,aAAA,EAAA,IAAA,IACA,oBAAA,KAEA,oCxDq1LH,IAAA,EwDn1LC,MAAA,IACE,WAAA,KACA,aAAA,EAAA,IAAA,IACA,oBAAA,KAEA,qCxDq1LH,IAAA,E0Dl7LC,KAAM,IACN,WAAA,KACA,aAAA,EAAA,IAAA,IACA,oBAAA,KAEA,SACA,SAAA,SACA,IAAA,EDXA,KAAA,EAEA,QAAA,KACA,QAAA,KACA,UAAA,MACA,QAAA,IACA,YAAA,iBAAA,UAAA,MAAA,WACA,UAAA,KACA,WAAA,OACA,YAAA,IACA,YAAA,WACA,WAAA,KACA,WAAA,MACA,gBAAA,KACA,YAAA,KACA,eAAA,KCAA,eAAA,OAEA,WAAA,OACA,aAAA,OAAA,UAAA,OACA,YAAA,OACA,iBAAA,KACA,wBAAA,YtD8CA,gBAAA,YACQ,OAAA,IAAA,MAAA,KJk5LT,OAAA,IAAA,MAAA,e0D77LC,cAAA,IAAY,mBAAA,EAAA,IAAA,KAAA,e1Dg8Lb,WAAA,EAAA,IAAA,KAAA,e0D/7La,WAAA,KACZ,aAAY,WAAA,MACZ,eAAY,YAAA,KAGd,gBACE,WAAA,KAEA,cACA,YAAA,MAEA,e1Dq8LD,QAAA,IAAA,K0Dl8LC,OAAQ,EACR,UAAA,K1Do8LD,iBAAA,Q0D57LC,cAAA,IAAA,MAAA,QzDy9LA,cAAe,IAAI,IAAI,EAAE,EyDt9LvB,iBACA,QAAA,IAAA,KAEA,gBACA,sB1D87LH,SAAA,S0D37LC,QAAS,MACT,MAAA,E1D67LD,OAAA,E0D37LC,aAAc,YACd,aAAA,M1D87LD,gB0Dz7LC,aAAA,KAEE,sBACA,QAAA,GACA,aAAA,KAEA,oB1D27LH,OAAA,M0D17LG,KAAA,IACE,YAAA,MACA,iBAAA,KACA,iBAAA,gBACA,oBAAA,E1D67LL,0B0Dz7LC,OAAA,IACE,YAAA,MACA,QAAA,IACA,iBAAA,KACA,oBAAA,EAEA,sB1D27LH,IAAA,I0D17LG,KAAA,MACE,WAAA,MACA,mBAAA,KACA,mBAAA,gBACA,kBAAA,E1D67LL,4B0Dz7LC,OAAA,MACE,KAAA,IACA,QAAA,IACA,mBAAA,KACA,kBAAA,EAEA,uB1D27LH,IAAA,M0D17LG,KAAA,IACE,YAAA,MACA,iBAAA,EACA,oBAAA,KACA,oBAAA,gB1D67LL,6B0Dx7LC,IAAA,IACE,YAAA,MACA,QAAA,IACA,iBAAA,EACA,oBAAA,KAEA,qB1D07LH,IAAA,I0Dz7LG,MAAA,MACE,WAAA,MACA,mBAAA,EACA,kBAAA,KACA,kBAAA,gB1D47LL,2B2DpjMC,MAAO,IACP,OAAA,M3DsjMD,QAAA,I2DnjMC,mBAAoB,EACpB,kBAAA,KAEA,U3DqjMD,SAAA,S2DljMG,gBACA,SAAA,SvD6KF,MAAA,KACK,SAAA,OJ04LN,sB2D/jMC,SAAU,S1D4lMV,QAAS,K0D9kML,mBAAA,IAAA,YAAA,K3DqjML,cAAA,IAAA,YAAA,K2D3hMC,WAAA,IAAA,YAAA,KvDmKK,4BAFL,0BAGQ,YAAA,EA3JA,qDA+GR,sBAEQ,mBAAA,kBAAA,IAAA,YJ86LP,cAAA,aAAA,IAAA,Y2DzjMG,WAAA,UAAA,IAAA,YvDmHJ,4BAAA,OACQ,oBAAA,OuDjHF,oBAAA,O3D4jML,YAAA,OI58LD,mCHs+LA,2BGr+LQ,KAAA,EuD5GF,kBAAA,sB3D6jML,UAAA,sBC2BD,kCADA,2BG5+LA,KAAA,EACQ,kBAAA,uBuDtGF,UAAA,uBArCN,6B3DomMD,gC2DpmMC,iC1D+nME,KAAM,E0DllMN,kBAAA,mB3D4jMH,UAAA,oBAGA,wB2D5mMD,sBAAA,sBAsDI,QAAA,MAEA,wB3D0jMH,KAAA,E2DtjMG,sB3DyjMH,sB2DrnMC,SAAU,SA+DR,IAAA,E3DyjMH,MAAA,KC0BD,sB0D/kMI,KAAA,KAnEJ,sBAuEI,KAAA,MAvEJ,2BA0EI,4B3DwjMH,KAAA,E2D/iMC,6BACA,KAAA,MAEA,8BACA,KAAA,KtC3FA,kBsC6FA,SAAA,SACA,IAAA,EACA,OAAA,EACA,KAAA,EACA,MAAA,I3DmjMD,UAAA,K2D9iMC,MAAA,KdnGE,WAAA,OACA,YAAA,EAAA,IAAA,IAAA,eACA,iBAAA,cAAA,OAAA,kBACA,QAAA,G7CqpMH,uB2DljMC,iBAAA,sEACE,iBAAA,iEACA,iBAAA,uFdxGA,iBAAA,kEACA,OAAA,+GACA,kBAAA,SACA,wBACA,MAAA,E7C6pMH,KAAA,K2DpjMC,iBAAA,sE1DglMA,iBAAiB,iE0D9kMf,iBAAA,uFACA,iBAAA,kEACA,OAAA,+GtCvHF,kBAAA,SsCyFF,wB3DslMC,wBC4BC,MAAO,KACP,gBAAiB,KACjB,OAAQ,kB0D7kMN,QAAA,EACA,QAAA,G3DwjMH,0C2DhmMD,2CA2CI,6BADA,6B1DklMF,SAAU,S0D7kMR,IAAA,IACA,QAAA,E3DqjMH,QAAA,a2DrmMC,WAAY,MAqDV,0CADA,6B3DsjMH,KAAA,I2D1mMC,YAAa,MA0DX,2CADA,6BAEA,MAAA,IACA,aAAA,MAME,6BADF,6B3DmjMH,MAAA,K2D9iMG,OAAA,KACE,YAAA,M3DgjML,YAAA,E2DriMC,oCACA,QAAA,QAEA,oCACA,QAAA,QAEA,qBACA,SAAA,SACA,OAAA,K3DwiMD,KAAA,I2DjjMC,QAAS,GAYP,MAAA,IACA,aAAA,EACA,YAAA,KACA,WAAA,OACA,WAAA,KAEA,wBACA,QAAA,aAWA,MAAA,KACA,OAAA,K3D8hMH,OAAA,I2D7jMC,YAAa,OAkCX,OAAA,QACA,iBAAA,OACA,iBAAA,cACA,OAAA,IAAA,MAAA,K3D8hMH,cAAA,K2DthMC,6BACA,MAAA,KACA,OAAA,KACA,OAAA,EACA,iBAAA,KAEA,kBACA,SAAA,SACA,MAAA,IACA,OAAA,K3DyhMD,KAAA,I2DxhMC,QAAA,GACE,YAAA,K3D0hMH,eAAA,K2Dj/LC,MAAO,KAhCP,WAAA,O1D8iMA,YAAa,EAAE,IAAI,IAAI,eAEzB,uB0D3iMM,YAAA,KAEA,oCACA,0C3DmhMH,2C2D3hMD,6BAAA,6BAYI,MAAA,K3DmhMH,OAAA,K2D/hMD,WAAA,M1D2jME,UAAW,KDxBZ,0C2D9gMD,6BACE,YAAA,MAEA,2C3DghMD,6B2D5gMD,aAAA,M3D+gMC,kBACF,MAAA,I4D7wMC,KAAA,I3DyyME,eAAgB,KAElB,qBACE,OAAQ,MAkBZ,qCADA,sCADA,mBADA,oBAXA,gBADA,iBAOA,uBADA,wBADA,iBADA,kBADA,wBADA,yBASA,mCADA,oC2DpzME,oBAAA,qBAAA,oBAAA,qB3D2zMF,WADA,YAOA,uBADA,wBADA,qBADA,sBADA,cADA,e2D/zMI,a3Dq0MJ,cDvBC,kB4D7yMG,mB3DqzMJ,WADA,YAwBE,QAAS,MACT,QAAS,IASX,qCADA,mBANA,gBAGA,uBADA,iBADA,wBAIA,mCDhBC,oB6D/0MC,oB5Dk2MF,W+B51MA,uBhCo0MC,qB4D5zMG,cChBF,aACA,kB5D+1MF,W+Br1ME,MAAO,KhCy0MR,cgCt0MC,QAAS,MACT,aAAA,KhCw0MD,YAAA,KgC/zMC,YhCk0MD,MAAA,gBgC/zMC,WhCk0MD,MAAA,egC/zMC,MhCk0MD,QAAA,e8Dz1MC,MACA,QAAA,gBAEA,WACA,WAAA,O9B8BF,WACE,KAAA,EAAA,EAAA,EhCg0MD,MAAA,YgCzzMC,YAAa,KACb,iBAAA,YhC2zMD,OAAA,E+D31MC,Q/D81MD,QAAA,eC4BD,OACE,SAAU,M+Dn4MV,chE42MD,MAAA,aC+BD,YADA,YADA,YADA,YAIE,QAAS,e+Dp5MT,kBhEs4MC,mBgEr4MD,yBhEi4MD,kB+Dl1MD,mBA6IA,yB9D4tMA,kBACA,mB8Dj3ME,yB9D62MF,kBACA,mBACA,yB+Dv5MY,QAAA,eACV,yBAAU,YhE04MT,QAAA,gBC4BD,iB+Dp6MU,QAAA,gBhE64MX,c+D51MG,QAAS,oB/Dg2MV,c+Dl2MC,c/Dm2MH,QAAA,sB+D91MG,yB/Dk2MD,kBACF,QAAA,iB+D91MG,yB/Dk2MD,mBACF,QAAA,kBgEh6MC,yBhEo6MC,yBgEn6MD,QAAA,wBACA,+CAAU,YhEw6MT,QAAA,gBC4BD,iB+Dl8MU,QAAA,gBhE26MX,c+Dr2MG,QAAS,oB/Dy2MV,c+D32MC,c/D42MH,QAAA,sB+Dv2MG,+C/D22MD,kBACF,QAAA,iB+Dv2MG,+C/D22MD,mBACF,QAAA,kBgE97MC,+ChEk8MC,yBgEj8MD,QAAA,wBACA,gDAAU,YhEs8MT,QAAA,gBC4BD,iB+Dh+MU,QAAA,gBhEy8MX,c+D92MG,QAAS,oB/Dk3MV,c+Dp3MC,c/Dq3MH,QAAA,sB+Dh3MG,gD/Do3MD,kBACF,QAAA,iB+Dh3MG,gD/Do3MD,mBACF,QAAA,kBgE59MC,gDhEg+MC,yBgE/9MD,QAAA,wBACA,0BAAU,YhEo+MT,QAAA,gBC4BD,iB+D9/MU,QAAA,gBhEu+MX,c+Dv3MG,QAAS,oB/D23MV,c+D73MC,c/D83MH,QAAA,sB+Dz3MG,0B/D63MD,kBACF,QAAA,iB+Dz3MG,0B/D63MD,mBACF,QAAA,kBgEl/MC,0BhEs/MC,yBACF,QAAA,wBgEv/MC,yBhE2/MC,WACF,QAAA,gBgE5/MC,+ChEggNC,WACF,QAAA,gBgEjgNC,gDhEqgNC,WACF,QAAA,gBAGA,0B+Dh3MC,WA4BE,QAAS,gBC5LX,eAAU,QAAA,eACV,aAAU,ehEyhNT,QAAA,gBC4BD,oB+DnjNU,QAAA,gBhE4hNX,iB+D93MG,QAAS,oBAMX,iB/D23MD,iB+Dt2MG,QAAS,sB/D22MZ,qB+D/3MC,QAAS,e/Dk4MV,a+D53MC,qBAcE,QAAS,iB/Dm3MZ,sB+Dh4MC,QAAS,e/Dm4MV,a+D73MC,sBAOE,QAAS,kB/D23MZ,4B+D53MC,QAAS,eCpLT,ahEojNC,4BACF,QAAA,wBC6BD,aACE,cACE,QAAS","sourcesContent":["/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\n\n//\n// 1. Set default font family to sans-serif.\n// 2. Prevent iOS and IE text size adjust after device orientation change,\n// without disabling user zoom.\n//\n\nhtml {\n font-family: sans-serif; // 1\n -ms-text-size-adjust: 100%; // 2\n -webkit-text-size-adjust: 100%; // 2\n}\n\n//\n// Remove default margin.\n//\n\nbody {\n margin: 0;\n}\n\n// HTML5 display definitions\n// ==========================================================================\n\n//\n// Correct `block` display not defined for any HTML5 element in IE 8/9.\n// Correct `block` display not defined for `details` or `summary` in IE 10/11\n// and Firefox.\n// Correct `block` display not defined for `main` in IE 11.\n//\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\n\n//\n// 1. Correct `inline-block` display not defined in IE 8/9.\n// 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n//\n\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block; // 1\n vertical-align: baseline; // 2\n}\n\n//\n// Prevent modern browsers from displaying `audio` without controls.\n// Remove excess height in iOS 5 devices.\n//\n\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n\n//\n// Address `[hidden]` styling not present in IE 8/9/10.\n// Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22.\n//\n\n[hidden],\ntemplate {\n display: none;\n}\n\n// Links\n// ==========================================================================\n\n//\n// Remove the gray background color from active links in IE 10.\n//\n\na {\n background-color: transparent;\n}\n\n//\n// Improve readability of focused elements when they are also in an\n// active/hover state.\n//\n\na:active,\na:hover {\n outline: 0;\n}\n\n// Text-level semantics\n// ==========================================================================\n\n//\n// Address styling not present in IE 8/9/10/11, Safari, and Chrome.\n//\n\nabbr[title] {\n border-bottom: 1px dotted;\n}\n\n//\n// Address style set to `bolder` in Firefox 4+, Safari, and Chrome.\n//\n\nb,\nstrong {\n font-weight: bold;\n}\n\n//\n// Address styling not present in Safari and Chrome.\n//\n\ndfn {\n font-style: italic;\n}\n\n//\n// Address variable `h1` font-size and margin within `section` and `article`\n// contexts in Firefox 4+, Safari, and Chrome.\n//\n\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\n\n//\n// Address styling not present in IE 8/9.\n//\n\nmark {\n background: #ff0;\n color: #000;\n}\n\n//\n// Address inconsistent and variable font size in all browsers.\n//\n\nsmall {\n font-size: 80%;\n}\n\n//\n// Prevent `sub` and `sup` affecting `line-height` in all browsers.\n//\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsup {\n top: -0.5em;\n}\n\nsub {\n bottom: -0.25em;\n}\n\n// Embedded content\n// ==========================================================================\n\n//\n// Remove border when inside `a` element in IE 8/9/10.\n//\n\nimg {\n border: 0;\n}\n\n//\n// Correct overflow not hidden in IE 9/10/11.\n//\n\nsvg:not(:root) {\n overflow: hidden;\n}\n\n// Grouping content\n// ==========================================================================\n\n//\n// Address margin not present in IE 8/9 and Safari.\n//\n\nfigure {\n margin: 1em 40px;\n}\n\n//\n// Address differences between Firefox and other browsers.\n//\n\nhr {\n box-sizing: content-box;\n height: 0;\n}\n\n//\n// Contain overflow in all browsers.\n//\n\npre {\n overflow: auto;\n}\n\n//\n// Address odd `em`-unit font size rendering in all browsers.\n//\n\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\n\n// Forms\n// ==========================================================================\n\n//\n// Known limitation: by default, Chrome and Safari on OS X allow very limited\n// styling of `select`, unless a `border` property is set.\n//\n\n//\n// 1. Correct color not being inherited.\n// Known issue: affects color of disabled elements.\n// 2. Correct font properties not being inherited.\n// 3. Address margins set differently in Firefox 4+, Safari, and Chrome.\n//\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit; // 1\n font: inherit; // 2\n margin: 0; // 3\n}\n\n//\n// Address `overflow` set to `hidden` in IE 8/9/10/11.\n//\n\nbutton {\n overflow: visible;\n}\n\n//\n// Address inconsistent `text-transform` inheritance for `button` and `select`.\n// All other form control elements do not inherit `text-transform` values.\n// Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.\n// Correct `select` style inheritance in Firefox.\n//\n\nbutton,\nselect {\n text-transform: none;\n}\n\n//\n// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n// and `video` controls.\n// 2. Correct inability to style clickable `input` types in iOS.\n// 3. Improve usability and consistency of cursor style between image-type\n// `input` and others.\n//\n\nbutton,\nhtml input[type=\"button\"], // 1\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button; // 2\n cursor: pointer; // 3\n}\n\n//\n// Re-set default cursor for disabled elements.\n//\n\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\n\n//\n// Remove inner padding and border in Firefox 4+.\n//\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\n\n//\n// Address Firefox 4+ setting `line-height` on `input` using `!important` in\n// the UA stylesheet.\n//\n\ninput {\n line-height: normal;\n}\n\n//\n// It's recommended that you don't attempt to style these elements.\n// Firefox's implementation doesn't respect box-sizing, padding, or width.\n//\n// 1. Address box sizing set to `content-box` in IE 8/9/10.\n// 2. Remove excess padding in IE 8/9/10.\n//\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box; // 1\n padding: 0; // 2\n}\n\n//\n// Fix the cursor style for Chrome's increment/decrement buttons. For certain\n// `font-size` values of the `input`, it causes the cursor style of the\n// decrement button to change from `default` to `text`.\n//\n\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n//\n// 1. Address `appearance` set to `searchfield` in Safari and Chrome.\n// 2. Address `box-sizing` set to `border-box` in Safari and Chrome.\n//\n\ninput[type=\"search\"] {\n -webkit-appearance: textfield; // 1\n box-sizing: content-box; //2\n}\n\n//\n// Remove inner padding and search cancel button in Safari and Chrome on OS X.\n// Safari (but not Chrome) clips the cancel button when the search input has\n// padding (and `textfield` appearance).\n//\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n//\n// Define consistent border, margin, and padding.\n//\n\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\n\n//\n// 1. Correct `color` not being inherited in IE 8/9/10/11.\n// 2. Remove padding so people aren't caught out if they zero out fieldsets.\n//\n\nlegend {\n border: 0; // 1\n padding: 0; // 2\n}\n\n//\n// Remove default vertical scrollbar in IE 8/9/10/11.\n//\n\ntextarea {\n overflow: auto;\n}\n\n//\n// Don't inherit the `font-weight` (applied by a rule above).\n// NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n//\n\noptgroup {\n font-weight: bold;\n}\n\n// Tables\n// ==========================================================================\n\n//\n// Remove most spacing between table cells.\n//\n\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\n\ntd,\nth {\n padding: 0;\n}\n","/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n\n// ==========================================================================\n// Print styles.\n// Inlined to avoid the additional HTTP request: h5bp.com/r\n// ==========================================================================\n\n@media print {\n *,\n *:before,\n *:after {\n background: transparent !important;\n color: #000 !important; // Black prints faster: h5bp.com/s\n box-shadow: none !important;\n text-shadow: none !important;\n }\n\n a,\n a:visited {\n text-decoration: underline;\n }\n\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n\n // Don't show links that are fragment identifiers,\n // or use the `javascript:` pseudo protocol\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n\n thead {\n display: table-header-group; // h5bp.com/t\n }\n\n tr,\n img {\n page-break-inside: avoid;\n }\n\n img {\n max-width: 100% !important;\n }\n\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n\n h2,\n h3 {\n page-break-after: avoid;\n }\n\n // Bootstrap specific changes start\n\n // Bootstrap components\n .navbar {\n display: none;\n }\n .btn,\n .dropup > .btn {\n > .caret {\n border-top-color: #000 !important;\n }\n }\n .label {\n border: 1px solid #000;\n }\n\n .table {\n border-collapse: collapse !important;\n\n td,\n th {\n background-color: #fff !important;\n }\n }\n .table-bordered {\n th,\n td {\n border: 1px solid #ddd !important;\n }\n }\n\n // Bootstrap specific changes end\n}\n","/*!\n * Bootstrap v3.3.7 (http://getbootstrap.com)\n * Copyright 2011-2016 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\nhtml {\n font-family: sans-serif;\n -ms-text-size-adjust: 100%;\n -webkit-text-size-adjust: 100%;\n}\nbody {\n margin: 0;\n}\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block;\n vertical-align: baseline;\n}\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n[hidden],\ntemplate {\n display: none;\n}\na {\n background-color: transparent;\n}\na:active,\na:hover {\n outline: 0;\n}\nabbr[title] {\n border-bottom: 1px dotted;\n}\nb,\nstrong {\n font-weight: bold;\n}\ndfn {\n font-style: italic;\n}\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\nmark {\n background: #ff0;\n color: #000;\n}\nsmall {\n font-size: 80%;\n}\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\nsup {\n top: -0.5em;\n}\nsub {\n bottom: -0.25em;\n}\nimg {\n border: 0;\n}\nsvg:not(:root) {\n overflow: hidden;\n}\nfigure {\n margin: 1em 40px;\n}\nhr {\n box-sizing: content-box;\n height: 0;\n}\npre {\n overflow: auto;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit;\n font: inherit;\n margin: 0;\n}\nbutton {\n overflow: visible;\n}\nbutton,\nselect {\n text-transform: none;\n}\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button;\n cursor: pointer;\n}\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\ninput {\n line-height: normal;\n}\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box;\n padding: 0;\n}\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: textfield;\n box-sizing: content-box;\n}\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\nlegend {\n border: 0;\n padding: 0;\n}\ntextarea {\n overflow: auto;\n}\noptgroup {\n font-weight: bold;\n}\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\ntd,\nth {\n padding: 0;\n}\n/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n@media print {\n *,\n *:before,\n *:after {\n background: transparent !important;\n color: #000 !important;\n box-shadow: none !important;\n text-shadow: none !important;\n }\n a,\n a:visited {\n text-decoration: underline;\n }\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n thead {\n display: table-header-group;\n }\n tr,\n img {\n page-break-inside: avoid;\n }\n img {\n max-width: 100% !important;\n }\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n h2,\n h3 {\n page-break-after: avoid;\n }\n .navbar {\n display: none;\n }\n .btn > .caret,\n .dropup > .btn > .caret {\n border-top-color: #000 !important;\n }\n .label {\n border: 1px solid #000;\n }\n .table {\n border-collapse: collapse !important;\n }\n .table td,\n .table th {\n background-color: #fff !important;\n }\n .table-bordered th,\n .table-bordered td {\n border: 1px solid #ddd !important;\n }\n}\n@font-face {\n font-family: 'Glyphicons Halflings';\n src: url('../fonts/glyphicons-halflings-regular.eot');\n src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');\n}\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n.glyphicon-asterisk:before {\n content: \"\\002a\";\n}\n.glyphicon-plus:before {\n content: \"\\002b\";\n}\n.glyphicon-euro:before,\n.glyphicon-eur:before {\n content: \"\\20ac\";\n}\n.glyphicon-minus:before {\n content: \"\\2212\";\n}\n.glyphicon-cloud:before {\n content: \"\\2601\";\n}\n.glyphicon-envelope:before {\n content: \"\\2709\";\n}\n.glyphicon-pencil:before {\n content: \"\\270f\";\n}\n.glyphicon-glass:before {\n content: \"\\e001\";\n}\n.glyphicon-music:before {\n content: \"\\e002\";\n}\n.glyphicon-search:before {\n content: \"\\e003\";\n}\n.glyphicon-heart:before {\n content: \"\\e005\";\n}\n.glyphicon-star:before {\n content: \"\\e006\";\n}\n.glyphicon-star-empty:before {\n content: \"\\e007\";\n}\n.glyphicon-user:before {\n content: \"\\e008\";\n}\n.glyphicon-film:before {\n content: \"\\e009\";\n}\n.glyphicon-th-large:before {\n content: \"\\e010\";\n}\n.glyphicon-th:before {\n content: \"\\e011\";\n}\n.glyphicon-th-list:before {\n content: \"\\e012\";\n}\n.glyphicon-ok:before {\n content: \"\\e013\";\n}\n.glyphicon-remove:before {\n content: \"\\e014\";\n}\n.glyphicon-zoom-in:before {\n content: \"\\e015\";\n}\n.glyphicon-zoom-out:before {\n content: \"\\e016\";\n}\n.glyphicon-off:before {\n content: \"\\e017\";\n}\n.glyphicon-signal:before {\n content: \"\\e018\";\n}\n.glyphicon-cog:before {\n content: \"\\e019\";\n}\n.glyphicon-trash:before {\n content: \"\\e020\";\n}\n.glyphicon-home:before {\n content: \"\\e021\";\n}\n.glyphicon-file:before {\n content: \"\\e022\";\n}\n.glyphicon-time:before {\n content: \"\\e023\";\n}\n.glyphicon-road:before {\n content: \"\\e024\";\n}\n.glyphicon-download-alt:before {\n content: \"\\e025\";\n}\n.glyphicon-download:before {\n content: \"\\e026\";\n}\n.glyphicon-upload:before {\n content: \"\\e027\";\n}\n.glyphicon-inbox:before {\n content: \"\\e028\";\n}\n.glyphicon-play-circle:before {\n content: \"\\e029\";\n}\n.glyphicon-repeat:before {\n content: \"\\e030\";\n}\n.glyphicon-refresh:before {\n content: \"\\e031\";\n}\n.glyphicon-list-alt:before {\n content: \"\\e032\";\n}\n.glyphicon-lock:before {\n content: \"\\e033\";\n}\n.glyphicon-flag:before {\n content: \"\\e034\";\n}\n.glyphicon-headphones:before {\n content: \"\\e035\";\n}\n.glyphicon-volume-off:before {\n content: \"\\e036\";\n}\n.glyphicon-volume-down:before {\n content: \"\\e037\";\n}\n.glyphicon-volume-up:before {\n content: \"\\e038\";\n}\n.glyphicon-qrcode:before {\n content: \"\\e039\";\n}\n.glyphicon-barcode:before {\n content: \"\\e040\";\n}\n.glyphicon-tag:before {\n content: \"\\e041\";\n}\n.glyphicon-tags:before {\n content: \"\\e042\";\n}\n.glyphicon-book:before {\n content: \"\\e043\";\n}\n.glyphicon-bookmark:before {\n content: \"\\e044\";\n}\n.glyphicon-print:before {\n content: \"\\e045\";\n}\n.glyphicon-camera:before {\n content: \"\\e046\";\n}\n.glyphicon-font:before {\n content: \"\\e047\";\n}\n.glyphicon-bold:before {\n content: \"\\e048\";\n}\n.glyphicon-italic:before {\n content: \"\\e049\";\n}\n.glyphicon-text-height:before {\n content: \"\\e050\";\n}\n.glyphicon-text-width:before {\n content: \"\\e051\";\n}\n.glyphicon-align-left:before {\n content: \"\\e052\";\n}\n.glyphicon-align-center:before {\n content: \"\\e053\";\n}\n.glyphicon-align-right:before {\n content: \"\\e054\";\n}\n.glyphicon-align-justify:before {\n content: \"\\e055\";\n}\n.glyphicon-list:before {\n content: \"\\e056\";\n}\n.glyphicon-indent-left:before {\n content: \"\\e057\";\n}\n.glyphicon-indent-right:before {\n content: \"\\e058\";\n}\n.glyphicon-facetime-video:before {\n content: \"\\e059\";\n}\n.glyphicon-picture:before {\n content: \"\\e060\";\n}\n.glyphicon-map-marker:before {\n content: \"\\e062\";\n}\n.glyphicon-adjust:before {\n content: \"\\e063\";\n}\n.glyphicon-tint:before {\n content: \"\\e064\";\n}\n.glyphicon-edit:before {\n content: \"\\e065\";\n}\n.glyphicon-share:before {\n content: \"\\e066\";\n}\n.glyphicon-check:before {\n content: \"\\e067\";\n}\n.glyphicon-move:before {\n content: \"\\e068\";\n}\n.glyphicon-step-backward:before {\n content: \"\\e069\";\n}\n.glyphicon-fast-backward:before {\n content: \"\\e070\";\n}\n.glyphicon-backward:before {\n content: \"\\e071\";\n}\n.glyphicon-play:before {\n content: \"\\e072\";\n}\n.glyphicon-pause:before {\n content: \"\\e073\";\n}\n.glyphicon-stop:before {\n content: \"\\e074\";\n}\n.glyphicon-forward:before {\n content: \"\\e075\";\n}\n.glyphicon-fast-forward:before {\n content: \"\\e076\";\n}\n.glyphicon-step-forward:before {\n content: \"\\e077\";\n}\n.glyphicon-eject:before {\n content: \"\\e078\";\n}\n.glyphicon-chevron-left:before {\n content: \"\\e079\";\n}\n.glyphicon-chevron-right:before {\n content: \"\\e080\";\n}\n.glyphicon-plus-sign:before {\n content: \"\\e081\";\n}\n.glyphicon-minus-sign:before {\n content: \"\\e082\";\n}\n.glyphicon-remove-sign:before {\n content: \"\\e083\";\n}\n.glyphicon-ok-sign:before {\n content: \"\\e084\";\n}\n.glyphicon-question-sign:before {\n content: \"\\e085\";\n}\n.glyphicon-info-sign:before {\n content: \"\\e086\";\n}\n.glyphicon-screenshot:before {\n content: \"\\e087\";\n}\n.glyphicon-remove-circle:before {\n content: \"\\e088\";\n}\n.glyphicon-ok-circle:before {\n content: \"\\e089\";\n}\n.glyphicon-ban-circle:before {\n content: \"\\e090\";\n}\n.glyphicon-arrow-left:before {\n content: \"\\e091\";\n}\n.glyphicon-arrow-right:before {\n content: \"\\e092\";\n}\n.glyphicon-arrow-up:before {\n content: \"\\e093\";\n}\n.glyphicon-arrow-down:before {\n content: \"\\e094\";\n}\n.glyphicon-share-alt:before {\n content: \"\\e095\";\n}\n.glyphicon-resize-full:before {\n content: \"\\e096\";\n}\n.glyphicon-resize-small:before {\n content: \"\\e097\";\n}\n.glyphicon-exclamation-sign:before {\n content: \"\\e101\";\n}\n.glyphicon-gift:before {\n content: \"\\e102\";\n}\n.glyphicon-leaf:before {\n content: \"\\e103\";\n}\n.glyphicon-fire:before {\n content: \"\\e104\";\n}\n.glyphicon-eye-open:before {\n content: \"\\e105\";\n}\n.glyphicon-eye-close:before {\n content: \"\\e106\";\n}\n.glyphicon-warning-sign:before {\n content: \"\\e107\";\n}\n.glyphicon-plane:before {\n content: \"\\e108\";\n}\n.glyphicon-calendar:before {\n content: \"\\e109\";\n}\n.glyphicon-random:before {\n content: \"\\e110\";\n}\n.glyphicon-comment:before {\n content: \"\\e111\";\n}\n.glyphicon-magnet:before {\n content: \"\\e112\";\n}\n.glyphicon-chevron-up:before {\n content: \"\\e113\";\n}\n.glyphicon-chevron-down:before {\n content: \"\\e114\";\n}\n.glyphicon-retweet:before {\n content: \"\\e115\";\n}\n.glyphicon-shopping-cart:before {\n content: \"\\e116\";\n}\n.glyphicon-folder-close:before {\n content: \"\\e117\";\n}\n.glyphicon-folder-open:before {\n content: \"\\e118\";\n}\n.glyphicon-resize-vertical:before {\n content: \"\\e119\";\n}\n.glyphicon-resize-horizontal:before {\n content: \"\\e120\";\n}\n.glyphicon-hdd:before {\n content: \"\\e121\";\n}\n.glyphicon-bullhorn:before {\n content: \"\\e122\";\n}\n.glyphicon-bell:before {\n content: \"\\e123\";\n}\n.glyphicon-certificate:before {\n content: \"\\e124\";\n}\n.glyphicon-thumbs-up:before {\n content: \"\\e125\";\n}\n.glyphicon-thumbs-down:before {\n content: \"\\e126\";\n}\n.glyphicon-hand-right:before {\n content: \"\\e127\";\n}\n.glyphicon-hand-left:before {\n content: \"\\e128\";\n}\n.glyphicon-hand-up:before {\n content: \"\\e129\";\n}\n.glyphicon-hand-down:before {\n content: \"\\e130\";\n}\n.glyphicon-circle-arrow-right:before {\n content: \"\\e131\";\n}\n.glyphicon-circle-arrow-left:before {\n content: \"\\e132\";\n}\n.glyphicon-circle-arrow-up:before {\n content: \"\\e133\";\n}\n.glyphicon-circle-arrow-down:before {\n content: \"\\e134\";\n}\n.glyphicon-globe:before {\n content: \"\\e135\";\n}\n.glyphicon-wrench:before {\n content: \"\\e136\";\n}\n.glyphicon-tasks:before {\n content: \"\\e137\";\n}\n.glyphicon-filter:before {\n content: \"\\e138\";\n}\n.glyphicon-briefcase:before {\n content: \"\\e139\";\n}\n.glyphicon-fullscreen:before {\n content: \"\\e140\";\n}\n.glyphicon-dashboard:before {\n content: \"\\e141\";\n}\n.glyphicon-paperclip:before {\n content: \"\\e142\";\n}\n.glyphicon-heart-empty:before {\n content: \"\\e143\";\n}\n.glyphicon-link:before {\n content: \"\\e144\";\n}\n.glyphicon-phone:before {\n content: \"\\e145\";\n}\n.glyphicon-pushpin:before {\n content: \"\\e146\";\n}\n.glyphicon-usd:before {\n content: \"\\e148\";\n}\n.glyphicon-gbp:before {\n content: \"\\e149\";\n}\n.glyphicon-sort:before {\n content: \"\\e150\";\n}\n.glyphicon-sort-by-alphabet:before {\n content: \"\\e151\";\n}\n.glyphicon-sort-by-alphabet-alt:before {\n content: \"\\e152\";\n}\n.glyphicon-sort-by-order:before {\n content: \"\\e153\";\n}\n.glyphicon-sort-by-order-alt:before {\n content: \"\\e154\";\n}\n.glyphicon-sort-by-attributes:before {\n content: \"\\e155\";\n}\n.glyphicon-sort-by-attributes-alt:before {\n content: \"\\e156\";\n}\n.glyphicon-unchecked:before {\n content: \"\\e157\";\n}\n.glyphicon-expand:before {\n content: \"\\e158\";\n}\n.glyphicon-collapse-down:before {\n content: \"\\e159\";\n}\n.glyphicon-collapse-up:before {\n content: \"\\e160\";\n}\n.glyphicon-log-in:before {\n content: \"\\e161\";\n}\n.glyphicon-flash:before {\n content: \"\\e162\";\n}\n.glyphicon-log-out:before {\n content: \"\\e163\";\n}\n.glyphicon-new-window:before {\n content: \"\\e164\";\n}\n.glyphicon-record:before {\n content: \"\\e165\";\n}\n.glyphicon-save:before {\n content: \"\\e166\";\n}\n.glyphicon-open:before {\n content: \"\\e167\";\n}\n.glyphicon-saved:before {\n content: \"\\e168\";\n}\n.glyphicon-import:before {\n content: \"\\e169\";\n}\n.glyphicon-export:before {\n content: \"\\e170\";\n}\n.glyphicon-send:before {\n content: \"\\e171\";\n}\n.glyphicon-floppy-disk:before {\n content: \"\\e172\";\n}\n.glyphicon-floppy-saved:before {\n content: \"\\e173\";\n}\n.glyphicon-floppy-remove:before {\n content: \"\\e174\";\n}\n.glyphicon-floppy-save:before {\n content: \"\\e175\";\n}\n.glyphicon-floppy-open:before {\n content: \"\\e176\";\n}\n.glyphicon-credit-card:before {\n content: \"\\e177\";\n}\n.glyphicon-transfer:before {\n content: \"\\e178\";\n}\n.glyphicon-cutlery:before {\n content: \"\\e179\";\n}\n.glyphicon-header:before {\n content: \"\\e180\";\n}\n.glyphicon-compressed:before {\n content: \"\\e181\";\n}\n.glyphicon-earphone:before {\n content: \"\\e182\";\n}\n.glyphicon-phone-alt:before {\n content: \"\\e183\";\n}\n.glyphicon-tower:before {\n content: \"\\e184\";\n}\n.glyphicon-stats:before {\n content: \"\\e185\";\n}\n.glyphicon-sd-video:before {\n content: \"\\e186\";\n}\n.glyphicon-hd-video:before {\n content: \"\\e187\";\n}\n.glyphicon-subtitles:before {\n content: \"\\e188\";\n}\n.glyphicon-sound-stereo:before {\n content: \"\\e189\";\n}\n.glyphicon-sound-dolby:before {\n content: \"\\e190\";\n}\n.glyphicon-sound-5-1:before {\n content: \"\\e191\";\n}\n.glyphicon-sound-6-1:before {\n content: \"\\e192\";\n}\n.glyphicon-sound-7-1:before {\n content: \"\\e193\";\n}\n.glyphicon-copyright-mark:before {\n content: \"\\e194\";\n}\n.glyphicon-registration-mark:before {\n content: \"\\e195\";\n}\n.glyphicon-cloud-download:before {\n content: \"\\e197\";\n}\n.glyphicon-cloud-upload:before {\n content: \"\\e198\";\n}\n.glyphicon-tree-conifer:before {\n content: \"\\e199\";\n}\n.glyphicon-tree-deciduous:before {\n content: \"\\e200\";\n}\n.glyphicon-cd:before {\n content: \"\\e201\";\n}\n.glyphicon-save-file:before {\n content: \"\\e202\";\n}\n.glyphicon-open-file:before {\n content: \"\\e203\";\n}\n.glyphicon-level-up:before {\n content: \"\\e204\";\n}\n.glyphicon-copy:before {\n content: \"\\e205\";\n}\n.glyphicon-paste:before {\n content: \"\\e206\";\n}\n.glyphicon-alert:before {\n content: \"\\e209\";\n}\n.glyphicon-equalizer:before {\n content: \"\\e210\";\n}\n.glyphicon-king:before {\n content: \"\\e211\";\n}\n.glyphicon-queen:before {\n content: \"\\e212\";\n}\n.glyphicon-pawn:before {\n content: \"\\e213\";\n}\n.glyphicon-bishop:before {\n content: \"\\e214\";\n}\n.glyphicon-knight:before {\n content: \"\\e215\";\n}\n.glyphicon-baby-formula:before {\n content: \"\\e216\";\n}\n.glyphicon-tent:before {\n content: \"\\26fa\";\n}\n.glyphicon-blackboard:before {\n content: \"\\e218\";\n}\n.glyphicon-bed:before {\n content: \"\\e219\";\n}\n.glyphicon-apple:before {\n content: \"\\f8ff\";\n}\n.glyphicon-erase:before {\n content: \"\\e221\";\n}\n.glyphicon-hourglass:before {\n content: \"\\231b\";\n}\n.glyphicon-lamp:before {\n content: \"\\e223\";\n}\n.glyphicon-duplicate:before {\n content: \"\\e224\";\n}\n.glyphicon-piggy-bank:before {\n content: \"\\e225\";\n}\n.glyphicon-scissors:before {\n content: \"\\e226\";\n}\n.glyphicon-bitcoin:before {\n content: \"\\e227\";\n}\n.glyphicon-btc:before {\n content: \"\\e227\";\n}\n.glyphicon-xbt:before {\n content: \"\\e227\";\n}\n.glyphicon-yen:before {\n content: \"\\00a5\";\n}\n.glyphicon-jpy:before {\n content: \"\\00a5\";\n}\n.glyphicon-ruble:before {\n content: \"\\20bd\";\n}\n.glyphicon-rub:before {\n content: \"\\20bd\";\n}\n.glyphicon-scale:before {\n content: \"\\e230\";\n}\n.glyphicon-ice-lolly:before {\n content: \"\\e231\";\n}\n.glyphicon-ice-lolly-tasted:before {\n content: \"\\e232\";\n}\n.glyphicon-education:before {\n content: \"\\e233\";\n}\n.glyphicon-option-horizontal:before {\n content: \"\\e234\";\n}\n.glyphicon-option-vertical:before {\n content: \"\\e235\";\n}\n.glyphicon-menu-hamburger:before {\n content: \"\\e236\";\n}\n.glyphicon-modal-window:before {\n content: \"\\e237\";\n}\n.glyphicon-oil:before {\n content: \"\\e238\";\n}\n.glyphicon-grain:before {\n content: \"\\e239\";\n}\n.glyphicon-sunglasses:before {\n content: \"\\e240\";\n}\n.glyphicon-text-size:before {\n content: \"\\e241\";\n}\n.glyphicon-text-color:before {\n content: \"\\e242\";\n}\n.glyphicon-text-background:before {\n content: \"\\e243\";\n}\n.glyphicon-object-align-top:before {\n content: \"\\e244\";\n}\n.glyphicon-object-align-bottom:before {\n content: \"\\e245\";\n}\n.glyphicon-object-align-horizontal:before {\n content: \"\\e246\";\n}\n.glyphicon-object-align-left:before {\n content: \"\\e247\";\n}\n.glyphicon-object-align-vertical:before {\n content: \"\\e248\";\n}\n.glyphicon-object-align-right:before {\n content: \"\\e249\";\n}\n.glyphicon-triangle-right:before {\n content: \"\\e250\";\n}\n.glyphicon-triangle-left:before {\n content: \"\\e251\";\n}\n.glyphicon-triangle-bottom:before {\n content: \"\\e252\";\n}\n.glyphicon-triangle-top:before {\n content: \"\\e253\";\n}\n.glyphicon-console:before {\n content: \"\\e254\";\n}\n.glyphicon-superscript:before {\n content: \"\\e255\";\n}\n.glyphicon-subscript:before {\n content: \"\\e256\";\n}\n.glyphicon-menu-left:before {\n content: \"\\e257\";\n}\n.glyphicon-menu-right:before {\n content: \"\\e258\";\n}\n.glyphicon-menu-down:before {\n content: \"\\e259\";\n}\n.glyphicon-menu-up:before {\n content: \"\\e260\";\n}\n* {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n*:before,\n*:after {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\nbody {\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 14px;\n line-height: 1.42857143;\n color: #333333;\n background-color: #fff;\n}\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\na {\n color: #337ab7;\n text-decoration: none;\n}\na:hover,\na:focus {\n color: #23527c;\n text-decoration: underline;\n}\na:focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\nfigure {\n margin: 0;\n}\nimg {\n vertical-align: middle;\n}\n.img-responsive,\n.thumbnail > img,\n.thumbnail a > img,\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n display: block;\n max-width: 100%;\n height: auto;\n}\n.img-rounded {\n border-radius: 6px;\n}\n.img-thumbnail {\n padding: 4px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: all 0.2s ease-in-out;\n -o-transition: all 0.2s ease-in-out;\n transition: all 0.2s ease-in-out;\n display: inline-block;\n max-width: 100%;\n height: auto;\n}\n.img-circle {\n border-radius: 50%;\n}\nhr {\n margin-top: 20px;\n margin-bottom: 20px;\n border: 0;\n border-top: 1px solid #eeeeee;\n}\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n}\n.sr-only-focusable:active,\n.sr-only-focusable:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n}\n[role=\"button\"] {\n cursor: pointer;\n}\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n font-family: inherit;\n font-weight: 500;\n line-height: 1.1;\n color: inherit;\n}\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small,\n.h1 small,\n.h2 small,\n.h3 small,\n.h4 small,\n.h5 small,\n.h6 small,\nh1 .small,\nh2 .small,\nh3 .small,\nh4 .small,\nh5 .small,\nh6 .small,\n.h1 .small,\n.h2 .small,\n.h3 .small,\n.h4 .small,\n.h5 .small,\n.h6 .small {\n font-weight: normal;\n line-height: 1;\n color: #777777;\n}\nh1,\n.h1,\nh2,\n.h2,\nh3,\n.h3 {\n margin-top: 20px;\n margin-bottom: 10px;\n}\nh1 small,\n.h1 small,\nh2 small,\n.h2 small,\nh3 small,\n.h3 small,\nh1 .small,\n.h1 .small,\nh2 .small,\n.h2 .small,\nh3 .small,\n.h3 .small {\n font-size: 65%;\n}\nh4,\n.h4,\nh5,\n.h5,\nh6,\n.h6 {\n margin-top: 10px;\n margin-bottom: 10px;\n}\nh4 small,\n.h4 small,\nh5 small,\n.h5 small,\nh6 small,\n.h6 small,\nh4 .small,\n.h4 .small,\nh5 .small,\n.h5 .small,\nh6 .small,\n.h6 .small {\n font-size: 75%;\n}\nh1,\n.h1 {\n font-size: 36px;\n}\nh2,\n.h2 {\n font-size: 30px;\n}\nh3,\n.h3 {\n font-size: 24px;\n}\nh4,\n.h4 {\n font-size: 18px;\n}\nh5,\n.h5 {\n font-size: 14px;\n}\nh6,\n.h6 {\n font-size: 12px;\n}\np {\n margin: 0 0 10px;\n}\n.lead {\n margin-bottom: 20px;\n font-size: 16px;\n font-weight: 300;\n line-height: 1.4;\n}\n@media (min-width: 768px) {\n .lead {\n font-size: 21px;\n }\n}\nsmall,\n.small {\n font-size: 85%;\n}\nmark,\n.mark {\n background-color: #fcf8e3;\n padding: .2em;\n}\n.text-left {\n text-align: left;\n}\n.text-right {\n text-align: right;\n}\n.text-center {\n text-align: center;\n}\n.text-justify {\n text-align: justify;\n}\n.text-nowrap {\n white-space: nowrap;\n}\n.text-lowercase {\n text-transform: lowercase;\n}\n.text-uppercase {\n text-transform: uppercase;\n}\n.text-capitalize {\n text-transform: capitalize;\n}\n.text-muted {\n color: #777777;\n}\n.text-primary {\n color: #337ab7;\n}\na.text-primary:hover,\na.text-primary:focus {\n color: #286090;\n}\n.text-success {\n color: #3c763d;\n}\na.text-success:hover,\na.text-success:focus {\n color: #2b542c;\n}\n.text-info {\n color: #31708f;\n}\na.text-info:hover,\na.text-info:focus {\n color: #245269;\n}\n.text-warning {\n color: #8a6d3b;\n}\na.text-warning:hover,\na.text-warning:focus {\n color: #66512c;\n}\n.text-danger {\n color: #a94442;\n}\na.text-danger:hover,\na.text-danger:focus {\n color: #843534;\n}\n.bg-primary {\n color: #fff;\n background-color: #337ab7;\n}\na.bg-primary:hover,\na.bg-primary:focus {\n background-color: #286090;\n}\n.bg-success {\n background-color: #dff0d8;\n}\na.bg-success:hover,\na.bg-success:focus {\n background-color: #c1e2b3;\n}\n.bg-info {\n background-color: #d9edf7;\n}\na.bg-info:hover,\na.bg-info:focus {\n background-color: #afd9ee;\n}\n.bg-warning {\n background-color: #fcf8e3;\n}\na.bg-warning:hover,\na.bg-warning:focus {\n background-color: #f7ecb5;\n}\n.bg-danger {\n background-color: #f2dede;\n}\na.bg-danger:hover,\na.bg-danger:focus {\n background-color: #e4b9b9;\n}\n.page-header {\n padding-bottom: 9px;\n margin: 40px 0 20px;\n border-bottom: 1px solid #eeeeee;\n}\nul,\nol {\n margin-top: 0;\n margin-bottom: 10px;\n}\nul ul,\nol ul,\nul ol,\nol ol {\n margin-bottom: 0;\n}\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n.list-inline {\n padding-left: 0;\n list-style: none;\n margin-left: -5px;\n}\n.list-inline > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n}\ndl {\n margin-top: 0;\n margin-bottom: 20px;\n}\ndt,\ndd {\n line-height: 1.42857143;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0;\n}\n@media (min-width: 768px) {\n .dl-horizontal dt {\n float: left;\n width: 160px;\n clear: left;\n text-align: right;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .dl-horizontal dd {\n margin-left: 180px;\n }\n}\nabbr[title],\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted #777777;\n}\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\nblockquote {\n padding: 10px 20px;\n margin: 0 0 20px;\n font-size: 17.5px;\n border-left: 5px solid #eeeeee;\n}\nblockquote p:last-child,\nblockquote ul:last-child,\nblockquote ol:last-child {\n margin-bottom: 0;\n}\nblockquote footer,\nblockquote small,\nblockquote .small {\n display: block;\n font-size: 80%;\n line-height: 1.42857143;\n color: #777777;\n}\nblockquote footer:before,\nblockquote small:before,\nblockquote .small:before {\n content: '\\2014 \\00A0';\n}\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid #eeeeee;\n border-left: 0;\n text-align: right;\n}\n.blockquote-reverse footer:before,\nblockquote.pull-right footer:before,\n.blockquote-reverse small:before,\nblockquote.pull-right small:before,\n.blockquote-reverse .small:before,\nblockquote.pull-right .small:before {\n content: '';\n}\n.blockquote-reverse footer:after,\nblockquote.pull-right footer:after,\n.blockquote-reverse small:after,\nblockquote.pull-right small:after,\n.blockquote-reverse .small:after,\nblockquote.pull-right .small:after {\n content: '\\00A0 \\2014';\n}\naddress {\n margin-bottom: 20px;\n font-style: normal;\n line-height: 1.42857143;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: Menlo, Monaco, Consolas, \"Courier New\", monospace;\n}\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: #c7254e;\n background-color: #f9f2f4;\n border-radius: 4px;\n}\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: #fff;\n background-color: #333;\n border-radius: 3px;\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\nkbd kbd {\n padding: 0;\n font-size: 100%;\n font-weight: bold;\n box-shadow: none;\n}\npre {\n display: block;\n padding: 9.5px;\n margin: 0 0 10px;\n font-size: 13px;\n line-height: 1.42857143;\n word-break: break-all;\n word-wrap: break-word;\n color: #333333;\n background-color: #f5f5f5;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\npre code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n}\n.pre-scrollable {\n max-height: 340px;\n overflow-y: scroll;\n}\n.container {\n margin-right: auto;\n margin-left: auto;\n padding-left: 15px;\n padding-right: 15px;\n}\n@media (min-width: 768px) {\n .container {\n width: 750px;\n }\n}\n@media (min-width: 992px) {\n .container {\n width: 970px;\n }\n}\n@media (min-width: 1200px) {\n .container {\n width: 1170px;\n }\n}\n.container-fluid {\n margin-right: auto;\n margin-left: auto;\n padding-left: 15px;\n padding-right: 15px;\n}\n.row {\n margin-left: -15px;\n margin-right: -15px;\n}\n.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {\n position: relative;\n min-height: 1px;\n padding-left: 15px;\n padding-right: 15px;\n}\n.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {\n float: left;\n}\n.col-xs-12 {\n width: 100%;\n}\n.col-xs-11 {\n width: 91.66666667%;\n}\n.col-xs-10 {\n width: 83.33333333%;\n}\n.col-xs-9 {\n width: 75%;\n}\n.col-xs-8 {\n width: 66.66666667%;\n}\n.col-xs-7 {\n width: 58.33333333%;\n}\n.col-xs-6 {\n width: 50%;\n}\n.col-xs-5 {\n width: 41.66666667%;\n}\n.col-xs-4 {\n width: 33.33333333%;\n}\n.col-xs-3 {\n width: 25%;\n}\n.col-xs-2 {\n width: 16.66666667%;\n}\n.col-xs-1 {\n width: 8.33333333%;\n}\n.col-xs-pull-12 {\n right: 100%;\n}\n.col-xs-pull-11 {\n right: 91.66666667%;\n}\n.col-xs-pull-10 {\n right: 83.33333333%;\n}\n.col-xs-pull-9 {\n right: 75%;\n}\n.col-xs-pull-8 {\n right: 66.66666667%;\n}\n.col-xs-pull-7 {\n right: 58.33333333%;\n}\n.col-xs-pull-6 {\n right: 50%;\n}\n.col-xs-pull-5 {\n right: 41.66666667%;\n}\n.col-xs-pull-4 {\n right: 33.33333333%;\n}\n.col-xs-pull-3 {\n right: 25%;\n}\n.col-xs-pull-2 {\n right: 16.66666667%;\n}\n.col-xs-pull-1 {\n right: 8.33333333%;\n}\n.col-xs-pull-0 {\n right: auto;\n}\n.col-xs-push-12 {\n left: 100%;\n}\n.col-xs-push-11 {\n left: 91.66666667%;\n}\n.col-xs-push-10 {\n left: 83.33333333%;\n}\n.col-xs-push-9 {\n left: 75%;\n}\n.col-xs-push-8 {\n left: 66.66666667%;\n}\n.col-xs-push-7 {\n left: 58.33333333%;\n}\n.col-xs-push-6 {\n left: 50%;\n}\n.col-xs-push-5 {\n left: 41.66666667%;\n}\n.col-xs-push-4 {\n left: 33.33333333%;\n}\n.col-xs-push-3 {\n left: 25%;\n}\n.col-xs-push-2 {\n left: 16.66666667%;\n}\n.col-xs-push-1 {\n left: 8.33333333%;\n}\n.col-xs-push-0 {\n left: auto;\n}\n.col-xs-offset-12 {\n margin-left: 100%;\n}\n.col-xs-offset-11 {\n margin-left: 91.66666667%;\n}\n.col-xs-offset-10 {\n margin-left: 83.33333333%;\n}\n.col-xs-offset-9 {\n margin-left: 75%;\n}\n.col-xs-offset-8 {\n margin-left: 66.66666667%;\n}\n.col-xs-offset-7 {\n margin-left: 58.33333333%;\n}\n.col-xs-offset-6 {\n margin-left: 50%;\n}\n.col-xs-offset-5 {\n margin-left: 41.66666667%;\n}\n.col-xs-offset-4 {\n margin-left: 33.33333333%;\n}\n.col-xs-offset-3 {\n margin-left: 25%;\n}\n.col-xs-offset-2 {\n margin-left: 16.66666667%;\n}\n.col-xs-offset-1 {\n margin-left: 8.33333333%;\n}\n.col-xs-offset-0 {\n margin-left: 0%;\n}\n@media (min-width: 768px) {\n .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {\n float: left;\n }\n .col-sm-12 {\n width: 100%;\n }\n .col-sm-11 {\n width: 91.66666667%;\n }\n .col-sm-10 {\n width: 83.33333333%;\n }\n .col-sm-9 {\n width: 75%;\n }\n .col-sm-8 {\n width: 66.66666667%;\n }\n .col-sm-7 {\n width: 58.33333333%;\n }\n .col-sm-6 {\n width: 50%;\n }\n .col-sm-5 {\n width: 41.66666667%;\n }\n .col-sm-4 {\n width: 33.33333333%;\n }\n .col-sm-3 {\n width: 25%;\n }\n .col-sm-2 {\n width: 16.66666667%;\n }\n .col-sm-1 {\n width: 8.33333333%;\n }\n .col-sm-pull-12 {\n right: 100%;\n }\n .col-sm-pull-11 {\n right: 91.66666667%;\n }\n .col-sm-pull-10 {\n right: 83.33333333%;\n }\n .col-sm-pull-9 {\n right: 75%;\n }\n .col-sm-pull-8 {\n right: 66.66666667%;\n }\n .col-sm-pull-7 {\n right: 58.33333333%;\n }\n .col-sm-pull-6 {\n right: 50%;\n }\n .col-sm-pull-5 {\n right: 41.66666667%;\n }\n .col-sm-pull-4 {\n right: 33.33333333%;\n }\n .col-sm-pull-3 {\n right: 25%;\n }\n .col-sm-pull-2 {\n right: 16.66666667%;\n }\n .col-sm-pull-1 {\n right: 8.33333333%;\n }\n .col-sm-pull-0 {\n right: auto;\n }\n .col-sm-push-12 {\n left: 100%;\n }\n .col-sm-push-11 {\n left: 91.66666667%;\n }\n .col-sm-push-10 {\n left: 83.33333333%;\n }\n .col-sm-push-9 {\n left: 75%;\n }\n .col-sm-push-8 {\n left: 66.66666667%;\n }\n .col-sm-push-7 {\n left: 58.33333333%;\n }\n .col-sm-push-6 {\n left: 50%;\n }\n .col-sm-push-5 {\n left: 41.66666667%;\n }\n .col-sm-push-4 {\n left: 33.33333333%;\n }\n .col-sm-push-3 {\n left: 25%;\n }\n .col-sm-push-2 {\n left: 16.66666667%;\n }\n .col-sm-push-1 {\n left: 8.33333333%;\n }\n .col-sm-push-0 {\n left: auto;\n }\n .col-sm-offset-12 {\n margin-left: 100%;\n }\n .col-sm-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-sm-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-sm-offset-9 {\n margin-left: 75%;\n }\n .col-sm-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-sm-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-sm-offset-6 {\n margin-left: 50%;\n }\n .col-sm-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-sm-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-sm-offset-3 {\n margin-left: 25%;\n }\n .col-sm-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-sm-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-sm-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 992px) {\n .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {\n float: left;\n }\n .col-md-12 {\n width: 100%;\n }\n .col-md-11 {\n width: 91.66666667%;\n }\n .col-md-10 {\n width: 83.33333333%;\n }\n .col-md-9 {\n width: 75%;\n }\n .col-md-8 {\n width: 66.66666667%;\n }\n .col-md-7 {\n width: 58.33333333%;\n }\n .col-md-6 {\n width: 50%;\n }\n .col-md-5 {\n width: 41.66666667%;\n }\n .col-md-4 {\n width: 33.33333333%;\n }\n .col-md-3 {\n width: 25%;\n }\n .col-md-2 {\n width: 16.66666667%;\n }\n .col-md-1 {\n width: 8.33333333%;\n }\n .col-md-pull-12 {\n right: 100%;\n }\n .col-md-pull-11 {\n right: 91.66666667%;\n }\n .col-md-pull-10 {\n right: 83.33333333%;\n }\n .col-md-pull-9 {\n right: 75%;\n }\n .col-md-pull-8 {\n right: 66.66666667%;\n }\n .col-md-pull-7 {\n right: 58.33333333%;\n }\n .col-md-pull-6 {\n right: 50%;\n }\n .col-md-pull-5 {\n right: 41.66666667%;\n }\n .col-md-pull-4 {\n right: 33.33333333%;\n }\n .col-md-pull-3 {\n right: 25%;\n }\n .col-md-pull-2 {\n right: 16.66666667%;\n }\n .col-md-pull-1 {\n right: 8.33333333%;\n }\n .col-md-pull-0 {\n right: auto;\n }\n .col-md-push-12 {\n left: 100%;\n }\n .col-md-push-11 {\n left: 91.66666667%;\n }\n .col-md-push-10 {\n left: 83.33333333%;\n }\n .col-md-push-9 {\n left: 75%;\n }\n .col-md-push-8 {\n left: 66.66666667%;\n }\n .col-md-push-7 {\n left: 58.33333333%;\n }\n .col-md-push-6 {\n left: 50%;\n }\n .col-md-push-5 {\n left: 41.66666667%;\n }\n .col-md-push-4 {\n left: 33.33333333%;\n }\n .col-md-push-3 {\n left: 25%;\n }\n .col-md-push-2 {\n left: 16.66666667%;\n }\n .col-md-push-1 {\n left: 8.33333333%;\n }\n .col-md-push-0 {\n left: auto;\n }\n .col-md-offset-12 {\n margin-left: 100%;\n }\n .col-md-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-md-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-md-offset-9 {\n margin-left: 75%;\n }\n .col-md-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-md-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-md-offset-6 {\n margin-left: 50%;\n }\n .col-md-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-md-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-md-offset-3 {\n margin-left: 25%;\n }\n .col-md-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-md-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-md-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 1200px) {\n .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {\n float: left;\n }\n .col-lg-12 {\n width: 100%;\n }\n .col-lg-11 {\n width: 91.66666667%;\n }\n .col-lg-10 {\n width: 83.33333333%;\n }\n .col-lg-9 {\n width: 75%;\n }\n .col-lg-8 {\n width: 66.66666667%;\n }\n .col-lg-7 {\n width: 58.33333333%;\n }\n .col-lg-6 {\n width: 50%;\n }\n .col-lg-5 {\n width: 41.66666667%;\n }\n .col-lg-4 {\n width: 33.33333333%;\n }\n .col-lg-3 {\n width: 25%;\n }\n .col-lg-2 {\n width: 16.66666667%;\n }\n .col-lg-1 {\n width: 8.33333333%;\n }\n .col-lg-pull-12 {\n right: 100%;\n }\n .col-lg-pull-11 {\n right: 91.66666667%;\n }\n .col-lg-pull-10 {\n right: 83.33333333%;\n }\n .col-lg-pull-9 {\n right: 75%;\n }\n .col-lg-pull-8 {\n right: 66.66666667%;\n }\n .col-lg-pull-7 {\n right: 58.33333333%;\n }\n .col-lg-pull-6 {\n right: 50%;\n }\n .col-lg-pull-5 {\n right: 41.66666667%;\n }\n .col-lg-pull-4 {\n right: 33.33333333%;\n }\n .col-lg-pull-3 {\n right: 25%;\n }\n .col-lg-pull-2 {\n right: 16.66666667%;\n }\n .col-lg-pull-1 {\n right: 8.33333333%;\n }\n .col-lg-pull-0 {\n right: auto;\n }\n .col-lg-push-12 {\n left: 100%;\n }\n .col-lg-push-11 {\n left: 91.66666667%;\n }\n .col-lg-push-10 {\n left: 83.33333333%;\n }\n .col-lg-push-9 {\n left: 75%;\n }\n .col-lg-push-8 {\n left: 66.66666667%;\n }\n .col-lg-push-7 {\n left: 58.33333333%;\n }\n .col-lg-push-6 {\n left: 50%;\n }\n .col-lg-push-5 {\n left: 41.66666667%;\n }\n .col-lg-push-4 {\n left: 33.33333333%;\n }\n .col-lg-push-3 {\n left: 25%;\n }\n .col-lg-push-2 {\n left: 16.66666667%;\n }\n .col-lg-push-1 {\n left: 8.33333333%;\n }\n .col-lg-push-0 {\n left: auto;\n }\n .col-lg-offset-12 {\n margin-left: 100%;\n }\n .col-lg-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-lg-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-lg-offset-9 {\n margin-left: 75%;\n }\n .col-lg-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-lg-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-lg-offset-6 {\n margin-left: 50%;\n }\n .col-lg-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-lg-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-lg-offset-3 {\n margin-left: 25%;\n }\n .col-lg-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-lg-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-lg-offset-0 {\n margin-left: 0%;\n }\n}\ntable {\n background-color: transparent;\n}\ncaption {\n padding-top: 8px;\n padding-bottom: 8px;\n color: #777777;\n text-align: left;\n}\nth {\n text-align: left;\n}\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: 20px;\n}\n.table > thead > tr > th,\n.table > tbody > tr > th,\n.table > tfoot > tr > th,\n.table > thead > tr > td,\n.table > tbody > tr > td,\n.table > tfoot > tr > td {\n padding: 8px;\n line-height: 1.42857143;\n vertical-align: top;\n border-top: 1px solid #ddd;\n}\n.table > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid #ddd;\n}\n.table > caption + thead > tr:first-child > th,\n.table > colgroup + thead > tr:first-child > th,\n.table > thead:first-child > tr:first-child > th,\n.table > caption + thead > tr:first-child > td,\n.table > colgroup + thead > tr:first-child > td,\n.table > thead:first-child > tr:first-child > td {\n border-top: 0;\n}\n.table > tbody + tbody {\n border-top: 2px solid #ddd;\n}\n.table .table {\n background-color: #fff;\n}\n.table-condensed > thead > tr > th,\n.table-condensed > tbody > tr > th,\n.table-condensed > tfoot > tr > th,\n.table-condensed > thead > tr > td,\n.table-condensed > tbody > tr > td,\n.table-condensed > tfoot > tr > td {\n padding: 5px;\n}\n.table-bordered {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > tbody > tr > th,\n.table-bordered > tfoot > tr > th,\n.table-bordered > thead > tr > td,\n.table-bordered > tbody > tr > td,\n.table-bordered > tfoot > tr > td {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > thead > tr > td {\n border-bottom-width: 2px;\n}\n.table-striped > tbody > tr:nth-of-type(odd) {\n background-color: #f9f9f9;\n}\n.table-hover > tbody > tr:hover {\n background-color: #f5f5f5;\n}\ntable col[class*=\"col-\"] {\n position: static;\n float: none;\n display: table-column;\n}\ntable td[class*=\"col-\"],\ntable th[class*=\"col-\"] {\n position: static;\n float: none;\n display: table-cell;\n}\n.table > thead > tr > td.active,\n.table > tbody > tr > td.active,\n.table > tfoot > tr > td.active,\n.table > thead > tr > th.active,\n.table > tbody > tr > th.active,\n.table > tfoot > tr > th.active,\n.table > thead > tr.active > td,\n.table > tbody > tr.active > td,\n.table > tfoot > tr.active > td,\n.table > thead > tr.active > th,\n.table > tbody > tr.active > th,\n.table > tfoot > tr.active > th {\n background-color: #f5f5f5;\n}\n.table-hover > tbody > tr > td.active:hover,\n.table-hover > tbody > tr > th.active:hover,\n.table-hover > tbody > tr.active:hover > td,\n.table-hover > tbody > tr:hover > .active,\n.table-hover > tbody > tr.active:hover > th {\n background-color: #e8e8e8;\n}\n.table > thead > tr > td.success,\n.table > tbody > tr > td.success,\n.table > tfoot > tr > td.success,\n.table > thead > tr > th.success,\n.table > tbody > tr > th.success,\n.table > tfoot > tr > th.success,\n.table > thead > tr.success > td,\n.table > tbody > tr.success > td,\n.table > tfoot > tr.success > td,\n.table > thead > tr.success > th,\n.table > tbody > tr.success > th,\n.table > tfoot > tr.success > th {\n background-color: #dff0d8;\n}\n.table-hover > tbody > tr > td.success:hover,\n.table-hover > tbody > tr > th.success:hover,\n.table-hover > tbody > tr.success:hover > td,\n.table-hover > tbody > tr:hover > .success,\n.table-hover > tbody > tr.success:hover > th {\n background-color: #d0e9c6;\n}\n.table > thead > tr > td.info,\n.table > tbody > tr > td.info,\n.table > tfoot > tr > td.info,\n.table > thead > tr > th.info,\n.table > tbody > tr > th.info,\n.table > tfoot > tr > th.info,\n.table > thead > tr.info > td,\n.table > tbody > tr.info > td,\n.table > tfoot > tr.info > td,\n.table > thead > tr.info > th,\n.table > tbody > tr.info > th,\n.table > tfoot > tr.info > th {\n background-color: #d9edf7;\n}\n.table-hover > tbody > tr > td.info:hover,\n.table-hover > tbody > tr > th.info:hover,\n.table-hover > tbody > tr.info:hover > td,\n.table-hover > tbody > tr:hover > .info,\n.table-hover > tbody > tr.info:hover > th {\n background-color: #c4e3f3;\n}\n.table > thead > tr > td.warning,\n.table > tbody > tr > td.warning,\n.table > tfoot > tr > td.warning,\n.table > thead > tr > th.warning,\n.table > tbody > tr > th.warning,\n.table > tfoot > tr > th.warning,\n.table > thead > tr.warning > td,\n.table > tbody > tr.warning > td,\n.table > tfoot > tr.warning > td,\n.table > thead > tr.warning > th,\n.table > tbody > tr.warning > th,\n.table > tfoot > tr.warning > th {\n background-color: #fcf8e3;\n}\n.table-hover > tbody > tr > td.warning:hover,\n.table-hover > tbody > tr > th.warning:hover,\n.table-hover > tbody > tr.warning:hover > td,\n.table-hover > tbody > tr:hover > .warning,\n.table-hover > tbody > tr.warning:hover > th {\n background-color: #faf2cc;\n}\n.table > thead > tr > td.danger,\n.table > tbody > tr > td.danger,\n.table > tfoot > tr > td.danger,\n.table > thead > tr > th.danger,\n.table > tbody > tr > th.danger,\n.table > tfoot > tr > th.danger,\n.table > thead > tr.danger > td,\n.table > tbody > tr.danger > td,\n.table > tfoot > tr.danger > td,\n.table > thead > tr.danger > th,\n.table > tbody > tr.danger > th,\n.table > tfoot > tr.danger > th {\n background-color: #f2dede;\n}\n.table-hover > tbody > tr > td.danger:hover,\n.table-hover > tbody > tr > th.danger:hover,\n.table-hover > tbody > tr.danger:hover > td,\n.table-hover > tbody > tr:hover > .danger,\n.table-hover > tbody > tr.danger:hover > th {\n background-color: #ebcccc;\n}\n.table-responsive {\n overflow-x: auto;\n min-height: 0.01%;\n}\n@media screen and (max-width: 767px) {\n .table-responsive {\n width: 100%;\n margin-bottom: 15px;\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid #ddd;\n }\n .table-responsive > .table {\n margin-bottom: 0;\n }\n .table-responsive > .table > thead > tr > th,\n .table-responsive > .table > tbody > tr > th,\n .table-responsive > .table > tfoot > tr > th,\n .table-responsive > .table > thead > tr > td,\n .table-responsive > .table > tbody > tr > td,\n .table-responsive > .table > tfoot > tr > td {\n white-space: nowrap;\n }\n .table-responsive > .table-bordered {\n border: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:first-child,\n .table-responsive > .table-bordered > tbody > tr > th:first-child,\n .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n .table-responsive > .table-bordered > thead > tr > td:first-child,\n .table-responsive > .table-bordered > tbody > tr > td:first-child,\n .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:last-child,\n .table-responsive > .table-bordered > tbody > tr > th:last-child,\n .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n .table-responsive > .table-bordered > thead > tr > td:last-child,\n .table-responsive > .table-bordered > tbody > tr > td:last-child,\n .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n }\n .table-responsive > .table-bordered > tbody > tr:last-child > th,\n .table-responsive > .table-bordered > tfoot > tr:last-child > th,\n .table-responsive > .table-bordered > tbody > tr:last-child > td,\n .table-responsive > .table-bordered > tfoot > tr:last-child > td {\n border-bottom: 0;\n }\n}\nfieldset {\n padding: 0;\n margin: 0;\n border: 0;\n min-width: 0;\n}\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: 20px;\n font-size: 21px;\n line-height: inherit;\n color: #333333;\n border: 0;\n border-bottom: 1px solid #e5e5e5;\n}\nlabel {\n display: inline-block;\n max-width: 100%;\n margin-bottom: 5px;\n font-weight: bold;\n}\ninput[type=\"search\"] {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9;\n line-height: normal;\n}\ninput[type=\"file\"] {\n display: block;\n}\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\nselect[multiple],\nselect[size] {\n height: auto;\n}\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\noutput {\n display: block;\n padding-top: 7px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n}\n.form-control {\n display: block;\n width: 100%;\n height: 34px;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n background-color: #fff;\n background-image: none;\n border: 1px solid #ccc;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n}\n.form-control:focus {\n border-color: #66afe9;\n outline: 0;\n -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);\n box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);\n}\n.form-control::-moz-placeholder {\n color: #999;\n opacity: 1;\n}\n.form-control:-ms-input-placeholder {\n color: #999;\n}\n.form-control::-webkit-input-placeholder {\n color: #999;\n}\n.form-control::-ms-expand {\n border: 0;\n background-color: transparent;\n}\n.form-control[disabled],\n.form-control[readonly],\nfieldset[disabled] .form-control {\n background-color: #eeeeee;\n opacity: 1;\n}\n.form-control[disabled],\nfieldset[disabled] .form-control {\n cursor: not-allowed;\n}\ntextarea.form-control {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: none;\n}\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n input[type=\"date\"].form-control,\n input[type=\"time\"].form-control,\n input[type=\"datetime-local\"].form-control,\n input[type=\"month\"].form-control {\n line-height: 34px;\n }\n input[type=\"date\"].input-sm,\n input[type=\"time\"].input-sm,\n input[type=\"datetime-local\"].input-sm,\n input[type=\"month\"].input-sm,\n .input-group-sm input[type=\"date\"],\n .input-group-sm input[type=\"time\"],\n .input-group-sm input[type=\"datetime-local\"],\n .input-group-sm input[type=\"month\"] {\n line-height: 30px;\n }\n input[type=\"date\"].input-lg,\n input[type=\"time\"].input-lg,\n input[type=\"datetime-local\"].input-lg,\n input[type=\"month\"].input-lg,\n .input-group-lg input[type=\"date\"],\n .input-group-lg input[type=\"time\"],\n .input-group-lg input[type=\"datetime-local\"],\n .input-group-lg input[type=\"month\"] {\n line-height: 46px;\n }\n}\n.form-group {\n margin-bottom: 15px;\n}\n.radio,\n.checkbox {\n position: relative;\n display: block;\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.radio label,\n.checkbox label {\n min-height: 20px;\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: normal;\n cursor: pointer;\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n position: absolute;\n margin-left: -20px;\n margin-top: 4px \\9;\n}\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px;\n}\n.radio-inline,\n.checkbox-inline {\n position: relative;\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n vertical-align: middle;\n font-weight: normal;\n cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px;\n}\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"].disabled,\ninput[type=\"checkbox\"].disabled,\nfieldset[disabled] input[type=\"radio\"],\nfieldset[disabled] input[type=\"checkbox\"] {\n cursor: not-allowed;\n}\n.radio-inline.disabled,\n.checkbox-inline.disabled,\nfieldset[disabled] .radio-inline,\nfieldset[disabled] .checkbox-inline {\n cursor: not-allowed;\n}\n.radio.disabled label,\n.checkbox.disabled label,\nfieldset[disabled] .radio label,\nfieldset[disabled] .checkbox label {\n cursor: not-allowed;\n}\n.form-control-static {\n padding-top: 7px;\n padding-bottom: 7px;\n margin-bottom: 0;\n min-height: 34px;\n}\n.form-control-static.input-lg,\n.form-control-static.input-sm {\n padding-left: 0;\n padding-right: 0;\n}\n.input-sm {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-sm {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-sm,\nselect[multiple].input-sm {\n height: auto;\n}\n.form-group-sm .form-control {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.form-group-sm select.form-control {\n height: 30px;\n line-height: 30px;\n}\n.form-group-sm textarea.form-control,\n.form-group-sm select[multiple].form-control {\n height: auto;\n}\n.form-group-sm .form-control-static {\n height: 30px;\n min-height: 32px;\n padding: 6px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.input-lg {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-lg {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-lg,\nselect[multiple].input-lg {\n height: auto;\n}\n.form-group-lg .form-control {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.form-group-lg select.form-control {\n height: 46px;\n line-height: 46px;\n}\n.form-group-lg textarea.form-control,\n.form-group-lg select[multiple].form-control {\n height: auto;\n}\n.form-group-lg .form-control-static {\n height: 46px;\n min-height: 38px;\n padding: 11px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.has-feedback {\n position: relative;\n}\n.has-feedback .form-control {\n padding-right: 42.5px;\n}\n.form-control-feedback {\n position: absolute;\n top: 0;\n right: 0;\n z-index: 2;\n display: block;\n width: 34px;\n height: 34px;\n line-height: 34px;\n text-align: center;\n pointer-events: none;\n}\n.input-lg + .form-control-feedback,\n.input-group-lg + .form-control-feedback,\n.form-group-lg .form-control + .form-control-feedback {\n width: 46px;\n height: 46px;\n line-height: 46px;\n}\n.input-sm + .form-control-feedback,\n.input-group-sm + .form-control-feedback,\n.form-group-sm .form-control + .form-control-feedback {\n width: 30px;\n height: 30px;\n line-height: 30px;\n}\n.has-success .help-block,\n.has-success .control-label,\n.has-success .radio,\n.has-success .checkbox,\n.has-success .radio-inline,\n.has-success .checkbox-inline,\n.has-success.radio label,\n.has-success.checkbox label,\n.has-success.radio-inline label,\n.has-success.checkbox-inline label {\n color: #3c763d;\n}\n.has-success .form-control {\n border-color: #3c763d;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-success .form-control:focus {\n border-color: #2b542c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n}\n.has-success .input-group-addon {\n color: #3c763d;\n border-color: #3c763d;\n background-color: #dff0d8;\n}\n.has-success .form-control-feedback {\n color: #3c763d;\n}\n.has-warning .help-block,\n.has-warning .control-label,\n.has-warning .radio,\n.has-warning .checkbox,\n.has-warning .radio-inline,\n.has-warning .checkbox-inline,\n.has-warning.radio label,\n.has-warning.checkbox label,\n.has-warning.radio-inline label,\n.has-warning.checkbox-inline label {\n color: #8a6d3b;\n}\n.has-warning .form-control {\n border-color: #8a6d3b;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-warning .form-control:focus {\n border-color: #66512c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n}\n.has-warning .input-group-addon {\n color: #8a6d3b;\n border-color: #8a6d3b;\n background-color: #fcf8e3;\n}\n.has-warning .form-control-feedback {\n color: #8a6d3b;\n}\n.has-error .help-block,\n.has-error .control-label,\n.has-error .radio,\n.has-error .checkbox,\n.has-error .radio-inline,\n.has-error .checkbox-inline,\n.has-error.radio label,\n.has-error.checkbox label,\n.has-error.radio-inline label,\n.has-error.checkbox-inline label {\n color: #a94442;\n}\n.has-error .form-control {\n border-color: #a94442;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-error .form-control:focus {\n border-color: #843534;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n}\n.has-error .input-group-addon {\n color: #a94442;\n border-color: #a94442;\n background-color: #f2dede;\n}\n.has-error .form-control-feedback {\n color: #a94442;\n}\n.has-feedback label ~ .form-control-feedback {\n top: 25px;\n}\n.has-feedback label.sr-only ~ .form-control-feedback {\n top: 0;\n}\n.help-block {\n display: block;\n margin-top: 5px;\n margin-bottom: 10px;\n color: #737373;\n}\n@media (min-width: 768px) {\n .form-inline .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .form-inline .form-control-static {\n display: inline-block;\n }\n .form-inline .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .form-inline .input-group .input-group-addon,\n .form-inline .input-group .input-group-btn,\n .form-inline .input-group .form-control {\n width: auto;\n }\n .form-inline .input-group > .form-control {\n width: 100%;\n }\n .form-inline .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio,\n .form-inline .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio label,\n .form-inline .checkbox label {\n padding-left: 0;\n }\n .form-inline .radio input[type=\"radio\"],\n .form-inline .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .form-inline .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox,\n.form-horizontal .radio-inline,\n.form-horizontal .checkbox-inline {\n margin-top: 0;\n margin-bottom: 0;\n padding-top: 7px;\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox {\n min-height: 27px;\n}\n.form-horizontal .form-group {\n margin-left: -15px;\n margin-right: -15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .control-label {\n text-align: right;\n margin-bottom: 0;\n padding-top: 7px;\n }\n}\n.form-horizontal .has-feedback .form-control-feedback {\n right: 15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-lg .control-label {\n padding-top: 11px;\n font-size: 18px;\n }\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-sm .control-label {\n padding-top: 6px;\n font-size: 12px;\n }\n}\n.btn {\n display: inline-block;\n margin-bottom: 0;\n font-weight: normal;\n text-align: center;\n vertical-align: middle;\n touch-action: manipulation;\n cursor: pointer;\n background-image: none;\n border: 1px solid transparent;\n white-space: nowrap;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n border-radius: 4px;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n}\n.btn:focus,\n.btn:active:focus,\n.btn.active:focus,\n.btn.focus,\n.btn:active.focus,\n.btn.active.focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n.btn:hover,\n.btn:focus,\n.btn.focus {\n color: #333;\n text-decoration: none;\n}\n.btn:active,\n.btn.active {\n outline: 0;\n background-image: none;\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn.disabled,\n.btn[disabled],\nfieldset[disabled] .btn {\n cursor: not-allowed;\n opacity: 0.65;\n filter: alpha(opacity=65);\n -webkit-box-shadow: none;\n box-shadow: none;\n}\na.btn.disabled,\nfieldset[disabled] a.btn {\n pointer-events: none;\n}\n.btn-default {\n color: #333;\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default:focus,\n.btn-default.focus {\n color: #333;\n background-color: #e6e6e6;\n border-color: #8c8c8c;\n}\n.btn-default:hover {\n color: #333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n color: #333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active:hover,\n.btn-default.active:hover,\n.open > .dropdown-toggle.btn-default:hover,\n.btn-default:active:focus,\n.btn-default.active:focus,\n.open > .dropdown-toggle.btn-default:focus,\n.btn-default:active.focus,\n.btn-default.active.focus,\n.open > .dropdown-toggle.btn-default.focus {\n color: #333;\n background-color: #d4d4d4;\n border-color: #8c8c8c;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n background-image: none;\n}\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus {\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default .badge {\n color: #fff;\n background-color: #333;\n}\n.btn-primary {\n color: #fff;\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary:focus,\n.btn-primary.focus {\n color: #fff;\n background-color: #286090;\n border-color: #122b40;\n}\n.btn-primary:hover {\n color: #fff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n color: #fff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active:hover,\n.btn-primary.active:hover,\n.open > .dropdown-toggle.btn-primary:hover,\n.btn-primary:active:focus,\n.btn-primary.active:focus,\n.open > .dropdown-toggle.btn-primary:focus,\n.btn-primary:active.focus,\n.btn-primary.active.focus,\n.open > .dropdown-toggle.btn-primary.focus {\n color: #fff;\n background-color: #204d74;\n border-color: #122b40;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n background-image: none;\n}\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus {\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.btn-success {\n color: #fff;\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success:focus,\n.btn-success.focus {\n color: #fff;\n background-color: #449d44;\n border-color: #255625;\n}\n.btn-success:hover {\n color: #fff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n color: #fff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active:hover,\n.btn-success.active:hover,\n.open > .dropdown-toggle.btn-success:hover,\n.btn-success:active:focus,\n.btn-success.active:focus,\n.open > .dropdown-toggle.btn-success:focus,\n.btn-success:active.focus,\n.btn-success.active.focus,\n.open > .dropdown-toggle.btn-success.focus {\n color: #fff;\n background-color: #398439;\n border-color: #255625;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n background-image: none;\n}\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus {\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success .badge {\n color: #5cb85c;\n background-color: #fff;\n}\n.btn-info {\n color: #fff;\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info:focus,\n.btn-info.focus {\n color: #fff;\n background-color: #31b0d5;\n border-color: #1b6d85;\n}\n.btn-info:hover {\n color: #fff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n color: #fff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active:hover,\n.btn-info.active:hover,\n.open > .dropdown-toggle.btn-info:hover,\n.btn-info:active:focus,\n.btn-info.active:focus,\n.open > .dropdown-toggle.btn-info:focus,\n.btn-info:active.focus,\n.btn-info.active.focus,\n.open > .dropdown-toggle.btn-info.focus {\n color: #fff;\n background-color: #269abc;\n border-color: #1b6d85;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n background-image: none;\n}\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus {\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info .badge {\n color: #5bc0de;\n background-color: #fff;\n}\n.btn-warning {\n color: #fff;\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning:focus,\n.btn-warning.focus {\n color: #fff;\n background-color: #ec971f;\n border-color: #985f0d;\n}\n.btn-warning:hover {\n color: #fff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n color: #fff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active:hover,\n.btn-warning.active:hover,\n.open > .dropdown-toggle.btn-warning:hover,\n.btn-warning:active:focus,\n.btn-warning.active:focus,\n.open > .dropdown-toggle.btn-warning:focus,\n.btn-warning:active.focus,\n.btn-warning.active.focus,\n.open > .dropdown-toggle.btn-warning.focus {\n color: #fff;\n background-color: #d58512;\n border-color: #985f0d;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n background-image: none;\n}\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus {\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning .badge {\n color: #f0ad4e;\n background-color: #fff;\n}\n.btn-danger {\n color: #fff;\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger:focus,\n.btn-danger.focus {\n color: #fff;\n background-color: #c9302c;\n border-color: #761c19;\n}\n.btn-danger:hover {\n color: #fff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n color: #fff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active:hover,\n.btn-danger.active:hover,\n.open > .dropdown-toggle.btn-danger:hover,\n.btn-danger:active:focus,\n.btn-danger.active:focus,\n.open > .dropdown-toggle.btn-danger:focus,\n.btn-danger:active.focus,\n.btn-danger.active.focus,\n.open > .dropdown-toggle.btn-danger.focus {\n color: #fff;\n background-color: #ac2925;\n border-color: #761c19;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n background-image: none;\n}\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus {\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger .badge {\n color: #d9534f;\n background-color: #fff;\n}\n.btn-link {\n color: #337ab7;\n font-weight: normal;\n border-radius: 0;\n}\n.btn-link,\n.btn-link:active,\n.btn-link.active,\n.btn-link[disabled],\nfieldset[disabled] .btn-link {\n background-color: transparent;\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-link,\n.btn-link:hover,\n.btn-link:focus,\n.btn-link:active {\n border-color: transparent;\n}\n.btn-link:hover,\n.btn-link:focus {\n color: #23527c;\n text-decoration: underline;\n background-color: transparent;\n}\n.btn-link[disabled]:hover,\nfieldset[disabled] .btn-link:hover,\n.btn-link[disabled]:focus,\nfieldset[disabled] .btn-link:focus {\n color: #777777;\n text-decoration: none;\n}\n.btn-lg,\n.btn-group-lg > .btn {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.btn-sm,\n.btn-group-sm > .btn {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-xs,\n.btn-group-xs > .btn {\n padding: 1px 5px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-block {\n display: block;\n width: 100%;\n}\n.btn-block + .btn-block {\n margin-top: 5px;\n}\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n width: 100%;\n}\n.fade {\n opacity: 0;\n -webkit-transition: opacity 0.15s linear;\n -o-transition: opacity 0.15s linear;\n transition: opacity 0.15s linear;\n}\n.fade.in {\n opacity: 1;\n}\n.collapse {\n display: none;\n}\n.collapse.in {\n display: block;\n}\ntr.collapse.in {\n display: table-row;\n}\ntbody.collapse.in {\n display: table-row-group;\n}\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n -webkit-transition-property: height, visibility;\n transition-property: height, visibility;\n -webkit-transition-duration: 0.35s;\n transition-duration: 0.35s;\n -webkit-transition-timing-function: ease;\n transition-timing-function: ease;\n}\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: 4px dashed;\n border-top: 4px solid \\9;\n border-right: 4px solid transparent;\n border-left: 4px solid transparent;\n}\n.dropup,\n.dropdown {\n position: relative;\n}\n.dropdown-toggle:focus {\n outline: 0;\n}\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n display: none;\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0;\n list-style: none;\n font-size: 14px;\n text-align: left;\n background-color: #fff;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, 0.15);\n border-radius: 4px;\n -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n background-clip: padding-box;\n}\n.dropdown-menu.pull-right {\n right: 0;\n left: auto;\n}\n.dropdown-menu .divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.dropdown-menu > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: 1.42857143;\n color: #333333;\n white-space: nowrap;\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n text-decoration: none;\n color: #262626;\n background-color: #f5f5f5;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n color: #fff;\n text-decoration: none;\n outline: 0;\n background-color: #337ab7;\n}\n.dropdown-menu > .disabled > a,\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n color: #777777;\n}\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n text-decoration: none;\n background-color: transparent;\n background-image: none;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n cursor: not-allowed;\n}\n.open > .dropdown-menu {\n display: block;\n}\n.open > a {\n outline: 0;\n}\n.dropdown-menu-right {\n left: auto;\n right: 0;\n}\n.dropdown-menu-left {\n left: 0;\n right: auto;\n}\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: 12px;\n line-height: 1.42857143;\n color: #777777;\n white-space: nowrap;\n}\n.dropdown-backdrop {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n z-index: 990;\n}\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n border-top: 0;\n border-bottom: 4px dashed;\n border-bottom: 4px solid \\9;\n content: \"\";\n}\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n}\n@media (min-width: 768px) {\n .navbar-right .dropdown-menu {\n left: auto;\n right: 0;\n }\n .navbar-right .dropdown-menu-left {\n left: 0;\n right: auto;\n }\n}\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle;\n}\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n position: relative;\n float: left;\n}\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group-vertical > .btn:focus,\n.btn-group > .btn:active,\n.btn-group-vertical > .btn:active,\n.btn-group > .btn.active,\n.btn-group-vertical > .btn.active {\n z-index: 2;\n}\n.btn-group .btn + .btn,\n.btn-group .btn + .btn-group,\n.btn-group .btn-group + .btn,\n.btn-group .btn-group + .btn-group {\n margin-left: -1px;\n}\n.btn-toolbar {\n margin-left: -5px;\n}\n.btn-toolbar .btn,\n.btn-toolbar .btn-group,\n.btn-toolbar .input-group {\n float: left;\n}\n.btn-toolbar > .btn,\n.btn-toolbar > .btn-group,\n.btn-toolbar > .input-group {\n margin-left: 5px;\n}\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n.btn-group > .btn:first-child {\n margin-left: 0;\n}\n.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n.btn-group > .btn + .dropdown-toggle {\n padding-left: 8px;\n padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-left: 12px;\n padding-right: 12px;\n}\n.btn-group.open .dropdown-toggle {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-group.open .dropdown-toggle.btn-link {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn .caret {\n margin-left: 0;\n}\n.btn-lg .caret {\n border-width: 5px 5px 0;\n border-bottom-width: 0;\n}\n.dropup .btn-lg .caret {\n border-width: 0 5px 5px;\n}\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group,\n.btn-group-vertical > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n}\n.btn-group-vertical > .btn-group > .btn {\n float: none;\n}\n.btn-group-vertical > .btn + .btn,\n.btn-group-vertical > .btn + .btn-group,\n.btn-group-vertical > .btn-group + .btn,\n.btn-group-vertical > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n}\n.btn-group-vertical > .btn:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.btn-group-vertical > .btn:first-child:not(:last-child) {\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn:last-child:not(:first-child) {\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n}\n.btn-group-justified > .btn,\n.btn-group-justified > .btn-group {\n float: none;\n display: table-cell;\n width: 1%;\n}\n.btn-group-justified > .btn-group .btn {\n width: 100%;\n}\n.btn-group-justified > .btn-group .dropdown-menu {\n left: auto;\n}\n[data-toggle=\"buttons\"] > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn input[type=\"checkbox\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0, 0, 0, 0);\n pointer-events: none;\n}\n.input-group {\n position: relative;\n display: table;\n border-collapse: separate;\n}\n.input-group[class*=\"col-\"] {\n float: none;\n padding-left: 0;\n padding-right: 0;\n}\n.input-group .form-control {\n position: relative;\n z-index: 2;\n float: left;\n width: 100%;\n margin-bottom: 0;\n}\n.input-group .form-control:focus {\n z-index: 3;\n}\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-group-lg > .form-control,\nselect.input-group-lg > .input-group-addon,\nselect.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-group-lg > .form-control,\ntextarea.input-group-lg > .input-group-addon,\ntextarea.input-group-lg > .input-group-btn > .btn,\nselect[multiple].input-group-lg > .form-control,\nselect[multiple].input-group-lg > .input-group-addon,\nselect[multiple].input-group-lg > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-group-sm > .form-control,\nselect.input-group-sm > .input-group-addon,\nselect.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-group-sm > .form-control,\ntextarea.input-group-sm > .input-group-addon,\ntextarea.input-group-sm > .input-group-btn > .btn,\nselect[multiple].input-group-sm > .form-control,\nselect[multiple].input-group-sm > .input-group-addon,\nselect[multiple].input-group-sm > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n}\n.input-group-addon:not(:first-child):not(:last-child),\n.input-group-btn:not(:first-child):not(:last-child),\n.input-group .form-control:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle;\n}\n.input-group-addon {\n padding: 6px 12px;\n font-size: 14px;\n font-weight: normal;\n line-height: 1;\n color: #555555;\n text-align: center;\n background-color: #eeeeee;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\n.input-group-addon.input-sm {\n padding: 5px 10px;\n font-size: 12px;\n border-radius: 3px;\n}\n.input-group-addon.input-lg {\n padding: 10px 16px;\n font-size: 18px;\n border-radius: 6px;\n}\n.input-group-addon input[type=\"radio\"],\n.input-group-addon input[type=\"checkbox\"] {\n margin-top: 0;\n}\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n.input-group-btn {\n position: relative;\n font-size: 0;\n white-space: nowrap;\n}\n.input-group-btn > .btn {\n position: relative;\n}\n.input-group-btn > .btn + .btn {\n margin-left: -1px;\n}\n.input-group-btn > .btn:hover,\n.input-group-btn > .btn:focus,\n.input-group-btn > .btn:active {\n z-index: 2;\n}\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group {\n margin-right: -1px;\n}\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group {\n z-index: 2;\n margin-left: -1px;\n}\n.nav {\n margin-bottom: 0;\n padding-left: 0;\n list-style: none;\n}\n.nav > li {\n position: relative;\n display: block;\n}\n.nav > li > a {\n position: relative;\n display: block;\n padding: 10px 15px;\n}\n.nav > li > a:hover,\n.nav > li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.nav > li.disabled > a {\n color: #777777;\n}\n.nav > li.disabled > a:hover,\n.nav > li.disabled > a:focus {\n color: #777777;\n text-decoration: none;\n background-color: transparent;\n cursor: not-allowed;\n}\n.nav .open > a,\n.nav .open > a:hover,\n.nav .open > a:focus {\n background-color: #eeeeee;\n border-color: #337ab7;\n}\n.nav .nav-divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.nav > li > a > img {\n max-width: none;\n}\n.nav-tabs {\n border-bottom: 1px solid #ddd;\n}\n.nav-tabs > li {\n float: left;\n margin-bottom: -1px;\n}\n.nav-tabs > li > a {\n margin-right: 2px;\n line-height: 1.42857143;\n border: 1px solid transparent;\n border-radius: 4px 4px 0 0;\n}\n.nav-tabs > li > a:hover {\n border-color: #eeeeee #eeeeee #ddd;\n}\n.nav-tabs > li.active > a,\n.nav-tabs > li.active > a:hover,\n.nav-tabs > li.active > a:focus {\n color: #555555;\n background-color: #fff;\n border: 1px solid #ddd;\n border-bottom-color: transparent;\n cursor: default;\n}\n.nav-tabs.nav-justified {\n width: 100%;\n border-bottom: 0;\n}\n.nav-tabs.nav-justified > li {\n float: none;\n}\n.nav-tabs.nav-justified > li > a {\n text-align: center;\n margin-bottom: 5px;\n}\n.nav-tabs.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-tabs.nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs.nav-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs.nav-justified > .active > a,\n.nav-tabs.nav-justified > .active > a:hover,\n.nav-tabs.nav-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs.nav-justified > .active > a,\n .nav-tabs.nav-justified > .active > a:hover,\n .nav-tabs.nav-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.nav-pills > li {\n float: left;\n}\n.nav-pills > li > a {\n border-radius: 4px;\n}\n.nav-pills > li + li {\n margin-left: 2px;\n}\n.nav-pills > li.active > a,\n.nav-pills > li.active > a:hover,\n.nav-pills > li.active > a:focus {\n color: #fff;\n background-color: #337ab7;\n}\n.nav-stacked > li {\n float: none;\n}\n.nav-stacked > li + li {\n margin-top: 2px;\n margin-left: 0;\n}\n.nav-justified {\n width: 100%;\n}\n.nav-justified > li {\n float: none;\n}\n.nav-justified > li > a {\n text-align: center;\n margin-bottom: 5px;\n}\n.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs-justified {\n border-bottom: 0;\n}\n.nav-tabs-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs-justified > .active > a,\n.nav-tabs-justified > .active > a:hover,\n.nav-tabs-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs-justified > .active > a,\n .nav-tabs-justified > .active > a:hover,\n .nav-tabs-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.tab-content > .tab-pane {\n display: none;\n}\n.tab-content > .active {\n display: block;\n}\n.nav-tabs .dropdown-menu {\n margin-top: -1px;\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.navbar {\n position: relative;\n min-height: 50px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n}\n@media (min-width: 768px) {\n .navbar {\n border-radius: 4px;\n }\n}\n@media (min-width: 768px) {\n .navbar-header {\n float: left;\n }\n}\n.navbar-collapse {\n overflow-x: visible;\n padding-right: 15px;\n padding-left: 15px;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);\n -webkit-overflow-scrolling: touch;\n}\n.navbar-collapse.in {\n overflow-y: auto;\n}\n@media (min-width: 768px) {\n .navbar-collapse {\n width: auto;\n border-top: 0;\n box-shadow: none;\n }\n .navbar-collapse.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0;\n overflow: visible !important;\n }\n .navbar-collapse.in {\n overflow-y: visible;\n }\n .navbar-fixed-top .navbar-collapse,\n .navbar-static-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n padding-left: 0;\n padding-right: 0;\n }\n}\n.navbar-fixed-top .navbar-collapse,\n.navbar-fixed-bottom .navbar-collapse {\n max-height: 340px;\n}\n@media (max-device-width: 480px) and (orientation: landscape) {\n .navbar-fixed-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n max-height: 200px;\n }\n}\n.container > .navbar-header,\n.container-fluid > .navbar-header,\n.container > .navbar-collapse,\n.container-fluid > .navbar-collapse {\n margin-right: -15px;\n margin-left: -15px;\n}\n@media (min-width: 768px) {\n .container > .navbar-header,\n .container-fluid > .navbar-header,\n .container > .navbar-collapse,\n .container-fluid > .navbar-collapse {\n margin-right: 0;\n margin-left: 0;\n }\n}\n.navbar-static-top {\n z-index: 1000;\n border-width: 0 0 1px;\n}\n@media (min-width: 768px) {\n .navbar-static-top {\n border-radius: 0;\n }\n}\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: 1030;\n}\n@media (min-width: 768px) {\n .navbar-fixed-top,\n .navbar-fixed-bottom {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0;\n border-width: 1px 0 0;\n}\n.navbar-brand {\n float: left;\n padding: 15px 15px;\n font-size: 18px;\n line-height: 20px;\n height: 50px;\n}\n.navbar-brand:hover,\n.navbar-brand:focus {\n text-decoration: none;\n}\n.navbar-brand > img {\n display: block;\n}\n@media (min-width: 768px) {\n .navbar > .container .navbar-brand,\n .navbar > .container-fluid .navbar-brand {\n margin-left: -15px;\n }\n}\n.navbar-toggle {\n position: relative;\n float: right;\n margin-right: 15px;\n padding: 9px 10px;\n margin-top: 8px;\n margin-bottom: 8px;\n background-color: transparent;\n background-image: none;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.navbar-toggle:focus {\n outline: 0;\n}\n.navbar-toggle .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n}\n.navbar-toggle .icon-bar + .icon-bar {\n margin-top: 4px;\n}\n@media (min-width: 768px) {\n .navbar-toggle {\n display: none;\n }\n}\n.navbar-nav {\n margin: 7.5px -15px;\n}\n.navbar-nav > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: 20px;\n}\n@media (max-width: 767px) {\n .navbar-nav .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n }\n .navbar-nav .open .dropdown-menu > li > a,\n .navbar-nav .open .dropdown-menu .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n .navbar-nav .open .dropdown-menu > li > a {\n line-height: 20px;\n }\n .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-nav .open .dropdown-menu > li > a:focus {\n background-image: none;\n }\n}\n@media (min-width: 768px) {\n .navbar-nav {\n float: left;\n margin: 0;\n }\n .navbar-nav > li {\n float: left;\n }\n .navbar-nav > li > a {\n padding-top: 15px;\n padding-bottom: 15px;\n }\n}\n.navbar-form {\n margin-left: -15px;\n margin-right: -15px;\n padding: 10px 15px;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n margin-top: 8px;\n margin-bottom: 8px;\n}\n@media (min-width: 768px) {\n .navbar-form .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .navbar-form .form-control-static {\n display: inline-block;\n }\n .navbar-form .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .navbar-form .input-group .input-group-addon,\n .navbar-form .input-group .input-group-btn,\n .navbar-form .input-group .form-control {\n width: auto;\n }\n .navbar-form .input-group > .form-control {\n width: 100%;\n }\n .navbar-form .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio,\n .navbar-form .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio label,\n .navbar-form .checkbox label {\n padding-left: 0;\n }\n .navbar-form .radio input[type=\"radio\"],\n .navbar-form .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .navbar-form .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n@media (max-width: 767px) {\n .navbar-form .form-group {\n margin-bottom: 5px;\n }\n .navbar-form .form-group:last-child {\n margin-bottom: 0;\n }\n}\n@media (min-width: 768px) {\n .navbar-form {\n width: auto;\n border: 0;\n margin-left: 0;\n margin-right: 0;\n padding-top: 0;\n padding-bottom: 0;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n}\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.navbar-btn {\n margin-top: 8px;\n margin-bottom: 8px;\n}\n.navbar-btn.btn-sm {\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.navbar-btn.btn-xs {\n margin-top: 14px;\n margin-bottom: 14px;\n}\n.navbar-text {\n margin-top: 15px;\n margin-bottom: 15px;\n}\n@media (min-width: 768px) {\n .navbar-text {\n float: left;\n margin-left: 15px;\n margin-right: 15px;\n }\n}\n@media (min-width: 768px) {\n .navbar-left {\n float: left !important;\n }\n .navbar-right {\n float: right !important;\n margin-right: -15px;\n }\n .navbar-right ~ .navbar-right {\n margin-right: 0;\n }\n}\n.navbar-default {\n background-color: #f8f8f8;\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-brand {\n color: #777;\n}\n.navbar-default .navbar-brand:hover,\n.navbar-default .navbar-brand:focus {\n color: #5e5e5e;\n background-color: transparent;\n}\n.navbar-default .navbar-text {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a:hover,\n.navbar-default .navbar-nav > li > a:focus {\n color: #333;\n background-color: transparent;\n}\n.navbar-default .navbar-nav > .active > a,\n.navbar-default .navbar-nav > .active > a:hover,\n.navbar-default .navbar-nav > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .disabled > a,\n.navbar-default .navbar-nav > .disabled > a:hover,\n.navbar-default .navbar-nav > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n}\n.navbar-default .navbar-toggle {\n border-color: #ddd;\n}\n.navbar-default .navbar-toggle:hover,\n.navbar-default .navbar-toggle:focus {\n background-color: #ddd;\n}\n.navbar-default .navbar-toggle .icon-bar {\n background-color: #888;\n}\n.navbar-default .navbar-collapse,\n.navbar-default .navbar-form {\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .open > a:hover,\n.navbar-default .navbar-nav > .open > a:focus {\n background-color: #e7e7e7;\n color: #555;\n}\n@media (max-width: 767px) {\n .navbar-default .navbar-nav .open .dropdown-menu > li > a {\n color: #777;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #333;\n background-color: transparent;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n }\n}\n.navbar-default .navbar-link {\n color: #777;\n}\n.navbar-default .navbar-link:hover {\n color: #333;\n}\n.navbar-default .btn-link {\n color: #777;\n}\n.navbar-default .btn-link:hover,\n.navbar-default .btn-link:focus {\n color: #333;\n}\n.navbar-default .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-default .btn-link:hover,\n.navbar-default .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-default .btn-link:focus {\n color: #ccc;\n}\n.navbar-inverse {\n background-color: #222;\n border-color: #080808;\n}\n.navbar-inverse .navbar-brand {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-brand:hover,\n.navbar-inverse .navbar-brand:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-text {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a:hover,\n.navbar-inverse .navbar-nav > li > a:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-nav > .active > a,\n.navbar-inverse .navbar-nav > .active > a:hover,\n.navbar-inverse .navbar-nav > .active > a:focus {\n color: #fff;\n background-color: #080808;\n}\n.navbar-inverse .navbar-nav > .disabled > a,\n.navbar-inverse .navbar-nav > .disabled > a:hover,\n.navbar-inverse .navbar-nav > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n}\n.navbar-inverse .navbar-toggle {\n border-color: #333;\n}\n.navbar-inverse .navbar-toggle:hover,\n.navbar-inverse .navbar-toggle:focus {\n background-color: #333;\n}\n.navbar-inverse .navbar-toggle .icon-bar {\n background-color: #fff;\n}\n.navbar-inverse .navbar-collapse,\n.navbar-inverse .navbar-form {\n border-color: #101010;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .open > a:hover,\n.navbar-inverse .navbar-nav > .open > a:focus {\n background-color: #080808;\n color: #fff;\n}\n@media (max-width: 767px) {\n .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {\n border-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu .divider {\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {\n color: #9d9d9d;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #fff;\n background-color: transparent;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #fff;\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n }\n}\n.navbar-inverse .navbar-link {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-link:hover {\n color: #fff;\n}\n.navbar-inverse .btn-link {\n color: #9d9d9d;\n}\n.navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link:focus {\n color: #fff;\n}\n.navbar-inverse .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-inverse .btn-link:focus {\n color: #444;\n}\n.breadcrumb {\n padding: 8px 15px;\n margin-bottom: 20px;\n list-style: none;\n background-color: #f5f5f5;\n border-radius: 4px;\n}\n.breadcrumb > li {\n display: inline-block;\n}\n.breadcrumb > li + li:before {\n content: \"/\\00a0\";\n padding: 0 5px;\n color: #ccc;\n}\n.breadcrumb > .active {\n color: #777777;\n}\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: 20px 0;\n border-radius: 4px;\n}\n.pagination > li {\n display: inline;\n}\n.pagination > li > a,\n.pagination > li > span {\n position: relative;\n float: left;\n padding: 6px 12px;\n line-height: 1.42857143;\n text-decoration: none;\n color: #337ab7;\n background-color: #fff;\n border: 1px solid #ddd;\n margin-left: -1px;\n}\n.pagination > li:first-child > a,\n.pagination > li:first-child > span {\n margin-left: 0;\n border-bottom-left-radius: 4px;\n border-top-left-radius: 4px;\n}\n.pagination > li:last-child > a,\n.pagination > li:last-child > span {\n border-bottom-right-radius: 4px;\n border-top-right-radius: 4px;\n}\n.pagination > li > a:hover,\n.pagination > li > span:hover,\n.pagination > li > a:focus,\n.pagination > li > span:focus {\n z-index: 2;\n color: #23527c;\n background-color: #eeeeee;\n border-color: #ddd;\n}\n.pagination > .active > a,\n.pagination > .active > span,\n.pagination > .active > a:hover,\n.pagination > .active > span:hover,\n.pagination > .active > a:focus,\n.pagination > .active > span:focus {\n z-index: 3;\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n cursor: default;\n}\n.pagination > .disabled > span,\n.pagination > .disabled > span:hover,\n.pagination > .disabled > span:focus,\n.pagination > .disabled > a,\n.pagination > .disabled > a:hover,\n.pagination > .disabled > a:focus {\n color: #777777;\n background-color: #fff;\n border-color: #ddd;\n cursor: not-allowed;\n}\n.pagination-lg > li > a,\n.pagination-lg > li > span {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.pagination-lg > li:first-child > a,\n.pagination-lg > li:first-child > span {\n border-bottom-left-radius: 6px;\n border-top-left-radius: 6px;\n}\n.pagination-lg > li:last-child > a,\n.pagination-lg > li:last-child > span {\n border-bottom-right-radius: 6px;\n border-top-right-radius: 6px;\n}\n.pagination-sm > li > a,\n.pagination-sm > li > span {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.pagination-sm > li:first-child > a,\n.pagination-sm > li:first-child > span {\n border-bottom-left-radius: 3px;\n border-top-left-radius: 3px;\n}\n.pagination-sm > li:last-child > a,\n.pagination-sm > li:last-child > span {\n border-bottom-right-radius: 3px;\n border-top-right-radius: 3px;\n}\n.pager {\n padding-left: 0;\n margin: 20px 0;\n list-style: none;\n text-align: center;\n}\n.pager li {\n display: inline;\n}\n.pager li > a,\n.pager li > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 15px;\n}\n.pager li > a:hover,\n.pager li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.pager .next > a,\n.pager .next > span {\n float: right;\n}\n.pager .previous > a,\n.pager .previous > span {\n float: left;\n}\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n color: #777777;\n background-color: #fff;\n cursor: not-allowed;\n}\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: #fff;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n}\na.label:hover,\na.label:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.label:empty {\n display: none;\n}\n.btn .label {\n position: relative;\n top: -1px;\n}\n.label-default {\n background-color: #777777;\n}\n.label-default[href]:hover,\n.label-default[href]:focus {\n background-color: #5e5e5e;\n}\n.label-primary {\n background-color: #337ab7;\n}\n.label-primary[href]:hover,\n.label-primary[href]:focus {\n background-color: #286090;\n}\n.label-success {\n background-color: #5cb85c;\n}\n.label-success[href]:hover,\n.label-success[href]:focus {\n background-color: #449d44;\n}\n.label-info {\n background-color: #5bc0de;\n}\n.label-info[href]:hover,\n.label-info[href]:focus {\n background-color: #31b0d5;\n}\n.label-warning {\n background-color: #f0ad4e;\n}\n.label-warning[href]:hover,\n.label-warning[href]:focus {\n background-color: #ec971f;\n}\n.label-danger {\n background-color: #d9534f;\n}\n.label-danger[href]:hover,\n.label-danger[href]:focus {\n background-color: #c9302c;\n}\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: 12px;\n font-weight: bold;\n color: #fff;\n line-height: 1;\n vertical-align: middle;\n white-space: nowrap;\n text-align: center;\n background-color: #777777;\n border-radius: 10px;\n}\n.badge:empty {\n display: none;\n}\n.btn .badge {\n position: relative;\n top: -1px;\n}\n.btn-xs .badge,\n.btn-group-xs > .btn .badge {\n top: 0;\n padding: 1px 5px;\n}\na.badge:hover,\na.badge:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.list-group-item > .badge {\n float: right;\n}\n.list-group-item > .badge + .badge {\n margin-right: 5px;\n}\n.nav-pills > li > a > .badge {\n margin-left: 3px;\n}\n.jumbotron {\n padding-top: 30px;\n padding-bottom: 30px;\n margin-bottom: 30px;\n color: inherit;\n background-color: #eeeeee;\n}\n.jumbotron h1,\n.jumbotron .h1 {\n color: inherit;\n}\n.jumbotron p {\n margin-bottom: 15px;\n font-size: 21px;\n font-weight: 200;\n}\n.jumbotron > hr {\n border-top-color: #d5d5d5;\n}\n.container .jumbotron,\n.container-fluid .jumbotron {\n border-radius: 6px;\n padding-left: 15px;\n padding-right: 15px;\n}\n.jumbotron .container {\n max-width: 100%;\n}\n@media screen and (min-width: 768px) {\n .jumbotron {\n padding-top: 48px;\n padding-bottom: 48px;\n }\n .container .jumbotron,\n .container-fluid .jumbotron {\n padding-left: 60px;\n padding-right: 60px;\n }\n .jumbotron h1,\n .jumbotron .h1 {\n font-size: 63px;\n }\n}\n.thumbnail {\n display: block;\n padding: 4px;\n margin-bottom: 20px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: border 0.2s ease-in-out;\n -o-transition: border 0.2s ease-in-out;\n transition: border 0.2s ease-in-out;\n}\n.thumbnail > img,\n.thumbnail a > img {\n margin-left: auto;\n margin-right: auto;\n}\na.thumbnail:hover,\na.thumbnail:focus,\na.thumbnail.active {\n border-color: #337ab7;\n}\n.thumbnail .caption {\n padding: 9px;\n color: #333333;\n}\n.alert {\n padding: 15px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.alert h4 {\n margin-top: 0;\n color: inherit;\n}\n.alert .alert-link {\n font-weight: bold;\n}\n.alert > p,\n.alert > ul {\n margin-bottom: 0;\n}\n.alert > p + p {\n margin-top: 5px;\n}\n.alert-dismissable,\n.alert-dismissible {\n padding-right: 35px;\n}\n.alert-dismissable .close,\n.alert-dismissible .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n}\n.alert-success {\n background-color: #dff0d8;\n border-color: #d6e9c6;\n color: #3c763d;\n}\n.alert-success hr {\n border-top-color: #c9e2b3;\n}\n.alert-success .alert-link {\n color: #2b542c;\n}\n.alert-info {\n background-color: #d9edf7;\n border-color: #bce8f1;\n color: #31708f;\n}\n.alert-info hr {\n border-top-color: #a6e1ec;\n}\n.alert-info .alert-link {\n color: #245269;\n}\n.alert-warning {\n background-color: #fcf8e3;\n border-color: #faebcc;\n color: #8a6d3b;\n}\n.alert-warning hr {\n border-top-color: #f7e1b5;\n}\n.alert-warning .alert-link {\n color: #66512c;\n}\n.alert-danger {\n background-color: #f2dede;\n border-color: #ebccd1;\n color: #a94442;\n}\n.alert-danger hr {\n border-top-color: #e4b9c0;\n}\n.alert-danger .alert-link {\n color: #843534;\n}\n@-webkit-keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n@keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n.progress {\n overflow: hidden;\n height: 20px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: 12px;\n line-height: 20px;\n color: #fff;\n text-align: center;\n background-color: #337ab7;\n -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n -webkit-transition: width 0.6s ease;\n -o-transition: width 0.6s ease;\n transition: width 0.6s ease;\n}\n.progress-striped .progress-bar,\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-size: 40px 40px;\n}\n.progress.active .progress-bar,\n.progress-bar.active {\n -webkit-animation: progress-bar-stripes 2s linear infinite;\n -o-animation: progress-bar-stripes 2s linear infinite;\n animation: progress-bar-stripes 2s linear infinite;\n}\n.progress-bar-success {\n background-color: #5cb85c;\n}\n.progress-striped .progress-bar-success {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-info {\n background-color: #5bc0de;\n}\n.progress-striped .progress-bar-info {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-warning {\n background-color: #f0ad4e;\n}\n.progress-striped .progress-bar-warning {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-danger {\n background-color: #d9534f;\n}\n.progress-striped .progress-bar-danger {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.media {\n margin-top: 15px;\n}\n.media:first-child {\n margin-top: 0;\n}\n.media,\n.media-body {\n zoom: 1;\n overflow: hidden;\n}\n.media-body {\n width: 10000px;\n}\n.media-object {\n display: block;\n}\n.media-object.img-thumbnail {\n max-width: none;\n}\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n.media-middle {\n vertical-align: middle;\n}\n.media-bottom {\n vertical-align: bottom;\n}\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n.list-group {\n margin-bottom: 20px;\n padding-left: 0;\n}\n.list-group-item {\n position: relative;\n display: block;\n padding: 10px 15px;\n margin-bottom: -1px;\n background-color: #fff;\n border: 1px solid #ddd;\n}\n.list-group-item:first-child {\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n}\n.list-group-item:last-child {\n margin-bottom: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\na.list-group-item,\nbutton.list-group-item {\n color: #555;\n}\na.list-group-item .list-group-item-heading,\nbutton.list-group-item .list-group-item-heading {\n color: #333;\n}\na.list-group-item:hover,\nbutton.list-group-item:hover,\na.list-group-item:focus,\nbutton.list-group-item:focus {\n text-decoration: none;\n color: #555;\n background-color: #f5f5f5;\n}\nbutton.list-group-item {\n width: 100%;\n text-align: left;\n}\n.list-group-item.disabled,\n.list-group-item.disabled:hover,\n.list-group-item.disabled:focus {\n background-color: #eeeeee;\n color: #777777;\n cursor: not-allowed;\n}\n.list-group-item.disabled .list-group-item-heading,\n.list-group-item.disabled:hover .list-group-item-heading,\n.list-group-item.disabled:focus .list-group-item-heading {\n color: inherit;\n}\n.list-group-item.disabled .list-group-item-text,\n.list-group-item.disabled:hover .list-group-item-text,\n.list-group-item.disabled:focus .list-group-item-text {\n color: #777777;\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n z-index: 2;\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.list-group-item.active .list-group-item-heading,\n.list-group-item.active:hover .list-group-item-heading,\n.list-group-item.active:focus .list-group-item-heading,\n.list-group-item.active .list-group-item-heading > small,\n.list-group-item.active:hover .list-group-item-heading > small,\n.list-group-item.active:focus .list-group-item-heading > small,\n.list-group-item.active .list-group-item-heading > .small,\n.list-group-item.active:hover .list-group-item-heading > .small,\n.list-group-item.active:focus .list-group-item-heading > .small {\n color: inherit;\n}\n.list-group-item.active .list-group-item-text,\n.list-group-item.active:hover .list-group-item-text,\n.list-group-item.active:focus .list-group-item-text {\n color: #c7ddef;\n}\n.list-group-item-success {\n color: #3c763d;\n background-color: #dff0d8;\n}\na.list-group-item-success,\nbutton.list-group-item-success {\n color: #3c763d;\n}\na.list-group-item-success .list-group-item-heading,\nbutton.list-group-item-success .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-success:hover,\nbutton.list-group-item-success:hover,\na.list-group-item-success:focus,\nbutton.list-group-item-success:focus {\n color: #3c763d;\n background-color: #d0e9c6;\n}\na.list-group-item-success.active,\nbutton.list-group-item-success.active,\na.list-group-item-success.active:hover,\nbutton.list-group-item-success.active:hover,\na.list-group-item-success.active:focus,\nbutton.list-group-item-success.active:focus {\n color: #fff;\n background-color: #3c763d;\n border-color: #3c763d;\n}\n.list-group-item-info {\n color: #31708f;\n background-color: #d9edf7;\n}\na.list-group-item-info,\nbutton.list-group-item-info {\n color: #31708f;\n}\na.list-group-item-info .list-group-item-heading,\nbutton.list-group-item-info .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-info:hover,\nbutton.list-group-item-info:hover,\na.list-group-item-info:focus,\nbutton.list-group-item-info:focus {\n color: #31708f;\n background-color: #c4e3f3;\n}\na.list-group-item-info.active,\nbutton.list-group-item-info.active,\na.list-group-item-info.active:hover,\nbutton.list-group-item-info.active:hover,\na.list-group-item-info.active:focus,\nbutton.list-group-item-info.active:focus {\n color: #fff;\n background-color: #31708f;\n border-color: #31708f;\n}\n.list-group-item-warning {\n color: #8a6d3b;\n background-color: #fcf8e3;\n}\na.list-group-item-warning,\nbutton.list-group-item-warning {\n color: #8a6d3b;\n}\na.list-group-item-warning .list-group-item-heading,\nbutton.list-group-item-warning .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-warning:hover,\nbutton.list-group-item-warning:hover,\na.list-group-item-warning:focus,\nbutton.list-group-item-warning:focus {\n color: #8a6d3b;\n background-color: #faf2cc;\n}\na.list-group-item-warning.active,\nbutton.list-group-item-warning.active,\na.list-group-item-warning.active:hover,\nbutton.list-group-item-warning.active:hover,\na.list-group-item-warning.active:focus,\nbutton.list-group-item-warning.active:focus {\n color: #fff;\n background-color: #8a6d3b;\n border-color: #8a6d3b;\n}\n.list-group-item-danger {\n color: #a94442;\n background-color: #f2dede;\n}\na.list-group-item-danger,\nbutton.list-group-item-danger {\n color: #a94442;\n}\na.list-group-item-danger .list-group-item-heading,\nbutton.list-group-item-danger .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-danger:hover,\nbutton.list-group-item-danger:hover,\na.list-group-item-danger:focus,\nbutton.list-group-item-danger:focus {\n color: #a94442;\n background-color: #ebcccc;\n}\na.list-group-item-danger.active,\nbutton.list-group-item-danger.active,\na.list-group-item-danger.active:hover,\nbutton.list-group-item-danger.active:hover,\na.list-group-item-danger.active:focus,\nbutton.list-group-item-danger.active:focus {\n color: #fff;\n background-color: #a94442;\n border-color: #a94442;\n}\n.list-group-item-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.list-group-item-text {\n margin-bottom: 0;\n line-height: 1.3;\n}\n.panel {\n margin-bottom: 20px;\n background-color: #fff;\n border: 1px solid transparent;\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.panel-body {\n padding: 15px;\n}\n.panel-heading {\n padding: 10px 15px;\n border-bottom: 1px solid transparent;\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel-heading > .dropdown .dropdown-toggle {\n color: inherit;\n}\n.panel-title {\n margin-top: 0;\n margin-bottom: 0;\n font-size: 16px;\n color: inherit;\n}\n.panel-title > a,\n.panel-title > small,\n.panel-title > .small,\n.panel-title > small > a,\n.panel-title > .small > a {\n color: inherit;\n}\n.panel-footer {\n padding: 10px 15px;\n background-color: #f5f5f5;\n border-top: 1px solid #ddd;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .list-group,\n.panel > .panel-collapse > .list-group {\n margin-bottom: 0;\n}\n.panel > .list-group .list-group-item,\n.panel > .panel-collapse > .list-group .list-group-item {\n border-width: 1px 0;\n border-radius: 0;\n}\n.panel > .list-group:first-child .list-group-item:first-child,\n.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child {\n border-top: 0;\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel > .list-group:last-child .list-group-item:last-child,\n.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child {\n border-bottom: 0;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child {\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.panel-heading + .list-group .list-group-item:first-child {\n border-top-width: 0;\n}\n.list-group + .panel-footer {\n border-top-width: 0;\n}\n.panel > .table,\n.panel > .table-responsive > .table,\n.panel > .panel-collapse > .table {\n margin-bottom: 0;\n}\n.panel > .table caption,\n.panel > .table-responsive > .table caption,\n.panel > .panel-collapse > .table caption {\n padding-left: 15px;\n padding-right: 15px;\n}\n.panel > .table:first-child,\n.panel > .table-responsive:first-child > .table:first-child {\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child {\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {\n border-top-right-radius: 3px;\n}\n.panel > .table:last-child,\n.panel > .table-responsive:last-child > .table:last-child {\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child {\n border-bottom-left-radius: 3px;\n border-bottom-right-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {\n border-bottom-right-radius: 3px;\n}\n.panel > .panel-body + .table,\n.panel > .panel-body + .table-responsive,\n.panel > .table + .panel-body,\n.panel > .table-responsive + .panel-body {\n border-top: 1px solid #ddd;\n}\n.panel > .table > tbody:first-child > tr:first-child th,\n.panel > .table > tbody:first-child > tr:first-child td {\n border-top: 0;\n}\n.panel > .table-bordered,\n.panel > .table-responsive > .table-bordered {\n border: 0;\n}\n.panel > .table-bordered > thead > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,\n.panel > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-bordered > thead > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,\n.panel > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-bordered > tfoot > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n}\n.panel > .table-bordered > thead > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,\n.panel > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-bordered > thead > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,\n.panel > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-bordered > tfoot > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n}\n.panel > .table-bordered > thead > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,\n.panel > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-bordered > thead > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,\n.panel > .table-bordered > tbody > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {\n border-bottom: 0;\n}\n.panel > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-bordered > tfoot > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {\n border-bottom: 0;\n}\n.panel > .table-responsive {\n border: 0;\n margin-bottom: 0;\n}\n.panel-group {\n margin-bottom: 20px;\n}\n.panel-group .panel {\n margin-bottom: 0;\n border-radius: 4px;\n}\n.panel-group .panel + .panel {\n margin-top: 5px;\n}\n.panel-group .panel-heading {\n border-bottom: 0;\n}\n.panel-group .panel-heading + .panel-collapse > .panel-body,\n.panel-group .panel-heading + .panel-collapse > .list-group {\n border-top: 1px solid #ddd;\n}\n.panel-group .panel-footer {\n border-top: 0;\n}\n.panel-group .panel-footer + .panel-collapse .panel-body {\n border-bottom: 1px solid #ddd;\n}\n.panel-default {\n border-color: #ddd;\n}\n.panel-default > .panel-heading {\n color: #333333;\n background-color: #f5f5f5;\n border-color: #ddd;\n}\n.panel-default > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ddd;\n}\n.panel-default > .panel-heading .badge {\n color: #f5f5f5;\n background-color: #333333;\n}\n.panel-default > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ddd;\n}\n.panel-primary {\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading {\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #337ab7;\n}\n.panel-primary > .panel-heading .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.panel-primary > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #337ab7;\n}\n.panel-success {\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #d6e9c6;\n}\n.panel-success > .panel-heading .badge {\n color: #dff0d8;\n background-color: #3c763d;\n}\n.panel-success > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #d6e9c6;\n}\n.panel-info {\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading {\n color: #31708f;\n background-color: #d9edf7;\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #bce8f1;\n}\n.panel-info > .panel-heading .badge {\n color: #d9edf7;\n background-color: #31708f;\n}\n.panel-info > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #bce8f1;\n}\n.panel-warning {\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #faebcc;\n}\n.panel-warning > .panel-heading .badge {\n color: #fcf8e3;\n background-color: #8a6d3b;\n}\n.panel-warning > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #faebcc;\n}\n.panel-danger {\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading {\n color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ebccd1;\n}\n.panel-danger > .panel-heading .badge {\n color: #f2dede;\n background-color: #a94442;\n}\n.panel-danger > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ebccd1;\n}\n.embed-responsive {\n position: relative;\n display: block;\n height: 0;\n padding: 0;\n overflow: hidden;\n}\n.embed-responsive .embed-responsive-item,\n.embed-responsive iframe,\n.embed-responsive embed,\n.embed-responsive object,\n.embed-responsive video {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n height: 100%;\n width: 100%;\n border: 0;\n}\n.embed-responsive-16by9 {\n padding-bottom: 56.25%;\n}\n.embed-responsive-4by3 {\n padding-bottom: 75%;\n}\n.well {\n min-height: 20px;\n padding: 19px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border: 1px solid #e3e3e3;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.well blockquote {\n border-color: #ddd;\n border-color: rgba(0, 0, 0, 0.15);\n}\n.well-lg {\n padding: 24px;\n border-radius: 6px;\n}\n.well-sm {\n padding: 9px;\n border-radius: 3px;\n}\n.close {\n float: right;\n font-size: 21px;\n font-weight: bold;\n line-height: 1;\n color: #000;\n text-shadow: 0 1px 0 #fff;\n opacity: 0.2;\n filter: alpha(opacity=20);\n}\n.close:hover,\n.close:focus {\n color: #000;\n text-decoration: none;\n cursor: pointer;\n opacity: 0.5;\n filter: alpha(opacity=50);\n}\nbutton.close {\n padding: 0;\n cursor: pointer;\n background: transparent;\n border: 0;\n -webkit-appearance: none;\n}\n.modal-open {\n overflow: hidden;\n}\n.modal {\n display: none;\n overflow: hidden;\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1050;\n -webkit-overflow-scrolling: touch;\n outline: 0;\n}\n.modal.fade .modal-dialog {\n -webkit-transform: translate(0, -25%);\n -ms-transform: translate(0, -25%);\n -o-transform: translate(0, -25%);\n transform: translate(0, -25%);\n -webkit-transition: -webkit-transform 0.3s ease-out;\n -moz-transition: -moz-transform 0.3s ease-out;\n -o-transition: -o-transform 0.3s ease-out;\n transition: transform 0.3s ease-out;\n}\n.modal.in .modal-dialog {\n -webkit-transform: translate(0, 0);\n -ms-transform: translate(0, 0);\n -o-transform: translate(0, 0);\n transform: translate(0, 0);\n}\n.modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto;\n}\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 10px;\n}\n.modal-content {\n position: relative;\n background-color: #fff;\n border: 1px solid #999;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n background-clip: padding-box;\n outline: 0;\n}\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1040;\n background-color: #000;\n}\n.modal-backdrop.fade {\n opacity: 0;\n filter: alpha(opacity=0);\n}\n.modal-backdrop.in {\n opacity: 0.5;\n filter: alpha(opacity=50);\n}\n.modal-header {\n padding: 15px;\n border-bottom: 1px solid #e5e5e5;\n}\n.modal-header .close {\n margin-top: -2px;\n}\n.modal-title {\n margin: 0;\n line-height: 1.42857143;\n}\n.modal-body {\n position: relative;\n padding: 15px;\n}\n.modal-footer {\n padding: 15px;\n text-align: right;\n border-top: 1px solid #e5e5e5;\n}\n.modal-footer .btn + .btn {\n margin-left: 5px;\n margin-bottom: 0;\n}\n.modal-footer .btn-group .btn + .btn {\n margin-left: -1px;\n}\n.modal-footer .btn-block + .btn-block {\n margin-left: 0;\n}\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n@media (min-width: 768px) {\n .modal-dialog {\n width: 600px;\n margin: 30px auto;\n }\n .modal-content {\n -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n }\n .modal-sm {\n width: 300px;\n }\n}\n@media (min-width: 992px) {\n .modal-lg {\n width: 900px;\n }\n}\n.tooltip {\n position: absolute;\n z-index: 1070;\n display: block;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-style: normal;\n font-weight: normal;\n letter-spacing: normal;\n line-break: auto;\n line-height: 1.42857143;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n white-space: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n font-size: 12px;\n opacity: 0;\n filter: alpha(opacity=0);\n}\n.tooltip.in {\n opacity: 0.9;\n filter: alpha(opacity=90);\n}\n.tooltip.top {\n margin-top: -3px;\n padding: 5px 0;\n}\n.tooltip.right {\n margin-left: 3px;\n padding: 0 5px;\n}\n.tooltip.bottom {\n margin-top: 3px;\n padding: 5px 0;\n}\n.tooltip.left {\n margin-left: -3px;\n padding: 0 5px;\n}\n.tooltip-inner {\n max-width: 200px;\n padding: 3px 8px;\n color: #fff;\n text-align: center;\n background-color: #000;\n border-radius: 4px;\n}\n.tooltip-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.tooltip.top .tooltip-arrow {\n bottom: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-left .tooltip-arrow {\n bottom: 0;\n right: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-right .tooltip-arrow {\n bottom: 0;\n left: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.right .tooltip-arrow {\n top: 50%;\n left: 0;\n margin-top: -5px;\n border-width: 5px 5px 5px 0;\n border-right-color: #000;\n}\n.tooltip.left .tooltip-arrow {\n top: 50%;\n right: 0;\n margin-top: -5px;\n border-width: 5px 0 5px 5px;\n border-left-color: #000;\n}\n.tooltip.bottom .tooltip-arrow {\n top: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-left .tooltip-arrow {\n top: 0;\n right: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-right .tooltip-arrow {\n top: 0;\n left: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 1060;\n display: none;\n max-width: 276px;\n padding: 1px;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-style: normal;\n font-weight: normal;\n letter-spacing: normal;\n line-break: auto;\n line-height: 1.42857143;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n white-space: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n font-size: 14px;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n}\n.popover.top {\n margin-top: -10px;\n}\n.popover.right {\n margin-left: 10px;\n}\n.popover.bottom {\n margin-top: 10px;\n}\n.popover.left {\n margin-left: -10px;\n}\n.popover-title {\n margin: 0;\n padding: 8px 14px;\n font-size: 14px;\n background-color: #f7f7f7;\n border-bottom: 1px solid #ebebeb;\n border-radius: 5px 5px 0 0;\n}\n.popover-content {\n padding: 9px 14px;\n}\n.popover > .arrow,\n.popover > .arrow:after {\n position: absolute;\n display: block;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.popover > .arrow {\n border-width: 11px;\n}\n.popover > .arrow:after {\n border-width: 10px;\n content: \"\";\n}\n.popover.top > .arrow {\n left: 50%;\n margin-left: -11px;\n border-bottom-width: 0;\n border-top-color: #999999;\n border-top-color: rgba(0, 0, 0, 0.25);\n bottom: -11px;\n}\n.popover.top > .arrow:after {\n content: \" \";\n bottom: 1px;\n margin-left: -10px;\n border-bottom-width: 0;\n border-top-color: #fff;\n}\n.popover.right > .arrow {\n top: 50%;\n left: -11px;\n margin-top: -11px;\n border-left-width: 0;\n border-right-color: #999999;\n border-right-color: rgba(0, 0, 0, 0.25);\n}\n.popover.right > .arrow:after {\n content: \" \";\n left: 1px;\n bottom: -10px;\n border-left-width: 0;\n border-right-color: #fff;\n}\n.popover.bottom > .arrow {\n left: 50%;\n margin-left: -11px;\n border-top-width: 0;\n border-bottom-color: #999999;\n border-bottom-color: rgba(0, 0, 0, 0.25);\n top: -11px;\n}\n.popover.bottom > .arrow:after {\n content: \" \";\n top: 1px;\n margin-left: -10px;\n border-top-width: 0;\n border-bottom-color: #fff;\n}\n.popover.left > .arrow {\n top: 50%;\n right: -11px;\n margin-top: -11px;\n border-right-width: 0;\n border-left-color: #999999;\n border-left-color: rgba(0, 0, 0, 0.25);\n}\n.popover.left > .arrow:after {\n content: \" \";\n right: 1px;\n border-right-width: 0;\n border-left-color: #fff;\n bottom: -10px;\n}\n.carousel {\n position: relative;\n}\n.carousel-inner {\n position: relative;\n overflow: hidden;\n width: 100%;\n}\n.carousel-inner > .item {\n display: none;\n position: relative;\n -webkit-transition: 0.6s ease-in-out left;\n -o-transition: 0.6s ease-in-out left;\n transition: 0.6s ease-in-out left;\n}\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n line-height: 1;\n}\n@media all and (transform-3d), (-webkit-transform-3d) {\n .carousel-inner > .item {\n -webkit-transition: -webkit-transform 0.6s ease-in-out;\n -moz-transition: -moz-transform 0.6s ease-in-out;\n -o-transition: -o-transform 0.6s ease-in-out;\n transition: transform 0.6s ease-in-out;\n -webkit-backface-visibility: hidden;\n -moz-backface-visibility: hidden;\n backface-visibility: hidden;\n -webkit-perspective: 1000px;\n -moz-perspective: 1000px;\n perspective: 1000px;\n }\n .carousel-inner > .item.next,\n .carousel-inner > .item.active.right {\n -webkit-transform: translate3d(100%, 0, 0);\n transform: translate3d(100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.prev,\n .carousel-inner > .item.active.left {\n -webkit-transform: translate3d(-100%, 0, 0);\n transform: translate3d(-100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.next.left,\n .carousel-inner > .item.prev.right,\n .carousel-inner > .item.active {\n -webkit-transform: translate3d(0, 0, 0);\n transform: translate3d(0, 0, 0);\n left: 0;\n }\n}\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n display: block;\n}\n.carousel-inner > .active {\n left: 0;\n}\n.carousel-inner > .next,\n.carousel-inner > .prev {\n position: absolute;\n top: 0;\n width: 100%;\n}\n.carousel-inner > .next {\n left: 100%;\n}\n.carousel-inner > .prev {\n left: -100%;\n}\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n left: 0;\n}\n.carousel-inner > .active.left {\n left: -100%;\n}\n.carousel-inner > .active.right {\n left: 100%;\n}\n.carousel-control {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n width: 15%;\n opacity: 0.5;\n filter: alpha(opacity=50);\n font-size: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n background-color: rgba(0, 0, 0, 0);\n}\n.carousel-control.left {\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);\n}\n.carousel-control.right {\n left: auto;\n right: 0;\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);\n}\n.carousel-control:hover,\n.carousel-control:focus {\n outline: 0;\n color: #fff;\n text-decoration: none;\n opacity: 0.9;\n filter: alpha(opacity=90);\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-left,\n.carousel-control .glyphicon-chevron-right {\n position: absolute;\n top: 50%;\n margin-top: -10px;\n z-index: 5;\n display: inline-block;\n}\n.carousel-control .icon-prev,\n.carousel-control .glyphicon-chevron-left {\n left: 50%;\n margin-left: -10px;\n}\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-right {\n right: 50%;\n margin-right: -10px;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next {\n width: 20px;\n height: 20px;\n line-height: 1;\n font-family: serif;\n}\n.carousel-control .icon-prev:before {\n content: '\\2039';\n}\n.carousel-control .icon-next:before {\n content: '\\203a';\n}\n.carousel-indicators {\n position: absolute;\n bottom: 10px;\n left: 50%;\n z-index: 15;\n width: 60%;\n margin-left: -30%;\n padding-left: 0;\n list-style: none;\n text-align: center;\n}\n.carousel-indicators li {\n display: inline-block;\n width: 10px;\n height: 10px;\n margin: 1px;\n text-indent: -999px;\n border: 1px solid #fff;\n border-radius: 10px;\n cursor: pointer;\n background-color: #000 \\9;\n background-color: rgba(0, 0, 0, 0);\n}\n.carousel-indicators .active {\n margin: 0;\n width: 12px;\n height: 12px;\n background-color: #fff;\n}\n.carousel-caption {\n position: absolute;\n left: 15%;\n right: 15%;\n bottom: 20px;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n}\n.carousel-caption .btn {\n text-shadow: none;\n}\n@media screen and (min-width: 768px) {\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-prev,\n .carousel-control .icon-next {\n width: 30px;\n height: 30px;\n margin-top: -10px;\n font-size: 30px;\n }\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .icon-prev {\n margin-left: -10px;\n }\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-next {\n margin-right: -10px;\n }\n .carousel-caption {\n left: 20%;\n right: 20%;\n padding-bottom: 30px;\n }\n .carousel-indicators {\n bottom: 20px;\n }\n}\n.clearfix:before,\n.clearfix:after,\n.dl-horizontal dd:before,\n.dl-horizontal dd:after,\n.container:before,\n.container:after,\n.container-fluid:before,\n.container-fluid:after,\n.row:before,\n.row:after,\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after,\n.btn-toolbar:before,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:before,\n.btn-group-vertical > .btn-group:after,\n.nav:before,\n.nav:after,\n.navbar:before,\n.navbar:after,\n.navbar-header:before,\n.navbar-header:after,\n.navbar-collapse:before,\n.navbar-collapse:after,\n.pager:before,\n.pager:after,\n.panel-body:before,\n.panel-body:after,\n.modal-header:before,\n.modal-header:after,\n.modal-footer:before,\n.modal-footer:after {\n content: \" \";\n display: table;\n}\n.clearfix:after,\n.dl-horizontal dd:after,\n.container:after,\n.container-fluid:after,\n.row:after,\n.form-horizontal .form-group:after,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:after,\n.nav:after,\n.navbar:after,\n.navbar-header:after,\n.navbar-collapse:after,\n.pager:after,\n.panel-body:after,\n.modal-header:after,\n.modal-footer:after {\n clear: both;\n}\n.center-block {\n display: block;\n margin-left: auto;\n margin-right: auto;\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n font: 0/0 a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n.hidden {\n display: none !important;\n}\n.affix {\n position: fixed;\n}\n@-ms-viewport {\n width: device-width;\n}\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n display: none !important;\n}\n.visible-xs-block,\n.visible-xs-inline,\n.visible-xs-inline-block,\n.visible-sm-block,\n.visible-sm-inline,\n.visible-sm-inline-block,\n.visible-md-block,\n.visible-md-inline,\n.visible-md-inline-block,\n.visible-lg-block,\n.visible-lg-inline,\n.visible-lg-inline-block {\n display: none !important;\n}\n@media (max-width: 767px) {\n .visible-xs {\n display: block !important;\n }\n table.visible-xs {\n display: table !important;\n }\n tr.visible-xs {\n display: table-row !important;\n }\n th.visible-xs,\n td.visible-xs {\n display: table-cell !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-block {\n display: block !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline {\n display: inline !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm {\n display: block !important;\n }\n table.visible-sm {\n display: table !important;\n }\n tr.visible-sm {\n display: table-row !important;\n }\n th.visible-sm,\n td.visible-sm {\n display: table-cell !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-block {\n display: block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline {\n display: inline !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md {\n display: block !important;\n }\n table.visible-md {\n display: table !important;\n }\n tr.visible-md {\n display: table-row !important;\n }\n th.visible-md,\n td.visible-md {\n display: table-cell !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-block {\n display: block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline {\n display: inline !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg {\n display: block !important;\n }\n table.visible-lg {\n display: table !important;\n }\n tr.visible-lg {\n display: table-row !important;\n }\n th.visible-lg,\n td.visible-lg {\n display: table-cell !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-block {\n display: block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline {\n display: inline !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline-block {\n display: inline-block !important;\n }\n}\n@media (max-width: 767px) {\n .hidden-xs {\n display: none !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .hidden-sm {\n display: none !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .hidden-md {\n display: none !important;\n }\n}\n@media (min-width: 1200px) {\n .hidden-lg {\n display: none !important;\n }\n}\n.visible-print {\n display: none !important;\n}\n@media print {\n .visible-print {\n display: block !important;\n }\n table.visible-print {\n display: table !important;\n }\n tr.visible-print {\n display: table-row !important;\n }\n th.visible-print,\n td.visible-print {\n display: table-cell !important;\n }\n}\n.visible-print-block {\n display: none !important;\n}\n@media print {\n .visible-print-block {\n display: block !important;\n }\n}\n.visible-print-inline {\n display: none !important;\n}\n@media print {\n .visible-print-inline {\n display: inline !important;\n }\n}\n.visible-print-inline-block {\n display: none !important;\n}\n@media print {\n .visible-print-inline-block {\n display: inline-block !important;\n }\n}\n@media print {\n .hidden-print {\n display: none !important;\n }\n}\n/*# sourceMappingURL=bootstrap.css.map */","/*!\n * Bootstrap v3.3.7 (http://getbootstrap.com)\n * Copyright 2011-2016 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\nhtml {\n font-family: sans-serif;\n -webkit-text-size-adjust: 100%;\n -ms-text-size-adjust: 100%;\n}\nbody {\n margin: 0;\n}\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block;\n vertical-align: baseline;\n}\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n[hidden],\ntemplate {\n display: none;\n}\na {\n background-color: transparent;\n}\na:active,\na:hover {\n outline: 0;\n}\nabbr[title] {\n border-bottom: 1px dotted;\n}\nb,\nstrong {\n font-weight: bold;\n}\ndfn {\n font-style: italic;\n}\nh1 {\n margin: .67em 0;\n font-size: 2em;\n}\nmark {\n color: #000;\n background: #ff0;\n}\nsmall {\n font-size: 80%;\n}\nsub,\nsup {\n position: relative;\n font-size: 75%;\n line-height: 0;\n vertical-align: baseline;\n}\nsup {\n top: -.5em;\n}\nsub {\n bottom: -.25em;\n}\nimg {\n border: 0;\n}\nsvg:not(:root) {\n overflow: hidden;\n}\nfigure {\n margin: 1em 40px;\n}\nhr {\n height: 0;\n -webkit-box-sizing: content-box;\n -moz-box-sizing: content-box;\n box-sizing: content-box;\n}\npre {\n overflow: auto;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n margin: 0;\n font: inherit;\n color: inherit;\n}\nbutton {\n overflow: visible;\n}\nbutton,\nselect {\n text-transform: none;\n}\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button;\n cursor: pointer;\n}\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n padding: 0;\n border: 0;\n}\ninput {\n line-height: normal;\n}\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n padding: 0;\n}\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-box-sizing: content-box;\n -moz-box-sizing: content-box;\n box-sizing: content-box;\n -webkit-appearance: textfield;\n}\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\nfieldset {\n padding: .35em .625em .75em;\n margin: 0 2px;\n border: 1px solid #c0c0c0;\n}\nlegend {\n padding: 0;\n border: 0;\n}\ntextarea {\n overflow: auto;\n}\noptgroup {\n font-weight: bold;\n}\ntable {\n border-spacing: 0;\n border-collapse: collapse;\n}\ntd,\nth {\n padding: 0;\n}\n/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n@media print {\n *,\n *:before,\n *:after {\n color: #000 !important;\n text-shadow: none !important;\n background: transparent !important;\n -webkit-box-shadow: none !important;\n box-shadow: none !important;\n }\n a,\n a:visited {\n text-decoration: underline;\n }\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n pre,\n blockquote {\n border: 1px solid #999;\n\n page-break-inside: avoid;\n }\n thead {\n display: table-header-group;\n }\n tr,\n img {\n page-break-inside: avoid;\n }\n img {\n max-width: 100% !important;\n }\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n h2,\n h3 {\n page-break-after: avoid;\n }\n .navbar {\n display: none;\n }\n .btn > .caret,\n .dropup > .btn > .caret {\n border-top-color: #000 !important;\n }\n .label {\n border: 1px solid #000;\n }\n .table {\n border-collapse: collapse !important;\n }\n .table td,\n .table th {\n background-color: #fff !important;\n }\n .table-bordered th,\n .table-bordered td {\n border: 1px solid #ddd !important;\n }\n}\n@font-face {\n font-family: 'Glyphicons Halflings';\n\n src: url('../fonts/glyphicons-halflings-regular.eot');\n src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');\n}\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n.glyphicon-asterisk:before {\n content: \"\\002a\";\n}\n.glyphicon-plus:before {\n content: \"\\002b\";\n}\n.glyphicon-euro:before,\n.glyphicon-eur:before {\n content: \"\\20ac\";\n}\n.glyphicon-minus:before {\n content: \"\\2212\";\n}\n.glyphicon-cloud:before {\n content: \"\\2601\";\n}\n.glyphicon-envelope:before {\n content: \"\\2709\";\n}\n.glyphicon-pencil:before {\n content: \"\\270f\";\n}\n.glyphicon-glass:before {\n content: \"\\e001\";\n}\n.glyphicon-music:before {\n content: \"\\e002\";\n}\n.glyphicon-search:before {\n content: \"\\e003\";\n}\n.glyphicon-heart:before {\n content: \"\\e005\";\n}\n.glyphicon-star:before {\n content: \"\\e006\";\n}\n.glyphicon-star-empty:before {\n content: \"\\e007\";\n}\n.glyphicon-user:before {\n content: \"\\e008\";\n}\n.glyphicon-film:before {\n content: \"\\e009\";\n}\n.glyphicon-th-large:before {\n content: \"\\e010\";\n}\n.glyphicon-th:before {\n content: \"\\e011\";\n}\n.glyphicon-th-list:before {\n content: \"\\e012\";\n}\n.glyphicon-ok:before {\n content: \"\\e013\";\n}\n.glyphicon-remove:before {\n content: \"\\e014\";\n}\n.glyphicon-zoom-in:before {\n content: \"\\e015\";\n}\n.glyphicon-zoom-out:before {\n content: \"\\e016\";\n}\n.glyphicon-off:before {\n content: \"\\e017\";\n}\n.glyphicon-signal:before {\n content: \"\\e018\";\n}\n.glyphicon-cog:before {\n content: \"\\e019\";\n}\n.glyphicon-trash:before {\n content: \"\\e020\";\n}\n.glyphicon-home:before {\n content: \"\\e021\";\n}\n.glyphicon-file:before {\n content: \"\\e022\";\n}\n.glyphicon-time:before {\n content: \"\\e023\";\n}\n.glyphicon-road:before {\n content: \"\\e024\";\n}\n.glyphicon-download-alt:before {\n content: \"\\e025\";\n}\n.glyphicon-download:before {\n content: \"\\e026\";\n}\n.glyphicon-upload:before {\n content: \"\\e027\";\n}\n.glyphicon-inbox:before {\n content: \"\\e028\";\n}\n.glyphicon-play-circle:before {\n content: \"\\e029\";\n}\n.glyphicon-repeat:before {\n content: \"\\e030\";\n}\n.glyphicon-refresh:before {\n content: \"\\e031\";\n}\n.glyphicon-list-alt:before {\n content: \"\\e032\";\n}\n.glyphicon-lock:before {\n content: \"\\e033\";\n}\n.glyphicon-flag:before {\n content: \"\\e034\";\n}\n.glyphicon-headphones:before {\n content: \"\\e035\";\n}\n.glyphicon-volume-off:before {\n content: \"\\e036\";\n}\n.glyphicon-volume-down:before {\n content: \"\\e037\";\n}\n.glyphicon-volume-up:before {\n content: \"\\e038\";\n}\n.glyphicon-qrcode:before {\n content: \"\\e039\";\n}\n.glyphicon-barcode:before {\n content: \"\\e040\";\n}\n.glyphicon-tag:before {\n content: \"\\e041\";\n}\n.glyphicon-tags:before {\n content: \"\\e042\";\n}\n.glyphicon-book:before {\n content: \"\\e043\";\n}\n.glyphicon-bookmark:before {\n content: \"\\e044\";\n}\n.glyphicon-print:before {\n content: \"\\e045\";\n}\n.glyphicon-camera:before {\n content: \"\\e046\";\n}\n.glyphicon-font:before {\n content: \"\\e047\";\n}\n.glyphicon-bold:before {\n content: \"\\e048\";\n}\n.glyphicon-italic:before {\n content: \"\\e049\";\n}\n.glyphicon-text-height:before {\n content: \"\\e050\";\n}\n.glyphicon-text-width:before {\n content: \"\\e051\";\n}\n.glyphicon-align-left:before {\n content: \"\\e052\";\n}\n.glyphicon-align-center:before {\n content: \"\\e053\";\n}\n.glyphicon-align-right:before {\n content: \"\\e054\";\n}\n.glyphicon-align-justify:before {\n content: \"\\e055\";\n}\n.glyphicon-list:before {\n content: \"\\e056\";\n}\n.glyphicon-indent-left:before {\n content: \"\\e057\";\n}\n.glyphicon-indent-right:before {\n content: \"\\e058\";\n}\n.glyphicon-facetime-video:before {\n content: \"\\e059\";\n}\n.glyphicon-picture:before {\n content: \"\\e060\";\n}\n.glyphicon-map-marker:before {\n content: \"\\e062\";\n}\n.glyphicon-adjust:before {\n content: \"\\e063\";\n}\n.glyphicon-tint:before {\n content: \"\\e064\";\n}\n.glyphicon-edit:before {\n content: \"\\e065\";\n}\n.glyphicon-share:before {\n content: \"\\e066\";\n}\n.glyphicon-check:before {\n content: \"\\e067\";\n}\n.glyphicon-move:before {\n content: \"\\e068\";\n}\n.glyphicon-step-backward:before {\n content: \"\\e069\";\n}\n.glyphicon-fast-backward:before {\n content: \"\\e070\";\n}\n.glyphicon-backward:before {\n content: \"\\e071\";\n}\n.glyphicon-play:before {\n content: \"\\e072\";\n}\n.glyphicon-pause:before {\n content: \"\\e073\";\n}\n.glyphicon-stop:before {\n content: \"\\e074\";\n}\n.glyphicon-forward:before {\n content: \"\\e075\";\n}\n.glyphicon-fast-forward:before {\n content: \"\\e076\";\n}\n.glyphicon-step-forward:before {\n content: \"\\e077\";\n}\n.glyphicon-eject:before {\n content: \"\\e078\";\n}\n.glyphicon-chevron-left:before {\n content: \"\\e079\";\n}\n.glyphicon-chevron-right:before {\n content: \"\\e080\";\n}\n.glyphicon-plus-sign:before {\n content: \"\\e081\";\n}\n.glyphicon-minus-sign:before {\n content: \"\\e082\";\n}\n.glyphicon-remove-sign:before {\n content: \"\\e083\";\n}\n.glyphicon-ok-sign:before {\n content: \"\\e084\";\n}\n.glyphicon-question-sign:before {\n content: \"\\e085\";\n}\n.glyphicon-info-sign:before {\n content: \"\\e086\";\n}\n.glyphicon-screenshot:before {\n content: \"\\e087\";\n}\n.glyphicon-remove-circle:before {\n content: \"\\e088\";\n}\n.glyphicon-ok-circle:before {\n content: \"\\e089\";\n}\n.glyphicon-ban-circle:before {\n content: \"\\e090\";\n}\n.glyphicon-arrow-left:before {\n content: \"\\e091\";\n}\n.glyphicon-arrow-right:before {\n content: \"\\e092\";\n}\n.glyphicon-arrow-up:before {\n content: \"\\e093\";\n}\n.glyphicon-arrow-down:before {\n content: \"\\e094\";\n}\n.glyphicon-share-alt:before {\n content: \"\\e095\";\n}\n.glyphicon-resize-full:before {\n content: \"\\e096\";\n}\n.glyphicon-resize-small:before {\n content: \"\\e097\";\n}\n.glyphicon-exclamation-sign:before {\n content: \"\\e101\";\n}\n.glyphicon-gift:before {\n content: \"\\e102\";\n}\n.glyphicon-leaf:before {\n content: \"\\e103\";\n}\n.glyphicon-fire:before {\n content: \"\\e104\";\n}\n.glyphicon-eye-open:before {\n content: \"\\e105\";\n}\n.glyphicon-eye-close:before {\n content: \"\\e106\";\n}\n.glyphicon-warning-sign:before {\n content: \"\\e107\";\n}\n.glyphicon-plane:before {\n content: \"\\e108\";\n}\n.glyphicon-calendar:before {\n content: \"\\e109\";\n}\n.glyphicon-random:before {\n content: \"\\e110\";\n}\n.glyphicon-comment:before {\n content: \"\\e111\";\n}\n.glyphicon-magnet:before {\n content: \"\\e112\";\n}\n.glyphicon-chevron-up:before {\n content: \"\\e113\";\n}\n.glyphicon-chevron-down:before {\n content: \"\\e114\";\n}\n.glyphicon-retweet:before {\n content: \"\\e115\";\n}\n.glyphicon-shopping-cart:before {\n content: \"\\e116\";\n}\n.glyphicon-folder-close:before {\n content: \"\\e117\";\n}\n.glyphicon-folder-open:before {\n content: \"\\e118\";\n}\n.glyphicon-resize-vertical:before {\n content: \"\\e119\";\n}\n.glyphicon-resize-horizontal:before {\n content: \"\\e120\";\n}\n.glyphicon-hdd:before {\n content: \"\\e121\";\n}\n.glyphicon-bullhorn:before {\n content: \"\\e122\";\n}\n.glyphicon-bell:before {\n content: \"\\e123\";\n}\n.glyphicon-certificate:before {\n content: \"\\e124\";\n}\n.glyphicon-thumbs-up:before {\n content: \"\\e125\";\n}\n.glyphicon-thumbs-down:before {\n content: \"\\e126\";\n}\n.glyphicon-hand-right:before {\n content: \"\\e127\";\n}\n.glyphicon-hand-left:before {\n content: \"\\e128\";\n}\n.glyphicon-hand-up:before {\n content: \"\\e129\";\n}\n.glyphicon-hand-down:before {\n content: \"\\e130\";\n}\n.glyphicon-circle-arrow-right:before {\n content: \"\\e131\";\n}\n.glyphicon-circle-arrow-left:before {\n content: \"\\e132\";\n}\n.glyphicon-circle-arrow-up:before {\n content: \"\\e133\";\n}\n.glyphicon-circle-arrow-down:before {\n content: \"\\e134\";\n}\n.glyphicon-globe:before {\n content: \"\\e135\";\n}\n.glyphicon-wrench:before {\n content: \"\\e136\";\n}\n.glyphicon-tasks:before {\n content: \"\\e137\";\n}\n.glyphicon-filter:before {\n content: \"\\e138\";\n}\n.glyphicon-briefcase:before {\n content: \"\\e139\";\n}\n.glyphicon-fullscreen:before {\n content: \"\\e140\";\n}\n.glyphicon-dashboard:before {\n content: \"\\e141\";\n}\n.glyphicon-paperclip:before {\n content: \"\\e142\";\n}\n.glyphicon-heart-empty:before {\n content: \"\\e143\";\n}\n.glyphicon-link:before {\n content: \"\\e144\";\n}\n.glyphicon-phone:before {\n content: \"\\e145\";\n}\n.glyphicon-pushpin:before {\n content: \"\\e146\";\n}\n.glyphicon-usd:before {\n content: \"\\e148\";\n}\n.glyphicon-gbp:before {\n content: \"\\e149\";\n}\n.glyphicon-sort:before {\n content: \"\\e150\";\n}\n.glyphicon-sort-by-alphabet:before {\n content: \"\\e151\";\n}\n.glyphicon-sort-by-alphabet-alt:before {\n content: \"\\e152\";\n}\n.glyphicon-sort-by-order:before {\n content: \"\\e153\";\n}\n.glyphicon-sort-by-order-alt:before {\n content: \"\\e154\";\n}\n.glyphicon-sort-by-attributes:before {\n content: \"\\e155\";\n}\n.glyphicon-sort-by-attributes-alt:before {\n content: \"\\e156\";\n}\n.glyphicon-unchecked:before {\n content: \"\\e157\";\n}\n.glyphicon-expand:before {\n content: \"\\e158\";\n}\n.glyphicon-collapse-down:before {\n content: \"\\e159\";\n}\n.glyphicon-collapse-up:before {\n content: \"\\e160\";\n}\n.glyphicon-log-in:before {\n content: \"\\e161\";\n}\n.glyphicon-flash:before {\n content: \"\\e162\";\n}\n.glyphicon-log-out:before {\n content: \"\\e163\";\n}\n.glyphicon-new-window:before {\n content: \"\\e164\";\n}\n.glyphicon-record:before {\n content: \"\\e165\";\n}\n.glyphicon-save:before {\n content: \"\\e166\";\n}\n.glyphicon-open:before {\n content: \"\\e167\";\n}\n.glyphicon-saved:before {\n content: \"\\e168\";\n}\n.glyphicon-import:before {\n content: \"\\e169\";\n}\n.glyphicon-export:before {\n content: \"\\e170\";\n}\n.glyphicon-send:before {\n content: \"\\e171\";\n}\n.glyphicon-floppy-disk:before {\n content: \"\\e172\";\n}\n.glyphicon-floppy-saved:before {\n content: \"\\e173\";\n}\n.glyphicon-floppy-remove:before {\n content: \"\\e174\";\n}\n.glyphicon-floppy-save:before {\n content: \"\\e175\";\n}\n.glyphicon-floppy-open:before {\n content: \"\\e176\";\n}\n.glyphicon-credit-card:before {\n content: \"\\e177\";\n}\n.glyphicon-transfer:before {\n content: \"\\e178\";\n}\n.glyphicon-cutlery:before {\n content: \"\\e179\";\n}\n.glyphicon-header:before {\n content: \"\\e180\";\n}\n.glyphicon-compressed:before {\n content: \"\\e181\";\n}\n.glyphicon-earphone:before {\n content: \"\\e182\";\n}\n.glyphicon-phone-alt:before {\n content: \"\\e183\";\n}\n.glyphicon-tower:before {\n content: \"\\e184\";\n}\n.glyphicon-stats:before {\n content: \"\\e185\";\n}\n.glyphicon-sd-video:before {\n content: \"\\e186\";\n}\n.glyphicon-hd-video:before {\n content: \"\\e187\";\n}\n.glyphicon-subtitles:before {\n content: \"\\e188\";\n}\n.glyphicon-sound-stereo:before {\n content: \"\\e189\";\n}\n.glyphicon-sound-dolby:before {\n content: \"\\e190\";\n}\n.glyphicon-sound-5-1:before {\n content: \"\\e191\";\n}\n.glyphicon-sound-6-1:before {\n content: \"\\e192\";\n}\n.glyphicon-sound-7-1:before {\n content: \"\\e193\";\n}\n.glyphicon-copyright-mark:before {\n content: \"\\e194\";\n}\n.glyphicon-registration-mark:before {\n content: \"\\e195\";\n}\n.glyphicon-cloud-download:before {\n content: \"\\e197\";\n}\n.glyphicon-cloud-upload:before {\n content: \"\\e198\";\n}\n.glyphicon-tree-conifer:before {\n content: \"\\e199\";\n}\n.glyphicon-tree-deciduous:before {\n content: \"\\e200\";\n}\n.glyphicon-cd:before {\n content: \"\\e201\";\n}\n.glyphicon-save-file:before {\n content: \"\\e202\";\n}\n.glyphicon-open-file:before {\n content: \"\\e203\";\n}\n.glyphicon-level-up:before {\n content: \"\\e204\";\n}\n.glyphicon-copy:before {\n content: \"\\e205\";\n}\n.glyphicon-paste:before {\n content: \"\\e206\";\n}\n.glyphicon-alert:before {\n content: \"\\e209\";\n}\n.glyphicon-equalizer:before {\n content: \"\\e210\";\n}\n.glyphicon-king:before {\n content: \"\\e211\";\n}\n.glyphicon-queen:before {\n content: \"\\e212\";\n}\n.glyphicon-pawn:before {\n content: \"\\e213\";\n}\n.glyphicon-bishop:before {\n content: \"\\e214\";\n}\n.glyphicon-knight:before {\n content: \"\\e215\";\n}\n.glyphicon-baby-formula:before {\n content: \"\\e216\";\n}\n.glyphicon-tent:before {\n content: \"\\26fa\";\n}\n.glyphicon-blackboard:before {\n content: \"\\e218\";\n}\n.glyphicon-bed:before {\n content: \"\\e219\";\n}\n.glyphicon-apple:before {\n content: \"\\f8ff\";\n}\n.glyphicon-erase:before {\n content: \"\\e221\";\n}\n.glyphicon-hourglass:before {\n content: \"\\231b\";\n}\n.glyphicon-lamp:before {\n content: \"\\e223\";\n}\n.glyphicon-duplicate:before {\n content: \"\\e224\";\n}\n.glyphicon-piggy-bank:before {\n content: \"\\e225\";\n}\n.glyphicon-scissors:before {\n content: \"\\e226\";\n}\n.glyphicon-bitcoin:before {\n content: \"\\e227\";\n}\n.glyphicon-btc:before {\n content: \"\\e227\";\n}\n.glyphicon-xbt:before {\n content: \"\\e227\";\n}\n.glyphicon-yen:before {\n content: \"\\00a5\";\n}\n.glyphicon-jpy:before {\n content: \"\\00a5\";\n}\n.glyphicon-ruble:before {\n content: \"\\20bd\";\n}\n.glyphicon-rub:before {\n content: \"\\20bd\";\n}\n.glyphicon-scale:before {\n content: \"\\e230\";\n}\n.glyphicon-ice-lolly:before {\n content: \"\\e231\";\n}\n.glyphicon-ice-lolly-tasted:before {\n content: \"\\e232\";\n}\n.glyphicon-education:before {\n content: \"\\e233\";\n}\n.glyphicon-option-horizontal:before {\n content: \"\\e234\";\n}\n.glyphicon-option-vertical:before {\n content: \"\\e235\";\n}\n.glyphicon-menu-hamburger:before {\n content: \"\\e236\";\n}\n.glyphicon-modal-window:before {\n content: \"\\e237\";\n}\n.glyphicon-oil:before {\n content: \"\\e238\";\n}\n.glyphicon-grain:before {\n content: \"\\e239\";\n}\n.glyphicon-sunglasses:before {\n content: \"\\e240\";\n}\n.glyphicon-text-size:before {\n content: \"\\e241\";\n}\n.glyphicon-text-color:before {\n content: \"\\e242\";\n}\n.glyphicon-text-background:before {\n content: \"\\e243\";\n}\n.glyphicon-object-align-top:before {\n content: \"\\e244\";\n}\n.glyphicon-object-align-bottom:before {\n content: \"\\e245\";\n}\n.glyphicon-object-align-horizontal:before {\n content: \"\\e246\";\n}\n.glyphicon-object-align-left:before {\n content: \"\\e247\";\n}\n.glyphicon-object-align-vertical:before {\n content: \"\\e248\";\n}\n.glyphicon-object-align-right:before {\n content: \"\\e249\";\n}\n.glyphicon-triangle-right:before {\n content: \"\\e250\";\n}\n.glyphicon-triangle-left:before {\n content: \"\\e251\";\n}\n.glyphicon-triangle-bottom:before {\n content: \"\\e252\";\n}\n.glyphicon-triangle-top:before {\n content: \"\\e253\";\n}\n.glyphicon-console:before {\n content: \"\\e254\";\n}\n.glyphicon-superscript:before {\n content: \"\\e255\";\n}\n.glyphicon-subscript:before {\n content: \"\\e256\";\n}\n.glyphicon-menu-left:before {\n content: \"\\e257\";\n}\n.glyphicon-menu-right:before {\n content: \"\\e258\";\n}\n.glyphicon-menu-down:before {\n content: \"\\e259\";\n}\n.glyphicon-menu-up:before {\n content: \"\\e260\";\n}\n* {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n*:before,\n*:after {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\nhtml {\n font-size: 10px;\n\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\nbody {\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 14px;\n line-height: 1.42857143;\n color: #333;\n background-color: #fff;\n}\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\na {\n color: #337ab7;\n text-decoration: none;\n}\na:hover,\na:focus {\n color: #23527c;\n text-decoration: underline;\n}\na:focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\nfigure {\n margin: 0;\n}\nimg {\n vertical-align: middle;\n}\n.img-responsive,\n.thumbnail > img,\n.thumbnail a > img,\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n display: block;\n max-width: 100%;\n height: auto;\n}\n.img-rounded {\n border-radius: 6px;\n}\n.img-thumbnail {\n display: inline-block;\n max-width: 100%;\n height: auto;\n padding: 4px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: all .2s ease-in-out;\n -o-transition: all .2s ease-in-out;\n transition: all .2s ease-in-out;\n}\n.img-circle {\n border-radius: 50%;\n}\nhr {\n margin-top: 20px;\n margin-bottom: 20px;\n border: 0;\n border-top: 1px solid #eee;\n}\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n}\n.sr-only-focusable:active,\n.sr-only-focusable:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n}\n[role=\"button\"] {\n cursor: pointer;\n}\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n font-family: inherit;\n font-weight: 500;\n line-height: 1.1;\n color: inherit;\n}\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small,\n.h1 small,\n.h2 small,\n.h3 small,\n.h4 small,\n.h5 small,\n.h6 small,\nh1 .small,\nh2 .small,\nh3 .small,\nh4 .small,\nh5 .small,\nh6 .small,\n.h1 .small,\n.h2 .small,\n.h3 .small,\n.h4 .small,\n.h5 .small,\n.h6 .small {\n font-weight: normal;\n line-height: 1;\n color: #777;\n}\nh1,\n.h1,\nh2,\n.h2,\nh3,\n.h3 {\n margin-top: 20px;\n margin-bottom: 10px;\n}\nh1 small,\n.h1 small,\nh2 small,\n.h2 small,\nh3 small,\n.h3 small,\nh1 .small,\n.h1 .small,\nh2 .small,\n.h2 .small,\nh3 .small,\n.h3 .small {\n font-size: 65%;\n}\nh4,\n.h4,\nh5,\n.h5,\nh6,\n.h6 {\n margin-top: 10px;\n margin-bottom: 10px;\n}\nh4 small,\n.h4 small,\nh5 small,\n.h5 small,\nh6 small,\n.h6 small,\nh4 .small,\n.h4 .small,\nh5 .small,\n.h5 .small,\nh6 .small,\n.h6 .small {\n font-size: 75%;\n}\nh1,\n.h1 {\n font-size: 36px;\n}\nh2,\n.h2 {\n font-size: 30px;\n}\nh3,\n.h3 {\n font-size: 24px;\n}\nh4,\n.h4 {\n font-size: 18px;\n}\nh5,\n.h5 {\n font-size: 14px;\n}\nh6,\n.h6 {\n font-size: 12px;\n}\np {\n margin: 0 0 10px;\n}\n.lead {\n margin-bottom: 20px;\n font-size: 16px;\n font-weight: 300;\n line-height: 1.4;\n}\n@media (min-width: 768px) {\n .lead {\n font-size: 21px;\n }\n}\nsmall,\n.small {\n font-size: 85%;\n}\nmark,\n.mark {\n padding: .2em;\n background-color: #fcf8e3;\n}\n.text-left {\n text-align: left;\n}\n.text-right {\n text-align: right;\n}\n.text-center {\n text-align: center;\n}\n.text-justify {\n text-align: justify;\n}\n.text-nowrap {\n white-space: nowrap;\n}\n.text-lowercase {\n text-transform: lowercase;\n}\n.text-uppercase {\n text-transform: uppercase;\n}\n.text-capitalize {\n text-transform: capitalize;\n}\n.text-muted {\n color: #777;\n}\n.text-primary {\n color: #337ab7;\n}\na.text-primary:hover,\na.text-primary:focus {\n color: #286090;\n}\n.text-success {\n color: #3c763d;\n}\na.text-success:hover,\na.text-success:focus {\n color: #2b542c;\n}\n.text-info {\n color: #31708f;\n}\na.text-info:hover,\na.text-info:focus {\n color: #245269;\n}\n.text-warning {\n color: #8a6d3b;\n}\na.text-warning:hover,\na.text-warning:focus {\n color: #66512c;\n}\n.text-danger {\n color: #a94442;\n}\na.text-danger:hover,\na.text-danger:focus {\n color: #843534;\n}\n.bg-primary {\n color: #fff;\n background-color: #337ab7;\n}\na.bg-primary:hover,\na.bg-primary:focus {\n background-color: #286090;\n}\n.bg-success {\n background-color: #dff0d8;\n}\na.bg-success:hover,\na.bg-success:focus {\n background-color: #c1e2b3;\n}\n.bg-info {\n background-color: #d9edf7;\n}\na.bg-info:hover,\na.bg-info:focus {\n background-color: #afd9ee;\n}\n.bg-warning {\n background-color: #fcf8e3;\n}\na.bg-warning:hover,\na.bg-warning:focus {\n background-color: #f7ecb5;\n}\n.bg-danger {\n background-color: #f2dede;\n}\na.bg-danger:hover,\na.bg-danger:focus {\n background-color: #e4b9b9;\n}\n.page-header {\n padding-bottom: 9px;\n margin: 40px 0 20px;\n border-bottom: 1px solid #eee;\n}\nul,\nol {\n margin-top: 0;\n margin-bottom: 10px;\n}\nul ul,\nol ul,\nul ol,\nol ol {\n margin-bottom: 0;\n}\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n.list-inline {\n padding-left: 0;\n margin-left: -5px;\n list-style: none;\n}\n.list-inline > li {\n display: inline-block;\n padding-right: 5px;\n padding-left: 5px;\n}\ndl {\n margin-top: 0;\n margin-bottom: 20px;\n}\ndt,\ndd {\n line-height: 1.42857143;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0;\n}\n@media (min-width: 768px) {\n .dl-horizontal dt {\n float: left;\n width: 160px;\n overflow: hidden;\n clear: left;\n text-align: right;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .dl-horizontal dd {\n margin-left: 180px;\n }\n}\nabbr[title],\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted #777;\n}\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\nblockquote {\n padding: 10px 20px;\n margin: 0 0 20px;\n font-size: 17.5px;\n border-left: 5px solid #eee;\n}\nblockquote p:last-child,\nblockquote ul:last-child,\nblockquote ol:last-child {\n margin-bottom: 0;\n}\nblockquote footer,\nblockquote small,\nblockquote .small {\n display: block;\n font-size: 80%;\n line-height: 1.42857143;\n color: #777;\n}\nblockquote footer:before,\nblockquote small:before,\nblockquote .small:before {\n content: '\\2014 \\00A0';\n}\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n text-align: right;\n border-right: 5px solid #eee;\n border-left: 0;\n}\n.blockquote-reverse footer:before,\nblockquote.pull-right footer:before,\n.blockquote-reverse small:before,\nblockquote.pull-right small:before,\n.blockquote-reverse .small:before,\nblockquote.pull-right .small:before {\n content: '';\n}\n.blockquote-reverse footer:after,\nblockquote.pull-right footer:after,\n.blockquote-reverse small:after,\nblockquote.pull-right small:after,\n.blockquote-reverse .small:after,\nblockquote.pull-right .small:after {\n content: '\\00A0 \\2014';\n}\naddress {\n margin-bottom: 20px;\n font-style: normal;\n line-height: 1.42857143;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: Menlo, Monaco, Consolas, \"Courier New\", monospace;\n}\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: #c7254e;\n background-color: #f9f2f4;\n border-radius: 4px;\n}\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: #fff;\n background-color: #333;\n border-radius: 3px;\n -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25);\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25);\n}\nkbd kbd {\n padding: 0;\n font-size: 100%;\n font-weight: bold;\n -webkit-box-shadow: none;\n box-shadow: none;\n}\npre {\n display: block;\n padding: 9.5px;\n margin: 0 0 10px;\n font-size: 13px;\n line-height: 1.42857143;\n color: #333;\n word-break: break-all;\n word-wrap: break-word;\n background-color: #f5f5f5;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\npre code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n}\n.pre-scrollable {\n max-height: 340px;\n overflow-y: scroll;\n}\n.container {\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n@media (min-width: 768px) {\n .container {\n width: 750px;\n }\n}\n@media (min-width: 992px) {\n .container {\n width: 970px;\n }\n}\n@media (min-width: 1200px) {\n .container {\n width: 1170px;\n }\n}\n.container-fluid {\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n.row {\n margin-right: -15px;\n margin-left: -15px;\n}\n.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {\n position: relative;\n min-height: 1px;\n padding-right: 15px;\n padding-left: 15px;\n}\n.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {\n float: left;\n}\n.col-xs-12 {\n width: 100%;\n}\n.col-xs-11 {\n width: 91.66666667%;\n}\n.col-xs-10 {\n width: 83.33333333%;\n}\n.col-xs-9 {\n width: 75%;\n}\n.col-xs-8 {\n width: 66.66666667%;\n}\n.col-xs-7 {\n width: 58.33333333%;\n}\n.col-xs-6 {\n width: 50%;\n}\n.col-xs-5 {\n width: 41.66666667%;\n}\n.col-xs-4 {\n width: 33.33333333%;\n}\n.col-xs-3 {\n width: 25%;\n}\n.col-xs-2 {\n width: 16.66666667%;\n}\n.col-xs-1 {\n width: 8.33333333%;\n}\n.col-xs-pull-12 {\n right: 100%;\n}\n.col-xs-pull-11 {\n right: 91.66666667%;\n}\n.col-xs-pull-10 {\n right: 83.33333333%;\n}\n.col-xs-pull-9 {\n right: 75%;\n}\n.col-xs-pull-8 {\n right: 66.66666667%;\n}\n.col-xs-pull-7 {\n right: 58.33333333%;\n}\n.col-xs-pull-6 {\n right: 50%;\n}\n.col-xs-pull-5 {\n right: 41.66666667%;\n}\n.col-xs-pull-4 {\n right: 33.33333333%;\n}\n.col-xs-pull-3 {\n right: 25%;\n}\n.col-xs-pull-2 {\n right: 16.66666667%;\n}\n.col-xs-pull-1 {\n right: 8.33333333%;\n}\n.col-xs-pull-0 {\n right: auto;\n}\n.col-xs-push-12 {\n left: 100%;\n}\n.col-xs-push-11 {\n left: 91.66666667%;\n}\n.col-xs-push-10 {\n left: 83.33333333%;\n}\n.col-xs-push-9 {\n left: 75%;\n}\n.col-xs-push-8 {\n left: 66.66666667%;\n}\n.col-xs-push-7 {\n left: 58.33333333%;\n}\n.col-xs-push-6 {\n left: 50%;\n}\n.col-xs-push-5 {\n left: 41.66666667%;\n}\n.col-xs-push-4 {\n left: 33.33333333%;\n}\n.col-xs-push-3 {\n left: 25%;\n}\n.col-xs-push-2 {\n left: 16.66666667%;\n}\n.col-xs-push-1 {\n left: 8.33333333%;\n}\n.col-xs-push-0 {\n left: auto;\n}\n.col-xs-offset-12 {\n margin-left: 100%;\n}\n.col-xs-offset-11 {\n margin-left: 91.66666667%;\n}\n.col-xs-offset-10 {\n margin-left: 83.33333333%;\n}\n.col-xs-offset-9 {\n margin-left: 75%;\n}\n.col-xs-offset-8 {\n margin-left: 66.66666667%;\n}\n.col-xs-offset-7 {\n margin-left: 58.33333333%;\n}\n.col-xs-offset-6 {\n margin-left: 50%;\n}\n.col-xs-offset-5 {\n margin-left: 41.66666667%;\n}\n.col-xs-offset-4 {\n margin-left: 33.33333333%;\n}\n.col-xs-offset-3 {\n margin-left: 25%;\n}\n.col-xs-offset-2 {\n margin-left: 16.66666667%;\n}\n.col-xs-offset-1 {\n margin-left: 8.33333333%;\n}\n.col-xs-offset-0 {\n margin-left: 0;\n}\n@media (min-width: 768px) {\n .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {\n float: left;\n }\n .col-sm-12 {\n width: 100%;\n }\n .col-sm-11 {\n width: 91.66666667%;\n }\n .col-sm-10 {\n width: 83.33333333%;\n }\n .col-sm-9 {\n width: 75%;\n }\n .col-sm-8 {\n width: 66.66666667%;\n }\n .col-sm-7 {\n width: 58.33333333%;\n }\n .col-sm-6 {\n width: 50%;\n }\n .col-sm-5 {\n width: 41.66666667%;\n }\n .col-sm-4 {\n width: 33.33333333%;\n }\n .col-sm-3 {\n width: 25%;\n }\n .col-sm-2 {\n width: 16.66666667%;\n }\n .col-sm-1 {\n width: 8.33333333%;\n }\n .col-sm-pull-12 {\n right: 100%;\n }\n .col-sm-pull-11 {\n right: 91.66666667%;\n }\n .col-sm-pull-10 {\n right: 83.33333333%;\n }\n .col-sm-pull-9 {\n right: 75%;\n }\n .col-sm-pull-8 {\n right: 66.66666667%;\n }\n .col-sm-pull-7 {\n right: 58.33333333%;\n }\n .col-sm-pull-6 {\n right: 50%;\n }\n .col-sm-pull-5 {\n right: 41.66666667%;\n }\n .col-sm-pull-4 {\n right: 33.33333333%;\n }\n .col-sm-pull-3 {\n right: 25%;\n }\n .col-sm-pull-2 {\n right: 16.66666667%;\n }\n .col-sm-pull-1 {\n right: 8.33333333%;\n }\n .col-sm-pull-0 {\n right: auto;\n }\n .col-sm-push-12 {\n left: 100%;\n }\n .col-sm-push-11 {\n left: 91.66666667%;\n }\n .col-sm-push-10 {\n left: 83.33333333%;\n }\n .col-sm-push-9 {\n left: 75%;\n }\n .col-sm-push-8 {\n left: 66.66666667%;\n }\n .col-sm-push-7 {\n left: 58.33333333%;\n }\n .col-sm-push-6 {\n left: 50%;\n }\n .col-sm-push-5 {\n left: 41.66666667%;\n }\n .col-sm-push-4 {\n left: 33.33333333%;\n }\n .col-sm-push-3 {\n left: 25%;\n }\n .col-sm-push-2 {\n left: 16.66666667%;\n }\n .col-sm-push-1 {\n left: 8.33333333%;\n }\n .col-sm-push-0 {\n left: auto;\n }\n .col-sm-offset-12 {\n margin-left: 100%;\n }\n .col-sm-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-sm-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-sm-offset-9 {\n margin-left: 75%;\n }\n .col-sm-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-sm-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-sm-offset-6 {\n margin-left: 50%;\n }\n .col-sm-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-sm-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-sm-offset-3 {\n margin-left: 25%;\n }\n .col-sm-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-sm-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-sm-offset-0 {\n margin-left: 0;\n }\n}\n@media (min-width: 992px) {\n .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {\n float: left;\n }\n .col-md-12 {\n width: 100%;\n }\n .col-md-11 {\n width: 91.66666667%;\n }\n .col-md-10 {\n width: 83.33333333%;\n }\n .col-md-9 {\n width: 75%;\n }\n .col-md-8 {\n width: 66.66666667%;\n }\n .col-md-7 {\n width: 58.33333333%;\n }\n .col-md-6 {\n width: 50%;\n }\n .col-md-5 {\n width: 41.66666667%;\n }\n .col-md-4 {\n width: 33.33333333%;\n }\n .col-md-3 {\n width: 25%;\n }\n .col-md-2 {\n width: 16.66666667%;\n }\n .col-md-1 {\n width: 8.33333333%;\n }\n .col-md-pull-12 {\n right: 100%;\n }\n .col-md-pull-11 {\n right: 91.66666667%;\n }\n .col-md-pull-10 {\n right: 83.33333333%;\n }\n .col-md-pull-9 {\n right: 75%;\n }\n .col-md-pull-8 {\n right: 66.66666667%;\n }\n .col-md-pull-7 {\n right: 58.33333333%;\n }\n .col-md-pull-6 {\n right: 50%;\n }\n .col-md-pull-5 {\n right: 41.66666667%;\n }\n .col-md-pull-4 {\n right: 33.33333333%;\n }\n .col-md-pull-3 {\n right: 25%;\n }\n .col-md-pull-2 {\n right: 16.66666667%;\n }\n .col-md-pull-1 {\n right: 8.33333333%;\n }\n .col-md-pull-0 {\n right: auto;\n }\n .col-md-push-12 {\n left: 100%;\n }\n .col-md-push-11 {\n left: 91.66666667%;\n }\n .col-md-push-10 {\n left: 83.33333333%;\n }\n .col-md-push-9 {\n left: 75%;\n }\n .col-md-push-8 {\n left: 66.66666667%;\n }\n .col-md-push-7 {\n left: 58.33333333%;\n }\n .col-md-push-6 {\n left: 50%;\n }\n .col-md-push-5 {\n left: 41.66666667%;\n }\n .col-md-push-4 {\n left: 33.33333333%;\n }\n .col-md-push-3 {\n left: 25%;\n }\n .col-md-push-2 {\n left: 16.66666667%;\n }\n .col-md-push-1 {\n left: 8.33333333%;\n }\n .col-md-push-0 {\n left: auto;\n }\n .col-md-offset-12 {\n margin-left: 100%;\n }\n .col-md-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-md-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-md-offset-9 {\n margin-left: 75%;\n }\n .col-md-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-md-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-md-offset-6 {\n margin-left: 50%;\n }\n .col-md-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-md-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-md-offset-3 {\n margin-left: 25%;\n }\n .col-md-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-md-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-md-offset-0 {\n margin-left: 0;\n }\n}\n@media (min-width: 1200px) {\n .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {\n float: left;\n }\n .col-lg-12 {\n width: 100%;\n }\n .col-lg-11 {\n width: 91.66666667%;\n }\n .col-lg-10 {\n width: 83.33333333%;\n }\n .col-lg-9 {\n width: 75%;\n }\n .col-lg-8 {\n width: 66.66666667%;\n }\n .col-lg-7 {\n width: 58.33333333%;\n }\n .col-lg-6 {\n width: 50%;\n }\n .col-lg-5 {\n width: 41.66666667%;\n }\n .col-lg-4 {\n width: 33.33333333%;\n }\n .col-lg-3 {\n width: 25%;\n }\n .col-lg-2 {\n width: 16.66666667%;\n }\n .col-lg-1 {\n width: 8.33333333%;\n }\n .col-lg-pull-12 {\n right: 100%;\n }\n .col-lg-pull-11 {\n right: 91.66666667%;\n }\n .col-lg-pull-10 {\n right: 83.33333333%;\n }\n .col-lg-pull-9 {\n right: 75%;\n }\n .col-lg-pull-8 {\n right: 66.66666667%;\n }\n .col-lg-pull-7 {\n right: 58.33333333%;\n }\n .col-lg-pull-6 {\n right: 50%;\n }\n .col-lg-pull-5 {\n right: 41.66666667%;\n }\n .col-lg-pull-4 {\n right: 33.33333333%;\n }\n .col-lg-pull-3 {\n right: 25%;\n }\n .col-lg-pull-2 {\n right: 16.66666667%;\n }\n .col-lg-pull-1 {\n right: 8.33333333%;\n }\n .col-lg-pull-0 {\n right: auto;\n }\n .col-lg-push-12 {\n left: 100%;\n }\n .col-lg-push-11 {\n left: 91.66666667%;\n }\n .col-lg-push-10 {\n left: 83.33333333%;\n }\n .col-lg-push-9 {\n left: 75%;\n }\n .col-lg-push-8 {\n left: 66.66666667%;\n }\n .col-lg-push-7 {\n left: 58.33333333%;\n }\n .col-lg-push-6 {\n left: 50%;\n }\n .col-lg-push-5 {\n left: 41.66666667%;\n }\n .col-lg-push-4 {\n left: 33.33333333%;\n }\n .col-lg-push-3 {\n left: 25%;\n }\n .col-lg-push-2 {\n left: 16.66666667%;\n }\n .col-lg-push-1 {\n left: 8.33333333%;\n }\n .col-lg-push-0 {\n left: auto;\n }\n .col-lg-offset-12 {\n margin-left: 100%;\n }\n .col-lg-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-lg-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-lg-offset-9 {\n margin-left: 75%;\n }\n .col-lg-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-lg-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-lg-offset-6 {\n margin-left: 50%;\n }\n .col-lg-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-lg-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-lg-offset-3 {\n margin-left: 25%;\n }\n .col-lg-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-lg-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-lg-offset-0 {\n margin-left: 0;\n }\n}\ntable {\n background-color: transparent;\n}\ncaption {\n padding-top: 8px;\n padding-bottom: 8px;\n color: #777;\n text-align: left;\n}\nth {\n text-align: left;\n}\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: 20px;\n}\n.table > thead > tr > th,\n.table > tbody > tr > th,\n.table > tfoot > tr > th,\n.table > thead > tr > td,\n.table > tbody > tr > td,\n.table > tfoot > tr > td {\n padding: 8px;\n line-height: 1.42857143;\n vertical-align: top;\n border-top: 1px solid #ddd;\n}\n.table > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid #ddd;\n}\n.table > caption + thead > tr:first-child > th,\n.table > colgroup + thead > tr:first-child > th,\n.table > thead:first-child > tr:first-child > th,\n.table > caption + thead > tr:first-child > td,\n.table > colgroup + thead > tr:first-child > td,\n.table > thead:first-child > tr:first-child > td {\n border-top: 0;\n}\n.table > tbody + tbody {\n border-top: 2px solid #ddd;\n}\n.table .table {\n background-color: #fff;\n}\n.table-condensed > thead > tr > th,\n.table-condensed > tbody > tr > th,\n.table-condensed > tfoot > tr > th,\n.table-condensed > thead > tr > td,\n.table-condensed > tbody > tr > td,\n.table-condensed > tfoot > tr > td {\n padding: 5px;\n}\n.table-bordered {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > tbody > tr > th,\n.table-bordered > tfoot > tr > th,\n.table-bordered > thead > tr > td,\n.table-bordered > tbody > tr > td,\n.table-bordered > tfoot > tr > td {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > thead > tr > td {\n border-bottom-width: 2px;\n}\n.table-striped > tbody > tr:nth-of-type(odd) {\n background-color: #f9f9f9;\n}\n.table-hover > tbody > tr:hover {\n background-color: #f5f5f5;\n}\ntable col[class*=\"col-\"] {\n position: static;\n display: table-column;\n float: none;\n}\ntable td[class*=\"col-\"],\ntable th[class*=\"col-\"] {\n position: static;\n display: table-cell;\n float: none;\n}\n.table > thead > tr > td.active,\n.table > tbody > tr > td.active,\n.table > tfoot > tr > td.active,\n.table > thead > tr > th.active,\n.table > tbody > tr > th.active,\n.table > tfoot > tr > th.active,\n.table > thead > tr.active > td,\n.table > tbody > tr.active > td,\n.table > tfoot > tr.active > td,\n.table > thead > tr.active > th,\n.table > tbody > tr.active > th,\n.table > tfoot > tr.active > th {\n background-color: #f5f5f5;\n}\n.table-hover > tbody > tr > td.active:hover,\n.table-hover > tbody > tr > th.active:hover,\n.table-hover > tbody > tr.active:hover > td,\n.table-hover > tbody > tr:hover > .active,\n.table-hover > tbody > tr.active:hover > th {\n background-color: #e8e8e8;\n}\n.table > thead > tr > td.success,\n.table > tbody > tr > td.success,\n.table > tfoot > tr > td.success,\n.table > thead > tr > th.success,\n.table > tbody > tr > th.success,\n.table > tfoot > tr > th.success,\n.table > thead > tr.success > td,\n.table > tbody > tr.success > td,\n.table > tfoot > tr.success > td,\n.table > thead > tr.success > th,\n.table > tbody > tr.success > th,\n.table > tfoot > tr.success > th {\n background-color: #dff0d8;\n}\n.table-hover > tbody > tr > td.success:hover,\n.table-hover > tbody > tr > th.success:hover,\n.table-hover > tbody > tr.success:hover > td,\n.table-hover > tbody > tr:hover > .success,\n.table-hover > tbody > tr.success:hover > th {\n background-color: #d0e9c6;\n}\n.table > thead > tr > td.info,\n.table > tbody > tr > td.info,\n.table > tfoot > tr > td.info,\n.table > thead > tr > th.info,\n.table > tbody > tr > th.info,\n.table > tfoot > tr > th.info,\n.table > thead > tr.info > td,\n.table > tbody > tr.info > td,\n.table > tfoot > tr.info > td,\n.table > thead > tr.info > th,\n.table > tbody > tr.info > th,\n.table > tfoot > tr.info > th {\n background-color: #d9edf7;\n}\n.table-hover > tbody > tr > td.info:hover,\n.table-hover > tbody > tr > th.info:hover,\n.table-hover > tbody > tr.info:hover > td,\n.table-hover > tbody > tr:hover > .info,\n.table-hover > tbody > tr.info:hover > th {\n background-color: #c4e3f3;\n}\n.table > thead > tr > td.warning,\n.table > tbody > tr > td.warning,\n.table > tfoot > tr > td.warning,\n.table > thead > tr > th.warning,\n.table > tbody > tr > th.warning,\n.table > tfoot > tr > th.warning,\n.table > thead > tr.warning > td,\n.table > tbody > tr.warning > td,\n.table > tfoot > tr.warning > td,\n.table > thead > tr.warning > th,\n.table > tbody > tr.warning > th,\n.table > tfoot > tr.warning > th {\n background-color: #fcf8e3;\n}\n.table-hover > tbody > tr > td.warning:hover,\n.table-hover > tbody > tr > th.warning:hover,\n.table-hover > tbody > tr.warning:hover > td,\n.table-hover > tbody > tr:hover > .warning,\n.table-hover > tbody > tr.warning:hover > th {\n background-color: #faf2cc;\n}\n.table > thead > tr > td.danger,\n.table > tbody > tr > td.danger,\n.table > tfoot > tr > td.danger,\n.table > thead > tr > th.danger,\n.table > tbody > tr > th.danger,\n.table > tfoot > tr > th.danger,\n.table > thead > tr.danger > td,\n.table > tbody > tr.danger > td,\n.table > tfoot > tr.danger > td,\n.table > thead > tr.danger > th,\n.table > tbody > tr.danger > th,\n.table > tfoot > tr.danger > th {\n background-color: #f2dede;\n}\n.table-hover > tbody > tr > td.danger:hover,\n.table-hover > tbody > tr > th.danger:hover,\n.table-hover > tbody > tr.danger:hover > td,\n.table-hover > tbody > tr:hover > .danger,\n.table-hover > tbody > tr.danger:hover > th {\n background-color: #ebcccc;\n}\n.table-responsive {\n min-height: .01%;\n overflow-x: auto;\n}\n@media screen and (max-width: 767px) {\n .table-responsive {\n width: 100%;\n margin-bottom: 15px;\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid #ddd;\n }\n .table-responsive > .table {\n margin-bottom: 0;\n }\n .table-responsive > .table > thead > tr > th,\n .table-responsive > .table > tbody > tr > th,\n .table-responsive > .table > tfoot > tr > th,\n .table-responsive > .table > thead > tr > td,\n .table-responsive > .table > tbody > tr > td,\n .table-responsive > .table > tfoot > tr > td {\n white-space: nowrap;\n }\n .table-responsive > .table-bordered {\n border: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:first-child,\n .table-responsive > .table-bordered > tbody > tr > th:first-child,\n .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n .table-responsive > .table-bordered > thead > tr > td:first-child,\n .table-responsive > .table-bordered > tbody > tr > td:first-child,\n .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:last-child,\n .table-responsive > .table-bordered > tbody > tr > th:last-child,\n .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n .table-responsive > .table-bordered > thead > tr > td:last-child,\n .table-responsive > .table-bordered > tbody > tr > td:last-child,\n .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n }\n .table-responsive > .table-bordered > tbody > tr:last-child > th,\n .table-responsive > .table-bordered > tfoot > tr:last-child > th,\n .table-responsive > .table-bordered > tbody > tr:last-child > td,\n .table-responsive > .table-bordered > tfoot > tr:last-child > td {\n border-bottom: 0;\n }\n}\nfieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: 20px;\n font-size: 21px;\n line-height: inherit;\n color: #333;\n border: 0;\n border-bottom: 1px solid #e5e5e5;\n}\nlabel {\n display: inline-block;\n max-width: 100%;\n margin-bottom: 5px;\n font-weight: bold;\n}\ninput[type=\"search\"] {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9;\n line-height: normal;\n}\ninput[type=\"file\"] {\n display: block;\n}\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\nselect[multiple],\nselect[size] {\n height: auto;\n}\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\noutput {\n display: block;\n padding-top: 7px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555;\n}\n.form-control {\n display: block;\n width: 100%;\n height: 34px;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555;\n background-color: #fff;\n background-image: none;\n border: 1px solid #ccc;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;\n -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n}\n.form-control:focus {\n border-color: #66afe9;\n outline: 0;\n -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);\n box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);\n}\n.form-control::-moz-placeholder {\n color: #999;\n opacity: 1;\n}\n.form-control:-ms-input-placeholder {\n color: #999;\n}\n.form-control::-webkit-input-placeholder {\n color: #999;\n}\n.form-control::-ms-expand {\n background-color: transparent;\n border: 0;\n}\n.form-control[disabled],\n.form-control[readonly],\nfieldset[disabled] .form-control {\n background-color: #eee;\n opacity: 1;\n}\n.form-control[disabled],\nfieldset[disabled] .form-control {\n cursor: not-allowed;\n}\ntextarea.form-control {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: none;\n}\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n input[type=\"date\"].form-control,\n input[type=\"time\"].form-control,\n input[type=\"datetime-local\"].form-control,\n input[type=\"month\"].form-control {\n line-height: 34px;\n }\n input[type=\"date\"].input-sm,\n input[type=\"time\"].input-sm,\n input[type=\"datetime-local\"].input-sm,\n input[type=\"month\"].input-sm,\n .input-group-sm input[type=\"date\"],\n .input-group-sm input[type=\"time\"],\n .input-group-sm input[type=\"datetime-local\"],\n .input-group-sm input[type=\"month\"] {\n line-height: 30px;\n }\n input[type=\"date\"].input-lg,\n input[type=\"time\"].input-lg,\n input[type=\"datetime-local\"].input-lg,\n input[type=\"month\"].input-lg,\n .input-group-lg input[type=\"date\"],\n .input-group-lg input[type=\"time\"],\n .input-group-lg input[type=\"datetime-local\"],\n .input-group-lg input[type=\"month\"] {\n line-height: 46px;\n }\n}\n.form-group {\n margin-bottom: 15px;\n}\n.radio,\n.checkbox {\n position: relative;\n display: block;\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.radio label,\n.checkbox label {\n min-height: 20px;\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: normal;\n cursor: pointer;\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n position: absolute;\n margin-top: 4px \\9;\n margin-left: -20px;\n}\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px;\n}\n.radio-inline,\n.checkbox-inline {\n position: relative;\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: normal;\n vertical-align: middle;\n cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px;\n}\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"].disabled,\ninput[type=\"checkbox\"].disabled,\nfieldset[disabled] input[type=\"radio\"],\nfieldset[disabled] input[type=\"checkbox\"] {\n cursor: not-allowed;\n}\n.radio-inline.disabled,\n.checkbox-inline.disabled,\nfieldset[disabled] .radio-inline,\nfieldset[disabled] .checkbox-inline {\n cursor: not-allowed;\n}\n.radio.disabled label,\n.checkbox.disabled label,\nfieldset[disabled] .radio label,\nfieldset[disabled] .checkbox label {\n cursor: not-allowed;\n}\n.form-control-static {\n min-height: 34px;\n padding-top: 7px;\n padding-bottom: 7px;\n margin-bottom: 0;\n}\n.form-control-static.input-lg,\n.form-control-static.input-sm {\n padding-right: 0;\n padding-left: 0;\n}\n.input-sm {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-sm {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-sm,\nselect[multiple].input-sm {\n height: auto;\n}\n.form-group-sm .form-control {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.form-group-sm select.form-control {\n height: 30px;\n line-height: 30px;\n}\n.form-group-sm textarea.form-control,\n.form-group-sm select[multiple].form-control {\n height: auto;\n}\n.form-group-sm .form-control-static {\n height: 30px;\n min-height: 32px;\n padding: 6px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.input-lg {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-lg {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-lg,\nselect[multiple].input-lg {\n height: auto;\n}\n.form-group-lg .form-control {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.form-group-lg select.form-control {\n height: 46px;\n line-height: 46px;\n}\n.form-group-lg textarea.form-control,\n.form-group-lg select[multiple].form-control {\n height: auto;\n}\n.form-group-lg .form-control-static {\n height: 46px;\n min-height: 38px;\n padding: 11px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.has-feedback {\n position: relative;\n}\n.has-feedback .form-control {\n padding-right: 42.5px;\n}\n.form-control-feedback {\n position: absolute;\n top: 0;\n right: 0;\n z-index: 2;\n display: block;\n width: 34px;\n height: 34px;\n line-height: 34px;\n text-align: center;\n pointer-events: none;\n}\n.input-lg + .form-control-feedback,\n.input-group-lg + .form-control-feedback,\n.form-group-lg .form-control + .form-control-feedback {\n width: 46px;\n height: 46px;\n line-height: 46px;\n}\n.input-sm + .form-control-feedback,\n.input-group-sm + .form-control-feedback,\n.form-group-sm .form-control + .form-control-feedback {\n width: 30px;\n height: 30px;\n line-height: 30px;\n}\n.has-success .help-block,\n.has-success .control-label,\n.has-success .radio,\n.has-success .checkbox,\n.has-success .radio-inline,\n.has-success .checkbox-inline,\n.has-success.radio label,\n.has-success.checkbox label,\n.has-success.radio-inline label,\n.has-success.checkbox-inline label {\n color: #3c763d;\n}\n.has-success .form-control {\n border-color: #3c763d;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n}\n.has-success .form-control:focus {\n border-color: #2b542c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168;\n}\n.has-success .input-group-addon {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #3c763d;\n}\n.has-success .form-control-feedback {\n color: #3c763d;\n}\n.has-warning .help-block,\n.has-warning .control-label,\n.has-warning .radio,\n.has-warning .checkbox,\n.has-warning .radio-inline,\n.has-warning .checkbox-inline,\n.has-warning.radio label,\n.has-warning.checkbox label,\n.has-warning.radio-inline label,\n.has-warning.checkbox-inline label {\n color: #8a6d3b;\n}\n.has-warning .form-control {\n border-color: #8a6d3b;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n}\n.has-warning .form-control:focus {\n border-color: #66512c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b;\n}\n.has-warning .input-group-addon {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #8a6d3b;\n}\n.has-warning .form-control-feedback {\n color: #8a6d3b;\n}\n.has-error .help-block,\n.has-error .control-label,\n.has-error .radio,\n.has-error .checkbox,\n.has-error .radio-inline,\n.has-error .checkbox-inline,\n.has-error.radio label,\n.has-error.checkbox label,\n.has-error.radio-inline label,\n.has-error.checkbox-inline label {\n color: #a94442;\n}\n.has-error .form-control {\n border-color: #a94442;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n}\n.has-error .form-control:focus {\n border-color: #843534;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483;\n}\n.has-error .input-group-addon {\n color: #a94442;\n background-color: #f2dede;\n border-color: #a94442;\n}\n.has-error .form-control-feedback {\n color: #a94442;\n}\n.has-feedback label ~ .form-control-feedback {\n top: 25px;\n}\n.has-feedback label.sr-only ~ .form-control-feedback {\n top: 0;\n}\n.help-block {\n display: block;\n margin-top: 5px;\n margin-bottom: 10px;\n color: #737373;\n}\n@media (min-width: 768px) {\n .form-inline .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .form-inline .form-control-static {\n display: inline-block;\n }\n .form-inline .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .form-inline .input-group .input-group-addon,\n .form-inline .input-group .input-group-btn,\n .form-inline .input-group .form-control {\n width: auto;\n }\n .form-inline .input-group > .form-control {\n width: 100%;\n }\n .form-inline .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio,\n .form-inline .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio label,\n .form-inline .checkbox label {\n padding-left: 0;\n }\n .form-inline .radio input[type=\"radio\"],\n .form-inline .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .form-inline .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox,\n.form-horizontal .radio-inline,\n.form-horizontal .checkbox-inline {\n padding-top: 7px;\n margin-top: 0;\n margin-bottom: 0;\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox {\n min-height: 27px;\n}\n.form-horizontal .form-group {\n margin-right: -15px;\n margin-left: -15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .control-label {\n padding-top: 7px;\n margin-bottom: 0;\n text-align: right;\n }\n}\n.form-horizontal .has-feedback .form-control-feedback {\n right: 15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-lg .control-label {\n padding-top: 11px;\n font-size: 18px;\n }\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-sm .control-label {\n padding-top: 6px;\n font-size: 12px;\n }\n}\n.btn {\n display: inline-block;\n padding: 6px 12px;\n margin-bottom: 0;\n font-size: 14px;\n font-weight: normal;\n line-height: 1.42857143;\n text-align: center;\n white-space: nowrap;\n vertical-align: middle;\n -ms-touch-action: manipulation;\n touch-action: manipulation;\n cursor: pointer;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n background-image: none;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.btn:focus,\n.btn:active:focus,\n.btn.active:focus,\n.btn.focus,\n.btn:active.focus,\n.btn.active.focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n.btn:hover,\n.btn:focus,\n.btn.focus {\n color: #333;\n text-decoration: none;\n}\n.btn:active,\n.btn.active {\n background-image: none;\n outline: 0;\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);\n}\n.btn.disabled,\n.btn[disabled],\nfieldset[disabled] .btn {\n cursor: not-allowed;\n filter: alpha(opacity=65);\n -webkit-box-shadow: none;\n box-shadow: none;\n opacity: .65;\n}\na.btn.disabled,\nfieldset[disabled] a.btn {\n pointer-events: none;\n}\n.btn-default {\n color: #333;\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default:focus,\n.btn-default.focus {\n color: #333;\n background-color: #e6e6e6;\n border-color: #8c8c8c;\n}\n.btn-default:hover {\n color: #333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n color: #333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active:hover,\n.btn-default.active:hover,\n.open > .dropdown-toggle.btn-default:hover,\n.btn-default:active:focus,\n.btn-default.active:focus,\n.open > .dropdown-toggle.btn-default:focus,\n.btn-default:active.focus,\n.btn-default.active.focus,\n.open > .dropdown-toggle.btn-default.focus {\n color: #333;\n background-color: #d4d4d4;\n border-color: #8c8c8c;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n background-image: none;\n}\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus {\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default .badge {\n color: #fff;\n background-color: #333;\n}\n.btn-primary {\n color: #fff;\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary:focus,\n.btn-primary.focus {\n color: #fff;\n background-color: #286090;\n border-color: #122b40;\n}\n.btn-primary:hover {\n color: #fff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n color: #fff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active:hover,\n.btn-primary.active:hover,\n.open > .dropdown-toggle.btn-primary:hover,\n.btn-primary:active:focus,\n.btn-primary.active:focus,\n.open > .dropdown-toggle.btn-primary:focus,\n.btn-primary:active.focus,\n.btn-primary.active.focus,\n.open > .dropdown-toggle.btn-primary.focus {\n color: #fff;\n background-color: #204d74;\n border-color: #122b40;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n background-image: none;\n}\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus {\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.btn-success {\n color: #fff;\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success:focus,\n.btn-success.focus {\n color: #fff;\n background-color: #449d44;\n border-color: #255625;\n}\n.btn-success:hover {\n color: #fff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n color: #fff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active:hover,\n.btn-success.active:hover,\n.open > .dropdown-toggle.btn-success:hover,\n.btn-success:active:focus,\n.btn-success.active:focus,\n.open > .dropdown-toggle.btn-success:focus,\n.btn-success:active.focus,\n.btn-success.active.focus,\n.open > .dropdown-toggle.btn-success.focus {\n color: #fff;\n background-color: #398439;\n border-color: #255625;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n background-image: none;\n}\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus {\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success .badge {\n color: #5cb85c;\n background-color: #fff;\n}\n.btn-info {\n color: #fff;\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info:focus,\n.btn-info.focus {\n color: #fff;\n background-color: #31b0d5;\n border-color: #1b6d85;\n}\n.btn-info:hover {\n color: #fff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n color: #fff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active:hover,\n.btn-info.active:hover,\n.open > .dropdown-toggle.btn-info:hover,\n.btn-info:active:focus,\n.btn-info.active:focus,\n.open > .dropdown-toggle.btn-info:focus,\n.btn-info:active.focus,\n.btn-info.active.focus,\n.open > .dropdown-toggle.btn-info.focus {\n color: #fff;\n background-color: #269abc;\n border-color: #1b6d85;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n background-image: none;\n}\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus {\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info .badge {\n color: #5bc0de;\n background-color: #fff;\n}\n.btn-warning {\n color: #fff;\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning:focus,\n.btn-warning.focus {\n color: #fff;\n background-color: #ec971f;\n border-color: #985f0d;\n}\n.btn-warning:hover {\n color: #fff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n color: #fff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active:hover,\n.btn-warning.active:hover,\n.open > .dropdown-toggle.btn-warning:hover,\n.btn-warning:active:focus,\n.btn-warning.active:focus,\n.open > .dropdown-toggle.btn-warning:focus,\n.btn-warning:active.focus,\n.btn-warning.active.focus,\n.open > .dropdown-toggle.btn-warning.focus {\n color: #fff;\n background-color: #d58512;\n border-color: #985f0d;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n background-image: none;\n}\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus {\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning .badge {\n color: #f0ad4e;\n background-color: #fff;\n}\n.btn-danger {\n color: #fff;\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger:focus,\n.btn-danger.focus {\n color: #fff;\n background-color: #c9302c;\n border-color: #761c19;\n}\n.btn-danger:hover {\n color: #fff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n color: #fff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active:hover,\n.btn-danger.active:hover,\n.open > .dropdown-toggle.btn-danger:hover,\n.btn-danger:active:focus,\n.btn-danger.active:focus,\n.open > .dropdown-toggle.btn-danger:focus,\n.btn-danger:active.focus,\n.btn-danger.active.focus,\n.open > .dropdown-toggle.btn-danger.focus {\n color: #fff;\n background-color: #ac2925;\n border-color: #761c19;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n background-image: none;\n}\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus {\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger .badge {\n color: #d9534f;\n background-color: #fff;\n}\n.btn-link {\n font-weight: normal;\n color: #337ab7;\n border-radius: 0;\n}\n.btn-link,\n.btn-link:active,\n.btn-link.active,\n.btn-link[disabled],\nfieldset[disabled] .btn-link {\n background-color: transparent;\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-link,\n.btn-link:hover,\n.btn-link:focus,\n.btn-link:active {\n border-color: transparent;\n}\n.btn-link:hover,\n.btn-link:focus {\n color: #23527c;\n text-decoration: underline;\n background-color: transparent;\n}\n.btn-link[disabled]:hover,\nfieldset[disabled] .btn-link:hover,\n.btn-link[disabled]:focus,\nfieldset[disabled] .btn-link:focus {\n color: #777;\n text-decoration: none;\n}\n.btn-lg,\n.btn-group-lg > .btn {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.btn-sm,\n.btn-group-sm > .btn {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-xs,\n.btn-group-xs > .btn {\n padding: 1px 5px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-block {\n display: block;\n width: 100%;\n}\n.btn-block + .btn-block {\n margin-top: 5px;\n}\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n width: 100%;\n}\n.fade {\n opacity: 0;\n -webkit-transition: opacity .15s linear;\n -o-transition: opacity .15s linear;\n transition: opacity .15s linear;\n}\n.fade.in {\n opacity: 1;\n}\n.collapse {\n display: none;\n}\n.collapse.in {\n display: block;\n}\ntr.collapse.in {\n display: table-row;\n}\ntbody.collapse.in {\n display: table-row-group;\n}\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n -webkit-transition-timing-function: ease;\n -o-transition-timing-function: ease;\n transition-timing-function: ease;\n -webkit-transition-duration: .35s;\n -o-transition-duration: .35s;\n transition-duration: .35s;\n -webkit-transition-property: height, visibility;\n -o-transition-property: height, visibility;\n transition-property: height, visibility;\n}\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: 4px dashed;\n border-top: 4px solid \\9;\n border-right: 4px solid transparent;\n border-left: 4px solid transparent;\n}\n.dropup,\n.dropdown {\n position: relative;\n}\n.dropdown-toggle:focus {\n outline: 0;\n}\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n display: none;\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0;\n font-size: 14px;\n text-align: left;\n list-style: none;\n background-color: #fff;\n -webkit-background-clip: padding-box;\n background-clip: padding-box;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, .15);\n border-radius: 4px;\n -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);\n box-shadow: 0 6px 12px rgba(0, 0, 0, .175);\n}\n.dropdown-menu.pull-right {\n right: 0;\n left: auto;\n}\n.dropdown-menu .divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.dropdown-menu > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: 1.42857143;\n color: #333;\n white-space: nowrap;\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n color: #262626;\n text-decoration: none;\n background-color: #f5f5f5;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n color: #fff;\n text-decoration: none;\n background-color: #337ab7;\n outline: 0;\n}\n.dropdown-menu > .disabled > a,\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n color: #777;\n}\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n text-decoration: none;\n cursor: not-allowed;\n background-color: transparent;\n background-image: none;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n}\n.open > .dropdown-menu {\n display: block;\n}\n.open > a {\n outline: 0;\n}\n.dropdown-menu-right {\n right: 0;\n left: auto;\n}\n.dropdown-menu-left {\n right: auto;\n left: 0;\n}\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: 12px;\n line-height: 1.42857143;\n color: #777;\n white-space: nowrap;\n}\n.dropdown-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 990;\n}\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n content: \"\";\n border-top: 0;\n border-bottom: 4px dashed;\n border-bottom: 4px solid \\9;\n}\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n}\n@media (min-width: 768px) {\n .navbar-right .dropdown-menu {\n right: 0;\n left: auto;\n }\n .navbar-right .dropdown-menu-left {\n right: auto;\n left: 0;\n }\n}\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle;\n}\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n position: relative;\n float: left;\n}\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group-vertical > .btn:focus,\n.btn-group > .btn:active,\n.btn-group-vertical > .btn:active,\n.btn-group > .btn.active,\n.btn-group-vertical > .btn.active {\n z-index: 2;\n}\n.btn-group .btn + .btn,\n.btn-group .btn + .btn-group,\n.btn-group .btn-group + .btn,\n.btn-group .btn-group + .btn-group {\n margin-left: -1px;\n}\n.btn-toolbar {\n margin-left: -5px;\n}\n.btn-toolbar .btn,\n.btn-toolbar .btn-group,\n.btn-toolbar .input-group {\n float: left;\n}\n.btn-toolbar > .btn,\n.btn-toolbar > .btn-group,\n.btn-toolbar > .input-group {\n margin-left: 5px;\n}\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n.btn-group > .btn:first-child {\n margin-left: 0;\n}\n.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n.btn-group > .btn + .dropdown-toggle {\n padding-right: 8px;\n padding-left: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-right: 12px;\n padding-left: 12px;\n}\n.btn-group.open .dropdown-toggle {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);\n}\n.btn-group.open .dropdown-toggle.btn-link {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn .caret {\n margin-left: 0;\n}\n.btn-lg .caret {\n border-width: 5px 5px 0;\n border-bottom-width: 0;\n}\n.dropup .btn-lg .caret {\n border-width: 0 5px 5px;\n}\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group,\n.btn-group-vertical > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n}\n.btn-group-vertical > .btn-group > .btn {\n float: none;\n}\n.btn-group-vertical > .btn + .btn,\n.btn-group-vertical > .btn + .btn-group,\n.btn-group-vertical > .btn-group + .btn,\n.btn-group-vertical > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n}\n.btn-group-vertical > .btn:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.btn-group-vertical > .btn:first-child:not(:last-child) {\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn:last-child:not(:first-child) {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n}\n.btn-group-justified > .btn,\n.btn-group-justified > .btn-group {\n display: table-cell;\n float: none;\n width: 1%;\n}\n.btn-group-justified > .btn-group .btn {\n width: 100%;\n}\n.btn-group-justified > .btn-group .dropdown-menu {\n left: auto;\n}\n[data-toggle=\"buttons\"] > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn input[type=\"checkbox\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0, 0, 0, 0);\n pointer-events: none;\n}\n.input-group {\n position: relative;\n display: table;\n border-collapse: separate;\n}\n.input-group[class*=\"col-\"] {\n float: none;\n padding-right: 0;\n padding-left: 0;\n}\n.input-group .form-control {\n position: relative;\n z-index: 2;\n float: left;\n width: 100%;\n margin-bottom: 0;\n}\n.input-group .form-control:focus {\n z-index: 3;\n}\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-group-lg > .form-control,\nselect.input-group-lg > .input-group-addon,\nselect.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-group-lg > .form-control,\ntextarea.input-group-lg > .input-group-addon,\ntextarea.input-group-lg > .input-group-btn > .btn,\nselect[multiple].input-group-lg > .form-control,\nselect[multiple].input-group-lg > .input-group-addon,\nselect[multiple].input-group-lg > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-group-sm > .form-control,\nselect.input-group-sm > .input-group-addon,\nselect.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-group-sm > .form-control,\ntextarea.input-group-sm > .input-group-addon,\ntextarea.input-group-sm > .input-group-btn > .btn,\nselect[multiple].input-group-sm > .form-control,\nselect[multiple].input-group-sm > .input-group-addon,\nselect[multiple].input-group-sm > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n}\n.input-group-addon:not(:first-child):not(:last-child),\n.input-group-btn:not(:first-child):not(:last-child),\n.input-group .form-control:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle;\n}\n.input-group-addon {\n padding: 6px 12px;\n font-size: 14px;\n font-weight: normal;\n line-height: 1;\n color: #555;\n text-align: center;\n background-color: #eee;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\n.input-group-addon.input-sm {\n padding: 5px 10px;\n font-size: 12px;\n border-radius: 3px;\n}\n.input-group-addon.input-lg {\n padding: 10px 16px;\n font-size: 18px;\n border-radius: 6px;\n}\n.input-group-addon input[type=\"radio\"],\n.input-group-addon input[type=\"checkbox\"] {\n margin-top: 0;\n}\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n.input-group-btn {\n position: relative;\n font-size: 0;\n white-space: nowrap;\n}\n.input-group-btn > .btn {\n position: relative;\n}\n.input-group-btn > .btn + .btn {\n margin-left: -1px;\n}\n.input-group-btn > .btn:hover,\n.input-group-btn > .btn:focus,\n.input-group-btn > .btn:active {\n z-index: 2;\n}\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group {\n margin-right: -1px;\n}\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group {\n z-index: 2;\n margin-left: -1px;\n}\n.nav {\n padding-left: 0;\n margin-bottom: 0;\n list-style: none;\n}\n.nav > li {\n position: relative;\n display: block;\n}\n.nav > li > a {\n position: relative;\n display: block;\n padding: 10px 15px;\n}\n.nav > li > a:hover,\n.nav > li > a:focus {\n text-decoration: none;\n background-color: #eee;\n}\n.nav > li.disabled > a {\n color: #777;\n}\n.nav > li.disabled > a:hover,\n.nav > li.disabled > a:focus {\n color: #777;\n text-decoration: none;\n cursor: not-allowed;\n background-color: transparent;\n}\n.nav .open > a,\n.nav .open > a:hover,\n.nav .open > a:focus {\n background-color: #eee;\n border-color: #337ab7;\n}\n.nav .nav-divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.nav > li > a > img {\n max-width: none;\n}\n.nav-tabs {\n border-bottom: 1px solid #ddd;\n}\n.nav-tabs > li {\n float: left;\n margin-bottom: -1px;\n}\n.nav-tabs > li > a {\n margin-right: 2px;\n line-height: 1.42857143;\n border: 1px solid transparent;\n border-radius: 4px 4px 0 0;\n}\n.nav-tabs > li > a:hover {\n border-color: #eee #eee #ddd;\n}\n.nav-tabs > li.active > a,\n.nav-tabs > li.active > a:hover,\n.nav-tabs > li.active > a:focus {\n color: #555;\n cursor: default;\n background-color: #fff;\n border: 1px solid #ddd;\n border-bottom-color: transparent;\n}\n.nav-tabs.nav-justified {\n width: 100%;\n border-bottom: 0;\n}\n.nav-tabs.nav-justified > li {\n float: none;\n}\n.nav-tabs.nav-justified > li > a {\n margin-bottom: 5px;\n text-align: center;\n}\n.nav-tabs.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-tabs.nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs.nav-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs.nav-justified > .active > a,\n.nav-tabs.nav-justified > .active > a:hover,\n.nav-tabs.nav-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs.nav-justified > .active > a,\n .nav-tabs.nav-justified > .active > a:hover,\n .nav-tabs.nav-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.nav-pills > li {\n float: left;\n}\n.nav-pills > li > a {\n border-radius: 4px;\n}\n.nav-pills > li + li {\n margin-left: 2px;\n}\n.nav-pills > li.active > a,\n.nav-pills > li.active > a:hover,\n.nav-pills > li.active > a:focus {\n color: #fff;\n background-color: #337ab7;\n}\n.nav-stacked > li {\n float: none;\n}\n.nav-stacked > li + li {\n margin-top: 2px;\n margin-left: 0;\n}\n.nav-justified {\n width: 100%;\n}\n.nav-justified > li {\n float: none;\n}\n.nav-justified > li > a {\n margin-bottom: 5px;\n text-align: center;\n}\n.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs-justified {\n border-bottom: 0;\n}\n.nav-tabs-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs-justified > .active > a,\n.nav-tabs-justified > .active > a:hover,\n.nav-tabs-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs-justified > .active > a,\n .nav-tabs-justified > .active > a:hover,\n .nav-tabs-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.tab-content > .tab-pane {\n display: none;\n}\n.tab-content > .active {\n display: block;\n}\n.nav-tabs .dropdown-menu {\n margin-top: -1px;\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.navbar {\n position: relative;\n min-height: 50px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n}\n@media (min-width: 768px) {\n .navbar {\n border-radius: 4px;\n }\n}\n@media (min-width: 768px) {\n .navbar-header {\n float: left;\n }\n}\n.navbar-collapse {\n padding-right: 15px;\n padding-left: 15px;\n overflow-x: visible;\n -webkit-overflow-scrolling: touch;\n border-top: 1px solid transparent;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1);\n}\n.navbar-collapse.in {\n overflow-y: auto;\n}\n@media (min-width: 768px) {\n .navbar-collapse {\n width: auto;\n border-top: 0;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n .navbar-collapse.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0;\n overflow: visible !important;\n }\n .navbar-collapse.in {\n overflow-y: visible;\n }\n .navbar-fixed-top .navbar-collapse,\n .navbar-static-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n padding-right: 0;\n padding-left: 0;\n }\n}\n.navbar-fixed-top .navbar-collapse,\n.navbar-fixed-bottom .navbar-collapse {\n max-height: 340px;\n}\n@media (max-device-width: 480px) and (orientation: landscape) {\n .navbar-fixed-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n max-height: 200px;\n }\n}\n.container > .navbar-header,\n.container-fluid > .navbar-header,\n.container > .navbar-collapse,\n.container-fluid > .navbar-collapse {\n margin-right: -15px;\n margin-left: -15px;\n}\n@media (min-width: 768px) {\n .container > .navbar-header,\n .container-fluid > .navbar-header,\n .container > .navbar-collapse,\n .container-fluid > .navbar-collapse {\n margin-right: 0;\n margin-left: 0;\n }\n}\n.navbar-static-top {\n z-index: 1000;\n border-width: 0 0 1px;\n}\n@media (min-width: 768px) {\n .navbar-static-top {\n border-radius: 0;\n }\n}\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: 1030;\n}\n@media (min-width: 768px) {\n .navbar-fixed-top,\n .navbar-fixed-bottom {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0;\n border-width: 1px 0 0;\n}\n.navbar-brand {\n float: left;\n height: 50px;\n padding: 15px 15px;\n font-size: 18px;\n line-height: 20px;\n}\n.navbar-brand:hover,\n.navbar-brand:focus {\n text-decoration: none;\n}\n.navbar-brand > img {\n display: block;\n}\n@media (min-width: 768px) {\n .navbar > .container .navbar-brand,\n .navbar > .container-fluid .navbar-brand {\n margin-left: -15px;\n }\n}\n.navbar-toggle {\n position: relative;\n float: right;\n padding: 9px 10px;\n margin-top: 8px;\n margin-right: 15px;\n margin-bottom: 8px;\n background-color: transparent;\n background-image: none;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.navbar-toggle:focus {\n outline: 0;\n}\n.navbar-toggle .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n}\n.navbar-toggle .icon-bar + .icon-bar {\n margin-top: 4px;\n}\n@media (min-width: 768px) {\n .navbar-toggle {\n display: none;\n }\n}\n.navbar-nav {\n margin: 7.5px -15px;\n}\n.navbar-nav > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: 20px;\n}\n@media (max-width: 767px) {\n .navbar-nav .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n .navbar-nav .open .dropdown-menu > li > a,\n .navbar-nav .open .dropdown-menu .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n .navbar-nav .open .dropdown-menu > li > a {\n line-height: 20px;\n }\n .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-nav .open .dropdown-menu > li > a:focus {\n background-image: none;\n }\n}\n@media (min-width: 768px) {\n .navbar-nav {\n float: left;\n margin: 0;\n }\n .navbar-nav > li {\n float: left;\n }\n .navbar-nav > li > a {\n padding-top: 15px;\n padding-bottom: 15px;\n }\n}\n.navbar-form {\n padding: 10px 15px;\n margin-top: 8px;\n margin-right: -15px;\n margin-bottom: 8px;\n margin-left: -15px;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1);\n}\n@media (min-width: 768px) {\n .navbar-form .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .navbar-form .form-control-static {\n display: inline-block;\n }\n .navbar-form .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .navbar-form .input-group .input-group-addon,\n .navbar-form .input-group .input-group-btn,\n .navbar-form .input-group .form-control {\n width: auto;\n }\n .navbar-form .input-group > .form-control {\n width: 100%;\n }\n .navbar-form .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio,\n .navbar-form .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio label,\n .navbar-form .checkbox label {\n padding-left: 0;\n }\n .navbar-form .radio input[type=\"radio\"],\n .navbar-form .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .navbar-form .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n@media (max-width: 767px) {\n .navbar-form .form-group {\n margin-bottom: 5px;\n }\n .navbar-form .form-group:last-child {\n margin-bottom: 0;\n }\n}\n@media (min-width: 768px) {\n .navbar-form {\n width: auto;\n padding-top: 0;\n padding-bottom: 0;\n margin-right: 0;\n margin-left: 0;\n border: 0;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n}\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.navbar-btn {\n margin-top: 8px;\n margin-bottom: 8px;\n}\n.navbar-btn.btn-sm {\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.navbar-btn.btn-xs {\n margin-top: 14px;\n margin-bottom: 14px;\n}\n.navbar-text {\n margin-top: 15px;\n margin-bottom: 15px;\n}\n@media (min-width: 768px) {\n .navbar-text {\n float: left;\n margin-right: 15px;\n margin-left: 15px;\n }\n}\n@media (min-width: 768px) {\n .navbar-left {\n float: left !important;\n }\n .navbar-right {\n float: right !important;\n margin-right: -15px;\n }\n .navbar-right ~ .navbar-right {\n margin-right: 0;\n }\n}\n.navbar-default {\n background-color: #f8f8f8;\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-brand {\n color: #777;\n}\n.navbar-default .navbar-brand:hover,\n.navbar-default .navbar-brand:focus {\n color: #5e5e5e;\n background-color: transparent;\n}\n.navbar-default .navbar-text {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a:hover,\n.navbar-default .navbar-nav > li > a:focus {\n color: #333;\n background-color: transparent;\n}\n.navbar-default .navbar-nav > .active > a,\n.navbar-default .navbar-nav > .active > a:hover,\n.navbar-default .navbar-nav > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .disabled > a,\n.navbar-default .navbar-nav > .disabled > a:hover,\n.navbar-default .navbar-nav > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n}\n.navbar-default .navbar-toggle {\n border-color: #ddd;\n}\n.navbar-default .navbar-toggle:hover,\n.navbar-default .navbar-toggle:focus {\n background-color: #ddd;\n}\n.navbar-default .navbar-toggle .icon-bar {\n background-color: #888;\n}\n.navbar-default .navbar-collapse,\n.navbar-default .navbar-form {\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .open > a:hover,\n.navbar-default .navbar-nav > .open > a:focus {\n color: #555;\n background-color: #e7e7e7;\n}\n@media (max-width: 767px) {\n .navbar-default .navbar-nav .open .dropdown-menu > li > a {\n color: #777;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #333;\n background-color: transparent;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n }\n}\n.navbar-default .navbar-link {\n color: #777;\n}\n.navbar-default .navbar-link:hover {\n color: #333;\n}\n.navbar-default .btn-link {\n color: #777;\n}\n.navbar-default .btn-link:hover,\n.navbar-default .btn-link:focus {\n color: #333;\n}\n.navbar-default .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-default .btn-link:hover,\n.navbar-default .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-default .btn-link:focus {\n color: #ccc;\n}\n.navbar-inverse {\n background-color: #222;\n border-color: #080808;\n}\n.navbar-inverse .navbar-brand {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-brand:hover,\n.navbar-inverse .navbar-brand:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-text {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a:hover,\n.navbar-inverse .navbar-nav > li > a:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-nav > .active > a,\n.navbar-inverse .navbar-nav > .active > a:hover,\n.navbar-inverse .navbar-nav > .active > a:focus {\n color: #fff;\n background-color: #080808;\n}\n.navbar-inverse .navbar-nav > .disabled > a,\n.navbar-inverse .navbar-nav > .disabled > a:hover,\n.navbar-inverse .navbar-nav > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n}\n.navbar-inverse .navbar-toggle {\n border-color: #333;\n}\n.navbar-inverse .navbar-toggle:hover,\n.navbar-inverse .navbar-toggle:focus {\n background-color: #333;\n}\n.navbar-inverse .navbar-toggle .icon-bar {\n background-color: #fff;\n}\n.navbar-inverse .navbar-collapse,\n.navbar-inverse .navbar-form {\n border-color: #101010;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .open > a:hover,\n.navbar-inverse .navbar-nav > .open > a:focus {\n color: #fff;\n background-color: #080808;\n}\n@media (max-width: 767px) {\n .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {\n border-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu .divider {\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {\n color: #9d9d9d;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #fff;\n background-color: transparent;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #fff;\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n }\n}\n.navbar-inverse .navbar-link {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-link:hover {\n color: #fff;\n}\n.navbar-inverse .btn-link {\n color: #9d9d9d;\n}\n.navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link:focus {\n color: #fff;\n}\n.navbar-inverse .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-inverse .btn-link:focus {\n color: #444;\n}\n.breadcrumb {\n padding: 8px 15px;\n margin-bottom: 20px;\n list-style: none;\n background-color: #f5f5f5;\n border-radius: 4px;\n}\n.breadcrumb > li {\n display: inline-block;\n}\n.breadcrumb > li + li:before {\n padding: 0 5px;\n color: #ccc;\n content: \"/\\00a0\";\n}\n.breadcrumb > .active {\n color: #777;\n}\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: 20px 0;\n border-radius: 4px;\n}\n.pagination > li {\n display: inline;\n}\n.pagination > li > a,\n.pagination > li > span {\n position: relative;\n float: left;\n padding: 6px 12px;\n margin-left: -1px;\n line-height: 1.42857143;\n color: #337ab7;\n text-decoration: none;\n background-color: #fff;\n border: 1px solid #ddd;\n}\n.pagination > li:first-child > a,\n.pagination > li:first-child > span {\n margin-left: 0;\n border-top-left-radius: 4px;\n border-bottom-left-radius: 4px;\n}\n.pagination > li:last-child > a,\n.pagination > li:last-child > span {\n border-top-right-radius: 4px;\n border-bottom-right-radius: 4px;\n}\n.pagination > li > a:hover,\n.pagination > li > span:hover,\n.pagination > li > a:focus,\n.pagination > li > span:focus {\n z-index: 2;\n color: #23527c;\n background-color: #eee;\n border-color: #ddd;\n}\n.pagination > .active > a,\n.pagination > .active > span,\n.pagination > .active > a:hover,\n.pagination > .active > span:hover,\n.pagination > .active > a:focus,\n.pagination > .active > span:focus {\n z-index: 3;\n color: #fff;\n cursor: default;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.pagination > .disabled > span,\n.pagination > .disabled > span:hover,\n.pagination > .disabled > span:focus,\n.pagination > .disabled > a,\n.pagination > .disabled > a:hover,\n.pagination > .disabled > a:focus {\n color: #777;\n cursor: not-allowed;\n background-color: #fff;\n border-color: #ddd;\n}\n.pagination-lg > li > a,\n.pagination-lg > li > span {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.pagination-lg > li:first-child > a,\n.pagination-lg > li:first-child > span {\n border-top-left-radius: 6px;\n border-bottom-left-radius: 6px;\n}\n.pagination-lg > li:last-child > a,\n.pagination-lg > li:last-child > span {\n border-top-right-radius: 6px;\n border-bottom-right-radius: 6px;\n}\n.pagination-sm > li > a,\n.pagination-sm > li > span {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.pagination-sm > li:first-child > a,\n.pagination-sm > li:first-child > span {\n border-top-left-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.pagination-sm > li:last-child > a,\n.pagination-sm > li:last-child > span {\n border-top-right-radius: 3px;\n border-bottom-right-radius: 3px;\n}\n.pager {\n padding-left: 0;\n margin: 20px 0;\n text-align: center;\n list-style: none;\n}\n.pager li {\n display: inline;\n}\n.pager li > a,\n.pager li > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 15px;\n}\n.pager li > a:hover,\n.pager li > a:focus {\n text-decoration: none;\n background-color: #eee;\n}\n.pager .next > a,\n.pager .next > span {\n float: right;\n}\n.pager .previous > a,\n.pager .previous > span {\n float: left;\n}\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n color: #777;\n cursor: not-allowed;\n background-color: #fff;\n}\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: #fff;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n}\na.label:hover,\na.label:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.label:empty {\n display: none;\n}\n.btn .label {\n position: relative;\n top: -1px;\n}\n.label-default {\n background-color: #777;\n}\n.label-default[href]:hover,\n.label-default[href]:focus {\n background-color: #5e5e5e;\n}\n.label-primary {\n background-color: #337ab7;\n}\n.label-primary[href]:hover,\n.label-primary[href]:focus {\n background-color: #286090;\n}\n.label-success {\n background-color: #5cb85c;\n}\n.label-success[href]:hover,\n.label-success[href]:focus {\n background-color: #449d44;\n}\n.label-info {\n background-color: #5bc0de;\n}\n.label-info[href]:hover,\n.label-info[href]:focus {\n background-color: #31b0d5;\n}\n.label-warning {\n background-color: #f0ad4e;\n}\n.label-warning[href]:hover,\n.label-warning[href]:focus {\n background-color: #ec971f;\n}\n.label-danger {\n background-color: #d9534f;\n}\n.label-danger[href]:hover,\n.label-danger[href]:focus {\n background-color: #c9302c;\n}\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: 12px;\n font-weight: bold;\n line-height: 1;\n color: #fff;\n text-align: center;\n white-space: nowrap;\n vertical-align: middle;\n background-color: #777;\n border-radius: 10px;\n}\n.badge:empty {\n display: none;\n}\n.btn .badge {\n position: relative;\n top: -1px;\n}\n.btn-xs .badge,\n.btn-group-xs > .btn .badge {\n top: 0;\n padding: 1px 5px;\n}\na.badge:hover,\na.badge:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.list-group-item > .badge {\n float: right;\n}\n.list-group-item > .badge + .badge {\n margin-right: 5px;\n}\n.nav-pills > li > a > .badge {\n margin-left: 3px;\n}\n.jumbotron {\n padding-top: 30px;\n padding-bottom: 30px;\n margin-bottom: 30px;\n color: inherit;\n background-color: #eee;\n}\n.jumbotron h1,\n.jumbotron .h1 {\n color: inherit;\n}\n.jumbotron p {\n margin-bottom: 15px;\n font-size: 21px;\n font-weight: 200;\n}\n.jumbotron > hr {\n border-top-color: #d5d5d5;\n}\n.container .jumbotron,\n.container-fluid .jumbotron {\n padding-right: 15px;\n padding-left: 15px;\n border-radius: 6px;\n}\n.jumbotron .container {\n max-width: 100%;\n}\n@media screen and (min-width: 768px) {\n .jumbotron {\n padding-top: 48px;\n padding-bottom: 48px;\n }\n .container .jumbotron,\n .container-fluid .jumbotron {\n padding-right: 60px;\n padding-left: 60px;\n }\n .jumbotron h1,\n .jumbotron .h1 {\n font-size: 63px;\n }\n}\n.thumbnail {\n display: block;\n padding: 4px;\n margin-bottom: 20px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: border .2s ease-in-out;\n -o-transition: border .2s ease-in-out;\n transition: border .2s ease-in-out;\n}\n.thumbnail > img,\n.thumbnail a > img {\n margin-right: auto;\n margin-left: auto;\n}\na.thumbnail:hover,\na.thumbnail:focus,\na.thumbnail.active {\n border-color: #337ab7;\n}\n.thumbnail .caption {\n padding: 9px;\n color: #333;\n}\n.alert {\n padding: 15px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.alert h4 {\n margin-top: 0;\n color: inherit;\n}\n.alert .alert-link {\n font-weight: bold;\n}\n.alert > p,\n.alert > ul {\n margin-bottom: 0;\n}\n.alert > p + p {\n margin-top: 5px;\n}\n.alert-dismissable,\n.alert-dismissible {\n padding-right: 35px;\n}\n.alert-dismissable .close,\n.alert-dismissible .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n}\n.alert-success {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #d6e9c6;\n}\n.alert-success hr {\n border-top-color: #c9e2b3;\n}\n.alert-success .alert-link {\n color: #2b542c;\n}\n.alert-info {\n color: #31708f;\n background-color: #d9edf7;\n border-color: #bce8f1;\n}\n.alert-info hr {\n border-top-color: #a6e1ec;\n}\n.alert-info .alert-link {\n color: #245269;\n}\n.alert-warning {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #faebcc;\n}\n.alert-warning hr {\n border-top-color: #f7e1b5;\n}\n.alert-warning .alert-link {\n color: #66512c;\n}\n.alert-danger {\n color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n}\n.alert-danger hr {\n border-top-color: #e4b9c0;\n}\n.alert-danger .alert-link {\n color: #843534;\n}\n@-webkit-keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n@-o-keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n@keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n.progress {\n height: 20px;\n margin-bottom: 20px;\n overflow: hidden;\n background-color: #f5f5f5;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1);\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1);\n}\n.progress-bar {\n float: left;\n width: 0;\n height: 100%;\n font-size: 12px;\n line-height: 20px;\n color: #fff;\n text-align: center;\n background-color: #337ab7;\n -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15);\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15);\n -webkit-transition: width .6s ease;\n -o-transition: width .6s ease;\n transition: width .6s ease;\n}\n.progress-striped .progress-bar,\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n -webkit-background-size: 40px 40px;\n background-size: 40px 40px;\n}\n.progress.active .progress-bar,\n.progress-bar.active {\n -webkit-animation: progress-bar-stripes 2s linear infinite;\n -o-animation: progress-bar-stripes 2s linear infinite;\n animation: progress-bar-stripes 2s linear infinite;\n}\n.progress-bar-success {\n background-color: #5cb85c;\n}\n.progress-striped .progress-bar-success {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n}\n.progress-bar-info {\n background-color: #5bc0de;\n}\n.progress-striped .progress-bar-info {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n}\n.progress-bar-warning {\n background-color: #f0ad4e;\n}\n.progress-striped .progress-bar-warning {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n}\n.progress-bar-danger {\n background-color: #d9534f;\n}\n.progress-striped .progress-bar-danger {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n}\n.media {\n margin-top: 15px;\n}\n.media:first-child {\n margin-top: 0;\n}\n.media,\n.media-body {\n overflow: hidden;\n zoom: 1;\n}\n.media-body {\n width: 10000px;\n}\n.media-object {\n display: block;\n}\n.media-object.img-thumbnail {\n max-width: none;\n}\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n.media-middle {\n vertical-align: middle;\n}\n.media-bottom {\n vertical-align: bottom;\n}\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n.list-group {\n padding-left: 0;\n margin-bottom: 20px;\n}\n.list-group-item {\n position: relative;\n display: block;\n padding: 10px 15px;\n margin-bottom: -1px;\n background-color: #fff;\n border: 1px solid #ddd;\n}\n.list-group-item:first-child {\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n}\n.list-group-item:last-child {\n margin-bottom: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\na.list-group-item,\nbutton.list-group-item {\n color: #555;\n}\na.list-group-item .list-group-item-heading,\nbutton.list-group-item .list-group-item-heading {\n color: #333;\n}\na.list-group-item:hover,\nbutton.list-group-item:hover,\na.list-group-item:focus,\nbutton.list-group-item:focus {\n color: #555;\n text-decoration: none;\n background-color: #f5f5f5;\n}\nbutton.list-group-item {\n width: 100%;\n text-align: left;\n}\n.list-group-item.disabled,\n.list-group-item.disabled:hover,\n.list-group-item.disabled:focus {\n color: #777;\n cursor: not-allowed;\n background-color: #eee;\n}\n.list-group-item.disabled .list-group-item-heading,\n.list-group-item.disabled:hover .list-group-item-heading,\n.list-group-item.disabled:focus .list-group-item-heading {\n color: inherit;\n}\n.list-group-item.disabled .list-group-item-text,\n.list-group-item.disabled:hover .list-group-item-text,\n.list-group-item.disabled:focus .list-group-item-text {\n color: #777;\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n z-index: 2;\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.list-group-item.active .list-group-item-heading,\n.list-group-item.active:hover .list-group-item-heading,\n.list-group-item.active:focus .list-group-item-heading,\n.list-group-item.active .list-group-item-heading > small,\n.list-group-item.active:hover .list-group-item-heading > small,\n.list-group-item.active:focus .list-group-item-heading > small,\n.list-group-item.active .list-group-item-heading > .small,\n.list-group-item.active:hover .list-group-item-heading > .small,\n.list-group-item.active:focus .list-group-item-heading > .small {\n color: inherit;\n}\n.list-group-item.active .list-group-item-text,\n.list-group-item.active:hover .list-group-item-text,\n.list-group-item.active:focus .list-group-item-text {\n color: #c7ddef;\n}\n.list-group-item-success {\n color: #3c763d;\n background-color: #dff0d8;\n}\na.list-group-item-success,\nbutton.list-group-item-success {\n color: #3c763d;\n}\na.list-group-item-success .list-group-item-heading,\nbutton.list-group-item-success .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-success:hover,\nbutton.list-group-item-success:hover,\na.list-group-item-success:focus,\nbutton.list-group-item-success:focus {\n color: #3c763d;\n background-color: #d0e9c6;\n}\na.list-group-item-success.active,\nbutton.list-group-item-success.active,\na.list-group-item-success.active:hover,\nbutton.list-group-item-success.active:hover,\na.list-group-item-success.active:focus,\nbutton.list-group-item-success.active:focus {\n color: #fff;\n background-color: #3c763d;\n border-color: #3c763d;\n}\n.list-group-item-info {\n color: #31708f;\n background-color: #d9edf7;\n}\na.list-group-item-info,\nbutton.list-group-item-info {\n color: #31708f;\n}\na.list-group-item-info .list-group-item-heading,\nbutton.list-group-item-info .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-info:hover,\nbutton.list-group-item-info:hover,\na.list-group-item-info:focus,\nbutton.list-group-item-info:focus {\n color: #31708f;\n background-color: #c4e3f3;\n}\na.list-group-item-info.active,\nbutton.list-group-item-info.active,\na.list-group-item-info.active:hover,\nbutton.list-group-item-info.active:hover,\na.list-group-item-info.active:focus,\nbutton.list-group-item-info.active:focus {\n color: #fff;\n background-color: #31708f;\n border-color: #31708f;\n}\n.list-group-item-warning {\n color: #8a6d3b;\n background-color: #fcf8e3;\n}\na.list-group-item-warning,\nbutton.list-group-item-warning {\n color: #8a6d3b;\n}\na.list-group-item-warning .list-group-item-heading,\nbutton.list-group-item-warning .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-warning:hover,\nbutton.list-group-item-warning:hover,\na.list-group-item-warning:focus,\nbutton.list-group-item-warning:focus {\n color: #8a6d3b;\n background-color: #faf2cc;\n}\na.list-group-item-warning.active,\nbutton.list-group-item-warning.active,\na.list-group-item-warning.active:hover,\nbutton.list-group-item-warning.active:hover,\na.list-group-item-warning.active:focus,\nbutton.list-group-item-warning.active:focus {\n color: #fff;\n background-color: #8a6d3b;\n border-color: #8a6d3b;\n}\n.list-group-item-danger {\n color: #a94442;\n background-color: #f2dede;\n}\na.list-group-item-danger,\nbutton.list-group-item-danger {\n color: #a94442;\n}\na.list-group-item-danger .list-group-item-heading,\nbutton.list-group-item-danger .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-danger:hover,\nbutton.list-group-item-danger:hover,\na.list-group-item-danger:focus,\nbutton.list-group-item-danger:focus {\n color: #a94442;\n background-color: #ebcccc;\n}\na.list-group-item-danger.active,\nbutton.list-group-item-danger.active,\na.list-group-item-danger.active:hover,\nbutton.list-group-item-danger.active:hover,\na.list-group-item-danger.active:focus,\nbutton.list-group-item-danger.active:focus {\n color: #fff;\n background-color: #a94442;\n border-color: #a94442;\n}\n.list-group-item-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.list-group-item-text {\n margin-bottom: 0;\n line-height: 1.3;\n}\n.panel {\n margin-bottom: 20px;\n background-color: #fff;\n border: 1px solid transparent;\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05);\n box-shadow: 0 1px 1px rgba(0, 0, 0, .05);\n}\n.panel-body {\n padding: 15px;\n}\n.panel-heading {\n padding: 10px 15px;\n border-bottom: 1px solid transparent;\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel-heading > .dropdown .dropdown-toggle {\n color: inherit;\n}\n.panel-title {\n margin-top: 0;\n margin-bottom: 0;\n font-size: 16px;\n color: inherit;\n}\n.panel-title > a,\n.panel-title > small,\n.panel-title > .small,\n.panel-title > small > a,\n.panel-title > .small > a {\n color: inherit;\n}\n.panel-footer {\n padding: 10px 15px;\n background-color: #f5f5f5;\n border-top: 1px solid #ddd;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .list-group,\n.panel > .panel-collapse > .list-group {\n margin-bottom: 0;\n}\n.panel > .list-group .list-group-item,\n.panel > .panel-collapse > .list-group .list-group-item {\n border-width: 1px 0;\n border-radius: 0;\n}\n.panel > .list-group:first-child .list-group-item:first-child,\n.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child {\n border-top: 0;\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .list-group:last-child .list-group-item:last-child,\n.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child {\n border-bottom: 0;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.panel-heading + .list-group .list-group-item:first-child {\n border-top-width: 0;\n}\n.list-group + .panel-footer {\n border-top-width: 0;\n}\n.panel > .table,\n.panel > .table-responsive > .table,\n.panel > .panel-collapse > .table {\n margin-bottom: 0;\n}\n.panel > .table caption,\n.panel > .table-responsive > .table caption,\n.panel > .panel-collapse > .table caption {\n padding-right: 15px;\n padding-left: 15px;\n}\n.panel > .table:first-child,\n.panel > .table-responsive:first-child > .table:first-child {\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child {\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {\n border-top-right-radius: 3px;\n}\n.panel > .table:last-child,\n.panel > .table-responsive:last-child > .table:last-child {\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child {\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {\n border-bottom-right-radius: 3px;\n}\n.panel > .panel-body + .table,\n.panel > .panel-body + .table-responsive,\n.panel > .table + .panel-body,\n.panel > .table-responsive + .panel-body {\n border-top: 1px solid #ddd;\n}\n.panel > .table > tbody:first-child > tr:first-child th,\n.panel > .table > tbody:first-child > tr:first-child td {\n border-top: 0;\n}\n.panel > .table-bordered,\n.panel > .table-responsive > .table-bordered {\n border: 0;\n}\n.panel > .table-bordered > thead > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,\n.panel > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-bordered > thead > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,\n.panel > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-bordered > tfoot > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n}\n.panel > .table-bordered > thead > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,\n.panel > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-bordered > thead > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,\n.panel > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-bordered > tfoot > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n}\n.panel > .table-bordered > thead > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,\n.panel > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-bordered > thead > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,\n.panel > .table-bordered > tbody > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {\n border-bottom: 0;\n}\n.panel > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-bordered > tfoot > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {\n border-bottom: 0;\n}\n.panel > .table-responsive {\n margin-bottom: 0;\n border: 0;\n}\n.panel-group {\n margin-bottom: 20px;\n}\n.panel-group .panel {\n margin-bottom: 0;\n border-radius: 4px;\n}\n.panel-group .panel + .panel {\n margin-top: 5px;\n}\n.panel-group .panel-heading {\n border-bottom: 0;\n}\n.panel-group .panel-heading + .panel-collapse > .panel-body,\n.panel-group .panel-heading + .panel-collapse > .list-group {\n border-top: 1px solid #ddd;\n}\n.panel-group .panel-footer {\n border-top: 0;\n}\n.panel-group .panel-footer + .panel-collapse .panel-body {\n border-bottom: 1px solid #ddd;\n}\n.panel-default {\n border-color: #ddd;\n}\n.panel-default > .panel-heading {\n color: #333;\n background-color: #f5f5f5;\n border-color: #ddd;\n}\n.panel-default > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ddd;\n}\n.panel-default > .panel-heading .badge {\n color: #f5f5f5;\n background-color: #333;\n}\n.panel-default > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ddd;\n}\n.panel-primary {\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading {\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #337ab7;\n}\n.panel-primary > .panel-heading .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.panel-primary > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #337ab7;\n}\n.panel-success {\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #d6e9c6;\n}\n.panel-success > .panel-heading .badge {\n color: #dff0d8;\n background-color: #3c763d;\n}\n.panel-success > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #d6e9c6;\n}\n.panel-info {\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading {\n color: #31708f;\n background-color: #d9edf7;\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #bce8f1;\n}\n.panel-info > .panel-heading .badge {\n color: #d9edf7;\n background-color: #31708f;\n}\n.panel-info > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #bce8f1;\n}\n.panel-warning {\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #faebcc;\n}\n.panel-warning > .panel-heading .badge {\n color: #fcf8e3;\n background-color: #8a6d3b;\n}\n.panel-warning > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #faebcc;\n}\n.panel-danger {\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading {\n color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ebccd1;\n}\n.panel-danger > .panel-heading .badge {\n color: #f2dede;\n background-color: #a94442;\n}\n.panel-danger > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ebccd1;\n}\n.embed-responsive {\n position: relative;\n display: block;\n height: 0;\n padding: 0;\n overflow: hidden;\n}\n.embed-responsive .embed-responsive-item,\n.embed-responsive iframe,\n.embed-responsive embed,\n.embed-responsive object,\n.embed-responsive video {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 100%;\n height: 100%;\n border: 0;\n}\n.embed-responsive-16by9 {\n padding-bottom: 56.25%;\n}\n.embed-responsive-4by3 {\n padding-bottom: 75%;\n}\n.well {\n min-height: 20px;\n padding: 19px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border: 1px solid #e3e3e3;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05);\n}\n.well blockquote {\n border-color: #ddd;\n border-color: rgba(0, 0, 0, .15);\n}\n.well-lg {\n padding: 24px;\n border-radius: 6px;\n}\n.well-sm {\n padding: 9px;\n border-radius: 3px;\n}\n.close {\n float: right;\n font-size: 21px;\n font-weight: bold;\n line-height: 1;\n color: #000;\n text-shadow: 0 1px 0 #fff;\n filter: alpha(opacity=20);\n opacity: .2;\n}\n.close:hover,\n.close:focus {\n color: #000;\n text-decoration: none;\n cursor: pointer;\n filter: alpha(opacity=50);\n opacity: .5;\n}\nbutton.close {\n -webkit-appearance: none;\n padding: 0;\n cursor: pointer;\n background: transparent;\n border: 0;\n}\n.modal-open {\n overflow: hidden;\n}\n.modal {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1050;\n display: none;\n overflow: hidden;\n -webkit-overflow-scrolling: touch;\n outline: 0;\n}\n.modal.fade .modal-dialog {\n -webkit-transition: -webkit-transform .3s ease-out;\n -o-transition: -o-transform .3s ease-out;\n transition: transform .3s ease-out;\n -webkit-transform: translate(0, -25%);\n -ms-transform: translate(0, -25%);\n -o-transform: translate(0, -25%);\n transform: translate(0, -25%);\n}\n.modal.in .modal-dialog {\n -webkit-transform: translate(0, 0);\n -ms-transform: translate(0, 0);\n -o-transform: translate(0, 0);\n transform: translate(0, 0);\n}\n.modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto;\n}\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 10px;\n}\n.modal-content {\n position: relative;\n background-color: #fff;\n -webkit-background-clip: padding-box;\n background-clip: padding-box;\n border: 1px solid #999;\n border: 1px solid rgba(0, 0, 0, .2);\n border-radius: 6px;\n outline: 0;\n -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5);\n box-shadow: 0 3px 9px rgba(0, 0, 0, .5);\n}\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1040;\n background-color: #000;\n}\n.modal-backdrop.fade {\n filter: alpha(opacity=0);\n opacity: 0;\n}\n.modal-backdrop.in {\n filter: alpha(opacity=50);\n opacity: .5;\n}\n.modal-header {\n padding: 15px;\n border-bottom: 1px solid #e5e5e5;\n}\n.modal-header .close {\n margin-top: -2px;\n}\n.modal-title {\n margin: 0;\n line-height: 1.42857143;\n}\n.modal-body {\n position: relative;\n padding: 15px;\n}\n.modal-footer {\n padding: 15px;\n text-align: right;\n border-top: 1px solid #e5e5e5;\n}\n.modal-footer .btn + .btn {\n margin-bottom: 0;\n margin-left: 5px;\n}\n.modal-footer .btn-group .btn + .btn {\n margin-left: -1px;\n}\n.modal-footer .btn-block + .btn-block {\n margin-left: 0;\n}\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n@media (min-width: 768px) {\n .modal-dialog {\n width: 600px;\n margin: 30px auto;\n }\n .modal-content {\n -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5);\n box-shadow: 0 5px 15px rgba(0, 0, 0, .5);\n }\n .modal-sm {\n width: 300px;\n }\n}\n@media (min-width: 992px) {\n .modal-lg {\n width: 900px;\n }\n}\n.tooltip {\n position: absolute;\n z-index: 1070;\n display: block;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 12px;\n font-style: normal;\n font-weight: normal;\n line-height: 1.42857143;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n letter-spacing: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n white-space: normal;\n filter: alpha(opacity=0);\n opacity: 0;\n\n line-break: auto;\n}\n.tooltip.in {\n filter: alpha(opacity=90);\n opacity: .9;\n}\n.tooltip.top {\n padding: 5px 0;\n margin-top: -3px;\n}\n.tooltip.right {\n padding: 0 5px;\n margin-left: 3px;\n}\n.tooltip.bottom {\n padding: 5px 0;\n margin-top: 3px;\n}\n.tooltip.left {\n padding: 0 5px;\n margin-left: -3px;\n}\n.tooltip-inner {\n max-width: 200px;\n padding: 3px 8px;\n color: #fff;\n text-align: center;\n background-color: #000;\n border-radius: 4px;\n}\n.tooltip-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.tooltip.top .tooltip-arrow {\n bottom: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-left .tooltip-arrow {\n right: 5px;\n bottom: 0;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-right .tooltip-arrow {\n bottom: 0;\n left: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.right .tooltip-arrow {\n top: 50%;\n left: 0;\n margin-top: -5px;\n border-width: 5px 5px 5px 0;\n border-right-color: #000;\n}\n.tooltip.left .tooltip-arrow {\n top: 50%;\n right: 0;\n margin-top: -5px;\n border-width: 5px 0 5px 5px;\n border-left-color: #000;\n}\n.tooltip.bottom .tooltip-arrow {\n top: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-left .tooltip-arrow {\n top: 0;\n right: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-right .tooltip-arrow {\n top: 0;\n left: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 1060;\n display: none;\n max-width: 276px;\n padding: 1px;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 14px;\n font-style: normal;\n font-weight: normal;\n line-height: 1.42857143;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n letter-spacing: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n white-space: normal;\n background-color: #fff;\n -webkit-background-clip: padding-box;\n background-clip: padding-box;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, .2);\n border-radius: 6px;\n -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2);\n box-shadow: 0 5px 10px rgba(0, 0, 0, .2);\n\n line-break: auto;\n}\n.popover.top {\n margin-top: -10px;\n}\n.popover.right {\n margin-left: 10px;\n}\n.popover.bottom {\n margin-top: 10px;\n}\n.popover.left {\n margin-left: -10px;\n}\n.popover-title {\n padding: 8px 14px;\n margin: 0;\n font-size: 14px;\n background-color: #f7f7f7;\n border-bottom: 1px solid #ebebeb;\n border-radius: 5px 5px 0 0;\n}\n.popover-content {\n padding: 9px 14px;\n}\n.popover > .arrow,\n.popover > .arrow:after {\n position: absolute;\n display: block;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.popover > .arrow {\n border-width: 11px;\n}\n.popover > .arrow:after {\n content: \"\";\n border-width: 10px;\n}\n.popover.top > .arrow {\n bottom: -11px;\n left: 50%;\n margin-left: -11px;\n border-top-color: #999;\n border-top-color: rgba(0, 0, 0, .25);\n border-bottom-width: 0;\n}\n.popover.top > .arrow:after {\n bottom: 1px;\n margin-left: -10px;\n content: \" \";\n border-top-color: #fff;\n border-bottom-width: 0;\n}\n.popover.right > .arrow {\n top: 50%;\n left: -11px;\n margin-top: -11px;\n border-right-color: #999;\n border-right-color: rgba(0, 0, 0, .25);\n border-left-width: 0;\n}\n.popover.right > .arrow:after {\n bottom: -10px;\n left: 1px;\n content: \" \";\n border-right-color: #fff;\n border-left-width: 0;\n}\n.popover.bottom > .arrow {\n top: -11px;\n left: 50%;\n margin-left: -11px;\n border-top-width: 0;\n border-bottom-color: #999;\n border-bottom-color: rgba(0, 0, 0, .25);\n}\n.popover.bottom > .arrow:after {\n top: 1px;\n margin-left: -10px;\n content: \" \";\n border-top-width: 0;\n border-bottom-color: #fff;\n}\n.popover.left > .arrow {\n top: 50%;\n right: -11px;\n margin-top: -11px;\n border-right-width: 0;\n border-left-color: #999;\n border-left-color: rgba(0, 0, 0, .25);\n}\n.popover.left > .arrow:after {\n right: 1px;\n bottom: -10px;\n content: \" \";\n border-right-width: 0;\n border-left-color: #fff;\n}\n.carousel {\n position: relative;\n}\n.carousel-inner {\n position: relative;\n width: 100%;\n overflow: hidden;\n}\n.carousel-inner > .item {\n position: relative;\n display: none;\n -webkit-transition: .6s ease-in-out left;\n -o-transition: .6s ease-in-out left;\n transition: .6s ease-in-out left;\n}\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n line-height: 1;\n}\n@media all and (transform-3d), (-webkit-transform-3d) {\n .carousel-inner > .item {\n -webkit-transition: -webkit-transform .6s ease-in-out;\n -o-transition: -o-transform .6s ease-in-out;\n transition: transform .6s ease-in-out;\n\n -webkit-backface-visibility: hidden;\n backface-visibility: hidden;\n -webkit-perspective: 1000px;\n perspective: 1000px;\n }\n .carousel-inner > .item.next,\n .carousel-inner > .item.active.right {\n left: 0;\n -webkit-transform: translate3d(100%, 0, 0);\n transform: translate3d(100%, 0, 0);\n }\n .carousel-inner > .item.prev,\n .carousel-inner > .item.active.left {\n left: 0;\n -webkit-transform: translate3d(-100%, 0, 0);\n transform: translate3d(-100%, 0, 0);\n }\n .carousel-inner > .item.next.left,\n .carousel-inner > .item.prev.right,\n .carousel-inner > .item.active {\n left: 0;\n -webkit-transform: translate3d(0, 0, 0);\n transform: translate3d(0, 0, 0);\n }\n}\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n display: block;\n}\n.carousel-inner > .active {\n left: 0;\n}\n.carousel-inner > .next,\n.carousel-inner > .prev {\n position: absolute;\n top: 0;\n width: 100%;\n}\n.carousel-inner > .next {\n left: 100%;\n}\n.carousel-inner > .prev {\n left: -100%;\n}\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n left: 0;\n}\n.carousel-inner > .active.left {\n left: -100%;\n}\n.carousel-inner > .active.right {\n left: 100%;\n}\n.carousel-control {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 15%;\n font-size: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, .6);\n background-color: rgba(0, 0, 0, 0);\n filter: alpha(opacity=50);\n opacity: .5;\n}\n.carousel-control.left {\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%);\n background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), to(rgba(0, 0, 0, .0001)));\n background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);\n background-repeat: repeat-x;\n}\n.carousel-control.right {\n right: 0;\n left: auto;\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%);\n background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .0001)), to(rgba(0, 0, 0, .5)));\n background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);\n background-repeat: repeat-x;\n}\n.carousel-control:hover,\n.carousel-control:focus {\n color: #fff;\n text-decoration: none;\n filter: alpha(opacity=90);\n outline: 0;\n opacity: .9;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-left,\n.carousel-control .glyphicon-chevron-right {\n position: absolute;\n top: 50%;\n z-index: 5;\n display: inline-block;\n margin-top: -10px;\n}\n.carousel-control .icon-prev,\n.carousel-control .glyphicon-chevron-left {\n left: 50%;\n margin-left: -10px;\n}\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-right {\n right: 50%;\n margin-right: -10px;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next {\n width: 20px;\n height: 20px;\n font-family: serif;\n line-height: 1;\n}\n.carousel-control .icon-prev:before {\n content: '\\2039';\n}\n.carousel-control .icon-next:before {\n content: '\\203a';\n}\n.carousel-indicators {\n position: absolute;\n bottom: 10px;\n left: 50%;\n z-index: 15;\n width: 60%;\n padding-left: 0;\n margin-left: -30%;\n text-align: center;\n list-style: none;\n}\n.carousel-indicators li {\n display: inline-block;\n width: 10px;\n height: 10px;\n margin: 1px;\n text-indent: -999px;\n cursor: pointer;\n background-color: #000 \\9;\n background-color: rgba(0, 0, 0, 0);\n border: 1px solid #fff;\n border-radius: 10px;\n}\n.carousel-indicators .active {\n width: 12px;\n height: 12px;\n margin: 0;\n background-color: #fff;\n}\n.carousel-caption {\n position: absolute;\n right: 15%;\n bottom: 20px;\n left: 15%;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, .6);\n}\n.carousel-caption .btn {\n text-shadow: none;\n}\n@media screen and (min-width: 768px) {\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-prev,\n .carousel-control .icon-next {\n width: 30px;\n height: 30px;\n margin-top: -10px;\n font-size: 30px;\n }\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .icon-prev {\n margin-left: -10px;\n }\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-next {\n margin-right: -10px;\n }\n .carousel-caption {\n right: 20%;\n left: 20%;\n padding-bottom: 30px;\n }\n .carousel-indicators {\n bottom: 20px;\n }\n}\n.clearfix:before,\n.clearfix:after,\n.dl-horizontal dd:before,\n.dl-horizontal dd:after,\n.container:before,\n.container:after,\n.container-fluid:before,\n.container-fluid:after,\n.row:before,\n.row:after,\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after,\n.btn-toolbar:before,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:before,\n.btn-group-vertical > .btn-group:after,\n.nav:before,\n.nav:after,\n.navbar:before,\n.navbar:after,\n.navbar-header:before,\n.navbar-header:after,\n.navbar-collapse:before,\n.navbar-collapse:after,\n.pager:before,\n.pager:after,\n.panel-body:before,\n.panel-body:after,\n.modal-header:before,\n.modal-header:after,\n.modal-footer:before,\n.modal-footer:after {\n display: table;\n content: \" \";\n}\n.clearfix:after,\n.dl-horizontal dd:after,\n.container:after,\n.container-fluid:after,\n.row:after,\n.form-horizontal .form-group:after,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:after,\n.nav:after,\n.navbar:after,\n.navbar-header:after,\n.navbar-collapse:after,\n.pager:after,\n.panel-body:after,\n.modal-header:after,\n.modal-footer:after {\n clear: both;\n}\n.center-block {\n display: block;\n margin-right: auto;\n margin-left: auto;\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n font: 0/0 a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n.hidden {\n display: none !important;\n}\n.affix {\n position: fixed;\n}\n@-ms-viewport {\n width: device-width;\n}\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n display: none !important;\n}\n.visible-xs-block,\n.visible-xs-inline,\n.visible-xs-inline-block,\n.visible-sm-block,\n.visible-sm-inline,\n.visible-sm-inline-block,\n.visible-md-block,\n.visible-md-inline,\n.visible-md-inline-block,\n.visible-lg-block,\n.visible-lg-inline,\n.visible-lg-inline-block {\n display: none !important;\n}\n@media (max-width: 767px) {\n .visible-xs {\n display: block !important;\n }\n table.visible-xs {\n display: table !important;\n }\n tr.visible-xs {\n display: table-row !important;\n }\n th.visible-xs,\n td.visible-xs {\n display: table-cell !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-block {\n display: block !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline {\n display: inline !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm {\n display: block !important;\n }\n table.visible-sm {\n display: table !important;\n }\n tr.visible-sm {\n display: table-row !important;\n }\n th.visible-sm,\n td.visible-sm {\n display: table-cell !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-block {\n display: block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline {\n display: inline !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md {\n display: block !important;\n }\n table.visible-md {\n display: table !important;\n }\n tr.visible-md {\n display: table-row !important;\n }\n th.visible-md,\n td.visible-md {\n display: table-cell !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-block {\n display: block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline {\n display: inline !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg {\n display: block !important;\n }\n table.visible-lg {\n display: table !important;\n }\n tr.visible-lg {\n display: table-row !important;\n }\n th.visible-lg,\n td.visible-lg {\n display: table-cell !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-block {\n display: block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline {\n display: inline !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline-block {\n display: inline-block !important;\n }\n}\n@media (max-width: 767px) {\n .hidden-xs {\n display: none !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .hidden-sm {\n display: none !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .hidden-md {\n display: none !important;\n }\n}\n@media (min-width: 1200px) {\n .hidden-lg {\n display: none !important;\n }\n}\n.visible-print {\n display: none !important;\n}\n@media print {\n .visible-print {\n display: block !important;\n }\n table.visible-print {\n display: table !important;\n }\n tr.visible-print {\n display: table-row !important;\n }\n th.visible-print,\n td.visible-print {\n display: table-cell !important;\n }\n}\n.visible-print-block {\n display: none !important;\n}\n@media print {\n .visible-print-block {\n display: block !important;\n }\n}\n.visible-print-inline {\n display: none !important;\n}\n@media print {\n .visible-print-inline {\n display: inline !important;\n }\n}\n.visible-print-inline-block {\n display: none !important;\n}\n@media print {\n .visible-print-inline-block {\n display: inline-block !important;\n }\n}\n@media print {\n .hidden-print {\n display: none !important;\n }\n}\n/*# sourceMappingURL=bootstrap.css.map */\n","//\n// Glyphicons for Bootstrap\n//\n// Since icons are fonts, they can be placed anywhere text is placed and are\n// thus automatically sized to match the surrounding child. To use, create an\n// inline element with the appropriate classes, like so:\n//\n// Star\n\n// Import the fonts\n@font-face {\n font-family: 'Glyphicons Halflings';\n src: url('@{icon-font-path}@{icon-font-name}.eot');\n src: url('@{icon-font-path}@{icon-font-name}.eot?#iefix') format('embedded-opentype'),\n url('@{icon-font-path}@{icon-font-name}.woff2') format('woff2'),\n url('@{icon-font-path}@{icon-font-name}.woff') format('woff'),\n url('@{icon-font-path}@{icon-font-name}.ttf') format('truetype'),\n url('@{icon-font-path}@{icon-font-name}.svg#@{icon-font-svg-id}') format('svg');\n}\n\n// Catchall baseclass\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n// Individual icons\n.glyphicon-asterisk { &:before { content: \"\\002a\"; } }\n.glyphicon-plus { &:before { content: \"\\002b\"; } }\n.glyphicon-euro,\n.glyphicon-eur { &:before { content: \"\\20ac\"; } }\n.glyphicon-minus { &:before { content: \"\\2212\"; } }\n.glyphicon-cloud { &:before { content: \"\\2601\"; } }\n.glyphicon-envelope { &:before { content: \"\\2709\"; } }\n.glyphicon-pencil { &:before { content: \"\\270f\"; } }\n.glyphicon-glass { &:before { content: \"\\e001\"; } }\n.glyphicon-music { &:before { content: \"\\e002\"; } }\n.glyphicon-search { &:before { content: \"\\e003\"; } }\n.glyphicon-heart { &:before { content: \"\\e005\"; } }\n.glyphicon-star { &:before { content: \"\\e006\"; } }\n.glyphicon-star-empty { &:before { content: \"\\e007\"; } }\n.glyphicon-user { &:before { content: \"\\e008\"; } }\n.glyphicon-film { &:before { content: \"\\e009\"; } }\n.glyphicon-th-large { &:before { content: \"\\e010\"; } }\n.glyphicon-th { &:before { content: \"\\e011\"; } }\n.glyphicon-th-list { &:before { content: \"\\e012\"; } }\n.glyphicon-ok { &:before { content: \"\\e013\"; } }\n.glyphicon-remove { &:before { content: \"\\e014\"; } }\n.glyphicon-zoom-in { &:before { content: \"\\e015\"; } }\n.glyphicon-zoom-out { &:before { content: \"\\e016\"; } }\n.glyphicon-off { &:before { content: \"\\e017\"; } }\n.glyphicon-signal { &:before { content: \"\\e018\"; } }\n.glyphicon-cog { &:before { content: \"\\e019\"; } }\n.glyphicon-trash { &:before { content: \"\\e020\"; } }\n.glyphicon-home { &:before { content: \"\\e021\"; } }\n.glyphicon-file { &:before { content: \"\\e022\"; } }\n.glyphicon-time { &:before { content: \"\\e023\"; } }\n.glyphicon-road { &:before { content: \"\\e024\"; } }\n.glyphicon-download-alt { &:before { content: \"\\e025\"; } }\n.glyphicon-download { &:before { content: \"\\e026\"; } }\n.glyphicon-upload { &:before { content: \"\\e027\"; } }\n.glyphicon-inbox { &:before { content: \"\\e028\"; } }\n.glyphicon-play-circle { &:before { content: \"\\e029\"; } }\n.glyphicon-repeat { &:before { content: \"\\e030\"; } }\n.glyphicon-refresh { &:before { content: \"\\e031\"; } }\n.glyphicon-list-alt { &:before { content: \"\\e032\"; } }\n.glyphicon-lock { &:before { content: \"\\e033\"; } }\n.glyphicon-flag { &:before { content: \"\\e034\"; } }\n.glyphicon-headphones { &:before { content: \"\\e035\"; } }\n.glyphicon-volume-off { &:before { content: \"\\e036\"; } }\n.glyphicon-volume-down { &:before { content: \"\\e037\"; } }\n.glyphicon-volume-up { &:before { content: \"\\e038\"; } }\n.glyphicon-qrcode { &:before { content: \"\\e039\"; } }\n.glyphicon-barcode { &:before { content: \"\\e040\"; } }\n.glyphicon-tag { &:before { content: \"\\e041\"; } }\n.glyphicon-tags { &:before { content: \"\\e042\"; } }\n.glyphicon-book { &:before { content: \"\\e043\"; } }\n.glyphicon-bookmark { &:before { content: \"\\e044\"; } }\n.glyphicon-print { &:before { content: \"\\e045\"; } }\n.glyphicon-camera { &:before { content: \"\\e046\"; } }\n.glyphicon-font { &:before { content: \"\\e047\"; } }\n.glyphicon-bold { &:before { content: \"\\e048\"; } }\n.glyphicon-italic { &:before { content: \"\\e049\"; } }\n.glyphicon-text-height { &:before { content: \"\\e050\"; } }\n.glyphicon-text-width { &:before { content: \"\\e051\"; } }\n.glyphicon-align-left { &:before { content: \"\\e052\"; } }\n.glyphicon-align-center { &:before { content: \"\\e053\"; } }\n.glyphicon-align-right { &:before { content: \"\\e054\"; } }\n.glyphicon-align-justify { &:before { content: \"\\e055\"; } }\n.glyphicon-list { &:before { content: \"\\e056\"; } }\n.glyphicon-indent-left { &:before { content: \"\\e057\"; } }\n.glyphicon-indent-right { &:before { content: \"\\e058\"; } }\n.glyphicon-facetime-video { &:before { content: \"\\e059\"; } }\n.glyphicon-picture { &:before { content: \"\\e060\"; } }\n.glyphicon-map-marker { &:before { content: \"\\e062\"; } }\n.glyphicon-adjust { &:before { content: \"\\e063\"; } }\n.glyphicon-tint { &:before { content: \"\\e064\"; } }\n.glyphicon-edit { &:before { content: \"\\e065\"; } }\n.glyphicon-share { &:before { content: \"\\e066\"; } }\n.glyphicon-check { &:before { content: \"\\e067\"; } }\n.glyphicon-move { &:before { content: \"\\e068\"; } }\n.glyphicon-step-backward { &:before { content: \"\\e069\"; } }\n.glyphicon-fast-backward { &:before { content: \"\\e070\"; } }\n.glyphicon-backward { &:before { content: \"\\e071\"; } }\n.glyphicon-play { &:before { content: \"\\e072\"; } }\n.glyphicon-pause { &:before { content: \"\\e073\"; } }\n.glyphicon-stop { &:before { content: \"\\e074\"; } }\n.glyphicon-forward { &:before { content: \"\\e075\"; } }\n.glyphicon-fast-forward { &:before { content: \"\\e076\"; } }\n.glyphicon-step-forward { &:before { content: \"\\e077\"; } }\n.glyphicon-eject { &:before { content: \"\\e078\"; } }\n.glyphicon-chevron-left { &:before { content: \"\\e079\"; } }\n.glyphicon-chevron-right { &:before { content: \"\\e080\"; } }\n.glyphicon-plus-sign { &:before { content: \"\\e081\"; } }\n.glyphicon-minus-sign { &:before { content: \"\\e082\"; } }\n.glyphicon-remove-sign { &:before { content: \"\\e083\"; } }\n.glyphicon-ok-sign { &:before { content: \"\\e084\"; } }\n.glyphicon-question-sign { &:before { content: \"\\e085\"; } }\n.glyphicon-info-sign { &:before { content: \"\\e086\"; } }\n.glyphicon-screenshot { &:before { content: \"\\e087\"; } }\n.glyphicon-remove-circle { &:before { content: \"\\e088\"; } }\n.glyphicon-ok-circle { &:before { content: \"\\e089\"; } }\n.glyphicon-ban-circle { &:before { content: \"\\e090\"; } }\n.glyphicon-arrow-left { &:before { content: \"\\e091\"; } }\n.glyphicon-arrow-right { &:before { content: \"\\e092\"; } }\n.glyphicon-arrow-up { &:before { content: \"\\e093\"; } }\n.glyphicon-arrow-down { &:before { content: \"\\e094\"; } }\n.glyphicon-share-alt { &:before { content: \"\\e095\"; } }\n.glyphicon-resize-full { &:before { content: \"\\e096\"; } }\n.glyphicon-resize-small { &:before { content: \"\\e097\"; } }\n.glyphicon-exclamation-sign { &:before { content: \"\\e101\"; } }\n.glyphicon-gift { &:before { content: \"\\e102\"; } }\n.glyphicon-leaf { &:before { content: \"\\e103\"; } }\n.glyphicon-fire { &:before { content: \"\\e104\"; } }\n.glyphicon-eye-open { &:before { content: \"\\e105\"; } }\n.glyphicon-eye-close { &:before { content: \"\\e106\"; } }\n.glyphicon-warning-sign { &:before { content: \"\\e107\"; } }\n.glyphicon-plane { &:before { content: \"\\e108\"; } }\n.glyphicon-calendar { &:before { content: \"\\e109\"; } }\n.glyphicon-random { &:before { content: \"\\e110\"; } }\n.glyphicon-comment { &:before { content: \"\\e111\"; } }\n.glyphicon-magnet { &:before { content: \"\\e112\"; } }\n.glyphicon-chevron-up { &:before { content: \"\\e113\"; } }\n.glyphicon-chevron-down { &:before { content: \"\\e114\"; } }\n.glyphicon-retweet { &:before { content: \"\\e115\"; } }\n.glyphicon-shopping-cart { &:before { content: \"\\e116\"; } }\n.glyphicon-folder-close { &:before { content: \"\\e117\"; } }\n.glyphicon-folder-open { &:before { content: \"\\e118\"; } }\n.glyphicon-resize-vertical { &:before { content: \"\\e119\"; } }\n.glyphicon-resize-horizontal { &:before { content: \"\\e120\"; } }\n.glyphicon-hdd { &:before { content: \"\\e121\"; } }\n.glyphicon-bullhorn { &:before { content: \"\\e122\"; } }\n.glyphicon-bell { &:before { content: \"\\e123\"; } }\n.glyphicon-certificate { &:before { content: \"\\e124\"; } }\n.glyphicon-thumbs-up { &:before { content: \"\\e125\"; } }\n.glyphicon-thumbs-down { &:before { content: \"\\e126\"; } }\n.glyphicon-hand-right { &:before { content: \"\\e127\"; } }\n.glyphicon-hand-left { &:before { content: \"\\e128\"; } }\n.glyphicon-hand-up { &:before { content: \"\\e129\"; } }\n.glyphicon-hand-down { &:before { content: \"\\e130\"; } }\n.glyphicon-circle-arrow-right { &:before { content: \"\\e131\"; } }\n.glyphicon-circle-arrow-left { &:before { content: \"\\e132\"; } }\n.glyphicon-circle-arrow-up { &:before { content: \"\\e133\"; } }\n.glyphicon-circle-arrow-down { &:before { content: \"\\e134\"; } }\n.glyphicon-globe { &:before { content: \"\\e135\"; } }\n.glyphicon-wrench { &:before { content: \"\\e136\"; } }\n.glyphicon-tasks { &:before { content: \"\\e137\"; } }\n.glyphicon-filter { &:before { content: \"\\e138\"; } }\n.glyphicon-briefcase { &:before { content: \"\\e139\"; } }\n.glyphicon-fullscreen { &:before { content: \"\\e140\"; } }\n.glyphicon-dashboard { &:before { content: \"\\e141\"; } }\n.glyphicon-paperclip { &:before { content: \"\\e142\"; } }\n.glyphicon-heart-empty { &:before { content: \"\\e143\"; } }\n.glyphicon-link { &:before { content: \"\\e144\"; } }\n.glyphicon-phone { &:before { content: \"\\e145\"; } }\n.glyphicon-pushpin { &:before { content: \"\\e146\"; } }\n.glyphicon-usd { &:before { content: \"\\e148\"; } }\n.glyphicon-gbp { &:before { content: \"\\e149\"; } }\n.glyphicon-sort { &:before { content: \"\\e150\"; } }\n.glyphicon-sort-by-alphabet { &:before { content: \"\\e151\"; } }\n.glyphicon-sort-by-alphabet-alt { &:before { content: \"\\e152\"; } }\n.glyphicon-sort-by-order { &:before { content: \"\\e153\"; } }\n.glyphicon-sort-by-order-alt { &:before { content: \"\\e154\"; } }\n.glyphicon-sort-by-attributes { &:before { content: \"\\e155\"; } }\n.glyphicon-sort-by-attributes-alt { &:before { content: \"\\e156\"; } }\n.glyphicon-unchecked { &:before { content: \"\\e157\"; } }\n.glyphicon-expand { &:before { content: \"\\e158\"; } }\n.glyphicon-collapse-down { &:before { content: \"\\e159\"; } }\n.glyphicon-collapse-up { &:before { content: \"\\e160\"; } }\n.glyphicon-log-in { &:before { content: \"\\e161\"; } }\n.glyphicon-flash { &:before { content: \"\\e162\"; } }\n.glyphicon-log-out { &:before { content: \"\\e163\"; } }\n.glyphicon-new-window { &:before { content: \"\\e164\"; } }\n.glyphicon-record { &:before { content: \"\\e165\"; } }\n.glyphicon-save { &:before { content: \"\\e166\"; } }\n.glyphicon-open { &:before { content: \"\\e167\"; } }\n.glyphicon-saved { &:before { content: \"\\e168\"; } }\n.glyphicon-import { &:before { content: \"\\e169\"; } }\n.glyphicon-export { &:before { content: \"\\e170\"; } }\n.glyphicon-send { &:before { content: \"\\e171\"; } }\n.glyphicon-floppy-disk { &:before { content: \"\\e172\"; } }\n.glyphicon-floppy-saved { &:before { content: \"\\e173\"; } }\n.glyphicon-floppy-remove { &:before { content: \"\\e174\"; } }\n.glyphicon-floppy-save { &:before { content: \"\\e175\"; } }\n.glyphicon-floppy-open { &:before { content: \"\\e176\"; } }\n.glyphicon-credit-card { &:before { content: \"\\e177\"; } }\n.glyphicon-transfer { &:before { content: \"\\e178\"; } }\n.glyphicon-cutlery { &:before { content: \"\\e179\"; } }\n.glyphicon-header { &:before { content: \"\\e180\"; } }\n.glyphicon-compressed { &:before { content: \"\\e181\"; } }\n.glyphicon-earphone { &:before { content: \"\\e182\"; } }\n.glyphicon-phone-alt { &:before { content: \"\\e183\"; } }\n.glyphicon-tower { &:before { content: \"\\e184\"; } }\n.glyphicon-stats { &:before { content: \"\\e185\"; } }\n.glyphicon-sd-video { &:before { content: \"\\e186\"; } }\n.glyphicon-hd-video { &:before { content: \"\\e187\"; } }\n.glyphicon-subtitles { &:before { content: \"\\e188\"; } }\n.glyphicon-sound-stereo { &:before { content: \"\\e189\"; } }\n.glyphicon-sound-dolby { &:before { content: \"\\e190\"; } }\n.glyphicon-sound-5-1 { &:before { content: \"\\e191\"; } }\n.glyphicon-sound-6-1 { &:before { content: \"\\e192\"; } }\n.glyphicon-sound-7-1 { &:before { content: \"\\e193\"; } }\n.glyphicon-copyright-mark { &:before { content: \"\\e194\"; } }\n.glyphicon-registration-mark { &:before { content: \"\\e195\"; } }\n.glyphicon-cloud-download { &:before { content: \"\\e197\"; } }\n.glyphicon-cloud-upload { &:before { content: \"\\e198\"; } }\n.glyphicon-tree-conifer { &:before { content: \"\\e199\"; } }\n.glyphicon-tree-deciduous { &:before { content: \"\\e200\"; } }\n.glyphicon-cd { &:before { content: \"\\e201\"; } }\n.glyphicon-save-file { &:before { content: \"\\e202\"; } }\n.glyphicon-open-file { &:before { content: \"\\e203\"; } }\n.glyphicon-level-up { &:before { content: \"\\e204\"; } }\n.glyphicon-copy { &:before { content: \"\\e205\"; } }\n.glyphicon-paste { &:before { content: \"\\e206\"; } }\n// The following 2 Glyphicons are omitted for the time being because\n// they currently use Unicode codepoints that are outside the\n// Basic Multilingual Plane (BMP). Older buggy versions of WebKit can't handle\n// non-BMP codepoints in CSS string escapes, and thus can't display these two icons.\n// Notably, the bug affects some older versions of the Android Browser.\n// More info: https://github.com/twbs/bootstrap/issues/10106\n// .glyphicon-door { &:before { content: \"\\1f6aa\"; } }\n// .glyphicon-key { &:before { content: \"\\1f511\"; } }\n.glyphicon-alert { &:before { content: \"\\e209\"; } }\n.glyphicon-equalizer { &:before { content: \"\\e210\"; } }\n.glyphicon-king { &:before { content: \"\\e211\"; } }\n.glyphicon-queen { &:before { content: \"\\e212\"; } }\n.glyphicon-pawn { &:before { content: \"\\e213\"; } }\n.glyphicon-bishop { &:before { content: \"\\e214\"; } }\n.glyphicon-knight { &:before { content: \"\\e215\"; } }\n.glyphicon-baby-formula { &:before { content: \"\\e216\"; } }\n.glyphicon-tent { &:before { content: \"\\26fa\"; } }\n.glyphicon-blackboard { &:before { content: \"\\e218\"; } }\n.glyphicon-bed { &:before { content: \"\\e219\"; } }\n.glyphicon-apple { &:before { content: \"\\f8ff\"; } }\n.glyphicon-erase { &:before { content: \"\\e221\"; } }\n.glyphicon-hourglass { &:before { content: \"\\231b\"; } }\n.glyphicon-lamp { &:before { content: \"\\e223\"; } }\n.glyphicon-duplicate { &:before { content: \"\\e224\"; } }\n.glyphicon-piggy-bank { &:before { content: \"\\e225\"; } }\n.glyphicon-scissors { &:before { content: \"\\e226\"; } }\n.glyphicon-bitcoin { &:before { content: \"\\e227\"; } }\n.glyphicon-btc { &:before { content: \"\\e227\"; } }\n.glyphicon-xbt { &:before { content: \"\\e227\"; } }\n.glyphicon-yen { &:before { content: \"\\00a5\"; } }\n.glyphicon-jpy { &:before { content: \"\\00a5\"; } }\n.glyphicon-ruble { &:before { content: \"\\20bd\"; } }\n.glyphicon-rub { &:before { content: \"\\20bd\"; } }\n.glyphicon-scale { &:before { content: \"\\e230\"; } }\n.glyphicon-ice-lolly { &:before { content: \"\\e231\"; } }\n.glyphicon-ice-lolly-tasted { &:before { content: \"\\e232\"; } }\n.glyphicon-education { &:before { content: \"\\e233\"; } }\n.glyphicon-option-horizontal { &:before { content: \"\\e234\"; } }\n.glyphicon-option-vertical { &:before { content: \"\\e235\"; } }\n.glyphicon-menu-hamburger { &:before { content: \"\\e236\"; } }\n.glyphicon-modal-window { &:before { content: \"\\e237\"; } }\n.glyphicon-oil { &:before { content: \"\\e238\"; } }\n.glyphicon-grain { &:before { content: \"\\e239\"; } }\n.glyphicon-sunglasses { &:before { content: \"\\e240\"; } }\n.glyphicon-text-size { &:before { content: \"\\e241\"; } }\n.glyphicon-text-color { &:before { content: \"\\e242\"; } }\n.glyphicon-text-background { &:before { content: \"\\e243\"; } }\n.glyphicon-object-align-top { &:before { content: \"\\e244\"; } }\n.glyphicon-object-align-bottom { &:before { content: \"\\e245\"; } }\n.glyphicon-object-align-horizontal{ &:before { content: \"\\e246\"; } }\n.glyphicon-object-align-left { &:before { content: \"\\e247\"; } }\n.glyphicon-object-align-vertical { &:before { content: \"\\e248\"; } }\n.glyphicon-object-align-right { &:before { content: \"\\e249\"; } }\n.glyphicon-triangle-right { &:before { content: \"\\e250\"; } }\n.glyphicon-triangle-left { &:before { content: \"\\e251\"; } }\n.glyphicon-triangle-bottom { &:before { content: \"\\e252\"; } }\n.glyphicon-triangle-top { &:before { content: \"\\e253\"; } }\n.glyphicon-console { &:before { content: \"\\e254\"; } }\n.glyphicon-superscript { &:before { content: \"\\e255\"; } }\n.glyphicon-subscript { &:before { content: \"\\e256\"; } }\n.glyphicon-menu-left { &:before { content: \"\\e257\"; } }\n.glyphicon-menu-right { &:before { content: \"\\e258\"; } }\n.glyphicon-menu-down { &:before { content: \"\\e259\"; } }\n.glyphicon-menu-up { &:before { content: \"\\e260\"; } }\n","//\n// Scaffolding\n// --------------------------------------------------\n\n\n// Reset the box-sizing\n//\n// Heads up! This reset may cause conflicts with some third-party widgets.\n// For recommendations on resolving such conflicts, see\n// http://getbootstrap.com/getting-started/#third-box-sizing\n* {\n .box-sizing(border-box);\n}\n*:before,\n*:after {\n .box-sizing(border-box);\n}\n\n\n// Body reset\n\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0,0,0,0);\n}\n\nbody {\n font-family: @font-family-base;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @text-color;\n background-color: @body-bg;\n}\n\n// Reset fonts for relevant elements\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\n\n// Links\n\na {\n color: @link-color;\n text-decoration: none;\n\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: @link-hover-decoration;\n }\n\n &:focus {\n .tab-focus();\n }\n}\n\n\n// Figures\n//\n// We reset this here because previously Normalize had no `figure` margins. This\n// ensures we don't break anyone's use of the element.\n\nfigure {\n margin: 0;\n}\n\n\n// Images\n\nimg {\n vertical-align: middle;\n}\n\n// Responsive images (ensure images don't scale beyond their parents)\n.img-responsive {\n .img-responsive();\n}\n\n// Rounded corners\n.img-rounded {\n border-radius: @border-radius-large;\n}\n\n// Image thumbnails\n//\n// Heads up! This is mixin-ed into thumbnails.less for `.thumbnail`.\n.img-thumbnail {\n padding: @thumbnail-padding;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(all .2s ease-in-out);\n\n // Keep them at most 100% wide\n .img-responsive(inline-block);\n}\n\n// Perfect circle\n.img-circle {\n border-radius: 50%; // set radius in percents\n}\n\n\n// Horizontal rules\n\nhr {\n margin-top: @line-height-computed;\n margin-bottom: @line-height-computed;\n border: 0;\n border-top: 1px solid @hr-border;\n}\n\n\n// Only display content to screen readers\n//\n// See: http://a11yproject.com/posts/how-to-hide-content\n\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0,0,0,0);\n border: 0;\n}\n\n// Use in conjunction with .sr-only to only display content when it's focused.\n// Useful for \"Skip to main content\" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1\n// Credit: HTML5 Boilerplate\n\n.sr-only-focusable {\n &:active,\n &:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n }\n}\n\n\n// iOS \"clickable elements\" fix for role=\"button\"\n//\n// Fixes \"clickability\" issue (and more generally, the firing of events such as focus as well)\n// for traditionally non-focusable elements with role=\"button\"\n// see https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile\n\n[role=\"button\"] {\n cursor: pointer;\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They have been removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility) {\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// WebKit-style focus\n\n.tab-focus() {\n // WebKit-specific. Other browsers will keep their default outline style.\n // (Initially tried to also force default via `outline: initial`,\n // but that seems to erroneously remove the outline in Firefox altogether.)\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n","// Image Mixins\n// - Responsive image\n// - Retina image\n\n\n// Responsive image\n//\n// Keep images from scaling beyond the width of their parents.\n.img-responsive(@display: block) {\n display: @display;\n max-width: 100%; // Part 1: Set a maximum relative to the parent\n height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching\n}\n\n\n// Retina image\n//\n// Short retina mixin for setting background-image and -size. Note that the\n// spelling of `min--moz-device-pixel-ratio` is intentional.\n.img-retina(@file-1x; @file-2x; @width-1x; @height-1x) {\n background-image: url(\"@{file-1x}\");\n\n @media\n only screen and (-webkit-min-device-pixel-ratio: 2),\n only screen and ( min--moz-device-pixel-ratio: 2),\n only screen and ( -o-min-device-pixel-ratio: 2/1),\n only screen and ( min-device-pixel-ratio: 2),\n only screen and ( min-resolution: 192dpi),\n only screen and ( min-resolution: 2dppx) {\n background-image: url(\"@{file-2x}\");\n background-size: @width-1x @height-1x;\n }\n}\n","//\n// Typography\n// --------------------------------------------------\n\n\n// Headings\n// -------------------------\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n font-family: @headings-font-family;\n font-weight: @headings-font-weight;\n line-height: @headings-line-height;\n color: @headings-color;\n\n small,\n .small {\n font-weight: normal;\n line-height: 1;\n color: @headings-small-color;\n }\n}\n\nh1, .h1,\nh2, .h2,\nh3, .h3 {\n margin-top: @line-height-computed;\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 65%;\n }\n}\nh4, .h4,\nh5, .h5,\nh6, .h6 {\n margin-top: (@line-height-computed / 2);\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 75%;\n }\n}\n\nh1, .h1 { font-size: @font-size-h1; }\nh2, .h2 { font-size: @font-size-h2; }\nh3, .h3 { font-size: @font-size-h3; }\nh4, .h4 { font-size: @font-size-h4; }\nh5, .h5 { font-size: @font-size-h5; }\nh6, .h6 { font-size: @font-size-h6; }\n\n\n// Body text\n// -------------------------\n\np {\n margin: 0 0 (@line-height-computed / 2);\n}\n\n.lead {\n margin-bottom: @line-height-computed;\n font-size: floor((@font-size-base * 1.15));\n font-weight: 300;\n line-height: 1.4;\n\n @media (min-width: @screen-sm-min) {\n font-size: (@font-size-base * 1.5);\n }\n}\n\n\n// Emphasis & misc\n// -------------------------\n\n// Ex: (12px small font / 14px base font) * 100% = about 85%\nsmall,\n.small {\n font-size: floor((100% * @font-size-small / @font-size-base));\n}\n\nmark,\n.mark {\n background-color: @state-warning-bg;\n padding: .2em;\n}\n\n// Alignment\n.text-left { text-align: left; }\n.text-right { text-align: right; }\n.text-center { text-align: center; }\n.text-justify { text-align: justify; }\n.text-nowrap { white-space: nowrap; }\n\n// Transformation\n.text-lowercase { text-transform: lowercase; }\n.text-uppercase { text-transform: uppercase; }\n.text-capitalize { text-transform: capitalize; }\n\n// Contextual colors\n.text-muted {\n color: @text-muted;\n}\n.text-primary {\n .text-emphasis-variant(@brand-primary);\n}\n.text-success {\n .text-emphasis-variant(@state-success-text);\n}\n.text-info {\n .text-emphasis-variant(@state-info-text);\n}\n.text-warning {\n .text-emphasis-variant(@state-warning-text);\n}\n.text-danger {\n .text-emphasis-variant(@state-danger-text);\n}\n\n// Contextual backgrounds\n// For now we'll leave these alongside the text classes until v4 when we can\n// safely shift things around (per SemVer rules).\n.bg-primary {\n // Given the contrast here, this is the only class to have its color inverted\n // automatically.\n color: #fff;\n .bg-variant(@brand-primary);\n}\n.bg-success {\n .bg-variant(@state-success-bg);\n}\n.bg-info {\n .bg-variant(@state-info-bg);\n}\n.bg-warning {\n .bg-variant(@state-warning-bg);\n}\n.bg-danger {\n .bg-variant(@state-danger-bg);\n}\n\n\n// Page header\n// -------------------------\n\n.page-header {\n padding-bottom: ((@line-height-computed / 2) - 1);\n margin: (@line-height-computed * 2) 0 @line-height-computed;\n border-bottom: 1px solid @page-header-border-color;\n}\n\n\n// Lists\n// -------------------------\n\n// Unordered and Ordered lists\nul,\nol {\n margin-top: 0;\n margin-bottom: (@line-height-computed / 2);\n ul,\n ol {\n margin-bottom: 0;\n }\n}\n\n// List options\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n\n// Inline turns list items into inline-block\n.list-inline {\n .list-unstyled();\n margin-left: -5px;\n\n > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n }\n}\n\n// Description Lists\ndl {\n margin-top: 0; // Remove browser default\n margin-bottom: @line-height-computed;\n}\ndt,\ndd {\n line-height: @line-height-base;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0; // Undo browser default\n}\n\n// Horizontal description lists\n//\n// Defaults to being stacked without any of the below styles applied, until the\n// grid breakpoint is reached (default of ~768px).\n\n.dl-horizontal {\n dd {\n &:extend(.clearfix all); // Clear the floated `dt` if an empty `dd` is present\n }\n\n @media (min-width: @dl-horizontal-breakpoint) {\n dt {\n float: left;\n width: (@dl-horizontal-offset - 20);\n clear: left;\n text-align: right;\n .text-overflow();\n }\n dd {\n margin-left: @dl-horizontal-offset;\n }\n }\n}\n\n\n// Misc\n// -------------------------\n\n// Abbreviations and acronyms\nabbr[title],\n// Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted @abbr-border-color;\n}\n.initialism {\n font-size: 90%;\n .text-uppercase();\n}\n\n// Blockquotes\nblockquote {\n padding: (@line-height-computed / 2) @line-height-computed;\n margin: 0 0 @line-height-computed;\n font-size: @blockquote-font-size;\n border-left: 5px solid @blockquote-border-color;\n\n p,\n ul,\n ol {\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n // Note: Deprecated small and .small as of v3.1.0\n // Context: https://github.com/twbs/bootstrap/issues/11660\n footer,\n small,\n .small {\n display: block;\n font-size: 80%; // back to default font-size\n line-height: @line-height-base;\n color: @blockquote-small-color;\n\n &:before {\n content: '\\2014 \\00A0'; // em dash, nbsp\n }\n }\n}\n\n// Opposite alignment of blockquote\n//\n// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0.\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid @blockquote-border-color;\n border-left: 0;\n text-align: right;\n\n // Account for citation\n footer,\n small,\n .small {\n &:before { content: ''; }\n &:after {\n content: '\\00A0 \\2014'; // nbsp, em dash\n }\n }\n}\n\n// Addresses\naddress {\n margin-bottom: @line-height-computed;\n font-style: normal;\n line-height: @line-height-base;\n}\n","// Typography\n\n.text-emphasis-variant(@color) {\n color: @color;\n a&:hover,\n a&:focus {\n color: darken(@color, 10%);\n }\n}\n","// Contextual backgrounds\n\n.bg-variant(@color) {\n background-color: @color;\n a&:hover,\n a&:focus {\n background-color: darken(@color, 10%);\n }\n}\n","// Text overflow\n// Requires inline-block or block for proper styling\n\n.text-overflow() {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n","//\n// Code (inline and block)\n// --------------------------------------------------\n\n\n// Inline and block code styles\ncode,\nkbd,\npre,\nsamp {\n font-family: @font-family-monospace;\n}\n\n// Inline code\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: @code-color;\n background-color: @code-bg;\n border-radius: @border-radius-base;\n}\n\n// User input typically entered via keyboard\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: @kbd-color;\n background-color: @kbd-bg;\n border-radius: @border-radius-small;\n box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);\n\n kbd {\n padding: 0;\n font-size: 100%;\n font-weight: bold;\n box-shadow: none;\n }\n}\n\n// Blocks of code\npre {\n display: block;\n padding: ((@line-height-computed - 1) / 2);\n margin: 0 0 (@line-height-computed / 2);\n font-size: (@font-size-base - 1); // 14px to 13px\n line-height: @line-height-base;\n word-break: break-all;\n word-wrap: break-word;\n color: @pre-color;\n background-color: @pre-bg;\n border: 1px solid @pre-border-color;\n border-radius: @border-radius-base;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n max-height: @pre-scrollable-max-height;\n overflow-y: scroll;\n}\n","//\n// Grid system\n// --------------------------------------------------\n\n\n// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n.container {\n .container-fixed();\n\n @media (min-width: @screen-sm-min) {\n width: @container-sm;\n }\n @media (min-width: @screen-md-min) {\n width: @container-md;\n }\n @media (min-width: @screen-lg-min) {\n width: @container-lg;\n }\n}\n\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but without any defined\n// width for fluid, full width layouts.\n\n.container-fluid {\n .container-fixed();\n}\n\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n.row {\n .make-row();\n}\n\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n.make-grid-columns();\n\n\n// Extra small grid\n//\n// Columns, offsets, pushes, and pulls for extra small devices like\n// smartphones.\n\n.make-grid(xs);\n\n\n// Small grid\n//\n// Columns, offsets, pushes, and pulls for the small device range, from phones\n// to tablets.\n\n@media (min-width: @screen-sm-min) {\n .make-grid(sm);\n}\n\n\n// Medium grid\n//\n// Columns, offsets, pushes, and pulls for the desktop device range.\n\n@media (min-width: @screen-md-min) {\n .make-grid(md);\n}\n\n\n// Large grid\n//\n// Columns, offsets, pushes, and pulls for the large desktop device range.\n\n@media (min-width: @screen-lg-min) {\n .make-grid(lg);\n}\n","// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n// Centered container element\n.container-fixed(@gutter: @grid-gutter-width) {\n margin-right: auto;\n margin-left: auto;\n padding-left: floor((@gutter / 2));\n padding-right: ceil((@gutter / 2));\n &:extend(.clearfix all);\n}\n\n// Creates a wrapper for a series of columns\n.make-row(@gutter: @grid-gutter-width) {\n margin-left: ceil((@gutter / -2));\n margin-right: floor((@gutter / -2));\n &:extend(.clearfix all);\n}\n\n// Generate the extra small columns\n.make-xs-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n float: left;\n width: percentage((@columns / @grid-columns));\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n}\n.make-xs-column-offset(@columns) {\n margin-left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-push(@columns) {\n left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-pull(@columns) {\n right: percentage((@columns / @grid-columns));\n}\n\n// Generate the small columns\n.make-sm-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-sm-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-offset(@columns) {\n @media (min-width: @screen-sm-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-push(@columns) {\n @media (min-width: @screen-sm-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-pull(@columns) {\n @media (min-width: @screen-sm-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the medium columns\n.make-md-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-md-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-offset(@columns) {\n @media (min-width: @screen-md-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-push(@columns) {\n @media (min-width: @screen-md-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-pull(@columns) {\n @media (min-width: @screen-md-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the large columns\n.make-lg-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-lg-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-offset(@columns) {\n @media (min-width: @screen-lg-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-push(@columns) {\n @media (min-width: @screen-lg-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-pull(@columns) {\n @media (min-width: @screen-lg-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `@grid-columns`.\n\n.make-grid-columns() {\n // Common styles for all sizes of grid columns, widths 1-12\n .col(@index) { // initial\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general; \"=<\" isn't a typo\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n position: relative;\n // Prevent columns from collapsing when empty\n min-height: 1px;\n // Inner gutter via padding\n padding-left: ceil((@grid-gutter-width / 2));\n padding-right: floor((@grid-gutter-width / 2));\n }\n }\n .col(1); // kickstart it\n}\n\n.float-grid-columns(@class) {\n .col(@index) { // initial\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n float: left;\n }\n }\n .col(1); // kickstart it\n}\n\n.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) {\n .col-@{class}-@{index} {\n width: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index > 0) {\n .col-@{class}-push-@{index} {\n left: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index = 0) {\n .col-@{class}-push-0 {\n left: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index > 0) {\n .col-@{class}-pull-@{index} {\n right: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index = 0) {\n .col-@{class}-pull-0 {\n right: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = offset) {\n .col-@{class}-offset-@{index} {\n margin-left: percentage((@index / @grid-columns));\n }\n}\n\n// Basic looping in LESS\n.loop-grid-columns(@index, @class, @type) when (@index >= 0) {\n .calc-grid-column(@index, @class, @type);\n // next iteration\n .loop-grid-columns((@index - 1), @class, @type);\n}\n\n// Create grid for specific class\n.make-grid(@class) {\n .float-grid-columns(@class);\n .loop-grid-columns(@grid-columns, @class, width);\n .loop-grid-columns(@grid-columns, @class, pull);\n .loop-grid-columns(@grid-columns, @class, push);\n .loop-grid-columns(@grid-columns, @class, offset);\n}\n","//\n// Tables\n// --------------------------------------------------\n\n\ntable {\n background-color: @table-bg;\n}\ncaption {\n padding-top: @table-cell-padding;\n padding-bottom: @table-cell-padding;\n color: @text-muted;\n text-align: left;\n}\nth {\n text-align: left;\n}\n\n\n// Baseline styles\n\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: @line-height-computed;\n // Cells\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-cell-padding;\n line-height: @line-height-base;\n vertical-align: top;\n border-top: 1px solid @table-border-color;\n }\n }\n }\n // Bottom align for column headings\n > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid @table-border-color;\n }\n // Remove top border from thead by default\n > caption + thead,\n > colgroup + thead,\n > thead:first-child {\n > tr:first-child {\n > th,\n > td {\n border-top: 0;\n }\n }\n }\n // Account for multiple tbody instances\n > tbody + tbody {\n border-top: 2px solid @table-border-color;\n }\n\n // Nesting\n .table {\n background-color: @body-bg;\n }\n}\n\n\n// Condensed table w/ half padding\n\n.table-condensed {\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-condensed-cell-padding;\n }\n }\n }\n}\n\n\n// Bordered version\n//\n// Add borders all around the table and between all the columns.\n\n.table-bordered {\n border: 1px solid @table-border-color;\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n border: 1px solid @table-border-color;\n }\n }\n }\n > thead > tr {\n > th,\n > td {\n border-bottom-width: 2px;\n }\n }\n}\n\n\n// Zebra-striping\n//\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n\n.table-striped {\n > tbody > tr:nth-of-type(odd) {\n background-color: @table-bg-accent;\n }\n}\n\n\n// Hover effect\n//\n// Placed here since it has to come after the potential zebra striping\n\n.table-hover {\n > tbody > tr:hover {\n background-color: @table-bg-hover;\n }\n}\n\n\n// Table cell sizing\n//\n// Reset default table behavior\n\ntable col[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-column;\n}\ntable {\n td,\n th {\n &[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-cell;\n }\n }\n}\n\n\n// Table backgrounds\n//\n// Exact selectors below required to override `.table-striped` and prevent\n// inheritance to nested tables.\n\n// Generate the contextual variants\n.table-row-variant(active; @table-bg-active);\n.table-row-variant(success; @state-success-bg);\n.table-row-variant(info; @state-info-bg);\n.table-row-variant(warning; @state-warning-bg);\n.table-row-variant(danger; @state-danger-bg);\n\n\n// Responsive tables\n//\n// Wrap your tables in `.table-responsive` and we'll make them mobile friendly\n// by enabling horizontal scrolling. Only applies <768px. Everything above that\n// will display normally.\n\n.table-responsive {\n overflow-x: auto;\n min-height: 0.01%; // Workaround for IE9 bug (see https://github.com/twbs/bootstrap/issues/14837)\n\n @media screen and (max-width: @screen-xs-max) {\n width: 100%;\n margin-bottom: (@line-height-computed * 0.75);\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid @table-border-color;\n\n // Tighten up spacing\n > .table {\n margin-bottom: 0;\n\n // Ensure the content doesn't wrap\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n white-space: nowrap;\n }\n }\n }\n }\n\n // Special overrides for the bordered tables\n > .table-bordered {\n border: 0;\n\n // Nuke the appropriate borders so that the parent can handle them\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th:first-child,\n > td:first-child {\n border-left: 0;\n }\n > th:last-child,\n > td:last-child {\n border-right: 0;\n }\n }\n }\n\n // Only nuke the last row's bottom-border in `tbody` and `tfoot` since\n // chances are there will be only one `tr` in a `thead` and that would\n // remove the border altogether.\n > tbody,\n > tfoot {\n > tr:last-child {\n > th,\n > td {\n border-bottom: 0;\n }\n }\n }\n\n }\n }\n}\n","// Tables\n\n.table-row-variant(@state; @background) {\n // Exact selectors below required to override `.table-striped` and prevent\n // inheritance to nested tables.\n .table > thead > tr,\n .table > tbody > tr,\n .table > tfoot > tr {\n > td.@{state},\n > th.@{state},\n &.@{state} > td,\n &.@{state} > th {\n background-color: @background;\n }\n }\n\n // Hover states for `.table-hover`\n // Note: this is not available for cells or rows within `thead` or `tfoot`.\n .table-hover > tbody > tr {\n > td.@{state}:hover,\n > th.@{state}:hover,\n &.@{state}:hover > td,\n &:hover > .@{state},\n &.@{state}:hover > th {\n background-color: darken(@background, 5%);\n }\n }\n}\n","//\n// Forms\n// --------------------------------------------------\n\n\n// Normalize non-controls\n//\n// Restyle and baseline non-control form elements.\n\nfieldset {\n padding: 0;\n margin: 0;\n border: 0;\n // Chrome and Firefox set a `min-width: min-content;` on fieldsets,\n // so we reset that to ensure it behaves more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359.\n min-width: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: @line-height-computed;\n font-size: (@font-size-base * 1.5);\n line-height: inherit;\n color: @legend-color;\n border: 0;\n border-bottom: 1px solid @legend-border-color;\n}\n\nlabel {\n display: inline-block;\n max-width: 100%; // Force IE8 to wrap long content (see https://github.com/twbs/bootstrap/issues/13141)\n margin-bottom: 5px;\n font-weight: bold;\n}\n\n\n// Normalize form controls\n//\n// While most of our form styles require extra classes, some basic normalization\n// is required to ensure optimum display with or without those classes to better\n// address browser inconsistencies.\n\n// Override content-box in Normalize (* isn't specific enough)\ninput[type=\"search\"] {\n .box-sizing(border-box);\n}\n\n// Position radios and checkboxes better\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9; // IE8-9\n line-height: normal;\n}\n\ninput[type=\"file\"] {\n display: block;\n}\n\n// Make range inputs behave like textual form controls\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\n\n// Make multiple select elements height not fixed\nselect[multiple],\nselect[size] {\n height: auto;\n}\n\n// Focus for file, radio, and checkbox\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n .tab-focus();\n}\n\n// Adjust output element\noutput {\n display: block;\n padding-top: (@padding-base-vertical + 1);\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n}\n\n\n// Common form controls\n//\n// Shared size and type resets for form controls. Apply `.form-control` to any\n// of the following form controls:\n//\n// select\n// textarea\n// input[type=\"text\"]\n// input[type=\"password\"]\n// input[type=\"datetime\"]\n// input[type=\"datetime-local\"]\n// input[type=\"date\"]\n// input[type=\"month\"]\n// input[type=\"time\"]\n// input[type=\"week\"]\n// input[type=\"number\"]\n// input[type=\"email\"]\n// input[type=\"url\"]\n// input[type=\"search\"]\n// input[type=\"tel\"]\n// input[type=\"color\"]\n\n.form-control {\n display: block;\n width: 100%;\n height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border)\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n background-color: @input-bg;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid @input-border;\n border-radius: @input-border-radius; // Note: This has no effect on s in CSS.\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.075));\n .transition(~\"border-color ease-in-out .15s, box-shadow ease-in-out .15s\");\n\n // Customize the `:focus` state to imitate native WebKit styles.\n .form-control-focus();\n\n // Placeholder\n .placeholder();\n\n // Unstyle the caret on ``\n// element gets special love because it's special, and that's a fact!\n.input-size(@input-height; @padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n height: @input-height;\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n\n select& {\n height: @input-height;\n line-height: @input-height;\n }\n\n textarea&,\n select[multiple]& {\n height: auto;\n }\n}\n","//\n// Buttons\n// --------------------------------------------------\n\n\n// Base styles\n// --------------------------------------------------\n\n.btn {\n display: inline-block;\n margin-bottom: 0; // For input.btn\n font-weight: @btn-font-weight;\n text-align: center;\n vertical-align: middle;\n touch-action: manipulation;\n cursor: pointer;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n white-space: nowrap;\n .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @btn-border-radius-base);\n .user-select(none);\n\n &,\n &:active,\n &.active {\n &:focus,\n &.focus {\n .tab-focus();\n }\n }\n\n &:hover,\n &:focus,\n &.focus {\n color: @btn-default-color;\n text-decoration: none;\n }\n\n &:active,\n &.active {\n outline: 0;\n background-image: none;\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n cursor: @cursor-disabled;\n .opacity(.65);\n .box-shadow(none);\n }\n\n a& {\n &.disabled,\n fieldset[disabled] & {\n pointer-events: none; // Future-proof disabling of clicks on `` elements\n }\n }\n}\n\n\n// Alternate buttons\n// --------------------------------------------------\n\n.btn-default {\n .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border);\n}\n.btn-primary {\n .button-variant(@btn-primary-color; @btn-primary-bg; @btn-primary-border);\n}\n// Success appears as green\n.btn-success {\n .button-variant(@btn-success-color; @btn-success-bg; @btn-success-border);\n}\n// Info appears as blue-green\n.btn-info {\n .button-variant(@btn-info-color; @btn-info-bg; @btn-info-border);\n}\n// Warning appears as orange\n.btn-warning {\n .button-variant(@btn-warning-color; @btn-warning-bg; @btn-warning-border);\n}\n// Danger and error appear as red\n.btn-danger {\n .button-variant(@btn-danger-color; @btn-danger-bg; @btn-danger-border);\n}\n\n\n// Link buttons\n// -------------------------\n\n// Make a button look and behave like a link\n.btn-link {\n color: @link-color;\n font-weight: normal;\n border-radius: 0;\n\n &,\n &:active,\n &.active,\n &[disabled],\n fieldset[disabled] & {\n background-color: transparent;\n .box-shadow(none);\n }\n &,\n &:hover,\n &:focus,\n &:active {\n border-color: transparent;\n }\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: @link-hover-decoration;\n background-color: transparent;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @btn-link-disabled-color;\n text-decoration: none;\n }\n }\n}\n\n\n// Button Sizes\n// --------------------------------------------------\n\n.btn-lg {\n // line-height: ensure even-numbered height of button next to large input\n .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @btn-border-radius-large);\n}\n.btn-sm {\n // line-height: ensure proper height of button next to small input\n .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small);\n}\n.btn-xs {\n .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small);\n}\n\n\n// Block button\n// --------------------------------------------------\n\n.btn-block {\n display: block;\n width: 100%;\n}\n\n// Vertically space out multiple block buttons\n.btn-block + .btn-block {\n margin-top: 5px;\n}\n\n// Specificity overrides\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"] {\n &.btn-block {\n width: 100%;\n }\n}\n","// Button variants\n//\n// Easily pump out default styles, as well as :hover, :focus, :active,\n// and disabled options for all buttons\n\n.button-variant(@color; @background; @border) {\n color: @color;\n background-color: @background;\n border-color: @border;\n\n &:focus,\n &.focus {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 25%);\n }\n &:hover {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 12%);\n }\n &:active,\n &.active,\n .open > .dropdown-toggle& {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 12%);\n\n &:hover,\n &:focus,\n &.focus {\n color: @color;\n background-color: darken(@background, 17%);\n border-color: darken(@border, 25%);\n }\n }\n &:active,\n &.active,\n .open > .dropdown-toggle& {\n background-image: none;\n }\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus,\n &.focus {\n background-color: @background;\n border-color: @border;\n }\n }\n\n .badge {\n color: @background;\n background-color: @color;\n }\n}\n\n// Button sizes\n.button-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n}\n","// Opacity\n\n.opacity(@opacity) {\n opacity: @opacity;\n // IE8 filter\n @opacity-ie: (@opacity * 100);\n filter: ~\"alpha(opacity=@{opacity-ie})\";\n}\n","//\n// Component animations\n// --------------------------------------------------\n\n// Heads up!\n//\n// We don't use the `.opacity()` mixin here since it causes a bug with text\n// fields in IE7-8. Source: https://github.com/twbs/bootstrap/pull/3552.\n\n.fade {\n opacity: 0;\n .transition(opacity .15s linear);\n &.in {\n opacity: 1;\n }\n}\n\n.collapse {\n display: none;\n\n &.in { display: block; }\n tr&.in { display: table-row; }\n tbody&.in { display: table-row-group; }\n}\n\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n .transition-property(~\"height, visibility\");\n .transition-duration(.35s);\n .transition-timing-function(ease);\n}\n","//\n// Dropdown menus\n// --------------------------------------------------\n\n\n// Dropdown arrow/caret\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: @caret-width-base dashed;\n border-top: @caret-width-base solid ~\"\\9\"; // IE8\n border-right: @caret-width-base solid transparent;\n border-left: @caret-width-base solid transparent;\n}\n\n// The dropdown wrapper (div)\n.dropup,\n.dropdown {\n position: relative;\n}\n\n// Prevent the focus on the dropdown toggle when closing dropdowns\n.dropdown-toggle:focus {\n outline: 0;\n}\n\n// The dropdown menu (ul)\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: @zindex-dropdown;\n display: none; // none by default, but block on \"open\" of the menu\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0; // override default ul\n list-style: none;\n font-size: @font-size-base;\n text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer)\n background-color: @dropdown-bg;\n border: 1px solid @dropdown-fallback-border; // IE8 fallback\n border: 1px solid @dropdown-border;\n border-radius: @border-radius-base;\n .box-shadow(0 6px 12px rgba(0,0,0,.175));\n background-clip: padding-box;\n\n // Aligns the dropdown menu to right\n //\n // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]`\n &.pull-right {\n right: 0;\n left: auto;\n }\n\n // Dividers (basically an hr) within the dropdown\n .divider {\n .nav-divider(@dropdown-divider-bg);\n }\n\n // Links within the dropdown menu\n > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: @line-height-base;\n color: @dropdown-link-color;\n white-space: nowrap; // prevent links from randomly breaking onto new lines\n }\n}\n\n// Hover/Focus state\n.dropdown-menu > li > a {\n &:hover,\n &:focus {\n text-decoration: none;\n color: @dropdown-link-hover-color;\n background-color: @dropdown-link-hover-bg;\n }\n}\n\n// Active state\n.dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-active-color;\n text-decoration: none;\n outline: 0;\n background-color: @dropdown-link-active-bg;\n }\n}\n\n// Disabled state\n//\n// Gray out text and ensure the hover/focus state remains gray\n\n.dropdown-menu > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-disabled-color;\n }\n\n // Nuke hover/focus effects\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: transparent;\n background-image: none; // Remove CSS gradient\n .reset-filter();\n cursor: @cursor-disabled;\n }\n}\n\n// Open state for the dropdown\n.open {\n // Show the menu\n > .dropdown-menu {\n display: block;\n }\n\n // Remove the outline when :focus is triggered\n > a {\n outline: 0;\n }\n}\n\n// Menu positioning\n//\n// Add extra class to `.dropdown-menu` to flip the alignment of the dropdown\n// menu with the parent.\n.dropdown-menu-right {\n left: auto; // Reset the default from `.dropdown-menu`\n right: 0;\n}\n// With v3, we enabled auto-flipping if you have a dropdown within a right\n// aligned nav component. To enable the undoing of that, we provide an override\n// to restore the default dropdown menu alignment.\n//\n// This is only for left-aligning a dropdown menu within a `.navbar-right` or\n// `.pull-right` nav component.\n.dropdown-menu-left {\n left: 0;\n right: auto;\n}\n\n// Dropdown section headers\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: @font-size-small;\n line-height: @line-height-base;\n color: @dropdown-header-color;\n white-space: nowrap; // as with > li > a\n}\n\n// Backdrop to catch body clicks on mobile, etc.\n.dropdown-backdrop {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n z-index: (@zindex-dropdown - 10);\n}\n\n// Right aligned dropdowns\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n\n// Allow for dropdowns to go bottom up (aka, dropup-menu)\n//\n// Just add .dropup after the standard .dropdown class and you're set, bro.\n// TODO: abstract this so that the navbar fixed styles are not placed here?\n\n.dropup,\n.navbar-fixed-bottom .dropdown {\n // Reverse the caret\n .caret {\n border-top: 0;\n border-bottom: @caret-width-base dashed;\n border-bottom: @caret-width-base solid ~\"\\9\"; // IE8\n content: \"\";\n }\n // Different positioning for bottom up menu\n .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n }\n}\n\n\n// Component alignment\n//\n// Reiterate per navbar.less and the modified component alignment there.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-right {\n .dropdown-menu {\n .dropdown-menu-right();\n }\n // Necessary for overrides of the default right aligned menu.\n // Will remove come v4 in all likelihood.\n .dropdown-menu-left {\n .dropdown-menu-left();\n }\n }\n}\n","// Horizontal dividers\n//\n// Dividers (basically an hr) within dropdowns and nav lists\n\n.nav-divider(@color: #e5e5e5) {\n height: 1px;\n margin: ((@line-height-computed / 2) - 1) 0;\n overflow: hidden;\n background-color: @color;\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n","//\n// Button groups\n// --------------------------------------------------\n\n// Make the div behave like a button\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle; // match .btn alignment given font-size hack above\n > .btn {\n position: relative;\n float: left;\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active,\n &.active {\n z-index: 2;\n }\n }\n}\n\n// Prevent double borders when buttons are next to each other\n.btn-group {\n .btn + .btn,\n .btn + .btn-group,\n .btn-group + .btn,\n .btn-group + .btn-group {\n margin-left: -1px;\n }\n}\n\n// Optional: Group multiple button groups together for a toolbar\n.btn-toolbar {\n margin-left: -5px; // Offset the first child's margin\n &:extend(.clearfix all);\n\n .btn,\n .btn-group,\n .input-group {\n float: left;\n }\n > .btn,\n > .btn-group,\n > .input-group {\n margin-left: 5px;\n }\n}\n\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n\n// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match\n.btn-group > .btn:first-child {\n margin-left: 0;\n &:not(:last-child):not(.dropdown-toggle) {\n .border-right-radius(0);\n }\n}\n// Need .dropdown-toggle since :last-child doesn't apply, given that a .dropdown-menu is used immediately after it\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n .border-left-radius(0);\n}\n\n// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group)\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-right-radius(0);\n }\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n .border-left-radius(0);\n}\n\n// On active and open, don't show outline\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n\n\n// Sizing\n//\n// Remix the default button sizing classes into new ones for easier manipulation.\n\n.btn-group-xs > .btn { &:extend(.btn-xs); }\n.btn-group-sm > .btn { &:extend(.btn-sm); }\n.btn-group-lg > .btn { &:extend(.btn-lg); }\n\n\n// Split button dropdowns\n// ----------------------\n\n// Give the line between buttons some depth\n.btn-group > .btn + .dropdown-toggle {\n padding-left: 8px;\n padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-left: 12px;\n padding-right: 12px;\n}\n\n// The clickable button for toggling the menu\n// Remove the gradient and set the same inset shadow as the :active state\n.btn-group.open .dropdown-toggle {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n\n // Show no shadow for `.btn-link` since it has no other button styles.\n &.btn-link {\n .box-shadow(none);\n }\n}\n\n\n// Reposition the caret\n.btn .caret {\n margin-left: 0;\n}\n// Carets in other button sizes\n.btn-lg .caret {\n border-width: @caret-width-large @caret-width-large 0;\n border-bottom-width: 0;\n}\n// Upside down carets for .dropup\n.dropup .btn-lg .caret {\n border-width: 0 @caret-width-large @caret-width-large;\n}\n\n\n// Vertical button groups\n// ----------------------\n\n.btn-group-vertical {\n > .btn,\n > .btn-group,\n > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n }\n\n // Clear floats so dropdown menus can be properly placed\n > .btn-group {\n &:extend(.clearfix all);\n > .btn {\n float: none;\n }\n }\n\n > .btn + .btn,\n > .btn + .btn-group,\n > .btn-group + .btn,\n > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n }\n}\n\n.btn-group-vertical > .btn {\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n &:first-child:not(:last-child) {\n .border-top-radius(@btn-border-radius-base);\n .border-bottom-radius(0);\n }\n &:last-child:not(:first-child) {\n .border-top-radius(0);\n .border-bottom-radius(@btn-border-radius-base);\n }\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-bottom-radius(0);\n }\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n .border-top-radius(0);\n}\n\n\n// Justified button groups\n// ----------------------\n\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n > .btn,\n > .btn-group {\n float: none;\n display: table-cell;\n width: 1%;\n }\n > .btn-group .btn {\n width: 100%;\n }\n\n > .btn-group .dropdown-menu {\n left: auto;\n }\n}\n\n\n// Checkbox and radio options\n//\n// In order to support the browser's form validation feedback, powered by the\n// `required` attribute, we have to \"hide\" the inputs via `clip`. We cannot use\n// `display: none;` or `visibility: hidden;` as that also hides the popover.\n// Simply visually hiding the inputs via `opacity` would leave them clickable in\n// certain cases which is prevented by using `clip` and `pointer-events`.\n// This way, we ensure a DOM element is visible to position the popover from.\n//\n// See https://github.com/twbs/bootstrap/pull/12794 and\n// https://github.com/twbs/bootstrap/pull/14559 for more information.\n\n[data-toggle=\"buttons\"] {\n > .btn,\n > .btn-group > .btn {\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0,0,0,0);\n pointer-events: none;\n }\n }\n}\n","// Single side border-radius\n\n.border-top-radius(@radius) {\n border-top-right-radius: @radius;\n border-top-left-radius: @radius;\n}\n.border-right-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-top-right-radius: @radius;\n}\n.border-bottom-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-bottom-left-radius: @radius;\n}\n.border-left-radius(@radius) {\n border-bottom-left-radius: @radius;\n border-top-left-radius: @radius;\n}\n","//\n// Input groups\n// --------------------------------------------------\n\n// Base styles\n// -------------------------\n.input-group {\n position: relative; // For dropdowns\n display: table;\n border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table\n\n // Undo padding and float of grid classes\n &[class*=\"col-\"] {\n float: none;\n padding-left: 0;\n padding-right: 0;\n }\n\n .form-control {\n // Ensure that the input is always above the *appended* addon button for\n // proper border colors.\n position: relative;\n z-index: 2;\n\n // IE9 fubars the placeholder attribute in text inputs and the arrows on\n // select elements in input groups. To fix it, we float the input. Details:\n // https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855\n float: left;\n\n width: 100%;\n margin-bottom: 0;\n\n &:focus {\n z-index: 3;\n }\n }\n}\n\n// Sizing options\n//\n// Remix the default form control sizing classes into new ones for easier\n// manipulation.\n\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n .input-lg();\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n .input-sm();\n}\n\n\n// Display as table-cell\n// -------------------------\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n}\n// Addon and addon wrapper for buttons\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle; // Match the inputs\n}\n\n// Text input groups\n// -------------------------\n.input-group-addon {\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n font-weight: normal;\n line-height: 1;\n color: @input-color;\n text-align: center;\n background-color: @input-group-addon-bg;\n border: 1px solid @input-group-addon-border-color;\n border-radius: @input-border-radius;\n\n // Sizing\n &.input-sm {\n padding: @padding-small-vertical @padding-small-horizontal;\n font-size: @font-size-small;\n border-radius: @input-border-radius-small;\n }\n &.input-lg {\n padding: @padding-large-vertical @padding-large-horizontal;\n font-size: @font-size-large;\n border-radius: @input-border-radius-large;\n }\n\n // Nuke default margins from checkboxes and radios to vertically center within.\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n margin-top: 0;\n }\n}\n\n// Reset rounded corners\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n .border-right-radius(0);\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n .border-left-radius(0);\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n\n// Button input groups\n// -------------------------\n.input-group-btn {\n position: relative;\n // Jankily prevent input button groups from wrapping with `white-space` and\n // `font-size` in combination with `inline-block` on buttons.\n font-size: 0;\n white-space: nowrap;\n\n // Negative margin for spacing, position for bringing hovered/focused/actived\n // element above the siblings.\n > .btn {\n position: relative;\n + .btn {\n margin-left: -1px;\n }\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active {\n z-index: 2;\n }\n }\n\n // Negative margin to only have a 1px border between the two\n &:first-child {\n > .btn,\n > .btn-group {\n margin-right: -1px;\n }\n }\n &:last-child {\n > .btn,\n > .btn-group {\n z-index: 2;\n margin-left: -1px;\n }\n }\n}\n","//\n// Navs\n// --------------------------------------------------\n\n\n// Base class\n// --------------------------------------------------\n\n.nav {\n margin-bottom: 0;\n padding-left: 0; // Override default ul/ol\n list-style: none;\n &:extend(.clearfix all);\n\n > li {\n position: relative;\n display: block;\n\n > a {\n position: relative;\n display: block;\n padding: @nav-link-padding;\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: @nav-link-hover-bg;\n }\n }\n\n // Disabled state sets text to gray and nukes hover/tab effects\n &.disabled > a {\n color: @nav-disabled-link-color;\n\n &:hover,\n &:focus {\n color: @nav-disabled-link-hover-color;\n text-decoration: none;\n background-color: transparent;\n cursor: @cursor-disabled;\n }\n }\n }\n\n // Open dropdowns\n .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @nav-link-hover-bg;\n border-color: @link-color;\n }\n }\n\n // Nav dividers (deprecated with v3.0.1)\n //\n // This should have been removed in v3 with the dropping of `.nav-list`, but\n // we missed it. We don't currently support this anywhere, but in the interest\n // of maintaining backward compatibility in case you use it, it's deprecated.\n .nav-divider {\n .nav-divider();\n }\n\n // Prevent IE8 from misplacing imgs\n //\n // See https://github.com/h5bp/html5-boilerplate/issues/984#issuecomment-3985989\n > li > a > img {\n max-width: none;\n }\n}\n\n\n// Tabs\n// -------------------------\n\n// Give the tabs something to sit on\n.nav-tabs {\n border-bottom: 1px solid @nav-tabs-border-color;\n > li {\n float: left;\n // Make the list-items overlay the bottom border\n margin-bottom: -1px;\n\n // Actual tabs (as links)\n > a {\n margin-right: 2px;\n line-height: @line-height-base;\n border: 1px solid transparent;\n border-radius: @border-radius-base @border-radius-base 0 0;\n &:hover {\n border-color: @nav-tabs-link-hover-border-color @nav-tabs-link-hover-border-color @nav-tabs-border-color;\n }\n }\n\n // Active state, and its :hover to override normal :hover\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-tabs-active-link-hover-color;\n background-color: @nav-tabs-active-link-hover-bg;\n border: 1px solid @nav-tabs-active-link-hover-border-color;\n border-bottom-color: transparent;\n cursor: default;\n }\n }\n }\n // pulling this in mainly for less shorthand\n &.nav-justified {\n .nav-justified();\n .nav-tabs-justified();\n }\n}\n\n\n// Pills\n// -------------------------\n.nav-pills {\n > li {\n float: left;\n\n // Links rendered as pills\n > a {\n border-radius: @nav-pills-border-radius;\n }\n + li {\n margin-left: 2px;\n }\n\n // Active state\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-pills-active-link-hover-color;\n background-color: @nav-pills-active-link-hover-bg;\n }\n }\n }\n}\n\n\n// Stacked pills\n.nav-stacked {\n > li {\n float: none;\n + li {\n margin-top: 2px;\n margin-left: 0; // no need for this gap between nav items\n }\n }\n}\n\n\n// Nav variations\n// --------------------------------------------------\n\n// Justified nav links\n// -------------------------\n\n.nav-justified {\n width: 100%;\n\n > li {\n float: none;\n > a {\n text-align: center;\n margin-bottom: 5px;\n }\n }\n\n > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n }\n\n @media (min-width: @screen-sm-min) {\n > li {\n display: table-cell;\n width: 1%;\n > a {\n margin-bottom: 0;\n }\n }\n }\n}\n\n// Move borders to anchors instead of bottom of list\n//\n// Mixin for adding on top the shared `.nav-justified` styles for our tabs\n.nav-tabs-justified {\n border-bottom: 0;\n\n > li > a {\n // Override margin from .nav-tabs\n margin-right: 0;\n border-radius: @border-radius-base;\n }\n\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border: 1px solid @nav-tabs-justified-link-border-color;\n }\n\n @media (min-width: @screen-sm-min) {\n > li > a {\n border-bottom: 1px solid @nav-tabs-justified-link-border-color;\n border-radius: @border-radius-base @border-radius-base 0 0;\n }\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border-bottom-color: @nav-tabs-justified-active-link-border-color;\n }\n }\n}\n\n\n// Tabbable tabs\n// -------------------------\n\n// Hide tabbable panes to start, show them when `.active`\n.tab-content {\n > .tab-pane {\n display: none;\n }\n > .active {\n display: block;\n }\n}\n\n\n// Dropdowns\n// -------------------------\n\n// Specific dropdowns\n.nav-tabs .dropdown-menu {\n // make dropdown border overlap tab border\n margin-top: -1px;\n // Remove the top rounded corners here since there is a hard edge above the menu\n .border-top-radius(0);\n}\n","//\n// Navbars\n// --------------------------------------------------\n\n\n// Wrapper and base class\n//\n// Provide a static navbar from which we expand to create full-width, fixed, and\n// other navbar variations.\n\n.navbar {\n position: relative;\n min-height: @navbar-height; // Ensure a navbar always shows (e.g., without a .navbar-brand in collapsed mode)\n margin-bottom: @navbar-margin-bottom;\n border: 1px solid transparent;\n\n // Prevent floats from breaking the navbar\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: @navbar-border-radius;\n }\n}\n\n\n// Navbar heading\n//\n// Groups `.navbar-brand` and `.navbar-toggle` into a single component for easy\n// styling of responsive aspects.\n\n.navbar-header {\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n }\n}\n\n\n// Navbar collapse (body)\n//\n// Group your navbar content into this for easy collapsing and expanding across\n// various device sizes. By default, this content is collapsed when <768px, but\n// will expand past that for a horizontal display.\n//\n// To start (on mobile devices) the navbar links, forms, and buttons are stacked\n// vertically and include a `max-height` to overflow in case you have too much\n// content for the user's viewport.\n\n.navbar-collapse {\n overflow-x: visible;\n padding-right: @navbar-padding-horizontal;\n padding-left: @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255,255,255,.1);\n &:extend(.clearfix all);\n -webkit-overflow-scrolling: touch;\n\n &.in {\n overflow-y: auto;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border-top: 0;\n box-shadow: none;\n\n &.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0; // Override default setting\n overflow: visible !important;\n }\n\n &.in {\n overflow-y: visible;\n }\n\n // Undo the collapse side padding for navbars with containers to ensure\n // alignment of right-aligned contents.\n .navbar-fixed-top &,\n .navbar-static-top &,\n .navbar-fixed-bottom & {\n padding-left: 0;\n padding-right: 0;\n }\n }\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n .navbar-collapse {\n max-height: @navbar-collapse-max-height;\n\n @media (max-device-width: @screen-xs-min) and (orientation: landscape) {\n max-height: 200px;\n }\n }\n}\n\n\n// Both navbar header and collapse\n//\n// When a container is present, change the behavior of the header and collapse.\n\n.container,\n.container-fluid {\n > .navbar-header,\n > .navbar-collapse {\n margin-right: -@navbar-padding-horizontal;\n margin-left: -@navbar-padding-horizontal;\n\n @media (min-width: @grid-float-breakpoint) {\n margin-right: 0;\n margin-left: 0;\n }\n }\n}\n\n\n//\n// Navbar alignment options\n//\n// Display the navbar across the entirety of the page or fixed it to the top or\n// bottom of the page.\n\n// Static top (unfixed, but 100% wide) navbar\n.navbar-static-top {\n z-index: @zindex-navbar;\n border-width: 0 0 1px;\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n\n// Fix the top/bottom navbars when screen real estate supports it\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: @zindex-navbar-fixed;\n\n // Undo the rounded corners\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0; // override .navbar defaults\n border-width: 1px 0 0;\n}\n\n\n// Brand/project name\n\n.navbar-brand {\n float: left;\n padding: @navbar-padding-vertical @navbar-padding-horizontal;\n font-size: @font-size-large;\n line-height: @line-height-computed;\n height: @navbar-height;\n\n &:hover,\n &:focus {\n text-decoration: none;\n }\n\n > img {\n display: block;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n .navbar > .container &,\n .navbar > .container-fluid & {\n margin-left: -@navbar-padding-horizontal;\n }\n }\n}\n\n\n// Navbar toggle\n//\n// Custom button for toggling the `.navbar-collapse`, powered by the collapse\n// JavaScript plugin.\n\n.navbar-toggle {\n position: relative;\n float: right;\n margin-right: @navbar-padding-horizontal;\n padding: 9px 10px;\n .navbar-vertical-align(34px);\n background-color: transparent;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n border-radius: @border-radius-base;\n\n // We remove the `outline` here, but later compensate by attaching `:hover`\n // styles to `:focus`.\n &:focus {\n outline: 0;\n }\n\n // Bars\n .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n }\n .icon-bar + .icon-bar {\n margin-top: 4px;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n display: none;\n }\n}\n\n\n// Navbar nav links\n//\n// Builds on top of the `.nav` components with its own modifier class to make\n// the nav the full height of the horizontal nav (above 768px).\n\n.navbar-nav {\n margin: (@navbar-padding-vertical / 2) -@navbar-padding-horizontal;\n\n > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: @line-height-computed;\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n > li > a,\n .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n > li > a {\n line-height: @line-height-computed;\n &:hover,\n &:focus {\n background-image: none;\n }\n }\n }\n }\n\n // Uncollapse the nav\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin: 0;\n\n > li {\n float: left;\n > a {\n padding-top: @navbar-padding-vertical;\n padding-bottom: @navbar-padding-vertical;\n }\n }\n }\n}\n\n\n// Navbar form\n//\n// Extension of the `.form-inline` with some extra flavor for optimum display in\n// our navbars.\n\n.navbar-form {\n margin-left: -@navbar-padding-horizontal;\n margin-right: -@navbar-padding-horizontal;\n padding: 10px @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n @shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n\n // Mixin behavior for optimum display\n .form-inline();\n\n .form-group {\n @media (max-width: @grid-float-breakpoint-max) {\n margin-bottom: 5px;\n\n &:last-child {\n margin-bottom: 0;\n }\n }\n }\n\n // Vertically center in expanded, horizontal navbar\n .navbar-vertical-align(@input-height-base);\n\n // Undo 100% width for pull classes\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border: 0;\n margin-left: 0;\n margin-right: 0;\n padding-top: 0;\n padding-bottom: 0;\n .box-shadow(none);\n }\n}\n\n\n// Dropdown menus\n\n// Menu position and menu carets\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n .border-top-radius(0);\n}\n// Menu position and menu caret support for dropups via extra dropup class\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n .border-top-radius(@navbar-border-radius);\n .border-bottom-radius(0);\n}\n\n\n// Buttons in navbars\n//\n// Vertically center a button within a navbar (when *not* in a form).\n\n.navbar-btn {\n .navbar-vertical-align(@input-height-base);\n\n &.btn-sm {\n .navbar-vertical-align(@input-height-small);\n }\n &.btn-xs {\n .navbar-vertical-align(22);\n }\n}\n\n\n// Text in navbars\n//\n// Add a class to make any element properly align itself vertically within the navbars.\n\n.navbar-text {\n .navbar-vertical-align(@line-height-computed);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin-left: @navbar-padding-horizontal;\n margin-right: @navbar-padding-horizontal;\n }\n}\n\n\n// Component alignment\n//\n// Repurpose the pull utilities as their own navbar utilities to avoid specificity\n// issues with parents and chaining. Only do this when the navbar is uncollapsed\n// though so that navbar contents properly stack and align in mobile.\n//\n// Declared after the navbar components to ensure more specificity on the margins.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-left { .pull-left(); }\n .navbar-right {\n .pull-right();\n margin-right: -@navbar-padding-horizontal;\n\n ~ .navbar-right {\n margin-right: 0;\n }\n }\n}\n\n\n// Alternate navbars\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n background-color: @navbar-default-bg;\n border-color: @navbar-default-border;\n\n .navbar-brand {\n color: @navbar-default-brand-color;\n &:hover,\n &:focus {\n color: @navbar-default-brand-hover-color;\n background-color: @navbar-default-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-default-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-default-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n\n .navbar-toggle {\n border-color: @navbar-default-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-default-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-default-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: @navbar-default-border;\n }\n\n // Dropdown menu items\n .navbar-nav {\n // Remove background color from open dropdown\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-default-link-active-bg;\n color: @navbar-default-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n > li > a {\n color: @navbar-default-link-color;\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n }\n }\n\n\n // Links in navbars\n //\n // Add a class to ensure links outside the navbar nav are colored correctly.\n\n .navbar-link {\n color: @navbar-default-link-color;\n &:hover {\n color: @navbar-default-link-hover-color;\n }\n }\n\n .btn-link {\n color: @navbar-default-link-color;\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n }\n }\n }\n}\n\n// Inverse navbar\n\n.navbar-inverse {\n background-color: @navbar-inverse-bg;\n border-color: @navbar-inverse-border;\n\n .navbar-brand {\n color: @navbar-inverse-brand-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-brand-hover-color;\n background-color: @navbar-inverse-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-inverse-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-inverse-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n\n // Darken the responsive nav toggle\n .navbar-toggle {\n border-color: @navbar-inverse-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-inverse-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-inverse-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: darken(@navbar-inverse-bg, 7%);\n }\n\n // Dropdowns\n .navbar-nav {\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-inverse-link-active-bg;\n color: @navbar-inverse-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display\n .open .dropdown-menu {\n > .dropdown-header {\n border-color: @navbar-inverse-border;\n }\n .divider {\n background-color: @navbar-inverse-border;\n }\n > li > a {\n color: @navbar-inverse-link-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n }\n }\n\n .navbar-link {\n color: @navbar-inverse-link-color;\n &:hover {\n color: @navbar-inverse-link-hover-color;\n }\n }\n\n .btn-link {\n color: @navbar-inverse-link-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n }\n }\n }\n}\n","// Navbar vertical align\n//\n// Vertically center elements in the navbar.\n// Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin.\n\n.navbar-vertical-align(@element-height) {\n margin-top: ((@navbar-height - @element-height) / 2);\n margin-bottom: ((@navbar-height - @element-height) / 2);\n}\n","//\n// Utility classes\n// --------------------------------------------------\n\n\n// Floats\n// -------------------------\n\n.clearfix {\n .clearfix();\n}\n.center-block {\n .center-block();\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n\n\n// Toggling content\n// -------------------------\n\n// Note: Deprecated .hide in favor of .hidden or .sr-only (as appropriate) in v3.0.1\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n .text-hide();\n}\n\n\n// Hide from screenreaders and browsers\n//\n// Credit: HTML5 Boilerplate\n\n.hidden {\n display: none !important;\n}\n\n\n// For Affix plugin\n// -------------------------\n\n.affix {\n position: fixed;\n}\n","//\n// Breadcrumbs\n// --------------------------------------------------\n\n\n.breadcrumb {\n padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal;\n margin-bottom: @line-height-computed;\n list-style: none;\n background-color: @breadcrumb-bg;\n border-radius: @border-radius-base;\n\n > li {\n display: inline-block;\n\n + li:before {\n content: \"@{breadcrumb-separator}\\00a0\"; // Unicode space added since inline-block means non-collapsing white-space\n padding: 0 5px;\n color: @breadcrumb-color;\n }\n }\n\n > .active {\n color: @breadcrumb-active-color;\n }\n}\n","//\n// Pagination (multiple pages)\n// --------------------------------------------------\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: @line-height-computed 0;\n border-radius: @border-radius-base;\n\n > li {\n display: inline; // Remove list-style and block-level defaults\n > a,\n > span {\n position: relative;\n float: left; // Collapse white-space\n padding: @padding-base-vertical @padding-base-horizontal;\n line-height: @line-height-base;\n text-decoration: none;\n color: @pagination-color;\n background-color: @pagination-bg;\n border: 1px solid @pagination-border;\n margin-left: -1px;\n }\n &:first-child {\n > a,\n > span {\n margin-left: 0;\n .border-left-radius(@border-radius-base);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius-base);\n }\n }\n }\n\n > li > a,\n > li > span {\n &:hover,\n &:focus {\n z-index: 2;\n color: @pagination-hover-color;\n background-color: @pagination-hover-bg;\n border-color: @pagination-hover-border;\n }\n }\n\n > .active > a,\n > .active > span {\n &,\n &:hover,\n &:focus {\n z-index: 3;\n color: @pagination-active-color;\n background-color: @pagination-active-bg;\n border-color: @pagination-active-border;\n cursor: default;\n }\n }\n\n > .disabled {\n > span,\n > span:hover,\n > span:focus,\n > a,\n > a:hover,\n > a:focus {\n color: @pagination-disabled-color;\n background-color: @pagination-disabled-bg;\n border-color: @pagination-disabled-border;\n cursor: @cursor-disabled;\n }\n }\n}\n\n// Sizing\n// --------------------------------------------------\n\n// Large\n.pagination-lg {\n .pagination-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\n}\n\n// Small\n.pagination-sm {\n .pagination-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n","// Pagination\n\n.pagination-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n > li {\n > a,\n > span {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n }\n &:first-child {\n > a,\n > span {\n .border-left-radius(@border-radius);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius);\n }\n }\n }\n}\n","//\n// Pager pagination\n// --------------------------------------------------\n\n\n.pager {\n padding-left: 0;\n margin: @line-height-computed 0;\n list-style: none;\n text-align: center;\n &:extend(.clearfix all);\n li {\n display: inline;\n > a,\n > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: @pager-bg;\n border: 1px solid @pager-border;\n border-radius: @pager-border-radius;\n }\n\n > a:hover,\n > a:focus {\n text-decoration: none;\n background-color: @pager-hover-bg;\n }\n }\n\n .next {\n > a,\n > span {\n float: right;\n }\n }\n\n .previous {\n > a,\n > span {\n float: left;\n }\n }\n\n .disabled {\n > a,\n > a:hover,\n > a:focus,\n > span {\n color: @pager-disabled-color;\n background-color: @pager-bg;\n cursor: @cursor-disabled;\n }\n }\n}\n","//\n// Labels\n// --------------------------------------------------\n\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: @label-color;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n\n // Add hover effects, but only for links\n a& {\n &:hover,\n &:focus {\n color: @label-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n }\n\n // Empty labels collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for labels in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n}\n\n// Colors\n// Contextual variations (linked labels get darker on :hover)\n\n.label-default {\n .label-variant(@label-default-bg);\n}\n\n.label-primary {\n .label-variant(@label-primary-bg);\n}\n\n.label-success {\n .label-variant(@label-success-bg);\n}\n\n.label-info {\n .label-variant(@label-info-bg);\n}\n\n.label-warning {\n .label-variant(@label-warning-bg);\n}\n\n.label-danger {\n .label-variant(@label-danger-bg);\n}\n","// Labels\n\n.label-variant(@color) {\n background-color: @color;\n\n &[href] {\n &:hover,\n &:focus {\n background-color: darken(@color, 10%);\n }\n }\n}\n","//\n// Badges\n// --------------------------------------------------\n\n\n// Base class\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: @font-size-small;\n font-weight: @badge-font-weight;\n color: @badge-color;\n line-height: @badge-line-height;\n vertical-align: middle;\n white-space: nowrap;\n text-align: center;\n background-color: @badge-bg;\n border-radius: @badge-border-radius;\n\n // Empty badges collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for badges in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n\n .btn-xs &,\n .btn-group-xs > .btn & {\n top: 0;\n padding: 1px 5px;\n }\n\n // Hover state, but only for links\n a& {\n &:hover,\n &:focus {\n color: @badge-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n }\n\n // Account for badges in navs\n .list-group-item.active > &,\n .nav-pills > .active > a > & {\n color: @badge-active-color;\n background-color: @badge-active-bg;\n }\n\n .list-group-item > & {\n float: right;\n }\n\n .list-group-item > & + & {\n margin-right: 5px;\n }\n\n .nav-pills > li > a > & {\n margin-left: 3px;\n }\n}\n","//\n// Jumbotron\n// --------------------------------------------------\n\n\n.jumbotron {\n padding-top: @jumbotron-padding;\n padding-bottom: @jumbotron-padding;\n margin-bottom: @jumbotron-padding;\n color: @jumbotron-color;\n background-color: @jumbotron-bg;\n\n h1,\n .h1 {\n color: @jumbotron-heading-color;\n }\n\n p {\n margin-bottom: (@jumbotron-padding / 2);\n font-size: @jumbotron-font-size;\n font-weight: 200;\n }\n\n > hr {\n border-top-color: darken(@jumbotron-bg, 10%);\n }\n\n .container &,\n .container-fluid & {\n border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container\n padding-left: (@grid-gutter-width / 2);\n padding-right: (@grid-gutter-width / 2);\n }\n\n .container {\n max-width: 100%;\n }\n\n @media screen and (min-width: @screen-sm-min) {\n padding-top: (@jumbotron-padding * 1.6);\n padding-bottom: (@jumbotron-padding * 1.6);\n\n .container &,\n .container-fluid & {\n padding-left: (@jumbotron-padding * 2);\n padding-right: (@jumbotron-padding * 2);\n }\n\n h1,\n .h1 {\n font-size: @jumbotron-heading-font-size;\n }\n }\n}\n","//\n// Thumbnails\n// --------------------------------------------------\n\n\n// Mixin and adjust the regular image class\n.thumbnail {\n display: block;\n padding: @thumbnail-padding;\n margin-bottom: @line-height-computed;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(border .2s ease-in-out);\n\n > img,\n a > img {\n &:extend(.img-responsive);\n margin-left: auto;\n margin-right: auto;\n }\n\n // Add a hover state for linked versions only\n a&:hover,\n a&:focus,\n a&.active {\n border-color: @link-color;\n }\n\n // Image captions\n .caption {\n padding: @thumbnail-caption-padding;\n color: @thumbnail-caption-color;\n }\n}\n","//\n// Alerts\n// --------------------------------------------------\n\n\n// Base styles\n// -------------------------\n\n.alert {\n padding: @alert-padding;\n margin-bottom: @line-height-computed;\n border: 1px solid transparent;\n border-radius: @alert-border-radius;\n\n // Headings for larger alerts\n h4 {\n margin-top: 0;\n // Specified for the h4 to prevent conflicts of changing @headings-color\n color: inherit;\n }\n\n // Provide class for links that match alerts\n .alert-link {\n font-weight: @alert-link-font-weight;\n }\n\n // Improve alignment and spacing of inner content\n > p,\n > ul {\n margin-bottom: 0;\n }\n\n > p + p {\n margin-top: 5px;\n }\n}\n\n// Dismissible alerts\n//\n// Expand the right padding and account for the close button's positioning.\n\n.alert-dismissable, // The misspelled .alert-dismissable was deprecated in 3.2.0.\n.alert-dismissible {\n padding-right: (@alert-padding + 20);\n\n // Adjust close link position\n .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n }\n}\n\n// Alternate styles\n//\n// Generate contextual modifier classes for colorizing the alert.\n\n.alert-success {\n .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text);\n}\n\n.alert-info {\n .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text);\n}\n\n.alert-warning {\n .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text);\n}\n\n.alert-danger {\n .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text);\n}\n","// Alerts\n\n.alert-variant(@background; @border; @text-color) {\n background-color: @background;\n border-color: @border;\n color: @text-color;\n\n hr {\n border-top-color: darken(@border, 5%);\n }\n .alert-link {\n color: darken(@text-color, 10%);\n }\n}\n","//\n// Progress bars\n// --------------------------------------------------\n\n\n// Bar animations\n// -------------------------\n\n// WebKit\n@-webkit-keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n// Spec and IE10+\n@keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n\n// Bar itself\n// -------------------------\n\n// Outer container\n.progress {\n overflow: hidden;\n height: @line-height-computed;\n margin-bottom: @line-height-computed;\n background-color: @progress-bg;\n border-radius: @progress-border-radius;\n .box-shadow(inset 0 1px 2px rgba(0,0,0,.1));\n}\n\n// Bar of progress\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: @font-size-small;\n line-height: @line-height-computed;\n color: @progress-bar-color;\n text-align: center;\n background-color: @progress-bar-bg;\n .box-shadow(inset 0 -1px 0 rgba(0,0,0,.15));\n .transition(width .6s ease);\n}\n\n// Striped bars\n//\n// `.progress-striped .progress-bar` is deprecated as of v3.2.0 in favor of the\n// `.progress-bar-striped` class, which you just add to an existing\n// `.progress-bar`.\n.progress-striped .progress-bar,\n.progress-bar-striped {\n #gradient > .striped();\n background-size: 40px 40px;\n}\n\n// Call animation for the active one\n//\n// `.progress.active .progress-bar` is deprecated as of v3.2.0 in favor of the\n// `.progress-bar.active` approach.\n.progress.active .progress-bar,\n.progress-bar.active {\n .animation(progress-bar-stripes 2s linear infinite);\n}\n\n\n// Variations\n// -------------------------\n\n.progress-bar-success {\n .progress-bar-variant(@progress-bar-success-bg);\n}\n\n.progress-bar-info {\n .progress-bar-variant(@progress-bar-info-bg);\n}\n\n.progress-bar-warning {\n .progress-bar-variant(@progress-bar-warning-bg);\n}\n\n.progress-bar-danger {\n .progress-bar-variant(@progress-bar-danger-bg);\n}\n","// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Progress bars\n\n.progress-bar-variant(@color) {\n background-color: @color;\n\n // Deprecated parent class requirement as of v3.2.0\n .progress-striped & {\n #gradient > .striped();\n }\n}\n",".media {\n // Proper spacing between instances of .media\n margin-top: 15px;\n\n &:first-child {\n margin-top: 0;\n }\n}\n\n.media,\n.media-body {\n zoom: 1;\n overflow: hidden;\n}\n\n.media-body {\n width: 10000px;\n}\n\n.media-object {\n display: block;\n\n // Fix collapse in webkit from max-width: 100% and display: table-cell.\n &.img-thumbnail {\n max-width: none;\n }\n}\n\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n\n.media-middle {\n vertical-align: middle;\n}\n\n.media-bottom {\n vertical-align: bottom;\n}\n\n// Reset margins on headings for tighter default spacing\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n\n// Media list variation\n//\n// Undo default ul/ol styles\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n","//\n// List groups\n// --------------------------------------------------\n\n\n// Base class\n//\n// Easily usable on
a",l.leadingWhitespace=3===a.firstChild.nodeType,l.tbody=!a.getElementsByTagName("tbody").length,l.htmlSerialize=!!a.getElementsByTagName("link").length,l.html5Clone="<:nav>"!==d.createElement("nav").cloneNode(!0).outerHTML,c.type="checkbox",c.checked=!0,b.appendChild(c),l.appendChecked=c.checked,a.innerHTML="",l.noCloneChecked=!!a.cloneNode(!0).lastChild.defaultValue,b.appendChild(a),c=d.createElement("input"),c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),a.appendChild(c),l.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,l.noCloneEvent=!!a.addEventListener,a[n.expando]=1,l.attributes=!a.getAttribute(n.expando)}();var da={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:l.htmlSerialize?[0,"",""]:[1,"X
","
"]};da.optgroup=da.option,da.tbody=da.tfoot=da.colgroup=da.caption=da.thead,da.th=da.td;function ea(a,b){var c,d,e=0,f="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||n.nodeName(d,b)?f.push(d):n.merge(f,ea(d,b));return void 0===b||b&&n.nodeName(a,b)?n.merge([a],f):f}function fa(a,b){for(var c,d=0;null!=(c=a[d]);d++)n._data(c,"globalEval",!b||n._data(b[d],"globalEval"))}var ga=/<|&#?\w+;/,ha=/r;r++)if(g=a[r],g||0===g)if("object"===n.type(g))n.merge(q,g.nodeType?[g]:g);else if(ga.test(g)){i=i||p.appendChild(b.createElement("div")),j=($.exec(g)||["",""])[1].toLowerCase(),m=da[j]||da._default,i.innerHTML=m[1]+n.htmlPrefilter(g)+m[2],f=m[0];while(f--)i=i.lastChild;if(!l.leadingWhitespace&&aa.test(g)&&q.push(b.createTextNode(aa.exec(g)[0])),!l.tbody){g="table"!==j||ha.test(g)?""!==m[1]||ha.test(g)?0:i:i.firstChild,f=g&&g.childNodes.length;while(f--)n.nodeName(k=g.childNodes[f],"tbody")&&!k.childNodes.length&&g.removeChild(k)}n.merge(q,i.childNodes),i.textContent="";while(i.firstChild)i.removeChild(i.firstChild);i=p.lastChild}else q.push(b.createTextNode(g));i&&p.removeChild(i),l.appendChecked||n.grep(ea(q,"input"),ia),r=0;while(g=q[r++])if(d&&n.inArray(g,d)>-1)e&&e.push(g);else if(h=n.contains(g.ownerDocument,g),i=ea(p.appendChild(g),"script"),h&&fa(i),c){f=0;while(g=i[f++])_.test(g.type||"")&&c.push(g)}return i=null,p}!function(){var b,c,e=d.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(l[b]=c in a)||(e.setAttribute(c,"t"),l[b]=e.attributes[c].expando===!1);e=null}();var ka=/^(?:input|select|textarea)$/i,la=/^key/,ma=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,na=/^(?:focusinfocus|focusoutblur)$/,oa=/^([^.]*)(?:\.(.+)|)/;function pa(){return!0}function qa(){return!1}function ra(){try{return d.activeElement}catch(a){}}function sa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)sa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=qa;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=n.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return"undefined"==typeof n||a&&n.event.triggered===a.type?void 0:n.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(G)||[""],h=b.length;while(h--)f=oa.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=n.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=n.event.special[o]||{},l=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},i),(m=g[o])||(m=g[o]=[],m.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,l):m.push(l),n.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n.hasData(a)&&n._data(a);if(r&&(k=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=oa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=m.length;while(f--)g=m[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(m.splice(f,1),g.selector&&m.delegateCount--,l.remove&&l.remove.call(a,g));i&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(k)&&(delete r.handle,n._removeData(a,"events"))}},trigger:function(b,c,e,f){var g,h,i,j,l,m,o,p=[e||d],q=k.call(b,"type")?b.type:b,r=k.call(b,"namespace")?b.namespace.split("."):[];if(i=m=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!na.test(q+n.event.triggered)&&(q.indexOf(".")>-1&&(r=q.split("."),q=r.shift(),r.sort()),h=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=r.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:n.makeArray(c,[b]),l=n.event.special[q]||{},f||!l.trigger||l.trigger.apply(e,c)!==!1)){if(!f&&!l.noBubble&&!n.isWindow(e)){for(j=l.delegateType||q,na.test(j+q)||(i=i.parentNode);i;i=i.parentNode)p.push(i),m=i;m===(e.ownerDocument||d)&&p.push(m.defaultView||m.parentWindow||a)}o=0;while((i=p[o++])&&!b.isPropagationStopped())b.type=o>1?j:l.bindType||q,g=(n._data(i,"events")||{})[b.type]&&n._data(i,"handle"),g&&g.apply(i,c),g=h&&i[h],g&&g.apply&&M(i)&&(b.result=g.apply(i,c),b.result===!1&&b.preventDefault());if(b.type=q,!f&&!b.isDefaultPrevented()&&(!l._default||l._default.apply(p.pop(),c)===!1)&&M(e)&&h&&e[q]&&!n.isWindow(e)){m=e[h],m&&(e[h]=null),n.event.triggered=q;try{e[q]()}catch(s){}n.event.triggered=void 0,m&&(e[h]=m)}return b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(n._data(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())a.rnamespace&&!a.rnamespace.test(g.namespace)||(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]","i"),va=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,wa=/\s*$/g,Aa=ca(d),Ba=Aa.appendChild(d.createElement("div"));function Ca(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function Da(a){return a.type=(null!==n.find.attr(a,"type"))+"/"+a.type,a}function Ea(a){var b=ya.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Fa(a,b){if(1===b.nodeType&&n.hasData(a)){var c,d,e,f=n._data(a),g=n._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)n.event.add(b,c,h[c][d])}g.data&&(g.data=n.extend({},g.data))}}function Ga(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!l.noCloneEvent&&b[n.expando]){e=n._data(b);for(d in e.events)n.removeEvent(b,d,e.handle);b.removeAttribute(n.expando)}"script"===c&&b.text!==a.text?(Da(b).text=a.text,Ea(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),l.html5Clone&&a.innerHTML&&!n.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&Z.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}}function Ha(a,b,c,d){b=f.apply([],b);var e,g,h,i,j,k,m=0,o=a.length,p=o-1,q=b[0],r=n.isFunction(q);if(r||o>1&&"string"==typeof q&&!l.checkClone&&xa.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),Ha(f,b,c,d)});if(o&&(k=ja(b,a[0].ownerDocument,!1,a,d),e=k.firstChild,1===k.childNodes.length&&(k=e),e||d)){for(i=n.map(ea(k,"script"),Da),h=i.length;o>m;m++)g=k,m!==p&&(g=n.clone(g,!0,!0),h&&n.merge(i,ea(g,"script"))),c.call(a[m],g,m);if(h)for(j=i[i.length-1].ownerDocument,n.map(i,Ea),m=0;h>m;m++)g=i[m],_.test(g.type||"")&&!n._data(g,"globalEval")&&n.contains(j,g)&&(g.src?n._evalUrl&&n._evalUrl(g.src):n.globalEval((g.text||g.textContent||g.innerHTML||"").replace(za,"")));k=e=null}return a}function Ia(a,b,c){for(var d,e=b?n.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||n.cleanData(ea(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&fa(ea(d,"script")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(va,"<$1>")},clone:function(a,b,c){var d,e,f,g,h,i=n.contains(a.ownerDocument,a);if(l.html5Clone||n.isXMLDoc(a)||!ua.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(Ba.innerHTML=a.outerHTML,Ba.removeChild(f=Ba.firstChild)),!(l.noCloneEvent&&l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(d=ea(f),h=ea(a),g=0;null!=(e=h[g]);++g)d[g]&&Ga(e,d[g]);if(b)if(c)for(h=h||ea(a),d=d||ea(f),g=0;null!=(e=h[g]);g++)Fa(e,d[g]);else Fa(a,f);return d=ea(f,"script"),d.length>0&&fa(d,!i&&ea(a,"script")),d=h=e=null,f},cleanData:function(a,b){for(var d,e,f,g,h=0,i=n.expando,j=n.cache,k=l.attributes,m=n.event.special;null!=(d=a[h]);h++)if((b||M(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)m[e]?n.event.remove(d,e):n.removeEvent(d,e,g.handle);j[f]&&(delete j[f],k||"undefined"==typeof d.removeAttribute?d[i]=void 0:d.removeAttribute(i),c.push(f))}}}),n.fn.extend({domManip:Ha,detach:function(a){return Ia(this,a,!0)},remove:function(a){return Ia(this,a)},text:function(a){return Y(this,function(a){return void 0===a?n.text(this):this.empty().append((this[0]&&this[0].ownerDocument||d).createTextNode(a))},null,a,arguments.length)},append:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.appendChild(a)}})},prepend:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&n.cleanData(ea(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&n.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return Y(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(ta,""):void 0;if("string"==typeof a&&!wa.test(a)&&(l.htmlSerialize||!ua.test(a))&&(l.leadingWhitespace||!aa.test(a))&&!da[($.exec(a)||["",""])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ea(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return Ha(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(ea(this)),c&&c.replaceChild(b,this))},a)}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=0,e=[],f=n(a),h=f.length-1;h>=d;d++)c=d===h?this:this.clone(!0),n(f[d])[b](c),g.apply(e,c.get());return this.pushStack(e)}});var Ja,Ka={HTML:"block",BODY:"block"};function La(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],"display");return c.detach(),d}function Ma(a){var b=d,c=Ka[a];return c||(c=La(a,b),"none"!==c&&c||(Ja=(Ja||n("