All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.caucho.v5.bartender.heartbeat.JoinClient Maven / Gradle / Ivy

There is a newer version: 1.0.1
Show newest version
/*
 * Copyright (c) 1998-2015 Caucho Technology -- all rights reserved
 *
 * This file is part of Baratine(TM)
 *
 * Each copy or derived work must preserve the copyright notice and this
 * notice unmodified.
 *
 * Baratine is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * Baratine is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
 * of NON-INFRINGEMENT.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Baratine; if not, write to the
 *
 *   Free Software Foundation, Inc.
 *   59 Temple Place, Suite 330
 *   Boston, MA 02111-1307  USA
 *
 * @author Scott Ferguson
 */

package com.caucho.v5.bartender.heartbeat;

import io.baratine.service.Result;
import io.baratine.service.ResultFuture;
import io.baratine.service.Result.Fork;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.caucho.v5.baratine.client.ServiceManagerClient;
import com.caucho.v5.bartender.ServerBartender;
import com.caucho.v5.bartender.hamp.ClientBartenderFactory;

/**
 * Handles pinging the remote IP interface of the servers the internal
 * name.
 */
class JoinClient
{
  private static final Logger log
    = Logger.getLogger(JoinClient.class.getName());
  
  private ServerSelf _selfServer;

  private RootHeartbeat _root;
  
  // private int _joinCount;

  //private HeartbeatLocalImpl _heartbeatImpl;

  public JoinClient(ServerSelf serverSelf,
                    RootHeartbeat root,
                    HeartbeatLocalImpl heartbeatImpl)
  {
    Objects.requireNonNull(serverSelf);
    Objects.requireNonNull(root);
    Objects.requireNonNull(heartbeatImpl);
    
    _selfServer = serverSelf;
    _root = root;
    //_heartbeatImpl = heartbeatImpl;
  }
  
  /*
  public int getJoinServerCount()
  {
    return _joinCount;
  }
  */
  
  public void start(Consumer consumer,
                    Result result)
  {
    if (_selfServer.port() < 0) {
      result.ok(0);
      return;
    }
    
    // boolean isPendingStart = false;
    
    ArrayList clusterList = new ArrayList<>();
    for (ClusterHeartbeat cluster : _root.getClusters()) {
      clusterList.add(cluster);
    }
    
    if (clusterList.size() == 0) {
      result.ok(0);
      return;
    }
    
    /*
    Result[]resultFork = result.fork(clusterList.size(),
                                              (x,r)->addInt(x,null,r),
                                              (x,y,r)->addInt(x,y,r));
                                              */
    Fork fork = result.fork();
    
    for (int i = 0; i < clusterList.size(); i++) {
      ClusterHeartbeat cluster = clusterList.get(i);
      
      startCluster(cluster, consumer, fork.branch()); // resultFork[i]);
    }
    
    fork.fail((v,f,r)->addInt(v,f,r));
    fork.join((v,r)->addInt(v,null,r));
    
    /*
    for (ClusterHeartbeat cluster : _root.getClusters()) {
      if (! _selfServer.getClusterId().equals(cluster.getId())) {
        startCluster(cluster, cont);
      }
    }
    */
  }
  
  private static void addInt(List values, 
                             List fails, 
                             Result result)
  {
    int count = 0;
    
    for (int i = 0; i < values.size(); i++) {
      Integer value = values.get(i);
      
      if (value != null) {
        count += value;
      }
    }
    
    result.ok(count);
  }
  
  private void startCluster(ClusterHeartbeat cluster, 
                            Consumer consumer,
                            Result cont)
  {
    ArrayList servers = new ArrayList<>();
    
    for (ServerHeartbeat server : cluster.getSeedServers()) {
      if (server.port() > 0) {
        servers.add(server);
      }
    }
    
    if (servers.size() == 0) {
      cont.ok(0);
      return;
    }
    
    Collections.sort(servers, new StartComparator());
    JoinFuture future = new JoinFuture(servers.size(), cont);

    for (ServerHeartbeat server : servers) {
      startServer(server, cluster, consumer, future);
    }
  }

  /*
  private boolean isSeedServer(ServerBartender server)
  {
    return (! "".equals(server.getAddress()) && server.getPort() > 0);
  }
  */
  
  private void startServer(ServerHeartbeat server,
                           ClusterHeartbeat cluster,
                           Consumer consumer,
                           JoinFuture future)
  {
    String address = server.getAddress();
    int port = server.port();

    if (port <= 0) {
      throw new IllegalStateException(String.valueOf(server));
    }
    
    if ("".equals(address)) {
      address = "127.0.0.1";
    }
    
    int seedIndex = getSeedIndex(server, cluster);
    
    ServiceManagerClient client = createBartenderClient(server); // address, port);
    
    /*
    ServerHeartbeat serverHeartbeat = (ServerHeartbeat) server;
    int portBartender = serverHeartbeat.getPortBartender();
    */

    JoinServerResult result = new JoinServerResult(future,
                                                   client,
                                                   consumer);
    
    try {
      HeartbeatService heartbeat = client.service("remote://" + HeartbeatService.PATH)
                                         .as(HeartbeatService.class);

      heartbeat.join(address, port,
                     _selfServer.getClusterId(),
                     _selfServer.getAddress(),
                     _selfServer.port(),
                     _selfServer.getPortBartender(),
                     _selfServer.getDisplayName(),
                     _selfServer.getMachineHash(),
                     seedIndex,
                     result);
    } catch (Throwable e) {
      result.fail(e);
    }
  }
  
