Exemple #1
0
        public override void SaveItemChange(SaveChangeAction saveChangeAction, ItemChange change, SaveChangeContext context)
        {
            // Extract the data from the change
            TransferMechanism data = context.ChangeData as TransferMechanism;
            // Item metadata
            ItemMetadata item = _sync.GetItemMetaData(saveChangeAction, change, data);

            // Now apply the change
            if (!(saveChangeAction == SaveChangeAction.UpdateVersionOnly) && ((change.ChangeKind & ChangeKind.Deleted) == 0))
            {
                // Only copy if destination file name is known
                // (May have been lost if loser of name collision)
                if (item.Uri != String.Empty)
                {
                    FileInfo fi = new FileInfo(System.IO.Path.Combine(Path, item.Uri));
                    if (!fi.Directory.Exists)
                    {
                        fi.Directory.Create();
                    }

                    // Change should have stream data, so copy the file data to the local store
                    using (FileStream outputStream = new FileStream(System.IO.Path.Combine(Path, item.Uri), FileMode.OpenOrCreate)) {
                        const int copyBlockSize = 4096;
                        byte[]    buffer        = new byte[copyBlockSize];

                        int bytesRead;
                        // Simple block-by-block copy
                        while ((bytesRead = data.DataStream.Read(buffer, 0, copyBlockSize)) > 0)
                        {
                            outputStream.Write(buffer, 0, bytesRead);
                        }
                        // Truncate if needed
                        outputStream.SetLength(outputStream.Position);
                    }

                    // Update the last write time from the updated file to the metadata entry
                    item.LastWriteTimeUtc = fi.LastWriteTimeUtc;
                }

                // Close input stream
                data.DataStream.Close();
            }
            else
            {
                // Not an update/create, so must be a delete or version only change
                // Is it a delete?...
                if (item.IsTombstone && item.Uri != String.Empty)
                {
                    // Change is a delete
                    File.Delete(System.IO.Path.Combine(Path, item.Uri));
                }
            }

            // If we made it here, the change was successfully applied locally
            // (or it is a version only change), so we can update our knowledge with the
            // learned knowledge from the change
            _sync.GetUpdatedKnowledge(context);
        }
Exemple #2
0
        public object LoadChangeData(LoadChangeContext loadChangeContext)
        {
            ItemMetadata item;

            // Retrieve metadata for the changed item
            if (metadataStore.TryGetItem(loadChangeContext.ItemChange.ItemId, out item))
            {
                // Make sure this isn't a delete
                if (item.IsTombstone)
                {
                    throw new InvalidOperationException("Cannot load change data for a deleted item.");
                }

                // Open the stream for the file we are transferring
                Stream dataStream = new FileStream(Path.Combine(FolderPath, item.Uri), FileMode.Open, FileAccess.Read, FileShare.Read);
                // Create an instance of our type for transferring change data
                TransferMechanism transferMechanism = new TransferMechanism(dataStream, item.Uri);

                // Return our data transfer object
                return(transferMechanism);
            }

            return(null);
        }
Exemple #3
0
        public ItemMetadata GetItemMetaData(SaveChangeAction saveChangeAction, ItemChange change, TransferMechanism data)
        {
            ItemMetadata item;

            // Populate the URI field of the updated item metadata
            if (saveChangeAction == SaveChangeAction.UpdateVersionOnly || ((change.ChangeKind & ChangeKind.Deleted) == ChangeKind.Deleted))
            {
                // Version only changes and deletions will not contain data,
                // so we cannot get the item URI from the change data
                //
                // So, we attempt to look up the item metadata instead (by item id)
                // to populate the URI field
                if (!metadataStore.TryGetItem(change.ItemId, out item))
                {
                    // Not found, must mean we've never seen this item locally
                    // Can safely use an empty URI
                    item     = new ItemMetadata();
                    item.Uri = String.Empty;
                }
            }
            else
            {
                // Since this isn't a version-only change or a delete, context should contain
                // change data
                item = new ItemMetadata(); // Used for storing updated item metadata

                // Populate the Uri field
                item.Uri = data.Uri;
            }

            // Now copy the rest of the metadata for the item from the change
            item.ItemId          = change.ItemId;
            item.CreationVersion = change.CreationVersion;
            item.ChangeVersion   = change.ChangeVersion;

            // If deletion change, mark it as a tombstone
            if ((change.ChangeKind & ChangeKind.Deleted) == ChangeKind.Deleted)
            {
                item.IsTombstone = true;
            }

            // Is this a new item?
            if (!metadataStore.Has(item.ItemId))
            {
                ItemMetadata oldItem;

                // Not found
                // Need to check for duplicates (by URI)
                if (metadataStore.TryGetItem(item.Uri, out oldItem))
                {
                    // Duplicate item (same Uri), so we deterministically choose a winner
                    // by comparing the guid part of the item ids
                    if (item.ItemId.CompareTo(oldItem.ItemId) > 0)
                    {
                        // New item is the winner
                        // Record old item as a loser
                        oldItem.IsTombstone   = true;
                        oldItem.Uri           = String.Empty;
                        oldItem.ChangeVersion = new SyncVersion(0, tickCount);
                    }
                    else
                    {
                        // Old item is the winner
                        // Record new item as a loser
                        item.IsTombstone   = true;
                        item.Uri           = String.Empty;
                        item.ChangeVersion = new SyncVersion(0, tickCount);
                    }

                    // Record the updated item metadata
                    metadataStore.SetItemInfo(item);
                    metadataStore.SetItemInfo(oldItem);
                }
            }

            // Save the updated item metadata
            metadataStore.SetItemInfo(item);

            return(item);
        }