public class AsyncWriteEngine extends EngineWrapper implements Engine
Engine
wrapper which provides asynchronous serialization and asynchronous write.
This class takes an object instance, passes it to background writer thread (using Write Cache)
where it is serialized and written to disk. Async write does not affect commit durability,
write cache is flushed into disk on each commit. Modified records are held in small instance cache,
until they are written into disk.
This feature is disabled by default and can be enabled by calling DBMaker.asyncWriteEnable()
.
Write Cache is flushed in regular intervals or when it becomes full. Flush interval is 100 ms by default and
can be controlled by DBMaker.asyncWriteFlushDelay(int)
. Increasing this interval may improve performance
in scenarios where frequently modified items should be cached, typically BTreeMap
import where keys
are presorted.
Asynchronous write does not affect commit durability. Write Cache is flushed during each commit, rollback and close call.
You may also flush Write Cache manually by using clearCache()
method.
There is global lock which prevents record being updated while commit is in progress.
This wrapper starts one threads named `MapDB writer #N` (where N is static counter).
Async Writer takes modified records from Write Cache and writes them into store.
It also preallocates new recids, as finding empty `recids` takes time so small stash is pre-allocated.
It runs as `daemon`, so it does not prevent JVM to exit.
Asynchronous Writes have several advantages (especially for single threaded user). But there are two things
user should be aware of:
* Because data are serialized on back-ground thread, they need to be thread safe or better immutable.
When you insert record into MapDB and modify it latter, this modification may happen before item
was serialized and you may not be sure what version was persisted
* Asynchronous writes have some overhead and introduce single bottle-neck. This usually not issue for
single or two threads, but in multi-threaded environment it may decrease performance.
So in truly concurrent environments with many updates (network servers, parallel computing )
you should disable Asynchronous Writes.Engine
,
EngineWrapper
Modifier and Type | Class and Description |
---|---|
protected static class |
AsyncWriteEngine.WriterRunnable |
EngineWrapper.CloseOnJVMShutdown, EngineWrapper.ImmutabilityCheckEngine, EngineWrapper.ReadOnlyEngine, EngineWrapper.SerializerCheckEngineWrapper, EngineWrapper.SynchronizedEngineWrapper
Modifier and Type | Field and Description |
---|---|
protected AtomicReference<CountDownLatch> |
action |
protected CountDownLatch |
activeThreadsCount
number of active threads running, used to await thread termination on close
|
protected int |
asyncFlushDelay
flush Write Queue every N milliseconds
|
protected boolean |
closeInProgress
indicates that `close()` was called and background threads are being terminated
|
protected ReentrantReadWriteLock |
commitLock
Each insert to Write Queue must hold read lock.
|
protected int |
maxSize |
protected long[] |
newRecids |
protected ReentrantLock |
newRecidsLock |
protected int |
newRecidsPos |
protected AtomicInteger |
size |
protected static AtomicLong |
threadCounter
ensures thread name is followed by number
|
protected Throwable |
threadFailedException
If background thread fails with exception, it is stored here, and rethrown to all callers.
|
protected static Object |
TOMBSTONE
used to signal that object was deleted
|
protected LongConcurrentHashMap<Fun.Tuple2<Object,Serializer>> |
writeCache
Associates `recid` from Write Queue with record data and serializer.
|
CLOSED
CATALOG_RECID, CHECK_RECORD, CLASS_INFO_RECID, LAST_RESERVED_RECID
Constructor and Description |
---|
AsyncWriteEngine(Engine engine) |
AsyncWriteEngine(Engine engine,
int _asyncFlushDelay,
int queueSize,
Executor executor)
Construct new class and starts background threads.
|
Modifier and Type | Method and Description |
---|---|
protected void |
checkState()
checks that background threads are ready and throws exception if not
|
void |
clearCache()
clears any underlying cache
|
void |
close()
Close store/cache.
|
void |
commit()
Makes all changes made since the previous commit/rollback permanent.
|
void |
compact()
This method blocks all put/update/delete operations until it finishes (via global ReadWrite Commit Lock).
|
<A> boolean |
compareAndSwap(long recid,
A expectedOldValue,
A newValue,
Serializer<A> serializer)
Updates existing record in atomic (Compare And Swap) manner.
|
<A> void |
delete(long recid,
Serializer<A> serializer)
Remove existing record from store/cache
Recid must be a number returned by 'put' method.
|
<A> A |
get(long recid,
Serializer<A> serializer)
Get existing record.
|
long |
preallocate()
Preallocates recid for not yet created record.
|
void |
preallocate(long[] recids)
Preallocates recids for not yet created record.
|
protected long |
preallocateNoCommitLock() |
protected void |
preallocateRefill() |
protected void |
preallocateRollback() |
<A> long |
put(A value,
Serializer<A> serializer)
Insert new record.
|
void |
rollback()
Undoes all changes made in the current transaction.
|
protected boolean |
runWriter()
runs on background thread.
|
protected void |
startThreads(Executor executor)
Starts background threads.
|
<A> void |
update(long recid,
A value,
Serializer<A> serializer)
Update existing record with new value.
|
protected void |
waitForAction(int actionNumber) |
canRollback, canSnapshot, checkClosed, closeListenerRegister, closeListenerUnregister, getSerializerPojo, getWrappedEngine, isClosed, isReadOnly, snapshot
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
canRollback, canSnapshot, closeListenerRegister, closeListenerUnregister, getSerializerPojo, isClosed, isReadOnly, snapshot
protected static final AtomicLong threadCounter
protected static final Object TOMBSTONE
protected final int maxSize
protected final AtomicInteger size
protected final long[] newRecids
protected int newRecidsPos
protected final ReentrantLock newRecidsLock
protected final LongConcurrentHashMap<Fun.Tuple2<Object,Serializer>> writeCache
protected final ReentrantReadWriteLock commitLock
protected final CountDownLatch activeThreadsCount
protected volatile Throwable threadFailedException
protected volatile boolean closeInProgress
protected final int asyncFlushDelay
protected final AtomicReference<CountDownLatch> action
public AsyncWriteEngine(Engine engine, int _asyncFlushDelay, int queueSize, Executor executor)
engine
- which stores data._asyncFlushDelay
- flush Write Queue every N millisecondsexecutor
- optional executor to run tasks. If null daemon threads will be createdpublic AsyncWriteEngine(Engine engine)
protected void startThreads(Executor executor)
executor
- optional executor to run tasks, if null deamon threads will be createdprotected boolean runWriter() throws InterruptedException
InterruptedException
protected void preallocateRollback()
public long preallocate()
Engine
preallocate
in interface Engine
preallocate
in class EngineWrapper
public void preallocate(long[] recids)
Engine
preallocate
in interface Engine
preallocate
in class EngineWrapper
recids
- array to put result intoprotected long preallocateNoCommitLock()
protected void preallocateRefill()
protected void checkState()
public <A> long put(A value, Serializer<A> serializer)
put
in interface Engine
put
in class EngineWrapper
value
- records to be addedserializer
- used to convert record into/from binary formpublic <A> A get(long recid, Serializer<A> serializer)
get
in interface Engine
get
in class EngineWrapper
recid
- (record identifier) under which record was persistedserializer
- used to deserialize record from binary formpublic <A> void update(long recid, A value, Serializer<A> serializer)
update
in interface Engine
update
in class EngineWrapper
recid
- (record identifier) under which record was persisted.value
- new record value to be storedserializer
- used to serialize record into binary formpublic <A> boolean compareAndSwap(long recid, A expectedOldValue, A newValue, Serializer<A> serializer)
oldValue==expectedOldValue
when old value is found in instance cacheoldValue
using serializer
and checking oldValue.equals(expectedOldValue)
expectedOldValue
using serializer
and comparing binary array with already serialized oldValue
compareAndSwap
in interface Engine
compareAndSwap
in class EngineWrapper
recid
- (record identifier) under which record was persisted.expectedOldValue
- old value to be compared with existing recordnewValue
- to be written if values are matchingserializer
- used to serialize record into binary formpublic <A> void delete(long recid, Serializer<A> serializer)
delete
in interface Engine
delete
in class EngineWrapper
recid
- (record identifier) under which was record persistedserializer
- which may be used in some circumstances to deserialize and store old objectpublic void close()
NullPointerException
There is an configuration option DBMaker.closeOnJvmShutdown()
which uses shutdown hook to automatically
close Engine when JVM shutdowns.
This method blocks until Write Queue is flushed and Writer Thread writes all records and finishes.
When this method was called `closeInProgress` is set and no record can be modified.close
in interface Engine
close
in class EngineWrapper
protected void waitForAction(int actionNumber)
public void commit()
commit
in interface Engine
commit
in class EngineWrapper
public void rollback()
UnsupportedOperationException
.
This method blocks until Write Queue is cleared.
All put/update/delete methods are blocked while rollback is in progress (via global ReadWrite Commit Lock).
After this method returns, commit lock is released and other operations may continuerollback
in interface Engine
rollback
in class EngineWrapper
public void compact()
compact
in interface Engine
compact
in class EngineWrapper
public void clearCache()
clearCache
in interface Engine
clearCache
in class EngineWrapper
Copyright © 2014. All Rights Reserved.