1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
package com.huadi.utils.directio.io;
import java.io.IOException;
import java.io.OutputStream;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.PointerByReference;
public class JNAOutputStream extends OutputStream {
//just a couple of them are used, here for eventual future uses
protected static final int O_RDONLY = 00;
protected static final int O_WRONLY = 01;
protected static final int O_RDWR = 02;
protected static final int O_CREAT = 0100;
protected static final int O_EXCL = 0200;
protected static final int O_NOCTTY = 0400;
protected static final int O_TRUNC = 01000;
protected static final int O_APPEND = 02000;
protected static final int O_NONBLOCK = 04000;
protected static final int O_NDELAY = O_NONBLOCK;
protected static final int O_SYNC = 010000;
protected static final int O_ASYNC = 020000;
protected static final int O_DIRECT = 040000;
protected static final int O_DIRECTORY = 0200000;
protected static final int O_NOFOLLOW = 0400000;
protected static final int O_NOATIME = 01000000;
protected static final int O_CLOEXEC = 02000000;
//fcntl has also other flags, not presented here
protected static final int F_SETFL = 4;
public static final int BLOCK_SIZE = 512;
static {
Native.register("c");
}
private native int open(String pathname, int flags, int mode);
private native int fcntl(int id, int cmd, int flags);
private native int write(int fd, Pointer buf, int count);
private native int posix_memalign(PointerByReference memptr, int alignment, int size);
private native int close(int fd);
private int fd;
private Pointer bufPnt;
private byte[] buffer;
private int pos;
public JNAOutputStream(String pathname, boolean direct) throws IOException {
if (!direct) {
fd = open(pathname, O_CREAT|O_TRUNC|O_WRONLY, 00755);
} else {
// fd = open(pathname, O_CREAT|O_TRUNC|O_WRONLY|O_DIRECT, 00755);
fd = open(pathname, O_CREAT|O_APPEND|O_WRONLY|O_DIRECT, 00755);
}
PointerByReference pntByRef = new PointerByReference();
posix_memalign(pntByRef, BLOCK_SIZE, BLOCK_SIZE);
bufPnt = pntByRef.getValue();
buffer = new byte[BLOCK_SIZE];
}
@Override
public void close() throws IOException {
if (pos % BLOCK_SIZE != 0) {
if (fcntl(fd, F_SETFL, ~O_DIRECT) < 0) {
throw new IOException("Impossible to modify fd on close()");
}
bufPnt.write(0, buffer, 0, pos);
int rtn = write(fd,bufPnt,pos);
if (rtn != pos) {
throw new IOException(rtn+"/"+pos+" bytes written to disk on close()");
}
}
if (close(fd)< 0) {
throw new IOException("Problems occured while doing close()");
}
}
@Override
public void write(int b) throws IOException {
if (pos < BLOCK_SIZE) {
buffer[pos++] = (byte)b;
}
if (pos == BLOCK_SIZE) {
bufPnt.write(0, buffer, 0, BLOCK_SIZE);
int rtn = write(fd, bufPnt, BLOCK_SIZE);
if (rtn != BLOCK_SIZE) {
throw new IOException(rtn+"/"+BLOCK_SIZE+" bytes written to disk");
}
pos = 0;
}
}
}
|