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

com.caucho.v5.bartender.pod.PodLocalImpl 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.pod;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Objects;
import java.util.logging.Logger;

import com.caucho.v5.amp.AmpSystem;
import com.caucho.v5.amp.Direct;
import com.caucho.v5.amp.ServicesAmp;
import com.caucho.v5.baratine.InService;
import com.caucho.v5.bartender.BartenderSystem;
import com.caucho.v5.bartender.ServerBartender;
import com.caucho.v5.bartender.heartbeat.ClusterHeartbeat;
import com.caucho.v5.bartender.heartbeat.HeartbeatImpl;
import com.caucho.v5.bartender.heartbeat.HeartbeatServiceLocal;
import com.caucho.v5.bartender.heartbeat.RootHeartbeat;
import com.caucho.v5.bartender.heartbeat.ServerHeartbeat;
import com.caucho.v5.lifecycle.Lifecycle;

import io.baratine.service.Result;

@InService(HeartbeatServiceLocal.class)
public class PodLocalImpl
{
  private static final Logger log = Logger.getLogger(PodLocalImpl.class.getName());
  
  // private final BartenderSystem _system;
  
  //private final BartenderServiceImpl _bartender;
  
//  private final HashMap _podMap = new HashMap<>();
//  private final HashMap _proxyMap = new HashMap<>();
  
  // private final HashMap _podClusterMap = new HashMap<>();
  
  private final HashMap _failoverMap = new HashMap<>();
  
  private HeartbeatImpl _heartbeatService;
  
  //private ShardWatch _watch;
  //private FileService _path;
  //private ArrayList _pathPodList = new ArrayList<>();
  
  // private PodOnUpdate _podEvents;

  private ServerHeartbeat _serverSelf;

  private RootHeartbeat _root;

  private UpdatePodSystem _updatePodSystem;
  
  private int _roundRobinPodGenerator;

  private PodLocalService _podServiceManager;

  private BartenderSystem _bartender;

  private FailoverEvents _failoverEvents;

  private long _lastRootSequence;

  private PodHeartbeatImpl _podHeartbeat;

  // private PodManagerImpl _podManager;
  
  private final Lifecycle _lifecycle = new Lifecycle();

  // private List _seedServers;
  
  public PodLocalImpl()
  {
    _heartbeatService = null;
  }
  
  public PodLocalImpl(BartenderSystem bartender,
                      PodHeartbeatImpl podHeartbeat)
  {
    Objects.requireNonNull(bartender);
    Objects.requireNonNull(podHeartbeat);

    _bartender = bartender;
    _podHeartbeat = podHeartbeat;
    
    _serverSelf = (ServerHeartbeat) bartender.serverSelf();
    
    /*
    _serverSelf = serverSelf;
    _root = root;
    
    ServiceManagerAmp rampManager = AmpSystem.getCurrentManager();
    
    new SchemePod(bartender, rampManager).bind("pod:");
    
    _heartbeatService = heartbeatService;
    
    EventService eventService = AmpSystem.getCurrent().getEventService();
    _failoverEvents = eventService.lookup(FailoverEvents.class);
    _podEvents = eventService.lookup(PodOnUpdate.class);
    
    eventService.subscribe(ServerBartenderEvents.class,
                           new HeartbeatEventsPod());
    
    _updatePodSystem = new UpdatePodSystem(_podMap.values());
    */
  }
  
  public void start()
  {
    if (! _lifecycle.toActive()) {
      return;
    }
    
    ServicesAmp rampManager = AmpSystem.currentManager();
    
    String clusterId = _serverSelf.getClusterId();
    
    /*
    _podServiceManager = rampManager.lookup("pod://cluster_root" + PodLocalService.PATH)
                                    .as(PodLocalService.class);
                                    */
    
    // _podManager.start();
    _podHeartbeat.start();
  }
  
  public void stop()
  {
    _lifecycle.toDestroy();
  }
  
  public UpdatePodSystem getUpdate()
  {
    return _updatePodSystem;
  }

  public boolean isStartValid()
  {
    return _heartbeatService.isStartValid();
  }

  //
  // service methods
  //  
  
