001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hdfs; 019 020import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.HADOOP_SECURITY_CRYPTO_CODEC_CLASSES_KEY_PREFIX; 021import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_BLOCK_SIZE_DEFAULT; 022import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_BLOCK_SIZE_KEY; 023import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_BYTES_PER_CHECKSUM_DEFAULT; 024import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_BYTES_PER_CHECKSUM_KEY; 025import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_BLOCK_WRITE_LOCATEFOLLOWINGBLOCK_RETRIES_DEFAULT; 026import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_BLOCK_WRITE_LOCATEFOLLOWINGBLOCK_RETRIES_KEY; 027import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_BLOCK_WRITE_RETRIES_DEFAULT; 028import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_BLOCK_WRITE_RETRIES_KEY; 029import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_CACHED_CONN_RETRY_DEFAULT; 030import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_CACHED_CONN_RETRY_KEY; 031import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_CACHE_DROP_BEHIND_READS; 032import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_CACHE_DROP_BEHIND_WRITES; 033import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_CACHE_READAHEAD; 034import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_CONTEXT; 035import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_CONTEXT_DEFAULT; 036import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_DATANODE_RESTART_TIMEOUT_DEFAULT; 037import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_DATANODE_RESTART_TIMEOUT_KEY; 038import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_FAILOVER_MAX_ATTEMPTS_DEFAULT; 039import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_FAILOVER_MAX_ATTEMPTS_KEY; 040import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_FAILOVER_SLEEPTIME_BASE_DEFAULT; 041import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_FAILOVER_SLEEPTIME_BASE_KEY; 042import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_FAILOVER_SLEEPTIME_MAX_DEFAULT; 043import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_FAILOVER_SLEEPTIME_MAX_KEY; 044import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_MAX_BLOCK_ACQUIRE_FAILURES_DEFAULT; 045import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_MAX_BLOCK_ACQUIRE_FAILURES_KEY; 046import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_READ_PREFETCH_SIZE_KEY; 047import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_RETRY_MAX_ATTEMPTS_DEFAULT; 048import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_RETRY_MAX_ATTEMPTS_KEY; 049import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_RETRY_WINDOW_BASE; 050import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_SOCKET_CACHE_CAPACITY_DEFAULT; 051import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_SOCKET_CACHE_CAPACITY_KEY; 052import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_SOCKET_CACHE_EXPIRY_MSEC_DEFAULT; 053import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_SOCKET_CACHE_EXPIRY_MSEC_KEY; 054import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_SOCKET_TIMEOUT_KEY; 055import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_USE_DN_HOSTNAME; 056import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_USE_DN_HOSTNAME_DEFAULT; 057import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_WRITE_EXCLUDE_NODES_CACHE_EXPIRY_INTERVAL; 058import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_WRITE_EXCLUDE_NODES_CACHE_EXPIRY_INTERVAL_DEFAULT; 059import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_WRITE_PACKET_SIZE_DEFAULT; 060import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_WRITE_PACKET_SIZE_KEY; 061import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_DATANODE_SOCKET_WRITE_TIMEOUT_KEY; 062import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_REPLICATION_DEFAULT; 063import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_REPLICATION_KEY; 064 065import java.io.BufferedOutputStream; 066import java.io.DataInputStream; 067import java.io.DataOutputStream; 068import java.io.FileNotFoundException; 069import java.io.IOException; 070import java.io.InputStream; 071import java.io.OutputStream; 072import java.lang.reflect.Proxy; 073import java.net.InetAddress; 074import java.net.InetSocketAddress; 075import java.net.Socket; 076import java.net.SocketAddress; 077import java.net.URI; 078import java.net.UnknownHostException; 079import java.nio.charset.Charset; 080import java.security.GeneralSecurityException; 081import java.util.ArrayList; 082import java.util.Collections; 083import java.util.EnumSet; 084import java.util.HashMap; 085import java.util.LinkedHashMap; 086import java.util.List; 087import java.util.Map; 088import java.util.Random; 089import java.util.concurrent.SynchronousQueue; 090import java.util.concurrent.ThreadPoolExecutor; 091import java.util.concurrent.TimeUnit; 092import java.util.concurrent.atomic.AtomicBoolean; 093import java.util.concurrent.atomic.AtomicInteger; 094 095import javax.net.SocketFactory; 096 097import org.apache.commons.logging.Log; 098import org.apache.commons.logging.LogFactory; 099import org.apache.hadoop.HadoopIllegalArgumentException; 100import org.apache.hadoop.classification.InterfaceAudience; 101import org.apache.hadoop.conf.Configuration; 102import org.apache.hadoop.crypto.CipherSuite; 103import org.apache.hadoop.crypto.CryptoCodec; 104import org.apache.hadoop.crypto.CryptoInputStream; 105import org.apache.hadoop.crypto.CryptoOutputStream; 106import org.apache.hadoop.crypto.CryptoProtocolVersion; 107import org.apache.hadoop.crypto.key.KeyProvider; 108import org.apache.hadoop.crypto.key.KeyProvider.KeyVersion; 109import org.apache.hadoop.crypto.key.KeyProviderCryptoExtension; 110import org.apache.hadoop.crypto.key.KeyProviderCryptoExtension.EncryptedKeyVersion; 111import org.apache.hadoop.fs.BlockLocation; 112import org.apache.hadoop.fs.BlockStorageLocation; 113import org.apache.hadoop.fs.CacheFlag; 114import org.apache.hadoop.fs.CommonConfigurationKeysPublic; 115import org.apache.hadoop.fs.ContentSummary; 116import org.apache.hadoop.fs.CreateFlag; 117import org.apache.hadoop.fs.FileAlreadyExistsException; 118import org.apache.hadoop.fs.FileEncryptionInfo; 119import org.apache.hadoop.fs.FileSystem; 120import org.apache.hadoop.fs.FsServerDefaults; 121import org.apache.hadoop.fs.FsStatus; 122import org.apache.hadoop.fs.HdfsBlockLocation; 123import org.apache.hadoop.fs.InvalidPathException; 124import org.apache.hadoop.fs.MD5MD5CRC32CastagnoliFileChecksum; 125import org.apache.hadoop.fs.MD5MD5CRC32FileChecksum; 126import org.apache.hadoop.fs.MD5MD5CRC32GzipFileChecksum; 127import org.apache.hadoop.fs.Options; 128import org.apache.hadoop.fs.Options.ChecksumOpt; 129import org.apache.hadoop.fs.ParentNotDirectoryException; 130import org.apache.hadoop.fs.Path; 131import org.apache.hadoop.fs.StorageType; 132import org.apache.hadoop.fs.RemoteIterator; 133import org.apache.hadoop.fs.UnresolvedLinkException; 134import org.apache.hadoop.fs.VolumeId; 135import org.apache.hadoop.fs.XAttr; 136import org.apache.hadoop.fs.XAttrSetFlag; 137import org.apache.hadoop.fs.permission.AclEntry; 138import org.apache.hadoop.fs.permission.AclStatus; 139import org.apache.hadoop.fs.permission.FsAction; 140import org.apache.hadoop.fs.permission.FsPermission; 141import org.apache.hadoop.hdfs.client.HdfsDataInputStream; 142import org.apache.hadoop.hdfs.client.HdfsDataOutputStream; 143import org.apache.hadoop.hdfs.net.Peer; 144import org.apache.hadoop.hdfs.net.TcpPeerServer; 145import org.apache.hadoop.hdfs.protocol.AclException; 146import org.apache.hadoop.hdfs.protocol.BlockStoragePolicy; 147import org.apache.hadoop.hdfs.protocol.CacheDirectiveEntry; 148import org.apache.hadoop.hdfs.protocol.CacheDirectiveInfo; 149import org.apache.hadoop.hdfs.protocol.CacheDirectiveIterator; 150import org.apache.hadoop.hdfs.protocol.CachePoolEntry; 151import org.apache.hadoop.hdfs.protocol.CachePoolInfo; 152import org.apache.hadoop.hdfs.protocol.CachePoolIterator; 153import org.apache.hadoop.hdfs.protocol.ClientProtocol; 154import org.apache.hadoop.hdfs.protocol.CorruptFileBlocks; 155import org.apache.hadoop.hdfs.protocol.DSQuotaExceededException; 156import org.apache.hadoop.hdfs.protocol.DatanodeID; 157import org.apache.hadoop.hdfs.protocol.DatanodeInfo; 158import org.apache.hadoop.hdfs.protocol.DirectoryListing; 159import org.apache.hadoop.hdfs.protocol.EncryptionZone; 160import org.apache.hadoop.hdfs.protocol.EncryptionZoneIterator; 161import org.apache.hadoop.hdfs.protocol.ExtendedBlock; 162import org.apache.hadoop.hdfs.protocol.HdfsBlocksMetadata; 163import org.apache.hadoop.hdfs.protocol.HdfsConstants; 164import org.apache.hadoop.hdfs.protocol.HdfsConstants.DatanodeReportType; 165import org.apache.hadoop.hdfs.protocol.HdfsConstants.RollingUpgradeAction; 166import org.apache.hadoop.hdfs.protocol.HdfsConstants.SafeModeAction; 167import org.apache.hadoop.hdfs.protocol.HdfsFileStatus; 168import org.apache.hadoop.hdfs.protocol.LastBlockWithStatus; 169import org.apache.hadoop.hdfs.protocol.LocatedBlock; 170import org.apache.hadoop.hdfs.protocol.LocatedBlocks; 171import org.apache.hadoop.hdfs.protocol.NSQuotaExceededException; 172import org.apache.hadoop.hdfs.protocol.QuotaByStorageTypeExceededException; 173import org.apache.hadoop.hdfs.protocol.RollingUpgradeInfo; 174import org.apache.hadoop.hdfs.protocol.SnapshotAccessControlException; 175import org.apache.hadoop.hdfs.protocol.SnapshotDiffReport; 176import org.apache.hadoop.hdfs.protocol.SnapshottableDirectoryStatus; 177import org.apache.hadoop.hdfs.protocol.UnresolvedPathException; 178import org.apache.hadoop.hdfs.protocol.datatransfer.DataTransferProtoUtil; 179import org.apache.hadoop.hdfs.protocol.datatransfer.IOStreamPair; 180import org.apache.hadoop.hdfs.protocol.datatransfer.Op; 181import org.apache.hadoop.hdfs.protocol.datatransfer.ReplaceDatanodeOnFailure; 182import org.apache.hadoop.hdfs.protocol.datatransfer.Sender; 183import org.apache.hadoop.hdfs.protocol.datatransfer.TrustedChannelResolver; 184import org.apache.hadoop.hdfs.protocol.datatransfer.sasl.DataEncryptionKeyFactory; 185import org.apache.hadoop.hdfs.protocol.datatransfer.sasl.DataTransferSaslUtil; 186import org.apache.hadoop.hdfs.protocol.datatransfer.sasl.SaslDataTransferClient; 187import org.apache.hadoop.hdfs.protocol.proto.DataTransferProtos.BlockOpResponseProto; 188import org.apache.hadoop.hdfs.protocol.proto.DataTransferProtos.OpBlockChecksumResponseProto; 189import org.apache.hadoop.hdfs.protocol.proto.DataTransferProtos.Status; 190import org.apache.hadoop.hdfs.protocolPB.PBHelper; 191import org.apache.hadoop.hdfs.security.token.block.BlockTokenIdentifier; 192import org.apache.hadoop.hdfs.security.token.block.DataEncryptionKey; 193import org.apache.hadoop.hdfs.security.token.block.InvalidBlockTokenException; 194import org.apache.hadoop.hdfs.security.token.delegation.DelegationTokenIdentifier; 195import org.apache.hadoop.hdfs.server.common.HdfsServerConstants; 196import org.apache.hadoop.hdfs.server.datanode.CachingStrategy; 197import org.apache.hadoop.hdfs.server.namenode.NameNode; 198import org.apache.hadoop.hdfs.server.namenode.SafeModeException; 199import org.apache.hadoop.hdfs.server.protocol.DatanodeStorageReport; 200import org.apache.hadoop.hdfs.util.ByteArrayManager; 201import org.apache.hadoop.io.DataOutputBuffer; 202import org.apache.hadoop.io.EnumSetWritable; 203import org.apache.hadoop.io.IOUtils; 204import org.apache.hadoop.io.MD5Hash; 205import org.apache.hadoop.io.Text; 206import org.apache.hadoop.io.retry.LossyRetryInvocationHandler; 207import org.apache.hadoop.ipc.Client; 208import org.apache.hadoop.ipc.RPC; 209import org.apache.hadoop.ipc.RemoteException; 210import org.apache.hadoop.ipc.RpcInvocationHandler; 211import org.apache.hadoop.net.DNS; 212import org.apache.hadoop.net.NetUtils; 213import org.apache.hadoop.security.AccessControlException; 214import org.apache.hadoop.security.UserGroupInformation; 215import org.apache.hadoop.security.token.SecretManager.InvalidToken; 216import org.apache.hadoop.security.token.Token; 217import org.apache.hadoop.security.token.TokenRenewer; 218import org.apache.hadoop.tracing.SpanReceiverHost; 219import org.apache.hadoop.tracing.TraceUtils; 220import org.apache.hadoop.util.Daemon; 221import org.apache.hadoop.util.DataChecksum; 222import org.apache.hadoop.util.DataChecksum.Type; 223import org.apache.hadoop.util.Progressable; 224import org.apache.hadoop.util.Time; 225import org.apache.htrace.Sampler; 226import org.apache.htrace.SamplerBuilder; 227import org.apache.htrace.Span; 228import org.apache.htrace.Trace; 229import org.apache.htrace.TraceScope; 230 231import com.google.common.annotations.VisibleForTesting; 232import com.google.common.base.Joiner; 233import com.google.common.base.Preconditions; 234import com.google.common.collect.Lists; 235import com.google.common.net.InetAddresses; 236 237/******************************************************** 238 * DFSClient can connect to a Hadoop Filesystem and 239 * perform basic file tasks. It uses the ClientProtocol 240 * to communicate with a NameNode daemon, and connects 241 * directly to DataNodes to read/write block data. 242 * 243 * Hadoop DFS users should obtain an instance of 244 * DistributedFileSystem, which uses DFSClient to handle 245 * filesystem tasks. 246 * 247 ********************************************************/ 248@InterfaceAudience.Private 249public class DFSClient implements java.io.Closeable, RemotePeerFactory, 250 DataEncryptionKeyFactory { 251 public static final Log LOG = LogFactory.getLog(DFSClient.class); 252 public static final long SERVER_DEFAULTS_VALIDITY_PERIOD = 60 * 60 * 1000L; // 1 hour 253 static final int TCP_WINDOW_SIZE = 128 * 1024; // 128 KB 254 255 private final Configuration conf; 256 private final Conf dfsClientConf; 257 final ClientProtocol namenode; 258 /* The service used for delegation tokens */ 259 private Text dtService; 260 261 final UserGroupInformation ugi; 262 volatile boolean clientRunning = true; 263 volatile long lastLeaseRenewal; 264 private volatile FsServerDefaults serverDefaults; 265 private volatile long serverDefaultsLastUpdate; 266 final String clientName; 267 final SocketFactory socketFactory; 268 final ReplaceDatanodeOnFailure dtpReplaceDatanodeOnFailure; 269 final FileSystem.Statistics stats; 270 private final String authority; 271 private final Random r = new Random(); 272 private SocketAddress[] localInterfaceAddrs; 273 private DataEncryptionKey encryptionKey; 274 final SaslDataTransferClient saslClient; 275 private final CachingStrategy defaultReadCachingStrategy; 276 private final CachingStrategy defaultWriteCachingStrategy; 277 private final ClientContext clientContext; 278 private volatile long hedgedReadThresholdMillis; 279 private static final DFSHedgedReadMetrics HEDGED_READ_METRIC = 280 new DFSHedgedReadMetrics(); 281 private static ThreadPoolExecutor HEDGED_READ_THREAD_POOL; 282 private final Sampler<?> traceSampler; 283 284 /** 285 * DFSClient configuration 286 */ 287 public static class Conf { 288 final int hdfsTimeout; // timeout value for a DFS operation. 289 290 final int maxFailoverAttempts; 291 final int maxRetryAttempts; 292 final int failoverSleepBaseMillis; 293 final int failoverSleepMaxMillis; 294 final int maxBlockAcquireFailures; 295 final int confTime; 296 final int ioBufferSize; 297 final ChecksumOpt defaultChecksumOpt; 298 final int writePacketSize; 299 final int writeMaxPackets; 300 final ByteArrayManager.Conf writeByteArrayManagerConf; 301 final int socketTimeout; 302 final int socketCacheCapacity; 303 final long socketCacheExpiry; 304 final long excludedNodesCacheExpiry; 305 /** Wait time window (in msec) if BlockMissingException is caught */ 306 final int timeWindow; 307 final int nCachedConnRetry; 308 final int nBlockWriteRetry; 309 final int nBlockWriteLocateFollowingRetry; 310 final long defaultBlockSize; 311 final long prefetchSize; 312 final short defaultReplication; 313 final String taskId; 314 final FsPermission uMask; 315 final boolean connectToDnViaHostname; 316 final boolean getHdfsBlocksMetadataEnabled; 317 final int getFileBlockStorageLocationsNumThreads; 318 final int getFileBlockStorageLocationsTimeoutMs; 319 final int retryTimesForGetLastBlockLength; 320 final int retryIntervalForGetLastBlockLength; 321 final long datanodeRestartTimeout; 322 final long dfsclientSlowIoWarningThresholdMs; 323 324 final boolean useLegacyBlockReader; 325 final boolean useLegacyBlockReaderLocal; 326 final String domainSocketPath; 327 final boolean skipShortCircuitChecksums; 328 final int shortCircuitBufferSize; 329 final boolean shortCircuitLocalReads; 330 final boolean domainSocketDataTraffic; 331 final int shortCircuitStreamsCacheSize; 332 final long shortCircuitStreamsCacheExpiryMs; 333 final int shortCircuitSharedMemoryWatcherInterruptCheckMs; 334 335 final boolean shortCircuitMmapEnabled; 336 final int shortCircuitMmapCacheSize; 337 final long shortCircuitMmapCacheExpiryMs; 338 final long shortCircuitMmapCacheRetryTimeout; 339 final long shortCircuitCacheStaleThresholdMs; 340 341 final long keyProviderCacheExpiryMs; 342 public BlockReaderFactory.FailureInjector brfFailureInjector = 343 new BlockReaderFactory.FailureInjector(); 344 345 public Conf(Configuration conf) { 346 // The hdfsTimeout is currently the same as the ipc timeout 347 hdfsTimeout = Client.getTimeout(conf); 348 maxFailoverAttempts = conf.getInt( 349 DFS_CLIENT_FAILOVER_MAX_ATTEMPTS_KEY, 350 DFS_CLIENT_FAILOVER_MAX_ATTEMPTS_DEFAULT); 351 maxRetryAttempts = conf.getInt( 352 DFS_CLIENT_RETRY_MAX_ATTEMPTS_KEY, 353 DFS_CLIENT_RETRY_MAX_ATTEMPTS_DEFAULT); 354 failoverSleepBaseMillis = conf.getInt( 355 DFS_CLIENT_FAILOVER_SLEEPTIME_BASE_KEY, 356 DFS_CLIENT_FAILOVER_SLEEPTIME_BASE_DEFAULT); 357 failoverSleepMaxMillis = conf.getInt( 358 DFS_CLIENT_FAILOVER_SLEEPTIME_MAX_KEY, 359 DFS_CLIENT_FAILOVER_SLEEPTIME_MAX_DEFAULT); 360 361 maxBlockAcquireFailures = conf.getInt( 362 DFS_CLIENT_MAX_BLOCK_ACQUIRE_FAILURES_KEY, 363 DFS_CLIENT_MAX_BLOCK_ACQUIRE_FAILURES_DEFAULT); 364 confTime = conf.getInt(DFS_DATANODE_SOCKET_WRITE_TIMEOUT_KEY, 365 HdfsServerConstants.WRITE_TIMEOUT); 366 ioBufferSize = conf.getInt( 367 CommonConfigurationKeysPublic.IO_FILE_BUFFER_SIZE_KEY, 368 CommonConfigurationKeysPublic.IO_FILE_BUFFER_SIZE_DEFAULT); 369 defaultChecksumOpt = getChecksumOptFromConf(conf); 370 socketTimeout = conf.getInt(DFS_CLIENT_SOCKET_TIMEOUT_KEY, 371 HdfsServerConstants.READ_TIMEOUT); 372 /** dfs.write.packet.size is an internal config variable */ 373 writePacketSize = conf.getInt(DFS_CLIENT_WRITE_PACKET_SIZE_KEY, 374 DFS_CLIENT_WRITE_PACKET_SIZE_DEFAULT); 375 writeMaxPackets = conf.getInt( 376 DFSConfigKeys.DFS_CLIENT_WRITE_MAX_PACKETS_IN_FLIGHT_KEY, 377 DFSConfigKeys.DFS_CLIENT_WRITE_MAX_PACKETS_IN_FLIGHT_DEFAULT); 378 379 final boolean byteArrayManagerEnabled = conf.getBoolean( 380 DFSConfigKeys.DFS_CLIENT_WRITE_BYTE_ARRAY_MANAGER_ENABLED_KEY, 381 DFSConfigKeys.DFS_CLIENT_WRITE_BYTE_ARRAY_MANAGER_ENABLED_DEFAULT); 382 if (!byteArrayManagerEnabled) { 383 writeByteArrayManagerConf = null; 384 } else { 385 final int countThreshold = conf.getInt( 386 DFSConfigKeys.DFS_CLIENT_WRITE_BYTE_ARRAY_MANAGER_COUNT_THRESHOLD_KEY, 387 DFSConfigKeys.DFS_CLIENT_WRITE_BYTE_ARRAY_MANAGER_COUNT_THRESHOLD_DEFAULT); 388 final int countLimit = conf.getInt( 389 DFSConfigKeys.DFS_CLIENT_WRITE_BYTE_ARRAY_MANAGER_COUNT_LIMIT_KEY, 390 DFSConfigKeys.DFS_CLIENT_WRITE_BYTE_ARRAY_MANAGER_COUNT_LIMIT_DEFAULT); 391 final long countResetTimePeriodMs = conf.getLong( 392 DFSConfigKeys.DFS_CLIENT_WRITE_BYTE_ARRAY_MANAGER_COUNT_RESET_TIME_PERIOD_MS_KEY, 393 DFSConfigKeys.DFS_CLIENT_WRITE_BYTE_ARRAY_MANAGER_COUNT_RESET_TIME_PERIOD_MS_DEFAULT); 394 writeByteArrayManagerConf = new ByteArrayManager.Conf( 395 countThreshold, countLimit, countResetTimePeriodMs); 396 } 397 398 399 defaultBlockSize = conf.getLongBytes(DFS_BLOCK_SIZE_KEY, 400 DFS_BLOCK_SIZE_DEFAULT); 401 defaultReplication = (short) conf.getInt( 402 DFS_REPLICATION_KEY, DFS_REPLICATION_DEFAULT); 403 taskId = conf.get("mapreduce.task.attempt.id", "NONMAPREDUCE"); 404 socketCacheCapacity = conf.getInt(DFS_CLIENT_SOCKET_CACHE_CAPACITY_KEY, 405 DFS_CLIENT_SOCKET_CACHE_CAPACITY_DEFAULT); 406 socketCacheExpiry = conf.getLong(DFS_CLIENT_SOCKET_CACHE_EXPIRY_MSEC_KEY, 407 DFS_CLIENT_SOCKET_CACHE_EXPIRY_MSEC_DEFAULT); 408 excludedNodesCacheExpiry = conf.getLong( 409 DFS_CLIENT_WRITE_EXCLUDE_NODES_CACHE_EXPIRY_INTERVAL, 410 DFS_CLIENT_WRITE_EXCLUDE_NODES_CACHE_EXPIRY_INTERVAL_DEFAULT); 411 prefetchSize = conf.getLong(DFS_CLIENT_READ_PREFETCH_SIZE_KEY, 412 10 * defaultBlockSize); 413 timeWindow = conf.getInt(DFS_CLIENT_RETRY_WINDOW_BASE, 3000); 414 nCachedConnRetry = conf.getInt(DFS_CLIENT_CACHED_CONN_RETRY_KEY, 415 DFS_CLIENT_CACHED_CONN_RETRY_DEFAULT); 416 nBlockWriteRetry = conf.getInt(DFS_CLIENT_BLOCK_WRITE_RETRIES_KEY, 417 DFS_CLIENT_BLOCK_WRITE_RETRIES_DEFAULT); 418 nBlockWriteLocateFollowingRetry = conf.getInt( 419 DFS_CLIENT_BLOCK_WRITE_LOCATEFOLLOWINGBLOCK_RETRIES_KEY, 420 DFS_CLIENT_BLOCK_WRITE_LOCATEFOLLOWINGBLOCK_RETRIES_DEFAULT); 421 uMask = FsPermission.getUMask(conf); 422 connectToDnViaHostname = conf.getBoolean(DFS_CLIENT_USE_DN_HOSTNAME, 423 DFS_CLIENT_USE_DN_HOSTNAME_DEFAULT); 424 getHdfsBlocksMetadataEnabled = conf.getBoolean( 425 DFSConfigKeys.DFS_HDFS_BLOCKS_METADATA_ENABLED, 426 DFSConfigKeys.DFS_HDFS_BLOCKS_METADATA_ENABLED_DEFAULT); 427 getFileBlockStorageLocationsNumThreads = conf.getInt( 428 DFSConfigKeys.DFS_CLIENT_FILE_BLOCK_STORAGE_LOCATIONS_NUM_THREADS, 429 DFSConfigKeys.DFS_CLIENT_FILE_BLOCK_STORAGE_LOCATIONS_NUM_THREADS_DEFAULT); 430 getFileBlockStorageLocationsTimeoutMs = conf.getInt( 431 DFSConfigKeys.DFS_CLIENT_FILE_BLOCK_STORAGE_LOCATIONS_TIMEOUT_MS, 432 DFSConfigKeys.DFS_CLIENT_FILE_BLOCK_STORAGE_LOCATIONS_TIMEOUT_MS_DEFAULT); 433 retryTimesForGetLastBlockLength = conf.getInt( 434 DFSConfigKeys.DFS_CLIENT_RETRY_TIMES_GET_LAST_BLOCK_LENGTH, 435 DFSConfigKeys.DFS_CLIENT_RETRY_TIMES_GET_LAST_BLOCK_LENGTH_DEFAULT); 436 retryIntervalForGetLastBlockLength = conf.getInt( 437 DFSConfigKeys.DFS_CLIENT_RETRY_INTERVAL_GET_LAST_BLOCK_LENGTH, 438 DFSConfigKeys.DFS_CLIENT_RETRY_INTERVAL_GET_LAST_BLOCK_LENGTH_DEFAULT); 439 440 useLegacyBlockReader = conf.getBoolean( 441 DFSConfigKeys.DFS_CLIENT_USE_LEGACY_BLOCKREADER, 442 DFSConfigKeys.DFS_CLIENT_USE_LEGACY_BLOCKREADER_DEFAULT); 443 useLegacyBlockReaderLocal = conf.getBoolean( 444 DFSConfigKeys.DFS_CLIENT_USE_LEGACY_BLOCKREADERLOCAL, 445 DFSConfigKeys.DFS_CLIENT_USE_LEGACY_BLOCKREADERLOCAL_DEFAULT); 446 shortCircuitLocalReads = conf.getBoolean( 447 DFSConfigKeys.DFS_CLIENT_READ_SHORTCIRCUIT_KEY, 448 DFSConfigKeys.DFS_CLIENT_READ_SHORTCIRCUIT_DEFAULT); 449 domainSocketDataTraffic = conf.getBoolean( 450 DFSConfigKeys.DFS_CLIENT_DOMAIN_SOCKET_DATA_TRAFFIC, 451 DFSConfigKeys.DFS_CLIENT_DOMAIN_SOCKET_DATA_TRAFFIC_DEFAULT); 452 domainSocketPath = conf.getTrimmed( 453 DFSConfigKeys.DFS_DOMAIN_SOCKET_PATH_KEY, 454 DFSConfigKeys.DFS_DOMAIN_SOCKET_PATH_DEFAULT); 455 456 if (BlockReaderLocal.LOG.isDebugEnabled()) { 457 BlockReaderLocal.LOG.debug( 458 DFSConfigKeys.DFS_CLIENT_USE_LEGACY_BLOCKREADERLOCAL 459 + " = " + useLegacyBlockReaderLocal); 460 BlockReaderLocal.LOG.debug( 461 DFSConfigKeys.DFS_CLIENT_READ_SHORTCIRCUIT_KEY 462 + " = " + shortCircuitLocalReads); 463 BlockReaderLocal.LOG.debug( 464 DFSConfigKeys.DFS_CLIENT_DOMAIN_SOCKET_DATA_TRAFFIC 465 + " = " + domainSocketDataTraffic); 466 BlockReaderLocal.LOG.debug( 467 DFSConfigKeys.DFS_DOMAIN_SOCKET_PATH_KEY 468 + " = " + domainSocketPath); 469 } 470 471 skipShortCircuitChecksums = conf.getBoolean( 472 DFSConfigKeys.DFS_CLIENT_READ_SHORTCIRCUIT_SKIP_CHECKSUM_KEY, 473 DFSConfigKeys.DFS_CLIENT_READ_SHORTCIRCUIT_SKIP_CHECKSUM_DEFAULT); 474 shortCircuitBufferSize = conf.getInt( 475 DFSConfigKeys.DFS_CLIENT_READ_SHORTCIRCUIT_BUFFER_SIZE_KEY, 476 DFSConfigKeys.DFS_CLIENT_READ_SHORTCIRCUIT_BUFFER_SIZE_DEFAULT); 477 shortCircuitStreamsCacheSize = conf.getInt( 478 DFSConfigKeys.DFS_CLIENT_READ_SHORTCIRCUIT_STREAMS_CACHE_SIZE_KEY, 479 DFSConfigKeys.DFS_CLIENT_READ_SHORTCIRCUIT_STREAMS_CACHE_SIZE_DEFAULT); 480 shortCircuitStreamsCacheExpiryMs = conf.getLong( 481 DFSConfigKeys.DFS_CLIENT_READ_SHORTCIRCUIT_STREAMS_CACHE_EXPIRY_MS_KEY, 482 DFSConfigKeys.DFS_CLIENT_READ_SHORTCIRCUIT_STREAMS_CACHE_EXPIRY_MS_DEFAULT); 483 shortCircuitMmapEnabled = conf.getBoolean( 484 DFSConfigKeys.DFS_CLIENT_MMAP_ENABLED, 485 DFSConfigKeys.DFS_CLIENT_MMAP_ENABLED_DEFAULT); 486 shortCircuitMmapCacheSize = conf.getInt( 487 DFSConfigKeys.DFS_CLIENT_MMAP_CACHE_SIZE, 488 DFSConfigKeys.DFS_CLIENT_MMAP_CACHE_SIZE_DEFAULT); 489 shortCircuitMmapCacheExpiryMs = conf.getLong( 490 DFSConfigKeys.DFS_CLIENT_MMAP_CACHE_TIMEOUT_MS, 491 DFSConfigKeys.DFS_CLIENT_MMAP_CACHE_TIMEOUT_MS_DEFAULT); 492 shortCircuitMmapCacheRetryTimeout = conf.getLong( 493 DFSConfigKeys.DFS_CLIENT_MMAP_RETRY_TIMEOUT_MS, 494 DFSConfigKeys.DFS_CLIENT_MMAP_RETRY_TIMEOUT_MS_DEFAULT); 495 shortCircuitCacheStaleThresholdMs = conf.getLong( 496 DFSConfigKeys.DFS_CLIENT_SHORT_CIRCUIT_REPLICA_STALE_THRESHOLD_MS, 497 DFSConfigKeys.DFS_CLIENT_SHORT_CIRCUIT_REPLICA_STALE_THRESHOLD_MS_DEFAULT); 498 shortCircuitSharedMemoryWatcherInterruptCheckMs = conf.getInt( 499 DFSConfigKeys.DFS_SHORT_CIRCUIT_SHARED_MEMORY_WATCHER_INTERRUPT_CHECK_MS, 500 DFSConfigKeys.DFS_SHORT_CIRCUIT_SHARED_MEMORY_WATCHER_INTERRUPT_CHECK_MS_DEFAULT); 501 502 datanodeRestartTimeout = conf.getLong( 503 DFS_CLIENT_DATANODE_RESTART_TIMEOUT_KEY, 504 DFS_CLIENT_DATANODE_RESTART_TIMEOUT_DEFAULT) * 1000; 505 dfsclientSlowIoWarningThresholdMs = conf.getLong( 506 DFSConfigKeys.DFS_CLIENT_SLOW_IO_WARNING_THRESHOLD_KEY, 507 DFSConfigKeys.DFS_CLIENT_SLOW_IO_WARNING_THRESHOLD_DEFAULT); 508 509 keyProviderCacheExpiryMs = conf.getLong( 510 DFSConfigKeys.DFS_CLIENT_KEY_PROVIDER_CACHE_EXPIRY_MS, 511 DFSConfigKeys.DFS_CLIENT_KEY_PROVIDER_CACHE_EXPIRY_DEFAULT); 512 } 513 514 public boolean isUseLegacyBlockReaderLocal() { 515 return useLegacyBlockReaderLocal; 516 } 517 518 public String getDomainSocketPath() { 519 return domainSocketPath; 520 } 521 522 public boolean isShortCircuitLocalReads() { 523 return shortCircuitLocalReads; 524 } 525 526 public boolean isDomainSocketDataTraffic() { 527 return domainSocketDataTraffic; 528 } 529 530 private DataChecksum.Type getChecksumType(Configuration conf) { 531 final String checksum = conf.get( 532 DFSConfigKeys.DFS_CHECKSUM_TYPE_KEY, 533 DFSConfigKeys.DFS_CHECKSUM_TYPE_DEFAULT); 534 try { 535 return DataChecksum.Type.valueOf(checksum); 536 } catch(IllegalArgumentException iae) { 537 LOG.warn("Bad checksum type: " + checksum + ". Using default " 538 + DFSConfigKeys.DFS_CHECKSUM_TYPE_DEFAULT); 539 return DataChecksum.Type.valueOf( 540 DFSConfigKeys.DFS_CHECKSUM_TYPE_DEFAULT); 541 } 542 } 543 544 // Construct a checksum option from conf 545 private ChecksumOpt getChecksumOptFromConf(Configuration conf) { 546 DataChecksum.Type type = getChecksumType(conf); 547 int bytesPerChecksum = conf.getInt(DFS_BYTES_PER_CHECKSUM_KEY, 548 DFS_BYTES_PER_CHECKSUM_DEFAULT); 549 return new ChecksumOpt(type, bytesPerChecksum); 550 } 551 552 // create a DataChecksum with the default option. 553 private DataChecksum createChecksum() throws IOException { 554 return createChecksum(null); 555 } 556 557 private DataChecksum createChecksum(ChecksumOpt userOpt) { 558 // Fill in any missing field with the default. 559 ChecksumOpt myOpt = ChecksumOpt.processChecksumOpt( 560 defaultChecksumOpt, userOpt); 561 DataChecksum dataChecksum = DataChecksum.newDataChecksum( 562 myOpt.getChecksumType(), 563 myOpt.getBytesPerChecksum()); 564 if (dataChecksum == null) { 565 throw new HadoopIllegalArgumentException("Invalid checksum type: userOpt=" 566 + userOpt + ", default=" + defaultChecksumOpt 567 + ", effective=null"); 568 } 569 return dataChecksum; 570 } 571 } 572 573 public Conf getConf() { 574 return dfsClientConf; 575 } 576 577 Configuration getConfiguration() { 578 return conf; 579 } 580 581 /** 582 * A map from file names to {@link DFSOutputStream} objects 583 * that are currently being written by this client. 584 * Note that a file can only be written by a single client. 585 */ 586 private final Map<Long, DFSOutputStream> filesBeingWritten 587 = new HashMap<Long, DFSOutputStream>(); 588 589 /** 590 * Same as this(NameNode.getAddress(conf), conf); 591 * @see #DFSClient(InetSocketAddress, Configuration) 592 * @deprecated Deprecated at 0.21 593 */ 594 @Deprecated 595 public DFSClient(Configuration conf) throws IOException { 596 this(NameNode.getAddress(conf), conf); 597 } 598 599 public DFSClient(InetSocketAddress address, Configuration conf) throws IOException { 600 this(NameNode.getUri(address), conf); 601 } 602 603 /** 604 * Same as this(nameNodeUri, conf, null); 605 * @see #DFSClient(URI, Configuration, FileSystem.Statistics) 606 */ 607 public DFSClient(URI nameNodeUri, Configuration conf 608 ) throws IOException { 609 this(nameNodeUri, conf, null); 610 } 611 612 /** 613 * Same as this(nameNodeUri, null, conf, stats); 614 * @see #DFSClient(URI, ClientProtocol, Configuration, FileSystem.Statistics) 615 */ 616 public DFSClient(URI nameNodeUri, Configuration conf, 617 FileSystem.Statistics stats) 618 throws IOException { 619 this(nameNodeUri, null, conf, stats); 620 } 621 622 /** 623 * Create a new DFSClient connected to the given nameNodeUri or rpcNamenode. 624 * If HA is enabled and a positive value is set for 625 * {@link DFSConfigKeys#DFS_CLIENT_TEST_DROP_NAMENODE_RESPONSE_NUM_KEY} in the 626 * configuration, the DFSClient will use {@link LossyRetryInvocationHandler} 627 * as its RetryInvocationHandler. Otherwise one of nameNodeUri or rpcNamenode 628 * must be null. 629 */ 630 @VisibleForTesting 631 public DFSClient(URI nameNodeUri, ClientProtocol rpcNamenode, 632 Configuration conf, FileSystem.Statistics stats) 633 throws IOException { 634 SpanReceiverHost.get(conf, DFSConfigKeys.DFS_CLIENT_HTRACE_PREFIX); 635 traceSampler = new SamplerBuilder(TraceUtils. 636 wrapHadoopConf(DFSConfigKeys.DFS_CLIENT_HTRACE_PREFIX, conf)).build(); 637 // Copy only the required DFSClient configuration 638 this.dfsClientConf = new Conf(conf); 639 if (this.dfsClientConf.useLegacyBlockReaderLocal) { 640 LOG.debug("Using legacy short-circuit local reads."); 641 } 642 this.conf = conf; 643 this.stats = stats; 644 this.socketFactory = NetUtils.getSocketFactory(conf, ClientProtocol.class); 645 this.dtpReplaceDatanodeOnFailure = ReplaceDatanodeOnFailure.get(conf); 646 647 this.ugi = UserGroupInformation.getCurrentUser(); 648 649 this.authority = nameNodeUri == null? "null": nameNodeUri.getAuthority(); 650 this.clientName = "DFSClient_" + dfsClientConf.taskId + "_" + 651 DFSUtil.getRandom().nextInt() + "_" + Thread.currentThread().getId(); 652 int numResponseToDrop = conf.getInt( 653 DFSConfigKeys.DFS_CLIENT_TEST_DROP_NAMENODE_RESPONSE_NUM_KEY, 654 DFSConfigKeys.DFS_CLIENT_TEST_DROP_NAMENODE_RESPONSE_NUM_DEFAULT); 655 NameNodeProxies.ProxyAndInfo<ClientProtocol> proxyInfo = null; 656 AtomicBoolean nnFallbackToSimpleAuth = new AtomicBoolean(false); 657 if (numResponseToDrop > 0) { 658 // This case is used for testing. 659 LOG.warn(DFSConfigKeys.DFS_CLIENT_TEST_DROP_NAMENODE_RESPONSE_NUM_KEY 660 + " is set to " + numResponseToDrop 661 + ", this hacked client will proactively drop responses"); 662 proxyInfo = NameNodeProxies.createProxyWithLossyRetryHandler(conf, 663 nameNodeUri, ClientProtocol.class, numResponseToDrop, 664 nnFallbackToSimpleAuth); 665 } 666 667 if (proxyInfo != null) { 668 this.dtService = proxyInfo.getDelegationTokenService(); 669 this.namenode = proxyInfo.getProxy(); 670 } else if (rpcNamenode != null) { 671 // This case is used for testing. 672 Preconditions.checkArgument(nameNodeUri == null); 673 this.namenode = rpcNamenode; 674 dtService = null; 675 } else { 676 Preconditions.checkArgument(nameNodeUri != null, 677 "null URI"); 678 proxyInfo = NameNodeProxies.createProxy(conf, nameNodeUri, 679 ClientProtocol.class, nnFallbackToSimpleAuth); 680 this.dtService = proxyInfo.getDelegationTokenService(); 681 this.namenode = proxyInfo.getProxy(); 682 } 683 684 String localInterfaces[] = 685 conf.getTrimmedStrings(DFSConfigKeys.DFS_CLIENT_LOCAL_INTERFACES); 686 localInterfaceAddrs = getLocalInterfaceAddrs(localInterfaces); 687 if (LOG.isDebugEnabled() && 0 != localInterfaces.length) { 688 LOG.debug("Using local interfaces [" + 689 Joiner.on(',').join(localInterfaces)+ "] with addresses [" + 690 Joiner.on(',').join(localInterfaceAddrs) + "]"); 691 } 692 693 Boolean readDropBehind = (conf.get(DFS_CLIENT_CACHE_DROP_BEHIND_READS) == null) ? 694 null : conf.getBoolean(DFS_CLIENT_CACHE_DROP_BEHIND_READS, false); 695 Long readahead = (conf.get(DFS_CLIENT_CACHE_READAHEAD) == null) ? 696 null : conf.getLong(DFS_CLIENT_CACHE_READAHEAD, 0); 697 Boolean writeDropBehind = (conf.get(DFS_CLIENT_CACHE_DROP_BEHIND_WRITES) == null) ? 698 null : conf.getBoolean(DFS_CLIENT_CACHE_DROP_BEHIND_WRITES, false); 699 this.defaultReadCachingStrategy = 700 new CachingStrategy(readDropBehind, readahead); 701 this.defaultWriteCachingStrategy = 702 new CachingStrategy(writeDropBehind, readahead); 703 this.clientContext = ClientContext.get( 704 conf.get(DFS_CLIENT_CONTEXT, DFS_CLIENT_CONTEXT_DEFAULT), 705 dfsClientConf); 706 this.hedgedReadThresholdMillis = conf.getLong( 707 DFSConfigKeys.DFS_DFSCLIENT_HEDGED_READ_THRESHOLD_MILLIS, 708 DFSConfigKeys.DEFAULT_DFSCLIENT_HEDGED_READ_THRESHOLD_MILLIS); 709 int numThreads = conf.getInt( 710 DFSConfigKeys.DFS_DFSCLIENT_HEDGED_READ_THREADPOOL_SIZE, 711 DFSConfigKeys.DEFAULT_DFSCLIENT_HEDGED_READ_THREADPOOL_SIZE); 712 if (numThreads > 0) { 713 this.initThreadsNumForHedgedReads(numThreads); 714 } 715 this.saslClient = new SaslDataTransferClient( 716 conf, DataTransferSaslUtil.getSaslPropertiesResolver(conf), 717 TrustedChannelResolver.getInstance(conf), nnFallbackToSimpleAuth); 718 } 719 720 /** 721 * Return the socket addresses to use with each configured 722 * local interface. Local interfaces may be specified by IP 723 * address, IP address range using CIDR notation, interface 724 * name (e.g. eth0) or sub-interface name (e.g. eth0:0). 725 * The socket addresses consist of the IPs for the interfaces 726 * and the ephemeral port (port 0). If an IP, IP range, or 727 * interface name matches an interface with sub-interfaces 728 * only the IP of the interface is used. Sub-interfaces can 729 * be used by specifying them explicitly (by IP or name). 730 * 731 * @return SocketAddresses for the configured local interfaces, 732 * or an empty array if none are configured 733 * @throws UnknownHostException if a given interface name is invalid 734 */ 735 private static SocketAddress[] getLocalInterfaceAddrs( 736 String interfaceNames[]) throws UnknownHostException { 737 List<SocketAddress> localAddrs = new ArrayList<SocketAddress>(); 738 for (String interfaceName : interfaceNames) { 739 if (InetAddresses.isInetAddress(interfaceName)) { 740 localAddrs.add(new InetSocketAddress(interfaceName, 0)); 741 } else if (NetUtils.isValidSubnet(interfaceName)) { 742 for (InetAddress addr : NetUtils.getIPs(interfaceName, false)) { 743 localAddrs.add(new InetSocketAddress(addr, 0)); 744 } 745 } else { 746 for (String ip : DNS.getIPs(interfaceName, false)) { 747 localAddrs.add(new InetSocketAddress(ip, 0)); 748 } 749 } 750 } 751 return localAddrs.toArray(new SocketAddress[localAddrs.size()]); 752 } 753 754 /** 755 * Select one of the configured local interfaces at random. We use a random 756 * interface because other policies like round-robin are less effective 757 * given that we cache connections to datanodes. 758 * 759 * @return one of the local interface addresses at random, or null if no 760 * local interfaces are configured 761 */ 762 SocketAddress getRandomLocalInterfaceAddr() { 763 if (localInterfaceAddrs.length == 0) { 764 return null; 765 } 766 final int idx = r.nextInt(localInterfaceAddrs.length); 767 final SocketAddress addr = localInterfaceAddrs[idx]; 768 if (LOG.isDebugEnabled()) { 769 LOG.debug("Using local interface " + addr); 770 } 771 return addr; 772 } 773 774 /** 775 * Return the number of times the client should go back to the namenode 776 * to retrieve block locations when reading. 777 */ 778 int getMaxBlockAcquireFailures() { 779 return dfsClientConf.maxBlockAcquireFailures; 780 } 781 782 /** 783 * Return the timeout that clients should use when writing to datanodes. 784 * @param numNodes the number of nodes in the pipeline. 785 */ 786 int getDatanodeWriteTimeout(int numNodes) { 787 return (dfsClientConf.confTime > 0) ? 788 (dfsClientConf.confTime + HdfsServerConstants.WRITE_TIMEOUT_EXTENSION * numNodes) : 0; 789 } 790 791 int getDatanodeReadTimeout(int numNodes) { 792 return dfsClientConf.socketTimeout > 0 ? 793 (HdfsServerConstants.READ_TIMEOUT_EXTENSION * numNodes + 794 dfsClientConf.socketTimeout) : 0; 795 } 796 797 int getHdfsTimeout() { 798 return dfsClientConf.hdfsTimeout; 799 } 800 801 @VisibleForTesting 802 public String getClientName() { 803 return clientName; 804 } 805 806 void checkOpen() throws IOException { 807 if (!clientRunning) { 808 IOException result = new IOException("Filesystem closed"); 809 throw result; 810 } 811 } 812 813 /** Return the lease renewer instance. The renewer thread won't start 814 * until the first output stream is created. The same instance will 815 * be returned until all output streams are closed. 816 */ 817 public LeaseRenewer getLeaseRenewer() throws IOException { 818 return LeaseRenewer.getInstance(authority, ugi, this); 819 } 820 821 /** Get a lease and start automatic renewal */ 822 private void beginFileLease(final long inodeId, final DFSOutputStream out) 823 throws IOException { 824 getLeaseRenewer().put(inodeId, out, this); 825 } 826 827 /** Stop renewal of lease for the file. */ 828 void endFileLease(final long inodeId) throws IOException { 829 getLeaseRenewer().closeFile(inodeId, this); 830 } 831 832 833 /** Put a file. Only called from LeaseRenewer, where proper locking is 834 * enforced to consistently update its local dfsclients array and 835 * client's filesBeingWritten map. 836 */ 837 void putFileBeingWritten(final long inodeId, final DFSOutputStream out) { 838 synchronized(filesBeingWritten) { 839 filesBeingWritten.put(inodeId, out); 840 // update the last lease renewal time only when there was no 841 // writes. once there is one write stream open, the lease renewer 842 // thread keeps it updated well with in anyone's expiration time. 843 if (lastLeaseRenewal == 0) { 844 updateLastLeaseRenewal(); 845 } 846 } 847 } 848 849 /** Remove a file. Only called from LeaseRenewer. */ 850 void removeFileBeingWritten(final long inodeId) { 851 synchronized(filesBeingWritten) { 852 filesBeingWritten.remove(inodeId); 853 if (filesBeingWritten.isEmpty()) { 854 lastLeaseRenewal = 0; 855 } 856 } 857 } 858 859 /** Is file-being-written map empty? */ 860 boolean isFilesBeingWrittenEmpty() { 861 synchronized(filesBeingWritten) { 862 return filesBeingWritten.isEmpty(); 863 } 864 } 865 866 /** @return true if the client is running */ 867 boolean isClientRunning() { 868 return clientRunning; 869 } 870 871 long getLastLeaseRenewal() { 872 return lastLeaseRenewal; 873 } 874 875 void updateLastLeaseRenewal() { 876 synchronized(filesBeingWritten) { 877 if (filesBeingWritten.isEmpty()) { 878 return; 879 } 880 lastLeaseRenewal = Time.monotonicNow(); 881 } 882 } 883 884 /** 885 * Renew leases. 886 * @return true if lease was renewed. May return false if this 887 * client has been closed or has no files open. 888 **/ 889 boolean renewLease() throws IOException { 890 if (clientRunning && !isFilesBeingWrittenEmpty()) { 891 try { 892 namenode.renewLease(clientName); 893 updateLastLeaseRenewal(); 894 return true; 895 } catch (IOException e) { 896 // Abort if the lease has already expired. 897 final long elapsed = Time.monotonicNow() - getLastLeaseRenewal(); 898 if (elapsed > HdfsConstants.LEASE_HARDLIMIT_PERIOD) { 899 LOG.warn("Failed to renew lease for " + clientName + " for " 900 + (elapsed/1000) + " seconds (>= hard-limit =" 901 + (HdfsConstants.LEASE_HARDLIMIT_PERIOD/1000) + " seconds.) " 902 + "Closing all files being written ...", e); 903 closeAllFilesBeingWritten(true); 904 } else { 905 // Let the lease renewer handle it and retry. 906 throw e; 907 } 908 } 909 } 910 return false; 911 } 912 913 /** 914 * Close connections the Namenode. 915 */ 916 void closeConnectionToNamenode() { 917 RPC.stopProxy(namenode); 918 } 919 920 /** Close/abort all files being written. */ 921 public void closeAllFilesBeingWritten(final boolean abort) { 922 for(;;) { 923 final long inodeId; 924 final DFSOutputStream out; 925 synchronized(filesBeingWritten) { 926 if (filesBeingWritten.isEmpty()) { 927 return; 928 } 929 inodeId = filesBeingWritten.keySet().iterator().next(); 930 out = filesBeingWritten.remove(inodeId); 931 } 932 if (out != null) { 933 try { 934 if (abort) { 935 out.abort(); 936 } else { 937 out.close(); 938 } 939 } catch(IOException ie) { 940 LOG.error("Failed to " + (abort? "abort": "close") + 941 " inode " + inodeId, ie); 942 } 943 } 944 } 945 } 946 947 /** 948 * Close the file system, abandoning all of the leases and files being 949 * created and close connections to the namenode. 950 */ 951 @Override 952 public synchronized void close() throws IOException { 953 if(clientRunning) { 954 closeAllFilesBeingWritten(false); 955 clientRunning = false; 956 getLeaseRenewer().closeClient(this); 957 // close connections to the namenode 958 closeConnectionToNamenode(); 959 } 960 } 961 962 /** 963 * Close all open streams, abandoning all of the leases and files being 964 * created. 965 * @param abort whether streams should be gracefully closed 966 */ 967 public void closeOutputStreams(boolean abort) { 968 if (clientRunning) { 969 closeAllFilesBeingWritten(abort); 970 } 971 } 972 973 /** 974 * Get the default block size for this cluster 975 * @return the default block size in bytes 976 */ 977 public long getDefaultBlockSize() { 978 return dfsClientConf.defaultBlockSize; 979 } 980 981 /** 982 * @see ClientProtocol#getPreferredBlockSize(String) 983 */ 984 public long getBlockSize(String f) throws IOException { 985 TraceScope scope = getPathTraceScope("getBlockSize", f); 986 try { 987 return namenode.getPreferredBlockSize(f); 988 } catch (IOException ie) { 989 LOG.warn("Problem getting block size", ie); 990 throw ie; 991 } finally { 992 scope.close(); 993 } 994 } 995 996 /** 997 * Get server default values for a number of configuration params. 998 * @see ClientProtocol#getServerDefaults() 999 */ 1000 public FsServerDefaults getServerDefaults() throws IOException { 1001 long now = Time.monotonicNow(); 1002 if ((serverDefaults == null) || 1003 (now - serverDefaultsLastUpdate > SERVER_DEFAULTS_VALIDITY_PERIOD)) { 1004 serverDefaults = namenode.getServerDefaults(); 1005 serverDefaultsLastUpdate = now; 1006 } 1007 assert serverDefaults != null; 1008 return serverDefaults; 1009 } 1010 1011 /** 1012 * Get a canonical token service name for this client's tokens. Null should 1013 * be returned if the client is not using tokens. 1014 * @return the token service for the client 1015 */ 1016 @InterfaceAudience.LimitedPrivate( { "HDFS" }) 1017 public String getCanonicalServiceName() { 1018 return (dtService != null) ? dtService.toString() : null; 1019 } 1020 1021 /** 1022 * @see ClientProtocol#getDelegationToken(Text) 1023 */ 1024 public Token<DelegationTokenIdentifier> getDelegationToken(Text renewer) 1025 throws IOException { 1026 assert dtService != null; 1027 TraceScope scope = Trace.startSpan("getDelegationToken", traceSampler); 1028 try { 1029 Token<DelegationTokenIdentifier> token = 1030 namenode.getDelegationToken(renewer); 1031 if (token != null) { 1032 token.setService(this.dtService); 1033 LOG.info("Created " + DelegationTokenIdentifier.stringifyToken(token)); 1034 } else { 1035 LOG.info("Cannot get delegation token from " + renewer); 1036 } 1037 return token; 1038 } finally { 1039 scope.close(); 1040 } 1041 } 1042 1043 /** 1044 * Renew a delegation token 1045 * @param token the token to renew 1046 * @return the new expiration time 1047 * @throws InvalidToken 1048 * @throws IOException 1049 * @deprecated Use Token.renew instead. 1050 */ 1051 @Deprecated 1052 public long renewDelegationToken(Token<DelegationTokenIdentifier> token) 1053 throws InvalidToken, IOException { 1054 LOG.info("Renewing " + DelegationTokenIdentifier.stringifyToken(token)); 1055 try { 1056 return token.renew(conf); 1057 } catch (InterruptedException ie) { 1058 throw new RuntimeException("caught interrupted", ie); 1059 } catch (RemoteException re) { 1060 throw re.unwrapRemoteException(InvalidToken.class, 1061 AccessControlException.class); 1062 } 1063 } 1064 1065 private static final Map<String, Boolean> localAddrMap = Collections 1066 .synchronizedMap(new HashMap<String, Boolean>()); 1067 1068 public static boolean isLocalAddress(InetSocketAddress targetAddr) { 1069 InetAddress addr = targetAddr.getAddress(); 1070 Boolean cached = localAddrMap.get(addr.getHostAddress()); 1071 if (cached != null) { 1072 if (LOG.isTraceEnabled()) { 1073 LOG.trace("Address " + targetAddr + 1074 (cached ? " is local" : " is not local")); 1075 } 1076 return cached; 1077 } 1078 1079 boolean local = NetUtils.isLocalAddress(addr); 1080 1081 if (LOG.isTraceEnabled()) { 1082 LOG.trace("Address " + targetAddr + 1083 (local ? " is local" : " is not local")); 1084 } 1085 localAddrMap.put(addr.getHostAddress(), local); 1086 return local; 1087 } 1088 1089 /** 1090 * Cancel a delegation token 1091 * @param token the token to cancel 1092 * @throws InvalidToken 1093 * @throws IOException 1094 * @deprecated Use Token.cancel instead. 1095 */ 1096 @Deprecated 1097 public void cancelDelegationToken(Token<DelegationTokenIdentifier> token) 1098 throws InvalidToken, IOException { 1099 LOG.info("Cancelling " + DelegationTokenIdentifier.stringifyToken(token)); 1100 try { 1101 token.cancel(conf); 1102 } catch (InterruptedException ie) { 1103 throw new RuntimeException("caught interrupted", ie); 1104 } catch (RemoteException re) { 1105 throw re.unwrapRemoteException(InvalidToken.class, 1106 AccessControlException.class); 1107 } 1108 } 1109 1110 @InterfaceAudience.Private 1111 public static class Renewer extends TokenRenewer { 1112 1113 static { 1114 //Ensure that HDFS Configuration files are loaded before trying to use 1115 // the renewer. 1116 HdfsConfiguration.init(); 1117 } 1118 1119 @Override 1120 public boolean handleKind(Text kind) { 1121 return DelegationTokenIdentifier.HDFS_DELEGATION_KIND.equals(kind); 1122 } 1123 1124 @SuppressWarnings("unchecked") 1125 @Override 1126 public long renew(Token<?> token, Configuration conf) throws IOException { 1127 Token<DelegationTokenIdentifier> delToken = 1128 (Token<DelegationTokenIdentifier>) token; 1129 ClientProtocol nn = getNNProxy(delToken, conf); 1130 try { 1131 return nn.renewDelegationToken(delToken); 1132 } catch (RemoteException re) { 1133 throw re.unwrapRemoteException(InvalidToken.class, 1134 AccessControlException.class); 1135 } 1136 } 1137 1138 @SuppressWarnings("unchecked") 1139 @Override 1140 public void cancel(Token<?> token, Configuration conf) throws IOException { 1141 Token<DelegationTokenIdentifier> delToken = 1142 (Token<DelegationTokenIdentifier>) token; 1143 LOG.info("Cancelling " + 1144 DelegationTokenIdentifier.stringifyToken(delToken)); 1145 ClientProtocol nn = getNNProxy(delToken, conf); 1146 try { 1147 nn.cancelDelegationToken(delToken); 1148 } catch (RemoteException re) { 1149 throw re.unwrapRemoteException(InvalidToken.class, 1150 AccessControlException.class); 1151 } 1152 } 1153 1154 private static ClientProtocol getNNProxy( 1155 Token<DelegationTokenIdentifier> token, Configuration conf) 1156 throws IOException { 1157 URI uri = HAUtil.getServiceUriFromToken(HdfsConstants.HDFS_URI_SCHEME, 1158 token); 1159 if (HAUtil.isTokenForLogicalUri(token) && 1160 !HAUtil.isLogicalUri(conf, uri)) { 1161 // If the token is for a logical nameservice, but the configuration 1162 // we have disagrees about that, we can't actually renew it. 1163 // This can be the case in MR, for example, if the RM doesn't 1164 // have all of the HA clusters configured in its configuration. 1165 throw new IOException("Unable to map logical nameservice URI '" + 1166 uri + "' to a NameNode. Local configuration does not have " + 1167 "a failover proxy provider configured."); 1168 } 1169 1170 NameNodeProxies.ProxyAndInfo<ClientProtocol> info = 1171 NameNodeProxies.createProxy(conf, uri, ClientProtocol.class); 1172 assert info.getDelegationTokenService().equals(token.getService()) : 1173 "Returned service '" + info.getDelegationTokenService().toString() + 1174 "' doesn't match expected service '" + 1175 token.getService().toString() + "'"; 1176 1177 return info.getProxy(); 1178 } 1179 1180 @Override 1181 public boolean isManaged(Token<?> token) throws IOException { 1182 return true; 1183 } 1184 1185 } 1186 1187 /** 1188 * Report corrupt blocks that were discovered by the client. 1189 * @see ClientProtocol#reportBadBlocks(LocatedBlock[]) 1190 */ 1191 public void reportBadBlocks(LocatedBlock[] blocks) throws IOException { 1192 namenode.reportBadBlocks(blocks); 1193 } 1194 1195 public short getDefaultReplication() { 1196 return dfsClientConf.defaultReplication; 1197 } 1198 1199 public LocatedBlocks getLocatedBlocks(String src, long start) 1200 throws IOException { 1201 return getLocatedBlocks(src, start, dfsClientConf.prefetchSize); 1202 } 1203 1204 /* 1205 * This is just a wrapper around callGetBlockLocations, but non-static so that 1206 * we can stub it out for tests. 1207 */ 1208 @VisibleForTesting 1209 public LocatedBlocks getLocatedBlocks(String src, long start, long length) 1210 throws IOException { 1211 TraceScope scope = getPathTraceScope("getBlockLocations", src); 1212 try { 1213 return callGetBlockLocations(namenode, src, start, length); 1214 } finally { 1215 scope.close(); 1216 } 1217 } 1218 1219 /** 1220 * @see ClientProtocol#getBlockLocations(String, long, long) 1221 */ 1222 static LocatedBlocks callGetBlockLocations(ClientProtocol namenode, 1223 String src, long start, long length) 1224 throws IOException { 1225 try { 1226 return namenode.getBlockLocations(src, start, length); 1227 } catch(RemoteException re) { 1228 throw re.unwrapRemoteException(AccessControlException.class, 1229 FileNotFoundException.class, 1230 UnresolvedPathException.class); 1231 } 1232 } 1233 1234 /** 1235 * Recover a file's lease 1236 * @param src a file's path 1237 * @return true if the file is already closed 1238 * @throws IOException 1239 */ 1240 boolean recoverLease(String src) throws IOException { 1241 checkOpen(); 1242 1243 TraceScope scope = getPathTraceScope("recoverLease", src); 1244 try { 1245 return namenode.recoverLease(src, clientName); 1246 } catch (RemoteException re) { 1247 throw re.unwrapRemoteException(FileNotFoundException.class, 1248 AccessControlException.class, 1249 UnresolvedPathException.class); 1250 } finally { 1251 scope.close(); 1252 } 1253 } 1254 1255 /** 1256 * Get block location info about file 1257 * 1258 * getBlockLocations() returns a list of hostnames that store 1259 * data for a specific file region. It returns a set of hostnames 1260 * for every block within the indicated region. 1261 * 1262 * This function is very useful when writing code that considers 1263 * data-placement when performing operations. For example, the 1264 * MapReduce system tries to schedule tasks on the same machines 1265 * as the data-block the task processes. 1266 */ 1267 public BlockLocation[] getBlockLocations(String src, long start, 1268 long length) throws IOException, UnresolvedLinkException { 1269 TraceScope scope = getPathTraceScope("getBlockLocations", src); 1270 try { 1271 LocatedBlocks blocks = getLocatedBlocks(src, start, length); 1272 BlockLocation[] locations = DFSUtil.locatedBlocks2Locations(blocks); 1273 HdfsBlockLocation[] hdfsLocations = new HdfsBlockLocation[locations.length]; 1274 for (int i = 0; i < locations.length; i++) { 1275 hdfsLocations[i] = new HdfsBlockLocation(locations[i], blocks.get(i)); 1276 } 1277 return hdfsLocations; 1278 } finally { 1279 scope.close(); 1280 } 1281 } 1282 1283 /** 1284 * Get block location information about a list of {@link HdfsBlockLocation}. 1285 * Used by {@link DistributedFileSystem#getFileBlockStorageLocations(List)} to 1286 * get {@link BlockStorageLocation}s for blocks returned by 1287 * {@link DistributedFileSystem#getFileBlockLocations(org.apache.hadoop.fs.FileStatus, long, long)} 1288 * . 1289 * 1290 * This is done by making a round of RPCs to the associated datanodes, asking 1291 * the volume of each block replica. The returned array of 1292 * {@link BlockStorageLocation} expose this information as a 1293 * {@link VolumeId}. 1294 * 1295 * @param blockLocations 1296 * target blocks on which to query volume location information 1297 * @return volumeBlockLocations original block array augmented with additional 1298 * volume location information for each replica. 1299 */ 1300 public BlockStorageLocation[] getBlockStorageLocations( 1301 List<BlockLocation> blockLocations) throws IOException, 1302 UnsupportedOperationException, InvalidBlockTokenException { 1303 if (!getConf().getHdfsBlocksMetadataEnabled) { 1304 throw new UnsupportedOperationException("Datanode-side support for " + 1305 "getVolumeBlockLocations() must also be enabled in the client " + 1306 "configuration."); 1307 } 1308 // Downcast blockLocations and fetch out required LocatedBlock(s) 1309 List<LocatedBlock> blocks = new ArrayList<LocatedBlock>(); 1310 for (BlockLocation loc : blockLocations) { 1311 if (!(loc instanceof HdfsBlockLocation)) { 1312 throw new ClassCastException("DFSClient#getVolumeBlockLocations " + 1313 "expected to be passed HdfsBlockLocations"); 1314 } 1315 HdfsBlockLocation hdfsLoc = (HdfsBlockLocation) loc; 1316 blocks.add(hdfsLoc.getLocatedBlock()); 1317 } 1318 1319 // Re-group the LocatedBlocks to be grouped by datanodes, with the values 1320 // a list of the LocatedBlocks on the datanode. 1321 Map<DatanodeInfo, List<LocatedBlock>> datanodeBlocks = 1322 new LinkedHashMap<DatanodeInfo, List<LocatedBlock>>(); 1323 for (LocatedBlock b : blocks) { 1324 for (DatanodeInfo info : b.getLocations()) { 1325 if (!datanodeBlocks.containsKey(info)) { 1326 datanodeBlocks.put(info, new ArrayList<LocatedBlock>()); 1327 } 1328 List<LocatedBlock> l = datanodeBlocks.get(info); 1329 l.add(b); 1330 } 1331 } 1332 1333 // Make RPCs to the datanodes to get volume locations for its replicas 1334 TraceScope scope = 1335 Trace.startSpan("getBlockStorageLocations", traceSampler); 1336 Map<DatanodeInfo, HdfsBlocksMetadata> metadatas; 1337 try { 1338 metadatas = BlockStorageLocationUtil. 1339 queryDatanodesForHdfsBlocksMetadata(conf, datanodeBlocks, 1340 getConf().getFileBlockStorageLocationsNumThreads, 1341 getConf().getFileBlockStorageLocationsTimeoutMs, 1342 getConf().connectToDnViaHostname); 1343 if (LOG.isTraceEnabled()) { 1344 LOG.trace("metadata returned: " 1345 + Joiner.on("\n").withKeyValueSeparator("=").join(metadatas)); 1346 } 1347 } finally { 1348 scope.close(); 1349 } 1350 1351 // Regroup the returned VolumeId metadata to again be grouped by 1352 // LocatedBlock rather than by datanode 1353 Map<LocatedBlock, List<VolumeId>> blockVolumeIds = BlockStorageLocationUtil 1354 .associateVolumeIdsWithBlocks(blocks, metadatas); 1355 1356 // Combine original BlockLocations with new VolumeId information 1357 BlockStorageLocation[] volumeBlockLocations = BlockStorageLocationUtil 1358 .convertToVolumeBlockLocations(blocks, blockVolumeIds); 1359 1360 return volumeBlockLocations; 1361 } 1362 1363 /** 1364 * Decrypts a EDEK by consulting the KeyProvider. 1365 */ 1366 private KeyVersion decryptEncryptedDataEncryptionKey(FileEncryptionInfo 1367 feInfo) throws IOException { 1368 TraceScope scope = Trace.startSpan("decryptEDEK", traceSampler); 1369 try { 1370 KeyProvider provider = getKeyProvider(); 1371 if (provider == null) { 1372 throw new IOException("No KeyProvider is configured, cannot access" + 1373 " an encrypted file"); 1374 } 1375 EncryptedKeyVersion ekv = EncryptedKeyVersion.createForDecryption( 1376 feInfo.getKeyName(), feInfo.getEzKeyVersionName(), feInfo.getIV(), 1377 feInfo.getEncryptedDataEncryptionKey()); 1378 try { 1379 KeyProviderCryptoExtension cryptoProvider = KeyProviderCryptoExtension 1380 .createKeyProviderCryptoExtension(provider); 1381 return cryptoProvider.decryptEncryptedKey(ekv); 1382 } catch (GeneralSecurityException e) { 1383 throw new IOException(e); 1384 } 1385 } finally { 1386 scope.close(); 1387 } 1388 } 1389 1390 /** 1391 * Obtain the crypto protocol version from the provided FileEncryptionInfo, 1392 * checking to see if this version is supported by. 1393 * 1394 * @param feInfo FileEncryptionInfo 1395 * @return CryptoProtocolVersion from the feInfo 1396 * @throws IOException if the protocol version is unsupported. 1397 */ 1398 private static CryptoProtocolVersion getCryptoProtocolVersion 1399 (FileEncryptionInfo feInfo) throws IOException { 1400 final CryptoProtocolVersion version = feInfo.getCryptoProtocolVersion(); 1401 if (!CryptoProtocolVersion.supports(version)) { 1402 throw new IOException("Client does not support specified " + 1403 "CryptoProtocolVersion " + version.getDescription() + " version " + 1404 "number" + version.getVersion()); 1405 } 1406 return version; 1407 } 1408 1409 /** 1410 * Obtain a CryptoCodec based on the CipherSuite set in a FileEncryptionInfo 1411 * and the available CryptoCodecs configured in the Configuration. 1412 * 1413 * @param conf Configuration 1414 * @param feInfo FileEncryptionInfo 1415 * @return CryptoCodec 1416 * @throws IOException if no suitable CryptoCodec for the CipherSuite is 1417 * available. 1418 */ 1419 private static CryptoCodec getCryptoCodec(Configuration conf, 1420 FileEncryptionInfo feInfo) throws IOException { 1421 final CipherSuite suite = feInfo.getCipherSuite(); 1422 if (suite.equals(CipherSuite.UNKNOWN)) { 1423 throw new IOException("NameNode specified unknown CipherSuite with ID " 1424 + suite.getUnknownValue() + ", cannot instantiate CryptoCodec."); 1425 } 1426 final CryptoCodec codec = CryptoCodec.getInstance(conf, suite); 1427 if (codec == null) { 1428 throw new UnknownCipherSuiteException( 1429 "No configuration found for the cipher suite " 1430 + suite.getConfigSuffix() + " prefixed with " 1431 + HADOOP_SECURITY_CRYPTO_CODEC_CLASSES_KEY_PREFIX 1432 + ". Please see the example configuration " 1433 + "hadoop.security.crypto.codec.classes.EXAMPLECIPHERSUITE " 1434 + "at core-default.xml for details."); 1435 } 1436 return codec; 1437 } 1438 1439 /** 1440 * Wraps the stream in a CryptoInputStream if the underlying file is 1441 * encrypted. 1442 */ 1443 public HdfsDataInputStream createWrappedInputStream(DFSInputStream dfsis) 1444 throws IOException { 1445 final FileEncryptionInfo feInfo = dfsis.getFileEncryptionInfo(); 1446 if (feInfo != null) { 1447 // File is encrypted, wrap the stream in a crypto stream. 1448 // Currently only one version, so no special logic based on the version # 1449 getCryptoProtocolVersion(feInfo); 1450 final CryptoCodec codec = getCryptoCodec(conf, feInfo); 1451 final KeyVersion decrypted = decryptEncryptedDataEncryptionKey(feInfo); 1452 final CryptoInputStream cryptoIn = 1453 new CryptoInputStream(dfsis, codec, decrypted.getMaterial(), 1454 feInfo.getIV()); 1455 return new HdfsDataInputStream(cryptoIn); 1456 } else { 1457 // No FileEncryptionInfo so no encryption. 1458 return new HdfsDataInputStream(dfsis); 1459 } 1460 } 1461 1462 /** 1463 * Wraps the stream in a CryptoOutputStream if the underlying file is 1464 * encrypted. 1465 */ 1466 public HdfsDataOutputStream createWrappedOutputStream(DFSOutputStream dfsos, 1467 FileSystem.Statistics statistics) throws IOException { 1468 return createWrappedOutputStream(dfsos, statistics, 0); 1469 } 1470 1471 /** 1472 * Wraps the stream in a CryptoOutputStream if the underlying file is 1473 * encrypted. 1474 */ 1475 public HdfsDataOutputStream createWrappedOutputStream(DFSOutputStream dfsos, 1476 FileSystem.Statistics statistics, long startPos) throws IOException { 1477 final FileEncryptionInfo feInfo = dfsos.getFileEncryptionInfo(); 1478 if (feInfo != null) { 1479 // File is encrypted, wrap the stream in a crypto stream. 1480 // Currently only one version, so no special logic based on the version # 1481 getCryptoProtocolVersion(feInfo); 1482 final CryptoCodec codec = getCryptoCodec(conf, feInfo); 1483 KeyVersion decrypted = decryptEncryptedDataEncryptionKey(feInfo); 1484 final CryptoOutputStream cryptoOut = 1485 new CryptoOutputStream(dfsos, codec, 1486 decrypted.getMaterial(), feInfo.getIV(), startPos); 1487 return new HdfsDataOutputStream(cryptoOut, statistics, startPos); 1488 } else { 1489 // No FileEncryptionInfo present so no encryption. 1490 return new HdfsDataOutputStream(dfsos, statistics, startPos); 1491 } 1492 } 1493 1494 public DFSInputStream open(String src) 1495 throws IOException, UnresolvedLinkException { 1496 return open(src, dfsClientConf.ioBufferSize, true, null); 1497 } 1498 1499 /** 1500 * Create an input stream that obtains a nodelist from the 1501 * namenode, and then reads from all the right places. Creates 1502 * inner subclass of InputStream that does the right out-of-band 1503 * work. 1504 * @deprecated Use {@link #open(String, int, boolean)} instead. 1505 */ 1506 @Deprecated 1507 public DFSInputStream open(String src, int buffersize, boolean verifyChecksum, 1508 FileSystem.Statistics stats) 1509 throws IOException, UnresolvedLinkException { 1510 return open(src, buffersize, verifyChecksum); 1511 } 1512 1513 1514 /** 1515 * Create an input stream that obtains a nodelist from the 1516 * namenode, and then reads from all the right places. Creates 1517 * inner subclass of InputStream that does the right out-of-band 1518 * work. 1519 */ 1520 public DFSInputStream open(String src, int buffersize, boolean verifyChecksum) 1521 throws IOException, UnresolvedLinkException { 1522 checkOpen(); 1523 // Get block info from namenode 1524 TraceScope scope = getPathTraceScope("newDFSInputStream", src); 1525 try { 1526 return new DFSInputStream(this, src, verifyChecksum); 1527 } finally { 1528 scope.close(); 1529 } 1530 } 1531 1532 /** 1533 * Get the namenode associated with this DFSClient object 1534 * @return the namenode associated with this DFSClient object 1535 */ 1536 public ClientProtocol getNamenode() { 1537 return namenode; 1538 } 1539 1540 /** 1541 * Call {@link #create(String, boolean, short, long, Progressable)} with 1542 * default <code>replication</code> and <code>blockSize<code> and null <code> 1543 * progress</code>. 1544 */ 1545 public OutputStream create(String src, boolean overwrite) 1546 throws IOException { 1547 return create(src, overwrite, dfsClientConf.defaultReplication, 1548 dfsClientConf.defaultBlockSize, null); 1549 } 1550 1551 /** 1552 * Call {@link #create(String, boolean, short, long, Progressable)} with 1553 * default <code>replication</code> and <code>blockSize<code>. 1554 */ 1555 public OutputStream create(String src, 1556 boolean overwrite, 1557 Progressable progress) throws IOException { 1558 return create(src, overwrite, dfsClientConf.defaultReplication, 1559 dfsClientConf.defaultBlockSize, progress); 1560 } 1561 1562 /** 1563 * Call {@link #create(String, boolean, short, long, Progressable)} with 1564 * null <code>progress</code>. 1565 */ 1566 public OutputStream create(String src, 1567 boolean overwrite, 1568 short replication, 1569 long blockSize) throws IOException { 1570 return create(src, overwrite, replication, blockSize, null); 1571 } 1572 1573 /** 1574 * Call {@link #create(String, boolean, short, long, Progressable, int)} 1575 * with default bufferSize. 1576 */ 1577 public OutputStream create(String src, boolean overwrite, short replication, 1578 long blockSize, Progressable progress) throws IOException { 1579 return create(src, overwrite, replication, blockSize, progress, 1580 dfsClientConf.ioBufferSize); 1581 } 1582 1583 /** 1584 * Call {@link #create(String, FsPermission, EnumSet, short, long, 1585 * Progressable, int, ChecksumOpt)} with default <code>permission</code> 1586 * {@link FsPermission#getFileDefault()}. 1587 * 1588 * @param src File name 1589 * @param overwrite overwrite an existing file if true 1590 * @param replication replication factor for the file 1591 * @param blockSize maximum block size 1592 * @param progress interface for reporting client progress 1593 * @param buffersize underlying buffersize 1594 * 1595 * @return output stream 1596 */ 1597 public OutputStream create(String src, 1598 boolean overwrite, 1599 short replication, 1600 long blockSize, 1601 Progressable progress, 1602 int buffersize) 1603 throws IOException { 1604 return create(src, FsPermission.getFileDefault(), 1605 overwrite ? EnumSet.of(CreateFlag.CREATE, CreateFlag.OVERWRITE) 1606 : EnumSet.of(CreateFlag.CREATE), replication, blockSize, progress, 1607 buffersize, null); 1608 } 1609 1610 /** 1611 * Call {@link #create(String, FsPermission, EnumSet, boolean, short, 1612 * long, Progressable, int, ChecksumOpt)} with <code>createParent</code> 1613 * set to true. 1614 */ 1615 public DFSOutputStream create(String src, 1616 FsPermission permission, 1617 EnumSet<CreateFlag> flag, 1618 short replication, 1619 long blockSize, 1620 Progressable progress, 1621 int buffersize, 1622 ChecksumOpt checksumOpt) 1623 throws IOException { 1624 return create(src, permission, flag, true, 1625 replication, blockSize, progress, buffersize, checksumOpt, null); 1626 } 1627 1628 /** 1629 * Create a new dfs file with the specified block replication 1630 * with write-progress reporting and return an output stream for writing 1631 * into the file. 1632 * 1633 * @param src File name 1634 * @param permission The permission of the directory being created. 1635 * If null, use default permission {@link FsPermission#getFileDefault()} 1636 * @param flag indicates create a new file or create/overwrite an 1637 * existing file or append to an existing file 1638 * @param createParent create missing parent directory if true 1639 * @param replication block replication 1640 * @param blockSize maximum block size 1641 * @param progress interface for reporting client progress 1642 * @param buffersize underlying buffer size 1643 * @param checksumOpt checksum options 1644 * 1645 * @return output stream 1646 * 1647 * @see ClientProtocol#create for detailed description of exceptions thrown 1648 */ 1649 public DFSOutputStream create(String src, 1650 FsPermission permission, 1651 EnumSet<CreateFlag> flag, 1652 boolean createParent, 1653 short replication, 1654 long blockSize, 1655 Progressable progress, 1656 int buffersize, 1657 ChecksumOpt checksumOpt) throws IOException { 1658 return create(src, permission, flag, createParent, replication, blockSize, 1659 progress, buffersize, checksumOpt, null); 1660 } 1661 1662 /** 1663 * Same as {@link #create(String, FsPermission, EnumSet, boolean, short, long, 1664 * Progressable, int, ChecksumOpt)} with the addition of favoredNodes that is 1665 * a hint to where the namenode should place the file blocks. 1666 * The favored nodes hint is not persisted in HDFS. Hence it may be honored 1667 * at the creation time only. HDFS could move the blocks during balancing or 1668 * replication, to move the blocks from favored nodes. A value of null means 1669 * no favored nodes for this create 1670 */ 1671 public DFSOutputStream create(String src, 1672 FsPermission permission, 1673 EnumSet<CreateFlag> flag, 1674 boolean createParent, 1675 short replication, 1676 long blockSize, 1677 Progressable progress, 1678 int buffersize, 1679 ChecksumOpt checksumOpt, 1680 InetSocketAddress[] favoredNodes) throws IOException { 1681 checkOpen(); 1682 if (permission == null) { 1683 permission = FsPermission.getFileDefault(); 1684 } 1685 FsPermission masked = permission.applyUMask(dfsClientConf.uMask); 1686 if(LOG.isDebugEnabled()) { 1687 LOG.debug(src + ": masked=" + masked); 1688 } 1689 final DFSOutputStream result = DFSOutputStream.newStreamForCreate(this, 1690 src, masked, flag, createParent, replication, blockSize, progress, 1691 buffersize, dfsClientConf.createChecksum(checksumOpt), 1692 getFavoredNodesStr(favoredNodes)); 1693 beginFileLease(result.getFileId(), result); 1694 return result; 1695 } 1696 1697 private String[] getFavoredNodesStr(InetSocketAddress[] favoredNodes) { 1698 String[] favoredNodeStrs = null; 1699 if (favoredNodes != null) { 1700 favoredNodeStrs = new String[favoredNodes.length]; 1701 for (int i = 0; i < favoredNodes.length; i++) { 1702 favoredNodeStrs[i] = 1703 favoredNodes[i].getHostName() + ":" 1704 + favoredNodes[i].getPort(); 1705 } 1706 } 1707 return favoredNodeStrs; 1708 } 1709 1710 /** 1711 * Append to an existing file if {@link CreateFlag#APPEND} is present 1712 */ 1713 private DFSOutputStream primitiveAppend(String src, EnumSet<CreateFlag> flag, 1714 int buffersize, Progressable progress) throws IOException { 1715 if (flag.contains(CreateFlag.APPEND)) { 1716 HdfsFileStatus stat = getFileInfo(src); 1717 if (stat == null) { // No file to append to 1718 // New file needs to be created if create option is present 1719 if (!flag.contains(CreateFlag.CREATE)) { 1720 throw new FileNotFoundException("failed to append to non-existent file " 1721 + src + " on client " + clientName); 1722 } 1723 return null; 1724 } 1725 return callAppend(src, buffersize, flag, progress, null); 1726 } 1727 return null; 1728 } 1729 1730 /** 1731 * Same as {{@link #create(String, FsPermission, EnumSet, short, long, 1732 * Progressable, int, ChecksumOpt)} except that the permission 1733 * is absolute (ie has already been masked with umask. 1734 */ 1735 public DFSOutputStream primitiveCreate(String src, 1736 FsPermission absPermission, 1737 EnumSet<CreateFlag> flag, 1738 boolean createParent, 1739 short replication, 1740 long blockSize, 1741 Progressable progress, 1742 int buffersize, 1743 ChecksumOpt checksumOpt) 1744 throws IOException, UnresolvedLinkException { 1745 checkOpen(); 1746 CreateFlag.validate(flag); 1747 DFSOutputStream result = primitiveAppend(src, flag, buffersize, progress); 1748 if (result == null) { 1749 DataChecksum checksum = dfsClientConf.createChecksum(checksumOpt); 1750 result = DFSOutputStream.newStreamForCreate(this, src, absPermission, 1751 flag, createParent, replication, blockSize, progress, buffersize, 1752 checksum, null); 1753 } 1754 beginFileLease(result.getFileId(), result); 1755 return result; 1756 } 1757 1758 /** 1759 * Creates a symbolic link. 1760 * 1761 * @see ClientProtocol#createSymlink(String, String,FsPermission, boolean) 1762 */ 1763 public void createSymlink(String target, String link, boolean createParent) 1764 throws IOException { 1765 TraceScope scope = getPathTraceScope("createSymlink", target); 1766 try { 1767 FsPermission dirPerm = 1768 FsPermission.getDefault().applyUMask(dfsClientConf.uMask); 1769 namenode.createSymlink(target, link, dirPerm, createParent); 1770 } catch (RemoteException re) { 1771 throw re.unwrapRemoteException(AccessControlException.class, 1772 FileAlreadyExistsException.class, 1773 FileNotFoundException.class, 1774 ParentNotDirectoryException.class, 1775 NSQuotaExceededException.class, 1776 DSQuotaExceededException.class, 1777 UnresolvedPathException.class, 1778 SnapshotAccessControlException.class); 1779 } finally { 1780 scope.close(); 1781 } 1782 } 1783 1784 /** 1785 * Resolve the *first* symlink, if any, in the path. 1786 * 1787 * @see ClientProtocol#getLinkTarget(String) 1788 */ 1789 public String getLinkTarget(String path) throws IOException { 1790 checkOpen(); 1791 TraceScope scope = getPathTraceScope("getLinkTarget", path); 1792 try { 1793 return namenode.getLinkTarget(path); 1794 } catch (RemoteException re) { 1795 throw re.unwrapRemoteException(AccessControlException.class, 1796 FileNotFoundException.class); 1797 } finally { 1798 scope.close(); 1799 } 1800 } 1801 1802 /** Method to get stream returned by append call */ 1803 private DFSOutputStream callAppend(String src, int buffersize, 1804 EnumSet<CreateFlag> flag, Progressable progress, String[] favoredNodes) 1805 throws IOException { 1806 CreateFlag.validateForAppend(flag); 1807 try { 1808 LastBlockWithStatus blkWithStatus = namenode.append(src, clientName, 1809 new EnumSetWritable<>(flag, CreateFlag.class)); 1810 HdfsFileStatus status = blkWithStatus.getFileStatus(); 1811 if (status == null) { 1812 DFSClient.LOG.debug("NameNode is on an older version, request file " + 1813 "info with additional RPC call for file: " + src); 1814 status = getFileInfo(src); 1815 } 1816 return DFSOutputStream.newStreamForAppend(this, src, flag, buffersize, 1817 progress, blkWithStatus.getLastBlock(), 1818 status, dfsClientConf.createChecksum(), 1819 favoredNodes); 1820 } catch(RemoteException re) { 1821 throw re.unwrapRemoteException(AccessControlException.class, 1822 FileNotFoundException.class, 1823 SafeModeException.class, 1824 DSQuotaExceededException.class, 1825 UnsupportedOperationException.class, 1826 UnresolvedPathException.class, 1827 SnapshotAccessControlException.class); 1828 } 1829 } 1830 1831 /** 1832 * Append to an existing HDFS file. 1833 * 1834 * @param src file name 1835 * @param buffersize buffer size 1836 * @param flag indicates whether to append data to a new block instead of 1837 * the last block 1838 * @param progress for reporting write-progress; null is acceptable. 1839 * @param statistics file system statistics; null is acceptable. 1840 * @return an output stream for writing into the file 1841 * 1842 * @see ClientProtocol#append(String, String, EnumSetWritable) 1843 */ 1844 public HdfsDataOutputStream append(final String src, final int buffersize, 1845 EnumSet<CreateFlag> flag, final Progressable progress, 1846 final FileSystem.Statistics statistics) throws IOException { 1847 final DFSOutputStream out = append(src, buffersize, flag, null, progress); 1848 return createWrappedOutputStream(out, statistics, out.getInitialLen()); 1849 } 1850 1851 /** 1852 * Append to an existing HDFS file. 1853 * 1854 * @param src file name 1855 * @param buffersize buffer size 1856 * @param flag indicates whether to append data to a new block instead of the 1857 * last block 1858 * @param progress for reporting write-progress; null is acceptable. 1859 * @param statistics file system statistics; null is acceptable. 1860 * @param favoredNodes FavoredNodes for new blocks 1861 * @return an output stream for writing into the file 1862 * @see ClientProtocol#append(String, String, EnumSetWritable) 1863 */ 1864 public HdfsDataOutputStream append(final String src, final int buffersize, 1865 EnumSet<CreateFlag> flag, final Progressable progress, 1866 final FileSystem.Statistics statistics, 1867 final InetSocketAddress[] favoredNodes) throws IOException { 1868 final DFSOutputStream out = append(src, buffersize, flag, 1869 getFavoredNodesStr(favoredNodes), progress); 1870 return createWrappedOutputStream(out, statistics, out.getInitialLen()); 1871 } 1872 1873 private DFSOutputStream append(String src, int buffersize, 1874 EnumSet<CreateFlag> flag, String[] favoredNodes, Progressable progress) 1875 throws IOException { 1876 checkOpen(); 1877 final DFSOutputStream result = callAppend(src, buffersize, flag, progress, 1878 favoredNodes); 1879 beginFileLease(result.getFileId(), result); 1880 return result; 1881 } 1882 1883 /** 1884 * Set replication for an existing file. 1885 * @param src file name 1886 * @param replication replication to set the file to 1887 * 1888 * @see ClientProtocol#setReplication(String, short) 1889 */ 1890 public boolean setReplication(String src, short replication) 1891 throws IOException { 1892 TraceScope scope = getPathTraceScope("setReplication", src); 1893 try { 1894 return namenode.setReplication(src, replication); 1895 } catch(RemoteException re) { 1896 throw re.unwrapRemoteException(AccessControlException.class, 1897 FileNotFoundException.class, 1898 SafeModeException.class, 1899 DSQuotaExceededException.class, 1900 UnresolvedPathException.class, 1901 SnapshotAccessControlException.class); 1902 } finally { 1903 scope.close(); 1904 } 1905 } 1906 1907 /** 1908 * Set storage policy for an existing file/directory 1909 * @param src file/directory name 1910 * @param policyName name of the storage policy 1911 */ 1912 public void setStoragePolicy(String src, String policyName) 1913 throws IOException { 1914 TraceScope scope = getPathTraceScope("setStoragePolicy", src); 1915 try { 1916 namenode.setStoragePolicy(src, policyName); 1917 } catch (RemoteException e) { 1918 throw e.unwrapRemoteException(AccessControlException.class, 1919 FileNotFoundException.class, 1920 SafeModeException.class, 1921 NSQuotaExceededException.class, 1922 UnresolvedPathException.class, 1923 SnapshotAccessControlException.class); 1924 } finally { 1925 scope.close(); 1926 } 1927 } 1928 1929 /** 1930 * @return All the existing storage policies 1931 */ 1932 public BlockStoragePolicy[] getStoragePolicies() throws IOException { 1933 TraceScope scope = Trace.startSpan("getStoragePolicies", traceSampler); 1934 try { 1935 return namenode.getStoragePolicies(); 1936 } finally { 1937 scope.close(); 1938 } 1939 } 1940 1941 /** 1942 * Rename file or directory. 1943 * @see ClientProtocol#rename(String, String) 1944 * @deprecated Use {@link #rename(String, String, Options.Rename...)} instead. 1945 */ 1946 @Deprecated 1947 public boolean rename(String src, String dst) throws IOException { 1948 checkOpen(); 1949 TraceScope scope = getSrcDstTraceScope("rename", src, dst); 1950 try { 1951 return namenode.rename(src, dst); 1952 } catch(RemoteException re) { 1953 throw re.unwrapRemoteException(AccessControlException.class, 1954 NSQuotaExceededException.class, 1955 DSQuotaExceededException.class, 1956 UnresolvedPathException.class, 1957 SnapshotAccessControlException.class); 1958 } finally { 1959 scope.close(); 1960 } 1961 } 1962 1963 /** 1964 * Move blocks from src to trg and delete src 1965 * See {@link ClientProtocol#concat}. 1966 */ 1967 public void concat(String trg, String [] srcs) throws IOException { 1968 checkOpen(); 1969 TraceScope scope = Trace.startSpan("concat", traceSampler); 1970 try { 1971 namenode.concat(trg, srcs); 1972 } catch(RemoteException re) { 1973 throw re.unwrapRemoteException(AccessControlException.class, 1974 UnresolvedPathException.class, 1975 SnapshotAccessControlException.class); 1976 } finally { 1977 scope.close(); 1978 } 1979 } 1980 /** 1981 * Rename file or directory. 1982 * @see ClientProtocol#rename2(String, String, Options.Rename...) 1983 */ 1984 public void rename(String src, String dst, Options.Rename... options) 1985 throws IOException { 1986 checkOpen(); 1987 TraceScope scope = getSrcDstTraceScope("rename2", src, dst); 1988 try { 1989 namenode.rename2(src, dst, options); 1990 } catch(RemoteException re) { 1991 throw re.unwrapRemoteException(AccessControlException.class, 1992 DSQuotaExceededException.class, 1993 FileAlreadyExistsException.class, 1994 FileNotFoundException.class, 1995 ParentNotDirectoryException.class, 1996 SafeModeException.class, 1997 NSQuotaExceededException.class, 1998 UnresolvedPathException.class, 1999 SnapshotAccessControlException.class); 2000 } finally { 2001 scope.close(); 2002 } 2003 } 2004 2005 /** 2006 * Truncate a file to an indicated size 2007 * See {@link ClientProtocol#truncate}. 2008 */ 2009 public boolean truncate(String src, long newLength) throws IOException { 2010 checkOpen(); 2011 if (newLength < 0) { 2012 throw new HadoopIllegalArgumentException( 2013 "Cannot truncate to a negative file size: " + newLength + "."); 2014 } 2015 try { 2016 return namenode.truncate(src, newLength, clientName); 2017 } catch (RemoteException re) { 2018 throw re.unwrapRemoteException(AccessControlException.class, 2019 UnresolvedPathException.class); 2020 } 2021 } 2022 2023 /** 2024 * Delete file or directory. 2025 * See {@link ClientProtocol#delete(String, boolean)}. 2026 */ 2027 @Deprecated 2028 public boolean delete(String src) throws IOException { 2029 checkOpen(); 2030 return delete(src, true); 2031 } 2032 2033 /** 2034 * delete file or directory. 2035 * delete contents of the directory if non empty and recursive 2036 * set to true 2037 * 2038 * @see ClientProtocol#delete(String, boolean) 2039 */ 2040 public boolean delete(String src, boolean recursive) throws IOException { 2041 checkOpen(); 2042 TraceScope scope = getPathTraceScope("delete", src); 2043 try { 2044 return namenode.delete(src, recursive); 2045 } catch(RemoteException re) { 2046 throw re.unwrapRemoteException(AccessControlException.class, 2047 FileNotFoundException.class, 2048 SafeModeException.class, 2049 UnresolvedPathException.class, 2050 SnapshotAccessControlException.class); 2051 } finally { 2052 scope.close(); 2053 } 2054 } 2055 2056 /** Implemented using getFileInfo(src) 2057 */ 2058 public boolean exists(String src) throws IOException { 2059 checkOpen(); 2060 return getFileInfo(src) != null; 2061 } 2062 2063 /** 2064 * Get a partial listing of the indicated directory 2065 * No block locations need to be fetched 2066 */ 2067 public DirectoryListing listPaths(String src, byte[] startAfter) 2068 throws IOException { 2069 return listPaths(src, startAfter, false); 2070 } 2071 2072 /** 2073 * Get a partial listing of the indicated directory 2074 * 2075 * Recommend to use HdfsFileStatus.EMPTY_NAME as startAfter 2076 * if the application wants to fetch a listing starting from 2077 * the first entry in the directory 2078 * 2079 * @see ClientProtocol#getListing(String, byte[], boolean) 2080 */ 2081 public DirectoryListing listPaths(String src, byte[] startAfter, 2082 boolean needLocation) throws IOException { 2083 checkOpen(); 2084 TraceScope scope = getPathTraceScope("listPaths", src); 2085 try { 2086 return namenode.getListing(src, startAfter, needLocation); 2087 } catch(RemoteException re) { 2088 throw re.unwrapRemoteException(AccessControlException.class, 2089 FileNotFoundException.class, 2090 UnresolvedPathException.class); 2091 } finally { 2092 scope.close(); 2093 } 2094 } 2095 2096 /** 2097 * Get the file info for a specific file or directory. 2098 * @param src The string representation of the path to the file 2099 * @return object containing information regarding the file 2100 * or null if file not found 2101 * 2102 * @see ClientProtocol#getFileInfo(String) for description of exceptions 2103 */ 2104 public HdfsFileStatus getFileInfo(String src) throws IOException { 2105 checkOpen(); 2106 TraceScope scope = getPathTraceScope("getFileInfo", src); 2107 try { 2108 return namenode.getFileInfo(src); 2109 } catch(RemoteException re) { 2110 throw re.unwrapRemoteException(AccessControlException.class, 2111 FileNotFoundException.class, 2112 UnresolvedPathException.class); 2113 } finally { 2114 scope.close(); 2115 } 2116 } 2117 2118 /** 2119 * Close status of a file 2120 * @return true if file is already closed 2121 */ 2122 public boolean isFileClosed(String src) throws IOException{ 2123 checkOpen(); 2124 TraceScope scope = getPathTraceScope("isFileClosed", src); 2125 try { 2126 return namenode.isFileClosed(src); 2127 } catch(RemoteException re) { 2128 throw re.unwrapRemoteException(AccessControlException.class, 2129 FileNotFoundException.class, 2130 UnresolvedPathException.class); 2131 } finally { 2132 scope.close(); 2133 } 2134 } 2135 2136 /** 2137 * Get the file info for a specific file or directory. If src 2138 * refers to a symlink then the FileStatus of the link is returned. 2139 * @param src path to a file or directory. 2140 * 2141 * For description of exceptions thrown 2142 * @see ClientProtocol#getFileLinkInfo(String) 2143 */ 2144 public HdfsFileStatus getFileLinkInfo(String src) throws IOException { 2145 checkOpen(); 2146 TraceScope scope = getPathTraceScope("getFileLinkInfo", src); 2147 try { 2148 return namenode.getFileLinkInfo(src); 2149 } catch(RemoteException re) { 2150 throw re.unwrapRemoteException(AccessControlException.class, 2151 UnresolvedPathException.class); 2152 } finally { 2153 scope.close(); 2154 } 2155 } 2156 2157 @InterfaceAudience.Private 2158 public void clearDataEncryptionKey() { 2159 LOG.debug("Clearing encryption key"); 2160 synchronized (this) { 2161 encryptionKey = null; 2162 } 2163 } 2164 2165 /** 2166 * @return true if data sent between this client and DNs should be encrypted, 2167 * false otherwise. 2168 * @throws IOException in the event of error communicating with the NN 2169 */ 2170 boolean shouldEncryptData() throws IOException { 2171 FsServerDefaults d = getServerDefaults(); 2172 return d == null ? false : d.getEncryptDataTransfer(); 2173 } 2174 2175 @Override 2176 public DataEncryptionKey newDataEncryptionKey() throws IOException { 2177 if (shouldEncryptData()) { 2178 synchronized (this) { 2179 if (encryptionKey == null || 2180 encryptionKey.expiryDate < Time.now()) { 2181 LOG.debug("Getting new encryption token from NN"); 2182 encryptionKey = namenode.getDataEncryptionKey(); 2183 } 2184 return encryptionKey; 2185 } 2186 } else { 2187 return null; 2188 } 2189 } 2190 2191 /** 2192 * Get the checksum of the whole file of a range of the file. Note that the 2193 * range always starts from the beginning of the file. 2194 * @param src The file path 2195 * @param length the length of the range, i.e., the range is [0, length] 2196 * @return The checksum 2197 * @see DistributedFileSystem#getFileChecksum(Path) 2198 */ 2199 public MD5MD5CRC32FileChecksum getFileChecksum(String src, long length) 2200 throws IOException { 2201 checkOpen(); 2202 Preconditions.checkArgument(length >= 0); 2203 //get block locations for the file range 2204 LocatedBlocks blockLocations = callGetBlockLocations(namenode, src, 0, 2205 length); 2206 if (null == blockLocations) { 2207 throw new FileNotFoundException("File does not exist: " + src); 2208 } 2209 List<LocatedBlock> locatedblocks = blockLocations.getLocatedBlocks(); 2210 final DataOutputBuffer md5out = new DataOutputBuffer(); 2211 int bytesPerCRC = -1; 2212 DataChecksum.Type crcType = DataChecksum.Type.DEFAULT; 2213 long crcPerBlock = 0; 2214 boolean refetchBlocks = false; 2215 int lastRetriedIndex = -1; 2216 2217 // get block checksum for each block 2218 long remaining = length; 2219 if (src.contains(HdfsConstants.SEPARATOR_DOT_SNAPSHOT_DIR_SEPARATOR)) { 2220 remaining = Math.min(length, blockLocations.getFileLength()); 2221 } 2222 for(int i = 0; i < locatedblocks.size() && remaining > 0; i++) { 2223 if (refetchBlocks) { // refetch to get fresh tokens 2224 blockLocations = callGetBlockLocations(namenode, src, 0, length); 2225 if (null == blockLocations) { 2226 throw new FileNotFoundException("File does not exist: " + src); 2227 } 2228 locatedblocks = blockLocations.getLocatedBlocks(); 2229 refetchBlocks = false; 2230 } 2231 LocatedBlock lb = locatedblocks.get(i); 2232 final ExtendedBlock block = lb.getBlock(); 2233 if (remaining < block.getNumBytes()) { 2234 block.setNumBytes(remaining); 2235 } 2236 remaining -= block.getNumBytes(); 2237 final DatanodeInfo[] datanodes = lb.getLocations(); 2238 2239 //try each datanode location of the block 2240 final int timeout = 3000 * datanodes.length + dfsClientConf.socketTimeout; 2241 boolean done = false; 2242 for(int j = 0; !done && j < datanodes.length; j++) { 2243 DataOutputStream out = null; 2244 DataInputStream in = null; 2245 2246 try { 2247 //connect to a datanode 2248 IOStreamPair pair = connectToDN(datanodes[j], timeout, lb); 2249 out = new DataOutputStream(new BufferedOutputStream(pair.out, 2250 HdfsConstants.SMALL_BUFFER_SIZE)); 2251 in = new DataInputStream(pair.in); 2252 2253 if (LOG.isDebugEnabled()) { 2254 LOG.debug("write to " + datanodes[j] + ": " 2255 + Op.BLOCK_CHECKSUM + ", block=" + block); 2256 } 2257 // get block MD5 2258 new Sender(out).blockChecksum(block, lb.getBlockToken()); 2259 2260 final BlockOpResponseProto reply = 2261 BlockOpResponseProto.parseFrom(PBHelper.vintPrefixed(in)); 2262 2263 String logInfo = "for block " + block + " from datanode " + datanodes[j]; 2264 DataTransferProtoUtil.checkBlockOpStatus(reply, logInfo); 2265 2266 OpBlockChecksumResponseProto checksumData = 2267 reply.getChecksumResponse(); 2268 2269 //read byte-per-checksum 2270 final int bpc = checksumData.getBytesPerCrc(); 2271 if (i == 0) { //first block 2272 bytesPerCRC = bpc; 2273 } 2274 else if (bpc != bytesPerCRC) { 2275 throw new IOException("Byte-per-checksum not matched: bpc=" + bpc 2276 + " but bytesPerCRC=" + bytesPerCRC); 2277 } 2278 2279 //read crc-per-block 2280 final long cpb = checksumData.getCrcPerBlock(); 2281 if (locatedblocks.size() > 1 && i == 0) { 2282 crcPerBlock = cpb; 2283 } 2284 2285 //read md5 2286 final MD5Hash md5 = new MD5Hash( 2287 checksumData.getMd5().toByteArray()); 2288 md5.write(md5out); 2289 2290 // read crc-type 2291 final DataChecksum.Type ct; 2292 if (checksumData.hasCrcType()) { 2293 ct = PBHelper.convert(checksumData 2294 .getCrcType()); 2295 } else { 2296 LOG.debug("Retrieving checksum from an earlier-version DataNode: " + 2297 "inferring checksum by reading first byte"); 2298 ct = inferChecksumTypeByReading(lb, datanodes[j]); 2299 } 2300 2301 if (i == 0) { // first block 2302 crcType = ct; 2303 } else if (crcType != DataChecksum.Type.MIXED 2304 && crcType != ct) { 2305 // if crc types are mixed in a file 2306 crcType = DataChecksum.Type.MIXED; 2307 } 2308 2309 done = true; 2310 2311 if (LOG.isDebugEnabled()) { 2312 if (i == 0) { 2313 LOG.debug("set bytesPerCRC=" + bytesPerCRC 2314 + ", crcPerBlock=" + crcPerBlock); 2315 } 2316 LOG.debug("got reply from " + datanodes[j] + ": md5=" + md5); 2317 } 2318 } catch (InvalidBlockTokenException ibte) { 2319 if (i > lastRetriedIndex) { 2320 if (LOG.isDebugEnabled()) { 2321 LOG.debug("Got access token error in response to OP_BLOCK_CHECKSUM " 2322 + "for file " + src + " for block " + block 2323 + " from datanode " + datanodes[j] 2324 + ". Will retry the block once."); 2325 } 2326 lastRetriedIndex = i; 2327 done = true; // actually it's not done; but we'll retry 2328 i--; // repeat at i-th block 2329 refetchBlocks = true; 2330 break; 2331 } 2332 } catch (IOException ie) { 2333 LOG.warn("src=" + src + ", datanodes["+j+"]=" + datanodes[j], ie); 2334 } finally { 2335 IOUtils.closeStream(in); 2336 IOUtils.closeStream(out); 2337 } 2338 } 2339 2340 if (!done) { 2341 throw new IOException("Fail to get block MD5 for " + block); 2342 } 2343 } 2344 2345 //compute file MD5 2346 final MD5Hash fileMD5 = MD5Hash.digest(md5out.getData()); 2347 switch (crcType) { 2348 case CRC32: 2349 return new MD5MD5CRC32GzipFileChecksum(bytesPerCRC, 2350 crcPerBlock, fileMD5); 2351 case CRC32C: 2352 return new MD5MD5CRC32CastagnoliFileChecksum(bytesPerCRC, 2353 crcPerBlock, fileMD5); 2354 default: 2355 // If there is no block allocated for the file, 2356 // return one with the magic entry that matches what previous 2357 // hdfs versions return. 2358 if (locatedblocks.size() == 0) { 2359 return new MD5MD5CRC32GzipFileChecksum(0, 0, fileMD5); 2360 } 2361 2362 // we should never get here since the validity was checked 2363 // when getCrcType() was called above. 2364 return null; 2365 } 2366 } 2367 2368 /** 2369 * Connect to the given datanode's datantrasfer port, and return 2370 * the resulting IOStreamPair. This includes encryption wrapping, etc. 2371 */ 2372 private IOStreamPair connectToDN(DatanodeInfo dn, int timeout, 2373 LocatedBlock lb) throws IOException { 2374 boolean success = false; 2375 Socket sock = null; 2376 try { 2377 sock = socketFactory.createSocket(); 2378 String dnAddr = dn.getXferAddr(getConf().connectToDnViaHostname); 2379 if (LOG.isDebugEnabled()) { 2380 LOG.debug("Connecting to datanode " + dnAddr); 2381 } 2382 NetUtils.connect(sock, NetUtils.createSocketAddr(dnAddr), timeout); 2383 sock.setSoTimeout(timeout); 2384 2385 OutputStream unbufOut = NetUtils.getOutputStream(sock); 2386 InputStream unbufIn = NetUtils.getInputStream(sock); 2387 IOStreamPair ret = saslClient.newSocketSend(sock, unbufOut, unbufIn, this, 2388 lb.getBlockToken(), dn); 2389 success = true; 2390 return ret; 2391 } finally { 2392 if (!success) { 2393 IOUtils.closeSocket(sock); 2394 } 2395 } 2396 } 2397 2398 /** 2399 * Infer the checksum type for a replica by sending an OP_READ_BLOCK 2400 * for the first byte of that replica. This is used for compatibility 2401 * with older HDFS versions which did not include the checksum type in 2402 * OpBlockChecksumResponseProto. 2403 * 2404 * @param lb the located block 2405 * @param dn the connected datanode 2406 * @return the inferred checksum type 2407 * @throws IOException if an error occurs 2408 */ 2409 private Type inferChecksumTypeByReading(LocatedBlock lb, DatanodeInfo dn) 2410 throws IOException { 2411 IOStreamPair pair = connectToDN(dn, dfsClientConf.socketTimeout, lb); 2412 2413 try { 2414 DataOutputStream out = new DataOutputStream(new BufferedOutputStream(pair.out, 2415 HdfsConstants.SMALL_BUFFER_SIZE)); 2416 DataInputStream in = new DataInputStream(pair.in); 2417 2418 new Sender(out).readBlock(lb.getBlock(), lb.getBlockToken(), clientName, 2419 0, 1, true, CachingStrategy.newDefaultStrategy()); 2420 final BlockOpResponseProto reply = 2421 BlockOpResponseProto.parseFrom(PBHelper.vintPrefixed(in)); 2422 String logInfo = "trying to read " + lb.getBlock() + " from datanode " + dn; 2423 DataTransferProtoUtil.checkBlockOpStatus(reply, logInfo); 2424 2425 return PBHelper.convert(reply.getReadOpChecksumInfo().getChecksum().getType()); 2426 } finally { 2427 IOUtils.cleanup(null, pair.in, pair.out); 2428 } 2429 } 2430 2431 /** 2432 * Set permissions to a file or directory. 2433 * @param src path name. 2434 * @param permission permission to set to 2435 * 2436 * @see ClientProtocol#setPermission(String, FsPermission) 2437 */ 2438 public void setPermission(String src, FsPermission permission) 2439 throws IOException { 2440 checkOpen(); 2441 TraceScope scope = getPathTraceScope("setPermission", src); 2442 try { 2443 namenode.setPermission(src, permission); 2444 } catch(RemoteException re) { 2445 throw re.unwrapRemoteException(AccessControlException.class, 2446 FileNotFoundException.class, 2447 SafeModeException.class, 2448 UnresolvedPathException.class, 2449 SnapshotAccessControlException.class); 2450 } finally { 2451 scope.close(); 2452 } 2453 } 2454 2455 /** 2456 * Set file or directory owner. 2457 * @param src path name. 2458 * @param username user id. 2459 * @param groupname user group. 2460 * 2461 * @see ClientProtocol#setOwner(String, String, String) 2462 */ 2463 public void setOwner(String src, String username, String groupname) 2464 throws IOException { 2465 checkOpen(); 2466 TraceScope scope = getPathTraceScope("setOwner", src); 2467 try { 2468 namenode.setOwner(src, username, groupname); 2469 } catch(RemoteException re) { 2470 throw re.unwrapRemoteException(AccessControlException.class, 2471 FileNotFoundException.class, 2472 SafeModeException.class, 2473 UnresolvedPathException.class, 2474 SnapshotAccessControlException.class); 2475 } finally { 2476 scope.close(); 2477 } 2478 } 2479 2480 private long[] callGetStats() throws IOException { 2481 checkOpen(); 2482 TraceScope scope = Trace.startSpan("getStats", traceSampler); 2483 try { 2484 return namenode.getStats(); 2485 } finally { 2486 scope.close(); 2487 } 2488 } 2489 2490 /** 2491 * @see ClientProtocol#getStats() 2492 */ 2493 public FsStatus getDiskStatus() throws IOException { 2494 long rawNums[] = callGetStats(); 2495 return new FsStatus(rawNums[0], rawNums[1], rawNums[2]); 2496 } 2497 2498 /** 2499 * Returns count of blocks with no good replicas left. Normally should be 2500 * zero. 2501 * @throws IOException 2502 */ 2503 public long getMissingBlocksCount() throws IOException { 2504 return callGetStats()[ClientProtocol.GET_STATS_MISSING_BLOCKS_IDX]; 2505 } 2506 2507 /** 2508 * Returns count of blocks with replication factor 1 and have 2509 * lost the only replica. 2510 * @throws IOException 2511 */ 2512 public long getMissingReplOneBlocksCount() throws IOException { 2513 return callGetStats()[ClientProtocol. 2514 GET_STATS_MISSING_REPL_ONE_BLOCKS_IDX]; 2515 } 2516 2517 /** 2518 * Returns count of blocks with one of more replica missing. 2519 * @throws IOException 2520 */ 2521 public long getUnderReplicatedBlocksCount() throws IOException { 2522 return callGetStats()[ClientProtocol.GET_STATS_UNDER_REPLICATED_IDX]; 2523 } 2524 2525 /** 2526 * Returns count of blocks with at least one replica marked corrupt. 2527 * @throws IOException 2528 */ 2529 public long getCorruptBlocksCount() throws IOException { 2530 return callGetStats()[ClientProtocol.GET_STATS_CORRUPT_BLOCKS_IDX]; 2531 } 2532 2533 /** 2534 * @return a list in which each entry describes a corrupt file/block 2535 * @throws IOException 2536 */ 2537 public CorruptFileBlocks listCorruptFileBlocks(String path, 2538 String cookie) 2539 throws IOException { 2540 checkOpen(); 2541 TraceScope scope = getPathTraceScope("listCorruptFileBlocks", path); 2542 try { 2543 return namenode.listCorruptFileBlocks(path, cookie); 2544 } finally { 2545 scope.close(); 2546 } 2547 } 2548 2549 public DatanodeInfo[] datanodeReport(DatanodeReportType type) 2550 throws IOException { 2551 checkOpen(); 2552 TraceScope scope = Trace.startSpan("datanodeReport", traceSampler); 2553 try { 2554 return namenode.getDatanodeReport(type); 2555 } finally { 2556 scope.close(); 2557 } 2558 } 2559 2560 public DatanodeStorageReport[] getDatanodeStorageReport( 2561 DatanodeReportType type) throws IOException { 2562 checkOpen(); 2563 TraceScope scope = 2564 Trace.startSpan("datanodeStorageReport", traceSampler); 2565 try { 2566 return namenode.getDatanodeStorageReport(type); 2567 } finally { 2568 scope.close(); 2569 } 2570 } 2571 2572 /** 2573 * Enter, leave or get safe mode. 2574 * 2575 * @see ClientProtocol#setSafeMode(HdfsConstants.SafeModeAction,boolean) 2576 */ 2577 public boolean setSafeMode(SafeModeAction action) throws IOException { 2578 return setSafeMode(action, false); 2579 } 2580 2581 /** 2582 * Enter, leave or get safe mode. 2583 * 2584 * @param action 2585 * One of SafeModeAction.GET, SafeModeAction.ENTER and 2586 * SafeModeActiob.LEAVE 2587 * @param isChecked 2588 * If true, then check only active namenode's safemode status, else 2589 * check first namenode's status. 2590 * @see ClientProtocol#setSafeMode(HdfsConstants.SafeModeAction, boolean) 2591 */ 2592 public boolean setSafeMode(SafeModeAction action, boolean isChecked) throws IOException{ 2593 TraceScope scope = 2594 Trace.startSpan("setSafeMode", traceSampler); 2595 try { 2596 return namenode.setSafeMode(action, isChecked); 2597 } finally { 2598 scope.close(); 2599 } 2600 } 2601 2602 /** 2603 * Create one snapshot. 2604 * 2605 * @param snapshotRoot The directory where the snapshot is to be taken 2606 * @param snapshotName Name of the snapshot 2607 * @return the snapshot path. 2608 * @see ClientProtocol#createSnapshot(String, String) 2609 */ 2610 public String createSnapshot(String snapshotRoot, String snapshotName) 2611 throws IOException { 2612 checkOpen(); 2613 TraceScope scope = Trace.startSpan("createSnapshot", traceSampler); 2614 try { 2615 return namenode.createSnapshot(snapshotRoot, snapshotName); 2616 } catch(RemoteException re) { 2617 throw re.unwrapRemoteException(); 2618 } finally { 2619 scope.close(); 2620 } 2621 } 2622 2623 /** 2624 * Delete a snapshot of a snapshottable directory. 2625 * 2626 * @param snapshotRoot The snapshottable directory that the 2627 * to-be-deleted snapshot belongs to 2628 * @param snapshotName The name of the to-be-deleted snapshot 2629 * @throws IOException 2630 * @see ClientProtocol#deleteSnapshot(String, String) 2631 */ 2632 public void deleteSnapshot(String snapshotRoot, String snapshotName) 2633 throws IOException { 2634 checkOpen(); 2635 TraceScope scope = Trace.startSpan("deleteSnapshot", traceSampler); 2636 try { 2637 namenode.deleteSnapshot(snapshotRoot, snapshotName); 2638 } catch(RemoteException re) { 2639 throw re.unwrapRemoteException(); 2640 } finally { 2641 scope.close(); 2642 } 2643 } 2644 2645 /** 2646 * Rename a snapshot. 2647 * @param snapshotDir The directory path where the snapshot was taken 2648 * @param snapshotOldName Old name of the snapshot 2649 * @param snapshotNewName New name of the snapshot 2650 * @throws IOException 2651 * @see ClientProtocol#renameSnapshot(String, String, String) 2652 */ 2653 public void renameSnapshot(String snapshotDir, String snapshotOldName, 2654 String snapshotNewName) throws IOException { 2655 checkOpen(); 2656 TraceScope scope = Trace.startSpan("renameSnapshot", traceSampler); 2657 try { 2658 namenode.renameSnapshot(snapshotDir, snapshotOldName, snapshotNewName); 2659 } catch(RemoteException re) { 2660 throw re.unwrapRemoteException(); 2661 } finally { 2662 scope.close(); 2663 } 2664 } 2665 2666 /** 2667 * Get all the current snapshottable directories. 2668 * @return All the current snapshottable directories 2669 * @throws IOException 2670 * @see ClientProtocol#getSnapshottableDirListing() 2671 */ 2672 public SnapshottableDirectoryStatus[] getSnapshottableDirListing() 2673 throws IOException { 2674 checkOpen(); 2675 TraceScope scope = Trace.startSpan("getSnapshottableDirListing", 2676 traceSampler); 2677 try { 2678 return namenode.getSnapshottableDirListing(); 2679 } catch(RemoteException re) { 2680 throw re.unwrapRemoteException(); 2681 } finally { 2682 scope.close(); 2683 } 2684 } 2685 2686 /** 2687 * Allow snapshot on a directory. 2688 * 2689 * @see ClientProtocol#allowSnapshot(String snapshotRoot) 2690 */ 2691 public void allowSnapshot(String snapshotRoot) throws IOException { 2692 checkOpen(); 2693 TraceScope scope = Trace.startSpan("allowSnapshot", traceSampler); 2694 try { 2695 namenode.allowSnapshot(snapshotRoot); 2696 } catch (RemoteException re) { 2697 throw re.unwrapRemoteException(); 2698 } finally { 2699 scope.close(); 2700 } 2701 } 2702 2703 /** 2704 * Disallow snapshot on a directory. 2705 * 2706 * @see ClientProtocol#disallowSnapshot(String snapshotRoot) 2707 */ 2708 public void disallowSnapshot(String snapshotRoot) throws IOException { 2709 checkOpen(); 2710 TraceScope scope = Trace.startSpan("disallowSnapshot", traceSampler); 2711 try { 2712 namenode.disallowSnapshot(snapshotRoot); 2713 } catch (RemoteException re) { 2714 throw re.unwrapRemoteException(); 2715 } finally { 2716 scope.close(); 2717 } 2718 } 2719 2720 /** 2721 * Get the difference between two snapshots, or between a snapshot and the 2722 * current tree of a directory. 2723 * @see ClientProtocol#getSnapshotDiffReport(String, String, String) 2724 */ 2725 public SnapshotDiffReport getSnapshotDiffReport(String snapshotDir, 2726 String fromSnapshot, String toSnapshot) throws IOException { 2727 checkOpen(); 2728 TraceScope scope = Trace.startSpan("getSnapshotDiffReport", traceSampler); 2729 try { 2730 return namenode.getSnapshotDiffReport(snapshotDir, 2731 fromSnapshot, toSnapshot); 2732 } catch(RemoteException re) { 2733 throw re.unwrapRemoteException(); 2734 } finally { 2735 scope.close(); 2736 } 2737 } 2738 2739 public long addCacheDirective( 2740 CacheDirectiveInfo info, EnumSet<CacheFlag> flags) throws IOException { 2741 checkOpen(); 2742 TraceScope scope = Trace.startSpan("addCacheDirective", traceSampler); 2743 try { 2744 return namenode.addCacheDirective(info, flags); 2745 } catch (RemoteException re) { 2746 throw re.unwrapRemoteException(); 2747 } finally { 2748 scope.close(); 2749 } 2750 } 2751 2752 public void modifyCacheDirective( 2753 CacheDirectiveInfo info, EnumSet<CacheFlag> flags) throws IOException { 2754 checkOpen(); 2755 TraceScope scope = Trace.startSpan("modifyCacheDirective", traceSampler); 2756 try { 2757 namenode.modifyCacheDirective(info, flags); 2758 } catch (RemoteException re) { 2759 throw re.unwrapRemoteException(); 2760 } finally { 2761 scope.close(); 2762 } 2763 } 2764 2765 public void removeCacheDirective(long id) 2766 throws IOException { 2767 checkOpen(); 2768 TraceScope scope = Trace.startSpan("removeCacheDirective", traceSampler); 2769 try { 2770 namenode.removeCacheDirective(id); 2771 } catch (RemoteException re) { 2772 throw re.unwrapRemoteException(); 2773 } finally { 2774 scope.close(); 2775 } 2776 } 2777 2778 public RemoteIterator<CacheDirectiveEntry> listCacheDirectives( 2779 CacheDirectiveInfo filter) throws IOException { 2780 return new CacheDirectiveIterator(namenode, filter, traceSampler); 2781 } 2782 2783 public void addCachePool(CachePoolInfo info) throws IOException { 2784 checkOpen(); 2785 TraceScope scope = Trace.startSpan("addCachePool", traceSampler); 2786 try { 2787 namenode.addCachePool(info); 2788 } catch (RemoteException re) { 2789 throw re.unwrapRemoteException(); 2790 } finally { 2791 scope.close(); 2792 } 2793 } 2794 2795 public void modifyCachePool(CachePoolInfo info) throws IOException { 2796 checkOpen(); 2797 TraceScope scope = Trace.startSpan("modifyCachePool", traceSampler); 2798 try { 2799 namenode.modifyCachePool(info); 2800 } catch (RemoteException re) { 2801 throw re.unwrapRemoteException(); 2802 } finally { 2803 scope.close(); 2804 } 2805 } 2806 2807 public void removeCachePool(String poolName) throws IOException { 2808 checkOpen(); 2809 TraceScope scope = Trace.startSpan("removeCachePool", traceSampler); 2810 try { 2811 namenode.removeCachePool(poolName); 2812 } catch (RemoteException re) { 2813 throw re.unwrapRemoteException(); 2814 } finally { 2815 scope.close(); 2816 } 2817 } 2818 2819 public RemoteIterator<CachePoolEntry> listCachePools() throws IOException { 2820 return new CachePoolIterator(namenode, traceSampler); 2821 } 2822 2823 /** 2824 * Save namespace image. 2825 * 2826 * @see ClientProtocol#saveNamespace() 2827 */ 2828 void saveNamespace() throws AccessControlException, IOException { 2829 TraceScope scope = Trace.startSpan("saveNamespace", traceSampler); 2830 try { 2831 namenode.saveNamespace(); 2832 } catch(RemoteException re) { 2833 throw re.unwrapRemoteException(AccessControlException.class); 2834 } finally { 2835 scope.close(); 2836 } 2837 } 2838 2839 /** 2840 * Rolls the edit log on the active NameNode. 2841 * @return the txid of the new log segment 2842 * 2843 * @see ClientProtocol#rollEdits() 2844 */ 2845 long rollEdits() throws AccessControlException, IOException { 2846 TraceScope scope = Trace.startSpan("rollEdits", traceSampler); 2847 try { 2848 return namenode.rollEdits(); 2849 } catch(RemoteException re) { 2850 throw re.unwrapRemoteException(AccessControlException.class); 2851 } finally { 2852 scope.close(); 2853 } 2854 } 2855 2856 @VisibleForTesting 2857 ExtendedBlock getPreviousBlock(long fileId) { 2858 return filesBeingWritten.get(fileId).getBlock(); 2859 } 2860 2861 /** 2862 * enable/disable restore failed storage. 2863 * 2864 * @see ClientProtocol#restoreFailedStorage(String arg) 2865 */ 2866 boolean restoreFailedStorage(String arg) 2867 throws AccessControlException, IOException{ 2868 TraceScope scope = Trace.startSpan("restoreFailedStorage", traceSampler); 2869 try { 2870 return namenode.restoreFailedStorage(arg); 2871 } finally { 2872 scope.close(); 2873 } 2874 } 2875 2876 /** 2877 * Refresh the hosts and exclude files. (Rereads them.) 2878 * See {@link ClientProtocol#refreshNodes()} 2879 * for more details. 2880 * 2881 * @see ClientProtocol#refreshNodes() 2882 */ 2883 public void refreshNodes() throws IOException { 2884 TraceScope scope = Trace.startSpan("refreshNodes", traceSampler); 2885 try { 2886 namenode.refreshNodes(); 2887 } finally { 2888 scope.close(); 2889 } 2890 } 2891 2892 /** 2893 * Dumps DFS data structures into specified file. 2894 * 2895 * @see ClientProtocol#metaSave(String) 2896 */ 2897 public void metaSave(String pathname) throws IOException { 2898 TraceScope scope = Trace.startSpan("metaSave", traceSampler); 2899 try { 2900 namenode.metaSave(pathname); 2901 } finally { 2902 scope.close(); 2903 } 2904 } 2905 2906 /** 2907 * Requests the namenode to tell all datanodes to use a new, non-persistent 2908 * bandwidth value for dfs.balance.bandwidthPerSec. 2909 * See {@link ClientProtocol#setBalancerBandwidth(long)} 2910 * for more details. 2911 * 2912 * @see ClientProtocol#setBalancerBandwidth(long) 2913 */ 2914 public void setBalancerBandwidth(long bandwidth) throws IOException { 2915 TraceScope scope = Trace.startSpan("setBalancerBandwidth", traceSampler); 2916 try { 2917 namenode.setBalancerBandwidth(bandwidth); 2918 } finally { 2919 scope.close(); 2920 } 2921 } 2922 2923 /** 2924 * @see ClientProtocol#finalizeUpgrade() 2925 */ 2926 public void finalizeUpgrade() throws IOException { 2927 TraceScope scope = Trace.startSpan("finalizeUpgrade", traceSampler); 2928 try { 2929 namenode.finalizeUpgrade(); 2930 } finally { 2931 scope.close(); 2932 } 2933 } 2934 2935 RollingUpgradeInfo rollingUpgrade(RollingUpgradeAction action) throws IOException { 2936 TraceScope scope = Trace.startSpan("rollingUpgrade", traceSampler); 2937 try { 2938 return namenode.rollingUpgrade(action); 2939 } finally { 2940 scope.close(); 2941 } 2942 } 2943 2944 /** 2945 */ 2946 @Deprecated 2947 public boolean mkdirs(String src) throws IOException { 2948 return mkdirs(src, null, true); 2949 } 2950 2951 /** 2952 * Create a directory (or hierarchy of directories) with the given 2953 * name and permission. 2954 * 2955 * @param src The path of the directory being created 2956 * @param permission The permission of the directory being created. 2957 * If permission == null, use {@link FsPermission#getDefault()}. 2958 * @param createParent create missing parent directory if true 2959 * 2960 * @return True if the operation success. 2961 * 2962 * @see ClientProtocol#mkdirs(String, FsPermission, boolean) 2963 */ 2964 public boolean mkdirs(String src, FsPermission permission, 2965 boolean createParent) throws IOException { 2966 if (permission == null) { 2967 permission = FsPermission.getDefault(); 2968 } 2969 FsPermission masked = permission.applyUMask(dfsClientConf.uMask); 2970 return primitiveMkdir(src, masked, createParent); 2971 } 2972 2973 /** 2974 * Same {{@link #mkdirs(String, FsPermission, boolean)} except 2975 * that the permissions has already been masked against umask. 2976 */ 2977 public boolean primitiveMkdir(String src, FsPermission absPermission) 2978 throws IOException { 2979 return primitiveMkdir(src, absPermission, true); 2980 } 2981 2982 /** 2983 * Same {{@link #mkdirs(String, FsPermission, boolean)} except 2984 * that the permissions has already been masked against umask. 2985 */ 2986 public boolean primitiveMkdir(String src, FsPermission absPermission, 2987 boolean createParent) 2988 throws IOException { 2989 checkOpen(); 2990 if (absPermission == null) { 2991 absPermission = 2992 FsPermission.getDefault().applyUMask(dfsClientConf.uMask); 2993 } 2994 2995 if(LOG.isDebugEnabled()) { 2996 LOG.debug(src + ": masked=" + absPermission); 2997 } 2998 TraceScope scope = Trace.startSpan("mkdir", traceSampler); 2999 try { 3000 return namenode.mkdirs(src, absPermission, createParent); 3001 } catch(RemoteException re) { 3002 throw re.unwrapRemoteException(AccessControlException.class, 3003 InvalidPathException.class, 3004 FileAlreadyExistsException.class, 3005 FileNotFoundException.class, 3006 ParentNotDirectoryException.class, 3007 SafeModeException.class, 3008 NSQuotaExceededException.class, 3009 DSQuotaExceededException.class, 3010 UnresolvedPathException.class, 3011 SnapshotAccessControlException.class); 3012 } finally { 3013 scope.close(); 3014 } 3015 } 3016 3017 /** 3018 * Get {@link ContentSummary} rooted at the specified directory. 3019 * @param src The string representation of the path 3020 * 3021 * @see ClientProtocol#getContentSummary(String) 3022 */ 3023 ContentSummary getContentSummary(String src) throws IOException { 3024 TraceScope scope = getPathTraceScope("getContentSummary", src); 3025 try { 3026 return namenode.getContentSummary(src); 3027 } catch(RemoteException re) { 3028 throw re.unwrapRemoteException(AccessControlException.class, 3029 FileNotFoundException.class, 3030 UnresolvedPathException.class); 3031 } finally { 3032 scope.close(); 3033 } 3034 } 3035 3036 /** 3037 * Sets or resets quotas for a directory. 3038 * @see ClientProtocol#setQuota(String, long, long, StorageType) 3039 */ 3040 void setQuota(String src, long namespaceQuota, long storagespaceQuota) 3041 throws IOException { 3042 // sanity check 3043 if ((namespaceQuota <= 0 && namespaceQuota != HdfsConstants.QUOTA_DONT_SET && 3044 namespaceQuota != HdfsConstants.QUOTA_RESET) || 3045 (storagespaceQuota <= 0 && storagespaceQuota != HdfsConstants.QUOTA_DONT_SET && 3046 storagespaceQuota != HdfsConstants.QUOTA_RESET)) { 3047 throw new IllegalArgumentException("Invalid values for quota : " + 3048 namespaceQuota + " and " + 3049 storagespaceQuota); 3050 3051 } 3052 TraceScope scope = getPathTraceScope("setQuota", src); 3053 try { 3054 // Pass null as storage type for traditional namespace/storagespace quota. 3055 namenode.setQuota(src, namespaceQuota, storagespaceQuota, null); 3056 } catch(RemoteException re) { 3057 throw re.unwrapRemoteException(AccessControlException.class, 3058 FileNotFoundException.class, 3059 NSQuotaExceededException.class, 3060 DSQuotaExceededException.class, 3061 UnresolvedPathException.class, 3062 SnapshotAccessControlException.class); 3063 } finally { 3064 scope.close(); 3065 } 3066 } 3067 3068 /** 3069 * Sets or resets quotas by storage type for a directory. 3070 * @see ClientProtocol#setQuota(String, long, long, StorageType) 3071 */ 3072 void setQuotaByStorageType(String src, StorageType type, long quota) 3073 throws IOException { 3074 if (quota <= 0 && quota != HdfsConstants.QUOTA_DONT_SET && 3075 quota != HdfsConstants.QUOTA_RESET) { 3076 throw new IllegalArgumentException("Invalid values for quota :" + 3077 quota); 3078 } 3079 if (type == null) { 3080 throw new IllegalArgumentException("Invalid storage type(null)"); 3081 } 3082 if (!type.supportTypeQuota()) { 3083 throw new IllegalArgumentException("Don't support Quota for storage type : " 3084 + type.toString()); 3085 } 3086 TraceScope scope = getPathTraceScope("setQuotaByStorageType", src); 3087 try { 3088 namenode.setQuota(src, HdfsConstants.QUOTA_DONT_SET, quota, type); 3089 } catch (RemoteException re) { 3090 throw re.unwrapRemoteException(AccessControlException.class, 3091 FileNotFoundException.class, 3092 QuotaByStorageTypeExceededException.class, 3093 UnresolvedPathException.class, 3094 SnapshotAccessControlException.class); 3095 } finally { 3096 scope.close(); 3097 } 3098 } 3099 /** 3100 * set the modification and access time of a file 3101 * 3102 * @see ClientProtocol#setTimes(String, long, long) 3103 */ 3104 public void setTimes(String src, long mtime, long atime) throws IOException { 3105 checkOpen(); 3106 TraceScope scope = getPathTraceScope("setTimes", src); 3107 try { 3108 namenode.setTimes(src, mtime, atime); 3109 } catch(RemoteException re) { 3110 throw re.unwrapRemoteException(AccessControlException.class, 3111 FileNotFoundException.class, 3112 UnresolvedPathException.class, 3113 SnapshotAccessControlException.class); 3114 } finally { 3115 scope.close(); 3116 } 3117 } 3118 3119 /** 3120 * @deprecated use {@link HdfsDataInputStream} instead. 3121 */ 3122 @Deprecated 3123 public static class DFSDataInputStream extends HdfsDataInputStream { 3124 3125 public DFSDataInputStream(DFSInputStream in) throws IOException { 3126 super(in); 3127 } 3128 } 3129 3130 void reportChecksumFailure(String file, ExtendedBlock blk, DatanodeInfo dn) { 3131 DatanodeInfo [] dnArr = { dn }; 3132 LocatedBlock [] lblocks = { new LocatedBlock(blk, dnArr) }; 3133 reportChecksumFailure(file, lblocks); 3134 } 3135 3136 // just reports checksum failure and ignores any exception during the report. 3137 void reportChecksumFailure(String file, LocatedBlock lblocks[]) { 3138 try { 3139 reportBadBlocks(lblocks); 3140 } catch (IOException ie) { 3141 LOG.info("Found corruption while reading " + file 3142 + ". Error repairing corrupt blocks. Bad blocks remain.", ie); 3143 } 3144 } 3145 3146 @Override 3147 public String toString() { 3148 return getClass().getSimpleName() + "[clientName=" + clientName 3149 + ", ugi=" + ugi + "]"; 3150 } 3151 3152 public CachingStrategy getDefaultReadCachingStrategy() { 3153 return defaultReadCachingStrategy; 3154 } 3155 3156 public CachingStrategy getDefaultWriteCachingStrategy() { 3157 return defaultWriteCachingStrategy; 3158 } 3159 3160 public ClientContext getClientContext() { 3161 return clientContext; 3162 } 3163 3164 public void modifyAclEntries(String src, List<AclEntry> aclSpec) 3165 throws IOException { 3166 checkOpen(); 3167 TraceScope scope = getPathTraceScope("modifyAclEntries", src); 3168 try { 3169 namenode.modifyAclEntries(src, aclSpec); 3170 } catch(RemoteException re) { 3171 throw re.unwrapRemoteException(AccessControlException.class, 3172 AclException.class, 3173 FileNotFoundException.class, 3174 NSQuotaExceededException.class, 3175 SafeModeException.class, 3176 SnapshotAccessControlException.class, 3177 UnresolvedPathException.class); 3178 } finally { 3179 scope.close(); 3180 } 3181 } 3182 3183 public void removeAclEntries(String src, List<AclEntry> aclSpec) 3184 throws IOException { 3185 checkOpen(); 3186 TraceScope scope = Trace.startSpan("removeAclEntries", traceSampler); 3187 try { 3188 namenode.removeAclEntries(src, aclSpec); 3189 } catch(RemoteException re) { 3190 throw re.unwrapRemoteException(AccessControlException.class, 3191 AclException.class, 3192 FileNotFoundException.class, 3193 NSQuotaExceededException.class, 3194 SafeModeException.class, 3195 SnapshotAccessControlException.class, 3196 UnresolvedPathException.class); 3197 } finally { 3198 scope.close(); 3199 } 3200 } 3201 3202 public void removeDefaultAcl(String src) throws IOException { 3203 checkOpen(); 3204 TraceScope scope = Trace.startSpan("removeDefaultAcl", traceSampler); 3205 try { 3206 namenode.removeDefaultAcl(src); 3207 } catch(RemoteException re) { 3208 throw re.unwrapRemoteException(AccessControlException.class, 3209 AclException.class, 3210 FileNotFoundException.class, 3211 NSQuotaExceededException.class, 3212 SafeModeException.class, 3213 SnapshotAccessControlException.class, 3214 UnresolvedPathException.class); 3215 } finally { 3216 scope.close(); 3217 } 3218 } 3219 3220 public void removeAcl(String src) throws IOException { 3221 checkOpen(); 3222 TraceScope scope = Trace.startSpan("removeAcl", traceSampler); 3223 try { 3224 namenode.removeAcl(src); 3225 } catch(RemoteException re) { 3226 throw re.unwrapRemoteException(AccessControlException.class, 3227 AclException.class, 3228 FileNotFoundException.class, 3229 NSQuotaExceededException.class, 3230 SafeModeException.class, 3231 SnapshotAccessControlException.class, 3232 UnresolvedPathException.class); 3233 } finally { 3234 scope.close(); 3235 } 3236 } 3237 3238 public void setAcl(String src, List<AclEntry> aclSpec) throws IOException { 3239 checkOpen(); 3240 TraceScope scope = Trace.startSpan("setAcl", traceSampler); 3241 try { 3242 namenode.setAcl(src, aclSpec); 3243 } catch(RemoteException re) { 3244 throw re.unwrapRemoteException(AccessControlException.class, 3245 AclException.class, 3246 FileNotFoundException.class, 3247 NSQuotaExceededException.class, 3248 SafeModeException.class, 3249 SnapshotAccessControlException.class, 3250 UnresolvedPathException.class); 3251 } finally { 3252 scope.close(); 3253 } 3254 } 3255 3256 public AclStatus getAclStatus(String src) throws IOException { 3257 checkOpen(); 3258 TraceScope scope = getPathTraceScope("getAclStatus", src); 3259 try { 3260 return namenode.getAclStatus(src); 3261 } catch(RemoteException re) { 3262 throw re.unwrapRemoteException(AccessControlException.class, 3263 AclException.class, 3264 FileNotFoundException.class, 3265 UnresolvedPathException.class); 3266 } finally { 3267 scope.close(); 3268 } 3269 } 3270 3271 public void createEncryptionZone(String src, String keyName) 3272 throws IOException { 3273 checkOpen(); 3274 TraceScope scope = getPathTraceScope("createEncryptionZone", src); 3275 try { 3276 namenode.createEncryptionZone(src, keyName); 3277 } catch (RemoteException re) { 3278 throw re.unwrapRemoteException(AccessControlException.class, 3279 SafeModeException.class, 3280 UnresolvedPathException.class); 3281 } finally { 3282 scope.close(); 3283 } 3284 } 3285 3286 public EncryptionZone getEZForPath(String src) 3287 throws IOException { 3288 checkOpen(); 3289 TraceScope scope = getPathTraceScope("getEZForPath", src); 3290 try { 3291 return namenode.getEZForPath(src); 3292 } catch (RemoteException re) { 3293 throw re.unwrapRemoteException(AccessControlException.class, 3294 UnresolvedPathException.class); 3295 } finally { 3296 scope.close(); 3297 } 3298 } 3299 3300 public RemoteIterator<EncryptionZone> listEncryptionZones() 3301 throws IOException { 3302 checkOpen(); 3303 return new EncryptionZoneIterator(namenode, traceSampler); 3304 } 3305 3306 public void setXAttr(String src, String name, byte[] value, 3307 EnumSet<XAttrSetFlag> flag) throws IOException { 3308 checkOpen(); 3309 TraceScope scope = getPathTraceScope("setXAttr", src); 3310 try { 3311 namenode.setXAttr(src, XAttrHelper.buildXAttr(name, value), flag); 3312 } catch (RemoteException re) { 3313 throw re.unwrapRemoteException(AccessControlException.class, 3314 FileNotFoundException.class, 3315 NSQuotaExceededException.class, 3316 SafeModeException.class, 3317 SnapshotAccessControlException.class, 3318 UnresolvedPathException.class); 3319 } finally { 3320 scope.close(); 3321 } 3322 } 3323 3324 public byte[] getXAttr(String src, String name) throws IOException { 3325 checkOpen(); 3326 TraceScope scope = getPathTraceScope("getXAttr", src); 3327 try { 3328 final List<XAttr> xAttrs = XAttrHelper.buildXAttrAsList(name); 3329 final List<XAttr> result = namenode.getXAttrs(src, xAttrs); 3330 return XAttrHelper.getFirstXAttrValue(result); 3331 } catch(RemoteException re) { 3332 throw re.unwrapRemoteException(AccessControlException.class, 3333 FileNotFoundException.class, 3334 UnresolvedPathException.class); 3335 } finally { 3336 scope.close(); 3337 } 3338 } 3339 3340 public Map<String, byte[]> getXAttrs(String src) throws IOException { 3341 checkOpen(); 3342 TraceScope scope = getPathTraceScope("getXAttrs", src); 3343 try { 3344 return XAttrHelper.buildXAttrMap(namenode.getXAttrs(src, null)); 3345 } catch(RemoteException re) { 3346 throw re.unwrapRemoteException(AccessControlException.class, 3347 FileNotFoundException.class, 3348 UnresolvedPathException.class); 3349 } finally { 3350 scope.close(); 3351 } 3352 } 3353 3354 public Map<String, byte[]> getXAttrs(String src, List<String> names) 3355 throws IOException { 3356 checkOpen(); 3357 TraceScope scope = getPathTraceScope("getXAttrs", src); 3358 try { 3359 return XAttrHelper.buildXAttrMap(namenode.getXAttrs( 3360 src, XAttrHelper.buildXAttrs(names))); 3361 } catch(RemoteException re) { 3362 throw re.unwrapRemoteException(AccessControlException.class, 3363 FileNotFoundException.class, 3364 UnresolvedPathException.class); 3365 } finally { 3366 scope.close(); 3367 } 3368 } 3369 3370 public List<String> listXAttrs(String src) 3371 throws IOException { 3372 checkOpen(); 3373 TraceScope scope = getPathTraceScope("listXAttrs", src); 3374 try { 3375 final Map<String, byte[]> xattrs = 3376 XAttrHelper.buildXAttrMap(namenode.listXAttrs(src)); 3377 return Lists.newArrayList(xattrs.keySet()); 3378 } catch(RemoteException re) { 3379 throw re.unwrapRemoteException(AccessControlException.class, 3380 FileNotFoundException.class, 3381 UnresolvedPathException.class); 3382 } finally { 3383 scope.close(); 3384 } 3385 } 3386 3387 public void removeXAttr(String src, String name) throws IOException { 3388 checkOpen(); 3389 TraceScope scope = getPathTraceScope("removeXAttr", src); 3390 try { 3391 namenode.removeXAttr(src, XAttrHelper.buildXAttr(name)); 3392 } catch(RemoteException re) { 3393 throw re.unwrapRemoteException(AccessControlException.class, 3394 FileNotFoundException.class, 3395 NSQuotaExceededException.class, 3396 SafeModeException.class, 3397 SnapshotAccessControlException.class, 3398 UnresolvedPathException.class); 3399 } finally { 3400 scope.close(); 3401 } 3402 } 3403 3404 public void checkAccess(String src, FsAction mode) throws IOException { 3405 checkOpen(); 3406 TraceScope scope = getPathTraceScope("checkAccess", src); 3407 try { 3408 namenode.checkAccess(src, mode); 3409 } catch (RemoteException re) { 3410 throw re.unwrapRemoteException(AccessControlException.class, 3411 FileNotFoundException.class, 3412 UnresolvedPathException.class); 3413 } finally { 3414 scope.close(); 3415 } 3416 } 3417 3418 public DFSInotifyEventInputStream getInotifyEventStream() throws IOException { 3419 return new DFSInotifyEventInputStream(traceSampler, namenode); 3420 } 3421 3422 public DFSInotifyEventInputStream getInotifyEventStream(long lastReadTxid) 3423 throws IOException { 3424 return new DFSInotifyEventInputStream(traceSampler, namenode, lastReadTxid); 3425 } 3426 3427 @Override // RemotePeerFactory 3428 public Peer newConnectedPeer(InetSocketAddress addr, 3429 Token<BlockTokenIdentifier> blockToken, DatanodeID datanodeId) 3430 throws IOException { 3431 Peer peer = null; 3432 boolean success = false; 3433 Socket sock = null; 3434 try { 3435 sock = socketFactory.createSocket(); 3436 NetUtils.connect(sock, addr, 3437 getRandomLocalInterfaceAddr(), 3438 dfsClientConf.socketTimeout); 3439 peer = TcpPeerServer.peerFromSocketAndKey(saslClient, sock, this, 3440 blockToken, datanodeId); 3441 peer.setReadTimeout(dfsClientConf.socketTimeout); 3442 success = true; 3443 return peer; 3444 } finally { 3445 if (!success) { 3446 IOUtils.cleanup(LOG, peer); 3447 IOUtils.closeSocket(sock); 3448 } 3449 } 3450 } 3451 3452 /** 3453 * Create hedged reads thread pool, HEDGED_READ_THREAD_POOL, if 3454 * it does not already exist. 3455 * @param num Number of threads for hedged reads thread pool. 3456 * If zero, skip hedged reads thread pool creation. 3457 */ 3458 private synchronized void initThreadsNumForHedgedReads(int num) { 3459 if (num <= 0 || HEDGED_READ_THREAD_POOL != null) return; 3460 HEDGED_READ_THREAD_POOL = new ThreadPoolExecutor(1, num, 60, 3461 TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), 3462 new Daemon.DaemonFactory() { 3463 private final AtomicInteger threadIndex = 3464 new AtomicInteger(0); 3465 @Override 3466 public Thread newThread(Runnable r) { 3467 Thread t = super.newThread(r); 3468 t.setName("hedgedRead-" + 3469 threadIndex.getAndIncrement()); 3470 return t; 3471 } 3472 }, 3473 new ThreadPoolExecutor.CallerRunsPolicy() { 3474 3475 @Override 3476 public void rejectedExecution(Runnable runnable, 3477 ThreadPoolExecutor e) { 3478 LOG.info("Execution rejected, Executing in current thread"); 3479 HEDGED_READ_METRIC.incHedgedReadOpsInCurThread(); 3480 // will run in the current thread 3481 super.rejectedExecution(runnable, e); 3482 } 3483 }); 3484 HEDGED_READ_THREAD_POOL.allowCoreThreadTimeOut(true); 3485 if (LOG.isDebugEnabled()) { 3486 LOG.debug("Using hedged reads; pool threads=" + num); 3487 } 3488 } 3489 3490 long getHedgedReadTimeout() { 3491 return this.hedgedReadThresholdMillis; 3492 } 3493 3494 @VisibleForTesting 3495 void setHedgedReadTimeout(long timeoutMillis) { 3496 this.hedgedReadThresholdMillis = timeoutMillis; 3497 } 3498 3499 ThreadPoolExecutor getHedgedReadsThreadPool() { 3500 return HEDGED_READ_THREAD_POOL; 3501 } 3502 3503 boolean isHedgedReadsEnabled() { 3504 return (HEDGED_READ_THREAD_POOL != null) && 3505 HEDGED_READ_THREAD_POOL.getMaximumPoolSize() > 0; 3506 } 3507 3508 DFSHedgedReadMetrics getHedgedReadMetrics() { 3509 return HEDGED_READ_METRIC; 3510 } 3511 3512 public KeyProvider getKeyProvider() { 3513 return clientContext.getKeyProviderCache().get(conf); 3514 } 3515 3516 @VisibleForTesting 3517 public void setKeyProvider(KeyProvider provider) { 3518 try { 3519 clientContext.getKeyProviderCache().setKeyProvider(conf, provider); 3520 } catch (IOException e) { 3521 LOG.error("Could not set KeyProvider !!", e); 3522 } 3523 } 3524 3525 /** 3526 * Probe for encryption enabled on this filesystem. 3527 * See {@link DFSUtil#isHDFSEncryptionEnabled(Configuration)} 3528 * @return true if encryption is enabled 3529 */ 3530 public boolean isHDFSEncryptionEnabled() { 3531 return DFSUtil.isHDFSEncryptionEnabled(this.conf); 3532 } 3533 3534 /** 3535 * Returns the SaslDataTransferClient configured for this DFSClient. 3536 * 3537 * @return SaslDataTransferClient configured for this DFSClient 3538 */ 3539 public SaslDataTransferClient getSaslDataTransferClient() { 3540 return saslClient; 3541 } 3542 3543 private static final byte[] PATH = "path".getBytes(Charset.forName("UTF-8")); 3544 3545 TraceScope getPathTraceScope(String description, String path) { 3546 TraceScope scope = Trace.startSpan(description, traceSampler); 3547 Span span = scope.getSpan(); 3548 if (span != null) { 3549 if (path != null) { 3550 span.addKVAnnotation(PATH, 3551 path.getBytes(Charset.forName("UTF-8"))); 3552 } 3553 } 3554 return scope; 3555 } 3556 3557 private static final byte[] SRC = "src".getBytes(Charset.forName("UTF-8")); 3558 3559 private static final byte[] DST = "dst".getBytes(Charset.forName("UTF-8")); 3560 3561 TraceScope getSrcDstTraceScope(String description, String src, String dst) { 3562 TraceScope scope = Trace.startSpan(description, traceSampler); 3563 Span span = scope.getSpan(); 3564 if (span != null) { 3565 if (src != null) { 3566 span.addKVAnnotation(SRC, 3567 src.getBytes(Charset.forName("UTF-8"))); 3568 } 3569 if (dst != null) { 3570 span.addKVAnnotation(DST, 3571 dst.getBytes(Charset.forName("UTF-8"))); 3572 } 3573 } 3574 return scope; 3575 } 3576}