예제 #1
0
        /// <summary>
        /// Method that synchronize the Cache by uploading all modified changes and then downloading the
        /// server changes.
        /// </summary>
        internal async Task <CacheRefreshStatistics> SynchronizeAsync(CancellationToken cancellationToken)
        {
            CacheRefreshStatistics statistics = new CacheRefreshStatistics();

            try
            {
                // Check if cancellation has occured
                if (cancellationToken.IsCancellationRequested)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                }

                // set start time
                statistics.StartTime = DateTime.Now;

                // First create the CacheRequestHandler
                this.cacheRequestHandler = new HttpCacheRequestHandler(this.serviceUri, this.controllerBehavior);

                // Then fire the BeginSession call on the local provider.
                this.localProvider.BeginSession();

                // Set the flag to indicate BeginSession was successful
                this.beginSessionComplete = true;

                // Do uploads first
                statistics = await this.EnqueueUploadRequest(statistics, cancellationToken);

                // Set end time
                statistics.EndTime = DateTime.Now;

                // Call EndSession only if BeginSession was successful.
                if (this.beginSessionComplete)
                {
                    this.localProvider.EndSession();
                }
            }
            catch (OperationCanceledException ex)
            {
                statistics.EndTime   = DateTime.Now;
                statistics.Cancelled = true;
                statistics.Error     = ex;

                this.localProvider.EndSession();
            }
            catch (Exception ex)
            {
                statistics.EndTime = DateTime.Now;
                statistics.Error   = ex;

                this.localProvider.EndSession();
            }
            finally
            {
                // Reset the state
                this.ResetAsyncWorkerManager();
            }

            return(statistics);
        }
예제 #2
0
        /// <summary>
        /// Method that performs an upload. It gets the ChangeSet from the local provider and then creates an
        /// CacheRequest object for that ChangeSet and then passed the processing asynchronously to the underlying
        /// CacheRequestHandler.
        /// </summary>
        private async Task <CacheRefreshStatistics> EnqueueUploadRequest(CacheRefreshStatistics statistics, CancellationToken cancellationToken)
        {
            this.changeSetId = Guid.NewGuid();

            try
            {
                // Check if cancellation has occured
                if (cancellationToken.IsCancellationRequested)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                }

                ChangeSet changeSet = this.localProvider.GetChangeSet(this.changeSetId);

                if (changeSet == null || changeSet.Data == null || changeSet.Data.Count == 0)
                {
                    // No data to upload. Skip upload phase.
                    statistics = await this.EnqueueDownloadRequest(statistics, cancellationToken);
                }
                else
                {
                    // Create a SyncRequest out of this.
                    CacheRequest request = new CacheRequest
                    {
                        RequestId     = this.changeSetId,
                        Format        = this.ControllerBehavior.SerializationFormat,
                        RequestType   = CacheRequestType.UploadChanges,
                        Changes       = changeSet.Data,
                        KnowledgeBlob = changeSet.ServerBlob,
                        IsLastBatch   = changeSet.IsLastBatch
                    };

                    var args = await this.cacheRequestHandler.ProcessCacheRequestAsync(request, changeSet.IsLastBatch, cancellationToken);

                    statistics = await this.ProcessCacheRequestResults(statistics, args, cancellationToken);
                }
            }
            catch (OperationCanceledException)
            {
                // Re throw the operation cancelled
                throw;
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                {
                    throw;
                }

                statistics.Error = e;
            }


            return(statistics);
        }
