]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.acorn/src/org/simantics/acorn/FileIO.java
Merge commit 'a2a4242'
[simantics/platform.git] / bundles / org.simantics.acorn / src / org / simantics / acorn / FileIO.java
1 package org.simantics.acorn;
2
3 import java.io.BufferedOutputStream;
4 import java.io.IOException;
5 import java.io.OutputStream;
6 import java.io.RandomAccessFile;
7 import java.nio.ByteBuffer;
8 import java.nio.channels.FileChannel;
9 import java.nio.channels.SeekableByteChannel;
10 import java.nio.file.Files;
11 import java.nio.file.OpenOption;
12 import java.nio.file.Path;
13 import java.nio.file.Paths;
14 import java.nio.file.StandardOpenOption;
15 import java.nio.file.attribute.FileAttribute;
16 import java.util.HashMap;
17 import java.util.HashSet;
18 import java.util.Map;
19 import java.util.Set;
20
21 import org.simantics.databoard.file.RuntimeIOException;
22
23 public class FileIO {
24         
25     private static final FileAttribute<?>[] NO_ATTRIBUTES = new FileAttribute[0];
26     
27     private static final Set<OpenOption> CREATE_OPTIONS = new HashSet<>(2);
28     private static final Set<OpenOption> APPEND_OPTIONS = new HashSet<>(1);
29     
30     static {
31         CREATE_OPTIONS.add(StandardOpenOption.WRITE);
32         CREATE_OPTIONS.add(StandardOpenOption.CREATE);
33         
34         APPEND_OPTIONS.add(StandardOpenOption.APPEND);
35     }
36     
37         private Path path;
38         private int writePosition = 0;
39
40         private FileIO(Path path) {
41                 this.path = path;
42         }
43         
44         private static Map<Path, FileIO> map = new HashMap<Path, FileIO>();
45         
46         public static FileIO get(Path path) {
47                 synchronized(map) {
48                         FileIO existing = map.get(path);
49                         if(existing == null) {
50                                 existing = new FileIO(path);
51                                 map.put(path, existing);
52                         }
53                         return existing;
54                 }
55         }
56         
57         //private static final boolean TRACE_SWAP = false;
58         private static final boolean TRACE_PERF = false;
59
60         public synchronized int saveBytes(byte[] bytes, int length, boolean overwrite) throws IOException {
61                 if(overwrite) writePosition = 0;
62                 int result = writePosition;
63                 long start = System.nanoTime();
64                 Set<OpenOption> options = writePosition == 0 ? CREATE_OPTIONS : APPEND_OPTIONS;
65                 
66                 ByteBuffer bb = ByteBuffer.wrap(bytes, 0, length);
67                 try (FileChannel fc = FileChannel.open(path, options, NO_ATTRIBUTES)) {
68             fc.write(bb);
69             
70             writePosition += length;
71             if(TRACE_PERF) {
72                 long duration = System.nanoTime()-start;
73                 double ds = 1e-9*duration;
74                 System.err.println("Wrote " + bytes.length + " bytes @ " + 1e-6*bytes.length / ds + "MB/s");
75             }
76             return result;
77                 } catch (Throwable t) {
78                     throw new IOException("An error occured file saving bytes for file " + path.toAbsolutePath().toString(), t);
79                 }
80         }
81
82     public synchronized byte[] readBytes(int offset, int length) throws IOException {
83         long start = System.nanoTime();
84         try (SeekableByteChannel channel = Files.newByteChannel(path)) {
85             channel.position(offset);
86             ByteBuffer buf = ByteBuffer.allocate(length);
87             int read = 0;
88             while (read < length) {
89                 read += channel.read(buf);
90             }
91             byte[] result = buf.array();
92             if (result.length != length)
93                 System.err.println("faa");
94             if (TRACE_PERF) {
95                 long duration = System.nanoTime() - start;
96                 double ds = 1e-9 * duration;
97                 System.err.println("Read " + result.length + " bytes @ " + 1e-6 * result.length / ds + "MB/s");
98             }
99             return result;
100         }
101     }
102
103         public static void syncPath(Path f) throws IOException {
104                 // Does not seem to need 's' according to unit test in Windows
105                 try (RandomAccessFile raf = new RandomAccessFile(f.toFile(), "rw")) {
106                         raf.getFD().sync();
107                 }
108         }
109
110         static void uncheckedSyncPath(Path f) {
111                 try {
112                         syncPath(f);
113                 } catch (IOException e) {
114                         throw new RuntimeIOException(e);
115                 }
116         }
117
118         public static void main(String[] args) throws Exception {
119
120                 byte[] buf = new byte[1024*1024];
121                 
122                 long s = System.nanoTime();
123                 
124                 Path test = Paths.get("e:/work/test.dat");
125                 OutputStream fs = Files.newOutputStream(test);
126                 OutputStream os = new BufferedOutputStream(fs, 128*1024);
127                 
128                 for(int i=0;i<40;i++) {
129                         os.write(buf);
130                 }
131                 
132                 os.flush();
133                 //fs.getFD().sync();
134                 os.close();
135                 
136                 syncPath(test);
137                 
138                 long duration = System.nanoTime()-s;
139                 System.err.println("Took " + 1e-6*duration + "ms.");
140                 
141                 
142         }
143         
144 }