  @Direct
  public PodBartender findPod(String name)
  {
    name = canonPodName(name);

    return _podHeartbeat.getPod(name);
  }
  
  @Direct
  public PodBartender findActivePod(String name)
  {
    name = canonPodName(name);
    
    return _podHeartbeat.getActivePod(name);
  }
  
  @Direct
  public ServerPod findActiveServer(String name)
  {
    FailoverNode failover = _failoverMap.get(name);
    
    if (failover != null) {
      return failover.getServer();
    }
    else {
      return null;
    }
  }
  
  public void onJoinStart()
  {
    _podHeartbeat.onJoinStart();
  }
  
  public Iterable getPods()
  {
    return _podHeartbeat.getPods();
  }
  
  /*
  public void createPodByBuilder(PodBuilder builder,
                                 Result result)
  {
    Objects.requireNonNull(builder);

    UpdatePod updatePod = createPodUpdate(builder);
    
    _podHeartbeat.addNewPod(updatePod, result);
  }
  */
  
  public void createPodByUpdate(UpdatePod updatePod,
                                 Result result)
  {
    Objects.requireNonNull(updatePod);
    
    _podHeartbeat.addNewPod(updatePod, result);
  }
  
  public UpdatePod getInitPod(String id)
  {
    return _podHeartbeat.getInitPod(id);
  }
  
  /*
  public UpdatePod createPodUpdate(PodBuilder podBuilder)
  {
    final String name = canonPodName(podBuilder.getName());
    
    UpdatePodBuilder builder = new UpdatePodBuilder();
    
    int p = name.indexOf('.');
    
    if (p >= 0) {
      String podName = name.substring(0, p);
      String clusterId = name.substring(p + 1);
      
      builder.name(podName);
      
      ClusterHeartbeat cluster = (ClusterHeartbeat) _bartender.findCluster(clusterId);
      
      builder.cluster(cluster);
    }
    else {
      builder.name(name);
      builder.cluster(_serverSelf.getCluster());
    }
    
    builder.type(podBuilder.getType());
   
    if (podBuilder.getType() == PodBartender.PodType.off) {
      builder.primaryCount(0);
      builder.pod(new ServerPod[0]);
    }
    else {
      int serverCount = Math.max(podBuilder.getSize(), 3);
   
      builder.setRoundRobin(_roundRobinPodGenerator++);
   
      for (ServiceServer.Server server : podBuilder.getServers()) {
        builder.server(server.getAddress(), server.getPort());
      }
   
      builder.pod(builder.buildServers(_serverSelf.getRack(), serverCount));
   
      builder.primaryCount(podBuilder.getSize());
    }
    
    return builder.build();
  }
  */

  /*
  public void updatePod(UpdatePod update,
                               Result result)
  {
    ClusterHeartbeat cluster = _root.findCluster(update.getClusterId());
   
    PodBartenderImpl pod = new PodBartenderImpl(update, cluster);
   
    addPod(pod);
   
    if (result != null) {
      result.complete(pod.getUpdate());
    }
  }
  */
  
  private String canonPodName(String name)
  {
    name = name.replace('-', '_');
    
    if (name.indexOf('.') < 0) {
      name = name + '.' + _serverSelf.getClusterId();
    }
    
    return name;
  }

  /*
  public boolean updatePodsFromHeartbeat()
  {
    long rootSequence = _root.getSequence();
    
    if (rootSequence == _lastRootSequence) {
      return false;
    }
    
    _lastRootSequence = rootSequence;
    
    boolean isUpdate = false;
    
    long lastCrc = _updatePodSystem.getCrc();
    
    for (PodBartenderImpl pod : _podMap.values()) {
      long oldPodCrc = pod.getUpdate().getCrc();
      
      if (pod.updateFromHeartbeat(this, _serverSelf)) {
        isUpdate = true;
            
        onUpdatePod(pod);
      }
    }
    
    if (isUpdate) {
      _updatePodSystem = new UpdatePodSystem(_podMap.values());

      if (_updatePodSystem.getCrc() != lastCrc) {
        _heartbeatService.onPodSystemUpdate();
      }
    }
    
    return isUpdate;
  }
  */

