Skip to content

Commit 984eef3

Browse files
committed
Fix procedure lock wait scheduling
1 parent a725ded commit 984eef3

6 files changed

Lines changed: 68 additions & 14 deletions

File tree

iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/Procedure.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,16 @@ protected void releaseLock(Env env) {
235235
// no op
236236
}
237237

238+
/**
239+
* Called after an execution attempt returns {@link ProcedureLockState#LOCK_EVENT_WAIT}. Override
240+
* it to put the procedure into the corresponding lock wait queue.
241+
*
242+
* @param env env
243+
*/
244+
protected void waitForLock(Env env) {
245+
// no op
246+
}
247+
238248
/**
239249
* Used to keep procedure lock even when the procedure is yielded or suspended.
240250
*

iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/ProcedureExecutor.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import org.apache.iotdb.commons.utils.RetryUtils;
2424
import org.apache.iotdb.commons.utils.TestOnly;
2525
import org.apache.iotdb.confignode.i18n.ProcedureMessages;
26-
import org.apache.iotdb.confignode.procedure.env.ConfigNodeProcedureEnv;
2726
import org.apache.iotdb.confignode.procedure.exception.ProcedureException;
2827
import org.apache.iotdb.confignode.procedure.scheduler.ProcedureScheduler;
2928
import org.apache.iotdb.confignode.procedure.scheduler.SimpleProcedureScheduler;
@@ -42,7 +41,6 @@
4241
import java.util.Deque;
4342
import java.util.HashSet;
4443
import java.util.List;
45-
import java.util.Objects;
4644
import java.util.Set;
4745
import java.util.concurrent.ConcurrentHashMap;
4846
import java.util.concurrent.CopyOnWriteArrayList;
@@ -397,9 +395,9 @@ private void executeProcedure(Procedure<Env> proc) {
397395
} finally {
398396
// Only after procedure has completed execution can it be allowed to be rescheduled to prevent
399397
// data races
400-
if (Objects.equals(lockState, ProcedureLockState.LOCK_EVENT_WAIT)) {
398+
if (lockState == ProcedureLockState.LOCK_EVENT_WAIT) {
401399
LOG.info(ProcedureMessages.PROCEDUREID_WAIT_FOR_LOCK, proc.getProcId());
402-
((ConfigNodeProcedureEnv) this.environment).getNodeLock().waitProcedure(proc);
400+
proc.waitForLock(this.environment);
403401
}
404402
}
405403
}

iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/node/AbstractNodeProcedure.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,18 @@ protected ProcedureLockState acquireLock(ConfigNodeProcedureEnv configNodeProced
5656
}
5757
}
5858

59+
@Override
60+
protected void waitForLock(ConfigNodeProcedureEnv configNodeProcedureEnv) {
61+
configNodeProcedureEnv.getSchedulerLock().lock();
62+
try {
63+
configNodeProcedureEnv
64+
.getNodeLock()
65+
.waitProcedure(this, configNodeProcedureEnv.getScheduler());
66+
} finally {
67+
configNodeProcedureEnv.getSchedulerLock().unlock();
68+
}
69+
}
70+
5971
@Override
6072
protected void releaseLock(ConfigNodeProcedureEnv configNodeProcedureEnv) {
6173
configNodeProcedureEnv.getSchedulerLock().lock();

iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/scheduler/LockQueue.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,11 @@ public boolean releaseLock(Procedure<?> procedure) {
4545
return true;
4646
}
4747

48-
public void waitProcedure(Procedure<?> procedure) {
48+
public void waitProcedure(Procedure<?> procedure, ProcedureScheduler procedureScheduler) {
49+
if (lockOwnerProcedure == null) {
50+
procedureScheduler.addFront(procedure);
51+
return;
52+
}
4953
deque.addLast(procedure);
5054
}
5155

iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/scheduler/SimpleProcedureScheduler.java

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.apache.iotdb.confignode.procedure.Procedure;
2323

2424
import java.util.concurrent.LinkedBlockingDeque;
25+
import java.util.concurrent.locks.ReentrantLock;
2526

2627
/** Simple scheduler for procedures */
2728
public class SimpleProcedureScheduler extends AbstractProcedureScheduler {
@@ -48,6 +49,7 @@ public void clear() {
4849
schedLock();
4950
try {
5051
runnables.clear();
52+
waitings.clear();
5153
} finally {
5254
schedUnlock();
5355
}
@@ -68,12 +70,37 @@ public int queueSize() {
6870
return runnables.size();
6971
}
7072

71-
public void addWaiting(Procedure proc) {
72-
waitings.add(proc);
73+
public void waitProcedure(Procedure proc, ReentrantLock lock) {
74+
boolean signal = false;
75+
schedLock();
76+
try {
77+
if (lock.isLocked()) {
78+
waitings.add(proc);
79+
} else {
80+
runnables.addFirst(proc);
81+
signal = true;
82+
}
83+
} finally {
84+
schedUnlock();
85+
}
86+
if (signal) {
87+
signalAll();
88+
}
7389
}
7490

75-
public void releaseWaiting() {
76-
runnables.addAll(waitings);
77-
waitings.clear();
91+
public void releaseWaiting(ReentrantLock lock) {
92+
boolean signal;
93+
schedLock();
94+
try {
95+
lock.unlock();
96+
signal = !waitings.isEmpty();
97+
runnables.addAll(waitings);
98+
waitings.clear();
99+
} finally {
100+
schedUnlock();
101+
}
102+
if (signal) {
103+
signalAll();
104+
}
78105
}
79106
}

iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/procedure/entity/SimpleLockProcedure.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,18 +53,21 @@ protected ProcedureLockState acquireLock(TestProcEnv testProcEnv) {
5353

5454
return ProcedureLockState.LOCK_ACQUIRED;
5555
}
56-
SimpleProcedureScheduler scheduler = (SimpleProcedureScheduler) testProcEnv.getScheduler();
57-
scheduler.addWaiting(this);
5856
System.out.println(procName + " wait for lock.");
5957
return ProcedureLockState.LOCK_EVENT_WAIT;
6058
}
6159

60+
@Override
61+
protected void waitForLock(TestProcEnv testProcEnv) {
62+
SimpleProcedureScheduler scheduler = (SimpleProcedureScheduler) testProcEnv.getScheduler();
63+
scheduler.waitProcedure(this, testProcEnv.getEnvLock());
64+
}
65+
6266
@Override
6367
protected void releaseLock(TestProcEnv testProcEnv) {
6468
System.out.println(procName + " release lock.");
65-
testProcEnv.getEnvLock().unlock();
6669
SimpleProcedureScheduler scheduler = (SimpleProcedureScheduler) testProcEnv.getScheduler();
67-
scheduler.releaseWaiting();
70+
scheduler.releaseWaiting(testProcEnv.getEnvLock());
6871
}
6972

7073
@Override

0 commit comments

Comments
 (0)