/** {@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;
  }
Esempio n. 15
0
  /** {@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.");
    }
  }