public string GetDbState()
        {
            JObject state     = new JObject();
            var     knowledge = GenerateLocalKnowledge().OrderBy((ri) => { return(ri.ReplicaId + ri.ReplicaTickCount.ToString()); });

            state.Add("knowledge", SyncUtil.KnowledgeToJson(knowledge));
            foreach (var itemType in GetItemTypes())
            {
                var        handler       = HandlerForItemType(itemType);
                JArray     items         = new JArray();
                IDbCommand selectCommand = _connection.CreateCommand();
                selectCommand.CommandText = String.Format("SELECT CreatedReplica, CreatedTickCount, ModifiedReplica, ModifiedTickCount FROM {0}", handler.DbTable);
                IList <ISyncableItemInfo> itemInfos = new List <ISyncableItemInfo>();
                using (IDataReader reader = selectCommand.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        IReplicaInfo createdReplicaInfo  = ReplicaInfoFromDataReader(reader, "Created");
                        IReplicaInfo modifiedReplicaInfo = ReplicaInfoFromDataReader(reader, "Modified");

                        itemInfos.Add(new SyncableItemInfo {
                            ItemType = handler.TypeName, Created = createdReplicaInfo, Modified = modifiedReplicaInfo, Deleted = false
                        });
                    }
                }


                var sortedItemInfos = itemInfos.OrderBy((ii) => { return(ii.Created.ReplicaId + ii.Created.ReplicaTickCount.ToString()); });
                foreach (var syncItemInfo in sortedItemInfos)
                {
                    JObject builder = SyncUtil.JsonItemFromSyncableItemInfo(syncItemInfo);
                    BuildItemData(syncItemInfo, builder);
                    items.Add(builder);
                }
                state.Add(itemType, items);
            }
            return(state.ToString());
        }
Ejemplo n.º 2
0
        private async Task PushChanges()
        {
            ReportProgressAndCheckCacellation(new SyncProgress
            {
                Stage           = SyncStage.FindingLocalChanges,
                PercentComplete = 0,
                Message         = "Finding local changes"
            });

            var request = new JObject {
                { "sessionID", _remoteSessionId }
            };

            var localKnowledge   = _store.GenerateLocalKnowledge();
            var changedItemInfos = _store.LocateChangedItems(_remoteKnowledge).ToList();

            int totalChanges = changedItemInfos.Count();

            request.Add(new JProperty("knowledge", SyncUtil.KnowledgeToJson(localKnowledge)));
            request.Add(new JProperty("changeCount", totalChanges));

            await _transport.TransportAsync(SyncEndpoint.PutChanges, request);

            ReportProgressAndCheckCacellation(new SyncProgress
            {
                Stage           = SyncStage.FindingLocalChanges,
                PercentComplete = 100,
                Message         = String.Format("Found {0} local changes", totalChanges)
            });

            ReportProgressAndCheckCacellation(new SyncProgress
            {
                Stage           = SyncStage.UploadingLocalChanges,
                PercentComplete = 0,
                Message         = String.Format("Uploading {0} local changes", totalChanges)
            });

            int  maxBatchCount           = PushMaxBatchCount;
            int  maxBatchSize            = PushMaxBatchSize;
            long startTick               = Environment.TickCount;
            int  previousPercentComplete = -1;
            int  i          = 0;
            var  batchArray = new JArray();
            int  batchSize  = 0;

            foreach (ISyncableItemInfo syncItemInfo in changedItemInfos)
            {
                i++;
                int percentComplete = ((i * 100) / totalChanges);
                if (percentComplete != previousPercentComplete)
                {
                    ReportProgressAndCheckCacellation(new SyncProgress
                    {
                        Stage           = SyncStage.UploadingLocalChanges,
                        PercentComplete = 100,
                        Message         =
                            String.Format("Uploading local changes, {0}% complete ({1})", percentComplete,
                                          String.Format("Averaging {0}ms/item over {1} items",
                                                        (Environment.TickCount - startTick) / i, i))
                    });
                }
                previousPercentComplete = percentComplete;

                var builder = SyncUtil.JsonItemFromSyncableItemInfo(syncItemInfo);
                if (!syncItemInfo.Deleted)
                {
                    _store.BuildItemData(syncItemInfo, builder);
                }

                var singleItemRequest = new JObject {
                    { "changeNumber", i }, { "item", builder }
                };

                batchSize += singleItemRequest.ToString().Length;
                batchArray.Add(singleItemRequest);

                if (i == totalChanges || (i % maxBatchCount) == 0 || batchSize >= maxBatchSize)
                {
                    var batchRequest = new JObject {
                        { "sessionID", _remoteSessionId }, { "batch", batchArray }
                    };
                    await _transport.TransportAsync(SyncEndpoint.PutItemDataBatch, batchRequest);

                    batchArray = new JArray();
                    batchSize  = 0;
                }
            }
            ReportProgressAndCheckCacellation(new SyncProgress
            {
                Stage           = SyncStage.UploadingLocalChanges,
                PercentComplete = 100,
                Message         = String.Format("Uploaded {0} local changes", totalChanges)
            });

            await ApplyChanges(totalChanges);
        }
