
com.alachisoft.ncache.client.internal.caching.EventManager Maven / Gradle / Ivy
package com.alachisoft.ncache.client.internal.caching;
import Alachisoft.NCache.Caching.CallbackInfo;
import Alachisoft.NCache.Common.*;
import Alachisoft.NCache.Caching.Util.CollectionUtil;
import Alachisoft.NCache.Common.BitSet;
import Alachisoft.NCache.Common.Enum.SerializationFormat;
import Alachisoft.NCache.Common.Enum.UserObjectType;
import Alachisoft.NCache.Common.JSON.ExtendedJsonValueBase;
import Alachisoft.NCache.Common.Logger.JLogger;
import Alachisoft.NCache.Common.Threading.ThreadPool;
import com.alachisoft.ncache.client.*;
import com.alachisoft.ncache.client.internal.messaging.MessageEventItem;
import com.alachisoft.ncache.runtime.caching.DistributedDataStructure;
import com.alachisoft.ncache.runtime.caching.TopicSubscription;
import com.alachisoft.ncache.runtime.caching.messaging.MessageReceivedListener;
import com.alachisoft.ncache.runtime.events.*;
import com.alachisoft.ncache.runtime.events.EventType;
import com.alachisoft.ncache.runtime.exceptions.CacheException;
import com.alachisoft.ncache.runtime.exceptions.OperationFailedException;
import java.util.*;
/**
* Has the responsibility of creating and
* registering it against a ResourcePool
*/
public class EventManager {
public static final short REFSTART = -1;
public static final short SELECTIVEREFSTARTRemove = 8000;
public static final short SELECTIVEREFSTARTUpdate = 9000;
public static final short COLLECTIONREFSTARTAdd = 11000;
public static final short COLLECTIONREFSTARTUpdate = 12000;
public static final short COLLECTIONREFSTARTRemove = 13000;
MessageReceivedListener selectiveEventMessageReceivedListener =null;
MessageReceivedListener generalEventMessageReceivedListener = null ;
MessageReceivedListener collectionEventMessageReceivedListener = null;
private String _cacheName = null;
private JLogger _logger;
private Object sync_lock_selective = new Object();
private Object sync_lock_general = new Object();
private Object sync_lock_collection = new Object();
// private static AsyncCallback asyn = new System.AsyncCallback(EndAsyncCallback);
private CacheImpl _cache;
private PollNotificationListener pollnotifyListener;
private ResourcePool _addEventPool = null;
private ResourcePool _cacheClearEventPool = null;
private EventDataFilter _addDataFilter = EventDataFilter.None;
private ResourcePool _removeEventPool = null;
private EventDataFilter _removeDataFilter = EventDataFilter.None;
private ResourcePool _updateEventPool = null;
private EventDataFilter _updateDataFilter = EventDataFilter.None;
private short _addEventRegistrationSequence = REFSTART; //Significant difference from old callback numbers
private short _updateEventRegisrationSequenceId = REFSTART; //Significant difference from old callback numbers
private short _removeEventRegistrationSequenceId = REFSTART; //Significant difference from old callback numbers
private ResourcePool _selectiveRemoveEventPool = null;
private ResourcePool _selectiveRemoveEventIDPool = null;
private ResourcePool _oldSelectiveCallbackPool = new ResourcePool();
private ResourcePool _oldSelectiveMappingCallbackPool = new ResourcePool();
private short _selectveRemoveCallbackRef = SELECTIVEREFSTARTRemove;
private ResourcePool _selectiveUpdateEventPool = null;
private ResourcePool _selectiveUpdateEventIDPool = null;
private short _selectiveUpdateCallbackRef = SELECTIVEREFSTARTUpdate;
private EventDataFilter _generalAddDataFilter = EventDataFilter.None;
private EventDataFilter _generalUpdateDataFilter = EventDataFilter.None;
private EventDataFilter _generalRemoveDataFilter = EventDataFilter.None;
private PollNotificationListener _pollClientCacheCallback;
private PollNotificationListener _pollPubSubCallback;
private ResourcePool _collectionAddEventPool = null;
private ResourcePool _collectionAddEventIdPool = null;
private short _collectionAddCallbackRef = COLLECTIONREFSTARTAdd;
private ResourcePool _collectionUpdateEventPool = null;
private ResourcePool _collectionUpdateEventIdPool = null;
private short _collectionUpdateCallbackRef = COLLECTIONREFSTARTUpdate;
private ResourcePool _collectionRemoveEventPool = null;
private ResourcePool _collectionRemoveEventIdPool = null;
private short _collectionRemoveCallbackRef = COLLECTIONREFSTARTRemove;
private int addCallbacks = -1;
private int removeCallbacks = -1;
private int updateCallbacks = -1;
private TopicSubscriptionImpl _generalEventsSubscription;
private TopicSubscriptionImpl _collectionEventsSubscription;
private TopicSubscription _selectiveEventsSubscription;
private Set eventHandlerSet= new HashSet<>();
public EventManager(String cacheName, JLogger logger, CacheImpl cache) {
_cacheName = cacheName;
_logger = logger;
_cache = cache;
if(generalEventMessageReceivedListener == null){
generalEventMessageReceivedListener = new GeneralEventMessageReceivedListener(this);
}
if(collectionEventMessageReceivedListener == null){
collectionEventMessageReceivedListener = new CollectionEventMessageReceivedListener(this);
}
if(selectiveEventMessageReceivedListener ==null)
selectiveEventMessageReceivedListener =new SelectiveEventMessageReceivedListener(this);
}
private static void fire(Object obj) {
try {
Object[] objArray = (Object[]) obj;
((CacheDataModificationListener) objArray[0]).onCacheDataModified((String) objArray[1], (CacheEventArg) objArray[2]);
} catch (Exception e) {
}
}
public final short getAddSequenceNumber() {
return _addEventRegistrationSequence;
}
public final short getUpdateSequenceNumber() {
return _updateEventRegisrationSequenceId;
}
public final short getRemoveSequenceNumber() {
return _removeEventRegistrationSequenceId;
}
public final Object getSyncLockGeneral() {
return sync_lock_general;
}
public final Object getSyncLockSelective() {
return sync_lock_selective;
}
public Object getSyncLockCollection()
{
return sync_lock_collection;
}
/**
* Provide
*
* @param eventType
* @return
*/
public final short generalEventRefCountAgainstEvent(EventType eventType) {
if ((eventType.getValue() & EventType.ItemAdded.getValue()) != 0) {
return _addEventRegistrationSequence;
}
if ((eventType.getValue() & EventType.ItemRemoved.getValue()) != 0) {
return _removeEventRegistrationSequenceId;
}
if ((eventType.getValue() & EventType.ItemUpdated.getValue()) != 0) {
return _updateEventRegisrationSequenceId;
}
return -1;
}
/**
* Returns the filter type of the eventType
*
* @param eventType
* @return
*/
public final EventDataFilter maxFilterAgainstEvent(EventType eventType) {
if ((eventType.getValue() & EventType.ItemAdded.getValue()) != 0) {
return _addDataFilter;
}
if ((eventType.getValue() & EventType.ItemRemoved.getValue()) != 0) {
return _removeDataFilter;
}
if ((eventType.getValue() & EventType.ItemUpdated.getValue()) != 0) {
return _updateDataFilter;
}
return EventDataFilter.DataWithMetadata;
}
public final short[] registerSelectiveEvent(CacheDataModificationListener listener, EnumSet enumTypeSet, EventDataFilter datafilter) throws CacheException {
if (listener != null) {
//Avoiding new ResourcePool(inside = new Hashtable) at constructor level
if (_selectiveUpdateEventPool == null) {
_selectiveUpdateEventPool = new ResourcePool();
_selectiveUpdateEventIDPool = new ResourcePool();
}
if (_selectiveRemoveEventPool == null) {
_selectiveRemoveEventPool = new ResourcePool();
_selectiveRemoveEventIDPool = new ResourcePool();
}
//CacheEventDiscriptor discriptor = CacheEventDiscriptor.CreateCacheDiscriptor(eventType, _cacheName, callback, datafilter);
return registerSelectiveDiscriptor(listener, enumTypeSet);
} else {
return new short[]
{
-1, -1
};
}
}
// public final short[] registerSelectiveEvent(CacheDataModificationListener listener, EventTypeInternal eventType, EventDataFilter datafilter) throws CacheException {
// return registerSelectiveEvent(listener, eventType, datafilter, ListenerType.PushBasedNotification);
// }
public final short[] registerSelectiveEvent(CacheDataModificationListener listener, EnumSet eventTypes, EventDataFilter datafilter, ListenerType listenerType) throws CacheException {
if (listener != null) {
if (_selectiveUpdateEventPool == null) {
_selectiveUpdateEventPool = new ResourcePool();
_selectiveUpdateEventIDPool = new ResourcePool();
}
if (_selectiveRemoveEventPool == null) {
_selectiveRemoveEventPool = new ResourcePool();
_selectiveRemoveEventIDPool = new ResourcePool();
}
return registerSelectiveDiscriptor(listener, eventTypes, listenerType);
} else {
return null;
}
}
public CacheEventDescriptor registerGeneralEvents(CacheDataModificationListener listener, EnumSet eventTypes, EventDataFilter datafilter) throws CacheException {
if (listener != null) {
if (_addEventPool == null) {
_addEventPool = new ResourcePool();
}
if (_removeEventPool == null) {
_removeEventPool = new ResourcePool();
}
if (_updateEventPool == null) {
_updateEventPool = new ResourcePool();
}
CacheEventDescriptor discriptor = CacheEventDescriptor.createCacheDiscriptor(eventTypes, _cacheName, listener, datafilter);
//Registers the handle
boolean registeredDescriptor=false;
for(EventType eventType:eventTypes) {
EventTypeInternal eventTypeInternal = EventUtil.getEventTypeInternal(eventType);
registeredDescriptor = registerGeneralDiscriptor(discriptor, eventTypeInternal);
}
if (!registeredDescriptor) {
return null;
}
return discriptor;
} else {
return null;
}
}
public final void unregisterAll() {
//TODO
}
/**
* TheadSafe and no locks internally
*
* @param key
* @param item
* @param oldItem
* @param reason
* @param notifyAsync
*/
public final void raiseGeneralCacheNotification(final String key, EventType eventType, EventCacheItem item, EventCacheItem oldItem, CacheItemRemovedReason reason, boolean notifyAsync) {
try {
Object[] registeredDiscriptors = null;
ResourcePool eventPool = getEventPool(EventUtil.getEventTypeInternal(eventType));
if (eventPool != null) {
registeredDiscriptors = eventPool.GetAllResourceKeys();
}
if (registeredDiscriptors != null && registeredDiscriptors.length > 0) {
for (int i = 0; i < registeredDiscriptors.length; i++) {
final CacheEventDescriptor discriptor = (CacheEventDescriptor) ((registeredDiscriptors[i] instanceof CacheEventDescriptor) ? registeredDiscriptors[i] : null);
if (discriptor == null) {
continue;
}
BitSet bitSet = new BitSet();
if (_cache.getSerializationFormat() == SerializationFormat.Json)
bitSet.SetBit((byte) BitSetConstants.JsonData);
if (item != null)
EventCacheItemWrapperInternal.setValue(item,_cache.safeDeserialize(item.getValue(null), _cache.getSerializationContext(), bitSet, UserObjectType.CacheItem,null));
if (oldItem != null)
EventCacheItemWrapperInternal.setValue(oldItem,_cache.safeDeserialize(oldItem.getValue(null), _cache.getSerializationContext(), bitSet, UserObjectType.CacheItem,null));
CacheEventArg arg = createCacheEventArgument(discriptor.getDataFilter(), key, _cacheName, eventType, item, oldItem, reason);
arg.setDescriptor(discriptor);
if (notifyAsync) {
ThreadPool.getInstance().executeTask((new Runnable() {
@Override
public void run() {
fire(new Object[]
{
discriptor.getCacheDataNotificationListener(), key, arg
});
}
}));
} else {
discriptor.getCacheDataNotificationListener().onCacheDataModified(key, arg);
}
}
}
} catch (RuntimeException | OperationFailedException ex) {
if (_logger != null && _logger.getIsErrorEnabled()) {
_logger.CriticalInfo(ex.toString());
}
}
}
private CacheEventArg createCacheEventArgument(EventDataFilter dataFilter, String key, String cacheName, EventType eventType, EventCacheItem item, EventCacheItem oldItem, CacheItemRemovedReason removedReason) {
EventCacheItem cloneItem = null;
EventCacheItem cloneOldItem = null;
if (dataFilter != EventDataFilter.None && item != null) {
Object tempVar = item.clone();
cloneItem = (EventCacheItem) ((tempVar instanceof EventCacheItem) ? tempVar : null);
if (cloneItem != null) {
if (dataFilter == EventDataFilter.Metadata) {
EventCacheItemWrapperInternal.setValue(cloneItem,null);
}
}
}
if (dataFilter != EventDataFilter.None && oldItem != null) {
Object tempVar2 = oldItem.clone();
cloneOldItem = (EventCacheItem) ((tempVar2 instanceof EventCacheItem) ? tempVar2 : null);
if (cloneOldItem != null) {
if (dataFilter == EventDataFilter.Metadata) {
EventCacheItemWrapperInternal.setValue(cloneOldItem,null);
}
}
}
CacheEventArg eventArg = new CacheEventArg(key, cacheName, eventType, cloneItem, null, removedReason);
if (eventType == EventType.ItemUpdated) {
eventArg.setOldItem(cloneOldItem);
}
return eventArg;
}
/**
* TheadSafe and no locks internally
*
* @param key
* @param item
* @param oldItem
* @param reason
* @param _notifyAsync
* @param eventhandle
*/
public final void raiseSelectiveCacheNotification(final String key, EnumSet eventEnumSet, EventCacheItem item, EventCacheItem oldItem, CacheItemRemovedReason reason, boolean _notifyAsync, EventHandle eventhandle, EventDataFilter dataFilter) {
try {
ResourcePool poolID = null;
if (eventEnumSet.contains(EventType.ItemUpdated)) {
poolID = _selectiveUpdateEventIDPool;
//arg = new CacheEventArg(key, _cacheName, EventType.ItemUpdated, item, null, oldItem);
} else if (eventEnumSet.contains(EventType.ItemRemoved)) {
poolID = _selectiveRemoveEventIDPool;
//arg = new CacheEventArg(key, _cacheName, EventType.ItemRemoved, item, null, reason);
}
if (poolID == null) {
return;
}
final CacheEventArg arg = createCacheEventArgument(dataFilter, key, _cacheName, EventUtil.getEventType(eventEnumSet), item, oldItem, reason);
Object tempVar = poolID.GetResource((short) eventhandle.getHandle());
final CacheDataModificationListener callback = (CacheDataModificationListener) ((tempVar instanceof CacheDataModificationListener) ? tempVar : null);
if (callback == null) //Can occur if Unregistered concurrently
{
return;
}
if (_notifyAsync) //callback.BeginInvoke(key, arg, asyn, null);
{
ThreadPool.getInstance().executeTask(new Runnable() {
@Override
public void run() {
fire(new Object[]
{
callback, key, arg
});
}
});
//System.Threading.ThreadPool.QueueUserWorkItem(waitC, new Object[]{callback, key, arg}); //Faster and better
} else {
callback.onCacheDataModified(key, arg);
}
} catch (RuntimeException ex) {
if (_logger != null && _logger.getIsErrorEnabled()) {
_logger.CriticalInfo(ex.toString());
}
}
}
/**
* Returning Negative value means operation not successful
*
* @return short array
*
* 1st value is Update callbackRef
nd value is removeRef
*/
private short[] registerSelectiveDiscriptor(CacheDataModificationListener listener, EnumSet eventTypes, ListenerType listenerType) throws CacheException {
if (listener == null) {
return null; //FAIL CONDITION
}
short[] returnValue = new short[]{-1, -1}; //First value update callback ref & sencond is remove callbackref
for (EventType type : eventTypes) {
if (type == EventType.ItemAdded) //ItemAdded not supported Yet
{
continue;
}
synchronized (getSyncLockSelective()) {
ResourcePool pool = null;
ResourcePool poolID = null;
//region pool selection
if (type == EventType.ItemRemoved ) {
pool = _selectiveRemoveEventPool;
poolID = _selectiveRemoveEventIDPool;
} else if (type == EventType.ItemUpdated ) {
pool = _selectiveUpdateEventPool;
poolID = _selectiveUpdateEventIDPool;
}
if (pool == null) {
continue;
}
//endregion
while (true) {
int i = type == EventType.ItemUpdated ? 0 : 1;
if (pool.GetResource(listener) == null) {
returnValue[i] = type == EventType.ItemUpdated ? ++_selectiveUpdateCallbackRef : ++_selectveRemoveCallbackRef;
pool.AddResource(listener, returnValue[i]);
poolID.AddResource(returnValue[i], listener);
break;
} else {
try {
short cref = (short) pool.GetResource(listener);
if (cref < 0) {
break; //FAIL CONDITION
}
//add it again into the table for updating ref count.
pool.AddResource(listener, cref);
poolID.AddResource(cref, listener);
returnValue[i] = cref;
break;
} catch (NullPointerException e) {
//Legacy code: can create an infinite loop
//Recomendation of returning a negative number instead of continue
continue;
}
}
}
}
}
if (_selectiveEventsSubscription == null && listenerType != ListenerType.PullBasedCallback) {
TopicImpl topic = (TopicImpl) _cache._messagingService.getTopic(TopicConstant.ItemLevelEventsTopic, true);
_selectiveEventsSubscription = topic.createEventSubscription(selectiveEventMessageReceivedListener);
}
return returnValue;
}
private short[] registerSelectiveDiscriptor(CacheDataModificationListener listener, EnumSet enumTypeSet) throws CacheException {
if (listener == null) {
return null; //FAIL CONDITION
}
short[] returnValue = new short[]
{
-1, -1
}; //First value update callback ref & sencond is remove callbackref
for (EventType type : EventType.values()) {
if (type == EventType.ItemAdded) //ItemAdded not supported Yet
{
continue;
}
synchronized (getSyncLockSelective()) {
ResourcePool pool = null;
ResourcePool poolID = null;
if (type.equals(EventType.ItemRemoved)
&& enumTypeSet.contains(type)) {
pool = _selectiveRemoveEventPool;
poolID = _selectiveRemoveEventIDPool;
} else if (type.equals(EventType.ItemUpdated)
&& enumTypeSet.contains(type)) {
pool = _selectiveUpdateEventPool;
poolID = _selectiveUpdateEventIDPool;
}
if (pool == null) {
continue;
}
while (true) {
int i = type.equals(EventType.ItemUpdated) ? 0 : 1;
if (pool.GetResource(listener) == null) {
returnValue[i] = type.equals(EventType.ItemUpdated) ? ++_selectiveUpdateCallbackRef : ++_selectveRemoveCallbackRef;
pool.AddResource(listener, returnValue[i]);
poolID.AddResource(returnValue[i], listener);
break;
} else {
try {
if (pool.GetResource(listener) != null) {
short cref = (Short) pool.GetResource(listener);
if (cref < 0) {
break; //FAIL CONDITION
}
//add it again into the table for updating ref count.
pool.AddResource(listener, cref);
poolID.AddResource(cref, listener);
returnValue[i] = cref;
break;
}
} catch (NullPointerException e) {
//Legacy code: can create an infinite loop
//Recomendation of returning a negative number instead of continue
continue;
}
}
}
if (_selectiveEventsSubscription == null )
{
TopicImpl topic = (TopicImpl)_cache._messagingService.getTopic(TopicConstant.ItemLevelEventsTopic, true);
SelectiveEventMessageReceivedListener eventListener=new SelectiveEventMessageReceivedListener(this);
_selectiveEventsSubscription = (TopicSubscription)topic.createEventSubscription(eventListener);
}
}
}
return returnValue;
}
public void onSelectiveEventsMessageRecieved(MessageEventItem eventMessage) {
String key = eventMessage.getKey();
CallbackInfo cbInfo = new CallbackInfo(null, eventMessage.getCallback(), eventMessage.getDataFilter());
EventHandle handle = null;
if (cbInfo != null)
{
short handler = (short)cbInfo.getCallback();
handle = new EventHandle(handler);
}
switch (eventMessage.getEventType())
{
case ITEM_UPDATED_CALLBACK:
raiseSelectiveCacheNotification(key, EnumSet.of(EventType.ItemUpdated), eventMessage.getItem(), eventMessage.getOldItem(), CacheItemRemovedReason.Underused, false, handle, cbInfo.getDataFilter());
break;
case ITEM_REMOVED_CALLBACK:
raiseSelectiveCacheNotification(key, EnumSet.of(EventType.ItemRemoved), eventMessage.getItem(), null, eventMessage.getReason(), false, handle, cbInfo.getDataFilter());
break;
}
}
private boolean registerGeneralDiscriptor(CacheEventDescriptor discriptor, EventTypeInternal eventType) throws CacheException {
if (discriptor == null) {
return false; //FAIL CONDITION
}
EventHandle handle = null;
for (EventTypeInternal type : EventTypeInternal.values()) {
ResourcePool pool = null;
boolean registrationUpdated = false;
if (type == eventType) {
pool = getEventPool(type);
}
if (pool == null) {
continue;
}
short registrationSequenceId = -1;
synchronized (getSyncLockGeneral()) {
pool.AddResource(discriptor, 1); // Everytime a new Discriptor is forcefully created
//Keeps a sequence number
switch (type) {
case ItemAdded:
if (discriptor.getDataFilter() != _generalAddDataFilter || _addEventRegistrationSequence == REFSTART) {
registrationUpdated = true;
registrationSequenceId = ++_addEventRegistrationSequence;
_generalAddDataFilter = discriptor.getDataFilter();
} else {
registrationSequenceId = _addEventRegistrationSequence;
}
break;
case ItemRemoved:
if (discriptor.getDataFilter() != _generalRemoveDataFilter || _removeEventRegistrationSequenceId == REFSTART) {
registrationUpdated = true;
registrationSequenceId = ++_removeEventRegistrationSequenceId;
_generalRemoveDataFilter = discriptor.getDataFilter();
} else {
registrationSequenceId = _removeEventRegistrationSequenceId;
}
break;
case ItemUpdated:
if (discriptor.getDataFilter() != _generalUpdateDataFilter || _updateEventRegisrationSequenceId == REFSTART) {
registrationUpdated = true;
registrationSequenceId = ++_updateEventRegisrationSequenceId;
_generalUpdateDataFilter = discriptor.getDataFilter();
} else {
registrationSequenceId = _updateEventRegisrationSequenceId;
}
break;
}
//Although the handle doesnt matter in general events
if (handle == null) {
handle = new EventHandle(registrationSequenceId);
}
}
if (_cache != null && registrationSequenceId != -1) {
_cache.addCacheNotificationDataFilter(type, discriptor.getDataFilter(), registrationSequenceId);
}
}
//Check for avoiding multiple subscriptions
if (_generalEventsSubscription == null) {
TopicImpl topic = (TopicImpl) _cache._messagingService.getTopic(TopicConstant.GeneralEventsTopic, true);
_generalEventsSubscription = (TopicSubscriptionImpl) topic.createEventSubscription(generalEventMessageReceivedListener);
}
discriptor.setIsRegistered(true);
discriptor.setHandle(handle);
return true;
}
/**
* Unregisters CacheDataNotificationCallback
*
* Flag based unregistration
*
* @param listener
*/
public final short[] unRegisterSelectiveNotification(CacheDataModificationListener listener, EnumSet eventTypes) throws Exception {
if (listener == null) {
return null;
}
short[] returnValue = new short[]
{
-1, -1
};
for (EventType type : eventTypes) {
if (type == EventType.ItemAdded) //ItemAdded not supported Yet
{
continue;
}
Object id = -1;
synchronized (getSyncLockSelective()) {
ResourcePool pool = null;
ResourcePool poolID = null;
///#region pool selection
if (type.equals(EventType.ItemRemoved)) {
pool = _selectiveRemoveEventPool;
poolID = _selectiveRemoveEventIDPool;
if (pool == null)
removeCallbacks = 0;
} else if (type.equals(EventType.ItemUpdated) ) {
pool = _selectiveUpdateEventPool;
poolID = _selectiveUpdateEventIDPool;
if (pool == null)
updateCallbacks = 0;
}
if(removeCallbacks==0 && updateCallbacks==0)
{
_selectiveEventsSubscription.unSubscribe();
_selectiveEventsSubscription=null;
}
if (pool == null) {
continue;
}
//Taimoor : For selective callback, we dont remove the callback as it can create chaos if user try to unregister
//a callback more then one time or against wrong items.
//cb = "iucb-" + System.Diagnostics.Process.GetCurrentProcess().Id + updateCallback.Method.Name;
//id = _selectiveEventPool.GetResource(discriptor);
int i = type == EventType.ItemUpdated ? 0 : 1;
id = pool.GetResource(listener);
if (id instanceof Short) {
returnValue[i] = (Short) id;
}
}
}
return returnValue;
}
public final EventHandle unRegisterDiscriptor(CacheEventDescriptor discriptor) throws Exception {
if (discriptor == null || !discriptor.getIsRegistered()) {
return null;
}
for (EventType type : EventType.values()) {
ResourcePool pool = null;
if (discriptor.getRegisteredAgainst().contains(type)) {
pool = getEventPool(EventUtil.getEventTypeInternal(type));
}
if (pool == null) {
continue;
}
short registrationSequenceId = -1;
boolean unregisterNotification;
EventDataFilter maxDataFilter = EventDataFilter.None;
synchronized (getSyncLockGeneral()) {
Object retVal = pool.RemoveResource(discriptor);
if (retVal == null) {
continue;
}
unregisterNotification = pool.getCount() == 0;
if (!unregisterNotification) {
Object[] pooledDescriptors = pool.GetAllResourceKeys();
if (pooledDescriptors != null) {
for (int i = 0; i < pooledDescriptors.length; i++) {
CacheEventDescriptor pooledDescriptor = (CacheEventDescriptor) ((pooledDescriptors[i] instanceof CacheEventDescriptor) ? pooledDescriptors[i] : null);
if (pooledDescriptor != null && pooledDescriptor.getDataFilter().getValue() > maxDataFilter.getValue()) {
maxDataFilter = pooledDescriptor.getDataFilter();
}
if (maxDataFilter.getValue() == EventDataFilter.DataWithMetadata.getValue()) {
break;
}
}
}
}
discriptor.setIsRegistered(false);
switch (type) {
case ItemAdded:
//Data filter is being updated
if (maxDataFilter != _generalAddDataFilter) {
_generalAddDataFilter = maxDataFilter;
registrationSequenceId = ++_addEventRegistrationSequence;
}
if (unregisterNotification) {
_generalAddDataFilter = EventDataFilter.None;
}
break;
case ItemRemoved:
if (maxDataFilter != _generalRemoveDataFilter) {
_generalRemoveDataFilter = maxDataFilter;
registrationSequenceId = ++_removeEventRegistrationSequenceId;
}
if (unregisterNotification) {
_generalAddDataFilter = EventDataFilter.None;
}
break;
case ItemUpdated:
if (maxDataFilter != _generalUpdateDataFilter) {
_generalUpdateDataFilter = maxDataFilter;
registrationSequenceId = ++_updateEventRegisrationSequenceId;
}
if (unregisterNotification) {
_generalAddDataFilter = EventDataFilter.None;
}
break;
}
}
if (_cache != null) {
if (unregisterNotification) {
_cache.removeGeneralCacheNotification(EventUtil.getEventTypeInternal(type));
if(_generalEventsSubscription!=null)
{
_generalEventsSubscription.unSubscribeEventTopic();
_generalEventsSubscription=null;
}
} else if (registrationSequenceId != -1) {
//only caused update of data filter either upgrade or downgrade
_cache.addCacheNotificationDataFilter(EventUtil.getEventTypeInternal(type), maxDataFilter, registrationSequenceId);
}
}
}
return null;
}
public final EventRegistrationInfo[] getEventRegistrationInfo() {
java.util.ArrayList registeredEvents = new java.util.ArrayList();
synchronized (getSyncLockGeneral()) {
if (_addEventPool != null && _addEventPool.getCount() > 0) {
registeredEvents.add(new EventRegistrationInfo(EventType.ItemAdded, _generalAddDataFilter, _addEventRegistrationSequence));
}
if (_updateEventPool != null && _updateEventPool.getCount() > 0) {
registeredEvents.add(new EventRegistrationInfo(EventType.ItemUpdated, _generalUpdateDataFilter, _updateEventRegisrationSequenceId));
}
if (_removeEventPool != null && _removeEventPool.getCount() > 0) {
registeredEvents.add(new EventRegistrationInfo(EventType.ItemRemoved, _generalRemoveDataFilter, _removeEventRegistrationSequenceId));
}
}
return registeredEvents.toArray(new EventRegistrationInfo[0]);
}
private ResourcePool getEventPool(EventTypeInternal eventType) {
ResourcePool pool = null;
if (eventType == EventTypeInternal.ItemAdded) {
pool = _addEventPool;
} else if (eventType == EventTypeInternal.ItemRemoved) {
pool = _removeEventPool;
} else if (eventType == EventTypeInternal.ItemUpdated) {
pool = _updateEventPool;
}
return pool;
}
public void raisePollNotification(short callbackId, EventTypeInternal eventType)
{
try
{
PollNotificationListener _pollCallback = null;
if ((eventType == EventTypeInternal.ClientCache) )
{
_pollCallback = _pollClientCacheCallback;
}
else if ((eventType == EventTypeInternal.PubSub))
{
_pollCallback = _pollPubSubCallback;
}
if (_pollCallback != null)
_pollCallback.onPollNotified();
}
catch (Exception ex)
{
if (_logger != null && _logger.getIsErrorEnabled()) _logger.CriticalInfo(ex.getMessage());
}
}
public short registerPollingEvent(PollNotificationListener pollNotifyListener, EventTypeInternal eventType) {
// Only one poll callback can be configured.
// No need to use pools.
if (eventType == EventTypeInternal.ClientCache) {
_pollClientCacheCallback = pollNotifyListener;
} else if (eventType == EventTypeInternal.PubSub) {
_pollPubSubCallback = pollNotifyListener;
}
return 10001;
}
public short[] registerCollectionEvent(DataStructureDataChangeListener dataStructureDataChangeListener, EnumSet enumSet, DataTypeEventDataFilter datafilter) throws CacheException {
if (dataStructureDataChangeListener != null)
{
if (_collectionAddEventPool == null)
{
_collectionAddEventPool = new ResourcePool();
_collectionAddEventIdPool = new ResourcePool();
}
if (_collectionUpdateEventPool == null)
{
_collectionUpdateEventPool = new ResourcePool();
_collectionUpdateEventIdPool = new ResourcePool();
}
if (_collectionRemoveEventPool == null)
{
_collectionRemoveEventPool = new ResourcePool();
_collectionRemoveEventIdPool = new ResourcePool();
}
return registerCollectionDescriptor(dataStructureDataChangeListener, enumSet);
}
else
{
return null;
}
}
public short[] UnregisterCollectionNotification(DataStructureDataChangeListener listener, EnumSet enumSet) throws Exception {
if (listener == null)
{
return null;
}
short[] returnValue = new short[] {-1, -1, -1}; // First value add callback ref & second is update callback ref & third is remove callbackref
for (EventTypeInternal type : enumSet)
{
Object id = -1;
synchronized (getSyncLockCollection())
{
ResourcePool pool = null;
ResourcePool poolID = null;
if (type == EventTypeInternal.ItemAdded)
{
pool = _collectionAddEventPool;
poolID = _collectionAddEventIdPool;
if (pool == null)
{
addCallbacks = 0;
}
}
if (type == EventTypeInternal.ItemRemoved)
{
pool = _collectionRemoveEventPool;
poolID = _collectionRemoveEventIdPool;
if (pool == null)
{
removeCallbacks = 0;
}
}
else if (type == EventTypeInternal.ItemUpdated)
{
pool = _collectionUpdateEventPool;
poolID = _collectionUpdateEventIdPool;
if (pool == null)
{
updateCallbacks = 0;
}
}
if (addCallbacks == 0 && removeCallbacks == 0 && updateCallbacks == 0)
{
_collectionEventsSubscription.unSubscribeEventTopic();
_collectionEventsSubscription = null;
}
if (pool == null)
{
continue;
}
// Taimoor : For selective callback, we dont remove the callback as it can create chaos if user tries to unregister
// a callback more then one time or against wrong items.
int i = type == EventTypeInternal.ItemAdded ? 0 : (type == EventTypeInternal.ItemUpdated ? 1 : 2);
id = pool.GetResource(listener);
if (id instanceof Short)
{
returnValue[i] = (Short)id;
}
}
}
return returnValue;
}
private short[] registerCollectionDescriptor(DataStructureDataChangeListener listener, EnumSet enumSet) throws CacheException {
if (listener == null)
{
return null;
}
// First value add callback ref & sencond is update callbackref & third is remove callbackref
short[] returnValue = new short[] {-1, -1, -1};
for (EventTypeInternal type : enumSet)
{
synchronized (getSyncLockCollection())
{
ResourcePool pool = null;
ResourcePool poolId = null;
if (type == EventTypeInternal.ItemAdded)
{
pool = _collectionAddEventPool;
poolId = _collectionAddEventIdPool;
}
else if (type == EventTypeInternal.ItemUpdated)
{
pool = _collectionUpdateEventPool;
poolId = _collectionUpdateEventIdPool;
}
else if (type == EventTypeInternal.ItemRemoved)
{
pool = _collectionRemoveEventPool;
poolId = _collectionRemoveEventIdPool;
}
if (pool == null)
{
continue;
}
while (true)
{
int index = type == EventTypeInternal.ItemAdded ? 0 : (type == EventTypeInternal.ItemUpdated ? 1 : 2);
if (pool.GetResource(listener) == null)
{
returnValue[index] = type == EventTypeInternal.ItemAdded ?++_collectionAddCallbackRef : (type == EventTypeInternal.ItemUpdated ?++_collectionUpdateCallbackRef :++_collectionRemoveCallbackRef);
pool.AddResource(listener, returnValue[index]);
poolId.AddResource(returnValue[index], listener);
break;
}
else
{
try
{
short cref = (short)pool.GetResource(listener);
if (cref < 0)
{
break;
}
// Add it again into the table for updating ref count.
pool.AddResource(listener, cref);
poolId.AddResource(cref, listener);
returnValue[index] = cref;
break;
}
catch (NullPointerException e)
{
//Legacy code: can create an infinite loop
//Recomendation of returning a negative number instead of continue
continue;
}
}
}
}
}
if (_collectionEventsSubscription == null)
{
TopicImpl topic = (TopicImpl)_cache._messagingService.getTopic(TopicConstant.CollectionEventsTopic, true);
_collectionEventsSubscription = (TopicSubscriptionImpl)topic.createEventSubscription(collectionEventMessageReceivedListener);
}
return returnValue;
}
public short registerSelectiveCallback(CacheItemRemovedListener removedCallback, ListenerType listenerType) throws CacheException {
if (removedCallback == null) {
return -1;
}
synchronized (getSyncLockSelective()) {
SelectiveRemoveListenerWrapper callbackWrapper = null;
if (_oldSelectiveCallbackPool.GetResource(removedCallback) == null) {
callbackWrapper = new SelectiveRemoveListenerWrapper(removedCallback);
_oldSelectiveCallbackPool.AddResource(removedCallback, callbackWrapper);
_oldSelectiveMappingCallbackPool.AddResource(callbackWrapper, removedCallback);
} else {
callbackWrapper = (SelectiveRemoveListenerWrapper) _oldSelectiveCallbackPool.GetResource(removedCallback);
_oldSelectiveCallbackPool.AddResource(removedCallback, callbackWrapper); //just to increment the refCount
}
short[] callbackIds = registerSelectiveEvent(callbackWrapper.getMappingListener(), EnumSet.of(EventType.ItemRemoved), EventDataFilter.DataWithMetadata, listenerType);
return callbackIds[1];
}
}
public short registerSelectiveCallback(CacheItemUpdatedListener updatedCallback, ListenerType listenerType) throws CacheException {
if (updatedCallback == null) {
return -1;
}
synchronized (getSyncLockSelective()) {
SelectiveUpdateListenerWrapper callbackWrapper = null;
if (_oldSelectiveCallbackPool.GetResource(updatedCallback) == null) {
callbackWrapper = new SelectiveUpdateListenerWrapper(updatedCallback);
_oldSelectiveCallbackPool.AddResource(updatedCallback, callbackWrapper);
_oldSelectiveMappingCallbackPool.AddResource(callbackWrapper, updatedCallback);
} else {
callbackWrapper = (SelectiveUpdateListenerWrapper) _oldSelectiveCallbackPool.GetResource(updatedCallback);
_oldSelectiveCallbackPool.AddResource(updatedCallback, callbackWrapper); //just to increment the refCount
}
short[] callbackIds = registerSelectiveEvent(callbackWrapper.getMappingListener(), EnumSet.of(EventType.ItemRemoved), EventDataFilter.DataWithMetadata, listenerType);
return callbackIds[1];
}
}
void raiseCollectionNotification(String collectionName, EventTypeInternal eventType, DistributedDataStructure dataType, DataTypeEventDataFilter dataFilter, Object collectionItem, Object oldCollectionItem, boolean _notifyAsync, EventHandle handle) {
try {
ResourcePool poolID = null;
DataStructureEventArg arg = null;
if (collectionItem != null)
{
if (dataType == DistributedDataStructure.Map)
{
java.util.Map.Entry pair = (java.util.Map.Entry)collectionItem;
collectionItem = new AbstractMap.SimpleEntry(pair.getKey(), CollectionUtil.
© 2015 - 2025 Weber Informatics LLC | Privacy Policy