Exemple #1
0
        /// <summary>
        /// UPDATE
        /// </summary>
        ///
        private void UpdateItem(ItemMetadata item, ItemChange change, SaveChangeContext context)
        {
            var data   = (IFileDataRetriever)context.ChangeData;
            var attr   = _metadataStore.GetItemInfo(item);
            var stream = data.FileData.IsDirectory ? null : data.FileStream;

            try
            {
                SyncedNodeAttributes updatedNode = null;
                //if pathes are different then consider renaming with unchanged content
                if (attr.Path != data.FileData.RelativePath)
                {
                    updatedNode = _nodeStore.MoveFile(attr.Path, data.FileData.RelativePath, attr.Id);
                    OnAppliedChange(ChangeType.Rename, data.FileData.RelativePath, attr.Path);
                }
                else
                {
                    updatedNode = _nodeStore.UpdateFile(attr.Path, data.FileData, stream, attr.Id);
                    OnAppliedChange(ChangeType.Update, data.FileData.RelativePath);
                }

                item.ChangeVersion = change.ChangeVersion;
                _metadataStore.SaveItemMetadata(item, updatedNode.Id, updatedNode.Path);
            }
            catch (MegaStoreConstraintException e)
            {
                ProcessConstraint(change, context, e, item, e.Node);
            }
            catch (MegaStoreException e)
            {
                ForgetItem(context, item, e);
            }
            catch (MegaApiException e)
            {
                context.RecordRecoverableErrorForItem(new RecoverableErrorData(e));
                OnDemandedResync();
            }
            catch (DirectoryNotFoundException e)
            {
                context.RecordRecoverableErrorForItem(new RecoverableErrorData(e));
                OnDemandedResync();
            }

            catch (COMException e)
            {
                OnDemandedResync();
                context.RecordRecoverableErrorForItem(new RecoverableErrorData(e));
            }
            finally
            {
                CloseStream(stream);
            }
        }
Exemple #2
0
        private void ProcessConstraint(
            ItemChange change,
            SaveChangeContext context,
            MegaStoreConstraintException e,
            ItemMetadata item,
            MegaNodeHelper conflictingNode)
        {
            switch (e.ConstraintType)
            {
            case MegaStoreConstraintType.TargetExists:
                ResolveConflict(item, change, context, conflictingNode);
                break;

            case MegaStoreConstraintType.NoParent:
                OnDemandedResync();
                context.RecordConstraintConflictForItem(ConstraintConflictReason.NoParent);
                break;

            // todo add no-free-space handling
            case MegaStoreConstraintType.ZeroSize:
                context.RecordConstraintConflictForItem(ConstraintConflictReason.Other);
                break;

            case MegaStoreConstraintType.NotEmpty:
                OnDemandedResync();
                context.RecordRecoverableErrorForItem(new RecoverableErrorData(e));
                break;
            }
        }
Exemple #3
0
 private void DoNothing(
     ItemMetadata item,
     ItemChange change,
     SaveChangeContext context,
     bool deleted = false,
     MegaNodeHelper existingNode = null)
 {
     // creating
     if (item == null)
     {
         if (existingNode == null)
         {
             context.RecordRecoverableErrorForItem(new RecoverableErrorData(new Exception()));
         }
         item = _metadataStore.Metadata.CreateItemMetadata(change.ItemId, change.CreationVersion);
         item.ChangeVersion = change.ChangeVersion;
         _metadataStore.SaveItemMetadata(item, existingNode.Node.Id, existingNode.Path);
         return;
     }
     if (deleted)
     {
         item.MarkAsDeleted(change.ChangeVersion);
     }
     item.ChangeVersion = change.ChangeVersion;
     _metadataStore.SaveItemMetadata(item);
 }
Exemple #4
0
 // the node is suddenly out, remove it from database
 // (it was a concurrency delete attempt - we should restore the existing version)
 private void ForgetItem(SaveChangeContext context, ItemMetadata item, Exception e)
 {
     _metadataStore.Metadata.RemoveItemMetadata(new List <SyncId> {
         item.GlobalId
     });
     OnDemandedResync();
     context.RecordRecoverableErrorForItem(new RecoverableErrorData(e));
 }
Exemple #5
0
        /// <summary>
        /// CREATE
        /// </summary>
        private void CreateItem(ItemChange change, SaveChangeContext context, ItemMetadata itemToSaveChanges = null)
        {
            var    data   = (IFileDataRetriever)context.ChangeData;
            Stream stream = null;

            try
            {
                stream = data.FileData.IsDirectory ? null : data.FileStream;
                var createdNode = _nodeStore.InsertNode(data.FileData, data.FileData.RelativePath, stream);
                if (itemToSaveChanges == null)
                {
                    itemToSaveChanges = _metadataStore.CreateItemMetadata(change.ItemId, change.CreationVersion);
                }
                itemToSaveChanges.ChangeVersion = change.ChangeVersion;

                _metadataStore.SaveItemMetadata(itemToSaveChanges, createdNode.Id, createdNode.Path);
                OnAppliedChange(ChangeType.Create, data.FileData.RelativePath);
            }
            catch (MegaStoreConstraintException e)
            {
                ProcessConstraint(change, context, e, null, e.Node);
            }
            catch (MegaApiException e)
            {
                context.RecordRecoverableErrorForItem(new RecoverableErrorData(e));
            }
            catch (DirectoryNotFoundException e)
            {
                OnDemandedResync();
                context.RecordRecoverableErrorForItem(new RecoverableErrorData(e));
            }
            catch (COMException e)
            {
                OnDemandedResync();
                context.RecordRecoverableErrorForItem(new RecoverableErrorData(e));
            }
            finally
            {
                CloseStream(stream);
            }
        }
