/// <summary>
 /// Submit a delta to be processed
 /// </summary>
 /// <param name="itemDelta"></param>
 /// <returns>the ticket number to get callback info</returns>
 public long Enqueue(IItemDelta itemDelta)
 {
     _queue.Enqueue(itemDelta);
     return(Interlocked.Increment(ref _ticketCounter));
 }
        public void SubmitDelta(IItemDelta itemDelta)
        {
            // Outline of handling this delta:
            //
            //  If there are any pending deltas for the item from the
            //      opposite source, then there is a conflict.  This conflict
            //      will cause the delta to lock up the queue
            //
            //  Resolving this conflict: choose whether to push all local
            //      deltas or all remote ones, OR to rename the local
            //      keep the remote, and close any deltas from the local.
            //      this new local file will be seen as an event for
            //      creating a new file that is not in the metadata
            //      and will spawn a delta to upload to the remote

            //See if the item exists in the metadata
            var entry = GetItemHandleByPath(itemDelta.PreProperties.Path);

            // Item exists in the metadata
            if (entry != null)
            {
                // If there is a temp ID and the source is remote, update the ID
                if (entry.Id[0] == '_' && itemDelta.Source == DeltaSource.Remote)
                {
                    entry.Id = itemDelta.Handle.Id;
                }

                if (entry.PendingDeltas.Any(kvp => kvp.Value.Source != itemDelta.Source))
                {
                    //conflicts
                    entry.ErrorState = ItemErrorState.VersionConflict;
                }
            }
            // Item doesn't exist in the metadata
            else
            {
                // if the item doesn't exist, we can't work with info we don't have,
                //  so add the pre-delta info to the metadata and submit the delta

                if (itemDelta.Source == DeltaSource.Local)
                {
                    // If the item doesn't exist and the source is local, then apply a temp id
                    //  until the update rebounds
                    var id = "_" + Interlocked.Increment(ref _tempItemIdCounter);
                    _itemMetadata.TryAdd(id, new MetadataEntry(id, new ItemProperties(itemDelta.PreProperties)));
                }
                else
                {
                    //not in metadata, remote source, so simply add the properties
                    _itemMetadata.TryAdd(itemDelta.Handle.Id,
                                         new MetadataEntry(itemDelta.Handle.Id, new ItemProperties(itemDelta.PreProperties)));
                }

                // This will NEVER be null
                entry = GetItemHandleByPath(itemDelta.PreProperties.Path);
            }

            // Submit the delta to the proper buffer
            long ticket = 0;

            switch (itemDelta.Source)
            {
            case DeltaSource.Local:
                ticket = _remoteDeltaBuffer.Enqueue(itemDelta);
                break;

            case DeltaSource.Remote:
                ticket = _localDeltaBuffer.Enqueue(itemDelta);
                break;
            }

            // Finally, add the delta to the pending delta dictionaries
            entry.PendingDeltas.Add(ticket, itemDelta);

            // TODO: this shouldn't ever fail since tickets are unique
            _pendingDeltas.TryAdd(ticket, itemDelta);
        }