  private int getSeedIndex(ServerBartender server, ClusterHeartbeat cluster)
  {
    int index = 0;
    
    for (ServerBartender seedServer : cluster.getSeedServers()) {
      if (seedServer.getAddress().isEmpty()
          || seedServer.getAddress().startsWith("127")) {
        continue;
      }
      
      index++;
      
      if (seedServer == server) {
        return index; 
      }
    }
    
    return 0;
  }
  
  private ServiceManagerClient createBartenderClient(ServerHeartbeat server)
  {
    String url;
    
    if (server.getPortBartender() > 0) {
      url = "bartender://" + server.getAddress() + ":" + server.getPortBartender() + "/bartender";
    }
    else {
      String scheme = "http";
      
      if (server.isSSL()) {
        scheme = "https";
      }
      
      url = scheme + "://" + server.getAddress() + ":" + server.port() + "/bartender";
    }
    
    return new ClientBartenderFactory(url).create();
  }
  
  private class StartComparator implements Comparator {
    @Override
    public int compare(ServerHeartbeat a, ServerHeartbeat b)
    {
      int portA = a.port();
      int portB = b.port();
      
      int portBarA = a.getPortBartender();
      int portBarB = b.getPortBartender();
      
      String addressA = a.getAddress();
      String addressB = b.getAddress();
      
      if (portBarA == _selfServer.port()) {
        portBarA = 0;
      }
      else if (portBarA <= 0) {
        portBarA = Integer.MAX_VALUE / 4;
      }
      
      if (portBarB == _selfServer.port()) {
        portBarB = 0;
      }
      else if (portBarB <= 0) {
        portBarB = Integer.MAX_VALUE / 4;
      }
      
      int cmp = portBarA - portBarB;
      
      if (cmp != 0) {
        return cmp;
      }
      
      if (portA == _selfServer.port()) {
        portA = 0;
      }
      
      if (portB == _selfServer.port()) {
        portB = 0;
      }
      
      cmp = portA - portB;
      
      if (cmp != 0) {
        return cmp;
      }
      
      if (addressA.equals(_selfServer.getAddress())) {
        addressA = "";
      }
      
      if (addressB.equals(_selfServer.getAddress())) {
        addressB = "";
      }
      
      return addressA.compareTo(addressB);
    }
  }
  
  private class JoinServerResult extends Result.Wrapper {
    private final ServiceManagerClient _client;
    private final Consumer _consumer;
    
    JoinServerResult(JoinFuture future, 
                     ServiceManagerClient client,
                     Consumer consumer)
    {
      super(future);

      _client = client;
      _consumer = consumer;
    }

    @Override
    public void ok(UpdateRackHeartbeat result)
    {
      // update rack and count only for foreign (non-self) join
      if (result != null) {
        // _joinCount++;
      
        _consumer.accept(result);
      }
      
      // System.out.println("COMPLETE: " + result);
      try {
        delegate().ok(result);
      } finally {
        _client.close();
      }
    }

    @Override
    public void fail(Throwable exn)
    {
      log.finer("Join to " + _client + " failed: " + exn);
      // exn.printStackTrace();
      
      try {
        super.fail(exn);
      } finally {
        _client.close();
      }
    }
  }
  
  private static class JoinFuture implements Result {
    private final int _serverCount;
    private final Result _cont;
    
    private boolean _isCompleted;
    
    private int _successCount;
    private int _remoteCount;
    private int _failedCount;
    
    JoinFuture(int serverCount, Result cont)
    {
      _serverCount = serverCount;
      _cont = cont;
    }
    
    @Override
    public void ok(UpdateRackHeartbeat result)
    {
      _successCount++;
      
      if (result != null) {
        _remoteCount++;
      }
      
      int count = _successCount + _failedCount;
      
      if ((_successCount > 1 || _serverCount <= count) && ! _isCompleted) {
        _isCompleted = true;
        
        if (_cont != null) {
          _cont.ok(_remoteCount);
        }
      }
    }
    
    @Override
    public void fail(Throwable exn)
    {
      _failedCount++;
      
      int count = _successCount + _failedCount;
      
      if (_serverCount <= count && ! _isCompleted) {
        _isCompleted = true;
        
        if (_cont != null) {
          _cont.fail(exn);
        }
      }
      
      log.finer(exn.toString());
      log.log(Level.FINEST, exn.toString(), exn);
    }
    
    @Override
    public void handle(UpdateRackHeartbeat result, Throwable exn)
    {
      if (exn != null) {
        fail(exn);
      }
      else {
        ok(result);
      }
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy