Skip to content

Commit 9b0aace

Browse files
committed
HDFS-14401. Refine the implementation for HDFS cache on SCM. Contributed by Feilong He.
1 parent 96dc5ce commit 9b0aace

File tree

13 files changed

+256
-202
lines changed

13 files changed

+256
-202
lines changed

hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/DFSConfigKeys.java

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@
2626
import org.apache.hadoop.hdfs.protocol.HdfsConstants.StoragePolicySatisfierMode;
2727
import org.apache.hadoop.hdfs.server.blockmanagement.BlockPlacementPolicyDefault;
2828
import org.apache.hadoop.hdfs.server.blockmanagement.BlockPlacementPolicyRackFaultTolerant;
29-
import org.apache.hadoop.hdfs.server.datanode.fsdataset.impl.MappableBlockLoader;
30-
import org.apache.hadoop.hdfs.server.datanode.fsdataset.impl.MemoryMappableBlockLoader;
3129
import org.apache.hadoop.hdfs.server.datanode.fsdataset.impl.RamDiskReplicaLruTracker;
3230
import org.apache.hadoop.hdfs.server.datanode.fsdataset.impl.ReservedSpaceCalculator;
3331
import org.apache.hadoop.hdfs.web.URLConnectionFactory;
@@ -392,22 +390,10 @@ public class DFSConfigKeys extends CommonConfigurationKeys {
392390
public static final String DFS_DATANODE_CACHE_REVOCATION_POLLING_MS = "dfs.datanode.cache.revocation.polling.ms";
393391
public static final long DFS_DATANODE_CACHE_REVOCATION_POLLING_MS_DEFAULT = 500L;
394392

395-
// Currently, the available cache loaders are MemoryMappableBlockLoader,
396-
// PmemMappableBlockLoader. MemoryMappableBlockLoader is the default cache
397-
// loader to cache block replica to memory.
398-
public static final String DFS_DATANODE_CACHE_LOADER_CLASS =
399-
"dfs.datanode.cache.loader.class";
400-
public static final Class<? extends MappableBlockLoader>
401-
DFS_DATANODE_CACHE_LOADER_CLASS_DEFAULT =
402-
MemoryMappableBlockLoader.class;
403393
// Multiple dirs separated by "," are acceptable.
404394
public static final String DFS_DATANODE_CACHE_PMEM_DIRS_KEY =
405395
"dfs.datanode.cache.pmem.dirs";
406396
public static final String DFS_DATANODE_CACHE_PMEM_DIRS_DEFAULT = "";
407-
// The cache capacity of persistent memory
408-
public static final String DFS_DATANODE_CACHE_PMEM_CAPACITY_KEY =
409-
"dfs.datanode.cache.pmem.capacity";
410-
public static final long DFS_DATANODE_CACHE_PMEM_CAPACITY_DEFAULT = 0L;
411397

412398
public static final String DFS_NAMENODE_DATANODE_REGISTRATION_IP_HOSTNAME_CHECK_KEY = "dfs.namenode.datanode.registration.ip-hostname-check";
413399
public static final boolean DFS_NAMENODE_DATANODE_REGISTRATION_IP_HOSTNAME_CHECK_DEFAULT = true;

hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DNConf.java

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,6 @@
2727
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_BLOCKREPORT_SPLIT_THRESHOLD_DEFAULT;
2828
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CACHEREPORT_INTERVAL_MSEC_DEFAULT;
2929
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CACHEREPORT_INTERVAL_MSEC_KEY;
30-
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_DATANODE_CACHE_LOADER_CLASS;
31-
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_DATANODE_CACHE_LOADER_CLASS_DEFAULT;
32-
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_DATANODE_CACHE_PMEM_CAPACITY_DEFAULT;
33-
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_DATANODE_CACHE_PMEM_CAPACITY_KEY;
3430
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_DATANODE_CACHE_PMEM_DIRS_KEY;
3531
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_DATANODE_LIFELINE_INTERVAL_SECONDS_KEY;
3632
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_DATANODE_NON_LOCAL_LAZY_PERSIST;
@@ -71,7 +67,6 @@
7167
import org.apache.hadoop.hdfs.protocol.datatransfer.TrustedChannelResolver;
7268
import org.apache.hadoop.hdfs.protocol.datatransfer.sasl.DataTransferSaslUtil;
7369
import org.apache.hadoop.hdfs.server.common.Util;
74-
import org.apache.hadoop.hdfs.server.datanode.fsdataset.impl.MappableBlockLoader;
7570
import org.apache.hadoop.security.SaslPropertiesResolver;
7671

7772
import java.util.concurrent.TimeUnit;
@@ -121,9 +116,7 @@ public class DNConf {
121116
final long xceiverStopTimeout;
122117
final long restartReplicaExpiry;
123118

124-
private final Class<? extends MappableBlockLoader> cacheLoaderClass;
125119
final long maxLockedMemory;
126-
private final long maxLockedPmem;
127120
private final String[] pmemDirs;
128121

129122
private final long bpReadyTimeout;
@@ -266,17 +259,10 @@ public DNConf(final Configurable dn) {
266259
DFS_DATANODE_XCEIVER_STOP_TIMEOUT_MILLIS_KEY,
267260
DFS_DATANODE_XCEIVER_STOP_TIMEOUT_MILLIS_DEFAULT);
268261

269-
this.cacheLoaderClass = getConf().getClass(DFS_DATANODE_CACHE_LOADER_CLASS,
270-
DFS_DATANODE_CACHE_LOADER_CLASS_DEFAULT, MappableBlockLoader.class);
271-
272262
this.maxLockedMemory = getConf().getLongBytes(
273263
DFS_DATANODE_MAX_LOCKED_MEMORY_KEY,
274264
DFS_DATANODE_MAX_LOCKED_MEMORY_DEFAULT);
275265

276-
this.maxLockedPmem = getConf().getLongBytes(
277-
DFS_DATANODE_CACHE_PMEM_CAPACITY_KEY,
278-
DFS_DATANODE_CACHE_PMEM_CAPACITY_DEFAULT);
279-
280266
this.pmemDirs = getConf().getTrimmedStrings(
281267
DFS_DATANODE_CACHE_PMEM_DIRS_KEY);
282268

@@ -342,10 +328,6 @@ public long getMaxLockedMemory() {
342328
return maxLockedMemory;
343329
}
344330

345-
public long getMaxLockedPmem() {
346-
return maxLockedPmem;
347-
}
348-
349331
/**
350332
* Returns true if connect to datanode via hostname
351333
*
@@ -449,10 +431,6 @@ int getMaxDataLength() {
449431
return maxDataLength;
450432
}
451433

452-
public Class<? extends MappableBlockLoader> getCacheLoaderClass() {
453-
return cacheLoaderClass;
454-
}
455-
456434
public String[] getPmemVolumes() {
457435
return pmemDirs;
458436
}

hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/fsdataset/impl/FsDatasetCache.java

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@
5353
import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
5454
import org.apache.hadoop.hdfs.server.datanode.DNConf;
5555
import org.apache.hadoop.hdfs.server.datanode.DatanodeUtil;
56-
import org.apache.hadoop.util.ReflectionUtils;
5756
import org.apache.hadoop.util.Time;
5857
import org.slf4j.Logger;
5958
import org.slf4j.LoggerFactory;
@@ -183,9 +182,8 @@ public FsDatasetCache(FsDatasetImpl dataset) throws IOException {
183182
this.memCacheStats = new MemoryCacheStats(
184183
dataset.datanode.getDnConf().getMaxLockedMemory());
185184

186-
Class<? extends MappableBlockLoader> cacheLoaderClass =
187-
dataset.datanode.getDnConf().getCacheLoaderClass();
188-
this.cacheLoader = ReflectionUtils.newInstance(cacheLoaderClass, null);
185+
this.cacheLoader = MappableBlockLoaderFactory.createCacheLoader(
186+
this.getDnConf());
189187
cacheLoader.initialize(this);
190188
}
191189

@@ -213,7 +211,7 @@ String getReplicaCachePath(String bpid, long blockId) {
213211
return null;
214212
}
215213
ExtendedBlockId key = new ExtendedBlockId(blockId, bpid);
216-
return cacheLoader.getCachedPath(key);
214+
return PmemVolumeManager.getInstance().getCachePath(key);
217215
}
218216

219217
/**
@@ -380,14 +378,13 @@ public void run() {
380378
MappableBlock mappableBlock = null;
381379
ExtendedBlock extBlk = new ExtendedBlock(key.getBlockPoolId(),
382380
key.getBlockId(), length, genstamp);
383-
long newUsedBytes = cacheLoader.reserve(length);
381+
long newUsedBytes = cacheLoader.reserve(key, length);
384382
boolean reservedBytes = false;
385383
try {
386384
if (newUsedBytes < 0) {
387-
LOG.warn("Failed to cache " + key + ": could not reserve " + length +
388-
" more bytes in the cache: " +
389-
cacheLoader.getCacheCapacityConfigKey() +
390-
" of " + cacheLoader.getCacheCapacity() + " exceeded.");
385+
LOG.warn("Failed to cache " + key + ": could not reserve " +
386+
"more bytes in the cache: " + cacheLoader.getCacheCapacity() +
387+
" exceeded when try to reserve " + length + "bytes.");
391388
return;
392389
}
393390
reservedBytes = true;
@@ -442,10 +439,10 @@ public void run() {
442439
IOUtils.closeQuietly(metaIn);
443440
if (!success) {
444441
if (reservedBytes) {
445-
cacheLoader.release(length);
442+
cacheLoader.release(key, length);
446443
}
447444
LOG.debug("Caching of {} was aborted. We are now caching only {} "
448-
+ "bytes in total.", key, memCacheStats.getCacheUsed());
445+
+ "bytes in total.", key, cacheLoader.getCacheUsed());
449446
IOUtils.closeQuietly(mappableBlock);
450447
numBlocksFailedToCache.incrementAndGet();
451448

@@ -519,7 +516,8 @@ public void run() {
519516
synchronized (FsDatasetCache.this) {
520517
mappableBlockMap.remove(key);
521518
}
522-
long newUsedBytes = cacheLoader.release(value.mappableBlock.getLength());
519+
long newUsedBytes = cacheLoader.
520+
release(key, value.mappableBlock.getLength());
523521
numBlocksCached.addAndGet(-1);
524522
dataset.datanode.getMetrics().incrBlocksUncached(1);
525523
if (revocationTimeMs != 0) {
@@ -592,4 +590,11 @@ public synchronized boolean isCached(String bpid, long blockId) {
592590
MappableBlockLoader getCacheLoader() {
593591
return cacheLoader;
594592
}
593+
594+
/**
595+
* This method can be executed during DataNode shutdown.
596+
*/
597+
void shutdown() {
598+
cacheLoader.shutdown();
599+
}
595600
}

hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/fsdataset/impl/FsDatasetImpl.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2328,6 +2328,8 @@ public void shutdown() {
23282328
"from LazyWriter.join");
23292329
}
23302330
}
2331+
2332+
cacheManager.shutdown();
23312333
}
23322334