  /*
  private void onUpdatePod(PodBartender pod)
  {
    updatePodFailover(pod);
    
    _podEvents.onUpdate(pod);
  }
  */
  
  //
  // updates
  //

  /**
   * Updates the pod system because of a heartbeat server change.
   * 
   * A new server can be added to an existing pod.
   */
  /*
  public void onUpdateFromPeer(UpdatePodSystem updatePodSystem)
  {
    long lastCrc = _updatePodSystem.getCrc();
                       
    for (UpdatePod updatePod : updatePodSystem.getPods()) {
      onUpdatePodFromPeer(updatePod);
    }
    
    if (_updatePodSystem.getCrc() != lastCrc) {
      _heartbeatService.updatePod(_updatePodSystem);
    }
  }
  */
  
  public void onUpdateFromPeerCluster(String clusterId, 
                                      UpdatePodSystem updatePodSystem)
  {
    // onUpdateFromPeer(updatePodSystem);
    
    /* XXX:
    PodCluster podCluster = _podClusterMap.get(clusterId);
    
    if (podCluster != null) {
      podCluster.updateFromPeer(updatePodSystem);
    }
    else {
      log.finer("Update unknown cluster pod: " + clusterId);
    }
    */
  }
  
  /*
  private void onUpdatePodFromPeer(UpdatePod updatePod)
  {
    PodBartenderImpl oldPod = _podMap.get(updatePod.getId());
    
    if (oldPod != null) {
      if (oldPod.onUpdateFromPeer(updatePod, this)) {
        _updatePodSystem = new UpdatePodSystem(_podMap.values());
        
        onUpdatePod(oldPod);
      }
      
      return;
    }
    
    ClusterHeartbeat cluster = _root.findCluster(updatePod.getClusterId());
    
    PodBartenderImpl newPod = new PodBartenderImpl(updatePod, 
                                                   cluster);
    
    addPod(newPod);
  }
  */

  /*
  void updatePodProxy(PodBartenderImpl pod)
  {
    String podName = pod.getId() + '.' + pod.getClusterId();
    
    PodBartenderProxy proxy = _proxyMap.get(podName);
    
    if (proxy == null) {
      proxy = new PodBartenderProxy(pod.getId());
      proxy.setDelegate(pod);
      
      _proxyMap.put(podName, proxy);
    }
    
    proxy.setDelegate(pod);
  }
  */
  
  /**
   * Create cluster pods using the configuration as a hint. Both the cluster
   * and cluster_hub pods use this.
   */
  private ServerPod []buildClusterServers(ClusterHeartbeat cluster,
                                          int serverCount)
  {
    ArrayList serversPod = new ArrayList<>();
    
    for (ServerHeartbeat server : cluster.getServers()) {
      ServerPod serverPod = new ServerPod(serversPod.size());
      serversPod.add(serverPod);
      
      // XXX: need to manage seed servers
      // serverPod.setHintServerId(server.getId());
    }
    
    /*
    if (cluster == _serverSelf.getCluster()) {
      if (serversPod.size() < serverCount && ! isServerPresent(serversPod)) {
        ServerPod serverPod = new ServerPod(serversPod.size());
        serversPod.add(serverPod);
      
        serverPod.setServer(_serverSelf);
      }
    }
    */
    
    while (serversPod.size() < serverCount) {
      serversPod.add(new ServerPod(serversPod.size()));
    }
    
    ServerPod []serverArray = new ServerPod[serverCount];
    for (int i = 0; i < serverCount; i++) {
      serverArray[i] = serversPod.get(i);
    }
    
    return serverArray;
  }
  
  /**
   * XXX: issue is server starting by itself when it's not a seed server.
   */
  /*
  private boolean isServerPresent(ArrayList serversPod)
  {
    for (ServerPod serverPod : serversPod) {
      ServerBartender server = serverPod.getServer();
      
      if (server != null && server.getPort() == _serverSelf.getPort()) {
        return true;
      }

      String hintServer = serverPod.getHint().getServer();
      
      if (hintServer == null) {
        continue;
      }
      
      int p = hintServer.lastIndexOf(':');
      int port = Integer.parseInt(hintServer.substring(p + 1));
      
      if (port == _serverSelf.getPort()) {
        return true;
      }
    }
    
    return false;
  }
  */
  
