/// <summary> /// Apply changes sent by a client to the server. /// </summary> /// <param name="serverBlob">Blob sent in the incoming request</param> /// <param name="entities">Changes from the client</param> /// <returns>Response containing the new knowledge and conflict/error information.</returns> public ApplyChangesResponse ApplyChanges(byte[] serverBlob, List<IOfflineEntity> entities) { WebUtil.CheckArgumentNull(serverBlob, "serverBlob"); WebUtil.CheckArgumentNull(entities, "entities"); if (0 == serverBlob.Length) { throw new InvalidOperationException("serverBlob is empty"); } var syncBlob = new SyncBlob(); SyncBlob incomingBlob = SyncBlob.DeSerialize(serverBlob); PopulateClientScopeNameAndSyncId(incomingBlob); // Set the scope name in the response blob. syncBlob.ClientScopeName = incomingBlob.ClientScopeName; // If the requested scope does not exists, then throw an error since we // don't initialize scopes on upload requests. if (!CheckIfScopeExists()) { throw SyncServiceException.CreateResourceNotFound("Scope does not exist"); } byte[] clientKnowledgeBlob = incomingBlob.ClientKnowledge; // Initialize a SqlSyncProvider object. _sqlSyncProvider = CreateSqlSyncProviderInstance(_clientScopeName, _serverConnectionString, _configuration.SyncObjectSchema); var response = new ApplyChangesResponse(); // Deserialize the knowledge or create new empty knowledge. SyncKnowledge clientKnowledge = GetSyncKnowledgeFromBlob(clientKnowledgeBlob); // If there are no entities to upload, then return the client knowledge as is. if (entities.Count == 0) { response.Conflicts = new List<SyncConflict>(); response.Errors = new List<SyncError>(); syncBlob.ClientKnowledge = clientKnowledge.Serialize(); response.ServerBlob = syncBlob.Serialize(); return response; } // Client never has any forgotten knowledge. So create a new one. var forgottenKnowledge = new ForgottenKnowledge(_sqlSyncProvider.IdFormats, clientKnowledge); // Convert the entities to dataset using the custom converter. DataSet changesDS = _converter.ConvertEntitiesToDataSet(entities); var stats = new SyncSessionStatistics(); var sessionContext = new SyncSessionContext(_sqlSyncProvider.IdFormats, new SyncCallbacks()); _sqlSyncProvider.BeginSession(SyncProviderPosition.Remote, sessionContext); ulong tickCount = 0; SyncKnowledge updatedClientKnowldege; try { uint batchSize; SyncKnowledge serverKnowledge; // This gives us the server knowledge. _sqlSyncProvider.GetSyncBatchParameters(out batchSize, out serverKnowledge); var changeBatch = new ChangeBatch(_sqlSyncProvider.IdFormats, clientKnowledge, forgottenKnowledge); changeBatch.SetLastBatch(); //Note: There is a possiblity of (-ve) item exceptions , between two uploads from the // same client (for example: in case of RI failures). This would result in an incorrect value if the function // FindMinTickCountForReplica is used to get the last tickcount. So, we need to ignore the -ve item exceptions // when finding the tickcount for the client replica from the server knowledge. /* Logic: * SyncKnowledge.GetKnowledgeForItemId could be used for itemid Zero and then we can find the mintickcount for client replica id. * This does not however seem to work, so we use the KnowledgeInspector and enumerate over each ClockVector * and find the client clockvector and get its tickcount. * * Assumption: The above approach assumes that we don't have any positive exceptions in the knowledge. */ try { // Check if the client replica key exists. uint clientReplicaKey = serverKnowledge.ReplicaKeyMap.LookupReplicaKey(_clientSyncId); var ki = new KnowledgeInspector(1, serverKnowledge); var clockVector = (ClockVector)ki.ScopeClockVector; int noOfReplicaKeys = clockVector.Count; for (int i = noOfReplicaKeys - 1; i >= 0; i--) { if (clockVector[i].ReplicaKey == clientReplicaKey) { tickCount = clockVector[i].TickCount; break; } } } catch (ReplicaNotFoundException exception) { SyncTracer.Info("ReplicaNotFoundException. NEW CLIENT. Exception details: {0}", WebUtil.GetExceptionMessage(exception)); // If the knowedge does not contain the client replica (first apply), initialize tickcount to zero. tickCount = 0; } // Increment the tickcount tickCount++; // update the made with knowledge to include the new tickcount. updatedClientKnowldege = new SyncKnowledge(_sqlSyncProvider.IdFormats, _clientSyncId, tickCount); updatedClientKnowldege.Combine(clientKnowledge); // The incoming data does not have metadata for each item, so we need to create it at this point. AddSyncColumnsToDataSet(changesDS, tickCount); // Make DbSyncContext var dbSyncContext = new DbSyncContext { IsDataBatched = false, IsLastBatch = true, DataSet = changesDS, MadeWithKnowledge = updatedClientKnowldege, MadeWithForgottenKnowledge = forgottenKnowledge, ScopeProgress = new DbSyncScopeProgress() }; _conflicts = new List<SyncConflict>(); _syncErrors = new List<SyncError>(); // Subscribe to the ApplyChangeFailed event to handle conflicts. _sqlSyncProvider.ApplyChangeFailed += SqlSyncProviderApplyChangeFailed; // Subscribe to the ChangesApplied event to read the server tickcount incase there are any conflicts. _sqlSyncProvider.ChangesApplied += SqlSyncProviderChangesApplied; //NOTE: The ConflictResolutionPolicy pass into the method is IGNORED. // Conflicts can be logged by subscribing to the failed events _sqlSyncProvider.ProcessChangeBatch(Microsoft.Synchronization.ConflictResolutionPolicy.DestinationWins, changeBatch, dbSyncContext, new SyncCallbacks(), stats); if (0 != _conflicts.Count) { _sqlSyncProvider.GetSyncBatchParameters(out batchSize, out serverKnowledge); // The way the current P2P provider works, versions are bumped up when conflicts are resolved on the server. // This would result in us sending the changes to the client on the next download request. We want // to not enumerate that change again on the next request from the same client. // The solution is to get the server knowledge after all changes are applied and then // project the knowledge of each conflictign item and add it as a positive exception to the updated client knowledge. AddConflictItemsKnowledgeToClientKnowledge(updatedClientKnowldege, serverKnowledge); } } finally { _sqlSyncProvider.EndSession(sessionContext); } // Don't send any updates to the server knowledge since the client has not got any updates yet. // This updated knowledge will only include an update to the client tickcount. // The client would obtain the server knowledge when it does a get changes. // If we include the serverknowlege, the client would never get any items that are // between the current server knowledge and the client known server knowledge. syncBlob.ClientKnowledge = updatedClientKnowldege.Serialize(); response.ServerBlob = syncBlob.Serialize(); response.Conflicts = _conflicts; response.Errors = _syncErrors; return response; }
public override void EndSession( SyncSessionContext syncSessionContext) { this.syncSessionContext = null; this.client.EndSession(); this.client = null; }
public void EndSession(byte[] changeApplierInfo) { SyncSessionContext sessionContext = SessionContext; sessionContext.ChangeApplierInfo = changeApplierInfo; Provider.EndSession(sessionContext); }
public void BeginSession(Microsoft.Synchronization.SyncProviderPosition position, byte[] changeApplierInfo) { SyncSessionContext sessionContext = SessionContext; sessionContext.ChangeApplierInfo = changeApplierInfo; Provider.BeginSession(position, sessionContext); }
public override void BeginSession(SyncProviderPosition position, SyncSessionContext syncSessionContext) { lock (_lock) { _syncPool.Add(ReplicaId); } base.BeginSession(position, syncSessionContext); }
public override void EndSession(SyncSessionContext syncSessionContext) { lock (_lock) { _syncPool.Remove(ReplicaId); } base.EndSession(syncSessionContext); }
/// <summary> /// When overridden in a derived class, notifies the provider that it is joining a synchronization session. /// </summary> /// <param name="position">The position of this provider, relative to the other provider in the session.</param> /// <param name="syncSessionContext">The current status of the corresponding session.</param> public override void BeginSession(SyncProviderPosition position, SyncSessionContext syncSessionContext) { if (_syncService == null) { throw new Exception("Not initalized"); } _syncSessionContext = syncSessionContext; _syncService.BeginSession(); }
public override void BeginSession(SyncProviderPosition position, SyncSessionContext syncSessionContext) { try { this.proxy.BeginSession(position); } catch (Exception) { } }
/// <inheritdoc /> public override void EndSession(SyncSessionContext syncSessionContext) { if (syncSessionContext.IsCanceled()) { m_session.Abort(); } else { m_session.Commit(); } }
//BeginSession is called at the beginning of each sync operation. Do initialization here. For example update //metadata if it was not updated as the actual data was changed. public override void BeginSession(SyncProviderPosition position, SyncSessionContext syncSessionContext) { Thread.Sleep(1000); InitializeMetadataStore(); //Make sure the metadata store is updated to reflect the state of the data before each sync operation. _metadataStore.BeginTransaction(); UpdateMetadataStoreWithLocalChanges(); _metadataStore.CommitTransaction(); _currentSessionContext = syncSessionContext; }
public override void EndSession(SyncSessionContext syncSessionContext) { Proxy.EndSession(); if (LocalBatchingDirectory != null) { LocalBatchingDirectory.Refresh(); if (LocalBatchingDirectory.Exists) { LocalBatchingDirectory.Delete(true); } } }
public override void EndSession(SyncSessionContext syncSessionContext) { proxy.EndSession(); if (this.localBatchingDirectory != null) { this.localBatchingDirectory.Refresh(); if (this.localBatchingDirectory.Exists) { //Cleanup batching releated files from this session this.localBatchingDirectory.Delete(true); } } }
/// <inheritdoc /> public override void BeginSession(SyncProviderPosition position, SyncSessionContext syncSessionContext) { if (!syncSessionContext.IsCanceled()) { if (position == SyncProviderPosition.Local) { m_session.BeginUpdate(); } else { m_session.BeginRead(); } } }
public override void BeginSession(SyncProviderPosition position, SyncSessionContext syncSessionContext) { InitializeMetaDataStore(); ReadDataStore(); if (_metaDataStore == null || _metaData == null) { throw new ArgumentNullException("metadata not initialized"); } //Make sure the metadata store is updated to reflect the state of the data before each sync operation. BeginTransaction(); UpdateMetadataStoreWithLocalChanges(); CommitTransaction(); _currentSessionContext = syncSessionContext; }
public override void BeginSession( SyncProviderPosition position, SyncSessionContext syncSessionContext) { if (this.client == null) { // Allow for the same proxy to be use in several unidirectional session this.client = new PosServerDbSyncServiceClient( endpointConfigurationName); this.client.CreateProviderForSyncSession(_companyId, _storeId, syncDataServiceName); } this.syncSessionContext = syncSessionContext; this.client.BeginSession(); }
public override void BeginSession( SyncProviderPosition position, SyncSessionContext syncSessionContext) { if (this.client == null) { // Allow for the same proxy to be use in several unidirectional session this.client = new Sync101WebServiceClient( endpointConfigurationName); this.client.CreateProviderForSyncSession(folderPath, this.storeName); } this.syncSessionContext = syncSessionContext; this.client.BeginSession(); }
/// <summary> /// Get changes for a client using the knowledge that is passed in. /// </summary> /// <param name="serverBlob">Client knowledge as byte[]</param> /// <returns>Response containing the new knowledge and the list of changes.</returns> public GetChangesResponse GetChanges(byte[] serverBlob) { bool isNewClient = false; var response = new GetChangesResponse(); var syncBlob = new SyncBlob(); byte[] clientKnowledgeBlob = null; // If the incoming knowledge blob is null, then we need to initialize a new scope // for this request. if (null == serverBlob || 0 == serverBlob.Length) { // Create a new Guid and use that as the client Id. Guid clientId = Guid.NewGuid(); _clientScopeName = String.Format(CultureInfo.InvariantCulture, "{0}_{1}", _scopeName, clientId); _clientSyncId = new SyncId(clientId); CreateNewScopeForClient(); isNewClient = true; syncBlob.ClientScopeName = clientId.ToString(); } else { SyncBlob incomingBlob = SyncBlob.DeSerialize(serverBlob); PopulateClientScopeNameAndSyncId(incomingBlob); syncBlob.ClientScopeName = incomingBlob.ClientScopeName; clientKnowledgeBlob = incomingBlob.ClientKnowledge; if (null != incomingBlob.BatchCode && null != incomingBlob.NextBatch) { // This is a batched request, so handle it separately. return GetChanges(incomingBlob.ClientKnowledge, incomingBlob.BatchCode.Value, incomingBlob.NextBatch.Value); } } // Intialize a SqlSyncProvider object. _sqlSyncProvider = CreateSqlSyncProviderInstance(_clientScopeName, _serverConnectionString, _configuration.SyncObjectSchema); var sessionContext = new SyncSessionContext(_sqlSyncProvider.IdFormats, new SyncCallbacks()); _sqlSyncProvider.BeginSession(SyncProviderPosition.Remote, sessionContext); try { // Get the SyncKnowledge from the blob. If the blob is null, initialize a default SyncKnowledge object. SyncKnowledge clientKnowledge = GetSyncKnowledgeFromBlob(clientKnowledgeBlob); DbSyncContext dbSyncContext; uint changeBatchSize = (_configuration.IsBatchingEnabled) ? (uint)_configuration.DownloadBatchSizeInKB : 0; RowSorter rowSorter = null; do { object changeDataRetriever; // Get the next batch. _sqlSyncProvider.GetChangeBatch(changeBatchSize, clientKnowledge, out changeDataRetriever); dbSyncContext = (DbSyncContext)changeDataRetriever; // Only initialize the RowSorter, if the data is batched. if (null == rowSorter && _configuration.IsBatchingEnabled) { // Clone the client knowledge. var clonedClientKnowledge = clientKnowledge.Clone(); // Combine with the MadeWithKnowledge of the server. clonedClientKnowledge.Combine(dbSyncContext.MadeWithKnowledge); // Use the new knowledge and get and instance of the RowSorter class. rowSorter = GetRowSorter(clonedClientKnowledge); } // Remove version information from the result dataset. RemoveSyncVersionColumns(dbSyncContext.DataSet); // For a new client, we don't want to send tombstones. This will reduce amount of data // transferred and the client doesn't care about tombstones anyways. if (isNewClient) { RemoveTombstoneRowsFromDataSet(dbSyncContext.DataSet); } // Add the dataset to the row sorter. Only use this if batching is enabled. if (_configuration.IsBatchingEnabled) { rowSorter.AddUnsortedDataSet(dbSyncContext.DataSet); // Delete the batch file generated by the provider, since we have read it. // Otherwise we will keep accumulating files which are not needed. if (!String.IsNullOrEmpty(dbSyncContext.BatchFileName) && File.Exists(dbSyncContext.BatchFileName)) { File.Delete(dbSyncContext.BatchFileName); } } } while (!dbSyncContext.IsLastBatch && dbSyncContext.IsDataBatched); List<IOfflineEntity> entities; if (_configuration.IsBatchingEnabled) { // If batching is enabled. Batch batch = SaveBatchesAndReturnFirstBatch(rowSorter); if (null == batch) { entities = new List<IOfflineEntity>(); } else { // Conver to to entities. entities = _converter.ConvertDataSetToEntities(batch.Data); //Only combine the knowledge of this batch. clientKnowledge.Combine(SyncKnowledge.Deserialize(_sqlSyncProvider.IdFormats, batch.LearnedKnowledge)); response.IsLastBatch = batch.IsLastBatch; syncBlob.IsLastBatch = batch.IsLastBatch; if (batch.IsLastBatch) { syncBlob.NextBatch = null; syncBlob.BatchCode = null; } else { syncBlob.NextBatch = batch.NextBatch; syncBlob.BatchCode = batch.BatchCode; } } } else { // No batching. response.IsLastBatch = true; entities = _converter.ConvertDataSetToEntities(dbSyncContext.DataSet); // combine the client and the server knowledge. // the server may have an updated knowledge from the last time the client sync'd. clientKnowledge.Combine(dbSyncContext.MadeWithKnowledge); } // Save data in the response object. syncBlob.ClientKnowledge = clientKnowledge.Serialize(); response.ServerBlob = syncBlob.Serialize(); response.EntityList = entities; } finally { _sqlSyncProvider.EndSession(sessionContext); } return response; }
//BeginSession is called at the beginning of each sync operation. Do initialization here. For example update //metadata if it was not updated as the actual data was changed. public override void BeginSession(SyncProviderPosition position, SyncSessionContext syncSessionContext) { BeginSession(); _currentSessionContext = syncSessionContext; }
/// <inheritdoc /> public override void EndSession(SyncSessionContext syncSessionContext) { if (syncSessionContext.IsCanceled()) m_session.Abort(); else m_session.Commit(); }
public override void EndSession(SyncSessionContext syncSessionContext) { service.SaveSyncSession(sync.Cast<LocalSyncDetails>()); System.Diagnostics.Debug.WriteLine("_____ Ending Session On RemoteStore ______"); }
/// <summary> /// When overridden in a derived class, notifies the provider that a synchronization session to which it was enlisted has completed. /// </summary> /// <param name="syncSessionContext">The current status of the corresponding session.</param> public override void EndSession(SyncSessionContext syncSessionContext) { _syncSessionContext = null; _syncService.EndSession(); }
//EndSession is called after the sync operation is completed. Cleanup happens here. public override void EndSession(SyncSessionContext syncSessionContext) { Thread.Sleep(1000); CloseMetadataStore(); }
/// <inheritdoc /> public override void BeginSession(SyncProviderPosition position, SyncSessionContext syncSessionContext) { if (!syncSessionContext.IsCanceled()) { if (position == SyncProviderPosition.Local) m_session.BeginUpdate(); else m_session.BeginRead(); } }
public override void BeginSession(SyncProviderPosition position, SyncSessionContext syncSessionContext) { syncProxy.BeginSession(); }
public override void BeginSession(SyncProviderPosition position, SyncSessionContext syncSessionContext) { _metadataStore.BeginSession(_nodeStore.Nodes); _currentSessionContext = syncSessionContext; }
public override void EndSession(SyncSessionContext syncSessionContext) { _metadataStore.EndSession(); }
public override void BeginSession(SyncProviderPosition position, SyncSessionContext syncSessionContext) { _position = position; SyncSessionContext = syncSessionContext; }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #endregion // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - public override void BeginSession(SyncSessionContext syncSessionContext) { Db.BeginSession(); }
public override void EndSession(SyncSessionContext syncSessionContext) { sync.Save(); System.Diagnostics.Debug.WriteLine("_____ Ending Session On LocalStore ______" ); }
/// <summary> /// When overridden in a derived class, notifies the provider that it is joining a synchronization session. /// </summary> /// <param name="position">The position of this provider, relative to the other provider in the session.</param> /// <param name="syncSessionContext">The current status of the corresponding session.</param> public override void BeginSession(SyncProviderPosition position, SyncSessionContext syncSessionContext) { if (_syncService == null) throw new Exception("Not initalized"); _syncSessionContext = syncSessionContext; _syncService.BeginSession(); }
public virtual void Cleanup() { SessionContext = null; Provider = null; }
public override void EndSession(SyncSessionContext syncSessionContext) { }
public override void BeginSession(Microsoft.Synchronization.SyncProviderPosition providerPosition, SyncSessionContext syncSessionContext) { currentSessionContext = syncSessionContext; _memConflictLog = new MemoryConflictLog(IdFormats); }
public override void EndSession(SyncSessionContext syncSessionContext) { syncProxy.EndSession(); }
public override void BeginSession(SyncProviderPosition position, SyncSessionContext syncSessionContext) { Proxy.BeginSession(position, syncSessionContext.ChangeApplierInfo); }
public override void EndSession(SyncSessionContext syncSessionContext) { Proxy.EndSession(syncSessionContext.ChangeApplierInfo); }
public override void EndSession(SyncSessionContext syncSessionContext) { SaveDataStore(); CloseMetaDataStore(); }
public override void EndSession(SyncSessionContext syncSessionContext) { try { proxy.EndSession(); } catch (Exception) { } if (this.localBatchingDirectory != null) { this.localBatchingDirectory.Refresh(); if (this.localBatchingDirectory.Exists) { //Cleanup batching releated files from this session this.localBatchingDirectory.Delete(true); } } }