2323import org .apache .iotdb .commons .utils .RetryUtils ;
2424import org .apache .iotdb .commons .utils .TestOnly ;
2525import org .apache .iotdb .confignode .i18n .ProcedureMessages ;
26- import org .apache .iotdb .confignode .procedure .env .ConfigNodeProcedureEnv ;
2726import org .apache .iotdb .confignode .procedure .exception .ProcedureException ;
2827import org .apache .iotdb .confignode .procedure .scheduler .ProcedureScheduler ;
2928import org .apache .iotdb .confignode .procedure .scheduler .SimpleProcedureScheduler ;
4241import java .util .Deque ;
4342import java .util .HashSet ;
4443import java .util .List ;
45- import java .util .Objects ;
4644import java .util .Set ;
4745import java .util .concurrent .ConcurrentHashMap ;
4846import java .util .concurrent .CopyOnWriteArrayList ;
@@ -86,6 +84,16 @@ public class ProcedureExecutor<Env> {
8684 private final Env environment ;
8785 private final IProcedureStore <Env > store ;
8886
87+ private static final class LockStateResult <Env > {
88+ private final ProcedureLockState lockState ;
89+ private final Procedure <Env > procedure ;
90+
91+ private LockStateResult (ProcedureLockState lockState , Procedure <Env > procedure ) {
92+ this .lockState = lockState ;
93+ this .procedure = procedure ;
94+ }
95+ }
96+
8997 public ProcedureExecutor (
9098 final Env environment , final IProcedureStore <Env > store , final ProcedureScheduler scheduler ) {
9199 this .environment = environment ;
@@ -329,33 +337,39 @@ private void executeProcedure(Procedure<Env> proc) {
329337 return ;
330338 }
331339 ProcedureLockState lockState = null ;
340+ Procedure <Env > lockEventWaitProcedure = null ;
332341 try {
333342 do {
334343 if (!rootProcStack .acquire ()) {
335344 if (rootProcStack .setRollback ()) {
336- lockState = executeRootStackRollback (rootProcId , rootProcStack );
345+ LockStateResult <Env > lockStateResult =
346+ executeRootStackRollback (rootProcId , rootProcStack );
347+ lockState = lockStateResult .lockState ;
337348 switch (lockState ) {
338349 case LOCK_ACQUIRED :
339350 break ;
340351 case LOCK_EVENT_WAIT :
341- LOG .info (ProcedureMessages .LOCK_EVENT_WAIT_ROLLBACK , proc );
352+ LOG .info (ProcedureMessages .LOCK_EVENT_WAIT_ROLLBACK , lockStateResult . procedure );
342353 rootProcStack .unsetRollback ();
354+ lockEventWaitProcedure = lockStateResult .procedure ;
343355 break ;
344356 case LOCK_YIELD_WAIT :
345357 rootProcStack .unsetRollback ();
346- scheduler .yield (proc );
358+ scheduler .yield (lockStateResult . procedure );
347359 break ;
348360 default :
349361 throw new UnsupportedOperationException ();
350362 }
351363 } else {
352364 if (!proc .wasExecuted ()) {
353- switch (executeRollback (proc )) {
365+ lockState = executeRollback (proc );
366+ switch (lockState ) {
354367 case LOCK_ACQUIRED :
355368 break ;
356369 case LOCK_EVENT_WAIT :
357370 LOG .info (
358371 ProcedureMessages .LOCK_EVENT_WAIT_CAN_T_ROLLBACK_CHILD_RUNNING_FOR , proc );
372+ lockEventWaitProcedure = proc ;
359373 break ;
360374 case LOCK_YIELD_WAIT :
361375 scheduler .yield (proc );
@@ -367,19 +381,25 @@ private void executeProcedure(Procedure<Env> proc) {
367381 }
368382 break ;
369383 }
370- lockState = acquireLock (proc );
371- switch (lockState ) {
372- case LOCK_ACQUIRED :
373- executeProcedure (rootProcStack , proc );
374- break ;
375- case LOCK_YIELD_WAIT :
376- case LOCK_EVENT_WAIT :
377- LOG .info (ProcedureMessages .LOCKSTATE_IS , proc , lockState );
378- break ;
379- default :
380- throw new UnsupportedOperationException ();
384+ try {
385+ lockState = acquireLock (proc );
386+ switch (lockState ) {
387+ case LOCK_ACQUIRED :
388+ executeProcedure (rootProcStack , proc );
389+ break ;
390+ case LOCK_YIELD_WAIT :
391+ case LOCK_EVENT_WAIT :
392+ LOG .info (ProcedureMessages .LOCKSTATE_IS , proc , lockState );
393+ if (lockState == ProcedureLockState .LOCK_EVENT_WAIT ) {
394+ lockEventWaitProcedure = proc ;
395+ }
396+ break ;
397+ default :
398+ throw new UnsupportedOperationException ();
399+ }
400+ } finally {
401+ rootProcStack .release ();
381402 }
382- rootProcStack .release ();
383403
384404 if (proc .isSuccess ()) {
385405 // update metrics on finishing the procedure
@@ -397,9 +417,9 @@ private void executeProcedure(Procedure<Env> proc) {
397417 } finally {
398418 // Only after procedure has completed execution can it be allowed to be rescheduled to prevent
399419 // data races
400- if (Objects . equals ( lockState , ProcedureLockState . LOCK_EVENT_WAIT ) ) {
401- LOG .info (ProcedureMessages .PROCEDUREID_WAIT_FOR_LOCK , proc .getProcId ());
402- (( ConfigNodeProcedureEnv ) this .environment ). getNodeLock (). waitProcedure ( proc );
420+ if (lockEventWaitProcedure != null ) {
421+ LOG .info (ProcedureMessages .PROCEDUREID_WAIT_FOR_LOCK , lockEventWaitProcedure .getProcId ());
422+ lockEventWaitProcedure . waitForLock ( this .environment );
403423 }
404424 }
405425 }
@@ -414,6 +434,7 @@ private void executeProcedure(RootProcedureStack rootProcStack, Procedure<Env> p
414434 if (proc .getState () != ProcedureState .RUNNABLE ) {
415435 LOG .error (
416436 "The executing procedure should in RUNNABLE state, but it's not. Procedure is {}" , proc );
437+ releaseLock (proc , false );
417438 return ;
418439 }
419440 boolean reExecute ;
@@ -615,8 +636,8 @@ private void yieldProcedure(Procedure<Env> proc) {
615636 * @param procedureStack root procedure stack
616637 * @return lock state
617638 */
618- private ProcedureLockState executeRootStackRollback (
619- Long rootProcId , RootProcedureStack procedureStack ) {
639+ private LockStateResult < Env > executeRootStackRollback (
640+ Long rootProcId , RootProcedureStack < Env > procedureStack ) {
620641 Procedure <Env > rootProcedure = procedures .get (rootProcId );
621642 ProcedureException exception = rootProcedure .getException ();
622643 if (exception == null ) {
@@ -637,19 +658,19 @@ private ProcedureLockState executeRootStackRollback(
637658 }
638659 ProcedureLockState lockState = acquireLock (procedure );
639660 if (lockState != ProcedureLockState .LOCK_ACQUIRED ) {
640- return lockState ;
661+ return new LockStateResult <>( lockState , procedure ) ;
641662 }
642663 lockState = executeRollback (procedure );
643664 releaseLock (procedure , false );
644665
645666 boolean abortRollback = lockState != ProcedureLockState .LOCK_ACQUIRED ;
646667 abortRollback |= !isRunning () || !store .isRunning ();
647668 if (abortRollback ) {
648- return lockState ;
669+ return new LockStateResult <>( lockState , procedure ) ;
649670 }
650671
651672 if (!procedure .isFinished () && procedure .isYieldAfterExecution (this .environment )) {
652- return ProcedureLockState .LOCK_YIELD_WAIT ;
673+ return new LockStateResult <>( ProcedureLockState .LOCK_YIELD_WAIT , procedure ) ;
653674 }
654675
655676 if (procedure != rootProcedure ) {
@@ -660,7 +681,7 @@ private ProcedureLockState executeRootStackRollback(
660681 LOG .info (
661682 ProcedureMessages .ROLLED_BACK_TIME_DURATION_IS , rootProcedure , rootProcedure .elapsedTime ());
662683 rootProcedureCleanup (rootProcedure );
663- return ProcedureLockState .LOCK_ACQUIRED ;
684+ return new LockStateResult <>( ProcedureLockState .LOCK_ACQUIRED , rootProcedure ) ;
664685 }
665686
666687 private ProcedureLockState acquireLock (Procedure <Env > proc ) {
@@ -795,21 +816,38 @@ public void run() {
795816 Thread .sleep (1000 );
796817 continue ;
797818 }
798- this .activeProcedure .set (procedure );
799- activeExecutorCount .incrementAndGet ();
800- startTime .set (System .currentTimeMillis ());
801- PROCEDURE_EXECUTION_CONTEXT .set (true );
819+ boolean executionAcquired = false ;
820+ while (isRunning () && !(executionAcquired = procedure .tryAcquireExecution ())) {
821+ Thread .sleep (10 );
822+ }
823+ if (!executionAcquired ) {
824+ continue ;
825+ }
802826 try {
803- executeProcedure (procedure );
804- } finally {
805- PROCEDURE_EXECUTION_CONTEXT .remove ();
827+ this .activeProcedure .set (procedure );
828+ activeExecutorCount .incrementAndGet ();
829+ startTime .set (System .currentTimeMillis ());
830+ try {
831+ PROCEDURE_EXECUTION_CONTEXT .set (true );
832+ try {
833+ executeProcedure (procedure );
834+ } finally {
835+ PROCEDURE_EXECUTION_CONTEXT .remove ();
836+ }
837+ } finally {
838+ procedure .releaseExecution ();
839+ activeExecutorCount .decrementAndGet ();
840+ LOG .trace (
841+ "Halt pid={}, activeCount={}" , procedure .getProcId (), activeExecutorCount .get ());
842+ this .activeProcedure .set (null );
843+ lastUpdated = System .currentTimeMillis ();
844+ startTime .set (lastUpdated );
845+ }
846+ } catch (Exception e ) {
847+ LOG .warn (
848+ "Exception happened when worker {} execute procedure {}" , getName (), procedure , e );
849+ throw e ;
806850 }
807- activeExecutorCount .decrementAndGet ();
808- LOG .trace (
809- "Halt pid={}, activeCount={}" , procedure .getProcId (), activeExecutorCount .get ());
810- this .activeProcedure .set (null );
811- lastUpdated = System .currentTimeMillis ();
812- startTime .set (lastUpdated );
813851 }
814852
815853 } catch (Exception e ) {
@@ -820,6 +858,7 @@ public void run() {
820858 this .activeProcedure .get (),
821859 e );
822860 }
861+ this .activeProcedure .set (null );
823862 } finally {
824863 LOG .info (ProcedureMessages .PROCEDURE_WORKER_TERMINATED , getName ());
825864 }
0 commit comments