/**
  * This function resets all counters for all users and recounts them.
  * 
  * This function do work which IS NOT multi-thread safe.
  */
 public static function setup($step = self::STEP_BEGIN, $extraParam = null)
 {
     $nextStep = $nextStepDelay = $nextStepExtraParam = null;
     //$s = 'CTaskCountersProcessorInstaller::setup()';
     //soundex($s);
     $timeLimit = microtime(true) + 5;
     // give at least 5 seconds for work
     while (microtime(true) <= $timeLimit) {
         /** @noinspection PhpUnusedLocalVariableInspection */
         $nextStep = $nextStepDelay = $nextStepExtraParam = null;
         //soundex($step);
         if ($step === self::STEP_BEGIN) {
             self::setStage(self::STAGE_INSTALL_IN_PROGRESS);
             /** @noinspection PhpDynamicAsStaticMethodCallInspection */
             CAgent::RemoveAgent('CTaskCountersProcessor::agent();', 'tasks');
             /** @noinspection PhpDynamicAsStaticMethodCallInspection */
             CAgent::RemoveAgent('CTaskCountersProcessorInstaller::setup();', 'tasks');
             /** @noinspection PhpDynamicAsStaticMethodCallInspection */
             CAgent::RemoveAgent('CTaskCountersProcessorInstaller::setup("' . self::STEP_DROP_COUNTERS . '");', 'tasks');
             /** @noinspection PhpDynamicAsStaticMethodCallInspection */
             CAgent::RemoveAgent('CTaskCountersProcessorInstaller::setup("' . self::STEP_COUNT_NEW_FOR_RESPONSIBLES . '");', 'tasks');
             /** @noinspection PhpDynamicAsStaticMethodCallInspection */
             CAgent::RemoveAgent('CTaskCountersProcessorInstaller::setup("' . self::STEP_COUNT_NEW_FOR_ACCOMPLICES . '");', 'tasks');
             //CAgent::RemoveAgent('CTaskCountersProcessorInstaller::setup("' . self::STEP_COUNT_NEW_FOR_AUDITORS . '");', 'tasks');
             /** @noinspection PhpDynamicAsStaticMethodCallInspection */
             CAgent::RemoveAgent('CTaskCountersProcessorInstaller::setup("' . self::STEP_COUNT_WAIT_CTRL_FOR_ORIGINATORS . '");', 'tasks');
             /** @noinspection PhpDynamicAsStaticMethodCallInspection */
             CAgent::RemoveAgent('CTaskCountersProcessorInstaller::setup("' . self::STEP_COUNT_EXPIRED . '");', 'tasks');
             /** @noinspection PhpDynamicAsStaticMethodCallInspection */
             CAgent::RemoveAgent('CTaskCountersProcessorInstaller::setup("' . self::STEP_COUNT_WITHOUT_DEADLINES_MY . '");', 'tasks');
             /** @noinspection PhpDynamicAsStaticMethodCallInspection */
             CAgent::RemoveAgent('CTaskCountersProcessorInstaller::setup("' . self::STEP_COUNT_WITHOUT_DEADLINES_FOR_ORIGINATORS . '");', 'tasks');
             // defer for at min 130 seconds the next step,
             // because we must give time for CTaskCountersProcessor::agent()
             // to complete its work, if it was already started
             $nextStep = self::STEP_DROP_COUNTERS;
             $nextStepDelay = 130;
         } else {
             switch ($step) {
                 case self::STEP_DROP_COUNTERS:
                     // reset DEADLINE_COUNTED flags and all tasks counters for all users
                     self::reset();
                     $nextStep = self::STEP_COUNT_NEW_FOR_RESPONSIBLES;
                     break;
                 case self::STEP_COUNT_NEW_FOR_RESPONSIBLES:
                     self::recountCounters_MY_NEW($userId = '*');
                     // recount for all users
                     $nextStep = self::STEP_COUNT_NEW_FOR_ACCOMPLICES;
                     break;
                 case self::STEP_COUNT_NEW_FOR_ACCOMPLICES:
                     self::recountCounters_ACCOMPLICE_NEW($userId = '*');
                     // recount for all users
                     //$nextStep = self::STEP_COUNT_NEW_FOR_AUDITORS;
                     $nextStep = self::STEP_COUNT_WAIT_CTRL_FOR_ORIGINATORS;
                     break;
                 case self::STEP_COUNT_WAIT_CTRL_FOR_ORIGINATORS:
                     self::recountCounters_ORIGINATORS_WAIT_CTRL($userId = '*');
                     // recount for all users
                     $nextStep = self::STEP_COUNT_WITHOUT_DEADLINES_MY;
                     break;
                 case self::STEP_COUNT_WITHOUT_DEADLINES_MY:
                     self::recountCounters_MY_WITHOUT_DEADLINES($userId = '*');
                     // recount for all users
                     $nextStep = self::STEP_COUNT_WITHOUT_DEADLINES_FOR_ORIGINATORS;
                     break;
                 case self::STEP_COUNT_WITHOUT_DEADLINES_FOR_ORIGINATORS:
                     self::recountCounters_ORIGINATORS_WITHOUT_DEADLINES($userId = '*');
                     // recount for all users
                     $nextStep = self::STEP_COUNT_EXPIRED;
                     break;
                 case self::STEP_COUNT_EXPIRED:
                     $executionTimeLimit = mt_rand(1, 6);
                     // time limit in seconds
                     $itemsProcessed = CTaskCountersProcessor::countExpiredAndExpiredSoonTasks($executionTimeLimit);
                     // Some items processed?
                     if ($itemsProcessed > 0) {
                         // try again
                         $nextStep = self::STEP_COUNT_EXPIRED;
                         $nextStepDelay = 5;
                     } else {
                         /** @noinspection PhpDynamicAsStaticMethodCallInspection */
                         CAgent::AddAgent('CTaskCountersProcessor::agent();', 'tasks', 'N', 900);
                         // every 15 minutes
                         self::setStage(self::STAGE_INSTALL_COMPLETE);
                         CTaskCountersProcessorHomeostasis::onCalculationComplete();
                         $nextStep = null;
                         // the end
                     }
                     break;
                 default:
                     CTaskAssert::logError('[0xd7b90d6d] ');
                     $nextStep = null;
                     // the end
                     break;
             }
         }
         if ($nextStep === null) {
             break;
         }
         if ($nextStepDelay > 0) {
             break;
         }
         $step = $nextStep;
     }
     if ($nextStep !== null) {
         /** @noinspection PhpDeprecationInspection */
         $nextExecTimestamp = time() + CTasksTools::getTimeZoneOffset();
         if ($nextStepDelay !== null) {
             $nextExecTimestamp += $nextStepDelay;
         } else {
             $nextExecTimestamp += 5;
         }
         // delay for ~5 seconds due to probably DB and PHP server time desynchronization
         $delayedTime = ConvertTimeStamp($nextExecTimestamp, 'FULL');
         /** @noinspection PhpDynamicAsStaticMethodCallInspection */
         CAgent::AddAgent('CTaskCountersProcessorInstaller::setup("' . $nextStep . '");', 'tasks', 'N', 86400000, $delayedTime, "Y", $delayedTime, 13);
     }
     return "";
     // remove self from agents table
 }