示例#1
0
        /// <summary>
        /// Gets the peer metadata engine.
        /// </summary>
        /// <param name="engine">The engine.</param>
        /// <param name="peer">The peer.</param>
        /// <returns></returns>
        private IPersistenceEngine GetPeerMetadataEngine(SyncEngine engine, Peer peer)
        {
            if (engine.SecondaryMetadataEngine == null || peer == Peer.Client)
                return engine.MetadataEngine;

            return engine.SecondaryMetadataEngine;
        }
示例#2
0
        /// <summary>
        /// Gets the last connection information for a given client
        /// </summary>
        /// <param name="clientId">The Id of the client the connection should be returns</param>
        /// <param name="server">The SyncEngine instance for reading connection information </param>
        /// <returns>The last connection information for a given client</returns>
        private Entity GetConnection(string clientId, SyncEngine server)
        {
            Entity connection = null;
            IList<Entity> connections = GetPeerMetadataEngine(server, Peer.Server).Load(String.Format("Evaluant:Uss:Sync:Connection[ClientId = '{0}']", clientId));

            if (connections.Count > 0)
                connection = connections[0];
            else
            {
                connection = new Entity(SyncUtils.CONNECTION);
                connection[SyncUtils.CLIENTID].Value = clientId;
                connection[SyncUtils.TRANSACTION].Value = 0;
            }

            return connection;
        }
示例#3
0
 public SyncCommandProcessor(SyncEngine engine, Transaction transaction, int transactionId)
 {
     this.transaction = transaction;
     this.transactionId = transactionId;
     this.engine = engine;
 }
示例#4
0
 /// <summary>
 /// Determines whether the specified engine is a central node .
 /// </summary>
 /// <param name="engine">The engine.</param>
 /// <returns>
 /// 	<c>true</c> if the specified engine is a central node; otherwise, <c>false</c>.
 /// </returns>
 private bool IsCentralNode(SyncEngine engine)
 {
     return engine.MetadataEngine != null && engine.SecondaryMetadataEngine != null;
 }
示例#5
0
        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
        }
示例#6
0
        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);
        }
示例#7
0
        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);
        }
示例#8
0
        /// <summary>
        /// Creates Compound commands if necessary
        /// </summary>
        /// <param name="commands"></param>
        private Command[] OptimizeCommands(SyncEngine engine, IList<Entity> commands)
        {
            if (commands == null)
                throw new ArgumentNullException("commands");

            if (commands.Count == 0)
                return new Command[0];

            HashedList<Command> optimizedCommands = new HashedList<Command>();

            System.Collections.Generic.List<CompoundCreateCommand> createdCommands = new System.Collections.Generic.List<CompoundCreateCommand>();

            int j;

            for (int i = 0; i < commands.Count; i++)
            {
                Entity e = commands[i];

                string currentId = e.GetString(SyncUtils.PARENTID);
                int transaction = e.GetInt32(SyncUtils.TRANSACTION);

                switch (e.Type)
                {
                    case SyncUtils.CREATE_ENTITY:

                        string createType = e.GetString(SyncUtils.TYPE);

                        j = i + 1;

                        CompoundCreateCommand ccc = new CompoundCreateCommand(currentId, createType, new List<AttributeCommand>());

                        CompoundCreateCommand actual = createdCommands.Find(delegate(CompoundCreateCommand toFind)
                        {
                            return toFind.ClientId == ccc.ClientId &&
                                toFind.ParentId == ccc.ParentId &&
                                toFind.Type == ccc.Type;
                        });

                        if (actual == null)
                        {
                            createdCommands.Add(ccc);
                            optimizedCommands.Add(ccc);

                            while (j < commands.Count)
                            {

                                string subType = commands[j].GetString(SyncUtils.PARENTTYPE);
                                string subId = commands[j].GetString(SyncUtils.PARENTID);
                                int subTransaction = commands[j].GetInt32(SyncUtils.TRANSACTION);
                                string subCommand = commands[j].Type;

                                if (commands[j].Type == SyncUtils.CREATE_ATTRIBUTE && subId == currentId && subType == createType)
                                {
                                    if (subTransaction != transaction)
                                        break;

                                    ccc.InnerCommands.Add((AttributeCommand)engine.CreateCommand(commands[j]));
                                    commands.RemoveAt(j);
                                }
                                else
                                {
                                    j++;
                                }
                            }
                        }
                        else
                        {
                            optimizedCommands.Remove(actual);
                            optimizedCommands.Add(ccc);

                            createdCommands.Remove(actual);
                            createdCommands.Add(ccc);
                        }

                        break;

                    case SyncUtils.UPDATE_ATTRIBUTE:

                        string updateType = e.GetString(SyncUtils.PARENTTYPE);

                        j = i + 1;

                        CompoundUpdateCommand cuc = new CompoundUpdateCommand(currentId, updateType, new List<AttributeCommand>());
                        cuc.InnerCommands.Add((AttributeCommand)engine.CreateCommand(commands[i]));
                        optimizedCommands.Add(cuc);

                        while (j < commands.Count)
                        {
                            string subType = commands[j].GetString(SyncUtils.PARENTTYPE);
                            string subId = commands[j].GetString(SyncUtils.PARENTID);
                            int subTransaction = commands[j].GetInt32(SyncUtils.TRANSACTION);
                            string subCommand = commands[j].Type;

                            if (commands[j].Type == SyncUtils.UPDATE_ATTRIBUTE && subId == currentId && subType == updateType)
                            {
                                if (subTransaction != transaction)
                                    break;

                                cuc.InnerCommands.Add((AttributeCommand)engine.CreateCommand(commands[j]));
                                commands.RemoveAt(j);
                            }
                            else
                            {
                                j++;
                            }
                        }

                        break;

                    default:
                        optimizedCommands.Add(engine.CreateCommand(e));
                        break;

                }
            }

            Command[] result = new Command[optimizedCommands.Count];
            for (int i = 0; i < result.Length; i++)
                result[i] = (Command)optimizedCommands[i];

            return result;
        }