|
@@ -262,7 +262,9 @@ public class DFSOutputStream extends FSOutputSummer
|
|
maxChunks = chunksPerPkt;
|
|
maxChunks = chunksPerPkt;
|
|
}
|
|
}
|
|
|
|
|
|
- void writeData(byte[] inarray, int off, int len) {
|
|
|
|
|
|
+ synchronized void writeData(byte[] inarray, int off, int len)
|
|
|
|
+ throws ClosedChannelException {
|
|
|
|
+ checkBuffer();
|
|
if (dataPos + len > buf.length) {
|
|
if (dataPos + len > buf.length) {
|
|
throw new BufferOverflowException();
|
|
throw new BufferOverflowException();
|
|
}
|
|
}
|
|
@@ -270,7 +272,9 @@ public class DFSOutputStream extends FSOutputSummer
|
|
dataPos += len;
|
|
dataPos += len;
|
|
}
|
|
}
|
|
|
|
|
|
- void writeChecksum(byte[] inarray, int off, int len) {
|
|
|
|
|
|
+ synchronized void writeChecksum(byte[] inarray, int off, int len)
|
|
|
|
+ throws ClosedChannelException {
|
|
|
|
+ checkBuffer();
|
|
if (len == 0) {
|
|
if (len == 0) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
@@ -284,7 +288,9 @@ public class DFSOutputStream extends FSOutputSummer
|
|
/**
|
|
/**
|
|
* Write the full packet, including the header, to the given output stream.
|
|
* Write the full packet, including the header, to the given output stream.
|
|
*/
|
|
*/
|
|
- void writeTo(DataOutputStream stm) throws IOException {
|
|
|
|
|
|
+ synchronized void writeTo(DataOutputStream stm) throws IOException {
|
|
|
|
+ checkBuffer();
|
|
|
|
+
|
|
final int dataLen = dataPos - dataStart;
|
|
final int dataLen = dataPos - dataStart;
|
|
final int checksumLen = checksumPos - checksumStart;
|
|
final int checksumLen = checksumPos - checksumStart;
|
|
final int pktLen = HdfsConstants.BYTES_IN_INTEGER + dataLen + checksumLen;
|
|
final int pktLen = HdfsConstants.BYTES_IN_INTEGER + dataLen + checksumLen;
|
|
@@ -326,7 +332,13 @@ public class DFSOutputStream extends FSOutputSummer
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- private void releaseBuffer(ByteArrayManager bam) {
|
|
|
|
|
|
+ private synchronized void checkBuffer() throws ClosedChannelException {
|
|
|
|
+ if (buf == null) {
|
|
|
|
+ throw new ClosedChannelException();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private synchronized void releaseBuffer(ByteArrayManager bam) {
|
|
bam.release(buf);
|
|
bam.release(buf);
|
|
buf = null;
|
|
buf = null;
|
|
}
|
|
}
|
|
@@ -712,7 +724,7 @@ public class DFSOutputStream extends FSOutputSummer
|
|
closeResponder(); // close and join
|
|
closeResponder(); // close and join
|
|
closeStream();
|
|
closeStream();
|
|
streamerClosed = true;
|
|
streamerClosed = true;
|
|
- closed = true;
|
|
|
|
|
|
+ setClosed();
|
|
synchronized (dataQueue) {
|
|
synchronized (dataQueue) {
|
|
dataQueue.notifyAll();
|
|
dataQueue.notifyAll();
|
|
}
|
|
}
|
|
@@ -1616,8 +1628,9 @@ public class DFSOutputStream extends FSOutputSummer
|
|
return sock;
|
|
return sock;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ @Override
|
|
protected void checkClosed() throws IOException {
|
|
protected void checkClosed() throws IOException {
|
|
- if (closed) {
|
|
|
|
|
|
+ if (isClosed()) {
|
|
IOException e = lastException.get();
|
|
IOException e = lastException.get();
|
|
throw e != null ? e : new ClosedChannelException();
|
|
throw e != null ? e : new ClosedChannelException();
|
|
}
|
|
}
|
|
@@ -1827,7 +1840,7 @@ public class DFSOutputStream extends FSOutputSummer
|
|
synchronized (dataQueue) {
|
|
synchronized (dataQueue) {
|
|
try {
|
|
try {
|
|
// If queue is full, then wait till we have enough space
|
|
// If queue is full, then wait till we have enough space
|
|
- while (!closed && dataQueue.size() + ackQueue.size() > dfsClient.getConf().writeMaxPackets) {
|
|
|
|
|
|
+ while (!isClosed() && dataQueue.size() + ackQueue.size() > dfsClient.getConf().writeMaxPackets) {
|
|
try {
|
|
try {
|
|
dataQueue.wait();
|
|
dataQueue.wait();
|
|
} catch (InterruptedException e) {
|
|
} catch (InterruptedException e) {
|
|
@@ -2013,8 +2026,9 @@ public class DFSOutputStream extends FSOutputSummer
|
|
// So send an empty sync packet.
|
|
// So send an empty sync packet.
|
|
currentPacket = createPacket(packetSize, chunksPerPacket,
|
|
currentPacket = createPacket(packetSize, chunksPerPacket,
|
|
bytesCurBlock, currentSeqno++);
|
|
bytesCurBlock, currentSeqno++);
|
|
- } else {
|
|
|
|
|
|
+ } else if (currentPacket != null) {
|
|
// just discard the current packet since it is already been sent.
|
|
// just discard the current packet since it is already been sent.
|
|
|
|
+ currentPacket.releaseBuffer(byteArrayManager);
|
|
currentPacket = null;
|
|
currentPacket = null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -2071,7 +2085,7 @@ public class DFSOutputStream extends FSOutputSummer
|
|
} catch (IOException e) {
|
|
} catch (IOException e) {
|
|
DFSClient.LOG.warn("Error while syncing", e);
|
|
DFSClient.LOG.warn("Error while syncing", e);
|
|
synchronized (this) {
|
|
synchronized (this) {
|
|
- if (!closed) {
|
|
|
|
|
|
+ if (!isClosed()) {
|
|
lastException.set(new IOException("IOException flush:" + e));
|
|
lastException.set(new IOException("IOException flush:" + e));
|
|
closeThreads(true);
|
|
closeThreads(true);
|
|
}
|
|
}
|
|
@@ -2133,7 +2147,7 @@ public class DFSOutputStream extends FSOutputSummer
|
|
long begin = Time.monotonicNow();
|
|
long begin = Time.monotonicNow();
|
|
try {
|
|
try {
|
|
synchronized (dataQueue) {
|
|
synchronized (dataQueue) {
|
|
- while (!closed) {
|
|
|
|
|
|
+ while (!isClosed()) {
|
|
checkClosed();
|
|
checkClosed();
|
|
if (lastAckedSeqno >= seqno) {
|
|
if (lastAckedSeqno >= seqno) {
|
|
break;
|
|
break;
|
|
@@ -2166,7 +2180,7 @@ public class DFSOutputStream extends FSOutputSummer
|
|
* resources associated with this stream.
|
|
* resources associated with this stream.
|
|
*/
|
|
*/
|
|
synchronized void abort() throws IOException {
|
|
synchronized void abort() throws IOException {
|
|
- if (closed) {
|
|
|
|
|
|
+ if (isClosed()) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
streamer.setLastException(new IOException("Lease timeout of "
|
|
streamer.setLastException(new IOException("Lease timeout of "
|
|
@@ -2175,6 +2189,25 @@ public class DFSOutputStream extends FSOutputSummer
|
|
dfsClient.endFileLease(fileId);
|
|
dfsClient.endFileLease(fileId);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ boolean isClosed() {
|
|
|
|
+ return closed;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ void setClosed() {
|
|
|
|
+ closed = true;
|
|
|
|
+ synchronized (dataQueue) {
|
|
|
|
+ releaseBuffer(dataQueue, byteArrayManager);
|
|
|
|
+ releaseBuffer(ackQueue, byteArrayManager);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private static void releaseBuffer(List<Packet> packets, ByteArrayManager bam) {
|
|
|
|
+ for(Packet p : packets) {
|
|
|
|
+ p.releaseBuffer(bam);
|
|
|
|
+ }
|
|
|
|
+ packets.clear();
|
|
|
|
+ }
|
|
|
|
+
|
|
// shutdown datastreamer and responseprocessor threads.
|
|
// shutdown datastreamer and responseprocessor threads.
|
|
// interrupt datastreamer if force is true
|
|
// interrupt datastreamer if force is true
|
|
private void closeThreads(boolean force) throws IOException {
|
|
private void closeThreads(boolean force) throws IOException {
|
|
@@ -2189,7 +2222,7 @@ public class DFSOutputStream extends FSOutputSummer
|
|
} finally {
|
|
} finally {
|
|
streamer = null;
|
|
streamer = null;
|
|
s = null;
|
|
s = null;
|
|
- closed = true;
|
|
|
|
|
|
+ setClosed();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2199,7 +2232,7 @@ public class DFSOutputStream extends FSOutputSummer
|
|
*/
|
|
*/
|
|
@Override
|
|
@Override
|
|
public synchronized void close() throws IOException {
|
|
public synchronized void close() throws IOException {
|
|
- if (closed) {
|
|
|
|
|
|
+ if (isClosed()) {
|
|
IOException e = lastException.getAndSet(null);
|
|
IOException e = lastException.getAndSet(null);
|
|
if (e == null)
|
|
if (e == null)
|
|
return;
|
|
return;
|
|
@@ -2229,7 +2262,7 @@ public class DFSOutputStream extends FSOutputSummer
|
|
dfsClient.endFileLease(fileId);
|
|
dfsClient.endFileLease(fileId);
|
|
} catch (ClosedChannelException e) {
|
|
} catch (ClosedChannelException e) {
|
|
} finally {
|
|
} finally {
|
|
- closed = true;
|
|
|
|
|
|
+ setClosed();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|