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