提交 7f774520 authored 作者: andrei's avatar andrei

Introduce overflow bit in tx state and some bit manipulation constants for readability

上级 8e29ff1f
...@@ -96,6 +96,11 @@ public final class DataUtils { ...@@ -96,6 +96,11 @@ public final class DataUtils {
*/ */
public static final int ERROR_TRANSACTION_ILLEGAL_STATE = 103; public static final int ERROR_TRANSACTION_ILLEGAL_STATE = 103;
/**
* The transaction contains too many changes.
*/
public static final int ERROR_TRANSACTION_TOO_BIG = 104;
/** /**
* The type for leaf page. * The type for leaf page.
*/ */
......
...@@ -50,7 +50,7 @@ public class Transaction { ...@@ -50,7 +50,7 @@ public class Transaction {
* This transaction's id can not be re-used until all the above is completed * This transaction's id can not be re-used until all the above is completed
* and transaction is closed. * and transaction is closed.
*/ */
public static final int STATUS_COMMITTED = 4; private static final int STATUS_COMMITTED = 4;
/** /**
* The status of a transaction that currently in a process of rolling back * The status of a transaction that currently in a process of rolling back
...@@ -68,6 +68,12 @@ public class Transaction { ...@@ -68,6 +68,12 @@ public class Transaction {
"CLOSED", "OPEN", "PREPARED", "COMMITTING", "CLOSED", "OPEN", "PREPARED", "COMMITTING",
"COMMITTED", "ROLLING_BACK", "ROLLED_BACK" "COMMITTED", "ROLLING_BACK", "ROLLED_BACK"
}; };
static final int LOG_ID_BITS = 40;
private static final int LOG_ID_BITS1 = LOG_ID_BITS + 1;
private static final long LOG_ID_MASK = (1L << LOG_ID_BITS) - 1;
private static final int STATUS_BITS = 4;
private static final int STATUS_MASK = (1 << STATUS_BITS) - 1;
/** /**
* The transaction store. * The transaction store.
...@@ -81,8 +87,9 @@ public class Transaction { ...@@ -81,8 +87,9 @@ public class Transaction {
/* /*
* Transation state is an atomic composite field: * Transation state is an atomic composite field:
* bit 44 : flag whether transaction had rollback(s) * bit 45 : flag whether transaction had rollback(s)
* bits 42-40 : status * bits 44-41 : status
* bits 40 : overflow control bit, always 0
* bits 39-0 : log id of the last entry in the undo log map * bits 39-0 : log id of the last entry in the undo log map
*/ */
private final AtomicLong statusAndLogId; private final AtomicLong statusAndLogId;
...@@ -202,6 +209,12 @@ public class Transaction { ...@@ -202,6 +209,12 @@ public class Transaction {
void log(int mapId, Object key, VersionedValue oldValue) { void log(int mapId, Object key, VersionedValue oldValue) {
long currentState = statusAndLogId.getAndIncrement(); long currentState = statusAndLogId.getAndIncrement();
long logId = getLogId(currentState); long logId = getLogId(currentState);
if (logId > LOG_ID_MASK) {
throw DataUtils.newIllegalStateException(
DataUtils.ERROR_TRANSACTION_TOO_BIG,
"Transaction {0} has too many changes",
transactionId);
}
store.log(this, logId, mapId, key, oldValue); store.log(this, logId, mapId, key, oldValue);
} }
...@@ -211,6 +224,12 @@ public class Transaction { ...@@ -211,6 +224,12 @@ public class Transaction {
void logUndo() { void logUndo() {
long currentState = statusAndLogId.decrementAndGet(); long currentState = statusAndLogId.decrementAndGet();
long logId = getLogId(currentState); long logId = getLogId(currentState);
if (logId == LOG_ID_MASK) {
throw DataUtils.newIllegalStateException(
DataUtils.ERROR_TRANSACTION_CORRUPT,
"Transaction {0} has internal error",
transactionId);
}
store.logUndo(this, logId); store.logUndo(this, logId);
} }
...@@ -269,7 +288,7 @@ public class Transaction { ...@@ -269,7 +288,7 @@ public class Transaction {
* Commit the transaction. Afterwards, this transaction is closed. * Commit the transaction. Afterwards, this transaction is closed.
*/ */
public void commit() { public void commit() {
long state = setStatus(Transaction.STATUS_COMMITTING); long state = setStatus(STATUS_COMMITTING);
long logId = Transaction.getLogId(state); long logId = Transaction.getLogId(state);
int oldStatus = Transaction.getStatus(state); int oldStatus = Transaction.getStatus(state);
store.commit(this, logId, oldStatus); store.commit(this, logId, oldStatus);
...@@ -357,16 +376,16 @@ public class Transaction { ...@@ -357,16 +376,16 @@ public class Transaction {
} }
public static int getStatus(long state) { private static int getStatus(long state) {
return (int)(state >>> 40) & 15; return (int)(state >>> LOG_ID_BITS1) & STATUS_MASK;
} }
public static long getLogId(long state) { private static long getLogId(long state) {
return state & ((1L << 40) - 1); return state & LOG_ID_MASK;
} }
private static boolean hasRollback(long state) { private static boolean hasRollback(long state) {
return (state & (1L << 44)) != 0; return (state & (1L << (STATUS_BITS + LOG_ID_BITS1))) != 0;
} }
private static boolean hasChanges(long state) { private static boolean hasChanges(long state) {
...@@ -374,9 +393,12 @@ public class Transaction { ...@@ -374,9 +393,12 @@ public class Transaction {
} }
private static long composeState(int status, long logId, boolean hasRollback) { private static long composeState(int status, long logId, boolean hasRollback) {
assert (logId & ~LOG_ID_MASK) == 0 : logId;
assert (status & ~STATUS_MASK) == 0 : status;
if (hasRollback) { if (hasRollback) {
status |= 16; status |= 1 << STATUS_BITS;
} }
return ((long)status << 40) | logId; return ((long)status << LOG_ID_BITS1) | logId;
} }
} }
...@@ -156,6 +156,9 @@ public class TransactionStore { ...@@ -156,6 +156,9 @@ public class TransactionStore {
return store.hasMap(name); return store.hasMap(name);
} }
private static final int LOG_ID_BITS = Transaction.LOG_ID_BITS;
private static final long LOG_ID_MASK = (1L << LOG_ID_BITS) - 1;
/** /**
* Combine the transaction id and the log id to an operation id. * Combine the transaction id and the log id to an operation id.
* *
...@@ -164,11 +167,11 @@ public class TransactionStore { ...@@ -164,11 +167,11 @@ public class TransactionStore {
* @return the operation id * @return the operation id
*/ */
static long getOperationId(int transactionId, long logId) { static long getOperationId(int transactionId, long logId) {
DataUtils.checkArgument(transactionId >= 0 && transactionId < (1 << 24), DataUtils.checkArgument(transactionId >= 0 && transactionId < (1 << (64 - LOG_ID_BITS)),
"Transaction id out of range: {0}", transactionId); "Transaction id out of range: {0}", transactionId);
DataUtils.checkArgument(logId >= 0 && logId < (1L << 40), DataUtils.checkArgument(logId >= 0 && logId <= LOG_ID_MASK,
"Transaction log id out of range: {0}", logId); "Transaction log id out of range: {0}", logId);
return ((long) transactionId << 40) | logId; return ((long) transactionId << LOG_ID_BITS) | logId;
} }
/** /**
...@@ -178,7 +181,7 @@ public class TransactionStore { ...@@ -178,7 +181,7 @@ public class TransactionStore {
* @return the transaction id * @return the transaction id
*/ */
static int getTransactionId(long operationId) { static int getTransactionId(long operationId) {
return (int) (operationId >>> 40); return (int) (operationId >>> LOG_ID_BITS);
} }
/** /**
...@@ -188,7 +191,7 @@ public class TransactionStore { ...@@ -188,7 +191,7 @@ public class TransactionStore {
* @return the log id * @return the log id
*/ */
static long getLogId(long operationId) { static long getLogId(long operationId) {
return operationId & ((1L << 40) - 1); return operationId & LOG_ID_MASK;
} }
/** /**
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论