package eu.europeana.cloud.service.dps.service.zoo; import eu.europeana.cloud.service.coordination.ZookeeperService; import eu.europeana.cloud.service.dps.TaskExecutionKillService; import java.util.Date; import java.util.List; import org.apache.zookeeper.data.Stat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Zookeeper implementation of {@link TaskExecutionKillService}. * @author Pavel Kefurt <Pavel.Kefurt@gmail.com> */ public class ZookeeperKillService implements TaskExecutionKillService { private static final Logger LOGGER = LoggerFactory.getLogger(ZookeeperKillService.class); private final static int ZOOKEEPER_CONNECTION_TIME = 3000; private final static int ZOOKEEPER_SESSION_TIMEOUT = 3000; private final static String ZOOKEEPER_PATH = "/tasks-to-kill"; private final ZookeeperService zS; /** * Construct kill service via zookeeper. * @param zS instance of zookeeper service */ public ZookeeperKillService(ZookeeperService zS) { this.zS = zS; } /** * Construct kill service via zookeeper. * @param zookeeperConnectString zookeeper servers (e.g. localhost:2181,192.168.47.129:2181) */ public ZookeeperKillService(String zookeeperConnectString) { zS = new ZookeeperService(zookeeperConnectString, ZOOKEEPER_CONNECTION_TIME, ZOOKEEPER_SESSION_TIMEOUT, ZOOKEEPER_PATH); } @Override public void killTask(String topology, long taskId) { String path = ZOOKEEPER_PATH +"/"+ topology +"/"+ String.valueOf(taskId); try { zS.getClient().create().creatingParentsIfNeeded().forPath(path); } catch(Exception ex) //node exists { LOGGER.warn("Cannot submit kill flag for task {} because: {}", taskId, ex.getMessage()); } } @Override public Boolean hasKillFlag(String topology, long taskId) { String path = ZOOKEEPER_PATH +"/"+ topology +"/"+ String.valueOf(taskId); Stat stat = null; try { stat= zS.getClient().checkExists().forPath(path); } catch(Exception ex) { LOGGER.warn("Cannot check kill flag of task {} because: {}", taskId, ex.getMessage()); } return stat != null; } @Override public void cleanOldFlags(String topology, long ttl) { String path = ZOOKEEPER_PATH +"/"+ topology; long threshold = new Date().getTime()-ttl; try { List<String> children = zS.getClient().getChildren().forPath(path); Stat stat; for(String child: children) { stat= zS.getClient().checkExists().forPath(path+"/"+child); if(stat != null) { long lastModifiTime = stat.getMtime(); //time in milliseconds from epoch when this znode was last modified if(lastModifiTime < threshold) { zS.getClient().delete().inBackground().forPath(path+"/"+child); } } } } catch(Exception ex) { LOGGER.warn("Cannot clean kill flags of {} topology because: {}", topology, ex.getMessage()); } } @Override public void removeFlag(String topology, long taskId) { String path = ZOOKEEPER_PATH +"/"+ topology +"/"+ String.valueOf(taskId); try { zS.getClient().delete().inBackground().forPath(path); } catch(Exception ex) { LOGGER.warn("Cannot remove kill flag of {} task because: {}", taskId, ex.getMessage()); } } }