Skip to content

Commit 24a688b

Browse files
committed
Merge pull request #2 from apache/trunk
[apache merge] Merge from apache/hadoop, 20141102.
2 parents ed63b11 + 5c0381c commit 24a688b

File tree

16 files changed

+1272
-58
lines changed

16 files changed

+1272
-58
lines changed

hadoop-common-project/hadoop-common/CHANGES.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,9 @@ Release 2.6.0 - UNRELEASED
616616

617617
HADOOP-11216. Improve Openssl library finding. (cmccabe via yliu)
618618

619+
HADOOP-11254. Changed visibility of AccessControlList to be public for
620+
consumption by ecosystem. (Zhijie Shen via vinodkv)
621+
619622
OPTIMIZATIONS
620623

621624
HADOOP-10838. Byte array native checksumming. (James Thomas via todd)

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/AccessControlList.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
/**
4040
* Class representing a configured access control list.
4141
*/
42-
@InterfaceAudience.LimitedPrivate({"HDFS", "MapReduce"})
42+
@InterfaceAudience.Public
4343
@InterfaceStability.Evolving
4444
public class AccessControlList implements Writable {
4545

@@ -209,15 +209,15 @@ public void removeGroup(String group) {
209209
* Get the names of users allowed for this service.
210210
* @return the set of user names. the set must not be modified.
211211
*/
212-
Collection<String> getUsers() {
212+
public Collection<String> getUsers() {
213213
return users;
214214
}
215215

216216
/**
217217
* Get the names of user groups allowed for this service.
218218
* @return the set of group names. the set must not be modified.
219219
*/
220-
Collection<String> getGroups() {
220+
public Collection<String> getGroups() {
221221
return groups;
222222
}
223223

hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,9 @@ Release 2.6.0 - UNRELEASED
686686
HDFS-7313. Support optional configuration of AES cipher suite on
687687
DataTransferProtocol. (cnauroth)
688688

689+
HDFS-7276. Limit the number of byte arrays used by DFSOutputStream and
690+
provide a mechanism for recycling arrays. (szetszwo)
691+
689692
OPTIMIZATIONS
690693

691694
HDFS-6690. Deduplicate xattr names in memory. (wang)

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.apache.hadoop.hdfs.DFSClient.Conf;
2727
import org.apache.hadoop.hdfs.shortcircuit.DomainSocketFactory;
2828
import org.apache.hadoop.hdfs.shortcircuit.ShortCircuitCache;
29+
import org.apache.hadoop.hdfs.util.ByteArrayManager;
2930

3031
import com.google.common.annotations.VisibleForTesting;
3132

@@ -84,6 +85,9 @@ public class ClientContext {
8485
*/
8586
private volatile boolean disableLegacyBlockReaderLocal = false;
8687

88+
/** Creating byte[] for {@link DFSOutputStream}. */
89+
private final ByteArrayManager byteArrayManager;
90+
8791
/**
8892
* Whether or not we complained about a DFSClient fetching a CacheContext that
8993
* didn't match its config values yet.
@@ -105,6 +109,8 @@ private ClientContext(String name, Conf conf) {
105109
new PeerCache(conf.socketCacheCapacity, conf.socketCacheExpiry);
106110
this.useLegacyBlockReaderLocal = conf.useLegacyBlockReaderLocal;
107111
this.domainSocketFactory = new DomainSocketFactory(conf);
112+
113+
this.byteArrayManager = ByteArrayManager.newInstance(conf.writeByteArrayManagerConf);
108114
}
109115

110116
public static String confAsString(Conf conf) {
@@ -204,4 +210,8 @@ public void setDisableLegacyBlockReaderLocal() {
204210
public DomainSocketFactory getDomainSocketFactory() {
205211
return domainSocketFactory;
206212
}
213+
214+
public ByteArrayManager getByteArrayManager() {
215+
return byteArrayManager;
216+
}
207217
}

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

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,6 @@
5656
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_USE_DN_HOSTNAME_DEFAULT;
5757
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_WRITE_EXCLUDE_NODES_CACHE_EXPIRY_INTERVAL;
5858
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_WRITE_EXCLUDE_NODES_CACHE_EXPIRY_INTERVAL_DEFAULT;
59-
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_WRITE_MAX_PACKETS_DEFAULT;
60-
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_WRITE_MAX_PACKETS_KEY;
6159
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_WRITE_PACKET_SIZE_DEFAULT;
6260
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_WRITE_PACKET_SIZE_KEY;
6361
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_DATANODE_SOCKET_WRITE_TIMEOUT_KEY;
@@ -194,6 +192,7 @@
194192
import org.apache.hadoop.hdfs.server.namenode.NameNode;
195193
import org.apache.hadoop.hdfs.server.namenode.SafeModeException;
196194
import org.apache.hadoop.hdfs.server.protocol.DatanodeStorageReport;
195+
import org.apache.hadoop.hdfs.util.ByteArrayManager;
197196
import org.apache.hadoop.io.DataOutputBuffer;
198197
import org.apache.hadoop.io.EnumSetWritable;
199198
import org.apache.hadoop.io.IOUtils;
@@ -294,6 +293,7 @@ public static class Conf {
294293
final ChecksumOpt defaultChecksumOpt;
295294
final int writePacketSize;
296295
final int writeMaxPackets;
296+
final ByteArrayManager.Conf writeByteArrayManagerConf;
297297
final int socketTimeout;
298298
final int socketCacheCapacity;
299299
final long socketCacheExpiry;
@@ -364,8 +364,30 @@ public Conf(Configuration conf) {
364364
/** dfs.write.packet.size is an internal config variable */
365365
writePacketSize = conf.getInt(DFS_CLIENT_WRITE_PACKET_SIZE_KEY,
366366
DFS_CLIENT_WRITE_PACKET_SIZE_DEFAULT);
367-
writeMaxPackets = conf.getInt(DFS_CLIENT_WRITE_MAX_PACKETS_KEY,
368-
DFS_CLIENT_WRITE_MAX_PACKETS_DEFAULT);
367+
writeMaxPackets = conf.getInt(
368+
DFSConfigKeys.DFS_CLIENT_WRITE_MAX_PACKETS_IN_FLIGHT_KEY,
369+
DFSConfigKeys.DFS_CLIENT_WRITE_MAX_PACKETS_IN_FLIGHT_DEFAULT);
370+
371+
final boolean byteArrayManagerEnabled = conf.getBoolean(
372+
DFSConfigKeys.DFS_CLIENT_WRITE_BYTE_ARRAY_MANAGER_ENABLED_KEY,
373+
DFSConfigKeys.DFS_CLIENT_WRITE_BYTE_ARRAY_MANAGER_ENABLED_DEFAULT);
374+
if (!byteArrayManagerEnabled) {
375+
writeByteArrayManagerConf = null;
376+
} else {
377+
final int countThreshold = conf.getInt(
378+
DFSConfigKeys.DFS_CLIENT_WRITE_BYTE_ARRAY_MANAGER_COUNT_THRESHOLD_KEY,
379+
DFSConfigKeys.DFS_CLIENT_WRITE_BYTE_ARRAY_MANAGER_COUNT_THRESHOLD_DEFAULT);
380+
final int countLimit = conf.getInt(
381+
DFSConfigKeys.DFS_CLIENT_WRITE_BYTE_ARRAY_MANAGER_COUNT_LIMIT_KEY,
382+
DFSConfigKeys.DFS_CLIENT_WRITE_BYTE_ARRAY_MANAGER_COUNT_LIMIT_DEFAULT);
383+
final long countResetTimePeriodMs = conf.getLong(
384+
DFSConfigKeys.DFS_CLIENT_WRITE_BYTE_ARRAY_MANAGER_COUNT_RESET_TIME_PERIOD_MS_KEY,
385+
DFSConfigKeys.DFS_CLIENT_WRITE_BYTE_ARRAY_MANAGER_COUNT_RESET_TIME_PERIOD_MS_DEFAULT);
386+
writeByteArrayManagerConf = new ByteArrayManager.Conf(
387+
countThreshold, countLimit, countResetTimePeriodMs);
388+
}
389+
390+
369391
defaultBlockSize = conf.getLongBytes(DFS_BLOCK_SIZE_KEY,
370392
DFS_BLOCK_SIZE_DEFAULT);
371393
defaultReplication = (short) conf.getInt(

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

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,27 @@ public class DFSConfigKeys extends CommonConfigurationKeys {
5050
public static final String DFS_CLIENT_RETRY_POLICY_SPEC_DEFAULT = "10000,6,60000,10"; //t1,n1,t2,n2,...
5151
public static final String DFS_CHECKSUM_TYPE_KEY = "dfs.checksum.type";
5252
public static final String DFS_CHECKSUM_TYPE_DEFAULT = "CRC32C";
53-
public static final String DFS_CLIENT_WRITE_MAX_PACKETS_KEY = "dfs.client.write.max-packets";
54-
public static final int DFS_CLIENT_WRITE_MAX_PACKETS_DEFAULT = 80;
53+
public static final String DFS_CLIENT_WRITE_MAX_PACKETS_IN_FLIGHT_KEY = "dfs.client.write.max-packets-in-flight";
54+
public static final int DFS_CLIENT_WRITE_MAX_PACKETS_IN_FLIGHT_DEFAULT = 80;
5555
public static final String DFS_CLIENT_WRITE_PACKET_SIZE_KEY = "dfs.client-write-packet-size";
5656
public static final int DFS_CLIENT_WRITE_PACKET_SIZE_DEFAULT = 64*1024;
57+
public static final String DFS_CLIENT_WRITE_BYTE_ARRAY_MANAGER_ENABLED_KEY
58+
= "dfs.client.write.byte-array-manager.enabled";
59+
public static final boolean DFS_CLIENT_WRITE_BYTE_ARRAY_MANAGER_ENABLED_DEFAULT
60+
= false;
61+
public static final String DFS_CLIENT_WRITE_BYTE_ARRAY_MANAGER_COUNT_THRESHOLD_KEY
62+
= "dfs.client.write.byte-array-manager.count-threshold";
63+
public static final int DFS_CLIENT_WRITE_BYTE_ARRAY_MANAGER_COUNT_THRESHOLD_DEFAULT
64+
= 128;
65+
public static final String DFS_CLIENT_WRITE_BYTE_ARRAY_MANAGER_COUNT_LIMIT_KEY
66+
= "dfs.client.write.byte-array-manager.count-limit";
67+
public static final int DFS_CLIENT_WRITE_BYTE_ARRAY_MANAGER_COUNT_LIMIT_DEFAULT
68+
= 2048;
69+
public static final String DFS_CLIENT_WRITE_BYTE_ARRAY_MANAGER_COUNT_RESET_TIME_PERIOD_MS_KEY
70+
= "dfs.client.write.byte-array-manager.count-reset-time-period-ms";
71+
public static final long DFS_CLIENT_WRITE_BYTE_ARRAY_MANAGER_COUNT_RESET_TIME_PERIOD_MS_DEFAULT
72+
= 10L * 1000;
73+
5774
public static final String DFS_CLIENT_WRITE_REPLACE_DATANODE_ON_FAILURE_ENABLE_KEY = "dfs.client.block.write.replace-datanode-on-failure.enable";
5875
public static final boolean DFS_CLIENT_WRITE_REPLACE_DATANODE_ON_FAILURE_ENABLE_DEFAULT = true;
5976
public static final String DFS_CLIENT_WRITE_REPLACE_DATANODE_ON_FAILURE_POLICY_KEY = "dfs.client.block.write.replace-datanode-on-failure.policy";

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

Lines changed: 54 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,9 @@
4141
import java.util.concurrent.atomic.AtomicBoolean;
4242
import java.util.concurrent.atomic.AtomicReference;
4343

44-
import com.google.common.base.Preconditions;
45-
4644
import org.apache.hadoop.HadoopIllegalArgumentException;
4745
import org.apache.hadoop.classification.InterfaceAudience;
46+
import org.apache.hadoop.crypto.CryptoProtocolVersion;
4847
import org.apache.hadoop.fs.CanSetDropBehind;
4948
import org.apache.hadoop.fs.CreateFlag;
5049
import org.apache.hadoop.fs.FSOutputSummer;
@@ -55,7 +54,6 @@
5554
import org.apache.hadoop.fs.permission.FsPermission;
5655
import org.apache.hadoop.hdfs.client.HdfsDataOutputStream;
5756
import org.apache.hadoop.hdfs.client.HdfsDataOutputStream.SyncFlag;
58-
import org.apache.hadoop.crypto.CryptoProtocolVersion;
5957
import org.apache.hadoop.hdfs.protocol.BlockStoragePolicy;
6058
import org.apache.hadoop.hdfs.protocol.DSQuotaExceededException;
6159
import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
@@ -83,6 +81,7 @@
8381
import org.apache.hadoop.hdfs.server.namenode.NotReplicatedYetException;
8482
import org.apache.hadoop.hdfs.server.namenode.RetryStartFileException;
8583
import org.apache.hadoop.hdfs.server.namenode.SafeModeException;
84+
import org.apache.hadoop.hdfs.util.ByteArrayManager;
8685
import org.apache.hadoop.io.EnumSetWritable;
8786
import org.apache.hadoop.io.IOUtils;
8887
import org.apache.hadoop.ipc.RemoteException;
@@ -99,6 +98,7 @@
9998
import org.htrace.TraceScope;
10099

101100
import com.google.common.annotations.VisibleForTesting;
101+
import com.google.common.base.Preconditions;
102102
import com.google.common.cache.CacheBuilder;
103103
import com.google.common.cache.CacheLoader;
104104
import com.google.common.cache.LoadingCache;
@@ -143,6 +143,7 @@ public class DFSOutputStream extends FSOutputSummer
143143

144144
private final DFSClient dfsClient;
145145
private final long dfsclientSlowLogThresholdMs;
146+
private final ByteArrayManager byteArrayManager;
146147
private Socket s;
147148
// closed is accessed by different threads under different locks.
148149
private volatile boolean closed = false;
@@ -181,14 +182,41 @@ public class DFSOutputStream extends FSOutputSummer
181182
private static final BlockStoragePolicySuite blockStoragePolicySuite =
182183
BlockStoragePolicySuite.createDefaultSuite();
183184

185+
/** Use {@link ByteArrayManager} to create buffer for non-heartbeat packets.*/
186+
private Packet createPacket(int packetSize, int chunksPerPkt, long offsetInBlock,
187+
long seqno) throws InterruptedIOException {
188+
final byte[] buf;
189+
final int bufferSize = PacketHeader.PKT_MAX_HEADER_LEN + packetSize;
190+
191+
try {
192+
buf = byteArrayManager.newByteArray(bufferSize);
193+
} catch (InterruptedException ie) {
194+
final InterruptedIOException iioe = new InterruptedIOException(
195+
"seqno=" + seqno);
196+
iioe.initCause(ie);
197+
throw iioe;
198+
}
199+
200+
return new Packet(buf, chunksPerPkt, offsetInBlock, seqno, getChecksumSize());
201+
}
202+
203+
/**
204+
* For heartbeat packets, create buffer directly by new byte[]
205+
* since heartbeats should not be blocked.
206+
*/
207+
private Packet createHeartbeatPacket() throws InterruptedIOException {
208+
final byte[] buf = new byte[PacketHeader.PKT_MAX_HEADER_LEN];
209+
return new Packet(buf, 0, 0, Packet.HEART_BEAT_SEQNO, getChecksumSize());
210+
}
211+
184212
private static class Packet {
185213
private static final long HEART_BEAT_SEQNO = -1L;
186214
final long seqno; // sequencenumber of buffer in block
187215
final long offsetInBlock; // offset in block
188216
boolean syncBlock; // this packet forces the current block to disk
189217
int numChunks; // number of chunks currently in packet
190218
final int maxChunks; // max chunks in packet
191-
final byte[] buf;
219+
private byte[] buf;
192220
private boolean lastPacketInBlock; // is this the last packet in block?
193221

194222
/**
@@ -210,13 +238,6 @@ private static class Packet {
210238
final int dataStart;
211239
int dataPos;
212240

213-
/**
214-
* Create a heartbeat packet.
215-
*/
216-
Packet(int checksumSize) {
217-
this(0, 0, 0, HEART_BEAT_SEQNO, checksumSize);
218-
}
219-
220241
/**
221242
* Create a new packet.
222243
*
@@ -225,15 +246,15 @@ private static class Packet {
225246
* @param chunksPerPkt maximum number of chunks per packet.
226247
* @param offsetInBlock offset in bytes into the HDFS block.
227248
*/
228-
Packet(int pktSize, int chunksPerPkt, long offsetInBlock,
229-
long seqno, int checksumSize) {
249+
private Packet(byte[] buf, int chunksPerPkt, long offsetInBlock, long seqno,
250+
int checksumSize) {
230251
this.lastPacketInBlock = false;
231252
this.numChunks = 0;
232253
this.offsetInBlock = offsetInBlock;
233254
this.seqno = seqno;
234-
235-
buf = new byte[PacketHeader.PKT_MAX_HEADER_LEN + pktSize];
236-
255+
256+
this.buf = buf;
257+
237258
checksumStart = PacketHeader.PKT_MAX_HEADER_LEN;
238259
checksumPos = checksumStart;
239260
dataStart = checksumStart + (chunksPerPkt * checksumSize);
@@ -304,6 +325,11 @@ void writeTo(DataOutputStream stm) throws IOException {
304325
buf[headerStart+header.getSerializedSize() + checksumLen + dataLen-1] ^= 0xff;
305326
}
306327
}
328+
329+
private void releaseBuffer(ByteArrayManager bam) {
330+
bam.release(buf);
331+
buf = null;
332+
}
307333

308334
// get the packet's last byte's offset in the block
309335
long getLastByteOffsetBlock() {
@@ -547,7 +573,7 @@ public void run() {
547573
}
548574
// get packet to be sent.
549575
if (dataQueue.isEmpty()) {
550-
one = new Packet(getChecksumSize()); // heartbeat packet
576+
one = createHeartbeatPacket();
551577
} else {
552578
one = dataQueue.getFirst(); // regular data packet
553579
}
@@ -907,6 +933,8 @@ public void run() {
907933
lastAckedSeqno = seqno;
908934
ackQueue.removeFirst();
909935
dataQueue.notifyAll();
936+
937+
one.releaseBuffer(byteArrayManager);
910938
}
911939
} catch (Exception e) {
912940
if (!responderClosed) {
@@ -1657,6 +1685,7 @@ private DFSOutputStream(DFSClient dfsClient, String src, Progressable progress,
16571685

16581686
this.dfsclientSlowLogThresholdMs =
16591687
dfsClient.getConf().dfsclientSlowIoWarningThresholdMs;
1688+
this.byteArrayManager = dfsClient.getClientContext().getByteArrayManager();
16601689
}
16611690

16621691
/** Construct a new output stream for creating a file. */
@@ -1836,8 +1865,8 @@ protected synchronized void writeChunk(byte[] b, int offset, int len,
18361865
}
18371866

18381867
if (currentPacket == null) {
1839-
currentPacket = new Packet(packetSize, chunksPerPacket,
1840-
bytesCurBlock, currentSeqno++, getChecksumSize());
1868+
currentPacket = createPacket(packetSize, chunksPerPacket,
1869+
bytesCurBlock, currentSeqno++);
18411870
if (DFSClient.LOG.isDebugEnabled()) {
18421871
DFSClient.LOG.debug("DFSClient writeChunk allocating new packet seqno=" +
18431872
currentPacket.seqno +
@@ -1884,8 +1913,7 @@ protected synchronized void writeChunk(byte[] b, int offset, int len,
18841913
// indicate the end of block and reset bytesCurBlock.
18851914
//
18861915
if (bytesCurBlock == blockSize) {
1887-
currentPacket = new Packet(0, 0, bytesCurBlock,
1888-
currentSeqno++, getChecksumSize());
1916+
currentPacket = createPacket(0, 0, bytesCurBlock, currentSeqno++);
18891917
currentPacket.lastPacketInBlock = true;
18901918
currentPacket.syncBlock = shouldSyncBlock;
18911919
waitAndQueueCurrentPacket();
@@ -1972,17 +2000,17 @@ private void flushOrSync(boolean isSync, EnumSet<SyncFlag> syncFlags)
19722000
// Nothing to send right now,
19732001
// but sync was requested.
19742002
// Send an empty packet
1975-
currentPacket = new Packet(packetSize, chunksPerPacket,
1976-
bytesCurBlock, currentSeqno++, getChecksumSize());
2003+
currentPacket = createPacket(packetSize, chunksPerPacket,
2004+
bytesCurBlock, currentSeqno++);
19772005
}
19782006
} else {
19792007
if (isSync && bytesCurBlock > 0) {
19802008
// Nothing to send right now,
19812009
// and the block was partially written,
19822010
// and sync was requested.
19832011
// So send an empty sync packet.
1984-
currentPacket = new Packet(packetSize, chunksPerPacket,
1985-
bytesCurBlock, currentSeqno++, getChecksumSize());
2012+
currentPacket = createPacket(packetSize, chunksPerPacket,
2013+
bytesCurBlock, currentSeqno++);
19862014
} else {
19872015
// just discard the current packet since it is already been sent.
19882016
currentPacket = null;
@@ -2186,7 +2214,7 @@ public synchronized void close() throws IOException {
21862214

21872215
if (bytesCurBlock != 0) {
21882216
// send an empty packet to mark the end of the block
2189-
currentPacket = new Packet(0, 0, bytesCurBlock, currentSeqno++, getChecksumSize());
2217+
currentPacket = createPacket(0, 0, bytesCurBlock, currentSeqno++);
21902218
currentPacket.lastPacketInBlock = true;
21912219
currentPacket.syncBlock = shouldSyncBlock;
21922220
}

0 commit comments

Comments
 (0)