private void SmartUpload(SyncEngine client, IPersistenceEngine server) { if (server == null) throw new ArgumentException("The server engine must be not null"); if (client == null) throw new ArgumentException("The client engine must be not null and a SyncProvider"); IList<Entity> commands = GetPeerMetadataEngine(client, Peer.Client).Load("from " + SyncUtils.COMMAND + " c orderby c.Processed, c.Number select c", 1, 0); EntitySet commandsToRemove = ((EntitySet)commands).Clone(); Command[] optimized = OptimizeCommands(client, commands); Transaction t = new Transaction(client.MetadataEngine.Factory.Model); foreach (Command c in optimized) { c.ClientId = client.ClientId; CompoundCreateCommand ccc = c as CompoundCreateCommand; if (ccc != null) foreach (Command cmd in ccc.InnerCommands) cmd.ClientId = client.ClientId; t.PushCommand(c); } t.Commit(server, false); // Deletes the metadata once they are processed t = new Transaction(client.MetadataEngine.Factory.Model); t.Delete(commandsToRemove); t.Commit(client.MetadataEngine, false); }
private void SmartUploadDownload(SyncEngine client, SyncEngine server) { Transaction t; #region Download Entity connection = GetConnection(client.ClientId, server); int lastTransactionId = GetLastTransaction(connection); IList<Entity> serverCommands = GetPeerMetadataEngine(server, Peer.Server).Load(String.Format("from {2} c where (c.ClientId != '{0}' || c.ClientId==null)) && Transaction > {1} orderby c.Processed, c.Number", client.ClientId, lastTransactionId, SyncUtils.COMMAND), 1, 0); IList<Entity> clientCommands = GetPeerMetadataEngine(client, Peer.Client).Load("from " + SyncUtils.COMMAND + " c orderby Processed, Number select c", 1, 0); // Detecting ClientCreateOrUpdateClientDelete to delete the UpdateCommands which occured before a delete IPersistenceEngine peerMetadataEngine = GetPeerMetadataEngine(client, Peer.Client); t = new Transaction(peerMetadataEngine.Factory.Model); for (int i = clientCommands.Count - 1; i >= 0; i--) { Entity ce = clientCommands[i]; if (ce.Type == SyncUtils.DELETE_ENTITY) { for (int j = i - 1; j >= 0; j--) { { Entity se = clientCommands[j]; if (ApplyOnTheSameEntity(ce, se)) { clientCommands.RemoveAt(j); t.Delete(se); i--; if (se.Type == SyncUtils.CREATE_ENTITY) { clientCommands.Remove(ce); t.Delete(ce); i--; } } } } } } t.Commit(peerMetadataEngine, false); // Detecting ClientDeleteServerDelete to ignore the Delete commands from the Client for (int i = clientCommands.Count - 1; i >= 0; i--) { Entity ce = clientCommands[i]; if (ce.Type == SyncUtils.DELETE_ENTITY) { // A delete occured on the client, verify if this command is already on the server for (int j = serverCommands.Count - 1; j >= 0; j--) { Entity se = serverCommands[j]; if (se.Type == SyncUtils.DELETE_ENTITY && se.GetString(SyncUtils.PARENTID) == ce.GetString(SyncUtils.PARENTID)) { clientCommands.Remove(ce); serverCommands.Remove(se); } } } } // Detecting ClientDeleteServerUpdate to delete the UpdateCommands which occured later on the server t = new Transaction(GetPeerMetadataEngine(server, Peer.Server).Factory.Model); for (int i = clientCommands.Count - 1; i >= 0; i--) { Entity ce = clientCommands[i]; if (ce.Type == SyncUtils.DELETE_ENTITY) { // A delete occured on the client, verify no update command where set on the server for (int j = serverCommands.Count - 1; j >= 0; j--) { Entity se = serverCommands[j]; if (se.Type == SyncUtils.UPDATE_ATTRIBUTE && se.GetString(SyncUtils.PARENTID) == ce.GetString(SyncUtils.PARENTID)) { serverCommands.Remove(se); t.Delete(se); } } } } t.Commit(GetPeerMetadataEngine(server, Peer.Server), false); // Detecting ServerDeleteClientUpdate to delete the UpdateCommands which occured later on the client t = new Transaction(GetPeerMetadataEngine(server, Peer.Client).Factory.Model); for (int i = serverCommands.Count - 1; i >= 0; i--) { Entity se = serverCommands[i]; if (se.Type == SyncUtils.DELETE_ENTITY) { // A delete occured on the server, verify no update command where set on the client for (int j = clientCommands.Count - 1; j >= 0; j--) { Entity ce = clientCommands[j]; if (ce.Type == SyncUtils.UPDATE_ATTRIBUTE && ce.GetString(SyncUtils.PARENTID) == se.GetString(SyncUtils.PARENTID)) { clientCommands.Remove(ce); t.Delete(ce); } } } } t.Commit(GetPeerMetadataEngine(client, Peer.Client), false); // Detecting ServerUpdateClientUpdate to delete the UpdateCommands which occured later on the client Transaction ct = new Transaction(GetPeerMetadataEngine(server, Peer.Client).Factory.Model); Transaction st = new Transaction(GetPeerMetadataEngine(server, Peer.Server).Factory.Model); for (int i = serverCommands.Count - 1; i >= 0; i--) { Entity se = serverCommands[i]; if (se.Type == SyncUtils.UPDATE_ATTRIBUTE) { for (int j = clientCommands.Count - 1; j >= 0; j--) { Entity ce = clientCommands[j]; if (ce.Type == SyncUtils.UPDATE_ATTRIBUTE && ce.GetString(SyncUtils.PARENTID) == se.GetString(SyncUtils.PARENTID) && ce.GetString(SyncUtils.NAME) == se.GetString(SyncUtils.NAME)) { ConflictEventArgs args = new ConflictEventArgs(client.CreateCommand(ce), client.CreateCommand(se), SyncConflict.ClientUpdateServerUpdate); if (Conflict != null) Conflict(this, args); if (args.Resolution == ConflictResolution.ClientWins) { serverCommands.Remove(se); st.Delete(se); } else { clientCommands.Remove(ce); ct.Delete(ce); } } } } } ct.Commit(GetPeerMetadataEngine(client, Peer.Client), false); st.Commit(GetPeerMetadataEngine(server, Peer.Server), false); EntitySet clientCommandsToRemove = ((EntitySet)clientCommands).Clone(); EntitySet serverCommandsToRemove = ((EntitySet)serverCommands).Clone(); Command[] optimizedClientCommands = OptimizeCommands(client, clientCommands); Command[] optimizedServerCommands = OptimizeCommands(server, serverCommands); StringCollection dataToProcess = new StringCollection(); foreach (string filter in filters) foreach (Entity e in server.Load(filter)) dataToProcess.Add(string.Concat(e.Type, SEPARATOR, e.Id)); t = new Transaction(client.Factory.Model); foreach (Command c in optimizedServerCommands) { string key = string.Empty; CompoundCreateCommand ccc = c as CompoundCreateCommand; if (ccc != null) key = string.Concat(ccc.Type, SEPARATOR, ccc.ParentId); CompoundUpdateCommand cuc = c as CompoundUpdateCommand; if (cuc != null) key = string.Concat(cuc.ParentType, SEPARATOR, cuc.ParentId); DeleteEntityCommand dec = c as DeleteEntityCommand; if (dec != null) key = string.Concat(dec.Type, SEPARATOR, dec.ParentId); DeleteAttributeCommand dac = c as DeleteAttributeCommand; if (dac != null) key = string.Concat(dac.ParentType, SEPARATOR, dac.ParentId); CreateReferenceCommand crc = c as CreateReferenceCommand; if (crc != null) key = string.Concat(crc.ParentType, SEPARATOR, crc.ParentId); DeleteReferenceCommand drc = c as DeleteReferenceCommand; if (drc != null) key = string.Concat(drc.ParentType, SEPARATOR, drc.ParentId); if (key != null && key != string.Empty && filters.Count > 0 && !dataToProcess.Contains(key)) continue; c.IgnoreMetadata = true; t.PushCommand(c); } t.Commit(client, false); #endregion #region Upload if (optimizedClientCommands.Length > 0) { t = new Transaction(server.Factory.Model); t.PushCommand(optimizedClientCommands); t.Commit(server, false); } // Updates the last transaction id for the client Entity info = GetPeerMetadataEngine(server, Peer.Server).Load(SyncUtils.INFO)[0]; connection[SyncUtils.TRANSACTION].Value = info.GetInt32(SyncUtils.TRANSACTION); t = new Transaction(GetPeerMetadataEngine(server, Peer.Server).Factory.Model); t.Serialize(connection); t.Commit(GetPeerMetadataEngine(server, Peer.Server), false); // Deletes the metadata once they are processed if (clientCommands.Count > 0) { t = new Transaction(GetPeerMetadataEngine(server, Peer.Client).Factory.Model); t.Delete(clientCommandsToRemove); t.Commit(GetPeerMetadataEngine(client, Peer.Client), false); } // Deletes all tombstoned server commands if (tombstone != TimeSpan.MaxValue) { serverCommands = GetPeerMetadataEngine(server, Peer.Server).Load("from Evaluant.Uss.Sync.Command c where c.Processed > #" + DateTime.Now.Add(-tombstone) + "# select c"); t = new Transaction(GetPeerMetadataEngine(server, Peer.Server).Factory.Model); t.Delete(serverCommandsToRemove); t.Commit(GetPeerMetadataEngine(server, Peer.Server), false); } #endregion }
private void SmartDownload(IPersistenceEngine client, SyncEngine server, string clientId) { if (client == null) throw new ArgumentException("The client engine must be not null"); if (server == null) throw new ArgumentException("The server engine must be not null and a SyncProvider"); Entity connection = GetConnection(clientId, server); int lastSync = connection.GetInt32(SyncUtils.TRANSACTION); Command[] commands = OptimizeCommands((SyncEngine)client, GetPeerMetadataEngine(server, Peer.Server).Load("from Evaluant.Uss.Sync.Command c where (c.ClientId!='" + client + "' || c.ClientId==null) and c.Transaction>" + lastSync.ToString() + " orderby c.Processed, c.Number", 1, 0) ); StringCollection dataToProcess = new StringCollection(); foreach (string filter in filters) foreach (Entity e in server.Load(filter)) dataToProcess.Add(string.Concat(e.Type, SEPARATOR, e.Id)); Transaction t = new Transaction(client.Factory.Model); foreach (Command c in commands) { string key = string.Empty; CompoundCreateCommand ccc = c as CompoundCreateCommand; if (ccc != null) key = string.Concat(ccc.Type, SEPARATOR, ccc.ParentId); CompoundUpdateCommand cuc = c as CompoundUpdateCommand; if (cuc != null) key = string.Concat(cuc.ParentType, SEPARATOR, cuc.ParentId); if (key != null && key != string.Empty && filters.Count > 0 && !dataToProcess.Contains(key)) continue; c.IgnoreMetadata = true; t.PushCommand(c); } t.Commit(client, false); Entity info = GetPeerMetadataEngine(server, Peer.Server).Load(SyncUtils.INFO)[0]; connection[SyncUtils.TRANSACTION].Value = info.GetInt32(SyncUtils.TRANSACTION); IPersistenceEngine peerMetadataEngine = GetPeerMetadataEngine(server, Peer.Server); t = new Transaction(peerMetadataEngine.Factory.Model); t.Serialize(connection); t.Commit(peerMetadataEngine, false); }