mirror of
https://github.com/corda/corda.git
synced 2025-01-05 20:54:13 +00:00
RandomAccessFile
This commit is contained in:
parent
7699c12597
commit
57f4463c4c
@ -155,69 +155,9 @@ doWrite(JNIEnv* e, jint fd, const jbyte* data, jint length)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
|
|
||||||
class Mapping {
|
|
||||||
public:
|
|
||||||
Mapping(uint8_t* start, size_t length, HANDLE mapping, HANDLE file):
|
|
||||||
start(start),
|
|
||||||
length(length),
|
|
||||||
mapping(mapping),
|
|
||||||
file(file)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
uint8_t* start;
|
|
||||||
size_t length;
|
|
||||||
HANDLE mapping;
|
|
||||||
HANDLE file;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline Mapping*
|
|
||||||
map(JNIEnv* e, string_t path)
|
|
||||||
{
|
|
||||||
Mapping* result = 0;
|
|
||||||
HANDLE file = CreateFileW(path, FILE_READ_DATA,
|
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
|
|
||||||
OPEN_EXISTING, 0, 0);
|
|
||||||
if (file != INVALID_HANDLE_VALUE) {
|
|
||||||
unsigned size = GetFileSize(file, 0);
|
|
||||||
if (size != INVALID_FILE_SIZE) {
|
|
||||||
HANDLE mapping = CreateFileMapping(file, 0, PAGE_READONLY, 0, size, 0);
|
|
||||||
if (mapping) {
|
|
||||||
void* data = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
|
|
||||||
if (data) {
|
|
||||||
void* p = allocate(e, sizeof(Mapping));
|
|
||||||
if (not e->ExceptionCheck()) {
|
|
||||||
result = new (p)
|
|
||||||
Mapping(static_cast<uint8_t*>(data), size, file, mapping);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result == 0) {
|
|
||||||
CloseHandle(mapping);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result == 0) {
|
|
||||||
CloseHandle(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (result == 0 and not e->ExceptionCheck()) {
|
|
||||||
throwNew(e, "java/io/IOException", "%d", GetLastError());
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void
|
|
||||||
unmap(JNIEnv*, Mapping* mapping)
|
|
||||||
{
|
|
||||||
UnmapViewOfFile(mapping->start);
|
|
||||||
CloseHandle(mapping->mapping);
|
|
||||||
CloseHandle(mapping->file);
|
|
||||||
free(mapping);
|
|
||||||
}
|
|
||||||
|
|
||||||
class Directory {
|
class Directory {
|
||||||
public:
|
public:
|
||||||
Directory(): handle(0), findNext(false) { }
|
Directory(): handle(0), findNext(false) { }
|
||||||
@ -250,51 +190,9 @@ class Directory {
|
|||||||
|
|
||||||
#else // not PLATFORM_WINDOWS
|
#else // not PLATFORM_WINDOWS
|
||||||
|
|
||||||
class Mapping {
|
|
||||||
public:
|
|
||||||
Mapping(uint8_t* start, size_t length):
|
|
||||||
start(start),
|
|
||||||
length(length)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
uint8_t* start;
|
|
||||||
size_t length;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline Mapping*
|
|
||||||
map(JNIEnv* e, string_t path)
|
|
||||||
{
|
|
||||||
Mapping* result = 0;
|
|
||||||
int fd = open(path, O_RDONLY);
|
|
||||||
if (fd != -1) {
|
|
||||||
struct stat s;
|
|
||||||
int r = fstat(fd, &s);
|
|
||||||
if (r != -1) {
|
|
||||||
void* data = mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
|
||||||
if (data) {
|
|
||||||
void* p = allocate(e, sizeof(Mapping));
|
|
||||||
if (not e->ExceptionCheck()) {
|
|
||||||
result = new (p) Mapping(static_cast<uint8_t*>(data), s.st_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
if (result == 0 and not e->ExceptionCheck()) {
|
|
||||||
throwNewErrno(e, "java/io/IOException");
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void
|
|
||||||
unmap(JNIEnv*, Mapping* mapping)
|
|
||||||
{
|
|
||||||
munmap(mapping->start, mapping->length);
|
|
||||||
free(mapping);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // not PLATFORM_WINDOWS
|
#endif // not PLATFORM_WINDOWS
|
||||||
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
inline string_t getChars(JNIEnv* e, jstring path) {
|
inline string_t getChars(JNIEnv* e, jstring path) {
|
||||||
@ -785,35 +683,54 @@ Java_java_io_RandomAccessFile_open(JNIEnv* e, jclass, jstring path,
|
|||||||
{
|
{
|
||||||
string_t chars = getChars(e, path);
|
string_t chars = getChars(e, path);
|
||||||
if (chars) {
|
if (chars) {
|
||||||
Mapping* mapping = map(e, chars);
|
int fd = ::open((const char*)chars, O_RDONLY);
|
||||||
|
releaseChars(e, path, chars);
|
||||||
|
if (fd == -1) {
|
||||||
|
throwNewErrno(e, "java/io/IOException");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
struct ::stat fileStats;
|
||||||
|
if(::fstat(fd, &fileStats) == -1) {
|
||||||
|
::close(fd);
|
||||||
|
throwNewErrno(e, "java/io/IOException");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
jlong peer = reinterpret_cast<jlong>(mapping);
|
jlong peer = fd;
|
||||||
e->SetLongArrayRegion(result, 0, 1, &peer);
|
e->SetLongArrayRegion(result, 0, 1, &peer);
|
||||||
|
|
||||||
jlong length = (mapping ? mapping->length : 0);
|
jlong length = fileStats.st_size;
|
||||||
e->SetLongArrayRegion(result, 1, 1, &length);
|
e->SetLongArrayRegion(result, 1, 1, &length);
|
||||||
|
|
||||||
releaseChars(e, path, chars);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
Java_java_io_RandomAccessFile_copy(JNIEnv* e, jclass, jlong peer,
|
Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, jclass, jlong peer,
|
||||||
jlong position, jbyteArray buffer,
|
jlong position, jbyteArray buffer,
|
||||||
int offset, int length)
|
int offset, int length)
|
||||||
{
|
{
|
||||||
|
int fd = (int)peer;
|
||||||
|
if(::lseek(fd, position, SEEK_SET) == -1) {
|
||||||
|
throwNewErrno(e, "java/io/IOException");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t* dst = reinterpret_cast<uint8_t*>
|
uint8_t* dst = reinterpret_cast<uint8_t*>
|
||||||
(e->GetPrimitiveArrayCritical(buffer, 0));
|
(e->GetPrimitiveArrayCritical(buffer, 0));
|
||||||
|
ssize_t bytesRead = ::read(fd, dst + offset, length);
|
||||||
memcpy(dst + offset,
|
|
||||||
reinterpret_cast<Mapping*>(peer)->start + position,
|
|
||||||
length);
|
|
||||||
|
|
||||||
e->ReleasePrimitiveArrayCritical(buffer, dst, 0);
|
e->ReleasePrimitiveArrayCritical(buffer, dst, 0);
|
||||||
|
|
||||||
|
if(bytesRead == -1) {
|
||||||
|
throwNewErrno(e, "java/io/IOException");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (jint)bytesRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_io_RandomAccessFile_close(JNIEnv* e, jclass, jlong peer)
|
Java_java_io_RandomAccessFile_close(JNIEnv*/* e*/, jclass, jlong peer)
|
||||||
{
|
{
|
||||||
unmap(e, reinterpret_cast<Mapping*>(peer));
|
int fd = (int)peer;
|
||||||
|
::close(fd);
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
package java.io;
|
package java.io;
|
||||||
|
|
||||||
|
import java.lang.IllegalArgumentException;
|
||||||
|
|
||||||
public class RandomAccessFile {
|
public class RandomAccessFile {
|
||||||
private long peer;
|
private long peer;
|
||||||
private File file;
|
private File file;
|
||||||
@ -61,27 +63,62 @@ public class RandomAccessFile {
|
|||||||
this.position = position + count;
|
this.position = position + count;
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void readFully(byte[] buffer, int offset, int length)
|
public int read(byte b[], int off, int len) throws IOException {
|
||||||
throws IOException
|
if(b == null)
|
||||||
{
|
throw new IllegalArgumentException();
|
||||||
if (peer == 0) throw new IOException();
|
if (peer == 0)
|
||||||
|
throw new IOException();
|
||||||
if (length == 0) return;
|
if(len == 0)
|
||||||
|
return 0;
|
||||||
if (position + length > this.length) {
|
if (position + len > this.length)
|
||||||
if (position + length > length()) throw new EOFException();
|
throw new EOFException();
|
||||||
}
|
if (off < 0 || off + len > b.length)
|
||||||
|
|
||||||
if (offset < 0 || offset + length > buffer.length)
|
|
||||||
throw new ArrayIndexOutOfBoundsException();
|
throw new ArrayIndexOutOfBoundsException();
|
||||||
|
int bytesRead = readBytes(peer, position, b, off, len);
|
||||||
copy(peer, position, buffer, offset, length);
|
position += bytesRead;
|
||||||
|
return bytesRead;
|
||||||
position += length;
|
}
|
||||||
|
|
||||||
|
public int read(byte b[]) throws IOException {
|
||||||
|
if(b == null)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
if (peer == 0)
|
||||||
|
throw new IOException();
|
||||||
|
if(b.length == 0)
|
||||||
|
return 0;
|
||||||
|
if (position + b.length > this.length)
|
||||||
|
throw new EOFException();
|
||||||
|
int bytesRead = readBytes(peer, position, b, 0, b.length);
|
||||||
|
position += bytesRead;
|
||||||
|
return bytesRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static native void copy(long peer, long position, byte[] buffer,
|
public void readFully(byte b[], int off, int len) throws IOException {
|
||||||
|
if(b == null)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
if (peer == 0)
|
||||||
|
throw new IOException();
|
||||||
|
if(len == 0)
|
||||||
|
return;
|
||||||
|
if (position + len > this.length)
|
||||||
|
throw new EOFException();
|
||||||
|
if (off < 0 || off + len > b.length)
|
||||||
|
throw new ArrayIndexOutOfBoundsException();
|
||||||
|
int n = 0;
|
||||||
|
do {
|
||||||
|
int count = readBytes(peer, position, b, off + n, len - n);
|
||||||
|
if (count < 0)
|
||||||
|
throw new EOFException();
|
||||||
|
n += count;
|
||||||
|
} while (n < len);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void readFully(byte b[]) throws IOException {
|
||||||
|
readFully(b, 0, b.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native int readBytes(long peer, long position, byte[] buffer,
|
||||||
int offset, int length);
|
int offset, int length);
|
||||||
|
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
|
Loading…
Reference in New Issue
Block a user