StorageDirect implements Engine { @Override public void compact(){ if(readOnly) throw new IllegalAccessError(); if(index.getFile()==null) throw new UnsupportedOperationException("compact not supported for memory storage yet"); lock.writeLock().lock(); try{ final File indexFile = index.getFile(); final File physFile = phys.getFile(); final boolean isRaf = index instanceof Volume.RandomAccessFileVol; Volume.Factory fab = Volume.fileFactory(false, isRaf, new File(indexFile+".compact")); StorageDirect store2 = new StorageDirect(fab); for(long recid =longStackTake(RECID_FREE_INDEX_SLOTS); recid!=0; recid=longStackTake(RECID_FREE_INDEX_SLOTS)){ store2.longStackPut(recid, RECID_FREE_INDEX_SLOTS); } final long indexSize = index.getLong(RECID_CURRENT_INDEX_FILE_SIZE*8)/8; store2.lock.writeLock().lock(); for(long recid = INDEX_OFFSET_START; recid<indexSize;recid++){ long physOffset = index.getLong(recid*8); long physSize = physOffset >>> 48; physOffset = physOffset & PHYS_OFFSET_MASK; store2.index.ensureAvailable(recid*8+8); if(physSize!=0){ DataInput2 in = phys.getDataInput(physOffset, (int)physSize); long physOffset2 = store2.freePhysRecTake((int)physSize) & PHYS_OFFSET_MASK; store2.phys.ensureAvailable((physOffset2 & PHYS_OFFSET_MASK)+physSize); synchronized (in.buf){ in.buf.limit((int) (in.pos+physSize)); in.buf.position(in.pos); store2.phys.putData(physOffset2, in.buf); } store2.index.putLong(recid*8, (physSize<<48)|physOffset2); }else{ store2.index.putLong(recid*8, 0); } } store2.index.putLong(RECID_CURRENT_INDEX_FILE_SIZE*8, indexSize*8); File indexFile2 = store2.index.getFile(); File physFile2 = store2.phys.getFile(); store2.lock.writeLock().unlock(); store2.close(); long time = System.currentTimeMillis(); File indexFile_ = new File(indexFile.getPath()+"_"+time+"_orig"); File physFile_ = new File(physFile.getPath()+"_"+time+"_orig"); index.close(); phys.close(); if(!indexFile.renameTo(indexFile_))throw new InternalError(); if(!physFile.renameTo(physFile_))throw new InternalError(); if(!indexFile2.renameTo(indexFile))throw new InternalError(); if(!physFile2.renameTo(physFile))throw new InternalError(); indexFile_.delete(); physFile_.delete(); Volume.Factory fac2 = Volume.fileFactory(false, isRaf, indexFile); index = fac2.createIndexVolume(); phys = fac2.createPhysVolume(); }catch(IOException e){ throw new IOError(e); }finally { lock.writeLock().unlock(); } } StorageDirect(Volume.Factory volFac, boolean appendOnly,
                   boolean deleteFilesOnExit, boolean failOnWrongHeader, boolean readOnly);  StorageDirect(Volume.Factory volFac); @Override long put(A value, Serializer<A> serializer); @Override A get(long recid, Serializer<A> serializer); @Override void update(long recid, A value, Serializer<A> serializer); @Override void delete(long recid, Serializer<A> serializer); @Override void commit(); @Override void rollback(); @Override void close(); @Override boolean isClosed(); @Override boolean compareAndSwap(long recid, A expectedOldValue, A newValue, Serializer<A> serializer); @Override boolean isReadOnly(); @Override void compact(); static final String DATA_FILE_EXT; }
@Test public void compact(){ Map<Long,Long> recids = new HashMap<Long, Long>(); for(Long l=0L;l<1000;l++){ recids.put(l, engine.put(l, Serializer.LONG_SERIALIZER)); } engine.commit(); engine.compact(); for(Map.Entry<Long,Long> e:recids.entrySet()){ Long recid= e.getValue(); Long value = e.getKey(); assertEquals(value, engine.get(recid, Serializer.LONG_SERIALIZER)); } }