예제 #3
0
        /// <summary>
        /// Method that performs a download. It gets the server blob anchor from the local provider and then creates an 
        /// CacheRequest object for that download request. It then passes the processing asynchronously to the underlying
        /// CacheRequestHandler.
        /// </summary>
        private async Task<CacheRefreshStatistics> EnqueueDownloadRequest(CacheRefreshStatistics statistics,
                                                                          CancellationToken cancellationToken,
                                                                          IProgress<SyncProgressEvent> progress = null)
        {
            try
            {
                if (cancellationToken.IsCancellationRequested)
                    cancellationToken.ThrowIfCancellationRequested();

                Boolean isLastBatch = false;

                while (!isLastBatch)
                {
                    if (cancellationToken.IsCancellationRequested)
                        cancellationToken.ThrowIfCancellationRequested();

                    // Create a SyncRequest for download.
                    CacheRequest request = new CacheRequest
                    {
                        Format = this.ControllerBehavior.SerializationFormat,
                        RequestType = CacheRequestType.DownloadChanges,
                        KnowledgeBlob = this.localProvider.GetServerBlob()
                    };

                    // Get Changes
                    DateTime durationStartDate = DateTime.Now;
                    var requestResult = await this.cacheRequestHandler.ProcessCacheRequestAsync(
                        request, null, cancellationToken);

                    statistics = await this.ProcessCacheRequestResults(statistics, requestResult, cancellationToken);

                    // Check if we are at the end 
                    if (requestResult.ChangeSet == null || requestResult.ChangeSet.IsLastBatch)
                        isLastBatch = true;

                    // Reporting progress after get changes from local store
                    if (progress != null)
                        progress.Report(new SyncProgressEvent(SyncStage.DownloadingChanges, DateTime.Now.Subtract(durationStartDate), true, (requestResult.ChangeSet != null ? requestResult.ChangeSet.Data : null)));
                }
            }
            catch (OperationCanceledException)
            {
                // Re throw the operation cancelled
                throw;
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                    throw;

                statistics.Error = e;
            }

            return statistics;
        }
        /// <summary>
        /// Internal ctor to prevent public instantiation.
        /// </summary>
        /// <param name="stats">Statistics parameter</param>
        /// <param name="error">Refresh exception.</param>
        /// <param name="cancelled">Cancellation flag</param>
        internal RefreshCompletedEventArgs(CacheRefreshStatistics stats, Exception error, bool cancelled)
        {
            if (stats == null)
            {
                throw new ArgumentNullException("stats");
            }

            this.Statistics = stats;
            this.Error      = error;
            this.Cancelled  = cancelled;
        }
        /// <summary>
        /// Internal ctor to prevent public instantiation.
        /// </summary>
        /// <param name="stats">Statistics parameter</param>
        /// <param name="error">Refresh exception.</param>
        /// <param name="cancelled">Cancellation flag</param>
        internal RefreshCompletedEventArgs(CacheRefreshStatistics stats, Exception error, bool cancelled)
        {
            if (stats == null)
            {
                throw new ArgumentNullException("stats");
            }

            this.Statistics = stats;
            this.Error = error;
            this.Cancelled = cancelled;
        }
예제 #6
0
        /// <summary>
        /// Method that refreshes the Cache by uploading all modified changes and then downloading the
        /// server changes.
        /// </summary>
        public void RefreshAsync()
        {
            if (this.IsBusy)
            {
                throw CacheControllerException.CreateCacheBusyException();
            }

            this.refreshStats = new CacheRefreshStatistics();

            this.StartAsyncWorkerManager();

            // Enqueue an async operation
            this._asyncWorkManager.AddWorkRequest(new AsyncWorkRequest(RefreshWorker, RefreshWorkerCompleted, null));
        }
예제 #7
0
        /// <summary>
        /// Method that performs a download. It gets the server blob anchor from the local provider and then creates an
        /// CacheRequest object for that download request. It then passes the processing asynchronously to the underlying
        /// CacheRequestHandler.
        /// </summary>
        private async Task <CacheRefreshStatistics> EnqueueDownloadRequest(CacheRefreshStatistics statistics, CancellationToken cancellationToken)
        {
            try
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                }

                // Create a SyncRequest for download.
                CacheRequest request = new CacheRequest
                {
                    Format        = this.ControllerBehavior.SerializationFormat,
                    RequestType   = CacheRequestType.DownloadChanges,
                    KnowledgeBlob = this.localProvider.GetServerBlob()
                };

                var args = await this.cacheRequestHandler.ProcessCacheRequestAsync(request, null, cancellationToken);

                statistics = await this.ProcessCacheRequestResults(statistics, args, cancellationToken);
            }
            catch (OperationCanceledException)
            {
                // Re throw the operation cancelled
                throw;
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                {
                    throw;
                }

                statistics.Error = e;
            }

            return(statistics);
        }
