| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.hadoop.hdfs.server.namenode.sps; |
| |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.apache.hadoop.classification.InterfaceAudience; |
| import org.apache.hadoop.conf.Configuration; |
| import org.apache.hadoop.fs.StorageType; |
| import org.apache.hadoop.hdfs.DFSConfigKeys; |
| import org.apache.hadoop.hdfs.server.namenode.sps.StoragePolicySatisfier.DatanodeMap; |
| import org.apache.hadoop.hdfs.server.protocol.DatanodeStorageReport; |
| import org.apache.hadoop.hdfs.server.protocol.StorageReport; |
| import org.apache.hadoop.net.NetworkTopology; |
| import org.apache.hadoop.util.Time; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| /** |
| * The Datanode cache Manager handles caching of {@link DatanodeStorageReport}. |
| * |
| * This class is instantiated by StoragePolicySatisifer. It maintains the array |
| * of datanode storage reports. It has a configurable refresh interval and |
| * periodically refresh the datanode cache by fetching latest |
| * {@link Context#getLiveDatanodeStorageReport()} once it reaches refresh |
| * interval. |
| */ |
| @InterfaceAudience.Private |
| public class DatanodeCacheManager { |
| private static final Logger LOG = LoggerFactory |
| .getLogger(DatanodeCacheManager.class); |
| |
| private final DatanodeMap datanodeMap; |
| private NetworkTopology cluster; |
| |
| /** |
| * Interval between scans in milliseconds. |
| */ |
| private final long refreshIntervalMs; |
| |
| private long lastAccessedTime; |
| |
| public DatanodeCacheManager(Configuration conf) { |
| refreshIntervalMs = conf.getLong( |
| DFSConfigKeys.DFS_SPS_DATANODE_CACHE_REFRESH_INTERVAL_MS, |
| DFSConfigKeys.DFS_SPS_DATANODE_CACHE_REFRESH_INTERVAL_MS_DEFAULT); |
| |
| LOG.info("DatanodeCacheManager refresh interval is {} milliseconds", |
| refreshIntervalMs); |
| datanodeMap = new DatanodeMap(); |
| } |
| |
| /** |
| * Returns the live datanodes and its storage details, which has available |
| * space (> 0) to schedule block moves. This will return array of datanodes |
| * from its local cache. It has a configurable refresh interval in millis and |
| * periodically refresh the datanode cache by fetching latest |
| * {@link Context#getLiveDatanodeStorageReport()} once it elapsed refresh |
| * interval. |
| * |
| * @throws IOException |
| */ |
| public DatanodeMap getLiveDatanodeStorageReport( |
| Context spsContext) throws IOException { |
| long now = Time.monotonicNow(); |
| long elapsedTimeMs = now - lastAccessedTime; |
| boolean refreshNeeded = elapsedTimeMs >= refreshIntervalMs; |
| lastAccessedTime = now; |
| if (refreshNeeded) { |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("elapsedTimeMs > refreshIntervalMs : {} > {}," |
| + " so refreshing cache", elapsedTimeMs, refreshIntervalMs); |
| } |
| datanodeMap.reset(); // clear all previously cached items. |
| |
| // Fetch live datanodes from namenode and prepare DatanodeMap. |
| DatanodeStorageReport[] liveDns = spsContext |
| .getLiveDatanodeStorageReport(); |
| for (DatanodeStorageReport storage : liveDns) { |
| StorageReport[] storageReports = storage.getStorageReports(); |
| List<StorageType> storageTypes = new ArrayList<>(); |
| List<Long> remainingSizeList = new ArrayList<>(); |
| for (StorageReport t : storageReports) { |
| if (t.getRemaining() > 0) { |
| storageTypes.add(t.getStorage().getStorageType()); |
| remainingSizeList.add(t.getRemaining()); |
| } |
| } |
| datanodeMap.addTarget(storage.getDatanodeInfo(), storageTypes, |
| remainingSizeList); |
| } |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("LIVE datanodes: {}", datanodeMap); |
| } |
| // get network topology |
| cluster = spsContext.getNetworkTopology(datanodeMap); |
| } |
| return datanodeMap; |
| } |
| |
| NetworkTopology getCluster() { |
| return cluster; |
| } |
| } |