/*
* Galaxy
* Copyright (c) 2012-2014, Parallel Universe Software Co. All rights reserved.
*
* This program and the accompanying materials are dual-licensed under
* either the terms of the Eclipse Public License v1.0 as published by
* the Eclipse Foundation
*
* or (per the licensee's choosing)
*
* under the terms of the GNU Lesser General Public License version 3.0
* as published by the Free Software Foundation.
*/
package co.paralleluniverse.galaxy.core;
import co.paralleluniverse.common.spring.Component;
import co.paralleluniverse.common.spring.Service;
import co.paralleluniverse.galaxy.Cluster;
import co.paralleluniverse.galaxy.cluster.LifecycleListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jmx.export.annotation.ManagedAttribute;
/**
* A {@link Component component} bound to the cluster's lifecycle.
* @author pron
*/
public abstract class ClusterService extends Service implements LifecycleListener {
private static final Logger LOG = LoggerFactory.getLogger(ClusterService.class);
private final Cluster cluster;
private final Object lifecycleLock = new Object();
private volatile boolean online; // is this node online
public ClusterService(String name, Cluster cluster) {
super(name);
this.cluster = cluster;
cluster.addLifecycleListener(this);
synchronized (lifecycleLock) {
online = cluster.isOnline();
}
}
@Override
protected void postInit() throws Exception {
if (online)
startService();
super.postInit();
}
private void startService() {
final boolean master = cluster.isMaster();
LOG.info("Starting service {} as {}", this, master ? "master" : "slave");
start(master);
LOG.info("Service {} started.", this);
}
/**
* Return {@code true} if this node is online; {@code false} otherwise.
* @return {@code true} if this node is online; {@code false} otherwise.
*/
@ManagedAttribute(currencyTimeLimit = 0)
protected boolean isOnline() {
return online;
}
/**
* Return {@code true} if this node is currently a master; {@code false} if it's a slave.
* @return {@code true} if this node is currently a master; {@code false} if it's a slave.
*/
protected boolean isMaster() {
return cluster.isMaster();
}
/**
* Called when this component has finished <i>and</i> has come online.
* @param master {@code true} if this node is currently a master; {@code false} if it's a slave.
*/
protected abstract void start(boolean master);
@Override
public void joinedCluster() {
LOG.info("JOINED CLUSTER (Service {})", this);
}
@Override
public final void online(boolean master) {
synchronized (lifecycleLock) {
if (!online) {
online = true;
if (isInitialized())
startService();
}
}
}
@Override
public final void offline() {
synchronized (lifecycleLock) {
if (online) {
online = false;
try {
LOG.info("Shutting down component {}", getName());
shutdown();
LOG.info("Component {} destroyed", getName());
} catch (RuntimeException e) {
LOG.warn("Exception while shutting down " + getName(), e);
throw e;
}
}
}
}
@Override
public void switchToMaster() {
LOG.info("Switching service {} to master", this);
}
/**
* Returns the cluster.
* @return The cluster.
*/
public Cluster getCluster() {
return cluster;
}
}