@Override public Map<String, Number> call() throws Exception { Map<String, Number> map = new HashMap<>(); Stats stats = remoteCache.getStats(); map.put(AVERAGE_READ_TIME, stats.getAverageReadTime()); map.put(AVERAGE_WRITE_TIME, stats.getAverageWriteTime()); map.put(AVERAGE_REMOVE_TIME, stats.getAverageRemoveTime()); map.put(EVICTIONS, stats.getEvictions()); map.put(HITS, stats.getHits()); map.put(MISSES, stats.getMisses()); final CacheMode cacheMode = getCacheMode(remoteCache); // for replicated caches, we don't need to send the number of entries since it is the same in // all the nodes. if (cacheMode.isDistributed()) { map.put(NUMBER_OF_ENTRIES, stats.getCurrentNumberOfEntries() / numOwners()); } else if (!cacheMode.isReplicated()) { map.put(NUMBER_OF_ENTRIES, stats.getCurrentNumberOfEntries()); } map.put(STORES, stats.getStores()); map.put(REMOVE_HITS, stats.getRemoveHits()); map.put(REMOVE_MISSES, stats.getRemoveMisses()); map.put(TIME_SINCE_START, stats.getTimeSinceStart()); LockManager lockManager = remoteCache.getLockManager(); map.put(NUMBER_OF_LOCKS_HELD, lockManager.getNumberOfLocksHeld()); // number of locks available is not exposed through the LockManager interface map.put(NUMBER_OF_LOCKS_AVAILABLE, 0); // invalidations InvalidationInterceptor invalidationInterceptor = getFirstInterceptorWhichExtends(remoteCache, InvalidationInterceptor.class); if (invalidationInterceptor != null) { map.put(INVALIDATIONS, invalidationInterceptor.getInvalidations()); } else { map.put(INVALIDATIONS, 0); } // passivations PassivationManager pManager = remoteCache.getComponentRegistry().getComponent(PassivationManager.class); if (pManager != null) { map.put(PASSIVATIONS, pManager.getPassivations()); } else { map.put(PASSIVATIONS, 0); } // activations ActivationManager aManager = remoteCache.getComponentRegistry().getComponent(ActivationManager.class); if (pManager != null) { map.put(ACTIVATIONS, aManager.getActivationCount()); } else { map.put(ACTIVATIONS, 0); } // cache loaders ActivationInterceptor aInterceptor = getFirstInterceptorWhichExtends(remoteCache, ActivationInterceptor.class); if (aInterceptor != null) { map.put(CACHE_LOADER_LOADS, aInterceptor.getCacheLoaderLoads()); map.put(CACHE_LOADER_MISSES, aInterceptor.getCacheLoaderMisses()); } else { map.put(CACHE_LOADER_LOADS, 0); map.put(CACHE_LOADER_MISSES, 0); } // cache store CacheWriterInterceptor interceptor = getFirstInterceptorWhichExtends(remoteCache, CacheWriterInterceptor.class); if (interceptor != null) { map.put(CACHE_WRITER_STORES, interceptor.getWritesToTheStores()); } else { map.put(CACHE_WRITER_STORES, 0); } return map; }
/** * Adds the listener using the provided filter converter and class loader. The provided builder is * used to add additional configuration including (clustered, onlyPrimary & identifier) which can * be used after this method is completed to see what values were used in the addition of this * listener * * @param listener * @param filter * @param converter * @param classLoader * @param <C> * @return */ public <C> void addListener( Object listener, CacheEventFilter<? super K, ? super V> filter, CacheEventConverter<? super K, ? super V, C> converter, ClassLoader classLoader) { Listener l = testListenerClassValidity(listener.getClass()); UUID generatedId = UUID.randomUUID(); CacheMode cacheMode = config.clustering().cacheMode(); CacheInvocationBuilder builder = new CacheInvocationBuilder(); builder .setIncludeCurrentState(l.includeCurrentState()) .setClustered(l.clustered()) .setOnlyPrimary( l.clustered() ? (cacheMode.isDistributed() ? true : false) : l.primaryOnly()) .setFilter(filter) .setConverter(converter) .setIdentifier(generatedId) .setClassLoader(classLoader); boolean foundMethods = validateAndAddListenerInvocation(listener, builder); if (foundMethods && l.clustered()) { if (cacheMode.isInvalidation()) { throw new UnsupportedOperationException( "Cluster listeners cannot be used with Invalidation Caches!"); } else if (cacheMode.isDistributed()) { clusterListenerIDs.put(listener, generatedId); EmbeddedCacheManager manager = cache.getCacheManager(); Address ourAddress = manager.getAddress(); List<Address> members = manager.getMembers(); // If we are the only member don't even worry about sending listeners if (members != null && members.size() > 1) { DistributedExecutionCompletionService decs = new DistributedExecutionCompletionService(distExecutorService); if (log.isTraceEnabled()) { log.tracef( "Replicating cluster listener to other nodes %s for cluster listener with id %s", members, generatedId); } Callable callable = new ClusterListenerReplicateCallable( generatedId, ourAddress, filter, converter, l.sync()); for (Address member : members) { if (!member.equals(ourAddress)) { decs.submit(member, callable); } } for (int i = 0; i < members.size() - 1; ++i) { try { decs.take().get(); } catch (InterruptedException e) { throw new CacheListenerException(e); } catch (ExecutionException e) { throw new CacheListenerException(e); } } int extraCount = 0; // If anyone else joined since we sent these we have to send the listeners again, since // they may have queried // before the other nodes got the new listener List<Address> membersAfter = manager.getMembers(); for (Address member : membersAfter) { if (!members.contains(member) && !member.equals(ourAddress)) { if (log.isTraceEnabled()) { log.tracef( "Found additional node %s that joined during replication of cluster listener with id %s", member, generatedId); } extraCount++; decs.submit(member, callable); } } for (int i = 0; i < extraCount; ++i) { try { decs.take().get(); } catch (InterruptedException e) { throw new CacheListenerException(e); } catch (ExecutionException e) { throw new CacheListenerException(e); } } } } } // If we have a segment listener handler, it means we have to do initial state QueueingSegmentListener handler = segmentHandler.remove(generatedId); if (handler != null) { if (log.isTraceEnabled()) { log.tracef("Listener %s requests initial state for cache", generatedId); } try (CloseableIterator<CacheEntry<K, C>> iterator = entryRetriever.retrieveEntries( filter == null ? null : new CacheEventFilterAsKeyValueFilter(filter), converter == null ? null : new CacheEventConverterAsConverter(converter), null, handler)) { while (iterator.hasNext()) { CacheEntry<K, C> entry = iterator.next(); // Mark the key as processed and see if we had a concurrent update Object value = handler.markKeyAsProcessing(entry.getKey()); if (value == BaseQueueingSegmentListener.REMOVED) { // Don't process this value if we had a concurrent remove continue; } raiseEventForInitialTransfer(generatedId, entry, builder.isClustered()); handler.notifiedKey(entry.getKey()); } } Set<CacheEntry> entries = handler.findCreatedEntries(); for (CacheEntry entry : entries) { raiseEventForInitialTransfer(generatedId, entry, builder.isClustered()); } if (log.isTraceEnabled()) { log.tracef("Listener %s initial state for cache completed", generatedId); } handler.transferComplete(); } }