Exemple #6
0
 /// <summary>
 /// DELETE
 /// </summary>
 private void DeleteItem(ItemMetadata item, ItemChange change, SaveChangeContext context, bool removeTombstone = false)
 {
     try
     {
         var attr = _metadataStore.GetItemInfo(item);
         _nodeStore.DeleteFile(attr.Path, attr.Id);
         OnAppliedChange(ChangeType.Delete, null, attr.Path);
         if (removeTombstone)
         {
             _metadataStore.Metadata.RemoveItemMetadata(new List <SyncId> {
                 item.GlobalId
             });
         }
         else
         {
             item.MarkAsDeleted(change.ChangeVersion);
             _metadataStore.SaveItemMetadata(item);
         }
     }
     catch (MegaStoreConstraintException e)
     {
         ProcessConstraint(change, context, e, item, null);
     }
     // never mind, the item isn't found anyway
     catch (MegaStoreException)
     {
         if (removeTombstone)
         {
             _metadataStore.Metadata.RemoveItemMetadata(new List <SyncId> {
                 item.GlobalId
             });
         }
         else
         {
             item.MarkAsDeleted(change.ChangeVersion);
             _metadataStore.SaveItemMetadata(item);
         }
     }
     catch (MegaApiException e)
     {
         context.RecordRecoverableErrorForItem(new RecoverableErrorData(e));
         OnDemandedResync();
     }
 }
        public void SaveItemChange(SaveChangeAction saveChangeAction, ItemChange change, SaveChangeContext context)
        {
            ItemMetadata item = null;
            T            data = default(T);

            try
            {
                switch (saveChangeAction)
                {
                case SaveChangeAction.Create:
                    try
                    {
                        //Do duplicate detection here
                        item = _metaData.FindItemMetadataById(change.ItemId);
                        if (item != null)
                        {
                            throw new SyncProviderException("SaveItemChange must not have Create action for existing items.");
                        }
                        item = _metaData.CreateItemMetadata(change.ItemId, change.CreationVersion);
                        item.ChangeVersion = change.ChangeVersion;
                        data = ConvertFromTransferData(context.ChangeData);
                        CreateDataItem(change, item, data);
                        SaveItemMetadata(item);
                    }
                    catch (Exception e)
                    {
                        throw new SyncProviderException(e, SaveChangeAction.Create);
                    }
                    break;

                case SaveChangeAction.UpdateVersionAndData:
                case SaveChangeAction.UpdateVersionOnly:
                    try
                    {
                        item = _metaData.FindItemMetadataById(change.ItemId);
                        if (null == item)
                        {
                            throw new SyncProviderException("Item Not Found in Store!?");
                        }

                        item.ChangeVersion = change.ChangeVersion;
                        if (saveChangeAction == SaveChangeAction.UpdateVersionOnly)
                        {
                            SaveItemMetadata(item);
                        }
                        else                                  //Also update the data.
                        {
                            data = ConvertFromTransferData(context.ChangeData);
                            UpdateDataItem(change, item, data);
                            SaveItemMetadata(item);
                        }
                    }
                    catch (Exception e)
                    {
                        throw new SyncProviderException(e, SaveChangeAction.UpdateVersionAndData);
                    }
                    break;

                case SaveChangeAction.DeleteAndStoreTombstone:
                    try
                    {
                        item = _metaData.FindItemMetadataById(change.ItemId);
                        if (null == item)
                        {
                            item = _metaData.CreateItemMetadata(change.ItemId, change.CreationVersion);
                        }
                        if (change.ChangeKind == ChangeKind.Deleted)
                        {
                            item.MarkAsDeleted(change.ChangeVersion);
                        }
                        else
                        {
                            // This should never happen in Sync Framework V1.0
                            throw new SyncProviderException("Invalid ChangeType");
                        }

                        item.ChangeVersion = change.ChangeVersion;
                        SaveItemMetadata(item);
                        DeleteDataItem(change, item, data);                                //item.GlobalId.GetGuidId());
                    }
                    catch (Exception e)
                    {
                        throw new SyncProviderException(e, SaveChangeAction.DeleteAndStoreTombstone);
                    }
                    break;

                //Merge the changes! (Take the data from the local item + the remote item),noting to update the tick count to propagate the resolution!
                case SaveChangeAction.UpdateVersionAndMergeData:
                    try
                    {
                        item = _metaData.FindItemMetadataById(change.ItemId);
                        if (null == item)
                        {
                            throw new SyncProviderException("Item Not Found in Store!?");
                        }
                        if (item.IsDeleted != true)
                        {
                            //Note - you must update the change version to propagate the resolution!
                            item.ChangeVersion = new SyncVersion(0, _metaData.GetNextTickCount());

                            //Combine the conflicting data...
                            T dataItem = GetDataItem(item);
                            if (dataItem == null)
                            {
                                throw new SyncProviderException("data item not found for merge");
                            }
                            data = ConvertFromTransferData(context.ChangeData);
                            data = MergeDataItem(dataItem, data);
                            UpdateDataItem(change, item, data);
                            SaveItemMetadata(item);
                        }
                    }
                    catch (Exception e)
                    {
                        throw new SyncProviderException(e, SaveChangeAction.UpdateVersionAndMergeData);
                    }
                    break;

                case SaveChangeAction.DeleteAndRemoveTombstone:
                    try
                    {
                        item = _metaData.FindItemMetadataById(change.ItemId);
                        if (item != null)
                        {
                            _metaData.RemoveItemMetadata(new SyncId[] { item.GlobalId });
                        }
                        data = ConvertFromTransferData(context.ChangeData);
                        DeleteDataItem(change, item, data);
                    }
                    catch (Exception e)
                    {
                        throw new SyncProviderException(e, SaveChangeAction.DeleteAndRemoveTombstone);
                    }
                    break;
                }
            }
            catch (SyncProviderException e)
            {
                Exception exception = e.InnerException != null ? e.InnerException : e;
                string    itemDescr = e.SaveChangeAction.ToString();
                string    errDescr  = e.Message + "[" + e.InnerException != null?e.InnerException.ToString()
                                          : string.Empty + "]";

                RecoverableErrorData recoverableError = new RecoverableErrorData(exception, itemDescr, errDescr);
                context.RecordRecoverableErrorForItem(recoverableError);
            }
        }
 // the node is suddenly out, remove it from database 
 // (it was a concurrency delete attempt - we should restore the existing version)
 private void ForgetItem(SaveChangeContext context, ItemMetadata item, Exception e)
 {
     _metadataStore.Metadata.RemoveItemMetadata(new List<SyncId> { item.GlobalId });
     OnDemandedResync();
     context.RecordRecoverableErrorForItem(new RecoverableErrorData(e));
 }
        private void ProcessConstraint(
            ItemChange change,
            SaveChangeContext context,
            MegaStoreConstraintException e,
            ItemMetadata item,
            MegaNodeHelper conflictingNode)
        {
            switch (e.ConstraintType)
            {
                case MegaStoreConstraintType.TargetExists:
                    ResolveConflict(item, change, context, conflictingNode);
                    break;

                case MegaStoreConstraintType.NoParent:
                    OnDemandedResync();
                    context.RecordConstraintConflictForItem(ConstraintConflictReason.NoParent);
                    break;
                // todo add no-free-space handling
                case MegaStoreConstraintType.ZeroSize:
                    context.RecordConstraintConflictForItem(ConstraintConflictReason.Other);
                    break;

                case MegaStoreConstraintType.NotEmpty:
                    OnDemandedResync();
                    context.RecordRecoverableErrorForItem(new RecoverableErrorData(e));
                    break;
            }
        }
 private void DoNothing(
     ItemMetadata item, 
     ItemChange change,
     SaveChangeContext context,
     bool deleted = false,
     MegaNodeHelper existingNode = null)
 {
     // creating
     if (item == null)
     {
         if (existingNode == null)
         {
             context.RecordRecoverableErrorForItem(new RecoverableErrorData(new Exception()));
         }
         item = _metadataStore.Metadata.CreateItemMetadata(change.ItemId, change.CreationVersion);
         item.ChangeVersion = change.ChangeVersion;
         _metadataStore.SaveItemMetadata(item, existingNode.Node.Id, existingNode.Path);
         return;
     }
     if (deleted)
     {
         item.MarkAsDeleted(change.ChangeVersion);
     }
     item.ChangeVersion = change.ChangeVersion;
     _metadataStore.SaveItemMetadata(item);
 }
 /// <summary>
 /// CONFLICT
 /// </summary>
 private void ResolveConflict(ItemMetadata item, ItemChange change, SaveChangeContext context, MegaNodeHelper conflictingNode)
 {
     var data = (IFileDataRetriever)context.ChangeData;
     // item does not exist in metadata (can happen when create+create)
     if (item == null) 
     {
         if (conflictingNode == null) 
         {
             context.RecordRecoverableErrorForItem(new RecoverableErrorData(new Exception()));
         }
         if (FilesAreEqual(data, conflictingNode))
         {
             DoNothing(item, change, context, false, conflictingNode);
         }
         else
         {
             BackupFile(item, conflictingNode.Path, change, context);
         }
         return;
     }
     var attr = _metadataStore.GetItemInfo(item);
     try
     {
         if (change.ChangeKind == ChangeKind.Deleted)
         {
             // local delete + remote delete
             if (item.IsDeleted)
             {
                 DoNothing(item, change, context, true);
             }
             // local delete + remote update
             else
             {
                 DownloadBack(item, change);
             }
         }
         else
         {
             // local update + remote delete
             if (item.IsDeleted)
             {
                 UploadBack(item, change, context);
             }
             // update + update
             else
             {
                 if (FilesAreEqual(data, _nodeStore.FindNodeById(attr.Id)))
                 {
                     DoNothing(item, change, context);
                 }
                 else
                 {
                     BackupFile(item, attr.Path, change, context);
                 }
             }
         }
     }
     catch (MegaApiException e)
     {
         context.RecordRecoverableErrorForItem(new RecoverableErrorData(e));
     }
 }
 /// <summary>
 /// DELETE
 /// </summary>
 private void DeleteItem(ItemMetadata item, ItemChange change, SaveChangeContext context, bool removeTombstone = false)
 {
     try
     {
         var attr = _metadataStore.GetItemInfo(item);
         _nodeStore.DeleteFile(attr.Path, attr.Id);
         OnAppliedChange(ChangeType.Delete, null, attr.Path);
         if (removeTombstone)
         {
             _metadataStore.Metadata.RemoveItemMetadata(new List<SyncId> { item.GlobalId });
         }
         else
         {
             item.MarkAsDeleted(change.ChangeVersion);
             _metadataStore.SaveItemMetadata(item);
         }
     }
     catch (MegaStoreConstraintException e)
     {
         ProcessConstraint(change, context, e, item, null);
     }
     // never mind, the item isn't found anyway
     catch (MegaStoreException)
     {
         if (removeTombstone)
         {
             _metadataStore.Metadata.RemoveItemMetadata(new List<SyncId> { item.GlobalId });
         }
         else
         {
             item.MarkAsDeleted(change.ChangeVersion);
             _metadataStore.SaveItemMetadata(item);
         }
     }
     catch (MegaApiException e)
     {
         context.RecordRecoverableErrorForItem(new RecoverableErrorData(e));
         OnDemandedResync();
     }
 }
        /// <summary>
        /// UPDATE
        /// </summary>
        /// 
        private void UpdateItem(ItemMetadata item, ItemChange change, SaveChangeContext context)
        {
            var data = (IFileDataRetriever)context.ChangeData;
            var attr = _metadataStore.GetItemInfo(item);
            var stream = data.FileData.IsDirectory ? null : data.FileStream;
            try
            {
                SyncedNodeAttributes updatedNode = null;
                //if pathes are different then consider renaming with unchanged content
                if (attr.Path != data.FileData.RelativePath)
                {
                    updatedNode = _nodeStore.MoveFile(attr.Path, data.FileData.RelativePath, attr.Id);
                    OnAppliedChange(ChangeType.Rename, data.FileData.RelativePath, attr.Path);
                }
                else
                {
                    updatedNode = _nodeStore.UpdateFile(attr.Path, data.FileData, stream, attr.Id);
                    OnAppliedChange(ChangeType.Update, data.FileData.RelativePath);
                }

                item.ChangeVersion = change.ChangeVersion;
                _metadataStore.SaveItemMetadata(item, updatedNode.Id, updatedNode.Path);
            }
            catch (MegaStoreConstraintException e)
            {
                ProcessConstraint(change, context, e, item, e.Node);
            }
            catch (MegaStoreException e)
            {
                ForgetItem(context, item, e);
            }
            catch (MegaApiException e)
            {
                context.RecordRecoverableErrorForItem(new RecoverableErrorData(e));
                OnDemandedResync();
            }
            catch (DirectoryNotFoundException e)
            {
                context.RecordRecoverableErrorForItem(new RecoverableErrorData(e));
                OnDemandedResync();
            }

            catch (COMException e)
            {
                OnDemandedResync();
                context.RecordRecoverableErrorForItem(new RecoverableErrorData(e));
            }
            finally
            {
                CloseStream(stream);
            }
        }
        /// <summary>
        /// CREATE
        /// </summary>
        private void CreateItem(ItemChange change, SaveChangeContext context, ItemMetadata itemToSaveChanges = null)
        {
            var data = (IFileDataRetriever)context.ChangeData;
            Stream stream = null;
            try
            {
                stream = data.FileData.IsDirectory ? null : data.FileStream;
                var createdNode = _nodeStore.InsertNode(data.FileData, data.FileData.RelativePath, stream);
                if (itemToSaveChanges == null)
                {
                    itemToSaveChanges = _metadataStore.CreateItemMetadata(change.ItemId, change.CreationVersion);
                }
                itemToSaveChanges.ChangeVersion = change.ChangeVersion;

                _metadataStore.SaveItemMetadata(itemToSaveChanges, createdNode.Id, createdNode.Path);
                OnAppliedChange(ChangeType.Create, data.FileData.RelativePath);
            }
            catch (MegaStoreConstraintException e)
            {
                ProcessConstraint(change, context, e, null, e.Node);
            }
            catch (MegaApiException e)
            {
                context.RecordRecoverableErrorForItem(new RecoverableErrorData(e));
            }
            catch (DirectoryNotFoundException e)
            {
                OnDemandedResync();
                context.RecordRecoverableErrorForItem(new RecoverableErrorData(e));
            }
            catch (COMException e)
            {
                OnDemandedResync();
                context.RecordRecoverableErrorForItem(new RecoverableErrorData(e));
            }
            finally
            {
                CloseStream(stream);
            }
        }
