Пример #1
0
        /// <summary>
        /// Handles an update to a single attribute.
        /// </summary>
        /// <param name="localEntity">Entity containing attribute.</param>
        /// <param name="componentName">Name of the component containing attribute.</param>
        /// <param name="attributeName">Name of the attribute.</param>
        /// <param name="remoteAttributeSyncInfo">Remote sync info on this attribute.</param>
        /// <returns>True if the update should be propagated to other sync nodes.</returns>
        private bool HandleRemoteChangedAttribute(Entity localEntity, string componentName, string attributeName,
                                                  AttributeSyncInfo remoteAttributeSyncInfo)
        {
            EntitySyncInfo localEntitySyncInfo = syncInfo[localEntity.Guid];

            bool shouldUpdateLocalAttribute = false;

            if (!localEntitySyncInfo.Components.ContainsKey(componentName) ||
                !localEntitySyncInfo[componentName].Attributes.ContainsKey(attributeName))
            {
                shouldUpdateLocalAttribute = true;
                localEntitySyncInfo[componentName][attributeName] = remoteAttributeSyncInfo;
            }
            else
            {
                AttributeSyncInfo localAttributeSyncInfo = localEntitySyncInfo[componentName][attributeName];
                shouldUpdateLocalAttribute =
                    (localAttributeSyncInfo.LastValue == null && remoteAttributeSyncInfo.LastValue != null) ||
                    (localAttributeSyncInfo.LastValue != null &&
                     !localAttributeSyncInfo.LastValue.Equals(remoteAttributeSyncInfo.LastValue));
                if (!localAttributeSyncInfo.Sync(remoteAttributeSyncInfo))
                {
                    return(false);  // ignore this update because sync discarded it
                }
            }

            if (shouldUpdateLocalAttribute)
            {
                try
                {
                    // This is necessary, because Json.NET serializes primitive types using basic JSON values, which do
                    // not retain original type (e.g. integer values always become int even if they were stored as
                    // float values before) and there is no way to change this.
                    var attributeType  = localEntity[componentName].Definition[attributeName].Type;
                    var attributeValue = remoteAttributeSyncInfo.LastValue;

                    // Ignore event for this change.
                    lock (ignoredAttributeChanges)
                    {
                        ignoredAttributeChanges.Add(new AttributeUpdate(localEntity.Guid, componentName, attributeName,
                                                                        attributeValue));
                    }

                    localEntity[componentName][attributeName].Suggest(attributeValue);
                    return(true);
                }
                catch (ComponentAccessException)
                {
                    // This is fine, because we may have some plugins not loaded on this node.
                }
            }

            // If we are here, it means that this update was not discarded by sync and thus should be propagated to
            // other nodes. This is still the case even if the value has been the same and local attribute has not been
            // update, because we still need to update sync info on other nodes.
            return(true);
        }
        public void ShouldCorrectlyResolveSyncConflicts()
        {
            var guid1 = Guid.Parse("38d6f8c5-ded5-405a-9f7d-80ebd36d7a26");
            var guid2 = Guid.Parse("e0021595-ead4-4a70-825b-749175c0d9b9");

            var info1 = new AttributeSyncInfo(guid2, 1);
            var info2 = new AttributeSyncInfo(guid2, 2);
            var info3 = new AttributeSyncInfo(guid1, 3);

            info3.LastTimestamp = info1.LastTimestamp;

            Assert.IsFalse(info2.Sync(info1));
            Assert.AreEqual(2, info2.LastValue);

            Assert.IsTrue(info3.Sync(info1));
            Assert.AreEqual(1, info3.LastValue);
        }
        public void ShouldCorrectlyResolveSyncConflicts()
        {
            var guid1 = Guid.Parse("38d6f8c5-ded5-405a-9f7d-80ebd36d7a26");
            var guid2 = Guid.Parse("e0021595-ead4-4a70-825b-749175c0d9b9");

            var info1 = new AttributeSyncInfo(guid2, 1);
            var info2 = new AttributeSyncInfo(guid2, 2);
            var info3 = new AttributeSyncInfo(guid1, 3);

            info3.LastTimestamp = info1.LastTimestamp;

            Assert.IsFalse(info2.Sync(info1));
            Assert.AreEqual(2, info2.LastValue);

            Assert.IsTrue(info3.Sync(info1));
            Assert.AreEqual(1, info3.LastValue);
        }