/** {@inheritDoc} */ @Override public void stop() { spi.setListener(null); Map<String, List<GridDeployment>> copy; synchronized (mux) { copy = new HashMap<String, List<GridDeployment>>(cache); for (Entry<String, List<GridDeployment>> entry : copy.entrySet()) { entry.setValue(new ArrayList<GridDeployment>(entry.getValue())); } } for (List<GridDeployment> deps : copy.values()) { for (GridDeployment cls : deps) { // We don't record event, as recording causes invocation of // discovery manager which is already stopped. undeploy(cls.classLoader(), /*don't record event. */ false); } } if (log.isDebugEnabled()) { log.debug(stopInfo()); } }
/** * Records undeploy event. * * @param dep Undeployed class loader. * @param recordEvt Flag indicating whether to record events. */ private void recordUndeploy(GridDeployment dep, boolean recordEvt) { assert dep.isUndeployed(); if (ctx.event().isRecordable(EVT_TASK_UNDEPLOYED) || ctx.event().isRecordable(EVT_CLASS_UNDEPLOYED)) { for (Class<?> cls : dep.deployedClasses()) { boolean isTask = isTask(cls); String msg = isTask ? "Task locally undeployed: " + cls : "Class locally undeployed: " + cls; if (ctx.event().isRecordable(isTask ? EVT_TASK_UNDEPLOYED : EVT_CLASS_UNDEPLOYED)) { if (recordEvt) { GridDeploymentEvent evt = new GridDeploymentEvent(); evt.message(msg); evt.nodeId(ctx.localNodeId()); evt.type(isTask ? EVT_TASK_UNDEPLOYED : EVT_CLASS_UNDEPLOYED); evt.alias(getAlias(dep, cls)); ctx.event().record(evt); } } if (log.isInfoEnabled()) { log.info(msg); } } } }
/** * @param alias Class alias. * @return Deployed class. */ @Nullable private GridDeployment getDeployment(String alias) { assert Thread.holdsLock(mux); LinkedList<GridDeployment> deps = cache.get(alias); if (deps != null) { assert !deps.isEmpty(); GridDeployment dep = deps.getFirst(); if (!dep.isUndeployed()) { return dep; } } return null; }
/** {@inheritDoc} */ @Nullable @Override public GridDeployment getDeployment(GridUuid ldrId) { synchronized (mux) { for (List<GridDeployment> deps : cache.values()) { for (GridDeployment dep : deps) { if (dep.classLoaderId().equals(ldrId)) { return dep; } } } } for (GridDeployment dep : ctx.task().getUsedDeployments()) { if (dep.classLoaderId().equals(ldrId)) { return dep; } } return null; }
/** * @param ldr Class loader to undeploy. * @param recEvt Whether or not to record the event. */ private void undeploy(ClassLoader ldr, boolean recEvt) { Collection<GridDeployment> doomed = new HashSet<GridDeployment>(); synchronized (mux) { for (Iterator<LinkedList<GridDeployment>> i1 = cache.values().iterator(); i1.hasNext(); ) { LinkedList<GridDeployment> deps = i1.next(); for (Iterator<GridDeployment> i2 = deps.iterator(); i2.hasNext(); ) { GridDeployment dep = i2.next(); if (dep.classLoader() == ldr) { dep.undeploy(); i2.remove(); doomed.add(dep); if (log.isInfoEnabled()) { log.info("Removed undeployed class: " + dep); } } } if (deps.isEmpty()) { i1.remove(); } } } for (GridDeployment dep : doomed) { if (dep.isObsolete()) { // Resource cleanup. ctx.resource().onUndeployed(dep); } if (recEvt) { recordUndeploy(dep, true); } } }
/** * Gets alias for a class. * * @param dep Deployment. * @param cls Class. * @return Alias for a class. */ private String getAlias(GridDeployment dep, Class<?> cls) { String alias = cls.getName(); if (isTask(cls)) { GridTaskName ann = dep.annotation(cls, GridTaskName.class); if (ann != null) { alias = ann.value(); } } return alias; }
/** * @param entries Entries to submit. * @param curFut Current future. * @throws GridInterruptedException If interrupted. */ private void submit(final List<Map.Entry<K, V>> entries, final GridFutureAdapter<Object> curFut) throws GridInterruptedException { assert entries != null; assert !entries.isEmpty(); assert curFut != null; incrementActiveTasks(); GridFuture<Object> fut; if (isLocNode) { fut = ctx.closure() .callLocalSafe( new GridDataLoadUpdateJob<>(ctx, log, cacheName, entries, false, updater), false); locFuts.add(fut); fut.listenAsync( new GridInClosure<GridFuture<Object>>() { @Override public void apply(GridFuture<Object> t) { try { boolean rmv = locFuts.remove(t); assert rmv; curFut.onDone(t.get()); } catch (GridException e) { curFut.onDone(e); } } }); } else { byte[] entriesBytes; try { entriesBytes = ctx.config().getMarshaller().marshal(entries); if (updaterBytes == null) { assert updater != null; updaterBytes = ctx.config().getMarshaller().marshal(updater); } if (topicBytes == null) topicBytes = ctx.config().getMarshaller().marshal(topic); } catch (GridException e) { U.error(log, "Failed to marshal (request will not be sent).", e); return; } GridDeployment dep = null; GridPeerDeployAware jobPda0 = null; if (ctx.deploy().enabled()) { try { jobPda0 = jobPda; assert jobPda0 != null; dep = ctx.deploy().deploy(jobPda0.deployClass(), jobPda0.classLoader()); } catch (GridException e) { U.error( log, "Failed to deploy class (request will not be sent): " + jobPda0.deployClass(), e); return; } if (dep == null) U.warn(log, "Failed to deploy class (request will be sent): " + jobPda0.deployClass()); } long reqId = idGen.incrementAndGet(); fut = curFut; reqs.put(reqId, (GridFutureAdapter<Object>) fut); GridDataLoadRequest<Object, Object> req = new GridDataLoadRequest<>( reqId, topicBytes, cacheName, updaterBytes, entriesBytes, true, dep != null ? dep.deployMode() : null, dep != null ? jobPda0.deployClass().getName() : null, dep != null ? dep.userVersion() : null, dep != null ? dep.participants() : null, dep != null ? dep.classLoaderId() : null, dep == null); try { ctx.io().send(node, TOPIC_DATALOAD, req, PUBLIC_POOL); if (log.isDebugEnabled()) log.debug("Sent request to node [nodeId=" + node.id() + ", req=" + req + ']'); } catch (GridException e) { if (ctx.discovery().alive(node) && ctx.discovery().pingNode(node.id())) ((GridFutureAdapter<Object>) fut).onDone(e); else ((GridFutureAdapter<Object>) fut) .onDone( new GridTopologyException( "Failed to send " + "request (node has left): " + node.id())); } } }
/** * @param depMode Deployment mode. * @param ldr Class loader to deploy. * @param cls Class. * @param alias Class alias. * @return Deployment. */ @SuppressWarnings({"ConstantConditions"}) private GridDeployment deploy( GridDeploymentMode depMode, ClassLoader ldr, Class<?> cls, String alias) { assert Thread.holdsLock(mux); LinkedList<GridDeployment> cachedDeps = null; GridDeployment dep = null; // Find existing class loader info. for (LinkedList<GridDeployment> deps : cache.values()) { for (GridDeployment d : deps) { if (d.classLoader() == ldr) { // Cache class and alias. d.addDeployedClass(cls, alias); cachedDeps = deps; dep = d; break; } } if (cachedDeps != null) { break; } } if (cachedDeps != null) { assert dep != null; cache.put(alias, cachedDeps); if (!cls.getName().equals(alias)) { // Cache by class name as well. cache.put(cls.getName(), cachedDeps); } return dep; } GridUuid ldrId = GridUuid.randomUuid(); long seqNum = seq.incrementAndGet(); String userVer = getUserVersion(ldr); dep = new GridDeployment(depMode, ldr, ldrId, seqNum, userVer, cls.getName(), true); dep.addDeployedClass(cls, alias); LinkedList<GridDeployment> deps = F.addIfAbsent(cache, alias, F.<GridDeployment>newLinkedList()); if (!deps.isEmpty()) { for (GridDeployment d : deps) { if (!d.isUndeployed()) { U.error( log, "Found more than one active deployment for the same resource " + "[cls=" + cls + ", depMode=" + depMode + ", dep=" + d + ']'); return null; } } } // Add at the beginning of the list for future fast access. deps.addFirst(dep); if (!cls.getName().equals(alias)) { // Cache by class name as well. cache.put(cls.getName(), deps); } if (log.isDebugEnabled()) { log.debug("Created new deployment: " + dep); } return dep; }
/** {@inheritDoc} */ @Nullable @SuppressWarnings({"UnusedCatchParameter"}) @Override public GridDeployment getDeployment(GridDeploymentMetadata meta) { GridDeployment dep; Class<?> cls = null; String alias = meta.alias(); synchronized (mux) { // Validate metadata. assert meta.alias() != null; dep = getDeployment(meta.alias()); if (dep != null) { if (log.isDebugEnabled()) { log.debug("Acquired deployment class from local cache: " + dep); } return dep; } GridDeploymentResource rsrc = spi.findResource(meta.alias()); if (rsrc != null) { dep = deploy( ctx.config().getDeploymentMode(), rsrc.getClassLoader(), rsrc.getResourceClass(), alias); if (dep == null) { return null; } if (log.isDebugEnabled()) { log.debug("Acquired deployment class from SPI: " + dep); } } // Auto-deploy. else { ClassLoader ldr = meta.classLoader(); if (ldr == null) { ldr = Thread.currentThread().getContextClassLoader(); // Safety. if (ldr == null) { ldr = ctxLdr; } } // Don't auto-deploy locally in case of nested execution. if (ldr instanceof GridDeploymentClassLoader) { return null; } try { // Check that class can be loaded. cls = ldr.loadClass(meta.alias()); spi.register(ldr, cls); rsrc = spi.findResource(alias); if (rsrc != null && rsrc.getResourceClass().equals(cls)) { if (log.isDebugEnabled()) { log.debug("Retrieved auto-loaded resource from spi: " + rsrc); } dep = deploy(ctx.config().getDeploymentMode(), ldr, cls, alias); if (dep == null) { return null; } } else { U.warn( log, "Failed to find resource from deployment SPI even after registering it: " + meta.alias()); return null; } } catch (ClassNotFoundException e) { if (log.isDebugEnabled()) { log.debug( "Failed to load class for local auto-deployment [ldr=" + ldr + ", meta=" + meta + ']'); } return null; } catch (GridSpiException e) { U.error(log, "Failed to deploy local class: " + meta.alias(), e); return null; } } } if (cls != null) { recordDeploy(cls, alias, meta.isRecord()); dep.addDeployedClass(cls, meta.className(), meta.alias()); } if (log.isDebugEnabled()) { log.debug("Acquired deployment class: " + dep); } return dep; }