23332335
@Override // FSDatasetMBean

hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/fsdataset/impl/MappableBlockLoader.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,26 +65,25 @@ abstract MappableBlock load(long length, FileInputStream blockIn,
6565
/**
6666
* Try to reserve some given bytes.
6767
*
68+
* @param key The ExtendedBlockId for a block.
69+
*
6870
* @param bytesCount The number of bytes to add.
6971
*
7072
* @return The new number of usedBytes if we succeeded;
7173
* -1 if we failed.
7274
*/
73-
abstract long reserve(long bytesCount);
75+
abstract long reserve(ExtendedBlockId key, long bytesCount);
7476

7577
/**
7678
* Release some bytes that we're using.
7779
*
80+
* @param key The ExtendedBlockId for a block.
81+
*
7882
* @param bytesCount The number of bytes to release.
7983
*
8084
* @return The new number of usedBytes.
8185
*/
82-
abstract long release(long bytesCount);
83-
84-
/**
85-
* Get the config key of cache capacity.
86-
*/
87-
abstract String getCacheCapacityConfigKey();
86+
abstract long release(ExtendedBlockId key, long bytesCount);
8887

8988
/**
9089
* Get the approximate amount of cache space used.
@@ -102,9 +101,11 @@ abstract MappableBlock load(long length, FileInputStream blockIn,
102101
abstract boolean isTransientCache();
103102

104103
/**
105-
* Get a cache file path if applicable. Otherwise return null.
104+
* Clean up cache, can be used during DataNode shutdown.
106105
*/
107-
abstract String getCachedPath(ExtendedBlockId key);
106+
void shutdown() {
107+
// Do nothing.
108+
}
108109

109110
/**
110111
* Reads bytes into a buffer until EOF or the buffer's limit is reached.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.apache.hadoop.hdfs.server.datanode.fsdataset.impl;
20+
21+
import org.apache.hadoop.classification.InterfaceAudience;
22+
import org.apache.hadoop.classification.InterfaceStability;
23+
import org.apache.hadoop.hdfs.server.datanode.DNConf;
24+
25+
/**
26+
* Creates MappableBlockLoader.
27+
*/
28+
@InterfaceAudience.Private
29+
@InterfaceStability.Unstable
30+
public final class MappableBlockLoaderFactory {
31+
32+
private MappableBlockLoaderFactory() {
33+
// Prevent instantiation
34+
}
35+
36+
/**
37+
* Create a specific cache loader according to the configuration.
38+
* If persistent memory volume is not configured, return a cache loader
39+
* for DRAM cache. Otherwise, return a cache loader for pmem cache.
40+
*/
41+
public static MappableBlockLoader createCacheLoader(DNConf conf) {
42+
if (conf.getPmemVolumes() == null || conf.getPmemVolumes().length == 0) {
43+
return new MemoryMappableBlockLoader();
44+
}
45+
return new PmemMappableBlockLoader();
46+
}
47+
}

hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/fsdataset/impl/MemoryMappableBlockLoader.java

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,12 @@
2222
import org.apache.commons.io.IOUtils;
2323
import org.apache.hadoop.classification.InterfaceAudience;
2424
import org.apache.hadoop.classification.InterfaceStability;
25-
import org.apache.hadoop.hdfs.DFSConfigKeys;
2625
import org.apache.hadoop.hdfs.ExtendedBlockId;
2726
import org.apache.hadoop.hdfs.server.datanode.BlockMetadataHeader;
2827
import org.apache.hadoop.io.nativeio.NativeIO;
2928
import org.apache.hadoop.util.DataChecksum;
29+
import org.slf4j.Logger;
30+
import org.slf4j.LoggerFactory;
3031

3132
import java.io.BufferedInputStream;
3233
import java.io.DataInputStream;
@@ -42,11 +43,13 @@
4243
@InterfaceAudience.Private
4344
@InterfaceStability.Unstable
4445
public class MemoryMappableBlockLoader extends MappableBlockLoader {
45-
46+
private static final Logger LOG =
47+
LoggerFactory.getLogger(MemoryMappableBlockLoader.class);
4648
private MemoryCacheStats memCacheStats;
4749

4850
@Override
4951
void initialize(FsDatasetCache cacheManager) throws IOException {
52+
LOG.info("Initializing cache loader: MemoryMappableBlockLoader.");
5053
this.memCacheStats = cacheManager.getMemCacheStats();
5154
}
5255

@@ -148,11 +151,6 @@ private void verifyChecksum(long length, FileInputStream metaIn,
148151
}
149152
}
150153

151-
@Override
152-
public String getCacheCapacityConfigKey() {
153-
return DFSConfigKeys.DFS_DATANODE_MAX_LOCKED_MEMORY_KEY;
154-
}
155-
156154
@Override
157155
public long getCacheUsed() {
158156
return memCacheStats.getCacheUsed();
@@ -164,22 +162,17 @@ public long getCacheCapacity() {
164162
}
165163

166164
@Override
167-
long reserve(long bytesCount) {
165+
long reserve(ExtendedBlockId key, long bytesCount) {
168166
return memCacheStats.reserve(bytesCount);
169167
}
170168

171169
@Override
172-
long release(long bytesCount) {
170+
long release(ExtendedBlockId key, long bytesCount) {
173171
return memCacheStats.release(bytesCount);
174172
}
175173

176174
@Override
177175
public boolean isTransientCache() {
178176
return true;
179177
}
180-
181-
@Override
182-
public String getCachedPath(ExtendedBlockId key) {
183-
return null;
184-
}
185178
}

0 commit comments

Comments
 (0)