  //
  // failover
  //
  
  /*
  public void updatePodFailover()
  {
    ArrayList pods = new ArrayList<>(_podMap.values());
    
    for (PodBartender pod : pods) {
      updatePodFailover(pod);
    }
  }
  */
  
  /*
  private void updatePodFailover(PodBartender pod)
  {
    int nodeCount = pod.getNodeCount();
    
    for (int i = 0; i < nodeCount; i++) {
      NodePodAmp node = pod.getNode(i);

      updatePodFailoverNode(node);
    }
  }
  */
  /*
  private void updatePodFailoverNode(NodePodAmp node)
  {
    int serverCount = node.getServerCount();
    
    if (! _heartbeatService.isJoinComplete()) {
      serverCount = Math.min(1, serverCount);
    }

    PodBartender pod = node.getPod();
    
    for (int i = 0; i < serverCount; i++) {
      ServerBartender server = node.getServer(i);
      
      if (server== null) {
        continue;
      }
      
      if (server.isUp()) {
        FailoverNode failoverNode = new FailoverNode(node.getPod(), 
                                                     node.getNodeIndex(),
                                                     serverPod);
        
        String name = node.getPod().getName() + "." + node.getNodeIndex();
        
        FailoverNode oldNode = _failoverMap.get(name);
        
        if (oldNode == null) {
          // XXX: failback
          _failoverMap.put(name, failoverNode);
          _failoverEvents.onUp(failoverNode);
        }
        else if (pod.getSequence() < oldNode.getPod().getSequence()) {
          continue;
        }
        else if (oldNode.getServer() != serverPod) {
          if (! oldNode.getServer().isUp()) {
            // failover
            _failoverMap.put(name, failoverNode);
            _failoverEvents.onUp(failoverNode);
          }
          else {
            // failback
            _failoverMap.put(name, failoverNode);
            _failoverEvents.onDown(failoverNode);
          }
        }
        
        return;
      }
    }
  }
  */

  //
  // impl
  //
  
  /*
  void addPod(PodBartenderImpl pod)
  {
    String name = pod.getId() + '.' + pod.getClusterId();
    
    PodBartenderImpl oldPod = _podMap.get(name);
    
    if (oldPod != null && pod.getSequence() < oldPod.getSequence()) {
      return;
    }
    
    _podMap.put(name, pod);

    PodBartenderProxy proxy = _proxyMap.get(name);
    
    if (proxy != null) {
      proxy.setDelegate(pod);
    }
    
    _updatePodSystem = new UpdatePodSystem(_podMap.values());
    
    _heartbeatService.updatePod(_updatePodSystem);
    
    onUpdatePod(pod);
  }
  */

  ServerHeartbeat createServer(String serverId)
  {
    int p = serverId.indexOf(':');
    
    String address = serverId.substring(0, p);
    int port = Integer.parseInt(serverId.substring(p + 1));
    
    boolean isSSL = false;

    return _heartbeatService.createServer(address, port, isSSL);
  }

  public ServerHeartbeat findServer(String hintServer)
  {
    ServerHeartbeat server = (ServerHeartbeat) _heartbeatService.getServer(hintServer);
    
    if (server.getRack() != null) {
      return server;
    }
    
    return null;
  }

  public ServerHeartbeat findFreeServer(ServerPod[] serversPod)
  {
    for (ServerHeartbeat server : _heartbeatService.getRack().getServers()) {
      if (server == null) {
        continue;
      }
      
      if (! isServerUsed(serversPod, server)) {
        return server;
      }
    }
    
    return null;
  }
  
  private boolean isServerUsed(ServerPod []serversPod, ServerBartender server)
  {
    for (ServerPod serverPod : serversPod) {
      if (serverPod.getServer() == server) {
        return true;
      }
    }
    
    return false;
  }

  /*
  private class HeartbeatEventsPod implements ServerBartenderEvents {
    @Override
    public void onServerStart(ServerBartender server)
    {
      updatePodFailover();
    }

    @Override
    public void onServerStop(ServerBartender server)
    {
      updatePodFailover();
    }
  }
  */
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy