CachingKVTransaction(CachingKVDatabase kvdb, KVTransaction inner, ExecutorService executor, long rttEstimate) { this.kvdb = kvdb; this.inner = inner; this.cachingKV = new CachingKVStore(inner, executor, rttEstimate); this.kvdb.copyCachingConfigTo(this.cachingKV); this.view = new MutableView(this.cachingKV); this.view.disableReadTracking(); }
@Override public void adjustCounter(byte[] key, long amount) { this.view.adjustCounter(key, amount); }
@Override public long decodeCounter(byte[] bytes) { return this.view.decodeCounter(bytes); }
void setNoLongerRebasable() { assert Thread.holdsLock(this.raft); assert this.rebasable == (this.view.getReads() != null); if (this.rebasable) { if (this.raft.logger.isTraceEnabled()) this.raft.trace("stopping rebasing for " + this); this.raft.setHighPriority(this, false); // if it's not longer rebasable, it can't be a victim of any conflicts this.view.disableReadTracking(); this.rebasable = false; } }
if (this.mods.getKVStore() instanceof MutableView) { // we are compacting assert this.compaction != null; final MutableView compactingMods = (MutableView)this.mods.getKVStore(); assert compactingMods.getKVStore() == this.kvstore; synchronized (compactingMods) { if (!compactingMods.getWrites().isEmpty()) compactingWrites = compactingMods.getWrites().immutableSnapshot(); if (!this.mods.getWrites().isEmpty()) this.modsWritesSnapshot = this.mods.getWrites().immutableSnapshot(); snapshot = new MutableView(snapshot, null, compactingWrites); if (outstandingWrites != null) snapshot = new MutableView(snapshot, null, outstandingWrites);
/** * {@inheritDoc} * * <p> * Mutable snapshots are supported by {@link RaftKVTransaction}. * * @return {@inheritDoc} * @throws UnsupportedOperationException {@inheritDoc} * @throws StaleTransactionException {@inheritDoc} * @throws io.permazen.kv.RetryTransactionException {@inheritDoc} */ @Override public CloseableKVStore mutableSnapshot() { final Writes writes; synchronized (this.view) { writes = this.view.getWrites().clone(); } synchronized (this.raft) { this.verifyExecuting(); assert this.snapshotRefs != null; this.snapshotRefs.ref(); final MutableView snapshotView = new MutableView(this.snapshotRefs.getKVStore(), null, writes); return new CloseableForwardingKVStore(snapshotView, this.snapshotRefs.getUnrefCloseable()); } }
final byte[] min = range.getMin(); final byte[] max = range.getMax(); this.mods.removeRange(min, max); this.modsWritesSnapshot = null; final byte[] key = entry.getKey(); final byte[] val = entry.getValue(); this.mods.put(key, val); this.modsWritesSnapshot = null; final byte[] key = entry.getKey(); final long adjust = entry.getValue(); this.mods.adjustCounter(key, adjust); this.modsWritesSnapshot = null;
@Override public synchronized CloseableKVStore mutableSnapshot() { if (this.closed) throw new StaleTransactionException(this, "transaction closed"); final XodusKVStore snapshot = this.buildKV().readOnlySnapshot(); return new CloseableForwardingKVStore(new MutableView(snapshot, null, new Writes()), snapshot); }
@Override public void commit() { // Grab transaction reads & writes, set to immutable final Writes writes; synchronized (this.view) { writes = this.view.getWrites(); this.view.setReadOnly(); this.cachingKV.close(); // this tells background read-ahead threads to ignore subsequent exceptions } // Apply writes and commit tx try { this.applyWritesBeforeCommitIfNotReadOnly(writes); this.inner.commit(); } finally { this.close(); } }
/** * Determine if committing this transaction will require appending a new log entry to the Raft log. * * @return true if this is not a read-only transaction and has either a config change or a key/value store mutation */ boolean addsLogEntry() { assert Thread.holdsLock(this.raft); if (this.readOnly) return false; if (this.configChange != null) return true; synchronized (this.view) { return !this.view.getWrites().isEmpty(); } }
@Override public byte[] encodeCounter(long value) { return this.view.encodeCounter(value); }
@Override public byte[] get(byte[] key) { return this.view.get(key); }
@Override public CloseableIterator<KVPair> getRange(byte[] minKey, byte[] maxKey, boolean reverse) { return this.view.getRange(minKey, maxKey, reverse); }
@Override public KVPair getAtMost(byte[] maxKey, byte[] minKey) { return this.view.getAtMost(maxKey, minKey); }
@Override public KVPair getAtLeast(byte[] minKey, byte[] maxKey) { return this.view.getAtLeast(minKey, maxKey); }
final Reads reads = tx.view.getReads(); final long readsDataSize = reads.serializedLength(); if (readsDataSize != (int)readsDataSize) final Writes writes = tx.view.getWrites(); // synchronization not req'd here because tx is COMMIT_READY final File file = new File(this.raft.logDir, String.format("%s%019d%s", RaftKVDatabase.TX_FILE_PREFIX, tx.txId, RaftKVDatabase.TEMP_FILE_SUFFIX));
/** * Constructor. * * @param raft associated database * @param consistency consistency guarantee * @param baseTerm term of the Raft log entry on which this transaction is based * @param baseIndex index of the Raft log entry on which this transaction is based * @param snapshot underlying state machine snapshot; will be closed with this instance * @param view this transaction's view of the (prefixed) key/value store */ RaftKVTransaction(RaftKVDatabase raft, Consistency consistency, long baseTerm, long baseIndex, CloseableKVStore snapshot, MutableView view) { this.raft = raft; this.consistency = consistency; this.baseTerm = baseTerm; this.baseIndex = baseIndex; this.snapshotRefs = new SnapshotRefs(snapshot); this.view = view; this.rebasable = consistency.isGuaranteesUpToDateReads(); // i.e., LINEARIZABLE if (!this.rebasable) this.view.disableReadTracking(); }
writesToCompact = this.mods.getWrites(); this.mods = new MutableView(this.mods, null, new Writes()); this.modsWritesSnapshot = null; previousModsFileLength = this.modsFileLength; this.modsFileSyncPoint = newModsFileSyncPoint; this.kvstore = new ArrayKVStore(this.indx, this.keys, this.vals); this.mods = new MutableView(this.kvstore, null, this.mods.getWrites()); this.modsWritesSnapshot = null; if (additionalModsLength == 0) final Writes writesDuringCompaction = this.mods.getWrites(); this.mods = new MutableView(this.kvstore, null, writesToCompact); this.modsWritesSnapshot = null; writesDuringCompaction.applyTo(this.mods);
this.mods = new MutableView(this.kvstore, null, new Writes());
/** * Create an instance from a local transaction. A corresponding temporary file will be created automatically. * * @param tx local transaction */ NewLogEntry(final RaftKVTransaction tx) throws IOException { this(tx.raft, new LogEntry.Data(tx.view.getWrites(), tx.getConfigChange())); }