Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,10 @@ public void lock() {
LOGGER.debug(
ManagerMessages.PIPETASKCOORDINATOR_LOCK_WAITING_FOR_THREAD,
Thread.currentThread().getName());
try {
semaphore.acquire();
LOGGER.debug(
ManagerMessages.PIPETASKCOORDINATOR_LOCK_ACQUIRED_BY_THREAD,
Thread.currentThread().getName());
} catch (final InterruptedException e) {
Thread.currentThread().interrupt();
PipeLogger.log(
LOGGER::error,
ManagerMessages.INTERRUPTED_WHILE_WAITING_FOR_PIPETASKCOORDINATOR_LOCK_CURRENT_THREAD,
Thread.currentThread().getName());
}
semaphore.acquireUninterruptibly();
LOGGER.debug(
ManagerMessages.PIPETASKCOORDINATOR_LOCK_ACQUIRED_BY_THREAD,
Thread.currentThread().getName());
}

public boolean tryLock() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

/**
Expand All @@ -62,6 +63,7 @@ public abstract class Procedure<Env> implements Comparable<Procedure<Env>> {
private volatile long lastUpdate;

private final AtomicReference<byte[]> result = new AtomicReference<>();
private final AtomicBoolean executing = new AtomicBoolean(false);
private volatile boolean locked = false;
private boolean lockedWhenLoading = false;

Expand Down Expand Up @@ -235,6 +237,16 @@ protected void releaseLock(Env env) {
// no op
}

/**
* Called after an execution attempt returns {@link ProcedureLockState#LOCK_EVENT_WAIT}. Override
* it to put the procedure into the corresponding lock wait queue.
*
* @param env env
*/
protected void waitForLock(Env env) {
// no op
}

