001package org.biojava.utils.io; 002 003import java.io.IOException; 004import java.nio.MappedByteBuffer; 005import java.nio.channels.FileChannel; 006 007import org.biojava.utils.Constants; 008 009/** 010 * Wrapper arround MappedByteBuffers to allow long-indexed access to files 011 * larger than 2 gigs. 012 * 013 * @author Matthews Pocock 014 */ 015public class LargeBuffer { 016 /* 017 * We will set up MappedByteBuffers that are responsible for PAGE_SIZE 018 * bytes. Unfortunately, word boundaries are not aligned, so someone could 019 * try to write a double to the last byte in a buffer. So, 020 */ 021 022 private static final long PAGE_SIZE; 023 private static final long PAGE_OVERLAP; 024 025 static { 026 PAGE_OVERLAP = Constants.BYTES_IN_LONG; 027 PAGE_SIZE = Integer.MAX_VALUE / 8 - PAGE_OVERLAP; 028 } 029 030 private final long pos; 031 private final long size; 032 private final FileChannel channel; 033 private final FileChannel.MapMode mode; 034 035 private long position = 0; 036 private int lastBufferIndex = -1; 037 private MappedByteBuffer lastBuffer = null; 038 039 040 public LargeBuffer( 041 FileChannel channel, 042 FileChannel.MapMode mode, 043 long pos, 044 long size 045 ) throws IOException { 046 this.channel = channel; 047 this.mode = mode; 048 this.pos = pos; 049 this.size = size; 050 } 051 052 private MappedByteBuffer getBuffer(int index) 053 throws IOException { 054 if(index != lastBufferIndex) { 055 System.out.println("Allocating page: " + index); 056 long offset = PAGE_SIZE * index; 057 System.out.println("From: " + (pos + offset)); 058 System.out.println("Size: " + Math.min(size - offset, PAGE_SIZE + PAGE_OVERLAP)); 059 lastBuffer = channel.map( 060 mode, 061 pos + offset, 062 Math.min(size - offset, PAGE_SIZE + PAGE_OVERLAP) 063 ); 064 lastBufferIndex = index; 065 System.out.println("Done"); 066 } 067 068 return lastBuffer; 069 } 070 071 public byte get(long pos) 072 throws IndexOutOfBoundsException, IOException { 073 int offset = getOffset(pos); 074 int index = getIndex(pos); 075 076 MappedByteBuffer buffer = getBuffer(index); 077 return buffer.get(offset); 078 } 079 080 public byte get() 081 throws IndexOutOfBoundsException, IOException { 082 byte val = get(position); 083 position += Constants.BYTES_IN_BYTE; 084 return val; 085 } 086 087 public void put(long pos, byte b) 088 throws IndexOutOfBoundsException, IOException { 089 int offset = getOffset(pos); 090 int index = getIndex(pos); 091 092 MappedByteBuffer buffer = getBuffer(index); 093 buffer.put(offset, b); 094 } 095 096 public void put(byte val) 097 throws IndexOutOfBoundsException, IOException { 098 put(position, val); 099 position += Constants.BYTES_IN_BYTE; 100 } 101 102 public char getChar(long pos) 103 throws IndexOutOfBoundsException, IOException { 104 int offset = getOffset(pos); 105 int index = getIndex(pos); 106 107 MappedByteBuffer buffer = getBuffer(index); 108 return buffer.getChar(offset); 109 } 110 111 public char getChar() 112 throws IndexOutOfBoundsException, IOException { 113 char val = getChar(position); 114 position += Constants.BYTES_IN_CHAR; 115 return val; 116 } 117 118 public void putChar(long pos, char c) 119 throws IndexOutOfBoundsException, IOException { 120 int offset = getOffset(pos); 121 int index = getIndex(pos); 122 123 MappedByteBuffer buffer = getBuffer(index); 124 buffer.putChar(offset, c); 125 } 126 127 public void putChar(char val) 128 throws IndexOutOfBoundsException, IOException { 129 putChar(position, val); 130 position += Constants.BYTES_IN_CHAR; 131 } 132 133 public double getDouble(long pos) 134 throws IndexOutOfBoundsException, IOException { 135 int offset = getOffset(pos); 136 int index = getIndex(pos); 137 138 MappedByteBuffer buffer = getBuffer(index); 139 return buffer.getDouble(offset); 140 } 141 142 public double getDouble() 143 throws IndexOutOfBoundsException, IOException { 144 double val = getDouble(position); 145 position += Constants.BYTES_IN_DOUBLE; 146 return val; 147 } 148 149 public void putDouble(long pos, double d) 150 throws IndexOutOfBoundsException, IOException { 151 int offset = getOffset(pos); 152 int index = getIndex(pos); 153 154 MappedByteBuffer buffer = getBuffer(index); 155 buffer.putDouble(offset, d); 156 } 157 158 public void putDouble(double val) 159 throws IndexOutOfBoundsException, IOException { 160 putDouble(position, val); 161 position += Constants.BYTES_IN_DOUBLE; 162 } 163 164 public float getFloat(long pos) 165 throws IndexOutOfBoundsException, IOException { 166 int offset = getOffset(pos); 167 int index = getIndex(pos); 168 169 MappedByteBuffer buffer = getBuffer(index); 170 return buffer.getFloat(offset); 171 } 172 173 public float getFloat() 174 throws IndexOutOfBoundsException, IOException { 175 float val = getFloat(position); 176 position += Constants.BYTES_IN_FLOAT; 177 return val; 178 } 179 180 public void putFloat(long pos, float f) 181 throws IndexOutOfBoundsException, IOException { 182 int offset = getOffset(pos); 183 int index = getIndex(pos); 184 185 MappedByteBuffer buffer = getBuffer(index); 186 buffer.putFloat(offset, f); 187 } 188 189 public void putFloat(float val) 190 throws IndexOutOfBoundsException, IOException { 191 putFloat(position, val); 192 position += Constants.BYTES_IN_FLOAT; 193 } 194 195 public int getInt(long pos) 196 throws IndexOutOfBoundsException, IOException { 197 int offset = getOffset(pos); 198 int index = getIndex(pos); 199 200 MappedByteBuffer buffer = getBuffer(index); 201 return buffer.getInt(offset); 202 } 203 204 public int getInt() 205 throws IndexOutOfBoundsException, IOException { 206 int val = getInt(position); 207 position += Constants.BYTES_IN_INT; 208 return val; 209 } 210 211 public void putInt(long pos, int i) 212 throws IndexOutOfBoundsException, IOException { 213 int offset = getOffset(pos); 214 int index = getIndex(pos); 215 216 MappedByteBuffer buffer = getBuffer(index); 217 buffer.putInt(offset, i); 218 } 219 220 public void putInt(int val) 221 throws IndexOutOfBoundsException, IOException { 222 putInt(position, val); 223 position += Constants.BYTES_IN_INT; 224 } 225 226 public long getLong(long pos) 227 throws IndexOutOfBoundsException, IOException { 228 int offset = getOffset(pos); 229 int index = getIndex(pos); 230 231 MappedByteBuffer buffer = getBuffer(index); 232 return buffer.getLong(offset); 233 } 234 235 public long getLong() 236 throws IndexOutOfBoundsException, IOException { 237 long val = getLong(position); 238 position += Constants.BYTES_IN_LONG; 239 return val; 240 } 241 242 public void putLong(long pos, long l) 243 throws IndexOutOfBoundsException, IOException { 244 int offset = getOffset(pos); 245 int index = getIndex(pos); 246 247 MappedByteBuffer buffer = getBuffer(index); 248 buffer.putLong(offset, l); 249 } 250 251 public void putLong(long val) 252 throws IndexOutOfBoundsException, IOException { 253 putLong(position, val); 254 position += Constants.BYTES_IN_LONG; 255 } 256 257 public short getShort(long pos) 258 throws IndexOutOfBoundsException, IOException { 259 int offset = getOffset(pos); 260 int index = getIndex(pos); 261 262 MappedByteBuffer buffer = getBuffer(index); 263 return buffer.getShort(offset); 264 } 265 266 public short getShort() 267 throws IndexOutOfBoundsException, IOException { 268 short val = getShort(position); 269 position += Constants.BYTES_IN_SHORT; 270 return val; 271 } 272 273 public void putShort(long pos, short s) 274 throws IndexOutOfBoundsException, IOException { 275 int offset = getOffset(pos); 276 int index = getIndex(pos); 277 278 MappedByteBuffer buffer = getBuffer(index); 279 buffer.putShort(offset, s); 280 } 281 282 public void putShort(short val) 283 throws IndexOutOfBoundsException, IOException { 284 putShort(position, val); 285 position += Constants.BYTES_IN_SHORT; 286 } 287 288 public long position() { 289 return position; 290 } 291 292 public void position(long pos) { 293 this.position = pos; 294 } 295 296 private int getOffset(long pos) 297 throws IndexOutOfBoundsException { 298 if(pos > size) { 299 throw new IndexOutOfBoundsException(); 300 } 301 return (int) (pos % PAGE_SIZE); 302 } 303 304 private int getIndex(long pos) { 305 return (int) (pos / (long) PAGE_SIZE); 306 } 307 308 public void force() { 309// for(Iterator i = buffers.iterator(); i.hasNext(); ) { 310// MappedByteBuffer buff = (MappedByteBuffer) i.next(); 311// buff.force(); 312// } 313 } 314}