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. + *

+ * @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. */