예제 #8
0
        /// <summary>
        /// Method that performs an upload. It gets the ChangeSet from the local provider and then creates an
        /// CacheRequest object for that ChangeSet and then passed the processing asynchronously to the underlying
        /// CacheRequestHandler.
        /// </summary>
        private async Task <CacheRefreshStatistics> EnqueueUploadRequest(CacheRefreshStatistics statistics,
                                                                         CancellationToken cancellationToken,
                                                                         IProgress <SyncProgressEvent> progress = null)
        {
            this.changeSetId = Guid.NewGuid();

            try
            {
                // Check if cancellation has occured
                if (cancellationToken.IsCancellationRequested)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                }

                // Get Changes
                DateTime  durationStartDate = DateTime.Now;
                ChangeSet changeSet         = await this.localProvider.GetChangeSet(this.changeSetId);

                // Reporting progress after get changes from local store
                if (progress != null)
                {
                    progress.Report(new SyncProgressEvent(SyncStage.GetChanges, DateTime.Now.Subtract(durationStartDate), true, (changeSet != null ? changeSet.Data : null)));
                }


                // No data to upload. Skip upload phase.
                if (changeSet == null || changeSet.Data == null || changeSet.Data.Count == 0)
                {
                    return(statistics);
                }

                // Create a SyncRequest out of this.
                CacheRequest request = new CacheRequest
                {
                    RequestId     = this.changeSetId,
                    Format        = this.ControllerBehavior.SerializationFormat,
                    RequestType   = CacheRequestType.UploadChanges,
                    Changes       = changeSet.Data,
                    KnowledgeBlob = changeSet.ServerBlob,
                    IsLastBatch   = changeSet.IsLastBatch
                };


                // Upload changes to server
                durationStartDate = DateTime.Now;
                var requestResult = await this.cacheRequestHandler.ProcessCacheRequestAsync(
                    request, changeSet.IsLastBatch, cancellationToken);

                // Get response from server if mb any conflicts or updated items
                statistics = await this.ProcessCacheRequestResults(statistics, requestResult, cancellationToken);

                // Reporting progress after uploading changes, and mb get back Conflicts and new Id from insterted items
                if (progress != null)
                {
                    progress.Report(new SyncProgressEvent(SyncStage.UploadingChanges, DateTime.Now.Subtract(durationStartDate), true,
                                                          changeSet.Data, requestResult.ChangeSetResponse.Conflicts, requestResult.ChangeSetResponse.UpdatedItems));
                }
            }
            catch (OperationCanceledException)
            {
                // Re throw the operation cancelled
                throw;
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                {
                    throw;
                }

                statistics.Error = e;
            }


            return(statistics);
        }
        /// <summary>
        /// Method that refreshes the Cache by uploading all modified changes and then downloading the
        /// server changes.
        /// </summary>
        public void RefreshAsync()
        {
            if (this.IsBusy)
            {
                throw CacheControllerException.CreateCacheBusyException();
            }

            this.refreshStats = new CacheRefreshStatistics();

            this.StartAsyncWorkerManager();

            // Enqueue an async operation
            this._asyncWorkManager.AddWorkRequest(new AsyncWorkRequest(RefreshWorker, RefreshWorkerCompleted, null));
        }
예제 #10
0
        /// <summary>
        /// Method that refreshes the Cache by uploading all modified changes and then downloading the
        /// server changes.
        /// </summary>
        /// <returns>A CacheRefreshStatistics object denoting the statistics from the Refresh call</returns>
        public CacheRefreshStatistics Refresh()
        {
            this._controllerBehavior.Locked = true;
            try
            {
                // First create the CacheRequestHandler
                this._cacheRequestHandler = CacheRequestHandler.CreateRequestHandler(this._serviceUri, this._controllerBehavior);

                CacheRefreshStatistics refreshStats = new CacheRefreshStatistics();
                refreshStats.StartTime = DateTime.Now;

                bool uploadComplete   = false;
                bool downloadComplete = false;

                // Start sync by executin an Upload request
                while (!uploadComplete || !downloadComplete)
                {
                    if (!uploadComplete)
                    {
                        Guid changeSetId = Guid.NewGuid();

                        ChangeSet changeSet = this._localProvider.GetChangeSet(changeSetId);

                        if (changeSet.Data == null || changeSet.Data.Count == 0)
                        {
                            // No data to upload. Skip upload phase.
                            uploadComplete = true;
                        }
                        else
                        {
                            // Create a SyncRequest out of this.
                            CacheRequest request = new CacheRequest()
                            {
                                RequestId     = changeSetId,
                                RequestType   = CacheRequestType.UploadChanges,
                                Changes       = changeSet.Data,
                                KnowledgeBlob = changeSet.ServerBlob,
                                IsLastBatch   = changeSet.IsLastBatch
                            };

                            // Increment the stats
                            refreshStats.TotalChangeSetsUploaded++;

                            ChangeSetResponse response = (ChangeSetResponse)this._cacheRequestHandler.ProcessCacheRequest(request);

                            // Increment the stats
                            refreshStats.TotalUploads += (uint)request.Changes.Count;
                            response.ConflictsInternal.ForEach((e1) =>
                            {
                                if (e1 is SyncConflict)
                                {
                                    refreshStats.TotalSyncConflicts++;
                                }
                                else
                                {
                                    refreshStats.TotalSyncErrors++;
                                }
                            });

                            // Send the response to the local provider
                            this._localProvider.OnChangeSetUploaded(changeSetId, response);

                            uploadComplete = request.IsLastBatch;
                        }
                    }
                    else if (!downloadComplete)
                    {
                        // Create a SyncRequest for download.
                        CacheRequest request = new CacheRequest()
                        {
                            RequestType   = CacheRequestType.DownloadChanges,
                            KnowledgeBlob = this.LocalProvider.GetServerBlob()
                        };

                        ChangeSet changeSet = (ChangeSet)this._cacheRequestHandler.ProcessCacheRequest(request);

                        // Increment the refresh stats
                        refreshStats.TotalChangeSetsDownloaded++;
                        refreshStats.TotalDownloads += (uint)changeSet.Data.Count;

                        // Call the SaveChangeSet method on local provider.
                        this.LocalProvider.SaveChangeSet(changeSet);

                        downloadComplete = changeSet.IsLastBatch;
                    }
                }

                refreshStats.EndTime = DateTime.Now;
                // Finally return the statistics object
                return(refreshStats);
            }
            finally
            {
                // Unlock the ControllerBehavior object
                this._controllerBehavior.Locked = false;
            }
        }