/**
* Used to keep procedure lock even when the procedure is yielded or suspended.
*
Expand All @@ -256,6 +268,14 @@ protected boolean isYieldAfterExecution(Env env) {
}

// -------------------------Internal methods - called by the procedureExecutor------------------
final boolean tryAcquireExecution() {
return executing.compareAndSet(false, true);
}

final void releaseExecution() {
executing.set(false);
}

/**
* Internal method called by the ProcedureExecutor that starts the user-level code execute().
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import org.apache.iotdb.commons.utils.RetryUtils;
import org.apache.iotdb.commons.utils.TestOnly;
import org.apache.iotdb.confignode.i18n.ProcedureMessages;
import org.apache.iotdb.confignode.procedure.env.ConfigNodeProcedureEnv;
import org.apache.iotdb.confignode.procedure.exception.ProcedureException;
import org.apache.iotdb.confignode.procedure.scheduler.ProcedureScheduler;
import org.apache.iotdb.confignode.procedure.scheduler.SimpleProcedureScheduler;
Expand All @@ -42,7 +41,6 @@
import java.util.Deque;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
Expand Down Expand Up @@ -86,6 +84,16 @@
private final Env environment;
private final IProcedureStore<Env> store;

private static final class LockStateResult<Env> {

Check warning on line 87 in iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/ProcedureExecutor.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Class type name 'Env' must match pattern '(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)'.

See more on https://sonarcloud.io/project/issues?id=apache_iotdb&issues=AZ7PpCuTAEcTTWTft4eq&open=AZ7PpCuTAEcTTWTft4eq&pullRequest=17902

Check warning on line 87 in iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/ProcedureExecutor.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rename this generic name to match the regular expression '^[A-Z][0-9]?$'.

See more on https://sonarcloud.io/project/issues?id=apache_iotdb&issues=AZ7PpCuTAEcTTWTft4eo&open=AZ7PpCuTAEcTTWTft4eo&pullRequest=17902
private final ProcedureLockState lockState;
private final Procedure<Env> procedure;

private LockStateResult(ProcedureLockState lockState, Procedure<Env> procedure) {
this.lockState = lockState;
this.procedure = procedure;
}
}

public ProcedureExecutor(
final Env environment, final IProcedureStore<Env> store, final ProcedureScheduler scheduler) {
this.environment = environment;
Expand Down Expand Up @@ -329,33 +337,39 @@
return;
}
ProcedureLockState lockState = null;
Procedure<Env> lockEventWaitProcedure = null;
try {
do {
if (!rootProcStack.acquire()) {
if (rootProcStack.setRollback()) {
lockState = executeRootStackRollback(rootProcId, rootProcStack);
LockStateResult<Env> lockStateResult =
executeRootStackRollback(rootProcId, rootProcStack);
lockState = lockStateResult.lockState;
switch (lockState) {
case LOCK_ACQUIRED:
break;
case LOCK_EVENT_WAIT:
LOG.info(ProcedureMessages.LOCK_EVENT_WAIT_ROLLBACK, proc);
LOG.info(ProcedureMessages.LOCK_EVENT_WAIT_ROLLBACK, lockStateResult.procedure);
rootProcStack.unsetRollback();
lockEventWaitProcedure = lockStateResult.procedure;
break;
case LOCK_YIELD_WAIT:
rootProcStack.unsetRollback();
scheduler.yield(proc);
scheduler.yield(lockStateResult.procedure);
break;
default:
throw new UnsupportedOperationException();
}
} else {
if (!proc.wasExecuted()) {
switch (executeRollback(proc)) {
lockState = executeRollback(proc);
switch (lockState) {
case LOCK_ACQUIRED:
break;
case LOCK_EVENT_WAIT:
LOG.info(
ProcedureMessages.LOCK_EVENT_WAIT_CAN_T_ROLLBACK_CHILD_RUNNING_FOR, proc);
lockEventWaitProcedure = proc;
break;
case LOCK_YIELD_WAIT:
scheduler.yield(proc);
Expand All @@ -367,19 +381,25 @@
}
break;
}
lockState = acquireLock(proc);
switch (lockState) {
case LOCK_ACQUIRED:
executeProcedure(rootProcStack, proc);
break;
case LOCK_YIELD_WAIT:
case LOCK_EVENT_WAIT:
LOG.info(ProcedureMessages.LOCKSTATE_IS, proc, lockState);
break;
default:
throw new UnsupportedOperationException();
try {
lockState = acquireLock(proc);
switch (lockState) {
case LOCK_ACQUIRED:
executeProcedure(rootProcStack, proc);
break;
case LOCK_YIELD_WAIT:
case LOCK_EVENT_WAIT:
LOG.info(ProcedureMessages.LOCKSTATE_IS, proc, lockState);
if (lockState == ProcedureLockState.LOCK_EVENT_WAIT) {
lockEventWaitProcedure = proc;
}
break;
default:
throw new UnsupportedOperationException();
}
} finally {
rootProcStack.release();
}
rootProcStack.release();

if (proc.isSuccess()) {
// update metrics on finishing the procedure
Expand All @@ -397,9 +417,9 @@
} finally {
// Only after procedure has completed execution can it be allowed to be rescheduled to prevent
// data races
if (Objects.equals(lockState, ProcedureLockState.LOCK_EVENT_WAIT)) {
LOG.info(ProcedureMessages.PROCEDUREID_WAIT_FOR_LOCK, proc.getProcId());
((ConfigNodeProcedureEnv) this.environment).getNodeLock().waitProcedure(proc);
if (lockEventWaitProcedure != null) {
LOG.info(ProcedureMessages.PROCEDUREID_WAIT_FOR_LOCK, lockEventWaitProcedure.getProcId());
lockEventWaitProcedure.waitForLock(this.environment);
}
}
}
Expand All @@ -414,6 +434,7 @@
if (proc.getState() != ProcedureState.RUNNABLE) {
LOG.error(
"The executing procedure should in RUNNABLE state, but it's not. Procedure is {}", proc);
releaseLock(proc, false);
return;
}
boolean reExecute;
Expand Down Expand Up @@ -615,8 +636,8 @@
* @param procedureStack root procedure stack
* @return lock state
*/
private ProcedureLockState executeRootStackRollback(
Long rootProcId, RootProcedureStack procedureStack) {
private LockStateResult<Env> executeRootStackRollback(
Long rootProcId, RootProcedureStack<Env> procedureStack) {
Procedure<Env> rootProcedure = procedures.get(rootProcId);
ProcedureException exception = rootProcedure.getException();
if (exception == null) {
Expand All @@ -637,19 +658,19 @@
}
ProcedureLockState lockState = acquireLock(procedure);
if (lockState != ProcedureLockState.LOCK_ACQUIRED) {
return lockState;
return new LockStateResult<>(lockState, procedure);
}
lockState = executeRollback(procedure);
releaseLock(procedure, false);

boolean abortRollback = lockState != ProcedureLockState.LOCK_ACQUIRED;
abortRollback |= !isRunning() || !store.isRunning();
if (abortRollback) {
return lockState;
return new LockStateResult<>(lockState, procedure);
}

if (!procedure.isFinished() && procedure.isYieldAfterExecution(this.environment)) {
return ProcedureLockState.LOCK_YIELD_WAIT;
return new LockStateResult<>(ProcedureLockState.LOCK_YIELD_WAIT, procedure);
}

if (procedure != rootProcedure) {
Expand All @@ -660,7 +681,7 @@
LOG.info(
ProcedureMessages.ROLLED_BACK_TIME_DURATION_IS, rootProcedure, rootProcedure.elapsedTime());
rootProcedureCleanup(rootProcedure);
return ProcedureLockState.LOCK_ACQUIRED;
return new LockStateResult<>(ProcedureLockState.LOCK_ACQUIRED, rootProcedure);
}

private ProcedureLockState acquireLock(Procedure<Env> proc) {
Expand Down Expand Up @@ -789,27 +810,44 @@
public void run() {
long lastUpdated = System.currentTimeMillis();
try {
while (isRunning() && keepAlive(lastUpdated)) {

Check warning on line 813 in iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/ProcedureExecutor.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Reduce the total number of break and continue statements in this loop to use at most one.

See more on https://sonarcloud.io/project/issues?id=apache_iotdb&issues=AZ6xDlUhfFqTS2wWbRPc&open=AZ6xDlUhfFqTS2wWbRPc&pullRequest=17902
Procedure<Env> procedure = scheduler.poll(keepAliveTime, TimeUnit.MILLISECONDS);
if (procedure == null) {
Thread.sleep(1000);
continue;
}
this.activeProcedure.set(procedure);
activeExecutorCount.incrementAndGet();
startTime.set(System.currentTimeMillis());
PROCEDURE_EXECUTION_CONTEXT.set(true);
boolean executionAcquired = false;
while (isRunning() && !(executionAcquired = procedure.tryAcquireExecution())) {
Thread.sleep(10);
}
if (!executionAcquired) {
continue;
}
try {

Check warning on line 826 in iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/ProcedureExecutor.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Extract this nested try block into a separate method.

See more on https://sonarcloud.io/project/issues?id=apache_iotdb&issues=AZ7PpCuTAEcTTWTft4en&open=AZ7PpCuTAEcTTWTft4en&pullRequest=17902
executeProcedure(procedure);
} finally {
PROCEDURE_EXECUTION_CONTEXT.remove();
this.activeProcedure.set(procedure);
activeExecutorCount.incrementAndGet();
startTime.set(System.currentTimeMillis());
try {
PROCEDURE_EXECUTION_CONTEXT.set(true);
try {
executeProcedure(procedure);
} finally {
PROCEDURE_EXECUTION_CONTEXT.remove();
}
} finally {
procedure.releaseExecution();
activeExecutorCount.decrementAndGet();
LOG.trace(
"Halt pid={}, activeCount={}", procedure.getProcId(), activeExecutorCount.get());
this.activeProcedure.set(null);
lastUpdated = System.currentTimeMillis();
startTime.set(lastUpdated);
}
} catch (Exception e) {

Check warning on line 846 in iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/ProcedureExecutor.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Either log this exception and handle it, or rethrow it with some contextual information.

See more on https://sonarcloud.io/project/issues?id=apache_iotdb&issues=AZ7PpCuTAEcTTWTft4ep&open=AZ7PpCuTAEcTTWTft4ep&pullRequest=17902
LOG.warn(
"Exception happened when worker {} execute procedure {}", getName(), procedure, e);
throw e;
}
activeExecutorCount.decrementAndGet();
LOG.trace(
"Halt pid={}, activeCount={}", procedure.getProcId(), activeExecutorCount.get());
this.activeProcedure.set(null);
lastUpdated = System.currentTimeMillis();
startTime.set(lastUpdated);
}

} catch (Exception e) {
Expand All @@ -820,6 +858,7 @@
this.activeProcedure.get(),
e);
}
this.activeProcedure.set(null);
} finally {
LOG.info(ProcedureMessages.PROCEDURE_WORKER_TERMINATED, getName());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,13 @@
}

public void add(Procedure<Env> procedure) {
queue.add(new ProcedureDelayContainer<>(procedure));
ProcedureDelayContainer<Env> delayTask = new ProcedureDelayContainer<>(procedure);
queue.remove(delayTask);

Check warning on line 47 in iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/TimeoutExecutorThread.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Do something with the "boolean" value returned by "remove".

See more on https://sonarcloud.io/project/issues?id=apache_iotdb&issues=AZ6xQoIAsClnBOWNLWo4&open=AZ6xQoIAsClnBOWNLWo4&pullRequest=17902
queue.add(delayTask);
}

public boolean remove(Procedure<Env> procedure) {
return queue.remove(new ProcedureDelayContainer<>(procedure));
return queue.remove(new ProcedureDelayContainer<>(procedure)) || procedure.isFinished();
}

private ProcedureDelayContainer<Env> takeQuietly() {
Expand All @@ -60,18 +62,23 @@
}

@Override
public void run() {

Check failure on line 65 in iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/TimeoutExecutorThread.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this method to reduce its Cognitive Complexity from 19 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=apache_iotdb&issues=AZ6xQoIAsClnBOWNLWo5&open=AZ6xQoIAsClnBOWNLWo5&pullRequest=17902
while (executor.isRunning()) {

Check warning on line 66 in iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/TimeoutExecutorThread.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Reduce the total number of break and continue statements in this loop to use at most one.

See more on https://sonarcloud.io/project/issues?id=apache_iotdb&issues=AZ6xQoIAsClnBOWNLWo3&open=AZ6xQoIAsClnBOWNLWo3&pullRequest=17902
ProcedureDelayContainer<Env> delayTask = takeQuietly();
if (delayTask == null) {
continue;
}
Procedure<Env> procedure = delayTask.getProcedure();
if (procedure instanceof InternalProcedure) {
if (procedure.isFinished()) {
continue;
}
InternalProcedure internal = (InternalProcedure) procedure;
internal.periodicExecute(executor.getEnvironment());
procedure.updateTimestamp();
queue.add(delayTask);
if (!procedure.isFinished()) {
procedure.updateTimestamp();
queue.add(delayTask);
}
} else {
if (procedure.setTimeoutFailure(executor.getEnvironment())) {
long rootProcId = executor.getRootProcedureId(procedure);
Expand Down Expand Up @@ -104,6 +111,23 @@
return procedure;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof ProcedureDelayContainer)) {
return false;
}
ProcedureDelayContainer<?> that = (ProcedureDelayContainer<?>) o;
return procedure == that.procedure;
}

@Override
public int hashCode() {
return System.identityHashCode(procedure);
}

@Override
public long getDelay(TimeUnit unit) {
long delay = procedure.getTimeoutTimestamp() - System.currentTimeMillis();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,8 @@ private void addNextStateAndCalculateCycles() {
nextState);
}
}
if (getStateId(getCurrentState()) == stateToBeAdded) {
final TState currentState = getCurrentState();
if (currentState != null && getStateId(currentState) == stateToBeAdded) {
cycles++;
} else {
cycles = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ public boolean equals(Object o) {
}
CreateCQProcedure that = (CreateCQProcedure) o;
return getProcId() == that.getProcId()
&& getCurrentState().equals(that.getCurrentState())
&& Objects.equals(getCurrentState(), that.getCurrentState())
&& getCycles() == that.getCycles()
&& isGeneratedByPipe == that.isGeneratedByPipe
&& firstExecutionTime == that.firstExecutionTime
Expand Down
Loading
Loading