Exemple #15
0
        /// <summary>
        /// CONFLICT
        /// </summary>
        private void ResolveConflict(ItemMetadata item, ItemChange change, SaveChangeContext context, MegaNodeHelper conflictingNode)
        {
            var data = (IFileDataRetriever)context.ChangeData;

            // item does not exist in metadata (can happen when create+create)
            if (item == null)
            {
                if (conflictingNode == null)
                {
                    context.RecordRecoverableErrorForItem(new RecoverableErrorData(new Exception()));
                }
                if (FilesAreEqual(data, conflictingNode))
                {
                    DoNothing(item, change, context, false, conflictingNode);
                }
                else
                {
                    BackupFile(item, conflictingNode.Path, change, context);
                }
                return;
            }
            var attr = _metadataStore.GetItemInfo(item);

            try
            {
                if (change.ChangeKind == ChangeKind.Deleted)
                {
                    // local delete + remote delete
                    if (item.IsDeleted)
                    {
                        DoNothing(item, change, context, true);
                    }
                    // local delete + remote update
                    else
                    {
                        DownloadBack(item, change);
                    }
                }
                else
                {
                    // local update + remote delete
                    if (item.IsDeleted)
                    {
                        UploadBack(item, change, context);
                    }
                    // update + update
                    else
                    {
                        if (FilesAreEqual(data, _nodeStore.FindNodeById(attr.Id)))
                        {
                            DoNothing(item, change, context);
                        }
                        else
                        {
                            BackupFile(item, attr.Path, change, context);
                        }
                    }
                }
            }
            catch (MegaApiException e)
            {
                context.RecordRecoverableErrorForItem(new RecoverableErrorData(e));
            }
        }