예제 #11
0
        /// <summary>
        /// Method that synchronize the Cache by uploading all modified changes and then downloading the
        /// server changes.
        /// </summary>
        internal async Task<CacheRefreshStatistics> SynchronizeAsync(CancellationToken cancellationToken,
                                                                     IProgress<SyncProgressEvent> progress = null)
        {
            CacheRefreshStatistics statistics = new CacheRefreshStatistics();

            // Check if cancellation has occured
            if (cancellationToken.IsCancellationRequested)
                cancellationToken.ThrowIfCancellationRequested();

            // set start time
            statistics.StartTime = DateTime.Now;

            // Reporting progress 
            if (progress != null)
                progress.Report(new SyncProgressEvent(SyncStage.StartingSync, TimeSpan.Zero));

            try
            {
                
                // First create the CacheRequestHandler
                this.cacheRequestHandler = new HttpCacheRequestHandler(this.serviceUri, this.controllerBehavior);

                // Then fire the BeginSession call on the local provider.
                await this.localProvider.BeginSession();

                // Set the flag to indicate BeginSession was successful
                this.beginSessionComplete = true;

                // Check if cancellation has occured
                if (cancellationToken.IsCancellationRequested)
                    cancellationToken.ThrowIfCancellationRequested();

                // Do uploads first (no batch mode on Upload Request)
                statistics = await this.EnqueueUploadRequest(statistics, cancellationToken, progress);

                // Check if cancellation has occured
                if (cancellationToken.IsCancellationRequested)
                    cancellationToken.ThrowIfCancellationRequested();

                // then Download (be careful, could be in batch mode)
                statistics = await this.EnqueueDownloadRequest(statistics, cancellationToken, progress);

                // Set end time
                statistics.EndTime = DateTime.Now;

                // Call EndSession only if BeginSession was successful.
                if (this.beginSessionComplete)
                    this.localProvider.EndSession();


            }
            catch (OperationCanceledException ex)
            {
                statistics.EndTime = DateTime.Now;
                statistics.Cancelled = true;
                statistics.Error = ex;

                this.localProvider.EndSession();
            }
            catch (Exception ex)
            {
                statistics.EndTime = DateTime.Now;
                statistics.Error = ex;

                this.localProvider.EndSession();
            }
            finally
            {
                // Reset the state
                this.ResetAsyncWorkerManager();
            }

            // Reporting progress 
            if (progress != null)
                progress.Report(new SyncProgressEvent(SyncStage.EndingSync, statistics.EndTime.Subtract(statistics.StartTime)));

            return statistics;

        }
예제 #12
0
        /// <summary>
        /// Method that performs a download. It gets the server blob anchor from the local provider and then creates an 
        /// CacheRequest object for that download request. It then passes the processing asynchronously to the underlying
        /// CacheRequestHandler.
        /// </summary>
        private async Task<CacheRefreshStatistics> EnqueueDownloadRequest(CacheRefreshStatistics statistics,
                                                                          CancellationToken cancellationToken,
                                                                          IProgress<SyncProgressEvent> progress = null)
        {
            try
            {
                if (cancellationToken.IsCancellationRequested)
                    cancellationToken.ThrowIfCancellationRequested();

                Boolean isLastBatch = false;

                while (!isLastBatch)
                {
                    if (cancellationToken.IsCancellationRequested)
                        cancellationToken.ThrowIfCancellationRequested();

                    // Create a SyncRequest for download.
                    CacheRequest request = new CacheRequest
                    {
                        Format = this.ControllerBehavior.SerializationFormat,
                        RequestType = CacheRequestType.DownloadChanges,
                        KnowledgeBlob = this.localProvider.GetServerBlob()
                    };

                    // Get Changes
                    DateTime durationStartDate = DateTime.Now;
                    var args = await this.cacheRequestHandler.ProcessCacheRequestAsync(request, null, cancellationToken);

                    statistics = await this.ProcessCacheRequestResults(statistics, args, cancellationToken);

                    // Check if we are at the end 
                    if (args.ChangeSet == null || args.ChangeSet.IsLastBatch)
                        isLastBatch = true;

                    // Reporting progress after get changes from local store
                    if (progress != null)
                        progress.Report(new SyncProgressEvent(SyncStage.DownloadingChanges, DateTime.Now.Subtract(durationStartDate), true, (args.ChangeSet != null ? args.ChangeSet.Data : null)));
                }
            }
            catch (OperationCanceledException)
            {
                // Re throw the operation cancelled
                throw;
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                    throw;

                statistics.Error = e;
            }

            return statistics;
        }
