Reusable Java library of general tools with minimal external dependencies.
For questions or support, please contact us:
Email: support@aoindustries.com
Phone: 1-800-519-9541
Phone: +1-251-607-9556
Web: https://www.aoindustries.com/contact
public class TwoCopyBarrierBuffer extends AbstractPersistentBuffer
Java does not support write barriers without a complete force call,
this class works-around this issue by maintaining two copies of the file and
updating the older copy to be the newer copy occasionally on barrier(false)
and immediately on barrier(true) (if protectionLevel is high enough).
All instances also share a to perform automatic
background flushing of caches. Automatic flushing is single-threaded to favor
low load averages over timely flushes.
Timer
This class also acts as a write cache that may batch or delay writes for potentially long periods of time. This is useful for media such as flash memory where write throughput is quite limited and the number of writes on the media is also limited. This also turns many random writes into fewer, sequential writes. This may help spinning platter-based media.
Since this class is intended for flash-based media, it will not rewrite the same data to a section of a file. Even if this means that it has to read the section of the file, compare the values, and then write only when changed. This is an attempt to help the wear leveling technology built into the media by dispatching a minimum number of writes.
An additional benefit may be that reads from cached data are performed directly from the write cache, although this is not the purpose of this buffer. Writes that would not change anything, however, are not cached and would not help as a read cache.
Two copies of the file are maintained. The most recent version of the file will normally be named with the regular name, but other versions will exist with .old or .new appended to the filename. The exact order of update is:
filename.old to filename.newfilename.newfilename to filename.oldfilename.new to filename
Complete Complete Old Partial
Normal: filename filename.old
filename filename.new
filename.new filename.old
Normal: filename filename.old
This implementation assumes an atomic file rename for correct recovery.
To reduce the chance of data loss, this registers a JVM shutdown hook to flush all caches on JVM shutdown. If it takes a long time to flush the data this can cause significant delays when stopping a JVM.
TODO: Should we run on top of RandomAccessBuffer/LargeMappedPersistentBuffer/MappedPersistentBuffer for memory-mapped read performance?
protectionLevel| Constructor and Description |
|---|
TwoCopyBarrierBuffer()
Creates a read-write buffer backed by temporary files.
|
TwoCopyBarrierBuffer(File file)
Creates a read-write buffer with
BARRIER protection level. |
TwoCopyBarrierBuffer(File file,
ProtectionLevel protectionLevel)
Creates a buffer.
|
TwoCopyBarrierBuffer(File file,
ProtectionLevel protectionLevel,
int sectorSize,
long asynchronousCommitDelay,
long synchronousCommitDelay)
Creates a buffer.
|
TwoCopyBarrierBuffer(String name)
Creates a read-write buffer with
BARRIER protection level. |
TwoCopyBarrierBuffer(String name,
ProtectionLevel protectionLevel)
Creates a buffer.
|
| Modifier and Type | Method and Description |
|---|---|
void |
barrier(boolean force)
Ensures that all writes before this barrier occur before all writes after
this barrier.
|
long |
capacity()
Gets the capacity of this buffer.
|
void |
close()
Closes this buffer.
|
void |
ensureZeros(long position,
long len)
Ensures that all values from the position for the provided length
are zeros.
|
protected void |
finalize() |
byte |
get(long position)
Implemented as call to
get(long,byte[],int,int). |
int |
getSome(long position,
byte[] buff,
int off,
int len)
Reads to the provided
byte[], may read fewer than len
bytes, but will always read at least one byte. |
boolean |
isClosed()
Checks if this buffer is closed.
|
void |
put(long position,
byte value)
Implemented as call to
put(long,byte[],int,int). |
void |
put(long position,
byte[] buff,
int off,
int len)
Writes the bytes to the provided position.
|
void |
setCapacity(long newCapacity)
Sets the capacity of this buffer.
|
get, getBoolean, getInputStream, getInt, getLong, getOutputStream, getProtectionLevel, putInt, putLongpublic TwoCopyBarrierBuffer()
throws IOException
NONE. The temporary file will be deleted when this
buffer is closed or on JVM shutdown.
Uses default sectorSize of 4096, asynchronous commit delay of 5 seconds, and synchronous commit delay of 60 seconds.
A shutdown hook is not registered.IOExceptionpublic TwoCopyBarrierBuffer(String name) throws IOException
BARRIER protection level.
Uses default sectorSize of 4096, asynchronous commit delay of 5 seconds, and synchronous commit delay of 60 seconds.IOExceptionpublic TwoCopyBarrierBuffer(String name, ProtectionLevel protectionLevel) throws IOException
IOExceptionpublic TwoCopyBarrierBuffer(File file) throws IOException
BARRIER protection level.
Uses default sectorSize of 4096, asynchronous commit delay of 5 seconds, and synchronous commit delay of 60 seconds.IOExceptionpublic TwoCopyBarrierBuffer(File file, ProtectionLevel protectionLevel) throws IOException
IOExceptionpublic TwoCopyBarrierBuffer(File file, ProtectionLevel protectionLevel, int sectorSize, long asynchronousCommitDelay, long synchronousCommitDelay) throws IOException
oldWriteCache with
any data the doesn't match the newer version of the file. This means that both files are read completely
at start-up in order to provide the most efficient synchronization later.file - The base filename, will be appended with ".old" and ".new" while committing changes.protectionLevel - The protection level for this buffer.sectorSize - The size of the sectors cached and written. For best results this should
match the underlying filesystem block size. Must be a power of two >= 1.asynchronousCommitDelay - The number of milliseconds before a background thread syncs uncommitted data to
the underlying storage. A value of Long.MAX_VALUE will avoid any
overhead of background thread management.synchronousCommitDelay - The number of milliseconds before a the calling thread syncs uncommitted data to
the underlying storage.IOExceptionprotected void finalize()
throws Throwable
public boolean isClosed()
PersistentBufferpublic void close()
throws IOException
PersistentBufferIOExceptionpublic long capacity()
throws IOException
PersistentBufferIOExceptionpublic void setCapacity(long newCapacity)
throws IOException
PersistentBufferbarrier(true), depending on implementation. This
should be considered an expensive operation.IOExceptionpublic byte get(long position)
throws IOException
AbstractPersistentBufferget(long,byte[],int,int). For performance
reasons, it is strongly recommended to provide a more efficient implementation
of this method.get in interface PersistentBufferget in class AbstractPersistentBufferIOExceptionAbstractPersistentBuffer.get(long, byte[], int, int)public int getSome(long position,
byte[] buff,
int off,
int len)
throws IOException
PersistentBufferbyte[], may read fewer than len
bytes, but will always read at least one byte. Blocks if no data is
available.IOExceptionpublic void put(long position,
byte value)
throws IOException
AbstractPersistentBufferput(long,byte[],int,int). For performance
reasons, it is strongly recommended to provide a more efficient implementation
of this method.put in interface PersistentBufferput in class AbstractPersistentBufferIOExceptionPersistentBuffer.put(long, byte[], int, int)public void ensureZeros(long position,
long len)
throws IOException
PersistentBufferIOExceptionpublic void put(long position,
byte[] buff,
int off,
int len)
throws IOException
PersistentBufferIOExceptionpublic void barrier(boolean force)
throws IOException
PersistentBufferforce is true, will also
commit to physical media synchronously before returning. This request
may be ignored or force downgraded to barrier-only depending on the current
protection level.IOExceptionPersistentBuffer.getProtectionLevel()Copyright © 2000–2016 AO Industries, Inc.. All rights reserved.