提交 2a2433e1 authored 作者: Andrei Tokar's avatar Andrei Tokar

add missing javadocs

encapsulate field in TxDecisionMaker
上级 78155dab
...@@ -1105,10 +1105,6 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -1105,10 +1105,6 @@ public class MVMap<K, V> extends AbstractMap<K, V>
getVersion(rootReference) > version; getVersion(rootReference) > version;
} }
public boolean isSingleWriter() {
return singleWriter;
}
/** /**
* Get the child page count for this page. This is to allow another map * Get the child page count for this page. This is to allow another map
* implementation to override the default, in case the last child is not to * implementation to override the default, in case the last child is not to
......
...@@ -503,7 +503,7 @@ public class MVStore implements AutoCloseable { ...@@ -503,7 +503,7 @@ public class MVStore implements AutoCloseable {
return map; return map;
} }
public <M extends MVMap<K, V>, K, V> M openMap(int id, MVMap.MapBuilder<M, K, V> builder) { private <M extends MVMap<K, V>, K, V> M openMap(int id, MVMap.MapBuilder<M, K, V> builder) {
storeLock.lock(); storeLock.lock();
try { try {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
...@@ -2963,6 +2963,14 @@ public class MVStore implements AutoCloseable { ...@@ -2963,6 +2963,14 @@ public class MVStore implements AutoCloseable {
return txCounter; return txCounter;
} }
/**
* De-register (close) completed operation (transaction).
* This will decrement usage counter for the corresponding version.
* If counter reaches zero, that version (and all unused after it)
* can be dropped immediately.
*
* @param txCounter to be decremented, obtained from registerVersionUsage()
*/
public void deregisterVersionUsage(TxCounter txCounter) { public void deregisterVersionUsage(TxCounter txCounter) {
if(txCounter != null) { if(txCounter != null) {
if(txCounter.counter.decrementAndGet() <= 0) { if(txCounter.counter.decrementAndGet() <= 0) {
...@@ -3001,7 +3009,14 @@ public class MVStore implements AutoCloseable { ...@@ -3001,7 +3009,14 @@ public class MVStore implements AutoCloseable {
* which are still operating on this version. * which are still operating on this version.
*/ */
public static final class TxCounter { public static final class TxCounter {
/**
* Version of a store, this TxCounter is related to
*/
public final long version; public final long version;
/**
* Counter of outstanding operation on this version of a store
*/
public final AtomicInteger counter = new AtomicInteger(); public final AtomicInteger counter = new AtomicInteger();
TxCounter(long version) { TxCounter(long version) {
......
...@@ -518,6 +518,14 @@ public abstract class Page implements Cloneable ...@@ -518,6 +518,14 @@ public abstract class Page implements Cloneable
return bKeys; return bKeys;
} }
/**
* Append additional key/value mappings to this Page.
* New mappings suppose to be in correct key order.
*
* @param extraKeyCount number of mappings to be added
* @param extraKeys to be added
* @param extraValues to be added
*/
abstract void expand(int extraKeyCount, Object[] extraKeys, Object[] extraValues); abstract void expand(int extraKeyCount, Object[] extraKeys, Object[] extraValues);
/** /**
...@@ -911,6 +919,12 @@ public abstract class Page implements Cloneable ...@@ -911,6 +919,12 @@ public abstract class Page implements Cloneable
} }
} }
/**
* Update given CursorPos chain to correspond to "append point" in a B-tree rooted at this Page.
*
* @param cursorPos to update, presumably pointing to this Page
* @return new head of the CursorPos chain
*/
public abstract CursorPos getAppendCursorPos(CursorPos cursorPos); public abstract CursorPos getAppendCursorPos(CursorPos cursorPos);
/** /**
...@@ -984,6 +998,11 @@ public abstract class Page implements Cloneable ...@@ -984,6 +998,11 @@ public abstract class Page implements Cloneable
return page; return page;
} }
/**
* Clear if necessary, reference to the actual child Page object,
* so it can be garbage collected if not actively used elsewhere.
* Reference is cleared only if corresponding page was already saved on a disk.
*/
void clearPageReference() { void clearPageReference() {
if (page != null) { if (page != null) {
page.writeEnd(); page.writeEnd();
......
...@@ -231,6 +231,11 @@ public class Transaction { ...@@ -231,6 +231,11 @@ public class Transaction {
} }
} }
/**
* Determine if any database changes were made as part of this transaction.
*
* @return true if there are changes to commit, false otherwise
*/
public boolean hasChanges() { public boolean hasChanges() {
return hasChanges(statusAndLogId.get()); return hasChanges(statusAndLogId.get());
} }
...@@ -259,11 +264,17 @@ public class Transaction { ...@@ -259,11 +264,17 @@ public class Transaction {
return getLogId(); return getLogId();
} }
/**
* Mark an entry into a new SQL statement execution within this transaction.
*/
public void markStatementStart() { public void markStatementStart() {
markStatementEnd(); markStatementEnd();
txCounter = store.store.registerVersionUsage(); txCounter = store.store.registerVersionUsage();
} }
/**
* Mark an exit from SQL statement execution within this transaction.
*/
public void markStatementEnd() { public void markStatementEnd() {
MVStore.TxCounter counter = txCounter; MVStore.TxCounter counter = txCounter;
if(counter != null) { if(counter != null) {
...@@ -278,6 +289,8 @@ public class Transaction { ...@@ -278,6 +289,8 @@ public class Transaction {
* @param mapId the map id * @param mapId the map id
* @param key the key * @param key the key
* @param oldValue the old value * @param oldValue the old value
*
* @return key for the newly added undo log entry
*/ */
long log(int mapId, Object key, VersionedValue oldValue) { long log(int mapId, Object key, VersionedValue oldValue) {
long currentState = statusAndLogId.getAndIncrement(); long currentState = statusAndLogId.getAndIncrement();
...@@ -487,6 +500,9 @@ public class Transaction { ...@@ -487,6 +500,9 @@ public class Transaction {
} }
} }
/**
* Transition this transaction into a closed state.
*/
void closeIt() { void closeIt() {
long lastState = setStatus(STATUS_CLOSED); long lastState = setStatus(STATUS_CLOSED);
store.store.deregisterVersionUsage(txCounter); store.store.deregisterVersionUsage(txCounter);
...@@ -499,6 +515,15 @@ public class Transaction { ...@@ -499,6 +515,15 @@ public class Transaction {
notifyAll(); notifyAll();
} }
/**
* Make this transaction to wait for the specified transaction to be closed,
* because both of them try to modify the same map entry.
*
* @param toWaitFor transaction to wait for
* @param map containing blocking entry
* @param key of the blocking entry
* @return true if other transaction was closed and this one can proceed, false if timed out
*/
public boolean waitFor(Transaction toWaitFor, MVMap<?,VersionedValue> map, Object key) { public boolean waitFor(Transaction toWaitFor, MVMap<?,VersionedValue> map, Object key) {
blockingTransaction = toWaitFor; blockingTransaction = toWaitFor;
blockingMap = map; blockingMap = map;
......
...@@ -102,6 +102,17 @@ public class TransactionStore { ...@@ -102,6 +102,17 @@ public class TransactionStore {
private static final int MAX_OPEN_TRANSACTIONS = 65535; private static final int MAX_OPEN_TRANSACTIONS = 65535;
/**
* Generate a string used to name undo log map for a specific transaction.
* This name will contain transaction id and reflect the fact
* whether transaction is logically committed or not.
* This information might be used by recovery procedure after unclean shutdown
* (termination before transaction is fully committed).
*
* @param committed true if transaction is logically committed, false otherwise
* @param transactionId of the corresponding transaction
* @return undo log name
*/
public static String getUndoLogName(boolean committed, int transactionId) { public static String getUndoLogName(boolean committed, int transactionId) {
return UNDO_LOG_NAME_PREFIX + return UNDO_LOG_NAME_PREFIX +
(committed ? UNDO_LOG_COMMITTED : UNDO_LOG_OPEN) + (committed ? UNDO_LOG_COMMITTED : UNDO_LOG_OPEN) +
......
...@@ -9,17 +9,42 @@ import org.h2.mvstore.MVMap; ...@@ -9,17 +9,42 @@ import org.h2.mvstore.MVMap;
import org.h2.value.VersionedValue; import org.h2.value.VersionedValue;
/** /**
* Class TxDecisionMaker. * Class TxDecisionMaker is a base implementation of MVMap.DecisionMaker
* to be used for TransactionMap modification.
* *
* @author <a href='mailto:andrei.tokar@gmail.com'>Andrei Tokar</a> * @author <a href='mailto:andrei.tokar@gmail.com'>Andrei Tokar</a>
*/ */
abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> { abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> {
/**
* Map to decide upon
*/
private final int mapId; private final int mapId;
/**
* Key for the map entry to decide upon
*/
private final Object key; private final Object key;
/**
* Value for the map entry
*/
final Object value; final Object value;
/**
* Transaction we are operating within
*/
private final Transaction transaction; private final Transaction transaction;
/**
* Id for the undo log entry created for this modification
*/
long undoKey; long undoKey;
protected long lastOperationId;
/**
* Id of the last operation, we decided to {@link MVMap.Decision.REPEAT}.
*/
private long lastOperationId;
private Transaction blockingTransaction; private Transaction blockingTransaction;
private MVMap.Decision decision; private MVMap.Decision decision;
...@@ -56,7 +81,7 @@ abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> { ...@@ -56,7 +81,7 @@ abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> {
// transaction is not committed yet // transaction is not committed yet
// should wait on blockingTransaction that was determined earlier // should wait on blockingTransaction that was determined earlier
decision = MVMap.Decision.ABORT; decision = MVMap.Decision.ABORT;
} else if (id == lastOperationId) { } else if (isRepeatedOperation(id)) {
// There is no transaction with that id, and we've tried it just // There is no transaction with that id, and we've tried it just
// before, but map root has not changed (which must be the case if // before, but map root has not changed (which must be the case if
// we just missed a closed transaction), therefore we came back here // we just missed a closed transaction), therefore we came back here
...@@ -72,7 +97,6 @@ abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> { ...@@ -72,7 +97,6 @@ abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> {
// we can retry immediately and either that entry become committed // we can retry immediately and either that entry become committed
// or we'll hit case above // or we'll hit case above
decision = MVMap.Decision.REPEAT; decision = MVMap.Decision.REPEAT;
lastOperationId = id;
} }
return decision; return decision;
} }
...@@ -99,14 +123,33 @@ abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> { ...@@ -99,14 +123,33 @@ abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> {
return blockingTransaction; return blockingTransaction;
} }
/**
* Create undo log entry
* @param value previous value to be logged
*/
final void logIt(VersionedValue value) { final void logIt(VersionedValue value) {
undoKey = transaction.log(mapId, key, value); undoKey = transaction.log(mapId, key, value);
} }
/**
* Check whether specified transaction id belongs to "current" transaction
* (transaction we are acting within).
*
* @param transactionId to check
* @return true it it is "current" transaction's id, false otherwise
*/
final boolean isThisTransaction(int transactionId) { final boolean isThisTransaction(int transactionId) {
return transactionId == transaction.transactionId; return transactionId == transaction.transactionId;
} }
/**
* Determine whether specified id corresponds to a logically committed transaction.
* In case of pending transaction, reference to actual Transaction object (if any)
* is preserved for future use.
*
* @param transactionId to use
* @return true if transaction should be considered as committed, false otherwise
*/
final boolean isCommitted(int transactionId) { final boolean isCommitted(int transactionId) {
Transaction blockingTx; Transaction blockingTx;
boolean result; boolean result;
...@@ -121,8 +164,30 @@ abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> { ...@@ -121,8 +164,30 @@ abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> {
return result; return result;
} }
final MVMap.Decision setDecision(MVMap.Decision d) { /**
return decision = d; * Store operation id provided, but before that, compare it against last stored one.
* This is to prevent an infinite loop in case of uncommitted "leftover" entry
* (one without a corresponding undo log entry, most likely as a result of unclean shutdown).
*
* @param id for the operation we decided to {@link MVMap.Decision.REPEAT}
* @return true if the same as last operation id, false otherwise
*/
final boolean isRepeatedOperation(long id) {
if (id == lastOperationId) {
return true;
}
lastOperationId = id;
return false;
}
/**
* Record for future references specified value as a decision that has been made.
*
* @param decision made
* @return argument provided
*/
final MVMap.Decision setDecision(MVMap.Decision decision) {
return this.decision = decision;
} }
@Override @Override
...@@ -184,7 +249,7 @@ abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> { ...@@ -184,7 +249,7 @@ abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> {
// should wait on blockingTransaction that was determined // should wait on blockingTransaction that was determined
// earlier and then try again // earlier and then try again
return setDecision(MVMap.Decision.ABORT); return setDecision(MVMap.Decision.ABORT);
} else if (id == lastOperationId) { } else if (isRepeatedOperation(id)) {
// There is no transaction with that id, and we've tried it // There is no transaction with that id, and we've tried it
// just before, but map root has not changed (which must be // just before, but map root has not changed (which must be
// the case if we just missed a closed transaction), // the case if we just missed a closed transaction),
...@@ -203,7 +268,6 @@ abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> { ...@@ -203,7 +268,6 @@ abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> {
// transaction has been committed/rolled back and is closed // transaction has been committed/rolled back and is closed
// by now, so we can retry immediately and either that entry // by now, so we can retry immediately and either that entry
// become committed or we'll hit case above // become committed or we'll hit case above
lastOperationId = id;
return setDecision(MVMap.Decision.REPEAT); return setDecision(MVMap.Decision.REPEAT);
} }
} }
......
...@@ -157,7 +157,7 @@ dateadd datediff datepart dates datestyle datetime datetimes datum david davide ...@@ -157,7 +157,7 @@ dateadd datediff datepart dates datestyle datetime datetimes datum david davide
day daylight dayname dayofmonth dayofweek dayofyear days dba dbbench dbcp dbid day daylight dayname dayofmonth dayofweek dayofyear days dba dbbench dbcp dbid
dbms dbname dbo dbs dbserv dbsnmp dclassifier dcmpg dcmpl dconst ddiv ddl dbms dbname dbo dbs dbserv dbsnmp dclassifier dcmpg dcmpl dconst ddiv ddl
ddladmin deactivate deactivated deactivation dead deadlock deadlocked deadlocks ddladmin deactivate deactivated deactivation dead deadlock deadlocked deadlocks
deal dealing deallocate death debug debugging dec decade december decide decimal deal dealing deallocate death debug debugging dec decade december decide decided decimal
decision deck declaration declarations declarative declaratory declare declared decision deck declaration declarations declarative declaratory declare declared
declaring decode decoded decoder decodes decoding decompile decompiler decompiles declaring decode decoded decoder decodes decoding decompile decompiler decompiles
decompiling decompress decompressed decompresser decompression decoration decompiling decompress decompressed decompresser decompression decoration
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论