From d581fd4fe2eebb0474f8939d8bca49f4023b52d0 Mon Sep 17 00:00:00 2001
From: jbhu2 <11207-jbhu2@users.noreply.git.iflytek.com>
Date: Thu, 4 Nov 2021 15:28:20 +0800
Subject: [PATCH 1/6] The modification of _ buffer size has been completed
---
.../nfsclient/nfs/io/NfsFileOutputStream.java | 66 ++++++++++++++++---
1 file changed, 56 insertions(+), 10 deletions(-)
diff --git a/src/main/java/com/emc/ecs/nfsclient/nfs/io/NfsFileOutputStream.java b/src/main/java/com/emc/ecs/nfsclient/nfs/io/NfsFileOutputStream.java
index 4469fee..f183265 100644
--- a/src/main/java/com/emc/ecs/nfsclient/nfs/io/NfsFileOutputStream.java
+++ b/src/main/java/com/emc/ecs/nfsclient/nfs/io/NfsFileOutputStream.java
@@ -1,5 +1,5 @@
-/**
- * Copyright 2016-2018 Dell Inc. or its subsidiaries. All rights reserved.
+package com.emc.ecs.nfsclient.nfs.io; /**
+ * Copyright 2016 EMC Corporation. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
@@ -12,12 +12,13 @@
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
-package com.emc.ecs.nfsclient.nfs.io;
import com.emc.ecs.nfsclient.nfs.NfsCreateMode;
import com.emc.ecs.nfsclient.nfs.NfsSetAttributes;
import com.emc.ecs.nfsclient.nfs.NfsWriteRequest;
import com.emc.ecs.nfsclient.nfs.NfsWriteResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.OutputStream;
@@ -25,9 +26,6 @@
import java.util.ArrayList;
import java.util.List;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
/**
* The NFS equivalent of java.io.FileOutputStream.
*
@@ -81,6 +79,13 @@ public class NfsFileOutputStream extends OutputStream {
*/
private boolean _closed = false;
+ /**
+ * The buffer size specified by the user when calling the write(byte[])
+ * 8K is enough for all metadata and A send operation can be avoided to
+ * the maximum extent when the user does not specify the bufferSize parameter.
+ */
+ private static final int bufferSize = 8 * 1024;
+
/**
* Creates a file output stream to write to the file represented by the
* specified NfsFile object, starting at
@@ -97,7 +102,7 @@ public class NfsFileOutputStream extends OutputStream {
* opened for any other reason
*/
public NfsFileOutputStream(NfsFile, ?> nfsFile) throws IOException {
- this(nfsFile, 0, NfsWriteRequest.FILE_SYNC);
+ this(nfsFile, 0, NfsWriteRequest.FILE_SYNC, bufferSize);
}
/**
@@ -124,7 +129,36 @@ public NfsFileOutputStream(NfsFile, ?> nfsFile) throws IOException {
* opened for any other reason
*/
public NfsFileOutputStream(NfsFile, ?> nfsFile, int syncType) throws IOException {
- this(nfsFile, 0, syncType);
+ this(nfsFile, syncType, bufferSize);
+ }
+
+ /**
+ * Creates a file output stream to write to the file represented by the
+ * specified NfsFile object, starting at
+ * offset = 0 and using syncType behavior.
+ *
+ * If the file does not exist, it will first be created.
+ *
+ * @param nfsFile
+ * The file to be opened for writing.
+ * @param syncType
+ * One of the values below.
+ *
+ * - UNSTABLE = 0 - Best effort, no promises.
+ * - DATA_SYNC = 1 - Commit all data to stable storage, plus
+ * enough metadata for retrieval, before returning.
+ * - FILE_SYNC = 2 - Commit all data and metadata to stable
+ * storage before returning.
+ *
+ * @param bufferSize
+ * The buffer size specified by the user when calling the write(byte[])
+ * @throws IOException
+ * If the file exists but is a directory rather than a regular
+ * file, does not exist but cannot be created, or cannot be
+ * opened for any other reason
+ */
+ public NfsFileOutputStream(NfsFile, ?> nfsFile, int syncType, int bufferSize) throws IOException {
+ this(nfsFile, 0, syncType, bufferSize);
}
/**
@@ -147,12 +181,14 @@ public NfsFileOutputStream(NfsFile, ?> nfsFile, int syncType) throws IOExcepti
* FILE_SYNC = 2 - Commit all data and metadata to stable
* storage before returning.
*
+ * @param bufferSize
+ * The buffer size specified by the user when calling the write(byte[])
* @throws IOException
* If the file exists but is a directory rather than a regular
* file, does not exist but cannot be created, or cannot be
* opened for any other reason
*/
- public NfsFileOutputStream(NfsFile, ?> nfsFile, long offset, int syncType) throws IOException {
+ public NfsFileOutputStream(NfsFile, ?> nfsFile, long offset, int syncType, int bufferSize) throws IOException {
// Validate the offset.
if (offset < 0) {
throw new IllegalArgumentException("Cannot start writing before offset 0: " + offset);
@@ -184,7 +220,8 @@ public NfsFileOutputStream(NfsFile, ?> nfsFile, long offset, int syncType) thr
_offset = offset;
_currentOffset = offset;
_syncType = syncType;
- _buffer = new byte[(int) Math.min(_nfsFile.fsinfo().getFsInfo().wtpref, Integer.MAX_VALUE)];
+ _buffer = new byte[(int) Math.min(_nfsFile.fsinfo().getFsInfo().wtpref, Integer.MAX_VALUE) - bufferSize];
+ //_buffer = new byte[1024 * 1020];
}
/*
@@ -243,6 +280,10 @@ public void write(byte[] b) throws IOException {
* @see java.io.OutputStream#write(byte[], int, int)
*/
public void write(byte[] b, int off, int len) throws IOException {
+ System.out.println("开始写入数据!");
+ System.out.println("_buffer:" + _buffer.length);
+ System.out.println("wtmax:" + _nfsFile.fsinfo().getFsInfo().wtmax);
+
checkForClosed();
if (b == null) {
throw new NullPointerException();
@@ -252,13 +293,16 @@ public void write(byte[] b, int off, int len) throws IOException {
return;
}
if (len > bytesLeftInBuffer()) {
+ System.out.println("进入if");
int bytesToWrite = bytesLeftInBuffer();
write(b, off, bytesToWrite);
write(b, off + bytesToWrite, len - bytesToWrite);
} else {
System.arraycopy(b, off, _buffer, _bufferOffset, len);
_bufferOffset += len;
+ System.out.println("bytesLeftInBuffer:" + bytesLeftInBuffer());
if (bytesLeftInBuffer() == 0) {
+ System.out.println("准备进入writeBufferToFile()");
writeBufferToFile();
}
}
@@ -290,11 +334,13 @@ private void checkForClosed() throws IOException {
* @throws IOException
*/
private void writeBufferToFile() throws IOException {
+ System.out.println("开始写入缓冲区数据到文件中!");
if (_bufferOffset > 0) {
List payload = new ArrayList(1);
payload.add(ByteBuffer.wrap(_buffer, 0, _bufferOffset));
NfsWriteResponse response = _nfsFile.write(_currentOffset, payload, _syncType);
int bytesWritten = response.getCount();
+ System.out.println("写入的数据为:" + bytesWritten);
_currentOffset += bytesWritten;
_bufferOffset -= bytesWritten;
if (0 != _bufferOffset) { // Everything was not written.
From 2a01f7463ff0e3392904373404c08cad02d3d6b2 Mon Sep 17 00:00:00 2001
From: jbhu2 <11207-jbhu2@users.noreply.git.iflytek.com>
Date: Thu, 4 Nov 2021 15:41:30 +0800
Subject: [PATCH 2/6] The modification of _ buffer size has been completed
---
.../emc/ecs/nfsclient/nfs/io/NfsFileOutputStream.java | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/src/main/java/com/emc/ecs/nfsclient/nfs/io/NfsFileOutputStream.java b/src/main/java/com/emc/ecs/nfsclient/nfs/io/NfsFileOutputStream.java
index f183265..0c765af 100644
--- a/src/main/java/com/emc/ecs/nfsclient/nfs/io/NfsFileOutputStream.java
+++ b/src/main/java/com/emc/ecs/nfsclient/nfs/io/NfsFileOutputStream.java
@@ -221,7 +221,6 @@ public NfsFileOutputStream(NfsFile, ?> nfsFile, long offset, int syncType, int
_currentOffset = offset;
_syncType = syncType;
_buffer = new byte[(int) Math.min(_nfsFile.fsinfo().getFsInfo().wtpref, Integer.MAX_VALUE) - bufferSize];
- //_buffer = new byte[1024 * 1020];
}
/*
@@ -280,10 +279,6 @@ public void write(byte[] b) throws IOException {
* @see java.io.OutputStream#write(byte[], int, int)
*/
public void write(byte[] b, int off, int len) throws IOException {
- System.out.println("开始写入数据!");
- System.out.println("_buffer:" + _buffer.length);
- System.out.println("wtmax:" + _nfsFile.fsinfo().getFsInfo().wtmax);
-
checkForClosed();
if (b == null) {
throw new NullPointerException();
@@ -293,16 +288,13 @@ public void write(byte[] b, int off, int len) throws IOException {
return;
}
if (len > bytesLeftInBuffer()) {
- System.out.println("进入if");
int bytesToWrite = bytesLeftInBuffer();
write(b, off, bytesToWrite);
write(b, off + bytesToWrite, len - bytesToWrite);
} else {
System.arraycopy(b, off, _buffer, _bufferOffset, len);
_bufferOffset += len;
- System.out.println("bytesLeftInBuffer:" + bytesLeftInBuffer());
if (bytesLeftInBuffer() == 0) {
- System.out.println("准备进入writeBufferToFile()");
writeBufferToFile();
}
}
@@ -334,13 +326,11 @@ private void checkForClosed() throws IOException {
* @throws IOException
*/
private void writeBufferToFile() throws IOException {
- System.out.println("开始写入缓冲区数据到文件中!");
if (_bufferOffset > 0) {
List payload = new ArrayList(1);
payload.add(ByteBuffer.wrap(_buffer, 0, _bufferOffset));
NfsWriteResponse response = _nfsFile.write(_currentOffset, payload, _syncType);
int bytesWritten = response.getCount();
- System.out.println("写入的数据为:" + bytesWritten);
_currentOffset += bytesWritten;
_bufferOffset -= bytesWritten;
if (0 != _bufferOffset) { // Everything was not written.
From c8644d0bea1d638f4bd7e4da733510d0e7e2b8e9 Mon Sep 17 00:00:00 2001
From: jbhu2 <11207-jbhu2@users.noreply.git.iflytek.com>
Date: Thu, 4 Nov 2021 15:49:30 +0800
Subject: [PATCH 3/6] The modification of _ buffer size has been completed
---
.../java/com/emc/ecs/nfsclient/nfs/io/NfsFileOutputStream.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main/java/com/emc/ecs/nfsclient/nfs/io/NfsFileOutputStream.java b/src/main/java/com/emc/ecs/nfsclient/nfs/io/NfsFileOutputStream.java
index 0c765af..b958964 100644
--- a/src/main/java/com/emc/ecs/nfsclient/nfs/io/NfsFileOutputStream.java
+++ b/src/main/java/com/emc/ecs/nfsclient/nfs/io/NfsFileOutputStream.java
@@ -80,7 +80,7 @@ public class NfsFileOutputStream extends OutputStream {
private boolean _closed = false;
/**
- * The buffer size specified by the user when calling the write(byte[])
+ * The buffer size specified by the user when calling the write()
* 8K is enough for all metadata and A send operation can be avoided to
* the maximum extent when the user does not specify the bufferSize parameter.
*/
From 1d2972bafc2ba870f0d5b5e8c5b27dc59b2e68cb Mon Sep 17 00:00:00 2001
From: "Hu J.B" <49035824+Hujiabei1997@users.noreply.github.com>
Date: Thu, 4 Nov 2021 16:27:26 +0800
Subject: [PATCH 4/6] Delete NfsFileOutputStream.java
---
.../nfsclient/nfs/io/NfsFileOutputStream.java | 344 ------------------
1 file changed, 344 deletions(-)
delete mode 100644 src/main/java/com/emc/ecs/nfsclient/nfs/io/NfsFileOutputStream.java
diff --git a/src/main/java/com/emc/ecs/nfsclient/nfs/io/NfsFileOutputStream.java b/src/main/java/com/emc/ecs/nfsclient/nfs/io/NfsFileOutputStream.java
deleted file mode 100644
index b958964..0000000
--- a/src/main/java/com/emc/ecs/nfsclient/nfs/io/NfsFileOutputStream.java
+++ /dev/null
@@ -1,344 +0,0 @@
-package com.emc.ecs.nfsclient.nfs.io; /**
- * Copyright 2016 EMC Corporation. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License").
- * You may not use this file except in compliance with the License.
- * A copy of the License is located at
- *
- * http://www.apache.org/licenses/LICENSE-2.0.txt
- *
- * or in the "license" file accompanying this file. This file is distributed
- * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
- * express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-import com.emc.ecs.nfsclient.nfs.NfsCreateMode;
-import com.emc.ecs.nfsclient.nfs.NfsSetAttributes;
-import com.emc.ecs.nfsclient.nfs.NfsWriteRequest;
-import com.emc.ecs.nfsclient.nfs.NfsWriteResponse;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * The NFS equivalent of java.io.FileOutputStream.
- *
- * @author seibed
- */
-public class NfsFileOutputStream extends OutputStream {
-
- /**
- * The usual logger.
- */
- private static final Logger LOG = LoggerFactory.getLogger(NfsFileOutputStream.class);
-
- private NfsFile, ?> _nfsFile;
-
- /**
- * The file offset used to write data that has not been committed. This is
- * advanced after each commit.
- */
- private long _offset;
-
- /**
- * The current value of the file offset to which we have written data. This
- * is advanced after each write.
- */
- private long _currentOffset;
-
- /**
- * How the NFS server should write to the file.
- *
- * - UNSTABLE = 0 - Best effort, no promises.
- * - DATA_SYNC = 1 - Commit all data to stable storage, plus enough
- * metadata for retrieval, before returning.
- * - FILE_SYNC = 2 - Commit all data and metadata to stable storage before
- * returning.
- *
- */
- private final int _syncType;
-
- /**
- * The data currently being buffered.
- */
- private final byte[] _buffer;
-
- /**
- * The next position for writing in the buffer.
- */
- private int _bufferOffset = 0;
-
- /**
- * Flag to make sure operations are not run after closing the stream.
- */
- private boolean _closed = false;
-
- /**
- * The buffer size specified by the user when calling the write()
- * 8K is enough for all metadata and A send operation can be avoided to
- * the maximum extent when the user does not specify the bufferSize parameter.
- */
- private static final int bufferSize = 8 * 1024;
-
- /**
- * Creates a file output stream to write to the file represented by the
- * specified NfsFile object, starting at
- * offset = 0 and using syncType = FILE_SYNC
- * (commit all data and metadata to stable storage before returning).
- *
- * If the file does not exist, it will first be created.
- *
- * @param nfsFile
- * The file to be opened for writing.
- * @throws IOException
- * If the file exists but is a directory rather than a regular
- * file, does not exist but cannot be created, or cannot be
- * opened for any other reason
- */
- public NfsFileOutputStream(NfsFile, ?> nfsFile) throws IOException {
- this(nfsFile, 0, NfsWriteRequest.FILE_SYNC, bufferSize);
- }
-
- /**
- * Creates a file output stream to write to the file represented by the
- * specified NfsFile object, starting at
- * offset = 0 and using syncType behavior.
- *
- * If the file does not exist, it will first be created.
- *
- * @param nfsFile
- * The file to be opened for writing.
- * @param syncType
- * One of the values below.
- *
- * - UNSTABLE = 0 - Best effort, no promises.
- * - DATA_SYNC = 1 - Commit all data to stable storage, plus
- * enough metadata for retrieval, before returning.
- * - FILE_SYNC = 2 - Commit all data and metadata to stable
- * storage before returning.
- *
- * @throws IOException
- * If the file exists but is a directory rather than a regular
- * file, does not exist but cannot be created, or cannot be
- * opened for any other reason
- */
- public NfsFileOutputStream(NfsFile, ?> nfsFile, int syncType) throws IOException {
- this(nfsFile, syncType, bufferSize);
- }
-
- /**
- * Creates a file output stream to write to the file represented by the
- * specified NfsFile object, starting at
- * offset = 0 and using syncType behavior.
- *
- * If the file does not exist, it will first be created.
- *
- * @param nfsFile
- * The file to be opened for writing.
- * @param syncType
- * One of the values below.
- *
- * - UNSTABLE = 0 - Best effort, no promises.
- * - DATA_SYNC = 1 - Commit all data to stable storage, plus
- * enough metadata for retrieval, before returning.
- * - FILE_SYNC = 2 - Commit all data and metadata to stable
- * storage before returning.
- *
- * @param bufferSize
- * The buffer size specified by the user when calling the write(byte[])
- * @throws IOException
- * If the file exists but is a directory rather than a regular
- * file, does not exist but cannot be created, or cannot be
- * opened for any other reason
- */
- public NfsFileOutputStream(NfsFile, ?> nfsFile, int syncType, int bufferSize) throws IOException {
- this(nfsFile, 0, syncType, bufferSize);
- }
-
- /**
- * Creates a file output stream to write to the file represented by the
- * specified NfsFile object, starting at offset
- * and using syncType behavior.
- *
- * If the file does not exist, it will first be created.
- *
- * @param nfsFile
- * The file to be opened for writing.
- * @param offset
- * Where to start writing to the file.
- * @param syncType
- * One of the values below.
- *
- * - UNSTABLE = 0 - Best effort, no promises.
- * - DATA_SYNC = 1 - Commit all data to stable storage, plus
- * enough metadata for retrieval, before returning.
- * - FILE_SYNC = 2 - Commit all data and metadata to stable
- * storage before returning.
- *
- * @param bufferSize
- * The buffer size specified by the user when calling the write(byte[])
- * @throws IOException
- * If the file exists but is a directory rather than a regular
- * file, does not exist but cannot be created, or cannot be
- * opened for any other reason
- */
- public NfsFileOutputStream(NfsFile, ?> nfsFile, long offset, int syncType, int bufferSize) throws IOException {
- // Validate the offset.
- if (offset < 0) {
- throw new IllegalArgumentException("Cannot start writing before offset 0: " + offset);
- }
-
- // Validate the syncType value.
- switch (syncType) {
- case NfsWriteRequest.DATA_SYNC:
- case NfsWriteRequest.FILE_SYNC:
- case NfsWriteRequest.UNSTABLE:
- break; // do nothing, these are fine.
- default:
- throw new IllegalArgumentException("The value of syncType is undefined: " + syncType);
- }
-
- _nfsFile = nfsFile;
- if (_nfsFile.exists()) {
- // Validate the file.
- if (!(_nfsFile.canExtend() && _nfsFile.canModify())) {
- throw new IllegalArgumentException(
- "The file must be writable by the client: " + nfsFile.getAbsolutePath());
- }
- } else {
- // Create the file.
- NfsSetAttributes attributes = new NfsSetAttributes();
- attributes.setMode(NfsFile.ownerReadModeBit | NfsFile.ownerWriteModeBit);
- _nfsFile.create(NfsCreateMode.GUARDED, attributes, null);
- }
- _offset = offset;
- _currentOffset = offset;
- _syncType = syncType;
- _buffer = new byte[(int) Math.min(_nfsFile.fsinfo().getFsInfo().wtpref, Integer.MAX_VALUE) - bufferSize];
- }
-
- /*
- * (non-Javadoc)
- *
- * @see java.io.OutputStream#close()
- */
- public void close() throws IOException {
- if (!_closed) {
- try {
- flush();
- } catch (Throwable t) {
- LOG.debug(t.getMessage(), t);
- }
- _closed = true;
- super.close();
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see java.io.OutputStream#flush()
- */
- public void flush() throws IOException {
- checkForClosed();
- writeBufferToFile();
- if (_currentOffset > _offset) { // something to commit
- _nfsFile.commit(_offset, (int) (_currentOffset - _offset));
- _offset = _currentOffset;
- }
- super.flush();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see java.io.OutputStream#write(int)
- */
- public void write(int b) throws IOException {
- write(new byte[] { (byte) b }, 0, 1);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see java.io.OutputStream#write(byte[])
- */
- public void write(byte[] b) throws IOException {
- write(b, 0, b.length);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see java.io.OutputStream#write(byte[], int, int)
- */
- public void write(byte[] b, int off, int len) throws IOException {
- checkForClosed();
- if (b == null) {
- throw new NullPointerException();
- } else if ((off < 0) || (len < 0) || ((off + len) > b.length)) {
- throw new IndexOutOfBoundsException();
- } else if (len == 0) {
- return;
- }
- if (len > bytesLeftInBuffer()) {
- int bytesToWrite = bytesLeftInBuffer();
- write(b, off, bytesToWrite);
- write(b, off + bytesToWrite, len - bytesToWrite);
- } else {
- System.arraycopy(b, off, _buffer, _bufferOffset, len);
- _bufferOffset += len;
- if (bytesLeftInBuffer() == 0) {
- writeBufferToFile();
- }
- }
- }
-
- /**
- * @return The number of bytes that can be written to the buffer before
- * overflow occurs.
- */
- private int bytesLeftInBuffer() {
- return _buffer.length - _bufferOffset;
- }
-
- /**
- * Convenience function.
- *
- * @throws IOException
- * If the stream has been closed.
- */
- private void checkForClosed() throws IOException {
- if (_closed) {
- throw new IOException("This stream has been closed.");
- }
- }
-
- /**
- * Write the buffer contents to the file and reset the buffer afterwards.
- *
- * @throws IOException
- */
- private void writeBufferToFile() throws IOException {
- if (_bufferOffset > 0) {
- List payload = new ArrayList(1);
- payload.add(ByteBuffer.wrap(_buffer, 0, _bufferOffset));
- NfsWriteResponse response = _nfsFile.write(_currentOffset, payload, _syncType);
- int bytesWritten = response.getCount();
- _currentOffset += bytesWritten;
- _bufferOffset -= bytesWritten;
- if (0 != _bufferOffset) { // Everything was not written.
- // _bufferOffset should be the number of unwritten bytes.
- // Copy the unwritten bytes to the beginning of the buffer.
- System.arraycopy(_buffer, bytesWritten, _buffer, 0, _bufferOffset);
- }
- }
- }
-
-}
From 2678aa80ba01faab9d2e71dec66183c96037b2b2 Mon Sep 17 00:00:00 2001
From: jbhu2 <11207-jbhu2@users.noreply.git.iflytek.com>
Date: Thu, 4 Nov 2021 16:29:07 +0800
Subject: [PATCH 5/6] The modification of _ buffer size has been completed
---
.../nfsclient/nfs/io/NfsFileOutputStream.java | 344 ++++++++++++++++++
1 file changed, 344 insertions(+)
create mode 100644 src/main/java/com/emc/ecs/nfsclient/nfs/io/NfsFileOutputStream.java
diff --git a/src/main/java/com/emc/ecs/nfsclient/nfs/io/NfsFileOutputStream.java b/src/main/java/com/emc/ecs/nfsclient/nfs/io/NfsFileOutputStream.java
new file mode 100644
index 0000000..0c765af
--- /dev/null
+++ b/src/main/java/com/emc/ecs/nfsclient/nfs/io/NfsFileOutputStream.java
@@ -0,0 +1,344 @@
+package com.emc.ecs.nfsclient.nfs.io; /**
+ * Copyright 2016 EMC Corporation. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0.txt
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+import com.emc.ecs.nfsclient.nfs.NfsCreateMode;
+import com.emc.ecs.nfsclient.nfs.NfsSetAttributes;
+import com.emc.ecs.nfsclient.nfs.NfsWriteRequest;
+import com.emc.ecs.nfsclient.nfs.NfsWriteResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The NFS equivalent of java.io.FileOutputStream.
+ *
+ * @author seibed
+ */
+public class NfsFileOutputStream extends OutputStream {
+
+ /**
+ * The usual logger.
+ */
+ private static final Logger LOG = LoggerFactory.getLogger(NfsFileOutputStream.class);
+
+ private NfsFile, ?> _nfsFile;
+
+ /**
+ * The file offset used to write data that has not been committed. This is
+ * advanced after each commit.
+ */
+ private long _offset;
+
+ /**
+ * The current value of the file offset to which we have written data. This
+ * is advanced after each write.
+ */
+ private long _currentOffset;
+
+ /**
+ * How the NFS server should write to the file.
+ *
+ * - UNSTABLE = 0 - Best effort, no promises.
+ * - DATA_SYNC = 1 - Commit all data to stable storage, plus enough
+ * metadata for retrieval, before returning.
+ * - FILE_SYNC = 2 - Commit all data and metadata to stable storage before
+ * returning.
+ *
+ */
+ private final int _syncType;
+
+ /**
+ * The data currently being buffered.
+ */
+ private final byte[] _buffer;
+
+ /**
+ * The next position for writing in the buffer.
+ */
+ private int _bufferOffset = 0;
+
+ /**
+ * Flag to make sure operations are not run after closing the stream.
+ */
+ private boolean _closed = false;
+
+ /**
+ * The buffer size specified by the user when calling the write(byte[])
+ * 8K is enough for all metadata and A send operation can be avoided to
+ * the maximum extent when the user does not specify the bufferSize parameter.
+ */
+ private static final int bufferSize = 8 * 1024;
+
+ /**
+ * Creates a file output stream to write to the file represented by the
+ * specified NfsFile object, starting at
+ * offset = 0 and using syncType = FILE_SYNC
+ * (commit all data and metadata to stable storage before returning).
+ *
+ * If the file does not exist, it will first be created.
+ *
+ * @param nfsFile
+ * The file to be opened for writing.
+ * @throws IOException
+ * If the file exists but is a directory rather than a regular
+ * file, does not exist but cannot be created, or cannot be
+ * opened for any other reason
+ */
+ public NfsFileOutputStream(NfsFile, ?> nfsFile) throws IOException {
+ this(nfsFile, 0, NfsWriteRequest.FILE_SYNC, bufferSize);
+ }
+
+ /**
+ * Creates a file output stream to write to the file represented by the
+ * specified NfsFile object, starting at
+ * offset = 0 and using syncType behavior.
+ *
+ * If the file does not exist, it will first be created.
+ *
+ * @param nfsFile
+ * The file to be opened for writing.
+ * @param syncType
+ * One of the values below.
+ *
+ * - UNSTABLE = 0 - Best effort, no promises.
+ * - DATA_SYNC = 1 - Commit all data to stable storage, plus
+ * enough metadata for retrieval, before returning.
+ * - FILE_SYNC = 2 - Commit all data and metadata to stable
+ * storage before returning.
+ *
+ * @throws IOException
+ * If the file exists but is a directory rather than a regular
+ * file, does not exist but cannot be created, or cannot be
+ * opened for any other reason
+ */
+ public NfsFileOutputStream(NfsFile, ?> nfsFile, int syncType) throws IOException {
+ this(nfsFile, syncType, bufferSize);
+ }
+
+ /**
+ * Creates a file output stream to write to the file represented by the
+ * specified NfsFile object, starting at
+ * offset = 0 and using syncType behavior.
+ *
+ * If the file does not exist, it will first be created.
+ *
+ * @param nfsFile
+ * The file to be opened for writing.
+ * @param syncType
+ * One of the values below.
+ *
+ * - UNSTABLE = 0 - Best effort, no promises.
+ * - DATA_SYNC = 1 - Commit all data to stable storage, plus
+ * enough metadata for retrieval, before returning.
+ * - FILE_SYNC = 2 - Commit all data and metadata to stable
+ * storage before returning.
+ *
+ * @param bufferSize
+ * The buffer size specified by the user when calling the write(byte[])
+ * @throws IOException
+ * If the file exists but is a directory rather than a regular
+ * file, does not exist but cannot be created, or cannot be
+ * opened for any other reason
+ */
+ public NfsFileOutputStream(NfsFile, ?> nfsFile, int syncType, int bufferSize) throws IOException {
+ this(nfsFile, 0, syncType, bufferSize);
+ }
+
+ /**
+ * Creates a file output stream to write to the file represented by the
+ * specified NfsFile object, starting at offset
+ * and using syncType behavior.
+ *
+ * If the file does not exist, it will first be created.
+ *
+ * @param nfsFile
+ * The file to be opened for writing.
+ * @param offset
+ * Where to start writing to the file.
+ * @param syncType
+ * One of the values below.
+ *
+ * - UNSTABLE = 0 - Best effort, no promises.
+ * - DATA_SYNC = 1 - Commit all data to stable storage, plus
+ * enough metadata for retrieval, before returning.
+ * - FILE_SYNC = 2 - Commit all data and metadata to stable
+ * storage before returning.
+ *
+ * @param bufferSize
+ * The buffer size specified by the user when calling the write(byte[])
+ * @throws IOException
+ * If the file exists but is a directory rather than a regular
+ * file, does not exist but cannot be created, or cannot be
+ * opened for any other reason
+ */
+ public NfsFileOutputStream(NfsFile, ?> nfsFile, long offset, int syncType, int bufferSize) throws IOException {
+ // Validate the offset.
+ if (offset < 0) {
+ throw new IllegalArgumentException("Cannot start writing before offset 0: " + offset);
+ }
+
+ // Validate the syncType value.
+ switch (syncType) {
+ case NfsWriteRequest.DATA_SYNC:
+ case NfsWriteRequest.FILE_SYNC:
+ case NfsWriteRequest.UNSTABLE:
+ break; // do nothing, these are fine.
+ default:
+ throw new IllegalArgumentException("The value of syncType is undefined: " + syncType);
+ }
+
+ _nfsFile = nfsFile;
+ if (_nfsFile.exists()) {
+ // Validate the file.
+ if (!(_nfsFile.canExtend() && _nfsFile.canModify())) {
+ throw new IllegalArgumentException(
+ "The file must be writable by the client: " + nfsFile.getAbsolutePath());
+ }
+ } else {
+ // Create the file.
+ NfsSetAttributes attributes = new NfsSetAttributes();
+ attributes.setMode(NfsFile.ownerReadModeBit | NfsFile.ownerWriteModeBit);
+ _nfsFile.create(NfsCreateMode.GUARDED, attributes, null);
+ }
+ _offset = offset;
+ _currentOffset = offset;
+ _syncType = syncType;
+ _buffer = new byte[(int) Math.min(_nfsFile.fsinfo().getFsInfo().wtpref, Integer.MAX_VALUE) - bufferSize];
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.io.OutputStream#close()
+ */
+ public void close() throws IOException {
+ if (!_closed) {
+ try {
+ flush();
+ } catch (Throwable t) {
+ LOG.debug(t.getMessage(), t);
+ }
+ _closed = true;
+ super.close();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.io.OutputStream#flush()
+ */
+ public void flush() throws IOException {
+ checkForClosed();
+ writeBufferToFile();
+ if (_currentOffset > _offset) { // something to commit
+ _nfsFile.commit(_offset, (int) (_currentOffset - _offset));
+ _offset = _currentOffset;
+ }
+ super.flush();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.io.OutputStream#write(int)
+ */
+ public void write(int b) throws IOException {
+ write(new byte[] { (byte) b }, 0, 1);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.io.OutputStream#write(byte[])
+ */
+ public void write(byte[] b) throws IOException {
+ write(b, 0, b.length);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.io.OutputStream#write(byte[], int, int)
+ */
+ public void write(byte[] b, int off, int len) throws IOException {
+ checkForClosed();
+ if (b == null) {
+ throw new NullPointerException();
+ } else if ((off < 0) || (len < 0) || ((off + len) > b.length)) {
+ throw new IndexOutOfBoundsException();
+ } else if (len == 0) {
+ return;
+ }
+ if (len > bytesLeftInBuffer()) {
+ int bytesToWrite = bytesLeftInBuffer();
+ write(b, off, bytesToWrite);
+ write(b, off + bytesToWrite, len - bytesToWrite);
+ } else {
+ System.arraycopy(b, off, _buffer, _bufferOffset, len);
+ _bufferOffset += len;
+ if (bytesLeftInBuffer() == 0) {
+ writeBufferToFile();
+ }
+ }
+ }
+
+ /**
+ * @return The number of bytes that can be written to the buffer before
+ * overflow occurs.
+ */
+ private int bytesLeftInBuffer() {
+ return _buffer.length - _bufferOffset;
+ }
+
+ /**
+ * Convenience function.
+ *
+ * @throws IOException
+ * If the stream has been closed.
+ */
+ private void checkForClosed() throws IOException {
+ if (_closed) {
+ throw new IOException("This stream has been closed.");
+ }
+ }
+
+ /**
+ * Write the buffer contents to the file and reset the buffer afterwards.
+ *
+ * @throws IOException
+ */
+ private void writeBufferToFile() throws IOException {
+ if (_bufferOffset > 0) {
+ List payload = new ArrayList(1);
+ payload.add(ByteBuffer.wrap(_buffer, 0, _bufferOffset));
+ NfsWriteResponse response = _nfsFile.write(_currentOffset, payload, _syncType);
+ int bytesWritten = response.getCount();
+ _currentOffset += bytesWritten;
+ _bufferOffset -= bytesWritten;
+ if (0 != _bufferOffset) { // Everything was not written.
+ // _bufferOffset should be the number of unwritten bytes.
+ // Copy the unwritten bytes to the beginning of the buffer.
+ System.arraycopy(_buffer, bytesWritten, _buffer, 0, _bufferOffset);
+ }
+ }
+ }
+
+}
From 12fe747062eadc4dc4b8f8f08c282c03e501d492 Mon Sep 17 00:00:00 2001
From: jbhu2 <11207-jbhu2@users.noreply.git.iflytek.com>
Date: Fri, 12 Nov 2021 20:03:57 +0800
Subject: [PATCH 6/6] Fixed an error in data writing: "Tcp IO error"
---
.../java/com/emc/ecs/nfsclient/nfs/io/NfsFileOutputStream.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main/java/com/emc/ecs/nfsclient/nfs/io/NfsFileOutputStream.java b/src/main/java/com/emc/ecs/nfsclient/nfs/io/NfsFileOutputStream.java
index 0c765af..b958964 100644
--- a/src/main/java/com/emc/ecs/nfsclient/nfs/io/NfsFileOutputStream.java
+++ b/src/main/java/com/emc/ecs/nfsclient/nfs/io/NfsFileOutputStream.java
@@ -80,7 +80,7 @@ public class NfsFileOutputStream extends OutputStream {
private boolean _closed = false;
/**
- * The buffer size specified by the user when calling the write(byte[])
+ * The buffer size specified by the user when calling the write()
* 8K is enough for all metadata and A send operation can be avoided to
* the maximum extent when the user does not specify the bufferSize parameter.
*/