/// <summary> /// Reaises the custom item remove call baack. /// </summary> /// <param name="key"></param> /// <param name="cbEntry"></param> internal void RaiseCustomRemoveCalbackNotifier(object key, CacheEntry cacheEntry, ItemRemoveReason reason, bool async, OperationContext operationContext, EventContext eventContext) { ArrayList destinations = null; ArrayList nodes = null; Hashtable intendedNotifiers = new Hashtable(); CallbackEntry cbEntry = cacheEntry.Value as CallbackEntry; if (cbEntry != null && cbEntry.ItemRemoveCallbackListener.Count > 0) { if (_stats.Nodes != null) { nodes = _stats.Nodes.Clone() as ArrayList; destinations = new ArrayList(); foreach (CallbackInfo cbInfo in cbEntry.ItemRemoveCallbackListener) { if (reason == ItemRemoveReason.Expired && cbInfo != null && !cbInfo.NotifyOnExpiration) continue; int index = nodes.IndexOf(new NodeInfo(Cluster.LocalAddress)); if (index != -1 && ((NodeInfo)nodes[index]).ConnectedClients.Contains(cbInfo.Client)) { if (!destinations.Contains(Cluster.LocalAddress)) { destinations.Add(Cluster.LocalAddress); } intendedNotifiers[cbInfo] = Cluster.LocalAddress; continue; } else { foreach (NodeInfo nInfo in nodes) { if (nInfo.ConnectedClients != null && nInfo.ConnectedClients.Contains(cbInfo.Client)) { if (!destinations.Contains(nInfo.Address)) { destinations.Add(nInfo.Address); intendedNotifiers[cbInfo] = nInfo.Address; break; } } } } } } } if (destinations != null && destinations.Count > 0) { if (operationContext == null) operationContext = new OperationContext(); if (eventContext == null || !eventContext.HasEventID(EventContextOperationType.CacheOperation)) { eventContext = CreateEventContext(operationContext, Persistence.EventType.ITEM_REMOVED_CALLBACK); eventContext.Item = CacheHelper.CreateCacheEventEntry(cbEntry.ItemRemoveCallbackListener, cacheEntry); eventContext.Add(EventContextFieldName.ItemRemoveCallbackList, cbEntry.ItemRemoveCallbackListener.Clone()); } object[] packed = new object[] { key, reason, intendedNotifiers, operationContext, eventContext }; ///Incase of parition, there can be same clients connected ///to multiple server. therefore the destinations list will contain more then ///one servers. so the callback will be sent to the same client through different server ///to avoid this, we will check the list for local server. if client is connected with ///local node, then there is no need to send callback to all other nodes ///if there is no local node, then we select the first node in the list. RaiseCustomRemoveCalbackNotifier(destinations, packed, async); } }