@Override public DataAccess createDataAccess(String name) { return new RAMDataAccess(name, directory, true, defaultOrder).setSegmentSize(128); } }
@Override public void rename(String newName) { if (!checkBeforeRename(newName)) { return; } if (store) { super.rename(newName); } // in every case set the name name = newName; }
@Override public DataAccess copyTo(DataAccess da) { if (da instanceof RAMDataAccess) { copyHeader(da); RAMDataAccess rda = (RAMDataAccess) da; // TODO PERFORMANCE we could reuse rda segments! rda.segments = new byte[segments.length][]; for (int i = 0; i < segments.length; i++) { byte[] area = segments[i]; rda.segments[i] = Arrays.copyOf(area, area.length); } rda.setSegmentSize(segmentSizeInBytes); // leave id, store and close unchanged return da; } else { return super.copyTo(da); } }
@Override public RAMDataAccess create(long bytes) { if (segments.length > 0) throw new IllegalThreadStateException("already created"); setSegmentSize(segmentSizeInBytes); ensureCapacity(Math.max(10 * 4, bytes)); return this; }
@Override public void flush() { if (closed) throw new IllegalStateException("already closed"); if (!store) return; try { RandomAccessFile raFile = new RandomAccessFile(getFullName(), "rw"); try { long len = getCapacity(); writeHeader(raFile, len, segmentSizeInBytes); raFile.seek(HEADER_OFFSET); // raFile.writeInt() <- too slow, so copy into byte array for (int s = 0; s < segments.length; s++) { byte area[] = segments[s]; raFile.write(area); } } finally { raFile.close(); } } catch (Exception ex) { throw new RuntimeException("Couldn't store bytes to " + toString(), ex); } }
throw new IllegalStateException("already initialized"); if (isClosed()) throw new IllegalStateException("already closed"); return false; File file = new File(getFullName()); if (!file.exists() || file.length() == 0) return false; RandomAccessFile raFile = new RandomAccessFile(getFullName(), "r"); try { long byteCount = readHeader(raFile) - HEADER_OFFSET; if (byteCount < 0) return false; int read = raFile.read(bytes); if (read <= 0) throw new IllegalStateException("segment " + s + " is empty? " + toString()); throw new RuntimeException("Problem while loading " + getFullName(), ex);
@Override public DataAccess find(String name, DAType type) { if (!name.equals(toLowerCase(name))) throw new IllegalArgumentException("Since 0.7 DataAccess objects does no longer accept upper case names"); DataAccess da = map.get(name); if (da != null) { if (!type.equals(da.getType())) throw new IllegalStateException("Found existing DataAccess object '" + name + "' but types did not match. Requested:" + type + ", was:" + da.getType()); return da; } if (type.isInMemory()) { if (type.isInteg()) { if (type.isStoring()) da = new RAMIntDataAccess(name, location, true, byteOrder); else da = new RAMIntDataAccess(name, location, false, byteOrder); } else if (type.isStoring()) da = new RAMDataAccess(name, location, true, byteOrder); else da = new RAMDataAccess(name, location, false, byteOrder); } else if (type.isMMap()) { da = new MMapDataAccess(name, location, byteOrder, type.isAllowWrites()); } else { da = new UnsafeDataAccess(name, location, byteOrder); } map.put(name, da); return da; }
@Override public void trimTo(long capacity) { if (capacity > getCapacity()) { throw new IllegalStateException("Cannot increase capacity (" + getCapacity() + ") to " + capacity + " via trimTo. Use ensureCapacity instead. "); } if (capacity < segmentSizeInBytes) capacity = segmentSizeInBytes; int remainingSegments = (int) (capacity / segmentSizeInBytes); if (capacity % segmentSizeInBytes != 0) { remainingSegments++; } segments = Arrays.copyOf(segments, remainingSegments); }
@Override public long getCapacity() { return (long) getSegments() * segmentSizeInBytes; }
@Override public final int getInt(long bytePos) { assert segmentSizePower > 0 : "call create or loadExisting before usage!"; int bufferIndex = (int) (bytePos >>> segmentSizePower); int index = (int) (bytePos & indexDivisor); assert index + 4 <= segmentSizeInBytes : "integer cannot be distributed over two segments"; if (bufferIndex > segments.length) { LoggerFactory.getLogger(getClass()).error(getName() + ", segments:" + segments.length + ", bufIndex:" + bufferIndex + ", bytePos:" + bytePos + ", segPower:" + segmentSizePower); } return bitUtil.toInt(segments[bufferIndex], index); }
@Override public void flush() { if (closed) throw new IllegalStateException("already closed"); if (!store) return; try { RandomAccessFile raFile = new RandomAccessFile(getFullName(), "rw"); try { long len = getCapacity(); writeHeader(raFile, len, segmentSizeInBytes); raFile.seek(HEADER_OFFSET); // raFile.writeInt() <- too slow, so copy into byte array for (int s = 0; s < segments.length; s++) { byte area[] = segments[s]; raFile.write(area); } } finally { raFile.close(); } } catch (Exception ex) { throw new RuntimeException("Couldn't store bytes to " + toString(), ex); } }
throw new IllegalStateException("already initialized"); if (isClosed()) throw new IllegalStateException("already closed"); return false; File file = new File(getFullName()); if (!file.exists() || file.length() == 0) return false; RandomAccessFile raFile = new RandomAccessFile(getFullName(), "r"); try { long byteCount = readHeader(raFile) - HEADER_OFFSET; if (byteCount < 0) return false; int read = raFile.read(bytes); if (read <= 0) throw new IllegalStateException("segment " + s + " is empty? " + toString()); throw new RuntimeException("Problem while loading " + getFullName(), ex);
@Override public RAMDataAccess create(long bytes) { if (segments.length > 0) throw new IllegalThreadStateException("already created"); // initialize transient values setSegmentSize(segmentSizeInBytes); ensureCapacity(Math.max(10 * 4, bytes)); return this; }
@Test public void textMixRAM2MMAP() { DataAccess da = new RAMDataAccess(name, directory, true, defaultOrder); assertFalse(da.loadExisting()); da.create(100); da.setInt(7 * 4, 123); da.flush(); da.close(); da = createDataAccess(name); assertTrue(da.loadExisting()); assertEquals(123, da.getInt(7 * 4)); da.close(); }
@Override public boolean ensureCapacity(long bytes) { if (bytes < 0) throw new IllegalArgumentException("new capacity has to be strictly positive"); long cap = getCapacity(); long newBytes = bytes - cap; if (newBytes <= 0) return false; int segmentsToCreate = (int) (newBytes / segmentSizeInBytes); if (newBytes % segmentSizeInBytes != 0) segmentsToCreate++; try { byte[][] newSegs = Arrays.copyOf(segments, segments.length + segmentsToCreate); for (int i = segments.length; i < newSegs.length; i++) { newSegs[i] = new byte[1 << segmentSizePower]; } segments = newSegs; } catch (OutOfMemoryError err) { throw new OutOfMemoryError(err.getMessage() + " - problem when allocating new memory. Old capacity: " + cap + ", new bytes:" + newBytes + ", segmentSizeIntsPower:" + segmentSizePower + ", new segments:" + segmentsToCreate + ", existing:" + segments.length); } return true; }
@Override public long getCapacity() { return (long) getSegments() * segmentSizeInBytes; }
@Override public final int getInt(long bytePos) { assert segmentSizePower > 0 : "call create or loadExisting before usage!"; int bufferIndex = (int) (bytePos >>> segmentSizePower); int index = (int) (bytePos & indexDivisor); assert index + 4 <= segmentSizeInBytes : "integer cannot be distributed over two segments"; if (bufferIndex > segments.length) { LoggerFactory.getLogger(getClass()).error(getName() + ", segments:" + segments.length + ", bufIndex:" + bufferIndex + ", bytePos:" + bytePos + ", segPower:" + segmentSizePower); } return bitUtil.toInt(segments[bufferIndex], index); }
@Override public void flush() { if (closed) throw new IllegalStateException("already closed"); if (!store) return; try { RandomAccessFile raFile = new RandomAccessFile(getFullName(), "rw"); try { long len = getCapacity(); writeHeader(raFile, len, segmentSizeInBytes); raFile.seek(HEADER_OFFSET); // raFile.writeInt() <- too slow, so copy into byte array for (int s = 0; s < segments.length; s++) { byte area[] = segments[s]; raFile.write(area); } } finally { raFile.close(); } } catch (Exception ex) { throw new RuntimeException("Couldn't store bytes to " + toString(), ex); } }
throw new IllegalStateException("already initialized"); if (isClosed()) throw new IllegalStateException("already closed"); return false; File file = new File(getFullName()); if (!file.exists() || file.length() == 0) return false; RandomAccessFile raFile = new RandomAccessFile(getFullName(), "r"); try { long byteCount = readHeader(raFile) - HEADER_OFFSET; if (byteCount < 0) return false; int read = raFile.read(bytes); if (read <= 0) throw new IllegalStateException("segment " + s + " is empty? " + toString()); throw new RuntimeException("Problem while loading " + getFullName(), ex);
@Override public RAMDataAccess create(long bytes) { if (segments.length > 0) throw new IllegalThreadStateException("already created"); // initialize transient values setSegmentSize(segmentSizeInBytes); ensureCapacity(Math.max(10 * 4, bytes)); return this; }