/// <summary> /// TheadSafe and no locks internally /// </summary> /// <param name="key"></param> /// <param name="eventType">Should contain one type i.e. should not be used as a flag. /// Every EventType should be executed from another thread</param> /// <param name="item"></param> /// <param name="oldItem"></param> /// <param name="reason"></param> /// <param name="notifyAsync"></param> internal void RaiseGeneralCacheNotification(string key, EventType eventType, EventCacheItem item, EventCacheItem oldItem, CacheItemRemovedReason reason, bool notifyAsync) { try { object[] registeredDiscriptors = null; ResourcePool eventPool = GetEventPool(eventType); if (eventPool != null) { registeredDiscriptors = eventPool.GetAllResourceKeys(); } if (registeredDiscriptors != null && registeredDiscriptors.Length > 0) { for (int i = 0; i < registeredDiscriptors.Length; i++) { CacheEventDescriptor discriptor = registeredDiscriptors[i] as CacheEventDescriptor; if (discriptor == null) { continue; } var arg = CreateCacheEventArgument(discriptor.DataFilter, key, _cacheName, eventType, item, oldItem, reason); arg.Descriptor = discriptor; if (notifyAsync) { #if !NETCORE discriptor.CacheDataNotificationCallback.BeginInvoke(key, arg, asyn, null); #elif NETCORE TaskFactory factory = new TaskFactory(); Task task = factory.StartNew(() => discriptor.CacheDataNotificationCallback(key, arg)); #endif } else { discriptor.CacheDataNotificationCallback.Invoke(key, arg); } } } } catch (Exception ex) { if (_logger != null && _logger.IsErrorEnabled) { _logger.CriticalInfo(ex.ToString()); } } }
internal EventHandle UnregisterDiscriptor(CacheEventDescriptor discriptor) { if (discriptor == null || !discriptor.IsRegistered) { return(null); } foreach (EventType type in Enum.GetValues(typeof(EventType))) { ResourcePool pool = null; #region Pool selection if ((type & discriptor.RegisteredAgainst) != 0) { pool = GetEventPool(EventsUtil.GetEventTypeInternal(type)); } if (pool == null) { continue; } #endregion short registrationSequenceId = -1; bool unregisterNotification = false; EventDataFilter maxDataFilter = EventDataFilter.None; lock (SyncLockGeneral) { object retVal = pool.RemoveResource(discriptor); if (retVal == null) { continue; } unregisterNotification = pool.Count == 0; if (!unregisterNotification) { object[] pooledDescriptors = pool.GetAllResourceKeys(); if (pooledDescriptors != null) { for (int i = 0; i < pooledDescriptors.Length; i++) { CacheEventDescriptor pooledDescriptor = pooledDescriptors[i] as CacheEventDescriptor; if (pooledDescriptor.DataFilter > maxDataFilter) { maxDataFilter = pooledDescriptor.DataFilter; } } } } discriptor.IsRegistered = false; //keeps a sequence number switch (type) { case EventType.ItemAdded: //Data filter is being updated if (maxDataFilter != _generalAddDataFilter) { _generalAddDataFilter = maxDataFilter; registrationSequenceId = ++_addEventRegistrationSequence; } if (unregisterNotification) { _generalAddDataFilter = EventDataFilter.None; } break; case EventType.ItemRemoved: if (maxDataFilter != _generalRemoveDataFilter) { _generalRemoveDataFilter = maxDataFilter; registrationSequenceId = ++_removeEventRegistrationSequenceId; } if (unregisterNotification) { _generalAddDataFilter = EventDataFilter.None; } break; case EventType.ItemUpdated: if (maxDataFilter != _generalUpdateDataFilter) { _generalUpdateDataFilter = maxDataFilter; registrationSequenceId = ++_updateEventRegisrationSequenceId; } if (unregisterNotification) { _generalAddDataFilter = EventDataFilter.None; } break; } } if (_cache != null) { if (unregisterNotification) { //client is no more interested in event, therefore unregister it from server _cache.UnregiserGeneralCacheNotification(EventsUtil.GetEventTypeInternal(type)); } else if (registrationSequenceId != -1) { //only caused update of data filter either upgrade or downgrade _cache.RegisterCacheNotificationDataFilter(EventsUtil.GetEventTypeInternal(type), maxDataFilter, registrationSequenceId); } } } return(null); }
/// <summary> /// TheadSafe and no locks internally /// </summary> /// <param name="key"></param> /// <param name="eventType">Should contain one type i.e. should not be used as a flag. /// Every EventType should be executed from another thread</param> /// <param name="item"></param> /// <param name="oldItem"></param> /// <param name="reason"></param> /// <param name="notifyAsync"></param> internal void RaiseGeneralCacheNotification(string key, EventType eventType, EventCacheItem item, EventCacheItem oldItem, CacheItemRemovedReason reason, bool notifyAsync) { try { object[] registeredDiscriptors = null; ResourcePool eventPool = GetEventPool(EventsUtil.GetEventTypeInternal(eventType)); if (eventPool != null) { registeredDiscriptors = eventPool.GetAllResourceKeys(); } if (registeredDiscriptors != null && registeredDiscriptors.Length > 0) { for (int i = 0; i < registeredDiscriptors.Length; i++) { CacheEventDescriptor discriptor = registeredDiscriptors[i] as CacheEventDescriptor; if (discriptor == null) { continue; } var bitSet = new BitSet(); if (_cache.SerializationFormat == Common.Enum.SerializationFormat.Json) { bitSet.SetBit(BitSetConstants.JsonData); } if (item != null) { item.SetValue(_cache.SafeDeserialize <object>(item.GetValue <object>(), _cache.SerializationContext, bitSet, UserObjectType.CacheItem)); } if (oldItem != null) { oldItem.SetValue(_cache.SafeDeserialize <object>(oldItem.GetValue <object>(), _cache.SerializationContext, bitSet, UserObjectType.CacheItem)); } var arg = CreateCacheEventArgument(discriptor.DataFilter, key, _cacheName, eventType, item, oldItem, reason); arg.Descriptor = discriptor; if (notifyAsync) { #if !NETCORE discriptor.CacheDataNotificationCallback.BeginInvoke(key, arg, asyn, null); #elif NETCORE //TODO: ALACHISOFT (BeginInvoke is not supported in .Net Core thus using TaskFactory) TaskFactory factory = new TaskFactory(); Task task = factory.StartNew(() => discriptor.CacheDataNotificationCallback(key, arg)); #endif } else { discriptor.CacheDataNotificationCallback.Invoke(key, arg); } } } } catch (Exception ex) { if (_logger != null && _logger.IsErrorEnabled) { _logger.CriticalInfo(ex.ToString()); } } }
/// <summary> /// This method Unregisters a custom callback that is fired on change in dataset of a continous query /// </summary> /// <param name="callback">A delegate to register your custom method with</param> /// <param name="eventType">Describes whether the event is to be raised on Item Added, Updated or Removed</param> /// <example> /// Lets consider we created an ItemCallback /// <code> /// ItemCallback(string key, CacheEventArg e) /// { /// ... /// } /// </code> /// Uregister your notification callback /// <code> /// cQ.RegisterNotification(new QueryDataNotificationCallback(ItemCallback),EventType.ItemAdded); /// </code> /// </example> public void UnRegisterNotification(QueryDataNotificationCallback callback, EventType eventType) { //BY LEGACY DESIGN THERE IS NO UNREGISTRATION PROCESS if (callback == null) { throw new ArgumentNullException("callback"); } object id = -1; foreach (EventType type in Enum.GetValues(typeof(EventType))) { lock (syncLock) { ResourcePool pool = null; ResourcePool poolDF = null; #region pool selection if (type == EventType.ItemAdded && (eventType & EventType.ItemAdded) != 0) { pool = _cqAddEventPool; poolDF = _cqAddEventDataFilter; } else if (type == EventType.ItemRemoved && (eventType & EventType.ItemRemoved) != 0) { pool = _cqRemoveEventPool; poolDF = _cqRemoveEventDataFilter; } else if (type == EventType.ItemUpdated && (eventType & EventType.ItemUpdated) != 0) { pool = _cqUpdateEventPool; poolDF = _cqUpdateEventDataFilter; } if (pool == null) { continue; } #endregion object temp = pool.GetResource(callback); short index = -1; index = Convert.ToInt16(temp); if (index > -1) { EventDataFilter datafilter = (EventDataFilter)poolDF.GetResource(index); object retVal = poolDF.RemoveResource(index); pool.RemoveResource(callback); if (retVal == null) { continue; } bool unregisterNotification = poolDF.Count == 0; EventDataFilter maxDataFilter = EventDataFilter.None; if (!unregisterNotification) { object[] callbackRefs = poolDF.GetAllResourceKeys(); if (callbackRefs != null) { for (int i = 0; i < callbackRefs.Length; i++) { EventDataFilter df = (EventDataFilter)callbackRefs[i]; if (df > maxDataFilter) { maxDataFilter = df; } if (maxDataFilter == EventDataFilter.DataWithMetadata) { break; } } } } if (type == EventType.ItemAdded) { _cqAddDF = maxDataFilter; } else if (type == EventType.ItemRemoved) { _cqRemoveDF = maxDataFilter; } else { _cqUpdateDF = maxDataFilter; } } } } }