예제 #13
0
        /// <summary>
        /// Method that performs an upload. It gets the ChangeSet from the local provider and then creates an
        /// CacheRequest object for that ChangeSet and then passed the processing asynchronously to the underlying
        /// CacheRequestHandler.
        /// </summary>
        private async Task<CacheRefreshStatistics> EnqueueUploadRequest(CacheRefreshStatistics statistics,
                                                                        CancellationToken cancellationToken,
                                                                        IProgress<SyncProgressEvent> progress = null)
        {
            this.changeSetId = Guid.NewGuid();

            try
            {
                // Check if cancellation has occured
                if (cancellationToken.IsCancellationRequested)
                    cancellationToken.ThrowIfCancellationRequested();

                // Get Changes
                DateTime durationStartDate = DateTime.Now;
                ChangeSet changeSet = await this.localProvider.GetChangeSet(this.changeSetId);

                // Reporting progress after get changes from local store
                if (progress != null)
                    progress.Report(new SyncProgressEvent(SyncStage.GetChanges, DateTime.Now.Subtract(durationStartDate), true, (changeSet != null ? changeSet.Data : null)));


                // No data to upload. Skip upload phase.
                if (changeSet == null || changeSet.Data == null || changeSet.Data.Count == 0)
                    return statistics;

                // Create a SyncRequest out of this.
                CacheRequest request = new CacheRequest
                {
                    RequestId = this.changeSetId,
                    Format = this.ControllerBehavior.SerializationFormat,
                    RequestType = CacheRequestType.UploadChanges,
                    Changes = changeSet.Data,
                    KnowledgeBlob = changeSet.ServerBlob,
                    IsLastBatch = changeSet.IsLastBatch
                };


                // Upload changes to server
                durationStartDate = DateTime.Now;
                var args = await this.cacheRequestHandler.ProcessCacheRequestAsync(request, changeSet.IsLastBatch, cancellationToken);

                // Get response from server if mb any conflicts or updated items
                statistics = await this.ProcessCacheRequestResults(statistics, args, cancellationToken);

                // Reporting progress after uploading changes, and mb get back Conflicts and new Id from insterted items
                if (progress != null)
                    progress.Report(new SyncProgressEvent(SyncStage.UploadingChanges, DateTime.Now.Subtract(durationStartDate), true,
                                                            changeSet.Data, args.ChangeSetResponse.Conflicts, args.ChangeSetResponse.UpdatedItems));

            }
            catch (OperationCanceledException)
            {
                // Re throw the operation cancelled
                throw;
            }
            catch (Exception e)
            {
                if (ExceptionUtility.IsFatal(e))
                    throw;

                statistics.Error = e;
            }


            return statistics;
        }
예제 #14
0
        /// <summary>
        /// Method that synchronize the Cache by uploading all modified changes and then downloading the
        /// server changes.
        /// </summary>
        internal async Task<CacheRefreshStatistics> SynchronizeAsync(CancellationToken cancellationToken,
                                                                     IProgress<SyncProgressEvent> progress = null)
        {
            CacheRefreshStatistics statistics = new CacheRefreshStatistics();

            // Check if cancellation has occured
            if (cancellationToken.IsCancellationRequested)
                cancellationToken.ThrowIfCancellationRequested();

            // set start time
            statistics.StartTime = DateTime.Now;

            // Reporting progress 
            if (progress != null)
                progress.Report(new SyncProgressEvent(SyncStage.StartingSync, TimeSpan.Zero));

            try
            {

                // First create the CacheRequestHandler
                this.cacheRequestHandler = new HttpCacheRequestHandler(this.serviceUri, this.controllerBehavior);

                // Then fire the BeginSession call on the local provider.
                await this.localProvider.BeginSession();

                // Set the flag to indicate BeginSession was successful
                this.beginSessionComplete = true;

                // Check if cancellation has occured
                if (cancellationToken.IsCancellationRequested)
                    cancellationToken.ThrowIfCancellationRequested();

                // Do uploads first (no batch mode on Upload Request)
                statistics = await this.EnqueueUploadRequest(statistics, cancellationToken, progress);

                // If there is an error during Upload request, dont want to donwload
                if (statistics.Error != null)
                    throw new Exception("Error occured during Upload request.", statistics.Error);

                // Check if cancellation has occured
                if (cancellationToken.IsCancellationRequested)
                    cancellationToken.ThrowIfCancellationRequested();

                // When there are records records that are not uploading successfully
                // a successfull download 1-N records will cause anchor to be updated.
                // if anchor is updated then the records on the device will not be attempted for upload again
                // on subsequent syncs. therefore check for null Error
                if (statistics.Error == null)
                {
                    // then Download (be careful, could be in batch mode)
                    statistics = await this.EnqueueDownloadRequest(statistics, cancellationToken, progress);
                }

                // Set end time
                statistics.EndTime = DateTime.Now;

                // Call EndSession only if BeginSession was successful.
                if (this.beginSessionComplete)
                    this.localProvider.EndSession();


            }
            catch (OperationCanceledException ex)
            {
                statistics.EndTime = DateTime.Now;
                statistics.Cancelled = true;
                statistics.Error = ex;

                if (this.beginSessionComplete)
                    this.localProvider.EndSession();
            }
            catch (Exception ex)
            {
                statistics.EndTime = DateTime.Now;
                statistics.Error = ex;

                if (this.beginSessionComplete)
                    this.localProvider.EndSession();
            }
            finally
            {
                // Reset the state
                this.ResetAsyncWorkerManager();
            }

            // Reporting progress 
            if (progress != null)
                progress.Report(new SyncProgressEvent(SyncStage.EndingSync, statistics.EndTime.Subtract(statistics.StartTime)));

            return statistics;

        }
