private void VerifyOrDeployResources()

in csharp/NativeUtils/ResourceLoader.cs [606:712]


        private void VerifyOrDeployResources(string deploymentPath, Opt options)
        {
            DisposeResourceFiles();
            // Check, if we can load the existing resource files
            try
            {
                Dbg("last.allFoundImmediately", false);
                if (VerifyExistingResourceFiles(deploymentPath, options))
                {
                    Log("All files already deployed");
                    Dbg("last.allFoundImmediately", true);
                    return;
                }
            }
            catch
            {
                Log("1st Verify call threw");
                throw;
            }

            Dbg("last.lockWaitSince", DateTime.Now);
            Dbg("last.lockedAt", null);
            Dbg("last.lockWaitTimeoutAt", null);
            Dbg("last.lockFileAgeMs", null);

            int startTime = Environment.TickCount, startTime0 = startTime;
            int retries = 3;
            int timeout = _retryTimeoutMs;
            while (null == (LockFile = FileJanitor.TryCreateLockFile(deploymentPath)))
            {
                Int32 elapsed = Environment.TickCount - startTime;
                // Yes, sleep at least once regardless of how much time remaining and re-check
                RandomSleep(timeout - elapsed);
                if (elapsed < timeout || --retries >= 0)
                    continue;

                DateTime now = DateTime.UtcNow;
                double lockFileAge = (now - FileJanitor.LockFileWriteTime(deploymentPath)).TotalMilliseconds;
                // If lockfile is updated between retryTimeout in the past and retryTimeout * 10 in the future(!!), extend timer
                if (lockFileAge < timeout && lockFileAge > -10 * timeout)
                {
                    startTime = Environment.TickCount;
                    retries = 3;
                    Log("Lock timer extended");
                    continue;
                }

                int elapsedTotal = Environment.TickCount - startTime0;
                Log(ERR, $"Lock timer expired at: {Dt2Str(now)}, elapsed: {elapsedTotal} ms, lock age: {lockFileAge} ms");
                DbgLast("lockWaitTimeoutAt", now);
                DbgLast("lockFileAgeMs", lockFileAge);
                throw new IOException(
                    $"Unable to grab Lock file (timeout: {timeout} ms, elapsed: {elapsedTotal} ms, lock age: {lockFileAge} ms)");
            }

            var dtNow = DateTime.Now;
            Dbg("last.lockedAt", dtNow);
            if (LogLevelLeast(DBG))
                Log($"Lock taken at: {Dt2Str(dtNow)}");

            try
            {
                try
                {
                    // Check again after possible lock contention
                    DbgLast("verifyOkAfterLock", false);
                    if (VerifyExistingResourceFiles(deploymentPath, options))
                    {
                        DbgLast("verifyOkAfterLock", true);
                        Log("Verified files after lock");
                        return;
                    }
                }
                catch
                {
                    Log("2nd Verify call threw");
                    DbgLast("2ndVerifyThrew", true);
                    throw;
                }

                Log($"Deploying to: {deploymentPath}");
                LockFileWatchdogInit();

                try
                {
                    DbgLast("deployAttempted", true);
                    DeployResourcesInternal(deploymentPath);
                }
                catch
                {
                    DbgLast("deployThrew", true);
                    Log("Deployment threw");
                    throw;
                }

                // Update watchdog one last time
                LockFileWatchdogUpdate();
            }
            catch
            {
                Log("Verify/Deploy throw/rethrow");
                throw;
            }

            // NOTE: LockFile may still exist and will be released later byt the caller
            // finally{} clause that releases the lock is removed from here
        }