/// <summary> /// This method registers 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> /// <param name="datafilter">This enum is to describe when registering an event, upon raise how much data is /// retrieved from cache when the event is raised</param> /// <example> /// /// First create an ItemCallback /// <code> /// ItemCallback(string key, CacheEventArg e) /// { /// ... /// } /// </code> /// Then declare your continous query /// <code> /// ContinuousQuery cQ=new ContinuousQuery(query,Hashtable vals); /// </code> /// Then register your notification callback /// <code> /// cQ.RegisterNotification(new QueryDataNotificationCallback(ItemCallback),EventType.ItemAdded, EventDataFilter.None); /// </code> /// </example> public void RegisterNotification(QueryDataNotificationCallback callback, EventType eventType, EventDataFilter datafilter) { if (callback != null) { //Avoiding new ResourcePool(inside = new Hashtable) at constructor level if (_cqAddEventPool == null && (eventType & EventType.ItemAdded) != 0) { _cqAddEventPool = new ResourcePool(); _cqAddEventDataFilter = new ResourcePool(); } if (_cqRemoveEventPool == null && (eventType & EventType.ItemRemoved) != 0) { _cqRemoveEventPool = new ResourcePool(); _cqRemoveEventDataFilter = new ResourcePool(); } if (_cqUpdateEventPool == null && (eventType & EventType.ItemUpdated) != 0) { _cqUpdateEventPool = new ResourcePool(); _cqUpdateEventDataFilter = new ResourcePool(); } RegisterCQ(callback, eventType, datafilter); } }
public void RegisterRemoveNotification(ContinuousQueryItemRemovedCallback itemRemovedCallback) { if (itemRemovedCallback != null) { _itemRemoved += itemRemovedCallback; lock (syncLock) { if (++refremove == 1) { removeCallback = new QueryDataNotificationCallback(_notificationsWrapper.OnQueryChangeNotifiation); this.RegisterNotification(removeCallback, EventType.ItemRemoved, EventDataFilter.DataWithMetadata); } } } else { _itemRemoved = null; lock (syncLock) { if (refremove > 0) { refremove = 0; this.UnRegisterNotification(removeCallback, EventType.ItemRemoved); } } } }
public void RegisterUpdateNotification(ContinuousQueryItemUpdatedCallback itemUpdatedCallback) { if (itemUpdatedCallback != null) { _itemUpdated += itemUpdatedCallback; lock (syncLock) { if (++refupdate == 1) { updateCallback = new QueryDataNotificationCallback(_notificationsWrapper.OnQueryChangeNotifiation); this.RegisterNotification(updateCallback, EventType.ItemUpdated, EventDataFilter.None); } } } else { _itemUpdated = null; lock (syncLock) { if (refupdate > 0) { refupdate = 0; this.UnRegisterNotification(updateCallback, EventType.ItemUpdated); } } } }
private static void EndAsyncCallback(IAsyncResult arr) { QueryDataNotificationCallback subscribber = (QueryDataNotificationCallback)arr.AsyncState; try { if (subscribber != null) { subscribber.EndInvoke(arr); } } catch (Exception e) { } }
internal void FireCQEvents(string key, EventType eventType, EventCacheItem item, EventCacheItem oldItem, bool notifyAsync, string cacheName, BitSet flag, EventDataFilter datafilter) { try { CQEventArg arg = null; ICollection collection = null; ResourcePool pool = null; ResourcePool filterPool = null; if ((eventType & EventType.ItemAdded) != 0 && _cqAddEventPool != null) { pool = _cqAddEventPool; collection = _cqAddEventPool.Keys; filterPool = _cqAddEventDataFilter; } else if ((eventType & EventType.ItemUpdated) != 0 && _cqUpdateEventPool != null) { pool = _cqUpdateEventPool; collection = _cqUpdateEventPool.Keys; filterPool = _cqUpdateEventDataFilter; } else if ((eventType & EventType.ItemRemoved) != 0 && _cqRemoveEventPool != null) { pool = _cqRemoveEventPool; collection = _cqRemoveEventPool.Keys; filterPool = _cqRemoveEventDataFilter; } else { return; } if (collection != null && collection.Count > 0) { QueryDataNotificationCallback[] disc = null; lock (syncLock) { disc = new QueryDataNotificationCallback[collection.Count]; collection.CopyTo(disc, 0); //to avoid locking } for (int i = 0; i < disc.Length; i++) { short index = -1; object obj = pool.GetResource(disc[i]); index = Convert.ToInt16(obj); if (index > -1) { //Not to fire event if datafilter recieved is less than requried OR noDF present EventDataFilter queryDataFilter = (EventDataFilter)filterPool.GetResource(index); if ((eventType & EventType.ItemAdded) != 0) { arg = CreateCQEventArgument(queryDataFilter, key, cacheName, EventType.ItemAdded, item, oldItem); } else if ((eventType & EventType.ItemUpdated) != 0) { arg = CreateCQEventArgument(queryDataFilter, key, cacheName, EventType.ItemUpdated, item, oldItem); } else if ((eventType & EventType.ItemRemoved) != 0) { arg = CreateCQEventArgument(queryDataFilter, key, cacheName, EventType.ItemRemoved, item, oldItem); } else { return; } arg.ContinuousQuery = this; if (notifyAsync) { #if !NETCORE disc[i].BeginInvoke(key, arg, asyn, disc[i]); #elif NETCORE TaskFactory factory = new TaskFactory(); int temp = i; Task task = factory.StartNew(() => disc[temp](key, arg)); #endif } else { disc[i].Invoke(key, arg); } } } } } catch (Exception ex) { } }
private void RegisterCQ(QueryDataNotificationCallback callback, EventType eventType, EventDataFilter datafilter) { if (callback == null) { throw new ArgumentNullException("callback"); } 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 while (true) { if (pool.GetResource(callback) == null) { short refcallback = -1; if (type == EventType.ItemAdded) { refcallback = ++_cqAddCallbackRef; _cqAddDF = _cqAddDF < datafilter ? datafilter : _cqAddDF; } else if (type == EventType.ItemRemoved) { refcallback = ++_cqRemoveCallbackRef; _cqRemoveDF = _cqRemoveDF < datafilter ? datafilter : _cqRemoveDF; } else { refcallback = ++_cqUpdateCallbackRef; _cqUpdateDF = _cqUpdateDF < datafilter ? datafilter : _cqUpdateDF; } pool.AddResource(callback, refcallback); poolDF.AddResource(refcallback, datafilter); break; } else { try { short cref = (short)pool.GetResource(callback); if (cref < 0) { break; //FAIL CONDITION } poolDF.RemoveResource(cref); pool.RemoveResource(callback); //add it again into the table for updating ref count. pool.AddResource(callback, cref); poolDF.AddResource(cref, datafilter); break; } catch (NullReferenceException) { continue; } } } } } }
/// <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; } } } } }