package cgl.iotcloud.core.master;
import cgl.iotcloud.core.Configuration;
import cgl.iotcloud.core.api.thrift.TSensorDeployDescriptor;
import cgl.iotcloud.core.master.events.*;
import cgl.iotcloud.core.sensorsite.SensorDeployDescriptor;
import cgl.iotcloud.core.sensorsite.SensorState;
import cgl.iotcloud.core.utils.SiteClientCache;
import com.google.common.eventbus.Subscribe;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Subscribe to sensor events and act accordingly
* Gets two types of events.
* 1. Events from user clients, these events are propagated to sites
* 2. Events from sites, results in updating the state locally and in zk
*/
public class ClientEventController {
private static Logger LOG = LoggerFactory.getLogger(ClientEventController.class);
private SiteClientCache clientCache;
private MasterContext context;
private CuratorFramework curatorFramework;
public ClientEventController(SiteClientCache clientCache, MasterContext context) {
this.clientCache = clientCache;
this.context = context;
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
this.curatorFramework = CuratorFrameworkFactory.newClient(Configuration.getZkConnectionString(context.getConf()), retryPolicy);
}
public void start() {
this.curatorFramework.start();
}
@Subscribe
public void handleClientEvents(MSensorClientEvent event) {
if (event.getState() == SensorState.DEPLOY) {
deploySensor(event);
} else if (event.getState() == SensorState.ACTIVATE) {
startSensor(event);
} else if (event.getState() == SensorState.DEACTIVATE) {
stopSensor(event);
} else if (event.getState() == SensorState.UN_DEPLOY) {
undeploySensor(event);
} else {
LOG.warn("Unrecognized event type {}", event.getState());
}
}
private void deploySensor(MSensorClientEvent deployEvent) {
TSensorDeployDescriptor sensor = deployEvent.getSensorDeployDescriptor();
SensorDeployDescriptor deployDescriptor = new SensorDeployDescriptor(sensor.getFilename(), sensor.getClassName());
deployDescriptor.addDeploySites(deployEvent.getSites());
if (sensor.getProperties() != null) {
for (Map.Entry<String, String> e : sensor.getProperties().entrySet()) {
deployDescriptor.addProperty(e.getKey(), e.getValue());
}
}
List<String> sites = getSites(deployEvent);
for (String site : sites) {
SiteClient client;
try {
client = clientCache.getSiteClient(site);
if (client != null) {
LOG.info("Requesting sensor site {} to deploy the sensor {} ", site, deployDescriptor);
client.deploySensor(deployDescriptor);
} else {
LOG.error("Requesting the sensor {} to be deployed in no-exsisting site {}", deployDescriptor, site);
}
} catch (Exception e) {
// we should report these kind of errors to some listening service or zookeeper in the future
// there is nothing much we can do at this point except to log it
LOG.error("Failed to deploy the sensor on the site {}", site, e);
}
}
}
private List<String> getSites(MSensorClientEvent deployEvent) {
List<String> sites = new ArrayList<String>(deployEvent.getSites());
if (sites.isEmpty()) {
sites.addAll(context.getSensorSites().keySet());
}
return sites;
}
private void stopSensor(MSensorClientEvent stopEvent) {
List<String> sites = getSites(stopEvent);
for (String site : sites) {
try {
LOG.info("Requesting sensor site {} to stop the sensor {} ", site, stopEvent.getId());
SiteClient client = clientCache.getSiteClient(site);
if (client != null) {
client.stopSensor(stopEvent.getId());
}
} catch (Exception e) {
// we should report these kind of errors to some listening service or zookeeper in the future
// there is nothing much we can do at this point except to log it
LOG.error("Failed to deploy the sensor on the site {}", site);
}
}
}
private void startSensor(MSensorClientEvent startEvent) {
List<String> sites = getSites(startEvent);
for (String site : sites) {
try {
LOG.info("Requesting sensor site {} to start the sensor {} ", site, startEvent.getId());
SiteClient client = clientCache.getSiteClient(site);
if (client != null) {
client.startSensor(startEvent.getId());
}
} catch (Exception e) {
// we should report these kind of errors to some listening service or zookeeper in the future
// there is nothing much we can do at this point except to log it
LOG.error("Failed to deploy the sensor on the site {}", site);
}
}
}
private void undeploySensor(MSensorClientEvent stopEvent) {
List<String> sites = getSites(stopEvent);
for (String site : sites) {
try {
LOG.info("Requesting sensor site {} to start the sensor {} ", site, stopEvent.getId());
SiteClient client = clientCache.getSiteClient(site);
if (client != null) {
client.unDeploySensor(stopEvent.getId());
}
} catch (Exception e) {
// we should report these kind of errors to some listening service or zookeeper in the future
// there is nothing much we can do at this point except to log it
LOG.error("Failed to deploy the sensor on the site {}", site);
}
}
}
}