RavenFS.Synchronization.SynchronizationQueue.EnqueueSynchronization C# (CSharp) Method

EnqueueSynchronization() public method

public EnqueueSynchronization ( string destination, SynchronizationWorkItem workItem ) : void
destination string
workItem SynchronizationWorkItem
return void
		public void EnqueueSynchronization(string destination, SynchronizationWorkItem workItem)
		{
			pendingRemoveLocks.GetOrAdd(destination, new ReaderWriterLockSlim()).EnterUpgradeableReadLock();

			try
			{
				var pendingForDestination = pendingSynchronizations.GetOrAdd(destination,
				                                                             new ConcurrentQueue<SynchronizationWorkItem>());

				// if delete work is enqueued and there are other synchronization works for a given file then remove them from a queue
				if (workItem.SynchronizationType == SynchronizationType.Delete &&
				    pendingForDestination.Any(
					    x => x.FileName == workItem.FileName && x.SynchronizationType != SynchronizationType.Delete))
				{
					pendingRemoveLocks.GetOrAdd(destination, new ReaderWriterLockSlim()).EnterWriteLock();

					try
					{
						var modifiedQueue = new ConcurrentQueue<SynchronizationWorkItem>();

						foreach (var pendingWork in pendingForDestination)
						{
							if (pendingWork.FileName != workItem.FileName)
								modifiedQueue.Enqueue(pendingWork);
						}

						modifiedQueue.Enqueue(workItem);

						pendingForDestination = pendingSynchronizations.AddOrUpdate(destination, modifiedQueue,
						                                                            (key, value) => modifiedQueue);
					}
					finally
					{
						pendingRemoveLocks.GetOrAdd(destination, new ReaderWriterLockSlim()).ExitWriteLock();
					}
				}

				foreach (var pendingWork in pendingForDestination)
				{
					// if there is a file in pending synchronizations do not add it again
					if (pendingWork.Equals(workItem))
					{
						Log.Debug("{0} for a file {1} and a destination {2} was already existed in a pending queue",
						          workItem.GetType().Name, workItem.FileName, destination);
						return;
					}

					// if there is a work for a file of the same type but with lower file ETag just refresh existing work metadata and do not enqueue again
					if (pendingWork.FileName == workItem.FileName &&
					    pendingWork.SynchronizationType == workItem.SynchronizationType &&
					    Buffers.Compare(workItem.FileETag.ToByteArray(), pendingWork.FileETag.ToByteArray()) > 0)
					{
						pendingWork.RefreshMetadata();
						Log.Debug(
							"{0} for a file {1} and a destination {2} was already existed in a pending queue but with older ETag, it's metadata has been refreshed",
							workItem.GetType().Name, workItem.FileName, destination);
						return;
					}
				}

				var activeForDestination = activeSynchronizations.GetOrAdd(destination,
				                                                           new ConcurrentDictionary<string, SynchronizationWorkItem>
					                                                           ());

				// if there is a work in an active synchronizations do not add it again
				if (activeForDestination.ContainsKey(workItem.FileName) && activeForDestination[workItem.FileName].Equals(workItem))
				{
					Log.Debug("{0} for a file {1} and a destination {2} was already existed in an active queue",
					          workItem.GetType().Name, workItem.FileName, destination);
					return;
				}

				pendingForDestination.Enqueue(workItem);
				Log.Debug("{0} for a file {1} and a destination {2} was enqueued", workItem.GetType().Name, workItem.FileName,
				          destination);
			}
			finally
			{
				pendingRemoveLocks.GetOrAdd(destination, new ReaderWriterLockSlim()).ExitUpgradeableReadLock();
			}
		}