protected void ChangeFirstLevelCaches(CacheDependencyNode node, ISet <IObjRef> intermediateDeletes) { List <IDataChangeEntry> deletes = new List <IDataChangeEntry>(); ICacheModification cacheModification = this.CacheModification; bool oldCacheModificationValue = cacheModification.Active; if (!oldCacheModificationValue) { cacheModification.Active = true; } try { ChangeFirstLevelCachesIntern(node, intermediateDeletes); } finally { if (!oldCacheModificationValue) { cacheModification.Active = oldCacheModificationValue; } } if (deletes.Count > 0) { IDataChange dce = DataChangeEvent.Create(0, 0, deletes.Count); ListUtil.AddAll(dce.Deletes, dce.Deletes.Count, deletes); GuiThreadHelper.InvokeOutOfGui(delegate() { EventDispatcher.DispatchEvent(dce); }); } }
public void UpdatePersonLists_2Changes_NonInSubscription_NothingAddedInSubscription_And_NoNotificationCreated(string municipalityCode) { var dce = new DataChangeEvent[] { new DataChangeEvent() { PersonRegistrationId = Guid.NewGuid(), DueDate = DateTime.Now, ReceivedDate = DateTime.Now, PersonUuid = Guid.NewGuid(), DataChangeEventId = Guid.NewGuid() }, new DataChangeEvent() { PersonRegistrationId = Guid.NewGuid(), DueDate = DateTime.Now, ReceivedDate = DateTime.Now, PersonUuid = Guid.NewGuid(), DataChangeEventId = Guid.NewGuid() } }; var sub = Utils.CreateCriteriaSubscription(municipalityCode); using (var dataContext = new EventBrokerDataContext()) { dataContext.DataChangeEvents.InsertAllOnSubmit(dce); dataContext.Subscriptions.InsertOnSubmit(sub); dataContext.SubmitChanges(); } using (var dataContext = new EventBrokerDataContext()) { int records = dataContext.UpdatePersonLists(DateTime.Now, (int)Data.SubscriptionType.SubscriptionTypes.DataChange); var subscriptionPerson = dataContext.SubscriptionPersons.Where(sp => sp.SubscriptionId == sub.SubscriptionId).SingleOrDefault(); Assert.Null(subscriptionPerson); var notif = dataContext.EventNotifications.Where(en => en.SubscriptionId == sub.SubscriptionId).SingleOrDefault(); Assert.Null(notif); } }
public static DataChangeEvent Serdes(DataChangeEvent e, AssetMapping mapping, ISerializer s) { if (s == null) { throw new ArgumentNullException(nameof(s)); } if (s.IsWriting() && e == null) { throw new ArgumentNullException(nameof(e)); } ChangeProperty property = s.EnumU8(nameof(ChangeProperty), e?.ChangeProperty ?? ChangeProperty.Unk0); return(property switch { ChangeProperty.Unk0 => ChangeUnk0Event.Serdes((ChangeUnk0Event)e, s), ChangeProperty.Health => ChangeHealthEvent.Serdes((ChangeHealthEvent)e, mapping, s), ChangeProperty.Mana => ChangeManaEvent.Serdes((ChangeManaEvent)e, mapping, s), ChangeProperty.Status => ChangeStatusEvent.Serdes((ChangeStatusEvent)e, mapping, s), ChangeProperty.Language => ChangeLanguageEvent.Serdes((ChangeLanguageEvent)e, mapping, s), ChangeProperty.Experience => ChangeExperienceEvent.Serdes((ChangeExperienceEvent)e, mapping, s), ChangeProperty.UnkB => ChangeUnkBEvent.Serdes((ChangeUnkBEvent)e, s), ChangeProperty.UnkC => ChangeUnkCEvent.Serdes((ChangeUnkCEvent)e, s), ChangeProperty.Item => ChangeItemEvent.Serdes((ChangeItemEvent)e, mapping, s), ChangeProperty.Gold => ChangeGoldEvent.Serdes((ChangeGoldEvent)e, mapping, s), ChangeProperty.Food => ChangeFoodEvent.Serdes((ChangeFoodEvent)e, mapping, s), _ => throw new FormatException($"Unexpected data change type \"{property}\"") });
/// <summary> /// 发布数据变更事件 /// </summary> /// <returns></returns> public static IRepository Publish(this IRepository repository, DataChangeEvent @event, string eventName = null, string eventBusName = null) { var bus = repository.ServiceProvider.GetRequiredService <IEventBusFactory>().CreateEventBus(eventBusName); bus.Publish(@event, eventName); return(repository); }
private void OnDataChangeEvent(DataChangeEvent changeEvent) { foreach (var pair in _keysDictionary) { if (pair.Value.Contains(changeEvent.EntityType)) { _cacheInstance.Remove(pair.Key); } } }
public virtual void Delete(T instance) { //SynchronousTask.DoSync(() => this.Connection.Delete(instance)); lock (this.Connection) { this.Connection.Delete(instance); } var modelChange = new DataChangeEvent <T>(instance.Identity, DataChangeKind.Deleted); this.changes.OnNext(modelChange); }
private void OnDataChangeEvent(DataChangeEvent changeEvent) { var type = changeEvent.EntityType; if (_typesDictionary.TryGetValue(type, out var routes)) { var keysForRemove = _etagDictionary.Keys.Where(url => routes.Any(url.StartsWith)); foreach (var key in keysForRemove) { _etagDictionary.TryRemove(key, out var unusedVal); } } }
public void DataMonitorEvent(NetFlowTool n) { NowProcess = Process.GetProcesses(); GetConnection(); SetNetProcess(); CalcNetProcessInfo(); DataChangeEvent?.Invoke(); CheckRestart(); }
void OnDataChange(DataChangeEvent e) { if (e.Property == DataChangeEvent.ChangeProperty.ReceiveOrRemoveItem && e.Mode == QuantityChangeOperation.AddAmount) { var transitionEvent = new LinearItemTransitionEvent(e.ItemId, (int)ConversationPositionRight.X, (int)ConversationPositionRight.Y, (int)ConversationPositionLeft.X, (int)ConversationPositionLeft.Y, null); Raise(transitionEvent); } }
private static void NotifyPersonRegistrationUpdate(Guid personUuid, Guid personRegistrationId) { using (var dataContext = new DataChangeEventDataContext()) { var pp = new DataChangeEvent() { DataChangeEventId = Guid.NewGuid(), PersonUuid = personUuid, PersonRegistrationId = personRegistrationId, ReceivedDate = DateTime.Now }; dataContext.DataChangeEvents.InsertOnSubmit(pp); dataContext.SubmitChanges(); } }
/// <summary> /// Register a listener to a key. /// </summary> public void AddListener(string key, DataChangeAction eventCallback) { if (string.IsNullOrWhiteSpace(key)) { throw new ArgumentNullException("key", "Invalid key name to register callback!"); } if (eventCallback == null) { return; } if (!blackboardEvents.ContainsKey(key)) { blackboardEvents[key] = new DataChangeEvent(); } blackboardEvents[key].AddListener(eventCallback); }
public SaveResult Save(T instance) { if (!instance.UncommittedEvents.Any()) { return(SaveResult.None); } var current = this.GetById(instance.Identity); int expectedVersion = instance.UncommittedEvents.First().Version - 1; if ((current == null && expectedVersion != 0) || (current != null && current.Version != expectedVersion)) { throw new ConcurrencyException(); } var snapshot = ((ISnapshotSupport)instance).GetSnapshot() as ISnapshot; this.manifest.UpdateManifest(instance.Identity, expectedVersion, snapshot.Version); var saveResult = this.repository.Save(snapshot); IDataChangeEvent modelChange = null; switch (saveResult) { case SaveResult.Added: modelChange = new DataChangeEvent(snapshot.GetType(), snapshot.Identity, snapshot, DataChangeKind.Added); break; case SaveResult.Updated: modelChange = new DataChangeEvent(snapshot.GetType(), snapshot.Identity, snapshot, DataChangeKind.Changed); break; } this.changes.OnNext(modelChange); this.PublishEvents(instance.UncommittedEvents); instance.Commit(); return(expectedVersion == 0 ? SaveResult.Added : SaveResult.Updated); }
public virtual SaveResult Save(T instance) { var result = SaveResult.Updated; // SynchronousTask.DoSync(() => { // //Console.WriteLine(string.Format("SqlRepo - Save {0} {1}", instance.GetType(),instance.Identity)); // // if (this.Connection.Update(instance) == 0) // { // this.Connection.Insert(instance); // result = SaveResult.Added; // } // }); lock (this.Connection) { if (this.Connection.Update(instance) == 0) { this.Connection.Insert(instance); result = SaveResult.Added; } } IDataChangeEvent modelChange = null; switch (result) { case SaveResult.Added: modelChange = new DataChangeEvent <T>(instance.Identity, instance, DataChangeKind.Added); break; case SaveResult.Updated: modelChange = new DataChangeEvent <T>(instance.Identity, instance, DataChangeKind.Changed); break; } this.changes.OnNext(modelChange); return(result); }
public virtual void DeleteId(Guid id) { // SynchronousTask.DoSync(() => { // Console.WriteLine(string.Format("SqlRepo - Delete {0} {1}", typeof(T), id)); // var map = this.Connection.GetMapping(typeof(T)); // var pk = map.PK; // // if (pk == null) // { // throw new NotSupportedException ("Cannot delete " + map.TableName + ": it has no PK"); // } // // var q = string.Format ("delete from \"{0}\" where \"{1}\" = ?", map.TableName, pk.Name); // this.Connection.Execute (q, id); // // var modelChange = new DataChangeEvent<T>(id, DataChangeKind.Deleted); // this.changes.OnNext(modelChange); // }); lock (this.Connection) { var map = this.Connection.GetMapping(typeof(T)); var pk = map.PK; if (pk == null) { throw new NotSupportedException("Cannot delete " + map.TableName + ": it has no PK"); } var q = string.Format("delete from \"{0}\" where \"{1}\" = ?", map.TableName, pk.Name); this.Connection.Execute(q, id); } var modelChange = new DataChangeEvent <T>(id, DataChangeKind.Deleted); this.changes.OnNext(modelChange); }
public void UpdatePersonLists_2Changes_1MovingIn_PersonAdded(string municipalityCode) { var dce = new DataChangeEvent[] { new DataChangeEvent() { PersonRegistrationId = Guid.NewGuid(), DueDate = DateTime.Now, ReceivedDate = DateTime.Now, PersonUuid = Guid.NewGuid(), DataChangeEventId = Guid.NewGuid() }, new DataChangeEvent() { PersonRegistrationId = Guid.NewGuid(), DueDate = DateTime.Now, ReceivedDate = DateTime.Now, PersonUuid = Guid.NewGuid(), DataChangeEventId = Guid.NewGuid() } }; var sub = Utils.CreateCriteriaSubscription(municipalityCode); sub.SubscriptionCriteriaMatches.Add(new SubscriptionCriteriaMatch() { SubscriptionCriteriaMatchId = Guid.NewGuid(), DataChangeEvent = dce[0] }); using (var dataContext = new EventBrokerDataContext()) { dataContext.DataChangeEvents.InsertAllOnSubmit(dce); dataContext.Subscriptions.InsertOnSubmit(sub); dataContext.SubmitChanges(); } using (var dataContext = new EventBrokerDataContext()) { int records = dataContext.UpdatePersonLists(DateTime.Now, (int)Data.SubscriptionType.SubscriptionTypes.DataChange); var subscriptionPersons = dataContext.SubscriptionPersons.Where(sp => sp.SubscriptionId == sub.SubscriptionId && sp.Removed == null).ToArray(); Assert.AreEqual(1, subscriptionPersons.Length); Assert.Null(subscriptionPersons[0].Removed); var notif = dataContext.EventNotifications.Where(en => en.SubscriptionId == sub.SubscriptionId).SingleOrDefault(); Assert.Null(notif); } }
public void UpdatePersonLists_2Changes_1MovingOut_PersonRemovedAndNotoficationAdded(string municipalityCode) { var dce = new DataChangeEvent[] { new DataChangeEvent() { PersonRegistrationId = Guid.NewGuid(), DueDate = DateTime.Now, ReceivedDate = DateTime.Now, PersonUuid = Guid.NewGuid(), DataChangeEventId = Guid.NewGuid() }, new DataChangeEvent() { PersonRegistrationId = Guid.NewGuid(), DueDate = DateTime.Now, ReceivedDate = DateTime.Now, PersonUuid = Guid.NewGuid(), DataChangeEventId = Guid.NewGuid() } }; var sub = Utils.CreateCriteriaSubscription(municipalityCode); sub.SubscriptionPersons.Add(new SubscriptionPerson() { SubscriptionPersonId = Guid.NewGuid(), PersonUuid = dce[0].PersonUuid, Created = DateTime.Now, Removed = null }); using (var dataContext = new EventBrokerDataContext()) { dataContext.DataChangeEvents.InsertAllOnSubmit(dce); dataContext.Subscriptions.InsertOnSubmit(sub); dataContext.SubmitChanges(); } using (var dataContext = new EventBrokerDataContext()) { int records = dataContext.UpdatePersonLists(DateTime.Now, (int)Data.SubscriptionType.SubscriptionTypes.DataChange); var subscriptionPerson = dataContext.SubscriptionPersons.Where(sp => sp.SubscriptionId == sub.SubscriptionId).Single(); Assert.NotNull(subscriptionPerson.Removed); var notif = dataContext.EventNotifications.Where(en => en.SubscriptionId == sub.SubscriptionId).Single(); Assert.NotNull(notif.IsLastNotification); Assert.True(notif.IsLastNotification.Value); } }
public static IMapEvent SerdesEvent(IMapEvent e, ISerializer s, AssetId chainSource, TextId textSourceId, AssetMapping mapping) { if (s == null) { throw new ArgumentNullException(nameof(s)); } var initialPosition = s.Offset; s.Begin(); var type = s.EnumU8("Type", e?.EventType ?? MapEventType.UnkFf); e = type switch // Individual parsers handle byte range [1,9] { MapEventType.Action => ActionEvent.Serdes((ActionEvent)e, mapping, s), MapEventType.AskSurrender => AskSurrenderEvent.Serdes((AskSurrenderEvent)e, s), MapEventType.ChangeIcon => ChangeIconEvent.Serdes((ChangeIconEvent)e, mapping, s), MapEventType.ChangeUsedItem => ChangeUsedItemEvent.Serdes((ChangeUsedItemEvent)e, mapping, s), MapEventType.Chest => ChestEvent.Serdes((ChestEvent)e, mapping, s, textSourceId), MapEventType.CloneAutomap => CloneAutomapEvent.Serdes((CloneAutomapEvent)e, mapping, s), MapEventType.CreateTransport => CreateTransportEvent.Serdes((CreateTransportEvent)e, s), MapEventType.DataChange => DataChangeEvent.Serdes((DataChangeEvent)e, mapping, s), MapEventType.Door => DoorEvent.Serdes((DoorEvent)e, mapping, s, textSourceId), MapEventType.Encounter => EncounterEvent.Serdes((EncounterEvent)e, s), MapEventType.EndDialogue => EndDialogueEvent.Serdes((EndDialogueEvent)e, s), MapEventType.Execute => ExecuteEvent.Serdes((ExecuteEvent)e, s), MapEventType.MapExit => TeleportEvent.Serdes((TeleportEvent)e, mapping, s), MapEventType.Modify => ModifyEvent.BaseSerdes((ModifyEvent)e, mapping, chainSource, s), MapEventType.Offset => OffsetEvent.Serdes((OffsetEvent)e, s), MapEventType.Pause => PauseEvent.Serdes((PauseEvent)e, s), MapEventType.PlaceAction => PlaceActionEvent.Serdes((PlaceActionEvent)e, s), MapEventType.PlayAnimation => PlayAnimationEvent.Serdes((PlayAnimationEvent)e, mapping, s), MapEventType.Query => QueryEvent.Serdes((QueryEvent)e, mapping, s, textSourceId), MapEventType.RemovePartyMember => RemovePartyMemberEvent.Serdes((RemovePartyMemberEvent)e, mapping, s), MapEventType.Script => DoScriptEvent.Serdes((DoScriptEvent)e, mapping, s), MapEventType.Signal => SignalEvent.Serdes((SignalEvent)e, s), MapEventType.SimpleChest => SimpleChestEvent.Serdes((SimpleChestEvent)e, mapping, s), MapEventType.Sound => SoundEvent.Serdes((SoundEvent)e, mapping, s), MapEventType.Spinner => SpinnerEvent.Serdes((SpinnerEvent)e, s), MapEventType.StartDialogue => StartDialogueEvent.Serdes((StartDialogueEvent)e, mapping, s), MapEventType.Text => MapTextEvent.Serdes((MapTextEvent)e, mapping, s, textSourceId), MapEventType.Trap => TrapEvent.Serdes((TrapEvent)e, s), MapEventType.Wipe => WipeEvent.Serdes((WipeEvent)e, s), _ => DummyMapEvent.Serdes((DummyMapEvent)e, s, type) }; s.End(); if (e is IBranchingEvent) { s.Assert(s.Offset - initialPosition == 8, "Query events should always be 8 bytes"); } else { s.Assert(s.Offset - initialPosition == 10, "Non-query map events should always be 10 bytes"); } return(e); } /* == Binary Serialisable Event types: == * 1 Teleport (teleport 300 32 75) * 2 Door (open_door ...) * 3 Chest (open_chest ...) * 4 Text (map_text 100) * 5 Spinner (spinner ...) * 6 Trap (trap ...) * 7 ChangeUsedItem (change_used_item ...) * 8 DataChange (further subdivided by operation: min,max,?,set,add,sub,add%,sub%) * 0 Unk0 (TODO) * 2 Health (party[Tom].health += 20%) * 3 Mana (party[Sira].mana -= 5) * 5 Status (party[Rainer].status[Poisoned] = max) * 7 Language (party[Tom].language[Iskai] = max) * 8 Experience (party[Drirr].experience += 2000) * B UnkB (TODO) * C UnkC (TODO) * 13 Item (party[Tom].items[LughsShield] = 1) * 14 Gold (party[Joe].gold += 12) * 15 Food (party[Siobhan].food -= 10%) * 9 ChangeIcon (scope: rel vs abs, temp vs perm) * 0 Underlay (map.tempUnderlay[23,12] = 47) * 1 Overlay (map.permOverlay[+0,-3] = 1231) * 2 Wall (map.tempWall[10, 10] = 7) * 3 Floor (map.permFloor[64, 64] = 1) * 4 Ceiling (map.permCeiling[12, 24] = 7) * 5 NpcMovement (npc[12].permMovement = 3) * 6 NpcSprite (npc[5].tempSprite = 14) * 7 Chain (map.tempChain[10, 10] = 15) * 8 BlockHard (block_hard ...) * 9 BlockSoft (block_soft ...) * A Trigger (map.tempTrigger[96, 7] = Normal) * A Encounter (encounter ...) * B PlaceAction * 0 LearnCloseCombat * 1 Heal * 2 Cure * 3 RemoveCurse * 4 AskOpinion * 5 RestoreItemEnergy * 6 SleepInRoom * 7 Merchant * 8 OrderFood * 9 ScrollMerchant * B LearnSpells * C RepairItem * C Query (further subdivided by operation: NZ, <=, !=, ==, >=, >, <) * 0 Switch (switch[100]), (!switch[203]), (switch[KhunagMentionedSecretPassage]) * 1 Unk1 * 4 Unk4 * 5 HasPartyMember (party[Tom].isPresent) * 6 HasItem (!party.hasItem[Axe]) * 7 UsedItem (context.usedItem == Pick) * 9 PreviousActionResult (context.result) * A ScriptDebugMode (context.isDebug) * C UnkC * E NpcActive (npc[16].isActive) * F Gold (party.gold > 100) * 11 RandomChance (random(50)) * 12 Unk12 * 14 ChosenVerb (context.verb == Examine) * 15 Conscious (party[Tom].isConscious) * 1A Leader (party[Rainer].isLeader) * 1C Ticker (ticker[50] > 12) * 1D Map (context.map == Drinno3) * 1E Unk1E * 1F PromptPlayer (askYesNo(100)) * 19 Unk19 * 20 TriggerType (context.trigger == UseItem) * 21 Unk21 * 22 EventUsed (context.event[108].hasRun) * 23 DemoVersion (context.isDemo) * 29 Unk29 * 2A Unk2A * 2B PromptPlayerNumeric (askNumeric() = 1042) * D Modify * 0 Switch (switch[125] = 1) * 1 DisableEventChain (map[CantosHouse].chain[120] = 0) * 2 Unk2 * 4 NpcActive (set_npc_active ...) * 5 AddPartyMember (add_party_member ...) * 6 InventoryItem (party.item[Knife] += 3) * B Lighting (map.lighting = 5) ?? * F PartyGold (party.gold = min) * 10 PartyRations (party.rations += 12) * 12 Time (context.time += 6) * 1A Leader (party.leader = Tom) * 1C Ticker (ticker[93] = 108) * E Action (action ...) * 0 Word * 1 AskAboutItem * 2 Unk2 // Pay money? See ES156 (Garris, Gratogel sailor) * 4 Unk4 * 5 Unk5 * 6 StartDialogue * 7 FinishDialogue * 8 DialogueLine * 9 Unk9 * E Unk14 * 17 Unk23 * 2D Unk45 * 2E UseItem * 2F EquipItem * 30 UnequipItem * 36 PickupItem * 39 Unk57 * 3D Unk61 * F Signal (signal ...) * 10 CloneAutomap (clone_automap ...) * 11 Sound (sound ...) * 12 StartDialogue (start_dialogue ...) * 13 CreateTransport (???) * 14 Execute (execute) * 15 RemovePartyMember (remove_party_member ...) * 16 EndDialogue (end_dialogue) * 17 Wipe (wipe ...) * 18 PlayAnimation (play_anim ...) * 19 Offset (offset 0 0) * 1A Pause (pause 3) * 1B SimpleChest (simple_chest ...) * 1C AskSurrender (ask_surrender) * 1D Script (script 15) * FF UnkFF */ }
public IOriCollection Merge(ICUDResult cudResult, IMethodDescription methodDescription) { int localDcId; IDataChange dataChange; IList <IChangeContainer> allChanges = cudResult.AllChanges; IList <IObjRef> resultOriList = new List <IObjRef>(allChanges.Count); String changedBy = "anonymous"; long changedOn; Lock writeLock = PersistenceMock.GetWriteLock(); writeLock.Lock(); try { localDcId = ++dcId; changedOn = DateTimeUtil.CurrentTimeMillis(); IList <IDataChangeEntry> inserts = new List <IDataChangeEntry>(); IList <IDataChangeEntry> updates = new List <IDataChangeEntry>(); IList <IDataChangeEntry> deletes = new List <IDataChangeEntry>(); for (int a = 0, size = allChanges.Count; a < size; a++) { IChangeContainer changeContainer = allChanges[a]; IObjRef reference = changeContainer.Reference; if (changeContainer is DeleteContainer) { PersistenceMock.RemoveObject(reference); resultOriList.Add(null); deletes.Add(new DataChangeEntry(reference.RealType, reference.IdNameIndex, reference.Id, reference.Version)); } else if (changeContainer is UpdateContainer) { resultOriList.Add(reference); reference.Version = ((int)reference.Version) + 1; PersistenceMock.ChangeObject(reference, ((UpdateContainer)changeContainer).Primitives, ((UpdateContainer)changeContainer).Relations, changedBy, changedOn); updates.Add(new DataChangeEntry(reference.RealType, reference.IdNameIndex, reference.Id, reference.Version)); } else if (changeContainer is CreateContainer) { Object newId = AcquireIdForEntityType(reference.RealType); if (newId == null) { throw new Exception("Id must be valid"); } IEntityMetaData metaData = EntityMetaDataProvider.GetMetaData(reference.RealType); newId = ConversionHelper.ConvertValueToType(metaData.IdMember.ElementType, newId); reference.Id = newId; reference.Version = 1; ((IDirectObjRef)reference).Direct = null; resultOriList.Add(reference); PersistenceMock.AddObject(reference, ((CreateContainer)changeContainer).Primitives, ((CreateContainer)changeContainer).Relations, changedBy, changedOn); inserts.Add(new DataChangeEntry(reference.RealType, ObjRef.PRIMARY_KEY_INDEX, reference.Id, reference.Version)); } } OriCollection oriColl = new OriCollection(resultOriList); oriColl.ChangedBy = changedBy; oriColl.ChangedOn = changedOn; MergeController.ApplyChangesToOriginals(cudResult, oriColl, null); dataChange = new DataChangeEvent(inserts, updates, deletes, DateTimeUtil.ConvertJavaMillisToDateTime(changedOn), false); } finally { writeLock.Unlock(); } EventDispatcher.DispatchEvent(dataChange, dataChange.ChangeTime, localDcId); OriCollection oriCollection = new OriCollection(resultOriList); oriCollection.ChangedBy = changedBy; oriCollection.ChangedOn = changedOn; return(oriCollection); }
protected virtual void ProcessCUDResult(Object objectToMerge, ICUDResult cudResult, IList <Object> unpersistedObjectsToDelete, ProceedWithMergeHook proceedHook, bool addNewEntitiesToCache) { if (cudResult.AllChanges.Count > 0 || (unpersistedObjectsToDelete != null && unpersistedObjectsToDelete.Count > 0)) { if (proceedHook != null) { bool proceed = proceedHook.Invoke(cudResult, unpersistedObjectsToDelete); if (!proceed) { return; } } } if (cudResult.AllChanges.Count == 0) { if (Log.InfoEnabled) { Log.Info("Service call skipped early because there is nothing to merge"); } } else { IOriCollection oriColl; EventDispatcher.EnableEventQueue(); try { EventDispatcher.Pause(Cache); try { bool?oldNewlyPersistedEntities = addNewlyPersistedEntitiesTL.Value; addNewlyPersistedEntitiesTL.Value = addNewEntitiesToCache; try { IResultingBackgroundWorkerDelegate <IOriCollection> runnable = new IResultingBackgroundWorkerDelegate <IOriCollection>(delegate() { IOriCollection oriColl2 = MergeService.Merge(cudResult, null); MergeController.ApplyChangesToOriginals(cudResult, oriColl2, null); return(oriColl2); }); if (Transaction == null || Transaction.Active) { oriColl = runnable(); } else { oriColl = Transaction.RunInLazyTransaction(runnable); } } finally { addNewlyPersistedEntitiesTL.Value = oldNewlyPersistedEntities; } } finally { EventDispatcher.Resume(Cache); } } finally { EventDispatcher.FlushEventQueue(); } DataChangeEvent dataChange = DataChangeEvent.Create(-1, -1, -1); // This is intentionally a remote source dataChange.IsLocalSource = false; if (IsNetworkClientMode) { IList <IChangeContainer> allChanges = cudResult.AllChanges; IList <IObjRef> orisInReturn = oriColl.AllChangeORIs; for (int a = allChanges.Count; a-- > 0;) { IChangeContainer changeContainer = allChanges[a]; IObjRef reference = changeContainer.Reference; IObjRef referenceInReturn = orisInReturn[a]; if (changeContainer is CreateContainer) { if (referenceInReturn.IdNameIndex != ObjRef.PRIMARY_KEY_INDEX) { throw new ArgumentException("Implementation error: Only PK references are allowed in events"); } dataChange.Inserts.Add(new DataChangeEntry(referenceInReturn.RealType, referenceInReturn.IdNameIndex, referenceInReturn.Id, referenceInReturn.Version)); } else if (changeContainer is UpdateContainer) { if (referenceInReturn.IdNameIndex != ObjRef.PRIMARY_KEY_INDEX) { throw new ArgumentException("Implementation error: Only PK references are allowed in events"); } dataChange.Updates.Add(new DataChangeEntry(referenceInReturn.RealType, referenceInReturn.IdNameIndex, referenceInReturn.Id, referenceInReturn.Version)); } else if (changeContainer is DeleteContainer) { if (reference.IdNameIndex != ObjRef.PRIMARY_KEY_INDEX) { throw new ArgumentException("Implementation error: Only PK references are allowed in events"); } dataChange.Deletes.Add(new DataChangeEntry(reference.RealType, reference.IdNameIndex, reference.Id, reference.Version)); } } //EventDispatcher.DispatchEvent(dataChange, DateTime.Now, -1); } } if (unpersistedObjectsToDelete != null && unpersistedObjectsToDelete.Count > 0) { // Create a DCE for all objects without an id but which should be deleted... // This is the case for newly created objects on client side, which should be // "cancelled". The DCE notifies all models which contain identity references to the related // objects to erase their existence in all controls. They are not relevant in the previous // server merge process DataChangeEvent dataChange = DataChangeEvent.Create(0, 0, unpersistedObjectsToDelete.Count); for (int a = unpersistedObjectsToDelete.Count; a-- > 0;) { Object unpersistedObject = unpersistedObjectsToDelete[a]; dataChange.Deletes.Add(new DirectDataChangeEntry(unpersistedObject)); } EventDispatcher.DispatchEvent(dataChange, DateTime.Now, -1); } RevertChangesHelper.RevertChanges(objectToMerge); }
protected void BatchEventsIntern(IList <IQueuedEvent> batchableEvents, IList <IQueuedEvent> targetBatchedEvents) { if (batchableEvents.Count == 1) { targetBatchedEvents.Add(batchableEvents[0]); return; } if (batchableEvents.Count == 0) { return; } // Check if all datachanges are in the same localsource state so that we can group them IDictionary <IObjRef, IObjRef> touchedObjRefSet = new Dictionary <IObjRef, IObjRef>(); ISet <IObjRef> touchedAsInsertObjRefDict = new HashSet <IObjRef>(); ISet <IObjRef> touchedAsUpdateObjRefDict = new HashSet <IObjRef>(); ISet <IObjRef> touchedAsDeleteObjRefDict = new HashSet <IObjRef>(); int splitIndex = -1; DateTime?lastDCETime = null, lastQueuedEventTime = null; long lastSequenceNumber = -1; bool? isLocalSource = null; for (int a = 0, size = batchableEvents.Count; a < size; a++) { IQueuedEvent batchableEvent = batchableEvents[a]; IDataChange dataChange = (IDataChange)batchableEvent.EventObject; if (isLocalSource.HasValue && isLocalSource.Value != dataChange.IsLocalSource) { // IsLocalSource differs, we can not batch the events here splitIndex = a; break; } isLocalSource = dataChange.IsLocalSource; lastQueuedEventTime = batchableEvent.DispatchTime; lastDCETime = dataChange.ChangeTime; lastSequenceNumber = batchableEvent.SequenceNumber; IList <IDataChangeEntry> insertsOfItem = dataChange.Inserts; IList <IDataChangeEntry> updatesOfItem = dataChange.Updates; IList <IDataChangeEntry> deletesOfItem = dataChange.Deletes; foreach (IDataChangeEntry insertOfItem in insertsOfItem) { if (insertOfItem.EntityType == null) { continue; } IObjRef objRef = ExtractAndMergeObjRef(insertOfItem, touchedObjRefSet); touchedAsInsertObjRefDict.Add(objRef); } foreach (IDataChangeEntry updateOfItem in updatesOfItem) { if (updateOfItem.EntityType == null) { continue; } IObjRef objRef = ExtractAndMergeObjRef(updateOfItem, touchedObjRefSet); if (touchedAsInsertObjRefDict.Contains(objRef)) { // Object is still seen as new in this batch sequence // So we ignore the update event for this item. The ObjRef already has the updated version continue; } touchedAsUpdateObjRefDict.Add(objRef); } foreach (IDataChangeEntry deleteOfItem in deletesOfItem) { if (deleteOfItem.EntityType == null) { continue; } IObjRef objRef = ExtractAndMergeObjRef(deleteOfItem, touchedObjRefSet); // Object can be removed from the queue because it has been updated AND deleted within the same batched sequence // From the entities point of view there is nothing we are interested in touchedAsUpdateObjRefDict.Remove(objRef); if (!touchedAsInsertObjRefDict.Remove(objRef)) { // Object will only be stored as deleted if it existed BEFORE the batched sequence touchedAsDeleteObjRefDict.Add(objRef); } } } if (splitIndex != -1 && splitIndex < batchableEvents.Count - 1) { // Cleanup garbage touchedAsInsertObjRefDict.Clear(); touchedAsUpdateObjRefDict.Clear(); touchedAsDeleteObjRefDict.Clear(); touchedObjRefSet.Clear(); SplitDataChangeBatch(batchableEvents, splitIndex, targetBatchedEvents); } else { IList <IDataChangeEntry> inserts = touchedAsInsertObjRefDict.Count > 0 ? new List <IDataChangeEntry>(touchedAsInsertObjRefDict.Count) : EmptyList.Empty <IDataChangeEntry>(); IList <IDataChangeEntry> updates = touchedAsUpdateObjRefDict.Count > 0 ? new List <IDataChangeEntry>(touchedAsUpdateObjRefDict.Count) : EmptyList.Empty <IDataChangeEntry>(); IList <IDataChangeEntry> deletes = touchedAsDeleteObjRefDict.Count > 0 ? new List <IDataChangeEntry>(touchedAsDeleteObjRefDict.Count) : EmptyList.Empty <IDataChangeEntry>(); foreach (IObjRef objRef in touchedAsInsertObjRefDict) { inserts.Add(new DataChangeEntry(objRef.RealType, objRef.IdNameIndex, objRef.Id, objRef.Version)); } foreach (IObjRef objRef in touchedAsUpdateObjRefDict) { updates.Add(new DataChangeEntry(objRef.RealType, objRef.IdNameIndex, objRef.Id, objRef.Version)); } foreach (IObjRef objRef in touchedAsDeleteObjRefDict) { deletes.Add(new DataChangeEntry(objRef.RealType, objRef.IdNameIndex, objRef.Id, objRef.Version)); } DataChangeEvent compositeDataChange = new DataChangeEvent(inserts, updates, deletes, lastDCETime.Value, isLocalSource.Value); targetBatchedEvents.Add(new QueuedEvent(compositeDataChange, lastQueuedEventTime.Value, lastSequenceNumber)); } }
protected virtual void RevertChangesIntern(IRevertChangesSavepoint savepoint, IList <Object> objectsToRevert, bool globally, RevertChangesFinishedCallback revertChangesFinishedCallback) { // Store the RevertChangesFinishedCallback from this thread on the stack and set the property null (for following calls): if (objectsToRevert == null || objectsToRevert.Count == 0) { if (revertChangesFinishedCallback != null) { revertChangesFinishedCallback.Invoke(true); } return; } if (globally) { GuiThreadHelper.InvokeOutOfGui(delegate() { bool success = false; try { DataChangeEvent dataChange = new DataChangeEvent(); dataChange.IsLocalSource = true; dataChange.Inserts = new List <IDataChangeEntry>(0); dataChange.Updates = new List <IDataChangeEntry>(); dataChange.Deletes = new List <IDataChangeEntry>(); for (int a = objectsToRevert.Count; a-- > 0;) { Object objectToRevert = objectsToRevert[a]; IEntityMetaData metaData = ((IEntityMetaDataHolder)objectToRevert).Get__EntityMetaData(); Object id = metaData.IdMember.GetValue(objectToRevert, false); if (id == null) { dataChange.Deletes.Add(new DirectDataChangeEntry(objectToRevert)); continue; } dataChange.Updates.Add(new DataChangeEntry(metaData.EntityType, ObjRef.PRIMARY_KEY_INDEX, id, null)); } EventDispatcher.DispatchEvent(dataChange, DateTime.Now, -1); success = true; } finally { if (revertChangesFinishedCallback != null) { revertChangesFinishedCallback.Invoke(success); } } }); } else { // Commented the following part from Ambeth 0.130 and use the part from Ambeth 0.129 due to a deadlock in the merge process: //GuiThreadHelper.InvokeOutOfGui(delegate() //{ // bool success1 = false; // try // { // IList<IDataChangeEntry> directObjectDeletes = new List<IDataChangeEntry>(); // IList<Object> initializedObjects = MergeController.ScanForInitializedObjects(objectsToRevert, true, null); // IList<IObjRef> orisToRevert = new List<IObjRef>(); // ISet<Object> persistedObjectsToRevert = new IdentityHashSet<Object>(); // for (int a = initializedObjects.Count; a-- > 0; ) // { // Object objectToRevert = initializedObjects[a]; // IEntityMetaData metaData = EntityMetaDataProvider.GetMetaData(objectToRevert.GetType()); // Object id = metaData.IdMember.GetValue(objectToRevert, false); // if (id == null) // { // directObjectDeletes.Add(new DirectDataChangeEntry(objectToRevert)); // continue; // } // persistedObjectsToRevert.Add(objectToRevert); // orisToRevert.Add(new ObjRef(metaData.EntityType, ObjRef.PRIMARY_KEY_INDEX, id, null)); // } // IList<Object> hardRefsToRootCacheValues = RootCache.GetObjects(orisToRevert, CacheDirective.CacheValueResult | CacheDirective.ReturnMisses); // for (int a = orisToRevert.Count; a-- > 0; ) // { // if (hardRefsToRootCacheValues[a] == null) // { // // Object could not be loaded/retrieved any more. So the ori refers to an invalid object // // We can not revert invalid objects and currently ignore them. They will raise exceptions if they will // // be tried to persist in a merge process any time in the future // orisToRevert.RemoveAt(a); // } // } // // We do nothing with the hardRef-list from the RootCache. It is only necessary to keep track of the instance reference on the stack // // To prohibit GC any potential WeakReferences in the meantime.... // GuiThreadHelper.InvokeInGuiAndWait(delegate() // { // IProcessResumeItem processResumeItem = WaitEventToResume(); // try // { // bool oldCacheModificationValue = CacheModification.IsActive; // CacheModification.IsActive = true; // bool oldFailEarlyModeActive = AbstractCache<Object>.FailEarlyModeActive; // AbstractCache<Object>.FailEarlyModeActive = true; // try // { // IList<IWritableCache> firstLevelCaches = FirstLevelCacheManager.SelectFirstLevelCaches(); // IList<Object> hardRefsToRootCacheValuesHere = hardRefsToRootCacheValues; // foreach (IWritableCache firstLevelCache in firstLevelCaches) // { // IList<Object> persistedObjectsInThisCache = firstLevelCache.GetObjects(orisToRevert, CacheDirective.FailEarly); // for (int a = persistedObjectsInThisCache.Count; a-- > 0; ) // { // Object persistedObjectInThisCache = persistedObjectsInThisCache[a]; // if (!persistedObjectsToRevert.Contains(persistedObjectInThisCache)) // { // continue; // } // RootCache.ApplyValues(persistedObjectInThisCache, (ICacheIntern)firstLevelCache); // } // } // for (int a = objectsToRevert.Count; a-- > 0; ) // { // Object objectToRevert = objectsToRevert[a]; // if (objectToRevert is IDataObject) // { // // Objects which are specified to be reverted loose their delete flag // ((IDataObject)objectToRevert).ToBeDeleted = false; // } // } // } // finally // { // AbstractCache<Object>.FailEarlyModeActive = oldFailEarlyModeActive; // CacheModification.IsActive = oldCacheModificationValue; // } // } // finally // { // if (processResumeItem != null) // { // processResumeItem.ResumeProcessingFinished(); // processResumeItem = null; // } // } // }); // if (directObjectDeletes.Count > 0) // { // DataChangeEvent dataChange = DataChangeEvent.Create(0, 0, 0); // dataChange.Deletes = directObjectDeletes; // EventDispatcher.DispatchEvent(dataChange, DateTime.Now, -1); // } // success1 = true; // } // finally // { // if (revertChangesFinishedCallback != null) // { // revertChangesFinishedCallback.Invoke(success1); // } // } //}); // Here comes the part from Ambeth 0.129: GuiThreadHelper.InvokeOutOfGui(delegate() { bool success1 = false; bool?success2 = null; bool?success3 = null; try { IList <IDataChangeEntry> directObjectDeletes = new List <IDataChangeEntry>(); List <IObjRef> objRefs = new List <IObjRef>(); List <ValueHolderRef> valueHolderKeys = new List <ValueHolderRef>(); IList <Object> initializedObjects = MergeController.ScanForInitializedObjects(objectsToRevert, true, null, objRefs, valueHolderKeys); IList <IObjRef> orisToRevert = new List <IObjRef>(); ISet <Object> persistedObjectsToRevert = new IdentityHashSet <Object>(); for (int a = initializedObjects.Count; a-- > 0;) { Object objectToRevert = initializedObjects[a]; IEntityMetaData metaData = ((IEntityMetaDataHolder)objectToRevert).Get__EntityMetaData(); Object id = metaData.IdMember.GetValue(objectToRevert, false); if (id == null) { directObjectDeletes.Add(new DirectDataChangeEntry(objectToRevert)); continue; } persistedObjectsToRevert.Add(objectToRevert); orisToRevert.Add(new ObjRef(metaData.EntityType, ObjRef.PRIMARY_KEY_INDEX, id, null)); } IList <Object> hardRefsToRootCacheValues = RootCache.GetObjects(orisToRevert, CacheDirective.CacheValueResult | CacheDirective.ReturnMisses); for (int a = orisToRevert.Count; a-- > 0;) { if (hardRefsToRootCacheValues[a] == null) { // Object could not be loaded/retrieved any more. So the ori refers to an invalid object // We can not revert invalid objects and currently ignore them. They will raise exceptions if they will // be tried to persist in a merge process any time in the future orisToRevert.RemoveAt(a); } } // We do nothing with the hardRef-list from the RootCache. It is only necessary to keep track of the instance reference on the stack // To prohibit GC any potential WeakReferences in the meantime.... success2 = false; GuiThreadHelper.InvokeInGui(delegate(Object state) { WaitEventToResume(delegate(IProcessResumeItem processResumeItem) { try { bool oldCacheModificationValue = CacheModification.Active; CacheModification.Active = true; bool oldFailEarlyModeActive = AbstractCache.FailInCacheHierarchyModeActive; AbstractCache.FailInCacheHierarchyModeActive = true; try { IList <IWritableCache> firstLevelCaches = FirstLevelCacheManager.SelectFirstLevelCaches(); IList <Object> hardRefsToRootCacheValuesHere = hardRefsToRootCacheValues; foreach (IWritableCache firstLevelCache in firstLevelCaches) { IList <Object> persistedObjectsInThisCache = firstLevelCache.GetObjects(orisToRevert, CacheDirective.FailEarly); for (int a = persistedObjectsInThisCache.Count; a-- > 0;) { Object persistedObjectInThisCache = persistedObjectsInThisCache[a]; if (!persistedObjectsToRevert.Contains(persistedObjectInThisCache)) { continue; } RootCache.ApplyValues(persistedObjectInThisCache, (ICacheIntern)firstLevelCache, null); } } for (int a = objectsToRevert.Count; a-- > 0;) { Object objectToRevert = objectsToRevert[a]; if (objectToRevert is IDataObject) { // Objects which are specified to be reverted loose their flags ((IDataObject)objectToRevert).ToBeDeleted = false; } } if (directObjectDeletes.Count == 0) { success2 = true; return; } } finally { AbstractCache.FailInCacheHierarchyModeActive = oldFailEarlyModeActive; CacheModification.Active = oldCacheModificationValue; } } finally { if (processResumeItem != null) { processResumeItem.ResumeProcessingFinished(); } } success3 = false; GuiThreadHelper.InvokeOutOfGui(delegate() { try { DataChangeEvent dataChange = DataChangeEvent.Create(0, 0, 0); dataChange.Deletes = directObjectDeletes; EventDispatcher.DispatchEvent(dataChange, DateTime.Now, -1); success3 = true; } finally { if (revertChangesFinishedCallback != null) { revertChangesFinishedCallback.Invoke(success3.Value); } } }); success2 = true; }, delegate(Exception e) { if (revertChangesFinishedCallback != null && success3 == null) { revertChangesFinishedCallback.Invoke(success2.Value); } }); }, null); success1 = true; } finally { if (revertChangesFinishedCallback != null && success2 == null && success3 == null) { revertChangesFinishedCallback.Invoke(success1); } } }); } }
public void OnNext(DataChangeEvent changeEvent) { DataChangeSubscribers(changeEvent); }