Ejemplo n.º 3
0
        private async Task <IEnumerable <SyncConflict> > PullChanges()
        {
            ReportProgressAndCheckCacellation(new SyncProgress
            {
                Stage           = SyncStage.FindingRemoteChanges,
                PercentComplete = 0,
                Message         = "Looking for remote changes"
            });

            var request = new JObject {
                { "sessionID", _remoteSessionId }
            };

            var localKnowledge = _store.GenerateLocalKnowledge().ToList();

            request.Add(new JProperty("knowledge", SyncUtil.KnowledgeToJson(localKnowledge)));

            JObject response = await _transport.TransportAsync(SyncEndpoint.GetChanges, request);

            _remoteKnowledge = SyncUtil.KnowledgeFromJson(response["knowledge"]);
            var totalChanges = (int)response["totalChanges"];

            ReportProgressAndCheckCacellation(new SyncProgress
            {
                Stage           = SyncStage.FindingRemoteChanges,
                PercentComplete = 100,
                Message         = String.Format("Found {0} remote changes", totalChanges)
            });

            ReportProgressAndCheckCacellation(new SyncProgress
            {
                Stage           = SyncStage.DownloadingRemoteChanges,
                PercentComplete = 0,
                Message         = String.Format("Downloading {0} remote changes", totalChanges)
            });
            using (var connection = _syncSessionDbConnectionProvider.GetSyncSessionDbConnection(_localSessionId))
            {
                connection.ExecuteNonQuery("BEGIN");
                SessionDbHelper.ClearSyncItems(connection);

                long startTick = Environment.TickCount;
                int  previousPercentComplete = -1;
                for (int i = 1; i <= totalChanges;)
                {
                    i += await SaveChangesBatch(connection, localKnowledge, i);

                    int percentComplete = ((i * 100) / totalChanges);
                    if (percentComplete != previousPercentComplete)
                    {
                        ReportProgressAndCheckCacellation(new SyncProgress
                        {
                            Stage           = SyncStage.DownloadingRemoteChanges,
                            PercentComplete = percentComplete,
                            Message         =
                                String.Format("Downloading remote changes, {0}% complete ({1})", percentComplete,
                                              String.Format("Averaging {0}ms/item over {1} items",
                                                            (Environment.TickCount - startTick) / i, i))
                        });
                    }
                    previousPercentComplete = percentComplete;
                }
                connection.ExecuteNonQuery("COMMIT");
                ReportProgressAndCheckCacellation(new SyncProgress
                {
                    Stage           = SyncStage.DownloadingRemoteChanges,
                    PercentComplete = 100,
                    Message         = String.Format("Downloaded all {0} remote changes", totalChanges)
                });

                ReportProgressAndCheckCacellation(new SyncProgress
                {
                    Stage           = SyncStage.CheckingForConflicts,
                    PercentComplete = 0,
                    Message         = "Looking for conflicts"
                });
                var conflicts = new List <SyncConflict>();
                conflicts.AddRange(CheckForDuplicates(connection));
                conflicts.AddRange(LoadConflicts(connection));
                ReportProgressAndCheckCacellation(new SyncProgress
                {
                    Stage           = SyncStage.CheckingForConflicts,
                    PercentComplete = 100,
                    Message         = String.Format("Found {0} conflicts", conflicts.Count)
                });
                return(conflicts);
            }
        }