예제 #15
0
        /// <summary>
        /// Called whenever the CacheRequestHandler proceeses an upload/download request. It is also responsible for
        /// issuing another request if it wasnt the last batch. In case of receiving an Upload response it calls the
        /// underlying provider with the status of the upload. In case of Download it notifies the local provider of the
        /// changes that it needs to save.
        /// </summary>
        private async Task <CacheRefreshStatistics> ProcessCacheRequestResults(CacheRefreshStatistics statistics, CacheRequestResult e, CancellationToken cancellationToken)
        {
            try
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                }

                if (e.Error != null)
                {
                    // Check to see if it was a UploadRequest in which case we will have to call OnChangeSetUploaded
                    // with error to reset the dirty bits.
                    if (e.ChangeSetResponse != null)
                    {
                        // its an response to a upload
                        this.localProvider.OnChangeSetUploaded(e.Id, e.ChangeSetResponse);
                    }

                    // Finally complete Refresh with error.
                    statistics.Error = e.Error;
                }
                else if (e.ChangeSetResponse != null)
                {
                    // its an response to a upload
                    this.localProvider.OnChangeSetUploaded(e.Id, e.ChangeSetResponse);

                    if (e.ChangeSetResponse.Error != null)
                    {
                        statistics.Error = e.ChangeSetResponse.Error;
                        return(statistics);
                    }

                    // Increment the ChangeSets uploaded count
                    statistics.TotalChangeSetsUploaded++;
                    statistics.TotalUploads += e.BatchUploadCount;

                    // Update refresh stats
                    foreach (var e1 in e.ChangeSetResponse.ConflictsInternal)
                    {
                        if (e1 is SyncConflict)
                        {
                            statistics.TotalSyncConflicts++;
                        }
                        else
                        {
                            statistics.TotalSyncErrors++;
                        }
                    }

                    // Dont enqueue another request if its been cancelled
                    if (!cancellationToken.IsCancellationRequested)
                    {
                        if (!((bool)e.State))
                        {
                            // Check to see if this was the last batch or else enqueue another pending Upload request
                            statistics = await this.EnqueueUploadRequest(statistics, cancellationToken);
                        }
                        else
                        {
                            // That was the last batch. Issue an Download request
                            statistics = await this.EnqueueDownloadRequest(statistics, cancellationToken);
                        }
                    }
                    else
                    {
                        cancellationToken.ThrowIfCancellationRequested();
                    }
                }
                else // It means its an Download response
                {
                    Debug.Assert(e.ChangeSet != null, "Completion is not for a download request.");

                    // Increment the refresh stats
                    if (e.ChangeSet != null)
                    {
                        statistics.TotalChangeSetsDownloaded++;
                        statistics.TotalDownloads += (uint)e.ChangeSet.Data.Count;

                        await this.localProvider.SaveChangeSet(e.ChangeSet);

                        // Dont enqueue another request if its been cancelled
                        if (!cancellationToken.IsCancellationRequested)
                        {
                            if (!e.ChangeSet.IsLastBatch)
                            {
                                // Enqueue the next download
                                statistics = await this.EnqueueDownloadRequest(statistics, cancellationToken);
                            }
                        }
                        else
                        {
                            cancellationToken.ThrowIfCancellationRequested();
                        }
                    }
                }
            }
            catch (OperationCanceledException)
            {
                // Re throw the operation cancelled
                throw;
            }
            catch (Exception exp)
            {
                if (ExceptionUtility.IsFatal(exp))
                {
                    throw;
                }
                statistics.Error = exp;
            }

            return(statistics);
        }
