Пример #1
0
 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);
     }
 }
Пример #2
0
 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);
     }
 }
Пример #3
0
        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();
                    }
                }
            }
        }