提交 b196558d authored 作者: noelgrandin@gmail.com's avatar noelgrandin@gmail.com

some minor renaming and code movement around table locking to make it easier for…

some minor renaming and code movement around table locking to make it easier for me to follow the code
上级 de2dfbc4
...@@ -50,8 +50,8 @@ public class MVTable extends TableBase { ...@@ -50,8 +50,8 @@ public class MVTable extends TableBase {
private MVPrimaryIndex primaryIndex; private MVPrimaryIndex primaryIndex;
private ArrayList<Index> indexes = New.arrayList(); private ArrayList<Index> indexes = New.arrayList();
private long lastModificationId; private long lastModificationId;
private volatile Session lockExclusive; private volatile Session lockExclusiveSession;
private HashSet<Session> lockShared = New.hashSet(); private HashSet<Session> lockSharedSessions = New.hashSet();
private final Trace traceLock; private final Trace traceLock;
private int changesSinceAnalyze; private int changesSinceAnalyze;
private int nextAnalyze; private int nextAnalyze;
...@@ -99,12 +99,12 @@ public class MVTable extends TableBase { ...@@ -99,12 +99,12 @@ public class MVTable extends TableBase {
} }
@Override @Override
public void lock(Session session, boolean exclusive, boolean force) { public void lock(Session session, boolean exclusive, boolean forceLockEvenInMvcc) {
int lockMode = database.getLockMode(); int lockMode = database.getLockMode();
if (lockMode == Constants.LOCK_MODE_OFF) { if (lockMode == Constants.LOCK_MODE_OFF) {
return; return;
} }
if (!force && database.isMultiVersion()) { if (!forceLockEvenInMvcc && database.isMultiVersion()) {
// MVCC: update, delete, and insert use a shared lock. // MVCC: update, delete, and insert use a shared lock.
// Select doesn't lock except when using FOR UPDATE and // Select doesn't lock except when using FOR UPDATE and
// the system property h2.selectForUpdateMvcc // the system property h2.selectForUpdateMvcc
...@@ -112,15 +112,19 @@ public class MVTable extends TableBase { ...@@ -112,15 +112,19 @@ public class MVTable extends TableBase {
if (exclusive) { if (exclusive) {
exclusive = false; exclusive = false;
} else { } else {
if (lockExclusive == null) { if (lockExclusiveSession == null) {
return; return;
} }
} }
} }
if (lockExclusive == session) { if (lockExclusiveSession == session) {
return; return;
} }
synchronized (database) { synchronized (database) {
if (lockExclusiveSession == session) {
return;
}
session.setWaitForLock(this, Thread.currentThread());
try { try {
doLock(session, lockMode, exclusive); doLock(session, lockMode, exclusive);
} finally { } finally {
...@@ -135,24 +139,21 @@ public class MVTable extends TableBase { ...@@ -135,24 +139,21 @@ public class MVTable extends TableBase {
long max = 0; long max = 0;
boolean checkDeadlock = false; boolean checkDeadlock = false;
while (true) { while (true) {
if (lockExclusive == session) {
return;
}
if (exclusive) { if (exclusive) {
if (lockExclusive == null) { if (lockExclusiveSession == null) {
if (lockShared.isEmpty()) { if (lockSharedSessions.isEmpty()) {
traceLock(session, exclusive, "added for"); traceLock(session, exclusive, "added for");
session.addLock(this); session.addLock(this);
lockExclusive = session; lockExclusiveSession = session;
return; return;
} else if (lockShared.size() == 1 && lockShared.contains(session)) { } else if (lockSharedSessions.size() == 1 && lockSharedSessions.contains(session)) {
traceLock(session, exclusive, "add (upgraded) for "); traceLock(session, exclusive, "add (upgraded) for ");
lockExclusive = session; lockExclusiveSession = session;
return; return;
} }
} }
} else { } else {
if (lockExclusive == null) { if (lockExclusiveSession == null) {
if (lockMode == Constants.LOCK_MODE_READ_COMMITTED) { if (lockMode == Constants.LOCK_MODE_READ_COMMITTED) {
if (!database.isMultiThreaded() && !database.isMultiVersion()) { if (!database.isMultiThreaded() && !database.isMultiVersion()) {
// READ_COMMITTED: a read lock is acquired, // READ_COMMITTED: a read lock is acquired,
...@@ -164,15 +165,14 @@ public class MVTable extends TableBase { ...@@ -164,15 +165,14 @@ public class MVTable extends TableBase {
return; return;
} }
} }
if (!lockShared.contains(session)) { if (!lockSharedSessions.contains(session)) {
traceLock(session, exclusive, "ok"); traceLock(session, exclusive, "ok");
session.addLock(this); session.addLock(this);
lockShared.add(session); lockSharedSessions.add(session);
} }
return; return;
} }
} }
session.setWaitForLock(this, Thread.currentThread());
if (checkDeadlock) { if (checkDeadlock) {
ArrayList<Session> sessions = checkDeadlock(session, null, null); ArrayList<Session> sessions = checkDeadlock(session, null, null);
if (sessions != null) { if (sessions != null) {
...@@ -239,7 +239,7 @@ public class MVTable extends TableBase { ...@@ -239,7 +239,7 @@ public class MVTable extends TableBase {
} }
buff.append(t.toString()); buff.append(t.toString());
if (t instanceof RegularTable) { if (t instanceof RegularTable) {
if (((MVTable) t).lockExclusive == s) { if (((MVTable) t).lockExclusiveSession == s) {
buff.append(" (exclusive)"); buff.append(" (exclusive)");
} else { } else {
buff.append(" (shared)"); buff.append(" (shared)");
...@@ -271,7 +271,7 @@ public class MVTable extends TableBase { ...@@ -271,7 +271,7 @@ public class MVTable extends TableBase {
} }
visited.add(session); visited.add(session);
ArrayList<Session> error = null; ArrayList<Session> error = null;
for (Session s : lockShared) { for (Session s : lockSharedSessions) {
if (s == session) { if (s == session) {
// it doesn't matter if we have locked the object already // it doesn't matter if we have locked the object already
continue; continue;
...@@ -285,10 +285,10 @@ public class MVTable extends TableBase { ...@@ -285,10 +285,10 @@ public class MVTable extends TableBase {
} }
} }
} }
if (error == null && lockExclusive != null) { if (error == null && lockExclusiveSession != null) {
Table t = lockExclusive.getWaitForLock(); Table t = lockExclusiveSession.getWaitForLock();
if (t != null) { if (t != null) {
error = t.checkDeadlock(lockExclusive, clash, visited); error = t.checkDeadlock(lockExclusiveSession, clash, visited);
if (error != null) { if (error != null) {
error.add(session); error.add(session);
} }
...@@ -308,23 +308,23 @@ public class MVTable extends TableBase { ...@@ -308,23 +308,23 @@ public class MVTable extends TableBase {
@Override @Override
public boolean isLockedExclusively() { public boolean isLockedExclusively() {
return lockExclusive != null; return lockExclusiveSession != null;
} }
@Override @Override
public boolean isLockedExclusivelyBy(Session session) { public boolean isLockedExclusivelyBy(Session session) {
return lockExclusive == session; return lockExclusiveSession == session;
} }
@Override @Override
public void unlock(Session s) { public void unlock(Session s) {
if (database != null) { if (database != null) {
traceLock(s, lockExclusive == s, "unlock"); traceLock(s, lockExclusiveSession == s, "unlock");
if (lockExclusive == s) { if (lockExclusiveSession == s) {
lockExclusive = null; lockExclusiveSession = null;
} }
if (lockShared.size() > 0) { if (lockSharedSessions.size() > 0) {
lockShared.remove(s); lockSharedSessions.remove(s);
} }
// TODO lock: maybe we need we fifo-queue to make sure nobody // TODO lock: maybe we need we fifo-queue to make sure nobody
// starves. check what other databases do // starves. check what other databases do
......
...@@ -87,7 +87,7 @@ public class FunctionTable extends Table { ...@@ -87,7 +87,7 @@ public class FunctionTable extends Table {
} }
@Override @Override
public void lock(Session session, boolean exclusive, boolean force) { public void lock(Session session, boolean exclusive, boolean forceLockEvenInMvcc) {
// nothing to do // nothing to do
} }
......
...@@ -590,7 +590,7 @@ public class MetaTable extends Table { ...@@ -590,7 +590,7 @@ public class MetaTable extends Table {
} }
@Override @Override
public void lock(Session session, boolean exclusive, boolean force) { public void lock(Session session, boolean exclusive, boolean forceLockEvenInMvcc) {
// nothing to do // nothing to do
} }
......
...@@ -64,7 +64,7 @@ public class RangeTable extends Table { ...@@ -64,7 +64,7 @@ public class RangeTable extends Table {
} }
@Override @Override
public void lock(Session session, boolean exclusive, boolean force) { public void lock(Session session, boolean exclusive, boolean forceLockEvenInMvcc) {
// nothing to do // nothing to do
} }
......
...@@ -52,8 +52,8 @@ public class RegularTable extends TableBase { ...@@ -52,8 +52,8 @@ public class RegularTable extends TableBase {
private Index scanIndex; private Index scanIndex;
private long rowCount; private long rowCount;
private volatile Session lockExclusive; private volatile Session lockExclusiveSession;
private HashSet<Session> lockShared = New.hashSet(); private HashSet<Session> lockSharedSessions = New.hashSet();
private final Trace traceLock; private final Trace traceLock;
private final ArrayList<Index> indexes = New.arrayList(); private final ArrayList<Index> indexes = New.arrayList();
private long lastModificationId; private long lastModificationId;
...@@ -435,30 +435,34 @@ public class RegularTable extends TableBase { ...@@ -435,30 +435,34 @@ public class RegularTable extends TableBase {
@Override @Override
public boolean isLockedExclusivelyBy(Session session) { public boolean isLockedExclusivelyBy(Session session) {
return lockExclusive == session; return lockExclusiveSession == session;
} }
@Override @Override
public void lock(Session session, boolean exclusive, boolean force) { public void lock(Session session, boolean exclusive, boolean forceLockEvenInMvcc) {
int lockMode = database.getLockMode(); int lockMode = database.getLockMode();
if (lockMode == Constants.LOCK_MODE_OFF) { if (lockMode == Constants.LOCK_MODE_OFF) {
return; return;
} }
if (!force && database.isMultiVersion()) { if (!forceLockEvenInMvcc && database.isMultiVersion()) {
// MVCC: update, delete, and insert use a shared lock. // MVCC: update, delete, and insert use a shared lock.
// Select doesn't lock except when using FOR UPDATE // Select doesn't lock except when using FOR UPDATE
if (exclusive) { if (exclusive) {
exclusive = false; exclusive = false;
} else { } else {
if (lockExclusive == null) { if (lockExclusiveSession == null) {
return; return;
} }
} }
} }
if (lockExclusive == session) { if (lockExclusiveSession == session) {
return; return;
} }
synchronized (database) { synchronized (database) {
if (lockExclusiveSession == session) {
return;
}
session.setWaitForLock(this, Thread.currentThread());
try { try {
doLock(session, lockMode, exclusive); doLock(session, lockMode, exclusive);
} finally { } finally {
...@@ -473,24 +477,21 @@ public class RegularTable extends TableBase { ...@@ -473,24 +477,21 @@ public class RegularTable extends TableBase {
long max = 0; long max = 0;
boolean checkDeadlock = false; boolean checkDeadlock = false;
while (true) { while (true) {
if (lockExclusive == session) {
return;
}
if (exclusive) { if (exclusive) {
if (lockExclusive == null) { if (lockExclusiveSession == null) {
if (lockShared.isEmpty()) { if (lockSharedSessions.isEmpty()) {
traceLock(session, exclusive, "added for"); traceLock(session, exclusive, "added for");
session.addLock(this); session.addLock(this);
lockExclusive = session; lockExclusiveSession = session;
return; return;
} else if (lockShared.size() == 1 && lockShared.contains(session)) { } else if (lockSharedSessions.size() == 1 && lockSharedSessions.contains(session)) {
traceLock(session, exclusive, "add (upgraded) for "); traceLock(session, exclusive, "add (upgraded) for ");
lockExclusive = session; lockExclusiveSession = session;
return; return;
} }
} }
} else { } else {
if (lockExclusive == null) { if (lockExclusiveSession == null) {
if (lockMode == Constants.LOCK_MODE_READ_COMMITTED) { if (lockMode == Constants.LOCK_MODE_READ_COMMITTED) {
if (!database.isMultiThreaded() && !database.isMultiVersion()) { if (!database.isMultiThreaded() && !database.isMultiVersion()) {
// READ_COMMITTED: a read lock is acquired, // READ_COMMITTED: a read lock is acquired,
...@@ -502,15 +503,14 @@ public class RegularTable extends TableBase { ...@@ -502,15 +503,14 @@ public class RegularTable extends TableBase {
return; return;
} }
} }
if (!lockShared.contains(session)) { if (!lockSharedSessions.contains(session)) {
traceLock(session, exclusive, "ok"); traceLock(session, exclusive, "ok");
session.addLock(this); session.addLock(this);
lockShared.add(session); lockSharedSessions.add(session);
} }
return; return;
} }
} }
session.setWaitForLock(this, Thread.currentThread());
if (checkDeadlock) { if (checkDeadlock) {
ArrayList<Session> sessions = checkDeadlock(session, null, null); ArrayList<Session> sessions = checkDeadlock(session, null, null);
if (sessions != null) { if (sessions != null) {
...@@ -574,7 +574,7 @@ public class RegularTable extends TableBase { ...@@ -574,7 +574,7 @@ public class RegularTable extends TableBase {
} }
buff.append(t.toString()); buff.append(t.toString());
if (t instanceof RegularTable) { if (t instanceof RegularTable) {
if (((RegularTable) t).lockExclusive == s) { if (((RegularTable) t).lockExclusiveSession == s) {
buff.append(" (exclusive)"); buff.append(" (exclusive)");
} else { } else {
buff.append(" (shared)"); buff.append(" (shared)");
...@@ -606,7 +606,7 @@ public class RegularTable extends TableBase { ...@@ -606,7 +606,7 @@ public class RegularTable extends TableBase {
} }
visited.add(session); visited.add(session);
ArrayList<Session> error = null; ArrayList<Session> error = null;
for (Session s : lockShared) { for (Session s : lockSharedSessions) {
if (s == session) { if (s == session) {
// it doesn't matter if we have locked the object already // it doesn't matter if we have locked the object already
continue; continue;
...@@ -620,10 +620,10 @@ public class RegularTable extends TableBase { ...@@ -620,10 +620,10 @@ public class RegularTable extends TableBase {
} }
} }
} }
if (error == null && lockExclusive != null) { if (error == null && lockExclusiveSession != null) {
Table t = lockExclusive.getWaitForLock(); Table t = lockExclusiveSession.getWaitForLock();
if (t != null) { if (t != null) {
error = t.checkDeadlock(lockExclusive, clash, visited); error = t.checkDeadlock(lockExclusiveSession, clash, visited);
if (error != null) { if (error != null) {
error.add(session); error.add(session);
} }
...@@ -642,18 +642,18 @@ public class RegularTable extends TableBase { ...@@ -642,18 +642,18 @@ public class RegularTable extends TableBase {
@Override @Override
public boolean isLockedExclusively() { public boolean isLockedExclusively() {
return lockExclusive != null; return lockExclusiveSession != null;
} }
@Override @Override
public void unlock(Session s) { public void unlock(Session s) {
if (database != null) { if (database != null) {
traceLock(s, lockExclusive == s, "unlock"); traceLock(s, lockExclusiveSession == s, "unlock");
if (lockExclusive == s) { if (lockExclusiveSession == s) {
lockExclusive = null; lockExclusiveSession = null;
} }
if (lockShared.size() > 0) { if (lockSharedSessions.size() > 0) {
lockShared.remove(s); lockSharedSessions.remove(s);
} }
// TODO lock: maybe we need we fifo-queue to make sure nobody // TODO lock: maybe we need we fifo-queue to make sure nobody
// starves. check what other databases do // starves. check what other databases do
...@@ -713,8 +713,8 @@ public class RegularTable extends TableBase { ...@@ -713,8 +713,8 @@ public class RegularTable extends TableBase {
scanIndex.remove(session); scanIndex.remove(session);
database.removeMeta(session, getId()); database.removeMeta(session, getId());
scanIndex = null; scanIndex = null;
lockExclusive = null; lockExclusiveSession = null;
lockShared = null; lockSharedSessions = null;
invalidate(); invalidate();
} }
......
...@@ -133,10 +133,10 @@ public abstract class Table extends SchemaObjectBase { ...@@ -133,10 +133,10 @@ public abstract class Table extends SchemaObjectBase {
* *
* @param session the session * @param session the session
* @param exclusive true for write locks, false for read locks * @param exclusive true for write locks, false for read locks
* @param force lock even in the MVCC mode * @param forceLockEvenInMvcc lock even in the MVCC mode
* @throws DbException if a lock timeout occurred * @throws DbException if a lock timeout occurred
*/ */
public abstract void lock(Session session, boolean exclusive, boolean force); public abstract void lock(Session session, boolean exclusive, boolean forceLockEvenInMvcc);
/** /**
* Close the table object and flush changes. * Close the table object and flush changes.
......
...@@ -140,12 +140,12 @@ public class TableFilter implements ColumnResolver { ...@@ -140,12 +140,12 @@ public class TableFilter implements ColumnResolver {
* *
* @param s the session * @param s the session
* @param exclusive true if an exclusive lock is required * @param exclusive true if an exclusive lock is required
* @param force lock even in the MVCC mode * @param forceLockEvenInMvcc lock even in the MVCC mode
*/ */
public void lock(Session s, boolean exclusive, boolean force) { public void lock(Session s, boolean exclusive, boolean forceLockEvenInMvcc) {
table.lock(s, exclusive, force); table.lock(s, exclusive, forceLockEvenInMvcc);
if (join != null) { if (join != null) {
join.lock(s, exclusive, force); join.lock(s, exclusive, forceLockEvenInMvcc);
} }
} }
......
...@@ -390,7 +390,7 @@ public class TableLink extends Table { ...@@ -390,7 +390,7 @@ public class TableLink extends Table {
} }
@Override @Override
public void lock(Session session, boolean exclusive, boolean force) { public void lock(Session session, boolean exclusive, boolean forceLockEvenInMvcc) {
// nothing to do // nothing to do
} }
......
...@@ -320,7 +320,7 @@ public class TableView extends Table { ...@@ -320,7 +320,7 @@ public class TableView extends Table {
} }
@Override @Override
public void lock(Session session, boolean exclusive, boolean force) { public void lock(Session session, boolean exclusive, boolean forceLockEvenInMvcc) {
// exclusive lock means: the view will be dropped // exclusive lock means: the view will be dropped
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论