예제 #16
0
        /// <summary>
        /// Called whenever the CacheRequestHandler proceeses an upload/download request. It is also responsible for
        /// issuing another request if it wasnt the last batch. In case of receiving an Upload response it calls the
        /// underlying provider with the status of the upload. In case of Download it notifies the local provider of the
        /// changes that it needs to save.
        /// </summary>
        private async Task <CacheRefreshStatistics> ProcessCacheRequestResults(
            CacheRefreshStatistics statistics, CacheRequestResult cacheRequestResult, CancellationToken cancellationToken)
        {
            try
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                }

                #region Error
                if (cacheRequestResult.Error != null)
                {
                    // We have an error but we have a ChangeSetResponse with reading the upload respose
                    // So we can serialize results and update dirty bits
                    if (cacheRequestResult.ChangeSetResponse != null &&
                        cacheRequestResult.HttpStep == HttpState.End)
                    {
                        await this.localProvider.OnChangeSetUploaded(cacheRequestResult.Id, cacheRequestResult.ChangeSetResponse);
                    }

                    // Finally complete Refresh with error.
                    statistics.Error = cacheRequestResult.Error;

                    return(statistics);
                }
                #endregion

                #region Upload response

                if (cacheRequestResult.ChangeSetResponse != null)
                {
                    if (cacheRequestResult.ChangeSetResponse.Error == null &&
                        cacheRequestResult.HttpStep == HttpState.End)
                    {
                        await this.localProvider.OnChangeSetUploaded(cacheRequestResult.Id, cacheRequestResult.ChangeSetResponse);
                    }

                    if (cacheRequestResult.ChangeSetResponse.Error != null)
                    {
                        statistics.Error = cacheRequestResult.ChangeSetResponse.Error;
                        return(statistics);
                    }

                    // Increment the ChangeSets uploaded count
                    statistics.TotalChangeSetsUploaded++;
                    statistics.TotalUploads += cacheRequestResult.BatchUploadCount;

                    // Update refresh stats
                    foreach (var e1 in cacheRequestResult.ChangeSetResponse.ConflictsInternal)
                    {
                        if (e1 is SyncConflict)
                        {
                            statistics.TotalSyncConflicts++;
                        }
                        else
                        {
                            statistics.TotalSyncErrors++;
                        }
                    }

                    return(statistics);
                }
                #endregion

                #region Download Response

                // it's a response to download
                Debug.Assert(cacheRequestResult.ChangeSet != null, "Completion is not for a download request.");

                // Increment the refresh stats
                if (cacheRequestResult.ChangeSet != null && cacheRequestResult.ChangeSet.Data != null && cacheRequestResult.ChangeSet.Data.Count > 0)
                {
                    statistics.TotalChangeSetsDownloaded++;
                    statistics.TotalDownloads += (uint)cacheRequestResult.ChangeSet.Data.Count;

                    await this.localProvider.SaveChangeSet(cacheRequestResult.ChangeSet);
                }

                return(statistics);

                #endregion
            }

            catch (OperationCanceledException)
            {
                // Re throw the operation cancelled
                throw;
            }
            catch (Exception exp)
            {
                if (ExceptionUtility.IsFatal(exp))
                {
                    throw;
                }
                statistics.Error = exp;
            }

            return(statistics);
        }
예제 #17
0
        /// <summary>
        /// Method that synchronize the Cache by uploading all modified changes and then downloading the
        /// server changes.
        /// </summary>
        internal async Task <CacheRefreshStatistics> SynchronizeAsync(CancellationToken cancellationToken,
                                                                      IProgress <SyncProgressEvent> progress = null)
        {
            CacheRefreshStatistics statistics = new CacheRefreshStatistics();

            // Check if cancellation has occured
            if (cancellationToken.IsCancellationRequested)
            {
                cancellationToken.ThrowIfCancellationRequested();
            }

            // set start time
            statistics.StartTime = DateTime.Now;

            // Reporting progress
            if (progress != null)
            {
                progress.Report(new SyncProgressEvent(SyncStage.StartingSync, TimeSpan.Zero));
            }

            try
            {
                // First create the CacheRequestHandler
                this.cacheRequestHandler = new HttpCacheRequestHandler(this.serviceUri, this.controllerBehavior);

                // Then fire the BeginSession call on the local provider.
                await this.localProvider.BeginSession();

                // Set the flag to indicate BeginSession was successful
                this.beginSessionComplete = true;

                // Check if cancellation has occured
                if (cancellationToken.IsCancellationRequested)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                }

                // Do uploads first (no batch mode on Upload Request)
                statistics = await this.EnqueueUploadRequest(statistics, cancellationToken, progress);

                // If there is an error during Upload request, dont want to donwload
                if (statistics.Error != null)
                {
                    throw new Exception("Error occured during Upload request.", statistics.Error);
                }

                // Check if cancellation has occured
                if (cancellationToken.IsCancellationRequested)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                }

                // When there are records records that are not uploading successfully
                // a successfull download 1-N records will cause anchor to be updated.
                // if anchor is updated then the records on the device will not be attempted for upload again
                // on subsequent syncs. therefore check for null Error
                if (statistics.Error == null)
                {
                    // then Download (be careful, could be in batch mode)
                    statistics = await this.EnqueueDownloadRequest(statistics, cancellationToken, progress);
                }

                // Set end time
                statistics.EndTime = DateTime.Now;

                // Call EndSession only if BeginSession was successful.
                if (this.beginSessionComplete)
                {
                    this.localProvider.EndSession();
                }
            }
            catch (OperationCanceledException ex)
            {
                statistics.EndTime   = DateTime.Now;
                statistics.Cancelled = true;
                statistics.Error     = ex;

                if (this.beginSessionComplete)
                {
                    this.localProvider.EndSession();
                }
            }
            catch (Exception ex)
            {
                statistics.EndTime = DateTime.Now;
                statistics.Error   = ex;

                if (this.beginSessionComplete)
                {
                    this.localProvider.EndSession();
                }
            }
            finally
            {
                // Reset the state
                this.ResetAsyncWorkerManager();
            }

            // Reporting progress
            if (progress != null)
            {
                progress.Report(new SyncProgressEvent(SyncStage.EndingSync, statistics.EndTime.Subtract(statistics.StartTime)));
            }

            return(statistics);
        }
예제 #18
0
        /// <summary>
        /// Called whenever the CacheRequestHandler proceeses an upload/download request. It is also responsible for
        /// issuing another request if it wasnt the last batch. In case of receiving an Upload response it calls the
        /// underlying provider with the status of the upload. In case of Download it notifies the local provider of the
        /// changes that it needs to save.
        /// </summary>
        private async Task<CacheRefreshStatistics> ProcessCacheRequestResults(CacheRefreshStatistics statistics, CacheRequestResult cacheRequestResult, CancellationToken cancellationToken)
        {
            try
            {
                if (cancellationToken.IsCancellationRequested)
                    cancellationToken.ThrowIfCancellationRequested();

                #region Error
                if (cacheRequestResult.Error != null)
                {
                    // Check to see if it was a UploadRequest in which case we will have to call OnChangeSetUploaded
                    // with error to reset the dirty bits.
                    if (cacheRequestResult.ChangeSetResponse != null)
                    {
                        // its an response to a upload
                        await this.localProvider.OnChangeSetUploaded(cacheRequestResult.Id, cacheRequestResult.ChangeSetResponse);
                    }

                    // Finally complete Refresh with error.
                    statistics.Error = cacheRequestResult.Error;

                    return statistics;
                }
                #endregion

                #region Upload response

                if (cacheRequestResult.ChangeSetResponse != null)
                {
                    // its an response to a upload
                    await this.localProvider.OnChangeSetUploaded(cacheRequestResult.Id, cacheRequestResult.ChangeSetResponse);

                    if (cacheRequestResult.ChangeSetResponse.Error != null)
                    {
                        statistics.Error = cacheRequestResult.ChangeSetResponse.Error;
                        return statistics;
                    }

                    // Increment the ChangeSets uploaded count
                    statistics.TotalChangeSetsUploaded++;
                    statistics.TotalUploads += cacheRequestResult.BatchUploadCount;

                    // Update refresh stats
                    foreach (var e1 in cacheRequestResult.ChangeSetResponse.ConflictsInternal)
                    {
                        if (e1 is SyncConflict)
                        {
                            statistics.TotalSyncConflicts++;
                        }
                        else
                        {
                            statistics.TotalSyncErrors++;
                        }
                    }

                    return statistics;

                }
                #endregion

                #region Download Response

                // it's a response to download
                Debug.Assert(cacheRequestResult.ChangeSet != null, "Completion is not for a download request.");

                // Increment the refresh stats
                if (cacheRequestResult.ChangeSet != null && cacheRequestResult.ChangeSet.Data != null && cacheRequestResult.ChangeSet.Data.Count > 0)
                {
                    statistics.TotalChangeSetsDownloaded++;
                    statistics.TotalDownloads += (uint)cacheRequestResult.ChangeSet.Data.Count;

                    await this.localProvider.SaveChangeSet(cacheRequestResult.ChangeSet);
                }

                return statistics;
                #endregion

            }

            catch (OperationCanceledException)
            {
                // Re throw the operation cancelled
                throw;
            }
            catch (Exception exp)
            {
                if (ExceptionUtility.IsFatal(exp))
                    throw;
                statistics.Error = exp;
            }

            return statistics;
        }