internal static void Add(List <PropertyUpdateXML> updates, ProviderPropertyDefinition pdef, object value, PropertyUpdateOperation op) { updates.Add(new PropertyUpdateXML { Operation = op, Property = PropertyXML.Create(pdef, value) }); }
private void UpdateSharedObject(PropertyChangedPayload data) { Debug.Assert(this.client.CheckAccess()); ObjectEntry entry = null; try { if (!this.TryGetValue(data.ObjectId, out entry)) { // Received update for an object we are not tracking Debug.WriteLine("[PropertyChanged] Missing shared object for update in incoming event."); return; } SharedProperty property = entry.IsDynamic ? entry.Properties[data.PropertyName] : entry.Properties[data.PropertyIndex]; // In case of dynamic properties, this could be the first time this property is seen if (property == null && entry.IsDynamic) { property = new SharedProperty() { Attributes = new SharedAttributes(), Index = (short)entry.Properties.Count, Name = data.PropertyName, ETag = new ETag(this.client.ClientId), PropertyType = data.PropertyType }; entry.Properties.Add(property.Index, property); } // Ignore changes for given object, add to list entry.IgnoreChanges = true; // Don't apply update if we made it locally bool applyUpdate = data.ClientId != this.client.ClientId; bool conflictDetected = false; PropertyUpdateOperation matchingUpdate = property.LocalUpdates.Where(x => x.Payload.Equals(data)).FirstOrDefault(); if (matchingUpdate != null) { // Remove update from pending list Debug.WriteLine("[PropertyChanged] Received acknowledgement of matching property update"); if (matchingUpdate.ReapplyUpdate) { applyUpdate = true; } property.LocalUpdates.Remove(matchingUpdate); } // Check for conflict, but won't stop us from applying update conflictDetected = data.IsConflict(property.LocalUpdates) && !property.IsServerAppliedProperty() && (property.Attributes.ConcurrencyAttribute != ConcurrencyPolicy.Overwrite); if (applyUpdate) { // Mark pending updates to re-apply if we are applying a change from another endpoint if (data.ClientId != this.client.ClientId) { property.LocalUpdates.ForEach(x => x.ReapplyUpdate = true); } if (entry.IsDynamic) { var dictionary = entry.Object as IDictionary <string, object>; if (dictionary == null) { throw new ArgumentException("Dictionary is null"); } // Insert up-to-date value for property dictionary[data.PropertyName] = Json.ReadObject(DynamicTypeMapping.Instance.GetTypeFromValue(data.PropertyType), data.PropertyValue); } else { Json.AssignProperty(entry.Object, property.Name, data.PropertyValue); } property.Value = data.PropertyValue; } property.ETag = data.ETag; if (conflictDetected) { Debug.WriteLine("[PropertyChanged] Conflict detected on property update"); IEnumerable <PropertyChangedPayload> rejectedUpdates = property.LocalUpdates.Select(x => x.Payload); if (property.Attributes.ConcurrencyAttribute == ConcurrencyPolicy.RejectAndNotify) { var notify = new ConcurrencyUpdateRejectedEventArgs(entry.Object, property.Name, rejectedUpdates.Select(x => Json.ReadProperty(entry.Object, property.Name, x.PropertyValue))); this.client.RaiseError(notify); } property.LocalUpdates.Clear(); } } finally { if (entry != null) { entry.IgnoreChanges = false; } } }
internal bool IsConflict(PropertyUpdateOperation other) { return (this.ObjectId == other.Payload.ObjectId) && (this.PropertyIndex == other.Payload.PropertyIndex) && (this.ClientId != other.Payload.ClientId); }
internal bool TryApplyChange(ProviderPropertyDefinition pdef, ConfigurableObject targetObject, PropertyUpdateOperation op) { object obj = null; if (this.TryGetValue(pdef, out obj)) { Exception ex = null; try { if (op == PropertyUpdateOperation.Replace) { object obj2 = targetObject[pdef]; if ((!object.Equals(obj, pdef.DefaultValue) || obj2 != null) && !object.Equals(obj2, obj)) { if (pdef == ADObjectSchema.ExchangeVersion) { targetObject.SetExchangeVersion((ExchangeObjectVersion)obj); } else { targetObject[pdef] = obj; } } } else { MultiValuedPropertyBase multiValuedPropertyBase = obj as MultiValuedPropertyBase; MultiValuedPropertyBase multiValuedPropertyBase2 = targetObject[pdef] as MultiValuedPropertyBase; if (multiValuedPropertyBase != null && multiValuedPropertyBase2 != null) { foreach (object item in ((IEnumerable)multiValuedPropertyBase)) { switch (op) { case PropertyUpdateOperation.AddValues: multiValuedPropertyBase2.Add(item); break; case PropertyUpdateOperation.RemoveValues: multiValuedPropertyBase2.Remove(item); break; } } } } return(true); } catch (DataValidationException ex2) { ex = ex2; } catch (ArgumentException ex3) { ex = ex3; } catch (FormatException ex4) { ex = ex4; } catch (LocalizedException ex5) { ex = ex5; } if (ex != null) { MrsTracer.Common.Warning("Property {0} could not be set to '{1}', error {2}", new object[] { pdef.Name, obj, CommonUtils.FullExceptionMessage(ex) }); return(false); } return(false); } return(false); }