Some bug fixes and tiny improvements upon seekable files.
This commit is contained in:
parent
0c5030a704
commit
061d34895d
5 changed files with 107 additions and 91 deletions
|
@ -19,7 +19,6 @@ package com.google.android.sambadocumentsprovider.nativefacade;
|
|||
|
||||
import android.system.ErrnoException;
|
||||
import android.system.StructStat;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
@ -27,15 +26,21 @@ import java.nio.ByteBuffer;
|
|||
class SambaFile implements SmbFile {
|
||||
|
||||
private final long mNativeHandler;
|
||||
|
||||
private int mNativeFd;
|
||||
private long mOffset;
|
||||
|
||||
SambaFile(long nativeHandler, int nativeFd) {
|
||||
mNativeHandler = nativeHandler;
|
||||
mNativeFd = nativeFd;
|
||||
}
|
||||
public int read(ByteBuffer buffer) throws IOException {
|
||||
|
||||
public int read(ByteBuffer buffer, int maxLen) throws IOException {
|
||||
try {
|
||||
return read(mNativeHandler, mNativeFd, buffer, buffer.capacity());
|
||||
final int bytesRead =
|
||||
read(mNativeHandler, mNativeFd, buffer, Math.min(maxLen, buffer.capacity()));
|
||||
mOffset += bytesRead;
|
||||
return bytesRead;
|
||||
} catch(ErrnoException e) {
|
||||
throw new IOException("Failed to read file. Fd: " + mNativeFd, e);
|
||||
}
|
||||
|
@ -43,15 +48,22 @@ class SambaFile implements SmbFile {
|
|||
|
||||
public int write(ByteBuffer buffer, int length) throws IOException {
|
||||
try {
|
||||
return write(mNativeHandler, mNativeFd, buffer, length);
|
||||
final int bytesWritten = write(mNativeHandler, mNativeFd, buffer, length);
|
||||
mOffset += bytesWritten;
|
||||
return bytesWritten;
|
||||
} catch(ErrnoException e) {
|
||||
throw new IOException("Failed to write file. Fd: " + mNativeFd, e);
|
||||
}
|
||||
}
|
||||
|
||||
public long seek(long offset) throws IOException {
|
||||
if (mOffset == offset) {
|
||||
return mOffset;
|
||||
}
|
||||
|
||||
try {
|
||||
return seek(mNativeHandler, mNativeFd, offset, 0);
|
||||
mOffset = seek(mNativeHandler, mNativeFd, offset, 0);
|
||||
return mOffset;
|
||||
} catch (ErrnoException e) {
|
||||
throw new IOException("Failed to move to offset in file. Fd: " + mNativeFd, e);
|
||||
}
|
||||
|
|
|
@ -39,14 +39,12 @@ class SambaFileClient extends BaseClient implements SmbFile {
|
|||
private static final int SEEK = 4;
|
||||
private static final int FSTAT = 5;
|
||||
|
||||
private static final String OFFSET = "offset";
|
||||
|
||||
SambaFileClient(Looper looper, SmbFile smbFileImpl) {
|
||||
mHandler = new SambaFileHandler(looper, smbFileImpl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(ByteBuffer buffer) throws IOException {
|
||||
public int read(ByteBuffer buffer, int maxLen) throws IOException {
|
||||
try(final MessageValues<ByteBuffer> messageValues = MessageValues.obtain()) {
|
||||
messageValues.setObj(buffer);
|
||||
final Message msg = mHandler.obtainMessage(READ, messageValues);
|
||||
|
@ -68,16 +66,12 @@ class SambaFileClient extends BaseClient implements SmbFile {
|
|||
|
||||
@Override
|
||||
public long seek(long offset) throws IOException {
|
||||
try (final MessageValues messageValues = MessageValues.obtain()) {
|
||||
try (final MessageValues<?> messageValues = MessageValues.obtain()) {
|
||||
final Message msg = mHandler.obtainMessage(SEEK, messageValues);
|
||||
|
||||
Bundle data = new Bundle();
|
||||
data.putLong(OFFSET, offset);
|
||||
|
||||
msg.setData(data);
|
||||
messageValues.setLong(offset);
|
||||
|
||||
enqueue(msg);
|
||||
return msg.peekData().getLong(OFFSET);
|
||||
return messageValues.getLong();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,7 +86,7 @@ class SambaFileClient extends BaseClient implements SmbFile {
|
|||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
try (final MessageValues messageValues = MessageValues.obtain()) {
|
||||
try (final MessageValues<?> messageValues = MessageValues.obtain()) {
|
||||
final Message msg = mHandler.obtainMessage(CLOSE, messageValues);
|
||||
enqueue(msg);
|
||||
messageValues.checkException();
|
||||
|
@ -115,10 +109,12 @@ class SambaFileClient extends BaseClient implements SmbFile {
|
|||
final MessageValues messageValues = (MessageValues) msg.obj;
|
||||
try {
|
||||
switch (msg.what) {
|
||||
case READ:
|
||||
case READ: {
|
||||
final int maxLen = messageValues.getInt();
|
||||
final ByteBuffer readBuffer = (ByteBuffer) messageValues.getObj();
|
||||
messageValues.setInt(mSmbFileImpl.read(readBuffer));
|
||||
messageValues.setInt(mSmbFileImpl.read(readBuffer, maxLen));
|
||||
break;
|
||||
}
|
||||
case WRITE: {
|
||||
final ByteBuffer writeBuffer = (ByteBuffer) messageValues.getObj();
|
||||
final int length = msg.arg1;
|
||||
|
@ -129,8 +125,9 @@ class SambaFileClient extends BaseClient implements SmbFile {
|
|||
mSmbFileImpl.close();
|
||||
break;
|
||||
case SEEK:
|
||||
long offset = mSmbFileImpl.seek(msg.peekData().getLong(OFFSET));
|
||||
msg.peekData().putLong(OFFSET, offset);
|
||||
long offset = mSmbFileImpl.seek(messageValues.getLong());
|
||||
messageValues.setLong(offset);
|
||||
break;
|
||||
case FSTAT:
|
||||
messageValues.setObj(mSmbFileImpl.fstat());
|
||||
break;
|
||||
|
|
|
@ -25,7 +25,7 @@ import java.nio.ByteBuffer;
|
|||
|
||||
public interface SmbFile extends Closeable {
|
||||
|
||||
int read(ByteBuffer buffer) throws IOException;
|
||||
int read(ByteBuffer buffer, int maxLen) throws IOException;
|
||||
int write(ByteBuffer buffer, int length) throws IOException;
|
||||
long seek(long offset) throws IOException;
|
||||
StructStat fstat() throws IOException;
|
||||
|
|
|
@ -61,7 +61,7 @@ public class ReadFileTask extends AsyncTask<Void, Void, Void> {
|
|||
int size;
|
||||
byte[] buf = new byte[mBuffer.capacity()];
|
||||
while ((mSignal == null || !mSignal.isCanceled())
|
||||
&& (size = file.read(mBuffer)) > 0) {
|
||||
&& (size = file.read(mBuffer, Integer.MAX_VALUE)) > 0) {
|
||||
mBuffer.get(buf, 0, size);
|
||||
os.write(buf, 0, size);
|
||||
mBuffer.clear();
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
package com.google.android.sambadocumentsprovider.provider;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.ProxyFileDescriptorCallback;
|
||||
import android.system.ErrnoException;
|
||||
|
@ -29,89 +30,95 @@ import java.io.ByteArrayOutputStream;
|
|||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
@TargetApi(26)
|
||||
public class SambaProxyFileCallback extends ProxyFileDescriptorCallback {
|
||||
private static final String TAG = "SambaProxyFileCallback";
|
||||
private static final String TAG = "SambaProxyFileCallback";
|
||||
|
||||
private final SmbFile mFile;
|
||||
private final ByteBufferPool mBufferPool;
|
||||
private final ByteBuffer mBuffer;
|
||||
private final CancellationSignal mSignal;
|
||||
private final SmbFile mFile;
|
||||
private final ByteBufferPool mBufferPool;
|
||||
private final CancellationSignal mSignal;
|
||||
|
||||
public SambaProxyFileCallback(SmbFile file, ByteBufferPool bufferPool, CancellationSignal signal) {
|
||||
mFile = file;
|
||||
mBufferPool = bufferPool;
|
||||
mBuffer = mBufferPool.obtainBuffer();
|
||||
mSignal = signal;
|
||||
public SambaProxyFileCallback(
|
||||
SmbFile file, ByteBufferPool bufferPool, CancellationSignal signal) {
|
||||
|
||||
mFile = file;
|
||||
mBufferPool = bufferPool;
|
||||
mSignal = signal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long onGetSize() throws ErrnoException {
|
||||
StructStat stat;
|
||||
try {
|
||||
stat = mFile.fstat();
|
||||
return stat.st_size;
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to get size for file", e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long onGetSize() throws ErrnoException {
|
||||
StructStat stat = null;
|
||||
try {
|
||||
stat = mFile.fstat();
|
||||
return stat.st_size;
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to get size for file");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onRead(long offset, int size, byte[] data) throws ErrnoException {
|
||||
final ByteBuffer buffer = mBufferPool.obtainBuffer();
|
||||
try {
|
||||
mFile.seek(offset);
|
||||
|
||||
int readSize;
|
||||
int total = 0;
|
||||
while ((mSignal == null || !mSignal.isCanceled())
|
||||
&& (readSize = mFile.read(buffer, size - total)) > 0) {
|
||||
final int len = Math.min(size - total, readSize);
|
||||
buffer.get(data, total, len);
|
||||
buffer.clear();
|
||||
total += len;
|
||||
if (total >= size) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return Math.min(size, total);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
mBufferPool.recycleBuffer(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onRead(long offset, int size, byte[] data) throws ErrnoException {
|
||||
try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
|
||||
mFile.seek(offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int readSize;
|
||||
int total = 0;
|
||||
while ((mSignal == null || !mSignal.isCanceled())
|
||||
&& (readSize = mFile.read(mBuffer)) > 0) {
|
||||
mBuffer.get(data, total, Math.min(size - total, readSize));
|
||||
mBuffer.clear();
|
||||
total += Math.min(size - total, readSize);
|
||||
if (total >= size) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public int onWrite(long offset, int size, byte[] data) throws ErrnoException {
|
||||
int written = 0;
|
||||
|
||||
return Math.min(size, total);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
final ByteBuffer buffer = mBufferPool.obtainBuffer();
|
||||
try {
|
||||
mFile.seek(offset);
|
||||
|
||||
return 0;
|
||||
while ((mSignal == null || !mSignal.isCanceled())
|
||||
&& written < size) {
|
||||
int willWrite = Math.min(size - written, buffer.capacity());
|
||||
buffer.put(data, written, willWrite);
|
||||
int res = mFile.write(buffer, willWrite);
|
||||
written += res;
|
||||
buffer.clear();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to write file.", e);
|
||||
} finally {
|
||||
mBufferPool.recycleBuffer(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onWrite(long offset, int size, byte[] data) throws ErrnoException {
|
||||
int written = 0;
|
||||
return written;
|
||||
}
|
||||
|
||||
try {
|
||||
mFile.seek(offset);
|
||||
|
||||
while ((mSignal == null || !mSignal.isCanceled())
|
||||
&& written < size) {
|
||||
int willWrite = Math.min(size - written, mBuffer.capacity());
|
||||
mBuffer.put(data, written, willWrite);
|
||||
int res = mFile.write(mBuffer, willWrite);
|
||||
written += res;
|
||||
mBuffer.clear();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to write file.", e);
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRelease() {
|
||||
mBufferPool.recycleBuffer(mBuffer);
|
||||
|
||||
try {
|
||||
mFile.close();
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to close file");
|
||||
}
|
||||
@Override
|
||||
public void onRelease() {
|
||||
try {
|
||||
mFile.close();
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to close file", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue