You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hive.apache.org by dk...@apache.org on 2020/03/23 09:26:52 UTC
[hive] branch master updated: HIVE-22888: Rewrite checkLock inner
select with JOIN operator (Denys Kuzmenko, reviewed by Peter Vary)
This is an automated email from the ASF dual-hosted git repository.
dkuzmenko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hive.git
The following commit(s) were added to refs/heads/master by this push:
new 95176bb HIVE-22888: Rewrite checkLock inner select with JOIN operator (Denys Kuzmenko, reviewed by Peter Vary)
95176bb is described below
commit 95176bb97e68a7e9af691f7f472ebed92fdba1c1
Author: Denys Kuzmenko <dk...@apache.org>
AuthorDate: Mon Mar 23 10:26:42 2020 +0100
HIVE-22888: Rewrite checkLock inner select with JOIN operator (Denys Kuzmenko, reviewed by Peter Vary)
---
.../hadoop/hive/metastore/txn/TxnDbUtil.java | 25 +-
.../hadoop/hive/metastore/txn/TxnHandler.java | 366 ++++-----------------
2 files changed, 86 insertions(+), 305 deletions(-)
diff --git a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/txn/TxnDbUtil.java b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/txn/TxnDbUtil.java
index 5f51cf5..efcf2e1 100644
--- a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/txn/TxnDbUtil.java
+++ b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/txn/TxnDbUtil.java
@@ -400,16 +400,7 @@ public final class TxnDbUtil {
stmt = conn.createStatement();
// We want to try these, whether they succeed or fail.
- try {
- stmt.execute("DROP INDEX HL_TXNID_INDEX");
- } catch (SQLException e) {
- if(!("42X65".equals(e.getSQLState()) && 30000 == e.getErrorCode())) {
- //42X65/3000 means index doesn't exist
- LOG.error("Unable to drop index HL_TXNID_INDEX " + e.getMessage() +
- "State=" + e.getSQLState() + " code=" + e.getErrorCode() + " retryCount=" + retryCount);
- success = false;
- }
- }
+ success &= dropIndex(stmt, "HL_TXNID_INDEX", retryCount);
success &= dropTable(stmt, "TXN_COMPONENTS", retryCount);
success &= dropTable(stmt, "COMPLETED_TXN_COMPONENTS", retryCount);
@@ -443,6 +434,20 @@ public final class TxnDbUtil {
throw new RuntimeException("Failed to clean up txn tables");
}
+ private static boolean dropIndex(Statement stmt, String index, int retryCount) {
+ try {
+ stmt.execute("DROP INDEX " + index);
+ } catch (SQLException e) {
+ if (!("42X65".equals(e.getSQLState()) && 30000 == e.getErrorCode())) {
+ //42X65/3000 means index doesn't exist
+ LOG.error("Unable to drop index {} {} State={} code={} retryCount={}",
+ index, e.getMessage(), e.getSQLState(), e.getErrorCode(), retryCount);
+ return false;
+ }
+ }
+ return true;
+ }
+
private static boolean dropTable(Statement stmt, String name, int retryCount) throws SQLException {
for (int i = 0; i < 3; i++) {
try {
diff --git a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/txn/TxnHandler.java b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/txn/TxnHandler.java
index 2995afa..42cd89f 100644
--- a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/txn/TxnHandler.java
+++ b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/txn/TxnHandler.java
@@ -41,8 +41,6 @@ import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
@@ -324,7 +322,6 @@ abstract class TxnHandler implements TxnStore, TxnStore.MutexAPI {
numOpenTxns = Metrics.getOrCreateGauge(MetricsConstants.NUM_OPEN_TXNS);
timeout = MetastoreConf.getTimeVar(conf, ConfVars.TXN_TIMEOUT, TimeUnit.MILLISECONDS);
- buildJumpTable();
retryInterval = MetastoreConf.getTimeVar(conf, ConfVars.HMS_HANDLER_INTERVAL,
TimeUnit.MILLISECONDS);
retryLimit = MetastoreConf.getIntVar(conf, ConfVars.HMS_HANDLER_ATTEMPTS);
@@ -2608,7 +2605,7 @@ abstract class TxnHandler implements TxnStore, TxnStore.MutexAPI {
}
private LockResponse checkLockWithRetry(Connection dbConn, long extLockId, long txnId)
- throws NoSuchLockException, NoSuchTxnException, TxnAbortedException, MetaException {
+ throws NoSuchLockException, TxnAbortedException, MetaException {
try {
try {
lockInternal();
@@ -2616,7 +2613,7 @@ abstract class TxnHandler implements TxnStore, TxnStore.MutexAPI {
//should only get here if retrying this op
dbConn = getDbConn(Connection.TRANSACTION_READ_COMMITTED);
}
- return checkLock(dbConn, extLockId);
+ return checkLock(dbConn, extLockId, txnId);
} catch (SQLException e) {
LOG.debug("Going to rollback");
rollbackDBConn(dbConn);
@@ -2676,7 +2673,7 @@ abstract class TxnHandler implements TxnStore, TxnStore.MutexAPI {
//todo: strictly speaking there is a bug here. heartbeat*() commits but both heartbeat and
//checkLock() are in the same retry block, so if checkLock() throws, heartbeat is also retired
//extra heartbeat is logically harmless, but ...
- return checkLock(dbConn, extLockId);
+ return checkLock(dbConn, extLockId, info.txnId);
} catch (SQLException e) {
LOG.debug("Going to rollback");
rollbackDBConn(dbConn);
@@ -4310,8 +4307,8 @@ abstract class TxnHandler implements TxnStore, TxnStore.MutexAPI {
* checkLock() will in the worst case keep locks in Waiting state a little longer.
*/
@RetrySemantics.SafeToRetry("See @SafeToRetry")
- private LockResponse checkLock(Connection dbConn, long extLockId)
- throws NoSuchLockException, TxnAbortedException, MetaException, SQLException {
+ private LockResponse checkLock(Connection dbConn, long extLockId, long txnId)
+ throws NoSuchLockException, TxnAbortedException, MetaException, SQLException {
Statement stmt = null;
ResultSet rs = null;
LockResponse response = new LockResponse();
@@ -4327,21 +4324,13 @@ abstract class TxnHandler implements TxnStore, TxnStore.MutexAPI {
*/
boolean isPartOfDynamicPartitionInsert = true;
try {
- List<LockInfo> locksBeingChecked = getLockInfoFromLockId(dbConn, extLockId);//being acquired now
+ List<LockInfo> locksBeingChecked = getLockInfoFromLockId(dbConn, extLockId); //being acquired now
response.setLockid(extLockId);
- LOG.debug("checkLock(): Setting savepoint. extLockId=" + JavaUtils.lockIdToString(extLockId));
-
- StringBuilder query = new StringBuilder("SELECT \"HL_LOCK_EXT_ID\", " +
- "\"HL_LOCK_INT_ID\", \"HL_DB\", \"HL_TABLE\", \"HL_PARTITION\", \"HL_LOCK_STATE\", " +
- "\"HL_LOCK_TYPE\", \"HL_TXNID\" FROM \"HIVE_LOCKS\" WHERE \"HL_DB\" IN (");
-
- Set<String> strings = new HashSet<>(locksBeingChecked.size());
//This the set of entities that the statement represented by extLockId wants to update
List<LockInfo> writeSet = new ArrayList<>();
for (LockInfo info : locksBeingChecked) {
- strings.add(info.db);
if(!isPartOfDynamicPartitionInsert && info.type == LockType.SHARED_WRITE) {
writeSet.add(info);
}
@@ -4399,155 +4388,80 @@ abstract class TxnHandler implements TxnStore, TxnStore.MutexAPI {
close(rs, stmt, null);
}
- boolean first = true;
- for (String s : strings) {
- if (first) first = false;
- else query.append(", ");
- query.append('\'');
- query.append(s);
- query.append('\'');
- }
- query.append(")");
-
- // If any of the table requests are null, then I need to pull all the
- // table locks for this db.
- boolean sawNull = false;
- strings.clear();
- for (LockInfo info : locksBeingChecked) {
- if (info.table == null) {
- sawNull = true;
- break;
- } else {
- strings.add(info.table);
- }
- }
- if (!sawNull) {
- query.append(" AND (\"HL_TABLE\" IS NULL OR \"HL_TABLE\" IN(");
- first = true;
- for (String s : strings) {
- if (first) first = false;
- else query.append(", ");
- query.append('\'');
- query.append(s);
- query.append('\'');
- }
- query.append("))");
-
- // If any of the partition requests are null, then I need to pull all
- // partition locks for this table.
- sawNull = false;
- strings.clear();
- for (LockInfo info : locksBeingChecked) {
- if (info.partition == null) {
- sawNull = true;
- break;
- } else {
- strings.add(info.partition);
- }
- }
- if (!sawNull) {
- query.append(" AND (\"HL_PARTITION\" IS NULL OR \"HL_PARTITION\" IN(");
- first = true;
- for (String s : strings) {
- if (first) first = false;
- else query.append(", ");
- query.append('\'');
- query.append(s);
- query.append('\'');
- }
- query.append("))");
- }
- }
- query.append(" AND \"HL_LOCK_EXT_ID\" < ").append(extLockId);
+ String queryStr =
+ " \"EX\".*, \"REQ\".\"HL_LOCK_INT_ID\" AS \"REQ_LOCK_INT_ID\" FROM (" +
+ " SELECT \"HL_LOCK_EXT_ID\", \"HL_LOCK_INT_ID\", \"HL_TXNID\", \"HL_DB\", \"HL_TABLE\", \"HL_PARTITION\"," +
+ " \"HL_LOCK_STATE\", \"HL_LOCK_TYPE\" FROM \"HIVE_LOCKS\"" +
+ " WHERE \"HL_LOCK_EXT_ID\" < " + extLockId + ") \"EX\"" +
+ " INNER JOIN (" +
+ " SELECT \"HL_LOCK_INT_ID\", \"HL_TXNID\", \"HL_DB\", \"HL_TABLE\", \"HL_PARTITION\"," +
+ " \"HL_LOCK_TYPE\" FROM \"HIVE_LOCKS\"" +
+ " WHERE \"HL_LOCK_EXT_ID\" = " + extLockId + ") \"REQ\"" +
+ " ON \"EX\".\"HL_DB\" = \"REQ\".\"HL_DB\"" +
+ " AND (\"EX\".\"HL_TABLE\" IS NULL OR \"REQ\".\"HL_TABLE\" IS NULL" +
+ " OR \"EX\".\"HL_TABLE\" = \"REQ\".\"HL_TABLE\"" +
+ " AND (\"EX\".\"HL_PARTITION\" IS NULL OR \"REQ\".\"HL_PARTITION\" IS NULL" +
+ " OR \"EX\".\"HL_PARTITION\" = \"REQ\".\"HL_PARTITION\"))" +
+ /*different locks from same txn should not conflict with each other,
+ txnId=0 means it's a select or IUD which does not write to ACID table*/
+ " WHERE (\"REQ\".\"HL_TXNID\" = 0 OR \"EX\".\"HL_TXNID\" != \"REQ\".\"HL_TXNID\")" +
+ " AND ";
+
+ /*EXCLUSIVE lock on partition should prevent SHARED_READ on the table, however there is no reason
+ for an EXCLUSIVE on a table to prevent SHARED_READ on a database. Similarly, EXCLUSIVE on a partition
+ should not conflict with SHARED_READ on a database.
+ SHARED_READ is usually acquired on a database to make sure it's not dropped, while some operation
+ is performed on that db (e.g. show tables, created table, etc).
+ EXCLUSIVE on an object may mean it's being dropped or overwritten.*/
+ String[] whereStr = {
+ // exclusive
+ " \"REQ\".\"HL_LOCK_TYPE\"='e'" +
+ " AND NOT (\"EX\".\"HL_TABLE\" IS NULL AND \"EX\".\"HL_LOCK_TYPE\"='r' AND \"REQ\".\"HL_TABLE\" IS NOT NULL)",
+ // shared-write
+ " \"REQ\".\"HL_LOCK_TYPE\"='w' AND \"EX\".\"HL_LOCK_TYPE\" IN ('w','e')",
+ // shared-read
+ " \"REQ\".\"HL_LOCK_TYPE\"='r' AND \"EX\".\"HL_LOCK_TYPE\"='e'" +
+ " AND NOT (\"EX\".\"HL_TABLE\" IS NOT NULL AND \"REQ\".\"HL_TABLE\" IS NULL)",
+ };
+
+ List<String> subQuery = new ArrayList<>();
+ for (String subCond : whereStr) {
+ subQuery.add("(" + sqlGenerator.addLimitClause(1, queryStr + subCond) + ")");
+ }
+ String query = String.join(" UNION ALL ", subQuery);
- LOG.debug("Going to execute query <" + query.toString() + ">");
stmt = dbConn.createStatement();
- rs = stmt.executeQuery(query.toString());
- SortedSet<LockInfo> lockSet = new TreeSet<LockInfo>(new LockInfoComparator());
- while (rs.next()) {
- lockSet.add(new LockInfo(rs));
- }
- // Turn the tree set into an array so we can move back and forth easily
- // in it.
- LockInfo[] locks = lockSet.toArray(new LockInfo[lockSet.size()]);
- if(LOG.isTraceEnabled()) {
- LOG.trace("Locks to check(full): ");
- for(LockInfo info : locks) {
- LOG.trace(" " + info);
- }
- }
+ LOG.debug("Going to execute query <" + query + ">");
+ rs = stmt.executeQuery(query);
- for (LockInfo info : locksBeingChecked) {
- // If we've found it and it's already been marked acquired,
- // then just look at the other locks.
- if (info.state == LockState.ACQUIRED) {
- /**this is what makes this method @SafeToRetry*/
- continue;
- }
+ if (rs.next()) {
+ // We acquire all locks for a given query atomically; if 1 blocks, all remain in Waiting state.
+ LockInfo blockedBy = new LockInfo(rs);
+ long intLockId = rs.getLong("REQ_LOCK_INT_ID");
- // Look at everything in front of this lock to see if it should block
- // it or not.
- for (int i = locks.length - 1; i >= 0; i--) {
- // Check if we're operating on the same database, if not, move on
- if (!info.db.equals(locks[i].db)) {
- continue;
- }
+ String sqlText = "UPDATE \"HIVE_LOCKS\"" +
+ " SET \"HL_BLOCKEDBY_EXT_ID\" = " + blockedBy.extLockId +
+ ", \"HL_BLOCKEDBY_INT_ID\" = " + blockedBy.intLockId +
+ " WHERE \"HL_LOCK_EXT_ID\" = " + extLockId + " AND \"HL_LOCK_INT_ID\" = " + intLockId;
- // If table is null on either of these, then they are claiming to
- // lock the whole database and we need to check it. Otherwise,
- // check if they are operating on the same table, if not, move on.
- if (info.table != null && locks[i].table != null
- && !info.table.equals(locks[i].table)) {
- continue;
- }
- // if here, we may be checking a DB level lock against a Table level lock. Alternatively,
- // we could have used Intention locks (for example a request for S lock on table would
- // cause an IS lock DB that contains the table). Similarly, at partition level.
-
- // If partition is null on either of these, then they are claiming to
- // lock the whole table and we need to check it. Otherwise,
- // check if they are operating on the same partition, if not, move on.
- if (info.partition != null && locks[i].partition != null
- && !info.partition.equals(locks[i].partition)) {
- continue;
- }
+ LOG.debug("Executing sql: " + sqlText);
+ int updCnt = stmt.executeUpdate(sqlText);
- // We've found something that matches what we're trying to lock,
- // so figure out if we can lock it too.
- LockAction lockAction = jumpTable.get(info.type).get(locks[i].type).get(locks[i].state);
- LOG.debug("desired Lock: " + info + " checked Lock: " + locks[i] + " action: " + lockAction);
- switch (lockAction) {
- case WAIT:
- if(!ignoreConflict(info, locks[i])) {
- String sqlText = "UPDATE \"HIVE_LOCKS\"" +
- " SET \"HL_BLOCKEDBY_EXT_ID\"=" + locks[i].extLockId +
- ", \"HL_BLOCKEDBY_INT_ID\"=" + locks[i].intLockId +
- " WHERE \"HL_LOCK_EXT_ID\"=" + info.extLockId + " AND \"HL_LOCK_INT_ID\"=" + info.intLockId;
- LOG.debug("Executing sql: " + sqlText);
- int updCnt = stmt.executeUpdate(sqlText);
- if(updCnt != 1) {
- shouldNeverHappen(info.txnId, info.extLockId, info.intLockId);
- }
- LOG.debug("Going to commit");
- dbConn.commit();
- response.setState(LockState.WAITING);
- LOG.debug("Lock(" + info + ") waiting for Lock(" + locks[i] + ")");
- return response;
- }
- //fall through to ACQUIRE
- case ACQUIRE:
- break;
- case KEEP_LOOKING:
- continue;
- }
- //if we got here, it means it's ok to acquire 'info' lock
- break;// so exit the loop and check next lock
+ if (updCnt != 1) {
+ shouldNeverHappen(txnId, extLockId, intLockId);
}
+ LOG.debug("Going to commit");
+ dbConn.commit();
+
+ LOG.debug("Lock({} intLockId:{} {}) is blocked by Lock({}})", JavaUtils.lockIdToString(extLockId),
+ intLockId, JavaUtils.txnIdToString(txnId), blockedBy);
+ response.setState(LockState.WAITING);
+ return response;
}
- //if here, ther were no locks that blocked any locks in 'locksBeingChecked' - acquire them all
+ // If here, there were no locks that would block any item from 'locksBeingChecked' - acquire them all
acquire(dbConn, stmt, locksBeingChecked);
- // We acquired all of the locks, so commit and return acquired.
+ // We acquired all the locks, so commit and return acquired.
LOG.debug("Going to commit");
dbConn.commit();
response.setState(LockState.ACQUIRED);
@@ -4556,6 +4470,7 @@ abstract class TxnHandler implements TxnStore, TxnStore.MutexAPI {
}
return response;
}
+
private void acquire(Connection dbConn, Statement stmt, List<LockInfo> locksBeingChecked)
throws SQLException, NoSuchLockException, MetaException {
if(locksBeingChecked == null || locksBeingChecked.isEmpty()) {
@@ -4600,37 +4515,6 @@ abstract class TxnHandler implements TxnStore, TxnStore.MutexAPI {
}
/**
- * the {@link #jumpTable} only deals with LockState/LockType. In some cases it's not
- * sufficient. For example, an EXCLUSIVE lock on partition should prevent SHARED_READ
- * on the table, but there is no reason for EXCLUSIVE on a table to prevent SHARED_READ
- * on a database. Similarly, EXCLUSIVE on a partition should not conflict with SHARED_READ on
- * a database. (SHARED_READ is usually acquired on a database to make sure it's not dropped
- * while some operation is performed on that db (e.g. show tables, created table, etc)
- * EXCLUSIVE on an object may mean it's being dropped or overwritten (for non-acid tables,
- * an Insert uses EXCLUSIVE as well)).
- */
- private boolean ignoreConflict(LockInfo desiredLock, LockInfo existingLock) {
- return
- ((desiredLock.isDbLock() && desiredLock.type == LockType.SHARED_READ &&
- existingLock.isTableLock() && existingLock.type == LockType.EXCLUSIVE) ||
- (existingLock.isDbLock() && existingLock.type == LockType.SHARED_READ &&
- desiredLock.isTableLock() && desiredLock.type == LockType.EXCLUSIVE) ||
-
- (desiredLock.isDbLock() && desiredLock.type == LockType.SHARED_READ &&
- existingLock.isPartitionLock() && existingLock.type == LockType.EXCLUSIVE) ||
- (existingLock.isDbLock() && existingLock.type == LockType.SHARED_READ &&
- desiredLock.isPartitionLock() && desiredLock.type == LockType.EXCLUSIVE))
- ||
-
- //different locks from same txn should not conflict with each other
- (desiredLock.txnId != 0 && desiredLock.txnId == existingLock.txnId) ||
- //txnId=0 means it's a select or IUD which does not write to ACID table, e.g
- //insert overwrite table T partition(p=1) select a,b from T and autoCommit=true
- // todo: fix comment as of HIVE-14988
- (desiredLock.txnId == 0 && desiredLock.extLockId == existingLock.extLockId);
- }
-
- /**
* Heartbeats on the lock table. This commits, so do not enter it with any state.
* Should not be called on a lock that belongs to transaction.
*/
@@ -5109,114 +4993,6 @@ abstract class TxnHandler implements TxnStore, TxnStore.MutexAPI {
}
}
- private static synchronized void buildJumpTable() {
- if (jumpTable != null) return;
-
- jumpTable = new HashMap<>(3);
-
- // SR: Lock we are trying to acquire is shared read
- Map<LockType, Map<LockState, LockAction>> m = new HashMap<>(3);
- jumpTable.put(LockType.SHARED_READ, m);
-
- // SR.SR: Lock we are examining is shared read
- Map<LockState, LockAction> m2 = new HashMap<>(2);
- m.put(LockType.SHARED_READ, m2);
-
- // SR.SR.acquired Lock we are examining is acquired; We can acquire
- // because two shared reads can acquire together and there must be
- // nothing in front of this one to prevent acquisition.
- m2.put(LockState.ACQUIRED, LockAction.ACQUIRE);
-
- // SR.SR.wait Lock we are examining is waiting. In this case we keep
- // looking, as it's possible that something in front is blocking it or
- // that the other locker hasn't checked yet and he could lock as well.
- m2.put(LockState.WAITING, LockAction.KEEP_LOOKING);
-
- // SR.SW: Lock we are examining is shared write
- m2 = new HashMap<>(2);
- m.put(LockType.SHARED_WRITE, m2);
-
- // SR.SW.acquired Lock we are examining is acquired; We can acquire
- // because a read can share with a write, and there must be
- // nothing in front of this one to prevent acquisition.
- m2.put(LockState.ACQUIRED, LockAction.ACQUIRE);
-
- // SR.SW.wait Lock we are examining is waiting. In this case we keep
- // looking, as it's possible that something in front is blocking it or
- // that the other locker hasn't checked yet and he could lock as well or
- // that something is blocking it that would not block a read.
- m2.put(LockState.WAITING, LockAction.KEEP_LOOKING);
-
- // SR.E: Lock we are examining is exclusive
- m2 = new HashMap<>(2);
- m.put(LockType.EXCLUSIVE, m2);
-
- // No matter whether it has acquired or not, we cannot pass an exclusive.
- m2.put(LockState.ACQUIRED, LockAction.WAIT);
- m2.put(LockState.WAITING, LockAction.WAIT);
-
- // SW: Lock we are trying to acquire is shared write
- m = new HashMap<>(3);
- jumpTable.put(LockType.SHARED_WRITE, m);
-
- // SW.SR: Lock we are examining is shared read
- m2 = new HashMap<>(2);
- m.put(LockType.SHARED_READ, m2);
-
- // SW.SR.acquired Lock we are examining is acquired; We need to keep
- // looking, because there may or may not be another shared write in front
- // that would block us.
- m2.put(LockState.ACQUIRED, LockAction.KEEP_LOOKING);
-
- // SW.SR.wait Lock we are examining is waiting. In this case we keep
- // looking, as it's possible that something in front is blocking it or
- // that the other locker hasn't checked yet and he could lock as well.
- m2.put(LockState.WAITING, LockAction.KEEP_LOOKING);
-
- // SW.SW: Lock we are examining is shared write
- m2 = new HashMap<>(2);
- m.put(LockType.SHARED_WRITE, m2);
-
- // Regardless of acquired or waiting, one shared write cannot pass another.
- m2.put(LockState.ACQUIRED, LockAction.WAIT);
- m2.put(LockState.WAITING, LockAction.WAIT);
-
- // SW.E: Lock we are examining is exclusive
- m2 = new HashMap<>(2);
- m.put(LockType.EXCLUSIVE, m2);
-
- // No matter whether it has acquired or not, we cannot pass an exclusive.
- m2.put(LockState.ACQUIRED, LockAction.WAIT);
- m2.put(LockState.WAITING, LockAction.WAIT);
-
- // E: Lock we are trying to acquire is exclusive
- m = new HashMap<>(3);
- jumpTable.put(LockType.EXCLUSIVE, m);
-
- // E.SR: Lock we are examining is shared read
- m2 = new HashMap<>(2);
- m.put(LockType.SHARED_READ, m2);
-
- // Exclusives can never pass
- m2.put(LockState.ACQUIRED, LockAction.WAIT);
- m2.put(LockState.WAITING, LockAction.WAIT);
-
- // E.SW: Lock we are examining is shared write
- m2 = new HashMap<>(2);
- m.put(LockType.SHARED_WRITE, m2);
-
- // Exclusives can never pass
- m2.put(LockState.ACQUIRED, LockAction.WAIT);
- m2.put(LockState.WAITING, LockAction.WAIT);
-
- // E.E: Lock we are examining is exclusive
- m2 = new HashMap<>(2);
- m.put(LockType.EXCLUSIVE, m2);
-
- // No matter whether it has acquired or not, we cannot pass an exclusive.
- m2.put(LockState.ACQUIRED, LockAction.WAIT);
- m2.put(LockState.WAITING, LockAction.WAIT);
- }
/**
* Returns true if {@code ex} should be retried
*/