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
}