/** * Unmarshalls transfer object from remote node within a given context. * * @param ctx Grid kernal context that provides deployment and marshalling services. * @param sndNodeId {@link UUID} of the sender node. * @param msg Transfer object that contains original serialized object and deployment information. * @return Unmarshalled object. * @throws IgniteCheckedException If node cannot obtain deployment. */ static Object unmarshall(GridKernalContext ctx, UUID sndNodeId, GridAffinityMessage msg) throws IgniteCheckedException { GridDeployment dep = ctx.deploy() .getGlobalDeployment( msg.deploymentMode(), msg.sourceClassName(), msg.sourceClassName(), msg.userVersion(), sndNodeId, msg.classLoaderId(), msg.loaderParticipants(), null); if (dep == null) throw new IgniteDeploymentCheckedException( "Failed to obtain affinity object (is peer class loading turned on?): " + msg); Object src = U.unmarshal(ctx, msg.source(), U.resolveClassLoader(dep.classLoader(), ctx.config())); // Resource injection. ctx.resource().inject(dep, dep.deployedClass(msg.sourceClassName()), src); return src; }
/** {@inheritDoc} */ @Override public RegisterStatus register( final UUID nodeId, final UUID routineId, final GridKernalContext ctx) throws IgniteCheckedException { assert nodeId != null; assert routineId != null; assert ctx != null; if (locLsnr != null) ctx.resource().injectGeneric(locLsnr); if (rmtFilter != null) ctx.resource().injectGeneric(rmtFilter); entryBufs = new ConcurrentHashMap<>(); backupQueue = new ConcurrentLinkedDeque8<>(); ackBuf = new AcknowledgeBuffer(); rcvs = new ConcurrentHashMap<>(); final boolean loc = nodeId.equals(ctx.localNodeId()); assert !skipPrimaryCheck || loc; final GridCacheContext<K, V> cctx = cacheContext(ctx); if (!internal && cctx != null && initUpdCntrs != null) { Map<Integer, Long> map = cctx.topology().updateCounters(); for (Map.Entry<Integer, Long> e : map.entrySet()) { Long cntr0 = initUpdCntrs.get(e.getKey()); Long cntr1 = e.getValue(); if (cntr0 == null || cntr1 > cntr0) initUpdCntrs.put(e.getKey(), cntr1); } } CacheContinuousQueryListener<K, V> lsnr = new CacheContinuousQueryListener<K, V>() { @Override public void onExecution() { if (ctx.event().isRecordable(EVT_CACHE_QUERY_EXECUTED)) { ctx.event() .record( new CacheQueryExecutedEvent<>( ctx.discovery().localNode(), "Continuous query executed.", EVT_CACHE_QUERY_EXECUTED, CacheQueryType.CONTINUOUS.name(), cacheName, null, null, null, rmtFilter, null, nodeId, taskName())); } } /** {@inheritDoc} */ @Override public boolean keepBinary() { return keepBinary; } @Override public void onEntryUpdated( CacheContinuousQueryEvent<K, V> evt, boolean primary, boolean recordIgniteEvt) { if (ignoreExpired && evt.getEventType() == EventType.EXPIRED) return; final GridCacheContext<K, V> cctx = cacheContext(ctx); // Check that cache stopped. if (cctx == null) return; // skipPrimaryCheck is set only when listen locally for replicated cache events. assert !skipPrimaryCheck || (cctx.isReplicated() && ctx.localNodeId().equals(nodeId)); boolean notify = true; if (rmtFilter != null) { try { notify = rmtFilter.evaluate(evt); } catch (Exception e) { U.error( cctx.logger(CacheContinuousQueryHandler.class), "CacheEntryEventFilter failed: " + e); } } try { final CacheContinuousQueryEntry entry = evt.entry(); if (!notify) entry.markFiltered(); if (primary || skipPrimaryCheck) { if (loc) { if (!locCache) { Collection<CacheContinuousQueryEntry> entries = handleEvent(ctx, entry); if (!entries.isEmpty()) { final IgniteCache cache = cctx.kernalContext().cache().jcache(cctx.name()); Iterable<CacheEntryEvent<? extends K, ? extends V>> evts = F.viewReadOnly( entries, new C1< CacheContinuousQueryEntry, CacheEntryEvent<? extends K, ? extends V>>() { @Override public CacheEntryEvent<? extends K, ? extends V> apply( CacheContinuousQueryEntry e) { return new CacheContinuousQueryEvent<>(cache, cctx, e); } }, new IgnitePredicate<CacheContinuousQueryEntry>() { @Override public boolean apply(CacheContinuousQueryEntry entry) { return !entry.isFiltered(); } }); locLsnr.onUpdated(evts); if (!internal && !skipPrimaryCheck) sendBackupAcknowledge(ackBuf.onAcknowledged(entry), routineId, ctx); } } else { if (!entry.isFiltered()) locLsnr.onUpdated(F.<CacheEntryEvent<? extends K, ? extends V>>asList(evt)); } } else { if (!entry.isFiltered()) prepareEntry(cctx, nodeId, entry); CacheContinuousQueryEntry e = handleEntry(entry); if (e != null) ctx.continuous().addNotification(nodeId, routineId, entry, topic, sync, true); } } else { if (!internal) { // Skip init query and expire entries. if (entry.updateCounter() != -1L) { entry.markBackup(); backupQueue.add(entry); } } } } catch (ClusterTopologyCheckedException ex) { IgniteLogger log = ctx.log(getClass()); if (log.isDebugEnabled()) log.debug( "Failed to send event notification to node, node left cluster " + "[node=" + nodeId + ", err=" + ex + ']'); } catch (IgniteCheckedException ex) { U.error( ctx.log(getClass()), "Failed to send event notification to node: " + nodeId, ex); } if (recordIgniteEvt && notify) { ctx.event() .record( new CacheQueryReadEvent<>( ctx.discovery().localNode(), "Continuous query executed.", EVT_CACHE_QUERY_OBJECT_READ, CacheQueryType.CONTINUOUS.name(), cacheName, null, null, null, rmtFilter, null, nodeId, taskName(), evt.getKey(), evt.getValue(), evt.getOldValue(), null)); } } @Override public void onUnregister() { if (rmtFilter instanceof PlatformContinuousQueryFilter) ((PlatformContinuousQueryFilter) rmtFilter).onQueryUnregister(); } @Override public void cleanupBackupQueue(Map<Integer, Long> updateCntrs) { Iterator<CacheContinuousQueryEntry> it = backupQueue.iterator(); while (it.hasNext()) { CacheContinuousQueryEntry backupEntry = it.next(); Long updateCntr = updateCntrs.get(backupEntry.partition()); if (updateCntr != null && backupEntry.updateCounter() <= updateCntr) it.remove(); } } @Override public void flushBackupQueue(GridKernalContext ctx, AffinityTopologyVersion topVer) { if (backupQueue.isEmpty()) return; try { GridCacheContext<K, V> cctx = cacheContext(ctx); for (CacheContinuousQueryEntry e : backupQueue) { if (!e.isFiltered()) prepareEntry(cctx, nodeId, e); } ctx.continuous().addBackupNotification(nodeId, routineId, backupQueue, topic); backupQueue.clear(); } catch (IgniteCheckedException e) { U.error( ctx.log(getClass()), "Failed to send backup event notification to node: " + nodeId, e); } } @Override public void acknowledgeBackupOnTimeout(GridKernalContext ctx) { sendBackupAcknowledge(ackBuf.acknowledgeOnTimeout(), routineId, ctx); } @Override public void skipUpdateEvent( CacheContinuousQueryEvent<K, V> evt, AffinityTopologyVersion topVer) { try { assert evt != null; CacheContinuousQueryEntry e = evt.entry(); EntryBuffer buf = entryBufs.get(e.partition()); if (buf == null) { buf = new EntryBuffer(); EntryBuffer oldRec = entryBufs.putIfAbsent(e.partition(), buf); if (oldRec != null) buf = oldRec; } e = buf.skipEntry(e); if (e != null && !ctx.localNodeId().equals(nodeId)) ctx.continuous().addNotification(nodeId, routineId, e, topic, sync, true); } catch (ClusterTopologyCheckedException ex) { IgniteLogger log = ctx.log(getClass()); if (log.isDebugEnabled()) log.debug( "Failed to send event notification to node, node left cluster " + "[node=" + nodeId + ", err=" + ex + ']'); } catch (IgniteCheckedException ex) { U.error( ctx.log(getClass()), "Failed to send event notification to node: " + nodeId, ex); } } @Override public void onPartitionEvicted(int part) { for (Iterator<CacheContinuousQueryEntry> it = backupQueue.iterator(); it.hasNext(); ) { if (it.next().partition() == part) it.remove(); } } @Override public boolean oldValueRequired() { return oldValRequired; } @Override public boolean notifyExisting() { return notifyExisting; } private String taskName() { return ctx.security().enabled() ? ctx.task().resolveTaskName(taskHash) : null; } }; CacheContinuousQueryManager mgr = manager(ctx); if (mgr == null) return RegisterStatus.DELAYED; return mgr.registerListener(routineId, lsnr, internal); }