/** {@inheritDoc} */ @Override public final Map<UUID, GridNodeMetrics> metrics(Collection<UUID> nodeIds) throws GridSpiException { assert !F.isEmpty(nodeIds); long now = U.currentTimeMillis(); Collection<UUID> expired = new LinkedList<>(); for (UUID id : nodeIds) { GridNodeMetrics nodeMetrics = metricsMap.get(id); Long ts = tsMap.get(id); if (nodeMetrics == null || ts == null || ts < now - metricsExpireTime) expired.add(id); } if (!expired.isEmpty()) { Map<UUID, GridNodeMetrics> refreshed = metrics0(expired); for (UUID id : refreshed.keySet()) tsMap.put(id, now); metricsMap.putAll(refreshed); } return F.view(metricsMap, F.contains(nodeIds)); }
/** * Resolves host for REST TCP server using grid configuration. * * @param cfg Grid configuration. * @return REST host. * @throws IOException If failed to resolve REST host. */ private InetAddress resolveRestTcpHost(GridConfiguration cfg) throws IOException { String host = cfg.getRestTcpHost(); if (host == null) host = cfg.getLocalHost(); return U.resolveLocalHost(host); }
/** * Load classes from given file. File could be either directory or JAR file. * * @param clsLdr Class loader to load files. * @param file Either directory or JAR file which contains classes or references to them. * @return Set of found and loaded classes or empty set if file does not exist. * @throws GridSpiException Thrown if given JAR file references to none existed class or * IOException occurred during processing. */ static Set<Class<? extends GridTask<?, ?>>> getClasses(ClassLoader clsLdr, File file) throws GridSpiException { Set<Class<? extends GridTask<?, ?>>> rsrcs = new HashSet<Class<? extends GridTask<?, ?>>>(); if (file.exists() == false) { return rsrcs; } GridUriDeploymentFileResourceLoader fileRsrcLdr = new GridUriDeploymentFileResourceLoader(clsLdr, file); if (file.isDirectory()) { findResourcesInDirectory(fileRsrcLdr, file, rsrcs); } else { try { for (JarEntry entry : U.asIterable(new JarFile(file.getAbsolutePath()).entries())) { Class<? extends GridTask<?, ?>> rsrc = fileRsrcLdr.createResource(entry.getName(), false); if (rsrc != null) { rsrcs.add(rsrc); } } } catch (IOException e) { throw new GridSpiException( "Failed to discover classes in file: " + file.getAbsolutePath(), e); } } return rsrcs; }
/** Stops Jetty. */ private void stopJetty() { // Jetty does not really stop the server if port is busy. try { if (httpSrv != null) { // If server was successfully started, deregister ports. if (httpSrv.isStarted()) ctx.ports().deregisterPorts(getClass()); // Record current interrupted status of calling thread. boolean interrupted = Thread.interrupted(); try { httpSrv.stop(); } finally { // Reset interrupted flag on calling thread. if (interrupted) Thread.currentThread().interrupt(); } } } catch (InterruptedException ignored) { if (log.isDebugEnabled()) log.debug("Thread has been interrupted."); Thread.currentThread().interrupt(); } catch (Exception e) { U.error(log, "Failed to stop Jetty HTTP server.", e); } }
/** * Records deploy event. * * @param cls Deployed class. * @param clsLdr Class loader. * @param recordEvt Flag indicating whether to record events. */ @SuppressWarnings({"unchecked"}) private void recordDeployFailed(Class<?> cls, ClassLoader clsLdr, boolean recordEvt) { assert cls != null; assert clsLdr != null; boolean isTask = isTask(cls); String msg = "Failed to deploy " + (isTask ? "task" : "class") + " [cls=" + cls + ", clsLdr=" + clsLdr + ']'; if (recordEvt && ctx.event().isRecordable(isTask ? EVT_CLASS_DEPLOY_FAILED : EVT_TASK_DEPLOY_FAILED)) { String taskName = isTask ? U.getTaskName((Class<? extends GridTask<?, ?>>) cls) : null; GridDeploymentEvent evt = new GridDeploymentEvent(); evt.message(msg); evt.nodeId(ctx.localNodeId()); evt.type(isTask(cls) ? EVT_CLASS_DEPLOY_FAILED : EVT_TASK_DEPLOY_FAILED); evt.alias(taskName); ctx.event().record(evt); } if (log.isInfoEnabled()) { log.info(msg); } }
/** * Method cleans up all events that either outnumber queue size or exceeds time-to-live value. It * does none if someone else cleans up queue (lock is locked) or if there are queue readers * (readersNum > 0). */ private void cleanupQueue() { long now = U.currentTimeMillis(); long queueOversize = evts.sizex() - expireCnt; for (int i = 0; i < queueOversize && evts.sizex() > expireCnt; i++) { GridEvent expired = evts.poll(); if (log.isDebugEnabled()) log.debug("Event expired by count: " + expired); } while (true) { ConcurrentLinkedDeque8.Node<GridEvent> node = evts.peekx(); if (node == null) // Queue is empty. break; GridEvent evt = node.item(); if (evt == null) // Competing with another thread. continue; if (now - evt.timestamp() < expireAgeMs) break; if (evts.unlinkx(node) && log.isDebugEnabled()) log.debug("Event expired by age: " + node.item()); } }
/** {@inheritDoc} */ @Override public void start() throws GridException { ctxLdr = U.detectClassLoader(getClass()); spi.setListener(new LocalDeploymentListener()); if (log.isDebugEnabled()) { log.debug(startInfo()); } }
/** * Converts given input stream expecting XML inside to {@link GridUriDeploymentSpringDocument}. * * <p>This is a workaround for the {@link InputStreamResource} which does not work properly. * * @param in Input stream with XML. * @param log Logger * @return Grid wrapper for the input stream. * @throws GridSpiException Thrown if incoming input stream could not be read or parsed by {@code * Spring} {@link XmlBeanFactory}. * @see XmlBeanFactory */ static GridUriDeploymentSpringDocument parseTasksDocument(InputStream in, GridLogger log) throws GridSpiException { assert in != null; // Note: use ByteArrayResource instead of InputStreamResource because InputStreamResource // doesn't work. ByteArrayOutputStream out = new ByteArrayOutputStream(); try { U.copy(in, out); XmlBeanFactory factory = new XmlBeanFactory(new ByteArrayResource(out.toByteArray())); return new GridUriDeploymentSpringDocument(factory); } catch (BeansException e) { throw new GridSpiException("Failed to parse spring XML file.", e); } catch (IOException e) { throw new GridSpiException("Failed to parse spring XML file.", e); } finally { U.close(out, log); } }
/** * Records deploy event. * * @param cls Deployed class. * @param alias Class alias. * @param recordEvt Flag indicating whether to record events. */ private void recordDeploy(Class<?> cls, String alias, boolean recordEvt) { assert cls != null; boolean isTask = isTask(cls); String msg = (isTask ? "Task" : "Class") + " locally deployed: " + cls; if (recordEvt && ctx.event().isRecordable(isTask ? EVT_TASK_DEPLOYED : EVT_CLASS_DEPLOYED)) { GridDeploymentEvent evt = new GridDeploymentEvent(); evt.message(msg); evt.nodeId(ctx.localNodeId()); evt.type(isTask ? EVT_TASK_DEPLOYED : EVT_CLASS_DEPLOYED); evt.alias(alias); ctx.event().record(evt); } // Don't record JDK or Grid classes. if (U.isGrid(cls) || U.isJdk(cls)) return; if (log.isInfoEnabled()) log.info(msg); }
/** * Send message optionally either blocking it or throwing an exception if it is of {@link * GridJobExecuteResponse} type. * * @param node Destination node. * @param msg Message to be sent. * @throws GridSpiException If failed. */ private void sendMessage0(GridNode node, GridTcpCommunicationMessageAdapter msg) throws GridSpiException { if (msg instanceof GridIoMessage) { GridIoMessage msg0 = (GridIoMessage) msg; if (msg0.message() instanceof GridJobExecuteResponse) { respLatch.countDown(); if (wait) { try { U.await(waitLatch); } catch (GridInterruptedException ignore) { // No-op. } } } } if (!block) super.sendMessage(node, msg); }
/** {@inheritDoc} */ @SuppressWarnings("BusyWait") @Override public void start(GridRestProtocolHandler hnd) throws GridException { InetAddress locHost; try { locHost = U.resolveLocalHost(ctx.config().getLocalHost()); } catch (IOException e) { throw new GridException( "Failed to resolve local host to bind address: " + ctx.config().getLocalHost(), e); } System.setProperty(GG_JETTY_HOST, locHost.getHostAddress()); jettyHnd = new GridJettyRestHandler( hnd, new C1<String, Boolean>() { @Override public Boolean apply(String tok) { return F.isEmpty(secretKey) || authenticate(tok); } }, log); String jettyPath = ctx.config().getRestJettyPath(); final URL cfgUrl; if (jettyPath == null) { cfgUrl = null; if (log.isDebugEnabled()) log.debug("Jetty configuration file is not provided, using defaults."); } else { cfgUrl = U.resolveGridGainUrl(jettyPath); if (cfgUrl == null) throw new GridSpiException("Invalid Jetty configuration file: " + jettyPath); else if (log.isDebugEnabled()) log.debug("Jetty configuration file: " + cfgUrl); } loadJettyConfiguration(cfgUrl); AbstractNetworkConnector connector = getJettyConnector(); try { host = InetAddress.getByName(connector.getHost()); } catch (UnknownHostException e) { throw new GridException("Failed to resolve Jetty host address: " + connector.getHost(), e); } int initPort = connector.getPort(); int lastPort = initPort + ctx.config().getRestPortRange() - 1; for (port = initPort; port <= lastPort; port++) { connector.setPort(port); if (startJetty()) { if (log.isInfoEnabled()) log.info(startInfo()); return; } } U.warn( log, "Failed to start Jetty REST server (possibly all ports in range are in use) " + "[firstPort=" + initPort + ", lastPort=" + lastPort + ']'); }
/** * Await for job execution response to come. * * @throws GridInterruptedException If interrupted. */ private void awaitResponse() throws GridInterruptedException { U.await(respLatch); }
/** * @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; }
/** {@inheritDoc} */ @SuppressWarnings("BusyWait") @Override public void start(final GridRestProtocolHandler hnd) throws GridException { assert hnd != null; GridConfiguration cfg = ctx.config(); GridNioServerListener<GridClientMessage> lsnr = new GridTcpRestNioListener(log, hnd); GridNioParser parser = new GridTcpRestParser(log); try { host = resolveRestTcpHost(cfg); SSLContext sslCtx = null; if (cfg.isRestTcpSslEnabled()) { GridSslContextFactory factory = cfg.getRestTcpSslContextFactory(); if (factory == null) // Thrown SSL exception instead of GridException for writing correct warning message into // log. throw new SSLException("SSL is enabled, but SSL context factory is not specified."); sslCtx = factory.createSslContext(); } int lastPort = cfg.getRestTcpPort() + cfg.getRestPortRange() - 1; for (port = cfg.getRestTcpPort(); port <= lastPort; port++) { if (startTcpServer(host, port, lsnr, parser, sslCtx, cfg)) { if (log.isInfoEnabled()) log.info(startInfo()); return; } } U.warn( log, "Failed to start TCP binary REST server (possibly all ports in range are in use) " + "[firstPort=" + cfg.getRestTcpPort() + ", lastPort=" + lastPort + ", host=" + host + ']'); } catch (SSLException e) { U.warn( log, "Failed to start " + name() + " protocol on port " + port + ": " + e.getMessage(), "Failed to start " + name() + " protocol on port " + port + ". Check if SSL context factory is " + "properly configured."); } catch (IOException e) { U.warn( log, "Failed to start " + name() + " protocol on port " + port + ": " + e.getMessage(), "Failed to start " + name() + " protocol on port " + port + ". " + "Check restTcpHost configuration property."); } }