private void PerformPostTaskProcessing(AcquireGVFSLockResult acquireLockResult) { try { if (acquireLockResult == AcquireGVFSLockResult.LockAcquired) { this.RunCallbackUntilSuccess(this.postCallback, "PostCallback"); if (this.backgroundTasks.Count == 0) { this.context.Repository.GVFSLock.ReleaseLockHeldByGVFS(); } } } catch (Exception e) { this.LogErrorAndExit($"{nameof(this.ProcessBackgroundTasks)} caught unhandled exception in {nameof(this.PerformPostTaskProcessing)}, exiting process", e); } }
private void PerformPostOperationProcessing(AcquireGVFSLockResult acquireLockResult) { try { if (acquireLockResult == AcquireGVFSLockResult.LockAcquired) { this.RunCallbackUntilSuccess(this.postCallback, "PostCallback"); if (this.backgroundOperations.Count == 0) { this.context.Repository.GVFSLock.ReleaseLock(); } } } catch (Exception e) { this.LogErrorAndExit("ProcessBackgroundOperations caught unhandled exception in PerformPostOperationProcessing, exiting process", e); } }
private void ProcessBackgroundTasks() { FileSystemTask backgroundTask; while (true) { AcquireGVFSLockResult acquireLockResult = AcquireGVFSLockResult.ShuttingDown; try { this.wakeUpThread.WaitOne(); if (this.isStopping) { return; } acquireLockResult = this.WaitToAcquireGVFSLock(); switch (acquireLockResult) { case AcquireGVFSLockResult.LockAcquired: break; case AcquireGVFSLockResult.ShuttingDown: return; default: this.LogErrorAndExit("Invalid " + nameof(AcquireGVFSLockResult) + " result"); return; } this.RunCallbackUntilSuccess(this.preCallback, "PreCallback"); int tasksProcessed = 0; while (this.backgroundTasks.TryPeek(out backgroundTask)) { if (tasksProcessed % LogUpdateTaskThreshold == 0 && (tasksProcessed >= LogUpdateTaskThreshold || this.backgroundTasks.Count >= LogUpdateTaskThreshold)) { this.LogTaskProcessingStatus(tasksProcessed); } if (this.isStopping) { // If we are stopping, then ProjFS has already been shut down // Some of the queued background tasks may require ProjFS, and so it is unsafe to // proceed. GVFS will resume any queued tasks next time it is mounted return; } FileSystemTaskResult callbackResult = this.callback(backgroundTask); switch (callbackResult) { case FileSystemTaskResult.Success: this.backgroundTasks.DequeueAndFlush(backgroundTask); ++tasksProcessed; break; case FileSystemTaskResult.RetryableError: if (!this.isStopping) { Thread.Sleep(ActionRetryDelayMS); } break; case FileSystemTaskResult.FatalError: this.LogErrorAndExit("Callback encountered fatal error, exiting process"); break; default: this.LogErrorAndExit("Invalid background operation result"); break; } } if (tasksProcessed >= LogUpdateTaskThreshold) { EventMetadata metadata = new EventMetadata(); metadata.Add("Area", EtwArea); metadata.Add("TasksProcessed", tasksProcessed); metadata.Add(TracingConstants.MessageKey.InfoMessage, "Processing background tasks complete"); this.context.Tracer.RelatedEvent(EventLevel.Informational, "TaskProcessingStatus", metadata); } if (this.isStopping) { return; } } catch (Exception e) { this.LogErrorAndExit($"{nameof(this.ProcessBackgroundTasks)} caught unhandled exception, exiting process", e); } finally { this.PerformPostTaskProcessing(acquireLockResult); } } }
private void ProcessBackgroundOperations() { TBackgroundOperation backgroundOperation; while (true) { AcquireGVFSLockResult acquireLockResult = AcquireGVFSLockResult.ShuttingDown; try { this.wakeUpThread.WaitOne(500); if (this.isStopping) { return; } if (this.backgroundOperations.IsEmpty) { if (this.context.Repository.GVFSLock.IsLockedByGVFS) { EventMetadata metadata = new EventMetadata(); metadata.Add("Area", EtwArea); metadata.Add("Message", "Releasing lock being held unnecessarily by GVFS."); this.context.Tracer.RelatedEvent(EventLevel.Informational, "TaskProcessingStatus", metadata); this.ReleaseGVFSLockIfNecessary(); } // Check for empty queue again since something might have been added // as we were attempting to release the lock. This avoids cycling back // if there are ops in the queue and having to wait for the next timeout on wakeUpThread. if (this.backgroundOperations.IsEmpty) { continue; } } acquireLockResult = this.WaitToAcquireGVFSLock(); switch (acquireLockResult) { case AcquireGVFSLockResult.LockAcquired: break; case AcquireGVFSLockResult.ShuttingDown: return; default: this.LogErrorAndExit("Invalid " + nameof(AcquireGVFSLockResult) + " result"); return; } this.RunCallbackUntilSuccess(this.preCallback, "PreCallback"); int tasksProcessed = 0; while (this.backgroundOperations.TryPeek(out backgroundOperation)) { if (tasksProcessed % LogUpdateTaskThreshold == 0 && (tasksProcessed >= LogUpdateTaskThreshold || this.backgroundOperations.Count >= LogUpdateTaskThreshold)) { this.LogTaskProcessingStatus(tasksProcessed); } if (this.isStopping) { // If we are stopping, then GVFlt has already been shut down // Some of the queued background tasks may require GVFlt, and so it is unsafe to // proceed. GVFS will resume any queued tasks next time it is mounted this.persistence.Flush(); return; } CallbackResult callbackResult = this.callback(backgroundOperation); switch (callbackResult) { case CallbackResult.Success: this.backgroundOperations.TryDequeue(out backgroundOperation); this.persistence.Remove(backgroundOperation.Id); ++tasksProcessed; break; case CallbackResult.RetryableError: if (!this.isStopping) { Thread.Sleep(ActionRetryDelayMS); } break; case CallbackResult.FatalError: this.LogErrorAndExit("Callback encountered fatal error, exiting process"); break; default: this.LogErrorAndExit("Invalid background operation result"); break; } } this.persistence.Flush(); if (tasksProcessed >= LogUpdateTaskThreshold) { EventMetadata metadata = new EventMetadata(); metadata.Add("Area", EtwArea); metadata.Add("TasksProcessed", tasksProcessed); metadata.Add("Message", "Processing background tasks complete"); this.context.Tracer.RelatedEvent(EventLevel.Informational, "TaskProcessingStatus", metadata); } if (this.isStopping) { return; } } catch (Exception e) { this.LogErrorAndExit("ProcessBackgroundOperations caught unhandled exception, exiting process", e); } finally { if (acquireLockResult == AcquireGVFSLockResult.LockAcquired) { this.RunCallbackUntilSuccess(this.postCallback, "PostCallback"); this.ReleaseGVFSLockIfNecessary(); } } } }