1 30 31 32 package org.hsqldb.persist; 33 34 import java.io.IOException ; 35 import java.io.RandomAccessFile ; 36 import java.nio.MappedByteBuffer ; 37 import java.nio.channels.FileChannel ; 38 39 import org.hsqldb.Database; 40 import org.hsqldb.Trace; 41 import org.hsqldb.lib.SimpleLog; 42 43 55 class ScaledRAFileNIO implements ScaledRAInterface { 56 57 private final boolean readOnly; 58 private final long bufferLength; 59 private RandomAccessFile file; 60 private MappedByteBuffer buffer; 61 private FileChannel channel; 62 private boolean bufferModified; 63 private SimpleLog appLog; 64 private final static String JVM_ERROR = "JVM threw unsupported Exception"; 65 66 ScaledRAFileNIO(Database database, String name, boolean readOnly, 67 int bufferLength) throws Throwable { 68 69 long fileLength; 70 71 if (bufferLength < 1 << 18) { 72 bufferLength = 1 << 18; 73 } 74 75 try { 76 file = new RandomAccessFile (name, readOnly ? "r" 77 : "rw"); 78 } catch (Throwable e) { 79 throw e; 80 } 81 82 try { 83 fileLength = file.length(); 84 } catch (Throwable e) { 85 file.close(); 86 87 throw e; 88 } 89 90 if (fileLength > ScaledRAFile.MAX_NIO_LENGTH) { 91 file.close(); 92 93 throw new IOException ("length exceeds nio limit"); 94 } 95 96 if (bufferLength < fileLength) { 97 bufferLength = (int) fileLength; 98 } 99 100 bufferLength = newNIOBufferSize(bufferLength); 101 102 if (readOnly) { 103 bufferLength = (int) fileLength; 104 } 105 106 if (fileLength < bufferLength) { 107 try { 108 file.seek(bufferLength - 1); 109 file.writeByte(0); 110 file.getFD().sync(); 111 file.close(); 112 113 file = new RandomAccessFile (name, readOnly ? "r" 114 : "rw"); 115 } catch (Throwable e) { 116 file.close(); 117 118 throw e; 119 } 120 } 121 122 this.appLog = database.logger.appLog; 123 this.readOnly = readOnly; 124 this.bufferLength = bufferLength; 125 this.channel = file.getChannel(); 126 127 try { 128 buffer = channel.map(readOnly ? FileChannel.MapMode.READ_ONLY 129 : FileChannel.MapMode.READ_WRITE, 0, 130 bufferLength); 131 132 Trace.printSystemOut("NIO file instance created. mode: " 133 + readOnly); 134 135 if (!readOnly) { 136 long tempSize = bufferLength - fileLength; 137 138 if (tempSize > 1 << 18) { 139 tempSize = 1 << 18; 140 } 141 142 byte[] temp = new byte[(int) tempSize]; 143 144 try { 145 long pos = fileLength; 146 147 for (; pos < bufferLength - tempSize; pos += tempSize) { 148 buffer.position((int) pos); 149 buffer.put(temp, 0, temp.length); 150 } 151 152 buffer.position((int) pos); 153 buffer.put(temp, 0, (int) (bufferLength - pos)); 154 buffer.force(); 155 } catch (Throwable t) { 156 appLog.logContext(t, JVM_ERROR + " " + "length: " 157 + bufferLength); 158 } 159 160 buffer.position(0); 161 } 162 } catch (Throwable e) { 163 Trace.printSystemOut("NIO constructor failed: " + bufferLength); 164 165 buffer = null; 166 channel = null; 167 168 file.close(); 169 System.gc(); 170 171 throw e; 172 } 173 } 174 175 public long length() throws IOException { 176 177 try { 178 return file.length(); 179 } catch (IOException e) { 180 appLog.logContext(e, "nio"); 181 182 throw e; 183 } catch (Throwable e) { 184 appLog.logContext(e, JVM_ERROR); 185 186 throw new IOException (e.toString()); 187 } 188 } 189 190 public void seek(long newPos) throws IOException { 191 192 try { 193 buffer.position((int) newPos); 194 } catch (IllegalArgumentException e) { 195 appLog.logContext(e, "nio"); 196 197 throw new IOException (e.toString()); 198 } catch (Throwable e) { 199 appLog.logContext(e, JVM_ERROR); 200 201 throw new IOException (e.toString()); 202 } 203 } 204 205 public long getFilePointer() throws IOException { 206 207 try { 208 return buffer.position(); 209 } catch (Throwable e) { 210 appLog.logContext(e, JVM_ERROR); 211 212 throw new IOException (e.toString()); 213 } 214 } 215 216 public int read() throws IOException { 217 218 try { 219 return buffer.get(); 220 } catch (Throwable e) { 221 appLog.logContext(e, JVM_ERROR); 222 223 throw new IOException (e.toString()); 224 } 225 } 226 227 public void read(byte[] b, int offset, int length) throws IOException { 228 229 try { 230 buffer.get(b, offset, length); 231 } catch (Throwable e) { 232 appLog.logContext(e, JVM_ERROR); 233 234 throw new IOException (e.toString()); 235 } 236 } 237 238 public int readInt() throws IOException { 239 240 try { 241 return buffer.getInt(); 242 } catch (Throwable e) { 243 appLog.logContext(e, JVM_ERROR); 244 245 throw new IOException (e.toString()); 246 } 247 } 248 249 public long readLong() throws IOException { 250 251 try { 252 return buffer.getLong(); 253 } catch (Throwable e) { 254 appLog.logContext(e, JVM_ERROR); 255 256 throw new IOException (e.toString()); 257 } 258 } 259 260 public void write(byte[] b, int offset, int len) throws IOException { 261 262 try { 263 bufferModified = true; 264 265 buffer.put(b, offset, len); 266 } catch (Throwable e) { 267 appLog.logContext(e, JVM_ERROR); 268 269 throw new IOException (e.toString()); 270 } 271 } 272 273 public void writeInt(int i) throws IOException { 274 275 try { 276 bufferModified = true; 277 278 buffer.putInt(i); 279 } catch (Throwable e) { 280 appLog.logContext(e, JVM_ERROR); 281 282 throw new IOException (e.toString()); 283 } 284 } 285 286 public void writeLong(long i) throws IOException { 287 288 try { 289 bufferModified = true; 290 291 buffer.putLong(i); 292 } catch (Throwable e) { 293 appLog.logContext(e, JVM_ERROR); 294 295 throw new IOException (e.toString()); 296 } 297 } 298 299 public void close() throws IOException { 300 301 try { 302 Trace.printSystemOut("NIO close() start - fileLength = " 303 + bufferLength); 304 305 if (buffer != null && bufferModified) { 306 try { 307 buffer.force(); 308 } catch (Throwable t) { 309 try { 310 buffer.force(); 311 } catch (Throwable t1) { 312 appLog.logContext(t, JVM_ERROR + " " + "length: " 313 + bufferLength); 314 } 315 } 316 } 317 318 buffer = null; 319 channel = null; 320 321 file.close(); 322 System.gc(); 323 } catch (Throwable e) { 324 appLog.logContext(e, "length: " + bufferLength); 325 326 throw new IOException (e.toString()); 327 } 328 } 329 330 public boolean isReadOnly() { 331 return readOnly; 332 } 333 334 public boolean wasNio() { 335 return true; 336 } 337 338 public boolean canAccess(int length) { 339 return buffer.position() + length <= bufferLength; 340 } 341 342 public boolean canSeek(long position) { 343 return position <= bufferLength; 344 } 345 346 public Database getDatabase() { 347 return null; 348 } 349 350 static int newNIOBufferSize(int newSize) { 351 352 int bufSize = 0; 353 354 for (int scale = 20; scale < 30; scale++) { 355 bufSize = 1 << scale; 356 357 if (bufSize >= newSize) { 358 break; 359 } 360 } 361 362 return bufSize; 363 } 364 } 365 | Popular Tags |